# CMplot: drawing Manhattan and circular Manhattan plots from GWAS results in R

> CMplot is an R package that turns genome-wide association study output into a Manhattan plot, a circular Manhattan plot, an SNP density track and a Q-Q plot, with around fifty parameters and two example datasets shipped with it. It suits a geneticist who already has a p-value table and wants a publication quality figure without writing the plotting code, and it does nothing beyond drawing, so the upstream analysis stays yours.

**YinLiLin/CMplot** — 📊 Circular and Rectangular Manhattan Plot

- Repository: https://github.com/YinLiLin/CMplot
- Stars: 648 · Forks: 123
- Language: R
- License: not declared
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/yinlilin-cmplot

## A drawing tool for output you already have

CMplot is described as a high-quality drawing tool designed for Manhattan plot of genomic analysis, and the primary language is R. The package is published on CRAN, the repository lists a version badge of 4.6.0, and the last push was on 2026-05-08.

The scope is narrow and worth stating at the start. CMplot takes a data frame of per-marker statistics and draws it. It does not run the association analysis, it does not read sequencing data, and it does not correct for population structure. Whatever produced the p-values produced them elsewhere.

What it does produce is the figure that usually takes the longest to get right in a paper. The README says that CMplot could handle not only genome-wide association study results, but also SNP effects, Fst, tajima's D and so on. The common denominator is a table where each row is a marker, with a chromosome, a position, and one or more numeric columns that are either p-values or effect sizes. The package is agnostic about which, and the plotting logic is the same.

The author places CMplot in a wider set of tools for genetic analyses and genomic breeding, and the README links several sibling projects, including HIBLUP as a versatile and easy-to-use GS toolbox, SIMER for data simulation for life science and breeding, KAML as an advanced GS method for complex traits, IAnimal as an omics knowledgebase for animals, hibayes as a Bayesian-based GWAS and GS tool, and rMVP as an efficient and easy-to-use GWAS tool. That is a useful map of the ecosystem the package is designed for, and it also tells you the intended input format, since the linked tools all produce the same kind of marker table.

The licence field on the repository is left empty, and the repository has no GitHub releases, so the CRAN version is the one to read.

## Installing from CRAN, or sourcing the script from master

The installation is two lines, and the README gives a third route for people who want the newest code.

```r
> install.packages("CMplot")
> library("CMplot")
```

For the latest version on GitHub, the README shows sourcing the script directly.

```r
> source("https://raw.githubusercontent.com/YinLiLin/CMplot/master/R/CMplot.r")
```

That second route is worth understanding rather than just copying. Sourcing a raw file from a branch means the code you run is whatever is on master at that moment, with no version pin and no CRAN review in between, which is fine for a plotting function you are going to read and adapt, and is the wrong choice for a figure in a submitted paper where you need to be able to say which version produced it.

The package ships two example datasets, and the README explains the column conventions. As the example datasets, the first three columns are names, chromosome, position of SNPs respectively, and the rest of columns are the pvalues of GWAS or effects of GS and GP for traits, with the number of traits unlimited. There is also a note that if plotting SNP_Density, only the first three columns are needed.

That last point is the design in one sentence. A single function handles every plot type, so the number of trait columns varies, and the SNP density plot is the case that ignores the numeric columns entirely.

The two datasets are a good illustration of the flexibility. The pig60K data is described as calculated p-values by MLM and carries three trait columns, while cattle50K is described as calculated SNP effects by rrblup and carries a somatic cell score and two production traits, milk yield and fat percentage.

```r
> data(pig60K)   #calculated p-values by MLM
> data(cattle50K)   #calculated SNP effects by rrblup
> head(pig60K)
```

A note on the tooling: the repository is small, with an R directory holding the package source, a Figure directory of rendered output, a README, and a User Manual for CMplot.pdf. There is no test suite and no build infrastructure, which is normal for a single-function plotting package but does mean the manual PDF is the reference documentation.

## Fifty parameters, and the ones that change the figure

The README states that a total of 50 or so parameters are available in CMplot, and that typing ?CMplot gets the detail of all parameters. The examples then show which ones actually change the output, and reading them is a reasonable substitute for the manual.

The SNP density example is the most instructive, because it exercises a dozen parameters in one call.

```r
> CMplot(pig60K,plot.type="d",bin.size=1e6,chr.den.col=c("darkgreen", "yellow", "red"),file="jpg",file.name=NULL,dpi=300,
    main="illumilla_60K",file.output=TRUE,verbose=TRUE,width=9,height=6)
```

The commented lines under that call explain the parameters in the author's own words, and they are the practical reference. bin.size is the window size, set here to 1e6. bin.breaks controls the legend breaks, for example bin.breaks=seq(0, 50, 10), and the windows out of the breaks will be plotted in the same color as min or max. file is the format of the output file, and if file="png", CMplot will output a transparent background file. file.name specifies the output file name, and the default is corresponding column name when setting file.name=NULL. chr.labels changes the chromosome names, and main changes the title of the plots.

There is also a note about the chromosome axis that answers a question every new user has. To show the full length of each chromosome, users can manually add every chromosome with one SNP, whose position equals to the length of corresponding chromosome, then specify the parameter CMplot(..., chr.pos.max=TRUE).

That workaround is the weakest part of the design. Rather than reading chromosome lengths from a reference, the package asks you to pad the data yourself, which means every user reimplements the same padding. A package that took a genome assembly as an argument would not have this problem, but the package does not appear to take one.

The verbose flag prints the per-window detail, and the README shows how to capture it into a variable, windinfo <- CMplot(pig60K, plot.type="d", ...), which is the mechanism for pulling the underlying numbers back out.

