07 June 2011

Handling a BigWig file from Java+JNI : my notebook

In a previous post I've shown how to use a Java JNI interface to control a NCURSES panel from a java program.
I'll show here how to use java JNI to call the C methods developped by Jim Kent's team at UCSC to handle a BigWig file.

The Makefile for compiling the following sources is defined below:

JAVA_HOME=/path/to/jdk
JKENTSRC=path/to/jkentsrc
CFLAGS= -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -I ${JKENTSRC}/src/inc -I ${JAVA_HOME}/include -I ${JAVA_HOME}/include/linux
JAVACC=javacc
test:libbigwig.so
java BigWig wgEncodeCrgMapabilityAlign100mer.bigWig
libbigwig.so:BigWig.h BigWig.c
gcc ${CFLAGS} -fpic -c BigWig.c -o BigWig.o
gcc -shared -o $@ BigWig.o ${JKENTSRC}/src/lib/jkent/jkweb.a -lm -lz
BigWig.h:BigWig.java
${JAVA_HOME}/bin/javac BigWig.java
${JAVA_HOME}/bin/javah BigWig
view raw Makefile hosted with ❤ by GitHub


Export the LD_LIBRARY_PATH:
export LD_LIBRARY_PATH=/path/to/current/directory


Download Jim Kent's sources from http://hgdownload.cse.ucsc.edu/admin/jksrc.zip. See the README file to compile jksrc/lib and jksrc/jkOwnLib.

The java source BigWig.java declares seven natives JNI methods. They will call the C methods for opening and closing the bigWig file, and getting the summaries in a given genomic range.
import java.io.*;
public class BigWig
{
private long fd=0L;
/** open the bigWig file */
private native long open(String fname);
/** close the big wig file */
private native void close(long fid);
/** get the summaries in the given genomic range */
private native Double mean(long fid,String chrom,int start,int end);
private native Double max(long fid,String chrom,int start,int end);
private native Double min(long fid,String chrom,int start,int end);
private native Double coverage(long fid,String chrom,int start,int end);
private native Double stddev(long fid,String chrom,int start,int end);
public BigWig(File f) throws IOException
{
if(!f.exists()) throw new FileNotFoundException(f.toString());
this.fd = open(f.getAbsolutePath());
if(this.fd==0L) throw new IOException("Cannot open bigwig "+f);
}
@Override
protected void finalize() throws Throwable {
try {
close();
} finally {
super.finalize();
}
}
public Double getMean(String chrom,int start,int end)
{
if(fd==0L) return null;
return mean(fd,chrom,start,end);
}
public Double getMax(String chrom,int start,int end)
{
if(fd==0L) return null;
return max(fd,chrom,start,end);
}
public Double getMin(String chrom,int start,int end)
{
if(fd==0L) return null;
return min(fd,chrom,start,end);
}
public Double getCoverage(String chrom,int start,int end)
{
if(fd==0L) return null;
return coverage(fd,chrom,start,end);
}
public Double getStdDev(String chrom,int start,int end)
{
if(fd==0L) return null;
return stddev(fd,chrom,start,end);
}
public void close()
{
if(this.fd!=0L)
{
close(this.fd);
}
this.fd=0L;
}
public static void main(String args[]) throws IOException
{
System.loadLibrary("bigwig");
BigWig big=new BigWig(new File(args[0]));
System.err.println(big.getMean("chr1",0,1000000));
System.err.println(big.getMax("chr1",0,1000000));
System.err.println(big.getMin("chr1",0,1000000));
System.err.println(big.getCoverage("chr1",0,1000000));
System.err.println(big.getStdDev("chr1",0,1000000));
System.err.println(big.getMean("chr2",0,1000000));
System.err.println(big.getMean("chr1",0,10));
big.close();
}
}
view raw BigWig.java hosted with ❤ by GitHub


After compiling the java source, the following C header is generated with javah:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class BigWig */
#ifndef _Included_BigWig
#define _Included_BigWig
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: BigWig
* Method: open
* Signature: (Ljava/lang/String;)J
*/
JNIEXPORT jlong JNICALL Java_BigWig_open
(JNIEnv *, jobject, jstring);
/*
* Class: BigWig
* Method: close
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_BigWig_close
(JNIEnv *, jobject, jlong);
/*
* Class: BigWig
* Method: mean
* Signature: (JLjava/lang/String;II)Ljava/lang/Double;
*/
JNIEXPORT jobject JNICALL Java_BigWig_mean
(JNIEnv *, jobject, jlong, jstring, jint, jint);
/*
* Class: BigWig
* Method: max
* Signature: (JLjava/lang/String;II)Ljava/lang/Double;
*/
JNIEXPORT jobject JNICALL Java_BigWig_max
(JNIEnv *, jobject, jlong, jstring, jint, jint);
/*
* Class: BigWig
* Method: min
* Signature: (JLjava/lang/String;II)Ljava/lang/Double;
*/
JNIEXPORT jobject JNICALL Java_BigWig_min
(JNIEnv *, jobject, jlong, jstring, jint, jint);
/*
* Class: BigWig
* Method: coverage
* Signature: (JLjava/lang/String;II)Ljava/lang/Double;
*/
JNIEXPORT jobject JNICALL Java_BigWig_coverage
(JNIEnv *, jobject, jlong, jstring, jint, jint);
/*
* Class: BigWig
* Method: stddev
* Signature: (JLjava/lang/String;II)Ljava/lang/Double;
*/
JNIEXPORT jobject JNICALL Java_BigWig_stddev
(JNIEnv *, jobject, jlong, jstring, jint, jint);
#ifdef __cplusplus
}
#endif
#endif
view raw BigWig.h hosted with ❤ by GitHub


