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 }