diff --git a/src/main/java/io/github/jervenbolleman/handlegraph4j/gfa1/GFA1Reader.java b/src/main/java/io/github/jervenbolleman/handlegraph4j/gfa1/GFA1Reader.java index d445634..55228df 100644 --- a/src/main/java/io/github/jervenbolleman/handlegraph4j/gfa1/GFA1Reader.java +++ b/src/main/java/io/github/jervenbolleman/handlegraph4j/gfa1/GFA1Reader.java @@ -96,8 +96,4 @@ public Line next() { next = null; } } - - public void parseNext() { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. - } } diff --git a/src/main/java/io/github/jervenbolleman/handlegraph4j/gfa1/GFA1Writer.java b/src/main/java/io/github/jervenbolleman/handlegraph4j/gfa1/GFA1Writer.java new file mode 100644 index 0000000..6501016 --- /dev/null +++ b/src/main/java/io/github/jervenbolleman/handlegraph4j/gfa1/GFA1Writer.java @@ -0,0 +1,103 @@ +/* + * The MIT License + * + * Copyright 2020 Jerven Bolleman . + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package io.github.jervenbolleman.handlegraph4j.gfa1; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.charset.StandardCharsets; + +import io.github.jervenbolleman.handlegraph4j.EdgeHandle; +import io.github.jervenbolleman.handlegraph4j.HandleGraph; +import io.github.jervenbolleman.handlegraph4j.NodeHandle; +import io.github.jervenbolleman.handlegraph4j.iterators.AutoClosedIterator; +import io.github.jervenbolleman.handlegraph4j.sequences.Sequence; + +public class GFA1Writer { + + public static void write(OutputStream io, HandleGraph> hg) throws IOException { + writeHeader(io); + writeSegments(io, hg); + writePaths(io, hg); + writeEdges(io, hg); + } + + private static void writeEdges(OutputStream io, HandleGraph> hg) + throws IOException { + try (AutoClosedIterator> edges = hg.edges()) { + while (edges.hasNext()) { + io.write('L'); + io.write('\t'); + EdgeHandle edge = edges.next(); + final NodeHandle left = edge.left(); + writeEdgeNode(io, hg, left); + io.write('\t'); + writeEdgeNode(io, hg, edge.right()); + io.write('\n'); + } + } + + } + + public static void writeEdgeNode(OutputStream io, HandleGraph> hg, + final NodeHandle left) throws IOException { + writeNodeId(io, hg, left); + io.write('\t'); + if (hg.isReverseNodeHandle(left)) { + io.write('-'); + } else { + io.write('+'); + } + } + + private static void writePaths(OutputStream io, HandleGraph hg) { + // TODO Auto-generated method stub + + } + + private static void writeSegments(OutputStream io, HandleGraph hg) throws IOException { + try (AutoClosedIterator nodes = hg.nodes()) { + while (nodes.hasNext()) { + io.write('S'); + io.write('\t'); + NodeHandle node = nodes.next(); + writeNodeId(io, hg, node); + io.write('\t'); + Sequence seq = hg.sequenceOf(node); + io.write(seq.asAsciiBytes()); + io.write('\n'); + } + } + + } + + public static void writeNodeId(OutputStream io, HandleGraph hg, NodeHandle node) throws IOException { + final long nId = hg.asLong(node); + io.write(Long.toString(nId).getBytes(StandardCharsets.US_ASCII)); + } + + private static void writeHeader(OutputStream io) throws IOException { + io.write(new byte[] { 'H', '\t', 'V', 'N', ':', 'Z', ':', '1', '.', '0', '\n' }); + } + +} diff --git a/src/test/java/io/github/jervenbolleman/handlegraph4j/gfa1/GFA1ReaderTest.java b/src/test/java/io/github/jervenbolleman/handlegraph4j/gfa1/GFA1ReaderTest.java index f4a8ef5..1618ba2 100644 --- a/src/test/java/io/github/jervenbolleman/handlegraph4j/gfa1/GFA1ReaderTest.java +++ b/src/test/java/io/github/jervenbolleman/handlegraph4j/gfa1/GFA1ReaderTest.java @@ -41,43 +41,44 @@ public class GFA1ReaderTest { public GFA1ReaderTest() { } - private static final String TEST_DATA = "H\tVN:Z:1.0\n" - + "S\t1\tCAAATAAG\n" - + "S\t2\tA\n" - + "S\t3\tG\n" - + "S\t4\tT\n" - + "S\t5\tC\n" - + "S\t6\tTTG\n" - + "S\t7\tA\n" - + "S\t8\tG\n" - + "S\t9\tAAATTTTCTGGAGTTCTAT\n" - + "S\t10\tA\n" - + "S\t11\tT\n" - + "S\t12\tATAT\n" - + "S\t13\tA\n" - + "S\t14\tT\n" - + "S\t15\tCCAACTCTCTG\n" - + "P\tx\t1+,3+,5+,6+,8+,9+,11+,12+,14+,15+\t8M,1M,1M,3M,1M,19M,1M,4M,1M,11M\n" - + "L\t1\t+\t2\t+\t0M\n" - + "L\t1\t+\t3\t+\t0M\n" - + "L\t2\t+\t4\t+\t0M\n" - + "L\t2\t+\t5\t+\t0M\n" - + "L\t3\t+\t4\t+\t0M\n" - + "L\t3\t+\t5\t+\t0M\n" - + "L\t4\t+\t6\t+\t0M\n" - + "L\t5\t+\t6\t+\t0M\n" - + "L\t6\t+\t7\t+\t0M\n" - + "L\t6\t+\t8\t+\t0M\n" - + "L\t7\t+\t9\t+\t0M\n" - + "L\t8\t+\t9\t+\t0M\n" - + "L\t9\t+\t10\t+\t0M\n" - + "L\t9\t+\t11\t+\t0M\n" - + "L\t10\t+\t12\t+\t0M\n" - + "L\t11\t+\t12\t+\t0M\n" - + "L\t12\t+\t13\t+\t0M\n" - + "L\t12\t+\t14\t+\t0M\n" - + "L\t13\t+\t15\t+\t0M\n" - + "L\t14\t+\t15\t+\t0M"; + private static final String TEST_DATA = """ + H\tVN:Z:1.0 + S\t1\tCAAATAAG + S\t2\tA + S\t3\tG + S\t4\tT + S\t5\tC + S\t6\tTTG + S\t7\tA + S\t8\tG + S\t9\tAAATTTTCTGGAGTTCTAT + S\t10\tA + S\t11\tT + S\t12\tATAT + S\t13\tA + S\t14\tT + S\t15\tCCAACTCTCTG + P\tx\t1+,3+,5+,6+,8+,9+,11+,12+,14+,15+\t8M,1M,1M,3M,1M,19M,1M,4M,1M,11M + L\t1\t+\t2\t+\t0M + L\t1\t+\t3\t+\t0M + L\t2\t+\t4\t+\t0M + L\t2\t+\t5\t+\t0M + L\t3\t+\t4\t+\t0M + L\t3\t+\t5\t+\t0M + L\t4\t+\t6\t+\t0M + L\t5\t+\t6\t+\t0M + L\t6\t+\t7\t+\t0M + L\t6\t+\t8\t+\t0M + L\t7\t+\t9\t+\t0M + L\t8\t+\t9\t+\t0M + L\t9\t+\t10\t+\t0M + L\t9\t+\t11\t+\t0M + L\t10\t+\t12\t+\t0M + L\t11\t+\t12\t+\t0M + L\t12\t+\t13\t+\t0M + L\t12\t+\t14\t+\t0M + L\t13\t+\t15\t+\t0M + L\t14\t+\t15\t+\t0M"""; @Test public void testByCountingLineTypes() { diff --git a/src/test/java/io/github/jervenbolleman/handlegraph4j/gfa1/GFA1WriterTest.java b/src/test/java/io/github/jervenbolleman/handlegraph4j/gfa1/GFA1WriterTest.java new file mode 100644 index 0000000..25c6e7a --- /dev/null +++ b/src/test/java/io/github/jervenbolleman/handlegraph4j/gfa1/GFA1WriterTest.java @@ -0,0 +1,105 @@ +/* + * The MIT License + * + * Copyright 2020 Jerven Bolleman . + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +package io.github.jervenbolleman.handlegraph4j.gfa1; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.util.Arrays; + +import org.junit.jupiter.api.Test; + +import io.github.jervenbolleman.handlegraph4j.gfa1.line.Line; + +/** + * + * @author Jerven Bolleman + */ +public class GFA1WriterTest { + private static final String TEST_DATA = """ + H\tVN:Z:1.0 + S\t1\tCAAATAAG + S\t2\tA + S\t3\tG + S\t4\tT + S\t5\tC + S\t6\tTTG + S\t7\tA + S\t8\tG + S\t9\tAAATTTTCTGGAGTTCTAT + S\t10\tA + S\t11\tT + S\t12\tATAT + S\t13\tA + S\t14\tT + S\t15\tCCAACTCTCTG + P\tx\t1+,3+,5+,6+,8+,9+,11+,12+,14+,15+\t8M,1M,1M,3M,1M,19M,1M,4M,1M,11M + L\t1\t+\t2\t+\t0M + L\t1\t+\t3\t+\t0M + L\t2\t+\t4\t+\t0M + L\t2\t+\t5\t+\t0M + L\t3\t+\t4\t+\t0M + L\t3\t+\t5\t+\t0M + L\t4\t+\t6\t+\t0M + L\t5\t+\t6\t+\t0M + L\t6\t+\t7\t+\t0M + L\t6\t+\t8\t+\t0M + L\t7\t+\t9\t+\t0M + L\t8\t+\t9\t+\t0M + L\t9\t+\t10\t+\t0M + L\t9\t+\t11\t+\t0M + L\t10\t+\t12\t+\t0M + L\t11\t+\t12\t+\t0M + L\t12\t+\t13\t+\t0M + L\t12\t+\t14\t+\t0M + L\t13\t+\t15\t+\t0M + L\t14\t+\t15\t+\t0M"""; + + @Test + public void testByCountingLineTypes() { + int paths = 0; + int max_path = 1; + int links = 0; + int max_links = 20; + int nodes = 0; + int max_nodes = 15; + GFA1Reader gfA1Reader = new GFA1Reader(Arrays.asList(TEST_DATA.split("\n")).iterator()); + while (gfA1Reader.hasNext()) { + Line line = gfA1Reader.next(); + assertNotNull(line); + if (line.getCode() == 'S') { + nodes++; + } + if (line.getCode() == 'P') { + paths++; + } + if (line.getCode() == 'L') { + links++; + } + } + assertEquals(max_links, links); + assertEquals(max_path, paths); + assertEquals(max_nodes, nodes); + } +} diff --git a/src/test/java/io/github/jervenbolleman/handlegraph4j/gfa1/PathHandleGraphForTests.java b/src/test/java/io/github/jervenbolleman/handlegraph4j/gfa1/PathHandleGraphForTests.java new file mode 100644 index 0000000..c54324c --- /dev/null +++ b/src/test/java/io/github/jervenbolleman/handlegraph4j/gfa1/PathHandleGraphForTests.java @@ -0,0 +1,150 @@ +package io.github.jervenbolleman.handlegraph4j.gfa1; + +import java.util.List; +import java.util.stream.LongStream; + +import io.github.jervenbolleman.handlegraph4j.HandleGraph; +import io.github.jervenbolleman.handlegraph4j.PathGraph; +import io.github.jervenbolleman.handlegraph4j.iterators.AutoClosedIterator; +import io.github.jervenbolleman.handlegraph4j.sequences.Sequence; + +class PathHandleGraphForTests implements HandleGraph, + PathGraph { + private final List paths; + + public PathHandleGraphForTests(List paths) { + super(); + this.paths = paths; + } + + @Override + public AutoClosedIterator paths() { + return AutoClosedIterator.from(paths.iterator()); + } + + @Override + public AutoClosedIterator steps() { + return AutoClosedIterator.from(paths.stream().map(TestPathHandle::steps).flatMap(List::stream).iterator()); + } + + @Override + public AutoClosedIterator stepsOf(TestPathHandle path) { + + return AutoClosedIterator.from(path.steps().iterator()); + } + + @Override + public TestPathHandle pathOfStep(TestStepHandle step) { + return step.path(); + } + + @Override + public TestNodeHandle nodeOfStep(TestStepHandle step) { + return step.node(); + } + + @Override + public long beginPositionOfStep(TestStepHandle step) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public long endPositionOfStep(TestStepHandle step) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public long rankOfStep(TestStepHandle step) { + // TODO Auto-generated method stub + return 0; + } + + @Override + public TestStepHandle stepByRankAndPath(TestPathHandle path, long rank) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isCircular(TestPathHandle path) { + return path.circular(); + } + + @Override + public String nameOfPath(TestPathHandle path) { + return path.name(); + } + + @Override + public TestPathHandle pathByName(String name) { + for (TestPathHandle path:paths) + if (path.name().equals(name)) + return path; + return null; + } + + @Override + public LongStream positionsOf(TestPathHandle path) { + // TODO Auto-generated method stub + return null; + } + + @Override + public boolean isReverseNodeHandle(TestNodeHandle nh) { + // TODO Auto-generated method stub + return false; + } + + @Override + public TestNodeHandle flip(TestNodeHandle nh) { + return new TestNodeHandle(nh.id(), ! nh.reverse(), nh.sequence()); + } + + @Override + public long asLong(TestNodeHandle nh) { + return nh.id(); + } + + @Override + public TestNodeHandle fromLong(long id) { + throw new UnsupportedOperationException(); + } + + @Override + public TestEdgeNodeHandle edge(long leftId, long rightId) { + throw new UnsupportedOperationException(); + } + + @Override + public AutoClosedIterator followEdgesToWardsTheRight(TestNodeHandle left) { + throw new UnsupportedOperationException(); + } + + @Override + public AutoClosedIterator followEdgesToWardsTheLeft(TestNodeHandle right) { + throw new UnsupportedOperationException(); + } + + @Override + public AutoClosedIterator edges() { + throw new UnsupportedOperationException(); + } + + @Override + public AutoClosedIterator nodes() { + throw new UnsupportedOperationException(); + } + + @Override + public Sequence sequenceOf(TestNodeHandle handle) { + return handle.sequence(); + } + + @Override + public AutoClosedIterator nodesWithSequence(Sequence s) { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/test/java/io/github/jervenbolleman/handlegraph4j/gfa1/TestEdgeNodeHandle.java b/src/test/java/io/github/jervenbolleman/handlegraph4j/gfa1/TestEdgeNodeHandle.java new file mode 100644 index 0000000..fea4546 --- /dev/null +++ b/src/test/java/io/github/jervenbolleman/handlegraph4j/gfa1/TestEdgeNodeHandle.java @@ -0,0 +1,7 @@ +package io.github.jervenbolleman.handlegraph4j.gfa1; + +import io.github.jervenbolleman.handlegraph4j.EdgeHandle; + +record TestEdgeNodeHandle(TestNodeHandle right, TestNodeHandle left) implements EdgeHandle { + +} diff --git a/src/test/java/io/github/jervenbolleman/handlegraph4j/gfa1/TestNodeHandle.java b/src/test/java/io/github/jervenbolleman/handlegraph4j/gfa1/TestNodeHandle.java new file mode 100644 index 0000000..ad76758 --- /dev/null +++ b/src/test/java/io/github/jervenbolleman/handlegraph4j/gfa1/TestNodeHandle.java @@ -0,0 +1,13 @@ +package io.github.jervenbolleman.handlegraph4j.gfa1; + +import io.github.jervenbolleman.handlegraph4j.NodeHandle; +import io.github.jervenbolleman.handlegraph4j.sequences.Sequence; + +record TestNodeHandle(long id, boolean reverse, Sequence sequence) implements NodeHandle { + + + @Override + public long id() { + return id; + } +} \ No newline at end of file diff --git a/src/test/java/io/github/jervenbolleman/handlegraph4j/gfa1/TestPathHandle.java b/src/test/java/io/github/jervenbolleman/handlegraph4j/gfa1/TestPathHandle.java new file mode 100644 index 0000000..a21afe9 --- /dev/null +++ b/src/test/java/io/github/jervenbolleman/handlegraph4j/gfa1/TestPathHandle.java @@ -0,0 +1,9 @@ +package io.github.jervenbolleman.handlegraph4j.gfa1; + +import java.util.List; + +import io.github.jervenbolleman.handlegraph4j.PathHandle; + +public record TestPathHandle(List steps, boolean circular, String name) implements PathHandle { + +} diff --git a/src/test/java/io/github/jervenbolleman/handlegraph4j/gfa1/TestStepHandle.java b/src/test/java/io/github/jervenbolleman/handlegraph4j/gfa1/TestStepHandle.java new file mode 100644 index 0000000..5701ad6 --- /dev/null +++ b/src/test/java/io/github/jervenbolleman/handlegraph4j/gfa1/TestStepHandle.java @@ -0,0 +1,7 @@ +package io.github.jervenbolleman.handlegraph4j.gfa1; + +import io.github.jervenbolleman.handlegraph4j.StepHandle; + +record TestStepHandle(TestPathHandle path, TestNodeHandle node) implements StepHandle { + +}