// writes an alignment public void WriteAlignment(BamAlignment al) { if (!IsOpen) { throw new IOException(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, ref _outputBuffer, 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); }