GMOD / jbrowse

JBrowse 1, a full-featured genome browser built with JavaScript and HTML5. For JBrowse 2, see https://github.com/GMOD/jbrowse-components.
http://jbrowse.org
Other
463 stars 199 forks source link

generate a printable/exportable image of the current view #81

Open rbuels opened 12 years ago

alpapan commented 12 years ago

not sure how without canvas...! or even if it is that useful. maybe dump the entire track (not just the part within view ) as an svg?

benwbooth commented 11 years ago

An SVG export option would be great. I think it could be done completely within the browser using a data: URI to save the file. Although I guess this would require writing an SVG renderer for the feature tracks.

My current workaround for this issue is to add &tracklist=0&nav=0&overview=0 to the URI and print the page as PDF

rbuels commented 11 years ago

Yes it would. Not going to happen.

The current plan is, once all of the tracks are using canvas, to try to stitch all of their contents together into another canvas, then make a data URI from that.

benwbooth commented 11 years ago

There is a project which simulates a canvas but builds a SVG:

http://svgkit.sourceforge.net/SVGCanvas.html

Would it be possible to write a jBrowse plugin that could export to SVG using something like this? I might look into writing one if I get some time.

rbuels commented 11 years ago

That's an interesting idea. Might be worth a shot, if SVGCanvas still works.

benwbooth commented 11 years ago

You might be able to avoid using SVGCanvas if you write an interface to abstract the drawing operations. The drawing operations for canvas and SVG are basically equivalent, except with some different naming and parameter ordering. You're probably only using a subset of drawing commands for the CanvasFeatures glyphs. If you create two implementations, such as SVGDraw and CanvasDraw, designed with the same interface for drawing operations, with the subset of drawing commands you're using, you can then use them interchangeably in the code., e.g.use CanvasDraw to draw the glyphs in the web page, and use SVGDraw for exporting images.

benwbooth commented 11 years ago

Being able to export figures in a scalable, resizable format suitable for publications is a must-have for us before we can switch away from our ugly hacked-together Bio::Graphics mess to JBrowse. Actually, I've been thinking about writing a patch for this myself, but I was waiting for the CanvasFeatures code to stabilize a bit, plus I haven't had much time lately at work. If I did find some time to work on it, would you be willing to accept a patch?

rbuels commented 11 years ago

Sure, always happy to have contributions of external code. You would probably want to start on the 2.x branch, since that's where the work for the 2.x series of JBrowse is going on.

When you feel ready to start working on this, the best starting point would be to drop into the #gmod IRC channel on the Freenode IRC network during US East business hours, and I can help get you pointed in the right direction.

rbuels commented 10 years ago

This is a tough one, I don't have a good idea for solving it yet. It's definitely possible to do with client-side code, and all the other rendering is client-side, and you want the same rendering code to be used for both.

Probably what will have to eventually be done is to write something similar to GD::SVG (which was written to solve this problem in GBrowse), but for canvas.

The strategy with GD::SVG is that it implements a GD drawing API, but it renders to SVG. So the analogous thing would be to make a fake canvas context2d object that implements a canvas drawing API, but renders to SVG.

That might be a good intern project, now that I think about it. I seem to remember that GD::SVG was done that way. I'll see if my current OICR intern is interested.

rbuels commented 10 years ago

Oh right, http://svgkit.sourceforge.net/SVGCanvas.html from earlier in this thread. Should definitely try that first.

breichholf commented 9 years ago

Has there been any progress on this? Just have installed jbrowse and love it. Still got to play around with it, but I'm missing two things so far: 1) export to scalable image (such/pdf/eps) 2) an easy way to set a fixed scale (max/min score) per track from within jbrowse, without having to go through "edit track".

I'm tempted to write the second plugin myself and am thinking that the first shouldn't be too hard with SVGCanvas, but haven't used js before. Where could I find the docs for the API?

enuggetry commented 9 years ago

I'm afraid any docs we have on the API are not in good shape. Your best resource will be the source code itself, for now. You will find embedded JSDoc in much of the codebase, but it has fallen out of maintenance and is incompatible with the current JSDoc.

cmdcolin commented 9 years ago

I never commented on this issue before, but I thought that I'd point out that high res canvas has been available for awhile and it kind of helps with this issue. It doesn't do full svgcanvas, but it can do higher resolution canvas, which is pretty good (previously canvasfeatures were quite blurry if used in a high res context). You can also automate the screenshot process with phantomJS

Link: http://gmod.org/wiki/JBrowse_Configuration_Guide#Rendering_high_resolution_screenshots_using_PhantomJS

Example of a pdf rendered with phantomjs: https://www.dropbox.com/s/7pceo4o406dys8s/output.pdf?dl=0

breichholf commented 9 years ago

