JAL-2089 patch broken merge to master for Release 2.10.0b1
[jalview.git] / src / jalview / ws / dbsources / Pdb.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3  * Copyright (C) $$Year-Rel$$ The Jalview Authors
4  * 
5  * This file is part of Jalview.
6  * 
7  * Jalview is free software: you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License 
9  * as published by the Free Software Foundation, either version 3
10  * of the License, or (at your option) any later version.
11  *  
12  * Jalview is distributed in the hope that it will be useful, but 
13  * WITHOUT ANY WARRANTY; without even the implied warranty 
14  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
15  * PURPOSE.  See the GNU General Public License for more details.
16  * 
17  * You should have received a copy of the GNU General Public License
18  * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
19  * The Jalview Authors are detailed in the 'AUTHORS' file.
20  */
21 package jalview.ws.dbsources;
22
23 import jalview.api.FeatureSettingsModelI;
24 import jalview.datamodel.AlignmentAnnotation;
25 import jalview.datamodel.AlignmentI;
26 import jalview.datamodel.DBRefEntry;
27 import jalview.datamodel.DBRefSource;
28 import jalview.datamodel.PDBEntry;
29 import jalview.datamodel.PDBEntry.Type;
30 import jalview.datamodel.SequenceI;
31 import jalview.io.FormatAdapter;
32 import jalview.io.PDBFeatureSettings;
33 import jalview.structure.StructureImportSettings;
34 import jalview.util.MessageManager;
35 import jalview.ws.ebi.EBIFetchClient;
36
37 import java.util.ArrayList;
38 import java.util.List;
39
40 import com.stevesoft.pat.Regex;
41
42 /**
43  * @author JimP
44  * 
45  */
46 public class Pdb extends EbiFileRetrievedProxy
47 {
48   private static final String SEPARATOR = "|";
49
50   private static final String COLON = ":";
51
52   private static final int PDB_ID_LENGTH = 4;
53
54   public Pdb()
55   {
56     super();
57   }
58
59   /*
60    * (non-Javadoc)
61    * 
62    * @see jalview.ws.DbSourceProxy#getAccessionSeparator()
63    */
64   @Override
65   public String getAccessionSeparator()
66   {
67     return null;
68   }
69
70   /*
71    * (non-Javadoc)
72    * 
73    * @see jalview.ws.DbSourceProxy#getAccessionValidator()
74    */
75   @Override
76   public Regex getAccessionValidator()
77   {
78     return new Regex("([1-9][0-9A-Za-z]{3}):?([ _A-Za-z0-9]?)");
79   }
80
81   /*
82    * (non-Javadoc)
83    * 
84    * @see jalview.ws.DbSourceProxy#getDbSource()
85    */
86   @Override
87   public String getDbSource()
88   {
89     return DBRefSource.PDB;
90   }
91
92   /*
93    * (non-Javadoc)
94    * 
95    * @see jalview.ws.DbSourceProxy#getDbVersion()
96    */
97   @Override
98   public String getDbVersion()
99   {
100     return "0";
101   }
102
103   /*
104    * (non-Javadoc)
105    * 
106    * @see jalview.ws.DbSourceProxy#getSequenceRecords(java.lang.String[])
107    */
108   @Override
109   public AlignmentI getSequenceRecords(String queries) throws Exception
110   {
111     AlignmentI pdbAlignment = null;
112     String chain = null;
113     String id = null;
114     if (queries.indexOf(COLON) > -1)
115     {
116       chain = queries.substring(queries.indexOf(COLON) + 1);
117       id = queries.substring(0, queries.indexOf(COLON));
118     }
119     else
120     {
121       id = queries;
122     }
123
124     /*
125      * extract chain code if it is appended to the id and we
126      * don't already have one
127      */
128     if (queries.length() > PDB_ID_LENGTH && chain == null)
129     {
130       chain = queries.substring(PDB_ID_LENGTH, PDB_ID_LENGTH + 1);
131       id = queries.substring(0, PDB_ID_LENGTH);
132     }
133
134     if (!isValidReference(id))
135     {
136       System.err.println("Ignoring invalid pdb query: '" + id + "'");
137       stopQuery();
138       return null;
139     }
140     String ext = StructureImportSettings.getDefaultStructureFileFormat()
141             .equalsIgnoreCase(Type.MMCIF.toString()) ? ".cif" : ".xml";
142     EBIFetchClient ebi = new EBIFetchClient();
143     file = ebi.fetchDataAsFile(
144             "pdb:" + id,
145             StructureImportSettings.getDefaultStructureFileFormat()
146                     .toLowerCase(), ext).getAbsolutePath();
147     stopQuery();
148     if (file == null)
149     {
150       return null;
151     }
152     try
153     {
154
155       pdbAlignment = new FormatAdapter().readFile(file,
156               jalview.io.AppletFormatAdapter.FILE,
157               StructureImportSettings.getDefaultStructureFileFormat());
158       if (pdbAlignment != null)
159       {
160         List<SequenceI> toremove = new ArrayList<SequenceI>();
161         for (SequenceI pdbcs : pdbAlignment.getSequences())
162         {
163           String chid = null;
164           // Mapping map=null;
165           for (PDBEntry pid : pdbcs.getAllPDBEntries())
166           {
167             if (pid.getFile() == file)
168             {
169               chid = pid.getChainCode();
170
171             }
172           }
173           if (chain == null
174                   || (chid != null && (chid.equals(chain)
175                           || chid.trim().equals(chain.trim()) || (chain
176                           .trim().length() == 0 && chid.equals("_")))))
177           {
178             // FIXME seems to result in 'PDB|1QIP|1qip|A' - 1QIP is redundant.
179             // TODO: suggest simplify naming to 1qip|A as default name defined
180             pdbcs.setName(jalview.datamodel.DBRefSource.PDB + SEPARATOR
181                     + id + SEPARATOR + pdbcs.getName());
182             // Might need to add more metadata to the PDBEntry object
183             // like below
184             /*
185              * PDBEntry entry = new PDBEntry(); // Construct the PDBEntry
186              * entry.setId(id); if (entry.getProperty() == null)
187              * entry.setProperty(new Hashtable());
188              * entry.getProperty().put("chains", pdbchain.id + "=" +
189              * sq.getStart() + "-" + sq.getEnd());
190              * sq.getDatasetSequence().addPDBId(entry);
191              */
192             // Add PDB DB Refs
193             // We make a DBRefEtntry because we have obtained the PDB file from
194             // a
195             // verifiable source
196             // JBPNote - PDB DBRefEntry should also carry the chain and mapping
197             // information
198             DBRefEntry dbentry = new DBRefEntry(getDbSource(),
199                     getDbVersion(), (chid == null ? id : id + chid));
200             // dbentry.setMap()
201             pdbcs.addDBRef(dbentry);
202           }
203           else
204           {
205             // mark this sequence to be removed from the alignment
206             // - since it's not from the right chain
207             toremove.add(pdbcs);
208           }
209         }
210         // now remove marked sequences
211         for (SequenceI pdbcs : toremove)
212         {
213           pdbAlignment.deleteSequence(pdbcs);
214           if (pdbcs.getAnnotation() != null)
215           {
216             for (AlignmentAnnotation aa : pdbcs.getAnnotation())
217             {
218               pdbAlignment.deleteAnnotation(aa);
219             }
220           }
221         }
222       }
223
224       if (pdbAlignment == null || pdbAlignment.getHeight() < 1)
225       {
226         throw new Exception(MessageManager.formatMessage(
227                 "exception.no_pdb_records_for_chain", new String[] { id,
228                     ((chain == null) ? "' '" : chain) }));
229       }
230
231     } catch (Exception ex) // Problem parsing PDB file
232     {
233       stopQuery();
234       throw (ex);
235     }
236     return pdbAlignment;
237   }
238
239   /*
240    * (non-Javadoc)
241    * 
242    * @see jalview.ws.DbSourceProxy#isValidReference(java.lang.String)
243    */
244   @Override
245   public boolean isValidReference(String accession)
246   {
247     Regex r = getAccessionValidator();
248     return r.search(accession.trim());
249   }
250
251   /**
252    * human glyoxalase
253    */
254   @Override
255   public String getTestQuery()
256   {
257     return "1QIP";
258   }
259
260   @Override
261   public String getDbName()
262   {
263     return "PDB"; // getDbSource();
264   }
265
266   @Override
267   public int getTier()
268   {
269     return 0;
270   }
271
272   /**
273    * Returns a descriptor for suitable feature display settings with
274    * <ul>
275    * <li>ResNums or insertions features visible</li>
276    * <li>insertions features coloured red</li>
277    * <li>ResNum features coloured by label</li>
278    * <li>Insertions displayed above (on top of) ResNums</li>
279    * </ul>
280    */
281   @Override
282   public FeatureSettingsModelI getFeatureColourScheme()
283   {
284     return new PDBFeatureSettings();
285   }
286 }