From ec4aaa5b1add2733c74eaeb9bb881034e702a916 Mon Sep 17 00:00:00 2001
From: Blaise Li <blaise.li__git@nsup.org>
Date: Tue, 20 Apr 2021 11:42:07 +0200
Subject: [PATCH] Add tests of bed-shifting code.

---
 tests/data/bt1.bed             |  10 +++
 tests/data/shifted/m0/bt1.bed  |  10 +++
 tests/data/shifted/m1/bt1.bed  |  10 +++
 tests/data/shifted/m10/bt1.bed |  10 +++
 tests/data/shifted/m11/bt1.bed |  10 +++
 tests/data/shifted/m19/bt1.bed |  10 +++
 tests/data/shifted/m20/bt1.bed |  10 +++
 tests/data/shifted/m21/bt1.bed |  10 +++
 tests/data/shifted/m4/bt1.bed  |  10 +++
 tests/data/shifted/m5/bt1.bed  |  10 +++
 tests/data/shifted/m6/bt1.bed  |  10 +++
 tests/data/shifted/m9/bt1.bed  |  10 +++
 tests/data/shifted/p0/bt1.bed  |  10 +++
 tests/data/shifted/p1/bt1.bed  |  10 +++
 tests/data/shifted/p10/bt1.bed |  10 +++
 tests/data/shifted/p11/bt1.bed |  10 +++
 tests/data/shifted/p19/bt1.bed |  10 +++
 tests/data/shifted/p20/bt1.bed |  10 +++
 tests/data/shifted/p21/bt1.bed |  10 +++
 tests/data/shifted/p4/bt1.bed  |  10 +++
 tests/data/shifted/p5/bt1.bed  |  10 +++
 tests/data/shifted/p6/bt1.bed  |  10 +++
 tests/data/shifted/p9/bt1.bed  |  10 +++
 tests/test_bam25prime.py       | 126 +++++++++++++++++++++++++++++++++
 24 files changed, 356 insertions(+)
 create mode 100644 tests/data/bt1.bed
 create mode 100644 tests/data/shifted/m0/bt1.bed
 create mode 100644 tests/data/shifted/m1/bt1.bed
 create mode 100644 tests/data/shifted/m10/bt1.bed
 create mode 100644 tests/data/shifted/m11/bt1.bed
 create mode 100644 tests/data/shifted/m19/bt1.bed
 create mode 100644 tests/data/shifted/m20/bt1.bed
 create mode 100644 tests/data/shifted/m21/bt1.bed
 create mode 100644 tests/data/shifted/m4/bt1.bed
 create mode 100644 tests/data/shifted/m5/bt1.bed
 create mode 100644 tests/data/shifted/m6/bt1.bed
 create mode 100644 tests/data/shifted/m9/bt1.bed
 create mode 100644 tests/data/shifted/p0/bt1.bed
 create mode 100644 tests/data/shifted/p1/bt1.bed
 create mode 100644 tests/data/shifted/p10/bt1.bed
 create mode 100644 tests/data/shifted/p11/bt1.bed
 create mode 100644 tests/data/shifted/p19/bt1.bed
 create mode 100644 tests/data/shifted/p20/bt1.bed
 create mode 100644 tests/data/shifted/p21/bt1.bed
 create mode 100644 tests/data/shifted/p4/bt1.bed
 create mode 100644 tests/data/shifted/p5/bt1.bed
 create mode 100644 tests/data/shifted/p6/bt1.bed
 create mode 100644 tests/data/shifted/p9/bt1.bed
 create mode 100755 tests/test_bam25prime.py

