From: gmungoc Date: Thu, 6 Jun 2019 13:33:40 +0000 (+0100) Subject: Merge branch 'develop' into trialMerge X-Git-Tag: Release_2_11_1_0~55 X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=74393b51f368cb9f58589472d432a433d9c4386d;p=jalview.git Merge branch 'develop' into trialMerge Conflicts: src/jalview/datamodel/features/SequenceFeatures.java src/jalview/gui/FeatureSettings.java src/jalview/gui/Jalview2XML.java src/jalview/gui/SeqPanel.java src/jalview/project/Jalview2XML.java src/jalview/renderer/seqfeatures/FeatureRenderer.java src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java test/jalview/io/Jalview2xmlTests.java --- 74393b51f368cb9f58589472d432a433d9c4386d diff --cc src/jalview/datamodel/features/SequenceFeatures.java index 1120291,ba8396a..db2f0e1 --- a/src/jalview/datamodel/features/SequenceFeatures.java +++ b/src/jalview/datamodel/features/SequenceFeatures.java @@@ -26,8 -25,7 +25,6 @@@ import jalview.io.gff.SequenceOntologyF import jalview.io.gff.SequenceOntologyI; import java.util.ArrayList; - import java.util.Collections; - import java.util.Comparator; -import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Map; diff --cc src/jalview/gui/FeatureSettings.java index 47c0cc5,9ca409b..a5585ce --- a/src/jalview/gui/FeatureSettings.java +++ b/src/jalview/gui/FeatureSettings.java @@@ -20,12 -20,11 +20,13 @@@ */ package jalview.gui; +import jalview.api.AlignViewportI; import jalview.api.FeatureColourI; import jalview.api.FeatureSettingsControllerI; +import jalview.api.ViewStyleI; import jalview.datamodel.AlignmentI; import jalview.datamodel.SequenceI; + import jalview.datamodel.features.FeatureMatcher; import jalview.datamodel.features.FeatureMatcherI; import jalview.datamodel.features.FeatureMatcherSet; import jalview.datamodel.features.FeatureMatcherSetI; @@@ -389,8 -398,8 +409,6 @@@ public class FeatureSettings extends JP final Object typeCol, final Map minmax, int x, int y) { -- final FeatureColourI featureColour = (FeatureColourI) typeCol; -- JPopupMenu men = new JPopupMenu(MessageManager .formatMessage("label.settings_for_param", new String[] { type })); @@@ -1338,21 -1288,89 +1340,105 @@@ } /** + * Repaints alignment, structure and overview (if shown). If there is a + * complementary view which is showing this view's features, then also + * repaints that. + */ + void refreshDisplay() + { + af.alignPanel.paintAlignment(true, true); + AlignViewportI complement = af.getViewport().getCodingComplement(); + if (complement != null && complement.isShowComplementFeatures()) + { + AlignFrame af2 = Desktop.getAlignFrameFor(complement); + af2.alignPanel.paintAlignment(true, true); + } + } + ++ /** + * Answers a suitable tooltip to show on the colour cell of the table + * + * @param fcol + * @param withHint - * if true include 'click to edit' and similar text ++ * if true include 'click to edit' and similar text + * @return + */ + public static String getColorTooltip(FeatureColourI fcol, + boolean withHint) + { + if (fcol == null) + { + return null; + } + if (fcol.isSimpleColour()) + { + return withHint ? BASE_TOOLTIP : null; + } + String description = fcol.getDescription(); + description = description.replaceAll("<", "<"); + description = description.replaceAll(">", ">"); + StringBuilder tt = new StringBuilder(description); + if (withHint) + { + tt.append("
").append(BASE_TOOLTIP).append("
"); + } + return JvSwingUtils.wrapTooltip(true, tt.toString()); + } + + public static void renderGraduatedColor(JLabel comp, FeatureColourI gcol, + int w, int h) + { + boolean thr = false; + StringBuilder tx = new StringBuilder(); + + if (gcol.isColourByAttribute()) + { + tx.append(FeatureMatcher + .toAttributeDisplayName(gcol.getAttributeName())); + } + else if (!gcol.isColourByLabel()) + { + tx.append(MessageManager.getString("label.score")); + } + tx.append(" "); + if (gcol.isAboveThreshold()) + { + thr = true; + tx.append(">"); + } + if (gcol.isBelowThreshold()) + { + thr = true; + tx.append("<"); + } + if (gcol.isColourByLabel()) + { + if (thr) + { + tx.append(" "); + } + if (!gcol.isColourByAttribute()) + { + tx.append("Label"); + } + comp.setIcon(null); + } + else + { + Color newColor = gcol.getMaxColour(); + comp.setBackground(newColor); + // System.err.println("Width is " + w / 2); + Icon ficon = new FeatureIcon(gcol, comp.getBackground(), w, h, thr); + comp.setIcon(ficon); + // tt+="RGB value: Max (" + newColor.getRed() + ", " + // + newColor.getGreen() + ", " + newColor.getBlue() + // + ")\nMin (" + minCol.getRed() + ", " + minCol.getGreen() + // + ", " + minCol.getBlue() + ")"); + } + comp.setHorizontalAlignment(SwingConstants.CENTER); + comp.setText(tx.toString()); + } + // /////////////////////////////////////////////////////////////////////// // http://java.sun.com/docs/books/tutorial/uiswing/components/table.html // /////////////////////////////////////////////////////////////////////// diff --cc src/jalview/gui/FeatureTypeSettings.java index ceb38b0,7456e18..5b77dfc --- a/src/jalview/gui/FeatureTypeSettings.java +++ b/src/jalview/gui/FeatureTypeSettings.java @@@ -20,9 -20,9 +20,10 @@@ */ package jalview.gui; +import jalview.api.AlignViewportI; import jalview.api.AlignmentViewPanel; import jalview.api.FeatureColourI; + import jalview.bin.Cache; import jalview.datamodel.GraphLine; import jalview.datamodel.features.FeatureAttributes; import jalview.datamodel.features.FeatureAttributes.Datatype; diff --cc src/jalview/gui/SeqPanel.java index 55b8559,1176df5..bc17cc2 --- a/src/jalview/gui/SeqPanel.java +++ b/src/jalview/gui/SeqPanel.java @@@ -49,7 -49,7 +50,8 @@@ import jalview.util.MappingUtils import jalview.util.MessageManager; import jalview.util.Platform; import jalview.viewmodel.AlignmentViewport; + import jalview.viewmodel.ViewportRanges; +import jalview.viewmodel.seqfeatures.FeatureRendererModel; import java.awt.BorderLayout; import java.awt.Color; diff --cc src/jalview/project/Jalview2XML.java index 2ce6ea7,0d2ec68..ef885c1 --- a/src/jalview/project/Jalview2XML.java +++ b/src/jalview/project/Jalview2XML.java @@@ -58,7 -58,7 +58,6 @@@ import jalview.gui.AlignmentPanel import jalview.gui.AppVarna; import jalview.gui.ChimeraViewFrame; import jalview.gui.Desktop; - import jalview.gui.Jalview2XML_V1; -import jalview.gui.FeatureRenderer; import jalview.gui.JvOptionPane; import jalview.gui.OOMWarning; import jalview.gui.PCAPanel; diff --cc src/jalview/renderer/seqfeatures/FeatureRenderer.java index d580f2c,13885b4..a1980c7 --- a/src/jalview/renderer/seqfeatures/FeatureRenderer.java +++ b/src/jalview/renderer/seqfeatures/FeatureRenderer.java @@@ -22,14 -22,10 +22,14 @@@ package jalview.renderer.seqfeatures import jalview.api.AlignViewportI; import jalview.api.FeatureColourI; + import jalview.datamodel.ContiguousI; +import jalview.datamodel.MappedFeatures; - import jalview.datamodel.Range; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; +import jalview.gui.AlignFrame; +import jalview.gui.Desktop; import jalview.util.Comparison; +import jalview.util.ReverseListIterator; import jalview.viewmodel.seqfeatures.FeatureRendererModel; import java.awt.AlphaComposite; @@@ -276,9 -272,8 +276,9 @@@ public class FeatureRenderer extends Fe /* * if columns are all gapped, or sequence has no features, nothing to do */ - Range visiblePositions = seq.findPositions(start+1, end+1); - if (visiblePositions == null || (!seq.getFeatures().hasFeatures() - && !av.isShowComplementFeatures())) + ContiguousI visiblePositions = seq.findPositions(start + 1, end + 1); - if (visiblePositions == null || !seq.getFeatures().hasFeatures()) ++ if (visiblePositions == null || !seq.getFeatures().hasFeatures() ++ && !av.isShowComplementFeatures()) { return null; } @@@ -431,48 -407,6 +431,52 @@@ } /** + * Find any features on the CDS/protein complement of the sequence region and + * draw them, with visibility and colouring as configured in the complementary + * viewport + * + * @param g + * @param seq + * @param start + * @param end + * @param y1 + * @param colourOnly + * @param visiblePositions + * @param drawnColour + * @return + */ + Color drawComplementFeatures(final Graphics g, final SequenceI seq, + int start, int end, int y1, boolean colourOnly, - Range visiblePositions, Color drawnColour) ++ ContiguousI visiblePositions, Color drawnColour) + { + AlignViewportI comp = av.getCodingComplement(); + FeatureRenderer fr2 = Desktop.getAlignFrameFor(comp) + .getFeatureRenderer(); - for (int pos = visiblePositions.start; pos <= visiblePositions.end; pos++) ++ ++ final int visibleStart = visiblePositions.getBegin(); ++ final int visibleEnd = visiblePositions.getEnd(); ++ ++ for (int pos = visibleStart; pos <= visibleEnd; pos++) + { + int column = seq.findIndex(pos); + MappedFeatures mf = fr2 + .findComplementFeaturesAtResidue(seq, pos); + if (mf != null) + { + for (SequenceFeature sf : mf.features) + { + FeatureColourI fc = fr2.getFeatureStyle(sf.getType()); + Color featureColour = fr2.getColor(sf, fc); + renderFeature(g, seq, column - 1, column - 1, featureColour, + start, end, y1, colourOnly); + drawnColour = featureColour; + } + } + } + return drawnColour; + } + + /** * Called when alignment in associated view has new/modified features to * discover and display. * diff --cc src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java index f090190,17f9362..2a17bf2 --- a/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java +++ b/src/jalview/viewmodel/seqfeatures/FeatureRendererModel.java @@@ -1155,98 -1156,32 +1161,126 @@@ public abstract class FeatureRendererMo return filter == null ? true : filter.matches(sf); } + /** + * Answers a bean containing a mapping, and a list of features in this + * alignment at a position (or range) which is mappable from the given + * sequence residue position in a mapped alignment. Features are returned in + * render order of feature type (on top last), with order within feature type + * undefined. If no features or mapping are found, answers null. + * + * @param sequence + * @param pos + * @return + */ + public MappedFeatures findComplementFeaturesAtResidue(SequenceI sequence, + int pos) + { + SequenceI ds = sequence.getDatasetSequence(); + if (ds == null) + { + ds = sequence; + } + final char residue = ds.getCharAt(pos - ds.getStart()); + + List found = new ArrayList<>(); + List mappings = this.av.getAlignment() + .getCodonFrame(sequence); + + /* + * todo: direct lookup of CDS for peptide and vice-versa; for now, + * have to search through an unordered list of mappings for a candidate + */ + Mapping mapping = null; + SequenceI mapFrom = null; + + for (AlignedCodonFrame acf : mappings) + { + mapping = acf.getMappingForSequence(sequence, true); + if (mapping == null || mapping.getMap().getFromRatio() == mapping + .getMap().getToRatio()) + { + continue; // we are only looking for 3:1 or 1:3 mappings + } + SearchResultsI sr = new SearchResults(); + acf.markMappedRegion(ds, pos, sr); + for (SearchResultMatchI match : sr.getResults()) + { + int fromRes = match.getStart(); + int toRes = match.getEnd(); + mapFrom = match.getSequence(); + List fs = findFeaturesAtResidue( + match.getSequence(), fromRes, toRes); + for (SequenceFeature sf : fs) + { + if (!found.contains(sf)) + { + found.add(sf); + } + } + } + + /* + * just take the first mapped features we find + */ + if (!found.isEmpty()) + { + break; + } + } + if (found.isEmpty()) + { + return null; + } + + /* + * sort by renderorder, inefficiently + */ + List result = new ArrayList<>(); + for (String type : renderOrder) + { + for (SequenceFeature sf : found) + { + if (type.equals(sf.getType())) + { + result.add(sf); + if (result.size() == found.size()) + { + return new MappedFeatures(mapping, mapFrom, pos, residue, + result); + } + } + } + } + + return new MappedFeatures(mapping, mapFrom, pos, residue, result); + } + + @Override + public boolean isVisible(SequenceFeature feature) + { + if (feature == null) + { + return false; + } + if (getFeaturesDisplayed() == null + || !getFeaturesDisplayed().isVisible(feature.getType())) + { + return false; + } + if (featureGroupNotShown(feature)) + { + return false; + } + FeatureColourI fc = featureColours.get(feature.getType()); + if (fc != null && fc.isOutwithThreshold(feature)) + { + return false; + } + if (!featureMatchesFilters(feature)) + { + return false; + } + return true; + } + } diff --cc test/jalview/gui/FeatureSettingsTest.java index 195ca87,6d8a47e..fd4bd4b --- a/test/jalview/gui/FeatureSettingsTest.java +++ b/test/jalview/gui/FeatureSettingsTest.java @@@ -13,8 -13,8 +13,9 @@@ import jalview.datamodel.features.Featu import jalview.io.DataSourceType; import jalview.io.FileLoader; import jalview.schemes.FeatureColour; + import jalview.schemes.FeatureColourTest; import jalview.util.matcher.Condition; +import jalview.viewmodel.seqfeatures.FeatureRendererModel; import java.awt.Color; import java.io.File; diff --cc test/jalview/io/FeaturesFileTest.java index f244ac5,77c18db..6f7bebe --- a/test/jalview/io/FeaturesFileTest.java +++ b/test/jalview/io/FeaturesFileTest.java @@@ -525,13 -521,40 +521,40 @@@ public class FeaturesFileTes + "Pfam\tff0000\n" + "GAMMA-TURN\tscore|ff0000|00ffff|noValueMin|20.0|95.0|below|66.0\n" + "\nSTARTGROUP\tuniprot\n" - + "Turn\tFER_CAPAA\t-1\t36\t38\tGAMMA-TURN\t0.0\n" + "Iron\tFER_CAPAA\t-1\t39\t39\tMETAL\t0.0\n" + "Pfam domainPfam_3_4\tFER_CAPAA\t-1\t20\t20\tPfam\t0.0\n" + + "Turn\tFER_CAPAA\t-1\t36\t38\tGAMMA-TURN\t0.0\n" + "ENDGROUP\tuniprot\n" - // null / empty group features output after features in named - // groups: + // null / empty group features are output after named groups + + "\ndesc2\tFER_CAPAN\t-1\t4\t9\tPfam\n" + + "\ndesc4\tFER1_SOLLC\t-1\t5\t8\tPfam\t-2.6\n"; + assertEquals(expected, exported); + + /* + * hide uniprot group + */ + fr.setGroupVisibility("uniprot", false); + expected = "METAL\tcc9900\n" + "Pfam\tff0000\n" + + "GAMMA-TURN\tscore|ff0000|00ffff|noValueMin|20.0|95.0|below|66.0\n" + + "\ndesc2\tFER_CAPAN\t-1\t4\t9\tPfam\n" + + "\ndesc4\tFER1_SOLLC\t-1\t5\t8\tPfam\t-2.6\n"; + exported = featuresFile.printJalviewFormat(al.getSequencesArray(), fr, + false); + assertEquals(expected, exported); + + /* + * include non-positional (overrides group not shown) + */ + exported = featuresFile.printJalviewFormat(al.getSequencesArray(), fr, + true); + expected = "METAL\tcc9900\n" + "Pfam\tff0000\n" + + "GAMMA-TURN\tscore|ff0000|00ffff|noValueMin|20.0|95.0|below|66.0\n" + + "\nSTARTGROUP\tuniprot\n" + + "Cath\tFER_CAPAA\t-1\t0\t0\tDomain\t0.0\n" + + "ENDGROUP\tuniprot\n" + + "\ndesc1\tFER_CAPAN\t-1\t0\t0\tPfam\t1.3\n" + "desc2\tFER_CAPAN\t-1\t4\t9\tPfam\n" + + "\ndesc3\tFER1_SOLLC\t-1\t0\t0\tPfam\n" + "desc4\tFER1_SOLLC\t-1\t5\t8\tPfam\t-2.6\n"; assertEquals(expected, exported); }