Thanks enuggetry, I'll have a look in to it when I have time.

cmdcolin, I've tried phantoms 2.0, both the binary as well as a fresh compile through macports. Strangely it will work fine for an url such as google.com, but not jbrowse. I've also tried wkhtmltopdf only with similar results.

cmdcolin commented 9 years ago

Can you get a screenshot of the browser on jbrowse.org ? E.g.

phantomjs rasterize.js 'http://jbrowse.org/code/latest-release/?data=sample_data/json/volvox&loc=ctgA:16409..18516&tracks=DNA,CDS,ReadingFrame,volvox-sorted_bam&tracklist=0' jbrowse.pdf "16in*8in"

Where rasterize.js https://github.com/ariya/phantomjs/blob/master/examples/rasterize.js ?

That returns for me a pdf with phantomjs 2.0 (note: i normally use a slightly altered rasterize.js which scales the viewport so it is widescreen, e.g. https://gist.github.com/cmdcolin/7327455a269a11ac4c66)

Note: the phantomjs needs jbrowse 1.11.5+ if you are using a release mode candidate, otherwise you get a blank screen (you can use phantomjs on jbrowse below 1.11.5 with dev mode versions of jbrowse)

breichholf commented 9 years ago

Huh, interesting. The phantomjs 2.0 provided rasterize.js doesn't work. Yours does though!

In either case, the imported pdf is not really vector graphics, so I'm toying with the idea of writing a little module that will just pass the location and current tracks to an R script in the background and generate a pdf from there…

On a completely different note: I've written a little dialogue window to conveniently manually set a scale and was thinking of committing it, if this is of interest. I'm clueless which branch I'd commit it to, and how I'd do so, never having worked with javascript and dojo before.

cmdcolin commented 9 years ago

@breichholf interested to see what you come up with. There are not really formal code submitting guidelines afaik so a pull request or just a new git issue with some code pasted is probably fine.

keiranmraine commented 9 years ago

So I've given this a go with your version of rasterize and that does give an image from our install (JB 1.11.6, phantomjs 2.0). There is a problem though which I'm guessing needs some sort of variable test to see if the requested action has completed. Basically what I see is the tracks don't complete loading. We're working with relatively large genome files and I suspect the initial download of the index file is the issue (they can easily be 10-25 MB)

jbrowse

keiranmraine commented 9 years ago

I've found reference to something that theoretically could be used to determine if the page had completed load (for dojo ajax calls). It looks like dojo.request.notify should be able to set a value that can be tested to see if the page has compelted all requested actions.

Then the 'setTimeout' function at the end of rasterize.js could watch for this value being set to true before attempting to render.

cmdcolin commented 9 years ago

@keiranmraine that would definitely be better, otherwise i would have only suggested to increase the timeout.

I think if you want to optimize it for timing, then instead of using something like that notification, the best bet might be to tell phantomjs to just "loop" until it detects something in the DOM (our phantomjs based javascript test runner does this for example https://github.com/GMOD/jbrowse/blob/master/tests/js_tests/run-jasmine.js, but it is looking for DOM elements on the test page, not the jbrowse window)

The reason i say that is because we have discussed that even if we detect when certain javascript code has been run, it does not necessarily mean that the DOM elements have been drawn to the page (see: http://gmod.827538.n3.nabble.com/Gmod-ajax-Detect-when-jBrowse-has-finished-loading-td4043750.html). I could be wrong though!

keiranmraine commented 8 years ago

@cmdcolin , did anything get done with dojo.request.notify? Just looking at this again and although you raise a good point that things may not have rendered, I suspect a wait of 1 second after this variable being set would be sufficient.

I've found in most cases that you are generally only waiting on one the final element to complete not all of the rendering to occur once the transfers are done.

Could you point me to an appropriate place to try patching in this test?

nathandunn commented 7 years ago

@keiranmraine I did something similar to this and got it to work over selenium.

benwbooth commented 6 years ago

If anyone needs this capability, the dalliance browser can export SVG images, and it supports many of the same file formats as JBrowse. It also can use the JBrowse-formatted REST API.

keiranmraine commented 6 years ago

... just an update as it's not linked here. The solution I ended on for scripting images generation used puppeteer. It has the ability to monitor inflight http requests so it's pretty easy to determine when a page has fully completed a data load, then pad for the last bit to render. I believe puppeteer can be used within a node module embedded in a site, pulling the relevant OS specific binary when needed.

cmdcolin commented 6 years ago

At least one other option that gives users an easy "click button screenshot" is @bhofmei 's plugin https://github.com/bhofmei/jbplugin-screenshot

The future is of course client side JS that can perform this, but this plugin is a nice option that works with phantomjs in the current mode of things

Edit: bad grammar fix:)