public void BinaryIO_Tests() { //Add null terminated string byte[] bytes1 = new byte[10]; int offset1 = 3; BinaryIO.AddNullTerminatedString(ref bytes1, ref offset1, "ABCDE"); Assert.Equal(9, offset1); //Add int bytes byte[] bytes2 = new byte[10]; int offset2 = 3; BinaryIO.AddIntBytes(ref bytes2, ref offset2, -4096); Assert.Equal(bytes2[4], 240); Assert.Equal(bytes2[5], 255); Assert.Equal(bytes2[6], 255); Assert.Equal(7, offset2); //Add uint bytes byte[] bytes3 = new byte[10]; int offset3 = 3; BinaryIO.AddUIntBytes(ref bytes3, ref offset3, 4096); Assert.Equal(bytes3[4], 16); Assert.Equal(7, offset3); }
/// <summary> /// Serialize alignment to a byte array, for later flushing to output file. /// </summary> static public bool SerializeAlignment(ref BamAlignment al, ref byte[] buffer, ref int offset) { // initialize uint nameLen = (uint)al.Name.Length + 1; uint numBases = (uint)al.Bases.Length; uint numCigarOperations = (uint)al.CigarData.Count; uint packedCigarLen = numCigarOperations * 4; uint numEncodedBases = (uint)((numBases / 2.0) + 0.5); uint tagDataLen = (uint)al.TagData.Length; uint dataBlockSize = nameLen + packedCigarLen + numEncodedBases + numBases + tagDataLen; uint alignBlockSize = BamConstants.CoreAlignmentDataLen + dataBlockSize; uint blockSize = alignBlockSize + 4; if (buffer == null) { offset = 0; buffer = new byte[blockSize]; } else if (offset + blockSize > buffer.Length) { return(false); } // store the block size BinaryIO.AddUIntBytes(ref buffer, ref offset, alignBlockSize); // store the BAM core data BinaryIO.AddIntBytes(ref buffer, ref offset, al.RefID); BinaryIO.AddIntBytes(ref buffer, ref offset, al.Position); BinaryIO.AddUIntBytes(ref buffer, ref offset, (al.Bin << 16) | (al.MapQuality << 8) | nameLen); BinaryIO.AddUIntBytes(ref buffer, ref offset, (al.AlignmentFlag << 16) | numCigarOperations); BinaryIO.AddUIntBytes(ref buffer, ref offset, numBases); BinaryIO.AddIntBytes(ref buffer, ref offset, al.MateRefID); BinaryIO.AddIntBytes(ref buffer, ref offset, al.MatePosition); BinaryIO.AddIntBytes(ref buffer, ref offset, al.FragmentLength); // store the alignment name BinaryIO.AddNullTerminatedString(ref buffer, ref offset, al.Name); // store the packed CIGAR string and packed bases PackCigar(ref offset, ref buffer, al.CigarData); PackBases(ref offset, ref buffer, numEncodedBases, al.Bases); // store the base qualities Buffer.BlockCopy(al.Qualities, 0, buffer, offset, al.Qualities.Length); offset += al.Qualities.Length; // store the tag data Buffer.BlockCopy(al.TagData, 0, buffer, offset, al.TagData.Length); offset += al.TagData.Length; return(true); }
// writes an alignment public void WriteAlignment(BamAlignment al) { if (!IsOpen) { throw new ApplicationException(string.Format("ERROR: Tried to write an alignment but the file has not been opened yet.")); } // initialize uint nameLen = (uint)al.Name.Length + 1; uint numBases = (uint)al.Bases.Length; uint numCigarOperations = (uint)al.CigarData.Count; uint packedCigarLen = numCigarOperations * 4; uint numEncodedBases = (uint)((numBases / 2.0) + 0.5); uint tagDataLen = (uint)al.TagData.Length; uint dataBlockSize = nameLen + packedCigarLen + numEncodedBases + numBases + tagDataLen; uint alignBlockSize = BamConstants.CoreAlignmentDataLen + dataBlockSize; uint blockSize = alignBlockSize + 4; int offset = 0; // test if we should flush the block if ((BlockOffset + blockSize) > MaxBlockSize) { FlushBlock(); } // redimension the buffer if needed if (blockSize > _outputBuffer.Length) { _outputBuffer = new byte[blockSize + 1024]; } // store the block size BinaryIO.AddUIntBytes(ref _outputBuffer, ref offset, alignBlockSize); // store the BAM core data BinaryIO.AddIntBytes(ref _outputBuffer, ref offset, al.RefID); BinaryIO.AddIntBytes(ref _outputBuffer, ref offset, al.Position); BinaryIO.AddUIntBytes(ref _outputBuffer, ref offset, (al.Bin << 16) | (al.MapQuality << 8) | nameLen); BinaryIO.AddUIntBytes(ref _outputBuffer, ref offset, (al.AlignmentFlag << 16) | numCigarOperations); BinaryIO.AddUIntBytes(ref _outputBuffer, ref offset, numBases); BinaryIO.AddIntBytes(ref _outputBuffer, ref offset, al.MateRefID); BinaryIO.AddIntBytes(ref _outputBuffer, ref offset, al.MatePosition); BinaryIO.AddIntBytes(ref _outputBuffer, ref offset, al.FragmentLength); // store the alignment name BinaryIO.AddNullTerminatedString(ref _outputBuffer, ref offset, al.Name); // store the packed CIGAR string and packed bases PackCigar(ref offset, al.CigarData); PackBases(ref offset, numEncodedBases, al.Bases); // store the base qualities Buffer.BlockCopy(al.Qualities, 0, _outputBuffer, offset, al.Qualities.Length); offset += al.Qualities.Length; // store the tag data Buffer.BlockCopy(al.TagData, 0, _outputBuffer, offset, al.TagData.Length); offset += al.TagData.Length; // write the alignment Write(_outputBuffer, blockSize); }