github.com/biogo/store@v0.0.0-20201120204734-aad293a2328f/interval/landscape/landscape.go (about)

     1  // Copyright ©2013 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 landscape implements persistence landscape calculation for a set of intervals.
     6  //
     7  // The detail of this representation are described in 'Statistical Topology Using Persistence
     8  // Landscapes.' P. Bubenik http://arxiv.org/pdf/1207.6437v1.pdf
     9  package landscape
    10  
    11  import (
    12  	"container/heap"
    13  	"sort"
    14  
    15  	"github.com/biogo/store/interval"
    16  )
    17  
    18  type endHeap []interval.IntInterface
    19  
    20  func (e endHeap) Len() int              { return len(e) }
    21  func (e endHeap) Less(i, j int) bool    { return e[i].Range().End < e[j].Range().End }
    22  func (e endHeap) Swap(i, j int)         { e[i], e[j] = e[j], e[i] }
    23  func (e *endHeap) Push(x interface{})   { *e = append(*e, x.(interval.IntInterface)) }
    24  func (e *endHeap) Pop() (i interface{}) { i, *e = (*e)[len(*e)-1], (*e)[:len(*e)-1]; return i }
    25  
    26  type endRangeHeap []interval.IntRange
    27  
    28  func (e endRangeHeap) Len() int              { return len(e) }
    29  func (e endRangeHeap) Less(i, j int) bool    { return e[i].End < e[j].End }
    30  func (e endRangeHeap) Swap(i, j int)         { e[i], e[j] = e[j], e[i] }
    31  func (e *endRangeHeap) Push(x interface{})   { *e = append(*e, x.(interval.IntRange)) }
    32  func (e *endRangeHeap) Pop() (i interface{}) { i, *e = (*e)[len(*e)-1], (*e)[:len(*e)-1]; return i }
    33  
    34  func min(a, b int) int {
    35  	if a < b {
    36  		return a
    37  	}
    38  	return b
    39  }
    40  
    41  func max(a, b int) int {
    42  	if a > b {
    43  		return a
    44  	}
    45  	return b
    46  }
    47  
    48  func reverse(v []int) {
    49  	for i, j := 0, len(v)-1; i < j; i, j = i+1, j-1 {
    50  		v[i], v[j] = v[j], v[i]
    51  	}
    52  }
    53  
    54  // DescribeTree calculates the persistence landscape functions λₖ for the interval
    55  // data in the provided interval tree. fn is called for each position t of the span
    56  // of the interval data with the values for t and the k λ functions at t.
    57  // Explicit zero values for a λₖ(t) are included only at the end points of intervals
    58  // in the span. Note that intervals stored in the tree must have unique id values
    59  // within the tree.
    60  func DescribeTree(it *interval.IntTree, fn func(t int, λₜ []int)) {
    61  	if it == nil || it.Len() == 0 {
    62  		return
    63  	}
    64  	var (
    65  		h    endHeap
    66  		t    = it.Root.Range.Start
    67  		end  = it.Root.Range.End
    68  		last = it.Max().ID()
    69  		l    []int
    70  	)
    71  	it.Do(func(iv interval.IntInterface) (done bool) {
    72  		if s := iv.Range().Start; s >= t || iv.ID() == last {
    73  			if iv.ID() == last {
    74  				heap.Push(&h, iv)
    75  				s, iv = iv.Range().End, nil
    76  			}
    77  			for ; t < s; t++ {
    78  				for len(h) > 0 && h[0].Range().End <= t {
    79  					heap.Pop(&h)
    80  					l = append(l, 0)
    81  				}
    82  				for _, iv := range h {
    83  					r := iv.Range()
    84  					if r.Start == t {
    85  						l = append(l, 0)
    86  					}
    87  					if v := max(0, min(t-r.Start, r.End-t)); v > 0 {
    88  						l = append(l, v)
    89  					}
    90  				}
    91  				sort.Ints(l)
    92  				reverse(l)
    93  				fn(t, l)
    94  				l = l[:0]
    95  			}
    96  		}
    97  		if iv != nil {
    98  			heap.Push(&h, iv)
    99  		} else {
   100  			for ; t <= end; t++ {
   101  				for len(h) > 0 && h[0].Range().End <= t {
   102  					heap.Pop(&h)
   103  					l = append(l, 0)
   104  				}
   105  				for _, iv := range h {
   106  					r := iv.Range()
   107  					if r.Start == t {
   108  						l = append(l, 0)
   109  					}
   110  					if v := max(0, min(t-r.Start, r.End-t)); v > 0 {
   111  						l = append(l, v)
   112  					}
   113  				}
   114  				sort.Ints(l)
   115  				reverse(l)
   116  				fn(t, l)
   117  				l = l[:0]
   118  			}
   119  		}
   120  		return
   121  	})
   122  }
   123  
   124  // The landscape Interface allows arbitrary collections to be described as a
   125  // persistence landscape.
   126  type Interface interface {
   127  	sort.Interface
   128  	Item(int) interval.IntRange
   129  }
   130  
   131  // Describe calculates the persistence landscape functions λₖ for the interval
   132  // data in the provided Interface. fn is called for each position t of the span
   133  // of the interval data with the values for t and the k λ functions at t.
   134  // Explicit zero values for a λₖ(t) are included only at the end points of intervals
   135  // in the span.
   136  func Describe(data Interface, fn func(t int, λₜ []int)) {
   137  	if data == nil || data.Len() == 0 {
   138  		return
   139  	}
   140  	sort.Sort(data)
   141  	var (
   142  		h   endRangeHeap
   143  		iv  = data.Item(0)
   144  		t   = iv.Start
   145  		end = iv.End
   146  		l   []int
   147  	)
   148  	for i := 0; i < data.Len(); i++ {
   149  		iv = data.Item(i)
   150  		if iv.End > end {
   151  			end = iv.End
   152  		}
   153  		if s := iv.Start; s >= t || i == data.Len()-1 {
   154  			if i == data.Len()-1 {
   155  				heap.Push(&h, iv)
   156  				s = iv.End
   157  			}
   158  			for ; t < s; t++ {
   159  				for len(h) > 0 && h[0].End <= t {
   160  					heap.Pop(&h)
   161  					l = append(l, 0)
   162  				}
   163  				for _, iv := range h {
   164  					if iv.Start == t {
   165  						l = append(l, 0)
   166  					}
   167  					if v := max(0, min(t-iv.Start, iv.End-t)); v > 0 {
   168  						l = append(l, v)
   169  					}
   170  				}
   171  				sort.Ints(l)
   172  				reverse(l)
   173  				fn(t, l)
   174  				l = l[:0]
   175  			}
   176  		}
   177  		if i != data.Len()-1 {
   178  			heap.Push(&h, iv)
   179  		} else {
   180  			for ; t <= end; t++ {
   181  				for len(h) > 0 && h[0].End <= t {
   182  					heap.Pop(&h)
   183  					l = append(l, 0)
   184  				}
   185  				for _, iv := range h {
   186  					if iv.Start == t {
   187  						l = append(l, 0)
   188  					}
   189  					if v := max(0, min(t-iv.Start, iv.End-t)); v > 0 {
   190  						l = append(l, v)
   191  					}
   192  				}
   193  				sort.Ints(l)
   194  				reverse(l)
   195  				fn(t, l)
   196  				l = l[:0]
   197  			}
   198  		}
   199  	}
   200  }