forked from enviPath/enviPy
Current Dev State
This commit is contained in:
301
static/js/ketcher2/script/chem/molfile/parseSGroup.js
Normal file
301
static/js/ketcher2/script/chem/molfile/parseSGroup.js
Normal file
@ -0,0 +1,301 @@
|
||||
/****************************************************************************
|
||||
* 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.
|
||||
***************************************************************************/
|
||||
|
||||
var Set = require('../../util/set');
|
||||
var Vec2 = require('../../util/vec2');
|
||||
|
||||
var Struct = require('./../struct/index');
|
||||
var utils = require('./utils');
|
||||
|
||||
function readKeyValuePairs(str, /* bool */ valueString) {
|
||||
/* reader */
|
||||
var ret = {};
|
||||
var partition = utils.partitionLineFixed(str, 3, true);
|
||||
var count = utils.parseDecimalInt(partition[0]);
|
||||
for (var i = 0; i < count; ++i) {
|
||||
/* eslint-disable no-mixed-operators*/
|
||||
ret[utils.parseDecimalInt(partition[2 * i + 1]) - 1] =
|
||||
valueString ? partition[2 * i + 2].trim() :
|
||||
utils.parseDecimalInt(partition[2 * i + 2]);
|
||||
/* eslint-enable no-mixed-operators*/
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function readKeyMultiValuePairs(str, /* bool */ valueString) {
|
||||
/* reader */
|
||||
var ret = [];
|
||||
var partition = utils.partitionLineFixed(str, 3, true);
|
||||
var count = utils.parseDecimalInt(partition[0]);
|
||||
for (var i = 0; i < count; ++i) {
|
||||
ret.push([
|
||||
/* eslint-disable no-mixed-operators*/
|
||||
utils.parseDecimalInt(partition[2 * i + 1]) - 1,
|
||||
valueString ? partition[2 * i + 2].trim() : utils.parseDecimalInt(partition[2 * i + 2])
|
||||
/* eslint-enable no-mixed-operators*/
|
||||
]);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function postLoadMul(sgroup, mol, atomMap) { // eslint-disable-line max-statements
|
||||
sgroup.data.mul = sgroup.data.subscript - 0;
|
||||
var atomReductionMap = {};
|
||||
|
||||
sgroup.atoms = Struct.SGroup.filterAtoms(sgroup.atoms, atomMap);
|
||||
sgroup.patoms = Struct.SGroup.filterAtoms(sgroup.patoms, atomMap);
|
||||
|
||||
// mark repetitions for removal
|
||||
for (var k = 1; k < sgroup.data.mul; ++k) {
|
||||
for (var m = 0; m < sgroup.patoms.length; ++m) {
|
||||
var raid = sgroup.atoms[k * sgroup.patoms.length + m]; // eslint-disable-line no-mixed-operators
|
||||
if (raid < 0)
|
||||
continue; // eslint-disable-line no-continue
|
||||
if (sgroup.patoms[m] < 0)
|
||||
throw new Error('parent atom missing');
|
||||
atomReductionMap[raid] = sgroup.patoms[m]; // "merge" atom in parent
|
||||
}
|
||||
}
|
||||
sgroup.patoms = Struct.SGroup.removeNegative(sgroup.patoms);
|
||||
|
||||
var patomsMap = identityMap(sgroup.patoms);
|
||||
|
||||
var bondsToRemove = [];
|
||||
mol.bonds.each(function (bid, bond) {
|
||||
var beginIn = bond.begin in atomReductionMap;
|
||||
var endIn = bond.end in atomReductionMap;
|
||||
// if both adjacent atoms of a bond are to be merged, remove it
|
||||
/* eslint-disable no-mixed-operators*/
|
||||
if (beginIn && endIn ||
|
||||
beginIn && bond.end in patomsMap ||
|
||||
endIn && bond.begin in patomsMap)
|
||||
bondsToRemove.push(bid);
|
||||
/* eslint-enable no-mixed-operators*/
|
||||
// if just one atom is merged, modify the bond accordingly
|
||||
else if (beginIn)
|
||||
bond.begin = atomReductionMap[bond.begin];
|
||||
else if (endIn)
|
||||
bond.end = atomReductionMap[bond.end];
|
||||
}, sgroup);
|
||||
|
||||
// apply removal lists
|
||||
for (var b = 0; b < bondsToRemove.length; ++b)
|
||||
mol.bonds.remove(bondsToRemove[b]);
|
||||
for (var a in atomReductionMap) {
|
||||
mol.atoms.remove(a);
|
||||
atomMap[a] = -1;
|
||||
}
|
||||
sgroup.atoms = sgroup.patoms;
|
||||
sgroup.patoms = null;
|
||||
}
|
||||
|
||||
function postLoadSru(sgroup) {
|
||||
sgroup.data.connectivity = (sgroup.data.connectivity || 'EU').trim().toLowerCase();
|
||||
}
|
||||
|
||||
function postLoadSup(sgroup) {
|
||||
sgroup.data.name = (sgroup.data.subscript || '').trim();
|
||||
sgroup.data.subscript = '';
|
||||
}
|
||||
|
||||
function postLoadGen(sgroup, mol, atomMap) { // eslint-disable-line no-unused-vars
|
||||
}
|
||||
|
||||
function postLoadDat(sgroup, mol) {
|
||||
if (!sgroup.data.absolute)
|
||||
sgroup.pp = sgroup.pp.add(Struct.SGroup.getMassCentre(mol, sgroup.atoms));
|
||||
}
|
||||
|
||||
function loadSGroup(mol, sg, atomMap) {
|
||||
var postLoadMap = {
|
||||
MUL: postLoadMul,
|
||||
SRU: postLoadSru,
|
||||
SUP: postLoadSup,
|
||||
DAT: postLoadDat,
|
||||
GEN: postLoadGen
|
||||
};
|
||||
|
||||
// add the group to the molecule
|
||||
sg.id = mol.sgroups.add(sg);
|
||||
|
||||
// apply type-specific post-processing
|
||||
postLoadMap[sg.type](sg, mol, atomMap);
|
||||
// mark atoms in the group as belonging to it
|
||||
for (var s = 0; s < sg.atoms.length; ++s) {
|
||||
if (mol.atoms.has(sg.atoms[s]))
|
||||
Set.add(mol.atoms.get(sg.atoms[s]).sgs, sg.id);
|
||||
}
|
||||
|
||||
if (sg.type == 'DAT')
|
||||
mol.sGroupForest.insert(sg.id, -1, []);
|
||||
else
|
||||
mol.sGroupForest.insert(sg.id);
|
||||
|
||||
return sg.id;
|
||||
}
|
||||
|
||||
function initSGroup(sGroups, propData) {
|
||||
/* reader */
|
||||
var kv = readKeyValuePairs(propData, true);
|
||||
for (var key in kv) {
|
||||
var type = kv[key];
|
||||
if (!(type in Struct.SGroup.TYPES))
|
||||
throw new Error('Unsupported S-group type');
|
||||
var sg = new Struct.SGroup(type);
|
||||
sg.number = key;
|
||||
sGroups[key] = sg;
|
||||
}
|
||||
}
|
||||
|
||||
function applySGroupProp(sGroups, propName, propData, numeric, core) { // eslint-disable-line max-params
|
||||
var kv = readKeyValuePairs(propData, !(numeric));
|
||||
for (var key in kv)
|
||||
// "core" properties are stored directly in an sgroup, not in sgroup.data
|
||||
(core ? sGroups[key] : sGroups[key].data)[propName] = kv[key];
|
||||
}
|
||||
|
||||
function applySGroupArrayProp(sGroups, propName, propData, shift) {
|
||||
/* reader */
|
||||
var sid = utils.parseDecimalInt(propData.slice(1, 4)) - 1;
|
||||
var num = utils.parseDecimalInt(propData.slice(4, 8));
|
||||
var part = toIntArray(utils.partitionLineFixed(propData.slice(8), 3, true));
|
||||
|
||||
if (part.length != num)
|
||||
throw new Error('File format invalid');
|
||||
if (shift) {
|
||||
part = part.map(function (v) {
|
||||
return v + shift;
|
||||
});
|
||||
}
|
||||
sGroups[sid][propName] = sGroups[sid][propName].concat(part);
|
||||
}
|
||||
|
||||
function applyDataSGroupName(sg, name) {
|
||||
/* reader */
|
||||
sg.data.fieldName = name;
|
||||
}
|
||||
|
||||
function applyDataSGroupQuery(sg, query) {
|
||||
/* reader */
|
||||
sg.data.query = query;
|
||||
}
|
||||
|
||||
function applyDataSGroupQueryOp(sg, queryOp) {
|
||||
/* reader */
|
||||
sg.data.queryOp = queryOp;
|
||||
}
|
||||
|
||||
function applyDataSGroupDesc(sGroups, propData) {
|
||||
/* reader */
|
||||
var split = utils.partitionLine(propData, [4, 31, 2, 20, 2, 3], false);
|
||||
var id = utils.parseDecimalInt(split[0]) - 1;
|
||||
var fieldName = split[1].trim();
|
||||
var fieldType = split[2].trim();
|
||||
var units = split[3].trim();
|
||||
var query = split[4].trim();
|
||||
var queryOp = split[5].trim();
|
||||
var sGroup = sGroups[id];
|
||||
sGroup.data.fieldType = fieldType;
|
||||
sGroup.data.fieldName = fieldName;
|
||||
sGroup.data.units = units;
|
||||
sGroup.data.query = query;
|
||||
sGroup.data.queryOp = queryOp;
|
||||
}
|
||||
|
||||
function applyDataSGroupInfo(sg, propData) { // eslint-disable-line max-statements
|
||||
/* reader */
|
||||
var split = utils.partitionLine(propData, [10/* x.x*/, 10/* y.y*/, 4/* eee*/, 1/* f*/, 1/* g*/, 1/* h*/, 3/* i */, 3/* jjj*/, 3/* kkk*/, 3/* ll*/, 2/* m*/, 3/* n*/, 2/* oo*/], false);
|
||||
|
||||
var x = parseFloat(split[0]);
|
||||
var y = parseFloat(split[1]);
|
||||
var attached = split[3].trim() == 'A';
|
||||
var absolute = split[4].trim() == 'A';
|
||||
var showUnits = split[5].trim() == 'U';
|
||||
var nCharsToDisplay = split[7].trim();
|
||||
nCharsToDisplay = nCharsToDisplay == 'ALL' ? -1 : utils.parseDecimalInt(nCharsToDisplay);
|
||||
var tagChar = split[10].trim();
|
||||
var daspPos = utils.parseDecimalInt(split[11].trim());
|
||||
|
||||
sg.pp = new Vec2(x, -y);
|
||||
sg.data.attached = attached;
|
||||
sg.data.absolute = absolute;
|
||||
sg.data.showUnits = showUnits;
|
||||
sg.data.nCharsToDisplay = nCharsToDisplay;
|
||||
sg.data.tagChar = tagChar;
|
||||
sg.data.daspPos = daspPos;
|
||||
}
|
||||
|
||||
function applyDataSGroupInfoLine(sGroups, propData) {
|
||||
/* reader */
|
||||
var id = utils.parseDecimalInt(propData.substr(0, 4)) - 1;
|
||||
var sg = sGroups[id];
|
||||
applyDataSGroupInfo(sg, propData.substr(5));
|
||||
}
|
||||
|
||||
function applyDataSGroupData(sg, data, finalize) {
|
||||
/* reader */
|
||||
sg.data.fieldValue = (sg.data.fieldValue || '') + data;
|
||||
if (finalize) {
|
||||
sg.data.fieldValue = trimRight(sg.data.fieldValue);
|
||||
if (sg.data.fieldValue.startsWith('"') && sg.data.fieldValue.endsWith('"'))
|
||||
sg.data.fieldValue = sg.data.fieldValue.substr(1, sg.data.fieldValue.length - 2);
|
||||
}
|
||||
}
|
||||
|
||||
function applyDataSGroupDataLine(sGroups, propData, finalize) {
|
||||
/* reader */
|
||||
var id = utils.parseDecimalInt(propData.substr(0, 5)) - 1;
|
||||
var data = propData.substr(5);
|
||||
var sg = sGroups[id];
|
||||
applyDataSGroupData(sg, data, finalize);
|
||||
}
|
||||
|
||||
// Utilities functions
|
||||
function toIntArray(strArray) {
|
||||
/* reader */
|
||||
var ret = [];
|
||||
for (var j = 0; j < strArray.length; ++j)
|
||||
ret[j] = utils.parseDecimalInt(strArray[j]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
function trimRight(str) {
|
||||
return str.replace(/\s+$/, '');
|
||||
}
|
||||
|
||||
function identityMap(array) {
|
||||
var map = {};
|
||||
for (var i = 0; i < array.length; ++i)
|
||||
map[array[i]] = array[i];
|
||||
return map;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
readKeyValuePairs: readKeyValuePairs,
|
||||
readKeyMultiValuePairs: readKeyMultiValuePairs,
|
||||
loadSGroup: loadSGroup,
|
||||
initSGroup: initSGroup,
|
||||
applySGroupProp: applySGroupProp,
|
||||
applySGroupArrayProp: applySGroupArrayProp,
|
||||
applyDataSGroupName: applyDataSGroupName,
|
||||
applyDataSGroupQuery: applyDataSGroupQuery,
|
||||
applyDataSGroupQueryOp: applyDataSGroupQueryOp,
|
||||
applyDataSGroupDesc: applyDataSGroupDesc,
|
||||
applyDataSGroupInfo: applyDataSGroupInfo,
|
||||
applyDataSGroupData: applyDataSGroupData,
|
||||
applyDataSGroupInfoLine: applyDataSGroupInfoLine,
|
||||
applyDataSGroupDataLine: applyDataSGroupDataLine
|
||||
};
|
||||
Reference in New Issue
Block a user