Back to index

wims  3.65+svn20090927
MoleculeStream.java
Go to the documentation of this file.
00001 /*
00002     Sketch Elements: Chemistry molecular diagram drawing tool.
00003     
00004     (c) 2005 Dr. Alex M. Clark
00005     
00006     Released as GNUware, under the Gnu Public License (GPL)
00007     
00008     See www.gnu.org for details.
00009 */
00010 
00011 package WIMSchem;
00012 
00013 import java.util.*;
00014 import java.io.*;
00015 import java.text.*;
00016 import java.lang.*;
00017 import java.nio.channels.*;
00018 
00019 /*
00020     Handles reading and writing of molecules to and from streams. Two formats are supported: native, which is a direct translation of
00021     the underlying data content; and a subset of MDL MOL, using only the fields that are relevant to WIMSchem.
00022 */
00023 
00024 public class MoleculeStream{
00025 
00026 
00027     // special implementation of the reader for when the format is not known a-priori, or might be a combination-of-two formats
00028     // as used by the clipboard; do some extra work to try to pull out the WIMSchem file preferentially
00029     public static Molecule ReadUnknown(InputStream istr) throws IOException 
00030     {
00031        return ReadUnknown(new BufferedReader(new InputStreamReader(istr)));
00032     }
00033     
00034     public static Molecule ReadUnknown(BufferedReader in) throws IOException
00035     {
00036        Molecule mdlmol=null,elmol=null;
00037        final int BUFFMAX=100000;
00038        in.mark(BUFFMAX);
00039        try
00040        {
00041            mdlmol=ReadMDLMOL(in);
00042            if (mdlmol!=null) in.mark(BUFFMAX); // so the WIMSchem version could follow
00043        }
00044        catch (IOException e) 
00045        {
00046            mdlmol=null;
00047            in.reset();
00048        }
00049        
00050        try
00051        {
00052            elmol=ReadNative(in);
00053        }
00054        catch (IOException e) {elmol=null;}
00055        
00056        if (elmol!=null) return elmol;
00057        if (mdlmol!=null) return mdlmol;
00058        
00059        throw new IOException("Unknown or invalid format.");
00060     }
00061 
00062     public static Molecule ReadNative(InputStream istr) throws IOException 
00063     {
00064        return ReadNative(new BufferedReader(new InputStreamReader(istr)));
00065     }
00066     public static Molecule ReadNative(BufferedReader in) throws IOException
00067     {
00068        Molecule mol=new Molecule();
00069        final String GENERIC_ERROR="Invalid WIMSchem file.";
00070        
00071        try
00072        {
00073            String line=in.readLine();
00074            if (!line.startsWith("WIMSchem!")) throw new IOException("Not a WIMSchem file.");
00075            int p1=line.indexOf('('),p2=line.indexOf(','),p3=line.indexOf(')');
00076            if (p1==0 || p2==0 || p3==0) throw new IOException(GENERIC_ERROR);
00077        
00078            int numAtoms=Integer.parseInt(line.substring(p1+1,p2).trim());
00079            int numBonds=Integer.parseInt(line.substring(p2+1,p3).trim());
00080            for (int n=0;n<numAtoms;n++) 
00081        {
00082               line=in.readLine();
00083               String[] bits=line.split("[\\=\\,\\;]");
00084               if (bits.length<5) throw new IOException(GENERIC_ERROR);
00085               int num=mol.AddAtom(bits[0],Double.parseDouble(bits[1].trim()),Double.parseDouble(bits[2].trim()),
00086                                 Integer.parseInt(bits[3].trim()),Integer.parseInt(bits[4].trim()));
00087               for (int i=5;i<bits.length;i++) if (bits[i].length()>0)
00088               {
00089                   if (bits[i].charAt(0)=='e') mol.SetAtomHExplicit(num,Integer.parseInt(bits[i].substring(1)));
00090                   else if (bits[i].charAt(0)=='n') mol.SetAtomMapNum(num,Integer.parseInt(bits[i].substring(1)));
00091               }
00092            }
00093            for (int n=0;n<numBonds;n++)
00094            {
00095               line=in.readLine();
00096               String[] bits=line.split("[\\-\\=\\,]");
00097               if (bits.length<4) throw new IOException(GENERIC_ERROR);
00098               mol.AddBond(Integer.parseInt(bits[0].trim()),Integer.parseInt(bits[1].trim()),
00099                          Integer.parseInt(bits[2].trim()),Integer.parseInt(bits[3].trim()));
00100            }
00101            line=in.readLine();
00102            if (line.compareTo("!FIN")!=0) throw new IOException(GENERIC_ERROR);
00103        }
00104        catch (Exception e)
00105        {
00106            throw new IOException(GENERIC_ERROR);
00107        }
00108 
00109        return mol;
00110     }
00111     
00112     public static void WriteNative(OutputStream ostr,Molecule mol) throws IOException
00113     {
00114        WriteNative(new BufferedWriter(new OutputStreamWriter(ostr)),mol);
00115     }
00116     public static void WriteNative(BufferedWriter out,Molecule mol) throws IOException
00117     {
00118        DecimalFormat fmt=new DecimalFormat("0.0000",new DecimalFormatSymbols(Locale.US));
00119 
00120        out.write("WIMSchem!("+mol.NumAtoms()+","+mol.NumBonds()+")\n");
00121        for (int n=1;n<=mol.NumAtoms();n++)
00122        {
00123            String hy=mol.AtomHExplicit(n)!=Molecule.HEXPLICIT_UNKNOWN ? ("e"+mol.AtomHExplicit(n)) : ("i"+mol.AtomHydrogens(n));
00124            out.write(mol.AtomElement(n)+"="+fmt.format(mol.AtomX(n))+","+fmt.format(mol.AtomY(n))+";"+
00125                                                                mol.AtomCharge(n)+","+mol.AtomUnpaired(n)+","+hy);
00126            if (mol.AtomMapNum(n)>0) out.write(",n"+mol.AtomMapNum(n));
00127            out.write("\n");
00128        }
00129        for (int n=1;n<=mol.NumBonds();n++)
00130        {
00131            out.write(mol.BondFrom(n)+"-"+mol.BondTo(n)+"="+mol.BondOrder(n)+","+mol.BondType(n)+"\n");
00132        }
00133        out.write("!FIN\n");
00134        
00135        out.flush();
00136     }
00137 
00138     // jm.evers
00139     // testing with a "convenient way to produce a "Native string" to be used as wims $variable in javascript. 
00140     public static void WriteNative2JavaScript(OutputStream ostr,Molecule mol) throws IOException {
00141        WriteNative2JavaScript(new BufferedWriter(new OutputStreamWriter(ostr)),mol);
00142     }
00143     public static void WriteNative2JavaScript(BufferedWriter out,Molecule mol) throws IOException {
00144        DecimalFormat fmt=new DecimalFormat("0.0000",new DecimalFormatSymbols(Locale.US));
00145        
00146        out.write("\"WIMSchem!("+mol.NumAtoms()+","+mol.NumBonds()+")\\n\"+");
00147        for (int n=1;n<=mol.NumAtoms();n++)
00148        {
00149            String hy=mol.AtomHExplicit(n)!=Molecule.HEXPLICIT_UNKNOWN ? ("e"+mol.AtomHExplicit(n)) : ("i"+mol.AtomHydrogens(n));
00150            out.write("\""+mol.AtomElement(n)+"="+fmt.format(mol.AtomX(n))+","+fmt.format(mol.AtomY(n))+";"+
00151                                                                mol.AtomCharge(n)+","+mol.AtomUnpaired(n)+","+hy);
00152            if (mol.AtomMapNum(n)>0) out.write(",n"+mol.AtomMapNum(n));
00153            out.write("\\n\"+");
00154        }
00155        for (int n=1;n<=mol.NumBonds();n++)
00156        {
00157            out.write("\""+mol.BondFrom(n)+"-"+mol.BondTo(n)+"="+mol.BondOrder(n)+","+mol.BondType(n)+"\\n\"+");
00158        }
00159        out.write("\"!FIN\"");
00160        
00161        out.flush();
00162     }
00163     
00164     // jm.evers
00165     // testing with a "convenient way to produce a "MDLMol string" to be used as wims $variable in javascript. 
00166     public static void WriteMDLMol2JavaScript(OutputStream ostr,Molecule mol) throws IOException {
00167        WriteMDLMol2JavaScript(new BufferedWriter(new OutputStreamWriter(ostr)),mol);
00168     }
00169     public static void WriteMDLMol2JavaScript(BufferedWriter out,Molecule mol) throws IOException {
00170         DecimalFormat fmt=new DecimalFormat("0.0000",new DecimalFormatSymbols(Locale.US));
00171        out.write("\"\\nWIMSchem molfile\\n\\n\"+");
00172        out.write("\""+intrpad(mol.NumAtoms(),3)+intrpad(mol.NumBonds(),3)+"  0  0  0  0  0  0  0  0999 V2000\\n\"+");
00173        String line;
00174        for (int n=1;n<=mol.NumAtoms();n++)
00175        {
00176            String str="\"   "+fmt.format(mol.AtomX(n)); 
00177            line=rep(" ",10-str.length())+str;
00178            str=fmt.format(mol.AtomY(n)); 
00179            line+=rep(" ",10-str.length())+str;
00180            line+="    0.0000 ";
00181            str=mol.AtomElement(n);
00182            line+=str+rep(" ",4-str.length())+"0";
00183            
00184            int chg=mol.AtomCharge(n),spin=mol.AtomUnpaired(n),mapnum=mol.AtomMapNum(n);
00185            if (chg>=-3 && chg<=-1) chg=4-chg;
00186            else if (chg==0 && spin==2) chg=4;
00187            else if (chg<1 || chg>3) chg=0;
00188            line+=intrpad(chg,3)+"  0  0  0  0  0  0  0"+intrpad(mapnum,3)+"  0  0";
00189            
00190            out.write(line+"\\n\"+");
00191        }
00192        
00193        for (int n=1;n<=mol.NumBonds();n++)
00194        {
00195            int type=mol.BondOrder(n);
00196            if (type<1 || type>3) type=1;
00197            int stereo=mol.BondType(n);
00198            if (stereo==Molecule.BONDTYPE_NORMAL) {}
00199            else if (stereo==Molecule.BONDTYPE_INCLINED) {stereo=1; type=1;}
00200            else if (stereo==Molecule.BONDTYPE_DECLINED) {stereo=6; type=1;}
00201            else if (stereo==Molecule.BONDTYPE_UNKNOWN) {stereo=4; type=1;}
00202            else stereo=0;
00203 
00204            out.write("\""+intrpad(mol.BondFrom(n),3)+intrpad(mol.BondTo(n),3)+intrpad(type,3)+intrpad(stereo,3)+"  0  0  0\\n\"+");
00205        }
00206        
00207        int count=0;
00208        line="";
00209        for (int n=1;n<=mol.NumAtoms();n++) if (mol.AtomCharge(n)!=0)
00210        {
00211            line+=intrpad(n,4)+intrpad(mol.AtomCharge(n),4);
00212            count++;
00213            if (count==8)
00214            {
00215               out.write("\"M  CHG"+intrpad(count,3)+line+"\\n\"+");
00216               count=0; line="";
00217            }
00218        }
00219        if (count>0) out.write("\"M  CHG"+intrpad(count,3)+line+"\\n\"+");
00220        
00221        count=0;
00222        line="";
00223        for (int n=1;n<=mol.NumAtoms();n++) if (mol.AtomUnpaired(n)!=0)
00224        {
00225            line+=intrpad(n,4)+intrpad(mol.AtomUnpaired(n),4);
00226            count++;
00227            if (count==8)
00228            {
00229               out.write("\"M  RAD"+intrpad(count,3)+line+"\\n\"+");
00230               count=0; line="";
00231            }
00232        }
00233        if (count>0) out.write("\"M  RAD"+intrpad(count,3)+line+"\\n\"");
00234        
00235        out.write("\"M  END\\n\"");
00236        out.flush();
00237     }
00238     
00239 
00240     //jm.evers
00241     // converting a molecule to a string in native fileformat.Used for comparing MDLMol js-string with student drawing
00242     public static String Molecule2String(Molecule mol) throws IOException {
00243        DecimalFormat fmt=new DecimalFormat("0.0000",new DecimalFormatSymbols(Locale.US));
00244        String i="WIMSchem!("+mol.NumAtoms()+","+mol.NumBonds()+")\n";
00245        for (int n=1;n<=mol.NumAtoms();n++)
00246        {
00247            String hy=mol.AtomHExplicit(n)!=Molecule.HEXPLICIT_UNKNOWN ? ("e"+mol.AtomHExplicit(n)) : ("i"+mol.AtomHydrogens(n));
00248            i=i+mol.AtomElement(n)+"="+fmt.format(mol.AtomX(n))+","+fmt.format(mol.AtomY(n))+";"+mol.AtomCharge(n)+","+mol.AtomUnpaired(n)+","+hy;
00249            if (mol.AtomMapNum(n)>0) i=i+",n"+mol.AtomMapNum(n);
00250            i=i+"\n";
00251        }
00252        for (int n=1;n<=mol.NumBonds();n++)
00253        {
00254            i=i+mol.BondFrom(n)+"-"+mol.BondTo(n)+"="+mol.BondOrder(n)+","+mol.BondType(n)+"\n";
00255        }
00256        i=i+"!FIN\n";
00257        return i;
00258     }
00259 
00260 
00261 
00262     public static Molecule ReadMDLMOL(BufferedReader in) throws IOException
00263     {
00264        Molecule mol=new Molecule();
00265        final String GENERIC_ERROR="Invalid MDL MOL file.";
00266 
00267        try
00268        {
00269            String line=null;
00270            for (int n=0;n<4;n++) line=in.readLine();
00271            if (!line.substring(34,39).equals("V2000")) throw new IOException(GENERIC_ERROR);
00272            int numAtoms=Integer.parseInt(line.substring(0,3).trim());
00273            int numBonds=Integer.parseInt(line.substring(3,6).trim());
00274            for (int n=0;n<numAtoms;n++)
00275            {
00276               line=in.readLine();
00277               
00278               double x=Double.parseDouble(line.substring(0,10).trim());
00279               double y=Double.parseDouble(line.substring(10,20).trim());
00280               String el=line.substring(31,34).trim();
00281               int chg=Integer.parseInt(line.substring(36,39).trim()),rad=0;
00282               int mapnum=Integer.parseInt(line.substring(60,63).trim());
00283               
00284               if (chg<=3) {}
00285               else if (chg==4) {chg=0; rad=2;}
00286               else chg=4-chg;
00287                             
00288               mol.AddAtom(el,x,y,chg,rad);
00289               mol.SetAtomMapNum(mol.NumAtoms(),mapnum);
00290            }
00291            for (int n=0;n<numBonds;n++)
00292            {
00293               line=in.readLine();
00294               
00295               int from=Integer.parseInt(line.substring(0,3).trim()),to=Integer.parseInt(line.substring(3,6).trim());
00296               int type=Integer.parseInt(line.substring(6,9).trim()),stereo=Integer.parseInt(line.substring(9,12).trim());
00297               
00298               if (from==to || from<1 || from>numAtoms || to<1 || to>numAtoms) throw new IOException(GENERIC_ERROR);
00299               
00300               int order=type>=1 && type<=3 ? type : 1;
00301               int style=Molecule.BONDTYPE_NORMAL;
00302               if (stereo==1) style=Molecule.BONDTYPE_INCLINED;
00303               else if (stereo==6) style=Molecule.BONDTYPE_DECLINED;
00304               // !! supposed to be for double bonds... else if (stereo==3 || stereo==4) style=Molecule.BONDTYPE_UNKNOWN;
00305 
00306                mol.AddBond(from,to,order,style);
00307            }
00308            while (true)
00309            {
00310               line=in.readLine();
00311               if (line.startsWith("M  END")) break;
00312               
00313               int type=0;
00314               if (line.startsWith("M  CHG")) type=1;
00315               else if (line.startsWith("M  RAD")) type=2;
00316               if (type>0)
00317               {
00318                   int len=Integer.parseInt(line.substring(6,9).trim());
00319                   for (int n=0;n<len;n++)
00320                   {
00321                      int apos=Integer.parseInt(line.substring(9+8*n,13+8*n).trim());
00322                      int aval=Integer.parseInt(line.substring(13+8*n,17+8*n).trim());
00323                      if (type==1) mol.SetAtomCharge(apos,aval); else mol.SetAtomUnpaired(apos,aval);
00324                   }
00325               }
00326            }
00327        }
00328        catch (Exception e) {throw new IOException(GENERIC_ERROR+"hier");}
00329 
00330        return mol;
00331     }
00332     
00333 
00334     public static void WriteMDLMOL(OutputStream ostr,Molecule mol) throws IOException
00335     {
00336        WriteMDLMOL(new BufferedWriter(new OutputStreamWriter(ostr)),mol);
00337     }
00338     public static void WriteMDLMOL(BufferedWriter out,Molecule mol) throws IOException
00339     {
00340        DecimalFormat fmt=new DecimalFormat("0.0000",new DecimalFormatSymbols(Locale.US));
00341        out.write("\nWIMSchem molfile\n\n");
00342        out.write(intrpad(mol.NumAtoms(),3)+intrpad(mol.NumBonds(),3)+"  0  0  0  0  0  0  0  0999 V2000\n");
00343        
00344        String line;
00345        
00346        for (int n=1;n<=mol.NumAtoms();n++)
00347        {
00348            String str=fmt.format(mol.AtomX(n)); 
00349            line=rep(" ",10-str.length())+str;
00350            str=fmt.format(mol.AtomY(n)); 
00351            line+=rep(" ",10-str.length())+str;
00352            line+="    0.0000 ";
00353            str=mol.AtomElement(n);
00354            line+=str+rep(" ",4-str.length())+"0";
00355            
00356            int chg=mol.AtomCharge(n),spin=mol.AtomUnpaired(n),mapnum=mol.AtomMapNum(n);
00357            if (chg>=-3 && chg<=-1) chg=4-chg;
00358            else if (chg==0 && spin==2) chg=4;
00359            else if (chg<1 || chg>3) chg=0;
00360            line+=intrpad(chg,3)+"  0  0  0  0  0  0  0"+intrpad(mapnum,3)+"  0  0";
00361            
00362            out.write(line+"\n");
00363        }
00364        
00365        for (int n=1;n<=mol.NumBonds();n++)
00366        {
00367            int type=mol.BondOrder(n);
00368            if (type<1 || type>3) type=1;
00369            int stereo=mol.BondType(n);
00370            if (stereo==Molecule.BONDTYPE_NORMAL) {}
00371            else if (stereo==Molecule.BONDTYPE_INCLINED) {stereo=1; type=1;}
00372            else if (stereo==Molecule.BONDTYPE_DECLINED) {stereo=6; type=1;}
00373            else if (stereo==Molecule.BONDTYPE_UNKNOWN) {stereo=4; type=1;}
00374            else stereo=0;
00375 
00376            out.write(intrpad(mol.BondFrom(n),3)+intrpad(mol.BondTo(n),3)+intrpad(type,3)+intrpad(stereo,3)+"  0  0  0\n");
00377        }
00378        
00379        int count=0;
00380        line="";
00381        for (int n=1;n<=mol.NumAtoms();n++) if (mol.AtomCharge(n)!=0)
00382        {
00383            line+=intrpad(n,4)+intrpad(mol.AtomCharge(n),4);
00384            count++;
00385            if (count==8)
00386            {
00387               out.write("M  CHG"+intrpad(count,3)+line+"\n");
00388               count=0; line="";
00389            }
00390        }
00391        if (count>0) out.write("M  CHG"+intrpad(count,3)+line+"\n");
00392        
00393        count=0;
00394        line="";
00395        for (int n=1;n<=mol.NumAtoms();n++) if (mol.AtomUnpaired(n)!=0)
00396        {
00397            line+=intrpad(n,4)+intrpad(mol.AtomUnpaired(n),4);
00398            count++;
00399            if (count==8)
00400            {
00401               out.write("M  RAD"+intrpad(count,3)+line+"\n");
00402               count=0; line="";
00403            }
00404        }
00405        if (count>0) out.write("M  RAD"+intrpad(count,3)+line+"\n");
00406        
00407        out.write("M  END\n");
00408        out.flush();
00409     }
00410     
00411     public static void WriteCMLXML(OutputStream ostr,Molecule mol) throws IOException
00412     {
00413        WriteCMLXML(new BufferedWriter(new OutputStreamWriter(ostr)),mol);
00414     }
00415     public static void WriteCMLXML(BufferedWriter out,Molecule mol) throws IOException
00416     {
00417        out.write("<cml>\n");
00418        out.write("  <molecule>\n");
00419 
00420        out.write("    <atomArray>\n");
00421        for (int n=1;n<=mol.NumAtoms();n++)
00422        {
00423            out.write("      <atom id=\"a"+n+"\" elementType=\""+mol.AtomElement(n)+"\""+
00424                              " x2=\""+mol.AtomX(n)+"\" y2=\""+mol.AtomY(n)+"\" hydrogenCount=\""+mol.AtomHydrogens(n)+"\"/>\n");
00425        }
00426        out.write("    </atomArray>\n");
00427        
00428        out.write("    <bondArray>\n");
00429        for (int n=1;n<=mol.NumBonds();n++)
00430        {
00431            out.write("      <bond id=\"b"+n+"\" atomRefs2=\"a"+mol.BondFrom(n)+" a"+mol.BondTo(n)+"\" order=\""+mol.BondOrder(n)+"\"/>\n");
00432        }
00433        out.write("    </bondArray>\n");
00434        
00435        out.write("  </molecule>\n");
00436        out.write("</cml>\n");
00437        out.flush();
00438     }
00439     
00440     // examines the beginning of a file and decides whether it can be considered a database of structures which this class is capable
00441     // of reading...
00442     // (NB: currently this includes MDL SD-files, and nothing else)
00443     static boolean ExamineIsDatabase(FileInputStream istr) throws IOException 
00444     {
00445        long lastpos=istr.getChannel().position();
00446        boolean isdb=FindNextPosition(istr,0)>=0;
00447        istr.getChannel().position(lastpos);
00448        return isdb;
00449     }
00450     
00451     static long FindNextPosition(FileInputStream istr,long startpos) throws IOException
00452     {
00453        FileChannel fch=istr.getChannel();
00454        fch.position(startpos);
00455        long pos=startpos,size=fch.size(),nextpos=-1;
00456        
00457        String rec="";
00458        while (nextpos<size)
00459        {
00460            int inp=istr.read();
00461            pos++;
00462            if (inp<0) break;
00463            char ch=(char)inp;
00464            if (ch=='\r') continue;
00465            rec=rec.concat(String.valueOf(ch));
00466            if (rec.endsWith("$$$$\n")) {nextpos=pos; break;}
00467        }
00468        if (nextpos<0) return -1;
00469 
00470        try
00471        {
00472            BufferedReader in=new BufferedReader(new StringReader(rec));
00473            Molecule mol=ReadMDLMOL(in);
00474            if (mol==null) nextpos=-1;
00475        }
00476        catch (IOException e) {nextpos=-1;}
00477        
00478        return nextpos;
00479     }
00480     
00481     static Molecule FetchFromPosition(FileInputStream istr,long pos) throws IOException
00482     {
00483        istr.getChannel().position(pos);
00484        return ReadMDLMOL(new BufferedReader(new InputStreamReader(istr)));
00485     }
00486     
00487     // miscellaneous help
00488     
00489     static String intrpad(int Val,int Len)
00490     {
00491        String str=Integer.toString(Val);
00492        str=rep(" ",Len-str.length())+str;
00493        if (str.length()>Len) str=str.substring(0,Len);
00494        return str;
00495     }
00496     static String rep(String Ch,int Len)
00497     {
00498        if (Len<=0) return "";
00499        String str=Ch;
00500        while (str.length()<Len) str=str+Ch;
00501        return str;
00502     }
00503 
00504     public static String GetSmiles(Molecule mol){
00505     // jm.evers
00506     // all very clumsy...there must be another/better way of doing this proper !
00507        int a;int b;int p=0;int H1=0;int H2=0;int C1=0;int C2=0;String c1="";;String c2="";
00508        String smile="";int M=mol.NumBonds();int N=mol.NumAtoms();
00509        try{
00510            if(N==1){
00511               if(mol.AtomHExplicit(1)!=Molecule.HEXPLICIT_UNKNOWN){
00512                   H1=mol.AtomHExplicit(1);
00513               }
00514               else
00515               {
00516                   H1=mol.AtomHydrogens(1);
00517               } 
00518               C1=mol.AtomCharge(1);
00519                if(C1 != 0){
00520                   if(C1>0){
00521                      if(C1==1){
00522                          c1="<sup><small><b>+</b></small></sup>";
00523                      }
00524                      else
00525                      {
00526                          c1="<sup><small><b>"+C1+"+</b></small></sup>";
00527                      }
00528                   }
00529                   else
00530                   {
00531                      C1=-1*C1;
00532                      if(C1 == 1){
00533                          c1="<sup><small><b>-</b></small></sup>";
00534                      }
00535                      else
00536                      {
00537                          c1="<sup><small><b>"+C1+"-</b></small></sup>";
00538                      }    
00539                   }
00540               }
00541               else
00542               {
00543                   c1 = "";
00544               }
00545               if(H1 != 0){
00546                   if(H1 == 1){
00547                      smile=mol.AtomElement(1)+c1+"H";
00548                   }
00549                   else
00550                   {
00551                      smile=mol.AtomElement(1)+c1+"H<sub><small>"+H1+"</small></sub>";
00552                   }
00553               }
00554               else
00555               {
00556                   smile=mol.AtomElement(1)+c1;
00557               }      
00558            }
00559            else
00560            {
00561               int[] From=new int[M+1];
00562               int[] To=new int[M+1];
00563               boolean[] Fdone=new boolean[N+1];
00564               boolean[] Tdone=new boolean[N+1];
00565               boolean test=true;
00566               for(int n=1;n<=M;n++){
00567                   From[n]=mol.BondFrom(n);
00568                   To[n]=mol.BondTo(n);
00569               }
00570               for(int n=0;n<=N;n++){
00571                   Fdone[n]=false;
00572                   Tdone[n]=false;
00573               }
00574               for(int n=1;n<=M;n++){
00575                   test=true;a=From[n];b=To[n];p=1;
00576                   if(mol.AtomHExplicit(a)!=Molecule.HEXPLICIT_UNKNOWN){
00577                      H1=mol.AtomHExplicit(a);
00578                   }
00579                   else
00580                   {
00581                      H1=mol.AtomHydrogens(a);
00582                   } 
00583                   if(mol.AtomHExplicit(b)!=Molecule.HEXPLICIT_UNKNOWN){
00584                      H2=mol.AtomHExplicit(b);
00585                   }
00586                   else
00587                   {
00588                      H2=mol.AtomHydrogens(b);
00589                   }
00590                   C1=mol.AtomCharge(a);
00591                   C2=mol.AtomCharge(b);
00592                   if(C1 != 0){
00593                      if(C1>0){
00594                          if(C1==1){
00595                             c1="<sup><small><b>+</b></small></sup>";
00596                          }
00597                          else
00598                          {
00599                             c1="<sup><small><b>"+C1+"+</b></small></sup>";
00600                          }
00601                      }
00602                      else
00603                      {
00604                          C1=-1*C1;
00605                          if(C1 == 1){
00606                             c1="<sup><small><b>-</b></small></sup>";
00607                          }
00608                          else
00609                          {
00610                             c1="<sup><small><b>"+C1+"-</b></small></sup>";
00611                          }    
00612                      }
00613                   }
00614                   else
00615                   {
00616                      c1 = "";
00617                   }
00618                   if(C2 != 0){
00619                      if(C2>0){
00620                          if(C2==1){
00621                             c2="<sup><small><b>+</b></small></sup>";
00622                          }
00623                          else
00624                          {
00625                             c2="<sup><small><b>"+C2+"+</b></small></sup>";
00626                          }
00627                      }
00628                      else
00629                      {
00630                          C2=-1*C2;
00631                          if(C2 == 1){
00632                             c2="<sup><small><b>-</b></small></sup>";
00633                          }
00634                          else
00635                          {
00636                             c2="<sup><small><b>"+C2+"-</b></small></sup>";
00637                          }    
00638                      }
00639                   }
00640                   else
00641                   {
00642                      c2 = "";
00643                   }
00644            
00645                   while(test && p<=M){
00646                      if(!Fdone[a] && !Tdone[a]){
00647                          if(H1 != 0){
00648                             if(H1 == 1){
00649                                 smile=smile+"("+(mol.AtomElement(a))+c1+"H)"+(htmlbond(mol.BondOrder(a)));
00650                             }
00651                             else
00652                             {
00653                                 smile=smile+"("+(mol.AtomElement(a))+c1+"H<sub><small>"+H1+"</small></sub>)"+(htmlbond(mol.BondOrder(a)));
00654                             }
00655                          }
00656                          else
00657                          {
00658                             smile=smile+(mol.AtomElement(a))+c1+(htmlbond(mol.BondOrder(a)));
00659                          }
00660                          Fdone[a]=true;
00661                      }
00662 
00663                      if(!Tdone[b] && !Fdone[b]){
00664                          if(n<M){
00665                             if(H2 != 0){
00666                                 if(H2 == 1){
00667                                    smile=smile+"("+(mol.AtomElement(b))+c2+"H)"+(htmlbond(mol.BondOrder(b))) ;
00668                                 }
00669                                 else
00670                                 {
00671                                    smile=smile+"("+(mol.AtomElement(b))+c2+"H<sub><small>"+H2+"</small></sub>)"+(htmlbond(mol.BondOrder(b))) ;
00672                                 }
00673                             }
00674                             else
00675                             {                    
00676                                 smile=smile+(mol.AtomElement(b))+c2+(htmlbond(mol.BondOrder(b))) ;
00677                             }
00678                          }
00679                          else
00680                          {
00681                             if( H2 != 0){
00682                                 if( H2 == 1){
00683                                    smile=smile+"("+(mol.AtomElement(b))+c2+"H)";
00684                                 }
00685                                 else
00686                                 {
00687                                    smile=smile+"("+(mol.AtomElement(b))+c2+"H<sub><small>"+H2+"</small></sub>)";
00688                                 }
00689                             }
00690                             else
00691                             {
00692                                 smile=smile+(mol.AtomElement(b))+c2;
00693                             }
00694                          }
00695                          Tdone[b]=true;
00696                      }
00697                      if(Tdone[b] || Fdone[a]){
00698                          test=false;
00699                      }
00700                       p++;
00701                   }
00702               }
00703            }
00704            return smile;
00705        }
00706        catch (Exception e){return "error \n Are You drawing more than 1 molecule ???";}
00707     }
00708     
00709     public static String htmlbond(int order){
00710     // jm.evers
00711        String s="&minus";
00712        if(order == 0){ 
00713            s="\u22Ef";
00714        }
00715        else
00716        {
00717            if(order == 1){ 
00718               s="&minus;";
00719            }
00720            else
00721            {
00722               if(order == 2){
00723                   s="=";
00724               }
00725               else
00726               {
00727                   if(order == 3){
00728                      s="&equiv;";
00729                   }
00730               }
00731            }
00732        }
00733        return s;
00734     }
00735 
00736 
00737 }