rplotlegend

R ChromoMap: Displaying legend and scatter plot y-axis


I am currently plotting a figure using the ChromoMap package in R. I am wondering whether there is a way to display the y-axis of the scatter plots using scientific notation (i.e. 0.0005 -> 5e-4). And likewise, the legend is showing as 0.0 -> 0.0 as the numbers are too small to be displayed.

Sample data:

chromosomes_sort <- data.frame(V1=c(1,2,3), V2=c(0, 0, 0), V3=c(20672072, 27257494, 24117510))
marker_ann_trans <- data.frame(rs=c("1:201000\\G,\\C", "2:930284\\C,\\T", "3:478390\\G,\\A", "1:293904\\C,\\G", "2:3424802\\C,\\T", "3:1058284\\A,\\G"), chr=c(1, 2, 3, 1, 2, 3), ps=c(201000, 930284, 478390, 293904, 3424802, 1058284), ps_end=c(201001, 930285, 478391, 293905, 3424803, 1058285), p_wald=c(0.0001902909, 0.0004996678, 0.0003569823, 0.0003602867, 0.0001265872, 0.0001001598))

Current plot script:


chromoMap(ch.file=list(chromosomes_sort), 
          data.files=list(marker_ann_trans),
          n_win.factor = 3,  
          data_based_color_map = T, 
          data_type = "numeric",
          canvas_width = 1400, 
          canvas_height = 1400, 
          left_margin = 80, 
          interactivity = F,
          legend = c(T), 
          lg_y = 750, 
          plot.legend.labels = c("Wald p-val"), 
          data_colors = list(c("red2","blue")), 
          plots = "scatter", 
          ch_gap = 0.1, 
          ref_line = T,
          plot_color = c("black"))

Output:

enter image description here

Unfortunately I wasn't able to find anything in the package's documentation for a solution.


Solution

  • There are a lot of options for this function but I could only come up with a workaround.

    This solution uses JS and the library htmlwidgets to change the plot after it's made. I didn't known if you wanted exponential format in terms of 5e-4 or 5 x 10-4 (the latter of which is what I always think of, but isn't technically 'exponential format').

    This code is designed to change the code in either of these two formats.

    At the end of the Javascript in the function htmlwidgets::onRender, you'll see data.frame(... with the comment # alternate choices are "exponential" and "by 10". These two choices will change how your format your values.

    chromoMap(ch.file=list(chromosomes_sort), 
              data.files=list(marker_ann_trans),
              n_win.factor = 3,  
              data_based_color_map = T, 
              data_type = "numeric",
              canvas_width = 1400, 
              canvas_height = 1400, 
              left_margin = 80, 
              interactivity = F,
              legend = c(T), 
              lg_y = 750, 
              plot.legend.labels = c("Wald p-val"), 
              data_colors = list(c("red2","blue")), 
              plots = "scatter", 
              ch_gap = 0.1, 
              ref_line = T,
              plot_color = c("black")) |> 
      htmlwidgets::onRender(
        "function(el, x, data) {
          tellMe = document.querySelectorAll('g text'); /* find all labels */
                         /* filter for labels that only contain numbers and decimal point*/
          xx = [...tellMe].map((_, i) => i ).filter(e => /^\\d*\\.?\\d*$/.test(tellMe[e].innerHTML) === true);
                         /* convert values to scientific notation */
          if(data.choice[0] === 'exponential') {        /* exponential mode chosen */
            xx.map(i => tellMe[i].innerHTML = Number(tellMe[i].innerHTML).toExponential()); /* change text */
          } else if (data.choice[0] === 'by 10') {      /* by 10 mode chosen */
                         /* get superscript shift size based on font size */
            ss = Number(window.getComputedStyle(tellMe[xx[1]]).fontSize.replace(/[^\\d]+/, '')) * -.2;
            xx.map(i => tellMe[i].innerHTML = '<tspan>' + Number(tellMe[i].innerHTML).toExponential().replace(/e\\+?/, ' x 10<tspan dy=' + ss + '>')  + '</tspan></tspan>');
          }
        }", data.frame(choice = "by 10")   # alternate choices are "exponential" and  "by 10"
      )
    

    In this image, I added the argument plot_height = c(60) so that the values were more legible.

    exp mode

    Because the text is so much wider, I changed the argument left_margin to 100 (you've got it set to 80 in your question). I also used plot_height = c(60) to make the text more legible.

    by 10 mode