diff -Nru igv-2.3.88+dfsg/debian/changelog igv-2.3.90+dfsg/debian/changelog --- igv-2.3.88+dfsg/debian/changelog 2016-12-13 11:18:16.000000000 +0000 +++ igv-2.3.90+dfsg/debian/changelog 2017-01-14 08:41:54.000000000 +0000 @@ -1,3 +1,10 @@ +igv (2.3.90+dfsg-1) unstable; urgency=medium + + * Team upload. + * New upstream version. + + -- Sascha Steinbiss Sat, 14 Jan 2017 08:41:54 +0000 + igv (2.3.88+dfsg-1) unstable; urgency=medium * New upstream version diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/batch/CommandExecutor.java igv-2.3.90+dfsg/src/org/broad/igv/batch/CommandExecutor.java --- igv-2.3.88+dfsg/src/org/broad/igv/batch/CommandExecutor.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/batch/CommandExecutor.java 2017-01-09 04:30:59.000000000 +0000 @@ -467,6 +467,7 @@ log.debug("Run load files"); + List files = StringUtils.breakQuotedString(fileString, ','); List names = StringUtils.breakQuotedString(nameString, ','); List indexFiles = StringUtils.breakQuotedString(indexString, ','); diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/batch/CommandListener.java igv-2.3.90+dfsg/src/org/broad/igv/batch/CommandListener.java --- igv-2.3.88+dfsg/src/org/broad/igv/batch/CommandListener.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/batch/CommandListener.java 2017-01-09 04:30:59.000000000 +0000 @@ -360,7 +360,7 @@ String sortTag = params.get("sortTag"); result = cmdExe.loadFiles(file, index, coverage, name, format, locus, merge, params, sort, sortTag); } else { - return ("ERROR Parameter \"file\" is required"); + result = "OK"; // No files, perhaps genome only } } else if (command.equals("/reload") || command.equals("/goto")) { String locus = params.get("locus"); diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/data/expression/ProbeToLocusMap.java igv-2.3.90+dfsg/src/org/broad/igv/data/expression/ProbeToLocusMap.java --- igv-2.3.88+dfsg/src/org/broad/igv/data/expression/ProbeToLocusMap.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/data/expression/ProbeToLocusMap.java 2017-01-09 04:30:59.000000000 +0000 @@ -54,7 +54,7 @@ enum Platform {Affymetrix, Agilient, Illumina, Methylation, Mirna, unknown} - public static final String SERVER_URL = "http://data.broadinstitute.org"; + public static final String SERVER_URL = "https://data.broadinstitute.org"; private static Logger log = Logger.getLogger(ProbeToLocusMap.class); private static String affyGenesMappingURL = diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/feature/AminoAcidManager.java igv-2.3.90+dfsg/src/org/broad/igv/feature/AminoAcidManager.java --- igv-2.3.88+dfsg/src/org/broad/igv/feature/AminoAcidManager.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/feature/AminoAcidManager.java 2017-01-09 04:30:59.000000000 +0000 @@ -174,6 +174,7 @@ * @param sequence * @return */ + List getAminoAcids(Strand direction, String sequence) { // Sequence must be divisible by 3. It is the responsibility of the @@ -184,7 +185,7 @@ for (int i = 0; i <= sequence.length() - 3; i += 3) { String codon = sequence.substring(i, i + 3).toUpperCase(); if (direction == Strand.NEGATIVE) { - codon = getNucleotideComplement(codon); + codon = getReverseComplement(codon); } AminoAcid aa = currentCodonTable.getAminoAcid(codon); acids.add(aa); @@ -210,9 +211,14 @@ if (seqBytes == null) { return null; } else { + + int l = seqBytes.length; + int rem = l % 3; + int aaStart = strand == Strand.POSITIVE ? 0 : rem; + String nucSequence = new String(seqBytes); List acids = getAminoAcids(strand, nucSequence); - return new AminoAcidSequence(strand, startPosition, acids, currentCodonTable.getKey()); + return new AminoAcidSequence(strand, startPosition + aaStart, acids, currentCodonTable.getKey()); } } @@ -255,7 +261,7 @@ return aa; } - public static String getNucleotideComplement(String sequence) { + public static String getReverseComplement(String sequence) { char[] complement = new char[sequence.length()]; int jj = complement.length; for (int ii = 0; ii < sequence.length(); ii++) { @@ -263,21 +269,29 @@ jj--; switch (c) { case 'T': - case 't': complement[jj] = 'A'; break; case 'A': - case 'a': complement[jj] = 'T'; break; case 'C': - case 'c': complement[jj] = 'G'; break; case 'G': - case 'g': complement[jj] = 'C'; break; + case 't': + complement[jj] = 'a'; + break; + case 'a': + complement[jj] = 't'; + break; + case 'c': + complement[jj] = 'g'; + break; + case 'g': + complement[jj] = 'c'; + break; default: complement[jj] = c; } diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/feature/basepair/BasePairFeature.java igv-2.3.90+dfsg/src/org/broad/igv/feature/basepair/BasePairFeature.java --- igv-2.3.88+dfsg/src/org/broad/igv/feature/basepair/BasePairFeature.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/feature/basepair/BasePairFeature.java 2017-01-09 04:30:59.000000000 +0000 @@ -70,4 +70,23 @@ public int getEnd() { return endRight; } + + public int getStartLeft() { return startLeft; } + + public int getStartRight() { return startRight; } + + public int getEndLeft() { return endLeft; } + + public int getEndRight() { return endRight; } + + public Color getColor() { return color; } + + + public String toStringNoColor() { + return getChr() + "\t" + startLeft + "\t" + startRight + "\t" + endLeft + "\t" + endRight; + } + + public String toString() { + return toStringNoColor() + "\t" + color; + } } diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/feature/basepair/BasePairFileParser.java igv-2.3.90+dfsg/src/org/broad/igv/feature/basepair/BasePairFileParser.java --- igv-2.3.88+dfsg/src/org/broad/igv/feature/basepair/BasePairFileParser.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/feature/basepair/BasePairFileParser.java 2017-01-09 04:30:59.000000000 +0000 @@ -17,9 +17,7 @@ static Logger log = Logger.getLogger(BasePairFileParser.class); - BasePairTrack track; - - public BasePairTrack loadTrack(ResourceLocator locator, Genome genome) { + public static BasePairData loadData(ResourceLocator locator, Genome genome) { AsciiLineReader reader = null; List colors = new ArrayList(); @@ -34,37 +32,35 @@ // read lines specifying arc colors nextLine = reader.readLine(); rowCounter++; - while (nextLine.substring(0,6).equals("color:")){ - String[] tokens = Globals.tabPattern.split(nextLine, -1); + while (nextLine.substring(0, 6).equals("color:")) { + String[] tokens = Globals.whitespacePattern.split(nextLine, -1); int r = Integer.parseInt(tokens[1]); int g = Integer.parseInt(tokens[2]); int b = Integer.parseInt(tokens[3]); - Color color = new Color(r,g,b,255); + Color color = new Color(r, g, b, 255); colors.add(color); nextLine = reader.readLine(); rowCounter++; } - for (Color color : colors){ + for (Color color : colors) { rowsByColor.put(color, new ArrayList()); } while (nextLine != null) { - String[] tokens = Globals.tabPattern.split(nextLine, -1); - - int nTokens = tokens.length; + String[] tokens = Globals.whitespacePattern.split(nextLine, -1); String chr = (genome == null ? tokens[0] : genome.getCanonicalChrName(tokens[0])); // TODO Future use - int startLeftNuc = Integer.parseInt(tokens[1])-1; // stick to IGV's 0-based coordinate convention - int startRightNuc = Integer.parseInt(tokens[2])-1; - int endLeftNuc = Integer.parseInt(tokens[3])-1; - int endRightNuc = Integer.parseInt(tokens[4])-1; + int startLeftNuc = Integer.parseInt(tokens[1]) - 1; // stick to IGV's 0-based coordinate convention + int startRightNuc = Integer.parseInt(tokens[2]) - 1; + int endLeftNuc = Integer.parseInt(tokens[3]) - 1; + int endRightNuc = Integer.parseInt(tokens[4]) - 1; Color color = colors.get(Integer.parseInt(tokens[5])); BasePairFeature feature; - if (startLeftNuc <= endRightNuc){ + if (startLeftNuc <= endRightNuc) { feature = new BasePairFeature(chr, Math.min(startLeftNuc, startRightNuc), Math.max(startLeftNuc, startRightNuc), @@ -87,7 +83,7 @@ } - basePairData.finish(); // Insure features are sorted by start position, important for rendering optimization + basePairData.finish(); // ensure features are sorted by start position, important for rendering optimization } catch (Exception e) { log.error("Error parsing base pair file", e); @@ -106,8 +102,7 @@ // System.out.println(row); //} - track = new BasePairTrack(basePairData, locator.getTrackName()); - return track; + return basePairData; } -} \ No newline at end of file +} diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/feature/basepair/BasePairRenderer.java igv-2.3.90+dfsg/src/org/broad/igv/feature/basepair/BasePairRenderer.java --- igv-2.3.88+dfsg/src/org/broad/igv/feature/basepair/BasePairRenderer.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/feature/basepair/BasePairRenderer.java 2017-01-09 04:30:59.000000000 +0000 @@ -12,6 +12,7 @@ import java.awt.geom.GeneralPath; // TODO: add vertical scaling option so arcs fit on track, or clip arcs outside of track rect? +// TODO: add visualization for very zoomed-out views public class BasePairRenderer { @@ -44,7 +45,7 @@ int end = (int) (origin + trackRectangle.width * nucsPerPixel) + 1; if (end <= start) return; - // TODO: should make this a function (ugh no multiple value return from java functions) + // TODO: make this a function java.util.List featureList = data.getFeatures(context.getChr()); @@ -57,8 +58,6 @@ //System.out.println("Color: "+data.colors[i]); int arcCount = 0; - // TODO: only render arcs whose interior overlaps the viewing area - i.e. if an arc starts left of the window and ends right of the window, should still render - //System.out.println("In arcRenderer.draw(): "); //System.out.println(" track.width = " + trackRectangle.width); @@ -103,9 +102,10 @@ /** * Draw a filled arc between two regions of equal length * - * @param startLeft the starting position of the feature, whether on-screen or not - * @param endLeft the ending position of the feature, whether on-screen or not - * @param pixelWidth the width of the arc in pixels + * @param startLeft the starting position of the feature, whether on-screen or not (outer left corner of arc) + * @param startRight (inner left corner of arc) + * @param endLeft the ending position of the feature, whether on-screen or not (inner right corner of arc) + * @param endRight (outer right corner of arc) * @param trackRectangle * @param context * @param featureColor the color specified for this feature. May be null. @@ -239,4 +239,4 @@ g2D.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_DEFAULT); g2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_DEFAULT); } -} \ No newline at end of file +} diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/feature/basepair/BasePairTrack.java igv-2.3.90+dfsg/src/org/broad/igv/feature/basepair/BasePairTrack.java --- igv-2.3.88+dfsg/src/org/broad/igv/feature/basepair/BasePairTrack.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/feature/basepair/BasePairTrack.java 2017-01-09 04:30:59.000000000 +0000 @@ -1,9 +1,11 @@ package org.broad.igv.feature.basepair; import org.apache.log4j.Logger; +import org.broad.igv.feature.genome.*; import org.broad.igv.renderer.*; import org.broad.igv.track.AbstractTrack; import org.broad.igv.track.RenderContext; +import org.broad.igv.util.ResourceLocator; import java.awt.*; @@ -19,9 +21,9 @@ private BasePairRenderer basePairRenderer = new BasePairRenderer(); private BasePairData basePairData; - public BasePairTrack(BasePairData data, String name) { - super(name); - basePairData = data; + public BasePairTrack(ResourceLocator locator, String id, String name, Genome genome) { + super(locator, id, name); + basePairData = BasePairFileParser.loadData(locator, genome); } public void render(RenderContext context, Rectangle rect) { diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/feature/BasePairFileUtils.java igv-2.3.90+dfsg/src/org/broad/igv/feature/BasePairFileUtils.java --- igv-2.3.88+dfsg/src/org/broad/igv/feature/BasePairFileUtils.java 1970-01-01 00:00:00.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/feature/BasePairFileUtils.java 2017-01-09 04:30:59.000000000 +0000 @@ -0,0 +1,444 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2007-2015 Broad Institute + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.broad.igv.feature; + + +import org.broad.igv.feature.basepair.BasePairFeature; +import org.broad.igv.Globals; +import org.broad.igv.util.Utilities; + + +import java.awt.Color; +import java.awt.Point; +import java.io.*; +import java.util.*; + + +// multiple return from loadDotBracket() and loadConnectTable() +class SeqLenAndPairs { + public int seqLen; + public ArrayList pairs; + + public SeqLenAndPairs(int seqLen, ArrayList pairs) { + this.seqLen = seqLen; + this.pairs = pairs; + } +} + +// multiple return from loadPairingProb() +class SeqLenAndBinnedPairs { + public int seqLen; + public ArrayList> binnedPairs; + + public SeqLenAndBinnedPairs(int seqLen, ArrayList> binnedPairs) { + this.seqLen = seqLen; + this.binnedPairs = binnedPairs; + } +} + + +/** + * @author sbusan + */ +public class BasePairFileUtils { + + // TODO: support bpseq, stockholm, other formats? + // TODO: warning dialog on file overwrite + + /** + * Convert RNA-based transcript coordinates to stranded chromosome coords for + * base-pairing arcs. + * + * @param arcs + * @param seqLen + * @param newLeft 1-based genomic coordinate for left-most + * position for input pairs sequence after transformation. + * If strand is "-", this will end up being the 3-prime end + * of the transcript (but the left end in genomic coords). + * @param strand "+" or "-" + * @return + */ + static LinkedList transformArcs(LinkedList arcs, + int seqLen, + int newLeft, + String strand) { + LinkedList transArcs = new LinkedList(); + for (BasePairFeature arc : arcs) { + String chr = arc.getChr(); + Color color = arc.getColor(); + int startLeft, startRight, endLeft, endRight; + if (strand == "+") { + startLeft = arc.getStartLeft() + newLeft - 1; + startRight = arc.getStartRight() + newLeft - 1; + endLeft = arc.getEndLeft() + newLeft - 1; + endRight = arc.getEndRight() + newLeft - 1; + } else if (strand == "-") { + startLeft = seqLen - arc.getEndRight() + newLeft; + startRight = seqLen - arc.getEndLeft() + newLeft; + endLeft = seqLen - arc.getStartRight() + newLeft; + endRight = seqLen - arc.getStartLeft() + newLeft; + } else { + throw new RuntimeException("Unrecognized strand (options: \"+\",\"-\")"); + } + BasePairFeature transArc = new BasePairFeature(chr, + startLeft, + startRight, + endLeft, + endRight, + color); + transArcs.add(transArc); + } + return transArcs; + } + + static SeqLenAndPairs loadDotBracket(String inFile) throws + FileNotFoundException, IOException { + // TODO: add error messages for misformatted file + ArrayList pairs = new ArrayList(); + int seqLen = 0; + + BufferedReader br = null; + + try { + br = new BufferedReader(new FileReader(inFile)); + String struct = ""; + + String nextLine; + while ((nextLine = br.readLine()) != null) { + + // skip leading header lines if present + if (nextLine.startsWith(">") || nextLine.startsWith("#")) { + continue; + } + + String s = nextLine.trim(); + if (Utilities.isAllLetters(s)) { + // sequence line + continue; + } else { + // assumed structure line + struct += s; + } + } + + String leftBrackets = "([{<"; + String rightBrackets = ")]}>"; + + ArrayList> openIndices = new ArrayList>(); + for (int i = 0; i < leftBrackets.length(); ++i) { + openIndices.add(new LinkedList()); + } + + for (int i = 0; i < struct.length(); ++i) { + int n = leftBrackets.indexOf(struct.charAt(i)); + int k = rightBrackets.indexOf(struct.charAt(i)); + if (n >= 0) { + openIndices.get(n).add(i); + } else if (k >= 0) { + int left = i + 1; + int right = openIndices.get(k).pollLast() + 1; + pairs.add(new Point(left, right)); + } + } + seqLen = struct.length(); + + } finally { + if (br != null) br.close(); + } + + return new SeqLenAndPairs(seqLen, pairs); + } + + static SeqLenAndPairs loadConnectTable(String inFile) throws + FileNotFoundException, IOException { + // TODO: add error messages for misformatted file + ArrayList pairs = new ArrayList(); + int seqLen = 0; + + BufferedReader br = null; + + try { + br = new BufferedReader(new FileReader(inFile)); + seqLen = Integer.parseInt(Globals.whitespacePattern.split(br.readLine().trim())[0]); + + String nextLine; + int n = 1; + while ((nextLine = br.readLine()) != null && n <= seqLen) { + String[] s = Globals.whitespacePattern.split(nextLine.trim()); + int left = Integer.parseInt(s[0]); + int right = Integer.parseInt(s[4]); + if (right > left) pairs.add(new Point(left, right)); + n++; + } + + } finally { + if (br != null) br.close(); + } + + return new SeqLenAndPairs(seqLen, pairs); + } + + static SeqLenAndBinnedPairs loadPairingProb(String inFile) throws + FileNotFoundException, IOException { + // TODO: add probability threshold color legend to track dropdown menu + // TODO: support alternate thresholds, interactive threshold update from track UI? + + ArrayList> binnedPairs = new ArrayList>(); + int seqLen = 0; + + double[] probThresh = {0.1, 0.3, 0.8}; + double[] negLogTenProbThresh = {0, 0, 0}; + for (int i = 0; i < probThresh.length; i++) { + negLogTenProbThresh[i] = -Math.log10(probThresh[i]); + } + + for (int i = 0; i < probThresh.length; i++) binnedPairs.add(new ArrayList()); + + BufferedReader br = null; + + try { + br = new BufferedReader(new FileReader(inFile)); + seqLen = Integer.parseInt(Globals.whitespacePattern.split(br.readLine().trim())[0]); + br.readLine(); + + String nextLine; + while ((nextLine = br.readLine()) != null) { + String[] s = Globals.whitespacePattern.split(nextLine.trim()); + int left = Integer.parseInt(s[0]); + int right = Integer.parseInt(s[1]); + double negLogTenProb = Double.parseDouble(s[2]); + int binIndex = -1; + for (int i = probThresh.length - 1; i >= 0; i--) { + if (negLogTenProb <= negLogTenProbThresh[i]) { + binIndex = i; + break; + } + } + if (binIndex != -1) binnedPairs.get(binIndex).add(new Point(left, right)); + } + + } finally { + if (br != null) br.close(); + } + + return new SeqLenAndBinnedPairs(seqLen, binnedPairs); + } + + + static void writeBasePairFile(String bpFile, + ArrayList colors, + ArrayList> groupedArcs) throws IOException { + PrintWriter pw = null; + + try { + pw = new PrintWriter(new BufferedWriter(new FileWriter(bpFile))); + // first write enumerated colors header + for (Color color : colors) { + pw.println("color:\t" + color.getRed() + "\t" + color.getGreen() + "\t" + color.getBlue()); + } + + // then write arc coordinates + int colorIndex = 0; + for (LinkedList colorGroup : groupedArcs) { + for (BasePairFeature arc : colorGroup) { + pw.println(arc.toStringNoColor() + "\t" + colorIndex); + } + colorIndex++; + } + } finally { + if (pw != null) pw.close(); + } + } + + /** + * Merge adjacent basepairs into helices. This makes assumptions about input pair list order. + */ + static LinkedList pairsToHelices(ArrayList pairs, + String chromosome) { + ArrayList bps = new ArrayList(pairs); + LinkedList> helixPairGroups = new LinkedList>(); + + // FIXME: there should be a much faster and more elegant way to do this + while (bps.size() > 0) { + Point bp = bps.get(0); + LinkedList helixPairs = new LinkedList(); + boolean[] removePairs = new boolean[bps.size()]; + helixPairs.add(bp); + removePairs[0] = true; + boolean endOfList = false; + /* - ignore other pairs starting with this left nuc + * - if any base pairs exist starting one nuc downstream of current left nuc + * and ending one nuc upstream of current right nuc, store index to remove + * and append to growing helix + */ + int i = 1; + int skippedCount = 0; + if (i < bps.size()) { + while (bps.get(i).x == bp.x) { + i++; + skippedCount++; + if (i >= bps.size()) { + endOfList = true; + break; + } + } + } else { + endOfList = true; + } + while (i < bps.size()) { + if (bps.get(i).x - bp.x > 1) { + // reached the end of the helix + helixPairGroups.add(helixPairs); + // remove helix pairs + ArrayList tmpBps = new ArrayList(); + for (int k = 0; k < bps.size(); k++) { + if (!removePairs[k]) tmpBps.add(bps.get(k)); + } + bps = tmpBps; + break; + } else if (bps.get(i).y - bp.y == -1) { + bp = bps.get(i); + helixPairs.add(bp); + removePairs[i] = true; + } + i++; + if (i >= bps.size()) { + endOfList = true; + break; + } + } + if (endOfList) { + helixPairGroups.add(helixPairs); + // remove helix pairs + ArrayList tmpBps = new ArrayList(); + for (int k = 0; k < bps.size(); k++) { + if (!removePairs[k]) tmpBps.add(bps.get(k)); + } + bps = tmpBps; + } + } + + // convert lists of adjacent pairs to BasePairFeatures + LinkedList helices = new LinkedList(); + for (LinkedList helixPairs : helixPairGroups) { + int startLeft = Integer.MAX_VALUE; + int startRight = 0; + int endLeft = Integer.MAX_VALUE; + int endRight = 0; + + for (Point pair : helixPairs) { + if (pair.x < startLeft) startLeft = pair.x; + if (pair.x > startRight) startRight = pair.x; + if (pair.y < endLeft) endLeft = pair.y; + if (pair.y > endRight) endRight = pair.y; + } + helices.add(new BasePairFeature(chromosome, + startLeft, + startRight, + endLeft, + endRight, + null)); + } + return helices; + } + + /** + * Convert a base pairing structure file in dot-bracket notation + * (also known as Vienna format) to an easily parseable .bp arcs file. Does not + * currently handle mapping coords to spliced transcripts. + */ + public static void dotBracketToBasePairFile(String inFile, + String bpFile, + String chromosome, + String strand, + int left) throws + FileNotFoundException, IOException { + + SeqLenAndPairs s = loadDotBracket(inFile); + ArrayList pairs = s.pairs; + int seqLen = s.seqLen; + LinkedList arcs = pairsToHelices(pairs, chromosome); + arcs = transformArcs(arcs, seqLen, left, strand); + ArrayList colors = new ArrayList(); + colors.add(Color.black); + ArrayList> groupedArcs = new ArrayList>(); + groupedArcs.add(arcs); // list of length 1 for this case (arcs only have 1 color) + writeBasePairFile(bpFile, colors, groupedArcs); + } + + /** + * Convert a connectivity table file as output by RNAStructure + * to an easily parseable .bp arcs file. Does not + * currently handle mapping coords to spliced transcripts. + */ + public static void connectTableToBasePairFile(String inFile, + String bpFile, + String chromosome, + String strand, + int left) throws + FileNotFoundException, IOException { + + SeqLenAndPairs s = loadConnectTable(inFile); + ArrayList pairs = s.pairs; + int seqLen = s.seqLen; + LinkedList arcs = pairsToHelices(pairs, chromosome); + arcs = transformArcs(arcs, seqLen, left, strand); + ArrayList colors = new ArrayList(); + colors.add(Color.black); + ArrayList> groupedArcs = new ArrayList>(); + groupedArcs.add(arcs); // list of length 1 for this case (arcs only have 1 color) + writeBasePairFile(bpFile, colors, groupedArcs); + } + + /** + * Convert a pairing probability file as output by RNAStructure + * and/or SuperFold to an easily parseable .bp arcs file. Does not + * currently handle mapping coords to spliced transcripts. + */ + public static void pairingProbToBasePairFile(String inFile, + String bpFile, + String chromosome, + String strand, + int left) throws + FileNotFoundException, IOException { + + SeqLenAndBinnedPairs s = loadPairingProb(inFile); + ArrayList> binnedPairs = s.binnedPairs; + int seqLen = s.seqLen; + ArrayList> groupedArcs = new ArrayList>(); + for (ArrayList pairGroup : binnedPairs) { + groupedArcs.add(transformArcs(pairsToHelices(pairGroup, chromosome), + seqLen, left, strand)); + } + ArrayList colors = new ArrayList(); + colors.add(new Color(255, 204, 0)); + colors.add(new Color(72, 143, 205)); + colors.add(new Color(81, 184, 72)); + writeBasePairFile(bpFile, colors, groupedArcs); + } + + +} diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/feature/Codon.java igv-2.3.90+dfsg/src/org/broad/igv/feature/Codon.java --- igv-2.3.88+dfsg/src/org/broad/igv/feature/Codon.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/feature/Codon.java 2017-01-09 04:30:59.000000000 +0000 @@ -115,7 +115,7 @@ } if (strand == Strand.NEGATIVE) { - aas = AminoAcidManager.getNucleotideComplement(aas); + aas = AminoAcidManager.getReverseComplement(aas); } this.sequence = aas; diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/feature/FeatureDB.java igv-2.3.90+dfsg/src/org/broad/igv/feature/FeatureDB.java --- igv-2.3.88+dfsg/src/org/broad/igv/feature/FeatureDB.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/feature/FeatureDB.java 2017-01-09 04:30:59.000000000 +0000 @@ -363,7 +363,7 @@ } tempNT = new String(nuclSequence); if (bf.getStrand() == Strand.NEGATIVE) { - tempNT = AminoAcidManager.getNucleotideComplement(tempNT); + tempNT = AminoAcidManager.getReverseComplement(tempNT); } if (tempNT.toUpperCase().equals(brefNT)) { diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/feature/genome/GenomeManager.java igv-2.3.90+dfsg/src/org/broad/igv/feature/genome/GenomeManager.java --- igv-2.3.88+dfsg/src/org/broad/igv/feature/genome/GenomeManager.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/feature/genome/GenomeManager.java 2017-01-09 04:30:59.000000000 +0000 @@ -147,7 +147,7 @@ Genome newGenome = null; if (monitor != null) { - monitor.fireProgressChange(25); + monitor.fireProgress(25); } // Clear Feature DB @@ -179,7 +179,7 @@ if (aliases != null) newGenome.addChrAliases(aliases); if (monitor != null) { - monitor.fireProgressChange(25); + monitor.fireProgress(25); } setCurrentGenome(newGenome); @@ -559,8 +559,10 @@ // Look in cache first try { if (cachedFile.exists()) { + //Check to see cached version has a custom sequence GenomeDescriptor cachedDescriptor = parseGenomeArchiveFile(cachedFile); + //File sizes won't be the same if the local version has a different sequence location boolean remoteModfied = HttpUtils.getInstance().remoteIsNewer(cachedFile, genomeArchiveURL, !cachedDescriptor.hasCustomSequenceLocation()); @@ -568,6 +570,7 @@ // Force an update of cached genome if file length does not equal remote content length boolean forceUpdate = remoteModfied && PreferenceManager.getInstance().getAsBoolean(PreferenceManager.AUTO_UPDATE_GENOMES); + if (forceUpdate) { log.info("Refreshing genome: " + genomeArchiveURL.toString()); File tmpFile = new File(cachedFile.getAbsolutePath() + ".tmp"); @@ -1212,7 +1215,7 @@ String chrAliasFileName, String genomeDisplayName, String genomeId, - ProgressMonitor monitor) + javax.swing.ProgressMonitor monitor) throws IOException { File refFlatFile = null; @@ -1235,15 +1238,18 @@ chrAliasFile = new File(chrAliasFileName); } - if (monitor != null) monitor.fireProgressChange(25); + if (monitor != null) monitor.setProgress(25); (new GenomeImporter()).createGenomeArchive(genomeFile, genomeId, genomeDisplayName, fastaFileName, refFlatFile, cytobandFile, chrAliasFile); - if (monitor != null) monitor.fireProgressChange(75); + if (monitor != null) monitor.setProgress(75); GenomeListItem newItem = new GenomeListItem(genomeDisplayName, genomeFile.getAbsolutePath(), genomeId); addGenomeItem(newItem, true); + + if (monitor != null) monitor.setProgress(100); + return newItem; } @@ -1261,7 +1267,7 @@ //Whether the srcGenome is simply a fasta file boolean isFastaFile = FastaUtils.isFastaPath(srcPath); - boolean showProgressDialog = !Globals.isHeadless() && !Globals.isBatch(); + String srcFileName = Utilities.getFileNameFromURL(srcPath); if (isFastaFile) { @@ -1269,12 +1275,15 @@ return downloadFasta(srcPath, targetDir, srcFileName, dialogsParent); } else if (srcFileName.endsWith(Globals.GENOME_FILE_EXTENSION)) { - //Most useful case of a .genome file, which contains nearly everything in it, except the - //sequence which is a fasta file stored elsewhere + + //A .genome file, which references a remote fasta file + String genomeName = Utilities.getFileNameFromURL(srcPath); File srcGenomeArchive = new File(targetDir, genomeName); RunnableResult genomeResult = HttpUtils.getInstance().downloadFile(srcPath, srcGenomeArchive); - if (!genomeResult.isSuccess()) return genomeResult; + if (!genomeResult.isSuccess()) { + return genomeResult; + } GenomeDescriptor descriptor = parseGenomeArchiveFile(srcGenomeArchive); @@ -1290,14 +1299,13 @@ } String sequenceFileName = Utilities.getFileNameFromURL(sequencePath); - File localSequenceFile = new File(targetDir, sequenceFileName); // Copy file directly from the server to local area // Shows cancellable dialog RunnableResult fastaResult = downloadFasta(sequencePath, targetDir, sequenceFileName, dialogsParent); if (fastaResult.isSuccess()) { //Rewrite properties file to point to local fasta - rewriteSequenceLocation(targetGenomeFile, localSequenceFile.getAbsolutePath()); + rewriteSequenceLocation(targetGenomeFile, sequenceFileName); } return fastaResult; } else { @@ -1362,11 +1370,10 @@ * the specified {@code newSequencePath}. Works by creating a temp file and renaming * * @param targetFile A .genome file, in zip format - * @param newSequencePath * @return boolean indicating success or failure. * @throws IOException */ - static boolean rewriteSequenceLocation(File targetFile, String newSequencePath) throws IOException { + static boolean rewriteSequenceLocation(File targetFile, String sequenceFileName) throws IOException { ZipFile targetZipFile = new ZipFile(targetFile); boolean success = false; @@ -1385,7 +1392,7 @@ //Copy over property.txt, only replacing a few properties inputProperties.load(reader); - inputProperties.put(Globals.GENOME_ARCHIVE_SEQUENCE_FILE_LOCATION_KEY, newSequencePath); + inputProperties.put(Globals.GENOME_ARCHIVE_SEQUENCE_FILE_LOCATION_KEY, sequenceFileName); inputProperties.put(Globals.GENOME_ARCHIVE_CUSTOM_SEQUENCE_LOCATION_KEY, Boolean.TRUE.toString()); diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/feature/ShapeFileUtils.java igv-2.3.90+dfsg/src/org/broad/igv/feature/ShapeFileUtils.java --- igv-2.3.88+dfsg/src/org/broad/igv/feature/ShapeFileUtils.java 1970-01-01 00:00:00.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/feature/ShapeFileUtils.java 2017-01-09 04:30:59.000000000 +0000 @@ -0,0 +1,162 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2007-2015 Broad Institute + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +package org.broad.igv.feature; + + +import org.broad.igv.Globals; + + +import java.io.*; +import java.lang.reflect.Array; +import java.util.*; + + +class LocAndVal { + public int loc; + public double val; + public LocAndVal(int loc, double val) { + this.loc = loc; + this.val = val; + } +} + + + +/** + * @author sbusan + */ +public class ShapeFileUtils { + + static LinkedList transformProfile(LinkedList profile, + int seqLen, + int newLeft, + String strand){ + LinkedList transProfile = new LinkedList(); + for (LocAndVal d : profile){ + int loc = d.loc; + double val = d.val; + if (strand == "+"){ + loc = loc + newLeft - 1; + } else if (strand == "-"){ + loc = seqLen - loc + newLeft; + } else { + throw new RuntimeException("Unrecognized strand (options: \"+\",\"-\")"); + } + transProfile.add(new LocAndVal(loc, val)); + } + return transProfile; + } + + static LinkedList loadShape(String inFile) throws + FileNotFoundException, IOException { + // TODO: add error messages for misformatted file + LinkedList profile = new LinkedList(); + + BufferedReader br = null; + + try { + br = new BufferedReader(new FileReader(inFile)); + + String nextLine; + while ((nextLine = br.readLine()) != null) { + String[] s = Globals.whitespacePattern.split(nextLine.trim()); + int loc = Integer.parseInt(s[0]); + double val = Double.parseDouble(s[1]); + if (val < -998) { + val = Double.NaN; + } + profile.add(new LocAndVal(loc, val)); + } + } finally { + if (br != null) br.close(); + } + + return profile; + } + + + static void writeWigFile(String wigFile, + String chrom, + LinkedList profile) throws IOException { + PrintWriter pw = null; + + try { + pw = new PrintWriter(new BufferedWriter(new FileWriter(wigFile))); + // write header + pw.println("variableStep chrom="+chrom); + + // write locs and values + for (LocAndVal d : profile) { + int loc = d.loc; + double val = d.val; + if (!Double.isNaN(val)){ + pw.println(""+loc+"\t"+String.format("%.6f",val)); + } + } + } finally { + if (pw != null) pw.close(); + } + } + + + public static void shapeToWigFile(String inFile, + String wigFile, + String chromosome, + String strand, + int left) throws + FileNotFoundException, IOException { + + LinkedList profile = loadShape(inFile); + profile = transformProfile(profile, profile.size(), left, strand); + writeWigFile(wigFile, chromosome, profile); + } + + /** + * Convert a base pairing structure file in dot-bracket notation + * (also known as Vienna format) to an easily parseable .bp arcs file. Does not + * currently handle mapping coords to spliced transcripts. + * + * @param dbFile Input file + * @param bpFile Output file + * @param chromosome Associated IGV chromosome + * @param strand Associated strand ("+" or "-") + * @param left Starting left-most position (0-based) + */ + + + /** + * Convert a pairing probability file as output by RNAStructure + * and/or SuperFold to an easily parseable .bp arcs file. Does not + * currently handle mapping coords to spliced transcripts. + * + * @param dpFile Input file + * @param bpFile Output file + * @param chromosome Associated IGV chromosome + * @param strand Associated strand ("+" or "-") + * @param left Starting left-most position (0-based) + */ + +} diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/PreferenceManager.java igv-2.3.90+dfsg/src/org/broad/igv/PreferenceManager.java --- igv-2.3.88+dfsg/src/org/broad/igv/PreferenceManager.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/PreferenceManager.java 2017-01-09 04:30:59.000000000 +0000 @@ -300,6 +300,8 @@ public static final String SESSION_RELATIVE_PATH = "SESSION.RELATIVE_PATH"; + public static final String CHECK_VERSION = "CHECK_VERSION"; + IGVPreferences preferences; Map defaultValues; @@ -1230,6 +1232,7 @@ defaultValues.put(SHOW_LOS, "true"); + defaultValues.put(CHECK_VERSION, "true"); } /** diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/renderer/DataRenderer.java igv-2.3.90+dfsg/src/org/broad/igv/renderer/DataRenderer.java --- igv-2.3.88+dfsg/src/org/broad/igv/renderer/DataRenderer.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/renderer/DataRenderer.java 2017-01-09 04:30:59.000000000 +0000 @@ -73,7 +73,10 @@ // has caused concurrent modification exceptions. synchronized (scores) { renderScores(track, scores, context, rect); - renderAxis(track, context, rect); + + if(context.isMerged() == false) { + renderAxis(track, context, rect); + } } } renderBorder(track, context, rect); diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/sam/AlignmentTrack.java igv-2.3.90+dfsg/src/org/broad/igv/sam/AlignmentTrack.java --- igv-2.3.88+dfsg/src/org/broad/igv/sam/AlignmentTrack.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/sam/AlignmentTrack.java 2017-01-09 04:30:59.000000000 +0000 @@ -38,6 +38,7 @@ import org.broad.igv.feature.FeatureUtils; import org.broad.igv.feature.Locus; import org.broad.igv.feature.Range; +import org.broad.igv.feature.Strand; import org.broad.igv.feature.genome.ChromosomeNameComparator; import org.broad.igv.feature.genome.Genome; import org.broad.igv.lists.GeneList; @@ -2058,6 +2059,8 @@ item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent aEvt) { + String blatSeq = alignment.getReadStrand() == Strand.NEGATIVE ? + SequenceTrack.getReverseComplement(seq) : seq; BlatClient.doBlatQuery(seq); } }); diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/sam/BaseAlignmentCounts.java igv-2.3.90+dfsg/src/org/broad/igv/sam/BaseAlignmentCounts.java --- igv-2.3.88+dfsg/src/org/broad/igv/sam/BaseAlignmentCounts.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/sam/BaseAlignmentCounts.java 2017-01-09 04:30:59.000000000 +0000 @@ -206,7 +206,6 @@ Set filteredSnps = knownSnps == null ? null : knownSnps.get(chr); if (filteredSnps == null || !filteredSnps.contains(pos + 1)) { - float threshold = snpThreshold * (qualityWeight ? getTotalQuality(pos) : getTotalCount(pos)); float mismatchQualitySum = 0; @@ -218,7 +217,7 @@ } } - return mismatchQualitySum >= threshold; + return (mismatchQualitySum >= threshold) && (threshold > 0); // (threshold > 0) avoids mismatch call in columns with all 0 quality } } return false; diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/sam/BisulfiteBaseInfo.java igv-2.3.90+dfsg/src/org/broad/igv/sam/BisulfiteBaseInfo.java --- igv-2.3.88+dfsg/src/org/broad/igv/sam/BisulfiteBaseInfo.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/sam/BisulfiteBaseInfo.java 2017-01-09 04:30:59.000000000 +0000 @@ -80,7 +80,7 @@ myContext = bisulfiteContext; byte[] inRead = block.getBases(); - if(inRead != null) { + if (inRead != null) { int alignmentLen = inRead.length; // We will only need reverse complement if the strand and paired end status don't match (2nd ends are G->A) @@ -113,6 +113,14 @@ byte readbase = read[idx]; if (readbase == '=') readbase = refbase; + // Force both bases to upper case + if (refbase > 90) { + refbase = (byte) (refbase - 32); + } + if (readbase > 90) { + readbase = (byte) (readbase - 32); + } + Color out = null; boolean matchesContext = false; @@ -195,13 +203,13 @@ * @param idx * @param bisulfiteContext * @return Returns the context that matched (in the case of the base class, this is always the same - * as the context passed in, derived classes might return a different context). - * If we don't match, return null. + * as the context passed in, derived classes might return a different context). + * If we don't match, return null. */ protected BisulfiteContext contextIsMatching(byte[] reference, byte[] read, int idx, BisulfiteContext bisulfiteContext) { - if(BisulfiteContext.NONE == bisulfiteContext) { + if (BisulfiteContext.NONE == bisulfiteContext) { return bisulfiteContext; } @@ -302,8 +310,8 @@ /** * @param item * @return 0 if the cytosine context is not symmetric, else the number of - * base pairs to shift the position by (caller must be careful to shift - * relative to the strand the cytosine is on). + * base pairs to shift the position by (caller must be careful to shift + * relative to the strand the cytosine is on). */ protected double getBisulfiteSymmetricCytosineShift(BisulfiteContext item) { double out = 0.0; diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/sam/BisulfiteCounts.java igv-2.3.90+dfsg/src/org/broad/igv/sam/BisulfiteCounts.java --- igv-2.3.88+dfsg/src/org/broad/igv/sam/BisulfiteCounts.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/sam/BisulfiteCounts.java 2017-01-09 04:30:59.000000000 +0000 @@ -95,12 +95,21 @@ // The read base can be an equals sign, so change that to the actual ref base byte refbase = reference[idx]; - + if (refbase > 90) { + refbase = (byte) (refbase - 32); // Uppercase + } // Strand has already been accounted for if (refbase == 'C') { byte readbase = read[idx]; - if (readbase == '=') readbase = refbase; + if (readbase == '=') { + readbase = refbase; + } + + // Force both bases to upper case + if (readbase > 90) { + readbase = (byte) (readbase - 32); + } if (AlignmentUtils.compareBases((byte) 'C', readbase) || AlignmentUtils.compareBases((byte) 'T', readbase)) { diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/sam/DenseAlignmentCounts.java igv-2.3.90+dfsg/src/org/broad/igv/sam/DenseAlignmentCounts.java --- igv-2.3.88+dfsg/src/org/broad/igv/sam/DenseAlignmentCounts.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/sam/DenseAlignmentCounts.java 2017-01-09 04:30:59.000000000 +0000 @@ -305,13 +305,9 @@ protected void incrementInsertion(AlignmentBlock insBlock) { int pos = insBlock.getStart(); int offset = pos - start; - // Insertions are between bases. increment count on either side + // Insertions are between bases. increment count at position just before insertion if (offset >= 0 && offset < ins.length) { - ins[offset] = ins[offset] + 1; - offset--; - if (offset >= 0) { - ins[offset] = ins[offset] + 1; - } + ins[offset] = ins[offset] + 1; } } diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/sam/reader/MergedAlignmentReader.java igv-2.3.90+dfsg/src/org/broad/igv/sam/reader/MergedAlignmentReader.java --- igv-2.3.88+dfsg/src/org/broad/igv/sam/reader/MergedAlignmentReader.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/sam/reader/MergedAlignmentReader.java 2017-01-09 04:30:59.000000000 +0000 @@ -235,6 +235,8 @@ Integer idx1 = chrNameIndex.get(a1.getChr()); Integer idx2 = chrNameIndex.get(a2.getChr()); + if(idx1==null) idx1 = Integer.MAX_VALUE; + if(idx2== null) idx2 = Integer.MAX_VALUE; // Put these records at the end. if (idx1 > idx2) { return 1; } else if (idx1 < idx2) { diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/tdf/TDFDataSource.java igv-2.3.90+dfsg/src/org/broad/igv/tdf/TDFDataSource.java --- igv-2.3.88+dfsg/src/org/broad/igv/tdf/TDFDataSource.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/tdf/TDFDataSource.java 2017-01-09 04:30:59.000000000 +0000 @@ -217,7 +217,7 @@ } else { - if(querySeq.equals(genome.getHomeChromosome())) { + if(querySeq.equals(Globals.CHR_ALL)) { scores = getWGRawScores(); } else { diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/track/AbstractTrack.java igv-2.3.90+dfsg/src/org/broad/igv/track/AbstractTrack.java --- igv-2.3.88+dfsg/src/org/broad/igv/track/AbstractTrack.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/track/AbstractTrack.java 2017-01-09 04:30:59.000000000 +0000 @@ -967,7 +967,15 @@ public String getNameValueString(int y) { - return getName(); + + StringBuffer buffer = new StringBuffer(); + buffer.append("" + getName()); + + if(resourceLocator != null && resourceLocator.getPath() != null) { + buffer.append("
" + this.resourceLocator.getPath()); + } + + return buffer.toString(); } /** diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/track/MergedTracks.java igv-2.3.90+dfsg/src/org/broad/igv/track/MergedTracks.java --- igv-2.3.88+dfsg/src/org/broad/igv/track/MergedTracks.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/track/MergedTracks.java 2017-01-09 04:30:59.000000000 +0000 @@ -54,7 +54,7 @@ * @date 2013-Nov-05 */ @XmlType(factoryMethod = "getNextTrack") -public class MergedTracks extends DataTrack { +public class MergedTracks extends DataTrack implements ScalableTrack { @XmlAttribute protected Class clazz = MergedTracks.class; @@ -83,6 +83,18 @@ this.memberTracks.add(inputTrack); } } + + // Set the group autoscale attribute only of all tracks are in the same group + this.removeAttribute(AttributeManager.GROUP_AUTOSCALE); + if (memberTracks.size() > 0) { + String group = memberTracks.iterator().next().getAttributeValue(AttributeManager.GROUP_AUTOSCALE); + if(group != null) { + for (Track t : memberTracks) { + if(!group.equals(t.getAttributeValue(AttributeManager.GROUP_AUTOSCALE))) return; + } + this.setAttributeValue(AttributeManager.GROUP_AUTOSCALE, group); + } + } } @Override @@ -95,7 +107,7 @@ } @XmlElement(name = MEMBER_TRACK_TAG_NAME) - Collection getMemberTracks() { + public Collection getMemberTracks() { return this.memberTracks; } @@ -110,6 +122,7 @@ @Override public void render(RenderContext context, Rectangle rect) { + context.setMerged(true); for (Track track : memberTracks) { track.render(context, rect); } @@ -178,7 +191,7 @@ @Override public boolean getAutoScale() { - boolean autoScale = super.getAutoScale(); + boolean autoScale = true; for (Track track : memberTracks) { autoScale &= track.getAutoScale(); } @@ -187,13 +200,33 @@ @Override public void setAutoScale(boolean autoScale) { - super.setAutoScale(autoScale); for (Track track : memberTracks) { track.setAutoScale(autoScale); } } @Override + public void setAttributeValue(String name, String value) { + super.setAttributeValue(name, value); + if (name.equals(AttributeManager.GROUP_AUTOSCALE)) { + for (Track track : memberTracks) { + track.setAttributeValue(name, value); + } + } + } + + @Override + public void removeAttribute(String name) { + super.removeAttribute(name); + if (name.equals(AttributeManager.GROUP_AUTOSCALE)) { + for (Track track : memberTracks) { + track.removeAttribute(name); + } + } + } + + + @Override public ContinuousColorScale getColorScale() { return super.getColorScale(); } @@ -267,13 +300,32 @@ return menu; } - //Not clear whether this is necessary, don't think it is, the real problem is loading not saving -// public void marshalMemberTracks(Marshaller m, Element trackElement) throws JAXBException{ -// for(DataTrack memberTrack: memberTracks){ -// JAXBElement element = new JAXBElement(new QName("", DataTrack.DATA_TRACK), DataTrack.class, memberTrack); -// m.marshal(element, trackElement); -// } -// } + + @Override + public Range getInViewRange(ReferenceFrame referenceFrame) { + + List scores = new ArrayList(); + for (DataTrack track : memberTracks) { + scores.addAll(track.getInViewScores(referenceFrame)); + } + + if (scores.size() > 0) { + float min = Float.MAX_VALUE; + float max = -Float.MAX_VALUE; + for (LocusScore score : scores) { + float value = score.getScore(); + if (!Float.isNaN(value)) { + min = Math.min(value, min); + max = Math.max(value, max); + } + } + return new Range(min, max); + } else { + return null; + } + + } + private enum ChangeTrackMethod { POSITIVE, NEGATIVE diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/track/RenderContextImpl.java igv-2.3.90+dfsg/src/org/broad/igv/track/RenderContextImpl.java --- igv-2.3.88+dfsg/src/org/broad/igv/track/RenderContextImpl.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/track/RenderContextImpl.java 2017-01-09 04:30:59.000000000 +0000 @@ -47,6 +47,7 @@ private ReferenceFrame referenceFrame; private JComponent panel; private Rectangle visibleRect; + boolean merged; public RenderContextImpl(JComponent panel, Graphics2D graphics, ReferenceFrame referenceFrame, Rectangle visibleRect) { @@ -114,6 +115,15 @@ return referenceFrame; } + @Override + public boolean isMerged() { + return merged; + } + + public void setMerged(boolean merged) { + this.merged = merged; + } + public int bpToScreenPixel(double location) { final double scale = getScale(); final double origin = getOrigin(); @@ -132,6 +142,8 @@ dispose(); } + + public void dispose() { for (Graphics2D g : graphicCacheByColor.values()) { g.dispose(); diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/track/RenderContext.java igv-2.3.90+dfsg/src/org/broad/igv/track/RenderContext.java --- igv-2.3.88+dfsg/src/org/broad/igv/track/RenderContext.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/track/RenderContext.java 2017-01-09 04:30:59.000000000 +0000 @@ -58,6 +58,10 @@ int bpToScreenPixel(double location); + void setMerged(boolean b); + + boolean isMerged(); + void dispose(); } diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/track/SequenceTrack.java igv-2.3.90+dfsg/src/org/broad/igv/track/SequenceTrack.java --- igv-2.3.88+dfsg/src/org/broad/igv/track/SequenceTrack.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/track/SequenceTrack.java 2017-01-09 04:30:59.000000000 +0000 @@ -171,8 +171,9 @@ private void flipStrand() { strand = (strand == Strand.POSITIVE ? Strand.NEGATIVE : Strand.POSITIVE); - repaint(); IGV.getInstance().clearSelections(); + repaint(); + } public void setShouldShowTranslation(boolean shouldShowTranslation) { @@ -269,8 +270,7 @@ public String getValueStringAt(String chr, double position, int y, ReferenceFrame frame) { if (sequenceVisible && !this.sequenceRenderer.hasSequence()) { - return "Sequence info not found. Make sure the server in question supports byte-range requests, and that " - + "there are no firewalls which remove this information"; + return "Sequence info not found"; } else { return null; } @@ -281,4 +281,43 @@ } + + public static String getReverseComplement(String sequence) { + char[] complement = new char[sequence.length()]; + int jj = complement.length; + for (int ii = 0; ii < sequence.length(); ii++) { + char c = sequence.charAt(ii); + jj--; + switch (c) { + case 'T': + complement[jj] = 'A'; + break; + case 'A': + complement[jj] = 'T'; + break; + case 'C': + complement[jj] = 'G'; + break; + case 'G': + complement[jj] = 'C'; + break; + case 't': + complement[jj] = 'a'; + break; + case 'a': + complement[jj] = 't'; + break; + case 'c': + complement[jj] = 'g'; + break; + case 'g': + complement[jj] = 'c'; + break; + default: + complement[jj] = c; + } + } + return new String(complement); + } + } diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/track/TrackLoader.java igv-2.3.90+dfsg/src/org/broad/igv/track/TrackLoader.java --- igv-2.3.88+dfsg/src/org/broad/igv/track/TrackLoader.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/track/TrackLoader.java 2017-01-09 04:30:59.000000000 +0000 @@ -47,7 +47,9 @@ import org.broad.igv.dev.db.SampleInfoSQLReader; import org.broad.igv.dev.db.SegmentedSQLReader; import org.broad.igv.exceptions.DataLoadException; -import org.broad.igv.feature.basepair.BasePairFileParser; +import org.broad.igv.feature.basepair.BasePairTrack; +import org.broad.igv.feature.BasePairFileUtils; +import org.broad.igv.feature.ShapeFileUtils; import org.broad.igv.feature.CachingFeatureSource; import org.broad.igv.feature.GisticFileParser; import org.broad.igv.feature.MutationTrackLoader; @@ -83,6 +85,8 @@ import org.broad.igv.ui.IGV; import org.broad.igv.ui.util.ConfirmDialog; import org.broad.igv.ui.util.MessageUtils; +import org.broad.igv.ui.util.ConvertFileDialog; +import org.broad.igv.ui.util.ConvertOptions; import org.broad.igv.util.FileUtils; import org.broad.igv.util.HttpUtils; import org.broad.igv.util.ParsingUtils; @@ -174,6 +178,8 @@ loadSyntentyMapping(locator, newTracks); } else if (isAlignmentTrack(typeString)) { loadAlignmentsTrack(locator, newTracks, genome); + } else if (typeString.endsWith(".shape") || typeString.endsWith(".map")) { + convertLoadShapeFile(locator, newTracks, genome); } else if (typeString.endsWith(".wig") || typeString.endsWith(".bedgraph") || typeString.endsWith(".bdg") || typeString.endsWith("cpg.txt") || typeString.endsWith(".expr")) { loadWigFile(locator, newTracks, genome); @@ -202,6 +208,12 @@ } else if (typeString.endsWith("mage-tab") || ExpressionFileParser.parsableMAGE_TAB(locator)) { locator.setDescription("MAGE_TAB"); loadGctFile(locator, newTracks, genome); + } else if (typeString.endsWith(".db") || typeString.endsWith(".dbn")) { + convertLoadStructureFile(locator, newTracks, genome, "dotBracket"); + } else if (typeString.endsWith(".ct")) { + convertLoadStructureFile(locator, newTracks, genome, "connectTable"); + } else if (typeString.endsWith(".dp")) { + convertLoadStructureFile(locator, newTracks, genome, "pairingProb"); } else if (typeString.endsWith(".bp")) { loadBasePairFile(locator, newTracks, genome); } else if (GWASParser.isGWASFile(typeString)) { @@ -1233,10 +1245,68 @@ PedigreeUtils.parseTrioFile(locator.getPath()); } + /** + * Convert an RNA chemical reactivity file (.shape, .map) into a .wig file + * and load. + + */ + private void convertLoadShapeFile(ResourceLocator locator, + List newTracks, + Genome genome) throws IOException { + String inPath = locator.getPath(); + String fileName = locator.getFileName(); + String outPath = inPath + ".wig"; + String message = "The chemical reactivity file
  " + fileName + "
needs to be converted to IGV chromosome
" + + "coordinates and .wig format before loading.

Click Continue " + + "to save converted file to
  " + fileName+".wig" + + "
and load with the selected options, or Cancel to skip this
file."; + + ConvertOptions opts = ConvertFileDialog.showConvertFileDialog(message); + if (opts.doConvert) { + ShapeFileUtils.shapeToWigFile(inPath, outPath, opts.chrom, opts.strand, opts.start); + loadWigFile(new ResourceLocator(outPath), newTracks, genome); + } + } + + /** + * Convert various RNA structure formats to a more easily parseable format + * in genomic coordinates, then load converted file. + + */ + private void convertLoadStructureFile(ResourceLocator locator, + List newTracks, + Genome genome, + String fileType) throws IOException { + String inPath = locator.getPath(); + String fileName = locator.getFileName(); + String outPath = inPath + ".bp"; + + String message = "The RNA structure file
  " + fileName + "
needs to be converted to IGV chromosome
" + + "coordinates and .bp format before loading.

Click Continue " + + "to save converted file to
  " + fileName+".bp" + + "
and load with the selected options, or Cancel to skip this
file."; + + ConvertOptions opts = ConvertFileDialog.showConvertFileDialog(message); + + if (opts.doConvert){ + if (fileType == "connectTable") { + BasePairFileUtils.connectTableToBasePairFile(inPath, outPath, opts.chrom, opts.strand, opts.start); + } else if (fileType == "pairingProb") { + BasePairFileUtils.pairingProbToBasePairFile(inPath, outPath, opts.chrom, opts.strand, opts.start); + } else if (fileType == "dotBracket") { + BasePairFileUtils.dotBracketToBasePairFile(inPath, outPath, opts.chrom, opts.strand, opts.start); + } + loadBasePairFile(new ResourceLocator(outPath), newTracks, genome); + } + } - private void loadBasePairFile(ResourceLocator locator, List newTracks, Genome genome) throws IOException { - BasePairFileParser parser = new BasePairFileParser(); - newTracks.add(parser.loadTrack(locator, genome)); // should create one track from the given file + private void loadBasePairFile(ResourceLocator locator, + List newTracks, + Genome genome) throws IOException { + String name = locator.getTrackName(); + String path = locator.getPath(); + String id = path + "_" + name; + newTracks.add(new BasePairTrack(locator, id, name, genome)); } public static boolean isIndexed(ResourceLocator locator, Genome genome) { diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/track/TrackMenuUtils.java igv-2.3.90+dfsg/src/org/broad/igv/track/TrackMenuUtils.java --- igv-2.3.88+dfsg/src/org/broad/igv/track/TrackMenuUtils.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/track/TrackMenuUtils.java 2017-01-09 04:30:59.000000000 +0000 @@ -34,9 +34,7 @@ import org.broad.igv.PreferenceManager; import org.broad.igv.data.AbstractDataSource; import org.broad.igv.data.CombinedDataSource; -import org.broad.igv.feature.Exon; -import org.broad.igv.feature.FeatureUtils; -import org.broad.igv.feature.IGVFeature; +import org.broad.igv.feature.*; import org.broad.igv.feature.Range; import org.broad.igv.feature.basepair.BasePairTrack; import org.broad.igv.feature.genome.Genome; @@ -333,7 +331,7 @@ menu.add(getAutoscaleItem(tracks)); - if (tracks.size() > 1) { + if (tracks.size() > 1 || (tracks.size() == 1 && tracks.iterator().next() instanceof MergedTracks)) { menu.add(getGroupAutoscaleItem(tracks)); } @@ -884,9 +882,6 @@ t.removeAttribute(AttributeManager.GROUP_AUTOSCALE); } } - - DataPanelContainer.resetStateHash(); - IGV.getInstance().repaint(); } }); @@ -901,15 +896,15 @@ autoscaleItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { + int nextAutoscaleGroup = IGV.getInstance().getSession().getNextAutoscaleGroup(); + for (Track t : selectedTracks) { t.setAttributeValue(AttributeManager.GROUP_AUTOSCALE, String.valueOf(nextAutoscaleGroup)); t.setAutoScale(false); } IGV.getInstance().getSession().incrementNextAutoscaleGroup(); - DataPanelContainer.resetStateHash(); - PreferenceManager.getInstance().setShowAttributeView(true); IGV.getInstance().getMainPanel().invalidate(); IGV.getInstance().doRefresh(); @@ -1068,7 +1063,6 @@ return; } - DataPanelContainer.resetStateHash(); IGV.getInstance().removeTracks(selectedTracks); IGV.getInstance().doRefresh(); } @@ -1349,12 +1343,19 @@ public static JMenuItem getCopySequenceItem(final Feature f) { + + final Strand strand; + if(f instanceof IGVFeature) { + strand = ((IGVFeature) f).getStrand(); + } else { + strand = Strand.NONE; + } + JMenuItem item = new JMenuItem("Copy Sequence"); item.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent evt) { Genome genome = GenomeManager.getInstance().getCurrentGenome(); - IGV.copySequenceToClipboard(genome, f.getChr(), f.getStart(), f.getEnd()); + IGV.copySequenceToClipboard(genome, f.getChr(), f.getStart(), f.getEnd(), strand); } }); return item; @@ -1366,7 +1367,15 @@ item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt) { - BlatClient.doBlatQuery(f.getChr(), f.getStart(), f.getEnd()); + + final Strand strand; + if(f instanceof IGVFeature) { + strand = ((IGVFeature) f).getStrand(); + } else { + strand = Strand.NONE; + } + + BlatClient.doBlatQuery(f.getChr(), f.getStart(), f.getEnd(), strand); } }); return item; diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/ui/GenomeSelectionDialog.java igv-2.3.90+dfsg/src/org/broad/igv/ui/GenomeSelectionDialog.java --- igv-2.3.88+dfsg/src/org/broad/igv/ui/GenomeSelectionDialog.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/ui/GenomeSelectionDialog.java 2017-01-09 04:30:59.000000000 +0000 @@ -162,6 +162,7 @@ } static void downloadGenome(final Frame dialogsParent, final GenomeListItem genomeListItem) { + final File targetDir = DirectoryManager.getGenomeCacheDirectory(); if(!targetDir.exists()){ targetDir.mkdirs(); diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/ui/IGV.java igv-2.3.90+dfsg/src/org/broad/igv/ui/IGV.java --- igv-2.3.88+dfsg/src/org/broad/igv/ui/IGV.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/ui/IGV.java 2017-01-09 04:30:59.000000000 +0000 @@ -39,6 +39,7 @@ import com.google.common.eventbus.Subscribe; import com.jidesoft.swing.JideSplitPane; import htsjdk.samtools.seekablestream.SeekableFileStream; +import htsjdk.samtools.util.StringUtil; import org.apache.log4j.Logger; import org.broad.igv.DirectoryManager; import org.broad.igv.Globals; @@ -48,9 +49,7 @@ import org.broad.igv.batch.CommandListener; import org.broad.igv.dev.api.IGVPlugin; import org.broad.igv.exceptions.DataLoadException; -import org.broad.igv.feature.Locus; -import org.broad.igv.feature.MaximumContigGenomeException; -import org.broad.igv.feature.RegionOfInterest; +import org.broad.igv.feature.*; import org.broad.igv.feature.genome.*; import org.broad.igv.lists.GeneList; import org.broad.igv.lists.Preloader; @@ -481,7 +480,7 @@ } - public void doDefineGenome(ProgressMonitor monitor) { + public void doDefineGenome(javax.swing.ProgressMonitor monitor) { ProgressBar.ProgressDialog progressDialog = null; File archiveFile = null; @@ -496,9 +495,6 @@ return; } - if (monitor != null) { - progressDialog = ProgressBar.showProgressDialog(mainFrame, "Defining Genome...", monitor, false); - } String cytobandFileName = genomeBuilderDialog.getCytobandFileName(); String geneAnnotFileName = genomeBuilderDialog.getGeneAnnotFileName(); @@ -517,7 +513,7 @@ contentPane.getCommandBar().selectGenome(genomeListItem.getId()); } if (monitor != null) { - monitor.fireProgressChange(100); + monitor.setProgress(100); } } catch (MaximumContigGenomeException e) { @@ -568,11 +564,10 @@ Runnable showDialog = new Runnable() { @Override public void run() { + Collection inputListItems = GenomeManager.getInstance().getServerGenomeArchiveList(); if (inputListItems == null) { - //Not necessary to display a message, getServerGenomeArchiveList does it already - //IOException exc = new IOException("Unable to reach genome server"); - //MessageUtils.showErrorMessage(exc.getMessage(), exc); + //Could not reach genome server. Not necessary to display a message, getServerGenomeArchiveList does it already return; } @@ -583,7 +578,9 @@ if (selectedValues != null && selectedValues.size() >= 1) { if (selectedValues.size() == 1 && dialog.downloadSequence()) { + GenomeListItem oldItem = selectedValues.get(0); + GenomeSelectionDialog.downloadGenome(getMainFrame(), oldItem); File newLocation = new File(DirectoryManager.getGenomeCacheDirectory().getAbsolutePath(), Utilities.getFileNameFromURL(oldItem.getLocation())); @@ -653,9 +650,15 @@ } public void loadGenomeById(String genomeId) { + + final Genome currentGenome = genomeManager.getCurrentGenome(); + if(currentGenome != null && genomeId.equals(currentGenome.getId())) { + return; // Already loaded + } + if (ParsingUtils.pathExists(genomeId)) { try { - IGV.getInstance().loadGenome(genomeId, null, false); + loadGenome(genomeId, null, false); } catch (IOException e) { log.error("Error loading genome file: " + genomeId, e); } @@ -2703,21 +2706,20 @@ } - public static void copySequenceToClipboard(Genome genome, String chr, int start, int end) { + public static void copySequenceToClipboard(Genome genome, String chr, int start, int end, Strand strand) { try { IGV.getMainFrame().setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR)); byte[] seqBytes = genome.getSequence(chr, start, end); if (seqBytes == null) { - MessageUtils.showMessage("Sequence not available. Try enabling http byte-range requests"); + MessageUtils.showMessage("Sequence not available"); } else { String sequence = new String(seqBytes); - //TODO This will complement sequence if sequence track is flipped - //Might be un-intuitive to user if they do it from region dialog -// SequenceTrack sequenceTrack = IGV.getInstance().getSequenceTrack(); -// if(sequenceTrack != null && sequenceTrack.getStrand() == Strand.NEGATIVE){ -// sequence = AminoAcidManager.getNucleotideComplement(sequence); -// } + + SequenceTrack sequenceTrack = IGV.getInstance().getSequenceTrack(); + if(strand == Strand.NEGATIVE || (sequenceTrack != null && sequenceTrack.getStrand() == Strand.NEGATIVE)){ + sequence = AminoAcidManager.getReverseComplement(sequence); + } StringUtils.copyTextToClipboard(sequence); } diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/ui/IGVMenuBar.java igv-2.3.90+dfsg/src/org/broad/igv/ui/IGVMenuBar.java --- igv-2.3.88+dfsg/src/org/broad/igv/ui/IGVMenuBar.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/ui/IGVMenuBar.java 2017-01-09 04:30:59.000000000 +0000 @@ -579,7 +579,8 @@ new MenuAction("Create .genome File...", null, KeyEvent.VK_D) { @Override public void actionPerformed(ActionEvent event) { - org.broad.igv.ui.util.ProgressMonitor monitor = new org.broad.igv.ui.util.ProgressMonitor(); + javax.swing.ProgressMonitor monitor = new javax.swing.ProgressMonitor(IGV.getInstance().getMainPanel(), + "Creating genome", null, 0, 100); igv.doDefineGenome(monitor); } }; @@ -597,9 +598,9 @@ dialog2.setVisible(true); boolean cancelled = dialog2.isCancelled(); List removedValuesList = dialog2.getRemovedValuesList(); + if (!cancelled) { - GenomeManager.getInstance().buildGenomeItemList(); - igv.getContentPane().getCommandBar().refreshGenomeListComboBox(); + if (removedValuesList != null && !removedValuesList.isEmpty()) { try { GenomeManager.getInstance().deleteDownloadedGenomes(removedValuesList); @@ -608,7 +609,20 @@ } GenomeManager.getInstance().updateImportedGenomePropertyFile(); notifyGenomesAddedRemoved(removedValuesList, false); + + String defaultGenomeKey = PreferenceManager.getInstance().get(PreferenceManager.DEFAULT_GENOME_KEY); + for (GenomeListItem item : removedValuesList) { + if (defaultGenomeKey.equals(item.getId())) { + PreferenceManager.getInstance().remove(PreferenceManager.DEFAULT_GENOME_KEY); + break; + } + } } + + GenomeManager.getInstance().buildGenomeItemList(); + + igv.getContentPane().getCommandBar().refreshGenomeListComboBox(); + } } }; diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/ui/Main.java igv-2.3.90+dfsg/src/org/broad/igv/ui/Main.java --- igv-2.3.88+dfsg/src/org/broad/igv/ui/Main.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/ui/Main.java 2017-01-09 04:30:59.000000000 +0000 @@ -145,6 +145,7 @@ System.setProperty("awt.useSystemAAFontSettings", "on"); System.setProperty("swing.aatext", "true"); + checkVersion(); @@ -161,47 +162,47 @@ private static void checkVersion() { - int readTimeout = Globals.READ_TIMEOUT; - int connectTimeout = Globals.CONNECT_TIMEOUT; - try { - Version thisVersion = Version.getVersion(Globals.VERSION); - if (thisVersion == null) return; // Can't compare - - Globals.CONNECT_TIMEOUT = 5000; - Globals.READ_TIMEOUT = 1000; - final String serverVersionString = HttpUtils.getInstance().getContentsAsString(new URL(Globals.getVersionURL())).trim(); - // See if user has specified to skip this update - - final String skipString = PreferenceManager.getInstance().get(PreferenceManager.SKIP_VERSION); - HashSet skipVersion = new HashSet(Arrays.asList(skipString.split(","))); - if (skipVersion.contains(serverVersionString)) return; - - Version serverVersion = Version.getVersion(serverVersionString.trim()); - if (serverVersion == null) return; - - if (thisVersion.lessThan(serverVersion)) { - - log.info("A later version of IGV is available (" + serverVersionString + ")"); -// final VersionUpdateDialog dlg = new VersionUpdateDialog(serverVersionString); -// SwingUtilities.invokeAndWait(new Runnable() { -// public void run() { -// dlg.setVisible(true); -// if (dlg.isSkipVersion()) { -// String newSkipString = skipString + "," + serverVersionString; -// PreferenceManager.getInstance().put(PreferenceManager.SKIP_VERSION, newSkipString); -// } -// } -// }); + Runnable runnable = new Runnable() { + public void run() { + try { + Version thisVersion = Version.getVersion(Globals.VERSION); + if (thisVersion == null) return; // Can't compare + + final String serverVersionString = HttpUtils.getInstance().getContentsAsString(new URL(Globals.getVersionURL())).trim(); + // See if user has specified to skip this update + + final String skipString = PreferenceManager.getInstance().get(PreferenceManager.SKIP_VERSION); + HashSet skipVersion = new HashSet(Arrays.asList(skipString.split(","))); + if (skipVersion.contains(serverVersionString)) return; + + Version serverVersion = Version.getVersion(serverVersionString.trim()); + if (serverVersion == null) return; + + if (thisVersion.lessThan(serverVersion)) { + + log.info("A later version of IGV is available (" + serverVersionString + ")"); + // final VersionUpdateDialog dlg = new VersionUpdateDialog(serverVersionString); + // SwingUtilities.invokeAndWait(new Runnable() { + // public void run() { + // dlg.setVisible(true); + // if (dlg.isSkipVersion()) { + // String newSkipString = skipString + "," + serverVersionString; + // PreferenceManager.getInstance().put(PreferenceManager.SKIP_VERSION, newSkipString); + // } + // } + // }); + } + + } catch (Exception e) { + log.error("Error checking version", e); + } finally { + } } + }; - } catch (Exception e) { - log.error("Error checking version", e); - } finally { - Globals.CONNECT_TIMEOUT = connectTimeout; - Globals.READ_TIMEOUT = readTimeout; - } + (new Thread(runnable)).start(); } diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/ui/ManageGenomesDialog.java igv-2.3.90+dfsg/src/org/broad/igv/ui/ManageGenomesDialog.java --- igv-2.3.88+dfsg/src/org/broad/igv/ui/ManageGenomesDialog.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/ui/ManageGenomesDialog.java 2017-01-09 04:30:59.000000000 +0000 @@ -108,12 +108,6 @@ countHasSeq++; } } - - if(countHasSeq > 0){ - String msg = String.format("%d of the genomes you chose to remove have downloaded sequences. Those will be deleted as well. Are you sure?", countHasSeq); - boolean sure = MessageUtils.confirm(msg); - if(!sure) return; - } } cancelled = false; diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/ui/panel/DataPanelContainer.java igv-2.3.90+dfsg/src/org/broad/igv/ui/panel/DataPanelContainer.java --- igv-2.3.88+dfsg/src/org/broad/igv/ui/panel/DataPanelContainer.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/ui/panel/DataPanelContainer.java 2017-01-09 04:30:59.000000000 +0000 @@ -27,8 +27,6 @@ import org.apache.log4j.Logger; import org.broad.igv.exceptions.DataLoadException; -import org.broad.igv.feature.FeatureUtils; -import org.broad.igv.feature.LocusScore; import org.broad.igv.renderer.DataRange; import org.broad.igv.track.*; import org.broad.igv.ui.IGV; @@ -53,16 +51,9 @@ private static Logger log = Logger.getLogger(DataPanelContainer.class); - static int lastStateHash = 0; // TODO -- could synchronization be an issue? - TrackPanel parent; - public static void resetStateHash() { - lastStateHash = 0; - } - - public DataPanelContainer(TrackPanel trackPanel) { super(trackPanel); @@ -261,28 +252,36 @@ private void autoscale() { - int stateHash = FrameManager.getStateHash(); - - //if(lastStateHash == stateHash) return; - - lastStateHash = stateHash; - final Collection trackList = IGV.getInstance().getAllTracks(); Map> autoscaleGroups = new HashMap>(); for (Track track : trackList) { - if(!track.isVisible()) continue; + if (!track.isVisible()) continue; String asGroup = track.getAttributeValue(AttributeManager.GROUP_AUTOSCALE); if (asGroup != null) { if (!autoscaleGroups.containsKey(asGroup)) { autoscaleGroups.put(asGroup, new ArrayList()); } - autoscaleGroups.get(asGroup).add(track); + + if (track instanceof MergedTracks) { + for (Track mt : ((MergedTracks) track).getMemberTracks()) { + autoscaleGroups.get(asGroup).add(track); + } + } else { + autoscaleGroups.get(asGroup).add(track); + } } else if (track.getAutoScale()) { - autoscaleGroup(Arrays.asList(track)); + + if (track instanceof MergedTracks) { + for (Track mt : ((MergedTracks) track).getMemberTracks()) { + autoscaleGroup(Arrays.asList(mt)); + } + } else { + autoscaleGroup(Arrays.asList(track)); + } } diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/ui/panel/RegionNavigatorDialog.java igv-2.3.90+dfsg/src/org/broad/igv/ui/panel/RegionNavigatorDialog.java --- igv-2.3.88+dfsg/src/org/broad/igv/ui/panel/RegionNavigatorDialog.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/ui/panel/RegionNavigatorDialog.java 2017-01-09 04:30:59.000000000 +0000 @@ -30,6 +30,7 @@ import org.apache.log4j.Logger; import org.broad.igv.feature.Range; import org.broad.igv.feature.RegionOfInterest; +import org.broad.igv.feature.Strand; import org.broad.igv.feature.genome.GenomeManager; import org.broad.igv.lists.GeneList; import org.broad.igv.ui.IGV; @@ -817,7 +818,7 @@ JOptionPane.showMessageDialog(RegionNavigatorDialog.this, "Region is to large to copy sequence data."); } else { IGV.copySequenceToClipboard(GenomeManager.getInstance().getCurrentGenome(), - chr, start, end); + chr, start, end, Strand.NONE); } } }); diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/ui/panel/RegionOfInterestPanel.java igv-2.3.90+dfsg/src/org/broad/igv/ui/panel/RegionOfInterestPanel.java --- igv-2.3.88+dfsg/src/org/broad/igv/ui/panel/RegionOfInterestPanel.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/ui/panel/RegionOfInterestPanel.java 2017-01-09 04:30:59.000000000 +0000 @@ -30,6 +30,7 @@ package org.broad.igv.ui.panel; import org.broad.igv.Globals; +import org.broad.igv.feature.Strand; import org.broad.igv.util.blat.BlatClient; import org.broad.igv.feature.RegionOfInterest; import org.broad.igv.feature.genome.Genome; @@ -182,7 +183,7 @@ public void run() { Genome genome = GenomeManager.getInstance().getCurrentGenome(); - IGV.copySequenceToClipboard(genome, roi.getChr(), roi.getStart(), roi.getEnd()); + IGV.copySequenceToClipboard(genome, roi.getChr(), roi.getStart(), roi.getEnd(), Strand.NONE); } }); } @@ -198,7 +199,7 @@ item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { - BlatClient.doBlatQuery(roi.getChr(), roi.getStart(), roi.getEnd()); + BlatClient.doBlatQuery(roi.getChr(), roi.getStart(), roi.getEnd(), Strand.NONE); } }); popupMenu.add(item); diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/ui/panel/TrackNamePanel.java igv-2.3.90+dfsg/src/org/broad/igv/ui/panel/TrackNamePanel.java --- igv-2.3.88+dfsg/src/org/broad/igv/ui/panel/TrackNamePanel.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/ui/panel/TrackNamePanel.java 2017-01-09 04:30:59.000000000 +0000 @@ -540,37 +540,22 @@ /** - * Mouse was clicked. Delegate single-click action to the track(s) clicked on. We won't know if this - * is a double click or not until the double-click interval has passed, so defer the action with a - * TimerTask. If a second click arrives it will be canceled. + * Mouse was clicked. Delegate single-click action to the track(s) clicked on. * * @param e */ @Override public void mouseClicked(final MouseEvent e) { - // If this is the second click of a double click, cancel the scheduled single click task. - if (e.getClickCount() > 1) { - clickScheduler.cancelClickTask(); - return; - } - - TimerTask clickTask = new TimerTask() { - - @Override - public void run() { - for (MouseableRegion mouseRegion : mouseRegions) { - if (mouseRegion.containsPoint(e.getX(), e.getY())) { - for (Track t : mouseRegion.getTracks()) { - t.handleNameClick(e); - } - return; - } - }//To change body of implemented methods use File | Settings | File Templates. + for (MouseableRegion mouseRegion : mouseRegions) { + if (mouseRegion.containsPoint(e.getX(), e.getY())) { + for (Track t : mouseRegion.getTracks()) { + t.handleNameClick(e); + } + return; } - }; - //clickScheduler.scheduleClickTask(clickTask); - clickTask.run(); + }//To change body of implemented methods use File | Settings | File Templates. + } protected void fireGhostDropEvent(GhostDropEvent evt) { diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/ui/util/CancellableProgressDialog.java igv-2.3.90+dfsg/src/org/broad/igv/ui/util/CancellableProgressDialog.java --- igv-2.3.88+dfsg/src/org/broad/igv/ui/util/CancellableProgressDialog.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/ui/util/CancellableProgressDialog.java 2017-01-09 04:30:59.000000000 +0000 @@ -172,7 +172,10 @@ * @param monitor Optional (may be null). Status text is updated based on monitor.updateStatus * @return */ - public static CancellableProgressDialog showCancellableProgressDialog(Frame dialogsParent, String title, final ActionListener buttonActionListener, final boolean autoClose, ProgressMonitor monitor){ + public static CancellableProgressDialog showCancellableProgressDialog(Frame dialogsParent, + String title, final + ActionListener buttonActionListener, + final boolean autoClose, ProgressMonitor monitor){ final CancellableProgressDialog progressDialog = new CancellableProgressDialog(dialogsParent); progressDialog.setTitle(title); diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/ui/util/ConvertFileDialog.java igv-2.3.90+dfsg/src/org/broad/igv/ui/util/ConvertFileDialog.java --- igv-2.3.88+dfsg/src/org/broad/igv/ui/util/ConvertFileDialog.java 1970-01-01 00:00:00.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/ui/util/ConvertFileDialog.java 2017-01-09 04:30:59.000000000 +0000 @@ -0,0 +1,257 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2007-2015 Broad Institute + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +/* + * Created by JFormDesigner on Tue Nov 15 14:22:59 EST 2016 + */ + +package org.broad.igv.ui.util; + +import org.broad.igv.Globals; +import org.broad.igv.PreferenceManager; +import org.broad.igv.ui.IGV; + +import java.awt.*; +import java.awt.event.*; +import java.text.NumberFormat; +import javax.swing.*; +import javax.swing.border.*; +import javax.swing.text.DefaultFormatterFactory; +import javax.swing.text.NumberFormatter; + +import java.util.*; + +/** + * Before converting .shape, .map, .ct, .db, or .dp files (associated with individual RNAs) + * to IGV-loadable formats, allow the user to select the applicable chromosome, + * coordinate offset, and strand, since that information is not present in those files. + * + * @author sbusan + */ +public class ConvertFileDialog extends JDialog { + + ConvertOptions opts = new ConvertOptions(); + + private ConvertFileDialog(Frame owner, String message, java.util.List chromosomes) { + super(owner); + this.setModal(true); + initComponents(); + label.setText("" + message + ""); + okButton.setText("Continue"); + + // FIXME: limit input to empty string or integer + /*NumberFormat format = NumberFormat.getInstance(); + NumberFormatter formatter = new NumberFormatter(format); + formatter.setValueClass(Integer.class); + formatter.setMinimum(0); + formatter.setMaximum(Integer.MAX_VALUE); + formatter.setAllowsInvalid(false); + DefaultFormatterFactory factory = new DefaultFormatterFactory(formatter); + startTextField.setFormatterFactory(factory);*/ + + DefaultComboBoxModel boxModel = new DefaultComboBoxModel(); + for (String chrom : chromosomes) { + boxModel.addElement(chrom); + } + chromBox.setModel(boxModel); + + getRootPane().setDefaultButton(okButton); + } + + public static ConvertOptions showConvertFileDialog(String message) { + ConvertFileDialog dlg = new ConvertFileDialog(IGV.getMainFrame(), + message, + IGV.getInstance().getGenomeManager().getCurrentGenome().getAllChromosomeNames()); + dlg.setVisible(true); + dlg.opts.chrom = dlg.chromBox.getSelectedItem().toString(); + dlg.opts.start = Integer.parseInt(dlg.startTextField.getText()); + if (dlg.reverseRadio.isSelected()) dlg.opts.strand = "-"; + return dlg.opts; + } + + private void cancelButtonActionPerformed(ActionEvent e) { + opts.doConvert = false; + setVisible(false); + } + + private void okButtonActionPerformed(ActionEvent e) { + opts.doConvert = true; + setVisible(false); + } + + private void initComponents() { + // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents + // Generated using JFormDesigner non-commercial license + dialogPane = new JPanel(); + contentPanel = new JPanel(); + label = new JLabel(); + forwardRadio = new JRadioButton(); + reverseRadio = new JRadioButton(); + label1 = new JLabel(); + label2 = new JLabel(); + label3 = new JLabel(); + startTextField = new JFormattedTextField(); + chromBox = new JComboBox(); + buttonBar = new JPanel(); + cancelButton = new JButton(); + okButton = new JButton(); + + //======== this ======== + setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + setResizable(false); + Container contentPane = getContentPane(); + contentPane.setLayout(new BorderLayout()); + + //======== dialogPane ======== + { + dialogPane.setBorder(new EmptyBorder(12, 12, 12, 12)); + dialogPane.setLayout(new BorderLayout()); + + //======== contentPanel ======== + { + contentPanel.setLayout(null); + + //---- label ---- + label.setText("text"); + label.setFont(label.getFont().deriveFont(label.getFont().getStyle() & ~Font.BOLD)); + contentPanel.add(label); + label.setBounds(0, 0, 415, 140); + + //---- forwardRadio ---- + forwardRadio.setText("Forward"); + forwardRadio.setSelected(true); + contentPanel.add(forwardRadio); + forwardRadio.setBounds(65, 180, forwardRadio.getPreferredSize().width, 23); + + //---- reverseRadio ---- + reverseRadio.setText("Reverse"); + contentPanel.add(reverseRadio); + reverseRadio.setBounds(145, 180, reverseRadio.getPreferredSize().width, 23); + + //---- label1 ---- + label1.setText("Strand:"); + label1.setHorizontalAlignment(SwingConstants.RIGHT); + contentPanel.add(label1); + label1.setBounds(5, 185, label1.getPreferredSize().width, 15); + + //---- label2 ---- + label2.setText("Chr:"); + label2.setHorizontalAlignment(SwingConstants.RIGHT); + contentPanel.add(label2); + label2.setBounds(10, 155, 42, 15); + + //---- label3 ---- + label3.setText("Start:"); + label3.setHorizontalAlignment(SwingConstants.RIGHT); + contentPanel.add(label3); + label3.setBounds(5, 215, 49, 15); + + //---- startTextField ---- + startTextField.setText("1"); + contentPanel.add(startTextField); + startTextField.setBounds(65, 210, 165, startTextField.getPreferredSize().height); + + //---- chromBox ---- + chromBox.setMaximumRowCount(100); + contentPanel.add(chromBox); + chromBox.setBounds(65, 150, 165, chromBox.getPreferredSize().height); + + { // compute preferred size + Dimension preferredSize = new Dimension(); + for (int i = 0; i < contentPanel.getComponentCount(); i++) { + Rectangle bounds = contentPanel.getComponent(i).getBounds(); + preferredSize.width = Math.max(bounds.x + bounds.width, preferredSize.width); + preferredSize.height = Math.max(bounds.y + bounds.height, preferredSize.height); + } + Insets insets = contentPanel.getInsets(); + preferredSize.width += insets.right; + preferredSize.height += insets.bottom; + contentPanel.setMinimumSize(preferredSize); + contentPanel.setPreferredSize(preferredSize); + } + } + dialogPane.add(contentPanel, BorderLayout.CENTER); + + //======== buttonBar ======== + { + buttonBar.setBorder(new EmptyBorder(12, 0, 0, 0)); + buttonBar.setLayout(new GridBagLayout()); + ((GridBagLayout) buttonBar.getLayout()).columnWidths = new int[]{0, 0, 80}; + ((GridBagLayout) buttonBar.getLayout()).columnWeights = new double[]{1.0, 0.0, 0.0}; + + //---- cancelButton ---- + cancelButton.setText("Cancel"); + cancelButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + cancelButtonActionPerformed(e); + } + }); + buttonBar.add(cancelButton, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 5, 5), 0, 0)); + + //---- okButton ---- + okButton.setText("OK"); + okButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + okButtonActionPerformed(e); + } + }); + buttonBar.add(okButton, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 5, 0), 0, 0)); + } + dialogPane.add(buttonBar, BorderLayout.SOUTH); + } + contentPane.add(dialogPane, BorderLayout.CENTER); + setSize(450, 355); + setLocationRelativeTo(getOwner()); + + //---- buttonGroup1 ---- + ButtonGroup buttonGroup1 = new ButtonGroup(); + buttonGroup1.add(forwardRadio); + buttonGroup1.add(reverseRadio); + // JFormDesigner - End of component initialization //GEN-END:initComponents + } + + // JFormDesigner - Variables declaration - DO NOT MODIFY //GEN-BEGIN:variables + // Generated using JFormDesigner non-commercial license + private JPanel dialogPane; + private JPanel contentPanel; + private JLabel label; + private JRadioButton forwardRadio; + private JRadioButton reverseRadio; + private JLabel label1; + private JLabel label2; + private JLabel label3; + private JFormattedTextField startTextField; + private JComboBox chromBox; + private JPanel buttonBar; + private JButton cancelButton; + private JButton okButton; + // JFormDesigner - End of variables declaration //GEN-END:variables +} diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/ui/util/ConvertFileDialog.jfd igv-2.3.90+dfsg/src/org/broad/igv/ui/util/ConvertFileDialog.jfd --- igv-2.3.88+dfsg/src/org/broad/igv/ui/util/ConvertFileDialog.jfd 1970-01-01 00:00:00.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/ui/util/ConvertFileDialog.jfd 2017-01-09 04:30:59.000000000 +0000 @@ -0,0 +1,481 @@ + + + + + form/swing + + + + + + javax.swing.JDialog + + java.awt.BorderLayout + + + defaultCloseOperation + 2 + + + $sizePolicy + 1 + + + resizable + false + + + + javax.swing.JPanel + + java.awt.BorderLayout + + + border + + 12 + 12 + 12 + 12 + + + + dialogPane + + + + javax.swing.JPanel + + com.jformdesigner.runtime.NullLayout + + + contentPanel + + + + javax.swing.JLabel + + text + text + + + font + + + 65536 + 0 + false + + + + label + + + + com.jformdesigner.runtime.NullConstraints + + x + 0 + + + y + 0 + + + width + 415 + + + height + 140 + + + + + + javax.swing.JRadioButton + + text + Forward + + + selected + true + + + $buttonGroup + + buttonGroup1 + + + + forwardRadio + + + + com.jformdesigner.runtime.NullConstraints + + x + 65 + + + y + 180 + + + height + 23 + + + + + + javax.swing.JRadioButton + + text + Reverse + + + $buttonGroup + + buttonGroup1 + + + + reverseRadio + + + + com.jformdesigner.runtime.NullConstraints + + x + 145 + + + y + 180 + + + height + 23 + + + + + + javax.swing.JLabel + + text + Strand: + + + horizontalAlignment + 4 + + + label1 + + + + com.jformdesigner.runtime.NullConstraints + + x + 5 + + + y + 185 + + + height + 15 + + + + + + javax.swing.JLabel + + text + Chr: + + + horizontalAlignment + 4 + + + label2 + + + + com.jformdesigner.runtime.NullConstraints + + width + 42 + + + height + 15 + + + x + 10 + + + y + 155 + + + + + + javax.swing.JLabel + + text + Start: + + + horizontalAlignment + 4 + + + label3 + + + + com.jformdesigner.runtime.NullConstraints + + width + 49 + + + height + 15 + + + x + 5 + + + y + 215 + + + + + + javax.swing.JFormattedTextField + + text + 1 + + + startTextField + + + + com.jformdesigner.runtime.NullConstraints + + x + 65 + + + y + 210 + + + width + 165 + + + + + + javax.swing.JComboBox + + maximumRowCount + 100 + + + chromBox + + + + com.jformdesigner.runtime.NullConstraints + + x + 65 + + + y + 150 + + + width + 165 + + + + + + java.lang.String + + value + Center + + + + + + javax.swing.JPanel + + java.awt.GridBagLayout + + $columnSpecs + 0:1.0, 0, 80 + + + $rowSpecs + 0, 0 + + + $hGap + 5 + + + $vGap + 5 + + + + border + + 12 + 0 + 0 + 0 + + + + buttonBar + + + + javax.swing.JButton + + text + Cancel + + + cancelButton + + + + java.awt.event.ActionListener + actionPerformed + cancelButtonActionPerformed + true + + + + + com.jformdesigner.runtime.GridBagConstraintsEx + + gridx + 1 + + + + + + javax.swing.JButton + + text + OK + + + okButton + + + + java.awt.event.ActionListener + actionPerformed + okButtonActionPerformed + true + + + + + com.jformdesigner.runtime.GridBagConstraintsEx + + gridx + 2 + + + gridy + 0 + + + + + + java.lang.String + + value + South + + + + + + java.lang.String + + value + Center + + + + + this + + + + + + location + + 0 + 0 + + + + size + + 450 + 355 + + + + + + + javax.swing.ButtonGroup + + buttonGroup1 + + + + + + location + + 0 + 316 + + + + + + + + diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/ui/util/ConvertOptions.java igv-2.3.90+dfsg/src/org/broad/igv/ui/util/ConvertOptions.java --- igv-2.3.88+dfsg/src/org/broad/igv/ui/util/ConvertOptions.java 1970-01-01 00:00:00.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/ui/util/ConvertOptions.java 2017-01-09 04:30:59.000000000 +0000 @@ -0,0 +1,34 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2007-2015 Broad Institute + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + + +package org.broad.igv.ui.util; + +public class ConvertOptions { + public boolean doConvert = false; + public String chrom = ""; + public String strand = "+"; + public int start = 1; +} diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/ui/util/ProgressBar.java igv-2.3.90+dfsg/src/org/broad/igv/ui/util/ProgressBar.java --- igv-2.3.88+dfsg/src/org/broad/igv/ui/util/ProgressBar.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/ui/util/ProgressBar.java 2017-01-09 04:30:59.000000000 +0000 @@ -78,7 +78,7 @@ progressBar.setValue(progress); - if (progress > 99 && closeOnCompletion) { + if (progress == 100 && closeOnCompletion) { setReady(false); // Accept no more input progressParentWindow.setVisible(false); } @@ -237,4 +237,4 @@ return isReady; } -} \ No newline at end of file +} diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/ui/util/ProgressMonitor.java igv-2.3.90+dfsg/src/org/broad/igv/ui/util/ProgressMonitor.java --- igv-2.3.88+dfsg/src/org/broad/igv/ui/util/ProgressMonitor.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/ui/util/ProgressMonitor.java 2017-01-09 04:30:59.000000000 +0000 @@ -76,6 +76,26 @@ } } + /** + * Sends an event to update the listening progress bar. + * + * @param newValue This value is the percent amount completed (which goes from 0 to 100). + */ + public void fireProgress(final int newValue) { + + if (isReady) { + + PropertyChangeEvent event = + new PropertyChangeEvent( + this, + PROGRESS_PROPERTY, + oldValue, + newValue); + propertyChangeSupport.firePropertyChange(event); + oldValue = newValue; + } + } + public void updateStatus(String newStatus){ if(isReady){ PropertyChangeEvent event = new PropertyChangeEvent(this, STATUS_PROPERTY, @@ -102,4 +122,4 @@ public boolean isReady() { return isReady; } -} \ No newline at end of file +} diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/util/blat/BlatClient.java igv-2.3.90+dfsg/src/org/broad/igv/util/blat/BlatClient.java --- igv-2.3.88+dfsg/src/org/broad/igv/util/blat/BlatClient.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/util/blat/BlatClient.java 2017-01-09 04:30:59.000000000 +0000 @@ -28,13 +28,11 @@ import org.broad.igv.Globals; import org.broad.igv.PreferenceManager; import org.broad.igv.feature.PSLRecord; +import org.broad.igv.feature.Strand; import org.broad.igv.feature.genome.Genome; import org.broad.igv.feature.genome.GenomeManager; import org.broad.igv.feature.tribble.PSLCodec; -import org.broad.igv.track.FeatureCollectionSource; -import org.broad.igv.track.FeatureSource; -import org.broad.igv.track.FeatureTrack; -import org.broad.igv.track.Track; +import org.broad.igv.track.*; import org.broad.igv.ui.IGV; import org.broad.igv.ui.util.MessageUtils; import org.broad.igv.util.HttpUtils; @@ -221,7 +219,7 @@ return records; } - public static void doBlatQuery(final String chr, final int start, final int end) { + public static void doBlatQuery(final String chr, final int start, final int end, Strand strand) { if((end - start) > 8000) { MessageUtils.showMessage("BLAT searches are limited to 8kb. Please try a shorter sequence."); @@ -232,6 +230,10 @@ final byte[] seqBytes = genome.getSequence(chr, start, end); String userSeq = new String(seqBytes); + if(strand == Strand.NEGATIVE) { + userSeq = SequenceTrack.getReverseComplement(userSeq); + } + doBlatQuery(userSeq); } diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/util/HttpUtils.java igv-2.3.90+dfsg/src/org/broad/igv/util/HttpUtils.java --- igv-2.3.88+dfsg/src/org/broad/igv/util/HttpUtils.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/util/HttpUtils.java 2017-01-09 04:30:59.000000000 +0000 @@ -458,7 +458,7 @@ urlDownloader.run(); return urlDownloader; } else { - ProgressMonitor monitor = new ProgressMonitor(); + javax.swing.ProgressMonitor monitor = new javax.swing.ProgressMonitor(IGV.getInstance().getMainPanel(), "Downloading " + outputFile.getName(), "", 0, 100); urlDownloader.setMonitor(monitor); ActionListener buttonListener = new ActionListener() { @Override @@ -466,15 +466,15 @@ urlDownloader.cancel(true); } }; - String permText = "Downloading " + url; - String title = dialogTitle != null ? dialogTitle : permText; - CancellableProgressDialog dialog = CancellableProgressDialog.showCancellableProgressDialog(dialogsParent, title, buttonListener, false, monitor); - dialog.setPermText(permText); + // String permText = "Downloading " + url; + // String title = dialogTitle != null ? dialogTitle : permText; + // CancellableProgressDialog dialog = CancellableProgressDialog.showCancellableProgressDialog(dialogsParent, title, buttonListener, false, monitor); + // dialog.setPermText(permText); - Dimension dms = new Dimension(600, 150); - dialog.setPreferredSize(dms); - dialog.setSize(dms); - dialog.validate(); + // Dimension dms = new Dimension(600, 150); + // dialog.setPreferredSize(dms); + // dialog.setSize(dms); + // dialog.validate(); LongRunningTask.submit(urlDownloader); return urlDownloader; diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/util/URLDownloader.java igv-2.3.90+dfsg/src/org/broad/igv/util/URLDownloader.java --- igv-2.3.88+dfsg/src/org/broad/igv/util/URLDownloader.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/util/URLDownloader.java 2017-01-09 04:30:59.000000000 +0000 @@ -42,7 +42,7 @@ private static Logger log = Logger.getLogger(URLDownloader.class); - private ProgressMonitor monitor = null; + private javax.swing.ProgressMonitor monitor = null; private final URL srcUrl; private final File outputFile; @@ -100,7 +100,6 @@ OutputStream out = null; long downloaded = 0; - long downSinceLast = 0; String curStatus; String msg1 = String.format("downloaded of %s total", contentLength >= 0 ? bytesToByteCountString(contentLength) : "unknown"); int perc = 0; @@ -111,21 +110,26 @@ byte[] buf = new byte[64 * 1024]; int counter = 0; int interval = 100; - int bytesRead = 0; + int bytesRead; while (!this.cancelled && (bytesRead = is.read(buf)) != -1) { out.write(buf, 0, bytesRead); downloaded += bytesRead; - downSinceLast += bytesRead; counter = (counter + 1) % interval; if (counter == 0 && this.monitor != null) { curStatus = String.format("%s %s", bytesToByteCountString(downloaded), msg1); - this.monitor.updateStatus(curStatus); + this.monitor.setNote(curStatus); if (contentLength >= 0) { - perc = (int) ((downSinceLast * 100) / contentLength); - this.monitor.fireProgressChange(perc); - if (perc >= 1) downSinceLast = 0; + perc = (int) ((downloaded * 100) / contentLength); + this.monitor.setProgress(perc); } } + + if(this.monitor != null && this.monitor.isCanceled()) { + is.close(); + outputFile.delete(); + this.cancelled = true; + } + } log.info("Download complete. Total bytes downloaded = " + downloaded); } catch (IOException e) { @@ -140,14 +144,15 @@ } long fileLength = outputFile.length(); + if (this.cancelled) return RunnableResult.CANCELLED; boolean knownComplete = contentLength == fileLength; //Assume success if file length not known if (knownComplete || contentLength < 0) { if (this.monitor != null) { - this.monitor.fireProgressChange(100); - this.monitor.updateStatus("Done"); + this.monitor.setProgress(100); + this.monitor.setNote("Done"); } return RunnableResult.SUCCESS; } else { @@ -178,7 +183,7 @@ return true; } - public void setMonitor(ProgressMonitor monitor) { + public void setMonitor(javax.swing.ProgressMonitor monitor) { this.monitor = monitor; } diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/util/Utilities.java igv-2.3.90+dfsg/src/org/broad/igv/util/Utilities.java --- igv-2.3.88+dfsg/src/org/broad/igv/util/Utilities.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/util/Utilities.java 2017-01-09 04:30:59.000000000 +0000 @@ -245,4 +245,23 @@ } } + + public static boolean isAllLetters(String s) { + byte [] bytes = s.getBytes(); + for(int i=0; i> Character.getType(codePoint)) & 1) + != 0; + } } diff -Nru igv-2.3.88+dfsg/src/org/broad/igv/variant/VariantRenderer.java igv-2.3.90+dfsg/src/org/broad/igv/variant/VariantRenderer.java --- igv-2.3.88+dfsg/src/org/broad/igv/variant/VariantRenderer.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/src/org/broad/igv/variant/VariantRenderer.java 2017-01-09 04:30:59.000000000 +0000 @@ -222,11 +222,6 @@ Genotype genotype = variant.getGenotype(sampleName); - if (sampleName.equals("CYP26B1-B12")) { - System.out.println(genotype.getTypeString() + " " + genotype.getGenotypeString() + " " + isFiltered); - } - - if (genotype == null) { log.error("Genotype not found for sample " + sampleName); } else { diff -Nru igv-2.3.88+dfsg/test/src/org/broad/igv/util/SeekableServiceStreamTest.java igv-2.3.90+dfsg/test/src/org/broad/igv/util/SeekableServiceStreamTest.java --- igv-2.3.88+dfsg/test/src/org/broad/igv/util/SeekableServiceStreamTest.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/test/src/org/broad/igv/util/SeekableServiceStreamTest.java 2017-01-09 04:30:59.000000000 +0000 @@ -48,7 +48,7 @@ @Test public void testRead() throws Exception { - String tdfFile = "http://data.broadinstitute.org/igvdata/annotations/hg18/conservation/omega.12mer.tdf"; + String tdfFile = "https://data.broadinstitute.org/igvdata/annotations/hg18/conservation/omega.12mer.tdf"; HttpUtils.getInstance().updateProxySettings(); diff -Nru igv-2.3.88+dfsg/test/src/org/broad/igv/util/TestByteRange.java igv-2.3.90+dfsg/test/src/org/broad/igv/util/TestByteRange.java --- igv-2.3.88+dfsg/test/src/org/broad/igv/util/TestByteRange.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/test/src/org/broad/igv/util/TestByteRange.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,73 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2007-2015 Broad Institute - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -package org.broad.igv.util; - -import org.junit.Test; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.HttpURLConnection; -import java.net.URL; - -import static org.junit.Assert.assertTrue; - - -/** - * @author Jim Robinson - * @date 12/21/11 - */ -public class TestByteRange { - - @Test - public void testByteRange() throws Exception { - - String urlString = "http://www.broadinstitute.org/igv/projects/dev/echo.php"; - String byteRange = "bytes=" + 5 + "-" + 10; - HttpURLConnection conn = (HttpURLConnection) (new URL(urlString)).openConnection(); - conn.setRequestMethod("GET"); - conn.setRequestProperty("Range", byteRange); - - InputStream is = null; - - int lines = 0; - try { - is = conn.getInputStream(); - BufferedReader br = new BufferedReader(new InputStreamReader(is)); - String nextLine; - while ((nextLine = br.readLine()) != null) { - lines++; - } - - } finally { - if (is != null) { - is.close(); - } - } - assertTrue(lines > 0); - } -} diff -Nru igv-2.3.88+dfsg/test/src/org/broad/igv/util/TestS3Access.java igv-2.3.90+dfsg/test/src/org/broad/igv/util/TestS3Access.java --- igv-2.3.88+dfsg/test/src/org/broad/igv/util/TestS3Access.java 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/test/src/org/broad/igv/util/TestS3Access.java 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +0,0 @@ -/* - * The MIT License (MIT) - * - * Copyright (c) 2007-2015 Broad Institute - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - - -package org.broad.igv.util; - -import org.junit.Ignore; -import org.junit.Test; - -import java.io.*; -import java.net.URL; -import java.util.Arrays; - -import static org.junit.Assert.assertTrue; - -/** - * Timing test for S3 storage files - */ -@Ignore //Not sure about URLs -public class TestS3Access { - - public static void main(String[] args) { - try { - testAsciiDownloadStatic(); - } catch (IOException e) { - e.printStackTrace(); //To change body of catch statement use File | Settings | File Templates. - } - } - - @Test - public void testAsciiDownload() throws Exception{ - testAsciiDownloadStatic(); - } - public static void testAsciiDownloadStatic() throws IOException { - - String broadURL = "http://data.broadinstitute.org/igvdata/annotations/hg18/refGene.txt"; - String s3URL = "http://s3.amazonaws.com/genomespace-igv/refGene.txt"; - - try { - - - for (int i = 0; i < 10; i++) { - for (String url : Arrays.asList(broadURL, s3URL)) { - - InputStream inputStream = HttpUtils.getInstance().openConnectionStream(new URL(url)); - BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); - int nLines = 0; - long t0 = System.currentTimeMillis(); - while (reader.readLine() != null) { - nLines++; - } - //System.out.println(url + " read " + nLines + " in " + (System.currentTimeMillis() - t0) + " ms "); - reader.close(); - assertTrue(nLines > 0); - } - } - } finally { - } - } -} diff -Nru igv-2.3.88+dfsg/test/src/org/broad/igv/util/UtilitiesTest.java igv-2.3.90+dfsg/test/src/org/broad/igv/util/UtilitiesTest.java --- igv-2.3.88+dfsg/test/src/org/broad/igv/util/UtilitiesTest.java 1970-01-01 00:00:00.000000000 +0000 +++ igv-2.3.90+dfsg/test/src/org/broad/igv/util/UtilitiesTest.java 2017-01-09 04:30:59.000000000 +0000 @@ -0,0 +1,24 @@ +package org.broad.igv.util; + +import org.junit.Test; + +import static org.junit.Assert.*; + +/** + * Created by jrobinso on 12/17/16. + */ +public class UtilitiesTest { + @Test + public void isAllLetters() throws Exception { + + boolean b = Utilities.isAllLetters("StringWithNothingButLetters"); + assertTrue(b); + + b = Utilities.isAllLetters("StringWithNumbers123"); + assertFalse(b); + + b = Utilities.isAllLetters("String with spaces"); + assertFalse(b); + } + +} \ No newline at end of file diff -Nru igv-2.3.88+dfsg/web/StaticLinkExamples.html igv-2.3.90+dfsg/web/StaticLinkExamples.html --- igv-2.3.88+dfsg/web/StaticLinkExamples.html 2016-11-07 10:42:41.000000000 +0000 +++ igv-2.3.90+dfsg/web/StaticLinkExamples.html 2017-01-09 04:30:59.000000000 +0000 @@ -6,27 +6,31 @@ -

- Dev launch link with name, merge = false

-

- Prod launch link with name

-

- Prod launch link with name, merge = false

-

- Prod igv.php link with name

-

- Direct load with name

-

- Direct load with name, merge = false

-

- Direct load no name

+

+ + Launch link with name

+

+ + Launch link with name, merge = false

+

+ + Direct load with name

+

+ + Direct load with name, merge = false

+

+ + Direct load with name, merge = true

+

+ + Direct load no name

+

+ Load fasta

+

+ + Direct load with fasta, merge=true

Batch sort

-

-