Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Rphenograph_iris_cluster.png
^appveyor\.yml$
^\.travis\.yml$
^codecov\.yml$
^.*\.Rproj$
^\.Rproj\.user$
11 changes: 11 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# R for travis: see documentation at https://docs.travis-ci.com/user/languages/r

language: R
sudo: true
cache: packages

r_packages:
- covr

after_success:
- Rscript -e 'covr::codecov()'
9 changes: 5 additions & 4 deletions DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Package: Rphenograph
Type: Package
Title: R implementation of the phenograph algorithm
Version: 0.99.1
Version: 0.99.1.9001
Date: 2015-09-07
Author: Hao Chen
Maintainer: Hao Chen <[email protected]>
Expand All @@ -13,14 +13,15 @@ Description: A simple R implementation of the phenograph [PhenoGraph](http://
sets, and then identifying communities using the well known ["Louvain method"]
(https://sites.google.com/site/findcommunities/) in this graph.
Depends:
R (>= 2.10.0), ggplot2, igraph
R (>= 2.10.0)
Imports:
igraph(>= 1.0.1),
RANN(>= 2.5),
Rcpp (>= 0.12.0),
ggplot2
LinkingTo: Rcpp
Suggests:
testthat
testthat,
covr
License: Artistic-2.0
RoxygenNote: 5.0.1
RoxygenNote: 6.1.1
4 changes: 4 additions & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ export(Rphenograph)
export(find_neighbors)
import(ggplot2)
importFrom(RANN,nn2)
importFrom(Rcpp,sourceCpp)
importFrom(igraph,as_adjacency_matrix)
importFrom(igraph,cluster_louvain)
importFrom(igraph,graph.data.frame)
importFrom(igraph,graph_from_adjacency_matrix)
importFrom(igraph,membership)
importFrom(igraph,modularity)
useDynLib(Rphenograph)
useDynLib(Rphenograph, .registration = TRUE)
4 changes: 2 additions & 2 deletions R/RcppExports.R
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This file was generated by Rcpp::compileAttributes
# Generated by using Rcpp::compileAttributes() -> do not edit by hand
# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393

jaccard_coeff <- function(idx) {
.Call('Rphenograph_jaccard_coeff', PACKAGE = 'Rphenograph', idx)
.Call('_Rphenograph_jaccard_coeff', PACKAGE = 'Rphenograph', idx)
}

5 changes: 5 additions & 0 deletions R/Rphenograph-package.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## usethis namespace: start
#' @importFrom Rcpp sourceCpp
#' @useDynLib Rphenograph, .registration = TRUE
## usethis namespace: end
NULL
54 changes: 38 additions & 16 deletions R/phenograph.R
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#'
#' @param data matrix; input data matrix
#' @param k integer; number of nearest neighbours (default:30)
#' @param directed logical; whether to use a symmetric (default) or asymmetric ("directed") graph (default:FALSE)
#' @param prune logical; determines whether symmetric matrix is generated by iGraph (FALSE) or element-wise multiplication (TRUE) with the transpose (defaults:FALSE)
#' @param clust_fun function; community detection algorithm. Defaults to cluster_louvian. Other options: cluster_walktrap, cluster_spinglass, cluster_leading_eigen, cluster_edge_betweenness, cluster_fast_greedy, cluster_label_prop
#'
#' @return a list contains an igraph graph object for \code{graph_from_data_frame} and a communities object, the operations of this class contains:
#' \item{print}{returns the communities object itself, invisibly.}
Expand All @@ -28,25 +31,33 @@
#'
#' @references Jacob H. Levine and et.al. Data-Driven Phenotypic Dissection of AML Reveals Progenitor-like Cells that Correlate with Prognosis. Cell, 2015.
#' @examples
#' library(igraph)
#' iris_unique <- unique(iris) # Remove duplicates
#' data <- as.matrix(iris_unique[,1:4])
#' Rphenograph_out <- Rphenograph(data, k = 45)
#' modularity(Rphenograph_out[[2]])
#' membership(Rphenograph_out[[2]])
#' iris_unique$phenograph_cluster <- factor(membership(Rphenograph_out[[2]]))
#' ggplot(iris_unique, aes(x=Sepal.Length, y=Sepal.Width, col=Species, shape=phenograph_cluster)) + geom_point(size = 3)+theme_bw()
#' library(ggplot2)
#' ggplot(iris_unique, aes(x=Sepal.Length, y=Sepal.Width, col=Species, shape=phenograph_cluster)) +
#' geom_point(size = 3) + theme_bw()
#'
#' @importFrom igraph graph.data.frame cluster_louvain modularity membership
#' @importFrom igraph graph.data.frame cluster_louvain modularity membership as_adjacency_matrix graph_from_adjacency_matrix
#' @import ggplot2
#' @useDynLib Rphenograph
#'
#' @export
Rphenograph <- function(data, k=30){
Rphenograph <- function(data, k=30, directed=FALSE, prune=FALSE, clust_fun=NULL){
if(prune){
print("Setting directed to FALSE because prune is TRUE")
directed <- FALSE
}

if(is.data.frame(data))
data <- as.matrix(data)

if(!is.matrix(data))
stop("Wrong input data, should be a data frame of matrix!")
stop("Wrong input data, should be a data frame or matrix!")

if(k<1){
stop("k must be a positive integer!")
Expand All @@ -61,20 +72,32 @@ Rphenograph <- function(data, k=30){
cat(" Finding nearest neighbors...")
t1 <- system.time(neighborMatrix <- find_neighbors(data, k=k+1)[,-1])
cat("DONE ~",t1[3],"s\n", " Compute jaccard coefficient between nearest-neighbor sets...")
t2 <- system.time(links <- jaccard_coeff(neighborMatrix))

t2 <- system.time(links <- Rphenograph:::jaccard_coeff(neighborMatrix))
cat("DONE ~",t2[3],"s\n", " Build undirected graph from the weighted links...")
links <- links[links[,1]>0, ]
relations <- as.data.frame(links)
colnames(relations)<- c("from","to","weight")
t3 <- system.time(g <- graph.data.frame(relations, directed=FALSE))

colnames(relations) <- c("from","to","weight")
t3 <- system.time({
if(prune){
cat("Removing non-symmetric links...")
g <- graph.data.frame(relations, directed=TRUE)
mat <- as_adjacency_matrix(g, sparse = FALSE)
mat <- mat * t(mat)
g <- graph_from_adjacency_matrix(mat, mode = "undirected")
} else {
g <- graph.data.frame(relations, directed=directed)
}
})

# Other community detection algorithms:
# cluster_walktrap, cluster_spinglass,
# cluster_leading_eigen, cluster_edge_betweenness,
# cluster_fast_greedy, cluster_label_prop
if(is.null(clust_fun)) clust_fun <- cluster_louvain

cat("DONE ~",t3[3],"s\n", " Run louvain clustering on the graph ...")
t4 <- system.time(community <- cluster_louvain(g))
t4 <- system.time(community <- clust_fun(g))
cat("DONE ~",t4[3],"s\n")

message("Run Rphenograph DONE, totally takes ", sum(c(t1[3],t2[3],t3[3],t4[3])), "s.")
Expand All @@ -84,7 +107,6 @@ Rphenograph <- function(data, k=30){
return(list(g, community))
}


#' K Nearest Neighbour Search
#'
#' Uses a kd-tree to find the p number of near neighbours for each point in an input/output dataset.
Expand All @@ -94,8 +116,7 @@ Rphenograph <- function(data, k=30){
#' to within a specified error bound. For more information on the ANN library please
#' visit http://www.cs.umd.edu/~mount/ANN/.
#'
#' @param data matrix; input data matrix
#' @param k integer; number of nearest neighbours
#' @describeIn Rphenograph Uses a kd-tree to find the p number of near neighbours for each point in an input/output dataset.
#'
#' @return a n-by-k matrix of neighbor indices
#'
Expand All @@ -107,6 +128,7 @@ Rphenograph <- function(data, k=30){
#' @importFrom RANN nn2
#' @export
find_neighbors <- function(data, k){
nearest <- nn2(data, data, k, searchtype = "standard")
return(nearest[[1]])
}
nearest <- nn2(data, data, k, searchtype = "standard")
return(nearest[[1]])
}

4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ R implementation of the PhenoGraph algorithm
===============

### Rphenograph
[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/TomKellyGenetics/Rphenograph?branch=master&svg=true)](https://ci.appveyor.com/project/TomKellyGenetics/Rphenograph)
[![Travis-CI Build Status](https://travis-ci.org/TomKellyGenetics/Rphenograph.svg?branch=master)](https://travis-ci.org/TomKellyGenetics/Rphenograph)
[![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](http://www.repostatus.org/badges/latest/active.svg)](http://www.repostatus.org/#active)
[![Coverage Status](https://img.shields.io/codecov/c/github/JinmiaoChenLab/Rphenograph/master.svg)](https://codecov.io/github/JinmiaoChenLab/Rphenograph?branch=master)

A simple R implementation of the [PhenoGraph](http://www.cell.com/cell/abstract/S0092-8674(15)00637-6) [1] algorithm, which is a clustering method designed for high-dimensional single-cell data analysis. It works by creating a graph ("network") representing phenotypic similarities between cells by calclating the Jaccard coefficient between nearest-neighbor sets, and then identifying communities using the well known [Louvain method](https://sites.google.com/site/findcommunities/) in this graph.

Expand Down
17 changes: 17 additions & 0 deletions Rphenograph.Rproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
Version: 1.0

RestoreWorkspace: Default
SaveWorkspace: Default
AlwaysSaveHistory: Default

EnableCodeIndexing: Yes
UseSpacesForTab: Yes
NumSpacesForTab: 2
Encoding: UTF-8

RnwWeave: Sweave
LaTeX: pdfLaTeX

BuildType: Package
PackageUseDevtools: Yes
PackageInstallArgs: --no-multiarch --with-keep.source
File renamed without changes
45 changes: 45 additions & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# DO NOT CHANGE the "init" and "install" sections below

# Download script file from GitHub
init:
ps: |
$ErrorActionPreference = "Stop"
Invoke-WebRequest http://raw.github.com/krlmlr/r-appveyor/master/scripts/appveyor-tool.ps1 -OutFile "..\appveyor-tool.ps1"
Import-Module '..\appveyor-tool.ps1'

install:
ps: Bootstrap

cache:
- C:\RLibrary

# Adapt as necessary starting from here

build_script:
- travis-tool.sh install_deps

test_script:
- travis-tool.sh run_tests

on_failure:
- 7z a failure.zip *.Rcheck\*
- appveyor PushArtifact failure.zip

artifacts:
- path: '*.Rcheck\**\*.log'
name: Logs

- path: '*.Rcheck\**\*.out'
name: Logs

- path: '*.Rcheck\**\*.fail'
name: Logs

- path: '*.Rcheck\**\*.Rout'
name: Logs

- path: '\*_*.tar.gz'
name: Bits

- path: '\*_*.zip'
name: Bits
1 change: 1 addition & 0 deletions codecov.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
comment: false
40 changes: 35 additions & 5 deletions man/Rphenograph.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 0 additions & 32 deletions man/find_neighbors.Rd

This file was deleted.

3 changes: 3 additions & 0 deletions src/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.o
*.so
*.dll
Loading