From 08cc3b53619f49a365d7346c3cc8d7a5ddd1b455 Mon Sep 17 00:00:00 2001 From: tcofoegbu Date: Thu, 22 Oct 2015 18:08:14 +0100 Subject: [PATCH] JAL-1479 added basic support for SIFTs mapping - more work to follow --- src/jalview/analysis/AlignSeq.java | 15 +- src/jalview/api/SiftsClientI.java | 153 +++++ src/jalview/io/SiftsClient.java | 624 ++++++++++++++++++++ .../structure/StructureSelectionManager.java | 135 ++--- src/jalview/ws/DBRefFetcher.java | 21 +- test/jalview/io/1a70.xml.gz | Bin 0 -> 6434 bytes test/jalview/io/SiftsClientTest.java | 180 ++++++ 7 files changed, 1022 insertions(+), 106 deletions(-) create mode 100644 src/jalview/api/SiftsClientI.java create mode 100644 src/jalview/io/SiftsClient.java create mode 100644 test/jalview/io/1a70.xml.gz create mode 100644 test/jalview/io/SiftsClientTest.java diff --git a/src/jalview/analysis/AlignSeq.java b/src/jalview/analysis/AlignSeq.java index 527b1ff..3e4a82b 100755 --- a/src/jalview/analysis/AlignSeq.java +++ b/src/jalview/analysis/AlignSeq.java @@ -580,17 +580,15 @@ public class AlignSeq int nochunks = ((aseq1.length - count) / len) + 1; pid = 0; - output.append("Score = ").append(score[maxi][maxj]).append(NEWLINE); - output.append("Length of alignment = ") - .append(String.valueOf(aseq1.length - count)).append(NEWLINE); - output.append("Sequence "); + output.append("Sequence \u27f7 Structure mapping details: ") + .append(NEWLINE); output.append(new Format("%" + maxid + "s").form(s1.getName())); output.append(" : ").append(String.valueOf(s1.getStart())) .append(" - ").append(String.valueOf(s1.getEnd())); output.append(" (Sequence length = ") .append(String.valueOf(s1str.length())).append(")") .append(NEWLINE); - output.append("Sequence "); + // output.append("Sequence "); output.append(new Format("%" + maxid + "s").form(s2.getName())); output.append(" : ").append(String.valueOf(s2.getStart())) .append(" - ").append(String.valueOf(s2.getEnd())); @@ -598,6 +596,7 @@ public class AlignSeq .append(String.valueOf(s2str.length())).append(")") .append(NEWLINE).append(NEWLINE); + // output mappings for (int j = 0; j < nochunks; j++) { // Print the first aligned sequence @@ -661,10 +660,16 @@ public class AlignSeq output.append(NEWLINE).append(NEWLINE); } + output.append("Length of alignment = ") + .append(String.valueOf(aseq1.length - count)).append(NEWLINE); + output.append("Score = ").append(score[maxi][maxj]).append(NEWLINE); + pid = pid / (aseq1.length - count) * 100; output = output.append(new Format("Percentage ID = %2.2f\n\n") .form(pid)); + output.append(NEWLINE).append( + "Mapping method: Needleman & Wunsch Alignment"); try { os.print(output.toString()); diff --git a/src/jalview/api/SiftsClientI.java b/src/jalview/api/SiftsClientI.java new file mode 100644 index 0000000..13223af --- /dev/null +++ b/src/jalview/api/SiftsClientI.java @@ -0,0 +1,153 @@ +/* + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. + */ +package jalview.api; + +import jalview.datamodel.SequenceI; +import jalview.structure.StructureMapping; +import jalview.xml.binding.sifts.Entry.Entity; + +import java.util.HashSet; + +public interface SiftsClientI +{ + /** + * Get the DB Accession Id for the SIFTs Entry + * + * @return + */ + public String getDbAccessionId(); + + /** + * Get DB Coordinate system for the SIFTs Entry + * + * @return + */ + public String getDbCoordSys(); + + /** + * Get DB Evidence for the SIFTs Entry + * + * @return + */ + public String getDbEvidence(); + + /** + * Get DB Source for the SIFTs Entry + * + * @return + */ + public String getDbSource(); + + /** + * Get DB version for the SIFTs Entry + * + * @return + */ + public String getDbVersion(); + + /** + * Get Number of Entities available in the SIFTs Entry + * + * @return + */ + public int getEntityCount(); + + /** + * Get a unique Entity by its Id + * + * @param id + * ID of the entity to fetch + * @return Entity + * @throws Exception + */ + public Entity getEntityById(String id) throws Exception; + + /** + * Get all accession Ids available in the current SIFTs entry + * + * @return a unique set of discovered accession strings + */ + public HashSet getAllMappingAccession(); + + /** + * Check if the accessionId is available in current SIFTs Entry + * + * @param accessionId + * @return + */ + public boolean isFoundInSiftsEntry(String accessionId); + + /** + * Get the standard DB referenced by the SIFTs Entry + * + * @return + */ + public String[] getEntryDBs(); + + /** + * Get the SIFTs Entry details + */ + public void getEntryDetails(); + + /** + * + * @param seq1 + * Sequence to map + * @param seq2 + * Structure Sequence + * @param seqID1 + * sequence id + * @param seqID2 + * structure sequence id + * @param seqType + * type of sequence for the mapping (pep or protein) + * @param nochunks + * @return sequence->structure mapping as int [][] + */ + public StringBuffer getMappingOutput(String seq1, String seq2, + String seqID1, String seqID2, String seqType, int nochunks); + + /** + * + * @param seq + * sequence to generate mapping against the structure + * @param pdbFile + * PDB file for the mapping + * @param chain + * the chain of the entry to use for mapping + * @return StructureMapping + */ + public StructureMapping getSiftsStructureMapping(SequenceI seq, String pdbFile, + String chain); + + /** + * Get residue by residue mapping for a given Sequence and SIFTs entity + * + * @param entityId + * Id of the target entity in the SIFTs entry + * @param seq + * SequenceI + * @return generated mapping + * @throws Exception + */ + public int[][] getGreedyMapping(String entityId, SequenceI seq, + java.io.PrintStream os) throws Exception; +} \ No newline at end of file diff --git a/src/jalview/io/SiftsClient.java b/src/jalview/io/SiftsClient.java new file mode 100644 index 0000000..bde215d --- /dev/null +++ b/src/jalview/io/SiftsClient.java @@ -0,0 +1,624 @@ +/* + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. + */ +package jalview.io; + +import jalview.analysis.AlignSeq; +import jalview.api.DBRefEntryI; +import jalview.api.SiftsClientI; +import jalview.datamodel.DBRefEntry; +import jalview.datamodel.SequenceI; +import jalview.schemes.ResidueProperties; +import jalview.structure.StructureMapping; +import jalview.util.Format; +import jalview.xml.binding.sifts.Entry; +import jalview.xml.binding.sifts.Entry.Entity; +import jalview.xml.binding.sifts.Entry.Entity.Segment; +import jalview.xml.binding.sifts.Entry.Entity.Segment.ListMapRegion.MapRegion; +import jalview.xml.binding.sifts.Entry.Entity.Segment.ListResidue.Residue; +import jalview.xml.binding.sifts.Entry.Entity.Segment.ListResidue.Residue.CrossRefDb; +import jalview.xml.binding.sifts.Entry.EntryDetail; +import jalview.xml.binding.sifts.Entry.ListDB.Db; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintStream; +import java.net.URL; +import java.net.URLConnection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.zip.GZIPInputStream; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.stream.FactoryConfigurationError; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +public class SiftsClient implements SiftsClientI +{ + private Entry siftsEntry; + + private String pdbId; + + private static final int BUFFER_SIZE = 4096; + + private static final String SIFTS_FTP_BASE_URL = "ftp://ftp.ebi.ac.uk/pub/databases/msd/sifts/xml/"; + + public static final String DEFAULT_SIFTS_DOWNLOAD_DIR = System + .getProperty("user.home") + + File.separatorChar + + ".sifts_downloads" + File.separatorChar; + + public static final String SIFTS_DOWNLOAD_DIR = jalview.bin.Cache + .getDefault("sifts_download_dir", DEFAULT_SIFTS_DOWNLOAD_DIR); + + private final static String NEWLINE = System.lineSeparator(); + + /** + * Fetch SIFTs file for the given PDB Id and construct an instance of + * SiftsClient + * + * @param pdbId + */ + public SiftsClient(String pdbId) + { + this.pdbId = pdbId; + try + { + File siftsFile = getSiftsFile(pdbId); + siftsEntry = parseSIFTs(siftsFile); + } catch (Exception e) + { + e.printStackTrace(); + } + } + + /** + * Construct an instance of SiftsClient using the supplied SIFTs file - + * the SIFTs file should correspond to the given PDB Id + * + * @param pdbId + * @param siftsFile + */ + public SiftsClient(String pdbId, File siftsFile) + { + this.pdbId = pdbId; + try + { + siftsEntry = parseSIFTs(siftsFile); + } catch (Exception e) + { + e.printStackTrace(); + } + + } + + /** + * Parse the given SIFTs File and return a JAXB POJO of parsed data + * + * @param siftFile + * - the GZipped SIFTs XML file to parse + * @return + * @throws Exception + * if a problem occurs while parsing the SIFTs XML + */ + private Entry parseSIFTs(File siftFile) throws Exception + { + try + { + System.out.println("File : " + siftFile.getAbsolutePath()); + JAXBContext jc = JAXBContext.newInstance("jalview.xml.binding.sifts"); + InputStream in = new FileInputStream(siftFile); + GZIPInputStream gzis = new GZIPInputStream(in); + XMLStreamReader streamReader = XMLInputFactory.newInstance() + .createXMLStreamReader(gzis); + Unmarshaller um = jc.createUnmarshaller(); + return (Entry) um.unmarshal(streamReader); + } catch (JAXBException e) + { + e.printStackTrace(); + } catch (FileNotFoundException e) + { + e.printStackTrace(); + } catch (XMLStreamException e) + { + e.printStackTrace(); + } catch (FactoryConfigurationError e) + { + e.printStackTrace(); + } catch (IOException e) + { + e.printStackTrace(); + } + throw new Exception("Error parsing siftFile"); + } + + /** + * Get a SIFTs XML file for a given PDB Id + * + * @param pdbId + * @return SIFTs XML file + */ + public static File getSiftsFile(String pdbId) + { + File siftsFile = new File(SIFTS_DOWNLOAD_DIR + pdbId.toLowerCase() + + ".xml.gz"); + if (siftsFile.exists()) + { + // TODO it may be worth performing a timestamp age check to determine if a + // new SIFTs file should be re-downloaded as SIFTs entries are usually + // updated weekly + System.out.println(">>> SIFTS File already downloaded for " + pdbId); + return siftsFile; + } + siftsFile = downloadSiftsFile(pdbId.toLowerCase()); + return siftsFile; + } + + /** + * Download a SIFTs XML file for a given PDB Id + * + * @param pdbId + * @return downloaded SIFTs XML file + */ + public static File downloadSiftsFile(String pdbId) + { + String siftFile = pdbId + ".xml.gz"; + String siftsFileFTPURL = SIFTS_FTP_BASE_URL + siftFile; + String downloadedSiftsFile = SIFTS_DOWNLOAD_DIR + siftFile; + File siftsDownloadDir = new File(SIFTS_DOWNLOAD_DIR); + if (!siftsDownloadDir.exists()) + { + siftsDownloadDir.mkdirs(); + } + try + { + System.out.println(">> Download ftp url : " + siftsFileFTPURL); + URL url = new URL(siftsFileFTPURL); + URLConnection conn = url.openConnection(); + InputStream inputStream = conn.getInputStream(); + FileOutputStream outputStream = new FileOutputStream( + downloadedSiftsFile); + byte[] buffer = new byte[BUFFER_SIZE]; + int bytesRead = -1; + while ((bytesRead = inputStream.read(buffer)) != -1) + { + outputStream.write(buffer, 0, bytesRead); + } + outputStream.close(); + inputStream.close(); + System.out.println(">>> File downloaded : " + downloadedSiftsFile); + } catch (IOException ex) + { + ex.printStackTrace(); + } + return new File(downloadedSiftsFile); + } + + /** + * Delete the SIFTs file for the given PDB Id in the local SIFTs download + * directory + * + * @param pdbId + * @return true if the file was deleted or doesn't exist + */ + public static boolean deleteSiftsFileByPDBId(String pdbId) + { + File siftsFile = new File(SIFTS_DOWNLOAD_DIR + pdbId.toLowerCase() + + ".xml.gz"); + if (siftsFile.exists()) + { + return siftsFile.delete(); + } + return true; + } + + + /** + * Get a valid SIFTs DBRef for the given sequence current SIFTs entry + * + * @param seq + * - the target sequence for the operation + * @return a valid DBRefEntry that is SIFTs compatible + * @throws Exception + * if no valid source DBRefEntry was found for the given sequences + */ + public DBRefEntryI getValidSourceDBRef(SequenceI seq) throws Exception + { + DBRefEntryI sourceDBRef = null; + sourceDBRef = seq.getSourceDBRef(); + if (sourceDBRef != null && isValidDBRefEntry(sourceDBRef)) + { + return sourceDBRef; + } + else + { + DBRefEntry[] dbRefs = seq.getDBRefs(); + if (dbRefs == null || dbRefs.length < 1) + { + final SequenceI[] seqs = new SequenceI[] { seq }; + new jalview.ws.DBRefFetcher(seqs, null, null, null, false) + .fetchDBRefs(true); + dbRefs = seq.getDBRefs(); + } + + if (dbRefs == null || dbRefs.length < 1) + { + throw new Exception("Could not get source DB Ref"); + } + + for (DBRefEntryI dbRef : dbRefs) + { + if (dbRef == null || dbRef.getAccessionId() == null + || dbRef.getSource() == null) + { + continue; + } + if (isFoundInSiftsEntry(dbRef.getAccessionId()) + && (dbRef.getSource().equalsIgnoreCase("uniprot") || dbRef + .getSource().equalsIgnoreCase("pdb"))) + { + return dbRef; + } + } + } + if (sourceDBRef != null && isValidDBRefEntry(sourceDBRef)) + { + return sourceDBRef; + } + throw new Exception("Could not get source DB Ref"); + } + + + /** + * Check that the DBRef Entry is properly populated and is available in the + * instantiated SIFTs Entry + * + * @param entry + * - DBRefEntry to validate + * @return true validation is successful otherwise false is returned. + */ + private boolean isValidDBRefEntry(DBRefEntryI entry) + { + return entry != null && entry.getAccessionId() != null + && isFoundInSiftsEntry(entry.getAccessionId()); + // & entry.getStartRes() > 0; + } + + @Override + public HashSet getAllMappingAccession() + { + HashSet accessions = new HashSet(); + List entities = siftsEntry.getEntity(); + for (Entity entity : entities) + { + List segments = entity.getSegment(); + for (Segment segment : segments) + { + List mapRegions = segment.getListMapRegion() + .getMapRegion(); + for (MapRegion mapRegion : mapRegions) + { + accessions.add(mapRegion.getDb().getDbAccessionId()); + } + } + } + return accessions; + } + + + @Override + public int[][] getGreedyMapping(String entityId, SequenceI seq, + java.io.PrintStream os) + throws Exception + { + System.out.println("Generating mappings for : " + entityId); + Entity entity = null; + entity = getEntityById(entityId); + String seqStr = AlignSeq.extractGaps(jalview.util.Comparison.GapChars, + seq.getSequenceAsString()); + // StringBuilder mappedStrucSeq = new StringBuilder(seqStr.length()); + String[] mappedStrucSeq = new String[seqStr.length()]; + int mapping[][] = new int[seqStr.length()][2]; + DBRefEntryI sourceDBRef = seq.getSourceDBRef(); + if (sourceDBRef == null) + { + sourceDBRef = getValidSourceDBRef(seq); + // TODO if sourceDBRef is null at this point then throw an Exception + + // TODO update sequence start/end with sourceDBRef start/end + // seq.setStart(sourceDBRef.getStartRes()); + // seq.setEnd(sourceDBRef.getEndRes()); + } + + String crossRefAccessionId = sourceDBRef.getAccessionId(); + int start = seq.getStart() - 1; + for (int residue[] : mapping) + { + residue[1] = start++; + } + + HashMap resNumMap = new HashMap(); + List segments = entity.getSegment(); + for (Segment segment : segments) + { + System.out.println("Mappging segments : " + segment.getSegId() + "\\" + + segment.getStart() + "-" + segment.getEnd()); + List residues = segment.getListResidue().getResidue(); + for (Residue residue : residues) + { + int refDbResNum = -1; + List cRefDbs = residue.getCrossRefDb(); + for (CrossRefDb cRefDb : cRefDbs) + { + if (cRefDb.getDbAccessionId().equalsIgnoreCase( + crossRefAccessionId)) + { + refDbResNum = Integer.valueOf(cRefDb.getDbResNum()); + } + } + if (refDbResNum == -1) + { + continue; + } + for (int[] x : mapping) + { + if (x[1] == refDbResNum) + { + int resNum = Integer.valueOf(residue.getDbResNum()); + x[0] = resNum; + String value = "x"; + resNumMap.put(resNum, value); + } + } + } + } + + //Generate visual mapping output + // StringBuilder strucSeq = new StringBuilder(); + // for(int[] x : mapping){ + // if(mapping[0] == 0){ + // strucSeq.append(b) + // } + // } + mappedStrucSeq[1] = "x"; + try + { + System.out.println(">>>> seq: " + seqStr + "\nlength " + + seqStr.length()); + System.out.println(">>>> pdb: " + mappedStrucSeq.toString() + + "\nlength " + mappedStrucSeq.toString().length()); + + String printedMapping = getMappingOutput(mappedStrucSeq.toString(), + seqStr, "seqAccession", "strucAccession", "pep", 3) + .toString(); + if (os != null) + { + os.print(printedMapping); + } + System.out.println(); + } catch (Exception ex) + { + ex.printStackTrace(); + } + return mapping; + } + + @Override + public boolean isFoundInSiftsEntry(String accessionId) + { + return accessionId != null + && getAllMappingAccession().contains(accessionId); + } + + @Override + public StructureMapping getSiftsStructureMapping(SequenceI seq, + String pdbFile, String chain) + { + System.out.println("Getting mapping for: " + pdbId + "|" + chain + + " : seq- " + seq.getName()); + + final StringBuilder mappingDetails = new StringBuilder(128); + PrintStream ps = new PrintStream(System.out) + { + @Override + public void print(String x) + { + mappingDetails.append(x); + } + + @Override + public void println() + { + mappingDetails.append(NEWLINE); + } + }; + int[][] mapping = null; + try + { + mapping = getGreedyMapping(chain, seq, ps); + } catch (Exception e) + { + e.printStackTrace(); + } + // String mappingOutput = mappingDetails.toString(); + String mappingOutput = null; + return new StructureMapping(seq, pdbFile, pdbId, chain, mapping, + mappingOutput); + } + + @Override + public Entity getEntityById(String id) throws Exception + { + List entities = siftsEntry.getEntity(); + for (Entity entity : entities) + { + if (!entity.getEntityId().equalsIgnoreCase(id)) + { + continue; + } + return entity; + } + throw new Exception("Entity " + id + " not found"); + } + + @Override + public String[] getEntryDBs() + { + System.out.println("\nListing DB entries..."); + List dbs = siftsEntry.getListDB().getDb(); + for (Db db : dbs) + { + System.out.println(db.getDbSource() + " | " + db.getDbCoordSys()); + } + return null; + } + + @Override + public void getEntryDetails() + { + List eds = siftsEntry.getEntryDetail(); + for (EntryDetail ed : eds) + { + System.out.println("Entry Details: " + ed.getContent() + " " + + ed.getDbSource() + " " + ed.getProperty() + " " + + ed.toString()); + } + } + + @Override + public StringBuffer getMappingOutput(String astr1, String astr2, String s1id, + String s2id, String type, int nochunks) + { + int maxid = s1id.length(); + int len = 72 - maxid - 1; + StringBuffer output = new StringBuffer(); + // output mappings + float pid = 0; + for (int j = 0; j < nochunks; j++) + { + // Print the first aligned sequence + output.append(new Format("%" + (maxid) + "s").form(s1id)).append(" "); + + for (int i = 0; i < len; i++) + { + if ((i + (j * len)) < astr1.length()) + { + output.append(astr1.charAt(i + (j * len))); + } + } + + output.append(NEWLINE); + output.append(new Format("%" + (maxid) + "s").form(" ")).append(" "); + + // Print out the matching chars + for (int i = 0; i < len; i++) + { + if ((i + (j * len)) < astr1.length()) + { + if (astr1.charAt(i + (j * len)) == astr2.charAt(i + (j * len)) + && !jalview.util.Comparison.isGap(astr1.charAt(i + + (j * len)))) + { + pid++; + output.append("|"); + } + else if (type.equals("pep")) + { + if (ResidueProperties.getPAM250(astr1.charAt(i + (j * len)), + astr2.charAt(i + (j * len))) > 0) + { + output.append("."); + } + else + { + output.append(" "); + } + } + else + { + output.append(" "); + } + } + } + // Now print the second aligned sequence + output = output.append(NEWLINE); + output = output.append(new Format("%" + (maxid) + "s").form(s2id)) + .append(" "); + for (int i = 0; i < len; i++) + { + if ((i + (j * len)) < astr2.length()) + { + output.append(astr2.charAt(i + (j * len))); + } + } + output.append(NEWLINE).append(NEWLINE); + } + pid = pid / (astr1.length()) * 100; + System.out.println(output); + System.out.println(pid); + // TODO return output & pid + return output; + } + + @Override + public int getEntityCount() + { + return siftsEntry.getEntity().size(); + } + + @Override + public String getDbAccessionId() + { + return siftsEntry.getDbAccessionId(); + } + + @Override + public String getDbCoordSys() + { + return siftsEntry.getDbCoordSys(); + } + + @Override + public String getDbEvidence() + { + return siftsEntry.getDbEvidence(); + } + + @Override + public String getDbSource() + { + return siftsEntry.getDbSource(); + } + + @Override + public String getDbVersion() + { + return siftsEntry.getDbVersion(); + } +} diff --git a/src/jalview/structure/StructureSelectionManager.java b/src/jalview/structure/StructureSelectionManager.java index e9d736f..0b3696c 100644 --- a/src/jalview/structure/StructureSelectionManager.java +++ b/src/jalview/structure/StructureSelectionManager.java @@ -458,117 +458,61 @@ public class StructureSelectionManager { continue; } - final StringBuilder mappingDetails = new StringBuilder(128); - mappingDetails.append(NEWLINE).append("PDB Sequence is :") - .append(NEWLINE).append("Sequence = ") - .append(maxChain.sequence.getSequenceAsString()); - mappingDetails.append(NEWLINE).append("No of residues = ") - .append(maxChain.residues.size()).append(NEWLINE) - .append(NEWLINE); - PrintStream ps = new PrintStream(System.out) - { - @Override - public void print(String x) - { - mappingDetails.append(x); - } - - @Override - public void println() - { - mappingDetails.append(NEWLINE); - } - }; - - // mapWithNWAlignment(); - // mapWithSIFTS(); - maxAlignseq.printAlignment(ps); - - mappingDetails.append(NEWLINE).append("PDB start/end "); - mappingDetails.append(String.valueOf(maxAlignseq.seq2start)).append( - " "); - mappingDetails.append(String.valueOf(maxAlignseq.seq2end)); - mappingDetails.append(NEWLINE).append("SEQ start/end "); - // TODO JAL-1887 should be fixed from here - mappingDetails.append( - String.valueOf(maxAlignseq.seq1start + seq.getStart() - 1)) - .append(" "); - mappingDetails.append(String.valueOf(maxAlignseq.seq1end - + seq.getEnd() - 1)); - - maxChain.makeExactMapping(maxAlignseq, seq); - jalview.datamodel.Mapping sqmpping = maxAlignseq - .getMappingFromS1(false); - jalview.datamodel.Mapping omap = new jalview.datamodel.Mapping( - sqmpping.getMap().getInverse()); - maxChain.transferRESNUMFeatures(seq, null); - - // allocate enough slots to store the mapping from positions in - // sequence[s] to the associated chain - int[][] mapping = new int[seq.findPosition(seq.getLength()) + 2][2]; - int resNum = -10000; - int index = 0; - - do - { - Atom tmp = maxChain.atoms.elementAt(index); - if (resNum != tmp.resNumber && tmp.alignmentMapping != -1) - { - resNum = tmp.resNumber; - if (tmp.alignmentMapping >= -1) - { - // TODO (JAL-1836) address root cause: negative residue no in PDB - // file - mapping[tmp.alignmentMapping + 1][0] = tmp.resNumber; - mapping[tmp.alignmentMapping + 1][1] = tmp.atomIndex; - } - } - - index++; - } while (index < maxChain.atoms.size()); if (protocol.equals(jalview.io.AppletFormatAdapter.PASTE)) { pdbFile = "INLINE" + pdb.id; } - // StructureMapping newMapping = new StructureMapping(seq, pdbFile, - // pdb.id, maxChainId, mapping, mappingDetails.toString()); - StructureMapping newMapping = new SiftsClient(pdb.id) - .getSiftsMappingsFor(seq, pdbFile, maxChainId); + + StructureMapping seqToStrucMapping = null; + boolean isMapViaSIFTs = Boolean.valueOf(jalview.bin.Cache.getDefault( + "MAP_WITH_SIFTS", "false")); + if (isMapViaSIFTs) + { + SiftsClient siftsClient = new SiftsClient(pdb.id); + seqToStrucMapping = siftsClient.getSiftsStructureMapping(seq, + pdbFile, maxChainId); + // TODO if SIFTs mapping fails.. then fallback to NW alignment + } + else + { + seqToStrucMapping = getNWMappings(seq, pdbFile, + maxChainId, maxChain, pdb, + maxAlignseq); + } + if (forStructureView) { - mappings.add(newMapping); + mappings.add(seqToStrucMapping); } - maxChain.transferResidueAnnotation(newMapping, sqmpping); } - // /////// - return pdb; } - private StructureMapping mapWithNWAlignment(StringBuilder mappingDetails, - PDBChain maxChain, AlignSeq maxAlignseq, SequenceI seq, - PrintStream ps) + private StructureMapping getNWMappings(SequenceI seq, String pdbFile, + String maxChainId, PDBChain maxChain, PDBfile pdb, + AlignSeq maxAlignseq) { - maxAlignseq.printAlignment(ps); + final StringBuilder mappingDetails = new StringBuilder(128); + PrintStream ps = new PrintStream(System.out) + { + @Override + public void print(String x) + { + mappingDetails.append(x); + } - mappingDetails.append(NEWLINE).append("PDB start/end "); - mappingDetails.append(String.valueOf(maxAlignseq.seq2start)) - .append(" "); - mappingDetails.append(String.valueOf(maxAlignseq.seq2end)); - mappingDetails.append(NEWLINE).append("SEQ start/end "); - // TODO JAL-1887 should be fixed from here - mappingDetails.append( - String.valueOf(maxAlignseq.seq1start + seq.getStart() - 1)) - .append(" "); - mappingDetails.append(String.valueOf(maxAlignseq.seq1end + seq.getEnd() - - 1)); + @Override + public void println() + { + mappingDetails.append(NEWLINE); + } + }; + maxAlignseq.printAlignment(ps); maxChain.makeExactMapping(maxAlignseq, seq); jalview.datamodel.Mapping sqmpping = maxAlignseq .getMappingFromS1(false); - jalview.datamodel.Mapping omap = new jalview.datamodel.Mapping(sqmpping - .getMap().getInverse()); maxChain.transferRESNUMFeatures(seq, null); // allocate enough slots to store the mapping from positions in @@ -595,7 +539,10 @@ public class StructureSelectionManager index++; } while (index < maxChain.atoms.size()); - return null; + StructureMapping nwMapping = new StructureMapping(seq, pdbFile, + pdb.id, maxChainId, mapping, mappingDetails.toString()); + maxChain.transferResidueAnnotation(nwMapping, sqmpping); + return nwMapping; } public void removeStructureViewerListener(Object svl, String[] pdbfiles) diff --git a/src/jalview/ws/DBRefFetcher.java b/src/jalview/ws/DBRefFetcher.java index 2e0197c..473d54f 100644 --- a/src/jalview/ws/DBRefFetcher.java +++ b/src/jalview/ws/DBRefFetcher.java @@ -57,7 +57,7 @@ public class DBRefFetcher implements Runnable { SequenceI[] dataset; - IProgressIndicator af; + IProgressIndicator progressWindow; CutAndPasteTransfer output = new CutAndPasteTransfer(); @@ -109,7 +109,7 @@ public class DBRefFetcher implements Runnable IProgressIndicator progressIndicatorFrame, DbSourceProxy[] sources, FeatureSettings featureSettings, boolean isNucleotide) { - this.af = progressIndicatorFrame; + this.progressWindow = progressIndicatorFrame; alseqs = new SequenceI[seqs.length]; SequenceI[] ds = new SequenceI[seqs.length]; for (int i = 0; i < seqs.length; i++) @@ -286,8 +286,12 @@ public class DBRefFetcher implements Runnable } running = true; long startTime = System.currentTimeMillis(); - af.setProgressBar(MessageManager.getString("status.fetching_db_refs"), + if (progressWindow != null) + { + progressWindow.setProgressBar( + MessageManager.getString("status.fetching_db_refs"), startTime); + } try { if (Cache.getDefault("DBREFFETCH_USEPICR", false)) @@ -472,11 +476,14 @@ public class DBRefFetcher implements Runnable // of the viewed sequence } + if (progressWindow != null) + { + progressWindow.setProgressBar( + MessageManager.getString("label.dbref_search_completed"), + startTime); + // promptBeforeBlast(); - af.setProgressBar( - MessageManager.getString("label.dbref_search_completed"), - startTime); - // promptBeforeBlast(); + } running = false; diff --git a/test/jalview/io/1a70.xml.gz b/test/jalview/io/1a70.xml.gz new file mode 100644 index 0000000000000000000000000000000000000000..3f0b68a10c8fe9c36a0c6a1c98dfe460e9b3c74c GIT binary patch literal 6434 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 RRoW95K5Cd87IW~x{{Y9jIG+Fj literal 0 HcmV?d00001 diff --git a/test/jalview/io/SiftsClientTest.java b/test/jalview/io/SiftsClientTest.java new file mode 100644 index 0000000..6ff3705 --- /dev/null +++ b/test/jalview/io/SiftsClientTest.java @@ -0,0 +1,180 @@ +/* + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors + * + * This file is part of Jalview. + * + * Jalview is free software: you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. + * + * Jalview is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . + * The Jalview Authors are detailed in the 'AUTHORS' file. + */ +package jalview.io; + +import jalview.datamodel.DBRefEntry; +import jalview.datamodel.Sequence; +import jalview.datamodel.SequenceI; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.PrintStream; + +import org.testng.Assert; +import org.testng.FileAssert; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +public class SiftsClientTest +{ + private final ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + + private String testPDBId = "1a70"; + + private SiftsClient siftsClient = null; + + SequenceI testSeq = new Sequence( + "P00221", + "MAAT..TTTMMG..MATTFVPKPQAPPMMAALPSNTGR..SLFGLKT.GSR..GGRMTMA" + + "AYKVTLVTPTGNVEFQCPDDVYILDAAEEEGIDLPYSCRAGSCSSCAGKLKTGSLNQDD" + + "QSFLDDDQIDEGWVLTCAAYPVSDVTIETHKEEELTA.", 1, 147); + + int[][] expectedMapping = { { 0, 0 }, { 0, 1 }, { 0, 2 }, { 0, 3 }, + { 0, 4 }, { 0, 5 }, { 0, 6 }, { 0, 7 }, { 0, 8 }, { 0, 9 }, + { 0, 10 }, { 0, 11 }, { 0, 12 }, { 0, 13 }, { 0, 14 }, { 0, 15 }, + { 0, 16 }, { 0, 17 }, { 0, 18 }, { 0, 19 }, { 0, 20 }, { 0, 21 }, + { 0, 22 }, { 0, 23 }, { 0, 24 }, { 0, 25 }, { 0, 26 }, { 0, 27 }, + { 0, 28 }, { 0, 29 }, { 0, 30 }, { 0, 31 }, { 0, 32 }, { 0, 33 }, + { 0, 34 }, { 0, 35 }, { 0, 36 }, { 0, 37 }, { 0, 38 }, { 0, 39 }, + { 0, 40 }, { 0, 41 }, { 0, 42 }, { 0, 43 }, { 0, 44 }, { 0, 45 }, + { 0, 46 }, { 0, 47 }, { 0, 48 }, { 0, 49 }, { 0, 50 }, { 1, 51 }, + { 2, 52 }, { 3, 53 }, { 4, 54 }, { 5, 55 }, { 6, 56 }, { 7, 57 }, + { 8, 58 }, { 9, 59 }, { 10, 60 }, { 11, 61 }, { 12, 62 }, { 13, 63 }, + { 14, 64 }, { 15, 65 }, { 16, 66 }, { 17, 67 }, { 18, 68 }, + { 19, 69 }, { 20, 70 }, { 21, 71 }, { 22, 72 }, { 23, 73 }, + { 24, 74 }, { 25, 75 }, { 26, 76 }, { 27, 77 }, { 28, 78 }, + { 29, 79 }, { 30, 80 }, { 31, 81 }, { 32, 82 }, { 33, 83 }, + { 34, 84 }, { 35, 85 }, { 36, 86 }, { 37, 87 }, { 38, 88 }, + { 39, 89 }, { 40, 90 }, { 41, 91 }, { 42, 92 }, { 43, 93 }, + { 44, 94 }, { 45, 95 }, { 46, 96 }, { 47, 97 }, { 48, 98 }, + { 49, 99 }, { 50, 100 }, { 51, 101 }, { 52, 102 }, { 53, 103 }, + { 54, 104 }, { 55, 105 }, { 56, 106 }, { 57, 107 }, { 58, 108 }, + { 59, 109 }, { 60, 110 }, { 61, 111 }, { 62, 112 }, { 63, 113 }, + { 64, 114 }, { 65, 115 }, { 66, 116 }, { 67, 117 }, { 68, 118 }, + { 69, 119 }, { 70, 120 }, { 71, 121 }, { 72, 122 }, { 73, 123 }, + { 74, 124 }, { 75, 125 }, { 76, 126 }, { 77, 127 }, { 78, 128 }, + { 79, 129 }, { 80, 130 }, { 81, 131 }, { 82, 132 }, { 83, 133 }, + { 84, 134 }, { 85, 135 }, { 86, 136 }, { 87, 137 }, { 88, 138 }, + { 89, 139 }, { 90, 140 }, { 91, 141 }, { 92, 142 }, { 93, 143 }, + { 94, 144 }, { 95, 145 }, { 96, 146 } }; + + @BeforeTest(alwaysRun = true) + public void setUpSiftsClient() + { + // SIFTs entries are updated weekly - so use saved SIFTs file to enforce + // test reproducibility + File testSiftsFile = new File("test/jalview/io/" + testPDBId + + ".xml.gz"); + siftsClient = new SiftsClient(testPDBId, testSiftsFile); + } + + @AfterTest(alwaysRun = true) + public void cleanUpSiftsClient() + { + siftsClient = null; + } + + @BeforeTest(alwaysRun = true) + public void setUpStreams() + { + System.setOut(new PrintStream(outContent)); + } + + @AfterTest(alwaysRun = true) + public void cleanUpStreams() + { + System.setOut(null); + } + + @Test(groups = { "Functional" }) + public void getSIFTsFileTest() + { + Assert.assertTrue(SiftsClient.deleteSiftsFileByPDBId(testPDBId)); + SiftsClient.getSiftsFile(testPDBId); + Assert.assertFalse(outContent.toString().contains( + ">>> SIFTS File already downloaded for " + testPDBId)); + + // test for SIFTs file caching + SiftsClient.getSiftsFile(testPDBId); + Assert.assertTrue(outContent.toString().contains( + ">>> SIFTS File already downloaded for " + testPDBId)); + } + + @Test(groups = { "Functional" }) + public void downloadSiftsFileTest() + { + // Assert that file isn't yet downloaded - if already downloaded, assert it + // is deleted + Assert.assertTrue(SiftsClient.deleteSiftsFileByPDBId(testPDBId)); + File siftsFile = SiftsClient.downloadSiftsFile(testPDBId); + FileAssert.assertFile(siftsFile); + SiftsClient.downloadSiftsFile(testPDBId); + } + + @Test(groups = { "Functional" }) + public void getAllMappingAccessionTest() + { + Assert.assertNotNull(siftsClient); + Assert.assertNotNull(siftsClient.getAllMappingAccession()); + Assert.assertTrue(siftsClient.getAllMappingAccession().size() > 1); + } + + @Test(groups = { "Functional" }) + public void getGreedyMappingTest() + { + Assert.assertNotNull(siftsClient); + Assert.assertNotNull(testSeq); + Assert.assertNotNull(expectedMapping); + + // TODO delete when auto-fetching of DBRefEntry is implemented + DBRefEntry dbRef = new DBRefEntry("uniprot", "", "P00221"); + dbRef.setStartRes(1); + dbRef.setEndRes(147); + testSeq.addDBRef(dbRef); + // testSeq.setSourceDBRef(dbRef); + + try + { + int[][] actualMapping = siftsClient.getGreedyMapping("A", testSeq, + null); + Assert.assertEquals(actualMapping, expectedMapping); + Assert.assertEquals(testSeq.getStart(), 1); + Assert.assertEquals(testSeq.getEnd(), 147); + } catch (Exception e) + { + e.printStackTrace(); + Assert.fail("Exception thrown while generating mapping..."); + } + } + + @Test(groups = { "Functional" }) + public void getValidSourceDBRefTest() + { + + } + + @Test(groups = { "Functional" }) + public void isValidDBRefEntryTest() + { + + } +} -- 1.7.10.2