github.com/biogo/biogo@v1.0.4/feat/feature.go (about) 1 // Copyright ©2012 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 feat provides the base for storage and manipulation of biological interval information. 6 package feat 7 8 type Conformationer interface { 9 Conformation() Conformation 10 SetConformation(Conformation) error 11 } 12 13 type Conformation int8 14 15 func (c Conformation) String() string { 16 switch c { 17 case UndefinedConformation: 18 return "undefined" 19 case Linear: 20 return "linear" 21 case Circular: 22 return "circular" 23 } 24 panic("feat: illegal conformation") 25 } 26 27 const ( 28 UndefinedConformation Conformation = iota - 1 29 Linear 30 Circular 31 ) 32 33 // Orienter wraps the Orientation method. 34 // 35 // Orientation returns the orientation of the feature relative to its location. 36 type Orienter interface { 37 Orientation() Orientation 38 } 39 40 type OrientSetter interface { 41 SetOrientation(Orientation) error 42 } 43 44 type Orientation int8 45 46 func (o Orientation) String() string { 47 switch o { 48 case Reverse: 49 return "reverse" 50 case NotOriented: 51 return "not oriented" 52 case Forward: 53 return "forward" 54 } 55 panic("feat: illegal orientation") 56 } 57 58 const ( 59 Reverse Orientation = iota - 1 60 NotOriented 61 Forward 62 ) 63 64 type Range interface { 65 Start() int 66 End() int 67 Len() int 68 } 69 70 // Feature is a Range whose coordinates are defined relative to a feature 71 // location. Start and End return the coordinates of the feature relative to 72 // its location which can be nil. In the latter case callers should make no 73 // assumptions whether coordinates of such features are comparable. 74 type Feature interface { 75 Range 76 // Name returns the name of the feature. 77 Name() string 78 // Description returns the description of the feature. 79 Description() string 80 // Location returns the reference feature on which the feature is located. 81 Location() Feature 82 } 83 84 type Offsetter interface { 85 SetOffset(int) error 86 } 87 88 type Mutable interface { 89 SetStart(int) error 90 SetEnd(int) error 91 } 92 93 type LocationSetter interface { 94 SetLocation(Feature) error 95 } 96 97 type Pair interface { 98 Features() [2]Feature 99 } 100 101 type Set interface { 102 Features() []Feature 103 } 104 105 type Adder interface { 106 Set 107 Add(...Feature) 108 } 109 110 type Collection interface { 111 Set 112 Location() Feature 113 } 114 115 // BasePositionOf returns the position in f coordinates converted to 116 // coordinates relative to the first nil feature location, and a reference 117 // which is the feature location preceding the nil. The returned reference 118 // feature should be used by callers of BasePositionOf to verify that 119 // coordinates are comparable. 120 // BasePositionOf will panic if the feature chain is deeper than 1000 links. 121 func BasePositionOf(f Feature, position int) (int, Feature) { 122 for n := 0; n < 1000; n++ { 123 position += f.Start() 124 if f.Location() != nil { 125 f = f.Location() 126 continue 127 } 128 return position, f 129 } 130 panic("feat: feature chain too long") 131 } 132 133 // PositionWithin returns the position in f coordinates converted to 134 // coordinates relative to the given reference feature and a boolean 135 // indicating whether f can be located relative to ref. 136 // PositionWithin will panic if the feature chain is deeper than 1000 links. 137 func PositionWithin(f, ref Feature, position int) (pos int, ok bool) { 138 for n := 0; n < 1000; n++ { 139 if f == ref { 140 return position, f != nil 141 } 142 position += f.Start() 143 if f.Location() != nil { 144 f = f.Location() 145 continue 146 } 147 return 0, false 148 } 149 panic("feat: feature chain too long") 150 } 151 152 // BaseOrientationOf returns the orientation of f relative to a reference 153 // which is the first non-nil, non-orientable feature location, and that 154 // reference feature. The returned reference feature should be used by callers 155 // of BaseOrientationOf to verify that orientations are comparable. If f is 156 // not orientable, the returned orientation will be NotOriented and the 157 // reference will be the first orientable or last non-nil feature. 158 // BaseOrientationOf will panic if the feature chain is deeper than 1000 links. 159 func BaseOrientationOf(f Feature) (ori Orientation, ref Feature) { 160 o, ok := f.(Orienter) 161 if !ok || o.Orientation() == NotOriented { 162 for n := 0; n < 1000; n++ { 163 if o, ok = f.Location().(Orienter); ok && o.Orientation() != NotOriented { 164 return NotOriented, f.Location() 165 } 166 if f.Location() == nil { 167 return NotOriented, f 168 } 169 f = f.Location() 170 } 171 panic("feat: feature chain too long") 172 } 173 174 ori = Forward 175 for n := 0; n < 1000; n++ { 176 ori *= o.Orientation() 177 if o, ok = f.Location().(Orienter); ok && o.Orientation() != NotOriented { 178 f = f.Location() 179 continue 180 } 181 if f.Location() != nil { 182 return ori, f.Location() 183 } 184 return ori, f 185 } 186 panic("feat: feature chain too long") 187 } 188 189 // OrientationWithin returns the orientation of f relative to the given 190 // reference feature. The returned orientation will be NotOriented if f is not 191 // located within the reference or if f is not orientable. 192 // OrientationWithin will panic if the feature chain is deeper than 1000 links. 193 func OrientationWithin(f, ref Feature) Orientation { 194 if ref == nil { 195 return NotOriented 196 } 197 ori := Forward 198 for n := 0; n < 1000; n++ { 199 o, ok := f.(Orienter) 200 if !ok { 201 return NotOriented 202 } 203 if o := o.Orientation(); o != NotOriented { 204 if f == ref { 205 return ori 206 } 207 ori *= o 208 f = f.Location() 209 if f == ref { 210 return ori 211 } 212 continue 213 } 214 return NotOriented 215 } 216 panic("feat: feature chain too long") 217 }