add methods for node coverage merge/add; serialize coverage
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 f61cb6f..90def56 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
@@ -34,6 +34,10 @@
 //                + ((bytes[offset + 6] & 0xff) << 8) + ((bytes[offset + 7] & 0xff) << 0);
     }
     
+    public static float getFloat(byte[] bytes, int offset) {   
+        return ByteBuffer.wrap(bytes, offset, 4).getFloat();
+    }
+    
     public static void putInt(int val, byte[] bytes, int offset) {
         bytes[offset] = (byte)((val >>> 24) & 0xFF);        
         bytes[offset + 1] = (byte)((val >>> 16) & 0xFF);
@@ -54,6 +58,11 @@
 //        bytes[offset + 7] = (byte)((val >>> 0) & 0xFF);
     }
     
+    public static void putFloat(float val, byte[] bytes, int offset) {
+        ByteBuffer byteBuffer = ByteBuffer.allocate(4);
+        System.arraycopy(byteBuffer.putFloat(val).array(), 0, bytes, offset, 4);
+    }
+    
     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/type/NodeWritable.java b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/NodeWritable.java
index d61f679..22fd374 100644
--- a/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/NodeWritable.java
+++ b/genomix/genomix-data/src/main/java/edu/uci/ics/genomix/type/NodeWritable.java
@@ -10,18 +10,23 @@
 import org.apache.hadoop.io.DataOutputBuffer;
 import org.apache.hadoop.io.WritableComparable;
 
+import edu.uci.ics.genomix.data.Marshal;
+
 
 public class NodeWritable implements WritableComparable<NodeWritable>, Serializable{
 
     private static final long serialVersionUID = 1L;
     public static final NodeWritable EMPTY_NODE = new NodeWritable();
     
+    private static final int SIZE_FLOAT = 4;
+    
     private PositionListWritable nodeIdList;
     private VKmerListWritable forwardForwardList;
     private VKmerListWritable forwardReverseList;
     private VKmerListWritable reverseForwardList;
     private VKmerListWritable reverseReverseList;
     private VKmerBytesWritable kmer;
+    private float averageCoverage;
     
     // merge/update directions
     public static class DirectionFlag {
@@ -39,27 +44,29 @@
         reverseForwardList = new VKmerListWritable();
         reverseReverseList = new VKmerListWritable();
         kmer = new VKmerBytesWritable();  // in graph construction - not set kmerlength Optimization: VKmer
+        averageCoverage = 0;
     }
     
     public NodeWritable(PositionListWritable nodeIdList, VKmerListWritable FFList, VKmerListWritable FRList,
-            VKmerListWritable RFList, VKmerListWritable RRList, VKmerBytesWritable kmer) {
+            VKmerListWritable RFList, VKmerListWritable RRList, VKmerBytesWritable kmer, float coverage) {
         this();
-        set(nodeIdList, FFList, FRList, RFList, RRList, kmer);
+        set(nodeIdList, FFList, FRList, RFList, RRList, kmer, coverage);
     }
     
     public void set(NodeWritable node){
         set(node.nodeIdList, node.forwardForwardList, node.forwardReverseList, node.reverseForwardList, 
-                node.reverseReverseList, node.kmer);
+                node.reverseReverseList, node.kmer, node.averageCoverage);
     }
     
     public void set(PositionListWritable nodeIdList, VKmerListWritable FFList, VKmerListWritable FRList,
-            VKmerListWritable RFList, VKmerListWritable RRList, VKmerBytesWritable kmer2) {
+            VKmerListWritable RFList, VKmerListWritable RRList, VKmerBytesWritable kmer2, float coverage) {
         this.nodeIdList.set(nodeIdList);
         this.forwardForwardList.setCopy(FFList);
         this.forwardReverseList.setCopy(FRList);
         this.reverseForwardList.setCopy(RFList);
         this.reverseReverseList.setCopy(RRList);
         this.kmer.setAsCopy(kmer2);
+        this.averageCoverage = coverage;
     }
 
     public void reset() {
@@ -69,6 +76,7 @@
         this.reverseForwardList.reset();
         this.reverseReverseList.reset();
         this.kmer.reset(0);
+        averageCoverage = 0;
     }
     
     
@@ -140,11 +148,40 @@
     }
 	
 	/**
+	 * Update my coverage to be the average of this and other. Used when merging paths.
+	 */
+	public void mergeCoverage(NodeWritable other) {
+	    // sequence considered in the average doesn't include anything overlapping with other kmers
+	    float adjustedLength = kmer.getKmerLetterLength() + other.kmer.getKmerLetterLength() - (KmerBytesWritable.getKmerLength() - 1) * 2;
+	    
+	    float myCount = (kmer.getKmerLetterLength() - KmerBytesWritable.getKmerLength() - 1) * averageCoverage;
+	    float otherCount = (other.kmer.getKmerLetterLength() - KmerBytesWritable.getKmerLength() - 1) * other.averageCoverage;
+	    averageCoverage = (myCount + otherCount) / adjustedLength;
+	}
+	
+	/**
+	 * Update my coverage as if all the reads in other became my own 
+	 */
+	public void addCoverage(NodeWritable other) {
+	    float myAdjustedLength = kmer.getKmerLetterLength() - KmerBytesWritable.getKmerLength() - 1;
+	    float otherAdjustedLength = other.kmer.getKmerLetterLength() - KmerBytesWritable.getKmerLength() - 1; 
+	    averageCoverage += other.averageCoverage * (otherAdjustedLength / myAdjustedLength);
+	}
+	
+	public void setAvgCoverage(float coverage) {
+	    averageCoverage = coverage;
+	}
+	
+	public float getAvgCoverage() {
+	    return averageCoverage;
+	}
+	
+	/**
 	 * Returns the length of the byte-array version of this node
 	 */
 	public int getSerializedLength() {
 	    return nodeIdList.getLength() + forwardForwardList.getLength() + forwardReverseList.getLength() + 
-	            reverseForwardList.getLength() + reverseReverseList.getLength() + kmer.getLength();
+	            reverseForwardList.getLength() + reverseReverseList.getLength() + kmer.getLength() + SIZE_FLOAT;
 	}
 	
 	/**
@@ -172,6 +209,9 @@
         
         curOffset += reverseReverseList.getLength();
         kmer.setAsCopy(data, curOffset);
+        
+        curOffset += kmer.getLength();
+        averageCoverage = Marshal.getFloat(data, curOffset);
     }
     
     public void setAsReference(byte[] data, int offset) {
@@ -189,6 +229,9 @@
         
         curOffset += reverseReverseList.getLength();
         kmer.setAsReference(data, curOffset);
+        
+        curOffset += kmer.getLength();
+        averageCoverage = Marshal.getFloat(data, curOffset);
     }
 	
     @Override
@@ -199,6 +242,7 @@
         this.reverseForwardList.write(out);
         this.reverseReverseList.write(out);
         this.kmer.write(out);
+        out.writeFloat(averageCoverage);
     }
 
     @Override
@@ -210,6 +254,7 @@
         this.reverseForwardList.readFields(in);
         this.reverseReverseList.readFields(in);
         this.kmer.readFields(in);
+        averageCoverage = in.readFloat();
     }
 
     @Override