@apollo-annotation/shared 0.1.18 → 0.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (157) hide show
  1. package/dist/Changes/AddAssemblyAndFeaturesFromFileChange.d.ts +33 -0
  2. package/dist/Changes/AddAssemblyAndFeaturesFromFileChange.js +83 -0
  3. package/dist/Changes/AddAssemblyAndFeaturesFromFileChange.js.map +1 -0
  4. package/dist/Changes/AddAssemblyFromExternalChange.d.ts +34 -0
  5. package/dist/Changes/AddAssemblyFromExternalChange.js +97 -0
  6. package/dist/Changes/AddAssemblyFromExternalChange.js.map +1 -0
  7. package/dist/Changes/AddAssemblyFromFileChange.d.ts +43 -0
  8. package/dist/Changes/AddAssemblyFromFileChange.js +140 -0
  9. package/dist/Changes/AddAssemblyFromFileChange.js.map +1 -0
  10. package/dist/Changes/AddFeatureChange.d.ts +35 -0
  11. package/dist/Changes/AddFeatureChange.js +169 -0
  12. package/dist/Changes/AddFeatureChange.js.map +1 -0
  13. package/dist/Changes/AddFeaturesFromFileChange.d.ts +32 -0
  14. package/dist/Changes/AddFeaturesFromFileChange.js +76 -0
  15. package/dist/Changes/AddFeaturesFromFileChange.js.map +1 -0
  16. package/dist/Changes/AddRefSeqAliasesChange.d.ts +20 -0
  17. package/dist/Changes/AddRefSeqAliasesChange.js +61 -0
  18. package/dist/Changes/AddRefSeqAliasesChange.js.map +1 -0
  19. package/dist/Changes/DeleteAssemblyChange.d.ts +18 -0
  20. package/dist/Changes/DeleteAssemblyChange.js +72 -0
  21. package/dist/Changes/DeleteAssemblyChange.js.map +1 -0
  22. package/dist/Changes/DeleteFeatureChange.d.ts +42 -0
  23. package/dist/Changes/DeleteFeatureChange.js +143 -0
  24. package/dist/Changes/DeleteFeatureChange.js.map +1 -0
  25. package/dist/Changes/DeleteUserChange.d.ts +25 -0
  26. package/dist/Changes/DeleteUserChange.js +53 -0
  27. package/dist/Changes/DeleteUserChange.js.map +1 -0
  28. package/dist/Changes/FeatureAttributeChange.d.ts +31 -0
  29. package/dist/Changes/FeatureAttributeChange.js +112 -0
  30. package/dist/Changes/FeatureAttributeChange.js.map +1 -0
  31. package/dist/Changes/FromFileBaseChange.d.ts +9 -0
  32. package/dist/Changes/FromFileBaseChange.js +187 -0
  33. package/dist/Changes/FromFileBaseChange.js.map +1 -0
  34. package/dist/Changes/ImportJBrowseConfigChange.d.ts +43 -0
  35. package/dist/Changes/ImportJBrowseConfigChange.js +67 -0
  36. package/dist/Changes/ImportJBrowseConfigChange.js.map +1 -0
  37. package/dist/Changes/LocationEndChange.d.ts +32 -0
  38. package/dist/Changes/LocationEndChange.js +129 -0
  39. package/dist/Changes/LocationEndChange.js.map +1 -0
  40. package/dist/Changes/LocationStartChange.d.ts +32 -0
  41. package/dist/Changes/LocationStartChange.js +129 -0
  42. package/dist/Changes/LocationStartChange.js.map +1 -0
  43. package/dist/Changes/StrandChange.d.ts +31 -0
  44. package/dist/Changes/StrandChange.js +114 -0
  45. package/dist/Changes/StrandChange.js.map +1 -0
  46. package/dist/Changes/TypeChange.d.ts +31 -0
  47. package/dist/Changes/TypeChange.js +114 -0
  48. package/dist/Changes/TypeChange.js.map +1 -0
  49. package/dist/Changes/UserChange.d.ts +25 -0
  50. package/dist/Changes/UserChange.js +51 -0
  51. package/dist/Changes/UserChange.js.map +1 -0
  52. package/dist/Changes/index.d.ts +50 -0
  53. package/dist/Changes/index.js +55 -0
  54. package/dist/Changes/index.js.map +1 -0
  55. package/dist/Checks/CDSCheck.d.ts +8 -0
  56. package/dist/Checks/CDSCheck.js +197 -0
  57. package/dist/Checks/CDSCheck.js.map +1 -0
  58. package/dist/Checks/index.d.ts +1 -0
  59. package/dist/Checks/index.js +5 -0
  60. package/dist/Checks/index.js.map +1 -0
  61. package/dist/Common/index.d.ts +1 -0
  62. package/dist/Common/index.js +5 -0
  63. package/dist/Common/index.js.map +1 -0
  64. package/dist/Common/jwtPayload.d.ts +12 -0
  65. package/dist/Common/jwtPayload.js +16 -0
  66. package/dist/Common/jwtPayload.js.map +1 -0
  67. package/dist/GFF3/gff3ToAnnotationFeature.d.ts +3 -0
  68. package/dist/GFF3/gff3ToAnnotationFeature.js +211 -0
  69. package/dist/GFF3/gff3ToAnnotationFeature.js.map +1 -0
  70. package/dist/GFF3/gff3ToAnnotationFeature.test.d.ts +1 -0
  71. package/dist/GFF3/gff3ToAnnotationFeature.test.js +174 -0
  72. package/dist/GFF3/gff3ToAnnotationFeature.test.js.map +1 -0
  73. package/dist/GFF3/gffReservedKeys.d.ts +5 -0
  74. package/dist/GFF3/gffReservedKeys.js +34 -0
  75. package/dist/GFF3/gffReservedKeys.js.map +1 -0
  76. package/dist/GFF3/index.d.ts +2 -0
  77. package/dist/GFF3/index.js +6 -0
  78. package/dist/GFF3/index.js.map +1 -0
  79. package/dist/Messages.d.ts +28 -0
  80. package/dist/Messages.js +3 -0
  81. package/dist/Messages.js.map +1 -0
  82. package/dist/Operations/GetAssembliesOperation.d.ts +13 -0
  83. package/dist/Operations/GetAssembliesOperation.js +20 -0
  84. package/dist/Operations/GetAssembliesOperation.js.map +1 -0
  85. package/dist/Operations/GetFeaturesOperation.d.ts +26 -0
  86. package/dist/Operations/GetFeaturesOperation.js +42 -0
  87. package/dist/Operations/GetFeaturesOperation.js.map +1 -0
  88. package/dist/Operations/index.d.ts +8 -0
  89. package/dist/Operations/index.js +10 -0
  90. package/dist/Operations/index.js.map +1 -0
  91. package/dist/Validations/CoreValidation.d.ts +17 -0
  92. package/dist/Validations/CoreValidation.js +36 -0
  93. package/dist/Validations/CoreValidation.js.map +1 -0
  94. package/dist/Validations/ParentChildValidation.d.ts +17 -0
  95. package/dist/Validations/ParentChildValidation.js +61 -0
  96. package/dist/Validations/ParentChildValidation.js.map +1 -0
  97. package/dist/Validations/Validation.d.ts +27 -0
  98. package/dist/Validations/Validation.js +27 -0
  99. package/dist/Validations/Validation.js.map +1 -0
  100. package/dist/Validations/ValidationSet.d.ts +24 -0
  101. package/dist/Validations/ValidationSet.js +86 -0
  102. package/dist/Validations/ValidationSet.js.map +1 -0
  103. package/dist/Validations/index.d.ts +4 -0
  104. package/dist/Validations/index.js +8 -0
  105. package/dist/Validations/index.js.map +1 -0
  106. package/dist/Validations/soSequenceTypes.d.ts +2 -0
  107. package/dist/Validations/soSequenceTypes.js +1868 -0
  108. package/dist/Validations/soSequenceTypes.js.map +1 -0
  109. package/dist/index.d.ts +8 -0
  110. package/dist/index.js +12 -0
  111. package/dist/index.js.map +1 -0
  112. package/dist/tsconfig.tsbuildinfo +1 -0
  113. package/dist/util.d.ts +4 -0
  114. package/dist/util.js +102 -0
  115. package/dist/util.js.map +1 -0
  116. package/package.json +17 -8
  117. package/src/Changes/AddAssemblyAndFeaturesFromFileChange.ts +13 -9
  118. package/src/Changes/AddAssemblyFromFileChange.ts +129 -43
  119. package/src/Changes/AddFeatureChange.ts +2 -3
  120. package/src/Changes/AddFeaturesFromFileChange.ts +8 -3
  121. package/src/Changes/AddRefSeqAliasesChange.ts +88 -0
  122. package/src/Changes/DeleteAssemblyChange.ts +1 -1
  123. package/src/Changes/DeleteFeatureChange.ts +1 -1
  124. package/src/Changes/FeatureAttributeChange.ts +1 -1
  125. package/src/Changes/FromFileBaseChange.ts +221 -0
  126. package/src/Changes/ImportJBrowseConfigChange.ts +116 -0
  127. package/src/Changes/LocationEndChange.ts +25 -18
  128. package/src/Changes/LocationStartChange.ts +25 -18
  129. package/src/Changes/TypeChange.ts +1 -1
  130. package/src/Changes/index.ts +6 -6
  131. package/src/Checks/CDSCheck.ts +125 -173
  132. package/src/Common/jwtPayload.ts +1 -1
  133. package/src/GFF3/gff3ToAnnotationFeature.test.ts +209 -0
  134. package/src/GFF3/gff3ToAnnotationFeature.ts +257 -0
  135. package/src/GFF3/gffReservedKeys.ts +61 -0
  136. package/src/GFF3/index.ts +2 -0
  137. package/src/Operations/GetFeaturesOperation.ts +2 -2
  138. package/src/Validations/ParentChildValidation.ts +5 -5
  139. package/src/index.ts +1 -0
  140. package/src/util.ts +16 -12
  141. package/test_data/braker.gff +13 -0
  142. package/test_data/example01.gff3 +26 -0
  143. package/test_data/example01.json +236 -0
  144. package/test_data/example02.json +225 -0
  145. package/test_data/example04.json +225 -0
  146. package/test_data/example05.gff3 +30 -0
  147. package/test_data/example06.gff3 +30 -0
  148. package/test_data/example07.gff3 +30 -0
  149. package/test_data/gene_mrna.gff3 +4 -0
  150. package/test_data/gene_representations.gff3 +1781 -0
  151. package/test_data/one_cds.gff3 +9 -0
  152. package/test_data/one_cds.json +67 -0
  153. package/test_data/two_cds.gff3 +9 -0
  154. package/test_data/two_cds.json +67 -0
  155. package/tsconfig.json +4 -4
  156. package/src/Changes/DiscontinuousLocationEndChange.ts +0 -182
  157. package/src/Changes/DiscontinuousLocationStartChange.ts +0 -182
