Rev 7196 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 7196 | Rev 7246 | ||
---|---|---|---|
Line 19... | Line 19... | ||
19 | /* |
19 | /* |
20 | Handles reading and writing of molecules to and from streams. Two formats are supported: native, which is a direct translation of |
20 | Handles reading and writing of molecules to and from streams. Two formats are supported: native, which is a direct translation of |
21 | the underlying data content; and a subset of MDL MOL, using only the fields that are relevant to WIMSchem. |
21 | the underlying data content; and a subset of MDL MOL, using only the fields that are relevant to WIMSchem. |
22 | */ |
22 | */ |
23 | 23 | ||
24 | public class MoleculeStream |
24 | public class MoleculeStream |
25 | - | ||
26 | 25 | { |
|
27 | // special implementation of the reader for when the format is not known a-priori, or might be a combination-of-two formats |
26 | // special implementation of the reader for when the format is not known a-priori, or might be a combination-of-two formats |
28 | // as used by the clipboard; do some extra work to try to pull out the WIMSchem file preferentially |
27 | // as used by the clipboard; do some extra work to try to pull out the WIMSchem file preferentially |
29 | public static Molecule |
28 | public static Molecule readUnknown(InputStream istr) throws IOException |
30 | { |
29 | { |
31 | return |
30 | return readUnknown(new BufferedReader(new InputStreamReader(istr))); |
32 | } |
31 | } |
33 | 32 | ||
34 | public static Molecule |
33 | public static Molecule readUnknown(BufferedReader in) throws IOException |
35 | { |
34 | { |
36 | Molecule mdlmol=null,elmol=null; |
35 | Molecule mdlmol=null,elmol=null; |
37 | final int BUFFMAX=100000; |
36 | final int BUFFMAX=100000; |
38 | in.mark(BUFFMAX); |
37 | in.mark(BUFFMAX); |
39 | try |
38 | try |
40 | { |
39 | { |
41 |
|
40 | mdlmol=readMDLMOL(in); |
42 | if (mdlmol!=null) in.mark(BUFFMAX); // so the WIMSchem version could follow |
41 | if (mdlmol!=null) in.mark(BUFFMAX); // so the WIMSchem version could follow |
43 | } |
42 | } |
44 | catch (IOException e) |
43 | catch (IOException e) |
45 | { |
44 | { |
46 | mdlmol=null; |
45 | mdlmol=null; |
47 | in.reset(); |
46 | in.reset(); |
48 | } |
47 | } |
49 | 48 | ||
50 | try |
49 | try |
51 | { |
50 | { |
52 |
|
51 | elmol=readNative(in); |
53 | } |
52 | } |
54 | catch (IOException e) {elmol=null;} |
53 | catch (IOException e) {elmol=null;} |
55 | 54 | ||
56 | if (elmol!=null) return elmol; |
55 | if (elmol!=null) return elmol; |
57 | if (mdlmol!=null) return mdlmol; |
56 | if (mdlmol!=null) return mdlmol; |
58 | 57 | ||
59 | throw new IOException("Unknown or invalid format."); |
58 | throw new IOException("Unknown or invalid format."); |
60 | } |
59 | } |
61 | 60 | ||
62 | public static Molecule |
61 | public static Molecule readNative(InputStream istr) throws IOException |
63 | { |
62 | { |
64 | return |
63 | return readNative(new BufferedReader(new InputStreamReader(istr))); |
65 | } |
64 | } |
66 | public static Molecule |
65 | public static Molecule readNative(BufferedReader in) throws IOException |
67 | { |
66 | { |
68 | Molecule mol=new Molecule(); |
67 | Molecule mol=new Molecule(); |
69 | final String GENERIC_ERROR="Invalid WIMSchem file."; |
68 | final String GENERIC_ERROR="Invalid WIMSchem file."; |
70 | 69 | ||
71 | try |
70 | try |
72 | { |
71 | { |
73 | String line=in.readLine(); |
72 | String line=in.readLine(); |
74 | if (!line.startsWith(" |
73 | if (!line.startsWith("SketchEl!") && !line.startsWith("WIMSchem!")) throw new IOException("Not a WIMSchem file...could not find start tag \"SketchEl!\""); |
75 | int p1=line.indexOf('('),p2=line.indexOf(','),p3=line.indexOf(')'); |
74 | int p1=line.indexOf('('),p2=line.indexOf(','),p3=line.indexOf(')'); |
76 | if (p1==0 || p2==0 || p3==0) throw new IOException(GENERIC_ERROR); |
75 | if (p1==0 || p2==0 || p3==0) throw new IOException(GENERIC_ERROR); |
77 | 76 | ||
78 | int numAtoms=Integer.parseInt(line.substring(p1+1,p2).trim()); |
77 | int numAtoms=Integer.parseInt(line.substring(p1+1,p2).trim()); |
79 | int numBonds=Integer.parseInt(line.substring(p2+1,p3).trim()); |
78 | int numBonds=Integer.parseInt(line.substring(p2+1,p3).trim()); |
80 | for (int n=0;n<numAtoms;n++) |
79 | for (int n=0;n<numAtoms;n++) |
81 | { |
80 | { |
82 | line=in.readLine(); |
81 | line=in.readLine(); |
83 | String[] bits=line.split("[\\=\\,\\;]"); |
82 | String[] bits=line.split("[\\=\\,\\;]"); |
84 | if (bits.length<5) throw new IOException( |
83 | if (bits.length<5) throw new IOException("WIMSchem format error: to few arguments in atomsection line"+n); |
85 | int num=mol. |
84 | int num=mol.addAtom(bits[0],Double.parseDouble(bits[1].trim()),Double.parseDouble(bits[2].trim()), |
86 | Integer.parseInt(bits[3].trim()),Integer.parseInt(bits[4].trim())); |
85 | Integer.parseInt(bits[3].trim()),Integer.parseInt(bits[4].trim())); |
87 | for (int i=5;i<bits.length;i++) if (bits[i].length()>0) |
86 | for (int i=5;i<bits.length;i++) if (bits[i].length()>0) |
88 | { |
87 | { |
89 | if (bits[i].charAt(0)=='e') mol. |
88 | if (bits[i].charAt(0)=='e') mol.setAtomHExplicit(num,Integer.parseInt(bits[i].substring(1))); |
90 | else if (bits[i].charAt(0)=='n') mol. |
89 | else if (bits[i].charAt(0)=='n') mol.setAtomMapNum(num,Integer.parseInt(bits[i].substring(1))); |
91 | } |
90 | } |
92 | } |
91 | } |
93 | for (int n=0;n<numBonds;n++) |
92 | for (int n=0;n<numBonds;n++) |
94 | { |
93 | { |
95 | line=in.readLine(); |
94 | line=in.readLine(); |
96 | String[] bits=line.split("[\\-\\=\\,]"); |
95 | String[] bits=line.split("[\\-\\=\\,]"); |
97 | if (bits.length<4) throw new IOException( |
96 | if (bits.length<4) throw new IOException("WIMSchem fromat error : to few aguments in bondsection line "+n); |
98 | mol. |
97 | mol.addBond(Integer.parseInt(bits[0].trim()),Integer.parseInt(bits[1].trim()), |
99 | Integer.parseInt(bits[2].trim()),Integer.parseInt(bits[3].trim())); |
98 | Integer.parseInt(bits[2].trim()),Integer.parseInt(bits[3].trim())); |
100 | } |
99 | } |
101 | line=in.readLine(); |
100 | line=in.readLine(); |
102 | if (line.compareTo(" |
101 | if (line.compareTo("!End")!=0 && line.compareTo("!FIN")!=0) throw new IOException("could not find the end tag \"!End\""); |
103 | } |
102 | } |
104 | catch (Exception e) |
103 | catch (Exception e) |
105 | { |
104 | { |
106 | throw new IOException(GENERIC_ERROR); |
105 | throw new IOException(GENERIC_ERROR); |
107 | } |
106 | } |
108 | 107 | ||
109 | return mol; |
108 | return mol; |
110 | } |
109 | } |
111 | 110 | ||
112 | public static void |
111 | public static void writeNative(OutputStream ostr,Molecule mol) throws IOException |
113 | { |
112 | { |
114 |
|
113 | writeNative(new BufferedWriter(new OutputStreamWriter(ostr)),mol); |
115 | } |
114 | } |
116 | public static void |
115 | public static void writeNative(BufferedWriter out,Molecule mol) throws IOException |
117 | { |
116 | { |
118 | DecimalFormat fmt=new DecimalFormat("0.0000" |
117 | DecimalFormat fmt=new DecimalFormat("0.0000"); |
119 | 118 | ||
120 | out.write(" |
119 | out.write("SketchEl!("+mol.numAtoms()+","+mol.numBonds()+")\n"); |
121 | for (int n=1;n<=mol. |
120 | for (int n=1;n<=mol.numAtoms();n++) |
122 | { |
121 | { |
123 | String hy=mol. |
122 | String hy=mol.atomHExplicit(n)!=Molecule.HEXPLICIT_UNKNOWN ? ("e"+mol.atomHExplicit(n)) : ("i"+mol.atomHydrogens(n)); |
124 | out.write(mol. |
123 | out.write(mol.atomElement(n)+"="+fmt.format(mol.atomX(n))+","+fmt.format(mol.atomY(n))+";"+ |
125 | mol. |
124 | mol.atomCharge(n)+","+mol.atomUnpaired(n)+","+hy); |
126 | if (mol. |
125 | if (mol.atomMapNum(n)>0) out.write(",n"+mol.atomMapNum(n)); |
127 | out.write("\n"); |
126 | out.write("\n"); |
128 | } |
127 | } |
129 | for (int n=1;n<=mol.NumBonds();n++) |
- | |
130 | { |
- | |
131 | out.write(mol.BondFrom(n)+"-"+mol.BondTo(n)+"="+mol.BondOrder(n)+","+mol.BondType(n)+"\n"); |
- | |
132 | } |
- | |
133 | out.write("!FIN\n"); |
- | |
134 | - | ||
135 | out.flush(); |
- | |
136 | } |
- | |
137 | - | ||
138 | // jm.evers |
- | |
139 | // testing with a "convenient way to produce a "Native string" to be used as wims $variable in javascript. |
- | |
140 | public static void WriteNative2JavaScript(OutputStream ostr,Molecule mol) throws IOException { |
- | |
141 | WriteNative2JavaScript(new BufferedWriter(new OutputStreamWriter(ostr)),mol); |
- | |
142 | } |
- | |
143 | public static void WriteNative2JavaScript(BufferedWriter out,Molecule mol) throws IOException { |
- | |
144 | DecimalFormat fmt=new DecimalFormat("0.0000",new DecimalFormatSymbols(Locale.US)); |
- | |
145 | - | ||
146 | out.write("\"WIMSchem!("+mol.NumAtoms()+","+mol.NumBonds()+")\\n\"+"); |
- | |
147 | for (int n=1;n<=mol.NumAtoms();n++) |
- | |
148 | { |
- | |
149 | String hy=mol.AtomHExplicit(n)!=Molecule.HEXPLICIT_UNKNOWN ? ("e"+mol.AtomHExplicit(n)) : ("i"+mol.AtomHydrogens(n)); |
- | |
150 | out.write("\""+mol.AtomElement(n)+"="+fmt.format(mol.AtomX(n))+","+fmt.format(mol.AtomY(n))+";"+ |
- | |
151 | mol.AtomCharge(n)+","+mol.AtomUnpaired(n)+","+hy); |
- | |
152 | if (mol.AtomMapNum(n)>0) out.write(",n"+mol.AtomMapNum(n)); |
- | |
153 | out.write("\\n\"+"); |
- | |
154 | } |
- | |
155 | for (int n=1;n<=mol.NumBonds();n++) |
- | |
156 | { |
- | |
157 | out.write("\""+mol.BondFrom(n)+"-"+mol.BondTo(n)+"="+mol.BondOrder(n)+","+mol.BondType(n)+"\\n\"+"); |
- | |
158 | } |
- | |
159 | out.write("\"!FIN\""); |
- | |
160 | - | ||
161 | out.flush(); |
- | |
162 | } |
- | |
163 | - | ||
164 | // jm.evers |
- | |
165 | // testing with a "convenient way to produce a "MDLMol string" to be used as wims $variable in javascript. |
- | |
166 | public static void WriteMDLMol2JavaScript(OutputStream ostr,Molecule mol) throws IOException { |
- | |
167 | WriteMDLMol2JavaScript(new BufferedWriter(new OutputStreamWriter(ostr)),mol); |
- | |
168 | } |
- | |
169 | public static void WriteMDLMol2JavaScript(BufferedWriter out,Molecule mol) throws IOException { |
- | |
170 | DecimalFormat fmt=new DecimalFormat("0.0000",new DecimalFormatSymbols(Locale.US)); |
- | |
171 | out.write("\"\\nWIMSchem molfile\\n\\n\"+"); |
- | |
172 | out.write("\""+intrpad(mol.NumAtoms(),3)+intrpad(mol.NumBonds(),3)+" 0 0 0 0 0 0 0 0999 V2000\\n\"+"); |
- | |
173 | String line; |
- | |
174 | for (int n=1;n<=mol.NumAtoms();n++) |
- | |
175 | { |
- | |
176 | String str="\" "+fmt.format(mol.AtomX(n)); |
- | |
177 | line=rep(" ",10-str.length())+str; |
- | |
178 | str=fmt.format(mol.AtomY(n)); |
- | |
179 | line+=rep(" ",10-str.length())+str; |
- | |
180 | line+=" 0.0000 "; |
- | |
181 | str=mol.AtomElement(n); |
- | |
182 | line+=str+rep(" ",4-str.length())+"0"; |
- | |
183 | - | ||
184 | int chg=mol.AtomCharge(n),spin=mol.AtomUnpaired(n),mapnum=mol.AtomMapNum(n); |
- | |
185 | if (chg>=-3 && chg<=-1) chg=4-chg; |
- | |
186 | else if (chg==0 && spin==2) chg=4; |
- | |
187 | else if (chg<1 || chg>3) chg=0; |
- | |
188 | line+=intrpad(chg,3)+" 0 0 0 0 0 0 0"+intrpad(mapnum,3)+" 0 0"; |
- | |
189 | - | ||
190 | out.write(line+"\\n\"+"); |
- | |
191 | } |
- | |
192 | - | ||
193 | for (int n=1;n<=mol. |
128 | for (int n=1;n<=mol.numBonds();n++) |
194 | { |
- | |
195 | int type=mol.BondOrder(n); |
- | |
196 | if (type<1 || type>3) type=1; |
- | |
197 | int stereo=mol.BondType(n); |
- | |
198 | if (stereo==Molecule.BONDTYPE_NORMAL) {} |
- | |
199 | else if (stereo==Molecule.BONDTYPE_INCLINED) {stereo=1; type=1;} |
- | |
200 | else if (stereo==Molecule.BONDTYPE_DECLINED) {stereo=6; type=1;} |
- | |
201 | else if (stereo==Molecule.BONDTYPE_UNKNOWN) {stereo=4; type=1;} |
- | |
202 | else stereo=0; |
- | |
203 | - | ||
204 | out.write("\""+intrpad(mol.BondFrom(n),3)+intrpad(mol.BondTo(n),3)+intrpad(type,3)+intrpad(stereo,3)+" 0 0 0\\n\"+"); |
- | |
205 | } |
- | |
206 | - | ||
207 | int count=0; |
- | |
208 | line=""; |
- | |
209 | for (int n=1;n<=mol.NumAtoms();n++) if (mol.AtomCharge(n)!=0) |
- | |
210 | { |
- | |
211 | line+=intrpad(n,4)+intrpad(mol.AtomCharge(n),4); |
- | |
212 | count++; |
- | |
213 | if (count==8) |
- | |
214 | { |
- | |
215 | out.write("\"M CHG"+intrpad(count,3)+line+"\\n\"+"); |
- | |
216 | count=0; line=""; |
- | |
217 | } |
- | |
218 | } |
- | |
219 | if (count>0) out.write("\"M CHG"+intrpad(count,3)+line+"\\n\"+"); |
- | |
220 | - | ||
221 | count=0; |
- | |
222 | line=""; |
- | |
223 | for (int n=1;n<=mol.NumAtoms();n++) if (mol.AtomUnpaired(n)!=0) |
- | |
224 | { |
129 | { |
225 | line+=intrpad(n,4)+intrpad(mol.AtomUnpaired(n),4); |
- | |
226 | count++; |
- | |
227 | if (count==8) |
- | |
228 | { |
- | |
229 |
|
130 | out.write(mol.bondFrom(n)+"-"+mol.bondTo(n)+"="+mol.bondOrder(n)+","+mol.bondType(n)+"\n"); |
230 | count=0; line=""; |
- | |
231 | } |
- | |
232 | } |
131 | } |
233 |
|
132 | out.write("!End\n"); |
234 | 133 | ||
235 | out.write("\"M END\\n\""); |
- | |
236 | out.flush(); |
134 | out.flush(); |
237 | } |
135 | } |
238 | - | ||
239 | - | ||
240 | //jm.evers |
- | |
241 | // converting a molecule to a string in native fileformat.Used for comparing MDLMol js-string with student drawing |
- | |
242 | public static String Molecule2String(Molecule mol) throws IOException { |
- | |
243 | DecimalFormat fmt=new DecimalFormat("0.0000",new DecimalFormatSymbols(Locale.US)); |
- | |
244 | String i="WIMSchem!("+mol.NumAtoms()+","+mol.NumBonds()+")\n"; |
- | |
245 | for (int n=1;n<=mol.NumAtoms();n++) |
- | |
246 | { |
- | |
247 | String hy=mol.AtomHExplicit(n)!=Molecule.HEXPLICIT_UNKNOWN ? ("e"+mol.AtomHExplicit(n)) : ("i"+mol.AtomHydrogens(n)); |
- | |
248 | i=i+mol.AtomElement(n)+"="+fmt.format(mol.AtomX(n))+","+fmt.format(mol.AtomY(n))+";"+mol.AtomCharge(n)+","+mol.AtomUnpaired(n)+","+hy; |
- | |
249 | if (mol.AtomMapNum(n)>0) i=i+",n"+mol.AtomMapNum(n); |
- | |
250 | i=i+"\n"; |
- | |
251 | } |
- | |
252 | for (int n=1;n<=mol.NumBonds();n++) |
- | |
253 | { |
- | |
254 | i=i+mol.BondFrom(n)+"-"+mol.BondTo(n)+"="+mol.BondOrder(n)+","+mol.BondType(n)+"\n"; |
- | |
255 | } |
- | |
256 | i=i+"!FIN\n"; |
- | |
257 | return i; |
- | |
258 | } |
- | |
259 | - | ||
260 | - | ||
261 | 136 | ||
262 | public static Molecule |
137 | public static Molecule readMDLMOL(BufferedReader in) throws IOException |
263 | { |
138 | { |
264 | Molecule mol=new Molecule(); |
139 | Molecule mol=new Molecule(); |
265 | final String GENERIC_ERROR="Invalid MDL MOL file."; |
140 | final String GENERIC_ERROR="Invalid MDL MOL file."; |
266 | 141 | ||
267 | try |
142 | try |
Line 272... | Line 147... | ||
272 | int numAtoms=Integer.parseInt(line.substring(0,3).trim()); |
147 | int numAtoms=Integer.parseInt(line.substring(0,3).trim()); |
273 | int numBonds=Integer.parseInt(line.substring(3,6).trim()); |
148 | int numBonds=Integer.parseInt(line.substring(3,6).trim()); |
274 | for (int n=0;n<numAtoms;n++) |
149 | for (int n=0;n<numAtoms;n++) |
275 | { |
150 | { |
276 | line=in.readLine(); |
151 | line=in.readLine(); |
277 | - | ||
278 | double x=Double.parseDouble(line.substring(0,10).trim()); |
152 | double x=Double.parseDouble(line.substring(0,10).trim()); |
279 | double y=Double.parseDouble(line.substring(10,20).trim()); |
153 | double y=Double.parseDouble(line.substring(10,20).trim()); |
280 | String el=line.substring(31,34).trim(); |
154 | String el=line.substring(31,34).trim(); |
281 | int chg=Integer.parseInt(line.substring(36,39).trim()),rad=0; |
155 | int chg=Integer.parseInt(line.substring(36,39).trim()),rad=0; |
282 | int mapnum=Integer.parseInt(line.substring(60,63).trim()); |
156 | int mapnum=Integer.parseInt(line.substring(60,63).trim()); |
283 | - | ||
284 | if (chg<=3) {} |
157 | if (chg<=3) {} |
285 | else if (chg==4) {chg=0; rad=2;} |
158 | else if (chg==4) {chg=0; rad=2;} |
286 | else chg=4-chg; |
159 | else chg=4-chg; |
287 | - | ||
288 | mol. |
160 | mol.addAtom(el,x,y,chg,rad); |
289 | mol. |
161 | mol.setAtomMapNum(mol.numAtoms(),mapnum); |
290 | } |
162 | } |
291 | for (int n=0;n<numBonds;n++) |
163 | for (int n=0;n<numBonds;n++) |
292 | { |
164 | { |
293 | line=in.readLine(); |
165 | line=in.readLine(); |
294 | - | ||
295 | int from=Integer.parseInt(line.substring(0,3).trim()),to=Integer.parseInt(line.substring(3,6).trim()); |
166 | int from=Integer.parseInt(line.substring(0,3).trim()),to=Integer.parseInt(line.substring(3,6).trim()); |
296 | int type=Integer.parseInt(line.substring(6,9).trim()),stereo=Integer.parseInt(line.substring(9,12).trim()); |
167 | int type=Integer.parseInt(line.substring(6,9).trim()),stereo=Integer.parseInt(line.substring(9,12).trim()); |
297 | - | ||
298 | if (from==to || from<1 || from>numAtoms || to<1 || to>numAtoms) throw new IOException(GENERIC_ERROR); |
168 | if (from==to || from<1 || from>numAtoms || to<1 || to>numAtoms) throw new IOException(GENERIC_ERROR); |
299 | - | ||
300 | int order=type>=1 && type<=3 ? type : 1; |
169 | int order=type>=1 && type<=3 ? type : 1; |
301 | int style=Molecule.BONDTYPE_NORMAL; |
170 | int style=Molecule.BONDTYPE_NORMAL; |
302 | if (stereo==1) style=Molecule.BONDTYPE_INCLINED; |
171 | if (stereo==1) style=Molecule.BONDTYPE_INCLINED; |
303 | else if (stereo==6) style=Molecule.BONDTYPE_DECLINED; |
172 | else if (stereo==6) style=Molecule.BONDTYPE_DECLINED; |
304 | // !! supposed to be for double bonds... else if (stereo==3 || stereo==4) style=Molecule.BONDTYPE_UNKNOWN; |
173 | // !! supposed to be for double bonds... else if (stereo==3 || stereo==4) style=Molecule.BONDTYPE_UNKNOWN; |
305 | - | ||
306 | mol. |
174 | mol.addBond(from,to,order,style); |
307 | } |
175 | } |
308 | while (true) |
176 | while (true) |
309 | { |
177 | { |
310 | line=in.readLine(); |
178 | line=in.readLine(); |
311 | if (line.startsWith("M END")) break; |
179 | if (line.startsWith("M END")) break; |
312 | - | ||
313 | int type=0; |
180 | int type=0; |
314 | if (line.startsWith("M CHG")) type=1; |
181 | if (line.startsWith("M CHG")) type=1; |
315 | else if (line.startsWith("M RAD")) type=2; |
182 | else if (line.startsWith("M RAD")) type=2; |
- | 183 | else if (line.startsWith("M RGP")) type=3; |
|
- | 184 | ||
316 | if (type>0) |
185 | if (type>0) |
317 | { |
186 | { |
318 | int len=Integer.parseInt(line.substring(6,9).trim()); |
187 | int len=Integer.parseInt(line.substring(6,9).trim()); |
319 | for (int n=0;n<len;n++) |
188 | for (int n=0;n<len;n++) |
320 | { |
189 | { |
321 | int apos=Integer.parseInt(line.substring(9+8*n,13+8*n).trim()); |
190 | int apos=Integer.parseInt(line.substring(9+8*n,13+8*n).trim()); |
322 | int aval=Integer.parseInt(line.substring(13+8*n,17+8*n).trim()); |
191 | int aval=Integer.parseInt(line.substring(13+8*n,17+8*n).trim()); |
- | 192 | if (apos<1 || apos>mol.numAtoms()) continue; |
|
- | 193 | ||
323 | if (type==1) mol. |
194 | if (type==1) mol.setAtomCharge(apos,aval); |
- | 195 | else if (type==2) mol.setAtomUnpaired(apos,aval); |
|
- | 196 | else if (type==3) mol.setAtomElement(apos,"R"+aval); |
|
324 | } |
197 | } |
325 | } |
198 | } |
326 | } |
199 | } |
327 | } |
200 | } |
328 | catch (Exception e) {throw new IOException( |
201 | catch (Exception e) {throw new IOException(GENERIC_ERROR,e);} |
329 | 202 | ||
330 | return mol; |
203 | return mol; |
331 | } |
204 | } |
332 | - | ||
333 | 205 | ||
334 | public static void |
206 | public static void writeMDLMOL(OutputStream ostr,Molecule mol) throws IOException |
335 | { |
207 | { |
336 |
|
208 | writeMDLMOL(new BufferedWriter(new OutputStreamWriter(ostr)),mol); |
337 | } |
209 | } |
338 | public static void |
210 | public static void writeMDLMOL(BufferedWriter out,Molecule mol) throws IOException |
339 | { |
211 | { |
340 | DecimalFormat fmt=new DecimalFormat("0.0000",new DecimalFormatSymbols(Locale.US)); |
212 | DecimalFormat fmt=new DecimalFormat("0.0000",new DecimalFormatSymbols(Locale.US)); |
- | 213 | ||
341 | out.write("\nWIMSchem molfile\n\n"); |
214 | out.write("\nWIMSchem molfile\n\n"); |
342 | out.write(intrpad(mol. |
215 | out.write(intrpad(mol.numAtoms(),3)+intrpad(mol.numBonds(),3)+" 0 0 0 0 0 0 0 0999 V2000\n"); |
343 | 216 | ||
344 | String line; |
217 | String line; |
345 | 218 | ||
- | 219 | int numRGroups=0,rgAtom[]=new int[mol.numAtoms()],rgNumber[]=new int[mol.numAtoms()]; |
|
- | 220 | ||
- | 221 | // export atoms, and make a few notes along the way |
|
- | 222 | ||
346 | for (int n=1;n<=mol. |
223 | for (int n=1;n<=mol.numAtoms();n++) |
347 | { |
224 | { |
348 | String str=fmt.format(mol. |
225 | String str=fmt.format(mol.atomX(n)); |
349 | line=rep(" ",10-str.length())+str; |
226 | line=rep(" ",10-str.length())+str; |
350 | str=fmt.format(mol. |
227 | str=fmt.format(mol.atomY(n)); |
351 | line+=rep(" ",10-str.length())+str; |
228 | line+=rep(" ",10-str.length())+str; |
352 | line+=" 0.0000 "; |
229 | line+=" 0.0000 "; |
- | 230 | ||
353 | str=mol. |
231 | str=mol.atomElement(n); |
- | 232 | if (str.length()>1 && str.charAt(0)=='R' && str.charAt(1)>='0' && str.charAt(1)<='9') |
|
- | 233 | { |
|
- | 234 | rgAtom[numRGroups]=n; |
|
- | 235 | rgNumber[numRGroups]=Util.safeInt(str.substring(1)); |
|
- | 236 | numRGroups++; |
|
- | 237 | str="R#"; |
|
- | 238 | } |
|
354 | line+=str+rep(" ",4-str.length())+"0"; |
239 | line+=str+rep(" ",4-str.length())+"0"; |
355 | 240 | ||
356 | int chg=mol. |
241 | int chg=mol.atomCharge(n),spin=mol.atomUnpaired(n),mapnum=mol.atomMapNum(n); |
357 | if (chg>=-3 && chg<=-1) chg=4-chg; |
242 | if (chg>=-3 && chg<=-1) chg=4-chg; |
358 | else if (chg==0 && spin==2) chg=4; |
243 | else if (chg==0 && spin==2) chg=4; |
359 | else if (chg<1 || chg>3) chg=0; |
244 | else if (chg<1 || chg>3) chg=0; |
360 | line+=intrpad(chg,3)+" 0 0 0 0 0 0 0"+intrpad(mapnum,3)+" 0 0"; |
245 | line+=intrpad(chg,3)+" 0 0 0 0 0 0 0"+intrpad(mapnum,3)+" 0 0"; |
361 | 246 | ||
362 | out.write(line+"\n"); |
247 | out.write(line+"\n"); |
363 | } |
248 | } |
- | 249 | ||
- | 250 | // export bonds |
|
364 | 251 | ||
365 | for (int n=1;n<=mol. |
252 | for (int n=1;n<=mol.numBonds();n++) |
366 | { |
253 | { |
367 | int type=mol. |
254 | int type=mol.bondOrder(n); |
368 | if (type<1 || type>3) type=1; |
255 | if (type<1 || type>3) type=1; |
369 | int stereo=mol. |
256 | int stereo=mol.bondType(n); |
370 | if (stereo==Molecule.BONDTYPE_NORMAL) {} |
257 | if (stereo==Molecule.BONDTYPE_NORMAL) {} |
371 | else if (stereo==Molecule.BONDTYPE_INCLINED) {stereo=1; type=1;} |
258 | else if (stereo==Molecule.BONDTYPE_INCLINED) {stereo=1; type=1;} |
372 | else if (stereo==Molecule.BONDTYPE_DECLINED) {stereo=6; type=1;} |
259 | else if (stereo==Molecule.BONDTYPE_DECLINED) {stereo=6; type=1;} |
373 | else if (stereo==Molecule.BONDTYPE_UNKNOWN) {stereo=4; type=1;} |
260 | else if (stereo==Molecule.BONDTYPE_UNKNOWN) {stereo=4; type=1;} |
374 | else stereo=0; |
261 | else stereo=0; |
375 | 262 | ||
376 | out.write(intrpad(mol. |
263 | out.write(intrpad(mol.bondFrom(n),3)+intrpad(mol.bondTo(n),3)+intrpad(type,3)+intrpad(stereo,3)+" 0 0 0\n"); |
377 | } |
264 | } |
- | 265 | ||
- | 266 | // export charges |
|
378 | 267 | ||
379 | int count=0; |
268 | int count=0; |
380 | line=""; |
269 | line=""; |
381 | for (int n=1;n<=mol. |
270 | for (int n=1;n<=mol.numAtoms();n++) if (mol.atomCharge(n)!=0) |
382 | { |
271 | { |
383 | line+=intrpad(n,4)+intrpad(mol. |
272 | line+=intrpad(n,4)+intrpad(mol.atomCharge(n),4); |
384 | count++; |
273 | count++; |
385 | if (count==8) |
274 | if (count==8) |
386 | { |
275 | { |
387 | out.write("M CHG"+intrpad(count,3)+line+"\n"); |
276 | out.write("M CHG"+intrpad(count,3)+line+"\n"); |
388 | count=0; line=""; |
277 | count=0; line=""; |
389 | } |
278 | } |
390 | } |
279 | } |
391 | if (count>0) out.write("M CHG"+intrpad(count,3)+line+"\n"); |
280 | if (count>0) out.write("M CHG"+intrpad(count,3)+line+"\n"); |
392 | 281 | ||
- | 282 | // export "unpaired" atom counts (aka radicals, sort of) |
|
- | 283 | ||
393 | count=0; |
284 | count=0; |
394 | line=""; |
285 | line=""; |
395 | for (int n=1;n<=mol. |
286 | for (int n=1;n<=mol.numAtoms();n++) if (mol.atomUnpaired(n)!=0) |
- | 287 | { |
|
- | 288 | line+=intrpad(n,4)+intrpad(mol.atomUnpaired(n),4); |
|
- | 289 | count++; |
|
- | 290 | if (count==8) |
|
- | 291 | { |
|
- | 292 | out.write("M RAD"+intrpad(count,3)+line+"\n"); |
|
- | 293 | count=0; line=""; |
|
- | 294 | } |
|
- | 295 | } |
|
- | 296 | if (count>0) out.write("M RAD"+intrpad(count,3)+line+"\n"); |
|
- | 297 | ||
- | 298 | // export R-group identifiers |
|
- | 299 | ||
- | 300 | count=0; |
|
- | 301 | line=""; |
|
- | 302 | for (int n=0;n<numRGroups;n++) |
|
396 | { |
303 | { |
397 | line+=intrpad( |
304 | line+=intrpad(rgAtom[n],4)+intrpad(rgNumber[n],4); |
398 | count++; |
305 | count++; |
399 | if (count==8) |
306 | if (count==8) |
400 | { |
307 | { |
401 | out.write("M |
308 | out.write("M RGP"+intrpad(count,3)+line+"\n"); |
402 | count=0; line=""; |
309 | count=0; line=""; |
403 | } |
310 | } |
404 | } |
311 | } |
405 | if (count>0) out.write("M |
312 | if (count>0) out.write("M RGP"+intrpad(count,3)+line+"\n"); |
406 | 313 | ||
407 | out.write("M END\n"); |
314 | out.write("M END\n"); |
408 | out.flush(); |
315 | out.flush(); |
409 | } |
316 | } |
410 | 317 | ||
411 | public static void |
318 | public static void writeCMLXML(OutputStream ostr,Molecule mol) throws IOException |
412 | { |
319 | { |
413 |
|
320 | writeCMLXML(new BufferedWriter(new OutputStreamWriter(ostr)),mol); |
414 | } |
321 | } |
415 | public static void |
322 | public static void writeCMLXML(BufferedWriter out,Molecule mol) throws IOException |
416 | { |
323 | { |
417 | out.write("<cml>\n"); |
324 | out.write("<cml>\n"); |
418 | out.write(" <molecule>\n"); |
325 | out.write(" <molecule>\n"); |
419 | 326 | ||
420 | out.write(" <atomArray>\n"); |
327 | out.write(" <atomArray>\n"); |
421 | for (int n=1;n<=mol. |
328 | for (int n=1;n<=mol.numAtoms();n++) |
422 | { |
329 | { |
423 | out.write(" <atom id=\"a"+n+"\" elementType=\""+mol. |
330 | out.write(" <atom id=\"a"+n+"\" elementType=\""+mol.atomElement(n)+"\""+ |
424 | " x2=\""+mol. |
331 | " x2=\""+mol.atomX(n)+"\" y2=\""+mol.atomY(n)+"\" hydrogenCount=\""+mol.atomHydrogens(n)+"\"/>\n"); |
425 | } |
332 | } |
426 | out.write(" </atomArray>\n"); |
333 | out.write(" </atomArray>\n"); |
427 | 334 | ||
428 | out.write(" <bondArray>\n"); |
335 | out.write(" <bondArray>\n"); |
429 | for (int n=1;n<=mol. |
336 | for (int n=1;n<=mol.numBonds();n++) |
430 | { |
337 | { |
431 | out.write(" <bond id=\"b"+n+"\" atomRefs2=\"a"+mol. |
338 | out.write(" <bond id=\"b"+n+"\" atomRefs2=\"a"+mol.bondFrom(n)+" a"+mol.bondTo(n)+"\" order=\""+mol.bondOrder(n)+"\"/>\n"); |
432 | } |
339 | } |
433 | out.write(" </bondArray>\n"); |
340 | out.write(" </bondArray>\n"); |
434 | 341 | ||
435 | out.write(" </molecule>\n"); |
342 | out.write(" </molecule>\n"); |
436 | out.write("</cml>\n"); |
343 | out.write("</cml>\n"); |
Line 438... | Line 345... | ||
438 | } |
345 | } |
439 | 346 | ||
440 | // examines the beginning of a file and decides whether it can be considered a database of structures which this class is capable |
347 | // examines the beginning of a file and decides whether it can be considered a database of structures which this class is capable |
441 | // of reading... |
348 | // of reading... |
442 | // (NB: currently this includes MDL SD-files, and nothing else) |
349 | // (NB: currently this includes MDL SD-files, and nothing else) |
443 | static boolean |
350 | static boolean examineIsDatabase(FileInputStream istr) throws IOException |
444 | { |
351 | { |
445 | long lastpos=istr.getChannel().position(); |
352 | long lastpos=istr.getChannel().position(); |
446 | boolean |
353 | boolean isdb=findNextPosition(istr,0)>=0; |
447 | istr.getChannel().position(lastpos); |
354 | istr.getChannel().position(lastpos); |
448 | return isdb; |
355 | return isdb; |
449 | } |
356 | } |
450 | 357 | ||
451 | static long |
358 | static long findNextPosition(FileInputStream istr,long startpos) throws IOException |
452 | { |
359 | { |
453 | FileChannel fch=istr.getChannel(); |
360 | FileChannel fch=istr.getChannel(); |
454 | fch.position(startpos); |
361 | fch.position(startpos); |
455 | long pos=startpos,size=fch.size(),nextpos=-1; |
362 | long pos=startpos,size=fch.size(),nextpos=-1; |
456 | 363 | ||
Line 468... | Line 375... | ||
468 | if (nextpos<0) return -1; |
375 | if (nextpos<0) return -1; |
469 | 376 | ||
470 | try |
377 | try |
471 | { |
378 | { |
472 | BufferedReader in=new BufferedReader(new StringReader(rec)); |
379 | BufferedReader in=new BufferedReader(new StringReader(rec)); |
473 | Molecule |
380 | Molecule mol=readMDLMOL(in); |
474 | if (mol==null) nextpos=-1; |
381 | if (mol==null) nextpos=-1; |
475 | } |
382 | } |
476 | catch (IOException e) {nextpos=-1;} |
383 | catch (IOException e) {nextpos=-1;} |
477 | 384 | ||
478 | return nextpos; |
385 | return nextpos; |
479 | } |
386 | } |
480 | 387 | ||
481 | static Molecule |
388 | static Molecule fetchFromPosition(FileInputStream istr,long pos) throws IOException |
482 | { |
389 | { |
483 | istr.getChannel().position(pos); |
390 | istr.getChannel().position(pos); |
484 | return |
391 | return readMDLMOL(new BufferedReader(new InputStreamReader(istr))); |
485 | } |
392 | } |
486 | 393 | ||
487 | // miscellaneous help |
394 | // miscellaneous help |
488 | 395 | ||
489 | static String intrpad(int Val,int Len) |
396 | static String intrpad(int Val,int Len) |
Line 498... | Line 405... | ||
498 | if (Len<=0) return ""; |
405 | if (Len<=0) return ""; |
499 | String str=Ch; |
406 | String str=Ch; |
500 | while (str.length()<Len) str=str+Ch; |
407 | while (str.length()<Len) str=str+Ch; |
501 | return str; |
408 | return str; |
502 | } |
409 | } |
503 | - | ||
504 | public static String GetSmiles(Molecule mol){ |
- | |
505 | // jm.evers |
- | |
506 | // all very clumsy...there must be another/better way of doing this proper ! |
- | |
507 | int a;int b;int p=0;int H1=0;int H2=0;int C1=0;int C2=0;String c1="";;String c2=""; |
- | |
508 | String smile="";int M=mol.NumBonds();int N=mol.NumAtoms(); |
- | |
509 | try{ |
- | |
510 | if(N==1){ |
- | |
511 | if(mol.AtomHExplicit(1)!=Molecule.HEXPLICIT_UNKNOWN){ |
- | |
512 | H1=mol.AtomHExplicit(1); |
- | |
513 | } |
- | |
514 | else |
- | |
515 | { |
- | |
516 | H1=mol.AtomHydrogens(1); |
- | |
517 | } |
- | |
518 | C1=mol.AtomCharge(1); |
- | |
519 | if(C1 != 0){ |
- | |
520 | if(C1>0){ |
- | |
521 | if(C1==1){ |
- | |
522 | c1="<sup><small><b>+</b></small></sup>"; |
- | |
523 | } |
- | |
524 | else |
- | |
525 | { |
- | |
526 | c1="<sup><small><b>"+C1+"+</b></small></sup>"; |
- | |
527 | } |
- | |
528 | } |
- | |
529 | else |
- | |
530 | { |
- | |
531 | C1=-1*C1; |
- | |
532 | if(C1 == 1){ |
- | |
533 | c1="<sup><small><b>-</b></small></sup>"; |
- | |
534 | } |
- | |
535 | else |
- | |
536 | { |
- | |
537 | c1="<sup><small><b>"+C1+"-</b></small></sup>"; |
- | |
538 | } |
- | |
539 | } |
- | |
540 | } |
- | |
541 | else |
- | |
542 | { |
- | |
543 | c1 = ""; |
- | |
544 | } |
- | |
545 | if(H1 != 0){ |
- | |
546 | if(H1 == 1){ |
- | |
547 | smile=mol.AtomElement(1)+c1+"H"; |
- | |
548 | } |
- | |
549 | else |
- | |
550 | { |
- | |
551 | smile=mol.AtomElement(1)+c1+"H<sub><small>"+H1+"</small></sub>"; |
- | |
552 | } |
- | |
553 | } |
- | |
554 | else |
- | |
555 | { |
- | |
556 | smile=mol.AtomElement(1)+c1; |
- | |
557 | } |
- | |
558 | } |
- | |
559 | else |
- | |
560 | { |
- | |
561 | int[] From=new int[M+1]; |
- | |
562 | int[] To=new int[M+1]; |
- | |
563 | boolean[] Fdone=new boolean[N+1]; |
- | |
564 | boolean[] Tdone=new boolean[N+1]; |
- | |
565 | boolean test=true; |
- | |
566 | for(int n=1;n<=M;n++){ |
- | |
567 | From[n]=mol.BondFrom(n); |
- | |
568 | To[n]=mol.BondTo(n); |
- | |
569 | } |
- | |
570 | for(int n=0;n<=N;n++){ |
- | |
571 | Fdone[n]=false; |
- | |
572 | Tdone[n]=false; |
- | |
573 | } |
- | |
574 | for(int n=1;n<=M;n++){ |
- | |
575 | test=true;a=From[n];b=To[n];p=1; |
- | |
576 | if(mol.AtomHExplicit(a)!=Molecule.HEXPLICIT_UNKNOWN){ |
- | |
577 | H1=mol.AtomHExplicit(a); |
- | |
578 | } |
- | |
579 | else |
- | |
580 | { |
- | |
581 | H1=mol.AtomHydrogens(a); |
- | |
582 | } |
- | |
583 | if(mol.AtomHExplicit(b)!=Molecule.HEXPLICIT_UNKNOWN){ |
- | |
584 | H2=mol.AtomHExplicit(b); |
- | |
585 | } |
- | |
586 | else |
- | |
587 | { |
- | |
588 | H2=mol.AtomHydrogens(b); |
- | |
589 | } |
- | |
590 | C1=mol.AtomCharge(a); |
- | |
591 | C2=mol.AtomCharge(b); |
- | |
592 | if(C1 != 0){ |
- | |
593 | if(C1>0){ |
- | |
594 | if(C1==1){ |
- | |
595 | c1="<sup><small><b>+</b></small></sup>"; |
- | |
596 | } |
- | |
597 | else |
- | |
598 | { |
- | |
599 | c1="<sup><small><b>"+C1+"+</b></small></sup>"; |
- | |
600 | } |
- | |
601 | } |
- | |
602 | else |
- | |
603 | { |
- | |
604 | C1=-1*C1; |
- | |
605 | if(C1 == 1){ |
- | |
606 | c1="<sup><small><b>-</b></small></sup>"; |
- | |
607 | } |
- | |
608 | else |
- | |
609 | { |
- | |
610 | c1="<sup><small><b>"+C1+"-</b></small></sup>"; |
- | |
611 | } |
- | |
612 | } |
- | |
613 | } |
- | |
614 | else |
- | |
615 | { |
- | |
616 | c1 = ""; |
- | |
617 | } |
- | |
618 | if(C2 != 0){ |
- | |
619 | if(C2>0){ |
- | |
620 | if(C2==1){ |
- | |
621 | c2="<sup><small><b>+</b></small></sup>"; |
- | |
622 | } |
- | |
623 | else |
- | |
624 | { |
- | |
625 | c2="<sup><small><b>"+C2+"+</b></small></sup>"; |
- | |
626 | } |
- | |
627 | } |
- | |
628 | else |
- | |
629 | { |
- | |
630 | C2=-1*C2; |
- | |
631 | if(C2 == 1){ |
- | |
632 | c2="<sup><small><b>-</b></small></sup>"; |
- | |
633 | } |
- | |
634 | else |
- | |
635 | { |
- | |
636 | c2="<sup><small><b>"+C2+"-</b></small></sup>"; |
- | |
637 | } |
- | |
638 | } |
- | |
639 | } |
- | |
640 | else |
- | |
641 | { |
- | |
642 | c2 = ""; |
- | |
643 | } |
- | |
644 | - | ||
645 | while(test && p<=M){ |
- | |
646 | if(!Fdone[a] && !Tdone[a]){ |
- | |
647 | if(H1 != 0){ |
- | |
648 | if(H1 == 1){ |
- | |
649 | smile=smile+"("+(mol.AtomElement(a))+c1+"H)"+(htmlbond(mol.BondOrder(a))); |
- | |
650 | } |
- | |
651 | else |
- | |
652 | { |
- | |
653 | smile=smile+"("+(mol.AtomElement(a))+c1+"H<sub><small>"+H1+"</small></sub>)"+(htmlbond(mol.BondOrder(a))); |
- | |
654 | } |
- | |
655 | } |
- | |
656 | else |
- | |
657 | { |
- | |
658 | smile=smile+(mol.AtomElement(a))+c1+(htmlbond(mol.BondOrder(a))); |
- | |
659 | } |
- | |
660 | Fdone[a]=true; |
- | |
661 | } |
- | |
662 | - | ||
663 | if(!Tdone[b] && !Fdone[b]){ |
- | |
664 | if(n<M){ |
- | |
665 | if(H2 != 0){ |
- | |
666 | if(H2 == 1){ |
- | |
667 | smile=smile+"("+(mol.AtomElement(b))+c2+"H)"+(htmlbond(mol.BondOrder(b))) ; |
- | |
668 | } |
- | |
669 | else |
- | |
670 | { |
- | |
671 | smile=smile+"("+(mol.AtomElement(b))+c2+"H<sub><small>"+H2+"</small></sub>)"+(htmlbond(mol.BondOrder(b))) ; |
- | |
672 | } |
- | |
673 | } |
- | |
674 | else |
- | |
675 | { |
- | |
676 | smile=smile+(mol.AtomElement(b))+c2+(htmlbond(mol.BondOrder(b))) ; |
- | |
677 | } |
- | |
678 | } |
- | |
679 | else |
- | |
680 | { |
- | |
681 | if( H2 != 0){ |
- | |
682 | if( H2 == 1){ |
- | |
683 | smile=smile+"("+(mol.AtomElement(b))+c2+"H)"; |
- | |
684 | } |
- | |
685 | else |
- | |
686 | { |
- | |
687 | smile=smile+"("+(mol.AtomElement(b))+c2+"H<sub><small>"+H2+"</small></sub>)"; |
- | |
688 | } |
- | |
689 | } |
- | |
690 | else |
- | |
691 | { |
- | |
692 | smile=smile+(mol.AtomElement(b))+c2; |
- | |
693 | } |
- | |
694 | } |
- | |
695 | Tdone[b]=true; |
- | |
696 | } |
- | |
697 | if(Tdone[b] || Fdone[a]){ |
- | |
698 | test=false; |
- | |
699 | } |
- | |
700 | p++; |
- | |
701 | } |
- | |
702 | } |
- | |
703 | } |
- | |
704 | return smile; |
- | |
705 | } |
- | |
706 | catch (Exception e){return "error \n Are You drawing more than 1 molecule ???";} |
- | |
707 | } |
- | |
708 | - | ||
709 | public static String htmlbond(int order){ |
- | |
710 | // jm.evers |
- | |
711 | String s="&minus"; |
- | |
712 | if(order == 0){ |
- | |
713 | s="\u22Ef"; |
- | |
714 | } |
- | |
715 | else |
- | |
716 | { |
- | |
717 | if(order == 1){ |
- | |
718 | s="−"; |
- | |
719 | } |
- | |
720 | else |
- | |
721 | { |
- | |
722 | if(order == 2){ |
- | |
723 | s="="; |
- | |
724 | } |
- | |
725 | else |
- | |
726 | { |
- | |
727 | if(order == 3){ |
- | |
728 | s="≡"; |
- | |
729 | } |
- | |
730 | } |
- | |
731 | } |
- | |
732 | } |
- | |
733 | return s; |
- | |
734 | } |
- | |
735 | - | ||
736 | - | ||
737 | } |
410 | } |