diff --git a/tests/data/bt1.bed b/tests/data/bt1.bed
new file mode 100644
index 0000000..1ae9665
--- /dev/null
+++ b/tests/data/bt1.bed
@@ -0,0 +1,10 @@
+I	0	5	a(I:0-5:+)	.	+
+I	0	5	b(I:0-5:-)	.	-
+I	0	10	c(I:0-10:+)	.	+
+I	0	10	d(I:0-10:-)	.	-
+I	5	10	e(I:5-10:+)	.	+
+I	5	10	f(I:5-10:-)	.	-
+I	5	20	g(I:5-20:+)	.	+
+I	5	20	h(I:5-20:-)	.	-
+I	10	15	i(I:10-15:+)	.	+
+I	10	15	j(I:10-15:-)	.	-
diff --git a/tests/data/shifted/m0/bt1.bed b/tests/data/shifted/m0/bt1.bed
new file mode 100644
index 0000000..1ae9665
--- /dev/null
+++ b/tests/data/shifted/m0/bt1.bed
@@ -0,0 +1,10 @@
+I	0	5	a(I:0-5:+)	.	+
+I	0	5	b(I:0-5:-)	.	-
+I	0	10	c(I:0-10:+)	.	+
+I	0	10	d(I:0-10:-)	.	-
+I	5	10	e(I:5-10:+)	.	+
+I	5	10	f(I:5-10:-)	.	-
+I	5	20	g(I:5-20:+)	.	+
+I	5	20	h(I:5-20:-)	.	-
+I	10	15	i(I:10-15:+)	.	+
+I	10	15	j(I:10-15:-)	.	-
diff --git a/tests/data/shifted/m1/bt1.bed b/tests/data/shifted/m1/bt1.bed
new file mode 100644
index 0000000..9e73706
--- /dev/null
+++ b/tests/data/shifted/m1/bt1.bed
@@ -0,0 +1,10 @@
+#I	-1	4	a(I:0-5:+)	.	+
+I	1	6	b(I:0-5:-)	.	-
+#I	-1	9	c(I:0-10:+)	.	+
+I	1	11	d(I:0-10:-)	.	-
+I	4	9	e(I:5-10:+)	.	+
+I	6	11	f(I:5-10:-)	.	-
+I	4	19	g(I:5-20:+)	.	+
+I	6	21	h(I:5-20:-)	.	-
+I	9	14	i(I:10-15:+)	.	+
+I	11	16	j(I:10-15:-)	.	-
diff --git a/tests/data/shifted/m10/bt1.bed b/tests/data/shifted/m10/bt1.bed
new file mode 100644
index 0000000..30fc82f
--- /dev/null
+++ b/tests/data/shifted/m10/bt1.bed
@@ -0,0 +1,10 @@
+#I	-10	-5	a(I:0-5:+)	.	+
+I	10	15	b(I:0-5:-)	.	-
+#I	-10	0	c(I:0-10:+)	.	+
+I	10	20	d(I:0-10:-)	.	-
+#I	-5	0	e(I:5-10:+)	.	+
+I	15	20	f(I:5-10:-)	.	-
+#I	-5	10	g(I:5-20:+)	.	+
+I	15	30	h(I:5-20:-)	.	-
+I	0	5	i(I:10-15:+)	.	+
+I	20	25	j(I:10-15:-)	.	-
diff --git a/tests/data/shifted/m11/bt1.bed b/tests/data/shifted/m11/bt1.bed
new file mode 100644
index 0000000..6279924
--- /dev/null
+++ b/tests/data/shifted/m11/bt1.bed
@@ -0,0 +1,10 @@
+#I	-11	-6	a(I:0-5:+)	.	+
+I	11	16	b(I:0-5:-)	.	-
+#I	-11	-1	c(I:0-10:+)	.	+
+I	11	21	d(I:0-10:-)	.	-
+#I	-6	-1	e(I:5-10:+)	.	+
+I	16	21	f(I:5-10:-)	.	-
+#I	-6	9	g(I:5-20:+)	.	+
+I	16	31	h(I:5-20:-)	.	-
+#I	-1	4	i(I:10-15:+)	.	+
+I	21	26	j(I:10-15:-)	.	-
diff --git a/tests/data/shifted/m19/bt1.bed b/tests/data/shifted/m19/bt1.bed
new file mode 100644
index 0000000..ea3b922
--- /dev/null
+++ b/tests/data/shifted/m19/bt1.bed
@@ -0,0 +1,10 @@
+#I	-19	-14	a(I:0-5:+)	.	+
+I	19	24	b(I:0-5:-)	.	-
+#I	-19	-9	c(I:0-10:+)	.	+
+I	19	29	d(I:0-10:-)	.	-
+#I	-14	-9	e(I:5-10:+)	.	+
+I	24	29	f(I:5-10:-)	.	-
+#I	-14	1	g(I:5-20:+)	.	+
+I	24	39	h(I:5-20:-)	.	-
+#I	-9	-4	i(I:10-15:+)	.	+
+I	29	34	j(I:10-15:-)	.	-
diff --git a/tests/data/shifted/m20/bt1.bed b/tests/data/shifted/m20/bt1.bed
new file mode 100644
index 0000000..4ad9d02
--- /dev/null
+++ b/tests/data/shifted/m20/bt1.bed
@@ -0,0 +1,10 @@
+#I	-20	-15	a(I:0-5:+)	.	+
+I	20	25	b(I:0-5:-)	.	-
+#I	-20	-10	c(I:0-10:+)	.	+
+I	20	30	d(I:0-10:-)	.	-
+#I	-15	-10	e(I:5-10:+)	.	+
+I	25	30	f(I:5-10:-)	.	-
+#I	-15	0	g(I:5-20:+)	.	+
+I	25	40	h(I:5-20:-)	.	-
+#I	-10	-5	i(I:10-15:+)	.	+
+I	30	35	j(I:10-15:-)	.	-
diff --git a/tests/data/shifted/m21/bt1.bed b/tests/data/shifted/m21/bt1.bed
new file mode 100644
index 0000000..a0a6754
--- /dev/null
+++ b/tests/data/shifted/m21/bt1.bed
@@ -0,0 +1,10 @@
+#I	-21	-16	a(I:0-5:+)	.	+
+I	21	26	b(I:0-5:-)	.	-
+#I	-21	-11	c(I:0-10:+)	.	+
+I	21	31	d(I:0-10:-)	.	-
+#I	-16	-11	e(I:5-10:+)	.	+
+I	26	31	f(I:5-10:-)	.	-
+#I	-16	-1	g(I:5-20:+)	.	+
+I	26	41	h(I:5-20:-)	.	-
+#I	-11	-6	i(I:10-15:+)	.	+
+I	31	36	j(I:10-15:-)	.	-
diff --git a/tests/data/shifted/m4/bt1.bed b/tests/data/shifted/m4/bt1.bed
new file mode 100644
index 0000000..d96672e
--- /dev/null
+++ b/tests/data/shifted/m4/bt1.bed
@@ -0,0 +1,10 @@
+#I	-4	1	a(I:0-5:+)	.	+
+I	4	9	b(I:0-5:-)	.	-
+#I	-4	6	c(I:0-10:+)	.	+
+I	4	14	d(I:0-10:-)	.	-
+I	1	6	e(I:5-10:+)	.	+
+I	9	14	f(I:5-10:-)	.	-
+I	1	16	g(I:5-20:+)	.	+
+I	9	24	h(I:5-20:-)	.	-
+I	6	11	i(I:10-15:+)	.	+
+I	14	19	j(I:10-15:-)	.	-
diff --git a/tests/data/shifted/m5/bt1.bed b/tests/data/shifted/m5/bt1.bed
new file mode 100644
index 0000000..b7c4094
--- /dev/null
+++ b/tests/data/shifted/m5/bt1.bed
@@ -0,0 +1,10 @@
+#I	-5	0	a(I:0-5:+)	.	+
+I	5	10	b(I:0-5:-)	.	-
+#I	-5	5	c(I:0-10:+)	.	+
+I	5	15	d(I:0-10:-)	.	-
+I	0	5	e(I:5-10:+)	.	+
+I	10	15	f(I:5-10:-)	.	-
+I	0	15	g(I:5-20:+)	.	+
+I	10	25	h(I:5-20:-)	.	-
+I	5	10	i(I:10-15:+)	.	+
+I	15	20	j(I:10-15:-)	.	-
diff --git a/tests/data/shifted/m6/bt1.bed b/tests/data/shifted/m6/bt1.bed
new file mode 100644
index 0000000..da19eec
--- /dev/null
+++ b/tests/data/shifted/m6/bt1.bed
@@ -0,0 +1,10 @@
+#I	-6	-1	a(I:0-5:+)	.	+
+I	6	11	b(I:0-5:-)	.	-
+#I	-6	4	c(I:0-10:+)	.	+
+I	6	16	d(I:0-10:-)	.	-
+#I	-1	4	e(I:5-10:+)	.	+
+I	11	16	f(I:5-10:-)	.	-
+#I	-1	14	g(I:5-20:+)	.	+
+I	11	26	h(I:5-20:-)	.	-
+I	4	9	i(I:10-15:+)	.	+
+I	16	21	j(I:10-15:-)	.	-
diff --git a/tests/data/shifted/m9/bt1.bed b/tests/data/shifted/m9/bt1.bed
new file mode 100644
index 0000000..9d7fecb
--- /dev/null
+++ b/tests/data/shifted/m9/bt1.bed
@@ -0,0 +1,10 @@
+#I	-9	-4	a(I:0-5:+)	.	+
+I	9	14	b(I:0-5:-)	.	-
+#I	-9	1	c(I:0-10:+)	.	+
+I	9	19	d(I:0-10:-)	.	-
+#I	-4	1	e(I:5-10:+)	.	+
+I	14	19	f(I:5-10:-)	.	-
+#I	-4	11	g(I:5-20:+)	.	+
+I	14	29	h(I:5-20:-)	.	-
+I	1	6	i(I:10-15:+)	.	+
+I	19	24	j(I:10-15:-)	.	-
diff --git a/tests/data/shifted/p0/bt1.bed b/tests/data/shifted/p0/bt1.bed
new file mode 100644
index 0000000..1ae9665
--- /dev/null
+++ b/tests/data/shifted/p0/bt1.bed
@@ -0,0 +1,10 @@
+I	0	5	a(I:0-5:+)	.	+
+I	0	5	b(I:0-5:-)	.	-
+I	0	10	c(I:0-10:+)	.	+
+I	0	10	d(I:0-10:-)	.	-
+I	5	10	e(I:5-10:+)	.	+
+I	5	10	f(I:5-10:-)	.	-
+I	5	20	g(I:5-20:+)	.	+
+I	5	20	h(I:5-20:-)	.	-
+I	10	15	i(I:10-15:+)	.	+
+I	10	15	j(I:10-15:-)	.	-
diff --git a/tests/data/shifted/p1/bt1.bed b/tests/data/shifted/p1/bt1.bed
new file mode 100644
index 0000000..4371a2c
--- /dev/null
+++ b/tests/data/shifted/p1/bt1.bed
@@ -0,0 +1,10 @@
+I	1	6	a(I:0-5:+)	.	+
+#I	-1	4	b(I:0-5:-)	.	-
+I	1	11	c(I:0-10:+)	.	+
+#I	-1	9	d(I:0-10:-)	.	-
+I	6	11	e(I:5-10:+)	.	+
+I	4	9	f(I:5-10:-)	.	-
+I	6	21	g(I:5-20:+)	.	+
+I	4	19	h(I:5-20:-)	.	-
+I	11	16	i(I:10-15:+)	.	+
+I	9	14	j(I:10-15:-)	.	-
diff --git a/tests/data/shifted/p10/bt1.bed b/tests/data/shifted/p10/bt1.bed
new file mode 100644
index 0000000..5e85143
--- /dev/null
+++ b/tests/data/shifted/p10/bt1.bed
@@ -0,0 +1,10 @@
+I	10	15	a(I:0-5:+)	.	+
+#I	-10	-5	b(I:0-5:-)	.	-
+I	10	20	c(I:0-10:+)	.	+
+#I	-10	0	d(I:0-10:-)	.	-
+I	15	20	e(I:5-10:+)	.	+
+#I	-5	0	f(I:5-10:-)	.	-
+I	15	30	g(I:5-20:+)	.	+
+#I	-5	10	h(I:5-20:-)	.	-
+I	20	25	i(I:10-15:+)	.	+
+I	0	5	j(I:10-15:-)	.	-
diff --git a/tests/data/shifted/p11/bt1.bed b/tests/data/shifted/p11/bt1.bed
new file mode 100644
index 0000000..761e685
--- /dev/null
+++ b/tests/data/shifted/p11/bt1.bed
@@ -0,0 +1,10 @@
+I	11	16	a(I:0-5:+)	.	+
+#I	-11	-6	b(I:0-5:-)	.	-
+I	11	21	c(I:0-10:+)	.	+
+#I	-11	-1	d(I:0-10:-)	.	-
+I	16	21	e(I:5-10:+)	.	+
+#I	-6	1	f(I:5-10:-)	.	-
+I	16	31	g(I:5-20:+)	.	+
+#I	-6	9	h(I:5-20:-)	.	-
+I	21	26	i(I:10-15:+)	.	+
+#I	-1	4	j(I:10-15:-)	.	-
diff --git a/tests/data/shifted/p19/bt1.bed b/tests/data/shifted/p19/bt1.bed
new file mode 100644
index 0000000..d80bd8b
--- /dev/null
+++ b/tests/data/shifted/p19/bt1.bed
@@ -0,0 +1,10 @@
+I	19	24	a(I:0-5:+)	.	+
+#I	-19	-14	b(I:0-5:-)	.	-
+I	19	29	c(I:0-10:+)	.	+
+#I	-19	-9	d(I:0-10:-)	.	-
+I	24	29	e(I:5-10:+)	.	+
+#I	-14	-9	f(I:5-10:-)	.	-
+I	24	39	g(I:5-20:+)	.	+
+#I	-14	1	h(I:5-20:-)	.	-
+I	29	34	i(I:10-15:+)	.	+
+#I	-9	-4	j(I:10-15:-)	.	-
diff --git a/tests/data/shifted/p20/bt1.bed b/tests/data/shifted/p20/bt1.bed
new file mode 100644
index 0000000..d72aaae
--- /dev/null
+++ b/tests/data/shifted/p20/bt1.bed
@@ -0,0 +1,10 @@
+I	20	25	a(I:0-5:+)	.	+
+#I	-20	-15	b(I:0-5:-)	.	-
+I	20	30	c(I:0-10:+)	.	+
+#I	-20	-10	d(I:0-10:-)	.	-
+I	25	30	e(I:5-10:+)	.	+
+#I	-15	-10	f(I:5-10:-)	.	-
+I	25	40	g(I:5-20:+)	.	+
+#I	-15	0	h(I:5-20:-)	.	-
+I	30	35	i(I:10-15:+)	.	+
+#I	-10	-5	j(I:10-15:-)	.	-
diff --git a/tests/data/shifted/p21/bt1.bed b/tests/data/shifted/p21/bt1.bed
new file mode 100644
index 0000000..6cafac3
--- /dev/null
+++ b/tests/data/shifted/p21/bt1.bed
@@ -0,0 +1,10 @@
+I	21	26	a(I:0-5:+)	.	+
+#I	-21	-16	b(I:0-5:-)	.	-
+I	21	31	c(I:0-10:+)	.	+
+#I	-21	-11	d(I:0-10:-)	.	-
+I	26	31	e(I:5-10:+)	.	+
+#I	-16	-11	f(I:5-10:-)	.	-
+I	26	41	g(I:5-20:+)	.	+
+#I	-16	-1	h(I:5-20:-)	.	-
+I	31	36	i(I:10-15:+)	.	+
+#I	-11	-6	j(I:10-15:-)	.	-
diff --git a/tests/data/shifted/p4/bt1.bed b/tests/data/shifted/p4/bt1.bed
new file mode 100644
index 0000000..6c26b23
--- /dev/null
+++ b/tests/data/shifted/p4/bt1.bed
@@ -0,0 +1,10 @@
+I	4	9	a(I:0-5:+)	.	+
+#I	-4	1	b(I:0-5:-)	.	-
+I	4	14	c(I:0-10:+)	.	+
+#I	-4	6	d(I:0-10:-)	.	-
+I	9	14	e(I:5-10:+)	.	+
+I	1	6	f(I:5-10:-)	.	-
+I	9	24	g(I:5-20:+)	.	+
+I	1	16	h(I:5-20:-)	.	-
+I	14	19	i(I:10-15:+)	.	+
+I	6	11	j(I:10-15:-)	.	-
diff --git a/tests/data/shifted/p5/bt1.bed b/tests/data/shifted/p5/bt1.bed
new file mode 100644
index 0000000..db85793
--- /dev/null
+++ b/tests/data/shifted/p5/bt1.bed
@@ -0,0 +1,10 @@
+I	5	10	a(I:0-5:+)	.	+
+#I	-5	0	b(I:0-5:-)	.	-
+I	5	15	c(I:0-10:+)	.	+
+#I	-5	5	d(I:0-10:-)	.	-
+I	10	15	e(I:5-10:+)	.	+
+I	0	5	f(I:5-10:-)	.	-
+I	10	25	g(I:5-20:+)	.	+
+I	0	15	h(I:5-20:-)	.	-
+I	15	20	i(I:10-15:+)	.	+
+I	5	10	j(I:10-15:-)	.	-
diff --git a/tests/data/shifted/p6/bt1.bed b/tests/data/shifted/p6/bt1.bed
new file mode 100644
index 0000000..fce8c22
--- /dev/null
+++ b/tests/data/shifted/p6/bt1.bed
@@ -0,0 +1,10 @@
+I	6	11	a(I:0-5:+)	.	+
+#I	-6	-1	b(I:0-5:-)	.	-
+I	6	16	c(I:0-10:+)	.	+
+#I	-6	4	d(I:0-10:-)	.	-
+I	11	16	e(I:5-10:+)	.	+
+#I	-1	4	f(I:5-10:-)	.	-
+I	11	26	g(I:5-20:+)	.	+
+#I	-1	14	h(I:5-20:-)	.	-
+I	16	21	i(I:10-15:+)	.	+
+I	4	9	j(I:10-15:-)	.	-
diff --git a/tests/data/shifted/p9/bt1.bed b/tests/data/shifted/p9/bt1.bed
new file mode 100644
index 0000000..26dc925
--- /dev/null
+++ b/tests/data/shifted/p9/bt1.bed
@@ -0,0 +1,10 @@
+I	9	14	a(I:0-5:+)	.	+
+#I	-9	-4	b(I:0-5:-)	.	-
+I	9	19	c(I:0-10:+)	.	+
+#I	-9	1	d(I:0-10:-)	.	-
+I	14	19	e(I:5-10:+)	.	+
+#I	-4	1	f(I:5-10:-)	.	-
+I	14	29	g(I:5-20:+)	.	+
+#I	-4	11	h(I:5-20:-)	.	-
+I	19	24	i(I:10-15:+)	.	+
+I	1	6	j(I:10-15:-)	.	-
diff --git a/tests/test_bam25prime.py b/tests/test_bam25prime.py
new file mode 100755
index 0000000..e2c76b3
--- /dev/null
+++ b/tests/test_bam25prime.py
@@ -0,0 +1,126 @@
+#!/usr/bin/env python3
+"""
+Test cases for bam25prime.
+"""
+
+import unittest
+from collections import namedtuple
+from pathlib import Path
+from bam25prime import (
+    BedTool, make_bed_shifter, make_bed_shift_checker)
+
+
+Interval = namedtuple("Interval", ["chrom", "start", "stop", "strand"])
+
+THIS_DIR = Path("__file__").resolve().parent
+data_dir = THIS_DIR.joinpath("data")
+
+
+def load_interval_dict(bed_path):
+    """
+    Build a dict to store intervals allowing easy comparison between
+    obtained and expected results using bed names (4th column) as keys.
+    """
+    itvl_dict = {}
+    with open(bed_path) as fh:
+        for line in fh:
+            if len(line.strip()) == 0 or line[0] == "#":
+                continue
+            (
+                chrom, start, stop,
+                name, _, strand, *_) = line.strip().split("\t")
+            assert name not in itvl_dict, f"Non unique name: {name}"
+            itvl_dict[name] = Interval(
+                chrom, int(start), int(stop), strand)
+    return itvl_dict
+
+
+def compare_itvl_dicts(observed, expected):
+    """
+    Compute the sets of interval names:
+    * missing in the observed
+    * spurious in the observed
+    * different in the observed
+    Return a (missing, spurious, different) tuple.
+    """
+    obs_names = set(observed.keys())
+    exp_names = set(expected.keys())
+    missing = exp_names - obs_names
+    spurious = obs_names - exp_names
+    common = obs_names & exp_names
+    different = set()
+    for itvl_name in common:
+        if observed[itvl_name] != expected[itvl_name]:
+            different.add(itvl_name)
+    return (missing, spurious, different)
+
+
+def check_shifter(bed_path, s_name, shifter, checker):
+    bt = BedTool(bed_path)
+    bed_name = bed_path.stem
+    msg_base = f"{bed_name} transformed with {s_name}"
+    print(msg_base)
+    expected = load_interval_dict(
+        data_dir.joinpath("shifted", s_name, f"{bed_name}.bed"))
+    #print("bt")
+    #print(bt)
+    #print(bt)
+    #shifted_1 = bt.each(shifter).saveas()
+    #print("  shifted")
+    #print(shifted_1)
+    #print(shifted_1)
+    #shifted_2 = shifted_1.remove_invalid().saveas()
+    shifted_2 = bt.filter(checker).each(shifter).remove_invalid().saveas()
+    #print(" invalid removed")
+    #print(shifted_2)
+    #print(shifted_2)
+    shifted = shifted_2.sort()
+    #print("  sorted")
+    #print(shifted)
+    #print(shifted)
+    observed = load_interval_dict(shifted.fn)
+    #print(observed)
+    (missing, spurious, different) = compare_itvl_dicts(
+        observed, expected)
+    msg = "\n".join([
+        msg_base,
+        f"\tMissing: {missing}",
+        f"\tSpurious: {spurious}",
+        f"\tDifferent: {different}"])
+    return (missing, spurious, different, msg)
+
+
+class TestBam25prime(unittest.TestCase):
+    def test_shift_pos(self):
+        shifters = {
+            f"p{shift}": (
+                make_bed_shifter(shift),
+                make_bed_shift_checker(shift))
+            for shift in [0, 1, 4, 5, 6, 9, 10, 11, 19, 20, 21]
+        }
+        for bed_path in data_dir.glob("*.bed"):
+            for (s_name, (shifter, checker)) in shifters.items():
+                (missing, spurious, different, msg) = check_shifter(
+                    bed_path, s_name, shifter, checker)
+                self.assertFalse(
+                    missing | spurious | different,
+                    msg)
+
+    def test_shift_neg(self):
+        shifters = {
+            f"m{shift}": (
+                make_bed_shifter(-shift),
+                make_bed_shift_checker(-shift))
+            for shift in [0, 1, 4, 5, 6, 9, 10, 11, 19, 20, 21]
+        }
+        for bed_path in data_dir.glob("*.bed"):
+            for (s_name, (shifter, checker)) in shifters.items():
+                (missing, spurious, different, msg) = check_shifter(
+                    bed_path, s_name, shifter, checker)
+                self.assertFalse(
+                    missing | spurious | different,
+                    msg)
+
+
+if __name__ == "__main__":
+    unittest.main()
-- 
GitLab