gladkia / igvShiny

An htmlwidget version of igv, for RStudio and Shiny apps
https://gladkia.github.io/igvShiny/
Other
36 stars 24 forks source link

Support for grouped deeptools bamCoverage tracks? #22

Closed ChristianRohde closed 2 years ago

ChristianRohde commented 2 years ago

Hi,

this is not an issue but rather a question: I started to use igvShiny to visualize peak regions in bed format. This works very well for background & regulated. Thank you so much for this software!

In IGV I usually inspect single sample files from each 3 x IP + IgG + input as normalized tracks generated with deeptools bamCoverage. The important point is: the scale is grouped within all samples. Do you think this would be possible as well in igvShiny?

Best, Christian

paul-shannon commented 2 years ago

Hi @ChristianRohde I'd be glad to give this a look. Can you provide (or point to) a sample data file, perhaps accompanied by instructions on how I can view this in desktop IGV in the way you find useful?

ChristianRohde commented 2 years ago

Hi @paul-shannon

thank you so much!

I found some good example files online from GSE70482. Here I downloaded the bigwig for GSM1782744, GSM1782743, GSM1782742 and GSM1782741 with a link such as https://www-ncbi-nlm-nih-gov.ezproxy.u-pec.fr/geo/query/acc.cgi?acc=GSM1782741. Next I load the data into IGV to inspect my region of interest. You can see that by default Autoscale is enabled such that each sample uses the full range and its own scale to visualize the data. With normalized data we prefer to group the Autoscale such that the visualization looks a bit clearer. Here I picked a peak at ASXL2 gene promoter as an example.

Best, Christian

Screenshot 2022-02-14 at 13 11 15 Screenshot 2022-02-14 at 13 12 03
paul-shannon commented 2 years ago

@ChristianRohde - this ("group autoscale") is already offered by the igv.js wig track, so all that remains is the straightforward job of exposing the capability in igvShiny.
For igvShiny, the wig track is represented (maybe counter-intuitively) as a BedGraph track, with this API

loadBedGraphTrack <- function(session, id, trackName, tbl, color="gray", trackHeight=30,
                              autoscale, min=NA_real_, max=NA_real_,
                              deleteTracksOfSameName=TRUE, quiet=TRUE)

I propose to add an extra integer parameter "autoscaleGroup", which will be ignored if autoscale is FALSE. I will add this to the igvR package also.

Will that give you the capability you are looking for?

ChristianRohde commented 2 years ago

Hi @paul-shannon this sounds great. I would like to try this. Will trackName accept a list of files which will be grouped with the autoscaleGroup parameter?

paul-shannon commented 2 years ago

We -could- do it that way. The igv.js API uses independent successive calls, implicitly linked via a shared autoscaleGroup number. Perhaps we could start with that?

On Feb 16, 2022, at 10:36 AM, ChristianRohde @.***> wrote:

Hi @paul-shannon this sounds great. I would like to try this. Will trackName accept a list of files which will be grouped with the autoscaleGroup parameter?

— Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android. You are receiving this because you were mentioned.

ChristianRohde commented 2 years ago

It would be nice if it would work in such flexible way. At the moment I am putting results from several clip-seq experiments into a shiny App. Sometimes replicates did not work and we end up with less samples than usual. In this case I could just pass as many files as we have to this list. Otherwise if I load each file independently many experiments would need a different igvshiny script layout I guess.

paul-shannon commented 2 years ago

How about a wrapper function, which takes takes the arguments as you think of them, then makes multiple calls to the stock igv.js-ish function, just slightly different from what we already have?

The wrapper function might be called like this - with each plural parameter being a list as long as the number of experiments you wish to display:

