Skip to content

Commit fc1bec7

Browse files
committed
R interface to TwoBit code
1 parent 958ada6 commit fc1bec7

File tree

5 files changed

+151
-3
lines changed

5 files changed

+151
-3
lines changed

Diff for: Makefile

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1-
all: twoBitFreq test
1+
all: twoBitFreq test twobit.so
22

33
twoBitFreq: main_freq.c twobit.c twobit.h
44
gcc -o twoBitFreq -Wall -g main_freq.c twobit.c
55

66
test: main.c twobit.c twobit.h
77
gcc -o test -Wall -g main.c twobit.c
8+
9+
twobit.so: twobit_R.c twobit.h twobit.c
10+
R CMD SHLIB twobit.c twobit_R.c

Diff for: twobit.R

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
#
2+
# R twoBit Interface
3+
#
4+
5+
twobit.curPath = getwd()
6+
7+
# look for twobit.so
8+
if (file.access(paste(twobit.curPath, "/twobit.so", sep='')) < 0) {
9+
# try hack
10+
twobit.curPath = dirname(sys.frame(1)$ofile)
11+
# test to see if it worked
12+
stopifnot(file.access(paste(twobit.curPath, "/twobit.so", sep='')) >= 0)
13+
}
14+
15+
twobit.load <- function(filename) {
16+
dyn.load(paste(twobit.curPath, "/twobit.so", sep=''))
17+
out <- .Call("rtwobit_load", filename)
18+
return(out)
19+
}
20+
21+
twobit.unload <- function(twobit) {
22+
stopifnot(!is.null(twobit))
23+
.Call("rtwobit_unload", twobit)
24+
invisible(NULL)
25+
}
26+
27+
twobit.sequence <- function(twobit, name, start, end) {
28+
stopifnot(!is.null(twobit), !is.null(name), !is.null(start), !is.null(end))
29+
stopifnot(end >= start)
30+
out <- .Call("rtwobit_sequence", twobit, name, start, end)
31+
return(out)
32+
}

Diff for: twobit.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ void free_index(struct twobit_index * index) {
141141
}
142142
}
143143

144-
TwoBit * twobit_open(char * filename) {
144+
TwoBit * twobit_open(const char * filename) {
145145
int fd;
146146
struct stat sb;
147147
char * data;

Diff for: twobit.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
typedef struct twobit_ TwoBit;
55

6-
TwoBit * twobit_open(char * filename);
6+
TwoBit * twobit_open(const char * filename);
77
void twobit_close(TwoBit * ptr);
88

99
int twobit_sequence_size(TwoBit * ptr, const char * name);

Diff for: twobit_R.c

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
/* R interface for wiglib */
2+
#include "twobit.h"
3+
#include <R.h>
4+
#include <Rdefines.h>
5+
6+
static void rtwobit_finalizer(SEXP ptr) {
7+
if (!R_ExternalPtrAddr(ptr)) return;
8+
twobit_close(R_ExternalPtrAddr(ptr));
9+
R_ClearExternalPtr(ptr); /* not really necessary */
10+
}
11+
12+
static SEXP rtwobit_names(TwoBit * twobit) {
13+
char ** names = twobit_sequence_names(twobit);
14+
SEXP result;
15+
int count = 0, i;
16+
char ** ptr;
17+
18+
for (ptr = names; *ptr != NULL; ++ptr)
19+
++count;
20+
21+
PROTECT(result = allocVector(STRSXP, count));
22+
23+
for (ptr = names, i = 0; *ptr != NULL; ++ptr, ++i) {
24+
SET_STRING_ELT(result, i, mkChar(*ptr));
25+
free(*ptr);
26+
}
27+
free(names);
28+
29+
UNPROTECT(1);
30+
31+
return result;
32+
}
33+
34+
/* Load / Unload */
35+
SEXP rtwobit_load(SEXP filename) {
36+
SEXP ans, ans_names, ptr;
37+
TwoBit * twobit;
38+
39+
40+
/* load twobit file */
41+
PROTECT(filename = AS_CHARACTER(filename));
42+
43+
twobit = twobit_open(CHAR(STRING_ELT(filename, 0)));
44+
45+
/* create answer */
46+
if (twobit == NULL) {
47+
UNPROTECT(1);
48+
return R_NilValue;
49+
}
50+
51+
PROTECT(ans = allocVector(VECSXP, 1)); /* names */
52+
PROTECT(ans_names = allocVector(STRSXP, 1));
53+
54+
/* make external pointer */
55+
ptr = R_MakeExternalPtr(twobit, install("TWOBIT_struct"), R_NilValue);
56+
PROTECT(ptr);
57+
R_RegisterCFinalizerEx(ptr, rtwobit_finalizer, TRUE);
58+
setAttrib(ans, install("handle_ptr"), ptr);
59+
60+
/* fill info */
61+
SET_VECTOR_ELT(ans, 0, rtwobit_names(twobit));
62+
SET_STRING_ELT(ans_names, 0, mkChar("names"));
63+
64+
setAttrib(ans, R_NamesSymbol, ans_names);
65+
UNPROTECT(4);
66+
67+
return ans;
68+
}
69+
70+
void rtwobit_unload(SEXP obj) {
71+
SEXP ptr;
72+
73+
PROTECT(ptr = GET_ATTR(obj, install("handle_ptr")));
74+
if (ptr == R_NilValue)
75+
error("invalid twobit object");
76+
77+
rtwobit_finalizer(ptr);
78+
79+
UNPROTECT(1);
80+
}
81+
82+
SEXP rtwobit_sequence(SEXP obj, SEXP name, SEXP start, SEXP end) {
83+
SEXP ptr, res = R_NilValue;
84+
TwoBit * twobit;
85+
86+
PROTECT(name = AS_CHARACTER(name));
87+
PROTECT(start = AS_INTEGER(start));
88+
PROTECT(end = AS_INTEGER(end));
89+
90+
PROTECT(ptr = GET_ATTR(obj, install("handle_ptr")));
91+
if (ptr == R_NilValue)
92+
error("invalid twobit object");
93+
94+
twobit = R_ExternalPtrAddr(ptr);
95+
if (twobit == NULL) {
96+
error("twobit object has been unloaded");
97+
} else {
98+
char * seq = twobit_sequence(twobit, CHAR(STRING_ELT(name, 0)),
99+
INTEGER(start)[0], INTEGER(end)[0]);
100+
if (seq == NULL)
101+
error("unknown sequence or invalid range");
102+
else {
103+
PROTECT(res = allocVector(STRSXP, 1));
104+
SET_STRING_ELT(res, 0, mkChar(seq));
105+
free(seq);
106+
UNPROTECT(1);
107+
}
108+
}
109+
110+
UNPROTECT(4);
111+
112+
return res;
113+
}

0 commit comments

Comments
 (0)