@@ -0,0 +1,257 @@
1
+ import { AnnotationFeatureSnapshot } from '@apollo-annotation/mst'
2
+ import { GFF3Feature, GFF3FeatureLineWithRefs } from '@gmod/gff'
3
+ import { doesIntersect2 } from '@jbrowse/core/util'
4
+ import ObjectID from 'bson-objectid'
5
+
6
+ import { gffToInternal, isGFFReservedAttribute } from './gffReservedKeys'
7
+
8
+ export function gff3ToAnnotationFeature(
9
+ gff3Feature: GFF3Feature,
10
+ refSeq?: string,
11
+ featureIds?: string[],
12
+ ): AnnotationFeatureSnapshot {
13
+ const [firstFeature] = gff3Feature
14
+ const { end, seq_id: refName, start, strand, type } = firstFeature
15
+ if (!refName) {
16
+ throw new Error(
17
+ `feature does not have seq_id: ${JSON.stringify(firstFeature)}`,
18
+ )
19
+ }
20
+ if (!type) {
21
+ throw new Error(
22
+ `feature does not have type: ${JSON.stringify(firstFeature)}`,
23
+ )
24
+ }
25
+ if (start === null) {
26
+ throw new Error(
27
+ `feature does not have start: ${JSON.stringify(firstFeature)}`,
28
+ )
29
+ }
30
+ if (end === null) {
31
+ throw new Error(
32
+ `feature does not have end: ${JSON.stringify(firstFeature)}`,
33
+ )
34
+ }
35
+
36
+ const [min, max] = getFeatureMinMax(gff3Feature)
37
+
38
+ const convertedChildren = convertChildren(gff3Feature, refSeq, featureIds)
39
+
40
+ const convertedAttributes = convertFeatureAttributes(gff3Feature)
41
+
42
+ const feature: AnnotationFeatureSnapshot = {
43
+ _id: new ObjectID().toHexString(),
44
+ refSeq: refSeq ?? refName,
45
+ type,
46
+ min,
47
+ max,
48
+ }
49
+ if (strand) {
50
+ if (strand === '+') {
51
+ feature.strand = 1
52
+ } else if (strand === '-') {
53
+ feature.strand = -1
54
+ } else {
55
+ throw new Error(`Unknown strand: "${strand}"`)
56
+ }
57
+ }
58
+ if (convertedChildren) {
59
+ feature.children = convertedChildren
60
+ }
61
+ if (convertedAttributes) {
62
+ feature.attributes = convertedAttributes
63
+ }
64
+ if (featureIds) {
65
+ featureIds.push(feature._id)
66
+ }
67
+ return feature
68
+ }
69
+
70
+ function getFeatureMinMax(gff3Feature: GFF3Feature): [number, number] {
71
+ if (gff3Feature.length > 1 && !gff3Feature.every((f) => f.type === 'CDS')) {
72
+ throw new Error('GFF3 features has multiple locations but is not a CDS')
73
+ }
74
+ const mins = gff3Feature.map((f) => f.start).filter((m) => m !== null)
75
+ const maxes = gff3Feature.map((f) => f.end).filter((m) => m !== null)
76
+ const min = Math.min(...mins)
77
+ const max = Math.max(...maxes)
78
+ return [min - 1, max]
79
+ }
80
+
81
+ function convertFeatureAttributes(
82
+ gff3Feature: GFF3Feature,
83
+ ): Record<string, string[] | undefined> | undefined {
84
+ const convertedAttributes: Record<string, string[] | undefined> | undefined =
85
+ {}
86
+ const scores = gff3Feature
87
+ .map((f) => f.score)
88
+ .filter((score) => score !== null)
89
+ const sources = gff3Feature
90
+ .map((f) => f.source)
91
+ .filter((source) => source !== null)
92
+ const attributesCollections = gff3Feature
93
+ .map((f) => f.attributes)
94
+ .filter((attributes) => attributes !== null)
95
+ if (scores.length > 0) {
96
+ let [score] = scores
97
+ if (scores.length > 1) {
98
+ const scoresSum = scores.reduce(
99
+ (accumulator, currentValue) => accumulator + currentValue,
100
+ 0,
101
+ )
102
+ // Average score
103
+ score = scoresSum / scores.length
104
+ }
105
+ convertedAttributes.gff_score = [String(score)]
106
+ }
107
+ if (sources.length > 0) {
108
+ let [source] = sources
109
+ if (sources.length > 1) {
110
+ const sourceSet = new Set(sources)
111
+ source = [...sourceSet].join(',')
112
+ }
113
+ convertedAttributes.gff_source = [source]
114
+ }
115
+ if (attributesCollections.length > 0) {
116
+ for (const attributesCollection of attributesCollections) {
117
+ for (const [key, val] of Object.entries(attributesCollection)) {
118
+ if (!val || key === 'Parent') {
119
+ continue
120
+ }
121
+ const newKey = isGFFReservedAttribute(key) ? gffToInternal[key] : key
122
+ const existingVal = convertedAttributes[newKey]
123
+ if (existingVal) {
124
+ const valSet = new Set([...existingVal, ...val])
125
+ convertedAttributes[newKey] = [...valSet]
126
+ } else {
127
+ convertedAttributes[newKey] = val
128
+ }
129
+ }
130
+ }
131
+ }
132
+ if (Object.keys(convertedAttributes).length > 0) {
133
+ return convertedAttributes
134
+ }
135
+ return
136
+ }
137
+
138
+ function convertChildren(
139
+ gff3Feature: GFF3Feature,
140
+ refSeq?: string,
141
+ featureIds?: string[],
142
+ ): Record<string, AnnotationFeatureSnapshot> | undefined {
143
+ const convertedChildren: Record<string, AnnotationFeatureSnapshot> = {}
144
+ const locationsWithChildren = gff3Feature.filter(
145
+ (feature) => feature.child_features.length > 0,
146
+ )
147
+ if (locationsWithChildren.length > 1) {
148
+ throw new Error('Features with multiple locations may not have children')
149
+ }
150
+ if (locationsWithChildren.length === 0) {
151
+ return
152
+ }
153
+ const [firstFeature] = locationsWithChildren
154
+ const { child_features: childFeatures } = firstFeature
155
+
156
+ const cdsFeatures: GFF3Feature[] = []
157
+ for (const childFeature of childFeatures) {
158
+ const [firstChildFeatureLocation] = childFeature
159
+ if (
160
+ firstChildFeatureLocation.type === 'three_prime_UTR' ||
161
+ firstChildFeatureLocation.type === 'five_prime_UTR' ||
162
+ firstChildFeatureLocation.type === 'intron' ||
163
+ firstChildFeatureLocation.type === 'start_codon' ||
164
+ firstChildFeatureLocation.type === 'stop_codon'
165
+ ) {
166
+ continue
167
+ }
168
+ if (firstChildFeatureLocation.type === 'CDS') {
169
+ cdsFeatures.push(childFeature)
170
+ } else {
171
+ const child = gff3ToAnnotationFeature(childFeature, refSeq, featureIds)
172
+ convertedChildren[child._id] = child
173
+ }
174
+ }
175
+ const processedCDS =
176
+ cdsFeatures.length > 0 ? processCDS(cdsFeatures, refSeq, featureIds) : []
177
+ for (const cds of processedCDS) {
178
+ convertedChildren[cds._id] = cds
179
+ }
180
+
181
+ if (Object.keys(convertedChildren).length > 0) {
182
+ return convertedChildren
183
+ }
184
+ return
185
+ }
186
+
187
+ /**
188
+ * If a GFF3 file has CDS features that either (1) don't have an ID or (2) have
189
+ * different IDs for each CDS, we have to do a bit of guessing about how they
190
+ * should be represented in our internal structure
191
+ * @param cdsFeatures -
192
+ */
193
+ function processCDS(
194
+ cdsFeatures: GFF3Feature[],
195
+ refSeq?: string,
196
+ featureIds?: string[],
197
+ ): AnnotationFeatureSnapshot[] {
198
+ const locationCounts = cdsFeatures.map((cds) => cds.length)
199
+ // If any CDS have multiple locations, assume it really is multiple CDS
200
+ // (e.g. the mRNA has multiple alternative translational start sites)
201
+ // and process normally.
202
+ if (locationCounts.some((count) => count > 1)) {
203
+ return cdsFeatures.map((cds) =>
204
+ gff3ToAnnotationFeature(cds, refSeq, featureIds),
205
+ )
206
+ }
207
+ // If all CDS have a single location, we guess that this GFF3 represented CDS
208
+ // as multiple features instead of a single feature with multiple locations.
209
+ // To figure out if it's actually representing one vs. multiple CDS features,
210
+ // first check to see if any of the CDS overlap
211
+ const sortedCDSLocations = cdsFeatures
212
+ .map((cds) => cds[0])
213
+ .filter((cds) => cds.start !== null && cds.end !== null)
214
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
215
+ .sort((cdsA, cdsB) => cdsA.start! - cdsB.start!)
216
+ const overlapping = sortedCDSLocations.some((loc, idx) => {
217
+ const nextLoc = sortedCDSLocations.at(idx + 1)
218
+ if (!nextLoc) {
219
+ return false
220
+ }
221
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
222
+ return doesIntersect2(loc.start!, loc.end!, nextLoc.start!, nextLoc.end!)
223
+ })
224
+ // If no overlaps, assume it's a single CDS feature
225
+ if (!overlapping) {
226
+ return [gff3ToAnnotationFeature(sortedCDSLocations, refSeq, featureIds)]
227
+ }
228
+ // Some CDS locations overlap, the best we can do is use the original order to
229
+ // guess how to group the locations into features
230
+ const cdsLocations = cdsFeatures.map((cds) => cds[0])
231
+ const groupedLocations: GFF3FeatureLineWithRefs[][] = []
232
+ for (const location of cdsLocations) {
233
+ const lastGroup = groupedLocations.at(-1)
234
+ if (!lastGroup) {
235
+ groupedLocations.push([location])
236
+ continue
237
+ }
238
+ const overlaps = lastGroup.some((lastGroupLoc) =>
239
+ doesIntersect2(
240
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
241
+ lastGroupLoc.start!,
242
+ lastGroupLoc.end!,
243
+ location.start!,
244
+ location.end!,
245
+ /* eslint-enable @typescript-eslint/no-non-null-assertion */
246
+ ),
247
+ )
248
+ if (overlaps) {
249
+ groupedLocations.push([location])
250
+ } else {
251
+ lastGroup.push(location)
252
+ }
253
+ }
254
+ return groupedLocations.map((group) =>
255
+ gff3ToAnnotationFeature(group, refSeq, featureIds),
256
+ )
257
+ }
@@ -0,0 +1,61 @@
1
+ export type GFFReservedAttribute =
2
+ | 'ID'
3
+ | 'Name'
4
+ | 'Alias'
5
+ | 'Parent'
6
+ | 'Target'
7
+ | 'Gap'
8
+ | 'Derives_from'
9
+ | 'Note'
10
+ | 'Dbxref'
11
+ | 'Ontology_term'
12
+ | 'Is_circular'
13
+
14
+ export type GFFInternalAttribute =
15
+ | 'gff_id'
16
+ | 'gff_name'
17
+ | 'gff_alias'
18
+ | 'gff_parent'
19
+ | 'gff_target'
20
+ | 'gff_gap'
21
+ | 'gff_derives_from'
22
+ | 'gff_note'
23
+ | 'gff_dbxref'
24
+ | 'gff_ontology_term'
25
+ | 'gff_is_circular'
26
+
27
+ export const gffToInternal: Record<GFFReservedAttribute, GFFInternalAttribute> =
28
+ {
29
+ ID: 'gff_id',
30
+ Name: 'gff_name',
31
+ Alias: 'gff_alias',
32
+ Parent: 'gff_parent',
33
+ Target: 'gff_target',
34
+ Gap: 'gff_gap',
35
+ Derives_from: 'gff_derives_from',
36
+ Note: 'gff_note',
37
+ Dbxref: 'gff_dbxref',
38
+ Ontology_term: 'gff_ontology_term',
39
+ Is_circular: 'gff_is_circular',
40
+ }
41
+
42
+ export function isGFFReservedAttribute(
43
+ attribute: string,
44
+ ): attribute is GFFReservedAttribute {
45
+ return attribute in gffToInternal
46
+ }
47
+
48
+ export const internalToGFF: Record<GFFInternalAttribute, GFFReservedAttribute> =
49
+ {
50
+ gff_id: 'ID',
51
+ gff_name: 'Name',
52
+ gff_alias: 'Alias',
53
+ gff_parent: 'Parent',
54
+ gff_target: 'Target',
55
+ gff_gap: 'Gap',
56
+ gff_derives_from: 'Derives_from',
57
+ gff_note: 'Note',
58
+ gff_dbxref: 'Dbxref',
59
+ gff_ontology_term: 'Ontology_term',
60
+ gff_is_circular: 'Is_circular',
61
+ }
@@ -0,0 +1,2 @@
1
+ export * from './gffReservedKeys'
2
+ export * from './gff3ToAnnotationFeature'
@@ -45,8 +45,8 @@ export class GetFeaturesOperation extends Operation {
45
45
  return backend.featureModel
46
46
  .find({
47
47
  refSeq: this.refSeq,
48
- start: { $lte: this.end },
49
- end: { $gte: this.start },
48
+ min: { $lte: this.end },
49
+ max: { $gte: this.start },
50
50
  status: 0,
51
51
  })
52
52
  .exec()
@@ -72,11 +72,11 @@ export class ParentChildValidation extends Validation {
72
72
  }
73
73
  for (const [, childFeature] of feature.children || new Map()) {
74
74
  if (
75
- feature.start !== null &&
76
- feature.end !== null &&
77
- childFeature.start !== null &&
78
- childFeature.end !== null &&
79
- (childFeature.end > feature.end || childFeature.start < feature.start)
75
+ feature.min !== null &&
76
+ feature.max !== null &&
77
+ childFeature.min !== null &&
78
+ childFeature.max !== null &&
79
+ (childFeature.max > feature.max || childFeature.min < feature.min)
80
80
  ) {
81
81
  throw new Error(
82
82
  `Feature "${childFeature._id}" exceeds the bounds of its parent, "${feature._id}"`,
package/src/index.ts CHANGED
@@ -5,3 +5,4 @@ export * from './Common'
5
5
  export * from './Checks'
6
6
  export * from './util'
7
7
  export * from './Messages'
8
+ export * from './GFF3'
package/src/util.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  /* eslint-disable @typescript-eslint/no-unsafe-assignment */
2
+
2
3
  import { AnnotationFeatureSnapshot } from '@apollo-annotation/mst'
3
4
  import { GFF3Feature } from '@gmod/gff'
4
5
 
@@ -7,9 +8,10 @@ export function makeGFF3Feature(
7
8
  parentId?: string,
8
9
  refSeqNames?: Record<string, string | undefined>,
9
10
  ): GFF3Feature {
10
- const locations = feature.discontinuousLocations?.length
11
- ? feature.discontinuousLocations
12
- : [{ start: feature.start, end: feature.end, phase: feature.phase }]
11
+ const locations = [{ start: feature.min, end: feature.max }]
12
+ // const locations = feature.discontinuousLocations?.length
13
+ // ? feature.discontinuousLocations
14
+ // : [{ start: feature.start, end: feature.end, phase: feature.phase }]
13
15
  const attributes: Record<string, string[] | undefined> = JSON.parse(
14
16
  JSON.stringify(feature.attributes),
15
17
  )
@@ -76,16 +78,18 @@ export function makeGFF3Feature(
76
78
  seq_id: refSeqNames ? refSeqNames[feature.refSeq] ?? null : feature.refSeq,
77
79
  source,
78
80
  type: feature.type,
79
- score: feature.score ?? null,
81
+ score: null,
82
+ // score: feature.score ?? null,
80
83
  strand: feature.strand ? (feature.strand === 1 ? '+' : '-') : null,
81
- phase:
82
- location.phase === 0
83
- ? '0'
84
- : location.phase === 1
85
- ? '1'
86
- : location.phase === 2
87
- ? '2'
88
- : null,
84
+ phase: null,
85
+ // phase:
86
+ // location.phase === 0
87
+ // ? '0'
88
+ // : location.phase === 1
89
+ // ? '1'
90
+ // : location.phase === 2
91
+ // ? '2'
92
+ // : null,
89
93
  attributes: Object.keys(attributes).length > 0 ? attributes : null,
90
94
  derived_features: [],
91
95
  child_features: feature.children
@@ -0,0 +1,13 @@
1
+ ##gff-version 3
2
+ CM033580.1 AUGUSTUS gene 15529 16566 0.92 - . ID=g1;
3
+ CM033580.1 AUGUSTUS mRNA 15529 16566 0.92 - . ID=g1.t1;Parent=g1;
4
+ CM033580.1 AUGUSTUS stop_codon 15529 15531 . - 0 ID=g1.t1.stop1;Parent=g1.t1;
5
+ CM033580.1 AUGUSTUS CDS 15529 15659 0.92 - 2 ID=g1.t1.CDS1;Parent=g1.t1;
6
+ CM033580.1 AUGUSTUS exon 15529 15659 . - . ID=g1.t1.exon1;Parent=g1.t1;
7
+ CM033580.1 AUGUSTUS intron 15660 16112 0.96 - . ID=g1.t1.intron1;Parent=g1.t1;
8
+ CM033580.1 AUGUSTUS CDS 16113 16314 0.96 - 0 ID=g1.t1.CDS2;Parent=g1.t1;
9
+ CM033580.1 AUGUSTUS exon 16113 16314 . - . ID=g1.t1.exon2;Parent=g1.t1;
10
+ CM033580.1 AUGUSTUS intron 16315 16536 0.96 - . ID=g1.t1.intron2;Parent=g1.t1;
11
+ CM033580.1 AUGUSTUS CDS 16537 16566 0.99 - 0 ID=g1.t1.CDS3;Parent=g1.t1;
12
+ CM033580.1 AUGUSTUS exon 16537 16566 . - . ID=g1.t1.exon3;Parent=g1.t1;
13
+ CM033580.1 AUGUSTUS start_codon 16564 16566 . - 0 ID=g1.t1.start1;Parent=g1.t1;
@@ -0,0 +1,26 @@
1
+ ##gff-version 3
2
+ ##sequence-region chr1 1000 9000
3
+ #example01
4
+ chr1 . gene 1000 9000 . + . ID=gene10001;Name=EDEN
5
+ chr1 . TF_binding_site 1000 1012 . + . ID=tfbs10001;Parent=gene10001
6
+ chr1 . mRNA 1050 9000 . + . ID=mRNA10001;Parent=gene10001;Name=EDEN.1
7
+ chr1 . mRNA 1050 9000 . + . ID=mRNA10002;Parent=gene10001;Name=EDEN.2
8
+ chr1 . mRNA 1300 9000 . + . ID=mRNA10003;Parent=gene10001;Name=EDEN.3
9
+ chr1 . exon 1050 1500 . + . ID=exon10001;Parent=mRNA10001,mRNA10002
10
+ chr1 . exon 1300 1500 . + . ID=exon10002;Parent=mRNA10003
11
+ chr1 . exon 3000 3902 . + . ID=exon10003;Parent=mRNA10001,mRNA10003
12
+ chr1 . exon 5000 5500 . + . ID=exon10004;Parent=mRNA10001,mRNA10002,mRNA10003
13
+ chr1 . exon 7000 9000 . + . ID=exon10005;Parent=mRNA10001,mRNA10002,mRNA10003
14
+ chr1 . CDS 1201 1500 . + 0 ID=cds10001;Parent=mRNA10001;Name=edenprotein.1
15
+ chr1 . CDS 3000 3902 . + 0 ID=cds10001;Parent=mRNA10001;Name=edenprotein.1
16
+ chr1 . CDS 5000 5500 . + 0 ID=cds10001;Parent=mRNA10001;Name=edenprotein.1
17
+ chr1 . CDS 7000 7600 . + 0 ID=cds10001;Parent=mRNA10001;Name=edenprotein.1
18
+ chr1 . CDS 1201 1500 . + 0 ID=cds10002;Parent=mRNA10002;Name=edenprotein.2
19
+ chr1 . CDS 5000 5500 . + 0 ID=cds10002;Parent=mRNA10002;Name=edenprotein.2
20
+ chr1 . CDS 7000 7600 . + 0 ID=cds10002;Parent=mRNA10002;Name=edenprotein.2
21
+ chr1 . CDS 3301 3902 . + 0 ID=cds10003;Parent=mRNA10003;Name=edenprotein.3
22
+ chr1 . CDS 5000 5500 . + 1 ID=cds10003;Parent=mRNA10003;Name=edenprotein.3
23
+ chr1 . CDS 7000 7600 . + 1 ID=cds10003;Parent=mRNA10003;Name=edenprotein.3
24
+ chr1 . CDS 3391 3902 . + 0 ID=cds10004;Parent=mRNA10003;Name=edenprotein.4
25
+ chr1 . CDS 5000 5500 . + 1 ID=cds10004;Parent=mRNA10003;Name=edenprotein.4
26
+ chr1 . CDS 7000 7600 . + 1 ID=cds10004;Parent=mRNA10003;Name=edenprotein.4
@@ -0,0 +1,236 @@
1
+ {
2
+ "_id": "66e049f17b9cedae9ad89108",
3
+ "refSeq": "chr1",
4
+ "type": "gene",
5
+ "min": 999,
6
+ "max": 9000,
7
+ "strand": 1,
8
+ "children": {
9
+ "66e049f17b9cedae9ad890f5": {
10
+ "_id": "66e049f17b9cedae9ad890f5",
11
+ "refSeq": "chr1",
12
+ "type": "TF_binding_site",
13
+ "min": 999,
14
+ "max": 1012,
15
+ "strand": 1,
16
+ "attributes": {
17
+ "gff_id": ["tfbs10001"]
18
+ }
19
+ },
20
+ "66e049f17b9cedae9ad890fb": {
21
+ "_id": "66e049f17b9cedae9ad890fb",
22
+ "refSeq": "chr1",
23
+ "type": "mRNA",
24
+ "min": 1049,
25
+ "max": 9000,
26
+ "strand": 1,
27
+ "children": {
28
+ "66e049f17b9cedae9ad890f6": {
29
+ "_id": "66e049f17b9cedae9ad890f6",
30
+ "refSeq": "chr1",
31
+ "type": "exon",
32
+ "min": 1049,
33
+ "max": 1500,
34
+ "strand": 1,
35
+ "attributes": {
36
+ "gff_id": ["exon10002"]
37
+ }
38
+ },
39
+ "66e049f17b9cedae9ad890f7": {
40
+ "_id": "66e049f17b9cedae9ad890f7",
41
+ "refSeq": "chr1",
42
+ "type": "exon",
43
+ "min": 2999,
44
+ "max": 3902,
45
+ "strand": 1,
46
+ "attributes": {
47
+ "gff_id": ["exon10003"]
48
+ }
49
+ },
50
+ "66e049f17b9cedae9ad890f8": {
51
+ "_id": "66e049f17b9cedae9ad890f8",
52
+ "refSeq": "chr1",
53
+ "type": "exon",
54
+ "min": 4999,
55
+ "max": 5500,
56
+ "strand": 1,
57
+ "attributes": {
58
+ "gff_id": ["exon10004"]
59
+ }
60
+ },
61
+ "66e049f17b9cedae9ad890f9": {
62
+ "_id": "66e049f17b9cedae9ad890f9",
63
+ "refSeq": "chr1",
64
+ "type": "exon",
65
+ "min": 6999,
66
+ "max": 9000,
67
+ "strand": 1,
68
+ "attributes": {
69
+ "gff_id": ["exon10005"]
70
+ }
71
+ },
72
+ "66e049f17b9cedae9ad890fa": {
73
+ "_id": "66e049f17b9cedae9ad890fa",
74
+ "refSeq": "chr1",
75
+ "type": "CDS",
76
+ "min": 1200,
77
+ "max": 7600,
78
+ "strand": 1,
79
+ "attributes": {
80
+ "gff_id": ["cds10001"],
81
+ "gff_name": ["edenprotein.1"]
82
+ }
83
+ }
84
+ },
85
+ "attributes": {
86
+ "gff_id": ["mRNA10001"],
87
+ "gff_name": ["EDEN.1"]
88
+ }
89
+ },
90
+ "66e049f17b9cedae9ad89100": {
91
+ "_id": "66e049f17b9cedae9ad89100",
92
+ "refSeq": "chr1",
93
+ "type": "mRNA",
94
+ "min": 1049,
95
+ "max": 9000,
96
+ "strand": 1,
97
+ "children": {
98
+ "66e049f17b9cedae9ad890fc": {
99
+ "_id": "66e049f17b9cedae9ad890fc",
100
+ "refSeq": "chr1",
101
+ "type": "exon",
102
+ "min": 1049,
103
+ "max": 1500,
104
+ "strand": 1,
105
+ "attributes": {
106
+ "gff_id": ["exon10002"]
107
+ }
108
+ },
109
+ "66e049f17b9cedae9ad890fd": {
110
+ "_id": "66e049f17b9cedae9ad890fd",
111
+ "refSeq": "chr1",
112
+ "type": "exon",
113
+ "min": 4999,
114
+ "max": 5500,
115
+ "strand": 1,
116
+ "attributes": {
117
+ "gff_id": ["exon10004"]
118
+ }
119
+ },
120
+ "66e049f17b9cedae9ad890fe": {
121
+ "_id": "66e049f17b9cedae9ad890fe",
122
+ "refSeq": "chr1",
123
+ "type": "exon",
124
+ "min": 6999,
125
+ "max": 9000,
126
+ "strand": 1,
127
+ "attributes": {
128
+ "gff_id": ["exon10005"]
129
+ }
130
+ },
131
+ "66e049f17b9cedae9ad890ff": {
132
+ "_id": "66e049f17b9cedae9ad890ff",
133
+ "refSeq": "chr1",
134
+ "type": "CDS",
135
+ "min": 1200,
136
+ "max": 7600,
137
+ "strand": 1,
138
+ "attributes": {
139
+ "gff_id": ["cds10002"],
140
+ "gff_name": ["edenprotein.2"]
141
+ }
142
+ }
143
+ },
144
+ "attributes": {
145
+ "gff_id": ["mRNA10002"],
146
+ "gff_name": ["EDEN.2"]
147
+ }
148
+ },
149
+ "66e049f17b9cedae9ad89107": {
150
+ "_id": "66e049f17b9cedae9ad89107",
151
+ "refSeq": "chr1",
152
+ "type": "mRNA",
153
+ "min": 1299,
154
+ "max": 9000,
155
+ "strand": 1,
156
+ "children": {
157
+ "66e049f17b9cedae9ad89101": {
158
+ "_id": "66e049f17b9cedae9ad89101",
159
+ "refSeq": "chr1",
160
+ "type": "exon",
161
+ "min": 1299,
162
+ "max": 1500,
163
+ "strand": 1,
164
+ "attributes": {
165
+ "gff_id": ["exon10001"]
166
+ }
167
+ },
168
+ "66e049f17b9cedae9ad89102": {
169
+ "_id": "66e049f17b9cedae9ad89102",
170
+ "refSeq": "chr1",
171
+ "type": "exon",
172
+ "min": 2999,
173
+ "max": 3902,
174
+ "strand": 1,
175
+ "attributes": {
176
+ "gff_id": ["exon10003"]
177
+ }
178
+ },
179
+ "66e049f17b9cedae9ad89103": {
180
+ "_id": "66e049f17b9cedae9ad89103",
181
+ "refSeq": "chr1",
182
+ "type": "exon",
183
+ "min": 4999,
184
+ "max": 5500,
185
+ "strand": 1,
186
+ "attributes": {
187
+ "gff_id": ["exon10004"]
188
+ }
189
+ },
190
+ "66e049f17b9cedae9ad89104": {
191
+ "_id": "66e049f17b9cedae9ad89104",
192
+ "refSeq": "chr1",
193
+ "type": "exon",
194
+ "min": 6999,
195
+ "max": 9000,
196
+ "strand": 1,
197
+ "attributes": {
198
+ "gff_id": ["exon10005"]
199
+ }
200
+ },
201
+ "66e049f17b9cedae9ad89105": {
202
+ "_id": "66e049f17b9cedae9ad89105",
203
+ "refSeq": "chr1",
204
+ "type": "CDS",
205
+ "min": 3300,
206
+ "max": 7600,
207
+ "strand": 1,
208
+ "attributes": {
209
+ "gff_id": ["cds10003"],
210
+ "gff_name": ["edenprotein.3"]
211
+ }
212
+ },
213
+ "66e049f17b9cedae9ad89106": {
214
+ "_id": "66e049f17b9cedae9ad89106",
215
+ "refSeq": "chr1",
216
+ "type": "CDS",
217
+ "min": 3390,
218
+ "max": 7600,
219
+ "strand": 1,
220
+ "attributes": {
221
+ "gff_id": ["cds10004"],
222
+ "gff_name": ["edenprotein.4"]
223
+ }
224
+ }
225
+ },
226
+ "attributes": {
227
+ "gff_id": ["mRNA10003"],
228
+ "gff_name": ["EDEN.3"]
229
+ }
230
+ }
231
+ },
232
+ "attributes": {
233
+ "gff_id": ["gene10001"],
234
+ "gff_name": ["EDEN"]
235
+ }
236
+ }