Showing posts with label jni. Show all posts
Showing posts with label jni. Show all posts

26 April 2013

Java JNI bindings for BWA(mem-lite)

Motivation

BWA 7.4(http://bio-bwa.sourceforge.net/) contains a small C example(https://github.com/lh3/bwa/blob/master/example.c) for running bwa-mem as a library (bwamem-lite). I created some JNI bindings to see if I can bind the C bwa library to java and get the same output than bwamem-lite. I put the code on github at https://github.com/lindenb/jbwa.

Example


(compare to https://github.com/lh3/bwa/blob/master/example.c )

System.loadLibrary("bwajni");
BwaIndex index=new BwaIndex(new File("hg19.fa"));
BwaMem mem=new BwaMem(index);
KSeq kseq=new KSeq(new File("input.fastq.gz");
ShortRead read=null;
while((read=kseq.next())!=null)
        {
        for(AlnRgn a: mem.align(read))
                {
                if(a.getSecondary()>=0) continue;
                System.out.println(  read.getName()+"\t"+  a.getStrand()+"\t"+  a.getChrom()+"\t"+
                        a.getPos()+"\t"+ a.getMQual()+"\t"+ a.getCigar()+"\t"+  a.getNm() );
                }
        }
kseq.dispose();
index.close();
mem.dispose();

Testing


Here is the ouput of the JAVA version:

gunzip -c input.fastq.gz | head -n 4000 |\
java  -Djava.library.path=src/main/native -cp src/main/java \
   com.github.lindenb.jbwa.jni.Example human_g1k_v37.fasta -| tail 


HWI-1KL149:20:C1CU7ACXX:4:1101:3077:33410       +       3       38647538        60      89M11S  1
HWI-1KL149:20:C1CU7ACXX:4:1101:3396:33445       +       8       52567289        60      100M    1
HWI-1KL149:20:C1CU7ACXX:4:1101:10013:33288      -       1       156104115       60      100M    1
HWI-1KL149:20:C1CU7ACXX:4:1101:10390:33496      -       6       123824853       60      100M    1
HWI-1KL149:20:C1CU7ACXX:4:1101:13537:33483      +       2       157367092       60      100M    1
HWI-1KL149:20:C1CU7ACXX:4:1101:14139:33390      +       20      31413797        60      100M    1
HWI-1KL149:20:C1CU7ACXX:4:1101:14514:33458      +       2       179401813       60      100M    1
HWI-1KL149:20:C1CU7ACXX:4:1101:15292:33282      +       15      63335820        60      100M    1
HWI-1KL149:20:C1CU7ACXX:4:1101:16960:33276      -       12      110782784       60      100M    1
HWI-1KL149:20:C1CU7ACXX:4:1101:17355:33322      +       6       126077895       60      100M    1

And the ouput of the Native C version:

gunzip -c input.fastq.gz | head -n 4000 |\
bwa-0.7.4/bwamem-lite human_g1k_v37.fasta - | tail 

HWI-1KL149:20:C1CU7ACXX:4:1101:3077:33410       +       3       38647538        60      89M11S  1
HWI-1KL149:20:C1CU7ACXX:4:1101:3396:33445       +       8       52567289        60      100M    1
HWI-1KL149:20:C1CU7ACXX:4:1101:10013:33288      -       1       156104115       60      100M    1
HWI-1KL149:20:C1CU7ACXX:4:1101:10390:33496      -       6       123824853       60      100M    1
HWI-1KL149:20:C1CU7ACXX:4:1101:13537:33483      +       2       157367092       60      100M    1
HWI-1KL149:20:C1CU7ACXX:4:1101:14139:33390      +       20      31413797        60      100M    1
HWI-1KL149:20:C1CU7ACXX:4:1101:14514:33458      +       2       179401813       60      100M    1
HWI-1KL149:20:C1CU7ACXX:4:1101:15292:33282      +       15      63335820        60      100M    1
HWI-1KL149:20:C1CU7ACXX:4:1101:16960:33276      -       12      110782784       60      100M    1
HWI-1KL149:20:C1CU7ACXX:4:1101:17355:33322      +       6       126077895       60      100M    1

GUI


As a test I also created a swing-Based interface for BWA:

java  -Djava.library.path=src/main/native  -cp src/main/java \
    com.github.lindenb.jbwa.jni.BwaFrame human_g1k_v37.fasta



That's it,


Pierre

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:


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.


After compiling the java source, the following C header is generated with javah:


The C source implements the native methods defined in the java source. The code was inspired from ${JKENTSRC}/src/utils/bigWigSummary/bigWigSummary.c.


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

10 January 2008

JAVA Native Interface (JNI): notebook

The JAVA Native Interface (JNI)allows Java code running in the Java virtual machine to call and (be called) some methods from libraries written in C/C++. I've learned this technology by trying to use the CURSES library (an API allowing the programmer to write text user interfaces in a terminal).

We starts by creating a java class: NCurses.java


1 /* A JNI test */
2 public class NCurses
3 {
4 public NCurses() {}
5 /** initializes the ncurses library */
6 public native static int install();
7 /** disposes the ncurses library */
8 public native static int uninstall();
9 /** set character on screen */
10 public native static void setCharAt(int x,int y,int ch);
11 /** update the screen */
12 public native static void refresh();
13 /** get the number of rows */
14 public native int getRowCount();
15 /** get the number of columns */
16 public native int getColumnCount();
17 /** inverse video */
18 public native int standout();
19 /** normal video */
20 public native int standend();
21
22 /** draw a string at the given position */
23 public void drawString(String s,int x, int y)
24 {
25 int maxx= getColumnCount();
26 for(int i=0;i< s.length() && i+x < maxx;++i)
27 {
28 if(i+3< s.length() && s.substring(i,i+3).equals("<b>"))
29 {
30 standout(); i+=2; continue;
31 }
32 else if(i+4< s.length() && s.substring(i,i+4).equals("</b>"))
33 {
34 standend(); i+=3; continue;
35 }
36 setCharAt(i+x,y,s.charAt(i));
37 }
38 }
39
40 public static void main(String[] args)
41 {
42 //load the C library
43 System.loadLibrary("NCurses");
44 //init curses
45 NCurses.install();
46
47 NCurses sample = new NCurses();
48
49 //draw a box
50 for(int i=1;i+1< sample.getRowCount();++i)
51 {
52 sample.setCharAt(1,i,'*');
53 sample.setCharAt(sample.getColumnCount()-2,i,'*');
54 }
55 for(int i=1;i+1< sample.getColumnCount();++i)
56 {
57 sample.setCharAt(i,1,'*');
58 sample.setCharAt(i,sample.getRowCount()-2,'*');
59 }
60 /* draw some strings */
61 int n=0;
62 for(int i=2;i+3< sample.getRowCount();i+=3)
63 {
64 sample.drawString("<b>Menu \t"+(++n)+"</b>: Hello Menu",5,i);
65 }
66 /* update the screen */
67 sample.refresh();
68 /* wait 10 sec */
69 try{ Thread.sleep(10000); } catch(Exception err) {}
70 //dispose ncurses
71 NCurses.uninstall();
72 }
73 }


This class contains some native methods that are not implemented in this class but they will be loading (line 43 by calling System.loadLibrary)

We can compile this class:
javac NCurses.java


We can run JAVAH on this class. javah will generate the C header file that are needed to implement our native methods.

javah NCurses


This generates the following file: NCurses.h


1 /* DO NOT EDIT THIS FILE - it is machine generated */
2 #include <jni.h>
3 /* Header for class NCurses */
4
5 #ifndef _Included_NCurses
6 #define _Included_NCurses
7 #ifdef __cplusplus
8 extern "C" {
9 #endif
10 /*
11 * Class: NCurses
12 * Method: install
13 * Signature: ()I
14 */
15 JNIEXPORT jint JNICALL Java_NCurses_install
16 (JNIEnv *, jclass);
17
18 /*
19 * Class: NCurses
20 * Method: uninstall
21 * Signature: ()I
22 */
23 JNIEXPORT jint JNICALL Java_NCurses_uninstall
24 (JNIEnv *, jclass);
25
26 /*
27 * Class: NCurses
28 * Method: setCharAt
29 * Signature: (III)V
30 */
31 JNIEXPORT void JNICALL Java_NCurses_setCharAt
32 (JNIEnv *, jclass, jint, jint, jint);
33
34 /*
35 * Class: NCurses
36 * Method: refresh
37 * Signature: ()V
38 */
39 JNIEXPORT void JNICALL Java_NCurses_refresh
40 (JNIEnv *, jclass);
41
42 /*
43 * Class: NCurses
44 * Method: getRowCount
45 * Signature: ()I
46 */
47 JNIEXPORT jint JNICALL Java_NCurses_getRowCount
48 (JNIEnv *, jobject);
49
50 /*
51 * Class: NCurses
52 * Method: getColumnCount
53 * Signature: ()I
54 */
55 JNIEXPORT jint JNICALL Java_NCurses_getColumnCount
56 (JNIEnv *, jobject);
57
58 /*
59 * Class: NCurses
60 * Method: standout
61 * Signature: ()I
62 */
63 JNIEXPORT jint JNICALL Java_NCurses_standout
64 (JNIEnv *, jobject);
65
66 /*
67 * Class: NCurses
68 * Method: standend
69 * Signature: ()I
70 */
71 JNIEXPORT jint JNICALL Java_NCurses_standend
72 (JNIEnv *, jobject);
73
74 #ifdef __cplusplus
75 }
76 #endif
77 #endif


I've implemented the C methods in the following file: NCurses.c

1 #include "NCurses.h"
2 #include <string.h>
3 #include <curses.h>
4 #include <signal.h>
5
6 JNIEXPORT jint JNICALL Java_NCurses_install(JNIEnv *env, jclass clazz)
7 {
8 //(void) signal(SIGINT, finish); /* arrange interrupts to terminate */
9
10 (void) initscr(); /* initialize the curses library */
11 keypad(stdscr, TRUE); /* enable keyboard mapping */
12 (void) nonl(); /* tell curses not to do NL->CR/NL on output */
13 (void) cbreak(); /* take input chars one at a time, no wait for \n */
14 (void) noecho(); /* don't echo input */
15 clear();
16 move(0,0);
17 refresh();
18 return 0;
19 }
20
21 JNIEXPORT jint JNICALL Java_NCurses_uninstall(JNIEnv *env, jclass clazz)
22 {
23 endwin();
24 return 0;
25 }
26
27 JNIEXPORT jint JNICALL Java_NCurses_getRowCount(JNIEnv *env, jobject obj)
28 {
29 int h, w;
30 getmaxyx(stdscr, h, w);
31 return h;
32 }
33
34
35 JNIEXPORT jint JNICALL Java_NCurses_getColumnCount(JNIEnv *env, jobject obj)
36 {
37 int h, w;
38 getmaxyx(stdscr, h, w);
39 return w;
40 }
41
42 /*
43 * Class: NCurses
44 * Method: setCharAt
45 * Signature: (III)V
46 */
47 JNIEXPORT void JNICALL Java_NCurses_setCharAt
48 (JNIEnv *env, jclass object, jint x, jint y, jint chr)
49 {
50 mvaddch(y,x,chr);
51 }
52
53 /*
54 * Class: NCurses
55 * Method: refresh
56 * Signature: ()V
57 */
58 JNIEXPORT void JNICALL Java_NCurses_refresh
59 (JNIEnv *env, jclass object)
60 {
61 refresh();
62 }
63
64
65 /*
66 * Class: NCurses
67 * Method: standout
68 * Signature: ()I
69 */
70 JNIEXPORT jint JNICALL Java_NCurses_standout
71 (JNIEnv *env, jobject object)
72 {
73 standout();
74 }
75
76 /*
77 * Class: NCurses
78 * Method: standend
79 * Signature: ()I
80 */
81 JNIEXPORT jint JNICALL Java_NCurses_standend
82 (JNIEnv * env, jobject object)
83 {
84 standend();
85 }


before compiling the C source, I set the variable LD_LIBRARY_PATH. For my machine it was:
export LD_LIBRARY_PATH=${PWD}:/usr/local/lib:/usr/lib


We can now compile NCurses.c and create the C library. You may need to add the path the java C headers which are contained in ${JAVA_HOME}/include/ and ${JAVA_HOME}/include/{your-machine}

gcc -fpic -c NCurses.c -o NCurses.o
gcc -shared -o libNCurses.so NCurses.o -lcurses


Let's run our java program:

java NCurses


The result looks like this:

*********************************************
* Menu 1 : Hello Menu *
* *
* *
* Menu 2 : Hello Menu *
* *
* *
* Menu 3 : Hello Menu *
* *
* *
* Menu 4 : Hello Menu *
* *
* *
* Menu 5 : Hello Menu *
* *
* *
* Menu 6 : Hello Menu *
* *
* *
* *
*********************************************


That's it.
Pierre