remake new graph class - PositionWritable and NodeWritable
diff --git a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/data/Marshal.java b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/data/Marshal.java
index e80d7da..4ce14cc 100644
--- a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/data/Marshal.java
+++ b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/data/Marshal.java
@@ -20,6 +20,12 @@
+ ((bytes[offset + 3] & 0xff) << 0);
}
+ public static long getLong(byte[] bytes, int offset) {
+ return ((bytes[offset] & 0xff) << 54) + ((bytes[offset] & 0xff) << 48) + ((bytes[offset + 1] & 0xff) << 40)
+ + ((bytes[offset + 2] & 0xff) << 32) + ((bytes[offset] & 0xff) << 24) + ((bytes[offset + 1] & 0xff) << 16)
+ + ((bytes[offset + 2] & 0xff) << 8) + ((bytes[offset + 3] & 0xff) << 0);
+ }
+
public static void putInt(int val, byte[] bytes, int offset) {
bytes[offset] = (byte)((val >>> 24) & 0xFF);
bytes[offset + 1] = (byte)((val >>> 16) & 0xFF);
@@ -27,6 +33,17 @@
bytes[offset + 3] = (byte)((val >>> 0) & 0xFF);
}
+ public static void putLong(long val, byte[] bytes, int offset) {
+ bytes[offset] = (byte)((val >>> 54) & 0xFF);
+ bytes[offset + 1] = (byte)((val >>> 48) & 0xFF);
+ bytes[offset + 2] = (byte)((val >>> 40) & 0xFF);
+ bytes[offset + 3] = (byte)((val >>> 32) & 0xFF);
+ bytes[offset + 4] = (byte)((val >>> 24) & 0xFF);
+ bytes[offset + 5] = (byte)((val >>> 16) & 0xFF);
+ bytes[offset + 6] = (byte)((val >>> 8) & 0xFF);
+ bytes[offset + 7] = (byte)((val >>> 0) & 0xFF);
+ }
+
public static int hashBytes(byte[] bytes, int offset, int length) {
int hash = 1;
for (int i = offset; i < offset + length; i++)
diff --git a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/newtype/NodeWritable.java b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/newtype/NodeWritable.java
new file mode 100644
index 0000000..b6e2055
--- /dev/null
+++ b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/newtype/NodeWritable.java
@@ -0,0 +1,196 @@
+package edu.uci.ics.genomix.newtype;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.Serializable;
+
+import org.apache.hadoop.io.WritableComparable;
+import edu.uci.ics.genomix.type.KmerBytesWritable;
+import edu.uci.ics.genomix.newtype.PositionListWritable;
+
+public class NodeWritable implements WritableComparable<NodeWritable>, Serializable{
+
+ private static final long serialVersionUID = 1L;
+ public static final NodeWritable EMPTY_NODE = new NodeWritable(0);
+
+ private PositionListWritable forwardForwardList;
+ private PositionListWritable forwardReverseList;
+ private PositionListWritable reverseForwardList;
+ private PositionListWritable reverseReverseList;
+ private KmerBytesWritable kmer;
+
+ // merge/update directions
+ public static class DirectionFlag {
+ public static final byte DIR_FF = 0b00 << 0;
+ public static final byte DIR_FR = 0b01 << 0;
+ public static final byte DIR_RF = 0b10 << 0;
+ public static final byte DIR_RR = 0b11 << 0;
+ public static final byte DIR_MASK = 0b11 << 0;
+ }
+
+ public NodeWritable() {
+ this(21);
+ }
+
+ public NodeWritable(int kmerSize) {
+ forwardForwardList = new PositionListWritable();
+ forwardReverseList = new PositionListWritable();
+ reverseForwardList = new PositionListWritable();
+ reverseReverseList = new PositionListWritable();
+ kmer = new KmerBytesWritable(kmerSize);
+ }
+
+ public NodeWritable(PositionListWritable FFList, PositionListWritable FRList,
+ PositionListWritable RFList, PositionListWritable RRList, KmerBytesWritable kmer) {
+ this(kmer.getKmerLength());
+ set(FFList, FRList, RFList, RRList, kmer);
+ }
+
+ public void set(NodeWritable node){
+ set(node.forwardForwardList, node.forwardReverseList, node.reverseForwardList,
+ node.reverseReverseList, node.kmer);
+ }
+
+ public void set(PositionListWritable FFList, PositionListWritable FRList,
+ PositionListWritable RFList, PositionListWritable RRList, KmerBytesWritable kmer) {
+ this.forwardForwardList.set(FFList);
+ this.forwardReverseList.set(FRList);
+ this.reverseForwardList.set(RFList);
+ this.reverseReverseList.set(RRList);
+ this.kmer.set(kmer);
+ }
+
+ public void reset(int kmerSize) {
+ forwardForwardList.reset();
+ forwardReverseList.reset();
+ reverseForwardList.reset();
+ reverseReverseList.reset();
+ kmer.reset(kmerSize);
+ }
+
+ public KmerBytesWritable getKmer() {
+ return kmer;
+ }
+
+ public void setKmer(KmerBytesWritable kmer) {
+ this.kmer = kmer;
+ }
+
+ public int getCount() {
+ return kmer.getKmerLength();
+ }
+
+ public PositionListWritable getFFList() {
+ return forwardForwardList;
+ }
+
+ public PositionListWritable getFRList() {
+ return forwardReverseList;
+ }
+
+ public PositionListWritable getRFList() {
+ return reverseForwardList;
+ }
+
+ public PositionListWritable getRRList() {
+ return reverseReverseList;
+ }
+
+ public PositionListWritable getListFromDir(byte dir) {
+ switch (dir & DirectionFlag.DIR_MASK) {
+ case DirectionFlag.DIR_FF:
+ return getFFList();
+ case DirectionFlag.DIR_FR:
+ return getFRList();
+ case DirectionFlag.DIR_RF:
+ return getRFList();
+ case DirectionFlag.DIR_RR:
+ return getRRList();
+ default:
+ throw new RuntimeException("Unrecognized direction in getListFromDir: " + dir);
+ }
+ }
+ @Override
+ public void write(DataOutput out) throws IOException {
+ this.forwardForwardList.write(out);
+ this.forwardReverseList.write(out);
+ this.reverseForwardList.write(out);
+ this.reverseReverseList.write(out);
+ this.kmer.write(out);
+ }
+
+ @Override
+ public void readFields(DataInput in) throws IOException {
+ this.forwardForwardList.readFields(in);
+ this.forwardReverseList.readFields(in);
+ this.reverseForwardList.readFields(in);
+ this.reverseReverseList.readFields(in);
+ this.kmer.readFields(in);
+ }
+
+ @Override
+ public int compareTo(NodeWritable other) {
+ return this.kmer.compareTo(other.kmer);
+ }
+
+ @Override
+ public int hashCode() {
+ return this.kmer.hashCode();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof NodeWritable) {
+ NodeWritable nw = (NodeWritable) o;
+ return (this.forwardForwardList.equals(nw.forwardForwardList)
+ && this.forwardReverseList.equals(nw.forwardReverseList)
+ && this.reverseForwardList.equals(nw.reverseForwardList)
+ && this.reverseReverseList.equals(nw.reverseReverseList) && this.kmer.equals(nw.kmer));
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sbuilder = new StringBuilder();
+ sbuilder.append('(');
+ sbuilder.append(forwardForwardList.toString()).append('\t');
+ sbuilder.append(forwardReverseList.toString()).append('\t');
+ sbuilder.append(reverseForwardList.toString()).append('\t');
+ sbuilder.append(reverseReverseList.toString()).append('\t');
+ sbuilder.append(kmer.toString()).append(')');
+ return sbuilder.toString();
+ }
+
+ public void mergeForwardNext(NodeWritable nextNode, int initialKmerSize) {
+ this.forwardForwardList.set(nextNode.forwardForwardList);
+ this.forwardReverseList.set(nextNode.forwardReverseList);
+ kmer.mergeWithFFKmer(initialKmerSize, nextNode.getKmer());
+ }
+
+ public void mergeForwardPre(NodeWritable preNode, int initialKmerSize) {
+ this.reverseForwardList.set(preNode.reverseForwardList);
+ this.reverseReverseList.set(preNode.reverseReverseList);
+ kmer.mergeWithRRKmer(initialKmerSize, preNode.getKmer());
+ }
+
+ public int inDegree() {
+ return reverseReverseList.getCountOfPosition() + reverseForwardList.getCountOfPosition();
+ }
+
+ public int outDegree() {
+ return forwardForwardList.getCountOfPosition() + forwardReverseList.getCountOfPosition();
+ }
+
+ /*
+ * Return if this node is a "path" compressible node, that is, it has an in-degree and out-degree of 1
+ */
+ public boolean isPathNode() {
+ return inDegree() == 1 && outDegree() == 1;
+ }
+
+ public boolean isSimpleOrTerminalPath() {
+ return isPathNode() || (inDegree() == 0 && outDegree() == 1) || (inDegree() == 1 && outDegree() == 0);
+ }
+}
diff --git a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/newtype/PositionListWritable.java b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/newtype/PositionListWritable.java
new file mode 100644
index 0000000..8ebeb3f
--- /dev/null
+++ b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/newtype/PositionListWritable.java
@@ -0,0 +1,238 @@
+package edu.uci.ics.genomix.newtype;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.Serializable;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.hadoop.io.Writable;
+
+import edu.uci.ics.genomix.data.Marshal;
+import edu.uci.ics.genomix.newtype.PositionWritable;
+
+public class PositionListWritable implements Writable, Iterable<PositionWritable>, Serializable{
+ private static final long serialVersionUID = 1L;
+ protected byte[] storage;
+ protected int offset;
+ protected int valueCount;
+ protected static final byte[] EMPTY = {};
+ public static final int LONGBYTES = 8;
+
+ protected PositionWritable posIter = new PositionWritable();
+
+ public PositionListWritable() {
+ this.storage = EMPTY;
+ this.valueCount = 0;
+ this.offset = 0;
+ }
+
+ public PositionListWritable(List<PositionWritable> posns) {
+ this();
+ for (PositionWritable p : posns) {
+ append(p);
+ }
+ }
+
+ public void setNewReference(int count, byte[] data, int offset) {
+ this.valueCount = count;
+ this.storage = data;
+ this.offset = offset;
+ }
+
+ public void append(long uuid) {
+ setSize((1 + valueCount) * PositionWritable.LENGTH);
+ Marshal.putLong(uuid, storage, offset + valueCount * PositionWritable.LENGTH);
+ valueCount += 1;
+ }
+
+ public void append(PositionWritable pos) {
+ if(pos != null){
+ setSize((1 + valueCount) * PositionWritable.LENGTH);
+ System.arraycopy(pos.getByteArray(), pos.getStartOffset(), storage, offset + valueCount
+ * PositionWritable.LENGTH, pos.getLength());
+ valueCount += 1;
+ }
+ }
+
+ /*
+ * Append the otherList to the end of myList
+ */
+ public void appendList(PositionListWritable otherList) {
+ if (otherList.valueCount > 0) {
+ setSize((valueCount + otherList.valueCount) * PositionWritable.LENGTH);
+ // copy contents of otherList into the end of my storage
+ System.arraycopy(otherList.storage, otherList.offset,
+ storage, offset + valueCount * PositionWritable.LENGTH,
+ otherList.valueCount * PositionWritable.LENGTH);
+ valueCount += otherList.valueCount;
+ }
+ }
+
+ public static int getCountByDataLength(int length) {
+ if (length % PositionWritable.LENGTH != 0) {
+ throw new IllegalArgumentException("Length of positionlist is invalid");
+ }
+ return length / PositionWritable.LENGTH;
+ }
+
+ public void set(PositionListWritable otherList) {
+ set(otherList.valueCount, otherList.storage, otherList.offset);
+ }
+
+ public void set(int valueCount, byte[] newData, int offset) {
+ this.valueCount = valueCount;
+ setSize(valueCount * PositionWritable.LENGTH);
+ if (valueCount > 0) {
+ System.arraycopy(newData, offset, storage, this.offset, valueCount * PositionWritable.LENGTH);
+ }
+ }
+
+ public void reset() {
+ valueCount = 0;
+ }
+
+ protected void setSize(int size) {
+ if (size > getCapacity()) {
+ setCapacity((size * 3 / 2));
+ }
+ }
+
+ protected int getCapacity() {
+ return storage.length - offset;
+ }
+
+ protected void setCapacity(int new_cap) {
+ if (new_cap > getCapacity()) {
+ byte[] new_data = new byte[new_cap];
+ if (storage.length - offset > 0) {
+ System.arraycopy(storage, offset, new_data, 0, storage.length - offset);
+ }
+ storage = new_data;
+ offset = 0;
+ }
+ }
+
+ public PositionWritable getPosition(int i) {
+ if (i >= valueCount) {
+ throw new ArrayIndexOutOfBoundsException("No such positions");
+ }
+ posIter.setNewReference(storage, offset + i * PositionWritable.LENGTH);
+ return posIter;
+ }
+
+ public void resetPosition(int i, long uuid) {
+ if (i >= valueCount) {
+ throw new ArrayIndexOutOfBoundsException("No such positions");
+ }
+ Marshal.putLong(uuid, storage, offset + i * PositionWritable.LENGTH);
+ }
+
+ public int getCountOfPosition() {
+ return valueCount;
+ }
+
+ public byte[] getByteArray() {
+ return storage;
+ }
+
+ public int getStartOffset() {
+ return offset;
+ }
+
+ public int getLength() {
+ return valueCount * PositionWritable.LENGTH;
+ }
+
+ @Override
+ public Iterator<PositionWritable> iterator() {
+ Iterator<PositionWritable> it = new Iterator<PositionWritable>() {
+
+ private int currentIndex = 0;
+
+ @Override
+ public boolean hasNext() {
+ return currentIndex < valueCount;
+ }
+
+ @Override
+ public PositionWritable next() {
+ return getPosition(currentIndex++);
+ }
+
+ @Override
+ public void remove() {
+ if(currentIndex < valueCount)
+ System.arraycopy(storage, offset + currentIndex * PositionWritable.LENGTH,
+ storage, offset + (currentIndex - 1) * PositionWritable.LENGTH,
+ (valueCount - currentIndex) * PositionWritable.LENGTH);
+ valueCount--;
+ currentIndex--;
+ }
+ };
+ return it;
+ }
+
+ /*
+ * remove the first instance of @toRemove. Uses a linear scan. Throws an exception if not in this list.
+ */
+ public void remove(PositionWritable toRemove) {
+ Iterator<PositionWritable> posIterator = this.iterator();
+ while (posIterator.hasNext()) {
+ if(toRemove.equals(posIterator.next())) {
+ posIterator.remove();
+ return;
+ }
+ }
+ //throw new ArrayIndexOutOfBoundsException("the PositionWritable `" + toRemove.toString() + "` was not found in this list.");
+ }
+
+ @Override
+ public void write(DataOutput out) throws IOException {
+ out.writeInt(valueCount);
+ out.write(storage, offset, valueCount * PositionWritable.LENGTH);
+ }
+
+ @Override
+ public void readFields(DataInput in) throws IOException {
+ this.valueCount = in.readInt();
+ setSize(valueCount * PositionWritable.LENGTH);
+ in.readFully(storage, offset, valueCount * PositionWritable.LENGTH);
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder sbuilder = new StringBuilder();
+ sbuilder.append('[');
+ for (PositionWritable pos : this) {
+ sbuilder.append(pos.toString());
+ sbuilder.append(',');
+ }
+ if (valueCount > 0) {
+ sbuilder.setCharAt(sbuilder.length() - 1, ']');
+ } else {
+ sbuilder.append(']');
+ }
+ return sbuilder.toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Marshal.hashBytes(getByteArray(), getStartOffset(), getLength());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof PositionListWritable))
+ return false;
+ PositionListWritable other = (PositionListWritable) o;
+ if (this.valueCount != other.valueCount)
+ return false;
+ for (int i=0; i < this.valueCount; i++) {
+ if (!this.getPosition(i).equals(other.getPosition(i)))
+ return false;
+ }
+ return true;
+ }
+}
diff --git a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/newtype/PositionWritable.java b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/newtype/PositionWritable.java
new file mode 100644
index 0000000..cde7226
--- /dev/null
+++ b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/newtype/PositionWritable.java
@@ -0,0 +1,91 @@
+package edu.uci.ics.genomix.newtype;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+import java.io.Serializable;
+
+import org.apache.hadoop.io.WritableComparable;
+
+import edu.uci.ics.genomix.data.Marshal;
+import edu.uci.ics.genomix.newtype.PositionWritable;
+
+public class PositionWritable implements WritableComparable<PositionWritable>, Serializable{
+ private static final long serialVersionUID = 1L;
+ protected byte[] storage;
+ protected int offset;
+ public static final int LENGTH = 5;
+ public static final int LONGBYTES = 8;
+
+ public PositionWritable() {
+ storage = new byte[LENGTH];
+ offset = 0;
+ }
+
+ public PositionWritable(long uuid){
+ this();
+ set(uuid);
+ }
+
+ public void set(long uuid){
+ Marshal.putLong(uuid, storage, offset);
+ }
+
+ public void set(PositionWritable pos) {
+ set(pos.getUUID());
+ }
+
+ public void setNewReference(byte[] storage, int offset) {
+ this.storage = storage;
+ this.offset = offset;
+ }
+
+ public long getUUID(){
+ return Marshal.getLong(storage, offset);
+ }
+
+ public byte[] getByteArray() {
+ return storage;
+ }
+
+ public int getStartOffset() {
+ return offset;
+ }
+
+ public int getLength() {
+ return LENGTH;
+ }
+
+ @Override
+ public void readFields(DataInput in) throws IOException {
+ in.readFully(storage, offset, LENGTH);
+ }
+
+ @Override
+ public void write(DataOutput out) throws IOException {
+ out.write(storage, offset, LENGTH);
+ }
+
+ @Override
+ public int hashCode() {
+ return Marshal.hashBytes(getByteArray(), getStartOffset(), getLength());
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof PositionWritable))
+ return false;
+ PositionWritable other = (PositionWritable) o;
+ return this.getUUID() == other.getUUID();
+ }
+
+ @Override
+ public int compareTo(PositionWritable other) {
+ return (this.getUUID() < other.getUUID()) ? -1 : ((this.getUUID() == other.getUUID()) ? 0 : 1);
+ }
+
+ @Override
+ public String toString() {
+ return "(" + Long.toString(this.getUUID()) + ")";
+ }
+}
diff --git a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/PositionListWritable.java b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/PositionListWritable.java
index ebcf7f0..d929dfc 100644
--- a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/PositionListWritable.java
+++ b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/PositionListWritable.java
@@ -117,10 +117,6 @@
@Override
public void remove() {
-// for(int cursor = currentIndex; cursor < valueCount; cursor++){
-// System.arraycopy(storage, offset + cursor * PositionWritable.LENGTH,
-// storage, offset + (cursor-1) * PositionWritable.LENGTH, PositionWritable.LENGTH);
-// }
if(currentIndex < valueCount)
System.arraycopy(storage, offset + currentIndex * PositionWritable.LENGTH,
storage, offset + (currentIndex - 1) * PositionWritable.LENGTH,