package com.asgow.ciel.examples.smithwaterman; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.InputStream; import com.asgow.ciel.executor.Ciel; import com.asgow.ciel.references.Reference; import com.asgow.ciel.references.WritableReference; import com.asgow.ciel.tasks.ConstantNumOutputsTask; import com.asgow.ciel.tasks.FirstClassJavaTask; public class SmithWatermanBlockTask implements ConstantNumOutputsTask { private final Reference horizontalChunk; private final Reference verticalChunk; private final Reference upLeftNeighbour; private final Reference upNeighbour; private final Reference leftNeighbour; private final int insertionScore; private final int deletionScore; private final int mismatchScore; private final int matchScore; public SmithWatermanBlockTask(Reference horizontalChunk, Reference verticalChunk, Reference upLeftNeighbour, Reference upNeighbour, Reference leftNeighbour, int insertionScore, int deletionScore, int mismatchScore, int matchScore) { this.horizontalChunk = horizontalChunk; this.verticalChunk = verticalChunk; this.upLeftNeighbour = upLeftNeighbour; this.upNeighbour = upNeighbour; this.leftNeighbour = leftNeighbour; this.insertionScore = insertionScore; this.deletionScore = deletionScore; this.mismatchScore = mismatchScore; this.matchScore = matchScore; } public int getNumOutputs() { return 3; } public Reference[] getDependencies() { return new Reference[] { this.horizontalChunk, this.verticalChunk, this.upLeftNeighbour, this.upNeighbour, this.leftNeighbour }; } public void invoke() throws Exception { // Read input chunks. int c; ByteArrayOutputStream horizontalChunkBuffer = new ByteArrayOutputStream(); InputStream horizontalChunkInput = Ciel.RPC.getStreamForReference(this.horizontalChunk); while ((c = horizontalChunkInput.read()) != -1) { horizontalChunkBuffer.write(c); } horizontalChunkInput.close(); byte[] horizontalChunkArray = horizontalChunkBuffer.toByteArray(); //System.err.printf("Horizontal chunk is length: %d\n", horizontalChunkArray.length); ByteArrayOutputStream verticalChunkBuffer = new ByteArrayOutputStream(); InputStream verticalChunkInput = Ciel.RPC.getStreamForReference(this.verticalChunk); while ((c = verticalChunkInput.read()) != -1) { verticalChunkBuffer.write(c); } verticalChunkInput.close(); byte[] verticalChunkArray = verticalChunkBuffer.toByteArray(); //System.err.printf("Vertical chunk is length: %d\n", verticalChunkArray.length); // Read in the up-left and up haloes (if available, otherwise set them to be zero). int[] previousRow = new int[horizontalChunkArray.length + 1]; int left; if (this.upLeftNeighbour == null) { left = 0; previousRow[0] = 0; } else { DataInputStream upLeftNeighbourInput = new DataInputStream(Ciel.RPC.getStreamForReference(this.upLeftNeighbour)); previousRow[0] = upLeftNeighbourInput.readInt(); left = previousRow[0]; upLeftNeighbourInput.close(); } if (this.upNeighbour == null) { for (int i = 1; i <= horizontalChunkArray.length; ++i) { previousRow[i] = 0; } } else { DataInputStream upNeighbourInput = new DataInputStream(Ciel.RPC.getStreamForReference(this.upNeighbour)); for (int i = 1; i <= horizontalChunkArray.length; ++i) { previousRow[i] = upNeighbourInput.readInt(); } upNeighbourInput.close(); } // If we don't have a left neighbour, stream in zeroes instead. DataInputStream leftNeighbourInput; if (this.leftNeighbour == null) { leftNeighbourInput = new DataInputStream(new ZeroInputStream()); } else { leftNeighbourInput = new DataInputStream(Ciel.RPC.getStreamForReference(this.leftNeighbour)); } // Output 2 is the right halo. WritableReference rightHalo = Ciel.RPC.getOutputFilename(2); DataOutputStream rightHaloOutput = new DataOutputStream(rightHalo.open()); int[] currentRow = new int[previousRow.length]; // Now actually execute the Smith-Waterman algorithm. for (int i = 0; i < verticalChunkArray.length; ++i) { int aboveLeft = left; left = leftNeighbourInput.readInt(); previousRow[0] = aboveLeft; currentRow[0] = left; for (int j = 1; j <= horizontalChunkArray.length; ++j) { if (verticalChunkArray[i] == horizontalChunkArray[j-1]) { // Characters match at this position. currentRow[j] = previousRow[j-1] + matchScore; } else { // Characters don't match at this position. int bestOption = 0; if (bestOption < previousRow[j-1] + mismatchScore) { bestOption = previousRow[j-1] + mismatchScore; } if (bestOption < currentRow[j-1] + insertionScore) { bestOption = currentRow[j-1] + insertionScore; } if (bestOption < previousRow[j] + deletionScore) { bestOption = previousRow[j] + deletionScore; } currentRow[j] = bestOption; } } rightHaloOutput.writeInt(currentRow[horizontalChunkArray.length]); int[] temp; temp = currentRow; currentRow = previousRow; previousRow = temp; } rightHaloOutput.close(); leftNeighbourInput.close(); // Write output halos. { DataOutputStream bottomRightHaloOutputStream = new DataOutputStream(Ciel.RPC.getOutputFilename(0).open()); bottomRightHaloOutputStream.writeInt(previousRow[horizontalChunkArray.length]); bottomRightHaloOutputStream.close(); } { DataOutputStream bottomHaloOutputStream = new DataOutputStream(Ciel.RPC.getOutputFilename(1).open()); for (int j = 1; j <= horizontalChunkArray.length; ++j) { bottomHaloOutputStream.writeInt(previousRow[j]); } bottomHaloOutputStream.close(); } } public void setup() { } }