2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
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.
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.
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.
21 package jalview.ws.sifts;
23 import jalview.analysis.AlignSeq;
24 import jalview.api.DBRefEntryI;
25 import jalview.api.SiftsClientI;
26 import jalview.datamodel.DBRefEntry;
27 import jalview.datamodel.DBRefSource;
28 import jalview.datamodel.SequenceI;
29 import jalview.io.StructureFile;
30 import jalview.schemes.ResidueProperties;
31 import jalview.structure.StructureMapping;
32 import jalview.structure.StructureMappingClient;
33 import jalview.structures.models.MappingOutputModel;
34 import jalview.util.Comparison;
35 import jalview.util.DBRefUtils;
36 import jalview.util.Format;
37 import jalview.xml.binding.sifts.Entry;
38 import jalview.xml.binding.sifts.Entry.Entity;
39 import jalview.xml.binding.sifts.Entry.Entity.Segment;
40 import jalview.xml.binding.sifts.Entry.Entity.Segment.ListMapRegion.MapRegion;
41 import jalview.xml.binding.sifts.Entry.Entity.Segment.ListResidue.Residue;
42 import jalview.xml.binding.sifts.Entry.Entity.Segment.ListResidue.Residue.CrossRefDb;
43 import jalview.xml.binding.sifts.Entry.Entity.Segment.ListResidue.Residue.ResidueDetail;
46 import java.io.FileInputStream;
47 import java.io.FileOutputStream;
48 import java.io.IOException;
49 import java.io.InputStream;
50 import java.io.PrintStream;
52 import java.net.URLConnection;
53 import java.nio.file.Files;
54 import java.nio.file.Path;
55 import java.nio.file.attribute.BasicFileAttributes;
56 import java.util.ArrayList;
57 import java.util.Arrays;
58 import java.util.Collections;
59 import java.util.Date;
60 import java.util.HashMap;
61 import java.util.HashSet;
62 import java.util.List;
65 import java.util.TreeMap;
66 import java.util.zip.GZIPInputStream;
68 import javax.xml.bind.JAXBContext;
69 import javax.xml.bind.Unmarshaller;
70 import javax.xml.stream.XMLInputFactory;
71 import javax.xml.stream.XMLStreamReader;
73 public class SiftsClient extends StructureMappingClient implements
77 * for use in mocking out file fetch for tests only
78 * - reset to null after testing!
80 private static File mockSiftsFile;
82 private Entry siftsEntry;
86 private String structId;
88 private CoordinateSys seqCoordSys = CoordinateSys.UNIPROT;
90 private static final int BUFFER_SIZE = 4096;
92 public static final int UNASSIGNED = -1;
94 private static final int PDB_RES_POS = 0;
96 private static final String NOT_OBSERVED = "Not_Observed";
98 private static final String SIFTS_FTP_BASE_URL = "http://ftp.ebi.ac.uk/pub/databases/msd/sifts/xml/";
100 private final static String NEWLINE = System.lineSeparator();
102 private String curSourceDBRef;
104 private HashSet<String> curDBRefAccessionIdsString;
106 private enum CoordinateSys
108 UNIPROT("UniProt"), PDB("PDBresnum"), PDBe("PDBe");
111 private CoordinateSys(String name)
116 public String getName()
122 private enum ResidueDetailType
124 NAME_SEC_STRUCTURE("nameSecondaryStructure"), CODE_SEC_STRUCTURE(
125 "codeSecondaryStructure"), ANNOTATION("Annotation");
128 private ResidueDetailType(String code)
133 public String getCode()
140 * Fetch SIFTs file for the given PDBfile and construct an instance of
144 * @throws SiftsException
146 public SiftsClient(StructureFile structureFile) throws SiftsException
148 this.structureFile = structureFile;
149 this.pdbId = structureFile.getId();
150 File siftsFile = getSiftsFile(pdbId);
151 siftsEntry = parseSIFTs(siftsFile);
155 * Parse the given SIFTs File and return a JAXB POJO of parsed data
158 * - the GZipped SIFTs XML file to parse
161 * if a problem occurs while parsing the SIFTs XML
163 private Entry parseSIFTs(File siftFile) throws SiftsException
165 try (InputStream in = new FileInputStream(siftFile);
166 GZIPInputStream gzis = new GZIPInputStream(in);)
168 // System.out.println("File : " + siftFile.getAbsolutePath());
169 JAXBContext jc = JAXBContext.newInstance("jalview.xml.binding.sifts");
170 XMLStreamReader streamReader = XMLInputFactory.newInstance()
171 .createXMLStreamReader(gzis);
172 Unmarshaller um = jc.createUnmarshaller();
173 return (Entry) um.unmarshal(streamReader);
174 } catch (Exception e)
177 throw new SiftsException(e.getMessage());
182 * Get a SIFTs XML file for a given PDB Id from Cache or download from FTP
183 * repository if not found in cache
186 * @return SIFTs XML file
187 * @throws SiftsException
189 public static File getSiftsFile(String pdbId) throws SiftsException
192 * return mocked file if it has been set
194 if (mockSiftsFile != null)
196 return mockSiftsFile;
199 String siftsFileName = SiftsSettings.getSiftDownloadDirectory()
200 + pdbId.toLowerCase() + ".xml.gz";
201 File siftsFile = new File(siftsFileName);
202 if (siftsFile.exists())
204 // The line below is required for unit testing... don't comment it out!!!
205 System.out.println(">>> SIFTS File already downloaded for " + pdbId);
207 if (isFileOlderThanThreshold(siftsFile,
208 SiftsSettings.getCacheThresholdInDays()))
210 File oldSiftsFile = new File(siftsFileName + "_old");
211 siftsFile.renameTo(oldSiftsFile);
214 siftsFile = downloadSiftsFile(pdbId.toLowerCase());
215 oldSiftsFile.delete();
217 } catch (IOException e)
220 oldSiftsFile.renameTo(siftsFile);
221 return new File(siftsFileName);
231 siftsFile = downloadSiftsFile(pdbId.toLowerCase());
232 } catch (IOException e)
234 throw new SiftsException(e.getMessage());
240 * This method enables checking if a cached file has exceeded a certain
246 * the threshold in days
249 public static boolean isFileOlderThanThreshold(File file, int noOfDays)
251 Path filePath = file.toPath();
252 BasicFileAttributes attr;
256 attr = Files.readAttributes(filePath, BasicFileAttributes.class);
257 diffInDays = (int) ((new Date().getTime() - attr.lastModifiedTime()
258 .toMillis()) / (1000 * 60 * 60 * 24));
259 // System.out.println("Diff in days : " + diffInDays);
260 } catch (IOException e)
264 return noOfDays <= diffInDays;
268 * Download a SIFTs XML file for a given PDB Id from an FTP repository
271 * @return downloaded SIFTs XML file
272 * @throws SiftsException
273 * @throws IOException
275 public static File downloadSiftsFile(String pdbId) throws SiftsException,
278 if (pdbId.contains(".cif"))
280 pdbId = pdbId.replace(".cif", "");
282 String siftFile = pdbId + ".xml.gz";
283 String siftsFileFTPURL = SIFTS_FTP_BASE_URL + siftFile;
284 String downloadedSiftsFile = SiftsSettings.getSiftDownloadDirectory()
286 File siftsDownloadDir = new File(
287 SiftsSettings.getSiftDownloadDirectory());
288 if (!siftsDownloadDir.exists())
290 siftsDownloadDir.mkdirs();
292 // System.out.println(">> Download ftp url : " + siftsFileFTPURL);
293 // long now = System.currentTimeMillis();
294 URL url = new URL(siftsFileFTPURL);
295 URLConnection conn = url.openConnection();
296 InputStream inputStream = conn.getInputStream();
297 FileOutputStream outputStream = new FileOutputStream(
298 downloadedSiftsFile);
299 byte[] buffer = new byte[BUFFER_SIZE];
301 while ((bytesRead = inputStream.read(buffer)) != -1)
303 outputStream.write(buffer, 0, bytesRead);
305 outputStream.close();
307 // System.out.println(">>> File downloaded : " + downloadedSiftsFile
308 // + " took " + (System.currentTimeMillis() - now) + "ms");
309 return new File(downloadedSiftsFile);
313 * Delete the SIFTs file for the given PDB Id in the local SIFTs download
317 * @return true if the file was deleted or doesn't exist
319 public static boolean deleteSiftsFileByPDBId(String pdbId)
321 File siftsFile = new File(SiftsSettings.getSiftDownloadDirectory()
322 + pdbId.toLowerCase() + ".xml.gz");
323 if (siftsFile.exists())
325 return siftsFile.delete();
331 * Get a valid SIFTs DBRef for the given sequence current SIFTs entry
334 * - the target sequence for the operation
335 * @return a valid DBRefEntry that is SIFTs compatible
337 * if no valid source DBRefEntry was found for the given sequences
339 public DBRefEntryI getValidSourceDBRef(SequenceI seq)
340 throws SiftsException
342 List<DBRefEntry> dbRefs = seq.getPrimaryDBRefs();
343 if (dbRefs == null || dbRefs.size() < 1)
345 throw new SiftsException(
346 "Source DBRef could not be determined. DBRefs might not have been retrieved.");
349 for (DBRefEntry dbRef : dbRefs)
351 if (dbRef == null || dbRef.getAccessionId() == null
352 || dbRef.getSource() == null)
356 String canonicalSource = DBRefUtils.getCanonicalName(dbRef
358 if (isValidDBRefEntry(dbRef)
359 && (canonicalSource.equalsIgnoreCase(DBRefSource.UNIPROT) || canonicalSource
360 .equalsIgnoreCase(DBRefSource.PDB)))
365 throw new SiftsException("Could not get source DB Ref");
369 * Check that the DBRef Entry is properly populated and is available in this
370 * SiftClient instance
373 * - DBRefEntry to validate
374 * @return true validation is successful otherwise false is returned.
376 boolean isValidDBRefEntry(DBRefEntryI entry)
378 return entry != null && entry.getAccessionId() != null
379 && isFoundInSiftsEntry(entry.getAccessionId());
383 public HashSet<String> getAllMappingAccession()
385 HashSet<String> accessions = new HashSet<String>();
386 List<Entity> entities = siftsEntry.getEntity();
387 for (Entity entity : entities)
389 List<Segment> segments = entity.getSegment();
390 for (Segment segment : segments)
392 List<MapRegion> mapRegions = segment.getListMapRegion()
394 for (MapRegion mapRegion : mapRegions)
397 .add(mapRegion.getDb().getDbAccessionId().toLowerCase());
405 public StructureMapping getStructureMapping(SequenceI seq,
406 String pdbFile, String chain) throws Exception,
407 StructureMappingException
409 structId = (chain == null) ? pdbId : pdbId + "|" + chain;
410 System.out.println("Getting SIFTS mapping for " + structId + ": seq "
413 final StringBuilder mappingDetails = new StringBuilder(128);
414 PrintStream ps = new PrintStream(System.out)
417 public void print(String x)
419 mappingDetails.append(x);
423 public void println()
425 mappingDetails.append(NEWLINE);
428 HashMap<Integer, int[]> mapping = getGreedyMapping(chain, seq, ps);
430 String mappingOutput = mappingDetails.toString();
431 StructureMapping siftsMapping = new StructureMapping(seq, pdbFile,
432 pdbId, chain, mapping, mappingOutput);
437 public HashMap<Integer, int[]> getGreedyMapping(String entityId,
438 SequenceI seq, java.io.PrintStream os) throws SiftsException,
439 StructureMappingException
441 List<Integer> omitNonObserved = new ArrayList<Integer>();
442 int nonObservedShiftIndex = 0;
443 // System.out.println("Generating mappings for : " + entityId);
444 Entity entity = null;
445 entity = getEntityById(entityId);
446 String originalSeq = AlignSeq.extractGaps(
447 jalview.util.Comparison.GapChars, seq.getSequenceAsString());
448 HashMap<Integer, int[]> mapping = new HashMap<Integer, int[]>();
449 DBRefEntryI sourceDBRef;
450 sourceDBRef = getValidSourceDBRef(seq);
451 // TODO ensure sequence start/end is in the same coordinate system and
452 // consistent with the choosen sourceDBRef
454 // set sequence coordinate system - default value is UniProt
455 if (sourceDBRef.getSource().equalsIgnoreCase(DBRefSource.PDB))
457 seqCoordSys = CoordinateSys.PDB;
460 HashSet<String> dbRefAccessionIdsString = new HashSet<String>();
461 for (DBRefEntry dbref : seq.getDBRefs())
463 dbRefAccessionIdsString.add(dbref.getAccessionId().toLowerCase());
465 dbRefAccessionIdsString.add(sourceDBRef.getAccessionId().toLowerCase());
467 curDBRefAccessionIdsString = dbRefAccessionIdsString;
468 curSourceDBRef = sourceDBRef.getAccessionId();
470 TreeMap<Integer, String> resNumMap = new TreeMap<Integer, String>();
471 List<Segment> segments = entity.getSegment();
472 SegmentHelperPojo shp = new SegmentHelperPojo(seq, mapping, resNumMap,
473 omitNonObserved, nonObservedShiftIndex);
474 processSegments(segments, shp);
477 populateAtomPositions(entityId, mapping);
478 } catch (Exception e)
482 if (seqCoordSys == CoordinateSys.UNIPROT)
484 padWithGaps(resNumMap, omitNonObserved);
486 int seqStart = UNASSIGNED;
487 int seqEnd = UNASSIGNED;
488 int pdbStart = UNASSIGNED;
489 int pdbEnd = UNASSIGNED;
491 if (mapping.isEmpty())
493 throw new SiftsException("SIFTS mapping failed");
496 Integer[] keys = mapping.keySet().toArray(new Integer[0]);
499 seqEnd = keys[keys.length - 1];
501 String matchedSeq = originalSeq;
502 if (seqStart != UNASSIGNED)
504 pdbStart = mapping.get(seqStart)[PDB_RES_POS];
505 pdbEnd = mapping.get(seqEnd)[PDB_RES_POS];
506 int orignalSeqStart = seq.getStart();
507 if (orignalSeqStart >= 1)
509 int subSeqStart = (seqStart >= orignalSeqStart) ? seqStart
510 - orignalSeqStart : 0;
511 int subSeqEnd = seqEnd - (orignalSeqStart - 1);
512 subSeqEnd = originalSeq.length() < subSeqEnd ? originalSeq.length()
514 matchedSeq = originalSeq.substring(subSeqStart, subSeqEnd);
518 matchedSeq = originalSeq.substring(1, originalSeq.length());
522 StringBuilder targetStrucSeqs = new StringBuilder();
523 for (String res : resNumMap.values())
525 targetStrucSeqs.append(res);
530 MappingOutputModel mop = new MappingOutputModel();
531 mop.setSeqStart(seqStart);
532 mop.setSeqEnd(seqEnd);
533 mop.setSeqName(seq.getName());
534 mop.setSeqResidue(matchedSeq);
536 mop.setStrStart(pdbStart);
537 mop.setStrEnd(pdbEnd);
538 mop.setStrName(structId);
539 mop.setStrResidue(targetStrucSeqs.toString());
542 os.print(getMappingOutput(mop).toString());
548 void processSegments(List<Segment> segments, SegmentHelperPojo shp)
550 SequenceI seq = shp.getSeq();
551 HashMap<Integer, int[]> mapping = shp.getMapping();
552 TreeMap<Integer, String> resNumMap = shp.getResNumMap();
553 List<Integer> omitNonObserved = shp.getOmitNonObserved();
554 int nonObservedShiftIndex = shp.getNonObservedShiftIndex();
555 for (Segment segment : segments)
557 // System.out.println("Mapping segments : " + segment.getSegId() + "\\"s
559 List<Residue> residues = segment.getListResidue().getResidue();
560 for (Residue residue : residues)
562 int currSeqIndex = UNASSIGNED;
563 List<CrossRefDb> cRefDbs = residue.getCrossRefDb();
564 CrossRefDb pdbRefDb = null;
565 for (CrossRefDb cRefDb : cRefDbs)
567 if (cRefDb.getDbSource().equalsIgnoreCase(DBRefSource.PDB))
571 if (cRefDb.getDbCoordSys()
572 .equalsIgnoreCase(seqCoordSys.getName())
573 && isAccessionMatched(cRefDb.getDbAccessionId()))
575 String resNumIndexString = cRefDb.getDbResNum()
576 .equalsIgnoreCase("None") ? String.valueOf(UNASSIGNED)
577 : cRefDb.getDbResNum();
580 currSeqIndex = Integer.valueOf(resNumIndexString);
581 } catch (NumberFormatException nfe)
583 currSeqIndex = Integer.valueOf(resNumIndexString
584 .split("[a-zA-Z]")[0]);
587 if (pdbRefDb != null)
589 break;// exit loop if pdb and uniprot are already found
593 if (currSeqIndex == UNASSIGNED)
597 if (currSeqIndex >= seq.getStart() && currSeqIndex <= seq.getEnd())
602 resNum = (pdbRefDb == null) ? Integer.valueOf(residue
603 .getDbResNum()) : Integer.valueOf(pdbRefDb
605 } catch (NumberFormatException nfe)
607 resNum = (pdbRefDb == null) ? Integer.valueOf(residue
608 .getDbResNum()) : Integer.valueOf(pdbRefDb
609 .getDbResNum().split("[a-zA-Z]")[0]);
613 if (isResidueObserved(residue)
614 || seqCoordSys == CoordinateSys.UNIPROT)
616 char resCharCode = ResidueProperties
617 .getSingleCharacterCode(ResidueProperties
618 .getCanonicalAminoAcid(residue.getDbResName()));
619 resNumMap.put(currSeqIndex, String.valueOf(resCharCode));
623 omitNonObserved.add(currSeqIndex);
624 ++nonObservedShiftIndex;
626 mapping.put(currSeqIndex - nonObservedShiftIndex, new int[] {
627 Integer.valueOf(resNum), UNASSIGNED });
635 * Checks if the residue instance is marked 'Not_observed' or not
640 private boolean isResidueObserved(Residue residue)
642 Set<String> annotations = getResidueAnnotaitons(residue,
643 ResidueDetailType.ANNOTATION);
644 if (annotations == null || annotations.isEmpty())
648 for (String annotation : annotations)
650 if (annotation.equalsIgnoreCase(NOT_OBSERVED))
659 * Get annotation String for a given residue and annotation type
665 private Set<String> getResidueAnnotaitons(Residue residue,
666 ResidueDetailType type)
668 HashSet<String> foundAnnotations = new HashSet<String>();
669 List<ResidueDetail> resDetails = residue.getResidueDetail();
670 for (ResidueDetail resDetail : resDetails)
672 if (resDetail.getProperty().equalsIgnoreCase(type.getCode()))
674 foundAnnotations.add(resDetail.getContent());
677 return foundAnnotations;
681 public boolean isAccessionMatched(String accession)
683 boolean isStrictMatch = true;
684 return isStrictMatch ? curSourceDBRef.equalsIgnoreCase(accession)
685 : curDBRefAccessionIdsString.contains(accession.toLowerCase());
688 private boolean isFoundInSiftsEntry(String accessionId)
690 Set<String> siftsDBRefs = getAllMappingAccession();
691 return accessionId != null
692 && siftsDBRefs.contains(accessionId.toLowerCase());
696 * Pad omitted residue positions in PDB sequence with gaps
700 void padWithGaps(Map<Integer, String> resNumMap,
701 List<Integer> omitNonObserved)
703 if (resNumMap == null || resNumMap.isEmpty())
707 Integer[] keys = resNumMap.keySet().toArray(new Integer[0]);
708 // Arrays.sort(keys);
709 int firstIndex = keys[0];
710 int lastIndex = keys[keys.length - 1];
711 // System.out.println("Min value " + firstIndex);
712 // System.out.println("Max value " + lastIndex);
713 for (int x = firstIndex; x <= lastIndex; x++)
715 if (!resNumMap.containsKey(x) && !omitNonObserved.contains(x))
717 resNumMap.put(x, "-");
723 public Entity getEntityById(String id) throws SiftsException
725 // Determines an entity to process by performing a heuristic matching of all
726 // Entities with the given chainId and choosing the best matching Entity
727 Entity entity = getEntityByMostOptimalMatchedId(id);
732 throw new SiftsException("Entity " + id + " not found");
736 * This method was added because EntityId is NOT always equal to ChainId.
737 * Hence, it provides the logic to greedily detect the "true" Entity for a
738 * given chainId where discrepancies exist.
743 public Entity getEntityByMostOptimalMatchedId(String chainId)
745 // System.out.println("---> advanced greedy entityId matching block entered..");
746 List<Entity> entities = siftsEntry.getEntity();
747 SiftsEntitySortPojo[] sPojo = new SiftsEntitySortPojo[entities.size()];
749 for (Entity entity : entities)
751 sPojo[count] = new SiftsEntitySortPojo();
752 sPojo[count].entityId = entity.getEntityId();
754 List<Segment> segments = entity.getSegment();
755 for (Segment segment : segments)
757 List<Residue> residues = segment.getListResidue().getResidue();
758 for (Residue residue : residues)
760 List<CrossRefDb> cRefDbs = residue.getCrossRefDb();
761 for (CrossRefDb cRefDb : cRefDbs)
763 if (!cRefDb.getDbSource().equalsIgnoreCase("PDB"))
767 ++sPojo[count].resCount;
768 if (cRefDb.getDbChainId().equalsIgnoreCase(chainId))
770 ++sPojo[count].chainIdFreq;
775 sPojo[count].pid = (100 * sPojo[count].chainIdFreq)
776 / sPojo[count].resCount;
779 Arrays.sort(sPojo, Collections.reverseOrder());
780 // System.out.println("highest matched entity : " + sPojo[0].entityId);
781 // System.out.println("highest matched pid : " + sPojo[0].pid);
783 if (sPojo[0].entityId != null)
785 if (sPojo[0].pid < 1)
789 for (Entity entity : entities)
791 if (!entity.getEntityId().equalsIgnoreCase(sPojo[0].entityId))
801 private class SiftsEntitySortPojo implements
802 Comparable<SiftsEntitySortPojo>
804 public String entityId;
806 public int chainIdFreq;
813 public int compareTo(SiftsEntitySortPojo o)
815 return this.pid - o.pid;
819 private class SegmentHelperPojo
821 private SequenceI seq;
823 private HashMap<Integer, int[]> mapping;
825 private TreeMap<Integer, String> resNumMap;
827 private List<Integer> omitNonObserved;
829 private int nonObservedShiftIndex;
831 public SegmentHelperPojo(SequenceI seq,
832 HashMap<Integer, int[]> mapping,
833 TreeMap<Integer, String> resNumMap,
834 List<Integer> omitNonObserved, int nonObservedShiftIndex)
838 setResNumMap(resNumMap);
839 setOmitNonObserved(omitNonObserved);
840 setNonObservedShiftIndex(nonObservedShiftIndex);
843 public SequenceI getSeq()
848 public void setSeq(SequenceI seq)
853 public HashMap<Integer, int[]> getMapping()
858 public void setMapping(HashMap<Integer, int[]> mapping)
860 this.mapping = mapping;
863 public TreeMap<Integer, String> getResNumMap()
868 public void setResNumMap(TreeMap<Integer, String> resNumMap)
870 this.resNumMap = resNumMap;
873 public List<Integer> getOmitNonObserved()
875 return omitNonObserved;
878 public void setOmitNonObserved(List<Integer> omitNonObserved)
880 this.omitNonObserved = omitNonObserved;
883 public int getNonObservedShiftIndex()
885 return nonObservedShiftIndex;
888 public void setNonObservedShiftIndex(int nonObservedShiftIndex)
890 this.nonObservedShiftIndex = nonObservedShiftIndex;
895 public StringBuffer getMappingOutput(MappingOutputModel mp)
896 throws StructureMappingException
898 String seqRes = mp.getSeqResidue();
899 String seqName = mp.getSeqName();
900 int sStart = mp.getSeqStart();
901 int sEnd = mp.getSeqEnd();
903 String strRes = mp.getStrResidue();
904 String strName = mp.getStrName();
905 int pdbStart = mp.getStrStart();
906 int pdbEnd = mp.getStrEnd();
908 String type = mp.getType();
910 int maxid = (seqName.length() >= strName.length()) ? seqName.length()
912 int len = 72 - maxid - 1;
914 int nochunks = ((seqRes.length()) / len)
915 + ((seqRes.length()) % len > 0 ? 1 : 0);
917 StringBuffer output = new StringBuffer();
918 output.append(NEWLINE);
919 output.append("Sequence \u27f7 Structure mapping details").append(
921 output.append("Method: SIFTS");
922 output.append(NEWLINE).append(NEWLINE);
924 output.append(new Format("%" + maxid + "s").form(seqName));
925 output.append(" : ");
926 output.append(String.valueOf(sStart));
927 output.append(" - ");
928 output.append(String.valueOf(sEnd));
929 output.append(" Maps to ");
930 output.append(NEWLINE);
931 output.append(new Format("%" + maxid + "s").form(structId));
932 output.append(" : ");
933 output.append(String.valueOf(pdbStart));
934 output.append(" - ");
935 output.append(String.valueOf(pdbEnd));
936 output.append(NEWLINE).append(NEWLINE);
938 int matchedSeqCount = 0;
939 for (int j = 0; j < nochunks; j++)
941 // Print the first aligned sequence
942 output.append(new Format("%" + (maxid) + "s").form(seqName)).append(
945 for (int i = 0; i < len; i++)
947 if ((i + (j * len)) < seqRes.length())
949 output.append(seqRes.charAt(i + (j * len)));
953 output.append(NEWLINE);
954 output.append(new Format("%" + (maxid) + "s").form(" ")).append(" ");
956 // Print out the matching chars
957 for (int i = 0; i < len; i++)
961 if ((i + (j * len)) < seqRes.length())
963 boolean sameChar = Comparison.isSameResidue(
964 seqRes.charAt(i + (j * len)),
965 strRes.charAt(i + (j * len)), false);
967 && !jalview.util.Comparison.isGap(seqRes.charAt(i
973 else if (type.equals("pep"))
975 if (ResidueProperties.getPAM250(seqRes.charAt(i + (j * len)),
976 strRes.charAt(i + (j * len))) > 0)
990 } catch (IndexOutOfBoundsException e)
995 // Now print the second aligned sequence
996 output = output.append(NEWLINE);
997 output = output.append(new Format("%" + (maxid) + "s").form(strName))
999 for (int i = 0; i < len; i++)
1001 if ((i + (j * len)) < strRes.length())
1003 output.append(strRes.charAt(i + (j * len)));
1006 output.append(NEWLINE).append(NEWLINE);
1008 float pid = (float) matchedSeqCount / seqRes.length() * 100;
1009 if (pid < SiftsSettings.getFailSafePIDThreshold())
1011 throw new StructureMappingException(
1012 ">>> Low PID detected for SIFTs mapping...");
1014 output.append("Length of alignment = " + seqRes.length()).append(
1016 output.append(new Format("Percentage ID = %2.2f").form(pid));
1021 public int getEntityCount()
1023 return siftsEntry.getEntity().size();
1027 public String getDbAccessionId()
1029 return siftsEntry.getDbAccessionId();
1033 public String getDbCoordSys()
1035 return siftsEntry.getDbCoordSys();
1039 public String getDbSource()
1041 return siftsEntry.getDbSource();
1045 public String getDbVersion()
1047 return siftsEntry.getDbVersion();
1050 public static void setMockSiftsFile(File file)
1052 mockSiftsFile = file;