From: Jim Procter Date: Fri, 15 Nov 2024 17:08:29 +0000 (+0000) Subject: Merge branch 'spikes/JAL-4366_3di_msa_forfoldseeks' into spike/JAL-4366_JAL-4386_JAL... X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=5e8bd075739b756cac8f741a47a7de952c45f879;p=jalview.git Merge branch 'spikes/JAL-4366_3di_msa_forfoldseeks' into spike/JAL-4366_JAL-4386_JAL-4435_expandedmsafromstructure Conflicts: resources/lang/Messages.properties src/jalview/analysis/AlignmentUtils.java src/jalview/analysis/scoremodels/SecondaryStructureDistanceModel.java src/jalview/api/AlignViewportI.java src/jalview/ext/jmol/JalviewJmolBinding.java src/jalview/gui/CalculationChooser.java src/jalview/structure/StructureSelectionManager.java src/jalview/viewmodel/AlignmentViewport.java src/jalview/workers/SecondaryStructureConsensusThread.java --- 5e8bd075739b756cac8f741a47a7de952c45f879 diff --cc src/jalview/analysis/AAFrequency.java index 2620c8d,dd5cb91..9e4f359 --- a/src/jalview/analysis/AAFrequency.java +++ b/src/jalview/analysis/AAFrequency.java @@@ -233,10 -233,8 +233,10 @@@ public class AAFrequenc int seqCount = sequences.length; + int seqWithSSCount = 0; + ProfileI[] result = new ProfileI[width]; - + int maxSSannotcount=0; for (int column = start; column < end; column++) { diff --cc src/jalview/analysis/AlignmentUtils.java index a7d03c4,34dd4dc..b16141f --- a/src/jalview/analysis/AlignmentUtils.java +++ b/src/jalview/analysis/AlignmentUtils.java @@@ -3144,123 -3220,4 +3280,123 @@@ public class AlignmentUtil } + public static Map> getSequenceAssociatedAlignmentAnnotations( + AlignmentAnnotation[] alignAnnotList, String selectedSSSource) + { + + Map> ssAlignmentAnnotationForSequences = new HashMap>(); + if (alignAnnotList == null || alignAnnotList.length == 0) + { + return ssAlignmentAnnotationForSequences; + } + + for (AlignmentAnnotation aa : alignAnnotList) + { + if (aa.sequenceRef == null) + { + continue; + } + + if (isSecondaryStructureFrom(selectedSSSource, aa)) + { + ssAlignmentAnnotationForSequences + .computeIfAbsent(aa.sequenceRef.getDatasetSequence(), + k -> new ArrayList<>()) + .add(aa); + } + } + + return ssAlignmentAnnotationForSequences; + + } + + /** + * + * @param selectedSSSource + * @param aa + * @return true if aa is from a provider or all providers as specified by + * selectedSSSource + */ + public static boolean isSecondaryStructureFrom(String selectedSSSource, + AlignmentAnnotation aa) + { + + for (String label : Constants.SECONDARY_STRUCTURE_LABELS.keySet()) + { + + if (label.equals(aa.label)) + { + + if (selectedSSSource.equals(Constants.SS_ALL_PROVIDERS)) + { + return true; + } + String ssSource = AlignmentUtils + .extractSSSourceFromAnnotationDescription(aa); + if (ssSource != null && ssSource.equals(selectedSSSource)) + { + return true; + } + } + } + return false; + } + + // Method to get the key for a given provider value + public static String getSecondaryStructureProviderKey(String providerValue) { + for (Map.Entry entry : Constants.STRUCTURE_PROVIDERS.entrySet()) { + if (entry.getValue().equals(providerValue)) { + return entry.getKey(); // Return the key (abbreviation) for the matching provider value + } + } + return null; // Return null if no match is found + } + + public static String reduceLabelLength(String label) { + // Split the input by " | " + String[] parts = label.split(" \\| "); + + // Map the full names to their abbreviations + String reducedLabel = Arrays.stream(parts) + .map(fullName -> Constants.STRUCTURE_PROVIDERS.entrySet().stream() + .filter(entry -> entry.getValue().equals(fullName)) + .map(Map.Entry::getKey) + .findFirst() + .orElse(fullName)) // Use fullName if no abbreviation is found + .collect(Collectors.joining(" | ")); + + return reducedLabel; // Return the reduced label if abbreviations were applied + } + + public static Color getSecondaryStructureProviderColor(String label) { + + //return Constants.STRUCTURE_PROVIDERS_COLOR.getOrDefault(label, Color.BLACK); + Color c = Constants.STRUCTURE_PROVIDERS_COLOR.get(label.trim()); + if(c==null) + c = Color.BLACK; + return c; + } + + + public static void assignSecondaryStructureProviderColor(Map secondaryStructureProviderColorMap, + List labels) { + + // Use a Set to track unique labels + Set uniqueLabels = new HashSet<>(labels); + + Color[] palette = ColorBrewer.Paired.getColorPalette(uniqueLabels.size()); + + + List colorList = new ArrayList<>(); + Collections.addAll(colorList, palette); + Collections.shuffle(colorList); + int i = 0; + + // Loop through each unique label and add it to the map with a color. + for (String label : uniqueLabels) { + // Generate or retrieve a color for the label. + secondaryStructureProviderColorMap.put(label.toUpperCase().trim(), colorList.get(i)); + i++; + } + } - } + } diff --cc src/jalview/analysis/scoremodels/SecondaryStructureDistanceModel.java index 52a60d1,9e2cfe9..907a9bb --- a/src/jalview/analysis/scoremodels/SecondaryStructureDistanceModel.java +++ b/src/jalview/analysis/scoremodels/SecondaryStructureDistanceModel.java @@@ -382,4 -413,4 +382,4 @@@ public class SecondaryStructureDistance return "Score between sequences based on similarity between binary " + "vectors marking secondary structure displayed at each column"; } --} ++} diff --cc src/jalview/api/AlignViewportI.java index 5e1b812,2c0afb7..0cc5cbf --- a/src/jalview/api/AlignViewportI.java +++ b/src/jalview/api/AlignViewportI.java @@@ -584,11 -587,9 +588,15 @@@ public interface AlignViewportI extend * @return contact matrix or NULL */ ContactMatrixI getContactMatrix(AlignmentAnnotation alignmentAnnotation); - ProfilesI getSequenceSSConsensusHash(); - boolean is3di(); + Map getSequenceSSConsensusHash(); + + List getSecondaryStructureSources(); + void setSecondaryStructureSources(List secondaryStructureSources); ++ ++ boolean is3di(); ++ + public AlignmentAnnotation getComparisonAnnotation(); + } diff --cc src/jalview/datamodel/SequenceGroup.java index 23761c0,8cd92bc..05929d4 --- a/src/jalview/datamodel/SequenceGroup.java +++ b/src/jalview/datamodel/SequenceGroup.java @@@ -162,10 -158,10 +164,12 @@@ public class SequenceGroup implements A private boolean showConsensusHistogram; + private boolean showSSConsensusHistogram; + private AnnotatedCollectionI context; + public Map hSSConsensusProfileMap; + /** * Creates a new SequenceGroup object. */ @@@ -237,8 -233,9 +241,10 @@@ hidereps = seqsel.hidereps; showNonconserved = seqsel.showNonconserved; showSequenceLogo = seqsel.showSequenceLogo; ++ showSequenceSSLogo = seqsel.showSequenceSSLogo; normaliseSequenceLogo = seqsel.normaliseSequenceLogo; showConsensusHistogram = seqsel.showConsensusHistogram; + showSSConsensusHistogram = seqsel.showSSConsensusHistogram; idColour = seqsel.idColour; outlineColour = seqsel.outlineColour; seqrep = seqsel.seqrep; diff --cc src/jalview/ext/jmol/JalviewJmolBinding.java index 36b2546,26bcecc..1a76bd1 --- a/src/jalview/ext/jmol/JalviewJmolBinding.java +++ b/src/jalview/ext/jmol/JalviewJmolBinding.java @@@ -785,25 -794,9 +794,26 @@@ public abstract class JalviewJmolBindin } else { + PDBEntry ppe = getPdbEntry(pe); + if (ppe == null) + { + Console.warn( + "Please report under JAL-4440: Unexpected null entry for PDBEntry for a structure (for structure " + + fileName + ")"); + + continue; + } + if (ppe.getFile() == null) + { + Console.warn( + "Please report under JAL-4440: Unexpected null entry for file that we just tried to load into Jmol: pdbEntry: " + + ppe.toString() + "(for structure " + fileName + + ")"); + continue; + } - File fl = new File(getPdbEntry(pe).getFile()); - matches = fl.equals(new File(fileName)); + String jvPdbFile = getPdbEntry(pe).getFile(); + File fl = new File(jvPdbFile); + matches = fl.equals(new File(fileName)) || JmolCommands.filePathMatch(fileName, jvPdbFile); if (matches) { foundEntry = true; diff --cc src/jalview/jbgui/GAlignFrame.java index 1e371ab,8c71384..ddf300b --- a/src/jalview/jbgui/GAlignFrame.java +++ b/src/jalview/jbgui/GAlignFrame.java @@@ -927,8 -915,19 +929,19 @@@ public class GAlignFrame extends JInter showConsensusHistogram_actionPerformed(e); } - }); + }); + showSSConsensusHistogram.setText( + MessageManager.getString("label.show_ssconsensus_histogram")); + showSSConsensusHistogram.addActionListener(new ActionListener() + { + + @Override + public void actionPerformed(ActionEvent e) + { - showConsensusHistogram_actionPerformed(e); ++ showSSConsensusHistogram_actionPerformed(e); + } + }); showSequenceLogo .setText(MessageManager.getString("label.show_consensus_logo")); showSequenceLogo.addActionListener(new ActionListener() diff --cc src/jalview/structure/StructureSelectionManager.java index c3c3b3e,a170e4f..a5795c9 --- a/src/jalview/structure/StructureSelectionManager.java +++ b/src/jalview/structure/StructureSelectionManager.java @@@ -56,7 -58,7 +58,8 @@@ import jalview.io.AppletFormatAdapter import jalview.io.DataSourceType; import jalview.io.StructureFile; import jalview.structure.StructureImportSettings.TFType; +import jalview.util.Constants; + import jalview.util.MapList; import jalview.util.MappingUtils; import jalview.util.MessageManager; import jalview.util.Platform; @@@ -597,9 -589,9 +590,10 @@@ public class StructureSelectionManage { pdbFile = "INLINE" + pdb.getId(); } - List seqToStrucMapping = new ArrayList<>(); + + List foundSiftsMappings = new ArrayList<>(); + String provider = null; if (isMapUsingSIFTs && seq.isProtein()) { if (progress != null) @@@ -666,97 -648,55 +650,115 @@@ jalview.bin.Console.errPrintln(e.getMessage()); } } + // If sifts was successful, add mappings and return if (!foundSiftsMappings.isEmpty()) { - seqToStrucMapping.addAll(foundSiftsMappings); ds.addPDBId(sqmpping.getTo().getAllPDBEntries().get(0)); } - else - { - StructureMapping nwMapping = getNWMappings(seq, pdbFile, - maxChainId, maxChain, pdb, maxAlignseq); - seqToStrucMapping.add(nwMapping); - maxChain.transferRESNUMFeatures(seq, null, - pdb.getId().toLowerCase(Locale.ROOT)); // FIXME: is this - // "IEA:Jalview" ? - maxChain.transferResidueAnnotation(nwMapping, sqmpping); - ds.addPDBId(maxChain.sequence.getAllPDBEntries().get(0)); - } + } + + // If sifts was successful, add mappings and return + if (!foundSiftsMappings.isEmpty()) + { + seqToStrucMapping.addAll(foundSiftsMappings); } } - else + if (foundSiftsMappings.isEmpty()) { - if (progress != null) + // Not doing SIFTS, or SIFTS failed for some reason. + + // first check if we should use an identity mapping + if (idLengthChain != null && maxAlignseq.getS2Coverage() < 0.75) { - 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 + { + if (maxAlignseq.getS1Coverage()<0.15 && maxAlignseq.getS2Coverage()<0.15) + { + // skip this - the NW alignment is spurious + continue; + } + // 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)); } - ++ ////// PROVIDER transfer metadata to annotation... ++ /////// TODO: USE PDBEntry directly if available !!! JAL-3914 + // JAL-4392 TODO: Unable to match PDBProvider with Annotation without + // matching struct file path + String ssAnnotDescriptionInPDB = null; + String ssStructFilePathNameInPDB = pdb.getInFile(); // Structure file name + // in PDB data model + // Secondary structure annotations in pdb data model + AlignmentAnnotation[] ssAnnotationsInPDB = pdb.getSeqs().get(0) + .getAnnotation(Constants.SS_ANNOTATION_LABEL); + if (ssAnnotationsInPDB != null && ssAnnotationsInPDB.length > 0) + { + ssAnnotDescriptionInPDB = ssAnnotationsInPDB[0].description; + } + + // Match the PDB entry using file path in the pdb data model and get the + // provider + if (ssStructFilePathNameInPDB != null + && seq.getDatasetSequence() != null) + { + Vector pdbEntries = seq.getDatasetSequence() + .getAllPDBEntries(); + if (pdbEntries != null) + { + for (PDBEntry pdbEntry : pdbEntries) + { + if (pdbEntry.getFile() != null && ssStructFilePathNameInPDB + .startsWith(pdbEntry.getFile())) + { + provider = pdbEntry.getProvider(); + break; + } + } + // Add provider value as property to the ss annotation + if (provider != null) + { + // TODO - JAL-2880 JAL-4441 this should be applied to all structure + // derived annotations, not just secondary structure! + AlignmentAnnotation[] ssAnnotList = ds + .getAnnotation(Constants.SS_ANNOTATION_LABEL); + if (ssAnnotList != null) + { + for (AlignmentAnnotation ssAnnot : ssAnnotList) + { + // Match the annotation description with the annotation in pdb + // data object + if (ssAnnot + .getProperty(Constants.SS_PROVIDER_PROPERTY) == null + && ssAnnot.description + .equals(ssAnnotDescriptionInPDB)) + { + ssAnnot.setProperty(Constants.SS_PROVIDER_PROPERTY, + provider); + } + } + } + } + } + } + if (forStructureView) { for (StructureMapping sm : seqToStrucMapping) diff --cc src/jalview/viewmodel/AlignmentViewport.java index 0c98f23,03e1a87..f29cf46 --- a/src/jalview/viewmodel/AlignmentViewport.java +++ b/src/jalview/viewmodel/AlignmentViewport.java @@@ -1006,45 -946,6 +1020,46 @@@ public abstract class AlignmentViewpor { return; } + List ssSources = viewStyle.getSecondaryStructureSources(); + if (secondaryStructureConsensus.size() != ssSources.size()) + { + + for (String source : ssSources) + { + boolean ssConsensusForSourcePresent = false; + for (AlignmentAnnotation aa : secondaryStructureConsensus) + { + if (aa.description.startsWith(source)) + { + ssConsensusForSourcePresent = true; + break; + } + } + + if (!ssConsensusForSourcePresent) + { ++ // i18n'ed data - this will break when moving jalview projects between places + AlignmentAnnotation ssConsensus = new AlignmentAnnotation( + MessageManager.getString("label.ssconsensus_label") + " " + + source, + source + " " + + MessageManager + .getString("label.ssconsensus_descr"), + new Annotation[1], 0f, 100f, + AlignmentAnnotation.BAR_GRAPH); + + ssConsensus.hasText = true; + ssConsensus.autoCalculated = true; + secondaryStructureConsensus.add(ssConsensus); + if (showSSConsensus) + { + ssConsensus.visible = true; + alignment.addAnnotation(ssConsensus); + + } + } + } + } if (calculator.getRegisteredWorkersOfClass( SecondaryStructureConsensusThread.class) == null) { @@@ -2150,31 -2083,9 +2198,34 @@@ consensus = new AlignmentAnnotation("Consensus", MessageManager.getString("label.consensus_descr"), new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH); + setSecondaryStructureSources(alignment.getAlignmentAnnotation()); + List secondaryStructureSources = getSecondaryStructureSources(); + ++ // merge cruft - should we also check ++ // if (!alignment.isNucleotide() && showSSConsensus) ++ + if (secondaryStructureSources != null) + { + + secondaryStructureConsensus = new ArrayList(); + for (String ssSource : secondaryStructureSources) + { + + AlignmentAnnotation ssConsensus = new AlignmentAnnotation( + MessageManager.getString("label.ssconsensus_label") + " " + + ssSource, + ssSource + " " + + MessageManager + .getString("label.ssconsensus_descr"), + new Annotation[1], 0f, 100f, + AlignmentAnnotation.BAR_GRAPH); + secondaryStructureConsensus.add(ssConsensus); + } + } initConsensus(consensus); + initSSConsensus(secondaryStructureConsensus); initGapCounts(); initComplementConsensus(); } @@@ -2231,23 -2142,21 +2282,27 @@@ } } - private void initSSConsensus() + private void initSSConsensus( + List secondaryStructureConsensuses) { - if (!alignment.isNucleotide() && showSSConsensus) + if (secondaryStructureConsensuses == null) { - if (secondaryStructureConsensus == null) - { - secondaryStructureConsensus = new AlignmentAnnotation( - MessageManager.getString("label.ssconsensus_label"), - MessageManager.getString("label.ssconsensus_descr"), - new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH); + return; + } ++// merge cruft - do we need ? ++ // if (!alignment.isNucleotide() && showSSConsensus) ++// { + - secondaryStructureConsensus.hasText = true; - secondaryStructureConsensus.autoCalculated = true; + for (AlignmentAnnotation aa : secondaryStructureConsensuses) + { + aa.hasText = true; + aa.autoCalculated = true; + + if (showSSConsensus) + { + alignment.addAnnotation(aa); } - alignment.addAnnotation(secondaryStructureConsensus); + } } diff --cc src/jalview/workers/SecondaryStructureConsensusThread.java index 13e22fd,5b046b6..044ba3e --- a/src/jalview/workers/SecondaryStructureConsensusThread.java +++ b/src/jalview/workers/SecondaryStructureConsensusThread.java @@@ -240,36 -179,14 +240,38 @@@ public class SecondaryStructureConsensu public void updateResultAnnotation(boolean immediate) { - AlignmentAnnotation ssConsensus = getSSConsensusAnnotation(); - ProfilesI hSSConsensus = (ProfilesI) getViewportSSConsensus(); - if (immediate || !calcMan.isWorking(this) && ssConsensus != null - && hSSConsensus != null) + List ssConsensuses = getSSConsensusAnnotation(); + Map ssConsensusProfileMap = getViewportSSConsensus(); + for (AlignmentAnnotation ssConsensus : ssConsensuses) { - deriveSSConsensus(ssConsensus, hSSConsensus); - - ssConsensus.hasData=hSSConsensus.getCount()>0; + ProfilesI ssConsensusProfile = null; + for (String source : ssConsensusProfileMap.keySet()) + { + if (ssConsensus.description.startsWith(source)) + { + ssConsensusProfile = ssConsensusProfileMap.get(source); + break; + } + } + if (ssConsensusProfile == null) + { + continue; + } + if (immediate || !calcMan.isWorking(this) && ssConsensus != null + && ssConsensusProfile != null) + { + if (ssConsensusProfile.get(0) != null) + ssConsensus.setNoOfSequencesIncluded( + ssConsensusProfile.get(0).getSeqWithSSCount()); + deriveSSConsensus(ssConsensus, ssConsensusProfile); ++ ssConsensus.hasData=ssConsensusProfile.getCount()>0; ++ + AlignmentAnnotation gap = getGapAnnotation(); + if (gap != null) + { + deriveGap(gap, ssConsensusProfile); + } + } } }