diff --git a/src/main/java/org/igv/Globals.java b/src/main/java/org/igv/Globals.java index d183a11c5f..206fb622fb 100644 --- a/src/main/java/org/igv/Globals.java +++ b/src/main/java/org/igv/Globals.java @@ -4,6 +4,7 @@ import org.igv.logging.Logger; import javax.swing.*; +import java.awt.*; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.List; @@ -15,6 +16,8 @@ * Date: Feb 3, 2010 */ public class Globals { + public static final Color DULL_BLUE = new Color(0, 0, 200); + public static final Color DULL_RED = new Color(200, 0, 0); private static Logger log = LogManager.getLogger(Globals.class); public static final int DESIGN_DPI = 96; diff --git a/src/main/java/org/igv/bedpe/HicInteractionTrack.java b/src/main/java/org/igv/bedpe/HicInteractionTrack.java index a1dd205786..d4592a199c 100644 --- a/src/main/java/org/igv/bedpe/HicInteractionTrack.java +++ b/src/main/java/org/igv/bedpe/HicInteractionTrack.java @@ -2,7 +2,6 @@ import org.igv.hic.HicFile; import org.igv.renderer.ContinuousColorScale; -import org.igv.track.RenderContext; import org.igv.track.TrackClickEvent; import org.igv.ui.IGV; import org.igv.ui.panel.FrameManager; @@ -31,9 +30,9 @@ public HicInteractionTrack(ResourceLocator locator, HicSource source) { // HiC-specific defaults maxFeatureCount = 5000; graphType = GraphType.NESTED_ARC; - useScore = true; isHIC = true; - setColor(Color.red); + setUseScore(false); // Alpha score is set in the renderer based + setDefaultColor(Color.red); } @Override @@ -147,8 +146,6 @@ void addHICItems(TrackClickEvent te, IGVPopupMenu menu) { menu.add(mapItem); } - - @Override public void marshalXML(Document document, Element element) { super.marshalXML(document, element); diff --git a/src/main/java/org/igv/bedpe/InteractionTrack.java b/src/main/java/org/igv/bedpe/InteractionTrack.java index c10f441c8f..7ded67eb1e 100644 --- a/src/main/java/org/igv/bedpe/InteractionTrack.java +++ b/src/main/java/org/igv/bedpe/InteractionTrack.java @@ -71,13 +71,9 @@ enum ArcOption {ALL, ONE_END, BOTH_ENDS} double maxScore = -1; int gap = 5; boolean showBlocks = false; - protected boolean useScore = false; protected boolean isHIC = false; private Map renderers; - private Color defaultColor = new Color(180, 25, 137); - - ContactMapView contactMapView; float transparency = 1.0f; protected String normalization = "NONE"; @@ -99,6 +95,7 @@ public InteractionTrack(ResourceLocator locator, InteractionSource src) { this.featureSource = src; setHeight(250, true); + setDefaultColor( new Color(180, 25, 137)); renderers = new HashMap<>(); renderers.put(GraphType.NESTED_ARC, new NestedArcRenderer(this)); @@ -305,6 +302,13 @@ public IGVPopupMenu getPopupMenu(TrackClickEvent te) { item.addActionListener(evt -> TrackMenuUtils.changeTrackColor(Collections.singleton(InteractionTrack.this))); menu.add(item); + item = new JMenuItem("Unset Track Color"); + item.addActionListener(evt -> { + this.setColor(null); + repaint(); + }); + menu.add(item); + if (!isHIC) { menu.addSeparator(); menu.add(new JLabel("Graph Type")); diff --git a/src/main/java/org/igv/bedpe/NestedArcRenderer.java b/src/main/java/org/igv/bedpe/NestedArcRenderer.java index c3b2d38225..6fd4e707a9 100644 --- a/src/main/java/org/igv/bedpe/NestedArcRenderer.java +++ b/src/main/java/org/igv/bedpe/NestedArcRenderer.java @@ -42,7 +42,6 @@ public void render(List features, g = (Graphics2D) context.getGraphics().create(); double origin = context.getOrigin(); double locScale = context.getScale(); - Color trackColor = track.getColor() == null ? DEFAULT_TRACK_COLOR : track.getColor(); int gap = track.gap; if (track.thickness > 1) { @@ -100,12 +99,16 @@ public void render(List features, } - Color fcolor = feature.getColor() == null ? trackColor : feature.getColor(); - float alpha = track.transparency; - if (track.useScore) { - alpha = track.transparency * Math.min(1.0f, Math.max(0.1f, feature.getScore() / 1000f)); + Color fcolor = track.getFeatureColor(feature); + + if(track.isHIC) { + float alpha = track.transparency; + if (track.isUseScore()) { + alpha = track.transparency * Math.min(1.0f, Math.max(0.1f, feature.getScore() / 1000f)); + } + fcolor = getAlphaColor(fcolor, alpha); } - fcolor = getAlphaColor(fcolor, alpha); + g.setColor(fcolor); final int trackBaseLine = trackRectangle.y + trackRectangle.height; diff --git a/src/main/java/org/igv/feature/genome/load/GenomeLoader.java b/src/main/java/org/igv/feature/genome/load/GenomeLoader.java index 56d38b38e2..ac92ba02c4 100644 --- a/src/main/java/org/igv/feature/genome/load/GenomeLoader.java +++ b/src/main/java/org/igv/feature/genome/load/GenomeLoader.java @@ -83,8 +83,6 @@ public static FeatureTrack createGeneTrack(Genome genome, List featureList, boolean alternateExonColor = (track instanceof FeatureTrack && ((FeatureTrack) track).isAlternateExonColor()); - Color trackPosColor = track.getColor(); - Color trackNegColor = alternateExonColor ? track.getColor() : track.getAltColor(); String labelField = track.getLabelField(); for (IGVFeature feature : featureList) { @@ -176,7 +170,7 @@ public void render(List featureList, continue; } - Color color = getFeatureColor(feature, track, trackPosColor, trackNegColor); + Color color = ((AbstractTrack) track).getFeatureColor(feature); Graphics2D g2D = context.getGraphic2DForColor(color); // Draw block representing entire feature @@ -699,68 +693,6 @@ public String getDisplayName() { return "Basic Feature"; } - protected Color getFeatureColor(IGVFeature feature, Track track, Color defaultPosColor, Color defaultNegColor) { - - // Set color used to draw the feature - Color color = null; - - // If an alt color is explicitly set use it for negative strand features; - if (feature.getStrand() == Strand.NEGATIVE) { - color = track.getExplicitAltColor(); - } - - // If color is explicitly set use it - if (color == null) { - color = track.getExplicitColor(); - } - - // No explicitly set color, try the feature itself - if (color == null && track.isItemRGB()) { - color = feature.getColor(); - } - - // If still no color use defaults - if (color == null) { - if (track.getTrackType() == TrackType.CNV) { - color = feature.getName().equals("gain") ? DULL_RED : DULL_BLUE; - } else { - color = feature.getStrand() == Strand.NEGATIVE ? defaultNegColor : defaultPosColor; - } - } - - if (track.isUseScore()) { - float min = getViewLimitMin(track); - float max = getViewLimitMax(track); - - float score = feature.getScore(); - float alpha = Float.isNaN(score) ? 1 : getAlpha(min, max, feature.getScore()); - color = ColorUtilities.getCompositeColor(color, alpha); - } - - return color; - } - - float getViewLimitMin(Track track) { - if (Float.isNaN(viewLimitMin)) { - viewLimitMin = Float.isNaN(track.getViewLimitMin()) ? 0 : track.getViewLimitMin(); - } - return viewLimitMin; - } - - float getViewLimitMax(Track track) { - if (Float.isNaN(viewLimitMax)) { - viewLimitMax = Float.isNaN(track.getViewLimitMax()) ? 1000 : track.getViewLimitMax(); - } - return viewLimitMax; - } - - private float getAlpha(float minRange, float maxRange, float value) { - float binWidth = (maxRange - minRange) / 9; - int binNumber = (int) ((value - minRange) / binWidth); - return Math.min(1.0f, 0.2f + (binNumber * 0.8f) / 9); - } - - protected int getPixelFromChromosomeLocation(String chr, int chromosomeLocation, double origin, double locationScale) { return (int) Math.round((chromosomeLocation - origin) / locationScale); diff --git a/src/main/java/org/igv/renderer/SpliceJunctionRenderer.java b/src/main/java/org/igv/renderer/SpliceJunctionRenderer.java index b01843fd2a..ac6a00b1d2 100644 --- a/src/main/java/org/igv/renderer/SpliceJunctionRenderer.java +++ b/src/main/java/org/igv/renderer/SpliceJunctionRenderer.java @@ -142,7 +142,10 @@ protected void drawFeature(SpliceJunctionFeature junctionFeature, boolean should We modify the alpha value of the chosen color to indicate if it is highlighted */ final Color color; - final Color trackColor = isPositiveStrand ? track.getExplicitColor() : track.getExplicitAltColor(); + Color trackColor = isPositiveStrand ? track.getColor() : track.getAltColor(); + if(trackColor == null) { + trackColor = track.getDefaultColor(); + } if (trackColor != null) { color = adjustAlpha(trackColor, highlight); } else if (featureColor != null) { diff --git a/src/main/java/org/igv/sam/CoverageTrack.java b/src/main/java/org/igv/sam/CoverageTrack.java index 352d2ed09c..414017dcdd 100644 --- a/src/main/java/org/igv/sam/CoverageTrack.java +++ b/src/main/java/org/igv/sam/CoverageTrack.java @@ -107,14 +107,9 @@ public CoverageTrack(ResourceLocator locator, String name, AlignmentTrack alignm @Override public Color getColor() { - return _color == null ? + return color == null ? ColorUtilities.slightlyDarker(alignmentTrack.getColor()) : - _color; - } - - @Override - public void setColor(Color color) { - _color = color; + color; } @Override diff --git a/src/main/java/org/igv/seg/CNFreqTrack.java b/src/main/java/org/igv/seg/CNFreqTrack.java index c73981b802..0409513bba 100644 --- a/src/main/java/org/igv/seg/CNFreqTrack.java +++ b/src/main/java/org/igv/seg/CNFreqTrack.java @@ -49,7 +49,7 @@ public CNFreqTrack(ResourceLocator rl, String id, String name, FreqData fd) { float nSamples = data.getNumberOfSamples(); this.setDataRange(new DataRange(-nSamples, 0, nSamples)); - this.posColor = Color.red; + this.color = Color.red; this.altColor = Color.blue; renderer = new BarChartRenderer(); diff --git a/src/main/java/org/igv/track/AbstractTrack.java b/src/main/java/org/igv/track/AbstractTrack.java index 6b69a8f5de..12ceee9f1e 100644 --- a/src/main/java/org/igv/track/AbstractTrack.java +++ b/src/main/java/org/igv/track/AbstractTrack.java @@ -5,6 +5,8 @@ import org.igv.Globals; import org.igv.event.IGVEventBus; import org.igv.event.IGVEventObserver; +import org.igv.feature.IGVFeature; +import org.igv.feature.Strand; import org.igv.logging.LogManager; import org.igv.logging.Logger; import org.igv.prefs.Constants; @@ -46,7 +48,6 @@ public abstract class AbstractTrack implements Track { public static final boolean DEFAULT_SHOW_FEATURE_NAMES = true; protected final boolean darkMode; - private Color defaultColor; private ResourceLocator resourceLocator; private String id; private String sampleId; @@ -57,8 +58,8 @@ public abstract class AbstractTrack implements Track { private boolean useScore; protected boolean autoScale = true; // By default, can be overriden by track line - private float viewLimitMin = Float.NaN; // From UCSC track line - private float viewLimitMax = Float.NaN; // From UCSC track line + private float viewLimitMin = 0; // From UCSC track line + private float viewLimitMax = 1000; // From UCSC track line protected int fontSize; private boolean showDataRange = true; @@ -80,7 +81,8 @@ public abstract class AbstractTrack implements Track { String autoscaleGroup; - protected Color posColor = null; + protected Color defaultColor; + protected Color color = null; protected Color altColor = null; protected int visibilityWindow = VISIBILITY_WINDOW; @@ -90,6 +92,7 @@ public abstract class AbstractTrack implements Track { protected DataRange dataRange; private boolean showFeatureNames = DEFAULT_SHOW_FEATURE_NAMES; + private String trackLine = null; public AbstractTrack() { this.darkMode = Globals.isDarkMode(); @@ -248,21 +251,31 @@ private Rectangle getDisplayableRect(Rectangle trackRectangle, Rectangle visible public void overlay(RenderContext context, Rectangle rect) { } + @Override + public void setColor(Color color) { + this.color = color; + } public Color getColor() { - return posColor == null ? defaultColor : posColor; + return color; } - public Color getExplicitColor() { - return posColor; + @Override + public void setAltColor(Color color) { + altColor = color; } public Color getAltColor() { return altColor == null ? getColor() : altColor; } - public Color getExplicitAltColor() { - return altColor; + public void setDefaultColor(Color color) { + this.defaultColor = color; + } + + @Override + public Color getDefaultColor() { + return defaultColor; } public ResourceLocator getResourceLocator() { @@ -428,14 +441,6 @@ public boolean isVisible() { return visible; } - public void setColor(Color color) { - this.posColor = color; - } - - public void setAltColor(Color color) { - altColor = color; - } - public void setVisible(boolean visible) { if (this.visible != visible) { this.visible = visible; @@ -575,9 +580,12 @@ public void setProperties(TrackProperties properties) { // The viewLimit properties com from UCSC track lines and control "useScore" shading. They // are somewhat redundant with dataRange, but we keep both for now to avoid breaking existing behavior. - this.viewLimitMin = properties.getMinValue() != null ? properties.getMinValue() : Float.NaN; - this.viewLimitMax = properties.getMaxValue() != null ? properties.getMaxValue() : Float.NaN; - + if (properties.getMinValue() != null) { + this.viewLimitMin = properties.getMinValue(); + } + if (properties.getMaxValue() != null) { + this.viewLimitMax = properties.getMaxValue(); + } if (properties.getMaxValue() != null) { @@ -660,6 +668,10 @@ public void setProperties(TrackProperties properties) { if (as != null) { this.autoScale = as; } + + if (properties.getFeatureVisibilityWindow() >= 0) { + setVisibilityWindow(properties.getFeatureVisibilityWindow()); + } } /** @@ -733,14 +745,6 @@ public boolean isUseScore() { return useScore; } - public float getViewLimitMin() { - return viewLimitMin; - } - - public float getViewLimitMax() { - return viewLimitMax; - } - public int getFontSize() { return fontSize; } @@ -949,6 +953,20 @@ public boolean isShowFeatureNames() { return showFeatureNames; } + @Override + public void setTrackLine(String trackLine) { + this.trackLine = trackLine; + } + + /** + * Return "track" line information for exporting features to a file. Default is null, subclasses may override. + * + * @return + */ + public String getExportTrackLine() { + return trackLine; + } + /** * Restore track from XML serialization -- work in progress * // @@ -968,38 +986,31 @@ public void marshalXML(Document document, Element element) { if (showFeatureNames != DEFAULT_SHOW_FEATURE_NAMES) { element.setAttribute("showFeatureNames", Boolean.toString(showFeatureNames)); } - if (posColor != null) { - element.setAttribute(SessionAttribute.COLOR, ColorUtilities.colorToString(posColor)); + if (color != null) { + element.setAttribute(SessionAttribute.COLOR, ColorUtilities.colorToString(color)); } if (altColor != null) { element.setAttribute(SessionAttribute.ALT_COLOR, ColorUtilities.colorToString(altColor)); } - if (visibilityWindow != VISIBILITY_WINDOW) { element.setAttribute("featureVisibilityWindow", String.valueOf(visibilityWindow)); } - if (displayMode != DEFAULT_DISPLAY_MODE) { element.setAttribute(SessionAttribute.DISPLAY_MODE, displayMode.toString()); } - if (height != DEFAULT_HEIGHT) { element.setAttribute(SessionAttribute.HEIGHT, height.toString()); } - if (colorScale != null) { //colorScale="ContinuousColorScale;-0.1;-1.5;0.1;1.5;0,153,204;255,255,255;255,0,0" element.setAttribute("colorScale", colorScale.asString()); } - if (height != DEFAULT_HEIGHT) { element.setAttribute("height", String.valueOf(this.height)); } - if (showDataRange == false) { element.setAttribute("showDataRange", Boolean.toString(showDataRange)); } - if (isNumeric()) { if (autoscaleGroup != null) { element.setAttribute("autoscaleGroup", this.autoscaleGroup); @@ -1044,7 +1055,7 @@ public void unmarshalXML(Element element, Integer version) { if (element.hasAttribute("color")) { try { Color c = ColorUtilities.stringToColor(element.getAttribute("color")); - this.posColor = c; + this.color = c; } catch (Exception e) { log.error("Unrecognized color: " + element.getAttribute("color")); } @@ -1166,4 +1177,47 @@ public String getSampleId() { return sampleId; } + public Color getFeatureColor(IGVFeature feature) { + + // Set color used to draw the feature + Color featureColor = null; + + // If an alt color is explicitly set use it for negative strand features; + if (feature.getStrand() == Strand.NEGATIVE) { + featureColor = getAltColor(); + } + + // If color is explicitly set use it + if (featureColor == null) { + featureColor = getColor(); + } + + // No explicitly set color, try the feature itself + if (featureColor == null) { + featureColor = feature.getColor(); + } + + // If still no color use defaults + if (featureColor == null) { + if (getTrackType() == TrackType.CNV) { + featureColor = feature.getName().equals("gain") ? Globals.DULL_RED : Globals.DULL_BLUE; + } else { + featureColor = getDefaultColor(); + } + } + + if (useScore) { + float score = feature.getScore(); + float alpha = 1; + if (!Float.isNaN(score)) { + float binWidth = (viewLimitMax - viewLimitMin) / 9; + int binNumber = (int) ((score - viewLimitMin) / binWidth); + alpha = Math.min(1.0f, 0.2f + (binNumber * 0.8f) / 9); + } + featureColor = ColorUtilities.getCompositeColor(featureColor, alpha); + } + + return featureColor; + } + } diff --git a/src/main/java/org/igv/track/FeatureTrack.java b/src/main/java/org/igv/track/FeatureTrack.java index 62a1e69feb..7a9114f2b6 100644 --- a/src/main/java/org/igv/track/FeatureTrack.java +++ b/src/main/java/org/igv/track/FeatureTrack.java @@ -18,7 +18,6 @@ import org.igv.renderer.*; import org.igv.tools.motiffinder.MotifFinderSource; import org.igv.ui.IGV; -import org.igv.ui.UIConstants; import org.igv.ui.panel.ReferenceFrame; import org.igv.ui.util.MessageUtils; import org.igv.util.BrowserLauncher; @@ -89,8 +88,6 @@ public class FeatureTrack extends AbstractTrack implements IGVEventObserver { private boolean alternateExonColor = false; - private String trackLine = null; - private boolean groupByStrand = false; private String labelField; @@ -971,21 +968,6 @@ public List getVisibleFeatures(ReferenceFrame frame) { } - @Override - public void setTrackLine(String trackLine) { - this.trackLine = trackLine; - } - - /** - * Return "track" line information for exporting features to a file. Default is null, subclasses may override. - * - * @return - */ - public String getExportTrackLine() { - return trackLine; - } - - public void setGroupByStrand(boolean selected) { this.groupByStrand = selected; for (PackedFeatures pf : packedFeaturesMap.values()) { diff --git a/src/main/java/org/igv/track/GisticTrack.java b/src/main/java/org/igv/track/GisticTrack.java index 06c92d3b84..a7c78aa70b 100644 --- a/src/main/java/org/igv/track/GisticTrack.java +++ b/src/main/java/org/igv/track/GisticTrack.java @@ -137,54 +137,6 @@ public List getDelScores(String chr) { return delScoreMap.get(chr); } - /** - * Return the score with the maximum "G Score" over the specified region. - * Assumes the scores are sorted by location - * - * @param chr - * @param start - * @param end - * @return - */ - public GisticScore getMaxForRegion(String chr, long start, long end) { - - List scores = ampScoreMap.get(chr); - if ((scores == null) || scores.isEmpty()) { - return null; - } - - GisticScore maxScore = null; - for (GisticScore score : scores) { - if (maxScore == null) { - if ((score.getStart() >= start) - || ((start >= score.getStart()) && (start <= score.getEnd()))) { - maxScore = score; - } - } else if (score.getStart() > end) { - break; - } else { - if (score.getGScore() > maxScore.getGScore()) { - maxScore = score; - } - } - } - - // If we haven't found bounding scores yet the region is to the right off the last - // score. Use the last score for the region. This should be a rare case and should - // probably be logged. - return (maxScore == null) ? ((GisticScore) scores.get(scores.size() - 1)) : maxScore; - - } - - /** - * Method description - * - * @return - */ - public double getMaxQValue() { - return maxQValue; - } - /** * Method description * @@ -242,15 +194,6 @@ public WindowFunction getWindowFunction() { return WindowFunction.median; } - /** - * Method description - * - * @param chr - * @return - */ - public double getMedian(String chr) { - return 1.0; - } /** * Method description @@ -273,32 +216,6 @@ public List getFeatures(String chr, int startLocation, int endLocati return null; } - /** - * This method is required for the interface, but will not be called. - * - * @param chr - * @param startLocation - * @param endLocation - * @param zoom - * @return - */ - public List getSummaryScores(String chr, int startLocation, int endLocation, - int zoom) { - - List ss = new ArrayList(); - List ampScores = ampScoreMap.get(chr); - if (ampScores != null) { - ss.addAll(ampScores); - } - List delScores = delScoreMap.get(chr); - if (delScores != null) { - ss.addAll(delScores); - } - return ss; - - // return getFeatures(chr, startLocation, endLocation); - } - /** * This method is required for the interface, but will not be called. * @@ -357,67 +274,9 @@ public String getValueStringAt(String chr, double position, int mouseX, int igno } } - /** - * Method description - * - * @param chr - * @param startLocation - * @param endLocation - * @return - */ - public List> getFeaturesByLevels(String chr, int startLocation, int endLocation) { - throw new UnsupportedOperationException("Not supported yet."); - } - - /** - * Method description - * - * @return - */ - public int getNumberOfFeatureLevels() { - return 1; - } - - /** - * Method description - * - * @param isMultiLevel - */ - public void setMultiLevelFeatures(boolean isMultiLevel) { - - // ignore - } - - /** - * Method description - * - * @return - */ - public boolean isMuliLevelFeatures() { - throw new UnsupportedOperationException("Not supported yet."); - } - - - public Color getColor() { - return null; - } - - public void setColor(Color color) { - // Not used - } - - public Color getAltColor() { - return null; - } - - public void setAltColor(Color color) { - // Not used - } - // GisticTrack does not expose its renderer public Renderer getRenderer() { return null; } - } diff --git a/src/main/java/org/igv/track/Track.java b/src/main/java/org/igv/track/Track.java index d2490a85ba..5b2a103068 100644 --- a/src/main/java/org/igv/track/Track.java +++ b/src/main/java/org/igv/track/Track.java @@ -3,6 +3,7 @@ import htsjdk.tribble.Feature; import htsjdk.tribble.NamedFeature; +import org.igv.Globals; import org.igv.renderer.ContinuousColorScale; import org.igv.renderer.DataRange; import org.igv.renderer.Renderer; @@ -202,18 +203,14 @@ default boolean isAlignment() { Color getColor(); - default Color getExplicitColor() { - return null; + default Color getDefaultColor() { + return Globals.isDarkMode() ? Color.cyan : Color.blue.brighter(); } void setColor(Color color); Color getAltColor(); - default Color getExplicitAltColor() { - return null; - } - void setAltColor(Color color); void setWindowFunction(WindowFunction type); @@ -266,10 +263,6 @@ default Color getExplicitAltColor() { boolean isUseScore(); - float getViewLimitMin(); - - float getViewLimitMax(); - DisplayMode getDisplayMode(); void setDisplayMode(DisplayMode mode); diff --git a/src/main/java/org/igv/track/TrackMenuUtils.java b/src/main/java/org/igv/track/TrackMenuUtils.java index 99fe00b831..82060e07a3 100644 --- a/src/main/java/org/igv/track/TrackMenuUtils.java +++ b/src/main/java/org/igv/track/TrackMenuUtils.java @@ -659,18 +659,28 @@ public static void addSharedItems(JPopupMenu menu, final Collection track menu.add(getTrackRenameItem(tracks)); - String colorLabel = "Change Track Color..."; + String colorLabel = "Set Track Color..."; JMenuItem item = new JMenuItem(colorLabel); item.addActionListener(evt -> changeTrackColor(tracks)); menu.add(item); // Change track color by attribute - item = new JMenuItem("Change Track Color (Negative Values or Strand)..."); + item = new JMenuItem("Set Track Color (Negative Values or Strand)..."); item.setToolTipText( "Change the alternate track color. This color is used when drawing features with negative values or on the negative strand."); item.addActionListener(evt -> changeAltTrackColor(tracks)); menu.add(item); + item = new JMenuItem("Unset Track Color"); + item.setToolTipText("Revert track color to default."); + item.addActionListener(evt -> { + tracks.forEach(track -> track.setColor(null)); + IGV.getInstance().repaint(tracks); + }); + // Enable only if at least one track has a non-null color + item.setEnabled(tracks.stream().anyMatch(track -> track.getColor() != null)); + menu.add(item); + menu.add(getChangeTrackHeightItem(tracks)); menu.add(getChangeFontSizeItem(tracks)); } @@ -1132,7 +1142,8 @@ public static void changeTrackColor(final Collection selectedTracks) { for (Track track : selectedTracks) { //We preserve the alpha value. This is motivated by MergedTracks - track.setColor(ColorUtilities.modifyAlpha(color, currentSelection.getAlpha())); + int currentAlpha = currentSelection != null ? currentSelection.getAlpha() : 255; + track.setColor(ColorUtilities.modifyAlpha(color, currentAlpha)); } IGV.getInstance().repaint(selectedTracks); } diff --git a/src/main/java/org/igv/util/ParsingUtils.java b/src/main/java/org/igv/util/ParsingUtils.java index 9df2b0aa0c..1aedb5f0cb 100644 --- a/src/main/java/org/igv/util/ParsingUtils.java +++ b/src/main/java/org/igv/util/ParsingUtils.java @@ -3,8 +3,9 @@ import htsjdk.samtools.util.ftp.FTPClient; import htsjdk.samtools.util.ftp.FTPReply; import htsjdk.tribble.readers.AsciiLineReader; -import org.igv.logging.*; import org.igv.Globals; +import org.igv.logging.LogManager; +import org.igv.logging.Logger; import org.igv.renderer.*; import org.igv.track.Track; import org.igv.track.TrackProperties; @@ -372,20 +373,18 @@ public static boolean parseTrackLine(String nextLine, TrackProperties trackPrope String key = kv.get(0).toLowerCase().trim(); String value = kv.get(1).replaceAll("\"", ""); - if(key.equals("format")) { + if (key.equals("format")) { trackProperties.setFormat(value.toLowerCase()); - } else if(key.equals("type")) { + } else if (key.equals("type")) { trackProperties.setType(value.toLowerCase()); - } - else if (key.equals("coords")) { + } else if (key.equals("coords")) { if (value.equals("0")) { trackProperties.setBaseCoord(TrackProperties.BaseCoord.ZERO); } else if (value.equals("1")) { trackProperties.setBaseCoord(TrackProperties.BaseCoord.ONE); } - } - else if (key.equals("name")) { + } else if (key.equals("name")) { trackProperties.setName(value); //dhmay adding name check for TopHat junctions files. graphType is also checked. if (value.equals("junctions")) { @@ -397,7 +396,7 @@ else if (key.equals("name")) { } else { final String valueLowerCase = value.toLowerCase(); if (key.equals("itemrgb")) { - trackProperties.setItemRGB(valueLowerCase.equals("on") || value.equals("1")); + trackProperties.setItemRGB(!(valueLowerCase.equals("off") || value.equals("0"))); // Any value other than 0 or off => on } else if (key.equals("usescore")) { trackProperties.setUseScore(value.equals("1")); } else if (key.equals("color")) { @@ -409,6 +408,13 @@ else if (key.equals("name")) { } else if (key.equals("midcolor")) { Color color = ColorUtilities.stringToColor(value); trackProperties.setMidColor(color); + } else if (key.equals("colorByStrand")) { + //Sets colors for + and - strands, in that order. The colors consist of three comma-separated RGB values from 0-255 each. + String[] colors = value.split(" "); + if (colors.length == 2) { + trackProperties.setColor(ColorUtilities.stringToColor(colors[0])); + trackProperties.setAltColor(ColorUtilities.stringToColor(colors[1])); + } } else if (key.equals("autoscale")) { boolean autoscale = value.equals("on"); trackProperties.setAutoScale(autoscale); @@ -603,7 +609,7 @@ public GZIPSafeBufferedStream(InputStream in) { @Override public int read(byte[] b, int off, int len) throws IOException { int ret = super.read(b, off, len); - if(available() == 0) { + if (available() == 0) { mark(26); read(); reset(); @@ -612,5 +618,4 @@ public int read(byte[] b, int off, int len) throws IOException { } - } \ No newline at end of file