## The circular plot, and the threshold colouring behind it

The circular Manhattan plot is the one that gives the package its name, and the example shows how many parameters it takes to get a usable one.

```r
> CMplot(pig60K,type="p",plot.type="c",chr.labels=paste("Chr",c(1:18,"X","Y"),sep=""),r=0.4,cir.axis=TRUE,
        outward=FALSE,cir.axis.col="black",cir.chr.h=1.3,chr.den.col="black",file="jpg",
        file.name=NULL,dpi=300,file.output=TRUE,verbose=TRUE,width=10,height=10)
# to remove the grid line in circles, add parameter cir.axis.grid=FALSE
# file.name: specify the output file name, the default is corresponding column name
```

The parameters here are specific to the circular layout. r is the radius ratio, cir.axis controls the circular axis, outward decides which way the labels sit, cir.axis.col and cir.chr.h set the axis colour and the height of the chromosome bands, and chr.den.col colours the density ring. There is also a chr.labels argument that takes a character vector, and the example builds it with paste("Chr", c(1:18,"X","Y"), sep=""), which is the readable way to label the chromosomes of the pig dataset.

The second circular example shows the threshold colouring, and the call is cut off in the README at the threshold argument, so the full form is not visible here.

```r
> CMplot(pig60K,type="p",plot.type="c",r=0.4,col=c("grey30","grey60"),chr.labels=paste("Chr",c(1:18,"X","Y"),sep=""),
      threshold=c(1e-6,1e-4
```

What that partial call shows is a different colouring scheme, two greys rather than a significance palette, with threshold set to two values, 1e-6 and 1e-4, which is the two-cutoff pattern used to distinguish suggestive from genome-wide significant hits in a GWAS plot.

The distinction between plot.type and type is worth pausing on, because it is a small trap. plot.type selects the figure, c for circular, d for SNP density, q for the Q-Q plot, b for the bar or regional plot, and p for the standard Manhattan plot, while type selects which column the numbers come from, p for p-values and e for effects. Passing type="p" and plot.type="c" is the circular Manhattan plot, while plot.type="c" with the default type gives the circular plot of the default statistic.

## Where the boundary of this tool sits

Three limits are worth naming.

The first is that the package is a drawing tool and nothing more. The p-values, the effect sizes, the Fst values and the Tajima's D values all arrive in the input table, and CMplot plots whatever is in the columns. It does not validate them, it does not filter them, and it does not tell you whether a p-value is significant for your design. A figure that looks convincing is not a check on the analysis behind it.

The second is the chromosome length problem described earlier, which is a real ergonomic cost in the most common use case, drawing a Manhattan plot across a full genome.

The third is the single-function model. Every plot type is an argument to the same CMplot call, and around fifty parameters are shared across them. That is efficient when you know what you want and it is what makes the documentation a PDF manual rather than a set of examples per function. It also means that a multi-panel figure, a plot with two different statistics side by side, or a figure that has to be regenerated from a pipeline with slightly different inputs, is a scripting exercise rather than a call you can make.

The alternative approaches sit on either side of that. A general statistical plotting package, with the extra work of writing the geometry yourself, gives complete control over a multi-panel figure and produces a vector output, at the cost of the parameter set and the chromosome handling that CMplot already does. A dedicated interactive genomic visualisation tool gives a different set of trade-offs again, since it is a program rather than a library and it expects the analysis to have been done elsewhere in a format it understands.

And there is the option of using the sibling tools directly. The README points at rMVP as an efficient and easy-to-use GWAS tool, and CMplot has been integrated into the developed GWAS package rMVP, which means the plotting path is already reachable from a tool that does the analysis too.

## Conclusion

CMplot fits a geneticist or breeder who has a table of p-values or SNP effects and wants a figure for a paper or a report, and it does not fit a team that needs an interactive exploration tool, a multi-panel figure pipeline, or a plot that reflects anything other than the numbers in the input table. Before using it, check the column conventions in the two example datasets, since the first three columns are always interpreted as name, chromosome and position, and note that the package is on CRAN at version 4.6.0, so a new analysis should be run against that release rather than against the raw script on the master branch.

## FAQ

### How do I install CMplot?

CMplot is available on CRAN, so install.packages("CMplot") followed by library("CMplot") is enough. The README also shows sourcing the latest version straight from the repository with source("https://raw.githubusercontent.com/YinLiLin/CMplot/master/R/CMplot.r"), which runs the current master branch without a CRAN release.

### What columns does CMplot expect in the input data?

The first three columns are the names, chromosome and position of the SNPs respectively, and the remaining columns are the pvalues of GWAS or the effects of GS and GP for traits, with the number of traits unlimited. For an SNP density plot only the first three columns are needed.

### How do I make a circular Manhattan plot with CMplot?

Call CMplot with plot.type="c", for example with type="p", r for the radius ratio, cir.axis for the circular axis, chr.labels built with paste, and the colour and size arguments. The README notes that cir.axis.grid=FALSE removes the grid line in the circles.

### How many plot types does CMplot support and how do I pick one?

The README states that around 50 parameters are available and that typing ?CMplot gives the detail of all of them, and it shows a circular Manhattan plot, a circular plot with threshold colouring and an SNP density plot. The plot type is selected with plot.type while type selects whether the plotted numbers are p-values or effects.

## Sources

- [Issues](https://github.com/YinLiLin/CMplot/issues)
- [README](https://github.com/YinLiLin/CMplot/blob/master/README.md)
- [YinLiLin/CMplot on GitHub](https://github.com/YinLiLin/CMplot)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/yinlilin-cmplot
