UNPKG

kekule

Version:

Open source JavaScript toolkit for chemoinformatics

514 lines (478 loc) 13.8 kB
/** * @fileoverview * IO reader/writer utilizing OpenBabel library. * @author Partridge Jiang */ /* * requires /lan/classes.js * requires /core/kekule.common.js * requires /io/kekule.io.js * requires /core/kekule.chemUtils.js * requires /_extras/OpenBabel/kekule.openbabel.adapters.js * requires /_extras/kekule.emscriptenUtils.js * requires /localization */ (function(){ /** @ignore */ var EU = Kekule.EmscriptenUtils; /** @ignore */ var OB = Kekule.OpenBabel; /** @ignore */ var AU = Kekule.OpenBabel.AdaptUtils; /** * Reader utilizing OpenBabel library to read a huge amount of chem data formats. * @class * @augments Kekule.IO.ChemDataReader */ Kekule.IO.OpenBabelReader = Class.create(Kekule.IO.ChemDataReader, /** @lends Kekule.IO.OpenBabelReader# */ { /** @private */ CLASS_NAME: 'Kekule.IO.OpenBabelReader', /** @constructs */ initialize: function(/*$super, */options) { this.tryApplySuper('initialize') /* $super() */; //this._obConv = new (OB.getClassCtor('ObConversionWrapper'))(); }, /** @ignore */ finalize: function(/*$super*/) { //this._obConv = null; this.tryApplySuper('finalize') /* $super() */; }, /** * Decide output object type: molecule or reaction. * @param {Object} obFormatWrapper */ getFormatTargetObClassName: function(obFormatWrapper) { var tname = obFormatWrapper.getTypeName(); var isReaction =( tname.toLowerCase().indexOf('reaction') >= 0); return isReaction? 'OBReaction': 'OBMol'; }, /** @private */ doReadData: function(data, dataType, format) { this._obConv = new (OB.getClassCtor('ObConversionWrapper'))(); try { var fInfo = Kekule.IO.DataFormatsManager.getFormatInfo(format); //console.log(format, fInfo); var mimeType = fInfo.mimeType; var fileExt = fInfo.fileExts[0]; //console.log(mimeType, fileExt); // decide type //var fmt = this._obConv.setInFormat(mimeType, fileExt); var fmt = this._obConv.setInFormatId(fInfo.id); //console.log('Format of : ' + format, mimeType, fileExt, fmt); var obClassName = this.getFormatTargetObClassName(fmt); try { /* var obObj = new (OB.getClassCtor(obClassName))(); this._obConv.readString(obObj, data); var kObj = AU.obObjToKekule(obObj); return kObj; */ // use new loop interface var kObjs = []; this._obConv.setInStr(data); //console.log(data); var obObj = new (OB.getClassCtor(obClassName))(); //try { var hasObj = this._obConv.readFromInput(obObj); while (hasObj) { if (obObj.NumAtoms && (obObj.NumAtoms() > 0)) // bypass empty molecule with no atoms { var kObj = AU.obObjToKekule(obObj); kObjs.push(kObj); //console.log(obObj, kObj.getNodeCount()); } hasObj = this._obConv.readFromInput(obObj); } } //catch(e) { } /* this._obConv.setOutFormat('', 'mol'); // must set a output format, otherwise convert will return 0 var convCount = this._obConv.convert(); console.log(convCount, 'molecule converted'); if (convCount > 0) { while (!this._obConv.isLastChemObject()) { var obObj = this._obConv.getChemObj(); if (obObj) { try { var kObj = AU.obObjToKekule(obObj); if (kObj) kObjs.push(kObj); } finally { obObj.delete(); } } } } else return null; */ var length = kObjs.length; if (length <= 0) return null; else if (length === 1) return kObjs[0] else // create a new ChemObjList { var result = new Kekule.ChemObjList(); for (var i = 0; i < length; ++i) { result.append(kObjs[i]); } return result; } /* // debug //this._obConv.setOutFormat(mimeType, fileExt); this._obConv.setOutFormat('', 'mol'); var str = this._obConv.writeString(obObj, true); console.log(str); */ // convert to Kekule one /* var mol = AU.obMolToKekule(obObj, null); console.log(mol); return mol; */ /* var kObj = AU.obObjToKekule(obObj); //console.log(kObj.getClassName(), kObj); return kObj; */ } finally { if (obObj) { //obObj.delete(); obObj['delete'](); // avoid exception in older version of IE obObj = null; } } } finally { if (this._obConv) { //this._obConv.delete(); this._obConv['delete'](); // avoid exception in older version of IE this._obConv = null; } } } }); /** * Writer utilizing OpenBabel library to write a huge amount of chem data formats. * @class * @augments Kekule.IO.ChemDataWriter */ Kekule.IO.OpenBabelWriter = Class.create(Kekule.IO.ChemDataWriter, /** @lends Kekule.IO.OpenBabelWriter# */ { /** @private */ CLASS_NAME: 'Kekule.IO.OpenBabelWriter', /** @constructs */ initialize: function(/*$super, */options) { this.tryApplySuper('initialize', [options]) /* $super(options) */; //this._obConv = new (OB.getClassCtor('ObConversionWrapper'))(); }, /** @ignore */ finalize: function(/*$super*/) { //this._obConv = null; this.tryApplySuper('finalize') /* $super() */; }, /** @private */ doWriteData: function(obj, dataType, format) { this._obConv = new (OB.getClassCtor('ObConversionWrapper'))(); try { var fInfo = Kekule.IO.DataFormatsManager.getFormatInfo(format); var mimeType = fInfo.mimeType; var fileExt = fInfo.fileExts[0]; //console.log(fInfo); //var f = this._obConv.setOutFormat(mimeType, fileExt); this._obConv.setOutFormatId(fInfo.id); //console.log(f); //this._obConv.clearOut(); var kObjs = Kekule.ChemStructureUtils.getChildStructureObjs(obj, true); // use new loop interface to write multiple basic objects for (var i = 0, l = kObjs.length; i < l; ++i) { var kObj = kObjs[i]; if (kObj) { var obObj = AU.kObjToOB(kObj); if (obObj) { try { var success = this._obConv.writeToOutput(obObj); if (!success) { break; } } finally { //obObj.delete(); obObj['delete'](); // avoid exception in older version of IE obObj = null; } } } } var result = this._obConv.getOutStr(); return result; /* var obObj = AU.kObjToOB(obj); try { //console.log(obMol.NumAtoms(), obMol.NumBonds()) var result = this._obConv.writeString(obObj, true); return result; } finally { if (obObj) obObj.delete(); } */ } finally { if (this._obConv) { //this._obConv.delete(); this._obConv['delete'](); // avoid exception in older version of IE } } }, /** @private */ isAllowedObj: function(kObj) { var classes = Kekule.IO.OpenBabelWriter.ALLOWED_CLASSES; return Kekule.ObjUtils.isInstanceOf(kObj, classes); } }); /** @ignore */ Kekule.IO.OpenBabelWriter.ALLOWED_CLASSES = [Kekule.StructureFragment, Kekule.Reaction, Kekule.ChemObjList, Kekule.ChemStructureObjectGroup, Kekule.ChemSpaceElement, Kekule.ChemSpace]; /** @ignore */ Kekule.OpenBabel.IORegHelper = Class.create({ listFormatInfo: function(ioType, converter) { var result = []; var delimiter = '\n'; var itemSep = '--'; var formatListStr; if (ioType === 'in') formatListStr = converter.getSupportedInputFormatsStr(delimiter); //formatListStr = Kekule.OpenBabel.obGetSupportedInputFormatsStr(delimiter); else formatListStr = converter.getSupportedOutputFormatsStr(delimiter); //formatListStr = Kekule.OpenBabel.obGetSupportedOutputFormatsStr(delimiter); var basicStrArray = formatListStr.split(delimiter); for (var i = 0, l = basicStrArray.length; i < l; ++i) { var s = basicStrArray[i]; // get str before '--', only the id var pos = s.indexOf(itemSep); if (pos > 0) { var id = s.substring(0, pos).trim(); // then get more details from id var info = converter.getFormatInfoById(id); result.push(info); //console.log(info); } } /* var lister = Kekule.OpenBabel.obGetSupportedFormatsDetailStr; if (lister) { formatListStr = lister(ioType, delimiter, itemSep); // analysis format list str var sitems = formatListStr.split(delimiter); for (var i = 0, l = sitems.length; i < l; ++i) { var s = sitems[i]; var details = s.split(itemSep); var info = { 'id': details[0], 'mimeType': details[1], 'description': details[2] }; result.push(info); } } */ return result; }, registerByInfos: function(infos, ioType) { //var iOManager = (ioType === 'in')? Kekule.IO.ChemDataReaderManager: Kekule.IO.ChemDataWriterManager; var formatManager = Kekule.IO.DataFormatsManager; var handleIds = []; //console.log(infos); for (var i = 0, l = infos.length; i < l; ++i) { var info = infos[i]; var id = info.id; var mimeType = info.mimeType; // check if fileExts or mimeType already exists // find by both mimeType and file exts, if mimeType exists but file ext not in, still register var fmtId = formatManager.findFormatId(mimeType); if (fmtId) fmtId = formatManager.findFormatId(null, id); /* if (!fmtId) fmtId = formatManager.findFormatId(null, id); */ if (!fmtId) // file ext or MIME type not exists, register { /* if (ioType === 'in') console.log(id, mimeType); */ // TODO: dataType is unknown from info. var fmtInfo = formatManager.register(id, mimeType, id, Kekule.IO.ChemDataType.UNKNOWN, info.description, info.description, {'specificationUrl': info.specificationURL}); var fmtId = fmtInfo.id; //console.log('[register]', id, mimeType, info); } /* else { console.log('[EXISTS]', fmtId, mimeType, info); } */ // check if fileExts or mimeType already has reader/writer var readerWriterInfo = (ioType === 'in')? Kekule.IO.ChemDataReaderManager.getReaderInfoByFormat(fmtId): Kekule.IO.ChemDataWriterManager.getWriterInfoByFormat(fmtId); if (!readerWriterInfo) // not has reader/writer, register open babel one { Kekule.ArrayUtils.pushUnique(handleIds, fmtId); } } //console.log(ioType, handleIds); if (handleIds.length) { if (ioType === 'in') { Kekule.IO.ChemDataReaderManager.register('openbabel', Kekule.IO.OpenBabelReader, handleIds); } else { Kekule.IO.ChemDataWriterManager.register('openbabel', Kekule.IO.OpenBabelWriter, Kekule.IO.OpenBabelWriter.ALLOWED_CLASSES, handleIds); } } }, registerAll: function() { var converter = new (OB.getClassCtor('ObConversionWrapper'))(); try { //console.log(converter); var infos = this.listFormatInfo('in', converter); //console.log('in', infos.length); this.registerByInfos(infos, 'in'); //console.log('out', infos.length); var infos = this.listFormatInfo('out', converter); this.registerByInfos(infos, 'out'); } finally { //converter.delete(); converter['delete'](); // avoid exception in older version of IE } /* var infos = this.listFormatInfo('in'); this.registerByInfos(infos, 'in'); var infos = this.listFormatInfo('out'); this.registerByInfos(infos, 'out'); */ } }); /** * A helper method to register all I/O formats supported by open babel. */ Kekule.IO.registerAllOpenBabelFormats = function() { if (Kekule.OpenBabel.AdaptUtils.isAvailable()) { try { var helper = new Kekule.OpenBabel.IORegHelper(); helper.registerAll(); } finally { helper = null; } } }; Kekule.OpenBabel._enableFuncs.push(Kekule.IO.registerAllOpenBabelFormats); /** * A helper method to load open babel script library and register all I/O formats */ Kekule.IO.enableOpenBabelFormats = function() { if (!Kekule.OpenBabel.AdaptUtils.isAvailable()) // OB not loaded? { Kekule.OpenBabel.loadObScript(document, function(){ Kekule.IO.registerAllOpenBabelFormats(); }); } else Kekule.IO.registerAllOpenBabelFormats(); }; (function(){ /* // register chem data formats Kekule.IO.DataFormatsManager.register('pdb', 'chemical/x-pdb', ['pdb', 'ent'], Kekule.IO.ChemDataType.TEXT, 'PDB format'); Kekule.IO.DataFormatsManager.register('smiles', 'chemical/x-daylight-smiles', ['smi'], Kekule.IO.ChemDataType.TEXT, 'SMILES format'); Kekule.IO.DataFormatsManager.register('mol2', 'chemical/x-mol2', ['mol2'], Kekule.IO.ChemDataType.TEXT, 'Sybyl mol2'); Kekule.IO.DataFormatsManager.register('cdx', 'chemical/x-cdx', ['cdx'], Kekule.IO.ChemDataType.BINARY, 'ChemDraw CDX'); Kekule.IO.DataFormatsManager.register('ct', 'chemical/x-ct', ['ct'], Kekule.IO.ChemDataType.TEXT, 'ct'); // register ChemData reader and writer Kekule.IO.ChemDataReaderManager.register('OpenBabel', Kekule.IO.OpenBabelReader, ['MDL-mol', 'MDL-rxn', 'pdb', 'smiles', 'mol2', 'cdx', 'ct']); Kekule.IO.ChemDataWriterManager.register('OpenBabel', Kekule.IO.OpenBabelWriter, [Kekule.StructureFragment], ['MDL-mol', 'pdb', 'smiles', 'mol2', 'cdx', 'ct']); Kekule.IO.ChemDataWriterManager.register('OpenBabel-Rxn', Kekule.IO.OpenBabelWriter, [Kekule.Reaction], ['MDL-rxn']); */ //Kekule.X.domReady(function() /* Kekule._registerAfterLoadProc(function() { Kekule.IO.registerAllOpenBabelFormats(); }); */ })(); })();