diff --git a/src/main/java/org/broad/igv/htsget/HtsgetUtils.java b/src/main/java/org/broad/igv/htsget/HtsgetUtils.java index 39525dc97a..88bf8bdc06 100644 --- a/src/main/java/org/broad/igv/htsget/HtsgetUtils.java +++ b/src/main/java/org/broad/igv/htsget/HtsgetUtils.java @@ -41,6 +41,9 @@ public static Metadata getMetadata(final String url) throws IOException { return null; } else { String format = json.get("htsget").getAsJsonObject().get("format").getAsString(); +// if(!(format.toUpperCase().equals("BAM")) || format.toUpperCase().equals("VCF")) { +// throw new RuntimeException(("Format")) +// } return new Metadata(url, format); } } diff --git a/src/main/java/org/broad/igv/track/TrackLoader.java b/src/main/java/org/broad/igv/track/TrackLoader.java index 03254f5707..0ded5799ef 100644 --- a/src/main/java/org/broad/igv/track/TrackLoader.java +++ b/src/main/java/org/broad/igv/track/TrackLoader.java @@ -124,6 +124,7 @@ public List load(ResourceLocator locator, Genome genome) throws DataLoadE log.info("Loading resource: " + (locator.isDataURL() ? "" : path)); try { + String format = locator.getFormat(); if (format.equals("tbi")) { @@ -134,9 +135,23 @@ public List load(ResourceLocator locator, Genome genome) throws DataLoadE //This list will hold all new tracks created for this locator List newTracks = new ArrayList(); + + // Determine track type, if possible, and add new tracks if (locator.isHtsget()) { - tryHtsget(locator, newTracks, genome); - } else if (format.equals("gmt")) { + HtsgetUtils.Metadata htsgetMeta = HtsgetUtils.getMetadata(locator.getPath()); + locator.setFormat(htsgetMeta.getFormat().toLowerCase()); + if (htsgetMeta.getFormat().equals("VCF")) { + locator.setHtsget(true); + HtsgetVariantSource source = new HtsgetVariantSource(htsgetMeta, genome); + loadVCFWithSource(locator, source, newTracks); + } else if (htsgetMeta.getFormat().equals("BAM") || htsgetMeta.getFormat().equals("CRAM")) { + locator.setHtsget(true); + loadAlignmentsTrack(locator, newTracks, genome); + } else { + throw new RuntimeException("Format: '" + htsgetMeta.getFormat() + "' is not supported for htsget servers."); + } + + } else if (format.equals("gmt")) { loadGMT(locator); } else if (format.equals("vcf.list")) { loadVCFListFile(locator, newTracks, genome); @@ -208,33 +223,29 @@ public List load(ResourceLocator locator, Genome genome) throws DataLoadE loadMutFile(locator, newTracks, genome); // Must be tried before ".maf" test below } else if (format.equals("maf")) { loadMultipleAlignmentTrack(locator, newTracks, genome); - } else { - //if a url, try htsget - boolean isHtsget = tryHtsget(locator, newTracks, genome); - if (!isHtsget) { - - // If the file is too large, give up - // TODO -- ftp test - final int tenMB = 10000000; - long fileLength = ParsingUtils.getContentLength(locator.getPath()); - if (fileLength > tenMB) { - MessageUtils.confirm("Cannot determine file type of: " + locator.getPath()); - } + } else { + // If the file is too large, give up + // TODO -- ftp test + final int tenMB = 10000000; + long fileLength = ParsingUtils.getContentLength(locator.getPath()); + if (fileLength > tenMB) { + MessageUtils.confirm("Cannot determine file type of: " + locator.getPath()); + } - // Read file contents and try to sort it out - String contents = FileUtils.getContents(locator.getPath()); - BufferedReader reader = new BufferedReader(new StringReader(contents)); - - if (CytoBandFileParser.isValid(reader, locator.getPath())) { - Track track = new CytobandTrack(locator, new BufferedReader(new StringReader(contents)), genome); - newTracks.add(track); - } else if (AttributeManager.isSampleInfoFile(reader)) { - // This might be a sample information file. - AttributeManager.getInstance().loadSampleInfo(locator); - } else { - MessageUtils.showMessage("Unknown file type: " + path + "
Check file extension"); - } + // Read file contents and try to sort it out + String contents = FileUtils.getContents(locator.getPath()); + BufferedReader reader = new BufferedReader(new StringReader(contents)); + + if (CytoBandFileParser.isValid(reader, locator.getPath())) { + Track track = new CytobandTrack(locator, new BufferedReader(new StringReader(contents)), genome); + newTracks.add(track); + } else if (AttributeManager.isSampleInfoFile(reader)) { + // This might be a sample information file. + AttributeManager.getInstance().loadSampleInfo(locator); + } else { + MessageUtils.showMessage("Unknown file type: " + path + "
Check file extension"); } + } // Track line @@ -275,46 +286,6 @@ public List load(ResourceLocator locator, Genome genome) throws DataLoadE } - /** - * Try to load as an htsget resource. As most (all?) htsget endpoints use an https:// scheme URL, there is - * no way to detect other than try. - * - * @param locator - * @param newTracks - * @param genome - * @return - */ - private boolean tryHtsget(ResourceLocator locator, List newTracks, Genome genome) { - boolean isHtsget = false; - if (locator.getPath().startsWith("https://") || - locator.getPath().startsWith("http://") || - locator.getPath().startsWith("htsget://")) { - try { - HtsgetUtils.Metadata htsgetMeta = HtsgetUtils.getMetadata(locator.getPath()); - if (htsgetMeta != null) { - isHtsget = true; - locator.setFormat(htsgetMeta.getFormat().toLowerCase()); - if (htsgetMeta.getFormat().equals("VCF")) { - locator.setHtsget(true); - HtsgetVariantSource source = new HtsgetVariantSource(htsgetMeta, genome); - loadVCFWithSource(locator, source, newTracks); - } else if (htsgetMeta.getFormat().equals("BAM") || htsgetMeta.getFormat().equals("CRAM")) { - locator.setHtsget(true); - loadAlignmentsTrack(locator, newTracks, genome); - } else { - throw new RuntimeException("Format: '" + htsgetMeta.getFormat() + "' is not supported for htsget servers."); - } - } - } catch (IOException e) { - // Not neccessarily an error, might just indicate its not an htsget server. Not sure - // if this should be logged or not, it will be a common and expected occurence when loading - // sample information, which is checked after htsget - return false; - } - } - return isHtsget; - } - public static boolean isAlignmentTrack(String typeString) { if (typeString == null) { return false; diff --git a/src/main/java/org/broad/igv/ui/IGVMenuBar.java b/src/main/java/org/broad/igv/ui/IGVMenuBar.java index 1537a7fcd6..7cbb546066 100644 --- a/src/main/java/org/broad/igv/ui/IGVMenuBar.java +++ b/src/main/java/org/broad/igv/ui/IGVMenuBar.java @@ -284,10 +284,14 @@ JMenu createFileMenu() { menuAction.setToolTipText(UIConstants.LOAD_TRACKS_TOOLTIP); menuItems.add(MenuAndToolbarUtils.createMenuItem(menuAction)); - menuAction = new LoadFromServerAction("Load from Server...", KeyEvent.VK_S, igv); + menuAction = new LoadFromServerAction("Load IGV Hosted Tracks...", KeyEvent.VK_S, igv); menuAction.setToolTipText(UIConstants.LOAD_SERVER_DATA_TOOLTIP); menuItems.add(MenuAndToolbarUtils.createMenuItem(menuAction)); + menuAction = new LoadFromURLMenuAction(LoadFromURLMenuAction.LOAD_FROM_HTSGET, 0, igv); + menuAction.setToolTipText(UIConstants.LOAD_HTSGET_TOOLTOP); + menuItems.add(MenuAndToolbarUtils.createMenuItem(menuAction)); + if (PreferencesManager.getPreferences().getAsBoolean(DB_ENABLED)) { menuAction = new LoadFromDatabaseAction("Load from Database...", 0, igv); menuItems.add(MenuAndToolbarUtils.createMenuItem(menuAction)); diff --git a/src/main/java/org/broad/igv/ui/UIConstants.java b/src/main/java/org/broad/igv/ui/UIConstants.java index fbefdddd00..466bb43b96 100644 --- a/src/main/java/org/broad/igv/ui/UIConstants.java +++ b/src/main/java/org/broad/igv/ui/UIConstants.java @@ -49,6 +49,8 @@ public class UIConstants { // Menu tooltips static final public String LOAD_TRACKS_TOOLTIP = "Load tracks or sample information"; + + static final public String LOAD_HTSGET_TOOLTOP = "Load BAM or VCF tracks from an htsget server"; static final public String LOAD_SERVER_DATA_TOOLTIP = "Load tracks or sample information from a server"; static final public String SAVE_PNG_IMAGE_TOOLTIP = "Capture and save a PNG image"; static final public String SAVE_SVG_IMAGE_TOOLTIP = "Capture and save an SVG image"; diff --git a/src/main/java/org/broad/igv/ui/action/LoadFromServerAction.java b/src/main/java/org/broad/igv/ui/action/LoadFromServerAction.java index 0db578542a..abc03108bf 100644 --- a/src/main/java/org/broad/igv/ui/action/LoadFromServerAction.java +++ b/src/main/java/org/broad/igv/ui/action/LoadFromServerAction.java @@ -113,7 +113,8 @@ public static LinkedHashSet getNodeURLs(String genomeURL) { nodeURLs = getResourceUrls(bufferedReader); } catch (IOException e) { //This is pretty common, if there is no data registry file for the genome the file won't exist - log.error("Error loading genome registry file", e); + //log.error("Error loading genome registry file", e); + log.warn("No data found for current genome."); } finally { if (is != null) { try { diff --git a/src/main/java/org/broad/igv/ui/action/LoadFromURLMenuAction.java b/src/main/java/org/broad/igv/ui/action/LoadFromURLMenuAction.java index 9c8473c975..bd97f5d026 100644 --- a/src/main/java/org/broad/igv/ui/action/LoadFromURLMenuAction.java +++ b/src/main/java/org/broad/igv/ui/action/LoadFromURLMenuAction.java @@ -59,6 +59,7 @@ public class LoadFromURLMenuAction extends MenuAction { static Logger log = LogManager.getLogger(LoadFilesMenuAction.class); public static final String LOAD_FROM_URL = "Load from URL..."; public static final String LOAD_GENOME_FROM_URL = "Load Genome from URL..."; + public static final String LOAD_FROM_HTSGET = "Load from htsget Server..."; private IGV igv; public LoadFromURLMenuAction(String label, int mnemonic, IGV igv) { @@ -71,9 +72,10 @@ public void actionPerformed(ActionEvent e) { JPanel ta = new JPanel(); ta.setPreferredSize(new Dimension(600, 20)); - if (e.getActionCommand().equalsIgnoreCase(LOAD_FROM_URL)) { + boolean isHtsGet = e.getActionCommand().equalsIgnoreCase(LOAD_FROM_HTSGET); + if (e.getActionCommand().equalsIgnoreCase(LOAD_FROM_URL) || isHtsGet) { - LoadFromURLDialog dlg = new LoadFromURLDialog(IGV.getInstance().getMainFrame()); + LoadFromURLDialog dlg = new LoadFromURLDialog(IGV.getInstance().getMainFrame(), isHtsGet); dlg.setVisible(true); if (!dlg.isCanceled()) { @@ -114,6 +116,9 @@ public void actionPerformed(ActionEvent e) { String indexUrl = indexes[i]; rl.setIndexPath(indexUrl); } + if(isHtsGet) { + rl.setHtsget(true); + } locators.add(rl); } igv.loadTracks(locators); diff --git a/src/main/java/org/broad/igv/ui/action/MenuAction.java b/src/main/java/org/broad/igv/ui/action/MenuAction.java index 16fd3c51da..dc28269a92 100644 --- a/src/main/java/org/broad/igv/ui/action/MenuAction.java +++ b/src/main/java/org/broad/igv/ui/action/MenuAction.java @@ -50,7 +50,7 @@ public class MenuAction extends AbstractAction { public MenuAction(String name, Icon icon, int mnemonic) { super(name, icon); if(mnemonic >= 0) { - putValue(MNEMONIC_KEY, new Integer(mnemonic)); + putValue(MNEMONIC_KEY, mnemonic); } } diff --git a/src/main/java/org/broad/igv/ui/util/LoadFromURLDialog.java b/src/main/java/org/broad/igv/ui/util/LoadFromURLDialog.java index b1588c29af..7c75c448e8 100644 --- a/src/main/java/org/broad/igv/ui/util/LoadFromURLDialog.java +++ b/src/main/java/org/broad/igv/ui/util/LoadFromURLDialog.java @@ -39,15 +39,15 @@ /** * @author James Robinson */ -public class LoadFromURLDialog extends org.broad.igv.ui.IGVDialog { +public class LoadFromURLDialog extends org.broad.igv.ui.IGVDialog { boolean canceled = false; String fileURL; String indexURL; - public LoadFromURLDialog(Frame owner) { - super(owner, "Load from URL"); - initComponents(); + public LoadFromURLDialog(Frame owner, boolean isHtsget) { + super(owner, isHtsget ? "htsget URL": "Load from URL"); + initComponents(isHtsget); } @@ -82,7 +82,7 @@ public String getIndexURL() { return indexURL; } - private void initComponents() { + private void initComponents(boolean isHtsget) { // JFormDesigner - Component initialization - DO NOT MODIFY //GEN-BEGIN:initComponents // Generated using JFormDesigner non-commercial license dialogPane = new JPanel(); @@ -112,69 +112,75 @@ private void initComponents() { { contentPanel.setBorder(new EmptyBorder(10, 10, 5, 5)); contentPanel.setLayout(new GridBagLayout()); - ((GridBagLayout)contentPanel.getLayout()).columnWidths = new int[] {0, 0, 0}; - ((GridBagLayout)contentPanel.getLayout()).rowHeights = new int[] {0, 0, 0, 0, 0, 0, 0}; - ((GridBagLayout)contentPanel.getLayout()).columnWeights = new double[] {0.0, 0.0, 1.0E-4}; - ((GridBagLayout)contentPanel.getLayout()).rowWeights = new double[] {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0E-4}; + ((GridBagLayout) contentPanel.getLayout()).columnWidths = new int[]{0, 0, 0}; + ((GridBagLayout) contentPanel.getLayout()).rowHeights = new int[]{0, 0, 0, 0, 0, 0, 0}; + ((GridBagLayout) contentPanel.getLayout()).columnWeights = new double[]{0.0, 0.0, 1.0E-4}; + ((GridBagLayout) contentPanel.getLayout()).rowWeights = new double[]{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0E-4}; contentPanel.add(vSpacer2, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, - GridBagConstraints.CENTER, GridBagConstraints.BOTH, - new Insets(0, 0, 10, 0), 0, 0)); + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 10, 0), 0, 0)); //---- label1 ---- label1.setText("File URL:"); contentPanel.add(label1, new GridBagConstraints(0, 1, 1, 1, 0.0, 0.0, - GridBagConstraints.CENTER, GridBagConstraints.BOTH, - new Insets(0, 0, 10, 5), 0, 0)); - + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 10, 5), 0, 0)); + fileField.setPreferredSize(new Dimension(720, 28)); + fileField.setMinimumSize(new Dimension(720, 28)); //---- label2 ---- - label2.setText("Index URL:"); - contentPanel.add(label2, new GridBagConstraints(0, 5, 1, 1, 0.0, 0.0, - GridBagConstraints.CENTER, GridBagConstraints.BOTH, - new Insets(0, 0, 0, 5), 0, 0)); + contentPanel.add(fileField, new GridBagConstraints(1, 1, 1, 1, 0.0, 0.0, - GridBagConstraints.CENTER, GridBagConstraints.BOTH, - new Insets(0, 0, 10, 0), 0, 0)); + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 10, 0), 0, 0)); contentPanel.add(vSpacer1, new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0, - GridBagConstraints.CENTER, GridBagConstraints.BOTH, - new Insets(0, 0, 10, 5), 0, 0)); + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 10, 5), 0, 0)); contentPanel.add(vSpacer3, new GridBagConstraints(0, 3, 1, 1, 0.0, 0.0, - GridBagConstraints.CENTER, GridBagConstraints.BOTH, - new Insets(0, 0, 10, 5), 0, 0)); + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 10, 5), 0, 0)); //---- indexField ---- - indexField.setPreferredSize(new Dimension(720, 28)); - indexField.setMinimumSize(new Dimension(720, 28)); - contentPanel.add(indexField, new GridBagConstraints(1, 5, 1, 1, 0.0, 0.0, - GridBagConstraints.CENTER, GridBagConstraints.BOTH, - new Insets(0, 0, 0, 0), 0, 0)); - - //---- label3 ---- - label3.setText("Specify url to an index file. Required for BAM and indexed files"); - contentPanel.add(label3, new GridBagConstraints(0, 4, 2, 1, 0.0, 0.0, - GridBagConstraints.CENTER, GridBagConstraints.BOTH, - new Insets(0, 0, 10, 0), 0, 0)); + if (!isHtsget) { + label2.setText("Index URL:"); + contentPanel.add(label2, new GridBagConstraints(0, 5, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 0, 5), 0, 0)); + + indexField.setPreferredSize(new Dimension(720, 28)); + indexField.setMinimumSize(new Dimension(720, 28)); + contentPanel.add(indexField, new GridBagConstraints(1, 5, 1, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 0, 0), 0, 0)); + + + //---- label3 ---- + label3.setText("Specify url to an index file. Required for BAM and indexed files"); + contentPanel.add(label3, new GridBagConstraints(0, 4, 2, 1, 0.0, 0.0, + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 10, 0), 0, 0)); + } } dialogPane.add(contentPanel, BorderLayout.CENTER); //======== buttonBar ======== { buttonBar.setLayout(new GridBagLayout()); - ((GridBagLayout)buttonBar.getLayout()).columnWidths = new int[] {0, 85, 80}; - ((GridBagLayout)buttonBar.getLayout()).columnWeights = new double[] {1.0, 0.0, 0.0}; + ((GridBagLayout) buttonBar.getLayout()).columnWidths = new int[]{0, 85, 80}; + ((GridBagLayout) buttonBar.getLayout()).columnWeights = new double[]{1.0, 0.0, 0.0}; //---- okButton ---- okButton.setText("OK"); okButton.addActionListener(e -> okButtonActionPerformed(e)); buttonBar.add(okButton, new GridBagConstraints(1, 0, 1, 1, 0.0, 0.0, - GridBagConstraints.CENTER, GridBagConstraints.BOTH, - new Insets(0, 0, 0, 5), 0, 0)); + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 0, 5), 0, 0)); //---- cancelButton ---- cancelButton.setText("Cancel"); cancelButton.addActionListener(e -> cancelButtonActionPerformed(e)); buttonBar.add(cancelButton, new GridBagConstraints(2, 0, 1, 1, 0.0, 0.0, - GridBagConstraints.CENTER, GridBagConstraints.BOTH, - new Insets(0, 0, 0, 0), 0, 0)); + GridBagConstraints.CENTER, GridBagConstraints.BOTH, + new Insets(0, 0, 0, 0), 0, 0)); } dialogPane.add(buttonBar, BorderLayout.SOUTH); }