Skip to content

Commit f7b532a

Browse files
Copy over code from ggrepel
resolves #179 resolves #182
1 parent 3206865 commit f7b532a

13 files changed

+756
-13
lines changed

DESCRIPTION

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Package: metacoder
22
Title: Tools for Parsing, Manipulating, and Graphing Hierarchical Data
3-
Version: 0.1.3.9033
3+
Version: 0.1.3.9034
44
Authors@R: c( person("Zachary", "Foster", email =
55
"[email protected]", role = c("aut", "cre")),
66
person("Niklaus", "Grunwald", email =
@@ -44,7 +44,8 @@ Imports:
4444
vegan,
4545
ggrepel,
4646
cowplot,
47-
GA
47+
GA,
48+
Rcpp
4849
Suggests:
4950
knitr,
5051
rmarkdown,
@@ -54,3 +55,4 @@ RoxygenNote: 6.0.1
5455
Date: 2017-05-22
5556
Encoding: UTF-8
5657
biocViews:
58+
LinkingTo: Rcpp

NAMESPACE

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ export(write_rdp)
4040
export(write_silva_fasta)
4141
export(write_unite_general)
4242
export(zero_low_counts)
43+
importFrom(Rcpp,sourceCpp)
4344
importFrom(dplyr,contains)
4445
importFrom(dplyr,ends_with)
4546
importFrom(dplyr,everything)
@@ -48,3 +49,4 @@ importFrom(dplyr,num_range)
4849
importFrom(dplyr,one_of)
4950
importFrom(dplyr,starts_with)
5051
importFrom(magrittr,"%>%")
52+
useDynLib(metacoder)

NEWS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414

1515
### Improvements
1616

17-
* `ggrepel` package now used to repel labels to avoid overlapping labels.
17+
* code from [ggrepel](https://github.com/slowkow/ggrepel) package now used to avoid overlapping labels. Thanks Kamil Slowikowski!
1818
* New function `heat_tree_matrix` to make plotting a pairwise matrix of heat trees for comparing treatments.
1919
* New parser named `parse_mothur_tax_summary` for mothur *.tax.summary file made by [classify.seqs](https://www.mothur.org/wiki/Classify.seqs).
2020
* New parser named `parse_mothur_taxonomy` for mothur *.taxonomy file made by [classify.seqs](https://www.mothur.org/wiki/Classify.seqs).

R/RcppExports.R

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
# Generated by using Rcpp::compileAttributes() -> do not edit by hand
2+
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393
3+
4+
#' Euclidean distance between two points.
5+
#' @param a A point.
6+
#' @param b A point.
7+
#' @return The distance between two points.
8+
#' @noRd
9+
NULL
10+
11+
#' Squared Euclidean distance between two points.
12+
#' @param a A point.
13+
#' @param b A point.
14+
#' @return The distance between two points.
15+
#' @noRd
16+
NULL
17+
18+
#' Move a box into the area specificied by x limits and y limits.
19+
#' @param b A box like \code{c(x1, y1, x2, y2)}
20+
#' @param xlim A Point with limits on the x axis like \code{c(xmin, xmax)}
21+
#' @param ylim A Point with limits on the y axis like \code{c(xmin, xmax)}
22+
#' @param force Magnitude of the force (defaults to \code{1e-6})
23+
#' @noRd
24+
NULL
25+
26+
#' Get the coordinates of the center of a box.
27+
#' @param b A box like \code{c(x1, y1, x2, y2)}
28+
#' @noRd
29+
NULL
30+
31+
#' Test if a box overlaps another box.
32+
#' @param a A box like \code{c(x1, y1, x2, y2)}
33+
#' @param b A box like \code{c(x1, y1, x2, y2)}
34+
#' @noRd
35+
NULL
36+
37+
#' Compute the repulsion force upon point \code{a} from point \code{b}.
38+
#'
39+
#' The force decays with the squared distance between the points, similar
40+
#' to the force of repulsion between magnets.
41+
#'
42+
#' @param a A point like \code{c(x, y)}
43+
#' @param b A point like \code{c(x, y)}
44+
#' @param force Magnitude of the force (defaults to \code{1e-6})
45+
#' @param direction direction in which to exert force, either "both", "x", or "y"
46+
#' @noRd
47+
NULL
48+
49+
#' Compute the spring force upon point \code{a} from point \code{b}.
50+
#'
51+
#' The force increases with the distance between the points, similar
52+
#' to Hooke's law for springs.
53+
#'
54+
#' @param a A point like \code{c(x, y)}
55+
#' @param b A point like \code{c(x, y)}
56+
#' @param force Magnitude of the force (defaults to \code{1e-6})
57+
#' @param direction direction in which to exert force, either "both", "x", or "y"
58+
#' @noRd
59+
NULL
60+
61+
#' Euclidean distance between two points.
62+
#' @param a A numeric vector.
63+
#' @param b A numeric vector.
64+
#' @return The distance between two points.
65+
#' @noRd
66+
euclid <- function(a, b) {
67+
.Call('_metacoder_euclid', PACKAGE = 'metacoder', a, b)
68+
}
69+
70+
#' Get the coordinates of the center of a box.
71+
#' @param b A box like \code{c(x1, y1, x2, y2)}
72+
#' @noRd
73+
centroid <- function(b) {
74+
.Call('_metacoder_centroid', PACKAGE = 'metacoder', b)
75+
}
76+
77+
#' Find the intersections between a line and a rectangle.
78+
#' @param p1 A point like \code{c(x, y)}
79+
#' @param p2 A point like \code{c(x, y)}
80+
#' @param b A rectangle like \code{c(x1, y1, x2, y2)}
81+
#' @noRd
82+
intersect_line_rectangle <- function(p1, p2, b) {
83+
.Call('_metacoder_intersect_line_rectangle', PACKAGE = 'metacoder', p1, p2, b)
84+
}
85+
86+
#' Adjust the layout of a list of potentially overlapping boxes.
87+
#' @param data_points A numeric matrix with rows representing points like
88+
#' \code{rbind(c(x, y), c(x, y), ...)}
89+
#' @param point_padding_x Padding around each data point on the x axis.
90+
#' @param point_padding_y Padding around each data point on the y axis.
91+
#' @param boxes A numeric matrix with rows representing boxes like
92+
#' \code{rbind(c(x1, y1, x2, y2), c(x1, y1, x2, y2), ...)}
93+
#' @param xlim A numeric vector representing the limits on the x axis like
94+
#' \code{c(xmin, xmax)}
95+
#' @param ylim A numeric vector representing the limits on the y axis like
96+
#' \code{c(ymin, ymax)}
97+
#' @param force Magnitude of the force (defaults to \code{1e-6})
98+
#' @param maxiter Maximum number of iterations to try to resolve overlaps
99+
#' (defaults to 2000)
100+
#' @noRd
101+
repel_boxes <- function(data_points, point_padding_x, point_padding_y, boxes, xlim, ylim, force = 1e-6, maxiter = 2000L, direction = "both") {
102+
.Call('_metacoder_repel_boxes', PACKAGE = 'metacoder', data_points, point_padding_x, point_padding_y, boxes, xlim, ylim, force, maxiter, direction)
103+
}
104+

R/heat_tree.R

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,15 @@ heat_tree.Taxmap <- function(.input, ...) {
304304
#' or setting logical boundaries (such as \code{c(0,1)} for proportions.
305305
#' Note that this is different from the "range" options, which determine the range of graphed sizes/colors.
306306
#'
307+
#' @section Acknowledgements
308+
#'
309+
#' This package includes code from the R package ggrepel to handle label overlap
310+
#' avoidance with permission from the author of ggrepel Kamil Slowikowski. We
311+
#' included the code instead of depending on ggrepel becacuse we are using
312+
#' internal functions to ggrepel that might change in the future. We thank Kamil
313+
#' Slowikowski for letting us use his code and would like to acknowledge his
314+
#' implementation of the label overlap avoidance used in metacoder.
315+
#'
307316
#' @examples
308317
#' \dontrun{
309318
#' # Parse dataset for plotting
@@ -700,7 +709,7 @@ heat_tree.default <- function(taxon_id, supertaxon_id,
700709
overlap <- (overlap ^ 2) / (scaled_vs[distance$index_1] ^ 2 + scaled_vs[distance$index_2] ^ 2)
701710
mean(overlap)
702711
}
703-
712+
704713
# Choose base range based on optimality criteria - - - - - - - - - - - - - - - - - - - - - - - -
705714
optimality_stat <- function(minimum, maximum) {
706715
overlap <- find_overlap(minimum, maximum, all_pairwise)
@@ -966,14 +975,16 @@ heat_tree.default <- function(taxon_id, supertaxon_id,
966975

967976
if (repel_labels) {
968977
movable <- text_data$group != "legend"
969-
text_data[movable, c("x", "y")] <- ggrepel:::repel_boxes(data_points = as.matrix(text_data[movable, c("x", "y")]),
970-
boxes = as.matrix(bounds[movable, c("xmin", "ymin", "xmax", "ymax")]),
971-
point_padding_x = 0, point_padding_y = 0,
972-
xlim = ranges$x,
973-
ylim = ranges$y,
974-
force = 1e-06 * repel_force,
975-
maxiter = repel_iter,
976-
direction = "both")
978+
text_data[movable, c("x", "y")] <- repel_boxes(data_points = as.matrix(text_data[movable, c("x", "y")]),
979+
boxes = as.matrix(bounds[movable, c("xmin", "ymin", "xmax", "ymax")]),
980+
point_padding_x = 0, point_padding_y = 0,
981+
xlim = ranges$x,
982+
ylim = ranges$y,
983+
# hjust = 0.5,
984+
# vjust = 0.5,
985+
force = 1e-06 * repel_force,
986+
maxiter = repel_iter,
987+
direction = "both")
977988
bounds <- label_bounds(label = text_data$label, x = text_data$x, y = text_data$y,
978989
height = text_data$size, rotation = text_data$rotation,
979990
just = text_data$justification)

R/metacoder-package.r renamed to R/metacoder-package.R

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,6 @@
4040
#' @author Zachary Foster
4141
#' @name metacoder
4242
#' @docType package
43+
#' @useDynLib metacoder
44+
#' @importFrom Rcpp sourceCpp
4345
NULL

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,10 @@ Foster ZSL, Sharpton TJ, Grünwald NJ (2017) Metacoder: An R package for visuali
4848
### License
4949

5050
This work is subject to the [MIT License](https://github.com/grunwaldlab/metacoder/blob/master/LICENSE).
51+
52+
### Acknowledgements
53+
54+
This package includes code from the R package [ggrepel](https://github.com/slowkow/ggrepel) to handle label overlap avoidance with permission from the author of [ggrepel](https://github.com/slowkow/ggrepel) [Kamil Slowikowski](https://github.com/slowkow).
55+
We included the code instead of depending on `ggrepel` becacuse we are using internal functions to `ggrepel` that might change in the future.
56+
We thank Kamil Slowikowski for letting us use his code and would like to acknowledge his implementation of the label overlap avoidance used in metacoder.
57+

man/metacoder.Rd

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/RcppExports.cpp

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
// Generated by using Rcpp::compileAttributes() -> do not edit by hand
2+
// Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393
3+
4+
#include <Rcpp.h>
5+
6+
using namespace Rcpp;
7+
8+
// euclid
9+
double euclid(NumericVector a, NumericVector b);
10+
RcppExport SEXP _metacoder_euclid(SEXP aSEXP, SEXP bSEXP) {
11+
BEGIN_RCPP
12+
Rcpp::RObject rcpp_result_gen;
13+
Rcpp::RNGScope rcpp_rngScope_gen;
14+
Rcpp::traits::input_parameter< NumericVector >::type a(aSEXP);
15+
Rcpp::traits::input_parameter< NumericVector >::type b(bSEXP);
16+
rcpp_result_gen = Rcpp::wrap(euclid(a, b));
17+
return rcpp_result_gen;
18+
END_RCPP
19+
}
20+
// centroid
21+
NumericVector centroid(NumericVector b);
22+
RcppExport SEXP _metacoder_centroid(SEXP bSEXP) {
23+
BEGIN_RCPP
24+
Rcpp::RObject rcpp_result_gen;
25+
Rcpp::RNGScope rcpp_rngScope_gen;
26+
Rcpp::traits::input_parameter< NumericVector >::type b(bSEXP);
27+
rcpp_result_gen = Rcpp::wrap(centroid(b));
28+
return rcpp_result_gen;
29+
END_RCPP
30+
}
31+
// intersect_line_rectangle
32+
NumericVector intersect_line_rectangle(NumericVector p1, NumericVector p2, NumericVector b);
33+
RcppExport SEXP _metacoder_intersect_line_rectangle(SEXP p1SEXP, SEXP p2SEXP, SEXP bSEXP) {
34+
BEGIN_RCPP
35+
Rcpp::RObject rcpp_result_gen;
36+
Rcpp::RNGScope rcpp_rngScope_gen;
37+
Rcpp::traits::input_parameter< NumericVector >::type p1(p1SEXP);
38+
Rcpp::traits::input_parameter< NumericVector >::type p2(p2SEXP);
39+
Rcpp::traits::input_parameter< NumericVector >::type b(bSEXP);
40+
rcpp_result_gen = Rcpp::wrap(intersect_line_rectangle(p1, p2, b));
41+
return rcpp_result_gen;
42+
END_RCPP
43+
}
44+
// repel_boxes
45+
DataFrame repel_boxes(NumericMatrix data_points, double point_padding_x, double point_padding_y, NumericMatrix boxes, NumericVector xlim, NumericVector ylim, double force, int maxiter, std::string direction);
46+
RcppExport SEXP _metacoder_repel_boxes(SEXP data_pointsSEXP, SEXP point_padding_xSEXP, SEXP point_padding_ySEXP, SEXP boxesSEXP, SEXP xlimSEXP, SEXP ylimSEXP, SEXP forceSEXP, SEXP maxiterSEXP, SEXP directionSEXP) {
47+
BEGIN_RCPP
48+
Rcpp::RObject rcpp_result_gen;
49+
Rcpp::RNGScope rcpp_rngScope_gen;
50+
Rcpp::traits::input_parameter< NumericMatrix >::type data_points(data_pointsSEXP);
51+
Rcpp::traits::input_parameter< double >::type point_padding_x(point_padding_xSEXP);
52+
Rcpp::traits::input_parameter< double >::type point_padding_y(point_padding_ySEXP);
53+
Rcpp::traits::input_parameter< NumericMatrix >::type boxes(boxesSEXP);
54+
Rcpp::traits::input_parameter< NumericVector >::type xlim(xlimSEXP);
55+
Rcpp::traits::input_parameter< NumericVector >::type ylim(ylimSEXP);
56+
Rcpp::traits::input_parameter< double >::type force(forceSEXP);
57+
Rcpp::traits::input_parameter< int >::type maxiter(maxiterSEXP);
58+
Rcpp::traits::input_parameter< std::string >::type direction(directionSEXP);
59+
rcpp_result_gen = Rcpp::wrap(repel_boxes(data_points, point_padding_x, point_padding_y, boxes, xlim, ylim, force, maxiter, direction));
60+
return rcpp_result_gen;
61+
END_RCPP
62+
}
63+
64+
static const R_CallMethodDef CallEntries[] = {
65+
{"_metacoder_euclid", (DL_FUNC) &_metacoder_euclid, 2},
66+
{"_metacoder_centroid", (DL_FUNC) &_metacoder_centroid, 1},
67+
{"_metacoder_intersect_line_rectangle", (DL_FUNC) &_metacoder_intersect_line_rectangle, 3},
68+
{"_metacoder_repel_boxes", (DL_FUNC) &_metacoder_repel_boxes, 9},
69+
{NULL, NULL, 0}
70+
};
71+
72+
RcppExport void R_init_metacoder(DllInfo *dll) {
73+
R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);
74+
R_useDynamicSymbols(dll, FALSE);
75+
}

src/RcppExports.o

1.36 MB
Binary file not shown.

src/metacoder.so

1.33 MB
Binary file not shown.

0 commit comments

Comments
 (0)