View on GitHub


A Robust BioConductor Framework for Automated Flow Data Analysis

Download this project as a .zip file Download this project as a tar.gz file


OpenCyto supports some default gating routines out of the box, but you may have your own preferred clustering or automated gating algorithm that you’d like to plug into OpenCyto.

We support this through a plugin framework. The OpenCyto gating template puts together a function call from the gating_method and gating_args and calls a wrapper function that must have a specific function signature.

It’s the responsibility of this wrapper function to return a filter object, which is a polygonGate, rectangleGate tmixFilter, or other object that inherits from the flowCore filter-class. These are just instantiations of a gate, with specific coordinates.

Plugging in your gating method

Let’s take an example (contributed by Jacob Frelinger at FHCRC). You have CyTOF data and you want to plugin a gating method for gating on the DNA-DNA channels to identify single-cells.

The gating function itself is shown below:

boundary <-  function(xs) {
    # xs is a matrix
    # find the boundary events that are above a quantile and below a line
    # scale data so that it can be compaired to the results from qnorm
    cxs <- scale(xs)
    # set a boundary level
    f <- qnorm(0.95) 

    # and find the p(x) for that level
    pd <- dmvnorm(c(f, f))[1]
    pxs <- dmvnorm(x=cxs)
    # find those points who are above the boundy level
    idxs <- (pxs > pd)     
    # find points that are below the line with y=-1*x+b
    idxs2 <- ((-1*cxs[,1]) + 1.96) > cxs[,2]     
    # intersection of points below line and above threshold level
    pos_xs <- xs[idxs&idxs2,]
    # find the boundary points of the intersection of cells
    hpts <- chull(pos_xs) 

This returns the convex hull of a set of events that meet some criteria for this specific type of gate. The wrapper function, which is called by OpenCyto, should have the following signature:

.wrapper <- function(fr, pp_res, channels=NA, filterId="",...){

where fr is a flowFrame, pp_res is the output of any preprocessing function (may be NULL), channels is a vector of channel names, filterId is a gate name assigned by OpenCyto from the template, and the ... are additional arguments. The signature of the wrapper must look exactly like this, and the name of the wrapper function must contain a . (dot) prefix, like .wrapper above.

The wrapper for the boundary gate above is the following:

.dnaGate <- function(fr, pp_res, channels=NA, filterId="", ...){
    xs <- exprs(fr[,c(channels)]) # extract just the parameter values being inspected
    pnts <- boundary(xs) # find the verticies of the gate
    return(polygonGate(boundaries=pnts, filterId=filterId))

You see that the signature is exactly as the template .wrapper function. The .dnaGate wrappe extracts the matrix of events from the flowFrame: fr, calls the boundary gate method, and constructs a polygonGate which inherits from the filter-class in flowCore, and returns it. That’s all. Your wrapper just needs to satisfy this contract. Take a flowFrame and some channels, and return a gate (filter).

Registering your gating function

After writing your wrapper, you make it visible to OpenCyto by calling registerPlugins.

registerPlugins(fun=.dnaGate,methodName='dnaGate', dep='mvtnorm',"gating")

This tells openCyto that .dnaGate is my wrapper, I will call it dnaGate in my template, and it depends on the mvtnorm package, and is a “gating” method (as opposed to a “preprocessing” method. If the dependency is not installed, the function will not be registered. This is useful if you want to distribute your plugins to other users.