JAL-2136 fixed failing unit test for Phyre2Client
[jalview.git] / src / jalview / ws / phyre2 / Phyre2Client.java
1 package jalview.ws.phyre2;
2
3 import jalview.datamodel.AlignmentI;
4 import jalview.datamodel.SequenceI;
5 import jalview.fts.core.DecimalFormatTableCellRenderer;
6 import jalview.io.AppletFormatAdapter;
7 import jalview.io.DataSourceType;
8 import jalview.io.FileFormat;
9 import jalview.io.FormatAdapter;
10 import jalview.io.StructureFile;
11 import jalview.schemes.ResidueProperties;
12 import jalview.structure.StructureMapping;
13 import jalview.structure.StructureMappingClient;
14 import jalview.structures.models.MappingOutputModel;
15 import jalview.util.Comparison;
16 import jalview.util.Format;
17
18 import java.io.BufferedReader;
19 import java.io.File;
20 import java.io.FileReader;
21 import java.io.IOException;
22 import java.io.PrintStream;
23 import java.util.ArrayList;
24 import java.util.HashMap;
25 import java.util.List;
26
27 import javax.swing.JTable;
28 import javax.swing.table.DefaultTableModel;
29
30 public class Phyre2Client extends StructureMappingClient
31 {
32   private final static String NEWLINE = System.lineSeparator();
33
34   public static final int UNASSIGNED = -1;
35
36   private final static String PATH_SEPARATOR = File.separator;
37
38   private String fastaMappingFile;
39
40   public Phyre2Client(StructureFile structureFile)
41   {
42     this.structureFile = structureFile;
43   }
44
45   public StructureMapping getStructureMapping(SequenceI seq,
46           String pdbFile, String fMappingFile, String chain)
47   {
48     this.fastaMappingFile = fMappingFile;
49     return getStructureMapping(seq, pdbFile, chain);
50   }
51
52   @Override
53   public StructureMapping getStructureMapping(SequenceI seq,
54           String pdbFile, String chain)
55   {
56     final StringBuilder mappingDetails = new StringBuilder(128);
57     PrintStream ps = new PrintStream(System.out)
58     {
59       @Override
60       public void print(String x)
61       {
62         mappingDetails.append(x);
63       }
64
65       @Override
66       public void println()
67       {
68         mappingDetails.append(NEWLINE);
69       }
70     };
71     HashMap<Integer, int[]> mapping = getPhyre2FastaMapping(seq, ps);
72
73     String mappingOutput = mappingDetails.toString();
74     StructureMapping phyre2ModelMapping = new StructureMapping(seq,
75             pdbFile, structureFile.getId(), chain, mapping, mappingOutput);
76     return phyre2ModelMapping;
77   }
78
79   public HashMap<Integer, int[]> getPhyre2FastaMapping(SequenceI inputSeq,
80           java.io.PrintStream os)
81   {
82     HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
83     AlignmentI seq2Phyre2ModelFastaMapping = null;
84     try
85     {
86       String fastaFile = getFastaMappingFile();
87       DataSourceType protocol = AppletFormatAdapter
88               .checkProtocol(fastaFile);
89       seq2Phyre2ModelFastaMapping = new FormatAdapter().readFile(fastaFile,
90               protocol, FileFormat.Fasta);
91     } catch (IOException e1)
92     {
93       e1.printStackTrace();
94     }
95     SequenceI[] seqs = seq2Phyre2ModelFastaMapping.getSequencesArray();
96     SequenceI tSequenceRes = seqs[0];
97     SequenceI tStructureRes = seqs[1];
98
99     // Essential to resolve fastaAlignment to input sequence and model sequence
100     // coordinates
101     tSequenceRes.setStart(inputSeq.getStart());
102     tSequenceRes.setEnd(inputSeq.getEnd());
103
104     tStructureRes.setStart(structureFile.getSeqsAsArray()[0].getStart());
105     tStructureRes.setEnd(structureFile.getSeqsAsArray()[0].getEnd());
106     try
107     {
108       int sequenceResLenght = tSequenceRes.getLength();
109       int structureResLenght = tStructureRes.getLength();
110       if (sequenceResLenght == structureResLenght)
111       {
112         int prevStructResNum = -1;
113         int alignmentLenght = sequenceResLenght + tSequenceRes.getStart();
114         for (int x = 0; x < alignmentLenght; x++)
115         {
116           int alignSeqResidueIndex = tSequenceRes.findIndex(x);
117           int structResNum = tStructureRes
118                   .findPosition(alignSeqResidueIndex);
119           int sequenceResNum = tSequenceRes
120                   .findPosition(alignSeqResidueIndex - 1);
121           boolean sameResNum = (structResNum == prevStructResNum);
122           // System.out.println(sequenceResNum + " : "
123           // + (sameResNum ? -1 : prevStructResNum));
124           mapping.put(sequenceResNum, new int[] {
125               sameResNum ? -1 : prevStructResNum, -1 });
126           prevStructResNum = structResNum;
127         }
128       }
129     } catch (Exception e)
130     {
131       e.printStackTrace();
132     }
133
134     try
135     {
136       populateAtomPositions(" ", mapping);
137     } catch (IllegalArgumentException e)
138     {
139       e.printStackTrace();
140     } catch (StructureMappingException e)
141     {
142       e.printStackTrace();
143     }
144
145     if (os != null)
146     {
147       MappingOutputModel mop = new MappingOutputModel();
148       mop.setSeqStart(tSequenceRes.getStart());
149       mop.setSeqEnd(tSequenceRes.getEnd());
150       mop.setSeqName(tSequenceRes.getName());
151       mop.setSeqResidue(tSequenceRes.getSequenceAsString());
152
153       mop.setStrStart(tStructureRes.getStart());
154       mop.setStrEnd(tStructureRes.getEnd());
155       mop.setStrName(tStructureRes.getName());
156       mop.setStrResidue(tStructureRes.getSequenceAsString());
157
158       mop.setType("pep");
159       try
160       {
161         os.print(getMappingOutput(mop).toString());
162       } catch (Exception e)
163       {
164         e.printStackTrace();
165       }
166       os.println();
167     }
168     return mapping;
169   }
170
171   private String getFastaMappingFile()
172   {
173     return fastaMappingFile;
174   }
175
176   void setFastaMappingFile(String fastaMappingFile)
177   {
178     this.fastaMappingFile = fastaMappingFile;
179   }
180
181   @Override
182   public StringBuffer getMappingOutput(MappingOutputModel mp)
183           throws StructureMappingException
184   {
185     String seqRes = mp.getSeqResidue();
186     String seqName = mp.getSeqName();
187     int sStart = mp.getSeqStart();
188     int sEnd = mp.getSeqEnd();
189
190     String strRes = mp.getStrResidue();
191     String strName = mp.getStrName();
192     int pdbStart = mp.getStrStart();
193     int pdbEnd = mp.getStrEnd();
194
195     String type = mp.getType();
196
197     int maxid = (seqName.length() >= strName.length()) ? seqName.length()
198             : strName.length();
199     int len = 72 - maxid - 1;
200
201     int nochunks = ((seqRes.length()) / len)
202             + ((seqRes.length()) % len > 0 ? 1 : 0);
203     // output mappings
204     StringBuffer output = new StringBuffer();
205     output.append(NEWLINE);
206     output.append("Sequence \u27f7 Structure mapping details").append(
207             NEWLINE);
208     output.append("Method: Phyre2 Alignment");
209     output.append(NEWLINE).append(NEWLINE);
210
211     output.append(new Format("%" + maxid + "s").form(seqName));
212     output.append(" :  ");
213     output.append(String.valueOf(sStart));
214     output.append(" - ");
215     output.append(String.valueOf(sEnd));
216     output.append(" Maps to ");
217     output.append(NEWLINE);
218     output.append(new Format("%" + maxid + "s").form(strName));
219     output.append(" :  ");
220     output.append(String.valueOf(pdbStart));
221     output.append(" - ");
222     output.append(String.valueOf(pdbEnd));
223     output.append(NEWLINE).append(NEWLINE);
224
225     int matchedSeqCount = 0;
226     for (int j = 0; j < nochunks; j++)
227     {
228       // Print the first aligned sequence
229       output.append(new Format("%" + (maxid) + "s").form(seqName)).append(
230               " ");
231
232       for (int i = 0; i < len; i++)
233       {
234         if ((i + (j * len)) < seqRes.length())
235         {
236           output.append(seqRes.charAt(i + (j * len)));
237         }
238       }
239
240       output.append(NEWLINE);
241       output.append(new Format("%" + (maxid) + "s").form(" ")).append(" ");
242
243       // Print out the matching chars
244       for (int i = 0; i < len; i++)
245       {
246         try
247         {
248           if ((i + (j * len)) < seqRes.length())
249           {
250             boolean sameChar = Comparison.isSameResidue(
251                     seqRes.charAt(i + (j * len)),
252                     strRes.charAt(i + (j * len)), false);
253             if (sameChar
254                     && !jalview.util.Comparison.isGap(seqRes.charAt(i
255                             + (j * len))))
256             {
257               matchedSeqCount++;
258               output.append("|");
259             }
260             else if (type.equals("pep"))
261             {
262               if (ResidueProperties.getPAM250(seqRes.charAt(i + (j * len)),
263                       strRes.charAt(i + (j * len))) > 0)
264               {
265                 output.append(".");
266               }
267               else
268               {
269                 output.append(" ");
270               }
271             }
272             else
273             {
274               output.append(" ");
275             }
276           }
277         } catch (IndexOutOfBoundsException e)
278         {
279           continue;
280         }
281       }
282       // Now print the second aligned sequence
283       output = output.append(NEWLINE);
284       output = output.append(new Format("%" + (maxid) + "s").form(strName))
285               .append(" ");
286       for (int i = 0; i < len; i++)
287       {
288         if ((i + (j * len)) < strRes.length())
289         {
290           output.append(strRes.charAt(i + (j * len)));
291         }
292       }
293       output.append(NEWLINE).append(NEWLINE);
294     }
295     float pid = (float) matchedSeqCount / seqRes.length() * 100;
296     output.append("Length of alignment = " + seqRes.length()).append(
297             NEWLINE);
298     output.append(new Format("Percentage ID = %2.2f").form(pid));
299     return output;
300   }
301
302
303   public static List<Phyre2SummaryPojo> parsePhyreCrudeList(String crudeList)
304   {
305     List<Phyre2SummaryPojo> phyre2Results = new ArrayList<Phyre2SummaryPojo>();
306     try (BufferedReader br = new BufferedReader(new FileReader(crudeList)))
307     {
308       String line;
309       while ((line = br.readLine()) != null)
310       {
311         String[] lineData = line.split(" ");
312         Phyre2SummaryPojo psp = new Phyre2SummaryPojo();
313         psp.setSerialNo(Integer.valueOf(lineData[0]));
314         psp.setTemplateId(lineData[1]);
315         psp.setConfidence(100 * Double.valueOf(lineData[2]));
316         psp.setPid(Integer.valueOf(lineData[3]));
317         psp.setAlignedRange(lineData[4] + " - " + lineData[5]);
318         // psp.setCoverage(coverage);
319         // psp.setTemplateSummary(templateSummary);
320         phyre2Results.add(psp);
321       }
322     } catch (Exception e)
323     {
324       e.printStackTrace();
325     }
326     return phyre2Results;
327   }
328
329   public static DefaultTableModel getTableModel(
330           List<Phyre2SummaryPojo> phyreResults)
331   {
332     if (phyreResults == null)
333     {
334       return null;
335     }
336     DefaultTableModel tableModel = new DefaultTableModel()
337     {
338       @Override
339       public boolean isCellEditable(int row, int column)
340       {
341         return false;
342       }
343
344       @Override
345       public Class<?> getColumnClass(int columnIndex)
346       {
347         switch (columnIndex)
348         {
349         case 0:
350           return Integer.class;
351         case 1:
352           return String.class;
353         case 2:
354           return String.class;
355         case 3:
356           return String.class;
357         case 4:
358           return Double.class;
359         case 5:
360           return Integer.class;
361         case 6:
362           return String.class;
363         default:
364           return String.class;
365         }
366       }
367
368     };
369
370     tableModel.addColumn("#");
371     tableModel.addColumn("Template");
372     tableModel.addColumn("Aligned Range");
373     tableModel.addColumn("Coverage");
374     tableModel.addColumn("Confidence");
375     tableModel.addColumn("%.i.d");
376     tableModel.addColumn("Template Information");
377
378     for (Phyre2SummaryPojo res : phyreResults)
379     {
380       tableModel.addRow(new Object[] { res.getSerialNo(),
381           res.getTemplateId(), res.getAlignedRange(), res.getCoverage(),
382           res.getConfidence(), res.getPid(), res.getTemplateSummary() }); 
383     }
384     return tableModel;
385   }
386
387   public static void configurePhyreResultTable(JTable phyreResultTable)
388   {
389
390     DecimalFormatTableCellRenderer idCellRender = new DecimalFormatTableCellRenderer(
391             true, 0);
392     DecimalFormatTableCellRenderer pidCellRender = new DecimalFormatTableCellRenderer(
393             true, 1);
394     DecimalFormatTableCellRenderer confidenceCellRender = new DecimalFormatTableCellRenderer(
395             true, 1);
396
397     phyreResultTable.getColumn("#").setMinWidth(20);
398     phyreResultTable.getColumn("#").setPreferredWidth(30);
399     phyreResultTable.getColumn("#").setMaxWidth(40);
400     phyreResultTable.getColumn("#").setCellRenderer(idCellRender);
401
402     phyreResultTable.getColumn("Template").setMinWidth(60);
403     phyreResultTable.getColumn("Template").setPreferredWidth(90);
404     phyreResultTable.getColumn("Template").setMaxWidth(150);
405
406     phyreResultTable.getColumn("Aligned Range").setMinWidth(80);
407     phyreResultTable.getColumn("Aligned Range").setPreferredWidth(80);
408     phyreResultTable.getColumn("Aligned Range").setMaxWidth(120);
409
410     phyreResultTable.getColumn("Coverage").setMinWidth(60);
411     phyreResultTable.getColumn("Coverage").setPreferredWidth(60);
412     phyreResultTable.getColumn("Coverage").setMaxWidth(90);
413
414     phyreResultTable.getColumn("Confidence").setMinWidth(60);
415     phyreResultTable.getColumn("Confidence").setPreferredWidth(60);
416     phyreResultTable.getColumn("Confidence").setMaxWidth(90);
417     phyreResultTable.getColumn("Confidence").setCellRenderer(
418             confidenceCellRender);
419
420     phyreResultTable.getColumn("%.i.d").setMinWidth(45);
421     phyreResultTable.getColumn("%.i.d").setPreferredWidth(450);
422     phyreResultTable.getColumn("%.i.d").setMaxWidth(65);
423     phyreResultTable.getColumn("%.i.d").setCellRenderer(pidCellRender);
424
425     phyreResultTable.getColumn("Template Information").setMinWidth(400);
426     phyreResultTable.getColumn("Template Information").setPreferredWidth(
427             600);
428     phyreResultTable.getColumn("Template Information").setMaxWidth(1500);
429   }
430 }