The C source implements the native methods defined in the java source. The code was inspired from ${JKENTSRC}/src/utils/bigWigSummary/bigWigSummary.c.
#include "BigWig.h"
#include "common.h"
#include "linefile.h"
#include "hash.h"
#include "options.h"
#include "sqlNum.h"
#include "udc.h"
#include "bigWig.h"
JNIEXPORT jlong JNICALL Java_BigWig_open
(JNIEnv *env, jobject o, jstring s)
{
const jbyte *fname = (*env)->GetStringUTFChars(env, s, NULL);
if(fname==NULL) return 0L;
struct bbiFile *bwf = bigWigFileOpen((char*)fname);
(*env)->ReleaseStringUTFChars(env, s, fname);
return (long)(bwf);
}
static jobject Java_BigWigSummary
(JNIEnv *env, jobject o, jlong ptr, jstring chrom, jint start, jint end,enum bbiSummaryType type)
{
jobject ret=NULL;
jbyte *reference ;
struct bbiFile *bwf =(struct bbiFile*)ptr;
double nan0 = strtod("NaN", NULL);
double summaryValues[]={nan0};
if(bwf==NULL) return NULL;
if(chrom==NULL) return NULL;
reference =(jbyte*) (*env)->GetStringUTFChars(env, chrom, NULL);
if(reference==NULL) return NULL;
if (bigWigSummaryArray(bwf, (char*)reference, start, end, type, 1, summaryValues))
{
if(!isnan(summaryValues[0]))
{
jclass clazz = (*env)->FindClass(env, "java/lang/Double");
jmethodID constructor = (*env)->GetMethodID(env,clazz, "<init>", "(D)V");
ret= (*env)->NewObject(env,clazz, constructor,(jdouble)summaryValues[0]);
}
}
(*env)->ReleaseStringUTFChars(env, chrom, reference);
return ret;
}
JNIEXPORT jobject JNICALL Java_BigWig_mean
(JNIEnv *env, jobject o, jlong ptr, jstring chrom, jint start, jint end)
{
return Java_BigWigSummary(env,o,ptr,chrom,start,end,bbiSumMean);
}
JNIEXPORT jobject JNICALL Java_BigWig_min
(JNIEnv *env, jobject o, jlong ptr, jstring chrom, jint start, jint end)
{
return Java_BigWigSummary(env,o,ptr,chrom,start,end,bbiSumMax);
}
JNIEXPORT jobject JNICALL Java_BigWig_max
(JNIEnv *env, jobject o, jlong ptr, jstring chrom, jint start, jint end)
{
return Java_BigWigSummary(env,o,ptr,chrom,start,end,bbiSumMin);
}
JNIEXPORT jobject JNICALL Java_BigWig_coverage
(JNIEnv *env, jobject o, jlong ptr, jstring chrom, jint start, jint end)
{
return Java_BigWigSummary(env,o,ptr,chrom,start,end,bbiSumCoverage);
}
JNIEXPORT jobject JNICALL Java_BigWig_stddev
(JNIEnv *env, jobject o, jlong ptr, jstring chrom, jint start, jint end)
{
return Java_BigWigSummary(env,o,ptr,chrom,start,end,bbiSumStandardDeviation);
}
JNIEXPORT void JNICALL Java_BigWig_close
(JNIEnv *env, jobject o, jlong ptr)
{
struct bbiFile *bwf =(struct bbiFile*)ptr;
if(bwf==NULL) return;
bigWigFileClose(&bwf);
}
view raw BigWig.c hosted with ❤ by GitHub


Download a bigwig file for a test: http://hgdownload.cse.ucsc.edu/goldenPath/hg19/encodeDCC/wgEncodeMapability/wgEncodeCrgMapabilityAlign100mer.bigWig.

The main method in BigWig.java contains.a test:
java BigWig wgEncodeCrgMapabilityAlign100mer.bigWig
0.394749239542279

And here is the original output of the utility 'bigWigSummary':
bigWigSummary wgEncodeCrgMapabilityAlign100mer.bigWig -type=mean chr1 1 1000000 1
0.394749


That's it,

Piere

No comments: