~ubuntu-branches/ubuntu/trusty/cdk/trusty-proposed

« back to all changes in this revision

Viewing changes to src/org/openscience/cdk/applications/jchempaint/InsertTextPanel.java

  • Committer: Bazaar Package Importer
  • Author(s): Paul Cager
  • Date: 2008-04-09 21:17:53 UTC
  • Revision ID: james.westby@ubuntu.com-20080409211753-46lmjw5z8mx5pd8d
Tags: upstream-1.0.2
ImportĀ upstreamĀ versionĀ 1.0.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
* Copyright (C) 2001-2007  Rajarshi Guha <rajarshi@users.sourceforge.net>
 
4
*
 
5
* Contact: cdk-devel@lists.sourceforge.net
 
6
*
 
7
* This program is free software; you can redistribute it and/or
 
8
* modify it under the terms of the GNU Lesser General Public License
 
9
* as published by the Free Software Foundation; either version 2.1
 
10
* of the License, or (at your option) any later version.
 
11
* All we ask is that proper credit is given for our work, which includes
 
12
* - but is not limited to - adding the above copyright notice to the beginning
 
13
* of your source code files, and to any copyright notice that you may distribute
 
14
* with programs based on this work.
 
15
*
 
16
* This program is distributed in the hope that it will be useful,
 
17
* but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
* GNU Lesser General Public License for more details.
 
20
*
 
21
* You should have received a copy of the GNU Lesser General Public License
 
22
* along with this program; if not, write to the Free Software
 
23
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 
24
*
 
25
*/
 
26
package org.openscience.cdk.applications.jchempaint;
 
27
 
 
28
import java.awt.GridBagConstraints;
 
29
import java.awt.GridBagLayout;
 
30
import java.awt.Insets;
 
31
import java.awt.event.ActionEvent;
 
32
import java.awt.event.ActionListener;
 
33
import java.io.BufferedReader;
 
34
import java.io.IOException;
 
35
import java.io.InputStreamReader;
 
36
import java.net.URL;
 
37
import java.util.ArrayList;
 
38
import java.util.Iterator;
 
39
import java.util.List;
 
40
import java.util.regex.Matcher;
 
41
import java.util.regex.Pattern;
 
42
 
 
43
import javax.swing.JButton;
 
44
import javax.swing.JComboBox;
 
45
import javax.swing.JFrame;
 
46
import javax.swing.JOptionPane;
 
47
import javax.swing.JPanel;
 
48
import javax.swing.text.JTextComponent;
 
49
import javax.vecmath.Vector2d;
 
50
 
 
51
import net.sf.jniinchi.INCHI_RET;
 
52
 
 
53
import org.openscience.cdk.DefaultChemObjectBuilder;
 
54
import org.openscience.cdk.MoleculeSet;
 
55
import org.openscience.cdk.exception.CDKException;
 
56
import org.openscience.cdk.exception.InvalidSmilesException;
 
57
import org.openscience.cdk.geometry.GeometryTools;
 
58
import org.openscience.cdk.inchi.InChIGeneratorFactory;
 
59
import org.openscience.cdk.inchi.InChIToStructure;
 
60
import org.openscience.cdk.interfaces.IAtomContainer;
 
61
import org.openscience.cdk.interfaces.IMolecule;
 
62
import org.openscience.cdk.layout.StructureDiagramGenerator;
 
63
import org.openscience.cdk.layout.TemplateHandler;
 
64
import org.openscience.cdk.renderer.Renderer2DModel;
 
65
import org.openscience.cdk.smiles.SmilesParser;
 
66
import org.openscience.cdk.tools.manipulator.ChemModelManipulator;
 
67
 
 
68
/**
 
69
 * A panel containing a text field and button to directly insert SMILES or InChI's
 
70
 *
 
71
 * @author Rajarshi Guha
 
72
 * @cdk.module jchempaint
 
73
 * @cdk.require swing
 
74
 */
 
