github.com/Schaudge/hts@v0.0.0-20240223063651-737b4d69d68c/bgzf/index/strategy.go (about)

     1  // Copyright ©2015 The bíogo Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package index
     6  
     7  import (
     8  	"github.com/Schaudge/hts/bgzf"
     9  )
    10  
    11  // MergeStrategy represents a chunk compression strategy.
    12  type MergeStrategy func([]bgzf.Chunk) []bgzf.Chunk
    13  
    14  var (
    15  	// Identity leaves the []bgzf.Chunk unaltered.
    16  	Identity MergeStrategy = identity
    17  
    18  	// Adjacent merges contiguous bgzf.Chunks.
    19  	Adjacent MergeStrategy = adjacent
    20  
    21  	// Squash merges all bgzf.Chunks into a single bgzf.Chunk.
    22  	Squash MergeStrategy = squash
    23  )
    24  
    25  // CompressorStrategy returns a MergeStrategy that will merge bgzf.Chunks
    26  // that have a distance between BGZF block starts less than or equal
    27  // to near.
    28  func CompressorStrategy(near int64) MergeStrategy {
    29  	return func(chunks []bgzf.Chunk) []bgzf.Chunk {
    30  		if len(chunks) == 0 {
    31  			return nil
    32  		}
    33  		for c := 1; c < len(chunks); c++ {
    34  			leftChunk := chunks[c-1]
    35  			rightChunk := &chunks[c]
    36  			if leftChunk.End.File+near >= rightChunk.Begin.File {
    37  				rightChunk.Begin = leftChunk.Begin
    38  				if vOffset(leftChunk.End) > vOffset(rightChunk.End) {
    39  					rightChunk.End = leftChunk.End
    40  				}
    41  				chunks = append(chunks[:c-1], chunks[c:]...)
    42  				c--
    43  			}
    44  		}
    45  		return chunks
    46  	}
    47  }
    48  
    49  func identity(chunks []bgzf.Chunk) []bgzf.Chunk { return chunks }
    50  
    51  func adjacent(chunks []bgzf.Chunk) []bgzf.Chunk {
    52  	if len(chunks) == 0 {
    53  		return nil
    54  	}
    55  	for c := 1; c < len(chunks); c++ {
    56  		leftChunk := chunks[c-1]
    57  		rightChunk := &chunks[c]
    58  		leftEndOffset := vOffset(leftChunk.End)
    59  		if leftEndOffset >= vOffset(rightChunk.Begin) {
    60  			rightChunk.Begin = leftChunk.Begin
    61  			if leftEndOffset > vOffset(rightChunk.End) {
    62  				rightChunk.End = leftChunk.End
    63  			}
    64  			chunks = append(chunks[:c-1], chunks[c:]...)
    65  			c--
    66  		}
    67  	}
    68  	return chunks
    69  }
    70  
    71  func squash(chunks []bgzf.Chunk) []bgzf.Chunk {
    72  	if len(chunks) == 0 {
    73  		return nil
    74  	}
    75  	left := chunks[0].Begin
    76  	right := chunks[0].End
    77  	for _, c := range chunks[1:] {
    78  		if vOffset(c.End) > vOffset(right) {
    79  			right = c.End
    80  		}
    81  	}
    82  	return []bgzf.Chunk{{Begin: left, End: right}}
    83  }