From 832101caf0bd7b01d0103879875a724078ea118f Mon Sep 17 00:00:00 2001 From: James Procter Date: Fri, 15 Dec 2023 14:17:24 +0000 Subject: [PATCH] JAL-4366 hacked in a 1:1 mapping --- .../structure/StructureSelectionManager.java | 138 +++++++++++++++++--- 1 file changed, 123 insertions(+), 15 deletions(-) diff --git a/src/jalview/structure/StructureSelectionManager.java b/src/jalview/structure/StructureSelectionManager.java index ec3e0a0..ad5da67 100644 --- a/src/jalview/structure/StructureSelectionManager.java +++ b/src/jalview/structure/StructureSelectionManager.java @@ -54,6 +54,7 @@ import jalview.io.AppletFormatAdapter; import jalview.io.DataSourceType; import jalview.io.StructureFile; import jalview.structure.StructureImportSettings.TFType; +import jalview.util.MapList; import jalview.util.MappingUtils; import jalview.util.MessageManager; import jalview.util.Platform; @@ -558,6 +559,7 @@ public class StructureSelectionManager String maxChainId = " "; PDBChain maxChain = null; boolean first = true; + PDBChain idLengthChain = null; for (PDBChain chain : pdb.getChains()) { if (targetChainId.length() > 0 && !targetChainId.equals(chain.id) @@ -570,10 +572,11 @@ public class StructureSelectionManager final String type = chain.isNa ? AlignSeq.DNA : AlignSeq.PEP; AlignSeq as = AlignSeq.doGlobalNWAlignment(seq, chain.sequence, type); - // equivalent to: - // AlignSeq as = new AlignSeq(sequence[s], chain.sequence, type); - // as.calcScoreMatrix(); - // as.traceAlignment(); + // TODO: JAL-4366 determinine of a crummy alignment but exact match should make this chain the one to be mapped to a 3di sequence + if (as.s1str.length() == 4 + as.s2str.length()) + { + idLengthChain = chain; + } if (first || as.maxscore > max || (as.maxscore == max && chain.id.equals(targetChainId))) @@ -589,13 +592,12 @@ public class StructureSelectionManager { continue; } - if (sourceType == DataSourceType.PASTE) { pdbFile = "INLINE" + pdb.getId(); } - List seqToStrucMapping = new ArrayList<>(); + if (isMapUsingSIFTs && seq.isProtein()) { if (progress != null) @@ -670,6 +672,9 @@ public class StructureSelectionManager } else { + /* + * fallback to NeedlemanWunch. + */ StructureMapping nwMapping = getNWMappings(seq, pdbFile, maxChainId, maxChain, pdb, maxAlignseq); seqToStrucMapping.add(nwMapping); @@ -683,17 +688,33 @@ public class StructureSelectionManager } else { - if (progress != null) + // Not doing SIFTS + // first check if we should use an identity mapping + if (idLengthChain != null && maxAlignseq.getS2Coverage() < 0.5) { - progress.setProgressBar( - MessageManager.getString( - "status.obtaining_mapping_with_nw_alignment"), - progressSessionId); + Console.info( + "Assuming 3Dsi identity mapping between structure and sequence"); + StructureMapping matchMapping = getIdMappings(seq, pdbFile, + idLengthChain.id, idLengthChain, pdb); + seqToStrucMapping.add(matchMapping); + ds.addPDBId(idLengthChain.sequence.getAllPDBEntries().get(0)); + Console.info("Mapping added."); + } + else + { + // Construct a needleman wunsch mapping instead. + if (progress != null) + { + progress.setProgressBar( + MessageManager.getString( + "status.obtaining_mapping_with_nw_alignment"), + progressSessionId); + } + StructureMapping nwMapping = getNWMappings(seq, pdbFile, + maxChainId, maxChain, pdb, maxAlignseq); + seqToStrucMapping.add(nwMapping); + ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0)); } - StructureMapping nwMapping = getNWMappings(seq, pdbFile, maxChainId, - maxChain, pdb, maxAlignseq); - seqToStrucMapping.add(nwMapping); - ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0)); } if (forStructureView) { @@ -795,6 +816,17 @@ public class StructureSelectionManager } return curChainMapping; } + + /** + * construct a mapping based on a pairwise alignment of the sequence and chain + * @param seq + * @param pdbFile + * @param maxChainId + * @param maxChain + * @param pdb + * @param maxAlignseq + * @return + */ private StructureMapping getNWMappings(SequenceI seq, String pdbFile, String maxChainId, PDBChain maxChain, StructureFile pdb, @@ -876,6 +908,82 @@ public class StructureSelectionManager maxChain.transferResidueAnnotation(nwMapping, sqmpping); return nwMapping; } + + /** + * construct a 1:1 mapping using given residue and sequence numbering + * @param seq + * @param pdbFile + * @param identityChainId + * @param identityChain + * @param pdb + * @return + */ + + private StructureMapping getIdMappings(SequenceI seq, String pdbFile, + String identityChainId, PDBChain identityChain, StructureFile pdb) + { + final StringBuilder mappingDetails = new StringBuilder(128); + mappingDetails.append(NEWLINE) + .append("Sequence \u27f7 Structure mapping details"); + mappingDetails.append(NEWLINE); + mappingDetails.append("Method: Matching length 1:1"); + mappingDetails.append(NEWLINE).append("PDB Sequence is :") + .append(NEWLINE).append("Sequence = ") + .append(identityChain.sequence.getSequenceAsString()); + mappingDetails.append(NEWLINE).append("No of residues = ") + .append(identityChain.residues.size()).append(NEWLINE) + .append(NEWLINE); + + mappingDetails.append(NEWLINE) + .append("Aligned Sequence is: " + seq.getDisplayId(true)); + mappingDetails.append(NEWLINE) + .append("Sequence = " + seq.getSequenceAsString()); + + int from = Math.max(seq.getStart(),identityChain.sequence.getStart()); + int to = Math.min(seq.getEnd(), identityChain.sequence.getEnd()); + jalview.datamodel.Mapping sqmpping = new jalview.datamodel.Mapping(seq, + new MapList(new int[] + { from,to }, + new int[] + { from,to }, + 1, 1)); + identityChain.mapChainWith(sqmpping, seq); + + identityChain.transferRESNUMFeatures(seq, null, + pdb.getId().toLowerCase(Locale.ROOT)); + + // Construct mapping + // TODO REFACTOR TO PDBChain as a builder + HashMap mapping = new HashMap<>(); + int resNum = -10000; + int index = 0; + char insCode = ' '; + + do + { + Atom tmp = identityChain.atoms.elementAt(index); + if ((resNum != tmp.resNumber || insCode != tmp.insCode) + && tmp.alignmentMapping != -1) + { + resNum = tmp.resNumber; + insCode = tmp.insCode; + if (tmp.alignmentMapping >= -1) + { + mapping.put(tmp.alignmentMapping + 1, + new int[] + { tmp.resNumber, tmp.atomIndex }); + } + } + + index++; + } while (index < identityChain.atoms.size()); + + StructureMapping idMapping = new StructureMapping(seq, pdbFile, + pdb.getId(), identityChainId, mapping, + mappingDetails.toString()); + identityChain.transferResidueAnnotation(idMapping, sqmpping); + return idMapping; + } public void removeStructureViewerListener(Object svl, String[] pdbfiles) { -- 1.7.10.2