loadBedGraphTrackGroup <- function(session, groupNumber, ids, trackNames, tbls, colors="gray”, trackHeights=30, autoscale, mins=NAreal, maxes=NAreal, deleteTracksOfSameName=TRUE, quiet=TRUE)

On Feb 16, 2022, at 11:01 AM, ChristianRohde @.***> wrote:

It would be nice if it would work in such flexible way. At the moment I am putting results from several clip-seq experiments into a shiny App. Sometimes replicates did not work and we end up with less samples than usual. In this case I could just pass as many files as we have to this list. Otherwise if I load each file independently many experiments would need a different igvshiny script layout I guess.

— Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android. You are receiving this because you were mentioned.

ChristianRohde commented 2 years ago

wow, this is exactly what I need. Maybe you could also make colors a list? Then IP can have different colors than IgG or input.

paul-shannon commented 2 years ago

“colors” is a list in the API I sketched out, so we are thinking the same way.

I think I can get these changes in by the end of the week.

How do you use igvShiny? Have you tried igvR? The latter is more powerful for individual researcher exploration, the former for creating displays for others to see. I am curious about your context…

On Feb 16, 2022, at 11:26 AM, ChristianRohde @.***> wrote:

wow, this is exactly what I need. Maybe you could also make colors a list? Then IP can have different colors than IgG or input.

— Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android. You are receiving this because you were mentioned.

ChristianRohde commented 2 years ago

I did not spot igvR so far. It perfectly works with my local Rstudio. I think this is ideal if I just want to learn how things work out or want to analyze some data for myself. However, usually I work on a Rstudio-server which is located at the university. Here igvR fails, please have a look at the attached screenshot. The server has a good connection to our data server. In this case it does not matter if I work via VPN from home or sit in the office with wireless: in any case the connection of the server to the data is better than with my local device. But the most important thing is that even if igvR would work with Rstudio-server then I would like to display it in a shiny App and provide a link with Shiny-server to my colleagues. This way they have direct access to our data without the need to install and maintain the R scripts themselves. I guess igvShiny is indeed what perfectly fits to my needs. Screenshot 2022-02-16 at 22 01 38

paul-shannon commented 2 years ago

@ChristianRohde thanks for the igvR remote server bug report. That ought to be possible - I'll study up.

igvShiny version 1.15.6, just pushed to this github repo, now supports an optional autoscaleGroup parameter. If 0 or larger, and autoscale=TRUE, you get the grouping. Here it is, in action, in inst/demos/igvShinyDemo.R image

The blue track wig1a has small values, wig1b's values are multiplied by 10.

Here is the shiny handler code to produce that group:

observeEvent(input$addAutoscaledGroupBedGraphTrackButton, {
      showGenomicRegion(session, id="igvShiny_0", "chr1:7,432,868-7,433,167")
      loadBedGraphTrack(session, id="igvShiny_0", trackName="wig1a", tbl=tbl.wig, color="blue",
                        autoscale=TRUE, autoscaleGroup=1)
      tbl.wig1b <- tbl.wig
      tbl.wig1b$value <-tbl.wig1b$value * 10
      loadBedGraphTrack(session, id="igvShiny_0", trackName="wig1b", tbl=tbl.wig1b, color="brown",
                        autoscale=TRUE, autoscaleGroup=1)
      })

I have to defer the convenience wrapper function we discussed until a few other more pressing tasks are taken care of.

Let me know how this works.

ChristianRohde commented 2 years ago

GREAT! I would say no additional wrapper is needed, everything is working pretty well.

I realized that I anyway have to import the data with rtracklayer before upload to igv which is different from local IGV on my PC, here I submit the files once as the are. But this gave me the opportunity to filter for the region of interest (extract from input[[sprintf("currentGenomicRegion.%s", "igvShiny_0")]]). Now I have loops for each IgG, input etc to load data and again loops to bring data into igvShiny with loadBedGraphTrack. This works super fast for me. The only disadvantage I see at the moment is that we have to click the Update/Import button each time I change the region. I tried to connect it with observeEvent(input[[sprintf("currentGenomicRegion.%s", "igvShiny_0_dew")]] but then it does not stop loading.

Do you have any idea how to improve this point?

Christian

Screenshot 2022-02-18 at 13 39 14

paul-shannon commented 2 years ago

Hi Christian,

A small example of the problem, a demo app, would be the best way for me to understand the problem.

Can you put together a small demo that illustrates the need to click the Update/Import button?
And shows how depending on the currentGenomicRegion input leads to “does not stop loading”?

It can be a bit of fuss to distill a small reproducible even self-contained example, but it is a huge help on my end.

On Feb 18, 2022, at 4:40 AM, ChristianRohde @.***> wrote:

GREAT! I would say no additional wrapper is needed, everything is working pretty well.

I realized that I anyway have to import the data with rtracklayer before upload to igv which is different from local IGV on my PC, here I submit the files once as the are. But this gave me the opportunity to filter for the region of interest (extract from input[[sprintf("currentGenomicRegion.%s", "igvShiny_0")]]). Now I have loops for each IgG, input etc to load data and again loops to bring data into igvShiny with loadBedGraphTrack. This works super fast for me. The only disadvantage I see at the moment is that we have to click the Update/Import button each time I change the region. I tried to connect it with observeEvent(input[[sprintf("currentGenomicRegion.%s", "igvShiny_0_dew")]] but then it does not stop loading.

Do you have any idea how to improve this point?

Christian

— Reply to this email directly, view it on GitHub, or unsubscribe. Triage notifications on the go with GitHub Mobile for iOS or Android. You are receiving this because you were mentioned.

ChristianRohde commented 2 years ago

Sure, please find attached my very simple example files attached. Here I execute loadBedGraphTrack each time observeEvent(input[[sprintf("currentGenomicRegion.%s", "igvShiny_0")]] says go. My idea is that automatically the respective data for the region of interest should be loaded after filtering with rtracklayer import function.

I made the App start at Myc and nothing is being loaded. This could be done with observeEvent(input$igvReady, but then tracks will only be loaded at start. OK, once you slide the region with your mouse or select another region (ASXL1 for example, I put some track data there) with search the tracks will be loaded fresh. This works, but the tracks keep flickering while being reloaded I assume. I have no idea, maybe this is a problem related to shiny itself?

rstudio-export.zip

paul-shannon commented 2 years ago

@ChristianRohde - Hi Christian,

I am making some progress on this. It turns out that igv.js emits an updateLocusSearchWidget event whenever a track is loaded. Which then sets off an infinite loop: locusChangeEvent loads a track generating a locusChangeEvent loads a track ...

Should be easy to fix, I am trying a few different strategies now.

Thanks for the bug report!

paul-shannon commented 2 years ago

@ChristianRohde
igvShiny 1.4.2 has the fix. Let me know if it solves your problem. Other bug reports and/or suggestions welcome.

ChristianRohde commented 2 years ago

Yes, indeed the infinite loop stopped. Unfortunately, the code still executes twice. With the simple bed example it is too fast to realize. I can see it with more data being loaded each time twice. You can see the problem if you put a print(input[[sprintf("currentGenomicRegion.%s", "igvShiny_0")]]) inside the observeEvent.

paul-shannon commented 2 years ago

good tip. I'll check that out, find a fix.

paul-shannon commented 2 years ago

@ChristianRohde - finally figured this out. I have some clean up to do in the morning, then I'll commit the code.

paul-shannon commented 2 years ago

@ChristianRohde version 1.4.3 fixes the bug in which two currentGenomicRegion events were issued on region change. Please let me know how it works for you.

ChristianRohde commented 2 years ago

yes, thank you very much for your help. Now it works well: I can load the track fresh each time a new window is found by input[[sprintf("currentGenomicRegion.%s", "igvShiny_0")]] and this happens only once. In principle this is true and works well in my example shiny. However, there still is some obscure minor problem left in my working shiny: here after the first search the loading is executed twice while the following searches work as expected. For example the search "ASXL1" or "chr20:32357060-32440319" is being conducted well but then in a next step the region is kind of updated to "chr20:32357060-32439789". I tried to figure out how this happens but I am not able to reproduce this behavior in my example shiny. As this is a very minor problem for me and probably the reason is my code and not igvShiny related I will stop thinking about it now. In case I find how to reproduce or address the problem I will come back to you. Best regards, Christian

paul-shannon commented 2 years ago

Glad to hear that 1.4.3 fixes the most obvious bug.

I added a feature to the javascript code so that, in a running shiny app, setting a variable in the javscript console turns on a flood of trace information.

If you'd like, and if you give me the url of your app, I'd be glad to use that technique to look at the remaining problem you describe.