From 752375e76ab4209f8c4c8db3cbd40c24d9dff3d9 Mon Sep 17 00:00:00 2001 From: jrobinso <933148+jrobinso@users.noreply.github.com> Date: Tue, 28 Nov 2023 14:04:09 -0800 Subject: [PATCH] bug fixes --- .../igv/feature/genome/GenomeManager.java | 5 +- src/main/java/org/broad/igv/ui/IGV.java | 25 ++-- .../broad/igv/ui/action/SearchCommand.java | 137 +++++++----------- .../igv/ui/commandbar/IGVCommandBar.java | 2 +- .../org/broad/igv/ui/panel/HeaderPanel.java | 2 +- .../broad/igv/ui/panel/ReferenceFrame.java | 8 +- .../igv/ui/action/SearchCommandTest.java | 18 +-- 7 files changed, 84 insertions(+), 113 deletions(-) diff --git a/src/main/java/org/broad/igv/feature/genome/GenomeManager.java b/src/main/java/org/broad/igv/feature/genome/GenomeManager.java index 81f9a816d3..040050da0a 100644 --- a/src/main/java/org/broad/igv/feature/genome/GenomeManager.java +++ b/src/main/java/org/broad/igv/feature/genome/GenomeManager.java @@ -56,6 +56,7 @@ import org.broad.igv.ui.PanelName; import org.broad.igv.ui.commandbar.GenomeListManager; import org.broad.igv.ui.panel.FrameManager; +import org.broad.igv.ui.panel.ReferenceFrame; import org.broad.igv.ui.util.MessageUtils; import org.broad.igv.ui.util.ProgressBar; import org.broad.igv.ui.util.ProgressMonitor; @@ -72,6 +73,7 @@ import java.net.SocketException; import java.net.URL; import java.net.URLDecoder; +import java.sql.Ref; import java.util.*; import java.util.List; @@ -231,8 +233,9 @@ public Genome loadGenome(String genomePath, ProgressMonitor monitor) throws IOEx // hasInstance() test needed for unit tests if (IGV.hasInstance()) { - IGV.getInstance().goToLocus(newGenome.getDefaultPos()); + IGV.getInstance().goToLocus(newGenome.getHomeChromosome()); // newGenome.getDefaultPos()); loadGenomeAnnotations(newGenome); + IGV.getInstance().resetFrames(); } if (PreferencesManager.getPreferences().getAsBoolean(Constants.CIRC_VIEW_ENABLED) && CircularViewUtilities.ping()) { diff --git a/src/main/java/org/broad/igv/ui/IGV.java b/src/main/java/org/broad/igv/ui/IGV.java index b7fa6e962f..b0ad43ec92 100644 --- a/src/main/java/org/broad/igv/ui/IGV.java +++ b/src/main/java/org/broad/igv/ui/IGV.java @@ -259,7 +259,7 @@ public void windowGainedFocus(WindowEvent windowEvent) { subscribeToEvents(); // Start running periodic autosaves (unless the user has specified not to retain timed autosaves) - if(PreferencesManager.getPreferences().getAsInt(Constants.AUTOSAVES_TO_KEEP) > 0) { + if (PreferencesManager.getPreferences().getAsInt(Constants.AUTOSAVES_TO_KEEP) > 0) { int timerDelay = PreferencesManager.getPreferences().getAsInt(AUTOSAVE_FREQUENCY) * 60000; // Convert timer delay to ms sessionAutosaveTimer.scheduleAtFixedRate(new AutosaveTimerTask(this), timerDelay, timerDelay); } @@ -515,11 +515,10 @@ final public void saveStateForExit() { this.stopTimedAutosave(); // Autosave current session if configured to do so - if(PreferencesManager.getPreferences().getAsBoolean(AUTOSAVE_ON_EXIT)) { + if (PreferencesManager.getPreferences().getAsBoolean(AUTOSAVE_ON_EXIT)) { try { SessionAutosaveManager.saveExitSessionAutosaveFile(session); - } - catch(Exception e) { + } catch (Exception e) { log.error("Error autosaving session", e); } } @@ -885,9 +884,9 @@ public boolean scrollToTrack(String trackName) { if (tp.getScrollPane().getNamePanel().scrollTo(trackName)) { found = true; } - } - return found; } + return found; + } /** @@ -1238,7 +1237,7 @@ public List load(ResourceLocator locator) throws DataLoadException { track.setAttributeValue(Globals.TRACK_DATA_TYPE_ATTRIBUTE, track.getTrackType().toString()); TrackProperties properties = locator.getTrackProperties(); - if(properties != null) { + if (properties != null) { track.setProperties(properties); } } @@ -1287,7 +1286,7 @@ public TrackPanel getPanelFor(Track track) { } } - if(track.getClass() == FeatureTrack.class && !PreferencesManager.getPreferences().getAsBoolean(SHOW_SINGLE_TRACK_PANE_KEY)) + if (track.getClass() == FeatureTrack.class && !PreferencesManager.getPreferences().getAsBoolean(SHOW_SINGLE_TRACK_PANE_KEY)) return getTrackPanel(FEATURE_PANEL_NAME); else { return getTrackPanel(DATA_PANEL_NAME); @@ -1365,7 +1364,7 @@ public void sortAlignmentTracks(SortOption option, String tag, final boolean inv public void sortAlignmentTracks(SortOption option, Double location, String tag, boolean invertSort, Set priorityRecords) { List alignmentTracks = getAllTracks().stream() .filter(track -> track instanceof AlignmentTrack) - .map(track -> (AlignmentTrack)track) + .map(track -> (AlignmentTrack) track) .peek(track -> track.sortRows(option, location, tag, invertSort, priorityRecords)) .collect(Collectors.toList()); this.repaint(alignmentTracks); @@ -1900,8 +1899,7 @@ public void run() { boolean autosavePresent = false; try { autosavePresent = SessionAutosaveManager.getMostRecentAutosaveFile().isPresent(); - } - catch(Exception e) { + } catch (Exception e) { log.error("Failure trying to get most recent autosave file", e); } boolean loadAutosave = autosavePresent && PreferencesManager.getPreferences().getAsBoolean(AUTOLOAD_LAST_AUTOSAVE); @@ -1918,7 +1916,7 @@ public void run() { } } // If we're not loading a session file, attempt to load a default genome file - if(igvArgs.getSessionFile() == null && !loadAutosave && !genomeLoaded) { + if (igvArgs.getSessionFile() == null && !loadAutosave && !genomeLoaded) { String genomeId = preferences.getDefaultGenome(); try { GenomeManager.getInstance().loadGenomeById(genomeId); @@ -2041,8 +2039,7 @@ public void run() { // Get the last autosave and attempt to load File sessionAutosave = SessionAutosaveManager.getMostRecentAutosaveFile().get(); success = loadSession(sessionAutosave.getAbsolutePath(), null); - } - catch(Exception e) { + } catch (Exception e) { log.error("Failure trying to load most recent autosave file", e); } diff --git a/src/main/java/org/broad/igv/ui/action/SearchCommand.java b/src/main/java/org/broad/igv/ui/action/SearchCommand.java index b4675beea6..242779f91f 100644 --- a/src/main/java/org/broad/igv/ui/action/SearchCommand.java +++ b/src/main/java/org/broad/igv/ui/action/SearchCommand.java @@ -70,36 +70,10 @@ public class SearchCommand implements Runnable { Genome genome; - private static HashMap tokenMatchers; + private static HashMap tokenMatchers; - static { - - //Regexp for a number with commas in it (no periods) - String num_withcommas = "(((\\d)+,?)+)"; - - //chromosome can include anything except whitespace - String chromo_string = "(\\S)+"; - - String chromo = chromo_string; - //This will match chr1:1-100, chr1:1, chr1 1, chr1 1 100 - String chromo_range = chromo_string + "(:|(\\s)+)" + num_withcommas + "(-|(\\s)+)?" + num_withcommas + "?(\\s)*"; - - //Simple feature - String feature = chromo_string; - //Amino acid mutation notation. e.g. KRAS:G12C. * is stop codon - String featureMutAA = chromo_string + ":[A-Z,a-z,*]" + num_withcommas + "[A-Z,a-z,*]"; - - //Nucleotide mutation notation. e.g. KRAS:123A>T - String nts = "[A,C,G,T,a,c,g,t]"; - String featureMutNT = chromo_string + ":" + num_withcommas + nts + "\\>" + nts; - - tokenMatchers = new HashMap(); - tokenMatchers.put(ResultType.CHROMOSOME, chromo); - tokenMatchers.put(ResultType.FEATURE, feature); - tokenMatchers.put(ResultType.LOCUS, chromo_range); - tokenMatchers.put(ResultType.FEATURE_MUT_AA, featureMutAA); - tokenMatchers.put(ResultType.FEATURE_MUT_NT, featureMutNT); - } + static String featureMutAA = "(\\S)+" + ":[A-Z,a-z,*]" + "(((\\d)+,?)+)" + "[A-Z,a-z,*]"; + static String featureMutNT = "(\\S)+" + ":" + "(\\S)+" + "[A,C,G,T,a,c,g,t]" + "\\>" + "[A,C,G,T,a,c,g,t]"; public SearchCommand(ReferenceFrame referenceFrame, String searchString) { @@ -166,10 +140,10 @@ public List runSearch(String searchString) { } if (mightBeLocus) { Chromosome c1 = genome.getChromosome(tokens[0]); - if(c1 != null) { + if (c1 != null) { Chromosome c2 = genome.getChromosome(tokens[1]); - if(c2 == null) { - results.add (calcChromoLocus(searchString)); + if (c2 == null) { + results.add(calcChromoLocus(searchString)); return results; } } @@ -184,8 +158,6 @@ public List runSearch(String searchString) { } - - // If this is a liftover search map the results // if (liftover != null) { // List mappedResults = new ArrayList<>(); @@ -232,23 +204,23 @@ public void showSearchResult(List results) { showFlankedRegion(result.chr, result.start, result.end); break; case LOCUS: - - Chromosome chromosome = GenomeManager.getInstance().getCurrentGenome().getChromosome(result.chr); - if (chromosome == null) { - message = "Unknow chromosome: " + result.chr; - success = false; - showMessage = true; - } else if (result.start > chromosome.getLength()) { - message = "Range " + result.locus + " is beyond the end of the chromosome"; - success = false; - showMessage = true; + if (result.chr.equalsIgnoreCase(Globals.CHR_ALL)) { + referenceFrame.changeChromosome(Globals.CHR_ALL, false); } else { - referenceFrame.jumpTo(result.chr, result.start, result.end); + Chromosome chromosome = GenomeManager.getInstance().getCurrentGenome().getChromosome(result.chr); + if (chromosome == null) { + message = "Unknow chromosome: " + result.chr; + success = false; + showMessage = true; + } else if (result.start > chromosome.getLength()) { + message = "Range " + result.locus + " is beyond the end of the chromosome"; + success = false; + showMessage = true; + } else { + referenceFrame.jumpTo(result.chr, result.start, result.end); + } } break; - case CHROMOSOME: - referenceFrame.changeChromosome(result.chr, true); - break; case ERROR: default: { message = "Cannot find feature or locus: " + searchString; @@ -321,9 +293,9 @@ public static Object[] getSelectionList(List results, boolean long Set checkTokenType(String token) { token = token.trim(); Set possibles = new HashSet<>(); - for (ResultType type : tokenMatchers.keySet()) { - if (token.matches(tokenMatchers.get(type))) { //note: entire string must match - possibles.add(type); + for (String key : tokenMatchers.keySet()) { + if (token.matches(key)) { + possibles.add(tokenMatchers.get(key)); } } return possibles; @@ -343,32 +315,26 @@ private SearchResult parseToken(String token) { return new SearchResult(feat); } - //Guess at token type via regex. - //We don't assume success - Set types = checkTokenType(token); - if (types.contains(ResultType.LOCUS) || types.contains(ResultType.CHROMOSOME)) { - //Check if a full or partial locus string - SearchResult result = calcChromoLocus(token); - if (result != null) { - return result; - } + //Check if a full or partial locus string + SearchResult result = calcChromoLocus(token); + if (result != null) { + return result; } - - if (types.contains(ResultType.FEATURE)) { - //Check if we have an exact match for the feature name - List searchableTracks = IGV.getInstance().getAllTracks().stream().filter(Track::isSearchable).toList(); - for (Track t : searchableTracks) { - NamedFeature match = t.search(token); - if (match != null) { - return new SearchResult(match); - } + //Check if we have an exact match for the feature name + List searchableTracks = IGV.getInstance().getAllTracks().stream().filter(Track::isSearchable).toList(); + for (Track t : searchableTracks) { + NamedFeature match = t.search(token); + if (match != null) { + return new SearchResult(match); } } //2 possible mutation notations, either amino acid (A123B) or nucleotide (123G>C) - if (types.contains(ResultType.FEATURE_MUT_AA) || types.contains(ResultType.FEATURE_MUT_NT)) { + boolean mutAA = token.matches(featureMutAA); + boolean mutNT = token.matches(featureMutNT); + if (mutAA || mutNT) { //We know it has the right form, but may //not be valid feature name or mutation //which exists. @@ -380,7 +346,7 @@ private SearchResult parseToken(String token) { Map genomePosList; //Should never match both mutation notations - if (types.contains(ResultType.FEATURE_MUT_AA)) { + if (mutAA) { String refSymbol = coords.substring(0, 1); String mutSymbol = coords.substring(coordLength - 1); @@ -388,7 +354,7 @@ private SearchResult parseToken(String token) { int location = Integer.parseInt(strLoc) - 1; genomePosList = FeatureDB.getMutationAA(name, location + 1, refSymbol, mutSymbol, genome); - } else if (types.contains(ResultType.FEATURE_MUT_NT)) { + } else if (mutNT) { //Exclude the "A>T" at end String strLoc = coords.substring(0, coordLength - 3); String refSymbol = coords.substring(coordLength - 3, coordLength - 2); @@ -470,18 +436,24 @@ private SearchResult calcChromoLocus(String searchString) { int colonIdx = searchString.lastIndexOf(":"); if (colonIdx > 0) { chr = searchString.substring(0, colonIdx); - String posString = searchString.substring(colonIdx).replace(":", ""); - startEnd = getStartEnd(posString); - //This MAY for case of chromoname having semicolon in it - if (startEnd == null) { - chr = searchString; + Chromosome chromosome = genome.getChromosome(chr); + if (chromosome == null) { + // try entire search string, chr name may have embedded colon + if (genome.getChromosome(searchString) != null) { + chr = searchString; + startEnd = null; + } + } else { + String posString = searchString.substring(colonIdx).replace(":", ""); + startEnd = getStartEnd(posString); + } } } // Show the "All chromosomes" view if the search string is "*" if (chr.equals("*") || chr.toLowerCase().equals("all")) { - return new SearchResult(ResultType.CHROMOSOME, Globals.CHR_ALL, 0, 1); + return new SearchResult(ResultType.LOCUS, Globals.CHR_ALL, 0, Integer.MAX_VALUE); } //startEnd will have coordinates if found. @@ -498,12 +470,14 @@ private SearchResult calcChromoLocus(String searchString) { } if (chromosome != null && !searchString.equals(Globals.CHR_ALL)) { - if (startEnd != null) { + chr = chromosome.getName(); + if (startEnd == null) { + return new SearchResult(ResultType.LOCUS, chr, 0, chromosome.getLength()); + } else { int start = Math.min(startEnd[0], startEnd[1]); int end = Math.max(startEnd[0], startEnd[1]); return new SearchResult(ResultType.LOCUS, chr, start, end); } - return new SearchResult(ResultType.CHROMOSOME, chr, 0, chromosome.getLength() - 1); } return null; } @@ -562,10 +536,7 @@ private static int[] getStartEnd(String posString) { public enum ResultType { FEATURE, - FEATURE_MUT_AA, - FEATURE_MUT_NT, LOCUS, - CHROMOSOME, ERROR, LIFTOVER } diff --git a/src/main/java/org/broad/igv/ui/commandbar/IGVCommandBar.java b/src/main/java/org/broad/igv/ui/commandbar/IGVCommandBar.java index 5655357e66..cf35c8d122 100644 --- a/src/main/java/org/broad/igv/ui/commandbar/IGVCommandBar.java +++ b/src/main/java/org/broad/igv/ui/commandbar/IGVCommandBar.java @@ -328,7 +328,7 @@ public void searchByLocus(final String searchText) { if ((searchText != null) && (searchText.length() > 0)) { String homeChr = GenomeManager.getInstance().getCurrentGenome().getHomeChromosome(); - if (searchText.equalsIgnoreCase("home") || searchText.equalsIgnoreCase(homeChr)) { + if (searchText.equalsIgnoreCase("home")) { homeButtonActionPerformed(null); } else { searchTextField.setText(searchText); diff --git a/src/main/java/org/broad/igv/ui/panel/HeaderPanel.java b/src/main/java/org/broad/igv/ui/panel/HeaderPanel.java index f9aa680844..db2866e7df 100644 --- a/src/main/java/org/broad/igv/ui/panel/HeaderPanel.java +++ b/src/main/java/org/broad/igv/ui/panel/HeaderPanel.java @@ -94,7 +94,7 @@ private void init() { geneListPanel.setPreferredSize(new java.awt.Dimension(0, 0)); geneListPanel.setLayout(new java.awt.BorderLayout()); - label = new JLabel(frame.getName()); + label = new JLabel(frame.getFormattedLocusString()); label.setForeground(Color.blue); label.setToolTipText("Go to " + frame.getName()); label.addMouseListener(new MouseAdapter() { diff --git a/src/main/java/org/broad/igv/ui/panel/ReferenceFrame.java b/src/main/java/org/broad/igv/ui/panel/ReferenceFrame.java index fcc3499a29..c05be54458 100644 --- a/src/main/java/org/broad/igv/ui/panel/ReferenceFrame.java +++ b/src/main/java/org/broad/igv/ui/panel/ReferenceFrame.java @@ -635,13 +635,13 @@ public int getMidpoint() { */ public String getFormattedLocusString() { - if (zoom == 0) { - return getGenome().getChromosomeDisplayName(getChrName()); - } else { +// if (zoom == 0) { +// return getGenome().getChromosomeDisplayName(getChrName()); +// } else { Range range = getCurrentRange(); String c = getGenome().getChromosomeDisplayName(range.getChr()); return Locus.getFormattedLocusString(c, range.getStart(), range.getEnd()); - } + // } } public Range getCurrentRange() { diff --git a/src/test/java/org/broad/igv/ui/action/SearchCommandTest.java b/src/test/java/org/broad/igv/ui/action/SearchCommandTest.java index 8e094a9f59..df5934b757 100644 --- a/src/test/java/org/broad/igv/ui/action/SearchCommandTest.java +++ b/src/test/java/org/broad/igv/ui/action/SearchCommandTest.java @@ -53,7 +53,7 @@ public void setUp() throws Exception { } @Test - public void testSingleChromosomes() throws Exception { + public void testSingleLOCUSs() throws Exception { int min = 1; int max = 22; @@ -66,8 +66,8 @@ public void testSingleChromosomes() throws Exception { chrs[cn - min] = chr; nums[cn - min] = "" + cn; } - tstFeatureTypes(chrs, SearchCommand.ResultType.CHROMOSOME); - tstFeatureTypes(nums, SearchCommand.ResultType.CHROMOSOME); + tstFeatureTypes(chrs, SearchCommand.ResultType.LOCUS); + tstFeatureTypes(nums, SearchCommand.ResultType.LOCUS); } @Test @@ -93,7 +93,7 @@ public void testChromoWithColon() throws Exception { cmd = new SearchCommand(null, searchStr, genome); List results = cmd.runSearch(cmd.searchString); assertEquals(1, results.size()); - assertEquals(SearchCommand.ResultType.CHROMOSOME, results.get(0).type); + assertEquals(SearchCommand.ResultType.LOCUS, results.get(0).type); assertEquals(chr, results.get(0).chr); } } @@ -180,8 +180,8 @@ public void tstMultiFeatures(String delim) throws Exception { SearchCommand.ResultType.FEATURE, SearchCommand.ResultType.FEATURE, SearchCommand.ResultType.LOCUS, - SearchCommand.ResultType.CHROMOSOME, - SearchCommand.ResultType.CHROMOSOME + SearchCommand.ResultType.LOCUS, + SearchCommand.ResultType.LOCUS }; String searchStr = tokens[0]; for (int ii = 1; ii < tokens.length; ii++) { @@ -204,7 +204,7 @@ public void tstMultiFeatures(String delim) throws Exception { } @Test - public void testMultiChromosomes() throws Exception { + public void testMultiLOCUSs() throws Exception { String[] tokens = {"chr1", "chr5", "4", "12", "X", "Y"}; String searchStr = tokens[0]; for (int ii = 1; ii < tokens.length; ii++) { @@ -218,7 +218,7 @@ public void testMultiChromosomes() throws Exception { for (int ii = 0; ii < tokens.length; ii++) { SearchCommand.SearchResult result = results.get(ii); - assertEquals(SearchCommand.ResultType.CHROMOSOME, result.type); + assertEquals(SearchCommand.ResultType.LOCUS, result.type); assertTrue(result.getLocus().contains(tokens[ii])); } } @@ -234,7 +234,7 @@ public void testTokenChecking() { String[] chromos = {"chr3", "chr20", "chrX", "chrY"}; SearchCommand cmd = new SearchCommand(null, "", genome); for (String chr : chromos) { - assertEquals(SearchCommand.ResultType.CHROMOSOME, cmd.checkTokenType(chr)); + assertEquals(SearchCommand.ResultType.LOCUS, cmd.checkTokenType(chr)); } String[] starts = {"39,239,480", "958392", "0,4829,44", "5"};