int ChampModelToPat()

in contrib/champ/champ.c [1335:1666]


int ChampModelToPat(CChamp *I,PyObject *model) 
{

  int nAtom,nBond;
  int a;
  int ok=true;
  int cur_atom=0,last_atom = 0;
  ListAtom *at;
  int cur_bond=0,last_bond = 0;
  ListBond *bd;
  int charge=0,order=1;
  int result = 0;
  int atom1,atom2;
  int *atom_index = NULL;
  int std_flag;
  char *c;

  PyObject *atomList = NULL;
  PyObject *bondList = NULL;
  PyObject *molec = NULL;
  PyObject *atom = NULL;
  PyObject *bnd = NULL;
  PyObject *index = NULL;
  PyObject *tmp = NULL;

  nAtom=0;
  nBond=0;

  atomList = PyObject_GetAttrString(model,"atom");
  if(atomList) 
    nAtom = PyList_Size(atomList);
  else 
    ok=err_message("ChampModel2Pat","can't get atom list");

  atom_index = mac_malloc_array(int,nAtom);

  if(ok) { 
	 for(a=nAtom-1;a>=0;a--) /* reverse order */
		{
        atom = PyList_GetItem(atomList,a);
        if(!atom) 
          ok=err_message("ChampModel2Pat","can't get atom");

        cur_atom = ListElemNewZero(&I->Atom);
        at = I->Atom + cur_atom;
        at->link = last_atom;
        last_atom = cur_atom;
        at->chempy_atom = atom;
        Py_INCREF(at->chempy_atom);

        atom_index[a] = cur_atom; /* for bonds */

        if(ok) {
          tmp = PyObject_GetAttrString(atom,"name");
          if (tmp)
            ok = PConvPyObjectToStrMaxClean(tmp,at->name,NAM_SIZE-1);
          if(!ok) 
            err_message("ChampModel2Pat","can't read name");
          Py_XDECREF(tmp);
        }

        if(ok) {
          if(PTruthCallStr(atom,"has","flags")) {         
            tmp = PyObject_GetAttrString(atom,"flags");
            if (tmp)
              ok = PConvPyObjectToInt(tmp,(int*)&at->tag);
            if(!ok) 
              err_message("ChampModel2Pat","can't read flags");
            Py_XDECREF(tmp);
          } else {
            at->tag = 0;
          }
        }

        if(ok) {
          if(PTruthCallStr(atom,"has","index")) {  /* note -- chempy models have 1-based index attributes
                                                      even though the arrays are zero-based */
            tmp = PyObject_GetAttrString(atom,"index");
            if (tmp)
              ok = PConvPyObjectToInt(tmp,(int*)&at->ext_index);
            if(!ok) 
              err_message("ChampModel2Pat","can't read index");
            Py_XDECREF(tmp);
          } else {
            at->index = 0;
          }
        }

        if(ok) {
          if(PTruthCallStr(atom,"has","coord")) {         
            tmp = PyObject_GetAttrString(atom,"coord");
            if (tmp)
              ok = PConvPyListToFloatArrayInPlace(tmp,at->coord,3);
            if(!ok) 
              err_message("ChampModel2Pat","can't read coordinates");
            Py_XDECREF(tmp);
          }
        }

        if(ok) {
          if(PTruthCallStr(atom,"has","formal_charge")) { 
            tmp = PyObject_GetAttrString(atom,"formal_charge");
            if (tmp)
              ok = PConvPyObjectToInt(tmp,&charge);
            if(!ok) 
              err_message("ChampModel2Pat","can't read formal_charge");
            Py_XDECREF(tmp);
          } else {
            charge = 0;
          }
          switch(charge) {
          case 0: at->charge = cH_Neutral; break;
          case 1: at->charge = cH_Cation; break;
          case 2: at->charge = cH_Dication; break;
          case -1: at->charge = cH_Anion; break;
          case -2: at->charge = cH_Dianion; break;
          }
        }

        if(ok) {
          tmp = PyObject_GetAttrString(atom,"resn");
          if (tmp)
            ok = PConvPyObjectToStrMaxClean(tmp,at->residue,RES_SIZE-1);
          if(!ok) 
            err_message("ChampModel2Pat","can't read resn");
          Py_XDECREF(tmp);
        }
        
		  if(ok) {
          tmp = PyObject_GetAttrString(atom,"symbol");
          if (tmp)
            ok = PConvPyObjectToStrMaxClean(tmp,at->symbol,SYM_SIZE-1);
          if(!ok) 
            err_message("ChampModel2Pat","can't read symbol");
          c = at->symbol;
          std_flag = false;
          switch(*c) {
          case 'C':
            switch(*(c+1)) {
            case 'l':
            case 'L':
              ChampParseAliphaticAtom(I,c,cur_atom,cH_Cl,2,false);
              std_flag = true;
              break;
            default:
              ChampParseAliphaticAtom(I,c,cur_atom,cH_C,1,true);
              std_flag = true;
              break;
            }
            break;
          case 'H': /* nonstandard */
            ChampParseAliphaticAtom(I,c,cur_atom,cH_H,1,false);
            std_flag = true;
            break;
          case 'N':
            ChampParseAliphaticAtom(I,c,cur_atom,cH_N,1,true);
            std_flag = true;
            break;      
          case 'O':
            ChampParseAliphaticAtom(I,c,cur_atom,cH_O,1,true);
            std_flag = true;
            break;      
          case 'B':
            switch(*(c+1)) {
            case 'r':
            case 'R':
              ChampParseAliphaticAtom(I,c,cur_atom,cH_Br,2,false);
              std_flag = true;
              break;
            default:
              ChampParseAliphaticAtom(I,c,cur_atom,cH_B,1,true);
              std_flag = true;
              break;
            }
            break;
          case 'A':
            ChampParseAliphaticAtom(I,c,cur_atom,cH_A,1,true);
            std_flag = true;
            break;      
          case 'P':
            ChampParseAliphaticAtom(I,c,cur_atom,cH_P,1,true);
            std_flag = true;
            break;      
          case 'S':
            ChampParseAliphaticAtom(I,c,cur_atom,cH_S,1,true);
            std_flag = true;
            break;      
          case 'F':
            ChampParseAliphaticAtom(I,c,cur_atom,cH_F,1,false);
            std_flag = true;
            break;      
          case 'I':
            ChampParseAliphaticAtom(I,c,cur_atom,cH_I,1,false);
            std_flag = true;
            break;      
          case 'E':
            ChampParseAliphaticAtom(I,c,cur_atom,cH_E,1,false);
            std_flag = true;
            break;      
          case 'G':
            ChampParseAliphaticAtom(I,c,cur_atom,cH_G,1,false);
            std_flag = true;
            break;      
          case 'J':
            ChampParseAliphaticAtom(I,c,cur_atom,cH_J,1,false);
            std_flag = true;
            break;      
          case 'L':
            ChampParseAliphaticAtom(I,c,cur_atom,cH_L,1,false);
            std_flag = true;
            break;      
          case 'M':
            ChampParseAliphaticAtom(I,c,cur_atom,cH_M,1,false);
            std_flag = true;
            break;      
          case 'Q':
            ChampParseAliphaticAtom(I,c,cur_atom,cH_Q,1,false);
            std_flag = true;
            break;      
          case 'R':
            ChampParseAliphaticAtom(I,c,cur_atom,cH_R,1,false);
            std_flag = true;
            break;      
          case 'T':
            ChampParseAliphaticAtom(I,c,cur_atom,cH_T,1,false);
            std_flag = true;
            break;      
          case 'X':
            ChampParseAliphaticAtom(I,c,cur_atom,cH_X,1,false);
            std_flag = true;
            break;      
          case 'Z':
            ChampParseAliphaticAtom(I,c,cur_atom,cH_Z,1,false);
            std_flag = true;
            break;      
          }
          if(!std_flag) {
            ChampParseStringAtom(I,c,cur_atom,strlen(c));
          }
          Py_XDECREF(tmp);
        }
        
		  if(!ok)
			 break;
		}
  }

  bondList = PyObject_GetAttrString(model,"bond");
  if(bondList) 
    nBond = PyList_Size(bondList);
  else
    ok=err_message("ChampModel2Pat","can't get bond list");

  if(ok) {
	 for(a=nBond-1;a>=0;a--) /* reverse order */
		{
        bnd = PyList_GetItem(bondList,a);
        if(!bnd) 
          ok=err_message("ChampModel2Pat","can't get bond");

        cur_bond = ListElemNewZero(&I->Bond);
        bd = I->Bond + cur_bond;
        bd->link = last_bond;
        last_bond = cur_bond;

        bd->chempy_bond = bnd;
        Py_INCREF(bd->chempy_bond);

        if(ok) {
          tmp = PyObject_GetAttrString(bnd,"order");
          if (tmp)
            ok = PConvPyObjectToInt(tmp,&order);
          if(!ok) 
            err_message("ChampModel2Pat","can't read bond order");
          switch(order) {
          case 1: bd->order = cH_Single; break;
          case 2: bd->order = cH_Double; break;
          case 3: bd->order = cH_Triple; break;
          case 4: bd->order = cH_Single; bd->class = cH_Aromatic|cH_Pi; break;
          }
          Py_XDECREF(tmp);
        }
        
        index = PyObject_GetAttrString(bnd,"index");
        if(!index) 
          ok=err_message("ChampModel2Pat","can't get bond indices");
        else {
          if(ok) ok = PConvPyObjectToInt(PyList_GetItem(index,0),&atom1);
          if(ok) ok = PConvPyObjectToInt(PyList_GetItem(index,1),&atom2);
          if(!ok) 
            err_message("ChampModel2Pat","can't read bond atoms");
          else {
            atom1 = atom_index[atom1];
            atom2 = atom_index[atom2];

            if(order==4) {
              I->Atom[atom1].class |= cH_Aromatic|cH_Pi;
              I->Atom[atom2].class |= cH_Aromatic|cH_Pi;
            }
            bd->atom[0]=atom1;
            bd->atom[1]=atom2;
            bd->pri[0]=0;
            bd->pri[1]=0;
            ChampAddBondToAtom(I,atom1,cur_bond);
            ChampAddBondToAtom(I,atom2,cur_bond);
          }
        }
        Py_XDECREF(index);
      }
  }
  Py_XDECREF(atomList);
  Py_XDECREF(bondList);

  if(PyObject_HasAttrString(model,"molecule")) {
    molec = PyObject_GetAttrString(model,"molecule"); /* returns new reference */
  } else {
    molec = NULL;
  }

  mac_free(atom_index);

  result = ListElemNewZero(&I->Pat); 
  if(result) 
    {
      I->ActivePatList = ListElemPushInt(&I->Int,I->ActivePatList,result);
      I->Pat[result].atom = cur_atom;
      I->Pat[result].bond = cur_bond;
      I->Pat[result].chempy_molecule = molec;
      ChampPatReindex(I,result);     
  }
  return(result);
}