75
public class InsertTextPanel extends JPanel implements ActionListener {
 
76
 
 
77
    private JChemPaintPanel jChemPaintPanel;
 
78
    private JComboBox textCombo;
 
79
    private JTextComponent editor;
 
80
    private JFrame closeafter=null;
 
81
 
 
82
 
 
83
    public InsertTextPanel(JChemPaintPanel jChemPaintPanel, JFrame closeafter) {
 
84
        super();
 
85
        this.closeafter=closeafter;
 
86
        setLayout(new GridBagLayout());
 
87
 
 
88
        List oldText = new ArrayList();
 
89
        oldText.add("");
 
90
 
 
91
        textCombo = new JComboBox(oldText.toArray());
 
92
        textCombo.setEditable(true);
 
93
        textCombo.setToolTipText("Enter a CAS, SMILES or InChI string");
 
94
 
 
95
        textCombo.addActionListener(this);
 
96
        editor = (JTextComponent) textCombo.getEditor().getEditorComponent();
 
97
 
 
98
 
 
99
        JButton button = new JButton("Insert");
 
100
        button.addActionListener(this);
 
101
 
 
102
        GridBagConstraints gridBagConstraints = new GridBagConstraints();
 
103
 
 
104
 
 
105
        gridBagConstraints.gridx = 0;
 
106
        gridBagConstraints.gridy = 0;
 
107
        gridBagConstraints.fill = GridBagConstraints.HORIZONTAL;
 
108
        gridBagConstraints.anchor = GridBagConstraints.FIRST_LINE_START;
 
109
        gridBagConstraints.weightx = 0.5;
 
110
        gridBagConstraints.ipadx = 5;
 
111
        gridBagConstraints.insets = new Insets(0, 0, 0, 5);
 
112
        add(textCombo, gridBagConstraints);
 
113
 
 
114
        gridBagConstraints.insets = new Insets(0, 0, 2, 0);
 
115
        gridBagConstraints.ipadx = 5;
 
116
        gridBagConstraints.ipady = 2;
 
117
        gridBagConstraints.weightx = 0.0;
 
118
        gridBagConstraints.gridx = 1;
 
119
        add(button, gridBagConstraints);
 
120
 
 
121
 
 
122
        this.jChemPaintPanel = jChemPaintPanel;
 
123
    }
 
124
 
 
125
    public void actionPerformed(ActionEvent actionEvent) {
 
126
        String actionCommand = actionEvent.getActionCommand();
 
127
        if (actionCommand.equals("comboBoxEdited") || actionCommand.equals("Insert")) {
 
128
            IMolecule molecule = getMolecule();
 
129
            if (molecule == null) return;
 
130
            generateModel(molecule);
 
131
            if(closeafter!=null)
 
132
                closeafter.setVisible(false);
 
133
        }
 
134
    }
 
135
 
 
136
    private IMolecule getMolecule() {
 
137
 
 
138
        IMolecule molecule;
 
139
        String text = (String) textCombo.getSelectedItem();
 
140
        text = text.trim(); // clean up extra white space
 
141
 
 
142
        if (text.equals("")) return null;
 
143
 
 
144
        if (text.startsWith("InChI")) { // handle it as an InChI
 
145
            try {
 
146
                InChIGeneratorFactory inchiFactory = new InChIGeneratorFactory();
 
147
                InChIToStructure inchiToStructure = inchiFactory.getInChIToStructure(text);
 
148
                INCHI_RET status = inchiToStructure.getReturnStatus();
 
149
                if (status != INCHI_RET.OKAY) {
 
150
                  JOptionPane.showMessageDialog(jChemPaintPanel, "Could not process InChI");
 
151
                  return null;
 
152
                }
 
153
                IAtomContainer atomContainer = inchiToStructure.getAtomContainer();
 
154
                molecule = atomContainer.getBuilder().newMolecule(atomContainer);
 
155
            } catch (CDKException e2) {
 
156
                JOptionPane.showMessageDialog(jChemPaintPanel, "Could not load InChI subsystem");
 
157
                return null;
 
158
            }
 
159
        } else if (isCASNumber(text)) { // is it a CAS number?
 
160
            try {
 
161
                molecule = getMoleculeFromCAS(text);
 
162
            } catch (IOException e) {
 
163
                JOptionPane.showMessageDialog(jChemPaintPanel, "Error in reading data from PubChem");
 
164
                return null;
 
165
            }
 
166
        } else { // OK, it must be a SMILES
 
167
            SmilesParser smilesParser = new SmilesParser(DefaultChemObjectBuilder.getInstance());
 
168
            try {
 
169
                molecule = smilesParser.parseSmiles(text);
 
170
            } catch (InvalidSmilesException e1) {
 
171
                JOptionPane.showMessageDialog(jChemPaintPanel, "Invalid SMILES specified");
 
172
                return null;
 
173
            }
 
174
        }
 
175
 
 
176
        // OK, we have a valid molecule, save it and show it
 
177
        String tmp = (String) textCombo.getItemAt(0);
 
178
        if (tmp.equals("")) textCombo.removeItemAt(0);
 
179
        textCombo.addItem(text);
 
180
        editor.setText("");
 
181
 
 
182
        return molecule;
 
183
    }
 
184
 
 
185
    private boolean isCASNumber(String text) {
 
186
        String[] chars = text.split("-");
 
187
        if (chars.length != 3) return false;
 
188
        for (int i = 0; i < 3; i++) {
 
189
            if (i == 2 && chars[i].length() != 1) return false;
 
190
            if (i == 1 && chars[i].length() != 2) return false;
 
191
            if (i == 0 && chars[i].length() > 6) return false;
 
192
            try {
 
193
                Integer.parseInt(chars[i]);
 
194
            } catch (NumberFormatException e) {
 
195
                return false;
 
196
            }
 
197
        }
 
198
        return true;
 
199
    }
 
200
 
 
201
    private IMolecule getMoleculeFromCAS(String cas) throws IOException {
 
202
        String data;
 
203
 
 
204
        String firstURL = "http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=pccompound&term=" + cas;
 
205
 
 
206
        data = getDataFromURL(firstURL);
 
207
 
 
208
        Pattern pattern = Pattern.compile("http://pubchem.ncbi.nlm.nih.gov/summary/summary.cgi\\?cid=(\\d*)");
 
209
        Matcher matcher = pattern.matcher(data);
 
210
 
 
211
        String cid = null;
 
212
        boolean found = false;
 
213
        while (matcher.find()) {
 
214
            cid = matcher.group(1);
 
215
            try { // should be an integer
 
216
                Integer.parseInt(cid);
 
217
                found = true;
 
218
                break;
 
219
            } catch (NumberFormatException e) {
 
220
                continue;
 
221
            }
 
222
        }
 
223
        if (!found) return null;
 
224
 
 
225
        String secondURL = "http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esummary.fcgi?tool=jcppubchem&db=pccompound&id=" + cid;
 
226
        data = getDataFromURL(secondURL);
 
227
 
 
228
        pattern = Pattern.compile("<Item Name=\"CanonicalSmile\" Type=\"String\">([^\\s]*?)</Item>");
 
229
        matcher = pattern.matcher(data);
 
230
        String smiles = null;
 
231
        found = false;
 
232
        while (matcher.find()) {
 
233
            smiles = matcher.group(1);
 
234
            if (smiles != null || !smiles.equals("")) {
 
235
                found = true;
 
236
                break;
 
237
            }
 
238
        }
 
239
        if (!found) return null;
 
240
 
 
241
        // got the canonical SMILES, lets get the molecule
 
242
        SmilesParser smilesParser = new SmilesParser(DefaultChemObjectBuilder.getInstance());
 
243
        IMolecule molecule;
 
244
        try {
 
245
            molecule = smilesParser.parseSmiles(smiles);
 
246
        } catch (InvalidSmilesException e1) {
 
247
            JOptionPane.showMessageDialog(jChemPaintPanel, "Couldn't process data from PubChem");
 
248
            return null;
 
249
        }
 
250
        return molecule;
 
251
    }
 
252
 
 
253
    private String getDataFromURL(String url) throws IOException {
 
254
        URL theURL = new URL(url);
 
255
        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(theURL.openStream()));
 
256
        String data = "";
 
257
        String line;
 
258
        while ((line = bufferedReader.readLine()) != null) data += line;
 
259
        bufferedReader.close();
 
260
        return data;
 
261
    }
 
