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 static final int UNASSIGNED = StructureMapping.UNASSIGNED; // -1
84 private static final int PDB_RES_POS = StructureMapping.PDB_RES_NUM_INDEX; // 0
86 private Entry siftsEntry;
90 private String structId;
92 private CoordinateSys seqCoordSys = CoordinateSys.UNIPROT;
94 private static final int BUFFER_SIZE = 4096;
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 if (pdbRefDb == null || pdbRefDb.getDbResNum().equals("null"))
612 resNum = Integer.valueOf(pdbRefDb
613 .getDbResNum().split("[a-zA-Z]")[0]);
617 if (isResidueObserved(residue)
618 || seqCoordSys == CoordinateSys.UNIPROT)
620 char resCharCode = ResidueProperties
621 .getSingleCharacterCode(ResidueProperties
622 .getCanonicalAminoAcid(residue.getDbResName()));
623 resNumMap.put(currSeqIndex, String.valueOf(resCharCode));
627 omitNonObserved.add(currSeqIndex);
628 ++nonObservedShiftIndex;
630 mapping.put(currSeqIndex - nonObservedShiftIndex, new int[] {
631 Integer.valueOf(resNum), UNASSIGNED });
639 * Checks if the residue instance is marked 'Not_observed' or not
644 private boolean isResidueObserved(Residue residue)
646 Set<String> annotations = getResidueAnnotaitons(residue,
647 ResidueDetailType.ANNOTATION);
648 if (annotations == null || annotations.isEmpty())
652 for (String annotation : annotations)
654 if (annotation.equalsIgnoreCase(NOT_OBSERVED))
663 * Get annotation String for a given residue and annotation type
669 private Set<String> getResidueAnnotaitons(Residue residue,
670 ResidueDetailType type)
672 HashSet<String> foundAnnotations = new HashSet<String>();
673 List<ResidueDetail> resDetails = residue.getResidueDetail();
674 for (ResidueDetail resDetail : resDetails)
676 if (resDetail.getProperty().equalsIgnoreCase(type.getCode()))
678 foundAnnotations.add(resDetail.getContent());
681 return foundAnnotations;
685 public boolean isAccessionMatched(String accession)
687 boolean isStrictMatch = true;
688 return isStrictMatch ? curSourceDBRef.equalsIgnoreCase(accession)
689 : curDBRefAccessionIdsString.contains(accession.toLowerCase());
692 private boolean isFoundInSiftsEntry(String accessionId)
694 Set<String> siftsDBRefs = getAllMappingAccession();
695 return accessionId != null
696 && siftsDBRefs.contains(accessionId.toLowerCase());
700 * Pad omitted residue positions in PDB sequence with gaps
704 void padWithGaps(Map<Integer, String> resNumMap,
705 List<Integer> omitNonObserved)
707 if (resNumMap == null || resNumMap.isEmpty())
711 Integer[] keys = resNumMap.keySet().toArray(new Integer[0]);
712 // Arrays.sort(keys);
713 int firstIndex = keys[0];
714 int lastIndex = keys[keys.length - 1];
715 // System.out.println("Min value " + firstIndex);
716 // System.out.println("Max value " + lastIndex);
717 for (int x = firstIndex; x <= lastIndex; x++)
719 if (!resNumMap.containsKey(x) && !omitNonObserved.contains(x))
721 resNumMap.put(x, "-");
727 public Entity getEntityById(String id) throws SiftsException
729 // Determines an entity to process by performing a heuristic matching of all
730 // Entities with the given chainId and choosing the best matching Entity
731 Entity entity = getEntityByMostOptimalMatchedId(id);
736 throw new SiftsException("Entity " + id + " not found");
740 * This method was added because EntityId is NOT always equal to ChainId.
741 * Hence, it provides the logic to greedily detect the "true" Entity for a
742 * given chainId where discrepancies exist.
747 public Entity getEntityByMostOptimalMatchedId(String chainId)
749 // System.out.println("---> advanced greedy entityId matching block entered..");
750 List<Entity> entities = siftsEntry.getEntity();
751 SiftsEntitySortPojo[] sPojo = new SiftsEntitySortPojo[entities.size()];
753 for (Entity entity : entities)
755 sPojo[count] = new SiftsEntitySortPojo();
756 sPojo[count].entityId = entity.getEntityId();
758 List<Segment> segments = entity.getSegment();
759 for (Segment segment : segments)
761 List<Residue> residues = segment.getListResidue().getResidue();
762 for (Residue residue : residues)
764 List<CrossRefDb> cRefDbs = residue.getCrossRefDb();
765 for (CrossRefDb cRefDb : cRefDbs)
767 if (!cRefDb.getDbSource().equalsIgnoreCase("PDB"))
771 ++sPojo[count].resCount;
772 if (cRefDb.getDbChainId().equalsIgnoreCase(chainId))
774 ++sPojo[count].chainIdFreq;
779 sPojo[count].pid = (100 * sPojo[count].chainIdFreq)
780 / sPojo[count].resCount;
783 Arrays.sort(sPojo, Collections.reverseOrder());
784 // System.out.println("highest matched entity : " + sPojo[0].entityId);
785 // System.out.println("highest matched pid : " + sPojo[0].pid);
787 if (sPojo[0].entityId != null)
789 if (sPojo[0].pid < 1)
793 for (Entity entity : entities)
795 if (!entity.getEntityId().equalsIgnoreCase(sPojo[0].entityId))
805 private class SiftsEntitySortPojo implements
806 Comparable<SiftsEntitySortPojo>
808 public String entityId;
810 public int chainIdFreq;
817 public int compareTo(SiftsEntitySortPojo o)
819 return this.pid - o.pid;
823 private class SegmentHelperPojo
825 private SequenceI seq;
827 private HashMap<Integer, int[]> mapping;
829 private TreeMap<Integer, String> resNumMap;
831 private List<Integer> omitNonObserved;
833 private int nonObservedShiftIndex;
835 public SegmentHelperPojo(SequenceI seq,
836 HashMap<Integer, int[]> mapping,
837 TreeMap<Integer, String> resNumMap,
838 List<Integer> omitNonObserved, int nonObservedShiftIndex)
842 setResNumMap(resNumMap);
843 setOmitNonObserved(omitNonObserved);
844 setNonObservedShiftIndex(nonObservedShiftIndex);
847 public SequenceI getSeq()
852 public void setSeq(SequenceI seq)
857 public HashMap<Integer, int[]> getMapping()
862 public void setMapping(HashMap<Integer, int[]> mapping)
864 this.mapping = mapping;
867 public TreeMap<Integer, String> getResNumMap()
872 public void setResNumMap(TreeMap<Integer, String> resNumMap)
874 this.resNumMap = resNumMap;
877 public List<Integer> getOmitNonObserved()
879 return omitNonObserved;
882 public void setOmitNonObserved(List<Integer> omitNonObserved)
884 this.omitNonObserved = omitNonObserved;
887 public int getNonObservedShiftIndex()
889 return nonObservedShiftIndex;
892 public void setNonObservedShiftIndex(int nonObservedShiftIndex)
894 this.nonObservedShiftIndex = nonObservedShiftIndex;
899 public StringBuffer getMappingOutput(MappingOutputModel mp)
900 throws StructureMappingException
902 String seqRes = mp.getSeqResidue();
903 String seqName = mp.getSeqName();
904 int sStart = mp.getSeqStart();
905 int sEnd = mp.getSeqEnd();
907 String strRes = mp.getStrResidue();
908 String strName = mp.getStrName();
909 int pdbStart = mp.getStrStart();
910 int pdbEnd = mp.getStrEnd();
912 String type = mp.getType();
914 int maxid = (seqName.length() >= strName.length()) ? seqName.length()
916 int len = 72 - maxid - 1;
918 int nochunks = ((seqRes.length()) / len)
919 + ((seqRes.length()) % len > 0 ? 1 : 0);
921 StringBuffer output = new StringBuffer();
922 output.append(NEWLINE);
923 output.append("Sequence \u27f7 Structure mapping details").append(
925 output.append("Method: SIFTS");
926 output.append(NEWLINE).append(NEWLINE);
928 output.append(new Format("%" + maxid + "s").form(seqName));
929 output.append(" : ");
930 output.append(String.valueOf(sStart));
931 output.append(" - ");
932 output.append(String.valueOf(sEnd));
933 output.append(" Maps to ");
934 output.append(NEWLINE);
935 output.append(new Format("%" + maxid + "s").form(structId));
936 output.append(" : ");
937 output.append(String.valueOf(pdbStart));
938 output.append(" - ");
939 output.append(String.valueOf(pdbEnd));
940 output.append(NEWLINE).append(NEWLINE);
942 int matchedSeqCount = 0;
943 for (int j = 0; j < nochunks; j++)
945 // Print the first aligned sequence
946 output.append(new Format("%" + (maxid) + "s").form(seqName)).append(
949 for (int i = 0; i < len; i++)
951 if ((i + (j * len)) < seqRes.length())
953 output.append(seqRes.charAt(i + (j * len)));
957 output.append(NEWLINE);
958 output.append(new Format("%" + (maxid) + "s").form(" ")).append(" ");
960 // Print out the matching chars
961 for (int i = 0; i < len; i++)
965 if ((i + (j * len)) < seqRes.length())
967 boolean sameChar = Comparison.isSameResidue(
968 seqRes.charAt(i + (j * len)),
969 strRes.charAt(i + (j * len)), false);
971 && !jalview.util.Comparison.isGap(seqRes.charAt(i
977 else if (type.equals("pep"))
979 if (ResidueProperties.getPAM250(seqRes.charAt(i + (j * len)),
980 strRes.charAt(i + (j * len))) > 0)
994 } catch (IndexOutOfBoundsException e)
999 // Now print the second aligned sequence
1000 output = output.append(NEWLINE);
1001 output = output.append(new Format("%" + (maxid) + "s").form(strName))
1003 for (int i = 0; i < len; i++)
1005 if ((i + (j * len)) < strRes.length())
1007 output.append(strRes.charAt(i + (j * len)));
1010 output.append(NEWLINE).append(NEWLINE);
1012 float pid = (float) matchedSeqCount / seqRes.length() * 100;
1013 if (pid < SiftsSettings.getFailSafePIDThreshold())
1015 throw new StructureMappingException(
1016 ">>> Low PID detected for SIFTs mapping...");
1018 output.append("Length of alignment = " + seqRes.length()).append(
1020 output.append(new Format("Percentage ID = %2.2f").form(pid));
1025 public int getEntityCount()
1027 return siftsEntry.getEntity().size();
1031 public String getDbAccessionId()
1033 return siftsEntry.getDbAccessionId();
1037 public String getDbCoordSys()
1039 return siftsEntry.getDbCoordSys();
1043 public String getDbSource()
1045 return siftsEntry.getDbSource();
1049 public String getDbVersion()
1051 return siftsEntry.getDbVersion();
1054 public static void setMockSiftsFile(File file)
1056 mockSiftsFile = file;