/* * 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.lists; import org.apache.batik.bridge.CursorManager; import org.apache.log4j.Logger; import org.broad.igv.Globals; import org.broad.igv.track.*; import org.broad.igv.ui.IGV; import org.broad.igv.ui.WaitCursorManager; import org.broad.igv.ui.panel.DataPanel; import org.broad.igv.ui.panel.FrameManager; import org.broad.igv.ui.panel.ReferenceFrame; import org.broad.igv.util.LongRunningTask; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.stream.Collectors; /** * This class added to preload data when using gene lists. Its actually more general than that, but its motivation * stems from the need to provide a wait cursor when loading gene lists. * * @author jrobinso * @date Mar 22, 2011 */ public class Preloader { private static Logger log = Logger.getLogger(Preloader.class); private static final ExecutorService threadExecutor = Executors.newFixedThreadPool(5); public static synchronized CompletableFuture preload() { Collection<Track> trackList = visibleTracks(); final List<ReferenceFrame> frames = FrameManager.getFrames(); List<CompletableFuture> futures = new ArrayList(trackList.size() * frames.size()); for (ReferenceFrame frame : frames) { for (Track track : trackList) { if (track.isReadyToPaint(frame) == false) { futures.add(CompletableFuture.runAsync(() -> { System.out.println("Preload " + Thread.currentThread()); System.out.println("Preloading" + track); track.load(frame); })); } } } if (futures.size() > 0) { WaitCursorManager.CursorToken token = WaitCursorManager.showWaitCursor(); CompletableFuture[] futureArray = futures.toArray(new CompletableFuture[futures.size()]); return CompletableFuture.allOf(futureArray).thenRun(() -> WaitCursorManager.removeWaitCursor(token)); } else { return CompletableFuture.completedFuture(null); } } public static List<Track> visibleTracks() { return IGV.getInstance().getAllTracks().stream(). filter(Track::isVisible). collect(Collectors.toList()); } public static synchronized void load(final DataPanel dataPanel) { ReferenceFrame frame = dataPanel.getFrame(); Collection<Track> trackList = dataPanel.visibleTracks(); List<CompletableFuture> futures = new ArrayList(trackList.size()); for (Track track : trackList) { if (track.isReadyToPaint(frame) == false) { final Runnable runnable = () -> { // log.info("Loading " + track.getName() + " " + frame.getFormattedLocusString()); track.load(frame); // log.info("Loaded " + track.getName() + " " + frame.getFormattedLocusString()); }; if(Globals.isBatch()) { runnable.run(); } else { futures.add(CompletableFuture.runAsync(runnable, threadExecutor)); } } } if (futures.size() > 0) { CompletableFuture[] futureArray = futures.toArray(new CompletableFuture[futures.size()]); WaitCursorManager.CursorToken token = WaitCursorManager.showWaitCursor(); CompletableFuture.allOf(futureArray).thenRun(() -> { List<Track> unloadedTracks = dataPanel.notloadedTracks(); if (unloadedTracks.size() > 0) { log.info("Unloaded tracks for " + frame.getFormattedLocusString() + " " + unloadedTracks); } log.info("Call repaint " + dataPanel.hashCode() + " " + dataPanel.allTracksLoaded()); dataPanel.loadInProgress = false; WaitCursorManager.removeWaitCursor(token); dataPanel.repaint(); }); } log.info("Exit load for " + frame.getFormattedLocusString()); } private static SequenceTrack findSequenceTrack(Collection<Track> trackList) { for(Track t : trackList) { if(t instanceof SequenceTrack) { return (SequenceTrack) t; } } return null; } }