262
 
 
263
    public void generateModel(IMolecule molecule) {
 
264
        if (molecule == null) return;
 
265
 
 
266
        // ok, get relevent bits from active model
 
267
        JChemPaintModel jcpModel = jChemPaintPanel.getJChemPaintModel();
 
268
        Renderer2DModel renderModel = jcpModel.getRendererModel();
 
269
        org.openscience.cdk.interfaces.IChemModel chemModel = jcpModel.getChemModel();
 
270
        org.openscience.cdk.interfaces.IMoleculeSet moleculeSet = chemModel.getMoleculeSet();
 
271
        if (moleculeSet == null) {
 
272
            moleculeSet = new MoleculeSet();
 
273
        }
 
274
 
 
275
        // ok, now generate 2D coordinates
 
276
        StructureDiagramGenerator sdg = new StructureDiagramGenerator();
 
277
        sdg.setTemplateHandler(new TemplateHandler(moleculeSet.getBuilder()));
 
278
        try {
 
279
            sdg.setMolecule(molecule);
 
280
            sdg.generateCoordinates(new Vector2d(0, 1));
 
281
            molecule = sdg.getMolecule();
 
282
            double bondLength = renderModel.getBondLength();
 
283
            double scaleFactor = GeometryTools.getScaleFactor(molecule, bondLength,jChemPaintPanel.getJChemPaintModel().getRendererModel().getRenderingCoordinates());
 
284
            GeometryTools.scaleMolecule(molecule, scaleFactor, renderModel.getRenderingCoordinates());
 
285
            //if there are no atoms in the actual chemModel all 2D-coordinates would be set to NaN
 
286
            if (ChemModelManipulator.getAtomCount(chemModel) != 0) {
 
287
                IAtomContainer container = chemModel.getBuilder().newAtomContainer();
 
288
                Iterator containers = ChemModelManipulator.getAllAtomContainers(chemModel).iterator();
 
289
                while (containers.hasNext()) {
 
290
                        container.add((IAtomContainer)containers.next());
 
291
                }
 
292
                GeometryTools.translate2DCenterTo((IAtomContainer)molecule,
 
293
                                GeometryTools.get2DCenter(container,
 
294
                                jChemPaintPanel.getJChemPaintModel().getRendererModel().getRenderingCoordinates()
 
295
                        ),
 
296
                        jChemPaintPanel.getJChemPaintModel().getRendererModel().getRenderingCoordinates()
 
297
                );
 
298
            }
 
299
            GeometryTools.translate2D(molecule, 5 * bondLength, 0, renderModel.getRenderingCoordinates()); // in pixels
 
300
        } catch (Exception exc) {
 
301
            exc.printStackTrace();
 
302
        }
 
303
 
 
304
        moleculeSet.addMolecule(molecule);
 
305
//        renderModel.setSelectedPart(m);
 
306
        jChemPaintPanel.getChemModel().setMoleculeSet(moleculeSet);
 
307
        jChemPaintPanel.scaleAndCenterMolecule(jChemPaintPanel.getChemModel());
 
308
        jcpModel.fireChange(jChemPaintPanel.getChemModel());
 
309
    }
 
310
}