com.actelion.research.chem.reaction.ReactionClassifier Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of openchemlib Show documentation
Show all versions of openchemlib Show documentation
Open Source Chemistry Library
/*
* Copyright (c) 1997 - 2016
* Actelion Pharmaceuticals Ltd.
* Gewerbestrasse 16
* CH-4123 Allschwil, Switzerland
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of the the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* @author Thomas Sander
*/
package com.actelion.research.chem.reaction;
import com.actelion.research.chem.Molecule;
import com.actelion.research.chem.StereoMolecule;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.nio.charset.StandardCharsets;
public class ReactionClassifier {
private static final boolean DEBUG = true;
// private static final int MAXAROMS = 19;
private static final int MAXFATMS = 64; // maximal no of atoms per fragment
private static final int MAXATMCNO = 190; // max allowed atomic number
private static final int MAXCONNS = 6;
// private static final int MAXMOLS = 16;
private static final int MAXATOMS = 256;
// private static final int MAXBONDS = 256;
private static final int MAXMPPNGNO = 512;
private static final int MAXINDICES = Classification.MAXINDICES;
// private static final int INDEXLEN = Classification.INDEXLEN;
private static final int MAXFLASH = Classification.MAXFLASH;
private static final int MAXUNITS = Classification.MAXUNITS;
// private static final int MAXENDUR = Classification.MAXENDUR;
// private static final int RCLASSES = 13;
private static final int S_CONST = 0;
private static final int HD_D_CONST = 1;
private static final int D_D_CONST = 2;
private static final int HD_REAR = 3;
private static final int D_REAR = 4;
private static final int S_FRAG = 5;
private static final int C1_REFU = 6;
private static final int LONG_REFU = 7;
private static final int HETERO_REFU = 8;
private static final int HD_D_FRAG = 9;
private static final int D_D_FRAG = 10;
private static final int E_RING_C = 11;
private static final int E_RING_O = 12;
private static final int BONDBITS = 5; // bits in indexfile: C-C bond specific data
private static final int HRXNBITS = 25; // half rxn specific data
private static final int DRXNBITS = 11; // two end half rxn specific data
private static final int CRXNBITS = 4; // bits for electrocyclic reaction class
private static final int REARBITS = 13; // half rearrangement specific data
private static final int PROPBITS = 11; // nr of bits of carbon describing properties
// private static final int MAXPRUNOPTIONS = 58;
public static final int cErrorNoError = 0;
public static final int cErrorNoChangeNorEFG = 1;
public static final int cErrorEductMapNoOverused = 2;
public static final int cErrorProdMapNoOverused1 = 3;
public static final int cErrorProdMapNoOverused2 = 4;
public static final int cErrorMapNoNotInProduct = 5;
public static final int cErrorMapNoNotInEduct = 6;
public static final int cErrorDupProdMapNoDifEd = 7;
// public static final int cErrorMaxNoOfMolsReached = 8;
public static final int cErrorProdRemapFailed = 9;
public static final int cErrorEduFragPartMapped = 10;
public static final int cErrorFragmentAtomLimit = 11;
public static final int cErrorProdFragPartMapped = 12;
public static final int cErrorUnexpected = 13;
public static final int cErrorUnMappedCInConOrFr = 14;
public static final int cErrorCCBondCleavageLimit = 15;
public static final int cErrorCCBondCreationLimit = 16;
public static final int cErrorComplexReaction = 17;
public static final int cErrorNoChangingAtoms = 18;
public static final int cErrorForkedOrLongStrand = 19;
public static final int cError2AlphasInSameStrand = 20;
public static final int cErrorHRClassifyError = 21;
public static final int cErrorCRClassifyError = 22;
public static final int cErrorDRClassifyError = 23;
public static final int cErrorRAClassifyError = 24;
public static final int cErrorREClassifyError = 25;
public static final int cErrorIncoOrLeavMissing = 26;
public static final int cErrorUnitReactionLimit = 27;
public static final int cErrorNoDatabaseReaction = 28;
public static final int cIndexNone = 0;
public static final int cIndexOnePermToFile = 1;
public static final int cIndexFullPermutation = 2;
private static final int cAtomPiChange = 0x0100; // TODO use real value
private static final int cAtomZChange = 0x0200; // TODO use real value
private static final int cAtomSigmaChange = 0x0400; // TODO use real value
private static final int cAtomChanges = 0x1000; // TODO use real value
private static final int cAtomNoCounterAtom = 0x2000; // TODO use real value
private static final int cAtomDBondToHetero = 0x4000; // TODO use real value
private static final int cAtomNotClassifiedYet = 0x8000; // TODO use real value
private static final int CARBON = 1;
// private static final int HYDROGEN = 3;
private static int data,mask;
private static int indexnum,indexpoin,availbits;
private ClassificationData mClassificationData;
private BufferedWriter gErrout;
private Reaction mRxn;
private Classification mResult;
private int mIndexToCreate,mUnitRxn;
private int[][] mAtomType,mSigma,mPi,mH,mZ,mAtomFlags,mCorProd,mCorAtom;
private int[][][] mConnMpNo,mConnCMNo,mConnType;
public ReactionClassifier() {
mClassificationData = ClassificationData.getInstance();
}
public int classify(Reaction theReaction) {
return classify(cIndexNone, theReaction);
}
public int classify(int indexToCreate, /*CBatchClassifier theBatchClassifierP,*/ Reaction theReaction) {
//TODO CEFGClassifier efgClassifier;
mIndexToCreate = indexToCreate;
mRxn = theReaction;
// mBatchClassifierP = theBatchClassifierP;
if (indexToCreate != cIndexNone && !(theReaction instanceof DatabaseReaction))
return cErrorNoDatabaseReaction;
for (int mol=0; mol 2)
return cErrorEductMapNoOverused;
}
}
if (!doubleFound)
continue;
for (int atm=0; atm 1)
return cErrorProdMapNoOverused1;
if (dirtyProduct != -1 && dirtyProduct != p)
return cErrorProdMapNoOverused2;
dirtyProduct = p;
}
proMapNoCount[mapNo]++;
proMol[mapNo] = p;
}
}
}
if (dirtyProduct == -1) // all products are free of duplicate mapping numbers
return cErrorNoError;
int highestMappingNo = 0;
for (int i=1; i 0 && proMapNoCount[i] > 0) {
highestMappingNo = i;
continue;
}
if (eduMapNoCount[i] != 0)
return cErrorMapNoNotInProduct;
if (proMapNoCount[i] != 0)
return cErrorMapNoNotInEduct;
}
int dirtyEduct = -1;
for (int i=1; i<=highestMappingNo; i++) {
if (proMapNoCount[i] > 1) {
if (dirtyEduct != -1 && dirtyEduct != eduMol[i])
return cErrorDupProdMapNoDifEd;
dirtyEduct = eduMol[i];
}
}
StereoMolecule duplicateEduct = new StereoMolecule(mRxn.getReactant(dirtyEduct));
duplicateEduct.ensureHelperArrays(Molecule.cHelperParities);
mRxn.addReactant(duplicateEduct, dirtyEduct);
StereoMolecule mol = mRxn.getProduct(dirtyProduct);
for (int atm=0; atm MAXMPPNGNO)
return false;
boolean successful = true; // default
for (atm=0; atm= 1) && (atomicNo <= MAXATMCNO))
mAtomType[m][atm] = types[atomicNo];
else if (gErrout != null) {
try {
gErrout.write("Rxn: "+mRxn.getName()+", unknown atomic #: "+atomicNo);
gErrout.newLine();
}
catch (IOException ioe) {}
}
}
}
for (int m=0; m mConnType[m][actlAtm][i]) {
if (mConnType[m][actlAtm][i] != 0) {
for (int j=MAXCONNS-1; j>i; j--)
mConnType[m][actlAtm][j] = mConnType[m][actlAtm][j-1];
}
mConnType[m][actlAtm][i] = remotTyp;
break;
}
}
}
}
}
if (gErrout != null) {
for (int atm=0; atm mConnMpNo[m][actlAtm][i]) {
if (mConnMpNo[m][actlAtm][i] != 0) {
for (int j=MAXCONNS-1; j>i; j--)
mConnMpNo[m][actlAtm][j] =
mConnMpNo[m][actlAtm][j-1];
}
mConnMpNo[m][actlAtm][i] = mol.getAtomMapNo(connAtm);
break;
}
}
}
// store sorted mapping no's of connected carbons
// independent of bond order only one entry
if (mAtomType[m][connAtm] == CARBON) {
for (int i=0; i mConnCMNo[m][actlAtm][i]) {
if (mConnCMNo[m][actlAtm][i] != 0) {
for (int j=MAXCONNS-1; j>i; j--)
mConnCMNo[m][actlAtm][j] =
mConnCMNo[m][actlAtm][j-1];
}
mConnCMNo[m][actlAtm][i] = mol.getAtomMapNo(connAtm);
break;
}
}
}
switch (3 & mAtomType[m][connAtm]) { // determine z,pi,sigma,h
case 1:
mSigma[m][actlAtm] += 1;
mPi[m][actlAtm] += mol.getBondOrder(bnd) - 1;
break;
case 2:
mZ[m][actlAtm] += mol.getBondOrder(bnd);
break;
}
}
}
for (int atm=0; atm= mols) && (mRxn.getAtomMappingNo( mol, atm ) == 0)) continue;
if (mCorAtom[m][atm] == 255) {
mAtomFlags[m][atm] |= cAtomChanges + cAtomNoCounterAtom;
continue; // no mapping info available
}
int proMol = mCorProd[m][atm];
int proAtm = mCorAtom[m][atm];
if (gErrout != null) {
try {
gErrout.write("EduAtom: "+atm+" conntype:");
for (int i=0; i<4; i++)
gErrout.write(mConnType[m][atm][i]);
gErrout.newLine();
gErrout.write("ProAtom: "+atm+" conntype:");
for (int i=0; i<4; i++)
gErrout.write(mConnType[proMol][proAtm][i]);
gErrout.newLine();
gErrout.write("EduAtom: "+atm+" connmpno:");
for (int i=0; i<4; i++)
gErrout.write(mConnMpNo[m][atm][i]);
gErrout.newLine();
gErrout.write("ProAtom: "+atm+" connmpno:");
for (int i=0; i<4; i++)
gErrout.write(mConnMpNo[proMol][proAtm][i]);
gErrout.newLine();
}
catch (IOException ioe) {}
}
boolean found = false;
for (int i=0; i 5) { // reset changMsk for nonchanging aromatics
for (int atm=0; atm atm) {
if (ccBndClv == 4) return cErrorCCBondCleavageLimit;
ccBCmol[ccBndClv] = m; // more than 2 CC-bonds cleaved
ccBCatm[ccBndClv] = atm;
ccBndClv++;
ccBCmol[ccBndClv] = m;
ccBCatm[ccBndClv] = oppositeAtom;
ccBndClv++;
}
}
}
}
for (int i=0; i= mRxn.getReactants())) continue;
StereoMolecule kMol = mRxn.getMolecule(k);
for (int l=0; l m)
|| ((oppositeMol == m) && (oppositeAtom > atm))) {
if (ccBndFrm == 4) return cErrorCCBondCreationLimit;
ccBFmol[ccBndFrm] = m; // more than 2 new C-C bonds
ccBFatm[ccBndFrm] = atm;
ccBndFrm++;
ccBFmol[ccBndFrm] = oppositeMol;
ccBFatm[ccBndFrm] = oppositeAtom;
ccBndFrm++;
}
}
}
}
}
}
if (gErrout != null) {
try {
gErrout.write("Form:"+ccBndFrm+", Clv:"+ccBndClv+"; ccBFmols:"+ccBFmol[0]+","+ccBFmol[1]+"; ccBFatms:"+ccBFatm[0]+","+ccBFatm[0]);
gErrout.newLine();
}
catch (IOException ioe) {}
}
if (ccBndFrm == 2 && ccBndClv == 0)
{
// gSC_no++;
int retval = snglCnst(ccBFmol,ccBFatm);
if (retval != 0) return retval;
// gCSC_no++;
}
else if (ccBndFrm == 4 && ccBndClv == 0)
{
// gDC_no++;
int retval = dblCnst(ccBFmol,ccBFatm);
if (retval != 0) return retval;
// gCDC_no++;
}
else if (ccBndFrm == 0 && ccBndClv == 2)
{
// gSF_no++;
int retval = snglFrgm(ccBCmol,ccBCatm);
if (retval != 0) return retval;
// gCSF_no++;
}
else if (ccBndFrm == 0 && ccBndClv == 4)
{
// gDF_no++;
int retval = dblFrgm(ccBCmol,ccBCatm);
if (retval != 0) return retval;
// gCDF_no++;
}
else if (ccBndFrm == 2 && ccBndClv == 2)
{
// gRA_no++;
int retval = rearrang(ccBFmol,ccBFatm,ccBCmol,ccBCatm);
if (retval != 0) return retval;
// gCRA_no++;
}
else if (ccBndFrm != 0 || ccBndClv != 0)
{
if (gErrout != null) {
try {
gErrout.write("Form:"+ccBndFrm+", Clv:"+ccBndClv);
gErrout.newLine();
}
catch (IOException ioe) {}
}
mResult.mClassName = "not classified";
return cErrorComplexReaction;
}
//if (ccBndFrm == 0 && ccBndClv == 0) gRE_no++;
int retval = refuncs();
if (retval != 0) return retval;
if (mUnitRxn == 0) // no skeletal nor refunc unit reactions found
if (mIndexToCreate != cIndexFullPermutation)
return cErrorNoChangingAtoms;
//if (ccBndFrm == 0 && ccBndClv == 0) gCRE_no++;
mResult.mUnitRxns = mUnitRxn;
findClassNam();
markReactionCenters();
return cErrorNoError;
}
private int snglCnst(int[] ccBFmol, int[] ccBFatm) {
int[] strLngth = new int[2];
int[][] strand = new int[2][8]; // strand[atm][0]: molecule
int atm; // strand[atm][1-8]: alpha - delta
for (atm=0; atm<2; atm++) // get atom no's of changing strand
{
strand[atm][0] = ccBFmol[atm];
strand[atm][1] = ccBFatm[atm];
strLngth[atm] = findStrand(strand[atm]);
if (gErrout != null)
try { gErrout.newLine(); } catch (IOException ioe) {}
if (strLngth[atm] < 1) return cErrorForkedOrLongStrand; // branched strand
}
return oneConst(strand[0],strand[1],strLngth[0],strLngth[1]);
}
/**
* manage one Construction Reaction with known strands
* @return
*/
private int oneConst( int[] strand1, int[] strand2, int strLen1, int strLen2 ) {
int[] indexdata = new int[3];
// electrocyclic ring closure
if (strand1[0] == strand2[0] && strand1[1] == strand2[strLen2])
return ringClosure(strand1,strand2,strLen1,strLen2);
int retval = bndSpcDat(strand1,strand2,2,indexdata,0);
if (retval != 0) return retval;
// z-pi-Lists of entire strand
int deltaLst = getDelta(strand1,strLen1,7); // classify first half construction
retval = clssfyHR(indexdata,1,deltaLst,strand1,strLen1,true,6);
if (retval != 0) return retval; // classification error
deltaLst = getDelta(strand2,strLen2,7); // classify second half construction
retval = clssfyHR(indexdata,2,deltaLst,strand2,strLen2,true,7);
if (retval != 0) return retval; // classification error
mResult.mMainClass[mUnitRxn] = S_CONST;
if (mIndexToCreate != cIndexNone) {
DatabaseReaction dbrxn = (DatabaseReaction)mRxn;
putindexbits('n',32,(dbrxn.getReactionYield() << 24) + dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[0]); // write rxn index entry
putindexbits(' ',HRXNBITS,indexdata[1]);
putindexbits('l',HRXNBITS,indexdata[2]);
// if (mBatchClassifierP)
// mBatchClassifierP->incIndexEntries( S_CONST );
if (mIndexToCreate == cIndexFullPermutation) { // supply index for query
putindexbits('c',32,dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[0]);
putindexbits(' ',HRXNBITS,indexdata[2]);
putindexbits('l',HRXNBITS,indexdata[1]);
}
}
mUnitRxn++;
return cErrorNoError;
}
/**
* manage an electrocyclic ring closure reaction
* @return
*/
private int ringClosure( int[] strand1, int[] strand2, int strLen1, int strLen2 ) {
int[] indexdata = new int[4];
int retval = bndSpcDat(strand1,strand2,2,indexdata,0);
if (retval != 0) return retval;
int deltaLst = getDelta(strand1,strLen1,7);
int tempDeltaLst = getDelta(strand2,strLen2,7);
if (tempDeltaLst > deltaLst)
deltaLst = tempDeltaLst;
retval = clssfyCR(indexdata,1,deltaLst,strand1,strLen1,true);
if (retval != 0) return retval; // classification error
indexdata[2] = properties(strand1[0],strand1[1]);
indexdata[3] = properties(strand2[0],strand2[1]);
mResult.mFlashMol[mUnitRxn][6] = strand1[0];
mResult.mFlashAtom[mUnitRxn][6] = strand1[1];
mResult.mFlashMol[mUnitRxn][7] = strand2[0];
mResult.mFlashAtom[mUnitRxn][7] = strand2[1];
mResult.mMainClass[mUnitRxn] = E_RING_C;
if (mIndexToCreate != cIndexNone) {
DatabaseReaction dbrxn = (DatabaseReaction)mRxn;
putindexbits('n',32,(dbrxn.getReactionYield() << 24) + dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[0]); // write rxn index entry
putindexbits(' ',CRXNBITS,indexdata[1]);
putindexbits(' ',PROPBITS,indexdata[2]);
putindexbits('l',PROPBITS,indexdata[3]);
// if (mBatchClassifierP)
// mBatchClassifierP->incIndexEntries( E_RING_C );
if (mIndexToCreate == cIndexFullPermutation)
{
putindexbits('c',32,dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[0]);
putindexbits(' ',CRXNBITS,indexdata[1]);
putindexbits(' ',PROPBITS,indexdata[3]);
putindexbits('l',PROPBITS,indexdata[2]);
}
}
mUnitRxn++;
return cErrorNoError;
}
/**
* calculate z-pi-list from strand no's
*/
private int getDelta(int[] strand, int strLngth, int maxLngth) {
int eduZ,proZ;
int i,mol;
int eduLst,proLst;
eduLst = proLst = 0;
mol = strand[0];
for (i=1; i<=maxLngth; i++)
{
eduLst <<= 4;
proLst <<= 4;
if (i>strLngth) continue;
eduZ = mZ[mol][strand[i]];
proZ = mZ[mCorProd[mol][strand[i]]][mCorAtom[mol][strand[i]]];
if ((eduZ == 4) || (proZ == 4))
{
eduZ -= 1;
proZ -= 1;
}
eduLst += (eduZ<<2) + mPi[mol][strand[i]];
proLst += (proZ<<2) + mPi[mCorProd[mol][strand[i]]][mCorAtom[mol][strand[i]]];
}
if (gErrout != null) {
try {
gErrout.write(String.format("eduLst:%8x, proLst:%8x, deltaLst:%8x\n", eduLst,proLst,eduLst-proLst));
gErrout.newLine();
}
catch (IOException ioe) {}
}
return eduLst-proLst;
}
/**
* double Construction Reaction
* @return
*/
private int dblCnst(int[] ccBFmol, int[] ccBFatm) {
int[] indexdata = new int[6];
int[] strLngth = new int[4];
int strnd;
int hlfRxn1,hlfRxn2,depRxn;
int[] dependnc = new int[2]; // indicates for each educt atom of new formed
// bond, if this an independent half reaction (0)
// or if the appropriate strand ends with an atom
// from that the second bond is formed (atm no)
int[][] strand = new int[4][8]; // strand[atm][0]: molecule
// strand[atm][1-7]: alpha - delta
for (int atm=0; atm<4; atm++) { // get atom no's of changing strands
strand[atm][0] = ccBFmol[atm];
strand[atm][1] = ccBFatm[atm];
strLngth[atm] = findStrand(strand[atm]);
if (gErrout != null)
try { gErrout.newLine(); } catch (IOException ioe) {}
if (strLngth[atm] < 1) return cErrorForkedOrLongStrand; // branched strand
}
for (int i=0; i<2; i++)
dependnc[i] =
+ (strand[i][0] == strand[2][0] && strand[i][1] == strand[2][strLngth[2]] ? 2 : 0)
+ (strand[i][0] == strand[3][0] && strand[i][1] == strand[3][strLngth[3]] ? 3 : 0);
if ((dependnc[0] == 0) && (dependnc[1] == 0)) {
int retval = oneConst(strand[0],strand[1],strLngth[0],strLngth[1]);
if (retval != 0) return retval;
return oneConst(strand[2],strand[3],strLngth[2],strLngth[3]);
}
if ((dependnc[0] == 0) || (dependnc[1] == 0)) {
if (dependnc[0] == 0) {
hlfRxn1 = 0;
hlfRxn2 = (dependnc[1] == 2) ? 3 : 2;
depRxn = 1;
}
else
{
hlfRxn1 = 1;
hlfRxn2 = (dependnc[0] == 2) ? 3 : 2;
depRxn = 0;
}
if (strand[hlfRxn1][0] == strand[depRxn][0])
if (strand[hlfRxn1][1] == strand[depRxn][strLngth[depRxn]])
return cError2AlphasInSameStrand; // both alpha carbons share one strand
if (strand[hlfRxn2][0] == strand[5-hlfRxn2][0])
if (strand[hlfRxn2][1] == strand[5-hlfRxn2][strLngth[5-hlfRxn2]])
return cError2AlphasInSameStrand; // both alpha carbons share one strand
int retval = bndSpcDat(strand[hlfRxn1],strand[depRxn],0,indexdata,0);
if (retval != 0) return retval;
retval = bndSpcDat(strand[hlfRxn2],strand[5-hlfRxn2],2,indexdata,1);
if (retval != 0) return retval;
int deltaLst = getDelta(strand[depRxn],strLngth[depRxn],strLngth[depRxn]);
int tempDeltaLst = getDelta(strand[5-hlfRxn2],strLngth[5-hlfRxn2],strLngth[5-hlfRxn2]);
if (tempDeltaLst > deltaLst) // use strand with higher delta z-pi-list
{
deltaLst = tempDeltaLst;
depRxn = 5-hlfRxn2;
}
// two end hlf rxn
retval = clssfyDR(indexdata,2,deltaLst,true,strand[depRxn],strLngth[depRxn],4);
if (retval != 0) return retval;
deltaLst = getDelta(strand[hlfRxn1],strLngth[hlfRxn1],7); // standard hlf rxn
retval = clssfyHR(indexdata,4,deltaLst,strand[hlfRxn1],strLngth[hlfRxn1],true,6);
if (retval != 0) return retval; // classification error
deltaLst = getDelta(strand[hlfRxn2],strLngth[hlfRxn2],7); // standard hlf rxn
retval = clssfyHR(indexdata,5,deltaLst,strand[hlfRxn2],strLngth[hlfRxn2],true,7);
if (retval != 0) return retval; // classification error
mResult.mMainClass[mUnitRxn] = HD_D_CONST;
if (mIndexToCreate != cIndexNone) {
DatabaseReaction dbrxn = (DatabaseReaction)mRxn;
putindexbits('n',32,(dbrxn.getReactionYield() << 24) + dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[0]); // write rxn index entry
putindexbits(' ',BONDBITS,indexdata[1]);
putindexbits(' ',DRXNBITS,indexdata[2]);
putindexbits(' ',HRXNBITS,indexdata[4]);
putindexbits('l',HRXNBITS,indexdata[5]);
// if (mBatchClassifierP)
// mBatchClassifierP->incIndexEntries( HD_D_CONST );
if (mIndexToCreate == cIndexFullPermutation) {
putindexbits('c',32,dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[1]);
putindexbits(' ',BONDBITS,indexdata[0]);
putindexbits(' ',DRXNBITS,indexdata[3]);
putindexbits(' ',HRXNBITS,indexdata[5]);
putindexbits('l',HRXNBITS,indexdata[4]);
}
}
mUnitRxn++;
for (int i=1; i<=strLngth[depRxn]; i++)
mAtomFlags[strand[depRxn][0]][strand[depRxn][i]] &= ~cAtomNotClassifiedYet;
}
else
{
if (strand[0][0] == strand[1][0])
if (strand[0][1] == strand[1][strLngth[1]])
return cError2AlphasInSameStrand; // both alpha carbons share one strand
if (strand[2][0] == strand[3][0])
if (strand[2][1] == strand[3][strLngth[3]])
return cError2AlphasInSameStrand; // both alpha carbons share one strand
int retval = bndSpcDat(strand[0],strand[1],0,indexdata,0);
if (retval != 0) return retval;
retval = bndSpcDat(strand[2],strand[3],2,indexdata,1);
if (retval != 0) return retval;
for (strnd=0; strnd<2; strnd++)
{
int deltaLst = getDelta(strand[strnd],strLngth[strnd],strLngth[strnd]);
int tempDeltaLst = getDelta(strand[dependnc[strnd]],strLngth[dependnc[strnd]],
strLngth[dependnc[strnd]]);
if (tempDeltaLst > deltaLst)
{
deltaLst = tempDeltaLst;
depRxn = dependnc[strnd];
}
else depRxn = strnd;
retval = clssfyDR(indexdata,2+2*strnd,deltaLst,true,strand[depRxn],strLngth[depRxn],strnd*2+4);
if (retval != 0) return retval;
for (int i=1; i<=strLngth[strnd]; i++)
mAtomFlags[strand[strnd][0]][strand[strnd][i]] &= ~cAtomNotClassifiedYet;
}
mResult.mMainClass[mUnitRxn] = D_D_CONST;
if (mIndexToCreate != cIndexNone) {
DatabaseReaction dbrxn = (DatabaseReaction)mRxn;
putindexbits('n',32,(dbrxn.getReactionYield() << 24) + dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[0]); // write rxn index entry
putindexbits(' ',BONDBITS,indexdata[1]);
putindexbits(' ',DRXNBITS,indexdata[2]);
putindexbits('l',DRXNBITS,indexdata[4]);
// if (mBatchClassifierP)
// mBatchClassifierP->incIndexEntries( D_D_CONST );
if (mIndexToCreate == cIndexFullPermutation) {
putindexbits('c',32,dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[0]);
putindexbits(' ',BONDBITS,indexdata[1]);
putindexbits(' ',DRXNBITS,indexdata[4]);
putindexbits('l',DRXNBITS,indexdata[2]);
putindexbits('c',32,dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[1]);
putindexbits(' ',BONDBITS,indexdata[0]);
putindexbits(' ',DRXNBITS,indexdata[3]);
putindexbits('l',DRXNBITS,indexdata[5]);
putindexbits('c',32,dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[1]);
putindexbits(' ',BONDBITS,indexdata[0]);
putindexbits(' ',DRXNBITS,indexdata[5]);
putindexbits('l',DRXNBITS,indexdata[3]);
}
}
mUnitRxn++;
}
return cErrorNoError;
}
/**
* single fragmentation Reaction
* @return
*/
private int snglFrgm(int[] ccBCmol, int[] ccBCatm) {
int[][] strand = new int[2][8];
int[] strLngth = new int[2];
for (int atm=0; atm<2; atm++) { // get atom no's of changing strand
strand[atm][0] = ccBCmol[atm];
strand[atm][1] = ccBCatm[atm];
strLngth[atm] = findStrand(strand[atm]);
if (gErrout != null)
try { gErrout.newLine(); } catch (IOException ioe) {}
if (strLngth[atm] < 1) return cErrorForkedOrLongStrand; // branched strand
}
return oneFrgm(strand[0],strand[1],strLngth[0],strLngth[1]);
}
/**
* handle one fragmentation Reaction
* @return
*/
private int oneFrgm(int[] strand1, int[] strand2, int strLen1, int strLen2) {
int[] indexdata = new int[3];
// electrocyclic ring opening
if (strand1[0] == strand2[0] && strand1[1] == strand2[strLen2])
return ringOpening(strand1,strand2,strLen1,strLen2);
int retval = bndSpcDat(strand1,strand2,2,indexdata,0);
if (retval != 0) return retval;
int deltaLst = getDelta(strand1,strLen1,7); // classify first half fragmentation
retval = clssfyHR(indexdata,1,-deltaLst,strand1,strLen1,false,6);
if (retval != 0) return retval; // classification error
deltaLst = getDelta(strand2,strLen2,7); // classify second half fragmentation
retval = clssfyHR(indexdata,2,-deltaLst,strand2,strLen2,false,7);
if (retval != 0) return retval; // classification error
mResult.mMainClass[mUnitRxn] = S_FRAG;
if (mIndexToCreate != cIndexNone) {
DatabaseReaction dbrxn = (DatabaseReaction)mRxn;
putindexbits('n',32,(dbrxn.getReactionYield() << 24) + dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[0]); // write rxn index entry
putindexbits(' ',HRXNBITS,indexdata[1]);
putindexbits('l',HRXNBITS,indexdata[2]);
// if (mBatchClassifierP)
// mBatchClassifierP->incIndexEntries( S_FRAG );
if (mIndexToCreate == cIndexFullPermutation) {
putindexbits('c',32,dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[0]);
putindexbits(' ',HRXNBITS,indexdata[2]);
putindexbits('l',HRXNBITS,indexdata[1]);
}
}
mUnitRxn++;
return cErrorNoError;
}
/**
* manage an electrocyclic ring opening reaction
* @return
*/
private int ringOpening(int[] strand1, int[] strand2, int strLen1, int strLen2) {
int[] indexdata = new int[4];
int retval = bndSpcDat(strand1,strand2,2,indexdata,0);
if (retval != 0) return retval;
int deltaLst = getDelta(strand1,strLen1,7);
int tempDeltaLst = getDelta(strand2,strLen2,7);
if (tempDeltaLst < deltaLst)
deltaLst = tempDeltaLst;
retval = clssfyCR(indexdata,1,-deltaLst,strand1,strLen1,false);
if (retval != 0) return retval; // classification error
indexdata[2] = properties(strand1[0],strand1[1]);
indexdata[3] = properties(strand2[0],strand2[1]);
mResult.mFlashMol[mUnitRxn][6] = strand1[0];
mResult.mFlashAtom[mUnitRxn][6] = strand1[1];
mResult.mFlashMol[mUnitRxn][7] = strand2[0];
mResult.mFlashAtom[mUnitRxn][7] = strand2[1];
mResult.mMainClass[mUnitRxn] = E_RING_O;
if (mIndexToCreate != cIndexNone) {
DatabaseReaction dbrxn = (DatabaseReaction)mRxn;
putindexbits('n',32,(dbrxn.getReactionYield() << 24) + dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[0]); // write rxn index entry
putindexbits(' ',CRXNBITS,indexdata[1]);
putindexbits(' ',PROPBITS,indexdata[2]);
putindexbits('l',PROPBITS,indexdata[3]);
// if (mBatchClassifierP)
// mBatchClassifierP->incIndexEntries( E_RING_O );
if (mIndexToCreate == cIndexFullPermutation)
{
putindexbits('c',32,dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[0]);
putindexbits(' ',CRXNBITS,indexdata[1]);
putindexbits(' ',PROPBITS,indexdata[3]);
putindexbits('l',PROPBITS,indexdata[2]);
}
}
mUnitRxn++;
return cErrorNoError;
}
/**
* double Fragmentation Reaction
* @return
*/
private int dblFrgm(int[] ccBCmol, int[] ccBCatm) {
int[] indexdata = new int[6];
int[] strLngth = new int[4];
int hlfRxn1,hlfRxn2,depRxn;
int[] dependnc = new int[2]; // indicates for each educt atom of new formed
// bond, if this an independent half reaction (0)
// or if the appropriate strand ends with an atom
// from that the second bond is formed (atm no)
int[][] strand = new int[4][8]; // strand[atm][0]: molecule
// strand[atm][1-8]: alpha - delta
for (int atm=0; atm<4; atm++) { // get atom no's of changing strands
strand[atm][0] = ccBCmol[atm];
strand[atm][1] = ccBCatm[atm];
strLngth[atm] = findStrand(strand[atm]);
if (gErrout != null)
try { gErrout.newLine(); } catch (IOException ioe) {}
if (strLngth[atm] < 1) return cErrorForkedOrLongStrand; // branched strand
}
for (int i=0; i<2; i++)
dependnc[i] =
+ (strand[i][0] == strand[2][0] && strand[i][1] == strand[2][strLngth[2]] ? 2 : 0)
+ (strand[i][0] == strand[3][0] && strand[i][1] == strand[3][strLngth[3]] ? 3 : 0);
if ((dependnc[0] == 0) && (dependnc[1] == 0)) {
int retval = oneFrgm(strand[0],strand[1],strLngth[0],strLngth[1]);
if (retval != 0) return retval;
return oneFrgm(strand[2],strand[3],strLngth[2],strLngth[3]);
}
if ((dependnc[0] == 0) || (dependnc[1] == 0))
{
if (dependnc[0] == 0)
{
hlfRxn1 = 0;
hlfRxn2 = (dependnc[1] == 2) ? 3 : 2;
depRxn = 1;
}
else
{
hlfRxn1 = 1;
hlfRxn2 = (dependnc[0] == 2) ? 3 : 2;
depRxn = 0;
}
if (strand[hlfRxn1][0] == strand[depRxn][0])
if (strand[hlfRxn1][1] == strand[depRxn][strLngth[depRxn]])
return cError2AlphasInSameStrand; // both alpha carbons share one strand
if (strand[hlfRxn2][0] == strand[5-hlfRxn2][0])
if (strand[hlfRxn2][1] == strand[5-hlfRxn2][strLngth[5-hlfRxn2]])
return cError2AlphasInSameStrand; // both alpha carbons share one strand
int retval = bndSpcDat(strand[hlfRxn1],strand[depRxn],0,indexdata,0);
if (retval != 0) return retval;
retval = bndSpcDat(strand[hlfRxn2],strand[5-hlfRxn2],2,indexdata,1);
if (retval != 0) return retval;
int deltaLst = getDelta(strand[depRxn],strLngth[depRxn],strLngth[depRxn]);
int tempDeltaLst = getDelta(strand[5-hlfRxn2],strLngth[5-hlfRxn2],strLngth[5-hlfRxn2]);
if (tempDeltaLst < deltaLst) { // lower delta z-pi-list here gives higher after inversion
deltaLst = tempDeltaLst;
depRxn = 5-hlfRxn2;
}
// two end hlf rxn
retval = clssfyDR(indexdata,2,-deltaLst,false,strand[depRxn],strLngth[depRxn],4);
if (retval != 0) return retval;
deltaLst = getDelta(strand[hlfRxn1],strLngth[hlfRxn1],7); // standard hlf rxn
retval = clssfyHR(indexdata,4,-deltaLst,strand[hlfRxn1],strLngth[hlfRxn1],false,6);
if (retval != 0) return retval; // classification error
deltaLst = getDelta(strand[hlfRxn2],strLngth[hlfRxn2],7); // standard hlf rxn
retval = clssfyHR(indexdata,5,-deltaLst,strand[hlfRxn2],strLngth[hlfRxn2],false,7);
if (retval != 0) return retval; // classification error
mResult.mMainClass[mUnitRxn] = HD_D_FRAG;
if (mIndexToCreate != cIndexNone) {
DatabaseReaction dbrxn = (DatabaseReaction)mRxn;
putindexbits('n',32,(dbrxn.getReactionYield() << 24) + dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[0]); // write rxn index entry
putindexbits(' ',BONDBITS,indexdata[1]);
putindexbits(' ',DRXNBITS,indexdata[2]);
putindexbits(' ',HRXNBITS,indexdata[4]);
putindexbits('l',HRXNBITS,indexdata[5]);
// if (mBatchClassifierP)
// mBatchClassifierP->incIndexEntries( HD_D_FRAG );
if (mIndexToCreate == cIndexFullPermutation)
{
putindexbits('c',32,dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[1]);
putindexbits(' ',BONDBITS,indexdata[0]);
putindexbits(' ',DRXNBITS,indexdata[3]);
putindexbits(' ',HRXNBITS,indexdata[5]);
putindexbits('l',HRXNBITS,indexdata[4]);
}
}
mUnitRxn++;
for (int i=1; i<=strLngth[depRxn]; i++)
mAtomFlags[strand[depRxn][0]][strand[depRxn][i]] &= ~cAtomNotClassifiedYet;
}
else
{
if (strand[0][0] == strand[1][0])
if (strand[0][1] == strand[1][strLngth[1]])
return cError2AlphasInSameStrand; // both alpha carbons share one strand
if (strand[2][0] == strand[3][0])
if (strand[2][1] == strand[3][strLngth[3]])
return cError2AlphasInSameStrand; // both alpha carbons share one strand
int retval = bndSpcDat(strand[0],strand[1],0,indexdata,0);
if (retval != 0) return retval;
retval = bndSpcDat(strand[2],strand[3],2,indexdata,1);
if (retval != 0) return retval;
for (int strnd=0; strnd<2; strnd++) {
int deltaLst = getDelta(strand[strnd],strLngth[strnd],strLngth[strnd]);
int tempDeltaLst = getDelta(strand[dependnc[strnd]],strLngth[dependnc[strnd]],strLngth[dependnc[strnd]]);
if (tempDeltaLst < deltaLst) {
deltaLst = tempDeltaLst;
depRxn = dependnc[strnd];
}
else depRxn = strnd;
retval = clssfyDR(indexdata,2+2*strnd,-deltaLst,false,strand[depRxn],strLngth[depRxn],strnd*2+4);
if (retval != 0) return retval;
for (int i=1; i<=strLngth[strnd]; i++)
mAtomFlags[strand[strnd][0]][strand[strnd][i]] &= ~cAtomNotClassifiedYet;
}
mResult.mMainClass[mUnitRxn] = D_D_FRAG;
if (mIndexToCreate != cIndexNone) {
DatabaseReaction dbrxn = (DatabaseReaction)mRxn;
putindexbits('n',32,(dbrxn.getReactionYield() << 24) + dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[0]); // write rxn index entry
putindexbits(' ',BONDBITS,indexdata[1]);
putindexbits(' ',DRXNBITS,indexdata[2]);
putindexbits('l',DRXNBITS,indexdata[4]);
// if (mBatchClassifierP)
// mBatchClassifierP->incIndexEntries( D_D_FRAG );
if (mIndexToCreate == cIndexFullPermutation)
{
putindexbits('c',32,dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[0]);
putindexbits(' ',BONDBITS,indexdata[1]);
putindexbits(' ',DRXNBITS,indexdata[4]);
putindexbits('l',DRXNBITS,indexdata[2]);
putindexbits('c',32,dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[1]);
putindexbits(' ',BONDBITS,indexdata[0]);
putindexbits(' ',DRXNBITS,indexdata[3]);
putindexbits('l',DRXNBITS,indexdata[5]);
putindexbits('c',32,dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[1]);
putindexbits(' ',BONDBITS,indexdata[0]);
putindexbits(' ',DRXNBITS,indexdata[5]);
putindexbits('l',DRXNBITS,indexdata[3]);
}
}
mUnitRxn++;
}
return cErrorNoError;
}
/**
* rearrangement
* @return
*/
private int rearrang(int[] ccBFmol, int[] ccBFatm, int[] ccBCmol, int[] ccBCatm) {
int[] strLngth = new int[4];
int[] indexdata = new int[5];
int[] dependnc = new int[2];// indicates for each educt atom of new formed
// bond, if this an independent half reaction (0)
// or if the appropriate strand ends with an atom
// from that the second bond is formed (atm no)
int[][] strand = new int[4][8]; // strand[atm][0]: molecule
// strand[atm][1-8]: alpha - delta
for (int i=0; i<2; i++) {
strand[i][0] = ccBFmol[i];
strand[i][1] = ccBFatm[i];
strLngth[i] = findStrand(strand[i]);
if (strLngth[i] < 1) return cErrorForkedOrLongStrand; // branched strand
int strEnd = strand[i][strLngth[i]];
for (int j=0; j<2; j++)
if (strEnd == ccBCatm[j] && ccBFmol[i] == ccBCmol[j])
dependnc[i] = j+2;
}
for (int i=0; i<2; i++) {
strand[i+2][0] = ccBCmol[i];
strand[i+2][1] = ccBCatm[i];
strLngth[i+2] = findStrand(strand[i+2]);
if (strLngth[i+2] < 1) return cErrorForkedOrLongStrand; // branched strand
}
if ((dependnc[0] == 0) && (dependnc[1] == 0)) {
int retval = oneConst(strand[0],strand[1],strLngth[0],strLngth[1]);
if (retval != 0) return retval;
return oneFrgm(strand[2],strand[3],strLngth[2],strLngth[3]);
}
if ((dependnc[0] == 0) || (dependnc[1] == 0)) {
int hlfCon,hlfFrg,depRxn;
if (dependnc[0] == 0) {
hlfCon = 0;
hlfFrg = (dependnc[1] == 2) ? 3 : 2;
depRxn = 1;
}
else
{
hlfCon = 1;
hlfFrg = (dependnc[0] == 2) ? 3 : 2;
depRxn = 0;
}
mResult.mRearStrandLen[0] = strLngth[depRxn];
int retval = bndSpcDat(strand[hlfCon],strand[depRxn],0,indexdata,0);
if (retval != 0) return retval;
retval = bndSpcDat(strand[hlfFrg],strand[5-hlfFrg],2,indexdata,1);
if (retval != 0) return retval;
int deltaLst = getDelta(strand[depRxn],strLngth[depRxn],7); // two end hlf rearr
retval = clssfyRA(indexdata,2,deltaLst,
strand[depRxn],strLngth[depRxn],4);
if (retval != 0) return retval;
deltaLst = getDelta(strand[hlfCon],strLngth[hlfCon],7); // contruction
retval = clssfyHR(indexdata,3,deltaLst,strand[hlfCon],strLngth[hlfCon],true,6);
if (retval != 0) return retval; // classification error
deltaLst = getDelta(strand[hlfFrg],strLngth[hlfFrg],7); // fragmentation
retval = clssfyHR(indexdata,4,-deltaLst,strand[hlfFrg],strLngth[hlfFrg],false,7);
if (retval != 0) return retval; // classification error
mResult.mMainClass[mUnitRxn] = HD_REAR;
if (mIndexToCreate != cIndexNone) {
DatabaseReaction dbrxn = (DatabaseReaction)mRxn;
putindexbits('n',32,(dbrxn.getReactionYield() << 24) + dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[0]); // write rxn index entry
putindexbits(' ',BONDBITS,indexdata[1]);
putindexbits(' ',REARBITS,indexdata[2]);
putindexbits(' ',HRXNBITS,indexdata[3]);
putindexbits('l',HRXNBITS,indexdata[4]);
// if (mBatchClassifierP)
// mBatchClassifierP->incIndexEntries( HD_REAR );
}
mUnitRxn++;
for (int i=1; i<=strLngth[depRxn]; i++)
mAtomFlags[strand[depRxn][0]][strand[depRxn][i]] &= ~cAtomNotClassifiedYet;
}
else {
for (int strnd=0; strnd<2; strnd++) {
mResult.mRearStrandLen[strnd] = strLngth[strnd];
int retval = bndSpcDat( strand[strnd*2],strand[strnd*2+1],
strnd*2,indexdata,strnd);
if (retval != 0) return retval;
int deltaLst = getDelta(strand[strnd],strLngth[strnd],7);
retval = clssfyRA(indexdata,2+strnd,deltaLst,
strand[strnd],strLngth[strnd],strnd*2+4);
if (retval != 0) return retval;
for (int i=1; i<=strLngth[strnd]; i++)
mAtomFlags[strand[strnd][0]][strand[strnd][i]] &= ~cAtomNotClassifiedYet;
}
mResult.mMainClass[mUnitRxn] = D_REAR;
if (mIndexToCreate != cIndexNone) {
DatabaseReaction dbrxn = (DatabaseReaction)mRxn;
putindexbits('n',32,(dbrxn.getReactionYield() << 24) + dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[0]); // write rxn index entry
putindexbits(' ',BONDBITS,indexdata[1]);
putindexbits(' ',REARBITS,indexdata[2]);
putindexbits('l',REARBITS,indexdata[3]);
// if (mBatchClassifierP)
// mBatchClassifierP->incIndexEntries( D_REAR );
if (mIndexToCreate == cIndexFullPermutation) {
putindexbits('c',32,dbrxn.getReactionRegNo());
putindexbits(' ',BONDBITS,indexdata[0]);
putindexbits(' ',BONDBITS,indexdata[1]);
putindexbits(' ',REARBITS,indexdata[3]);
putindexbits('l',REARBITS,indexdata[2]);
}
}
mUnitRxn++;
}
return cErrorNoError;
}
/**
* classify simple half reaction
* @return
*/
private int clssfyHR(int[] HRindex, int hr, int deltazp,
int[] strand, int strLngth, boolean construction, int flshBase) {
int[] fgroup = new int[4];
int[] fAtm = new int[4];
mResult.mFlashMol[mUnitRxn][flshBase] = strand[0];
mResult.mFlashAtom[mUnitRxn][flshBase] = strand[1];
for (int i=0; i maxgroup)
{
maxgroup = fgroup[j];
maxatm = fAtm[j];
}
}
}
HRindex[hr] |= maxgroup;
mResult.mChngGrps[mUnitRxn][flshBase-6] = maxgroup;
mResult.mFlashMol[mUnitRxn][flshBase+2] = flashMol;
mResult.mFlashAtom[mUnitRxn][flshBase+2] = maxatm;
return cErrorNoError;
}
// #if WRITE_DELTA
if (gErrout != null) {
try {
gErrout.write(String.format("HR-deltaZP: %x",deltazp));
gErrout.newLine();
}
catch (IOException ioe) {}
}
return cErrorHRClassifyError;
}
/**
* classify ring closure reaction
* @return
*/
private int clssfyCR(int[] CRindex, int cr, int deltazp, int[] strand, int strLen, boolean ringClosure) {
for (int i=0; i 1) wdrawing = 1;
}
}
}
DRindex[dr] <<= 2;
DRindex[dr] |= donating + wdrawing;
DRindex[dr+1] = (0xFFFFFFC3 & DRindex[dr]) | (16*sigma2 + 4*sigma1);
return cErrorNoError;
}
}
// #if WRITE_DELTA
if (gErrout != null) {
try {
gErrout.write(String.format("DR-deltaZP: %x",deltazp));
gErrout.newLine();
}
catch (IOException ioe) {}
}
return cErrorDRClassifyError;
}
/**
* classify two end half rearrangement
* @return
*/
private int clssfyRA(int[] RAindex, int ra, int deltazp, int[] strand, int strLngth, int flshBase) {
int i,mol,formAtm,clvgAtm;
mResult.mFlashMol[mUnitRxn][flshBase] = strand[0];
mResult.mFlashAtom[mUnitRxn][flshBase] = strand[1];
mResult.mFlashMol[mUnitRxn][flshBase+1] = strand[0];
mResult.mFlashAtom[mUnitRxn][flshBase+1] = strand[strLngth];
for (i=0; i= entries) || (deltazp > mClassificationData.getRRxnDelta(poin))) {
poin -= step;
step >>= 1;
}
else if (deltazp < mClassificationData.getRRxnDelta(poin)) {
poin += step;
step >>= 1;
}
else {
mResult.mUnitName[mUnitRxn] = mClassificationData.getRRefuncName( poin );
mResult.mClassResult[mUnitRxn] = poin;
return cErrorNoError;
}
}
// #if WRITE_DELTA
if (gErrout != null) {
try {
gErrout.write(String.format("RE-deltaZP: %x",deltazp));
gErrout.newLine();
}
catch (IOException ioe) {}
}
return cErrorREClassifyError;
}
/**
* store C-C bond specific data
* @return
*/
private int bndSpcDat(int[] strand1, int[] strand2, int flshBase, int[] bndIndex, int bi) {
bndIndex[bi] = 0;
int m1 = strand1[0];
int m2 = strand2[0];
int atm1 = strand1[1];
int atm2 = strand2[1];
mResult.mFlashAtom[mUnitRxn][flshBase] = m1;
mResult.mFlashAtom[mUnitRxn][flshBase] = atm1;
mResult.mFlashAtom[mUnitRxn][flshBase+1] = m2;
mResult.mFlashAtom[mUnitRxn][flshBase+1] = atm2;
if (m1 != m2) return cErrorNoError;
// intermolecular because of different educt molecules
if (conLngth(m1,atm1,atm2,false) != 0) bndIndex[bi] = 16; // bit 4: intramolecular
StereoMolecule mol1 = mRxn.getMolecule(m1);
for (int i=0; i 0) if (connLength > 15) connLength = 15;
bndIndex[bi] |= connLength; // bit 0-3: new ring's size
return cErrorNoError;
}
/**
* classify refunctionalisation reactions
* @return
*/
private int refuncs() {
int[][] leavType = new int[8][MAXCONNS]; // all leaving groups within one refunc
int[][] incoType = new int[8][MAXCONNS]; // all incoming groups within one refunc
int[] nrofLeav = new int[8];
int[] nrofInco = new int[8]; // appropriate numbers of inc/leav grps
int[][] leavAtm = new int[8][MAXCONNS]; // corresponding atom numbers
int[][] incoAtm = new int[8][MAXCONNS];
int[][] stereo = new int[8][1];
int[][] strand = new int[2][8];
int[][][] fGrpCombs = new int[MAXUNITS][MAXINDICES][4];
int[][] REindex = new int[MAXUNITS][2];
// contains index information for all single refunc rxns within one
// REACCS entry (in case mIndexToCreate == cIndexOnePermToFile) or
// all possible indices of one refunc rxn due to different combinations
// of functional groups (mIndexToCreate == cIndexFullPermutation)
int[] delLst = new int[2];
int[] dummy = new int[1];
for (int mol=0; mol delLst[0]) ? 1 : 0;
int retval = clssfyRE(delLst[higher]);
if (retval != 0) return retval;
for (int i=1; i<=strLngth; i++)
mAtomFlags[mol][strand[0][i]] &= ~cAtomNotClassifiedYet;
cChange++;
if (strLngth == 1) mResult.mMainClass[mUnitRxn] = C1_REFU;
else mResult.mMainClass[mUnitRxn] = LONG_REFU;
for (int i=1; i<=strLngth; i++) // initialize arrays for changing groups
for (int j=0; j<4; j++) {
incoType[i][j] = 0;
leavType[i][j] = 0;
}
for (int i=1; i<=strLngth; i++) { // get class numbers of changing groups
int actlAtm = strand[higher][i];
int proMol = mCorProd[mol][actlAtm];
int proAtm = mCorAtom[mol][actlAtm];
// incoming atoms
nrofInco[i] = leaving(proMol,proAtm,mol,actlAtm,incoType[i],incoAtm[i],stereo[i]);
for (int j=0; j> 4;
if ((mClassificationData.getRRxnDef( mResult.mClassResult[mUnitRxn], i, j ) & 64) != 0)
fGrpCombs[mUnitRxn][i][j] = incoType[strndPos][num];
else
fGrpCombs[mUnitRxn][i][j] = leavType[strndPos][num];
}
}
boolean schonda = false;
for (int j=firstRefuUnit; j>1); k++) {
if (fGrpCombs[mUnitRxn][k][0] == fGrpCombs[j][0][0]
&& fGrpCombs[mUnitRxn][k][1] == fGrpCombs[j][0][1]
&& fGrpCombs[mUnitRxn][k][2] == fGrpCombs[j][0][2]
&& fGrpCombs[mUnitRxn][k][3] == fGrpCombs[j][0][3]) {
schonda = true;
break;
}
}
}
if (REindex[mUnitRxn][0] == REindex[j][1]) {
for (int k=(mClassificationData.getRRxnMasks( mResult.mClassResult[mUnitRxn] ) >>1);
k> 4;
if ((mClassificationData.getRRxnDef( mResult.mClassResult[mUnitRxn], 0, j ) & 64) != 0) {
mResult.mFlashMol[mUnitRxn][j+2] = mCorProd[mol][strand[higher][1]];
mResult.mFlashAtom[mUnitRxn][j+2] = incoAtm[strndPos][num];
}
else {
mResult.mFlashMol[mUnitRxn][j+2] = mol;
mResult.mFlashAtom[mUnitRxn][j+2] = leavAtm[strndPos][num];
}
}
mUnitRxn++;
if (mUnitRxn == MAXUNITS) return cErrorUnitReactionLimit;
}
if (mUnitRxn == MAXUNITS) return cErrorUnitReactionLimit;
}
if (cChange != 0) {
if (mIndexToCreate != cIndexNone) {
DatabaseReaction dbrxn = (DatabaseReaction)mRxn;
if (mIndexToCreate == cIndexOnePermToFile) { // write one entry per separated unit rxn to file
int unitRxns = mUnitRxn;
for (mUnitRxn=firstRefuUnit; mUnitRxnincIndexEntries( mResult.mMainClass[mUnitRxn] );
}
}
else if (mIndexToCreate == cIndexFullPermutation) { // store all combinations of all unit rxns into array
int unitRxns = mUnitRxn;
for (mUnitRxn=firstRefuUnit; mUnitRxn= (mClassificationData.getRRxnMasks( mResult.mClassResult[mUnitRxn] )/2))) {
putindexbits('c',32,dbrxn.getReactionRegNo());
putindexbits(' ',midBits,REindex[mUnitRxn][1]);
putindexbits(' ',8,fGrpCombs[mUnitRxn][j][0]);
putindexbits(' ',8,fGrpCombs[mUnitRxn][j][1]);
putindexbits(' ',8,fGrpCombs[mUnitRxn][j][2]);
putindexbits('l',8,fGrpCombs[mUnitRxn][j][3]);
}
else {
putindexbits('c',32,dbrxn.getReactionRegNo());
putindexbits(' ',midBits,REindex[mUnitRxn][0]);
putindexbits(' ',8,fGrpCombs[mUnitRxn][j][0]);
putindexbits(' ',8,fGrpCombs[mUnitRxn][j][1]);
putindexbits(' ',8,fGrpCombs[mUnitRxn][j][2]);
putindexbits('l',8,fGrpCombs[mUnitRxn][j][3]);
}
}
}
}
}
}
int hChange = 0; // refunctionalisation at non-carbon atom
firstRefuUnit = mUnitRxn;
for (int m=0; m 0)
mResult.mUnitName[mUnitRxn] = "R"+deltaZ+Molecule.cAtomLabel[mol.getAtomicNo(atm)];
else
mResult.mUnitName[mUnitRxn] = "S,"+Molecule.cAtomLabel[mol.getAtomicNo(atm)];
mAtomFlags[m][atm] &= ~cAtomNotClassifiedYet;
mResult.mMainClass[mUnitRxn] = HETERO_REFU;
hChange++;
if (mIndexToCreate == cIndexNone) { mUnitRxn++; continue; }
incoType[0][0] = incoType[0][1] = 0;
nrofInco[0] = leaving(mCorProd[m][atm],mCorAtom[m][atm],m,atm,incoType[0],incoAtm[0],dummy);
while (nrofInco[0] > 2) {
boolean found = false;
for (int j=0; !found && j 2) {
boolean found = false;
for (int j=0; !found && jincIndexEntries( HETERO_REFU );
}
}
else if (mIndexToCreate == cIndexFullPermutation) { // store all combinations of one(!) refunc rxn in array
int unitRxns = mUnitRxn;
for (mUnitRxn=firstRefuUnit; mUnitRxn 0)) return;
if (bits != 0) mask = 1 << (bits-1);
for (int i=0; ilongToIndexFile( &data,
// mClassResultP->getMainClass( mUnitRxn ) );
data = 0;
availbits = 32;
}
data <<= 1;
if ((mask & datum) != 0) data |= 1;
mask >>= 1;
availbits--;
}
if (mode == 'l') { // write last bits of entry
data <<= availbits;
if (mIndexToCreate == cIndexFullPermutation)
mResult.mIndex[mUnitRxn][indexnum][indexpoin] = data;
// if (mIndexToCreate == cIndexOnePermToFile)
// mBatchClassifierP->longToIndexFile( &data,
// mClassResultP->getMainClass( mUnitRxn ) );
}
}
/**
* if (checkProduct == 0) then return length of shortest chain between two
* atoms except direct bond (any mol allowed )
* if (checkProduct == 1) then return length of shortest chain between two
* educt atoms, that exists in the product as well
* (only educt atoms allowed)
* @param mol
* @param atm1
* @param atm2
* @param checkProduct
* @return
*/
private int conLngth( int mol, int atm1, int atm2, boolean checkProduct ) {
int[][] mask = new int[2][MAXATOMS];
int[] lastAtm = new int[MAXATOMS];
int[] proAtm = new int[MAXATOMS];
StereoMolecule mol1 = mRxn.getMolecule(mol);
for (int atm=0; atm");
}
catch (IOException ioe) {}
}
while (true) {
boolean overflow = false;
int atm = -1;
do {
overflow = (histConn[histpoin] == mol.getConnAtoms(histAtms[histpoin]));
if (overflow) break;
atm = mol.getConnAtom(histAtms[histpoin], histConn[histpoin]++);
} while ((atm == histAtms[histpoin-1])
|| (foundMsk[atm] != 0)
|| (mAtomType[m][atm] != CARBON));
if (!overflow) {
if (frgAtmNo > MAXFATMS)
return cErrorFragmentAtomLimit; // fragment carbons exceed limit
fragAtms[frgAtmNo] = atm;
foundMsk[atm] = frgAtmNo++;
histAtms[++histpoin] = atm;
histConn[histpoin] = 0;
if (gErrout != null)
try { gErrout.write(" "+atm); } catch (IOException ioe) {}
}
else {
if (--histpoin == 0) break;
}
}
fragAtms[0] = frgAtmNo-1;
if (gErrout != null)
try { gErrout.newLine(); } catch (IOException ioe) {}
return cErrorNoError;
}
/*/////////////////////////////////////////////////////////////////// private //
void flagAromaticBonds( int mol, int aromAtms[] )
////////////////////////////////////////////////////////////////////////////////
{
int atm,aroms,i,j,k;
if (!aromAtms[0])
return;
aroms = 31 & (int)aromAtms[0];
for (i=2; i<=aroms; i++)
{
atm = aromAtms[i];
for (j=1; j 0)
if (eCharge > pCharge)
for (int i=0; i 4) return 0;
if (!mol2.isAtomStereoCenter(atm2)) return 0;
if (!mol1.isAtomStereoCenter(atm1)) return 1;
// for (i=0; i 8) continue; // not likely to happen
grpAtm[nrofTypes] = connAtm;
grpMapNo[nrofTypes] = mol.getAtomMapNo(connAtm);
type[nrofTypes] = gettyp( m, connAtm, atm, fGrpBndOrdr, secCrit[nrofTypes] );
nrofTypes++;
for (int j=1; j C-C-O-CH2-Me
* comparing the mapping numbers of CO and CH2 answers if a real substitution of
* acetate by ethanolate or a reduction takes place !
* @param atm atom Y
* @param xAtm atom A
* @param bndOrdr bond order A-Y
* @return type of leaving group connected to atom A in A-Y[-Z]
*/
private int gettyp(int m, int atm, int xAtm, int bndOrdr, int[] secCrit ) {
int connAtm,i;
final int[] fGrpClass = { 0,
2, 0,
40, 48, 56, 0, 0, 0,216, 0,
36, 42, 50, 58, 0, 0,220, 0,
37, 44, 64, 68, 70, 80, 84, 85, 86, 87, 72, 76, 52, 59,232, 0,222, 0,
38, 45, 65, 69, 71, 82, 0, 89, 90, 91, 73, 77, 54, 60, 62, 0,223, 0,
39, 46, 66, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111,
69, 71, 83, 92, 93, 94, 95, 74, 78, 55, 61, 63, 0, 0, 0,
0, 47, 67, 114,115,116,117,118,119,120,121,122,123,124,125,126,127,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 6,222, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
secCrit[0] = 0; // default for uncomplicated leaving groups
secCrit[1] = 0;
StereoMolecule mol = mRxn.getMolecule(m);
if (mol.getAtomicNo(atm) == 7) { // nitrogen functionalities
if (mol.getAtomMapNo(atm) != 0) {
secCrit[0] = mol.getAtomMapNo(atm);
secCrit[1] = bndOrdr;
}
if (bndOrdr == 3) return 184; // nitrile
if (bndOrdr == 2) {
if (mol.getAtomCharge(atm) == 1) { // positive charge at N
switch (mZ[m][atm]) {
case 0: return 176; // immonium
case 1: return 178; // nitrones etc.
default: return 179; // iso nitro etc.
}
}
else
{
switch (mZ[m][atm]) {
case 0: return 180; // imine
default: return 182; // oximes etc.
}
}
}
else
{
if (mol.getAtomCharge(atm) == 1) { // positive charge at N
if (mZ[m][atm] == 1) return 172; // amine oxide
if (mZ[m][atm] > 1) return 174; // nitro etc.
switch (mPi[m][atm]) {
case 0: return 168; // ammonium
case 1: return 170; // immonium
default: return 171; // isonitrile
}
}
if (mZ[m][atm] == 0) { // no hetero atoms at N
if (mPi[m][atm] == 0) { // no double bonds to C
switch (mSigma[m][atm]) {
case 1: return 160; // prim amine
case 2: return 161; // sec amine
default: return 162; // tert amine
}
}
else return 163; // imine -N=C
}
else if (mZ[m][atm] == 1) { // z=1 at N
return 164;
}
else { // z=2 at N
return 166;
}
}
}
else if (mol.getAtomicNo(atm) == 8) { // oxygen functionalities
if (bndOrdr == 2) return 156; // carbonyl
connAtm = -1;
for (i=0; i