1 /* @source ajfeat *************************************************************
2 **
3 ** A genome feature (in AJAX program context) is a description of a
4 ** genomic entity which was determined by some 'source' analysis
5 ** (which may be of 'wet lab' experimental or 'in silico'
6 ** computational nature), has a 'primary' descriptor ('Primary_Tag'),
7 ** may have some 'score' asserting the level of analysis confidence in
8 ** its identity (e.g. log likelihood relative to a null hypothesis or
9 ** other similar entity), has a 'Position' in the genome, and may have
10 ** any arbitrary number of descriptor tags associated with it.
11 **
12 ** @author Copyright (C) 1999 Richard Bruskiewich
13 ** @version $Revision: 1.192 $
14 ** @modified 2000 Ian Longden.
15 ** @modified 2001 Peter Rice.
16 ** @modified $Date: 2013/06/29 22:31:59 $ by $Author: rice $
17 ** @@
18 **
19 ** This library is free software; you can redistribute it and/or
20 ** modify it under the terms of the GNU Lesser General Public
21 ** License as published by the Free Software Foundation; either
22 ** version 2.1 of the License, or (at your option) any later version.
23 **
24 ** This library is distributed in the hope that it will be useful,
25 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
26 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 ** Lesser General Public License for more details.
28 **
29 ** You should have received a copy of the GNU Lesser General Public
30 ** License along with this library; if not, write to the Free Software
31 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
32 ** MA 02110-1301, USA.
33 **
34 ** Implementation Notes:
35 **
36 ** see also the header file, ajfeat.h, for details on class structure.
37 **
38 ** FT6.2 todo alternate mandatory qualifiers /citation /compare
39 ** labelled with m/ in Efeatures.*
40 ** FT6.2 todo /compare special value accession.version
41 ** FT6.2 todo check spaces in /anticodon /codon and other special values
42 ** when used in practice
43 ** FT6.2 todo warning for /cons_splice with YES YES
44 ** FT6.2 todo list of db_xref databases from
45 ** http://www.ncbi.nlm.nih.gov/projects/collab/db_xref.html
46 ** FT6.2 todo list of /country country names from
47 ** http://www.ncbi.nlm.nih.gov/projects/collab/country.html
48 ** FT6.2 todo EC_number value check
49 ** FT6.2 todo /frequency value check 0.0 to 1.0
50 ** FT6.2 todo QWORD values with no spaces /translation /locus_tag
51 ** /old_locus_tag
52 ** FT6.2 todo vocab for mod_base ... rel_std*.dat Aug-09 has
53 ** 794 OTHER
54 ** 1475 p
55 ** 971 d
56 ** 331 m5c
57 ** 300 m1a
58 ** 260 t
59 ** 242 m7g
60 ** 241 m2g
61 ** 215 gm
62 ** 202 m1g
63 ** 186 m22g
64 ** 153 cm
65 ** 102 um
66 ** 93 t6a
67 ** 55 s4u
68 ** 52 i
69 ** 52 ac4c
70 ** 49 m1f
71 ** 48 m1i
72 ** 41 x
73 ** 41 i6a
74 ** 33 m3c
75 ** 31 ms2i6a
76 ** 31 m6a
77 ** 27 q
78 ** 22 m2a
79 ** 17 tm
80 ** 11 mt6a
81 ** 11 mcm5s2u
82 ** 8 yw
83 ** 6 s2t
84 ** 6 osyw
85 ** 6 fm
86 ** 6 cmnm5u
87 ** 5 s2c
88 ** 5 mam5s2u
89 ** 4 mo5u
90 ** 4 mcm5u
91 ** 3 o5u
92 ** 3 ms2t6a
93 **
94 ** FT6.2 todo *qualifier for non-standard qualifiers (for Artemis)
95 ******************************************************************************/
96
97 #include "ajlib.h"
98
99 #include "ajfeat.h"
100 #include "ajfeatread.h"
101 #include "ajfeatwrite.h"
102 #include "ajtagval.h"
103 #include "ajmath.h"
104 #include "ajlist.h"
105 #include "ajtable.h"
106 #include "ajutil.h"
107 #include "ajreg.h"
108 #include "ajsys.h"
109 #include "ajnam.h"
110 #include "ajseq.h"
111 #include "ajseqread.h"
112 #include "ajfiledata.h"
113 #include "ajfileio.h"
114
115 #define FEATDEBUG 0
116
117 static AjPRegexp featRegTagReplace = NULL;
118
119 static AjPRegexp featRegSpecialAnticodon = NULL;
120 static AjPRegexp featRegSpecialBiomaterial = NULL;
121 static AjPRegexp featRegSpecialCodon = NULL;
122 static AjPRegexp featRegSpecialCodonBad = NULL;
123 static AjPRegexp featRegSpecialColdate = NULL;
124 static AjPRegexp featRegSpecialCompare = NULL;
125 static AjPRegexp featRegSpecialConssplice = NULL;
126 static AjPRegexp featRegSpecialEstlen = NULL;
127 static AjPRegexp featRegSpecialInference = NULL;
128 static AjPRegexp featRegSpecialLatlon = NULL;
129 static AjPRegexp featRegSpecialMobile = NULL;
130 static AjPRegexp featRegSpecialPrimer = NULL;
131 static AjPRegexp featRegSpecialRptRange = NULL;
132 static AjPRegexp featRegSpecialRptRangeLab = NULL;
133 static AjPRegexp featRegSpecialRptRangeComp = NULL;
134 static AjPRegexp featRegSpecialRptunitSeq = NULL;
135 static AjPRegexp featRegSpecialRptunitSeqPos = NULL;
136 static AjPRegexp featRegSpecialTrans = NULL;
137 static AjPRegexp featRegSpecialTransBad = NULL;
138 static AjPRegexp featRegSpecialTransComp = NULL;
139 static AjPRegexp featRegSpecialTransBadComp = NULL;
140
141
142
143
144
145 static AjBool FeatInitDone = AJFALSE;
146 static AjPTable FeatTypeTableDna = NULL;
147 static AjPTable FeatTagsTableDna = NULL;
148 static AjPTable FeatTypeTableProtein = NULL;
149 static AjPTable FeatTagsTableProtein = NULL;
150
151 static AjPTable FeatTypeTableGff2 = NULL;
152 static AjPTable FeatTagsTableGff2 = NULL;
153 static AjPTable FeatTypeTableGff2protein = NULL;
154 static AjPTable FeatTagsTableGff2protein = NULL;
155
156 static AjPTable FeatTypeTableGff3 = NULL;
157 static AjPTable FeatTagsTableGff3 = NULL;
158 static AjPTable FeatTypeTableGff3protein = NULL;
159 static AjPTable FeatTagsTableGff3protein = NULL;
160
161 static AjPTable FeatTypeTableEmbl = NULL;
162 static AjPTable FeatTagsTableEmbl = NULL;
163
164 static AjPTable FeatTypeTablePir = NULL;
165 static AjPTable FeatTagsTablePir = NULL;
166
167 static AjPTable FeatTypeTableSwiss = NULL;
168 static AjPTable FeatTagsTableSwiss = NULL;
169
170 static AjPTable FeatTypeTableRefseqp = NULL;
171 static AjPTable FeatTagsTableRefseqp = NULL;
172
173 static AjPTable FeatCategoryTable = NULL;
174 static ajint featWarnCount = 0;
175
176 static AjPStr featTypeMiscfeat = NULL;
177 static AjPStr featTypeEmpty = NULL;
178 static AjPStr featDefSource = NULL;
179 static AjPStr featFmtTmp = NULL;
180 static AjPStr featTagTmp = NULL;
181 static AjPStr featTagTmp2 = NULL;
182 static AjPStr featValTmp = NULL;
183 static AjPStr featValTmp2 = NULL;
184 static AjPStr featTagNote = NULL;
185
186 static AjPStrTok featVocabSplit = NULL;
187
188 static AjPStr featTransBegStr = NULL;
189 static AjPStr featTransEndStr = NULL;
190 static AjPStr featTransAaStr = NULL;
191 static AjPStr featTmpStr = NULL;
192 static AjPStr featTempQry = NULL;
193
194
195 static const AjPTable featVocabInit(ajuint ivocab);
196 static void featClear(AjPFeature thys );
197 static AjBool featFeatType(const AjPStr line, AjPStr* type,
198 AjPStr* sofaid, AjPStr* tag, AjPStr* req);
199 static AjPFeature featFeatureNew(void);
200 static void featInit(void);
201 static void featTableInit(AjPFeattable thys,
202 const AjPStr name);
203 static AjPFeattable featTableNew(void);
204 static AjPFeattable featTableNewS(const AjPStr name);
205 static const AjPStr featTableTypeInternal(const AjPStr type,
206 const AjPTable table);
207 static const AjPStr featTableTypeInternalLimit(const AjPStr type,
208 const AjPTable table);
209 static const AjPStr featTagDna(const AjPStr type, AjBool* known);
210 static AjBool featTagGff3PredefinedTag(const AjPStr tag);
211 static AjBool featTagName(const AjPStr line, AjPStr* name, AjPStr* type,
212 AjPStr* rest);
213 static const AjPStr featTagProt(const AjPStr type, AjBool* known);
214 static void featTagSetDefault(AjPFeature thys,
215 const AjPStr tag, const AjPStr value,
216 AjPStr* pdeftag, AjPStr* pdefval);
217 static void featTagSetDefaultDna(const AjPStr tag, const AjPStr value,
218 AjPStr* pdeftag, AjPStr* pdefval);
219 static void featTagSetDefaultProt(const AjPStr tag,
220 const AjPStr value,
221 AjPStr* pdeftag, AjPStr* pdefval);
222 static AjBool featTagSpecialAllAnticodon(const AjPStr val);
223 static AjBool featTagSpecialAllBiomaterial(const AjPStr val);
224 static AjBool featTagSpecialAllCitation(const AjPStr val);
225 static AjBool featTagSpecialAllCodon(AjPStr* pval);
226 static AjBool featTagSpecialAllCollectiondate(const AjPStr pval);
227 static AjBool featTagSpecialAllConssplice(AjPStr* pval);
228 static AjBool featTagSpecialAllInference(const AjPStr pval);
229 static AjBool featTagSpecialAllLatlon(const AjPStr pval);
230 static AjBool featTagSpecialAllMobile(const AjPStr pval);
231 static AjBool featTagSpecialAllPcrprimers(const AjPStr pval);
232 static AjBool featTagSpecialAllRptunit(const AjPStr val);
233 static AjBool featTagSpecialAllRange(const AjPStr val);
234 static AjBool featTagSpecialAllRptunitseq(AjPStr *Pval);
235 static AjBool featTagSpecialAllTranslexcept(const AjPStr val);
236 static AjBool featTagSpecialAllDbxref(const AjPStr val);
237 static AjBool featTagSpecialAllProteinid(const AjPStr val);
238 static AjBool featTagSpecialAllReplace(AjPStr* pval);
239 static AjBool featTagSpecialAllTranslation(AjPStr* pval);
240 static AjBool featTagSpecialAllEstimatedlength(AjPStr* pval);
241 static AjBool featTagSpecialAllCompare(const AjPStr val);
242 static AjBool featTagSpecialAllNcrnaclass(const AjPStr val);
243 static AjPTagval featTagval(const AjPFeature thys, const AjPStr tag);
244 static AjPTagval featTagvalNew(const AjPFeature thys,
245 const AjPStr tag, const AjPStr value);
246 static AjPTagval featTagvalNewDna(const AjPStr tag, const AjPStr value);
247 static AjPTagval featTagvalNewProt(const AjPStr tag, const AjPStr value);
248 static const AjPStr featTypeDna(const AjPStr type);
249 static const AjPStr featTypeDnaLimit(const AjPStr type);
250 static const AjPStr featTypeProt(const AjPStr type);
251 static const AjPStr featTypeProtLimit(const AjPStr type);
252 static AjBool featVocabRead(const char *name,
253 AjPTable pTypeTable, AjPTable pTagsTable);
254 static AjBool featVocabReadTypes(const AjPStr fname,
255 AjPTable pTypeTable,
256 const AjPTable pTagsTable,
257 AjBool recursion);
258 static AjBool featVocabReadTags(const AjPStr fname,
259 AjPTable pTagsTable,
260 AjBool recursion);
261 static AjBool featTypeTestDnaWild(const AjPStr type, const AjPStr str);
262 static AjBool featTypeTestProtWild(const AjPStr type, const AjPStr str);
263 static AjBool featTableTypeTestWild(const AjPStr type,
264 const AjPTable table,
265 const AjPStr str);
266
267
268 static void feattableMakeQry(const AjPFeattable thys, AjPStr* qry);
269
270
271
272 /* @datastatic FeatPVocab *****************************************************
273 **
274 ** Feature vocabularies
275 **
276 ** @alias FeatSVocab
277 ** @alias FeatOVocab
278 **
279 ** @attr Name [const char*] Vocabulary name
280 ** @attr Truename [const char*] Vocabulary true name used for definition files
281 ** @attr Nucleotide [AjBool] True if suitable for nucleotide data
282 ** @attr Protein [AjBool] True if suitable for protein data
283 ** @attr Typetable [AjPTable*] Type table
284 ** @attr Tagstable [AjPTable*] Tags table
285 ** @attr Desc [const char*] Description
286 ** @attr Alias [AjBool] True if name is an alias for an identical definition
287 ** @attr Padding [ajint] Padding to alignment boundary
288 ** @@
289 ******************************************************************************/
290
291 typedef struct FeatSVocab
292 {
293 const char* Name;
294 const char* Truename;
295 AjBool Nucleotide;
296 AjBool Protein;
297 AjPTable* Typetable;
298 AjPTable* Tagstable;
299 const char* Desc;
300 AjBool Alias;
301 ajint Padding;
302 } FeatOVocab;
303
304 #define FeatPVocab FeatOVocab*
305
306
307
308
309 /* @funclist featVocabDef *****************************************************
310 **
311 ** Feature vocabularies
312 **
313 ** Includes pointers to the type and tag tables to be initialised
314 **
315 ******************************************************************************/
316
317 static FeatOVocab featVocabDef[] =
318 {
319 /* Name Truename Nucleotide Prot
320 Typetable Tagstable
321 Description Alias Padding */
322 {"gff3", "gff3", AJTRUE, AJFALSE,
323 &FeatTypeTableGff3, &FeatTagsTableGff3,
324 "GFF version 3", AJFALSE, 0},
325 {"gff3", "gff3protein", AJFALSE, AJTRUE,
326 &FeatTypeTableGff3protein, &FeatTagsTableGff3protein,
327 "GFF version 3", AJTRUE, 0},
328 {"gff", "gff3", AJTRUE, AJFALSE,
329 &FeatTypeTableGff3, &FeatTagsTableGff3,
330 "GFF version 3", AJFALSE, 0},
331 {"gff", "gff3protein", AJFALSE, AJTRUE,
332 &FeatTypeTableGff3protein, &FeatTagsTableGff3protein,
333 "GFF version 3", AJFALSE, 0},
334 {"gff2", "gff2", AJTRUE, AJFALSE,
335 &FeatTypeTableGff2, &FeatTagsTableGff2,
336 "GFF version 2", AJFALSE, 0},
337 {"gff2", "gff2protein", AJFALSE, AJTRUE,
338 &FeatTypeTableGff2protein, &FeatTagsTableGff2protein,
339 "GFF version 2", AJFALSE, 0},
340 {"embl", "embl", AJTRUE, AJFALSE,
341 &FeatTypeTableEmbl, &FeatTagsTableEmbl,
342 "embl format", AJFALSE, 0},
343 {"em", "embl", AJTRUE, AJFALSE,
344 &FeatTypeTableEmbl, &FeatTagsTableEmbl,
345 "embl format", AJTRUE, 0},
346 {"genbank", "embl", AJTRUE, AJFALSE,
347 &FeatTypeTableEmbl, &FeatTagsTableEmbl,
348 "genbank format", AJFALSE, 0},
349 {"gb", "embl", AJTRUE, AJFALSE,
350 &FeatTypeTableEmbl, &FeatTagsTableEmbl,
351 "genbank format", AJTRUE, 0},
352 {"ddbj", "embl", AJTRUE, AJFALSE,
353 &FeatTypeTableEmbl, &FeatTagsTableEmbl,
354 "ddbj format", AJFALSE, 0},
355 {"refseq", "embl", AJTRUE, AJFALSE,
356 &FeatTypeTableEmbl, &FeatTagsTableEmbl,
357 "genbank format", AJTRUE, 0},
358 {"refseqp", "refseqp", AJFALSE, AJTRUE,
359 &FeatTypeTableRefseqp, &FeatTagsTableRefseqp,
360 "genbank format", AJTRUE, 0},
361 {"pir", "pir", AJFALSE, AJTRUE,
362 &FeatTypeTablePir, &FeatTagsTablePir,
363 "PIR format", AJFALSE, 0},
364 {"nbrf", "pir", AJFALSE, AJTRUE,
365 &FeatTypeTablePir, &FeatTagsTablePir,
366 "PIR format", AJTRUE, 0},
367 {"sw", "swiss", AJFALSE, AJTRUE,
368 &FeatTypeTableSwiss, &FeatTagsTableSwiss,
369 "SwissProt format", AJTRUE, 0},
370 {"swissprot", "swiss", AJFALSE, AJTRUE,
371 &FeatTypeTableSwiss, &FeatTagsTableSwiss,
372 "SwissProt format", AJTRUE, 0},
373 {"dasgff", "gff3", AJTRUE, AJFALSE,
374 &FeatTypeTableGff3, &FeatTagsTableGff3,
375 "DAS GFF format", AJFALSE, 0},
376 {"dasgff", "gff3protein", AJFALSE, AJTRUE,
377 &FeatTypeTableGff3protein, &FeatTagsTableGff3protein,
378 "DAS GFF format", AJFALSE, 0},
379 {"debug", "emboss", AJTRUE, AJFALSE,
380 &FeatTypeTableDna, &FeatTagsTableDna,
381 "Debugging trace", AJFALSE, 0},
382 {"debug", "protein", AJFALSE, AJTRUE,
383 &FeatTypeTableProtein, &FeatTagsTableProtein,
384 "Debugging trace", AJFALSE, 0},
385 {NULL, NULL, AJFALSE, AJFALSE, NULL, NULL, NULL, AJFALSE, 0}
386 };
387
388 static FeatPVocab featVocab = featVocabDef;
389
390
391
392
393
394
395 /* @datastatic FeatPCategory **************************************************
396 **
397 ** Feature output types
398 **
399 ** @alias FeatSCategory
400 ** @alias FeatOCategory
401 **
402 ** @attr Name [const char*] Specified name
403 ** @attr Desc [const char*] Description
404 ** @attr Types [const char*] Internal type names in this category
405 ** @@
406 ******************************************************************************/
407
408 typedef struct FeatSCategory
409 {
410 const char* Name;
411 const char* Desc;
412 const char* Types;
413 } FeatOCategory;
414
415 #define FeatPCategory FeatOCategory*
416
417
418
419
420 static FeatOCategory featCategory[] =
421 {
422 {"other", "all other features",
423 "SO:2000061,SO:0000110,SO:0000723,SO:0000298,SO:0000724,SO:0000704,"
424 "SO:0000410,SO:0000409,SO:0000297,SO:0000313,SO:0005836_rep_origin"},
425 {"component", "component of a sequence assembly",
426 ""},
427 {"supercomponent", "reference sequence assembly",
428 ""},
429 {"translation", "translation to protein",
430 "SO:0000316,SO:0000419,SO:0000418,SO:0000725,"
431 "SO:0000204,SO:0000205,SO:0000139"},
432 {"transcription", "transcription of RNA",
433 "SO:0000147,SO:0000188,SO:0000673,SO:0005836,SO:0000234,SO:0000551,"
434 "SO:0000553,SO:0000185_precursor_RNA,SO:0000185,SO:0000252,"
435 "SO:0000013,SO:0000275,SO:0000274,SO:0000253,SO:0000557,SO:0000555"},
436 {"promoter", "promoter regions and regulation of transcription",
437 "SO:0000167,SO:0000172,SO:0000174,SO:0000178,SO:0000140,SO:0000173"
438 "SO:0000175,SO:0000176,SO:0000165,SO:0000141"},
439 {"variation", "polymorphic regions",
440 ""},
441 {"structural", "mapping, sequence and assembly - with no "
442 "biological information",
443 "SO:0005850,SO:0000002,SO:0000331,SO:0000730"},
444 {"similarity", "areas similar to other sequences",
445 ""},
446 {"repeat", "areas of repetitive sequence",
447 "SO:0000657,SO:0000726,SO:0000005,SO:0000286"},
448 {"experimental", "experimental results",
449 ""},
450 {"immunoglobulin", "immunoglobulin processing regions",
451 "SO:0000001_C_region,SO:0000001_J_segment,SO:0000001_N_region,"
452 "SO:0000001_S_region,SO:0000001_V_region,SO:0000001_V_segment,"
453 "SO:0000458"},
454 {NULL, NULL,
455 NULL}
456 };
457
458
459
460
461 /* ==================================================================== */
462 /* ========================= constructors ============================= */
463 /* ==================================================================== */
464
465
466
467
468 /* @section Feature Object Constructors ***************************************
469 **
470 ** All constructors return a new feature or feature table set by pointer.
471 ** It is the responsibility of the user to first destroy any previous feature.
472 ** The target pointer does not need to be initialised to NULL, but it is good
473 ** programming practice to do so anyway.
474 **
475 ** Generally, however, the AjPFeattable feature table object will first
476 ** be created, prior to creating any 'AjPFeature' objects and adding them.
477 **
478 ** To replace or reuse an existing feature object see instead
479 ** the {Feature Assignments} and {Feature Modifiers} methods.
480 **
481 ******************************************************************************/
482
483
484
485
486 /* @func ajFeatNew ************************************************************
487 **
488 ** Constructor - must specify associated 'ajFeattable'
489 ** to which the new feature is automatically added!
490 **
491 ** @param [u] thys [AjPFeattable] Pointer to the ajFeattable which
492 ** will own the feature
493 ** @param [r] source [const AjPStr] Analysis basis for feature
494 ** @param [r] type [const AjPStr] Type of feature (e.g. exon)
495 ** @param [r] Start [ajint] Start position of the feature
496 ** @param [r] End [ajint] End position of the feature
497 ** @param [r] score [float] Analysis score for the feature
498 ** @param [r] strand [char] Strand of the feature
499 ** @param [r] frame [ajint] Frame of the feature
500 ** @return [AjPFeature] newly allocated feature object
501 ** @category new [AjPFeature] Constructor - must specify the associated
502 ** (non-null) AjPFeattable
503 **
504 ** @release 2.0.0
505 ** @@
506 ******************************************************************************/
507
ajFeatNew(AjPFeattable thys,const AjPStr source,const AjPStr type,ajint Start,ajint End,float score,char strand,ajint frame)508 AjPFeature ajFeatNew(AjPFeattable thys,
509 const AjPStr source,
510 const AjPStr type,
511 ajint Start, ajint End,
512 float score,
513 char strand,
514 ajint frame)
515 {
516 ajuint flags = 0;
517 AjPFeature ret = NULL;
518
519 if(ajStrMatchC(thys->Type, "P"))
520 ret = ajFeatNewProtFlags(thys,source,type,Start,End,score,flags);
521 else
522 ret = ajFeatNewNucFlags(thys,source,type,Start,End,score,strand,frame,
523 0,0,0,NULL, NULL,flags);
524
525 return ret;
526 }
527
528
529
530
531 /* @func ajFeatNewBetween ******************************************************
532 **
533 ** Simple constructor with location between the start positions and
534 ** the previous base.
535 **
536 ** User must specify associated 'ajFeattable' to which the new feature
537 ** is automatically added!
538 **
539 ** @param [u] thys [AjPFeattable] Pointer to the ajFeattable which
540 ** will own the feature
541 ** @param [r] Start [ajint] Start position of the feature
542 ** @return [AjPFeature] newly allocated feature object
543 **
544 ** @release 6.5.0
545 ** @@
546 ******************************************************************************/
547
ajFeatNewBetween(AjPFeattable thys,ajint Start)548 AjPFeature ajFeatNewBetween(AjPFeattable thys,
549 ajint Start)
550 {
551 AjPStr source = NULL;
552 float score = 0.0;
553 char strand = '.';
554 ajint frame = 0;
555 ajint flags = AJFEATFLAG_BETWEEN_SEQ;
556
557 AjPFeature ret = NULL ;
558
559 /*ajDebug("ajFeatNewBetween %d\n", Start);*/
560
561 if(!featTypeMiscfeat)
562 featTypeMiscfeat = ajStrNewC("misc_feature");
563
564 ret = ajFeatNewNucFlags(thys,source,featTypeMiscfeat,
565 Start-1,Start,score,strand,frame,
566 0,0,0,NULL,NULL,flags);
567
568 return ret;
569 }
570
571
572
573
574 /* @func ajFeatNewSub *********************************************************
575 **
576 ** Constructor - must specify associated 'ajFeattable'
577 ** to which the new feature is automatically added!
578 **
579 ** @param [u] thys [AjPFeattable] Pointer to the ajFeattable which
580 ** will own the feature
581 ** @param [u] parent [AjPFeature] Parent feature
582 ** @param [r] source [const AjPStr] Analysis basis for feature
583 ** @param [r] type [const AjPStr] Type of feature (e.g. exon)
584 ** @param [r] Start [ajint] Start position of the feature
585 ** @param [r] End [ajint] End position of the feature
586 ** @param [r] score [float] Analysis score for the feature
587 ** @param [r] strand [char] Strand of the feature
588 ** @param [r] frame [ajint] Frame of the feature
589 ** @return [AjPFeature] newly allocated feature object
590 ** @category new [AjPFeature] Constructor - must specify the associated
591 ** (non-null) AjPFeattable
592 **
593 ** @release 6.4.0
594 ** @@
595 ******************************************************************************/
596
ajFeatNewSub(AjPFeattable thys,AjPFeature parent,const AjPStr source,const AjPStr type,ajint Start,ajint End,float score,char strand,ajint frame)597 AjPFeature ajFeatNewSub(AjPFeattable thys,
598 AjPFeature parent,
599 const AjPStr source,
600 const AjPStr type,
601 ajint Start, ajint End,
602 float score,
603 char strand,
604 ajint frame)
605 {
606 ajuint flags = 0;
607 AjPFeature ret = NULL;
608
609 if(ajStrMatchC(thys->Type, "P"))
610 ret = ajFeatNewProtFlagsSub(thys,parent,
611 source,type,Start,End,score,flags);
612 else
613 ret = ajFeatNewNucFlagsSub(thys,parent,
614 source,type,Start,End,score,strand,frame,
615 0,0,0,NULL, NULL,flags);
616
617 return ret;
618 }
619
620
621
622
623 /* @func ajFeatNewII **********************************************************
624 **
625 ** Simple constructor with only start and end positions
626 **
627 ** User must specify associated 'ajFeattable' to which the new feature
628 ** is automatically added!
629 **
630 ** @param [u] thys [AjPFeattable] Pointer to the ajFeattable which
631 ** will own the feature
632 ** @param [r] Start [ajint] Start position of the feature
633 ** @param [r] End [ajint] End position of the feature
634 ** @return [AjPFeature] newly allocated feature object
635 ** @category new [AjPFeature] Simple constructor with only start and end
636 ** positions
637 **
638 ** @release 2.1.0
639 ** @@
640 ******************************************************************************/
641
ajFeatNewII(AjPFeattable thys,ajint Start,ajint End)642 AjPFeature ajFeatNewII(AjPFeattable thys,
643 ajint Start, ajint End)
644 {
645 AjPStr source = NULL;
646 float score = 0.0;
647 char strand = '.';
648 ajint frame = 0;
649 ajint flags = 0;
650
651 AjPFeature ret = NULL ;
652
653 /*ajDebug("ajFeatNewII %d %d\n", Start, End);*/
654
655 if(!featTypeMiscfeat)
656 featTypeMiscfeat = ajStrNewC("misc_feature");
657
658 if(Start > End)
659 ret = ajFeatNewNucFlags(thys,source,featTypeMiscfeat,
660 End,Start,score,'-',frame,
661 0,0,0,NULL, NULL,flags);
662 else
663 ret = ajFeatNewNucFlags(thys,source,featTypeMiscfeat,
664 Start,End,score,strand,frame,
665 0,0,0,NULL, NULL,flags);
666
667 return ret;
668 }
669
670
671
672
673 /* @func ajFeatNewIISub *******************************************************
674 **
675 ** Simple constructor with only start and end positions
676 **
677 ** User must specify associated 'ajFeattable' to which the new feature
678 ** is automatically added!
679 **
680 ** @param [u] thys [AjPFeattable] Pointer to the ajFeattable which
681 ** will own the feature
682 ** @param [u] parent [AjPFeature] Parent feature
683 ** @param [r] Start [ajint] Start position of the feature
684 ** @param [r] End [ajint] End position of the feature
685 ** @return [AjPFeature] newly allocated feature object
686 ** @category new [AjPFeature] Simple constructor with only start and end
687 ** positions
688 **
689 ** @release 6.4.0
690 ** @@
691 ******************************************************************************/
692
ajFeatNewIISub(AjPFeattable thys,AjPFeature parent,ajint Start,ajint End)693 AjPFeature ajFeatNewIISub(AjPFeattable thys,
694 AjPFeature parent,
695 ajint Start, ajint End)
696 {
697 AjPStr source = NULL;
698 float score = 0.0;
699 char strand = '.';
700 ajint frame = 0;
701 ajint flags = 0;
702
703 AjPFeature ret = NULL ;
704
705 /*ajDebug("ajFeatNewII %d %d\n", Start, End);*/
706
707 if(!featTypeMiscfeat)
708 featTypeMiscfeat = ajStrNewC("misc_feature");
709
710 if(Start > End)
711 ret = ajFeatNewNucFlagsSub(thys,parent,
712 source,featTypeMiscfeat,
713 End,Start,score,'-',frame,
714 0,0,0,NULL, NULL,flags);
715 else
716 ret = ajFeatNewNucFlagsSub(thys,parent,
717 source,featTypeMiscfeat,
718 Start,End,score,strand,frame,
719 0,0,0,NULL, NULL,flags);
720
721 return ret;
722 }
723
724
725
726
727 /* @func ajFeatNewIIRev *******************************************************
728 **
729 ** Simple constructor with only start and end positions, sets feature to be
730 ** on the reverse strand
731 **
732 ** User must specify associated 'ajFeattable' to which the new feature
733 ** is automatically added!
734 **
735 ** @param [u] thys [AjPFeattable] Pointer to the ajFeattable which
736 ** will own the feature
737 ** @param [r] Start [ajint] Start position of the feature
738 ** @param [r] End [ajint] End position of the feature
739 ** @return [AjPFeature] newly allocated feature object
740 ** @category new [AjPFeature] Simple constructor with only start and end
741 ** positions, sets feature to be
742 ** on the reverse strand
743 **
744 ** @release 2.8.0
745 ** @@
746 ******************************************************************************/
747
ajFeatNewIIRev(AjPFeattable thys,ajint Start,ajint End)748 AjPFeature ajFeatNewIIRev(AjPFeattable thys,
749 ajint Start, ajint End)
750 {
751 AjPFeature ret = NULL ;
752
753 /*ajDebug("ajFeatNewIIRev %d %d\n", Start, End);*/
754
755 if(Start > End)
756 ret = ajFeatNewII(thys,End,Start);
757 else
758 ret = ajFeatNewII(thys,Start,End);
759
760 ret->Strand = '-';
761
762 return ret;
763 }
764
765
766
767
768 /* @func ajFeatNewIIRevSub ****************************************************
769 **
770 ** Simple constructor with only start and end positions, sets feature to be
771 ** on the reverse strand
772 **
773 ** User must specify associated 'ajFeattable' to which the new feature
774 ** is automatically added!
775 **
776 ** @param [u] thys [AjPFeattable] Pointer to the ajFeattable which
777 ** will own the feature
778 ** @param [u] parent [AjPFeature] Parent feature
779 ** @param [r] Start [ajint] Start position of the feature
780 ** @param [r] End [ajint] End position of the feature
781 ** @return [AjPFeature] newly allocated feature object
782 ** @category new [AjPFeature] Simple constructor with only start and end
783 ** positions, sets feature to be
784 ** on the reverse strand
785 **
786 ** @release 6.4.0
787 ** @@
788 ******************************************************************************/
789
ajFeatNewIIRevSub(AjPFeattable thys,AjPFeature parent,ajint Start,ajint End)790 AjPFeature ajFeatNewIIRevSub(AjPFeattable thys, AjPFeature parent,
791 ajint Start, ajint End)
792 {
793 AjPFeature ret = NULL ;
794
795 /*ajDebug("ajFeatNewIIRev %d %d\n", Start, End);*/
796
797 if(Start > End)
798 ret = ajFeatNewIISub(thys,parent,End,Start);
799 else
800 ret = ajFeatNewIISub(thys,parent,Start,End);
801
802 ret->Strand = '-';
803
804 return ret;
805 }
806
807
808
809
810 /* @func ajFeatNewProt ********************************************************
811 **
812 ** Constructor - must specify associated 'ajFeattable'
813 ** to which the new feature is automatically added!
814 **
815 ** @param [u] thys [AjPFeattable] Pointer to the ajFeattable which
816 ** will own the feature
817 ** @param [r] source [const AjPStr] Analysis basis for feature
818 ** @param [r] type [const AjPStr] Type of feature (e.g. exon)
819 ** @param [r] Start [ajint] Start position of the feature
820 ** @param [r] End [ajint] End position of the feature
821 ** @param [r] score [float] Analysis score for the feature
822 ** @return [AjPFeature] newly allocated feature object
823 ** @category new [AjPFeature] Protein-specific constructor -
824 ** must specify the associated
825 ** (non-null) AjPFeattable
826 **
827 ** @release 2.0.0
828 ** @@
829 **
830 ******************************************************************************/
831
ajFeatNewProt(AjPFeattable thys,const AjPStr source,const AjPStr type,ajint Start,ajint End,float score)832 AjPFeature ajFeatNewProt(AjPFeattable thys,
833 const AjPStr source,
834 const AjPStr type,
835 ajint Start, ajint End,
836 float score)
837 {
838 return ajFeatNewProtFlags(thys, source, type, Start, End, score, 0);
839 }
840
841
842
843
844 /* @func ajFeatNewProtSub *****************************************************
845 **
846 ** Constructor - must specify associated 'ajFeattable'
847 ** to which the new feature is automatically added!
848 **
849 ** @param [u] thys [AjPFeattable] Pointer to the ajFeattable which
850 ** will own the feature
851 ** @param [u] parent [AjPFeature] Parent feature
852 ** @param [r] source [const AjPStr] Analysis basis for feature
853 ** @param [r] type [const AjPStr] Type of feature (e.g. exon)
854 ** @param [r] Start [ajint] Start position of the feature
855 ** @param [r] End [ajint] End position of the feature
856 ** @param [r] score [float] Analysis score for the feature
857 ** @return [AjPFeature] newly allocated feature object
858 ** @category new [AjPFeature] Protein-specific constructor -
859 ** must specify the associated
860 ** (non-null) AjPFeattable
861 **
862 ** @release 6.4.0
863 ** @@
864 **
865 ******************************************************************************/
866
ajFeatNewProtSub(AjPFeattable thys,AjPFeature parent,const AjPStr source,const AjPStr type,ajint Start,ajint End,float score)867 AjPFeature ajFeatNewProtSub(AjPFeattable thys, AjPFeature parent,
868 const AjPStr source,
869 const AjPStr type,
870 ajint Start, ajint End,
871 float score)
872 {
873 return ajFeatNewProtFlagsSub(thys, parent,
874 source, type, Start, End, score, 0);
875 }
876
877
878
879
880 /* @func ajFeatNewProtFlags ***************************************************
881 **
882 ** Constructor - must specify associated 'ajFeattable'
883 ** to which the new feature is automatically added!
884 **
885 ** @param [u] thys [AjPFeattable] Pointer to the ajFeattable which
886 ** will own the feature
887 ** @param [r] source [const AjPStr] Analysis basis for feature
888 ** @param [r] type [const AjPStr] Type of feature (e.g. exon)
889 ** @param [r] Start [ajint] Start position of the feature
890 ** @param [r] End [ajint] End position of the feature
891 ** @param [r] score [float] Analysis score for the feature
892 ** @param [r] flags [ajuint] flags.
893 ** @return [AjPFeature] newly allocated feature object
894 ** @category new [AjPFeature] Protein-specific constructor -
895 ** must specify the associated
896 ** (non-null) AjPFeattable
897 **
898 ** @release 6.4.0
899 ** @@
900 **
901 ******************************************************************************/
902
ajFeatNewProtFlags(AjPFeattable thys,const AjPStr source,const AjPStr type,ajint Start,ajint End,float score,ajuint flags)903 AjPFeature ajFeatNewProtFlags(AjPFeattable thys,
904 const AjPStr source,
905 const AjPStr type,
906 ajint Start, ajint End,
907 float score,
908 ajuint flags)
909 {
910 AjPFeature ret = NULL ;
911
912 if(!featDefSource)
913 ajStrAssignS(&featDefSource, ajUtilGetProgram());
914
915 ajDebug("\najFeatNewProtFlags '%S' %d .. %d %x\n",
916 type, Start, End, flags);
917
918 if(!ajStrGetLen(type))
919 return NULL;
920
921 featInit();
922
923 /* Allocate the object... and a new Tags list */
924 ret = featFeatureNew() ;
925
926 thys->Groups++;
927 ret->Group = thys->Groups;
928 ret->Exon = 0;
929
930 if(ajStrGetLen(source))
931 ajStrAssignS(&ret->Source, source);
932 else
933 ajStrAssignS(&ret->Source, featDefSource);
934
935 ajStrAssignS(&ret->Type, featTypeProt(type));
936 ajDebug("ajFeatNewProt feature type '%S' => '%S'\n", type, ret->Type);
937
938 ret->Score = score;
939
940 ret->Flags = flags;
941
942 ret->Strand = '\0' ;
943
944 ret->Frame = 0 ;
945 ret->Start = Start;
946 ret->End = End;
947 ret->Start2 = 0;
948 ret->End2 = 0;
949
950 ret->Protein = ajTrue;
951
952 if(!(ret->Flags & AJFEATFLAG_REMOTEID) &&
953 !(ret->Flags & AJFEATFLAG_LABEL))
954 {
955 thys->Len = AJMAX(thys->Len, ret->Start);
956 thys->Len = AJMAX(thys->Len, ret->End);
957 }
958
959 ajFeattableAdd(thys,ret) ;
960
961 return ret;
962 }
963
964
965
966
967 /* @func ajFeatNewProtFlagsSub ************************************************
968 **
969 ** Constructor - must specify associated 'ajFeattable'
970 ** to which the new feature is automatically added!
971 **
972 ** @param [u] thys [AjPFeattable] Pointer to the ajFeattable which
973 ** will own the feature
974 ** @param [u] parent [AjPFeature] Parent feature
975 ** @param [r] source [const AjPStr] Analysis basis for feature
976 ** @param [r] type [const AjPStr] Type of feature (e.g. exon)
977 ** @param [r] Start [ajint] Start position of the feature
978 ** @param [r] End [ajint] End position of the feature
979 ** @param [r] score [float] Analysis score for the feature
980 ** @param [r] flags [ajuint] flags.
981 ** @return [AjPFeature] newly allocated feature object
982 ** @category new [AjPFeature] Protein-specific constructor -
983 ** must specify the associated
984 ** (non-null) AjPFeattable
985 **
986 ** @release 6.4.0
987 ** @@
988 **
989 ******************************************************************************/
990
ajFeatNewProtFlagsSub(AjPFeattable thys,AjPFeature parent,const AjPStr source,const AjPStr type,ajint Start,ajint End,float score,ajuint flags)991 AjPFeature ajFeatNewProtFlagsSub(AjPFeattable thys,
992 AjPFeature parent,
993 const AjPStr source,
994 const AjPStr type,
995 ajint Start, ajint End,
996 float score,
997 ajuint flags)
998 {
999 AjPFeature ret = NULL ;
1000
1001 if(!featDefSource)
1002 ajStrAssignS(&featDefSource, ajUtilGetProgram());
1003
1004 ajDebug("\najFeatNewProtFlagsSub '%S' %d .. %d %x\n",
1005 type, Start, End, flags);
1006
1007 if(!ajStrGetLen(type))
1008 return NULL;
1009
1010 featInit();
1011
1012 /* Allocate the object... and a new Tags list */
1013 ret = featFeatureNew() ;
1014
1015 thys->Groups++;
1016 ret->Group = thys->Groups;
1017 ret->Exon = 0;
1018
1019 if(ajStrGetLen(source))
1020 ajStrAssignS(&ret->Source, source);
1021 else
1022 ajStrAssignS(&ret->Source, featDefSource);
1023
1024 ajStrAssignS(&ret->Type, featTypeProt(type));
1025 ajDebug("ajFeatNewProt feature type '%S' => '%S'\n", type, ret->Type);
1026
1027 ret->Score = score;
1028
1029 ret->Flags = flags;
1030
1031 ret->Strand = '\0' ;
1032
1033 ret->Frame = 0 ;
1034 ret->Start = Start;
1035 ret->End = End;
1036 ret->Start2 = 0;
1037 ret->End2 = 0;
1038
1039 ret->Protein = ajTrue;
1040
1041 if(!(ret->Flags & AJFEATFLAG_REMOTEID) &&
1042 !(ret->Flags & AJFEATFLAG_LABEL))
1043 {
1044 thys->Len = AJMAX(thys->Len, ret->Start);
1045 thys->Len = AJMAX(thys->Len, ret->End);
1046 }
1047
1048 if(!parent->Subfeatures)
1049 parent->Subfeatures = ajListNew();
1050
1051 ajListPushAppend(parent->Subfeatures, ret);
1052
1053 return ret;
1054 }
1055
1056
1057
1058
1059 /* @func ajFeatCompByStart ****************************************************
1060 **
1061 ** Compare two features by their start.
1062 **
1063 ** @param [r] a [const void *] feature
1064 ** @param [r] b [const void *] another feature
1065 **
1066 ** @return [ajint] -1 if a is less than b, 0 if a is equal to b else +1.
1067 **
1068 ** @release 6.4.0
1069 ** @@
1070 ******************************************************************************/
1071
ajFeatCompByStart(const void * a,const void * b)1072 ajint ajFeatCompByStart(const void *a, const void *b)
1073 {
1074 const AjPFeature gfa;
1075 const AjPFeature gfb;
1076 ajint val = 0;
1077
1078 gfa = *(AjPFeature const *) a;
1079 gfb = *(AjPFeature const *) b;
1080
1081 val = gfa->Start - gfb->Start;
1082
1083 if(val)
1084 return val;
1085 else
1086 {
1087 val = gfb->End - gfa->End;
1088 if(val)
1089 return val;
1090 }
1091
1092 return 0;
1093 }
1094
1095
1096
1097
1098 /* @func ajFeatCompByEnd ******************************************************
1099 **
1100 ** Compare two features by their end.
1101 **
1102 ** @param [r] a [const void *] feature
1103 ** @param [r] b [const void *] another feature
1104 **
1105 ** @return [ajint] -1 if a is less than b, 0 if a is equal to b else +1.
1106 **
1107 ** @release 6.4.0
1108 ** @@
1109 ******************************************************************************/
1110
ajFeatCompByEnd(const void * a,const void * b)1111 ajint ajFeatCompByEnd(const void *a, const void *b)
1112 {
1113 const AjPFeature gfa;
1114 const AjPFeature gfb;
1115
1116 ajint val = 0;
1117
1118 gfa = *(AjPFeature const *) a;
1119 gfb = *(AjPFeature const *) b;
1120
1121 val = gfa->End - gfb->End;
1122
1123 if(val)
1124 return val;
1125 else
1126 {
1127 val = gfa->Start - gfb->Start;
1128 if(val)
1129 return val;
1130 }
1131
1132 return 0;
1133 }
1134
1135
1136
1137
1138 /* @func ajFeatCompByGroup ****************************************************
1139 **
1140 ** Compare two features by their group and exon numbers
1141 **
1142 ** @param [r] a [const void *] feature
1143 ** @param [r] b [const void *] another feature
1144 **
1145 ** @return [ajint] -1 if a is less than b, 0 if a is equal to b else +1.
1146 **
1147 ** @release 6.4.0
1148 ** @@
1149 ******************************************************************************/
1150
ajFeatCompByGroup(const void * a,const void * b)1151 ajint ajFeatCompByGroup(const void *a, const void *b)
1152 {
1153 const AjPFeature gfa;
1154 const AjPFeature gfb;
1155
1156 ajint val = 0;
1157
1158 gfa = *(AjPFeature const *) a;
1159 gfb = *(AjPFeature const *) b;
1160
1161 val = gfa->Group - gfb->Group;
1162
1163 if(val)
1164 return val;
1165
1166 val = gfa->Exon - gfb->Exon;
1167
1168 return val;
1169 }
1170
1171
1172
1173
1174 /* @func ajFeatCompByType *****************************************************
1175 **
1176 ** Compare two features by their type (key).
1177 **
1178 ** @param [r] a [const void *] feature
1179 ** @param [r] b [const void *] another feature
1180 **
1181 ** @return [ajint] -1 if a is less than b, 0 if a is equal to b else +1.
1182 **
1183 ** @release 6.4.0
1184 ** @@
1185 ******************************************************************************/
1186
ajFeatCompByType(const void * a,const void * b)1187 ajint ajFeatCompByType(const void *a, const void *b)
1188 {
1189 const AjPFeature gfa;
1190 const AjPFeature gfb;
1191
1192 ajint val = 0;
1193
1194 gfa = *(AjPFeature const *) a;
1195 gfb = *(AjPFeature const *) b;
1196
1197 val = ajStrVcmp(&gfa->Type,&gfb->Type);
1198
1199 if(val)
1200 return val;
1201 else
1202 {
1203 val = gfa->Start - gfb->Start;
1204
1205 if(val)
1206 return val;
1207 else
1208 {
1209 val = gfa->End - gfb->End;
1210
1211 if(val)
1212 return val;
1213 }
1214 }
1215
1216 return 0;
1217 }
1218
1219
1220
1221
1222 /******************************************************************************
1223 **
1224 ** Utility classes...
1225 **
1226 ******************************************************************************/
1227
1228
1229
1230
1231 /* @func ajFeatNewNuc *********************************************************
1232 **
1233 ** Constructor for a new feature,
1234 ** automatically added to the specified table.
1235 **
1236 ** @param [u] thys [AjPFeattable] Pointer to the ajFeattable which
1237 ** will own the feature
1238 ** @param [r] source [const AjPStr] Analysis basis for feature
1239 ** @param [r] type [const AjPStr] Type of feature (e.g. exon)
1240 ** @param [r] Start [ajint] Start position of the feature
1241 ** @param [r] End [ajint] End position of the feature
1242 ** @param [r] score [float] Analysis score for the feature
1243 ** @param [r] strand [char] Strand of the feature
1244 ** @param [r] frame [ajint] Frame of the feature
1245 ** @param [r] exon [ajint] exon number (0 for default value)
1246 ** @param [r] Start2 [ajint] 2nd Start position of the feature
1247 ** @param [r] End2 [ajint] 2nd End position of the feature
1248 ** @param [r] entryid [const AjPStr] Entry ID for location in
1249 ** another entry
1250 ** @param [r] label [const AjPStr] Label for location (non-numeric)
1251 ** @return [AjPFeature] newly allocated feature object
1252 **
1253 ** @release 6.4.0
1254 ** @@
1255 ******************************************************************************/
1256
ajFeatNewNuc(AjPFeattable thys,const AjPStr source,const AjPStr type,ajint Start,ajint End,float score,char strand,ajint frame,ajint exon,ajint Start2,ajint End2,const AjPStr entryid,const AjPStr label)1257 AjPFeature ajFeatNewNuc(AjPFeattable thys,
1258 const AjPStr source,
1259 const AjPStr type,
1260 ajint Start,
1261 ajint End,
1262 float score,
1263 char strand,
1264 ajint frame,
1265 ajint exon,
1266 ajint Start2,
1267 ajint End2,
1268 const AjPStr entryid,
1269 const AjPStr label)
1270 {
1271 return ajFeatNewNucFlags(thys, source, type, Start, End,
1272 score, strand, frame, exon, Start2, End2,
1273 entryid, label, 0);
1274 }
1275
1276
1277
1278
1279 /* @func ajFeatNewNucSub ******************************************************
1280 **
1281 ** Constructor for a new feature,
1282 ** automatically added to the specified table.
1283 **
1284 ** @param [u] thys [AjPFeattable] Pointer to the ajFeattable which
1285 ** will own the feature
1286 ** @param [u] parent [AjPFeature] Parent feature
1287 ** @param [r] source [const AjPStr] Analysis basis for feature
1288 ** @param [r] type [const AjPStr] Type of feature (e.g. exon)
1289 ** @param [r] Start [ajint] Start position of the feature
1290 ** @param [r] End [ajint] End position of the feature
1291 ** @param [r] score [float] Analysis score for the feature
1292 ** @param [r] strand [char] Strand of the feature
1293 ** @param [r] frame [ajint] Frame of the feature
1294 ** @param [r] exon [ajint] exon number (0 for default value)
1295 ** @param [r] Start2 [ajint] 2nd Start position of the feature
1296 ** @param [r] End2 [ajint] 2nd End position of the feature
1297 ** @param [r] entryid [const AjPStr] Entry ID for location in
1298 ** another entry
1299 ** @param [r] label [const AjPStr] Label for location (non-numeric)
1300 ** @return [AjPFeature] newly allocated feature object
1301 **
1302 ** @release 6.4.0
1303 ** @@
1304 ******************************************************************************/
1305
ajFeatNewNucSub(AjPFeattable thys,AjPFeature parent,const AjPStr source,const AjPStr type,ajint Start,ajint End,float score,char strand,ajint frame,ajint exon,ajint Start2,ajint End2,const AjPStr entryid,const AjPStr label)1306 AjPFeature ajFeatNewNucSub(AjPFeattable thys,
1307 AjPFeature parent,
1308 const AjPStr source,
1309 const AjPStr type,
1310 ajint Start,
1311 ajint End,
1312 float score,
1313 char strand,
1314 ajint frame,
1315 ajint exon,
1316 ajint Start2,
1317 ajint End2,
1318 const AjPStr entryid,
1319 const AjPStr label)
1320 {
1321 return ajFeatNewNucFlagsSub(thys, parent,
1322 source, type, Start, End,
1323 score, strand, frame, exon, Start2, End2,
1324 entryid, label, 0);
1325 }
1326
1327
1328
1329
1330 /* @func ajFeatNewNucFlags ****************************************************
1331 **
1332 ** Constructor for a new feature,
1333 ** automatically added to the specified table.
1334 **
1335 ** @param [u] thys [AjPFeattable] Pointer to the ajFeattable which
1336 ** will own the feature
1337 ** @param [r] source [const AjPStr] Analysis basis for feature
1338 ** @param [r] type [const AjPStr] Type of feature (e.g. exon)
1339 ** @param [r] Start [ajint] Start position of the feature
1340 ** @param [r] End [ajint] End position of the feature
1341 ** @param [r] score [float] Analysis score for the feature
1342 ** @param [r] strand [char] Strand of the feature
1343 ** @param [r] frame [ajint] Frame of the feature
1344 ** @param [r] exon [ajint] exon number (0 for default value)
1345 ** @param [r] Start2 [ajint] 2nd Start position of the feature
1346 ** @param [r] End2 [ajint] 2nd End position of the feature
1347 ** @param [r] entryid [const AjPStr] Entry ID for location in
1348 ** another entry
1349 ** @param [r] label [const AjPStr] Label for location (non-numeric)
1350 ** @param [r] flags [ajuint] flags.
1351 ** @return [AjPFeature] newly allocated feature object
1352 **
1353 ** @release 6.4.0
1354 ** @@
1355 ******************************************************************************/
1356
ajFeatNewNucFlags(AjPFeattable thys,const AjPStr source,const AjPStr type,ajint Start,ajint End,float score,char strand,ajint frame,ajint exon,ajint Start2,ajint End2,const AjPStr entryid,const AjPStr label,ajuint flags)1357 AjPFeature ajFeatNewNucFlags(AjPFeattable thys,
1358 const AjPStr source,
1359 const AjPStr type,
1360 ajint Start,
1361 ajint End,
1362 float score,
1363 char strand,
1364 ajint frame,
1365 ajint exon,
1366 ajint Start2,
1367 ajint End2,
1368 const AjPStr entryid,
1369 const AjPStr label,
1370 ajuint flags)
1371 {
1372 AjPFeature ret = NULL;
1373
1374 ajDebug("ajFeatNewNucFlags %d %d '%c' type: '%S'\n",
1375 Start, End, strand, type);
1376
1377 if(!featDefSource)
1378 ajStrAssignS(&featDefSource, ajUtilGetProgram());
1379
1380 if(!ajStrGetLen(type))
1381 return NULL;
1382
1383 featInit();
1384
1385 /* Allocate the object... */
1386
1387 ret = featFeatureNew();
1388
1389 thys->Groups++;
1390 ret->Group = thys->Groups;
1391 ret->Exon = exon;
1392
1393 if(ajStrGetLen(source))
1394 ajStrAssignS(&ret->Source, source);
1395 else
1396 ajStrAssignS(&ret->Source, featDefSource);
1397
1398 /*ajDebug("featFeatNew type '%S'\n", thys->Type);*/
1399
1400 if(ajStrMatchC(thys->Type, "P"))
1401 ajStrAssignS(&ret->Type, featTypeProt(type));
1402 else
1403 ajStrAssignS(&ret->Type, featTypeDna(type));
1404
1405 ajDebug("featFeatNew feature type '%S' => '%S'\n", type, ret->Type);
1406 ret->Score = score;
1407
1408 ret->Flags = flags;
1409
1410 if(strand == '+' || strand == '-')
1411 ret->Strand = strand;
1412 else ret->Strand = '\0';
1413
1414 ret->Frame = frame ;
1415 ret->Start = Start;
1416 ret->End = End;
1417 ret->Start2 = Start2;
1418 ret->End2 = End2;
1419
1420 if(ajStrGetLen(entryid))
1421 ajStrAssignS(&ret->Remote, entryid);
1422 else
1423 {
1424 if(!(ret->Flags & AJFEATFLAG_REMOTEID) &&
1425 !(ret->Flags & AJFEATFLAG_LABEL))
1426 {
1427 thys->Len = AJMAX(thys->Len, ret->Start);
1428 thys->Len = AJMAX(thys->Len, ret->End);
1429 }
1430 }
1431
1432 if(ajStrGetLen(label))
1433 {
1434 ajStrAssignS(&ret->Label, label);
1435 ajFeatWarn("%S: Feature label '%S' used",
1436 thys->Seqid, label);
1437 }
1438
1439 ajFeattableAdd(thys,ret);
1440
1441 return ret ;
1442 }
1443
1444
1445
1446
1447 /* @func ajFeatNewNucFlagsSub *************************************************
1448 **
1449 ** Constructor for a new feature,
1450 ** automatically added to the specified table.
1451 **
1452 ** @param [u] thys [AjPFeattable] Pointer to the ajFeattable which
1453 ** will own the feature
1454 ** @param [u] parent [AjPFeature] Parent feature
1455 ** @param [r] source [const AjPStr] Analysis basis for feature
1456 ** @param [r] type [const AjPStr] Type of feature (e.g. exon)
1457 ** @param [r] Start [ajint] Start position of the feature
1458 ** @param [r] End [ajint] End position of the feature
1459 ** @param [r] score [float] Analysis score for the feature
1460 ** @param [r] strand [char] Strand of the feature
1461 ** @param [r] frame [ajint] Frame of the feature
1462 ** @param [r] exon [ajint] exon number (0 for default value)
1463 ** @param [r] Start2 [ajint] 2nd Start position of the feature
1464 ** @param [r] End2 [ajint] 2nd End position of the feature
1465 ** @param [r] entryid [const AjPStr] Entry ID for location in
1466 ** another entry
1467 ** @param [r] label [const AjPStr] Label for location (non-numeric)
1468 ** @param [r] flags [ajuint] flags.
1469 ** @return [AjPFeature] newly allocated feature object
1470 **
1471 ** @release 6.4.0
1472 ** @@
1473 ******************************************************************************/
1474
ajFeatNewNucFlagsSub(AjPFeattable thys,AjPFeature parent,const AjPStr source,const AjPStr type,ajint Start,ajint End,float score,char strand,ajint frame,ajint exon,ajint Start2,ajint End2,const AjPStr entryid,const AjPStr label,ajuint flags)1475 AjPFeature ajFeatNewNucFlagsSub(AjPFeattable thys,
1476 AjPFeature parent,
1477 const AjPStr source,
1478 const AjPStr type,
1479 ajint Start,
1480 ajint End,
1481 float score,
1482 char strand,
1483 ajint frame,
1484 ajint exon,
1485 ajint Start2,
1486 ajint End2,
1487 const AjPStr entryid,
1488 const AjPStr label,
1489 ajuint flags)
1490 {
1491 AjPFeature ret = NULL;
1492
1493 ajDebug("ajFeatNewNucFlagsSub %d %d '%c' type: '%S'\n",
1494 Start, End, strand, type);
1495
1496 if(!featDefSource)
1497 ajStrAssignS(&featDefSource, ajUtilGetProgram());
1498
1499 if(!ajStrGetLen(type))
1500 return NULL;
1501
1502 featInit();
1503
1504 /* Allocate the object... */
1505
1506 ret = featFeatureNew();
1507
1508 thys->Groups++;
1509 ret->Group = thys->Groups;
1510 ret->Exon = exon;
1511
1512 if(ajStrGetLen(source))
1513 ajStrAssignS(&ret->Source, source);
1514 else
1515 ajStrAssignS(&ret->Source, featDefSource);
1516
1517 /*ajDebug("featFeatNew type '%S'\n", thys->Type);*/
1518
1519 if(ajStrMatchC(thys->Type, "P"))
1520 ajStrAssignS(&ret->Type, featTypeProt(type));
1521 else
1522 ajStrAssignS(&ret->Type, featTypeDna(type));
1523
1524 ajDebug("featFeatNew feature type '%S' => '%S'\n", type, ret->Type);
1525 ret->Score = score;
1526
1527 ret->Flags = flags;
1528
1529 if(strand == '+' || strand == '-')
1530 ret->Strand = strand;
1531 else ret->Strand = '\0';
1532
1533 ret->Frame = frame ;
1534 ret->Start = Start;
1535 ret->End = End;
1536 ret->Start2 = Start2;
1537 ret->End2 = End2;
1538
1539 if(ajStrGetLen(entryid))
1540 ajStrAssignS(&ret->Remote, entryid);
1541 else
1542 {
1543 if(!(ret->Flags & AJFEATFLAG_REMOTEID) &&
1544 !(ret->Flags & AJFEATFLAG_LABEL))
1545 {
1546 thys->Len = AJMAX(thys->Len, ret->Start);
1547 thys->Len = AJMAX(thys->Len, ret->End);
1548 }
1549 }
1550
1551 if(ajStrGetLen(label))
1552 {
1553 ajStrAssignS(&ret->Label, label);
1554 ajFeatWarn("%S: Feature label '%S' used",
1555 thys->Seqid, label);
1556 }
1557
1558 if(!parent->Subfeatures)
1559 parent->Subfeatures = ajListNew();
1560
1561 ajListPushAppend(parent->Subfeatures, ret);
1562
1563 return ret ;
1564 }
1565
1566
1567
1568
1569 /* ==================================================================== */
1570 /* =========================== destructor ============================= */
1571 /* ==================================================================== */
1572
1573
1574
1575
1576 /* @section Feature Object Destructors ****************************************
1577 **
1578 ** (Simple minded) object destruction by release of memory.
1579 **
1580 ** No reference counting (for now).
1581 **
1582 ******************************************************************************/
1583
1584
1585
1586
1587 /* @func ajFeattableDel *******************************************************
1588 **
1589 ** Destructor for ajFeattable objects.
1590 ** If the given object (pointer) is NULL, or a NULL pointer, simply returns.
1591 **
1592 ** @param [d] pthis [AjPFeattable*] Pointer to the object to be deleted.
1593 ** The pointer is always deleted.
1594 ** @return [void]
1595 ** @category delete [AjPFeattable] Default destructor
1596 **
1597 ** @release 2.1.0
1598 ** @@
1599 ******************************************************************************/
1600
ajFeattableDel(AjPFeattable * pthis)1601 void ajFeattableDel(AjPFeattable *pthis)
1602 {
1603 AjPFeattable thys;
1604
1605 if(!pthis)
1606 return;
1607
1608 thys = *pthis;
1609
1610 /*ajDebug("ajFeattableDel %x\n", thys);*/
1611
1612 if(!thys)
1613 return;
1614
1615 ajFeattableClear(thys);
1616
1617 ajStrDel(&thys->Seqid);
1618 ajStrDel(&thys->Type);
1619 ajStrDel(&thys->Db);
1620 ajStrDel(&thys->Setdb);
1621 ajStrDel(&thys->Full);
1622 ajStrDel(&thys->Qry);
1623 ajStrDel(&thys->Formatstr);
1624 ajStrDel(&thys->Filename);
1625 ajStrDel(&thys->TextPtr);
1626
1627 ajListFree(&thys->Features);
1628
1629 AJFREE(*pthis);
1630 *pthis = NULL;
1631
1632 return;
1633 }
1634
1635
1636
1637
1638 /* @func ajFeatDel ************************************************************
1639 **
1640 ** Destructor for AjPFeature objects.
1641 ** If the given object (pointer) is NULL, or a NULL pointer, simply returns.
1642 **
1643 ** @param [d] pthis [AjPFeature*] Pointer to the object to be deleted.
1644 ** The pointer is always deleted.
1645 ** @return [void]
1646 ** @category delete [AjPFeature] Default destructor
1647 **
1648 ** @release 1.0.0
1649 ** @@
1650 ******************************************************************************/
1651
ajFeatDel(AjPFeature * pthis)1652 void ajFeatDel(AjPFeature *pthis)
1653 {
1654 if(!pthis)
1655 return ;
1656
1657 if(!*pthis)
1658 return ;
1659
1660 featClear(*pthis);
1661
1662 AJFREE(*pthis);
1663 *pthis = NULL ;
1664
1665 return;
1666 }
1667
1668
1669
1670
1671 /* @funcstatic featClear ******************************************************
1672 **
1673 ** Deletes all feature tag-value pairs from a feature line
1674 **
1675 ** @param [u] thys [AjPFeature] Feature
1676 ** @return [void]
1677 **
1678 ** @release 1.0.0
1679 ** @@
1680 ******************************************************************************/
1681
featClear(AjPFeature thys)1682 static void featClear(AjPFeature thys)
1683 {
1684 AjIList iter = NULL;
1685 AjPTagval item = NULL;
1686 AjPFeature subfeat = NULL;
1687
1688 if(!thys)
1689 return;
1690
1691 /* We need to delete the associated Tag data structures too!!!*/
1692
1693 if(thys->Subfeatures)
1694 {
1695 iter = ajListIterNew(thys->Subfeatures);
1696 while(!ajListIterDone(iter))
1697 {
1698 subfeat = (AjPFeature)ajListIterGet(iter);
1699 ajFeatDel(&subfeat);
1700 }
1701 ajListIterDel(&iter);
1702 }
1703
1704 ajListFree(&(thys->Subfeatures));
1705
1706 if(thys->Tags)
1707 {
1708 iter = ajListIterNew(thys->Tags);
1709 while(!ajListIterDone(iter))
1710 {
1711 item = (AjPTagval)ajListIterGet(iter);
1712 /* assuming a simple block memory free for now...*/
1713 ajTagvalDel(&item);
1714 ajListIterRemove(iter);
1715 }
1716 ajListIterDel(&iter);
1717 }
1718
1719 ajListFree(&(thys->Tags));
1720
1721 if(thys->GffTags)
1722 {
1723 iter = ajListIterNew(thys->GffTags);
1724 while(!ajListIterDone(iter))
1725 {
1726 item = (AjPTagval)ajListIterGet(iter);
1727 /* assuming a simple block memory free for now...*/
1728 ajTagvalDel(&item);
1729 ajListIterRemove(iter);
1730 }
1731 ajListIterDel(&iter);
1732 }
1733
1734 ajListFree(&(thys->GffTags));
1735
1736 ajStrDel(&thys->Source);
1737 ajStrDel(&thys->Type);
1738 ajStrDel(&thys->Remote);
1739 ajStrDel(&thys->Label);
1740
1741 return;
1742 }
1743
1744
1745
1746
1747 /* ==================================================================== */
1748 /* ========================== Assignments ============================= */
1749 /* ==================================================================== */
1750
1751
1752
1753
1754 /* @section Feature Assignments ***********************************************
1755 **
1756 ******************************************************************************/
1757
1758
1759
1760
1761 /* @func ajFeatSortByType *****************************************************
1762 **
1763 ** Sort Feature table by Type.
1764 **
1765 ** @param [u] Feattab [AjPFeattable] Feature table to be sorted.
1766 **
1767 ** @return [void]
1768 **
1769 ** @release 1.0.0
1770 ** @@
1771 ******************************************************************************/
1772
ajFeatSortByType(AjPFeattable Feattab)1773 void ajFeatSortByType(AjPFeattable Feattab)
1774 {
1775 ajListSort(Feattab->Features, &ajFeatCompByType);
1776
1777 return;
1778 }
1779
1780
1781
1782
1783 /* @func ajFeatSortByStart ****************************************************
1784 **
1785 ** Sort Feature table by Start position.
1786 **
1787 ** @param [u] Feattab [AjPFeattable] Feature table to be sorted.
1788 **
1789 ** @return [void]
1790 **
1791 ** @release 1.0.0
1792 ** @@
1793 ******************************************************************************/
1794
ajFeatSortByStart(AjPFeattable Feattab)1795 void ajFeatSortByStart(AjPFeattable Feattab)
1796 {
1797 ajListSort(Feattab->Features, &ajFeatCompByStart);
1798 }
1799
1800
1801
1802
1803 /* @func ajFeatSortByEnd ******************************************************
1804 **
1805 ** Sort Feature table by End position.
1806 **
1807 ** @param [u] Feattab [AjPFeattable] Feature table to be sorted.
1808 **
1809 ** @return [void]
1810 **
1811 ** @release 1.0.0
1812 ** @@
1813 ******************************************************************************/
1814
ajFeatSortByEnd(AjPFeattable Feattab)1815 void ajFeatSortByEnd(AjPFeattable Feattab)
1816 {
1817 ajListSort(Feattab->Features, &ajFeatCompByEnd);
1818
1819 return;
1820 }
1821
1822
1823
1824
1825 /* ==================================================================== */
1826 /* ========================== Modifiers ============================= */
1827 /* ==================================================================== */
1828
1829
1830
1831
1832 /* @section Feature Table Modifiers ******************************************
1833 **
1834 ******************************************************************************/
1835
1836
1837
1838
1839 /* @func ajFeattableAdd *******************************************************
1840 **
1841 ** Method to add a new AjPFeature to a AjPFeattable
1842 **
1843 ** @param [u] thys [AjPFeattable] The feature table
1844 ** @param [u] feature [AjPFeature] Feature to be added to the set
1845 ** @return [void]
1846 ** @category modify [AjPFeattable] Adds an AjPFeature to a set
1847 **
1848 ** @release 2.1.0
1849 ** @@
1850 ******************************************************************************/
1851
ajFeattableAdd(AjPFeattable thys,AjPFeature feature)1852 void ajFeattableAdd(AjPFeattable thys, AjPFeature feature)
1853 {
1854 if(!(feature->Flags & AJFEATFLAG_REMOTEID) &&
1855 !(feature->Flags & AJFEATFLAG_LABEL))
1856 {
1857 thys->Len = AJMAX(thys->Len, feature->Start);
1858 thys->Len = AJMAX(thys->Len, feature->End);
1859 }
1860
1861 ajListPushAppend(thys->Features, feature);
1862
1863 return;
1864 }
1865
1866
1867
1868
1869 /* @func ajFeattableAddNew ****************************************************
1870 **
1871 ** Method to add a new AjPFeature to a AjPFeattable as a new feature,
1872 ** updating the feature group.
1873 **
1874 ** @param [u] thys [AjPFeattable] The feature table
1875 ** @param [u] feature [AjPFeature] Feature to be added to the set
1876 ** @return [void]
1877 ** @category modify [AjPFeattable] Adds an AjPFeature to a set
1878 **
1879 ** @release 2.1.0
1880 ** @@
1881 ******************************************************************************/
1882
ajFeattableAddNew(AjPFeattable thys,AjPFeature feature)1883 void ajFeattableAddNew(AjPFeattable thys, AjPFeature feature)
1884 {
1885 AjIList iter = NULL;
1886 AjPFeature subfeat = NULL;
1887
1888 if(!(feature->Flags & AJFEATFLAG_REMOTEID) &&
1889 !(feature->Flags & AJFEATFLAG_LABEL))
1890 {
1891 thys->Len = AJMAX(thys->Len, feature->Start);
1892 thys->Len = AJMAX(thys->Len, feature->End);
1893 }
1894
1895 thys->Groups++;
1896 feature->Group = thys->Groups;
1897
1898 if(feature->Subfeatures)
1899 {
1900 iter = ajListIterNew(feature->Subfeatures);
1901 while(!ajListIterDone(iter))
1902 {
1903 subfeat = (AjPFeature)ajListIterGet(iter);
1904 subfeat->Group = thys->Groups;
1905 }
1906 ajListIterDel(&iter);
1907 }
1908
1909 ajListPushAppend(thys->Features, feature);
1910
1911 return;
1912 }
1913
1914
1915
1916
1917 /* @func ajFeattableMerge *****************************************************
1918 **
1919 ** Merges a feature table into an existing feature table.
1920 **
1921 ** @param [u] thys [AjPFeattable] Feature table to be appended to
1922 ** @param [r] srctable [const AjPFeattable] Additional feature table
1923 ** @return [ajuint] Size of the new feature table.
1924 **
1925 ** @release 6.5.0
1926 ** @@
1927 ******************************************************************************/
1928
ajFeattableMerge(AjPFeattable thys,const AjPFeattable srctable)1929 ajuint ajFeattableMerge(AjPFeattable thys, const AjPFeattable srctable)
1930 {
1931 AjIList iter;
1932 AjPFeature featsrc;
1933 AjPFeature feat = NULL;
1934
1935 if(!thys)
1936 return 0;
1937
1938 if(!srctable)
1939 return 0;
1940
1941 iter = ajListIterNewread(srctable->Features);
1942
1943 while(!ajListIterDone(iter))
1944 {
1945 featsrc = ajListIterGet(iter);
1946 feat = ajFeatNewFeat(featsrc);
1947 ajFeattableAdd(thys, feat);
1948 }
1949
1950 ajListIterDel(&iter);
1951
1952 return (ajuint) ajListGetLength(thys->Features);
1953 }
1954
1955
1956
1957
1958 /* ==================================================================== */
1959 /* ======================== Operators ==================================*/
1960 /* ==================================================================== */
1961
1962
1963
1964
1965 /* @section Feature Object Operators ******************************************
1966 **
1967 ** These functions use the contents of a feature object,
1968 ** but do not make any changes.
1969 **
1970 ******************************************************************************/
1971
1972
1973
1974
1975 /* @funcstatic featTableInit **************************************************
1976 **
1977 ** Initialise the components of a previously allocated AjPFeattable object.
1978 **
1979 ** @param [u] thys [AjPFeattable] Target feature table object
1980 ** @param [r] name [const AjPStr] Name of the table (e.g.
1981 ** sequence name)
1982 ** @return [void]
1983 **
1984 ** @release 2.1.0
1985 ** @@
1986 **
1987 ******************************************************************************/
1988
featTableInit(AjPFeattable thys,const AjPStr name)1989 static void featTableInit(AjPFeattable thys,
1990 const AjPStr name)
1991 {
1992 /*ajDebug("featTableInit Entering...\n");*/
1993
1994 /*ajDebug("featTableInit initialising seqid: '%S'\n", name);*/
1995 ajStrAssignS(&thys->Seqid,name) ;
1996 thys->Format = 0;
1997
1998 return;
1999 }
2000
2001
2002
2003
2004 /* @func ajFeattableClear *****************************************************
2005 **
2006 ** Clears a feature table of all features
2007 **
2008 ** @param [u] thys [AjPFeattable] Feature table
2009 ** @return [void]
2010 **
2011 ** @release 2.1.0
2012 ** @@
2013 ******************************************************************************/
2014
ajFeattableClear(AjPFeattable thys)2015 void ajFeattableClear(AjPFeattable thys)
2016 {
2017 AjIList iter = NULL ;
2018 AjPFeature feature = NULL ;
2019
2020 if(!thys)
2021 return ;
2022
2023 if(MAJSTRGETLEN(thys->Seqid))
2024 ajStrSetClear(&thys->Seqid);
2025 if(MAJSTRGETLEN(thys->Type))
2026 ajStrSetClear(&thys->Type);
2027 if(MAJSTRGETLEN(thys->Db))
2028 ajStrSetClear(&thys->Db);
2029 if(MAJSTRGETLEN(thys->Setdb))
2030 ajStrSetClear(&thys->Setdb);
2031 if(MAJSTRGETLEN(thys->Full))
2032 ajStrSetClear(&thys->Full);
2033 if(MAJSTRGETLEN(thys->Qry))
2034 ajStrSetClear(&thys->Qry);
2035 if(MAJSTRGETLEN(thys->Formatstr))
2036 ajStrSetClear(&thys->Formatstr);
2037 if(MAJSTRGETLEN(thys->Filename))
2038 ajStrSetClear(&thys->Filename);
2039 if(MAJSTRGETLEN(thys->TextPtr))
2040 ajStrSetClear(&thys->TextPtr);
2041
2042 if(thys->Features)
2043 {
2044 iter = ajListIterNew(thys->Features) ;
2045 while(!ajListIterDone(iter))
2046 {
2047 feature = (AjPFeature)ajListIterGet(iter) ;
2048 ajFeatDel(&feature) ;
2049 ajListIterRemove(iter) ;
2050 }
2051 ajListIterDel(&iter) ;
2052 }
2053
2054 thys->Format = 0;
2055 thys->Start = 0;
2056 thys->End = 0;
2057 thys->Len = 0;
2058 thys->Offset = 0;
2059 thys->Rev = ajFalse;
2060 thys->Reversed = ajFalse;
2061 thys->Trimmed = ajFalse;
2062
2063 thys->Groups = 0;
2064 thys->Fpos = 0L;
2065 thys->Circular = AJFALSE;
2066
2067 return;
2068 }
2069
2070
2071
2072
2073 /* @funcstatic featFeatType ***************************************************
2074 **
2075 ** Process Efeatures file line
2076 **
2077 ** Lines starting with text are new types
2078 **
2079 ** Lines with '=' are aliases that update a previous defined type name
2080 ** and can have only + and - tag lines.
2081 **
2082 ** Lines starting with / or m/ are tags for the current type
2083 **
2084 ** Lines starting with +/ or -/ add and remove tags for the current type
2085 **
2086 ** @param [r] line [const AjPStr] Tags file line
2087 ** @param [w] type [AjPStr*] Feature type
2088 ** @param [w] intids [AjPStr*] Internal feature keys, preferably based on the
2089 ** Sequence Ontology Feature Annotation ID
2090 ** @param [w] tag [AjPStr*] Tag name
2091 ** @param [w] req [AjPStr*] Required (mandatory) code
2092 ** M = mandatory, m = alternate mandatory,
2093 ** + = add to existing tags,
2094 ** - = remove from existing tags
2095 ** @return [AjBool] ajTrue if a match was found
2096 ** ajFalse means an error occurred
2097 **
2098 ** @release 3.0.0
2099 ******************************************************************************/
2100
featFeatType(const AjPStr line,AjPStr * type,AjPStr * intids,AjPStr * tag,AjPStr * req)2101 static AjBool featFeatType(const AjPStr line, AjPStr* type,
2102 AjPStr* intids, AjPStr* tag, AjPStr* req)
2103 {
2104 const char* cp = ajStrGetPtr(line);
2105 const char* cq;
2106 ajint i;
2107 AjBool istag = ajFalse;
2108
2109 ajStrAssignClear(type);
2110 ajStrAssignClear(intids);
2111 ajStrAssignClear(tag);
2112 ajStrAssignClear(req);
2113
2114 while(isspace((ajint)*cp))
2115 cp++;
2116
2117 if(!*cp)
2118 return ajFalse;
2119
2120 if(*cp == '/')
2121 istag = ajTrue;
2122 else if(*cp == 'm' || *cp == 'M' || *cp == '-')
2123 {
2124 if(*(cp+1) == '/')
2125 {
2126 istag = ajTrue;
2127 ajStrAppendK(req, *cp++);
2128 }
2129 }
2130 else if(*cp == '+')
2131 {
2132 if(*(cp+1) == 'm' || *(cp+1) == 'M')
2133 {
2134 if(*(cp+2) == '/')
2135 {
2136 istag = ajTrue;
2137 ajStrAppendK(req, *cp++);
2138 ajStrAppendK(req, *cp++);
2139 }
2140 }
2141 else
2142 {
2143 if(*(cp+1) == '/')
2144 {
2145 istag = ajTrue;
2146 ajStrAppendK(req, *cp++);
2147 }
2148 }
2149 }
2150
2151 if(istag)
2152 {
2153 /* /tag name */
2154 cp++;
2155 cq = cp;
2156 i = 0;
2157
2158 while(*cp && !isspace((ajint)*cp++))
2159 {
2160 i++;
2161 }
2162
2163 ajStrAssignLenC(tag, cq, i);
2164
2165 if(!ajStrGetLen(*tag))
2166 return ajFalse;
2167 }
2168 else
2169 {
2170 /* type internal id */
2171 cq = cp;
2172 i = 0;
2173
2174 while(*cp && !isspace((ajint)*cp++))
2175 {
2176 i++;
2177 }
2178
2179 ajStrAssignLenC(type, cq, i);
2180
2181 if(!ajStrGetLen(*type))
2182 return ajFalse;
2183
2184 while(*cp && isspace((ajint)*cp))
2185 cp++;
2186
2187 if(!*cp)
2188 return ajTrue;
2189
2190 if(*cp == '=')
2191 ajStrAppendK(req, *cp++);
2192
2193 while(*cp && isspace((ajint)*cp))
2194 cp++;
2195
2196 cq = cp;
2197 i = 0;
2198
2199 while(*cp && !isspace((ajint)*cp++))
2200 i++;
2201
2202 ajStrAppendLenC(intids, cq, i);
2203
2204 while(*cp)
2205 {
2206 while(*cp && isspace((ajint)*cp))
2207 cp++;
2208
2209 if(!*cp)
2210 return ajTrue;
2211
2212 cq = cp;
2213 i = 0;
2214
2215 while(*cp && !isspace((ajint)*cp++))
2216 i++;
2217
2218 ajStrAppendK(intids, ' ');
2219 ajStrAppendLenC(intids, cq, i);
2220 }
2221 }
2222
2223 return ajTrue;
2224 }
2225
2226
2227
2228
2229 /* @func ajFeatTypeGetCategory ************************************************
2230 **
2231 ** returns the category name for a feature type
2232 **
2233 ** Used to identify category for DASGFF output
2234 **
2235 ** @param [r] type [const AjPStr] Feature type
2236 ** @return [const AjPStr] Feature category
2237 **
2238 **
2239 ** @release 6.1.0
2240 ******************************************************************************/
2241
ajFeatTypeGetCategory(const AjPStr type)2242 const AjPStr ajFeatTypeGetCategory(const AjPStr type)
2243 {
2244 ajuint i;
2245 AjPStrTok catsplit = NULL;
2246 AjPStr token = NULL;
2247 AjPStr name = NULL;
2248 AjPStr types = NULL;
2249 AjPStr refname = NULL;
2250 const AjPStr ret = NULL;
2251
2252 if(FeatCategoryTable == NULL)
2253 {
2254 FeatCategoryTable = ajTablestrNewCase(200);
2255
2256 for(i=0;featCategory[i].Name;i++)
2257 {
2258 name = ajStrNewC(featCategory[i].Name);
2259 types = ajStrNewC(featCategory[i].Types);
2260
2261 if(!i)
2262 {
2263 token = ajStrNewC("");
2264 refname = ajStrNewRef(name);
2265 ajTablePut(FeatCategoryTable, token, refname);
2266 token = NULL;
2267 }
2268
2269 catsplit = ajStrTokenNewC(types,",");
2270
2271 while(ajStrTokenNextParse(catsplit,&token))
2272 {
2273 refname = ajStrNewRef(name);
2274 ajTablePut(FeatCategoryTable, token, refname);
2275 token = NULL;
2276 }
2277
2278 ajStrDel(&token);
2279 ajStrDel(&name);
2280 ajStrDel(&types);
2281 ajStrTokenDel(&catsplit);
2282 }
2283
2284 }
2285
2286 ret = ajTablestrFetchS(FeatCategoryTable,type);
2287 if(!ret)
2288 {
2289 token = ajStrNewC("");
2290 ret = ajTablestrFetchS(FeatCategoryTable,token);
2291 ajStrDel(&token);
2292 }
2293
2294 return ret;
2295 }
2296
2297
2298
2299
2300 /* @func ajFeattableGetEntry **************************************************
2301 **
2302 ** Return the full text
2303 **
2304 ** @param [r] thys [const AjPFeattable] Feature table object
2305 **
2306 ** @return [const AjPStr] Returned full text
2307 **
2308 **
2309 ** @release 6.4.0
2310 ******************************************************************************/
2311
ajFeattableGetEntry(const AjPFeattable thys)2312 const AjPStr ajFeattableGetEntry(const AjPFeattable thys)
2313 {
2314 if(thys->TextPtr)
2315 return thys->TextPtr;
2316
2317 return ajStrConstEmpty();
2318 }
2319
2320
2321
2322
2323 /* @func ajFeattableGetQryC ***************************************************
2324 **
2325 ** Returns the query string of a feature table data object.
2326 ** Because this is a pointer to the real internal string
2327 ** the caller must take care not to change the character string in any way.
2328 ** If the string is to be changed (case for example) then it must first
2329 ** be copied.
2330 **
2331 ** @param [r] ftable [const AjPFeattable] Feature table data object.
2332 ** @return [const char*] Query as a character string.
2333 **
2334 ** @release 6.4.0
2335 ** @@
2336 ******************************************************************************/
2337
ajFeattableGetQryC(const AjPFeattable ftable)2338 const char* ajFeattableGetQryC(const AjPFeattable ftable)
2339 {
2340 return MAJSTRGETPTR(ajFeattableGetQryS(ftable));
2341 }
2342
2343
2344
2345
2346 /* @func ajFeattableGetQryS ***************************************************
2347 **
2348 ** Returns the query string of a feature table data object.
2349 ** Because this is a pointer to the real internal string
2350 ** the caller must take care not to change the character string in any way.
2351 ** If the string is to be changed (case for example) then it must first
2352 ** be copied.
2353 **
2354 ** @param [r] ftable [const AjPFeattable] Feature table data object.
2355 ** @return [const AjPStr] Query as a string.
2356 **
2357 ** @release 6.4.0
2358 ** @@
2359 ******************************************************************************/
2360
ajFeattableGetQryS(const AjPFeattable ftable)2361 const AjPStr ajFeattableGetQryS(const AjPFeattable ftable)
2362 {
2363 ajDebug("ajFeattableGetQryS '%S'\n", ftable->Qry);
2364
2365 if(ajStrGetLen(ftable->Qry))
2366 return ftable->Qry;
2367
2368 feattableMakeQry(ftable, &featTempQry);
2369
2370 return featTempQry;
2371 }
2372
2373
2374
2375
2376 /* @func ajFeattableGetTypeC **************************************************
2377 **
2378 ** Returns the name of a feature table object. This is a copy of the
2379 ** pointer to the name, and is still owned by the feature table
2380 ** and is not to be destroyed.
2381 **
2382 ** @param [r] thys [const AjPFeattable] Feature table
2383 ** @return [const char*] Feature table type.
2384 **
2385 ** @release 4.0.0
2386 ** @@
2387 ******************************************************************************/
2388
ajFeattableGetTypeC(const AjPFeattable thys)2389 const char* ajFeattableGetTypeC(const AjPFeattable thys)
2390 {
2391 return ajStrGetPtr(thys->Type);
2392 }
2393
2394
2395
2396
2397 /* @func ajFeattableGetTypeS **************************************************
2398 **
2399 ** Returns the name of a feature table object. This is a copy of the
2400 ** pointer to the name, and is still owned by the feature table
2401 ** and is not to be destroyed.
2402 **
2403 ** @param [r] thys [const AjPFeattable] Feature table
2404 ** @return [const AjPStr] Feature table name.
2405 **
2406 ** @release 4.0.0
2407 ** @@
2408 ******************************************************************************/
2409
ajFeattableGetTypeS(const AjPFeattable thys)2410 const AjPStr ajFeattableGetTypeS(const AjPFeattable thys)
2411 {
2412 return thys->Type;
2413 }
2414
2415
2416
2417
2418 /* @func ajFeattableGetXrefs **************************************************
2419 **
2420 ** Returns all cross-references from a feature table
2421 **
2422 ** @param [r] thys [const AjPFeattable] Feature table
2423 ** @param [u] Pxreflist [AjPList*] List of sequence cross-reference objects
2424 ** @param [w] Ptaxid [ajuint*] Taxon ID
2425 ** @return [AjBool] True on success
2426 **
2427 ** @release 6.1.0
2428 ** @@
2429 ******************************************************************************/
2430
ajFeattableGetXrefs(const AjPFeattable thys,AjPList * Pxreflist,ajuint * Ptaxid)2431 AjBool ajFeattableGetXrefs(const AjPFeattable thys, AjPList *Pxreflist,
2432 ajuint *Ptaxid)
2433 {
2434 AjIList iterfeat = NULL;
2435 AjIList itertags = NULL;
2436 AjPTagval item = NULL;
2437 AjPSeqXref xref = NULL;
2438 ajlong ipos;
2439 ajuint inum = 0;
2440 AjPFeature feat = NULL;
2441 AjPList xreflist;
2442 AjPStrTok handle = NULL;
2443 AjPStr tmpstr = NULL;
2444 const AjPStr tagval = NULL;
2445
2446 if(!*Pxreflist)
2447 *Pxreflist = ajListNew();
2448 xreflist = *Pxreflist;
2449
2450 *Ptaxid = 0;
2451
2452 if(thys->Features)
2453 {
2454 iterfeat = ajListIterNewread(thys->Features);
2455
2456 while(!ajListIterDone(iterfeat))
2457 {
2458 feat = (AjPFeature)ajListIterGet(iterfeat);
2459 if(feat->Tags)
2460 {
2461 itertags = ajListIterNewread(feat->Tags);
2462
2463 while(!ajListIterDone(itertags))
2464 {
2465 item = (AjPTagval)ajListIterGet(itertags);
2466
2467 if(ajStrMatchCaseC(MAJTAGVALGETTAG(item), "db_xref"))
2468 {
2469 tagval = ajTagvalGetValue(item);
2470 ipos = ajStrFindAnyK(tagval, ':');
2471 if(ipos > 0)
2472 {
2473 inum++;
2474 xref = ajSeqxrefNew();
2475 ajStrAssignSubS(&xref->Db,
2476 tagval, 0, ipos-1);
2477 ajStrAssignSubS(&xref->Id,
2478 tagval, ipos+1, -1);
2479 ajListPushAppend(xreflist, xref);
2480 xref->Start = ajFeatGetStart(feat);
2481 xref->End = ajFeatGetEnd(feat);
2482 xref->Type = XREF_DBXREF;
2483 if(!*Ptaxid && ajStrMatchCaseC(xref->Db, "taxon"))
2484 {
2485 if(!ajStrToUint(xref->Id, Ptaxid))
2486 *Ptaxid = 0;
2487 }
2488 xref = NULL;
2489 }
2490 }
2491 }
2492
2493 ajListIterDel(&itertags);
2494 }
2495
2496 if(feat->GffTags)
2497 {
2498 itertags = ajListIterNewread(feat->GffTags);
2499
2500 while(!ajListIterDone(itertags))
2501 {
2502 item = (AjPTagval)ajListIterGet(itertags);
2503
2504 if(ajStrMatchCaseC(MAJTAGVALGETTAG(item), "Dbxref"))
2505 {
2506 tagval = ajTagvalGetValue(item);
2507 handle = ajStrTokenNewC(tagval, ",");
2508 while(ajStrTokenNextParse(handle, &tmpstr))
2509 {
2510 ipos = ajStrFindAnyK(tmpstr, ':');
2511 if(ipos > 0)
2512 {
2513 inum++;
2514 xref = ajSeqxrefNew();
2515 ajStrAssignSubS(&xref->Db,
2516 tmpstr, 0, ipos-1);
2517 ajStrAssignSubS(&xref->Id,
2518 tmpstr, ipos+1, -1);
2519 ajListPushAppend(xreflist, xref);
2520 xref->Start = ajFeatGetStart(feat);
2521 xref->End = ajFeatGetEnd(feat);
2522 xref->Type = XREF_DBXREF;
2523 if(!*Ptaxid &&
2524 ajStrMatchCaseC(xref->Db, "taxon"))
2525 {
2526 if(!ajStrToUint(xref->Id, Ptaxid))
2527 *Ptaxid = 0;
2528 }
2529 xref = NULL;
2530 }
2531 }
2532
2533 ajStrTokenDel(&handle);
2534 ajStrDel(&tmpstr);
2535 }
2536 }
2537
2538 ajListIterDel(&itertags);
2539 }
2540 }
2541 }
2542
2543 ajListIterDel(&iterfeat);
2544
2545 if(!inum)
2546 return ajFalse;
2547
2548 return ajTrue;
2549 }
2550
2551
2552
2553
2554 /* @funcstatic feattableMakeQry ***********************************************
2555 **
2556 ** Sets the query for a feature table data object.
2557 **
2558 ** @param [r] thys [const AjPFeattable] Feature table data object
2559 ** @param [w] qry [AjPStr*] Query string in full
2560 ** @return [void]
2561 **
2562 ** @release 6.4.0
2563 ** @@
2564 ******************************************************************************/
2565
feattableMakeQry(const AjPFeattable thys,AjPStr * qry)2566 static void feattableMakeQry(const AjPFeattable thys, AjPStr* qry)
2567 {
2568 ajDebug("feattableMakeQry (Seqid <%S> Formatstr <%S> Db <%S> "
2569 "Filename <%S>)\n",
2570 thys->Seqid, thys->Formatstr, thys->Db,
2571 thys->Filename);
2572
2573 /* ajResourceTrace(thys); */
2574
2575 if(ajStrGetLen(thys->Db))
2576 ajFmtPrintS(qry, "%S-id:%S", thys->Db, thys->Seqid);
2577 else
2578 {
2579 ajFmtPrintS(qry, "%S::%S:%S", thys->Formatstr,
2580 thys->Filename,thys->Seqid);
2581 }
2582
2583 ajDebug(" result: <%S>\n",
2584 *qry);
2585
2586 return;
2587 }
2588
2589
2590
2591
2592 /* @func ajFeatframeGetFrame **************************************************
2593 **
2594 ** Converts a frame number in the range 0 to 3 to a GFF frame character
2595 ** or '.' as the general default
2596 **
2597 ** @param [r] frame [ajint] Feature frame number
2598 ** @return [char] character for this frame in GFF
2599 **
2600 ** @release 6.4.0
2601 ******************************************************************************/
2602
ajFeatframeGetFrame(ajint frame)2603 char ajFeatframeGetFrame(ajint frame)
2604 {
2605 static char framestr[] = ".012";
2606
2607 if(frame < 0)
2608 return '.';
2609
2610 if(frame > 3)
2611 return '.';
2612
2613 return framestr[frame];
2614 }
2615
2616
2617
2618
2619 /* @func ajFeatframeGetFrameNuc ***********************************************
2620 **
2621 ** Converts a frame number in the range 0 to 3 to a GFF frame character
2622 ** or '0' for the nucleotide default
2623 **
2624 ** @param [r] frame [ajint] Feature frame number
2625 ** @return [char] character for this frame in GFF
2626 **
2627 ** @release 6.4.0
2628 ******************************************************************************/
2629
ajFeatframeGetFrameNuc(ajint frame)2630 char ajFeatframeGetFrameNuc(ajint frame)
2631 {
2632 static char framestr[] = ".012";
2633
2634 if(frame <= 0)
2635 return '0';
2636
2637 if(frame > 3)
2638 return '0';
2639
2640 return framestr[frame];
2641 }
2642
2643
2644
2645
2646 /* @func ajFeatstrandGetStrand ************************************************
2647 **
2648 ** Converts a strand number to a GFF strand character. NULL characters
2649 ** are converted to '+' All other values are simply cast to character.
2650 **
2651 ** @param [r] strand [ajint] Strand
2652 ** @return [char] GFF character for this strand.
2653 **
2654 ** @release 6.4.0
2655 ** @@
2656 ******************************************************************************/
2657
ajFeatstrandGetStrand(ajint strand)2658 char ajFeatstrandGetStrand(ajint strand)
2659 {
2660 if(ajSysCastItoc(strand) != '-')
2661 return '+';
2662
2663 return '-';
2664 }
2665
2666
2667
2668
2669 /* @func ajFeattableIsCircular ************************************************
2670 **
2671 ** Returns true if a feature table is circular
2672 **
2673 ** @param [r] thys [const AjPFeattable] Feature table
2674 ** @return [AjBool] ajTrue for a circular feature table
2675 **
2676 ** @release 2.5.0
2677 ** @@
2678 ******************************************************************************/
2679
ajFeattableIsCircular(const AjPFeattable thys)2680 AjBool ajFeattableIsCircular(const AjPFeattable thys)
2681 {
2682 return thys->Circular;
2683 }
2684
2685
2686
2687
2688 /* @func ajFeattableIsNuc *****************************************************
2689 **
2690 ** Returns ajTrue if a feature table is nucleotide
2691 **
2692 ** @param [r] thys [const AjPFeattable] Feature table
2693 ** @return [AjBool] ajTrue for a protein feature table
2694 **
2695 ** @release 2.5.0
2696 ** @@
2697 ******************************************************************************/
2698
ajFeattableIsNuc(const AjPFeattable thys)2699 AjBool ajFeattableIsNuc(const AjPFeattable thys)
2700 {
2701 if(ajStrMatchC(thys->Type, "N"))
2702 return ajTrue;
2703
2704 if(ajStrMatchC(thys->Type, "P"))
2705 return ajFalse;
2706
2707 return ajTrue;
2708 }
2709
2710
2711
2712
2713 /* @func ajFeattableIsProt ****************************************************
2714 **
2715 ** Returns ajTrue if a feature table is protein
2716 **
2717 ** @param [r] thys [const AjPFeattable] Feature table
2718 ** @return [AjBool] ajTrue for a protein feature table
2719 **
2720 ** @release 2.5.0
2721 ** @@
2722 ******************************************************************************/
2723
ajFeattableIsProt(const AjPFeattable thys)2724 AjBool ajFeattableIsProt(const AjPFeattable thys)
2725 {
2726 if(ajStrMatchC(thys->Type, "P"))
2727 return ajTrue;
2728
2729 if(ajStrMatchC(thys->Type, "N"))
2730 return ajFalse;
2731
2732 return ajTrue;
2733 }
2734
2735
2736
2737
2738 /* @func ajFeattableGetBegin **************************************************
2739 **
2740 ** Returns the feature table start position, or 1 if no start has been set.
2741 **
2742 ** @param [r] thys [const AjPFeattable] feature table object
2743 ** @return [ajint] Start position.
2744 **
2745 ** @release 6.2.0
2746 ** @@
2747 ******************************************************************************/
2748
ajFeattableGetBegin(const AjPFeattable thys)2749 ajint ajFeattableGetBegin(const AjPFeattable thys)
2750 {
2751 if(!thys->Start)
2752 return 1;
2753
2754 return ajFeattablePos(thys, thys->Start);
2755 }
2756
2757
2758
2759
2760 /* @func ajFeattableGetEnd ****************************************************
2761 **
2762 ** Returns the features table end position, or the feature table length if
2763 ** no end has been set.
2764 **
2765 ** @param [r] thys [const AjPFeattable] feature table object
2766 ** @return [ajint] End position.
2767 **
2768 ** @release 6.2.0
2769 ** @@
2770 ******************************************************************************/
2771
ajFeattableGetEnd(const AjPFeattable thys)2772 ajint ajFeattableGetEnd(const AjPFeattable thys)
2773 {
2774 if(!thys->End)
2775 return (ajFeattableGetLen(thys));
2776
2777 return ajFeattablePosI(thys, ajFeattableGetBegin(thys), thys->End);
2778 }
2779
2780
2781
2782
2783 /* @func ajFeattableGetLen ****************************************************
2784 **
2785 ** Returns the sequence length of a feature table
2786 **
2787 ** @param [r] thys [const AjPFeattable] Feature table
2788 ** @return [ajint] Length in bases or residues
2789 **
2790 ** @release 6.2.0
2791 ** @@
2792 ******************************************************************************/
2793
ajFeattableGetLen(const AjPFeattable thys)2794 ajint ajFeattableGetLen(const AjPFeattable thys)
2795 {
2796 if(!thys)
2797 return 0;
2798
2799 return (thys->Len);
2800 }
2801
2802
2803
2804
2805 /* @func ajFeattableGetName ***************************************************
2806 **
2807 ** Returns the name of a feature table object. This is a copy of the
2808 ** pointer to the name, and is still owned by the feature table
2809 ** and is not to be destroyed.
2810 **
2811 ** @param [r] thys [const AjPFeattable] Feature table
2812 ** @return [const AjPStr] Feature table name.
2813 **
2814 ** @release 2.1.0
2815 ** @@
2816 ******************************************************************************/
2817
ajFeattableGetName(const AjPFeattable thys)2818 const AjPStr ajFeattableGetName(const AjPFeattable thys)
2819 {
2820 if(!thys)
2821 return NULL;
2822
2823 return thys->Seqid;
2824 }
2825
2826
2827
2828
2829 /* @func ajFeattableGetSize ***************************************************
2830 **
2831 ** Returns the size of a feature table object.
2832 **
2833 ** @param [r] thys [const AjPFeattable] Feature table
2834 ** @return [ajuint] Feature table size.
2835 **
2836 ** @release 6.1.0
2837 ** @@
2838 ******************************************************************************/
2839
ajFeattableGetSize(const AjPFeattable thys)2840 ajuint ajFeattableGetSize(const AjPFeattable thys)
2841 {
2842 if(!thys)
2843 return 0;
2844
2845 return (ajuint) ajListGetLength(thys->Features);
2846 }
2847
2848
2849
2850
2851 /* @func ajFeattableGetScorerange *********************************************
2852 **
2853 ** Returns the range of scores for feature table object.
2854 **
2855 ** @param [r] thys [const AjPFeattable] Feature table
2856 ** @param [w] minscore [float*] Minimum score
2857 ** @param [w] maxscore [float*] Maximum score
2858 ** @return [AjBool] True if scores were found
2859 **
2860 ** @release 6.5.0
2861 ** @@
2862 ******************************************************************************/
2863
ajFeattableGetScorerange(const AjPFeattable thys,float * minscore,float * maxscore)2864 AjBool ajFeattableGetScorerange(const AjPFeattable thys,
2865 float *minscore, float *maxscore)
2866 {
2867 AjBool ret = ajFalse;
2868 float curmin = 0.0;
2869 float curmax = 0.0;
2870 AjIList iter;
2871 AjPFeature gf = NULL;
2872
2873 if(!thys)
2874 return 0;
2875
2876 *minscore = 0.0;
2877 *maxscore = 0.0;
2878
2879 iter = ajListIterNewread(thys->Features);
2880 while(!ajListIterDone(iter))
2881 {
2882 gf = ajListIterGet(iter);
2883
2884 curmin = 0.0;
2885 curmax = 0.0;
2886
2887 if(ajFeatGetScorerange(gf, &curmin, &curmax))
2888 {
2889 if(curmin < *minscore)
2890 {
2891 ret = ajTrue;
2892 *minscore = curmin;
2893 }
2894 if(curmax > *maxscore)
2895 {
2896 ret = ajTrue;
2897 *maxscore = curmax;
2898 }
2899 }
2900 }
2901
2902 ajListIterDel(&iter);
2903
2904 return ret;
2905 }
2906
2907
2908
2909
2910 /* @func ajFeatGetScorerange **************************************************
2911 **
2912 ** Returns the range of scores for a feature object.
2913 **
2914 ** @param [r] thys [const AjPFeature] Feature
2915 ** @param [w] minscore [float*] Minimum score
2916 ** @param [w] maxscore [float*] Maximum score
2917 ** @return [AjBool] True if scores were found
2918 **
2919 ** @release 6.5.0
2920 ** @@
2921 ******************************************************************************/
2922
ajFeatGetScorerange(const AjPFeature thys,float * minscore,float * maxscore)2923 AjBool ajFeatGetScorerange(const AjPFeature thys,
2924 float *minscore, float *maxscore)
2925 {
2926 AjBool ret = ajFalse;
2927 float curmin = 0.0;
2928 float curmax = 0.0;
2929 AjIList iter;
2930 AjPFeature gf = NULL;
2931
2932 if(!thys)
2933 return 0;
2934
2935 *minscore = 0.0;
2936 *maxscore = 0.0;
2937
2938 if(thys->Score < *minscore)
2939 {
2940 ret = ajTrue;
2941 *minscore = curmin;
2942 }
2943 if(thys->Score > *maxscore)
2944 {
2945 ret = ajTrue;
2946 *maxscore = curmax;
2947 }
2948
2949 iter = ajListIterNewread(thys->Subfeatures);
2950 while(!ajListIterDone(iter))
2951 {
2952 gf = ajListIterGet(iter);
2953
2954 curmin = 0.0;
2955 curmax = 0.0;
2956
2957 if(ajFeatGetScorerange(gf, &curmin, &curmax))
2958 {
2959 if(curmin < *minscore)
2960 {
2961 ret = ajTrue;
2962 *minscore = curmin;
2963 }
2964 if(curmax > *maxscore)
2965 {
2966 ret = ajTrue;
2967 *maxscore = curmax;
2968 }
2969 }
2970 }
2971
2972 ajListIterDel(&iter);
2973
2974 return ret;
2975 }
2976
2977
2978
2979
2980 /* @func ajFeatGetFlags *******************************************************
2981 **
2982 ** Returns the sequence matching a feature. For multiple location features
2983 ** (joins in an EMBL/GenBank feature table) the full feature table is used
2984 ** to find all exons.
2985 **
2986 ** The database name is used to retrieve sequences from other entries
2987 **
2988 ** @param [r] thys [const AjPFeature] Feature
2989 ** @param [u] Pflagstr [AjPStr*] Sequence for this feature
2990 ** @return [AjBool] True on success
2991 **
2992 ** @release 6.2.0
2993 ** @@
2994 ******************************************************************************/
2995
ajFeatGetFlags(const AjPFeature thys,AjPStr * Pflagstr)2996 AjBool ajFeatGetFlags(const AjPFeature thys, AjPStr* Pflagstr)
2997 {
2998 ajStrAssignC(Pflagstr, "");
2999
3000 if(thys->Flags & AJFEATFLAG_START_BEFORE_SEQ)
3001 ajStrAppendC(Pflagstr, "<start ");
3002 if(thys->Flags & AJFEATFLAG_END_AFTER_SEQ)
3003 ajStrAppendC(Pflagstr, ">end ");
3004 if(thys->Flags & AJFEATFLAG_BETWEEN_SEQ)
3005 ajStrAppendC(Pflagstr, "x^y ");
3006 if(thys->Flags & AJFEATFLAG_START_TWO)
3007 ajStrAppendC(Pflagstr, "startrange ");
3008 if(thys->Flags & AJFEATFLAG_END_TWO)
3009 ajStrAppendC(Pflagstr, "endrange ");
3010 if(thys->Flags & AJFEATFLAG_POINT)
3011 ajStrAppendC(Pflagstr, "single-base ");
3012 if(thys->Flags & AJFEATFLAG_COMPLEMENT_MAIN)
3013 ajStrAppendC(Pflagstr, "complement(join) ");
3014 if(thys->Flags & AJFEATFLAG_MULTIPLE)
3015 ajStrAppendC(Pflagstr, "multiple ");
3016 if(thys->Flags & AJFEATFLAG_GROUP)
3017 ajStrAppendC(Pflagstr, "group ");
3018 if(thys->Flags & AJFEATFLAG_ORDER)
3019 ajStrAppendC(Pflagstr, "order ");
3020 if(thys->Flags & AJFEATFLAG_ONEOF)
3021 ajStrAppendC(Pflagstr, "oneof ");
3022 if(thys->Flags & AJFEATFLAG_REMOTEID)
3023 ajStrAppendC(Pflagstr, "remoteid ");
3024 if(thys->Flags & AJFEATFLAG_LABEL)
3025 ajStrAppendC(Pflagstr, "LABEL ");
3026 if(thys->Flags & AJFEATFLAG_START_UNSURE)
3027 ajStrAppendC(Pflagstr, "start-unsure ");
3028 if(thys->Flags & AJFEATFLAG_END_UNSURE)
3029 ajStrAppendC(Pflagstr, "end-unsure ");
3030
3031 ajStrTrimWhite(Pflagstr);
3032
3033 return ajTrue;
3034 }
3035
3036
3037
3038
3039 /* @func ajFeatGetSeq *********************************************************
3040 **
3041 ** Returns the sequence matching a feature.
3042 **
3043 ** The database name is used to retrieve sequences from other entries
3044 **
3045 ** @param [r] thys [const AjPFeature] Feature
3046 ** @param [r] seq [const AjPSeq] Sequence for the current feature table
3047 ** @param [u] Pseqstr [AjPStr*] Sequence for this feature
3048 ** @return [AjBool] True on success
3049 **
3050 ** @release 6.1.0
3051 ** @@
3052 ******************************************************************************/
3053
ajFeatGetSeq(const AjPFeature thys,const AjPSeq seq,AjPStr * Pseqstr)3054 AjBool ajFeatGetSeq(const AjPFeature thys,
3055 const AjPSeq seq, AjPStr* Pseqstr)
3056 {
3057 AjPSeq remoteseq = NULL;
3058 /* AjBool isjoin = ajFalse; */
3059 AjPStr tmpseq = NULL;
3060 AjBool compjoin = ajFalse;
3061
3062 ajStrSetClear(Pseqstr);
3063
3064 /* isjoin = ajFeatIsMultiple(thys); */
3065
3066 ajDebug("ajFeatGetSeq usa:%S\n",
3067 ajSeqGetUsaS(seq));
3068
3069 if(thys->Flags & AJFEATFLAG_BETWEEN_SEQ)
3070 return ajTrue;
3071
3072 ajFeatTrace(thys);
3073
3074 if(thys->Flags & AJFEATFLAG_REMOTEID)
3075 {
3076 if(!remoteseq)
3077 remoteseq = ajSeqNew();
3078
3079 ajFeatGetRemoteseq(thys, ajSeqGetUsaS(seq), remoteseq);
3080 ajStrAppendS(Pseqstr, ajSeqGetSeqS(remoteseq));
3081 }
3082 else
3083 {
3084 if(thys->Strand == '-' && !compjoin)
3085 {
3086 ajStrAppendSubS(&tmpseq, ajSeqGetSeqS(seq),
3087 ajFeatGetStart(thys)-1, ajFeatGetEnd(thys)-1);
3088 ajSeqstrReverse(&tmpseq);
3089 ajStrInsertS(Pseqstr, 0, tmpseq);
3090 ajStrDel(&tmpseq);
3091 }
3092 else
3093 {
3094 ajStrAppendSubS(Pseqstr, ajSeqGetSeqS(seq),
3095 ajFeatGetStart(thys)-1, ajFeatGetEnd(thys)-1);
3096 }
3097 }
3098
3099 ajSeqDel(&remoteseq);
3100
3101 return ajTrue;
3102 }
3103
3104
3105
3106
3107 /* @func ajFeatGetSeqJoin *****************************************************
3108 **
3109 ** Returns the sequence matching a feature. For multiple location features
3110 ** (joins in an EMBL/GenBank feature table) the full feature table is used
3111 ** to find all exons.
3112 **
3113 ** The database name is used to retrieve sequences from other entries
3114 **
3115 ** @param [r] thys [const AjPFeature] Feature
3116 ** @param [r] seq [const AjPSeq] Sequence for the current feature table
3117 ** @param [u] Pseqstr [AjPStr*] Sequence for this feature
3118 ** @return [AjBool] True on success
3119 **
3120 ** @release 6.2.0
3121 ** @@
3122 ******************************************************************************/
3123
ajFeatGetSeqJoin(const AjPFeature thys,const AjPSeq seq,AjPStr * Pseqstr)3124 AjBool ajFeatGetSeqJoin(const AjPFeature thys,
3125 const AjPSeq seq, AjPStr* Pseqstr)
3126 {
3127 const AjPFeature gf;
3128 AjIList iter = NULL;
3129 AjPSeq remoteseq = NULL;
3130 /* AjBool isjoin = ajFalse; */
3131 AjPStr tmpseq = NULL;
3132 AjBool compjoin = ajFalse;
3133 AjPStr flags = NULL;
3134 ajuint count=0;
3135
3136 ajDebug("ajFeatGetSeqJoin nfeat:%Lu usa:%S %u..%u %S\n",
3137 ajListGetLength(thys->Subfeatures), ajSeqGetUsaS(seq),
3138 thys->Start, thys->End, thys->Type);
3139
3140 if(!ajListGetLength(thys->Subfeatures))
3141 return ajFeatGetSeq(thys, seq, Pseqstr);
3142
3143 ajStrSetClear(Pseqstr);
3144
3145 /* isjoin = ajFeatIsMultiple(thys); */
3146 if(thys->Flags & AJFEATFLAG_COMPLEMENT_MAIN)
3147 compjoin = ajTrue;
3148
3149
3150 iter = ajListIterNewread(thys->Subfeatures);
3151
3152 while(!ajListIterDone(iter))
3153 {
3154 count++;
3155 gf = (const AjPFeature) ajListIterGet(iter);
3156
3157 ajFeatGetFlags(gf, &flags);
3158 ajFeatTrace(gf);
3159
3160 if(gf->Flags & AJFEATFLAG_BETWEEN_SEQ)
3161 continue;
3162
3163 if(gf->Flags & AJFEATFLAG_REMOTEID)
3164 {
3165 if(!remoteseq)
3166 remoteseq = ajSeqNew();
3167
3168 ajFeatGetRemoteseq(gf, ajSeqGetUsaS(seq), remoteseq);
3169 ajStrAppendS(Pseqstr, ajSeqGetSeqS(remoteseq));
3170 }
3171 else
3172 {
3173 if(gf->Strand == '-' && !compjoin)
3174 {
3175 ajStrAppendSubS(&tmpseq, ajSeqGetSeqS(seq),
3176 ajFeatGetStart(gf)-1, ajFeatGetEnd(gf)-1);
3177 ajSeqstrReverse(&tmpseq);
3178 ajStrAppendS(Pseqstr, tmpseq);
3179 ajStrDel(&tmpseq);
3180 }
3181 else
3182 {
3183 ajStrAppendSubS(Pseqstr, ajSeqGetSeqS(seq),
3184 ajFeatGetStart(gf)-1, ajFeatGetEnd(gf)-1);
3185 }
3186 }
3187 }
3188
3189 if(compjoin)
3190 ajSeqstrReverse(Pseqstr);
3191
3192 ajListIterDel(&iter);
3193 ajSeqDel(&remoteseq);
3194 ajStrDel(&flags);
3195
3196 return ajTrue;
3197 }
3198
3199
3200
3201
3202 /* @func ajFeatGetRemoteseq ***************************************************
3203 **
3204 ** Returns a sequence entry from a feature location which points to
3205 ** another entry
3206 **
3207 ** @param [r] thys [const AjPFeature] Feature
3208 ** @param [r] usa [const AjPStr] usa of query
3209 ** @param [u] seq [AjPSeq] Sequence object for results
3210 ** @return [AjBool] True on success
3211 **
3212 ** @release 6.1.0
3213 ** @@
3214 ******************************************************************************/
3215
ajFeatGetRemoteseq(const AjPFeature thys,const AjPStr usa,AjPSeq seq)3216 AjBool ajFeatGetRemoteseq(const AjPFeature thys, const AjPStr usa,
3217 AjPSeq seq)
3218 {
3219 AjPStr baseusa = NULL;
3220 ajuint ilen;
3221 const AjPStr remoteid = NULL;
3222
3223 remoteid = ajSeqtestIsSeqversion(thys->Remote);
3224
3225 if(!remoteid)
3226 remoteid = thys->Remote;
3227
3228 ajSeqUsaGetBase(usa, &baseusa);
3229
3230 ajStrAppendK(&baseusa, ':');
3231 ajStrAppendS(&baseusa, remoteid);
3232 ajSeqGetFromUsa(baseusa, thys->Protein, seq);
3233
3234 ilen = ajSeqGetLen(seq);
3235
3236 if(thys->Strand == '-')
3237 ajSeqSetRangeRev(seq, ajFeatGetStart(thys), ajFeatGetEnd(thys));
3238 else
3239 ajSeqSetRange(seq, ajFeatGetStart(thys), ajFeatGetEnd(thys));
3240
3241 ajSeqTrim(seq);
3242
3243 ajDebug("ajFeatGetRemoteseq (%S) '%S' => '%S' %u %u..%u (%u)\n",
3244 thys->Remote, usa, baseusa, ilen,
3245 ajFeatGetStart(thys), ajFeatGetEnd(thys), ajSeqGetLen(seq));
3246
3247 ajStrDel(&baseusa);
3248
3249 return ajTrue;
3250 }
3251
3252
3253
3254
3255 /* @func ajFeatGetSubtype *****************************************************
3256 **
3257 ** Returns the feature type of the first subfeature
3258 **
3259 ** @param [r] thys [const AjPFeature] Feature
3260 ** @return [const AjPStr] Subfeature type
3261 **
3262 ** @release 6.5.0
3263 ** @@
3264 ******************************************************************************/
3265
ajFeatGetSubtype(const AjPFeature thys)3266 const AjPStr ajFeatGetSubtype(const AjPFeature thys)
3267 {
3268 AjPFeature subft= NULL;
3269
3270 if(!ajListGetLength(thys->Subfeatures))
3271 return NULL;
3272
3273 ajListPeek(thys->Subfeatures, (void**) &subft);
3274
3275 return subft->Type;
3276 }
3277
3278
3279
3280
3281 /* @func ajFeatGetXrefs *******************************************************
3282 **
3283 ** Returns all cross-references from a feature
3284 **
3285 ** @param [r] thys [const AjPFeature] Feature
3286 ** @param [u] Pxreflist [AjPList*] List of sequence cross-reference objects
3287 ** @return [AjBool] True on success
3288 **
3289 ** @release 6.1.0
3290 ** @@
3291 ******************************************************************************/
3292
ajFeatGetXrefs(const AjPFeature thys,AjPList * Pxreflist)3293 AjBool ajFeatGetXrefs(const AjPFeature thys, AjPList *Pxreflist)
3294 {
3295 AjIList iter = NULL;
3296 AjPTagval item = NULL;
3297 AjPSeqXref xref = NULL;
3298 ajlong ipos;
3299 ajuint inum = 0;
3300 AjPList xreflist;
3301 AjPStrTok handle = NULL;
3302 AjPStr tmpstr = NULL;
3303 const AjPStr tagval = NULL;
3304
3305 if(!*Pxreflist)
3306 *Pxreflist = ajListNew();
3307 xreflist = *Pxreflist;
3308
3309 if(thys->Tags)
3310 {
3311 iter = ajListIterNewread(thys->Tags);
3312
3313 while(!ajListIterDone(iter))
3314 {
3315 item = (AjPTagval)ajListIterGet(iter);
3316
3317 if(ajStrMatchCaseC(MAJTAGVALGETTAG(item), "db_xref"))
3318 {
3319 tagval = ajTagvalGetValue(item);
3320 ipos = ajStrFindAnyK(tagval, ':');
3321
3322 if(ipos > 0)
3323 {
3324 inum++;
3325 xref = ajSeqxrefNew();
3326 ajStrAssignSubS(&xref->Db, tagval, 0, ipos-1);
3327 ajStrAssignSubS(&xref->Id, tagval, ipos+1, -1);
3328 xref->Start = ajFeatGetStart(thys)-1;
3329 xref->End = ajFeatGetEnd(thys)-1;
3330 ajListPushAppend(xreflist, xref);
3331 xref->Type = XREF_DBXREF;
3332 xref = NULL;
3333 }
3334 }
3335 }
3336
3337 ajListIterDel(&iter);
3338 }
3339
3340 if(thys->GffTags)
3341 {
3342 iter = ajListIterNewread(thys->GffTags);
3343
3344 while(!ajListIterDone(iter))
3345 {
3346 item = (AjPTagval)ajListIterGet(iter);
3347
3348 if(ajStrMatchCaseC(MAJTAGVALGETTAG(item), "Dbxref"))
3349 {
3350 tagval = ajTagvalGetValue(item);
3351 handle = ajStrTokenNewC(tagval, ",");
3352
3353 while(ajStrTokenNextParse(handle, &tmpstr))
3354 {
3355 ipos = ajStrFindAnyK(tmpstr, ':');
3356
3357 if(ipos > 0)
3358 {
3359 inum++;
3360 xref = ajSeqxrefNew();
3361 ajStrAssignSubS(&xref->Db,
3362 tmpstr, 0, ipos-1);
3363 ajStrAssignSubS(&xref->Id,
3364 tmpstr, ipos+1, -1);
3365 ajListPushAppend(xreflist, xref);
3366 xref->Start = ajFeatGetStart(thys);
3367 xref->End = ajFeatGetEnd(thys);
3368 xref->Type = XREF_DBXREF;
3369 }
3370 }
3371
3372 ajStrTokenDel(&handle);
3373 ajStrDel(&tmpstr);
3374 }
3375 }
3376
3377 ajListIterDel(&iter);
3378 }
3379
3380 if(!inum)
3381 return ajFalse;
3382
3383 return ajTrue;
3384 }
3385
3386
3387
3388
3389 /* @func ajFeatLocMark ********************************************************
3390 **
3391 ** Returns a sequence entry converted to lower case where a feature
3392 ** location matches.
3393 **
3394 ** @param [r] thys [const AjPFeature] Feature
3395 ** @param [r] table [const AjPFeattable] Feature table
3396 ** @param [u] Pseqstr [AjPStr*] Sequence to be marked in lower case
3397 ** @return [AjBool] true on success
3398 **
3399 ** @release 4.1.0
3400 ** @@
3401 ******************************************************************************/
3402
ajFeatLocMark(const AjPFeature thys,const AjPFeattable table,AjPStr * Pseqstr)3403 AjBool ajFeatLocMark(const AjPFeature thys, const AjPFeattable table,
3404 AjPStr* Pseqstr)
3405 {
3406 const AjPFeature gf;
3407 AjIList iter = NULL;
3408
3409 iter = ajListIterNewread(table->Features);
3410
3411 while(!ajListIterDone(iter))
3412 {
3413 gf = (const AjPFeature) ajListIterGet(iter);
3414
3415 if(gf->Group == thys->Group)
3416 {
3417 if(gf->Flags & AJFEATFLAG_BETWEEN_SEQ)
3418 continue;
3419
3420 if(gf->Flags & AJFEATFLAG_REMOTEID)
3421 continue;
3422
3423 ajStrFmtLowerSub(Pseqstr,ajFeatGetStart(gf)-1,ajFeatGetEnd(gf)-1);
3424 }
3425 }
3426
3427 ajListIterDel(&iter);
3428
3429 return ajTrue;
3430 }
3431
3432
3433
3434
3435 /* @func ajFeatGetNoteC *******************************************************
3436 **
3437 ** Finds a named note tag (with a * prefix)
3438 **
3439 ** @param [r] thys [const AjPFeature] Feature object
3440 ** @param [r] name [const char*] Tag name
3441 ** @param [w] val [AjPStr*] Tag value (if found)
3442 **
3443 ** @return [AjBool] ajTrue on success (feature tag found)
3444 **
3445 ** @release 4.0.0
3446 ** @@
3447 ******************************************************************************/
3448
ajFeatGetNoteC(const AjPFeature thys,const char * name,AjPStr * val)3449 AjBool ajFeatGetNoteC(const AjPFeature thys, const char* name, AjPStr* val)
3450 {
3451 return ajFeatGetNoteCI(thys, name, 0, val);
3452 }
3453
3454
3455
3456
3457 /* @func ajFeatGetNoteCI ******************************************************
3458 **
3459 ** Finds a named note tag (with a * prefix)
3460 **
3461 ** @param [r] thys [const AjPFeature] Feature object
3462 ** @param [r] name [const char*] Tag name
3463 ** @param [r] count [ajint] Tag count: zero for any, 1 for first, 2 for second
3464 ** @param [w] val [AjPStr*] Tag value (if found)
3465 **
3466 ** @return [AjBool] ajTrue on success (feature tag found)
3467 **
3468 ** @release 4.0.0
3469 ** @@
3470 ******************************************************************************/
3471
ajFeatGetNoteCI(const AjPFeature thys,const char * name,ajint count,AjPStr * val)3472 AjBool ajFeatGetNoteCI(const AjPFeature thys, const char* name, ajint count,
3473 AjPStr* val)
3474 {
3475 AjIList iter = NULL;
3476 AjPTagval item = NULL;
3477 ajint icount = 0;
3478 ajuint ilen = strlen(name);
3479 const AjPStr tagval = NULL;
3480
3481 /*ajDebug("ajFeatGetNoteCI '%s'\n", name);*/
3482
3483 if(thys->Tags)
3484 {
3485 iter = ajListIterNewread(thys->Tags);
3486
3487 while(!ajListIterDone(iter))
3488 {
3489 item = (AjPTagval)ajListIterGet(iter);
3490 if(ajFeattagIsNote(MAJTAGVALGETTAG(item)))
3491 {
3492 tagval = ajTagvalGetValue(item);
3493 if(ajStrGetCharFirst(tagval) == '*')
3494 {
3495 /*ajDebug(" testing *name\n");*/
3496 if(ajCharPrefixCaseC(ajStrGetPtr(tagval)+1, name))
3497 {
3498 icount++;
3499 /*ajDebug(" found [%d] '%S'\n", icount, name);*/
3500
3501 if(icount >= count)
3502 {
3503 if(ajStrGetLen(tagval) > (ilen+1))
3504 {
3505 if(ajStrGetCharPos(tagval, ilen+1) != ' ')
3506 return ajFalse;
3507
3508 ajStrAssignC(val,
3509 ajStrGetPtr(tagval) +
3510 ilen+2);
3511
3512 }
3513 else /* no value */
3514 ajStrAssignClear(val);
3515
3516 ajListIterDel(&iter);
3517 return ajTrue;
3518 }
3519 }
3520 }
3521 }
3522 }
3523 }
3524
3525 ajStrDel(val);
3526 ajListIterDel(&iter);
3527
3528 return ajFalse;
3529 }
3530
3531
3532
3533
3534 /* @func ajFeatGetNoteSI ******************************************************
3535 **
3536 ** Finds a named note tag (with a * prefix)
3537 **
3538 ** @param [r] thys [const AjPFeature] Feature object
3539 ** @param [r] name [const AjPStr] Tag name
3540 ** @param [r] count [ajint] Tag count: zero for any, 1 for first, 2 for second
3541 ** @param [w] val [AjPStr*] Tag value (if found)
3542 **
3543 ** @return [AjBool] ajTrue on success (feature tag found)
3544 **
3545 ** @release 6.2.0
3546 ** @@
3547 ******************************************************************************/
3548
ajFeatGetNoteSI(const AjPFeature thys,const AjPStr name,ajint count,AjPStr * val)3549 AjBool ajFeatGetNoteSI(const AjPFeature thys, const AjPStr name, ajint count,
3550 AjPStr* val)
3551 {
3552 return ajFeatGetNoteCI(thys, ajStrGetPtr(name), count, val);
3553 }
3554
3555
3556
3557
3558 /* @func ajFeatGetNoteS *******************************************************
3559 **
3560 ** Finds a named note tag (with a * prefix)
3561 **
3562 ** @param [r] thys [const AjPFeature] Feature object
3563 ** @param [r] name [const AjPStr] Tag name
3564 ** @param [w] val [AjPStr*] Tag value (if found)
3565 **
3566 ** @return [AjBool] ajTrue on success (feature tag found)
3567 **
3568 ** @release 6.2.0
3569 ** @@
3570 ******************************************************************************/
3571
ajFeatGetNoteS(const AjPFeature thys,const AjPStr name,AjPStr * val)3572 AjBool ajFeatGetNoteS(const AjPFeature thys, const AjPStr name, AjPStr* val)
3573 {
3574 return ajFeatGetNoteSI(thys, name, 0, val);
3575 }
3576
3577
3578
3579
3580 /* @func ajFeatGetTagC ********************************************************
3581 **
3582 ** Returns the nth value of a named feature tag.
3583 **
3584 ** If not found as a tag, also searches for a named note
3585 **
3586 ** @param [r] thys [const AjPFeature] Feature object
3587 ** @param [r] tname [const char*] Tag name
3588 ** @param [r] num [ajint] Tag number
3589 ** @param [w] Pval [AjPStr*] Tag value (if found)
3590 **
3591 ** @return [AjBool] ajTrue on success (feature tag found)
3592 **
3593 ** @release 6.1.0
3594 ** @@
3595 ******************************************************************************/
3596
ajFeatGetTagC(const AjPFeature thys,const char * tname,ajint num,AjPStr * Pval)3597 AjBool ajFeatGetTagC(const AjPFeature thys, const char* tname, ajint num,
3598 AjPStr* Pval)
3599 {
3600 AjIList iter = NULL;
3601 AjPTagval item = NULL;
3602 ajint inum = 0;
3603 AjBool isnote;
3604 ajint noteposcolon=0;
3605 ajint noteposvalue=0;
3606 const AjPStr tagval = NULL;
3607
3608 ajDebug("ajFeatGetTagC '%s'\n", tname);
3609 isnote = ajCharMatchC(tname, "note");
3610 noteposcolon = strlen(tname) + 1;
3611 noteposvalue = strlen(tname) + 3;
3612
3613 if(thys->Tags)
3614 {
3615 iter = ajListIterNewread(thys->Tags);
3616 while(!ajListIterDone(iter))
3617 {
3618 item = (AjPTagval)ajListIterGet(iter);
3619 tagval = ajTagvalGetValue(item);
3620
3621 ajDebug("testing '%S'\n", ajTagvalGetTag(item));
3622
3623 if(ajStrMatchCaseC(MAJTAGVALGETTAG(item), tname))
3624 {
3625 inum++;
3626 ajDebug("test1 inum %d\n", inum);
3627
3628 if(num == inum)
3629 {
3630 ajDebug("++match1\n");
3631 ajStrAssignS(Pval, tagval);
3632 ajListIterDel(&iter);
3633 return ajTrue;
3634 }
3635 }
3636 else if(!isnote &&
3637 ajStrMatchCaseC(MAJTAGVALGETTAG(item), "note") &&
3638 ajStrGetCharFirst(tagval) == '*' &&
3639 ajCharPrefixCaseC(ajStrGetPtr(tagval)+1, tname) &&
3640 ajStrGetCharPos(tagval, noteposcolon) == ':')
3641 {
3642 inum++;
3643 ajDebug("test2 inum %d\n", inum);
3644
3645 if(num == inum)
3646 {
3647 ajDebug("++match2 from %d\n", noteposvalue);
3648 ajStrAssignSubS(Pval, tagval, noteposvalue, -1);
3649 ajListIterDel(&iter);
3650 return ajTrue;
3651 }
3652 }
3653 }
3654 }
3655
3656 ajDebug("No match to '%s'\n", tname);
3657
3658 ajStrDel(Pval);
3659 ajListIterDel(&iter);
3660
3661 return ajFalse;
3662 }
3663
3664
3665
3666
3667 /* @func ajFeatGetTagS ********************************************************
3668 **
3669 ** Returns the nth value of a named feature tag.
3670 **
3671 ** If not found as a tag, also searches for a named note
3672 **
3673 ** @param [r] thys [const AjPFeature] Feature object
3674 ** @param [r] name [const AjPStr] Tag name
3675 ** @param [r] num [ajint] Tag number
3676 ** @param [w] val [AjPStr*] Tag value (if found)
3677 **
3678 ** @return [AjBool] ajTrue on success (feature tag found)
3679 **
3680 ** @release 6.1.0
3681 ** @@
3682 ******************************************************************************/
3683
ajFeatGetTagS(const AjPFeature thys,const AjPStr name,ajint num,AjPStr * val)3684 AjBool ajFeatGetTagS(const AjPFeature thys, const AjPStr name, ajint num,
3685 AjPStr* val)
3686 {
3687 AjIList iter = NULL;
3688 AjPTagval item = NULL;
3689 ajint inum = 0;
3690 AjBool isnote;
3691 ajint noteposcolon=0;
3692 ajint noteposvalue=0;
3693 const AjPStr tagval = NULL;
3694
3695 isnote = ajStrMatchC(name, "note");
3696 noteposcolon = ajStrGetLen(name) + 1;
3697 noteposvalue = ajStrGetLen(name) + 3;
3698
3699 if(thys->Tags)
3700 {
3701 iter = ajListIterNewread(thys->Tags);
3702
3703 while(!ajListIterDone(iter))
3704 {
3705 item = (AjPTagval)ajListIterGet(iter);
3706 tagval = ajTagvalGetValue(item);
3707 if(ajStrMatchCaseS(MAJTAGVALGETTAG(item), name))
3708 {
3709 inum++;
3710
3711 if(num == inum)
3712 {
3713 ajStrAssignS(val, tagval);
3714 ajListIterDel(&iter);
3715 return ajTrue;
3716 }
3717 }
3718 else if(!isnote &&
3719 ajStrMatchCaseC(MAJTAGVALGETTAG(item), "note") &&
3720 ajStrGetCharFirst(tagval) == '*' &&
3721 ajCharPrefixCaseS(ajStrGetPtr(tagval)+1, name) &&
3722 ajStrGetCharPos(tagval, noteposcolon) == ':')
3723 {
3724 inum++;
3725
3726 if(num == inum)
3727 {
3728 ajStrAssignSubS(val, tagval, noteposvalue, -1);
3729 ajListIterDel(&iter);
3730 return ajTrue;
3731 }
3732 }
3733 }
3734 }
3735
3736 ajStrDel(val);
3737 ajListIterDel(&iter);
3738
3739 return ajFalse;
3740 }
3741
3742
3743
3744
3745 /* @func ajFeatGetType ********************************************************
3746 **
3747 ** Returns the type (key) of a feature object. This is a copy of the
3748 ** pointer to the type, and is still owned by the feature
3749 ** and is not to be destroyed.
3750 **
3751 ** @param [r] thys [const AjPFeature] Feature object
3752 **
3753 ** @return [const AjPStr] Feature type, read only
3754 **
3755 ** @release 2.1.0
3756 ** @@
3757 ******************************************************************************/
3758
ajFeatGetType(const AjPFeature thys)3759 const AjPStr ajFeatGetType(const AjPFeature thys)
3760 {
3761 if(!FeatInitDone)
3762 featInit();
3763
3764 if(thys->Protein)
3765 return ajFeattypeGetExternal(thys->Type, FeatTypeTableProtein);
3766 else
3767 return ajFeattypeGetExternal(thys->Type, FeatTypeTableDna);
3768 }
3769
3770
3771
3772
3773 /* @func ajFeatGetSource*******************************************************
3774 **
3775 ** Returns the source name of a feature object.
3776 **
3777 ** @param [r] thys [const AjPFeature] Feature object
3778 **
3779 ** @return [const AjPStr] Feature source name
3780 **
3781 ** @release 4.0.0
3782 ** @@
3783 ******************************************************************************/
3784
ajFeatGetSource(const AjPFeature thys)3785 const AjPStr ajFeatGetSource(const AjPFeature thys)
3786 {
3787 return thys->Source;
3788 }
3789
3790
3791
3792
3793 /* @func ajFeatGetStart *******************************************************
3794 **
3795 ** Returns the start position of a feature object.
3796 **
3797 ** @param [r] thys [const AjPFeature] Feature object
3798 **
3799 ** @return [ajuint] Feature start position
3800 **
3801 ** @release 2.1.0
3802 ** @@
3803 ******************************************************************************/
3804
ajFeatGetStart(const AjPFeature thys)3805 ajuint ajFeatGetStart(const AjPFeature thys)
3806 {
3807 if((thys->Flags & AJFEATFLAG_START_TWO) &&
3808 (thys->Start2 < thys->Start))
3809 return thys->Start2;
3810
3811 return thys->Start;
3812 }
3813
3814
3815
3816
3817 /* @func ajFeatGetStrand ******************************************************
3818 **
3819 ** Returns the strand of a feature object.
3820 **
3821 ** @param [r] thys [const AjPFeature] Feature object
3822 **
3823 ** @return [char] Feature strand code
3824 **
3825 ** @release 4.0.0
3826 ** @@
3827 ******************************************************************************/
3828
ajFeatGetStrand(const AjPFeature thys)3829 char ajFeatGetStrand(const AjPFeature thys)
3830 {
3831 if(thys->Protein)
3832 return '.';
3833
3834 if(thys->Strand == '-')
3835 return '-';
3836 else
3837 return '+';
3838 }
3839
3840
3841
3842
3843 /* @func ajFeatGetEnd *********************************************************
3844 **
3845 ** Returns the end position of a feature object.
3846 **
3847 ** @param [r] thys [const AjPFeature] Feature object
3848 **
3849 ** @return [ajuint] Feature end position
3850 **
3851 ** @release 2.1.0
3852 ** @@
3853 ******************************************************************************/
3854
ajFeatGetEnd(const AjPFeature thys)3855 ajuint ajFeatGetEnd(const AjPFeature thys)
3856 {
3857 if((thys->Flags & AJFEATFLAG_END_TWO) &&
3858 (thys->End2 < thys->End))
3859 return thys->End2;
3860
3861 return thys->End;
3862 }
3863
3864
3865
3866
3867 /* @func ajFeatGetLength ******************************************************
3868 **
3869 ** Returns the sequence length of a feature object.
3870 **
3871 ** @param [r] thys [const AjPFeature] Feature object
3872 **
3873 ** @return [ajuint] Feature length
3874 **
3875 ** @release 4.0.0
3876 ** @@
3877 ******************************************************************************/
3878
ajFeatGetLength(const AjPFeature thys)3879 ajuint ajFeatGetLength(const AjPFeature thys)
3880 {
3881 return thys->End - thys->Start + 1;
3882 }
3883
3884
3885
3886
3887 /* @func ajFeatGetScore *******************************************************
3888 **
3889 ** Returns the score of a feature object.
3890 **
3891 ** @param [r] thys [const AjPFeature] Feature object
3892 **
3893 ** @return [float] Feature score
3894 **
3895 ** @release 4.0.0
3896 ** @@
3897 ******************************************************************************/
3898
ajFeatGetScore(const AjPFeature thys)3899 float ajFeatGetScore(const AjPFeature thys)
3900 {
3901 return thys->Score;
3902 }
3903
3904
3905
3906
3907 /* @func ajFeatGetForward *****************************************************
3908 **
3909 ** Returns the direction of a feature object.
3910 **
3911 ** @param [r] thys [const AjPFeature] Feature object
3912 **
3913 ** @return [AjBool] ajTrue for a forward direction, ajFalse for reverse
3914 **
3915 ** @release 2.1.0
3916 ** @@
3917 ******************************************************************************/
3918
ajFeatGetForward(const AjPFeature thys)3919 AjBool ajFeatGetForward(const AjPFeature thys)
3920 {
3921 if(ajSysCastItoc(thys->Strand) != '-')
3922 return ajTrue;
3923
3924 return ajFalse;
3925 }
3926
3927
3928
3929
3930 /* @func ajFeatGetFrame *******************************************************
3931 **
3932 ** Returns the reading frame of a feature object.
3933 **
3934 ** @param [r] thys [const AjPFeature] Feature object
3935 **
3936 ** @return [ajint] Feature reading frame (zero for undefined)
3937 **
3938 ** @release 2.1.0
3939 ** @@
3940 ******************************************************************************/
3941
ajFeatGetFrame(const AjPFeature thys)3942 ajint ajFeatGetFrame(const AjPFeature thys)
3943 {
3944 return thys->Frame;
3945 }
3946
3947
3948
3949
3950 /* @func ajFeatGetTranslation *************************************************
3951 **
3952 ** Returns translation tag value
3953 **
3954 ** @param [r] thys [const AjPFeature] Feature
3955 ** @param [w] Ptrans [AjPStr*] Translations
3956 **
3957 ** @return [AjBool] True if translation tag was found
3958 **
3959 ** @release 6.1.0
3960 ** @@
3961 ******************************************************************************/
3962
ajFeatGetTranslation(const AjPFeature thys,AjPStr * Ptrans)3963 AjBool ajFeatGetTranslation(const AjPFeature thys, AjPStr *Ptrans)
3964 {
3965 return ajFeatGetTagC(thys, "translation", 1, Ptrans);
3966 }
3967
3968
3969
3970
3971 /*========================================================================
3972 ======================= NEW FUNCTIONS ====================================
3973 ========================================================================*/
3974
3975
3976
3977
3978 /* @func ajFeatTest ***********************************************************
3979 **
3980 ** Temporary testing function for feature handling
3981 ** to be deleted when all is working happily
3982 **
3983 ** @return [void]
3984 **
3985 ** @release 2.0.0
3986 ** @@
3987 ******************************************************************************/
3988
ajFeatTest(void)3989 void ajFeatTest(void)
3990 {
3991 AjPFeattable table = NULL;
3992 AjPStr desc = NULL;
3993 AjPStr source = NULL;
3994 AjPStr type = NULL;
3995 AjPFeature ft = NULL;
3996
3997 featInit();
3998 table = ajFeattableNew(NULL);
3999
4000 ajStrAssignC(&source, "testft");
4001 ajStrAssignC(&type, "misc_feature");
4002 ajStrAssignC(&desc, "Just testing");
4003
4004 ft = ajFeatNew(table, source, type, 5, 7, (float)1.23, '+', 0);
4005 ajFeatSetDesc(ft, desc);
4006
4007 ajStrAssignC(&desc, "Testing again");
4008 ft = ajFeatNew(table, source, type, 9, 19, (float)4.56, '-', 3);
4009 ajFeatSetDesc(ft, desc);
4010
4011 ajFeattableTrace(table);
4012
4013 ajFeattableDel(&table);
4014 ajStrDel(&desc);
4015 ajStrDel(&source);
4016 ajStrDel(&type);
4017
4018 return;
4019 }
4020
4021
4022
4023
4024 /* @funcstatic featInit *******************************************************
4025 **
4026 ** Initialises everything needed for feature handling
4027 **
4028 ** @return [void]
4029 **
4030 ** @release 2.0.0
4031 ** @@
4032 ******************************************************************************/
4033
featInit(void)4034 static void featInit(void)
4035 {
4036 if(FeatInitDone)
4037 return;
4038
4039 FeatInitDone = ajTrue;
4040
4041 if(!FeatTypeTableDna)
4042 {
4043 FeatTypeTableDna = ajTablestrNewCase(200);
4044 FeatTagsTableDna = ajTablestrNewCase(200);
4045 featVocabRead("emboss",FeatTypeTableDna, FeatTagsTableDna);
4046 }
4047
4048 if(!FeatTypeTableProtein)
4049 {
4050 FeatTypeTableProtein = ajTablestrNewCase(200);
4051 FeatTagsTableProtein = ajTablestrNewCase(200);
4052 featVocabRead("protein", FeatTypeTableProtein, FeatTagsTableProtein);
4053 }
4054
4055 /*ajDebug("Tables internal (Dna, Prot) Type: %x %x Tags: %x %x\n",
4056 FeatTypeTableDna, FeatTypeTableProtein,
4057 FeatTagsTableDna, FeatTagsTableProtein);*/
4058
4059
4060 return;
4061 }
4062
4063
4064
4065
4066 /* @funcstatic featVocabRead **************************************************
4067 **
4068 ** Reads the possible feature types (keys) and tags (qualifiers)
4069 ** from files.
4070 **
4071 ** @param [r] name [const char*] Feature type ("emboss", "protein", or external
4072 ** feature types "swiss", "gff", "embl", etc.
4073 ** @param [w] pTypeTable [AjPTable] Feature type table
4074 ** @param [w] pTagsTable [AjPTable] Feature tags table
4075 ** @return [AjBool] ajTrue on success
4076 **
4077 ** @release 2.0.0
4078 ** @@
4079 ******************************************************************************/
4080
featVocabRead(const char * name,AjPTable pTypeTable,AjPTable pTagsTable)4081 static AjBool featVocabRead(const char* name,
4082 AjPTable pTypeTable, AjPTable pTagsTable)
4083 {
4084 AjPStr TypeFName = NULL;
4085 AjPStr TagsFName = NULL;
4086
4087 /* First read in the list of all possible tags */
4088
4089 ajFmtPrintS(&TagsFName, "Etags.%s", name);
4090 ajDebug("featVocabRead '%S' typetable %x tagstable %x\n",
4091 TagsFName, pTypeTable, pTagsTable);
4092
4093 if(!featVocabReadTags(TagsFName, pTagsTable, ajTrue))
4094 return ajFalse;
4095
4096 /*ajDebug("Trace tagstable '%S'", TagsFName);*/
4097 /*ajTablestrTrace(pTagsTable);*/
4098
4099 /* Efeatures file
4100 ** format: featuretype
4101 ** M/mandatorytag
4102 ** /tag
4103 ** /tag
4104 **
4105 ** All tags must be defined in the Etags file (read earlier into pTagsTable)
4106 */
4107
4108 ajFmtPrintS(&TypeFName, "Efeatures.%s", name);
4109 /*ajDebug("Trying to open %S...\n",TypeFName);*/
4110 if(!featVocabReadTypes(TypeFName, pTypeTable, pTagsTable, ajTrue))
4111 return ajFalse;
4112
4113 /*ajDebug("Trace typetable '%S'", TypeFName);*/
4114 /*ajTablestrTrace(pTypeTable);*/
4115
4116 ajStrDel(&TagsFName);
4117 ajStrDel(&TypeFName);
4118
4119 return ajTrue;
4120 }
4121
4122
4123
4124
4125 /* @funcstatic featVocabReadTags **********************************************
4126 **
4127 ** Reads the possible feature tags (qualifiers)
4128 ** from files.
4129 **
4130 ** @param [r] fname [const AjPStr] Feature tags definitions datafile name
4131 ** @param [w] pTagsTable [AjPTable] Feature tags table
4132 ** @param [r] recursion [AjBool] If true process any include lines
4133 ** @return [AjBool] ajTrue on success
4134 **
4135 ** @release 6.0.0
4136 ** @@
4137 ******************************************************************************/
4138
featVocabReadTags(const AjPStr fname,AjPTable pTagsTable,AjBool recursion)4139 static AjBool featVocabReadTags(const AjPStr fname, AjPTable pTagsTable,
4140 AjBool recursion)
4141 {
4142 AjPFile TagsFile = NULL;
4143 AjPStr TagsFName = NULL;
4144 AjPStr line = NULL;
4145 AjPStr tagname = NULL; /* stored in table */
4146 AjPStr tagstr = NULL; /* stored in table */
4147 AjPStr defname = NULL; /* stored in table */
4148 AjPStr tagtype = NULL;
4149 AjPStr token = NULL;
4150 AjPStr rest = NULL;
4151 ajint linecount = 0;
4152 ajlong tagscount = 0;
4153 ajint numtype = -1;
4154 ajint i;
4155
4156 const char* TagType[] =
4157 {
4158 "QTEXT", /* quoted text */
4159 "QWORD", /* quoted text, no space */
4160 "BTEXT", /* bracketed text */
4161 "TEXT", /* unquoted, no white space */
4162 "VOID", /* no value */
4163 "LIMITED", /* limited vocabulary */
4164 "QLIMITED", /* limited vocabulary, with quotes */
4165 "SPECIAL", /* special formatting */
4166 "QSPECIAL", /* special formatting, with quotes */
4167 "TAGVAL", /* /type=value for swissprot */
4168 NULL
4169 };
4170
4171 TagsFile = ajDatafileNewInNameS(fname);
4172
4173 if(!TagsFile)
4174 {
4175 ajErr("Unable to read feature tags data file '%S'\n", fname);
4176 return ajFalse;
4177 }
4178
4179 tagscount = ajTableGetLength(pTagsTable);
4180 linecount = 0;
4181
4182 while(ajReadlineTrim(TagsFile,&line))
4183 {
4184 linecount++;
4185 ajStrRemoveWhiteExcess(&line);
4186
4187 if(ajStrPrefixC(line, "#"))
4188 {
4189 if(recursion && ajStrPrefixCaseC(line, "#include "))
4190 {
4191 ajStrCutStart(&line, 9);
4192 ajStrExtractWord(line, &rest, &TagsFName);
4193 ajStrDel(&rest);
4194 if(!featVocabReadTags(TagsFName, pTagsTable, ajTrue))
4195 {
4196 ajStrDel(&line);
4197 ajStrDel(&TagsFName);
4198 return ajFalse;
4199 }
4200 tagscount = ajTableGetLength(pTagsTable);
4201 }
4202
4203 if(recursion && ajStrPrefixCaseC(line, "#includeonly "))
4204 {
4205 ajStrCutStart(&line, 13);
4206 ajStrExtractWord(line, &rest, &TagsFName);
4207 ajStrDel(&rest);
4208
4209 if(!featVocabReadTags(TagsFName, pTagsTable, ajFalse))
4210 {
4211 ajStrDel(&line);
4212 ajStrDel(&TagsFName);
4213 return ajFalse;
4214 }
4215 tagscount = ajTableGetLength(pTagsTable);
4216 }
4217 }
4218 else if(ajStrGetLen(line)) /* skip comments */
4219 {
4220 ajStrDel(&tagname); /* create a new tag */
4221
4222 if(featTagName(line, &tagname, &tagtype, &featTmpStr))
4223 {
4224 numtype = -1;
4225
4226 for(i=0; TagType[i]; i++)
4227 if(!ajStrCmpC(tagtype,TagType[i]))
4228 {
4229 numtype = i;
4230 break;
4231 }
4232
4233 if(numtype < 0)
4234 {
4235 /*ajDebug("Bad feature tag type '%S' in %F line %d\n",
4236 tagtype, TagsFile, linecount);*/
4237 ajErr("Bad feature tag type '%S' in %F line %d",
4238 tagtype, TagsFile, linecount);
4239 break;
4240 }
4241 ajStrDel(&tagtype);
4242
4243 tagscount++;
4244
4245 if(tagscount == 1) /* save first tag as the default */
4246 {
4247 tagstr = NULL;
4248 ajStrAssignClear(&defname);
4249 ajStrAssignS(&tagstr, tagname);
4250
4251 if(ajTablePut (pTagsTable, defname, tagstr))
4252 ajErr("%S duplicate tag for '%S'",
4253 fname, defname);
4254
4255 tagstr = NULL;
4256 defname = NULL;
4257 }
4258
4259 tagstr = NULL;
4260 ajFmtPrintS(&tagstr, "%s;", TagType[numtype]);
4261
4262 /*
4263 ** Controlled vocabulary :
4264 ** read the list of valid values
4265 */
4266
4267 if(ajCharMatchCaseC(TagType[numtype], "LIMITED") ||
4268 ajCharMatchCaseC(TagType[numtype], "QLIMITED"))
4269 {
4270 ajStrTokenAssignC(&featVocabSplit, featTmpStr, "\", \t");
4271
4272 while(ajStrTokenNextParse(featVocabSplit, &token))
4273 {
4274 ajFmtPrintAppS(&tagstr, "%S;", token);
4275 }
4276
4277 ajStrDelStatic(&featTmpStr);
4278 ajStrTokenDel(&featVocabSplit);
4279 }
4280
4281 if(ajTablePut(pTagsTable, tagname, tagstr))
4282 ajErr("%S duplicate tag for '%S'", fname, tagname);
4283
4284 tagstr = NULL;
4285 tagname = NULL;
4286 }
4287 else
4288 {
4289 /*ajDebug("** line format bad **\n%S", line);*/
4290 }
4291 }
4292 }
4293
4294 ajFileClose(&TagsFile);
4295 ajStrDel(&TagsFName);
4296 ajStrDel(&line);
4297 ajStrDel(&token);
4298 ajStrDel(&tagname);
4299 ajStrDel(&tagtype);
4300
4301 /*
4302 ajTableTrace(pTagsTable);
4303 ajTablestrPrint(pTagsTable);
4304 */
4305
4306 return ajTrue;
4307 }
4308
4309
4310
4311
4312 /* @funcstatic featTagName ****************************************************
4313 **
4314 ** Process anything up to ':' as an entry ID (a feature in another entry)
4315 ** Anything up to ',' is this location
4316 **
4317 ** @param [r] line [const AjPStr] Tags file line
4318 ** @param [w] name [AjPStr*] Tag name
4319 ** @param [w] type [AjPStr*] Tag type
4320 ** @param [w] rest [AjPStr*] Remainder of line
4321 ** @return [AjBool] ajTrue if a match was found
4322 ** ajFalse means an error occurred
4323 **
4324 ** @release 3.0.0
4325 ******************************************************************************/
4326
featTagName(const AjPStr line,AjPStr * name,AjPStr * type,AjPStr * rest)4327 static AjBool featTagName(const AjPStr line, AjPStr* name, AjPStr* type,
4328 AjPStr* rest)
4329 {
4330 const char* cp = ajStrGetPtr(line);
4331
4332 ajStrAssignClear(name);
4333 ajStrAssignClear(type);
4334 ajStrAssignClear(rest);
4335
4336 while(isspace((ajint)*cp))
4337 cp++;
4338
4339 while(*cp && !isspace((ajint)*cp))
4340 ajStrAppendK(name, *cp++);
4341
4342 while(isspace((ajint)*cp))
4343 cp++;
4344
4345 if(!*cp)
4346 {
4347 ajStrAssignClear(name);
4348
4349 return ajFalse;
4350 }
4351
4352 while(isalpha((ajint)*cp))
4353 ajStrAppendK(type, *cp++);
4354
4355 if(!ajStrMatchC(*type, "LIMITED") || ajStrMatchC(*type, "QLIMITED"))
4356 return ajTrue;
4357
4358 while(isspace((ajint)*cp))
4359 cp++;
4360
4361 while(*cp)
4362 ajStrAppendK(rest, *cp++);
4363
4364 return ajTrue;
4365 }
4366
4367
4368
4369
4370 /* @funcstatic featVocabReadTypes *********************************************
4371 **
4372 ** Reads the possible feature types (keys)
4373 ** from files.
4374 **
4375 ** @param [r] fname [const AjPStr] Feature type definitions datafile name
4376 ** @param [w] pTypeTable [AjPTable] Feature type table
4377 ** @param [r] pTagsTable [const AjPTable] Feature tags table
4378 ** @param [r] recursion [AjBool] If true process any include lines
4379 ** @return [AjBool] ajTrue on success
4380 **
4381 ** @release 6.0.0
4382 ** @@
4383 ******************************************************************************/
4384
featVocabReadTypes(const AjPStr fname,AjPTable pTypeTable,const AjPTable pTagsTable,AjBool recursion)4385 static AjBool featVocabReadTypes(const AjPStr fname, AjPTable pTypeTable,
4386 const AjPTable pTagsTable,
4387 AjBool recursion)
4388 {
4389 AjPStr TypeFName = NULL;
4390 AjPFile TypeFile = NULL;
4391 AjPStr line = NULL;
4392 AjPStr intids = NULL;
4393 AjPStr tag = NULL;
4394 AjPStr req = NULL;
4395 AjPStr localname = NULL;
4396 AjPStr sofaname = NULL;
4397 AjPStr type = NULL;
4398 AjPStr defname = NULL;
4399 AjPStr defid = NULL;
4400 AjPStr typtagstr = NULL;
4401 AjPStr savetype = NULL;
4402 AjPStr firstid = NULL;
4403 AjPStr token = NULL;
4404 AjPStr rest = NULL;
4405 AjPStr editstr = NULL;
4406 AjPStr modtype = NULL;
4407 const AjPStr tablestr = NULL;
4408 const AjPStr sofaid = NULL;
4409 const AjPStr storetype = NULL;
4410
4411 ajlong typecount = 0;
4412 ajint filetypecount = 0;
4413
4414 char reqchar;
4415 char modchar;
4416 ajlong ipos;
4417 AjBool ismodtype = ajFalse;
4418 AjPStr* Ptyptagstr = NULL;
4419 /* AjBool taginternal = ajFalse; */
4420 AjBool newdefid = ajFalse;
4421 static ajuint level = 0;
4422
4423 level++;
4424
4425 TypeFile = ajDatafileNewInNameS(fname);
4426
4427 if(!TypeFile)
4428 {
4429 ajErr("Unable to read feature types data file '%S'\n", fname);
4430 level--;
4431 return ajFalse;
4432 }
4433
4434 filetypecount = 0;
4435 typecount = ajTableGetLength(pTypeTable);
4436
4437 while(ajReadlineTrim(TypeFile,&line))
4438 {
4439 ajStrRemoveWhiteExcess(&line);
4440
4441 if(ajStrPrefixC(line,"#")) /* if a comment skip it */
4442 {
4443 if(recursion && ajStrPrefixCaseC(line, "#include "))
4444 {
4445 ajStrCutStart(&line, 9);
4446 ajStrExtractFirst(line, &rest, &TypeFName);
4447 ajStrDel(&rest);
4448
4449 if(!featVocabReadTypes(TypeFName, pTypeTable, pTagsTable,
4450 ajTrue))
4451 {
4452 ajStrDel(&line);
4453 ajStrDel(&TypeFName);
4454 ajStrDel(&firstid);
4455 ajStrDel(&savetype);
4456 ajStrDel(&sofaname);
4457 level--;
4458 return ajFalse;
4459 }
4460
4461 typecount = ajTableGetLength(pTypeTable);
4462 }
4463
4464 if(recursion && ajStrPrefixCaseC(line, "#includeonly "))
4465 {
4466 ajStrCutStart(&line, 13);
4467 ajStrExtractFirst(line, &rest, &TypeFName);
4468 ajStrDel(&rest);
4469
4470 if(!featVocabReadTypes(TypeFName, pTypeTable, pTagsTable,
4471 ajFalse))
4472 {
4473 ajStrDel(&line);
4474 ajStrDel(&TypeFName);
4475 ajStrDel(&firstid);
4476 ajStrDel(&savetype);
4477 ajStrDel(&sofaname);
4478 level--;
4479 return ajFalse;
4480
4481 }
4482 typecount = ajTableGetLength(pTypeTable);
4483 }
4484 }
4485 else if(ajStrGetLen(line))
4486 {
4487 if(featFeatType(line, &type, &intids, &tag, &req))
4488 {
4489 if(ajStrGetLen(type)) /* new feature type */
4490 {
4491 if(!ismodtype &&
4492 ajStrGetLen(savetype)) /* save previous type and tags */
4493 {
4494 #if FEATDEBUG
4495 ajDebug("%S %Ld saved '%S' as '%S'\n",
4496 fname, typecount, savetype, typtagstr);
4497 ajDebug("+type %S='%S'\n",
4498 savetype, typtagstr);
4499 #endif
4500 /*
4501 tablestr = ajTablePut(pTypeTable,
4502 savetype, typtagstr);
4503 */
4504 tablestr = ajTableFetchS(pTypeTable, savetype);
4505
4506 if(tablestr)
4507 {
4508 if(recursion)
4509 {
4510 ajErr("%S duplicate type %S='%S' "
4511 "already defined as '%S'",
4512 fname, savetype, typtagstr, tablestr);
4513 }
4514 else
4515 {
4516 #if FEATDEBUG
4517 ajDebug("found savetype '%S' with value '%S'\n",
4518 savetype, tablestr);
4519 #endif
4520 }
4521
4522 ajStrDel(&typtagstr);
4523 ajStrDel(&savetype);
4524 }
4525 else
4526 {
4527 ajTablePut(pTypeTable, savetype, typtagstr);
4528 typtagstr = NULL;
4529 savetype = NULL;
4530 }
4531 }
4532
4533 if(ajStrMatchC(req, "="))
4534 {
4535 ismodtype = ajTrue;
4536 ajStrAssignS(&modtype, type);
4537
4538 if(ajStrMatchC(type, ".")) /* replace default */
4539 ajStrAssignClear(&type);
4540
4541 ajStrAssignS(&localname, type);
4542 ajStrAssignS(&sofaname, intids);
4543 tablestr = ajTableFetchS(pTypeTable, localname);
4544
4545 if(tablestr)
4546 {
4547 #if FEATDEBUG
4548 ajDebug("%S duplicate alias type "
4549 "%S='%S' already defined as '%S'\n",
4550 fname, localname,
4551 sofaname, tablestr);
4552 #endif
4553 ajStrDel(&localname);
4554 }
4555 else
4556 {
4557 ajTablePut(pTypeTable, localname,
4558 sofaname);
4559 localname = NULL;
4560 sofaname = NULL;
4561 }
4562
4563 Ptyptagstr = ajTablestrFetchmod(pTypeTable, intids);
4564
4565 if(!Ptyptagstr)
4566 ajWarn("%S (level %u) undefined internal ID '%S'",
4567 fname, level, intids);
4568
4569 ipos = ajStrFindAnyK(*Ptyptagstr, ';');
4570
4571 if(ipos >= 0)
4572 ajStrCutStart(Ptyptagstr, (size_t) ipos);
4573 else
4574 ajStrInsertK(Ptyptagstr, 0, ';');
4575
4576 ajStrInsertS(Ptyptagstr, 0, type);
4577 ajStrDel(&savetype);
4578 savetype = type;
4579 type = NULL;
4580 typtagstr = *Ptyptagstr;
4581 /* taginternal = ajTrue; */
4582 }
4583 else
4584 {
4585 typecount++;
4586 filetypecount++;
4587
4588 if(typecount == 1) /* type saved as "" default */
4589 {
4590 defname = NULL;
4591 defid = NULL;
4592 ajStrAssignClear(&defname);
4593 ajStrAssignS(&defid, type);
4594 newdefid = ajTrue;
4595 tablestr = ajTableFetchS(pTypeTable, defname);
4596
4597 if(tablestr)
4598 {
4599 ajErr("%S duplicate type %S='%S' "
4600 "already defined as '%S'",
4601 fname, defname, typtagstr, tablestr);
4602 ajStrDel(&typtagstr);
4603 ajStrDel(&defname);
4604 }
4605 else
4606 {
4607 ajTablePut(pTypeTable, defname, defid);
4608 defname = NULL;
4609 }
4610
4611 }
4612
4613 ismodtype = ajFalse;
4614
4615 /*
4616 ** set up new feature type and type-tag strings
4617 ** ready to save the details
4618 */
4619
4620 typtagstr = ajStrNewResC(";", 256);
4621 /* taginternal = ajFalse; */
4622
4623 if(ajStrGetLen(intids))
4624 {
4625 sofaid = ajStrParseWhite(intids);
4626 ajStrAssignS(&firstid, sofaid);
4627 storetype = type;
4628
4629 while(sofaid)
4630 {
4631 if(newdefid)
4632 {
4633 ajStrAssignS(&defid, sofaid);
4634 newdefid = ajFalse;
4635 defid = NULL;
4636 }
4637
4638 #if FEATDEBUG
4639 ajDebug("+type %B storetype:'%S' "
4640 "firstid:'%S'\n",
4641 ajStrMatchCaseS(storetype, firstid),
4642 storetype, firstid);
4643 #endif
4644
4645 if(!ajStrMatchCaseS(storetype, firstid))
4646 {
4647 ajStrAssignS(&localname, storetype);
4648 ajStrAssignS(&sofaname, firstid);
4649 #if FEATDEBUG
4650 ajDebug("%S sofaid "
4651 "'%S' = '%S'\n",
4652 fname,localname, sofaname);
4653 ajDebug("+type (alias) %S='%S'\n",
4654 localname, sofaname);
4655 #endif
4656 tablestr = ajTableFetchS(pTypeTable,
4657 localname);
4658 if(tablestr)
4659 {
4660 if(recursion)
4661 {
4662 ajErr("%S duplicate localname type "
4663 "%S='%S' already defined "
4664 "as '%S'",
4665 fname, localname,
4666 sofaname, tablestr);
4667 }
4668 ajStrDel(&localname);
4669 ajStrDel(&sofaname);
4670 }
4671 else
4672 {
4673 ajTablePut(pTypeTable,
4674 localname, sofaname);
4675 localname = NULL;
4676 sofaname = NULL;
4677 storetype = sofaid;
4678 }
4679
4680 }
4681
4682 sofaid = ajStrParseWhite(NULL);
4683 }
4684
4685 ajStrInsertS(&typtagstr, 0, type);
4686 ajStrAssignClear(&type);
4687 ajStrDel(&savetype);
4688 savetype = firstid;
4689 firstid = NULL;
4690 sofaid = NULL;
4691 ajStrAssignClear(&intids);
4692 }
4693 else
4694 {
4695 ajStrDel(&savetype);
4696 savetype = type;
4697 type = NULL;
4698 ajStrAssignClear(&intids);
4699 }
4700 }
4701 }
4702 else /* tag name */
4703 {
4704 if(!ajTableFetchS(pTagsTable, tag))
4705 {
4706 if(ismodtype)
4707 ajFeatWarn("%S: tag %S (feature %S) "
4708 "not in Etags file",
4709 fname, tag, modtype);
4710 else
4711 ajFeatWarn("%S: tag %S (feature %S) "
4712 "not in Etags file",
4713 fname, tag, savetype);
4714 }
4715
4716 modchar = ajStrGetCharFirst(req);
4717 reqchar = ajStrGetCharLast(req);
4718
4719 if(modchar == '-')
4720 {
4721 ajFmtPrintS(&editstr, ";%S;", tag);
4722 ajStrExchangeSC(&typtagstr, editstr, ";");
4723
4724 if(!modtype)
4725 ajFeatWarn("%S: delete tag '%S' for %S not modified",
4726 fname, tag, modtype);
4727 }
4728 else
4729 {
4730 if(reqchar == 'M' ||
4731 reqchar == 'm')
4732 ajFmtPrintAppS(&typtagstr, "*");
4733
4734 ajFmtPrintAppS(&typtagstr, "%S;", tag);
4735
4736 if(modchar == '+')
4737 {
4738 if(!modtype)
4739 ajFeatWarn("%S: new tag '%S' for %S not modified",
4740 fname, tag, modtype);
4741 }
4742 }
4743 }
4744 }
4745 }
4746 }
4747
4748 if(filetypecount > 0) /* save the last feature type */
4749 {
4750 #if FEATDEBUG
4751 ajDebug("+type (final) %S='%S'\n",
4752 savetype, typtagstr);
4753 #endif
4754 tablestr = ajTableFetchS(pTypeTable, savetype);
4755 if(tablestr)
4756 {
4757 if(recursion)
4758 {
4759 ajErr("%S: duplicate type %S='%S' already defined as '%S'",
4760 fname, savetype, typtagstr, tablestr);
4761 }
4762 ajStrDel(&typtagstr);
4763 ajStrDel(&savetype);
4764 }
4765 else
4766 {
4767 ajTablePut(pTypeTable, savetype, typtagstr);
4768 typtagstr = NULL;
4769 savetype = NULL;
4770 }
4771 }
4772
4773 ajFileClose(&TypeFile);
4774
4775 ajDebug("Total types...: %Ld\n", typecount);
4776
4777 ajStrDel(&line);
4778 ajStrDel(&token);
4779 ajStrDel(&intids);
4780
4781
4782 /*
4783 ajTableTrace(pTypeTable);
4784 ajTablestrPrint(pTypeTable);
4785 */
4786
4787 ajStrDelStatic(&featTmpStr);
4788 ajStrDel(&TypeFName);
4789 ajStrDel(&req);
4790 ajStrDel(&tag);
4791 ajStrDel(&type);
4792 ajStrDel(&intids);
4793 ajStrDel(&modtype);
4794 ajStrDel(&localname);
4795 ajStrDel(&sofaname);
4796 ajStrDel(&firstid);
4797 ajStrDel(&savetype);
4798
4799 level--;
4800
4801 return ajTrue;
4802 }
4803
4804
4805
4806
4807 /* @func ajFeatVocabGetTags ***************************************************
4808 **
4809 ** Returns tags table for a named feature format
4810 **
4811 ** @param [r] name [const char*] Feature format name
4812 ** @return [const AjPTable] Tags table on success
4813 ** NULL on failure
4814 **
4815 ** @release 6.4.0
4816 ******************************************************************************/
4817
ajFeatVocabGetTags(const char * name)4818 const AjPTable ajFeatVocabGetTags(const char* name)
4819 {
4820 ajuint i;
4821
4822 if(!FeatInitDone)
4823 featInit();
4824
4825 for(i=0; featVocab[i].Name; i++)
4826 {
4827 if(!strcmp(name, featVocab[i].Truename) ||
4828 !strcmp(name, featVocab[i].Name))
4829 {
4830 if(!*(featVocab[i].Tagstable))
4831 if(!featVocabInit(i))
4832 return NULL;
4833
4834 return *(featVocab[i].Tagstable);
4835 }
4836 }
4837
4838 return NULL;
4839 }
4840
4841
4842
4843
4844 /* @func ajFeatVocabGetTagsNuc ************************************************
4845 **
4846 ** Returns tags table for a named nucleotide feature format
4847 **
4848 ** @param [r] name [const char*] Feature format name
4849 ** @return [const AjPTable] Tags table on success
4850 ** NULL on failure
4851 **
4852 ** @release 6.4.0
4853 ******************************************************************************/
4854
ajFeatVocabGetTagsNuc(const char * name)4855 const AjPTable ajFeatVocabGetTagsNuc(const char* name)
4856 {
4857 ajuint i;
4858
4859 if(!FeatInitDone)
4860 featInit();
4861
4862 for(i=0; featVocab[i].Name; i++)
4863 {
4864 if(!featVocab[i].Nucleotide)
4865 continue;
4866
4867 if(!strcmp(name, featVocab[i].Truename) ||
4868 !strcmp(name, featVocab[i].Name))
4869 {
4870 if(!*(featVocab[i].Tagstable))
4871 if(!featVocabInit(i))
4872 return NULL;
4873
4874 return *(featVocab[i].Tagstable);
4875 }
4876 }
4877
4878 return NULL;
4879 }
4880
4881
4882
4883
4884 /* @func ajFeatVocabGetTagsProt ***********************************************
4885 **
4886 ** Returns tags table for a named protein feature format
4887 **
4888 ** @param [r] name [const char*] Feature format name
4889 ** @return [const AjPTable] Tags table on success
4890 ** NULL on failure
4891 **
4892 ** @release 6.4.0
4893 ******************************************************************************/
4894
ajFeatVocabGetTagsProt(const char * name)4895 const AjPTable ajFeatVocabGetTagsProt(const char* name)
4896 {
4897 ajuint i;
4898
4899 if(!FeatInitDone)
4900 featInit();
4901
4902 for(i=0; featVocab[i].Name; i++)
4903 {
4904 if(!featVocab[i].Protein)
4905 continue;
4906
4907 if(!strcmp(name, featVocab[i].Truename) ||
4908 !strcmp(name, featVocab[i].Name))
4909 {
4910 if(!*(featVocab[i].Tagstable))
4911 if(!featVocabInit(i))
4912 return NULL;
4913
4914 return *(featVocab[i].Tagstable);
4915 }
4916 }
4917
4918 return NULL;
4919 }
4920
4921
4922
4923
4924 /* @func ajFeatVocabGetTypes **************************************************
4925 **
4926 ** Returns types table for a named feature format
4927 **
4928 ** @param [r] name [const char*] Feature format name
4929 ** @return [const AjPTable] Type table on success
4930 ** NULL on failure
4931 **
4932 ** @release 6.4.0
4933 ******************************************************************************/
4934
ajFeatVocabGetTypes(const char * name)4935 const AjPTable ajFeatVocabGetTypes(const char* name)
4936 {
4937 ajuint i;
4938
4939 if(!FeatInitDone)
4940 featInit();
4941
4942 for(i=0; featVocab[i].Name; i++)
4943 {
4944 if(!strcmp(name, featVocab[i].Truename) ||
4945 !strcmp(name, featVocab[i].Name))
4946 {
4947 if(!*(featVocab[i].Typetable))
4948 if(!featVocabInit(i))
4949 return NULL;
4950
4951 return *(featVocab[i].Typetable);
4952 }
4953 }
4954
4955 return NULL;
4956 }
4957
4958
4959
4960
4961 /* @func ajFeatVocabGetTypesNuc ***********************************************
4962 **
4963 ** Returns types table for a named nucleotide feature format
4964 **
4965 ** @param [r] name [const char*] Feature format name
4966 ** @return [const AjPTable] Type table on success
4967 ** NULL on failure
4968 **
4969 ** @release 6.4.0
4970 ******************************************************************************/
4971
ajFeatVocabGetTypesNuc(const char * name)4972 const AjPTable ajFeatVocabGetTypesNuc(const char* name)
4973 {
4974 ajuint i;
4975
4976 if(!FeatInitDone)
4977 featInit();
4978
4979 for(i=0; featVocab[i].Name; i++)
4980 {
4981 if(!featVocab[i].Nucleotide)
4982 continue;
4983
4984 if(!strcmp(name, featVocab[i].Truename) ||
4985 !strcmp(name, featVocab[i].Name))
4986 {
4987 if(!*(featVocab[i].Typetable))
4988 if(!featVocabInit(i))
4989 return NULL;
4990
4991 return *(featVocab[i].Typetable);
4992 }
4993 }
4994
4995 return NULL;
4996 }
4997
4998
4999
5000
5001 /* @func ajFeatVocabGetTypesProt **********************************************
5002 **
5003 ** Returns types table for a named protein feature format
5004 **
5005 ** @param [r] name [const char*] Feature format name
5006 ** @return [const AjPTable] Type table on success
5007 ** NULL on failure
5008 **
5009 ** @release 6.4.0
5010 ******************************************************************************/
5011
ajFeatVocabGetTypesProt(const char * name)5012 const AjPTable ajFeatVocabGetTypesProt(const char* name)
5013 {
5014 ajuint i;
5015
5016 if(!FeatInitDone)
5017 featInit();
5018
5019 for(i=0; featVocab[i].Name; i++)
5020 {
5021 if(!featVocab[i].Protein)
5022 continue;
5023
5024 if(!strcmp(name, featVocab[i].Truename) ||
5025 !strcmp(name, featVocab[i].Name))
5026 {
5027 if(!*(featVocab[i].Typetable))
5028 if(!featVocabInit(i))
5029 return NULL;
5030
5031 return *(featVocab[i].Typetable);
5032 }
5033 }
5034
5035 return NULL;
5036 }
5037
5038
5039
5040
5041 /* @func ajFeatVocabInit ******************************************************
5042 **
5043 ** Initialises feature table internals for a named feature format
5044 **
5045 ** @param [r] name [const char*] Feature format name
5046 ** @return [const AjPTable] Type table on success
5047 ** NULL on failure
5048 **
5049 ** @release 6.4.0
5050 ******************************************************************************/
5051
ajFeatVocabInit(const char * name)5052 const AjPTable ajFeatVocabInit(const char* name)
5053 {
5054 ajuint i;
5055
5056 if(!FeatInitDone)
5057 featInit();
5058
5059 for(i=0; featVocab[i].Name; i++)
5060 {
5061 if(!strcmp(name, featVocab[i].Truename) ||
5062 !strcmp(name, featVocab[i].Name))
5063 {
5064 if(*(featVocab[i].Typetable))
5065 return *(featVocab[i].Typetable);
5066 else
5067 return featVocabInit(i);
5068 }
5069 }
5070
5071 return NULL;
5072 }
5073
5074
5075
5076
5077 /* @func ajFeatVocabInitNuc ***************************************************
5078 **
5079 ** Initialises feature table internals for a named feature format
5080 **
5081 ** @param [r] name [const char*] Feature format name
5082 ** @return [const AjPTable] Type table on success
5083 ** NULL on failure
5084 **
5085 ** @release 6.4.0
5086 ******************************************************************************/
5087
ajFeatVocabInitNuc(const char * name)5088 const AjPTable ajFeatVocabInitNuc(const char* name)
5089 {
5090 ajuint i;
5091
5092 if(!FeatInitDone)
5093 featInit();
5094
5095 for(i=0; featVocab[i].Name; i++)
5096 {
5097 if(!featVocab[i].Nucleotide)
5098 continue;
5099
5100 if(!strcmp(name, featVocab[i].Truename) ||
5101 !strcmp(name, featVocab[i].Name))
5102 {
5103 if(*(featVocab[i].Typetable))
5104 return *(featVocab[i].Typetable);
5105 else
5106 return featVocabInit(i);
5107 }
5108 }
5109
5110 return NULL;
5111 }
5112
5113
5114
5115
5116 /* @func ajFeatVocabInitProt **************************************************
5117 **
5118 ** Initialises feature table internals for a named feature format
5119 **
5120 ** @param [r] name [const char*] Feature format name
5121 ** @return [const AjPTable] Type table on success
5122 ** NULL on failure
5123 **
5124 ** @release 6.4.0
5125 ******************************************************************************/
5126
ajFeatVocabInitProt(const char * name)5127 const AjPTable ajFeatVocabInitProt(const char* name)
5128 {
5129 ajuint i;
5130
5131 if(!FeatInitDone)
5132 featInit();
5133
5134 for(i=0; featVocab[i].Name; i++)
5135 {
5136 if(!featVocab[i].Protein)
5137 continue;
5138
5139 if(!strcmp(name, featVocab[i].Truename) ||
5140 !strcmp(name, featVocab[i].Name))
5141 {
5142 if(*(featVocab[i].Typetable))
5143 return *(featVocab[i].Typetable);
5144 else
5145 return featVocabInit(i);
5146 }
5147 }
5148
5149 return NULL;
5150 }
5151
5152
5153
5154
5155 /* @funcstatic featVocabInit **************************************************
5156 **
5157 ** Initialises feature table internals for a named feature format
5158 ** and returns the types table
5159 **
5160 ** @param [r] ivocab [ajuint] Vocabulary index
5161 ** @return [const AjPTable] Table if found
5162 **
5163 ** @release 6.4.0
5164 ******************************************************************************/
5165
featVocabInit(ajuint ivocab)5166 static const AjPTable featVocabInit(ajuint ivocab)
5167 {
5168 const char* name = featVocab[ivocab].Truename;
5169 AjPTable *Ptypetable = featVocab[ivocab].Typetable;
5170 AjPTable *Ptagstable = featVocab[ivocab].Tagstable;
5171
5172 if(!FeatInitDone)
5173 featInit();
5174
5175 if(!*Ptypetable)
5176 {
5177 *Ptypetable = ajTablestrNewCase(200);
5178 *Ptagstable = ajTablestrNewCase(200);
5179
5180 featVocabRead(name, *Ptypetable, *Ptagstable);
5181
5182 if(!*Ptagstable)
5183 return NULL;
5184
5185 return *Ptypetable;
5186 }
5187
5188 return *Ptypetable;
5189 }
5190
5191
5192
5193
5194 /* @func ajFeatSetDescApp *****************************************************
5195 **
5196 ** Sets the description for a feature
5197 **
5198 ** @param [u] thys [AjPFeature] Feature
5199 ** @param [r] desc [const AjPStr] Feature description (simple text)
5200 ** @return [void]
5201 **
5202 ** @release 2.3.0
5203 ** @@
5204 ******************************************************************************/
5205
ajFeatSetDescApp(AjPFeature thys,const AjPStr desc)5206 void ajFeatSetDescApp(AjPFeature thys, const AjPStr desc)
5207 {
5208 AjPTagval tv = NULL;
5209
5210 if(!featTagNote)
5211 ajStrAssignC(&featTagNote, "note");
5212
5213 tv = featTagval(thys, featTagNote);
5214
5215 if(tv)
5216 {
5217 ajTagvalAppendC(tv, ", ");
5218 ajTagvalAppendS(tv, desc);
5219 }
5220 else
5221 ajFeatTagSet(thys, featTagNote, desc);
5222
5223 return;
5224 }
5225
5226
5227
5228
5229 /* @func ajFeatSetDesc ********************************************************
5230 **
5231 ** Sets the description for a feature
5232 **
5233 ** @param [u] thys [AjPFeature] Feature
5234 ** @param [r] desc [const AjPStr] Feature description (simple text)
5235 ** @return [void]
5236 **
5237 ** @release 2.0.0
5238 ** @@
5239 ******************************************************************************/
5240
ajFeatSetDesc(AjPFeature thys,const AjPStr desc)5241 void ajFeatSetDesc(AjPFeature thys, const AjPStr desc)
5242 {
5243 ajFeatTagSetC(thys, "note", desc);
5244
5245 return;
5246 }
5247
5248
5249
5250
5251 /* @func ajFeatSetSource ******************************************************
5252 **
5253 ** Sets the source for a feature
5254 **
5255 ** @param [u] thys [AjPFeature] Feature
5256 ** @param [r] source [const AjPStr] Feature source
5257 ** @return [void]
5258 **
5259 ** @release 6.4.0
5260 ** @@
5261 ******************************************************************************/
5262
ajFeatSetSource(AjPFeature thys,const AjPStr source)5263 void ajFeatSetSource(AjPFeature thys, const AjPStr source)
5264 {
5265 ajStrAssignS(&thys->Source, source);
5266
5267 return;
5268 }
5269
5270
5271
5272
5273 /* @func ajFeatSetScore *******************************************************
5274 **
5275 ** Sets the score for a feature
5276 **
5277 ** @param [u] thys [AjPFeature] Feature
5278 ** @param [r] score [float] Score value
5279 ** @return [void]
5280 **
5281 ** @release 4.0.0
5282 ** @@
5283 ******************************************************************************/
5284
ajFeatSetScore(AjPFeature thys,float score)5285 void ajFeatSetScore(AjPFeature thys, float score)
5286 {
5287 thys->Score = score;
5288 return;
5289 }
5290
5291
5292
5293
5294 /* @func ajFeatSetStrand ******************************************************
5295 **
5296 ** Sets the strand for a feature
5297 **
5298 ** @param [u] thys [AjPFeature] Feature
5299 ** @param [r] rev [AjBool] True if reverse strand
5300 ** @return [void]
5301 **
5302 ** @release 4.0.0
5303 ** @@
5304 ******************************************************************************/
5305
ajFeatSetStrand(AjPFeature thys,AjBool rev)5306 void ajFeatSetStrand(AjPFeature thys, AjBool rev)
5307 {
5308 if(rev)
5309 thys->Strand = '-';
5310 else
5311 thys->Strand = '+';
5312
5313 return;
5314 }
5315
5316
5317
5318
5319 /* @func ajFeatTagSetC ********************************************************
5320 **
5321 ** Sets a feature tag value
5322 **
5323 ** @param [u] thys [AjPFeature] Feature
5324 ** @param [r] tag [const char*] Feature tag
5325 ** @param [r] value [const AjPStr] Feature tag value
5326 ** @return [AjBool] ajTrue is value was valid
5327 ** ajFalse if it was "corrected"
5328 **
5329 ** @release 2.0.0
5330 ** @@
5331 ******************************************************************************/
5332
ajFeatTagSetC(AjPFeature thys,const char * tag,const AjPStr value)5333 AjBool ajFeatTagSetC(AjPFeature thys, const char* tag, const AjPStr value)
5334 {
5335 AjPStr tmptag = NULL;
5336 AjBool ret = ajFalse;
5337
5338 ajStrAssignC(&tmptag, tag);
5339
5340 ret = ajFeatTagSet(thys, tmptag, value);
5341 ajStrDel(&tmptag);
5342
5343 return ret;
5344 }
5345
5346
5347
5348
5349 /* @func ajFeatTagSet *********************************************************
5350 **
5351 ** Sets a feature tag value
5352 **
5353 ** @param [u] thys [AjPFeature] Feature
5354 ** @param [r] tag [const AjPStr] Feature tag
5355 ** @param [r] value [const AjPStr] Feature tag value
5356 ** @return [AjBool] ajTrue is value was valid
5357 ** ajFalse if it was "corrected"
5358 **
5359 ** @release 2.0.0
5360 ** @@
5361 ******************************************************************************/
5362
ajFeatTagSet(AjPFeature thys,const AjPStr tag,const AjPStr value)5363 AjBool ajFeatTagSet(AjPFeature thys, const AjPStr tag, const AjPStr value)
5364 {
5365 AjBool ret = ajTrue;
5366 AjPTagval tv = NULL;
5367 AjBool knowntag = ajTrue;
5368
5369 const AjPStr tmptag = NULL; /* this comes from AjPTable */
5370 /* so please, please don't delete */
5371 const char* cp;
5372
5373 ajDebug("ajFeatTagSet '%S' '%S' type: '%S' Prot: %B\n",
5374 tag, value, thys->Type, thys->Protein);
5375
5376 featInit();
5377
5378 if(thys->Protein)
5379 {
5380 tmptag = ajFeattagGetNameS(tag, FeatTagsTableProtein, &knowntag);
5381 ajFeattagFormat(tmptag, FeatTagsTableProtein, &featFmtTmp);
5382 }
5383 else
5384 {
5385 tmptag = ajFeattagGetNameS(tag, FeatTagsTableDna, &knowntag);
5386 ajFeattagFormat(tmptag, FeatTagsTableDna, &featFmtTmp);
5387 }
5388
5389 ajStrAssignS(&featValTmp, value);
5390 ajStrAssignS(&featTagTmp, tmptag);
5391
5392 cp = ajStrGetPtr(featFmtTmp);
5393
5394 switch(CASE2(cp[0], cp[1]))
5395 {
5396 case CASE2('L','I') : /* limited */
5397 /* ajDebug("case limited\n"); */
5398 break;
5399 case CASE2('Q', 'L') : /* limited, escape quotes */
5400 /* ajDebug("case qlimited\n"); */
5401 break;
5402 case CASE2('Q', 'S') : /* special regexp, quoted */
5403 /* ajDebug("case qspecial\n"); */
5404 if(!ajFeattagSpecial(tmptag, &featValTmp))
5405 {
5406 ret = ajFalse;
5407 featTagSetDefault(thys, tmptag, value, &featTagTmp,
5408 &featValTmp);
5409 }
5410 break;
5411 case CASE2('S','P') : /* special regexp */
5412 /* ajDebug("case special\n"); */
5413 if(!ajFeattagSpecial(tmptag, &featValTmp))
5414 {
5415 ret = ajFalse;
5416 featTagSetDefault(thys, tmptag, value, &featTagTmp,
5417 &featValTmp);
5418 }
5419 break;
5420 case CASE2('T','E') : /* no space, no quotes, wrap at margin */
5421 /* ajDebug("case text\n"); */
5422 break;
5423 case CASE2('V','O') : /* no value, so an error here */
5424 /*ajDebug("case void\n");*/
5425 break;
5426 case CASE2('Q','T') : /* escape quotes, wrap at space */
5427 /* ajDebug("case qtext\n"); */
5428 break;
5429 case CASE2('Q','W') : /* escape quotes, remove space */
5430 /* ajDebug("case qword\n"); */
5431 break;
5432 default:
5433 ajFeatWarn("Unknown internal feature tag type '%S' for '%S'",
5434 featFmtTmp, tmptag);
5435 }
5436
5437 tv = featTagval(thys, featTagTmp);
5438
5439 if(tv) /* replace current value */
5440 {
5441 ajTagvalReplaceS(tv, featValTmp);
5442 return ret;
5443 }
5444
5445 /* new tag-value */
5446 tv = featTagvalNew(thys, featTagTmp, featValTmp);
5447 ajListPushAppend(thys->Tags, tv);
5448 /* ajDebug("...new tag-value\n"); */
5449
5450 return ret;
5451 }
5452
5453
5454
5455
5456 /* @func ajFeattagSpecialGff2 *************************************************
5457 **
5458 ** Special processing for known GFF tags
5459 **
5460 ** This function will be very similar to featTagSpecial, with scope
5461 ** for future GFF-specific extensions
5462 **
5463 ** @param [r] tag [const AjPStr] original tag name
5464 ** @param [u] pval [AjPStr*] tag value
5465 ** @return [AjBool] ajTrue on success
5466 **
5467 ** @release 6.4.0
5468 ** @@
5469 ******************************************************************************/
5470
ajFeattagSpecialGff2(const AjPStr tag,AjPStr * pval)5471 AjBool ajFeattagSpecialGff2(const AjPStr tag, AjPStr* pval)
5472 {
5473 /*ajDebug("ajFeattagSpecialGff2 '%S' '%S'\n", tag, *pval);*/
5474
5475 if(ajStrMatchC(tag, "anticodon"))
5476 return featTagSpecialAllAnticodon(*pval);
5477
5478 else if(ajStrMatchC(tag, "bio_material") ||
5479 ajStrMatchC(tag, "culture_collection") ||
5480 ajStrMatchC(tag, "specimen_voucher"))
5481 return featTagSpecialAllBiomaterial(*pval);
5482
5483 else if(ajStrMatchC(tag, "citation"))
5484 return featTagSpecialAllCitation(*pval);
5485
5486 else if(ajStrMatchC(tag, "codon"))
5487 return featTagSpecialAllCodon(pval);
5488
5489 else if(ajStrMatchC(tag, "collection_date"))
5490 return featTagSpecialAllCollectiondate(*pval);
5491
5492 else if(ajStrMatchC(tag, "compare"))
5493 return featTagSpecialAllCompare(*pval);
5494
5495 else if(ajStrMatchC(tag, "cons_splice"))
5496 return featTagSpecialAllConssplice(pval);
5497
5498 else if(ajStrMatchC(tag, "db_xref"))
5499 return featTagSpecialAllDbxref(*pval);
5500
5501 else if(ajStrMatchC(tag, "estimated_length"))
5502 return featTagSpecialAllEstimatedlength(pval);
5503
5504 else if(ajStrMatchC(tag, "inference"))
5505 return featTagSpecialAllInference(*pval);
5506
5507 else if(ajStrMatchC(tag, "lat_lon"))
5508 return featTagSpecialAllLatlon(*pval);
5509
5510 else if(ajStrMatchC(tag, "mobile_element"))
5511 return featTagSpecialAllMobile(*pval);
5512
5513 else if(ajStrMatchC(tag, "PCR_primers"))
5514 return featTagSpecialAllPcrprimers(*pval);
5515
5516 else if(ajStrMatchC(tag, "protein_id"))
5517 return featTagSpecialAllProteinid(*pval);
5518
5519 else if(ajStrMatchC(tag, "replace"))
5520 return featTagSpecialAllReplace(pval);
5521
5522 else if(ajStrMatchC(tag, "rpt_unit"))
5523 return featTagSpecialAllRptunit(*pval);
5524
5525 else if(ajStrMatchC(tag, "rpt_unit_range") ||
5526 ajStrMatchC(tag, "tag_peptide"))
5527 return featTagSpecialAllRange(*pval);
5528
5529 else if(ajStrMatchC(tag, "rpt_unit_seq"))
5530 return featTagSpecialAllRptunitseq(pval);
5531
5532 else if(ajStrMatchC(tag, "transl_except"))
5533 return featTagSpecialAllTranslexcept(*pval);
5534
5535 else if(ajStrMatchC(tag, "translation"))
5536 return featTagSpecialAllTranslation(pval);
5537
5538 /*ajDebug("Unrecognised special GFF feature tag '%S'\n", tag);*/
5539 ajFeatWarn("Unrecognised special GFF feature tag '%S'", tag);
5540
5541 return ajFalse;
5542 }
5543
5544
5545
5546
5547 /* @funcstatic featTagGff3PredefinedTag ***************************************
5548 **
5549 ** Checks whether the specified tag is one of GFF3 tags
5550 ** that have predefined meanings
5551 **
5552 ** @param [r] tag [const AjPStr] tag name
5553 ** @return [AjBool] ajTrue on success
5554 **
5555 ** @release 6.4.0
5556 ** @@
5557 ******************************************************************************/
5558
featTagGff3PredefinedTag(const AjPStr tag)5559 static AjBool featTagGff3PredefinedTag(const AjPStr tag)
5560 {
5561 const char* tags[] = {"ID", "Name", "Alias", "Parent", "Target", "Gap",
5562 "Derives_from", "Note", "Dbxref",
5563 "Ontology_term", "Is_circular", NULL};
5564 int i=0;
5565
5566 while(tags[i])
5567 if(ajStrMatchC(tag, tags[i++]))
5568 return ajTrue;
5569
5570 return ajFalse;
5571 }
5572
5573
5574
5575
5576 /* @func ajFeattagSpecialGff3 *************************************************
5577 **
5578 ** Special processing for known GFF3 tags
5579 **
5580 ** This function will be very similar to featTagSpecial, with scope
5581 ** for future GFF3-specific extensions
5582 **
5583 ** @param [r] tag [const AjPStr] original tag name
5584 ** @param [u] pval [AjPStr*] tag value
5585 ** @return [AjBool] ajTrue on success
5586 **
5587 ** @release 6.4.0
5588 ** @@
5589 ******************************************************************************/
5590
ajFeattagSpecialGff3(const AjPStr tag,AjPStr * pval)5591 AjBool ajFeattagSpecialGff3(const AjPStr tag, AjPStr* pval)
5592 {
5593 /*ajDebug("featTagGff3Special '%S' '%S'\n", tag, *pval);*/
5594
5595 if(ajStrMatchC(tag, "anticodon"))
5596 return featTagSpecialAllAnticodon(*pval);
5597
5598 else if(ajStrMatchC(tag, "bio_material") ||
5599 ajStrMatchC(tag, "culture_collection") ||
5600 ajStrMatchC(tag, "specimen_voucher"))
5601 return featTagSpecialAllBiomaterial(*pval);
5602
5603 else if(ajStrMatchC(tag, "citation"))
5604 return featTagSpecialAllCitation(*pval);
5605
5606 else if(ajStrMatchC(tag, "codon"))
5607 return featTagSpecialAllCodon(pval);
5608
5609 else if(ajStrMatchC(tag, "collection_date"))
5610 return featTagSpecialAllCollectiondate(*pval);
5611
5612 else if(ajStrMatchC(tag, "compare"))
5613 return featTagSpecialAllCompare(*pval);
5614
5615 else if(ajStrMatchC(tag, "cons_splice"))
5616 return featTagSpecialAllConssplice(pval);
5617
5618 else if(ajStrMatchC(tag, "db_xref"))
5619 return featTagSpecialAllDbxref(*pval);
5620
5621 else if(ajStrMatchC(tag, "estimated_length"))
5622 return featTagSpecialAllEstimatedlength(pval);
5623
5624 else if(ajStrMatchC(tag, "inference"))
5625 return featTagSpecialAllInference(*pval);
5626
5627 else if(ajStrMatchC(tag, "lat_lon"))
5628 return featTagSpecialAllLatlon(*pval);
5629
5630 else if(ajStrMatchC(tag, "mobile_element"))
5631 return featTagSpecialAllMobile(*pval);
5632
5633 else if(ajStrMatchC(tag, "ncRNA_class"))
5634 return featTagSpecialAllNcrnaclass(*pval);
5635
5636 else if(ajStrMatchC(tag, "PCR_primers"))
5637 return featTagSpecialAllPcrprimers(*pval);
5638
5639 else if(ajStrMatchC(tag, "protein_id"))
5640 return featTagSpecialAllProteinid(*pval);
5641
5642 else if(ajStrMatchC(tag, "replace"))
5643 return featTagSpecialAllReplace(pval);
5644
5645 else if(ajStrMatchC(tag, "rpt_unit"))
5646 return featTagSpecialAllRptunit(*pval);
5647
5648 else if(ajStrMatchC(tag, "rpt_unit_range") ||
5649 ajStrMatchC(tag, "tag_peptide"))
5650 return featTagSpecialAllRange(*pval);
5651
5652 else if(ajStrMatchC(tag, "rpt_unit_seq"))
5653 return featTagSpecialAllRptunitseq(pval);
5654
5655 else if(ajStrMatchC(tag, "transl_except"))
5656 return featTagSpecialAllTranslexcept(*pval);
5657
5658 else if(ajStrMatchC(tag, "translation"))
5659 return featTagSpecialAllTranslation(pval);
5660
5661 /*ajDebug("Unrecognised special GFF feature tag '%S'\n", tag);*/
5662 ajFeatWarn("Unrecognised special GFF feature tag '%S'", tag);
5663
5664 return ajFalse;
5665 }
5666
5667
5668
5669
5670 /* @func ajFeatTagAddCC *******************************************************
5671 **
5672 ** Sets a feature tag value, creating a new feature tag even if one
5673 ** already exists.
5674 **
5675 ** @param [u] thys [AjPFeature] Feature
5676 ** @param [r] tag [const char*] Feature tag
5677 ** @param [r] value [const char*] Feature tag value
5678 ** @return [AjBool] ajTrue if value was valid
5679 ** ajFalse if it was bad and was "corrected"
5680 **
5681 ** @release 2.4.0
5682 ** @@
5683 ******************************************************************************/
5684
ajFeatTagAddCC(AjPFeature thys,const char * tag,const char * value)5685 AjBool ajFeatTagAddCC(AjPFeature thys, const char* tag, const char* value)
5686 {
5687 AjBool ret;
5688 AjPStr tagstr = NULL;
5689 AjPStr valstr = NULL;
5690
5691 ajStrAssignC(&tagstr, tag);
5692 ajStrAssignC(&valstr, value);
5693
5694 ret = ajFeatTagAddSS(thys, tagstr, valstr);
5695 ajStrDel(&tagstr);
5696 ajStrDel(&valstr);
5697
5698 return ret;
5699 }
5700
5701
5702
5703
5704 /* @func ajFeatTagAddCS *******************************************************
5705 **
5706 ** Sets a feature tag value, creating a new feature tag even if one
5707 ** already exists.
5708 **
5709 ** @param [u] thys [AjPFeature] Feature
5710 ** @param [r] tag [const char*] Feature tag
5711 ** @param [r] value [const AjPStr] Feature tag value
5712 ** @return [AjBool] ajTrue if value was valid
5713 ** ajFalse if it was bad and was "corrected"
5714 **
5715 ** @release 2.4.0
5716 ** @@
5717 ******************************************************************************/
5718
ajFeatTagAddCS(AjPFeature thys,const char * tag,const AjPStr value)5719 AjBool ajFeatTagAddCS(AjPFeature thys, const char* tag, const AjPStr value)
5720 {
5721 AjBool ret;
5722 static AjPStr tagstr = NULL;
5723
5724 ajStrAssignC(&tagstr, tag);
5725
5726 ret = ajFeatTagAddSS(thys, tagstr, value);
5727
5728 ajStrDel(&tagstr);
5729
5730 return ret;
5731 }
5732
5733
5734
5735
5736 /* @func ajFeatTagAddSS *******************************************************
5737 **
5738 ** Sets a feature tag value, creating a new feature tag even if one
5739 ** already exists.
5740 **
5741 ** @param [u] thys [AjPFeature] Feature
5742 ** @param [r] tag [const AjPStr] Feature tag
5743 ** @param [r] value [const AjPStr] Feature tag value
5744 ** @return [AjBool] ajTrue if value was valid
5745 ** ajFalse if it was bad and was "corrected"
5746 **
5747 ** @release 2.0.0
5748 ** @@
5749 ******************************************************************************/
5750
ajFeatTagAddSS(AjPFeature thys,const AjPStr tag,const AjPStr value)5751 AjBool ajFeatTagAddSS(AjPFeature thys, const AjPStr tag, const AjPStr value)
5752 {
5753 AjBool ret = ajTrue;
5754 AjPTagval tv = NULL;
5755 const AjPStr tmptag = NULL; /* this comes from AjPTable */
5756 /* so please, please don't delete */
5757 AjBool knowntag = ajTrue;
5758 const char* cp;
5759
5760 #if FEATDEBUG
5761 ajDebug("ajFeatTagAddSS '%S' '%S' type: '%S' Prot: %B\n",
5762 tag, value, thys->Type, thys->Protein);
5763 #endif
5764
5765 featInit();
5766
5767 if(thys->Protein)
5768 {
5769 tmptag = ajFeattagGetNameS(tag, FeatTagsTableProtein, &knowntag);
5770 ajFeattagFormat(tmptag, FeatTagsTableProtein, &featFmtTmp);
5771 }
5772 else
5773 {
5774 tmptag = ajFeattagGetNameS(tag, FeatTagsTableDna, &knowntag);
5775 ajFeattagFormat(tmptag, FeatTagsTableDna, &featFmtTmp);
5776 }
5777
5778 #if FEATDEBUG
5779 ajDebug("tag: '%S' format: '%S'\n", tmptag, featFmtTmp);
5780 #endif
5781
5782 ajStrAssignS(&featValTmp2, value);
5783 ajStrAssignS(&featTagTmp2, tmptag);
5784
5785 cp = ajStrGetPtr(featFmtTmp);
5786
5787 switch(CASE2(cp[0], cp[1]))
5788 {
5789 case CASE2('L','I') : /* limited */
5790 /* ajDebug("case limited\n"); */
5791 break;
5792 case CASE2('Q', 'L') : /* limited, escape quotes */
5793 /* ajDebug("case qlimited\n"); */
5794 break;
5795 case CASE2('Q', 'S') : /* special regexp, quoted */
5796 /* ajDebug("case qspecial\n"); */
5797 if(!ajFeattagSpecial(tmptag, &featValTmp2))
5798 {
5799 ret = ajFalse;
5800 featTagSetDefault(thys, tmptag, value, &featTagTmp2,
5801 &featValTmp2);
5802 }
5803 break;
5804 case CASE2('S','P') : /* special regexp */
5805 /* ajDebug("case special\n");*/
5806 if(!ajFeattagSpecial(tmptag, &featValTmp2))
5807 {
5808 ret = ajFalse;
5809 featTagSetDefault(thys, tmptag, value, &featTagTmp2,
5810 &featValTmp2);
5811 }
5812 break;
5813 case CASE2('T','E') : /* no space, no quotes, wrap at margin */
5814 /* ajDebug("case text\n"); */
5815 break;
5816 case CASE2('V','O') : /* no value, so an error here */
5817 /* ajDebug("case void\n"); */
5818 break;
5819 case CASE2('Q','T') : /* escape quotes, wrap at space */
5820 /* ajDebug("case qtext\n"); */
5821 if(!knowntag && tag)
5822 ajFmtPrintS(&featValTmp2, "*%S: %S", tag, value);
5823 /*ajDebug("ajFeatTagAdd qtext knowntag %B tag '%S' Tmp '%S' '%S'\n",
5824 knowntag, tag, featTagTmp2, featValTmp2);*/
5825 break;
5826 case CASE2('Q','W') : /* escape quotes, remove space */
5827 /* ajDebug("case qword\n"); */
5828 break;
5829 default:
5830 ajFeatWarn("Unknown internal feature tag type '%S' for '%S'",
5831 featFmtTmp, tmptag);
5832 }
5833
5834 tv = featTagvalNew(thys, featTagTmp2, featValTmp2);
5835
5836 ajListPushAppend(thys->Tags, tv);
5837 /* ajDebug("...new tag-value\n"); */
5838
5839 return ret;
5840 }
5841
5842
5843
5844
5845 /* @func ajFeatTagAddTag ******************************************************
5846 **
5847 ** Sets a feature tag value, creating a new feature tag even if one
5848 ** already exists.
5849 **
5850 ** @param [u] thys [AjPFeature] Feature
5851 ** @param [r] tagval [const AjPTagval] Tag value pair
5852 ** @return [AjBool] ajTrue if value was valid
5853 ** ajFalse if it was bad and was "corrected"
5854 **
5855 ** @release 6.5.0
5856 ** @@
5857 ******************************************************************************/
5858
ajFeatTagAddTag(AjPFeature thys,const AjPTagval tagval)5859 AjBool ajFeatTagAddTag(AjPFeature thys, const AjPTagval tagval)
5860 {
5861 return ajFeatTagAddSS(thys,
5862 MAJTAGVALGETTAG(tagval),
5863 MAJTAGVALGETVALUE(tagval));
5864 }
5865
5866
5867
5868
5869 /* @func ajFeattagSpecial *****************************************************
5870 **
5871 ** Special processing for known internal (EMBL) tags
5872 **
5873 ** @param [r] tag [const AjPStr] original tag name
5874 ** @param [u] pval [AjPStr*] parameter value
5875 ** @return [AjBool] ajTrue on success
5876 **
5877 ** @release 6.4.0
5878 ** @@
5879 ******************************************************************************/
5880
ajFeattagSpecial(const AjPStr tag,AjPStr * pval)5881 AjBool ajFeattagSpecial(const AjPStr tag, AjPStr* pval)
5882 {
5883 /*ajDebug("featTagSpecial '%S'\n", tag);*/
5884
5885 if(ajStrMatchC(tag, "anticodon"))
5886 return featTagSpecialAllAnticodon(*pval);
5887
5888 else if(ajStrMatchC(tag, "bio_material") ||
5889 ajStrMatchC(tag, "culture_collection") ||
5890 ajStrMatchC(tag, "specimen_voucher"))
5891 return featTagSpecialAllBiomaterial(*pval);
5892
5893 else if(ajStrMatchC(tag, "citation"))
5894 return featTagSpecialAllCitation(*pval);
5895
5896 else if(ajStrMatchC(tag, "codon"))
5897 return featTagSpecialAllCodon(pval);
5898
5899 else if(ajStrMatchC(tag, "collection_date"))
5900 return featTagSpecialAllCollectiondate(*pval);
5901
5902 else if(ajStrMatchC(tag, "compare"))
5903 return featTagSpecialAllCompare(*pval);
5904
5905 else if(ajStrMatchC(tag, "cons_splice"))
5906 return featTagSpecialAllConssplice(pval);
5907
5908 else if(ajStrMatchC(tag, "db_xref"))
5909 return featTagSpecialAllDbxref(*pval);
5910
5911 else if(ajStrMatchC(tag, "estimated_length"))
5912 return featTagSpecialAllEstimatedlength(pval);
5913
5914 else if(ajStrMatchC(tag, "inference"))
5915 return featTagSpecialAllInference(*pval);
5916
5917 else if(ajStrMatchC(tag, "lat_lon"))
5918 return featTagSpecialAllLatlon(*pval);
5919
5920 else if(ajStrMatchC(tag, "mobile_element"))
5921 return featTagSpecialAllMobile(*pval);
5922
5923 else if(ajStrMatchC(tag, "ncRNA_class"))
5924 return featTagSpecialAllNcrnaclass(*pval);
5925
5926 else if(ajStrMatchC(tag, "PCR_primers"))
5927 return featTagSpecialAllPcrprimers(*pval);
5928
5929 else if(ajStrMatchC(tag, "protein_id"))
5930 return featTagSpecialAllProteinid(*pval);
5931
5932 else if(ajStrMatchC(tag, "replace"))
5933 return featTagSpecialAllReplace(pval);
5934
5935 else if(ajStrMatchC(tag, "rpt_unit"))
5936 return featTagSpecialAllRptunit(*pval);
5937
5938 else if(ajStrMatchC(tag, "rpt_unit_range") ||
5939 ajStrMatchC(tag, "tag_peptide"))
5940 return featTagSpecialAllRange(*pval);
5941
5942 else if(ajStrMatchC(tag, "rpt_unit_seq"))
5943 return featTagSpecialAllRptunitseq(pval);
5944
5945 else if(ajStrMatchC(tag, "transl_except"))
5946 return featTagSpecialAllTranslexcept(*pval);
5947
5948 else if(ajStrMatchC(tag, "translation"))
5949 return featTagSpecialAllTranslation(pval);
5950
5951 /*ajDebug("Unrecognised special EMBL feature tag '%S'\n", tag);*/
5952 ajFeatWarn("Unrecognised special EMBL feature tag '%S'", tag);
5953
5954 return ajFalse;
5955 }
5956
5957
5958
5959
5960 /* @funcstatic featTagSpecialAllBiomaterial ***********************************
5961 **
5962 ** Tests a string as a valid internal (EMBL) feature /bio_material tag
5963 **
5964 ** The format is a known type and optional :name
5965 **
5966 ** @param [r] val [const AjPStr] parameter value
5967 ** @return [AjBool] ajTrue for a valid value, possibly corrected
5968 ** ajFalse if invalid, to be converted to default (note) type
5969 **
5970 ** @release 6.1.0
5971 ** @@
5972 ******************************************************************************/
5973
featTagSpecialAllBiomaterial(const AjPStr val)5974 static AjBool featTagSpecialAllBiomaterial(const AjPStr val)
5975 {
5976 AjPStr inststr = NULL;
5977 AjPStr collstr = NULL;
5978 AjPStr idstr = NULL;
5979 AjBool ret = ajFalse;
5980
5981 if(!featRegSpecialBiomaterial)
5982 featRegSpecialBiomaterial = ajRegCompC("^([^:]+)(:([^:]+))?(:(.*))?$");
5983
5984 if(ajRegExec(featRegSpecialBiomaterial, val))
5985 {
5986 ajRegSubI(featRegSpecialBiomaterial, 1, &inststr);
5987 ajRegSubI(featRegSpecialBiomaterial, 3, &collstr);
5988 ajRegSubI(featRegSpecialBiomaterial, 5, &idstr);
5989 ret = ajTrue;
5990 }
5991
5992 if(!ret)
5993 {
5994 ajFeatWarn("bad /bio_material value '%S'", val);
5995 }
5996
5997 ajStrDel(&inststr);
5998 ajStrDel(&collstr);
5999 ajStrDel(&idstr);
6000
6001 return ret;
6002 }
6003
6004
6005
6006
6007 /* @funcstatic featTagSpecialAllAnticodon *************************************
6008 **
6009 ** Tests a string as a valid internal (EMBL) feature /anticodon tag
6010 **
6011 ** The format is (pos:base_range,aa:amino_acid)
6012 **
6013 ** @param [r] val [const AjPStr] parameter value
6014 ** @return [AjBool] ajTrue for a valid value, possibly corrected
6015 ** ajFalse if invalid, to be converted to default (note) type
6016 **
6017 ** @release 2.0.0
6018 ** @@
6019 ******************************************************************************/
6020
featTagSpecialAllAnticodon(const AjPStr val)6021 static AjBool featTagSpecialAllAnticodon(const AjPStr val)
6022 {
6023 /*
6024 static AjPStr begstr = NULL;
6025 static AjPStr endstr = NULL;
6026 static AjPStr aastr = NULL;
6027 AjBool saveit = ajFalse;
6028 */
6029 AjBool ret = ajFalse;
6030
6031 if(!featRegSpecialAnticodon)
6032 featRegSpecialAnticodon =
6033 ajRegCompC("^[(]pos:([0-9]+)[.][.]([0-9]+),aa:([^)]+)[)]$");
6034
6035 if(ajRegExec(featRegSpecialAnticodon, val))
6036 {
6037 ret = ajTrue;
6038 /*
6039 if(saveit)
6040 {
6041 ajRegSubI(featRegSpecialAnticodon, 1, &begstr);
6042 ajRegSubI(featRegSpecialAnticodon, 2, &endstr);
6043 ajRegSubI(featRegSpecialAnticodon, 3, &aastr);
6044 }
6045 */
6046
6047 }
6048
6049 if(!ret)
6050 {
6051 ajFeatWarn("bad /anticodon value '%S'", val);
6052 }
6053
6054 return ret;
6055 }
6056
6057
6058
6059
6060 /* @funcstatic featTagSpecialAllCitation **************************************
6061 **
6062 ** Tests a string as a valid internal (EMBL) feature /citation tag
6063 **
6064 ** The format is [1] where the number is a citation in an EMBL entry.
6065 **
6066 ** @param [r] val [const AjPStr] parameter value
6067 ** @return [AjBool] ajTrue for a valid value, possibly corrected
6068 ** ajFalse if invalid, to be converted to default (note) type
6069 **
6070 ** @release 2.0.0
6071 ** @@
6072 ******************************************************************************/
6073
featTagSpecialAllCitation(const AjPStr val)6074 static AjBool featTagSpecialAllCitation(const AjPStr val)
6075 {
6076 const char* cp = ajStrGetPtr(val);
6077 ajint i = 0;
6078 AjBool ret = ajFalse;
6079
6080 if(*cp++ == '[')
6081 {
6082 while(*cp)
6083 {
6084 if(!isdigit((ajint)*cp))
6085 break;
6086
6087 i++;
6088 cp++;
6089 }
6090
6091 if(*cp++ == ']')
6092 if(!*cp)
6093 ret = ajTrue;
6094 if(!i)
6095 ret = ajFalse;
6096 }
6097
6098 if(!ret)
6099 {
6100 ajFeatWarn("bad /citation value '%S'", val);
6101 }
6102
6103 return ret;
6104 }
6105
6106
6107
6108
6109 /* @funcstatic featTagSpecialAllCodon *****************************************
6110 **
6111 ** Tests a string as a valid internal (EMBL) feature /codon tag
6112 **
6113 ** The format is (seq:"ttt",aa:Leu)
6114 **
6115 ** Corrects missing quotes
6116 **
6117 ** @param [u] pval [AjPStr*] parameter value
6118 ** @return [AjBool] ajTrue for a valid value, possibly corrected
6119 ** ajFalse if invalid, to be converted to default (note) type
6120 **
6121 ** @release 2.0.0
6122 ** @@
6123 ******************************************************************************/
6124
featTagSpecialAllCodon(AjPStr * pval)6125 static AjBool featTagSpecialAllCodon(AjPStr* pval)
6126 {
6127 AjPStr seqstr = NULL;
6128 AjPStr aastr = NULL;
6129 AjBool saveit = ajFalse;
6130 AjBool ret = ajFalse;
6131
6132 if(!featRegSpecialCodon)
6133 featRegSpecialCodon =
6134 ajRegCompC("^[(]seq:\"([acgt][acgt][acgt])\",aa:([^)]+)[)]$");
6135
6136 if(!featRegSpecialCodonBad) /* sometimes fails to quote sequence */
6137 featRegSpecialCodonBad =
6138 ajRegCompC("^[(]seq:([acgt][acgt][acgt]),aa:([^)]+)[)]$");
6139
6140 if(ajRegExec(featRegSpecialCodon, *pval))
6141 {
6142 ret = ajTrue;
6143
6144 if(saveit)
6145 {
6146 ajRegSubI(featRegSpecialCodon, 1, &seqstr);
6147 ajRegSubI(featRegSpecialCodon, 2, &aastr);
6148 }
6149 }
6150
6151 else if(ajRegExec(featRegSpecialCodonBad, *pval))
6152 {
6153 ret = ajTrue;
6154 ajRegSubI(featRegSpecialCodonBad, 1, &seqstr); /* needed correction */
6155 ajRegSubI(featRegSpecialCodonBad, 2, &aastr);
6156 ajFmtPrintS(pval, "(seq:\"%S\",aa:%S)",seqstr, aastr);
6157 ajFeatWarn("unquoted /codon value corrected to '%S'", *pval);
6158 }
6159
6160 if(!ret)
6161 {
6162 ajFeatWarn("bad /codon value '%S'", *pval);
6163 }
6164
6165 ajStrDel(&seqstr);
6166 ajStrDel(&aastr);
6167
6168 return ret;
6169 }
6170
6171
6172
6173
6174 /* @funcstatic featTagSpecialAllCollectiondate ********************************
6175 **
6176 ** Tests a string as a valid internal (EMBL) feature /collection_date tag
6177 **
6178 ** The format is YYYY Mmm-YYYY or DD-Mmm-YYYY
6179 **
6180 ** @param [r] val [const AjPStr] parameter value
6181 ** @return [AjBool] ajTrue for a valid value, possibly corrected
6182 ** ajFalse if invalid, to be converted to default (note) type
6183 **
6184 ** @release 4.0.0
6185 ** @@
6186 ******************************************************************************/
6187
featTagSpecialAllCollectiondate(const AjPStr val)6188 static AjBool featTagSpecialAllCollectiondate(const AjPStr val)
6189 {
6190 AjPStr daystr = NULL;
6191 AjPStr monstr = NULL;
6192 ajint day;
6193 ajint i;
6194 AjBool ret = ajFalse;
6195 AjBool ok;
6196 const char* months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
6197 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
6198
6199 if(!featRegSpecialColdate)
6200 featRegSpecialColdate =
6201 ajRegCompC("^((\\d\\d)[-])?(([ADFJMNOS][A-Za-z][A-Za-z])[-])?([12]"
6202 "[7890]\\d\\d)$");
6203
6204 if(ajRegExec(featRegSpecialColdate, val))
6205 {
6206 ret = ajTrue;
6207 ajRegSubI(featRegSpecialColdate, 2, &daystr);
6208 ajRegSubI(featRegSpecialColdate, 4, &monstr);
6209
6210 if(ajStrGetLen(daystr))
6211 {
6212 if(!ajStrGetLen(monstr))
6213 ret = ajFalse;
6214
6215 ajStrToInt(daystr, &day);
6216
6217 if(day<1 || day > 31)
6218 ret = ajFalse;
6219 }
6220
6221 if(ajStrGetLen(monstr))
6222 {
6223 ok = ajFalse;
6224
6225 for(i=0;i<12;i++)
6226 if(ajStrMatchCaseC(monstr, months[i]))
6227 {
6228 ok = ajTrue;
6229 break;
6230 }
6231
6232 if(!ok)
6233 ret = ajFalse;
6234 }
6235 }
6236
6237 if(!ret)
6238 ajFeatWarn("bad /collection_date value '%S'", val);
6239
6240 ajStrDel(&daystr);
6241 ajStrDel(&monstr);
6242
6243 return ret;
6244 }
6245
6246
6247
6248
6249 /* @funcstatic featTagSpecialAllConssplice ************************************
6250 **
6251 ** Tests a string as a valid internal (EMBL) feature /cons_splice tag
6252 **
6253 ** The format is (5'site:YES,3'site:NO) where the booleans can
6254 ** be YES, NO, or ABSENT (intended for use where one site is NO and
6255 ** the other is missing)
6256 **
6257 ** Corrects missing parts of the value and bad case.
6258 **
6259 ** @param [u] pval [AjPStr*] parameter value
6260 ** @return [AjBool] ajTrue for a valid value, possibly corrected
6261 ** ajFalse if invalid, to be converted to default (note) type
6262 **
6263 ** @release 2.0.0
6264 ** @@
6265 ******************************************************************************/
6266
featTagSpecialAllConssplice(AjPStr * pval)6267 static AjBool featTagSpecialAllConssplice(AjPStr* pval)
6268 {
6269 AjPStr begstr = NULL;
6270 AjPStr endstr = NULL;
6271 const char* cp;
6272 const char* cq;
6273 ajint i;
6274 AjBool islow = ajFalse;
6275 AjBool ret = ajFalse;
6276
6277 if(!featRegSpecialConssplice)
6278 featRegSpecialConssplice =
6279 ajRegCompC("^[(]5'site:([A-Za-z]+),3'site:([A-Za-z]+)[)]$");
6280
6281
6282 if(ajStrPrefixC(*pval, "(5'site:") && ajStrGetCharLast(*pval) == ')')
6283 {
6284 cp = ajStrGetPtr(*pval);
6285 cp += 8;
6286 cq = cp;
6287 i=0;
6288
6289 while(*cp && (*cp != ','))
6290 {
6291 if(islower((ajint)*cp++))
6292 islow = ajTrue;
6293
6294 i++;
6295 }
6296
6297 ajStrAssignLenC(&begstr, cq, i);
6298
6299 if(ajCharPrefixC(cp, ",3'site:"))
6300 {
6301 cp += 8;
6302 cq = cp;
6303 i=0;
6304
6305 while(*cp && (*cp != ')'))
6306 {
6307 if(islower((ajint)*cp++))
6308 islow = ajTrue;
6309
6310 i++;
6311 }
6312 ajStrAssignLenC(&endstr, cq, i);
6313
6314 if(*cp == ')' && !*(cp+1) &&
6315 ajStrGetLen(begstr) && ajStrGetLen(endstr))
6316 ret = ajTrue;
6317
6318 switch(ajStrGetCharFirst(begstr))
6319 {
6320 case 'Y':
6321 if(!ajStrMatchCaseC(begstr, "yes"))
6322 ret = ajFalse;
6323
6324 break;
6325 case 'N':
6326 if(!ajStrMatchCaseC(begstr, "no"))
6327 ret = ajFalse;
6328
6329 break;
6330 case 'A':
6331 if(!ajStrMatchCaseC(begstr, "absent"))
6332 ret = ajFalse;
6333
6334 break;
6335 default:
6336 ret = ajFalse;
6337 }
6338
6339 switch(ajStrGetCharFirst(endstr))
6340 {
6341 case 'Y':
6342 if(!ajStrMatchCaseC(endstr, "yes"))
6343 ret = ajFalse;
6344
6345 break;
6346 case 'N':
6347 if(!ajStrMatchCaseC(endstr, "no"))
6348 ret = ajFalse;
6349
6350 break;
6351 case 'A':
6352 if(!ajStrMatchCaseC(endstr, "absent"))
6353 ret = ajFalse;
6354
6355 break;
6356 default:
6357 ret = ajFalse;
6358 }
6359 }
6360 }
6361
6362 if(!ret)
6363 {
6364 ajFeatWarn("bad /cons_splice value '%S'", *pval);
6365 ajDebug("bad /cons_splice value '%S' beg: '%S' end: '%S'",
6366 *pval, begstr, endstr);
6367 }
6368
6369 if(islow)
6370 {
6371 ajFmtPrintS(pval, "(5'site:%S,3'site:%S)", begstr, endstr);
6372 ajFeatWarn("bad /cons_splice value corrected to '%S'", *pval);
6373 }
6374
6375 ajStrDel(&begstr);
6376 ajStrDel(&endstr);
6377
6378 return ret;
6379 }
6380
6381
6382
6383
6384 /* @funcstatic featTagSpecialAllInference *************************************
6385 **
6386 ** Tests a string as a valid internal (EMBL) feature /inference tag
6387 **
6388 ** The format is TYPE:EVIDENCE_BASIS
6389 ** where TYPE is a list of defined values with optionally " (same species)"
6390 ** and EVIDENCE is dbname:accesion.version of algorithm:version
6391 **
6392 ** @param [r] val [const AjPStr] parameter value
6393 ** @return [AjBool] ajTrue for a valid value, possibly corrected
6394 ** ajFalse if invalid, to be converted to default (note) type
6395 **
6396 ** @release 4.0.0
6397 ** @@
6398 ******************************************************************************/
6399
featTagSpecialAllInference(const AjPStr val)6400 static AjBool featTagSpecialAllInference(const AjPStr val)
6401 {
6402 AjPStr typstr = NULL;
6403 ajint i;
6404 AjBool ret = ajFalse;
6405 AjBool ok;
6406 const char* types[] =
6407 {
6408 "non-experimental evidence, no additional details recorded",
6409 "similar to sequence",
6410 "similar to AA sequence",
6411 "similar to AA sequence sequence", /* found in EMBL 104 */
6412 "similar to DNA sequence",
6413 "similar to RNA sequence",
6414 "similar to RNA sequence, mRNA",
6415 "similar to RNA sequence,mRNA", /* nonstandard, found in EMBL 104 */
6416 "similar to RNA sequence, EST",
6417 "similar to RNA sequence, other RNA",
6418 "profile",
6419 "nucleotide motif",
6420 "protein motif",
6421 "ab initio prediction",
6422 "alignment",
6423 NULL
6424 };
6425
6426 if(!featRegSpecialInference)
6427 featRegSpecialInference = ajRegCompC("^([^:]+)(:([^:]+)?)*$");
6428
6429 if(ajRegExec(featRegSpecialInference, val))
6430 {
6431 ret = ajTrue;
6432 ajRegSubI(featRegSpecialInference, 1, &typstr);
6433
6434 ok = ajFalse;
6435 for(i=0; types[i]; i++)
6436 {
6437 if(ajStrPrefixC(typstr, types[i]))
6438 {
6439 if(ajStrMatchC(typstr, types[i]))
6440 {
6441 ok = ajTrue;
6442 break;
6443 }
6444
6445 if(ajStrSuffixC(typstr, " (same species)"))
6446 {
6447 if(ajStrGetLen(typstr) == strlen(types[i]) + 15)
6448 {
6449 ok = ajTrue;
6450 break;
6451 }
6452 }
6453
6454 else if(ajStrSuffixC(typstr, "(same species)"))
6455 { /* found in EMBL 104 without expected space */
6456 if(ajStrGetLen(typstr) == strlen(types[i]) + 14)
6457 {
6458 ok = ajTrue;
6459 break;
6460 }
6461 }
6462
6463 else if(ajStrSuffixC(typstr, " (same species) "))
6464 { /* found in EMBL 104 with extra trailing space */
6465 if(ajStrGetLen(typstr) == strlen(types[i]) + 16)
6466 {
6467 ok = ajTrue;
6468 break;
6469 }
6470 }
6471 }
6472 }
6473
6474 if(!ok)
6475 ret = ajFalse;
6476 }
6477
6478 if(!ret)
6479 ajFeatWarn("bad /inference value '%S' type: '%S'", val, typstr);
6480
6481 ajStrDel(&typstr);
6482 return ret;
6483 }
6484
6485
6486
6487
6488 /* @funcstatic featTagSpecialAllLatlon ****************************************
6489 **
6490 ** Tests a string as a valid internal (EMBL) feature /lat_lon tag
6491 **
6492 ** @param [r] val [const AjPStr] parameter value
6493 ** @return [AjBool] ajTrue for a valid value, possibly corrected
6494 ** ajFalse if invalid, to be converted to default (note) type
6495 **
6496 ** @release 4.0.0
6497 ** @@
6498 ******************************************************************************/
6499
featTagSpecialAllLatlon(const AjPStr val)6500 static AjBool featTagSpecialAllLatlon(const AjPStr val)
6501 {
6502 AjPStr labstr = NULL;
6503 AjBool saveit = ajFalse;
6504 AjBool ret = ajFalse;
6505
6506 if(!featRegSpecialLatlon)
6507 featRegSpecialLatlon = ajRegCompC("^[0-9.]+ [NS] [0-9.]+ [EW]$");
6508
6509 if(ajRegExec(featRegSpecialLatlon, val))
6510 {
6511 ret = ajTrue;
6512 if(saveit)
6513 ajRegSubI(featRegSpecialLatlon, 1, &labstr);
6514 }
6515
6516 if(!ret)
6517 {
6518 ajFeatWarn("bad /lat_lon value '%S'", val);
6519 }
6520
6521 return ret;
6522 }
6523
6524
6525
6526
6527 /* @funcstatic featTagSpecialAllPcrprimers ************************************
6528 **
6529 ** Tests a string as a valid internal (EMBL) feature /PCR_primers tag
6530 **
6531 ** @param [r] val [const AjPStr] parameter value
6532 ** @return [AjBool] ajTrue for a valid value
6533 ** ajFalse if invalid, to be converted to default (note) type
6534 **
6535 ** @release 4.0.0
6536 ** @@
6537 ******************************************************************************/
6538
featTagSpecialAllPcrprimers(const AjPStr val)6539 static AjBool featTagSpecialAllPcrprimers(const AjPStr val)
6540 {
6541 AjBool ret = ajFalse;
6542
6543 if(!featRegSpecialPrimer)
6544 featRegSpecialPrimer = ajRegCompC("^((fwd|rev)_name: [^,]+, )?"
6545 "(fwd|rev)_seq: [acgtubdhkmnrsvwxy<>i]+"
6546 "(, ((fwd|rev)_name: [^,]+, )?"
6547 "(fwd|rev)_seq: [acgtubdhkmnrsvwxy<>i]+)*");
6548
6549 if(ajRegExec(featRegSpecialPrimer, val))
6550 {
6551 ret = ajTrue;
6552 }
6553
6554 if(!ret)
6555 {
6556 ajFeatWarn("bad /PCR_primers value '%S'", val);
6557 }
6558
6559 return ret;
6560 }
6561
6562
6563
6564
6565 /* @funcstatic featTagSpecialAllRptunit ***************************************
6566 **
6567 ** Tests a string as a valid internal (EMBL) feature /rpt_unit tag
6568 **
6569 ** The format is 123..789
6570 ** Labels are also allowed which should be feature tags in the entry.
6571 ** Genbank (NCBI) appear to be putting the sequence consensus in. Usually
6572 ** this is a valid "label" - except of course that the label does not exist.
6573 ** One horror (July 2002) was: /rpt_unit=TCCTCACGTAG(T/C)
6574 ** others are /rpt_unit=gaa;taa /rpt_unit=(CA)2(TG)6(CA)2
6575 ** /rpt_unit=attatatgata(n)6-7gttt(n)3gtagactagtt(n)3ttatgttt
6576 **
6577 ** Version 6 of the feature table allows /rpt_unit="sequence" to include
6578 ** these nasties trim spaces and resolve ambiguities. Not to be used
6579 ** for "alu" etc.
6580 **
6581 ** Location can be complement(nn..nn)
6582 **
6583 ** @param [r] val [const AjPStr] parameter value
6584 ** @return [AjBool] ajTrue for a valid value, possibly corrected
6585 ** ajFalse if invalid, to be converted to default (note) type
6586 **
6587 ** @release 2.0.0
6588 ** @@
6589 ******************************************************************************/
6590
featTagSpecialAllRptunit(const AjPStr val)6591 static AjBool featTagSpecialAllRptunit(const AjPStr val)
6592 {
6593 AjBool ret = ajFalse;
6594
6595 /*
6596 AjBool saveit = ajFalse;
6597 AjPStr begstr = NULL;
6598 AjPStr endstr = NULL;
6599 AjPStr labstr = NULL;
6600 */
6601
6602 if(!featRegSpecialRptRange) /* base range */
6603 featRegSpecialRptRange =
6604 ajRegCompC("^(([a-zA-Z0-9_]+:)?[0-9]+)[.][.]([0-9]+)$");
6605 if(!featRegSpecialRptRangeLab) /* feature label */
6606 featRegSpecialRptRangeLab =
6607 ajRegCompC("^(([a-zA-Z0-9_]+:)?[a-zA-Z0-9_]+)$");
6608 if(!featRegSpecialRptRangeComp) /* complement(base range) */
6609 featRegSpecialRptRangeComp =
6610 ajRegCompC("^(complement[(]([a-zA-Z0-9_]+:)?[0-9]+)"
6611 "[.][.]([0-9]+)[)]$");
6612 if(!featRegSpecialRptunitSeq)
6613 featRegSpecialRptunitSeq =
6614 ajRegCompC("^([abcdghkmnrstuvwxyABCDGHKMNRSTUVWXY0-9/();-]+)$");
6615
6616 if(ajRegExec(featRegSpecialRptRange, val))
6617 {
6618 ret = ajTrue;
6619 /*
6620 if(saveit)
6621 {
6622 ajRegSubI(featRegSpecialRptRange, 1, &begstr);
6623 ajRegSubI(featRegSpecialRptRange, 3, &endstr);
6624 }
6625 */
6626 }
6627
6628 else if(ajRegExec(featRegSpecialRptRangeLab, val))
6629 {
6630 ret = ajTrue;
6631 /*
6632 if(saveit)
6633 ajRegSubI(featRegSpecialRptRangeLab, 1, &labstr);
6634 */
6635 }
6636
6637 else if(ajRegExec(featRegSpecialRptRangeComp, val))
6638 {
6639 ret = ajTrue;
6640 /*
6641 if(saveit)
6642 {
6643 ajRegSubI(featRegSpecialRptRangeComp, 3, &begstr);
6644 ajRegSubI(featRegSpecialRptRangeComp, 1, &endstr);
6645 }
6646 */
6647 }
6648
6649 if(ajRegExec(featRegSpecialRptRangeComp, val))
6650 {
6651 ret = ajTrue;
6652 /*
6653 if(saveit)
6654 {
6655 ajRegSubI(featRegSpecialRptRangeComp, 3, &begstr);
6656 ajRegSubI(featRegSpecialRptRangeComp, 1, &endstr);
6657 }
6658 */
6659 }
6660
6661 /* provided because EMBL/Genbank has things like this:
6662 /rpt_unit=TCCTCACGTAG(T/C)
6663 /rpt_unit=(A)n
6664 */
6665
6666 else if(ajRegExec(featRegSpecialRptunitSeq, val))
6667 {
6668 ret = ajTrue;
6669 /*
6670 if(saveit)
6671 ajRegSubI(featRegSpecialRptunitSeq, 1, &labstr);
6672 */
6673 }
6674
6675 if(!ret)
6676 {
6677 ajFeatWarn("bad /rpt_unit value '%S'", val);
6678 }
6679
6680 return ret;
6681 }
6682
6683
6684
6685
6686 /* @funcstatic featTagSpecialAllRange *****************************************
6687 **
6688 ** Tests a string as a valid internal (EMBL) feature /rpt_unit_range tag
6689 **
6690 ** The format is 123..789
6691 ** Labels are also allowed which should be feature tags in the entry.
6692 ** Genbank (NCBI) appear to be putting the sequence consensus in. Usually
6693 ** this is a valid "label" - except of course that the label does not exist.
6694 ** One horror (July 2002) was: /rpt_unit=TCCTCACGTAG(T/C)
6695 ** others are /rpt_unit=gaa;taa /rpt_unit=(CA)2(TG)6(CA)2
6696 ** /rpt_unit=attatatgata(n)6-7gttt(n)3gtagactagtt(n)3ttatgttt
6697 **
6698 ** Version 6 of the feature table allows /rpt_unit="sequence" to include
6699 ** these nasties trim spaces and resolve ambiguities. Not to be used
6700 ** for "alu" etc.
6701 **
6702 ** Location can be complement(nn..nn)
6703 **
6704 ** @param [r] val [const AjPStr] parameter value
6705 ** @return [AjBool] ajTrue for a valid value, possibly corrected
6706 ** ajFalse if invalid, to be converted to default (note) type
6707 **
6708 ** @release 6.1.0
6709 ** @@
6710 ******************************************************************************/
6711
featTagSpecialAllRange(const AjPStr val)6712 static AjBool featTagSpecialAllRange(const AjPStr val)
6713 {
6714 AjBool ret = ajFalse;
6715 /*
6716 AjBool saveit = ajFalse;
6717 AjPStr begstr = NULL;
6718 AjPStr endstr = NULL;
6719 AjPStr labstr = NULL;
6720 */
6721
6722 if(!featRegSpecialRptRange) /* base range */
6723 featRegSpecialRptRange =
6724 ajRegCompC("^(([a-zA-Z0-9_]+:)?[0-9]+)[.][.]([0-9]+)$");
6725
6726 if(!featRegSpecialRptRangeLab) /* feature label */
6727 featRegSpecialRptRangeLab =
6728 ajRegCompC("^(([a-zA-Z0-9_]+:)?[a-zA-Z0-9_]+)$");
6729
6730 if(!featRegSpecialRptRangeComp) /* complement(base range) */
6731 featRegSpecialRptRangeComp =
6732 ajRegCompC("^(complement[(]([a-zA-Z0-9_]+:)?[0-9]+)"
6733 "[.][.]([0-9]+)[)]$");
6734
6735 if(ajRegExec(featRegSpecialRptRange, val))
6736 {
6737 ret = ajTrue;
6738 /*
6739 if(saveit)
6740 {
6741 ajRegSubI(featRegSpecialRptRange, 1, &begstr);
6742 ajRegSubI(featRegSpecialRptRange, 3, &endstr);
6743 }
6744 */
6745 }
6746
6747 else if(ajRegExec(featRegSpecialRptRangeLab, val))
6748 {
6749 ret = ajTrue;
6750 /*
6751 if(saveit)
6752 ajRegSubI(featRegSpecialRptRangeLab, 1, &labstr);
6753 */
6754 }
6755
6756 else if(ajRegExec(featRegSpecialRptRangeComp, val))
6757 {
6758 ret = ajTrue;
6759 /*
6760 if(saveit)
6761 {
6762 ajRegSubI(featRegSpecialRptRangeComp, 3, &begstr);
6763 ajRegSubI(featRegSpecialRptRangeComp, 1, &endstr);
6764 }
6765 */
6766 }
6767
6768
6769 if(!ret)
6770 {
6771 ajFeatWarn("bad /rpt_unit_tange value '%S'", val);
6772 }
6773
6774 return ret;
6775 }
6776
6777
6778
6779
6780 /* @funcstatic featTagSpecialAllRptunitseq ************************************
6781 **
6782 ** Tests a string as a valid internal (EMBL) feature /rpt_unit_seq tag
6783 **
6784 ** examples from GenBank include /rpt_unit_seq=TCCTCACGTAG(T/C)
6785 ** others are /rpt_unit_seq=gaa;taa /rpt_unit_seq=(CA)2(TG)6(CA)2
6786 ** /rpt_unit_seq=attatatgata(n)6-7gttt(n)3gtagactagtt(n)3ttatgttt
6787 **
6788 ** Corrects extra spaces from long sequence values
6789 **
6790 ** @param [u] pval [AjPStr*] parameter value
6791 ** @return [AjBool] ajTrue for a valid value, possibly corrected
6792 ** ajFalse if invalid, to be converted to default (note) type
6793 **
6794 ** @release 4.0.0
6795 ** @@
6796 ******************************************************************************/
6797
featTagSpecialAllRptunitseq(AjPStr * pval)6798 static AjBool featTagSpecialAllRptunitseq(AjPStr *pval)
6799 {
6800 AjBool ret = ajFalse;
6801 ajuint i;
6802 const char* specials[] =
6803 {
6804 "a-rich", /* found in EMBL 104 */
6805 "at-rich", /* found in EMBL 104 */
6806 "c-rich", /* found in EMBL 104 */
6807 "ct-rich", /* found in EMBL 104 */
6808 "CT-rich", /* found in EMBL 104 */
6809 "g-rich", /* found in EMBL 104 */
6810 "ga-rich", /* found in EMBL 104 */
6811 "GA-rich", /* found in EMBL 104 */
6812 "gc-rich", /* found in EMBL 104 */
6813 "t-rich", /* found in EMBL 104 */
6814 "CT_AT", /* found in EMBL 104 */
6815 "TA_CA", /* found in EMBL 104 */
6816 "AGAT_AGAC", /* found in EMBL 104 */
6817 "GAA-repeat", /* found in EMBL 104 */
6818 "GGA-repeat", /* found in EMBL 104 */
6819 "tgtc (imperfect)", /* found in EMBL 104 */
6820 "score", /* found in EMBL 104 */
6821 "direct", /* found in EMBL 104 */
6822 "dispersed", /* found in EMBL 104 */
6823 "inverted", /* found in EMBL 104 */
6824 "ca repeat", /* found in EMBL 104 */
6825 "cac/caa/cag compound repeat", /* found in EMBL 104 */
6826 "cata interrupted repeat", /* found in EMBL 104 */
6827 "CA dinucleotide microsatellite", /* found in EMBL 104 */
6828 "gaa/gac compound repeat", /* found in EMBL 104 */
6829 "dodecanucleotide", /* found in EMBL 104 */
6830 "heptamer", /* found in EMBL 104 */
6831 "gttt..gt", /* found in EMBL 104 */
6832 "telunit", /* found in EMBL 104 */
6833 "af(12)", /* found in EMBL 104 */
6834 "alu", /* found in EMBL 104 */
6835 "Alu", /* found in EMBL 104 */
6836 "AluJo", /* found in EMBL 104 */
6837 "AluSg", /* found in EMBL 104 */
6838 "AluY", /* found in EMBL 104 */
6839 "hif2DR", /* found in EMBL 104 */
6840 "B1element", /* found in EMBL 104 */
6841 "L1MC/D", /* found in EMBL 104 */
6842 "L1MC3", /* found in EMBL 104 */
6843 "L1MD3", /* found in EMBL 104 */
6844 "L1ME", /* found in EMBL 104 */
6845 "RMER17B", /* found in EMBL 104 */
6846 "RLTR11A", /* found in EMBL 104 */
6847 "poly A", /* found in EMBL 104 */
6848 "core-vntr1", /* found in EMBL 104 */
6849 "core-vntr2", /* found in EMBL 104 */
6850 NULL
6851 };
6852
6853 /*
6854 AjBool saveit = ajFalse;
6855 AjPStr labstr = NULL;
6856 */
6857
6858 if(!featRegSpecialRptunitSeq)
6859 featRegSpecialRptunitSeq =
6860 ajRegCompC("^([ abcdghkmnrstuvwxyABCDGHKMNRSTUVWXY0-9"
6861 "_/\\[\\]\\(\\):;.,+-]+)$");
6862
6863 if(!featRegSpecialRptunitSeqPos)
6864 featRegSpecialRptunitSeqPos =
6865 ajRegCompC("^((complement[\\(])?[<]?\\d+[.][.]?[>]?\\d+[\\)]?)$");
6866
6867 if(ajRegExec(featRegSpecialRptunitSeq, *pval))
6868 {
6869 ajStrRemoveWhite(pval); /* remove wrapping spaces in long seq. */
6870
6871 ret = ajTrue;
6872 /*
6873 if(saveit)
6874 ajRegSubI(featRegSpecialRptunitSeq, 1, &labstr);
6875 */
6876 }
6877 else if(ajRegExec(featRegSpecialRptunitSeqPos, *pval))
6878 {
6879 ret = ajTrue;
6880 }
6881 else
6882 {
6883 for(i=0; specials[i]; i++)
6884 {
6885 if(ajStrMatchC(*pval, specials[i]))
6886 {
6887 ret = ajTrue;
6888 break;
6889 }
6890 }
6891 }
6892
6893 if(!ret)
6894 {
6895 ajFeatWarn("bad /rpt_unit_seq value '%S'", *pval);
6896 }
6897
6898 return ret;
6899 }
6900
6901
6902
6903
6904 /* @funcstatic featTagSpecialAllTranslexcept **********************************
6905 **
6906 ** Tests a string as a valid internal (EMBL) feature /transl_except tag
6907 **
6908 ** The format is (pos:213..215,aa:Trp)
6909 **
6910 ** FT 6.2 todo aa 3 letter codes, or Sec (U) or TERM or OTHER
6911 **
6912 ** FT 6.2 todo pos can be 1 or 2 bases for polyA-completed stops (TERM)
6913 ** which should have a /note
6914 **
6915 ** @param [r] val [const AjPStr] parameter value
6916 ** @return [AjBool] ajTrue for a valid value, possibly corrected
6917 ** ajFalse if invalid, to be converted to default (note) type
6918 **
6919 ** @release 2.0.0
6920 ** @@
6921 ******************************************************************************/
6922
featTagSpecialAllTranslexcept(const AjPStr val)6923 static AjBool featTagSpecialAllTranslexcept(const AjPStr val)
6924 {
6925 AjBool saveit = ajFalse;
6926 AjBool ret = ajFalse;
6927
6928 if(!featRegSpecialTrans)
6929 featRegSpecialTrans =
6930 ajRegCompC("^[(]pos:([0-9]+)[.][.]([0-9]+),aa:([^)]+)[)]$");
6931
6932 if(!featRegSpecialTransBad) /* start position only */
6933 featRegSpecialTransBad =
6934 ajRegCompC("^[(]pos:([0-9]+),aa:([^)]+)[)]$");
6935
6936 if(!featRegSpecialTransComp)
6937 featRegSpecialTransComp =
6938 ajRegCompC("^[(]pos:complement\\(([0-9]+)[.][.]([0-9]+)\\),"
6939 "aa:([^)]+)[)]$");
6940
6941 if(!featRegSpecialTransBadComp)
6942 featRegSpecialTransBadComp =
6943 ajRegCompC("^[(]pos:complement\\(([0-9]+)\\),"
6944 "aa:([^)]+)[)]$");
6945
6946 if(ajRegExec(featRegSpecialTrans, val))
6947 {
6948 ret = ajTrue;
6949
6950 if(saveit)
6951 {
6952 ajRegSubI(featRegSpecialTrans, 1, &featTransBegStr);
6953 ajRegSubI(featRegSpecialTrans, 2, &featTransEndStr);
6954 ajRegSubI(featRegSpecialTrans, 3, &featTransAaStr);
6955 }
6956 }
6957 else if(ajRegExec(featRegSpecialTransComp, val))
6958 {
6959 ret = ajTrue;
6960
6961 if(saveit)
6962 {
6963 ajRegSubI(featRegSpecialTransComp, 1, &featTransBegStr);
6964 ajRegSubI(featRegSpecialTransComp, 2, &featTransEndStr);
6965 ajRegSubI(featRegSpecialTransComp, 3, &featTransAaStr);
6966 }
6967 }
6968
6969 /* Can have single base (or 2 base) positions where trailing As are
6970 added as post-processing in some species */
6971
6972 else if(ajRegExec(featRegSpecialTransBad, val))
6973 {
6974 ret = ajTrue;
6975
6976 if(saveit)
6977 {
6978 ajRegSubI(featRegSpecialTransBad, 1, &featTransBegStr);
6979 ajRegSubI(featRegSpecialTransBad, 2, &featTransAaStr);
6980 }
6981 }
6982 else if(ajRegExec(featRegSpecialTransBadComp, val))
6983 {
6984 ret = ajTrue;
6985
6986 if(saveit)
6987 {
6988 ajRegSubI(featRegSpecialTransBadComp, 1, &featTransBegStr);
6989 ajRegSubI(featRegSpecialTransBadComp, 2, &featTransAaStr);
6990 }
6991 }
6992
6993 if(!ret)
6994 {
6995 ajFeatWarn("bad /transl_except value '%S'", val);
6996 }
6997
6998 return ret;
6999 }
7000
7001
7002
7003
7004 /* @funcstatic featTagSpecialAllDbxref ****************************************
7005 **
7006 ** Tests a string as a valid internal (EMBL) feature /db_xref tag
7007 **
7008 ** The format is <database>:<identifier>
7009 **
7010 ** @param [r] val [const AjPStr] parameter value
7011 ** @return [AjBool] ajTrue for a valid value, possibly corrected
7012 ** ajFalse if invalid, to be converted to default (note) type
7013 **
7014 ** @release 2.0.0
7015 ** @@
7016 ******************************************************************************/
7017
featTagSpecialAllDbxref(const AjPStr val)7018 static AjBool featTagSpecialAllDbxref(const AjPStr val)
7019 {
7020 const char* cp = NULL;
7021 AjBool ret = ajTrue;
7022
7023 /*
7024 AjBool saveit = ajFalse;
7025 AjPStr dbstr = NULL;
7026 AjPStr idstr = NULL;
7027 */
7028
7029 cp = ajStrGetPtr(val);
7030 /*
7031 if(saveit)
7032 ajStrAssignResC(&dbstr, ajStrGetLen(val), "");
7033 */
7034 while(*cp && (*cp != ':'))
7035 {
7036 /*
7037 if(saveit)
7038 ajStrAppendK(&dbstr, *cp);
7039 */
7040 cp++;
7041 }
7042
7043 if(!*cp)
7044 ret = ajFalse;
7045 else
7046 {
7047 cp++;
7048 if(!*cp)
7049 ret = ajFalse;
7050 }
7051
7052 /*
7053 if(saveit)
7054 ajStrAssignC(&idstr, cp);
7055 */
7056
7057 if(!ret)
7058 {
7059 ajFeatWarn("bad /db_xref value '%S'", val);
7060 }
7061
7062 return ret;
7063 }
7064
7065
7066
7067
7068 /* @funcstatic featTagSpecialAllProteinid *************************************
7069 **
7070 ** Tests a string as a valid internal (EMBL) feature /protein_id tag
7071 **
7072 ** The format is AAA12345.1
7073 **
7074 ** @param [r] val [const AjPStr] parameter value
7075 ** @return [AjBool] ajTrue for a valid value, possibly corrected
7076 ** ajFalse if invalid, to be converted to default (note) type
7077 **
7078 ** @release 2.0.0
7079 ** @@
7080 ******************************************************************************/
7081
featTagSpecialAllProteinid(const AjPStr val)7082 static AjBool featTagSpecialAllProteinid(const AjPStr val)
7083 {
7084 const char* cp = ajStrGetPtr(val);
7085 /* const char* cq; */
7086 ajint icp;
7087 ajint i = 0;
7088 ajint idot = 0;
7089 AjBool ret = ajFalse;
7090
7091 /*
7092 AjBool saveit = ajFalse;
7093 AjPStr idstr = NULL;
7094 AjPStr preidstr = NULL;
7095 */
7096
7097 if(ajStrPrefixC(val, "ENSP")) /* older entries had ENSEMBL Protein IDs */
7098 {
7099 cp += 4;
7100
7101 while(*cp)
7102 {
7103 if(!isdigit((ajint)*cp++))
7104 break;
7105 i++;
7106 }
7107
7108 /* ENSP then all numbers */
7109 if(!*cp && i > 5)
7110 ret = ajTrue;
7111
7112 /* if(ret)
7113 ajFeatWarn("ENSEMBL /protein_id value '%S'", val);*/
7114
7115 /*
7116 if(saveit)
7117 {
7118 ajStrAssignS(&preidstr, val);
7119 ajStrAssignS(&idstr, val);
7120 }
7121 */
7122 }
7123 else
7124 {
7125 cp = ajStrGetPtr(val);
7126 /* cq = cp; */
7127 i=0;
7128 while(*cp)
7129 {
7130 i++;
7131 icp = *cp;
7132
7133 if(i <= 3)
7134 {
7135 if(icp == '_')
7136 {
7137 if(i!=3)
7138 break;
7139 }
7140 else if(!isalpha(icp) || !isupper(icp))
7141 break;
7142 }
7143 else if(*cp == '.')
7144 {
7145 if(idot) /* once only */
7146 break;
7147
7148 idot = i;
7149
7150 if(idot < 9) /* at least ABC12345. */
7151 break;
7152 }
7153 else
7154 {
7155 if(!isdigit(icp))
7156 break;
7157 }
7158 cp++;
7159 }
7160
7161 /*
7162 if(saveit)
7163 {
7164 ajStrAssignLenC(&preidstr, cq, idot-1);
7165 ajStrAssignLenC(&idstr, cq, i);
7166 }
7167 */
7168
7169 if(!*cp && idot && (i > idot))
7170 ret = ajTrue;
7171 }
7172
7173 if(!ret)
7174 {
7175 ajFeatWarn("bad /protein_id value '%S'", val);
7176 }
7177
7178 return ret;
7179 }
7180
7181
7182
7183
7184 /* @funcstatic featTagSpecialAllReplace ***************************************
7185 **
7186 ** Tests a string as a valid internal (EMBL) feature /replace tag
7187 **
7188 ** The format is "<sequence>" where sequence is empty for a deletion
7189 **
7190 ** Corrects extra spaces from long sequence values
7191 **
7192 ** @param [u] pval [AjPStr*] parameter value
7193 ** @return [AjBool] ajTrue for a valid value, possibly corrected
7194 ** ajFalse if invalid, to be converted to default (note) type
7195 **
7196 ** @release 2.0.0
7197 ** @@
7198 ******************************************************************************/
7199
featTagSpecialAllReplace(AjPStr * pval)7200 static AjBool featTagSpecialAllReplace(AjPStr* pval)
7201 {
7202 AjBool ret = ajFalse;
7203
7204 /* n is used in old_sequence */
7205 /* and in misc_difference features */
7206 if(!featRegTagReplace)
7207 featRegTagReplace =
7208 ajRegCompC("^([abcdghkmnrstuvwxyABCDGHKMNRSTUVWXY/-]*)$");
7209
7210 /* if(!featRegTagReplace)
7211 featRegTagReplace = ajRegCompC("^\"([acgt]*)\"$");*/
7212
7213 /* no need to add quotes here - we will add them if needed on output */
7214
7215 /*
7216 ajDebug("Before quote '%S' %c %c\n", *pval,
7217 ajStrGetCharFirst(*pval), ajStrGetCharLast(*pval));
7218 ajStrFmtQuote(pval);
7219 ajDebug(" After quote '%S' %c %c\n", *pval,
7220 ajStrGetCharFirst(*pval), ajStrGetCharLast(*pval));
7221 */
7222
7223 ajStrRemoveWhite(pval); /* remove wrapping spaces in long seq. */
7224
7225 if(ajRegExec(featRegTagReplace, *pval))
7226 ret = ajTrue; /* substring 1 has the matched sequence */
7227
7228 if(!ret)
7229 {
7230 ajFeatWarn("bad /replace value '%S'", *pval);
7231 }
7232
7233 return ret;
7234 }
7235
7236
7237
7238
7239 /* @funcstatic featTagSpecialAllTranslation ***********************************
7240 **
7241 ** Tests a string as a valid internal (EMBL) feature /translation tag
7242 **
7243 ** The format is valid amino acid codes, no white space
7244 **
7245 ** Corrects extra spaces from long sequence values
7246 **
7247 ** @param [u] pval [AjPStr*] parameter value
7248 ** @return [AjBool] ajTrue for a valid value, possibly corrected
7249 ** ajFalse if invalid, to be converted to default (note) type
7250 **
7251 ** @release 2.0.0
7252 ** @@
7253 ******************************************************************************/
7254
featTagSpecialAllTranslation(AjPStr * pval)7255 static AjBool featTagSpecialAllTranslation(AjPStr* pval)
7256 {
7257 AjPStr seqstr = NULL;
7258 const char* cp;
7259 ajint icp;
7260 AjBool saveit = ajFalse;
7261 AjBool ret = ajFalse;
7262
7263 ajStrRemoveWhite(pval); /* remove wrapping spaces in long seq. */
7264 cp = ajStrGetPtr(*pval);
7265
7266 if(saveit)
7267 ajStrAssignResC(&seqstr, ajStrGetLen(*pval), "");
7268
7269 while(*cp)
7270 {
7271 icp = *cp;
7272
7273 if(!isalpha(icp))
7274 break;
7275
7276 if(!isupper(icp))
7277 break;
7278
7279 /* if(strchr("JO",icp))
7280 break; */
7281
7282 if(saveit)
7283 ajStrAppendK(&seqstr, *cp);
7284 cp++;
7285 }
7286
7287 if(!*cp)
7288 ret = ajTrue;
7289
7290 if(!ret)
7291 {
7292 ajFeatWarn("bad /translation value '%S'", *pval);
7293 }
7294
7295 return ret;
7296 }
7297
7298
7299
7300
7301 /* @funcstatic featTagSpecialAllEstimatedlength *******************************
7302 **
7303 ** Tests a string as a valid internal (EMBL) feature /estimated_length tag
7304 **
7305 ** The format is a positive integer, or unknown (unquoted)
7306 **
7307 ** @param [u] pval [AjPStr*] parameter value
7308 ** @return [AjBool] ajTrue for a valid value, possibly corrected
7309 ** ajFalse if invalid, to be converted to default (note) type
7310 **
7311 ** @release 3.0.0
7312 ** @@
7313 ******************************************************************************/
7314
featTagSpecialAllEstimatedlength(AjPStr * pval)7315 static AjBool featTagSpecialAllEstimatedlength(AjPStr* pval)
7316 {
7317 AjPStr numstr = NULL;
7318 AjBool saveit = ajFalse;
7319 AjBool ret = ajFalse;
7320
7321 if(!featRegSpecialEstlen)
7322 featRegSpecialEstlen = ajRegCompC("^(unknown|[1-9][0-9]*)$");
7323
7324 if(ajRegExec(featRegSpecialEstlen, *pval))
7325 {
7326 ret = ajTrue;
7327
7328 if(saveit)
7329 ajRegSubI(featRegSpecialEstlen, 1, &numstr);
7330 }
7331
7332 if(!ret)
7333 {
7334 ajFeatWarn("bad /estimated_length value '%S' corrected to 'unknown'",
7335 *pval);
7336 ajStrAssignC(pval, "unknown");
7337 }
7338
7339 ajStrDel(&numstr);
7340
7341 return ret;
7342 }
7343
7344
7345
7346
7347 /* @funcstatic featTagSpecialAllCompare ***************************************
7348 **
7349 ** Tests a string as a valid internal (EMBL) feature /compare tag
7350 **
7351 ** The format is a sequence versin
7352 **
7353 ** @param [r] val [const AjPStr] parameter value
7354 ** @return [AjBool] ajTrue for a valid value, possibly corrected
7355 ** ajFalse if invalid, to be converted to default (note) type
7356 **
7357 ** @release 3.0.0
7358 ** @@
7359 ******************************************************************************/
7360
featTagSpecialAllCompare(const AjPStr val)7361 static AjBool featTagSpecialAllCompare(const AjPStr val)
7362 {
7363 AjPStr numstr = NULL;
7364 AjBool saveit = ajFalse;
7365 AjBool ret = ajFalse;
7366
7367 /* value is a sequence version accnumber.number */
7368 if(!featRegSpecialCompare)
7369 featRegSpecialCompare = ajRegCompC("^([A-Z]+[0-9]+([.][1-9][0-9]*)?)$");
7370
7371 if(ajRegExec(featRegSpecialCompare, val))
7372 {
7373 ret = ajTrue;
7374 if(saveit)
7375 ajRegSubI(featRegSpecialCompare, 1, &numstr);
7376 }
7377
7378 if(!ret)
7379 {
7380 ajFeatWarn("bad /compare value '%S'", val);
7381 }
7382 ajStrDel(&numstr);
7383
7384 return ret;
7385 }
7386
7387
7388
7389
7390 /* @funcstatic featTagSpecialAllMobile ****************************************
7391 **
7392 ** Tests a string as a valid internal (EMBL) feature /mobile_element tag
7393 **
7394 ** The format is a known type and optional :name
7395 **
7396 ** @param [r] val [const AjPStr] parameter value
7397 ** @return [AjBool] ajTrue for a valid value, possibly corrected
7398 ** ajFalse if invalid, to be converted to default (note) type
7399 **
7400 ** @release 5.0.0
7401 ** @@
7402 ******************************************************************************/
7403
featTagSpecialAllMobile(const AjPStr val)7404 static AjBool featTagSpecialAllMobile(const AjPStr val)
7405 {
7406 AjPStr typstr = NULL;
7407 AjPStr namstr = NULL;
7408 AjBool saveit = ajFalse;
7409 AjBool ret = ajFalse;
7410 ajuint i;
7411
7412 const char* elements[] =
7413 {
7414 "transposon", "retrotransposon", "integron",
7415 "insertion sequence", "non-LTR retrotransposon",
7416 "SINE", "MITE", "LINE", "other", NULL
7417 };
7418
7419 /* value is a type or type:name */
7420 if(!featRegSpecialMobile)
7421 featRegSpecialMobile = ajRegCompC("^([^:]+)(:(.*))?$");
7422
7423 if(ajRegExec(featRegSpecialMobile, val))
7424 {
7425 ajRegSubI(featRegSpecialMobile, 1, &typstr);
7426
7427 for(i=0;elements[i];i++)
7428 if(ajStrMatchC(typstr, elements[i])) break;
7429
7430 if(elements[i])
7431 ret = ajTrue;
7432
7433 if(saveit)
7434 {
7435 ajRegSubI(featRegSpecialMobile, 3, &namstr);
7436 }
7437 }
7438
7439 if(!ret)
7440 {
7441 ajFeatWarn("bad /mobile_element value '%S'", val);
7442 }
7443 ajStrDel(&typstr);
7444 ajStrDel(&namstr);
7445
7446 return ret;
7447 }
7448
7449
7450
7451
7452 /* @funcstatic featTagSpecialAllNcrnaclass ************************************
7453 **
7454 ** Tests a string as a valid internal (EMBL) feature /ncRNA_class tag
7455 **
7456 ** The format is a known type and optional :name
7457 **
7458 ** value is a term taken from the INSDC controlled vocabulary for ncRNA classes
7459 ** http://www.insdc.org/page.php?page=rna_vocab
7460 ** or http://www.ebi.ac.uk/embl/Documentation/ncRNA_class.html
7461 **
7462 ** @param [r] val [const AjPStr] parameter value
7463 ** @return [AjBool] ajTrue for a valid value, possibly corrected
7464 ** ajFalse if invalid, to be converted to default (note) type
7465 **
7466 ** @release 6.1.0
7467 ** @@
7468 ******************************************************************************/
7469
featTagSpecialAllNcrnaclass(const AjPStr val)7470 static AjBool featTagSpecialAllNcrnaclass(const AjPStr val)
7471 {
7472 AjPStr typstr = NULL;
7473 AjPStr namstr = NULL;
7474 AjBool ret = ajFalse;
7475 ajuint i;
7476
7477 const char* classes[] =
7478 {
7479 "antisense_RNA", "autocatalytically_spliced_intron",
7480 "ribozyme", "hammerhead_ribozyme",
7481 "RNase_P_RNA",
7482 "RNase_MRP_RNA", "telomerase_RNA", "guide_RNA", "rasiRNA",
7483 "scRNA", "siRNA", "miRNA", "piRNA",
7484 "snoRNA", "snRNA", "SRP_RNA", "vault_RNA", "Y_RNA",
7485 "other",
7486 NULL
7487 };
7488
7489 for(i=0;classes[i];i++)
7490 if(ajStrMatchC(val, classes[i])) break;
7491
7492 if(classes[i])
7493 ret = ajTrue;
7494
7495 if(!ret)
7496 {
7497 ajFeatWarn("bad /ncRNA_class value '%S'", val);
7498 }
7499
7500 ajStrDel(&typstr);
7501 ajStrDel(&namstr);
7502
7503 return ret;
7504 }
7505
7506
7507
7508
7509 /* @funcstatic featTagSetDefault **********************************************
7510 **
7511 ** Sets a feature tag value, using the default feature tag
7512 **
7513 ** @param [u] thys [AjPFeature] Feature
7514 ** @param [r] tag [const AjPStr] Feature tag
7515 ** @param [r] value [const AjPStr] feature tag value
7516 ** @param [w] Pdeftag [AjPStr*] Default tag
7517 ** @param [w] Pdefval [AjPStr*] Default tag value as "*tag: value"
7518 ** @return [void]
7519 **
7520 ** @release 2.0.0
7521 ** @@
7522 ******************************************************************************/
7523
featTagSetDefault(AjPFeature thys,const AjPStr tag,const AjPStr value,AjPStr * Pdeftag,AjPStr * Pdefval)7524 static void featTagSetDefault(AjPFeature thys,
7525 const AjPStr tag, const AjPStr value,
7526 AjPStr* Pdeftag, AjPStr* Pdefval)
7527 {
7528 featInit();
7529
7530 if(thys->Protein)
7531 featTagSetDefaultDna(tag, value, Pdeftag, Pdefval);
7532 else
7533 featTagSetDefaultProt(tag, value, Pdeftag, Pdefval);
7534
7535 return;
7536 }
7537
7538
7539
7540
7541 /* @funcstatic featTagSetDefaultDna *******************************************
7542 **
7543 ** Sets a feature tag value, using the default DNA feature tag
7544 **
7545 ** @param [r] tag [const AjPStr] Feature tag
7546 ** @param [r] value [const AjPStr] feature tag value
7547 ** @param [w] Pdeftag [AjPStr*] Default tag
7548 ** @param [w] Pdefval [AjPStr*] Default tag value as "*tag: value"
7549 ** @return [void]
7550 **
7551 ** @release 2.0.0
7552 ** @@
7553 ******************************************************************************/
7554
featTagSetDefaultDna(const AjPStr tag,const AjPStr value,AjPStr * Pdeftag,AjPStr * Pdefval)7555 static void featTagSetDefaultDna(const AjPStr tag, const AjPStr value,
7556 AjPStr* Pdeftag, AjPStr* Pdefval)
7557 {
7558 featInit();
7559
7560 ajStrAssignS(Pdeftag,
7561 (const AjPStr) ajTableFetchC(FeatTagsTableDna, ""));
7562 ajFmtPrintS(Pdefval, "*%S: %S", tag, value);
7563
7564 return;
7565 }
7566
7567
7568
7569
7570 /* @funcstatic featTagSetDefaultProt ******************************************
7571 **
7572 ** Sets a feature tag value, using the default protein feature tag
7573 **
7574 ** @param [r] tag [const AjPStr] Feature tag
7575 ** @param [r] value [const AjPStr] feature tag value
7576 ** @param [w] Pdeftag [AjPStr*] Default tag
7577 ** @param [w] Pdefval [AjPStr*] Default tag value as "*tag: value"
7578 ** @return [void]
7579 **
7580 ** @release 2.0.0
7581 ** @@
7582 ******************************************************************************/
7583
featTagSetDefaultProt(const AjPStr tag,const AjPStr value,AjPStr * Pdeftag,AjPStr * Pdefval)7584 static void featTagSetDefaultProt(const AjPStr tag, const AjPStr value,
7585 AjPStr* Pdeftag, AjPStr* Pdefval)
7586 {
7587 featInit();
7588
7589 ajStrAssignS(Pdeftag,
7590 (const AjPStr) ajTableFetchC(FeatTagsTableProtein, ""));
7591 ajFmtPrintS(Pdefval, "*%S: %S", tag, value);
7592
7593 return;
7594 }
7595
7596
7597
7598
7599 /* @func ajFeattableNew *******************************************************
7600 **
7601 ** Constructor for a new (generic) feature table.
7602 ** Does not define the feature table type.
7603 **
7604 ** @param [r] name [const AjPStr] Name for new feature table
7605 ** (or NULL for unnamed)
7606 ** @return [AjPFeattable] Pointer to a new (empty) feature table
7607 ** @category new [AjPFeattable] Constructor
7608 **
7609 ** @release 2.0.0
7610 ** @@
7611 ******************************************************************************/
7612
ajFeattableNew(const AjPStr name)7613 AjPFeattable ajFeattableNew(const AjPStr name )
7614 {
7615 AjPFeattable thys = NULL;
7616
7617 /* Allocate the object... */
7618 thys = featTableNewS(name) ;
7619
7620 /*ajDebug("ajFeattableNew %x\n", thys);*/
7621
7622 return thys;
7623 }
7624
7625
7626
7627
7628 /* @func ajFeattableReset *****************************************************
7629 **
7630 ** Resets a feature table with a new name
7631 **
7632 ** @param [u] thys [AjPFeattable] Feature table
7633 ** @param [r] name [const AjPStr] Name for new feature table
7634 ** @return [void]
7635 **
7636 ** @release 6.6.0
7637 ** @@
7638 ******************************************************************************/
7639
ajFeattableReset(AjPFeattable thys,const AjPStr name)7640 void ajFeattableReset(AjPFeattable thys, const AjPStr name)
7641 {
7642 ajFeattableClear(thys);
7643
7644 ajStrAssignS(&thys->Seqid, name);
7645
7646 return;
7647 }
7648
7649
7650
7651
7652 /* @func ajFeattableSetCircular ***********************************************
7653 **
7654 ** Sets a feature table to be circular
7655 **
7656 ** @param [u] thys [AjPFeattable] Feature table
7657 ** @return [void]
7658 **
7659 ** @release 6.5.0
7660 ** @@
7661 ******************************************************************************/
7662
ajFeattableSetCircular(AjPFeattable thys)7663 void ajFeattableSetCircular(AjPFeattable thys)
7664 {
7665 thys->Circular = ajTrue;
7666
7667 return;
7668 }
7669
7670
7671
7672
7673 /* @func ajFeattableSetDefname ************************************************
7674 **
7675 ** Provides a unique (for this program run) name for a feature table.
7676 **
7677 ** @param [w] thys [AjPFeattable] Feature table
7678 ** @param [r] setname [const AjPStr] Name set by caller
7679 ** @return [void]
7680 **
7681 ** @release 6.2.0
7682 ** @@
7683 ******************************************************************************/
7684
ajFeattableSetDefname(AjPFeattable thys,const AjPStr setname)7685 void ajFeattableSetDefname(AjPFeattable thys, const AjPStr setname)
7686 {
7687 if(ajStrGetLen(thys->Seqid))
7688 {
7689 ajDebug("ajFeattableSetDefname already has a name '%S'\n", thys->Seqid);
7690 return;
7691 }
7692
7693 if(ajStrGetLen(setname))
7694 ajStrAssignS(&thys->Seqid, setname);
7695
7696 ajDebug("ajFeattableSetDefname set to '%S'\n", setname);
7697
7698 return;
7699 }
7700
7701
7702
7703
7704 /* @func ajFeattableSetLength *************************************************
7705 **
7706 ** Sets the length of a feature table with the length of the source sequence.
7707 **
7708 ** This is needed to reverse the table correctly
7709 **
7710 ** @param [u] thys [AjPFeattable] Feature table object
7711 ** @param [r] len [ajuint] Length
7712 ** @return [void]
7713 **
7714 ** @release 6.0.0
7715 ** @@
7716 **
7717 ******************************************************************************/
7718
ajFeattableSetLength(AjPFeattable thys,ajuint len)7719 void ajFeattableSetLength(AjPFeattable thys, ajuint len)
7720 {
7721 thys->Len = len;
7722
7723 return;
7724 }
7725
7726
7727
7728
7729 /* @func ajFeattableSetLinear *************************************************
7730 **
7731 ** Sets a feature table to be linear
7732 **
7733 ** @param [w] thys [AjPFeattable] Feature table
7734 ** @return [void]
7735 **
7736 ** @release 6.5.0
7737 ** @@
7738 ******************************************************************************/
7739
ajFeattableSetLinear(AjPFeattable thys)7740 void ajFeattableSetLinear(AjPFeattable thys)
7741 {
7742 thys->Circular = ajFalse;
7743
7744 return;
7745 }
7746
7747
7748
7749
7750 /* @func ajFeattableSetNuc ****************************************************
7751 **
7752 ** Sets the type of a feature table as nucleotide
7753 **
7754 ** @param [u] thys [AjPFeattable] Feature table object
7755 ** @return [void]
7756 **
7757 ** @release 4.0.0
7758 ** @@
7759 **
7760 ******************************************************************************/
7761
ajFeattableSetNuc(AjPFeattable thys)7762 void ajFeattableSetNuc(AjPFeattable thys)
7763 {
7764 ajStrAssignEmptyC(&thys->Type, "N");
7765
7766 return;
7767 }
7768
7769
7770
7771
7772 /* @func ajFeattableSetProt ***************************************************
7773 **
7774 ** Sets the type of a feature table as Protein
7775 **
7776 ** @param [u] thys [AjPFeattable] Feature table object
7777 ** @return [void]
7778 **
7779 ** @release 2.1.0
7780 ** @@
7781 **
7782 ******************************************************************************/
7783
ajFeattableSetProt(AjPFeattable thys)7784 void ajFeattableSetProt(AjPFeattable thys)
7785 {
7786 ajStrAssignEmptyC(&thys->Type, "P");
7787
7788 return;
7789 }
7790
7791
7792
7793
7794 /* @func ajFeattableSetRange **************************************************
7795 **
7796 ** Set the begin and end range for a feature table
7797 **
7798 ** @param [u] thys [AjPFeattable] Feature table object
7799 ** @param [r] fbegin [ajint] Begin position
7800 ** @param [r] fend [ajint] End position
7801 ** @return [void]
7802 **
7803 ** @release 2.5.0
7804 ******************************************************************************/
7805
ajFeattableSetRange(AjPFeattable thys,ajint fbegin,ajint fend)7806 void ajFeattableSetRange(AjPFeattable thys, ajint fbegin, ajint fend)
7807 {
7808 thys->Start = ajFeattablePosI(thys, 1, fbegin);
7809 thys->End = ajFeattablePosII(thys->Len, thys->Start, fend);
7810
7811 return;
7812 }
7813
7814
7815
7816
7817 /* @func ajFeattableSetReverse ************************************************
7818 **
7819 ** Sets a feature table to be reversed
7820 **
7821 ** @param [u] thys [AjPFeattable] Feature table
7822 ** @return [void]
7823 **
7824 ** @release 6.6.0
7825 ** @@
7826 ******************************************************************************/
7827
ajFeattableSetReverse(AjPFeattable thys)7828 void ajFeattableSetReverse(AjPFeattable thys)
7829 {
7830 if(thys->Rev)
7831 thys->Rev = ajFalse;
7832 else
7833 thys->Rev = ajTrue;
7834
7835 thys->Reversed = ajFalse;
7836
7837 return;
7838 }
7839
7840
7841
7842
7843 /* @func ajFeattableReverse ***************************************************
7844 **
7845 ** Reverse the features in a feature table by iterating through and
7846 ** reversing all positions and strands.
7847 **
7848 ** @param [u] thys [AjPFeattable] Feature table object
7849 ** @return [void]
7850 **
7851 ** @release 2.5.0
7852 ******************************************************************************/
7853
ajFeattableReverse(AjPFeattable thys)7854 void ajFeattableReverse(AjPFeattable thys)
7855 {
7856 AjIList iter = NULL;
7857 AjPFeature gf = NULL;
7858
7859 if(ajFeattableIsProt(thys))
7860 return;
7861
7862 if(!thys->Rev) /* Not flagged for reversal */
7863 return;
7864
7865 iter = ajListIterNewread(thys->Features);
7866
7867 while(!ajListIterDone(iter))
7868 {
7869 gf = ajListIterGet(iter);
7870
7871 if((gf->Flags & AJFEATFLAG_REMOTEID) ||
7872 (gf->Flags & AJFEATFLAG_LABEL))
7873 continue;
7874
7875 ajFeatReverse(gf, thys->Len) ;
7876 }
7877
7878 ajListIterDel(&iter);
7879
7880 thys->Rev = ajFalse;
7881
7882 if(thys->Reversed)
7883 thys->Reversed = ajFalse;
7884 else
7885 thys->Reversed = ajTrue;
7886
7887 return;
7888 }
7889
7890
7891
7892
7893 /* @func ajFeatReverse ********************************************************
7894 **
7895 ** Reverse one feature by reversing all positions and strand.
7896 **
7897 ** @param [u] thys [AjPFeature] Feature object
7898 ** @param [r] ilen [ajint] Sequence length
7899 ** @return [void]
7900 **
7901 ** @release 2.5.0
7902 ******************************************************************************/
7903
ajFeatReverse(AjPFeature thys,ajint ilen)7904 void ajFeatReverse(AjPFeature thys, ajint ilen)
7905 {
7906 AjIList iter = NULL;
7907 AjPFeature gf = NULL;
7908 ajint itmp;
7909 ajint saveflags;
7910
7911 ajDebug("ajFeatReverse ilen %d %x '%c' %d..%d %d..%d\n",
7912 ilen, thys->Flags, thys->Strand,
7913 thys->Start, thys->End, thys->Start2, thys->End2);
7914
7915 saveflags = thys->Flags;
7916
7917 if(thys->Start != thys->End)
7918 {
7919 if(thys->Strand == '-')
7920 thys->Strand = '+';
7921 else
7922 thys->Strand = '-';
7923 }
7924
7925 itmp = thys->Start;
7926
7927 if(thys->End)
7928 thys->Start = 1 + ilen - thys->End;
7929 else
7930 thys->Start = 0;
7931
7932 if(itmp)
7933 thys->End = 1 + ilen - itmp;
7934 else
7935 thys->End = 0;
7936
7937 itmp = thys->Start2;
7938 if(thys->End2)
7939 thys->Start2 = 1 + ilen - thys->End2;
7940 else
7941 thys->Start2 = 0;
7942
7943 /* reverse the flags */
7944
7945 if(saveflags & AJFEATFLAG_START_BEFORE_SEQ)
7946 thys->Flags |= AJFEATFLAG_END_AFTER_SEQ;
7947 else
7948 thys->Flags &= ~AJFEATFLAG_END_AFTER_SEQ;
7949
7950 if(saveflags & AJFEATFLAG_END_AFTER_SEQ)
7951 thys->Flags |= AJFEATFLAG_START_BEFORE_SEQ;
7952 else
7953 thys->Flags &= ~AJFEATFLAG_START_BEFORE_SEQ;
7954
7955 if(saveflags & AJFEATFLAG_START_TWO)
7956 thys->Flags |= AJFEATFLAG_END_TWO;
7957 else
7958 thys->Flags &= ~AJFEATFLAG_END_TWO;
7959
7960 if(saveflags & AJFEATFLAG_END_TWO)
7961 thys->Flags |= AJFEATFLAG_START_TWO;
7962 else
7963 thys->Flags &= ~AJFEATFLAG_START_TWO;
7964
7965 if(saveflags & AJFEATFLAG_START_UNSURE)
7966 thys->Flags |= AJFEATFLAG_END_UNSURE;
7967 else
7968 thys->Flags &= ~AJFEATFLAG_END_UNSURE;
7969
7970 if(saveflags & AJFEATFLAG_END_UNSURE)
7971 thys->Flags |= AJFEATFLAG_START_UNSURE;
7972 else
7973 thys->Flags &= ~AJFEATFLAG_START_UNSURE;
7974
7975 if(itmp)
7976 thys->End2 = 1 + ilen - itmp;
7977 else
7978 thys->End2 = 0;
7979
7980 /* thys->Frame is rather hard to guess ... leave alone for now */
7981
7982 thys->Frame = 0; /* set to unknown */
7983
7984 /*ajDebug(" Reversed %x '%c' %d..%d %d..%d\n",
7985 thys->Flags, thys->Strand,
7986 thys->Start, thys->End, thys->Start2, thys->End2);*/
7987
7988 if(thys->Subfeatures)
7989 {
7990 iter = ajListIterNewread(thys->Subfeatures);
7991 while(!ajListIterDone(iter))
7992 {
7993 gf = ajListIterGet(iter);
7994 ajFeatReverse(gf, ilen);
7995 }
7996 ajListIterDel(&iter);
7997 }
7998
7999 return;
8000 }
8001
8002
8003
8004
8005 /* @func ajFeattableNewDna ****************************************************
8006 **
8007 ** Constructor for a new DNA feature table
8008 **
8009 ** @param [r] name [const AjPStr] Name for new feature table
8010 ** (or NULL for unnamed)
8011 ** @return [AjPFeattable] Pointer to a new (empty) feature table
8012 ** @exception 'Mem_Failed' from memory allocation
8013 **
8014 ** @release 2.0.0
8015 ** @@
8016 **
8017 ******************************************************************************/
8018
ajFeattableNewDna(const AjPStr name)8019 AjPFeattable ajFeattableNewDna(const AjPStr name)
8020 {
8021 AjPFeattable thys = NULL;
8022
8023 /* Allocate the object... */
8024 thys = featTableNewS(name);
8025
8026 ajStrAssignC(&thys->Type, "N");
8027
8028 /*ajDebug("ajFeattableNewDna %x\n", thys);*/
8029
8030 return thys;
8031 }
8032
8033
8034
8035
8036 /* @func ajFeattableNewSeq ****************************************************
8037 **
8038 ** Constructor for a new feature table for an existing sequence.
8039 ** The feature table type is determined by the sequence type.
8040 **
8041 ** @param [r] seq [const AjPSeq] Sequence object to provide the name and type
8042 ** @return [AjPFeattable] Pointer to a new (empty) feature table
8043 ** @exception 'Mem_Failed' from memory allocation
8044 **
8045 ** @release 2.0.0
8046 ** @@
8047 **
8048 ******************************************************************************/
8049
ajFeattableNewSeq(const AjPSeq seq)8050 AjPFeattable ajFeattableNewSeq(const AjPSeq seq)
8051 {
8052 AjPFeattable thys = NULL;
8053
8054 /* Allocate the object... */
8055 /* AJNEW0(thys); deleted by AJB */
8056
8057 if(ajSeqIsProt(seq))
8058 thys = ajFeattableNewProt(ajSeqGetNameS(seq));
8059 else
8060 thys = ajFeattableNewDna(ajSeqGetNameS(seq));
8061
8062 thys->Len = ajSeqGetLen(seq);
8063
8064 return thys;
8065 }
8066
8067
8068
8069
8070 /* @func ajFeattableNewProt ***************************************************
8071 **
8072 ** Constructor for a new protein feature table
8073 **
8074 ** @param [r] name [const AjPStr] Name for new feature table
8075 ** (or NULL for unnamed)
8076 ** @return [AjPFeattable] Pointer to a new (empty) feature table
8077 ** @exception 'Mem_Failed' from memory allocation
8078 **
8079 ** @release 2.0.0
8080 ** @@
8081 **
8082 ******************************************************************************/
8083
ajFeattableNewProt(const AjPStr name)8084 AjPFeattable ajFeattableNewProt(const AjPStr name)
8085 {
8086 AjPFeattable thys = NULL;
8087
8088 /* Allocate the object... */
8089 thys = featTableNewS(name);
8090
8091 ajStrAssignC(&thys->Type, "P");
8092
8093 /*ajDebug("ajFeattableNewProt %x\n", thys);*/
8094
8095 return thys;
8096 }
8097
8098
8099
8100
8101 /* @funcstatic featTagvalNew **************************************************
8102 **
8103 ** Constructor for a feature tag-value pair
8104 **
8105 ** @param [r] thys [const AjPFeature] Feature
8106 ** @param [r] tag [const AjPStr] Tag name
8107 ** @param [r] value [const AjPStr] Tag value
8108 ** @return [AjPTagval] New tag-value pair object
8109 **
8110 ** @release 2.0.0
8111 ** @@
8112 ******************************************************************************/
8113
featTagvalNew(const AjPFeature thys,const AjPStr tag,const AjPStr value)8114 static AjPTagval featTagvalNew(const AjPFeature thys,
8115 const AjPStr tag, const AjPStr value)
8116 {
8117 AjPTagval ret;
8118
8119 if(thys->Protein)
8120 ret = featTagvalNewProt(tag, value);
8121 else
8122 ret = featTagvalNewDna(tag, value);
8123
8124 return ret;
8125 }
8126
8127
8128
8129
8130 /* @func ajFeatGfftagAddCS ****************************************************
8131 **
8132 ** Constructor for a feature GFF3 tag-value pair
8133 **
8134 ** @param [u] thys [AjPFeature] Feature
8135 ** @param [r] tag [const char*] Tag name
8136 ** @param [r] value [const AjPStr] Tag value list
8137 ** @return [ajuint] Number of values added
8138 **
8139 ** @release 6.4.0
8140 ** @@
8141 ******************************************************************************/
8142
ajFeatGfftagAddCS(AjPFeature thys,const char * tag,const AjPStr value)8143 ajuint ajFeatGfftagAddCS(AjPFeature thys,
8144 const char* tag, const AjPStr value)
8145 {
8146 ajuint ret;
8147
8148 AjPStr tagstr = NULL;
8149
8150 tagstr= ajStrNewC(tag);
8151
8152 ret = ajFeatGfftagAddSS(thys, tagstr, value);
8153
8154 ajStrDel(&tagstr);
8155
8156 return ret;
8157 }
8158
8159
8160
8161
8162 /* @func ajFeatGfftagAddSS ****************************************************
8163 **
8164 ** Constructor for a feature GFF3 tag-value pair
8165 **
8166 ** @param [u] thys [AjPFeature] Feature
8167 ** @param [r] tag [const AjPStr] Tag name
8168 ** @param [r] value [const AjPStr] Tag value list
8169 ** @return [ajuint] Number of values added
8170 **
8171 ** @release 6.4.0
8172 ** @@
8173 ******************************************************************************/
8174
ajFeatGfftagAddSS(AjPFeature thys,const AjPStr tag,const AjPStr value)8175 ajuint ajFeatGfftagAddSS(AjPFeature thys,
8176 const AjPStr tag, const AjPStr value)
8177 {
8178 ajuint ret = 0;
8179 AjPTagval tagval;
8180 AjPStrTok handle = NULL;
8181 AjPStr tmpstr = NULL;
8182 AjBool predefinedTag = ajFalse;
8183
8184 featInit();
8185 predefinedTag = featTagGff3PredefinedTag(tag);
8186
8187 if(!thys->GffTags && predefinedTag)
8188 thys->GffTags = ajListNew();
8189
8190 handle = ajStrTokenNewC(value, ",");
8191
8192 while(ajStrTokenNextParse(handle, &tmpstr))
8193 {
8194 tagval = ajTagvalNewS(tag, tmpstr);
8195
8196 ret++;
8197
8198 if(predefinedTag)
8199 ajListPushAppend(thys->GffTags, tagval);
8200 else
8201 ajListPushAppend(thys->Tags, tagval);
8202 tagval = NULL;
8203 }
8204
8205 ajStrTokenDel(&handle);
8206 ajStrDel(&tmpstr);
8207
8208 return ret;
8209 }
8210
8211
8212
8213
8214 /* @func ajFeatGfftagAddTag ***************************************************
8215 **
8216 ** Sets a feature tag value, creating a new feature tag even if one
8217 ** already exists.
8218 **
8219 ** @param [u] thys [AjPFeature] Feature
8220 ** @param [r] tagval [const AjPTagval] Tag value pair
8221 ** @return [AjBool] ajTrue if value was valid
8222 ** ajFalse if it was bad and was "corrected"
8223 **
8224 ** @release 6.5.0
8225 ** @@
8226 ******************************************************************************/
8227
ajFeatGfftagAddTag(AjPFeature thys,const AjPTagval tagval)8228 AjBool ajFeatGfftagAddTag(AjPFeature thys, const AjPTagval tagval)
8229 {
8230 return ajFeatGfftagAddSS(thys,
8231 MAJTAGVALGETTAG(tagval),
8232 MAJTAGVALGETVALUE(tagval));
8233 }
8234
8235
8236
8237
8238 /* @funcstatic featTagvalNewDna ***********************************************
8239 **
8240 ** Constructor for a feature tag-value pair
8241 **
8242 ** @param [r] tag [const AjPStr] Tag name
8243 ** @param [r] value [const AjPStr] Tag value
8244 ** @return [AjPTagval] New tag-value pair object
8245 **
8246 ** @release 2.0.0
8247 ** @@
8248 ******************************************************************************/
8249
featTagvalNewDna(const AjPStr tag,const AjPStr value)8250 static AjPTagval featTagvalNewDna(const AjPStr tag, const AjPStr value)
8251 {
8252 AjPTagval ret;
8253 const AjPStr tmptag = NULL; /* from AjPTable, don't delete */
8254 AjBool knowntag = ajTrue;
8255
8256 featInit();
8257
8258 tmptag = ajFeattagGetNameS(tag, FeatTagsTableDna, &knowntag);
8259
8260 ret = ajTagvalNewS(tmptag, value);
8261
8262 return ret;
8263 }
8264
8265
8266
8267
8268 /* @funcstatic featTagvalNewProt **********************************************
8269 **
8270 ** Constructor for a protein feature tag-value pair
8271 **
8272 ** @param [r] tag [const AjPStr] Tag name
8273 ** @param [r] value [const AjPStr] Tag value
8274 ** @return [AjPTagval] New tag-value pair object
8275 **
8276 ** @release 2.0.0
8277 ** @@
8278 ******************************************************************************/
8279
featTagvalNewProt(const AjPStr tag,const AjPStr value)8280 static AjPTagval featTagvalNewProt(const AjPStr tag, const AjPStr value)
8281 {
8282 AjPTagval ret;
8283 const AjPStr tmptag = NULL; /* from AjPTable, don't delete */
8284 AjBool knowntag = ajTrue;
8285
8286 featInit();
8287
8288 tmptag = ajFeattagGetNameS(tag, FeatTagsTableProtein, &knowntag);
8289
8290 ret = ajTagvalNewS(tmptag, value);
8291
8292 return ret;
8293 }
8294
8295
8296
8297
8298 /* @funcstatic featTagval *****************************************************
8299 **
8300 ** Checks for the existence of a defined tag for a feature.
8301 **
8302 ** @param [r] thys [const AjPFeature] Feature object
8303 ** @param [r] tag [const AjPStr] Tag name
8304 ** @return [AjPTagval] Returns the tag-value pair if found,
8305 ** NULL if not found.
8306 **
8307 ** @release 2.0.0
8308 ** @@
8309 ******************************************************************************/
8310
featTagval(const AjPFeature thys,const AjPStr tag)8311 static AjPTagval featTagval(const AjPFeature thys, const AjPStr tag)
8312 {
8313 AjIList iter = NULL;
8314 AjPTagval ret = NULL;
8315 AjPTagval tv = NULL;
8316
8317 iter = ajListIterNewread(thys->Tags);
8318
8319 while(!ajListIterDone(iter))
8320 {
8321 tv = ajListIterGet(iter);
8322
8323 if(ajStrMatchCaseS(MAJTAGVALGETTAG(tv), tag))
8324 {
8325 /* ajDebug("featTagval '%S' found value '%S'\n",
8326 tag, MAJTAGVALGETVALUE(tv)); */
8327 ret = tv;
8328 break;
8329 }
8330 }
8331
8332 ajListIterDel(&iter);
8333
8334 /*
8335 if(!ret)
8336 ajDebug("featTagval '%S' not found\n", tag);
8337 */
8338
8339
8340 return ret;
8341 }
8342
8343
8344
8345
8346 /* @func ajFeattableNewFtable *************************************************
8347 **
8348 ** Makes a copy of a feature table.
8349 **
8350 ** For cases where we need a copy we can safely change and/or delete.
8351 **
8352 ** @param [r] orig [const AjPFeattable] Original feature table
8353 ** @return [AjPFeattable] Feature table copy of the original
8354 **
8355 ** @release 6.2.0
8356 ** @@
8357 ******************************************************************************/
8358
ajFeattableNewFtable(const AjPFeattable orig)8359 AjPFeattable ajFeattableNewFtable(const AjPFeattable orig)
8360 {
8361 AjPFeattable ret = NULL;
8362 AjIList iter;
8363 AjPFeature featorig;
8364 AjPFeature feat = NULL;
8365
8366 if(!orig)
8367 return NULL;
8368
8369 ret = featTableNew();
8370
8371 ajStrAssignS(&ret->Seqid, orig->Seqid);
8372 ajStrAssignS(&ret->Type, orig->Type);
8373
8374 ajStrAssignS(&ret->Formatstr, orig->Formatstr);
8375 ret->Format = orig->Format;
8376
8377 ret->Groups = orig->Groups;
8378 ret->Start = orig->Start;
8379 ret->End = orig->End;
8380 ret->Len = orig->Len;
8381 ret->Offset = orig->Offset;
8382 ret->Rev = orig->Rev;
8383 ret->Reversed = orig->Reversed;
8384 ret->Trimmed = orig->Trimmed;
8385 ret->Circular = orig->Circular;
8386
8387 ret->Fpos = orig->Fpos;
8388
8389 ajStrAssignS(&ret->Db, orig->Db);
8390 ajStrAssignS(&ret->Setdb, orig->Setdb);
8391 ajStrAssignS(&ret->Full, orig->Full);
8392 ajStrAssignS(&ret->Qry, orig->Qry);
8393 ajStrAssignS(&ret->Filename, orig->Filename);
8394 ajStrAssignS(&ret->TextPtr, orig->TextPtr);
8395
8396 iter = ajListIterNewread(orig->Features);
8397
8398 while(!ajListIterDone(iter))
8399 {
8400 featorig = ajListIterGet(iter);
8401 feat = ajFeatNewFeat(featorig);
8402 ajFeattableAdd(ret, feat);
8403 }
8404
8405 ajListIterDel(&iter);
8406
8407 return ret;
8408 }
8409
8410
8411
8412
8413 /* @func ajFeattableNewFtableLimit ********************************************
8414 **
8415 ** Makes a copy of a feature table using only a limited number of features.
8416 **
8417 ** For cases where we need a copy we can safely change and/or delete.
8418 **
8419 ** @param [r] orig [const AjPFeattable] Original feature table
8420 ** @param [r] limit [ajint] Limit to number of features copied
8421 ** @return [AjPFeattable] Feature table copy of the original
8422 **
8423 ** @release 6.2.0
8424 ** @@
8425 ******************************************************************************/
8426
ajFeattableNewFtableLimit(const AjPFeattable orig,ajint limit)8427 AjPFeattable ajFeattableNewFtableLimit(const AjPFeattable orig, ajint limit)
8428 {
8429 AjPFeattable ret = NULL;
8430 AjIList iter;
8431 AjPFeature featorig;
8432 AjPFeature feat = NULL;
8433 ajint ift = 0;
8434
8435 if(!orig)
8436 return NULL;
8437
8438 ret = featTableNew();
8439
8440 ajStrAssignS(&ret->Seqid, orig->Seqid);
8441 ajStrAssignS(&ret->Type, orig->Type);
8442 ajStrAssignS(&ret->Formatstr, orig->Formatstr);
8443 ret->Format = orig->Format;
8444 ret->Start = orig->Start;
8445 ret->End = orig->End;
8446 ret->Len = orig->Len;
8447 ret->Groups = orig->Groups;
8448
8449 iter = ajListIterNewread(orig->Features);
8450
8451 while(!ajListIterDone(iter) && (ift++ < limit))
8452 {
8453 featorig = ajListIterGet(iter);
8454 feat = ajFeatNewFeat(featorig);
8455 ajFeattableAdd(ret, feat);
8456 }
8457
8458 ajListIterDel(&iter);
8459
8460 return ret;
8461 }
8462
8463
8464
8465
8466 /* @func ajFeatNewFeat ********************************************************
8467 **
8468 ** Makes a copy of a feature.
8469 **
8470 ** For cases where we need a copy we can safely change and/or delete.
8471 **
8472 ** @param [r] orig [const AjPFeature] Original feature
8473 ** @return [AjPFeature] Feature copy of the original
8474 ** @category new [AjPFeature] Copy constructor
8475 **
8476 ** @release 6.2.0
8477 ** @@
8478 ******************************************************************************/
8479
ajFeatNewFeat(const AjPFeature orig)8480 AjPFeature ajFeatNewFeat(const AjPFeature orig)
8481 {
8482 AjPFeature ret;
8483 AjPFeature subfeat;
8484 AjIList iter;
8485 AjPTagval tvorig;
8486
8487 ret = featFeatureNew();
8488
8489 if(orig->Source)
8490 ajStrAssignS(&ret->Source, orig->Source);
8491 if(orig->Type)
8492 ajStrAssignS(&ret->Type, orig->Type);
8493 if(orig->Remote)
8494 ajStrAssignS(&ret->Remote, orig->Remote);
8495 if(orig->Label)
8496 ajStrAssignS(&ret->Label, orig->Label);
8497
8498 ret->Protein = orig->Protein;
8499 ret->Start = orig->Start;
8500 ret->End = orig->End;
8501 ret->Start2 = orig->Start2;
8502 ret->End2 = orig->End2;
8503 ret->Score = orig->Score;
8504 ret->Strand = orig->Strand;
8505 ret->Frame = orig->Frame;
8506 ret->Flags = orig->Flags;
8507 ret->Group = orig->Group;
8508 ret->Exon = orig->Exon;
8509
8510 if(orig->Subfeatures)
8511 {
8512 iter = ajListIterNewread(orig->Subfeatures);
8513
8514 while(!ajListIterDone(iter))
8515 {
8516 subfeat = ajListIterGet(iter);
8517 ajListPushAppend(ret->Subfeatures, ajFeatNewFeat(subfeat));
8518 }
8519
8520 ajListIterDel(&iter);
8521 }
8522
8523 if(orig->Tags)
8524 {
8525 iter = ajListIterNewread(orig->Tags);
8526
8527 while(!ajListIterDone(iter))
8528 {
8529 tvorig = ajListIterGet(iter);
8530 ajFeatTagAddTag(ret, tvorig);
8531 }
8532
8533 ajListIterDel(&iter);
8534 }
8535
8536 if(orig->GffTags)
8537 {
8538 iter = ajListIterNewread(orig->GffTags);
8539
8540 while(!ajListIterDone(iter))
8541 {
8542 tvorig = ajListIterGet(iter);
8543 ajFeatGfftagAddTag(ret, tvorig);
8544 }
8545
8546 ajListIterDel(&iter);
8547 }
8548
8549 return ret;
8550 }
8551
8552
8553
8554
8555 /* @func ajFeatTrace **********************************************************
8556 **
8557 ** Traces (to the debug file) a feature object
8558 **
8559 ** @param [r] thys [const AjPFeature] Feature
8560 ** @return [void]
8561 **
8562 ** @release 1.0.0
8563 ** @@
8564 ******************************************************************************/
8565
ajFeatTrace(const AjPFeature thys)8566 void ajFeatTrace(const AjPFeature thys)
8567 {
8568 AjPStr flagstr = NULL;
8569 AjPFeature subft = NULL;
8570 AjIList iter = NULL;
8571 ajuint isub = 0;
8572
8573 ajDebug(" address: %p\n", thys);
8574 ajDebug(" Source: '%S'\n", thys->Source);
8575 if(thys->Protein)
8576 ajDebug(" Type: '%S' protein: %B '%S'\n",
8577 thys->Type, thys->Protein, ajFeatTypeProt(thys->Type));
8578 else
8579 ajDebug(" Type: '%S' protein: %B '%S'\n",
8580 thys->Type, thys->Protein, ajFeatTypeNuc(thys->Type));
8581 ajDebug(" Location: %d..%d\n", thys->Start, thys->End);
8582 ajDebug(" Strand: '%c'\n", thys->Strand);
8583 ajDebug(" Frame: '%d'\n", thys->Frame);
8584 ajDebug(" Score: '%f'\n", thys->Score);
8585 ajDebug(" Start2: '%d'\n", thys->Start2);
8586 ajDebug(" End2: '%d'\n", thys->Start2);
8587 ajDebug(" RemoteId: '%S'\n", thys->Remote);
8588 ajDebug(" Label: '%S'\n", thys->Label);
8589
8590 if(thys->Flags)
8591 {
8592 if(thys->Flags & AJFEATFLAG_START_BEFORE_SEQ)
8593 ajStrAppendC(&flagstr, "start_before ");
8594
8595 if(thys->Flags & AJFEATFLAG_END_AFTER_SEQ)
8596 ajStrAppendC(&flagstr, "end_after ");
8597
8598 if(thys->Flags & AJFEATFLAG_GENERATED)
8599 ajStrAppendC(&flagstr, "generated ");
8600
8601 if(thys->Flags & AJFEATFLAG_BETWEEN_SEQ)
8602 ajStrAppendC(&flagstr, "between ");
8603
8604 if(thys->Flags & AJFEATFLAG_START_TWO)
8605 ajStrAppendC(&flagstr, "start2 ");
8606
8607 if(thys->Flags & AJFEATFLAG_END_TWO)
8608 ajStrAppendC(&flagstr, "end2 ");
8609
8610 if(thys->Flags & AJFEATFLAG_POINT)
8611 ajStrAppendC(&flagstr, "point ");
8612
8613 if(thys->Flags & AJFEATFLAG_COMPLEMENT_MAIN)
8614 ajStrAppendC(&flagstr, "overall_complement ");
8615
8616 if(thys->Flags & AJFEATFLAG_MULTIPLE)
8617 ajStrAppendC(&flagstr, "multiple ");
8618
8619 if(thys->Flags & AJFEATFLAG_ORDER)
8620 ajStrAppendC(&flagstr, "order ");
8621
8622 if(thys->Flags & AJFEATFLAG_REMOTEID)
8623 ajStrAppendC(&flagstr, "remote_id ");
8624
8625 if(thys->Flags & AJFEATFLAG_LABEL)
8626 ajStrAppendC(&flagstr, "label ");
8627
8628 if(thys->Flags & AJFEATFLAG_START_UNSURE)
8629 ajStrAppendC(&flagstr, "start_unsure ");
8630
8631 if(thys->Flags & AJFEATFLAG_END_UNSURE)
8632 ajStrAppendC(&flagstr, "end_unsure ");
8633
8634 ajStrCutEnd(&flagstr, 1);
8635 ajDebug(" Flags: '%x' (%S)\n", thys->Flags, flagstr);
8636 }
8637 else
8638 {
8639 ajDebug(" Flags: '%x'\n", thys->Flags);
8640 }
8641
8642 ajDebug(" Group: '%u' exon: %u\n", thys->Group, thys->Exon);
8643
8644 ajFeatTagTrace(thys);
8645 ajStrDel(&flagstr);
8646
8647 if(ajListGetLength(thys->Subfeatures))
8648 {
8649 ajDebug(" Subfeatures: %Lu\n\n", ajListGetLength(thys->Subfeatures));
8650 isub = 0;
8651 iter = ajListIterNewread(thys->Subfeatures);
8652 while(!ajListIterDone(iter))
8653 {
8654 ajDebug("Subfeature[%u] ...\n", ++isub);
8655 subft = ajListIterGet(iter);
8656 ajFeatTrace(subft);
8657 }
8658 ajListIterDel(&iter);
8659 ajDebug(" Sub %u done\n\n", isub);
8660 }
8661
8662 return;
8663 }
8664
8665
8666
8667
8668 /* @func ajFeatTagTrace *******************************************************
8669 **
8670 ** Traces (to the debug file) the tag-value pairs of a feature object
8671 **
8672 ** @param [r] thys [const AjPFeature] Feature
8673 ** @return [void]
8674 **
8675 ** @release 2.0.0
8676 ** @@
8677 ******************************************************************************/
8678
ajFeatTagTrace(const AjPFeature thys)8679 void ajFeatTagTrace(const AjPFeature thys)
8680 {
8681 AjIList iter;
8682 ajint i = 0;
8683 AjPTagval tv = NULL;
8684
8685 ajFeatGfftagTrace(thys);
8686
8687 iter = ajListIterNewread(thys->Tags);
8688
8689 while(!ajListIterDone(iter))
8690 {
8691 tv = ajListIterGet(iter);
8692 ajDebug(" %3d %S : '%S'\n",
8693 ++i, ajTagvalGetTag(tv), ajTagvalGetValue(tv));
8694 }
8695
8696 ajListIterDel(&iter);
8697
8698 return;
8699 }
8700
8701
8702
8703
8704 /* @func ajFeatGfftagTrace ****************************************************
8705 **
8706 ** Traces (to the debug file) the GFF tag-value pairs of a feature object
8707 **
8708 ** @param [r] thys [const AjPFeature] Feature
8709 ** @return [void]
8710 **
8711 ** @release 6.5.0
8712 ** @@
8713 ******************************************************************************/
8714
ajFeatGfftagTrace(const AjPFeature thys)8715 void ajFeatGfftagTrace(const AjPFeature thys)
8716 {
8717 AjIList iter;
8718 ajint i = 0;
8719 AjPTagval tv = NULL;
8720
8721 iter = ajListIterNewread(thys->GffTags);
8722
8723 while(!ajListIterDone(iter))
8724 {
8725 tv = ajListIterGet(iter);
8726 ajDebug(" %3d %S : '%S'\n",
8727 ++i, ajTagvalGetTag(tv), ajTagvalGetValue(tv));
8728 }
8729
8730 ajListIterDel(&iter);
8731
8732 return;
8733 }
8734
8735
8736
8737
8738 /* @func ajFeatGfftagsNew *****************************************************
8739 **
8740 ** Creates a structure holding GFF tag value pairs
8741 **
8742 ** @return [AjPFeatGfftags] GFF tag-values structure
8743 **
8744 ** @release 6.4.0
8745 ** @@
8746 ******************************************************************************/
8747
ajFeatGfftagsNew(void)8748 AjPFeatGfftags ajFeatGfftagsNew(void)
8749 {
8750 AjPFeatGfftags ret = NULL;
8751
8752 AJNEW0(ret);
8753
8754 return ret;
8755 }
8756
8757
8758
8759
8760 /* @func ajFeatGfftagsDel *****************************************************
8761 **
8762 ** Destroys a structure holding GFF tag value pairs
8763 **
8764 ** @param [d] Pthys [AjPFeatGfftags*] GFF tag-values structure
8765 ** @return [void]
8766 **
8767 ** @release 6.4.0
8768 ** @@
8769 ******************************************************************************/
8770
ajFeatGfftagsDel(AjPFeatGfftags * Pthys)8771 void ajFeatGfftagsDel(AjPFeatGfftags *Pthys)
8772 {
8773 AjPFeatGfftags thys;
8774
8775 if(!Pthys)
8776 return;
8777 if(!*Pthys)
8778 return;
8779
8780 thys = *Pthys;
8781
8782 ajStrDel(&thys->Id);
8783 ajStrDel(&thys->Name);
8784 ajStrDel(&thys->Alias);
8785 ajStrDel(&thys->Parent);
8786 ajStrDel(&thys->Target);
8787 ajStrDel(&thys->Gap);
8788 ajStrDel(&thys->DerivesFrom);
8789 ajStrDel(&thys->Note);
8790 ajStrDel(&thys->Dbxref);
8791 ajStrDel(&thys->OntologyTerm);
8792 ajStrDel(&thys->IsCircular);
8793
8794 AJFREE(*Pthys);
8795
8796 return;
8797 }
8798
8799
8800
8801
8802 /* @func ajFeatGetGfftags *****************************************************
8803 **
8804 ** Returns an object with all feature GFF tag-value pairs
8805 **
8806 ** @param [r] thys [const AjPFeature] Feature
8807 ** @return [AjPFeatGfftags] Gff tags object
8808 **
8809 ** @release 6.4.0
8810 ** @@
8811 ******************************************************************************/
8812
ajFeatGetGfftags(const AjPFeature thys)8813 AjPFeatGfftags ajFeatGetGfftags(const AjPFeature thys)
8814 {
8815 AjPFeatGfftags ret = NULL;
8816 AjIList iter;
8817 AjPStr *Pvalstr = NULL;
8818 AjPStr tmpstr = NULL;
8819 AjPTagval tv = NULL;
8820 AjBool multivalues = ajFalse;
8821 const AjPStr tvtag = NULL;
8822
8823 ret = ajFeatGfftagsNew();
8824
8825 if(!thys)
8826 return ret;
8827
8828 if(!ajListGetLength(thys->GffTags))
8829 return ret;
8830
8831 iter = ajListIterNewread(thys->GffTags);
8832
8833 while(!ajListIterDone(iter))
8834 {
8835 tv = ajListIterGet(iter);
8836 tvtag = ajTagvalGetTag(tv);
8837
8838 Pvalstr = NULL;
8839 multivalues = ajFalse;
8840
8841 if(ajStrMatchC(tvtag, "ID"))
8842 Pvalstr = &ret->Id;
8843 else if(ajStrMatchC(tvtag, "Name"))
8844 Pvalstr = &ret->Name;
8845 else if(ajStrMatchC(tvtag, "Alias"))
8846 {
8847 multivalues = ajTrue;
8848 Pvalstr = &ret->Alias;
8849 }
8850 else if(ajStrMatchC(tvtag, "Parent"))
8851 {
8852 multivalues = ajTrue;
8853 Pvalstr = &ret->Parent;
8854 }
8855 else if(ajStrMatchC(tvtag, "Target"))
8856 Pvalstr = &ret->Target;
8857 else if(ajStrMatchC(tvtag, "Gap"))
8858 Pvalstr = &ret->Gap;
8859 else if(ajStrMatchC(tvtag, "Derives_from"))
8860 Pvalstr = &ret->DerivesFrom;
8861 else if(ajStrMatchC(tvtag, "Note"))
8862 {
8863 multivalues = ajTrue;
8864 Pvalstr = &ret->Note;
8865 }
8866 else if(ajStrMatchC(tvtag, "Dbxref"))
8867 {
8868 multivalues = ajTrue;
8869 Pvalstr = &ret->Dbxref;
8870 }
8871 else if(ajStrMatchC(tvtag, "Ontology_term"))
8872 {
8873 multivalues = ajTrue;
8874 Pvalstr = &ret->OntologyTerm;
8875 }
8876 else if(ajStrMatchC(tvtag, "Is_circular"))
8877 Pvalstr = &ret->IsCircular;
8878
8879 if(Pvalstr)
8880 {
8881 ajStrAssignS(&tmpstr, ajTagvalGetValue(tv));
8882 ajStrFmtPercentEncodeC(&tmpstr, ";=&%,");
8883 if(multivalues)
8884 {
8885 if(ajStrGetLen(*Pvalstr))
8886 ajStrAppendC(Pvalstr, ",");
8887 ajStrAppendS(Pvalstr, tmpstr);
8888 }
8889 else
8890 ajStrAssignS(Pvalstr, tmpstr);
8891 }
8892 }
8893
8894 ajListIterDel(&iter);
8895 ajStrDel(&tmpstr);
8896
8897 return ret;
8898 }
8899
8900
8901
8902
8903 /* @func ajFeatGetId **********************************************************
8904 **
8905 ** Returns the GFF ID tag of a feature with GFF tag-value pairs
8906 **
8907 ** @param [r] thys [const AjPFeature] Feature
8908 ** @return [const AjPStr] ID tag
8909 **
8910 ** @release 6.5.0
8911 ** @@
8912 ******************************************************************************/
8913
ajFeatGetId(const AjPFeature thys)8914 const AjPStr ajFeatGetId(const AjPFeature thys)
8915 {
8916 AjIList iter;
8917 AjPTagval tv = NULL;
8918
8919 if(!thys)
8920 return NULL;
8921
8922 if(!ajListGetLength(thys->GffTags))
8923 return NULL;
8924
8925 iter = ajListIterNewread(thys->GffTags);
8926
8927 while(!ajListIterDone(iter))
8928 {
8929 tv = ajListIterGet(iter);
8930
8931 if(ajStrMatchC(MAJTAGVALGETTAG(tv), "Id"))
8932 {
8933 ajListIterDel(&iter);
8934 return MAJTAGVALGETVALUE(tv);
8935 }
8936 }
8937
8938 return NULL;
8939 }
8940
8941
8942
8943
8944 /* @func ajFeatGetParent ******************************************************
8945 **
8946 ** Returns the GFF Parent tag of a feature with GFF tag-value pairs
8947 **
8948 ** @param [r] thys [const AjPFeature] Feature
8949 ** @return [const AjPStr] Parent tag
8950 **
8951 ** @release 6.4.0
8952 ** @@
8953 ******************************************************************************/
8954
ajFeatGetParent(const AjPFeature thys)8955 const AjPStr ajFeatGetParent(const AjPFeature thys)
8956 {
8957 AjIList iter;
8958 AjPTagval tv = NULL;
8959
8960 if(!thys)
8961 return NULL;
8962
8963 if(!ajListGetLength(thys->GffTags))
8964 return NULL;
8965
8966 iter = ajListIterNewread(thys->GffTags);
8967
8968 while(!ajListIterDone(iter))
8969 {
8970 tv = ajListIterGet(iter);
8971
8972 if(ajStrMatchC(MAJTAGVALGETTAG(tv), "Parent"))
8973 {
8974 ajListIterDel(&iter);
8975 return MAJTAGVALGETVALUE(tv);
8976 }
8977 }
8978
8979 return NULL;
8980 }
8981
8982
8983
8984
8985 /* @func ajFeatTagIter ********************************************************
8986 **
8987 ** Returns an iterator over all feature tag-value pairs
8988 **
8989 ** @param [r] thys [const AjPFeature] Feature
8990 ** @return [AjIList] List iterator
8991 **
8992 ** @release 2.0.0
8993 ** @@
8994 ******************************************************************************/
8995
ajFeatTagIter(const AjPFeature thys)8996 AjIList ajFeatTagIter(const AjPFeature thys)
8997 {
8998 return ajListIterNewread(thys->Tags);
8999 }
9000
9001
9002
9003
9004 /* @func ajFeatSubIter ********************************************************
9005 **
9006 ** Returns an iterator over all subfeaturers
9007 **
9008 ** @param [r] thys [const AjPFeature] Feature
9009 ** @return [AjIList] List iterator
9010 **
9011 ** @release 6.4.0
9012 ** @@
9013 ******************************************************************************/
9014
ajFeatSubIter(const AjPFeature thys)9015 AjIList ajFeatSubIter(const AjPFeature thys)
9016 {
9017 if(!ajListGetLength(thys->Subfeatures))
9018 return NULL;
9019
9020 return ajListIterNewread(thys->Subfeatures);
9021 }
9022
9023
9024
9025
9026 /* @func ajFeatTagval *********************************************************
9027 **
9028 ** Returns the tag-value pairs of a feature object
9029 **
9030 ** @param [u] iter [AjIList] List iterator from ajFeatTagIter
9031 ** @param [w] Ptagnam [AjPStr*] Tag name
9032 ** @param [w] Ptagval [AjPStr*] Tag val
9033 ** @return [AjBool] ajTrue if another tag-value pair was returned
9034 **
9035 ** @release 2.0.0
9036 ** @@
9037 ******************************************************************************/
9038
ajFeatTagval(AjIList iter,AjPStr * Ptagnam,AjPStr * Ptagval)9039 AjBool ajFeatTagval(AjIList iter, AjPStr* Ptagnam, AjPStr* Ptagval)
9040 {
9041 AjPTagval tv = NULL;
9042
9043 tv = ajListIterGet(iter);
9044
9045 if(!tv)
9046 return ajFalse;
9047
9048 ajStrAssignS(Ptagnam, MAJTAGVALGETTAG(tv));
9049 ajStrAssignS(Ptagval, MAJTAGVALGETVALUE(tv));
9050
9051 return ajTrue;
9052 }
9053
9054
9055
9056
9057 /* @func ajFeattableTrace *****************************************************
9058 **
9059 ** Traces (to the debug file) a complete feature table
9060 **
9061 ** @param [r] thys [const AjPFeattable] Feature table
9062 ** @return [void]
9063 **
9064 ** @release 2.0.0
9065 ** @@
9066 ******************************************************************************/
9067
ajFeattableTrace(const AjPFeattable thys)9068 void ajFeattableTrace(const AjPFeattable thys)
9069 {
9070 AjIList iter = NULL;
9071 AjPFeature ft = NULL;
9072 ajint i = 0;
9073
9074 ajDebug("== ajFeattableTrace Start ==\n");
9075
9076 if(!thys)
9077 {
9078 ajDebug("NULL table\n");
9079 return;
9080 }
9081
9082 ajDebug(" Seqid: '%S'\n", thys->Seqid);
9083
9084 iter = ajListIterNew(thys->Features);
9085
9086 while(!ajListIterDone(iter))
9087 {
9088 ft = ajListIterGet(iter);
9089 ajDebug("Features[%d]\n", ++i);
9090 ajFeatTrace(ft);
9091 }
9092
9093 ajListIterDel(&iter);
9094
9095 ajDebug("== ajFeattableTrace Done ==\n");
9096 return;
9097 }
9098
9099
9100
9101
9102 /* @func ajFeatTypeNuc ********************************************************
9103 **
9104 ** Given a feature type name,
9105 ** returns the valid feature type for the internal DNA feature table
9106 **
9107 ** @param [r] type [const AjPStr] Type name
9108 ** @return [const AjPStr] Valid feature type
9109 **
9110 ** @release 6.0.0
9111 ** @@
9112 ******************************************************************************/
9113
ajFeatTypeNuc(const AjPStr type)9114 const AjPStr ajFeatTypeNuc(const AjPStr type)
9115 {
9116 if(!FeatInitDone)
9117 featInit();
9118
9119 return ajFeattypeGetExternal(type, FeatTypeTableDna);
9120 }
9121
9122
9123
9124
9125 /* @func ajFeatTypeProt *******************************************************
9126 **
9127 ** Given a feature type name,
9128 ** returns the valid feature type for the internal protein feature table
9129 **
9130 ** @param [r] type [const AjPStr] Type name
9131 ** @return [const AjPStr] Valid feature type
9132 **
9133 ** @release 6.0.0
9134 ** @@
9135 ******************************************************************************/
9136
ajFeatTypeProt(const AjPStr type)9137 const AjPStr ajFeatTypeProt(const AjPStr type)
9138 {
9139 if(!FeatInitDone)
9140 featInit();
9141
9142 return ajFeattypeGetExternal(type, FeatTypeTableProtein);
9143 }
9144
9145
9146
9147
9148 /* @funcstatic featTypeDna ****************************************************
9149 **
9150 ** Given a feature type name,
9151 ** returns the valid feature type for the internal DNA feature table
9152 **
9153 ** @param [r] type [const AjPStr] Type name
9154 ** @return [const AjPStr] Valid feature type
9155 **
9156 ** @release 2.0.0
9157 ** @@
9158 ******************************************************************************/
9159
featTypeDna(const AjPStr type)9160 static const AjPStr featTypeDna(const AjPStr type)
9161 {
9162 if(!FeatInitDone)
9163 featInit();
9164
9165 return featTableTypeInternal(type, FeatTypeTableDna);
9166 }
9167
9168
9169
9170
9171 /* @funcstatic featTypeProt ***************************************************
9172 **
9173 ** Given a feature type name,
9174 ** returns the valid feature type for the internal protein feature table
9175 **
9176 ** @param [r] type [const AjPStr] Type name
9177 ** @return [const AjPStr] Valid feature type
9178 **
9179 ** @release 2.0.0
9180 ** @@
9181 ******************************************************************************/
9182
featTypeProt(const AjPStr type)9183 static const AjPStr featTypeProt(const AjPStr type)
9184 {
9185 if(!FeatInitDone)
9186 featInit();
9187
9188 return featTableTypeInternal(type, FeatTypeTableProtein);
9189 }
9190
9191
9192
9193
9194 /* @funcstatic featTypeDnaLimit ***********************************************
9195 **
9196 ** Given a feature type name,
9197 ** returns the valid feature type for the internal DNA feature table
9198 ** following alternative names until a unique name is found
9199 **
9200 ** @param [r] type [const AjPStr] Type name
9201 ** @return [const AjPStr] Valid feature type
9202 **
9203 ** @release 6.1.0
9204 ** @@
9205 ******************************************************************************/
9206
featTypeDnaLimit(const AjPStr type)9207 static const AjPStr featTypeDnaLimit(const AjPStr type)
9208 {
9209 if(!FeatInitDone)
9210 featInit();
9211
9212 return featTableTypeInternalLimit(type, FeatTypeTableDna);
9213 }
9214
9215
9216
9217
9218 /* @funcstatic featTypeProtLimit **********************************************
9219 **
9220 ** Given a feature type name,
9221 ** returns the valid feature type for the internal protein feature table
9222 ** following alternative names until a unique name is found
9223 **
9224 ** @param [r] type [const AjPStr] Type name
9225 ** @return [const AjPStr] Valid feature type
9226 **
9227 ** @release 6.1.0
9228 ** @@
9229 ******************************************************************************/
9230
featTypeProtLimit(const AjPStr type)9231 static const AjPStr featTypeProtLimit(const AjPStr type)
9232 {
9233 if(!FeatInitDone)
9234 featInit();
9235
9236 return featTableTypeInternalLimit(type, FeatTypeTableProtein);
9237 }
9238
9239
9240
9241
9242 /* @funcstatic featTypeTestDnaWild ********************************************
9243 **
9244 ** Given a feature type name,
9245 ** returns the valid feature type for the internal DNA feature table
9246 ** following alternative names until a matching wildcard name is found
9247 **
9248 ** @param [r] type [const AjPStr] Type name
9249 ** @param [r] str [const AjPStr] Wildcard name
9250 ** @return [AjBool] True if a match is found
9251 **
9252 ** @release 6.2.0
9253 ** @@
9254 ******************************************************************************/
9255
featTypeTestDnaWild(const AjPStr type,const AjPStr str)9256 static AjBool featTypeTestDnaWild(const AjPStr type, const AjPStr str)
9257 {
9258 if(!FeatInitDone)
9259 featInit();
9260
9261 return featTableTypeTestWild(type, FeatTypeTableDna, str);
9262 }
9263
9264
9265
9266
9267 /* @funcstatic featTypeTestProtWild *******************************************
9268 **
9269 ** Given a feature type name,
9270 ** returns the valid feature type for the internal protein feature table
9271 ** following alternative names until a unique name is found
9272 **
9273 ** @param [r] type [const AjPStr] Type name
9274 ** @param [r] str [const AjPStr] Wildcard name
9275 ** @return [AjBool] True if a match is found
9276 **
9277 ** @release 6.2.0
9278 ** @@
9279 ******************************************************************************/
9280
featTypeTestProtWild(const AjPStr type,const AjPStr str)9281 static AjBool featTypeTestProtWild(const AjPStr type, const AjPStr str)
9282 {
9283 if(!FeatInitDone)
9284 featInit();
9285
9286 return featTableTypeTestWild(type, FeatTypeTableProtein, str);
9287 }
9288
9289
9290
9291
9292 /* @funcstatic featTagDna *****************************************************
9293 **
9294 ** Given a feature tag name,
9295 ** returns the valid feature tag for the internal DNA feature table
9296 **
9297 ** @param [r] thys [const AjPStr] Tag name
9298 ** @param [w] knowntag [AjBool*] ajTrue if the tag was found in the
9299 ** list of known tags
9300 ** @return [const AjPStr] Valid feature tag name
9301 **
9302 ** @release 2.0.0
9303 ** @@
9304 ******************************************************************************/
9305
featTagDna(const AjPStr thys,AjBool * knowntag)9306 static const AjPStr featTagDna(const AjPStr thys, AjBool* knowntag)
9307 {
9308 featInit();
9309
9310 return ajFeattagGetNameS(thys, FeatTagsTableDna, knowntag);
9311 }
9312
9313
9314
9315
9316 /* @funcstatic featTagProt ****************************************************
9317 **
9318 ** Given a feature tag name,
9319 ** returns the valid feature tag for the internal protein feature table
9320 **
9321 ** @param [r] thys [const AjPStr] Tag name
9322 ** @param [w] knowntag [AjBool*] ajTrue if the tag was found in the
9323 ** list of known tags
9324 ** @return [const AjPStr] Valid feature tag name
9325 **
9326 ** @release 2.0.0
9327 ** @@
9328 ******************************************************************************/
9329
featTagProt(const AjPStr thys,AjBool * knowntag)9330 static const AjPStr featTagProt(const AjPStr thys, AjBool* knowntag)
9331 {
9332 featInit();
9333
9334 return ajFeattagGetNameS(thys, FeatTagsTableProtein, knowntag);
9335 }
9336
9337
9338
9339
9340 /* @func ajFeattypeGetExternal ************************************************
9341 **
9342 ** Given a feature type name,
9343 ** returns the valid feature type for a feature table
9344 **
9345 ** @param [r] type [const AjPStr] Type name
9346 ** @param [r] table [const AjPTable] Feature table
9347 ** @return [const AjPStr] Valid feature type
9348 **
9349 ** @release 6.4.0
9350 ** @@
9351 ******************************************************************************/
9352
ajFeattypeGetExternal(const AjPStr type,const AjPTable table)9353 const AjPStr ajFeattypeGetExternal(const AjPStr type,
9354 const AjPTable table)
9355 {
9356 static const AjPStr ret = NULL;
9357 static const AjPStr retkey = NULL;
9358 AjPStr defaultid = NULL;
9359 AjPStr tmpstr = NULL;
9360 ajlong i;
9361
9362 retkey = ajTablestrFetchkeyS(table, type);
9363
9364 if(!retkey)
9365 {
9366 defaultid = ajStrNew();
9367 retkey = ajTableFetchS(table, defaultid);
9368 ajStrDel(&defaultid);
9369 ajDebug("ajFeattypeGetExternal '%S' not in external table %x, "
9370 "use default '%S'\n", type, table, retkey);
9371 }
9372
9373 ret = ajTableFetchS(table, retkey);
9374 /*ajDebug("ajFeattypeGetExternal a '%S' found in internal table as"
9375 " '%S' = '%S\n", type, retkey, ret);*/
9376
9377 if(ajStrGetCharLast(ret) != ';')
9378 {
9379 retkey = ret;
9380 ret = ajTableFetchS(table, retkey);
9381 ajDebug("ajFeattypeGetExternal b '%S' found in internal table"
9382 " as '%S' = '%S\n", type, retkey, ret);
9383 }
9384
9385 if(ajStrGetCharLast(ret) == ';')
9386 {
9387 if(ajStrGetCharFirst(ret) == ';')
9388 {
9389 ret = retkey;
9390 }
9391 else
9392 {
9393 i = ajStrFindAnyK(ret, ';');
9394 ajStrAssignSubS(&tmpstr, ret, 0, i-1);
9395 /*ajDebug("ajFeattypeGetExternal '%S' is an alias for '%S'\n",
9396 retkey, tmpstr);*/
9397 ret = ajTablestrFetchkeyS(table, tmpstr);
9398
9399 if(!ret) /* oops, back to the previous one */
9400 {
9401 ajFeatWarn("ajFeattypeGetExternal failed to find"
9402 " '%S' alias '%S",
9403 type, tmpstr);
9404 ret = ajTableFetchS(table, retkey);
9405 }
9406
9407 ajStrDel(&tmpstr);
9408 }
9409 }
9410
9411 /*ajDebug("ajFeattypeGetExternal result '%S'\n",
9412 ret);*/
9413
9414 return ret;
9415 }
9416
9417
9418
9419
9420 /* @func ajFeattypeGetInternal ************************************************
9421 **
9422 ** Given a feature type name,
9423 ** returns the valid feature type for an internal feature table
9424 **
9425 ** @param [r] type [const AjPStr] Type name
9426 ** @return [const AjPStr] Valid feature type
9427 **
9428 ** @release 6.4.0
9429 ** @@
9430 ******************************************************************************/
9431
ajFeattypeGetInternal(const AjPStr type)9432 const AjPStr ajFeattypeGetInternal(const AjPStr type)
9433 {
9434 const AjPStr ret = NULL;
9435
9436 if(!FeatInitDone)
9437 featInit();
9438
9439 ret = featTableTypeInternal(type, FeatTypeTableDna);
9440 if(ret)
9441 return ret;
9442
9443 return featTableTypeInternal(type, FeatTypeTableProtein);
9444 }
9445
9446
9447
9448
9449 /* @func ajFeattypeGetInternalEmbl ********************************************
9450 **
9451 ** Given a feature type name,
9452 ** returns the valid feature type for an EMBL format feature table
9453 **
9454 ** @param [r] type [const AjPStr] Type name
9455 ** @return [const AjPStr] Valid feature type
9456 **
9457 ** @release 6.4.0
9458 ** @@
9459 ******************************************************************************/
9460
ajFeattypeGetInternalEmbl(const AjPStr type)9461 const AjPStr ajFeattypeGetInternalEmbl(const AjPStr type)
9462 {
9463 if(!FeatInitDone)
9464 featInit();
9465
9466 if(!FeatTypeTableEmbl)
9467 ajFeatVocabInitNuc("embl");
9468
9469 return featTableTypeInternal(type, FeatTypeTableEmbl);
9470 }
9471
9472
9473
9474
9475 /* @func ajFeattypeGetInternalNuc *********************************************
9476 **
9477 ** Given a feature type name,
9478 ** returns the valid feature type for an internal feature table
9479 **
9480 ** @param [r] type [const AjPStr] Type name
9481 ** @return [const AjPStr] Valid feature type
9482 **
9483 ** @release 6.4.0
9484 ** @@
9485 ******************************************************************************/
9486
ajFeattypeGetInternalNuc(const AjPStr type)9487 const AjPStr ajFeattypeGetInternalNuc(const AjPStr type)
9488 {
9489 if(!FeatInitDone)
9490 featInit();
9491
9492 return featTableTypeInternal(type, FeatTypeTableDna);
9493 }
9494
9495
9496
9497
9498 /* @func ajFeattypeGetInternalPir *********************************************
9499 **
9500 ** Given a feature type name,
9501 ** returns the valid feature type for an internal feature table
9502 **
9503 ** @param [r] type [const AjPStr] Type name
9504 ** @return [const AjPStr] Valid feature type
9505 **
9506 ** @release 6.4.0
9507 ** @@
9508 ******************************************************************************/
9509
ajFeattypeGetInternalPir(const AjPStr type)9510 const AjPStr ajFeattypeGetInternalPir(const AjPStr type)
9511 {
9512 if(!FeatInitDone)
9513 featInit();
9514
9515 if(!FeatTypeTablePir)
9516 ajFeatVocabInitProt("pir");
9517
9518 return featTableTypeInternal(type, FeatTypeTablePir);
9519 }
9520
9521
9522
9523
9524 /* @func ajFeattypeGetInternalProt ********************************************
9525 **
9526 ** Given a feature type name,
9527 ** returns the valid feature type for an internal feature table
9528 **
9529 ** @param [r] type [const AjPStr] Type name
9530 ** @return [const AjPStr] Valid feature type
9531 **
9532 ** @release 6.4.0
9533 ** @@
9534 ******************************************************************************/
9535
ajFeattypeGetInternalProt(const AjPStr type)9536 const AjPStr ajFeattypeGetInternalProt(const AjPStr type)
9537 {
9538 if(!FeatInitDone)
9539 featInit();
9540
9541 return featTableTypeInternal(type, FeatTypeTableProtein);
9542 }
9543
9544
9545
9546
9547 /* @func ajFeattypeGetInternalRefseqp *****************************************
9548 **
9549 ** Given a feature type name,
9550 ** returns the valid feature type for a REFSEQP format feature table
9551 **
9552 ** @param [r] type [const AjPStr] Type name
9553 ** @return [const AjPStr] Valid feature type
9554 **
9555 ** @release 6.4.0
9556 ** @@
9557 ******************************************************************************/
9558
ajFeattypeGetInternalRefseqp(const AjPStr type)9559 const AjPStr ajFeattypeGetInternalRefseqp(const AjPStr type)
9560 {
9561 if(!FeatInitDone)
9562 featInit();
9563
9564 if(!FeatTypeTableRefseqp)
9565 ajFeatVocabInitProt("refseqp");
9566
9567 return featTableTypeInternal(type, FeatTypeTableRefseqp);
9568 }
9569
9570
9571
9572
9573 /* @funcstatic featTableTypeInternal ******************************************
9574 **
9575 ** Given a feature type name,
9576 ** returns the valid feature type for a feature table
9577 **
9578 ** @param [r] type [const AjPStr] Type name
9579 ** @param [r] table [const AjPTable] Feature table
9580 ** @return [const AjPStr] Valid feature type
9581 **
9582 ** @release 4.0.0
9583 ** @@
9584 ******************************************************************************/
9585
featTableTypeInternal(const AjPStr type,const AjPTable table)9586 static const AjPStr featTableTypeInternal(const AjPStr type,
9587 const AjPTable table)
9588 {
9589 const AjPStr ret = NULL;
9590 const AjPStr retkey = NULL;
9591 const AjPStr tmpstr = NULL;
9592
9593 retkey = ajTablestrFetchkeyS(table, type);
9594
9595 if(retkey)
9596 {
9597 #if FEATDEBUG
9598 ajDebug("featTableTypeInternal '%S' found in internal table"
9599 " as '%S'\n",type, retkey);
9600 #endif
9601
9602 tmpstr = ajTableFetchS(table, retkey);
9603
9604 if(ajStrGetCharLast(tmpstr) != ';')
9605 {
9606 #if FEATDEBUG
9607 ajDebug("featTableTypeInternal '%S' is an alias for '%S'\n",
9608 retkey, tmpstr);
9609 #endif
9610 retkey = ajTablestrFetchkeyS(table, tmpstr);
9611 }
9612
9613 ajDebug("featTableTypeInternal result '%S'\n",
9614 retkey);
9615 return retkey;
9616 }
9617
9618 ret = ajTableFetchS(table, ajStrNew());
9619 #if FEATDEBUG
9620 ajDebug("featTableTypeInternal '%S' not in internal table %x, "
9621 "default to '%S'\n", type, table, ret);
9622
9623 /* ajTablestrTrace(table); */
9624
9625 /*ajDebug("featTableTypeInternal result '%S'\n",
9626 ret);*/
9627 #endif
9628
9629 return ret;
9630 }
9631
9632
9633
9634
9635 /* @funcstatic featTableTypeInternalLimit *************************************
9636 **
9637 ** Given a feature type name,
9638 ** returns the valid feature type for a feature table
9639 ** following alternative names which are common in the internal table
9640 ** which is a combination of multiple definitions
9641 **
9642 ** @param [r] type [const AjPStr] Type name
9643 ** @param [r] table [const AjPTable] Feature table
9644 ** @return [const AjPStr] Valid feature type or NULL if not found
9645 **
9646 ** @release 6.1.0
9647 ** @@
9648 ******************************************************************************/
9649
featTableTypeInternalLimit(const AjPStr type,const AjPTable table)9650 static const AjPStr featTableTypeInternalLimit(const AjPStr type,
9651 const AjPTable table)
9652 {
9653 const AjPStr retkey = NULL;
9654 const AjPStr tmpstr = NULL;
9655 const AjPStr savekey = NULL;
9656 ajuint i = 0;
9657
9658 retkey = ajTablestrFetchkeyS(table, type);
9659
9660 while(retkey && i < 5)
9661 {
9662 savekey = retkey;
9663 tmpstr = ajTableFetchS(table, retkey);
9664
9665 #if FEATDEBUG
9666 ajDebug("featTableTypeInternalLimit '%S' found in internal table"
9667 " as '%S' (%S)\n",type, retkey, tmpstr);
9668 #endif
9669
9670 if(ajStrGetCharLast(tmpstr) != ';')
9671 {
9672 #if FEATDEBUG
9673 ajDebug("featTableTypeInternalLimit '%S' is an alias for '%S'\n",
9674 retkey, tmpstr);
9675 #endif
9676 retkey = ajTablestrFetchkeyS(table, tmpstr);
9677 }
9678 else
9679 {
9680 tmpstr = ajTableFetchS(table, retkey);
9681 retkey = ajTablestrFetchkeyS(table, tmpstr);
9682
9683 if(ajStrMatchS(retkey, savekey))
9684 retkey = NULL;
9685 }
9686 #if FEATDEBUG
9687 ajDebug("featTableTypeInternalLimit result %u '%S'\n",
9688 ++i, savekey);
9689 #endif
9690 }
9691
9692 if(savekey)
9693 return savekey;
9694
9695 ajDebug("featTableTypeInternalLimit '%S' not in internal table %x, "
9696 "default to NULL\n", type, table);
9697
9698 /* ajTablestrTrace(table); */
9699
9700 /*ajDebug("featTableTypeInternalLimit result '%S'\n",
9701 ret);*/
9702 return NULL;
9703 }
9704
9705
9706
9707
9708 /* @funcstatic featTableTypeTestWild ******************************************
9709 **
9710 ** Given a feature type name,
9711 ** returns the valid feature type for a feature table
9712 ** following alternative names which are common in the internal table
9713 ** which is a combination of multiple definitions
9714 **
9715 ** @param [r] type [const AjPStr] Type name
9716 ** @param [r] table [const AjPTable] Feature table
9717 ** @param [r] str [const AjPStr] Wildcard name
9718 ** @return [AjBool] True if a match is found
9719 **
9720 ** @release 6.2.0
9721 ** @@
9722 ******************************************************************************/
9723
featTableTypeTestWild(const AjPStr type,const AjPTable table,const AjPStr str)9724 static AjBool featTableTypeTestWild(const AjPStr type,
9725 const AjPTable table,
9726 const AjPStr str)
9727 {
9728 const AjPStr retkey = NULL;
9729 const AjPStr tmpstr = NULL;
9730 AjPStr tmpkey = NULL;
9731 ajulong i = 0UL;
9732 ajulong nkeys;
9733 void **keys = NULL;
9734 AjPStr key = NULL;
9735
9736 if(ajStrMatchWildS(type, str))
9737 return ajTrue;
9738
9739 retkey = ajTablestrFetchkeyS(table, type);
9740
9741 while(retkey && i < 5)
9742 {
9743 tmpstr = ajTableFetchS(table, retkey);
9744 ajDebug("featTableTypeTestWild '%S' found in internal table"
9745 " as '%S' (%S)\n",type, retkey, tmpstr);
9746
9747 if(ajStrGetCharLast(tmpstr) != ';')
9748 {
9749 if(ajStrMatchWildS(tmpstr, str))
9750 return ajTrue;
9751
9752 tmpstr = ajTableFetchS(table, retkey);
9753 retkey = ajTablestrFetchkeyS(table, tmpstr);
9754 }
9755 else
9756 {
9757 ajStrAssignSubS(&tmpkey, tmpstr, 0, ajStrFindAnyK(tmpstr, ';')-1);
9758
9759 if(ajStrMatchWildS(tmpkey, str))
9760 {
9761 ajStrDel(&tmpkey);
9762 return ajTrue;
9763 }
9764
9765 ajStrDel(&tmpkey);
9766
9767 ajDebug("featTableTypeTestWild '%S' is an alias for '%S'\n",
9768 retkey, tmpstr);
9769
9770 retkey = ajTablestrFetchkeyS(table, tmpstr);
9771
9772 }
9773
9774 ajDebug("featTableTypeTestWild result %u '%S'\n",
9775 ++i, retkey);
9776 }
9777
9778 nkeys = ajTableToarrayKeys(table, &keys);
9779 for (i=0; i<nkeys; i++)
9780 {
9781 key = (AjPStr) keys[i];
9782 if(ajStrMatchWildS(key, str))
9783 {
9784 if(ajStrMatchS(featTableTypeInternalLimit(key,table),
9785 featTableTypeInternalLimit(type,table)))
9786 {
9787 AJFREE(keys);
9788 return ajTrue;
9789 }
9790 }
9791 }
9792
9793 AJFREE(keys);
9794 ajDebug("featTableTypeTestWild '%S' not in internal table %x, "
9795 "default to NULL\n", type, table);
9796
9797 return ajFalse;
9798 }
9799
9800
9801
9802
9803 /* @func ajFeattagGetNameC ****************************************************
9804 **
9805 ** Given a feature tag name,
9806 ** returns the valid feature tag name for a feature table
9807 **
9808 ** @param [r] tag [const char*] Type name
9809 ** @param [r] table [const AjPTable] Feature table
9810 ** @param [w] knowntag [AjBool*] ajTrue if the tag name is known
9811 ** ajFalse if the default name was substituted
9812 ** @return [const AjPStr] Valid feature tag name
9813 **
9814 ** @release 6.4.0
9815 ** @@
9816 ******************************************************************************/
9817
ajFeattagGetNameC(const char * tag,const AjPTable table,AjBool * knowntag)9818 const AjPStr ajFeattagGetNameC(const char* tag, const AjPTable table,
9819 AjBool* knowntag)
9820 {
9821 static const AjPStr ret = NULL;
9822
9823 static const AjPStr deftag = NULL;
9824
9825 deftag = ajTableFetchC(table, "");
9826
9827 if(tag)
9828 {
9829 ret = ajTablestrFetchkeyC(table, tag);
9830
9831 if(ret)
9832 {
9833 *knowntag = ajTrue;
9834 #if FEATDEBUG
9835 if(ajStrMatchS(ret, deftag))
9836 {
9837 ajDebug("featTag '%s' found in internal table as '%S' "
9838 "(default)\n",
9839 tag, ret);
9840 }
9841 else
9842 {
9843 ajDebug("featTag '%s' found in internal table as '%S'\n",
9844 tag, ret);
9845 }
9846 #endif
9847 return ret;
9848 }
9849 else
9850 {
9851 *knowntag = ajFalse;
9852 ret = deftag;
9853 #if FEATDEBUG
9854 ajDebug("featTag '%s' not in internal table %x,"
9855 " default to '%S'\n",
9856 tag, table, deftag);
9857 /* ajTablestrTrace(table); */
9858 #endif
9859 }
9860 }
9861 else
9862 {
9863 *knowntag = ajFalse;
9864 ret = deftag;
9865 #if FEATDEBUG
9866 ajDebug("featTag '%s' use default '%S'\n",
9867 tag, deftag);
9868 #endif
9869 }
9870
9871 return ret;
9872 }
9873
9874
9875
9876
9877 /* @func ajFeattagGetNameS ****************************************************
9878 **
9879 ** Given a feature tag name,
9880 ** returns the valid feature tag name for a feature table
9881 **
9882 ** @param [r] tag [const AjPStr] Type name
9883 ** @param [r] table [const AjPTable] Feature table
9884 ** @param [w] knowntag [AjBool*] ajTrue if the tag was found in the
9885 ** list of known tags
9886 ** @return [const AjPStr] Valid feature tag name
9887 **
9888 ** @release 6.4.0
9889 ** @@
9890 ******************************************************************************/
9891
ajFeattagGetNameS(const AjPStr tag,const AjPTable table,AjBool * knowntag)9892 const AjPStr ajFeattagGetNameS(const AjPStr tag, const AjPTable table,
9893 AjBool* knowntag)
9894 {
9895 static const AjPStr ret = NULL;
9896 static const AjPStr deftag = NULL;
9897
9898 deftag = ajTableFetchC(table, "");
9899
9900 if(tag)
9901 {
9902 ret = ajTablestrFetchkeyS(table, tag);
9903
9904 if(ret)
9905 {
9906 *knowntag = ajTrue;
9907 #if FEATDEBUG
9908 if(ajStrMatchS(ret, deftag))
9909 {
9910 ajDebug("featTag '%S' found in internal table as '%S' (default)\n",
9911 tag, ret);
9912 }
9913 else
9914 {
9915 ajDebug("featTag '%S' found in internal table as '%S'\n",
9916 tag, ret);
9917 }
9918 #endif
9919 return ret;
9920 }
9921 else
9922 {
9923 *knowntag = ajFalse;
9924 ret = deftag;
9925 #if FEATDEBUG
9926 ajDebug("featTag '%S' not in internal table %x,"
9927 " default to '%S'\n",
9928 tag, table, deftag);
9929 /* ajTablestrTrace(table); */
9930 #endif
9931 }
9932 }
9933 else
9934 {
9935 *knowntag = ajFalse;
9936 ret = deftag;
9937 #if FEATDEBUG
9938 ajDebug("featTag '%S' use default '%S'\n",
9939 tag, deftag);
9940 #endif
9941 }
9942
9943 return ret;
9944 }
9945
9946
9947
9948
9949 /* @func ajFeattagFormat ******************************************************
9950 **
9951 ** Converts a feature tag value into the correct format, after
9952 ** checking it is an acceptable value
9953 **
9954 ** @param [r] name [const AjPStr] Tag name
9955 ** @param [r] table [const AjPTable] Tag table
9956 ** @param [w] retstr [AjPStr*] string with formatted value.
9957 ** @return [void]
9958 **
9959 ** @release 6.4.0
9960 ** @@
9961 ******************************************************************************/
9962
ajFeattagFormat(const AjPStr name,const AjPTable table,AjPStr * retstr)9963 void ajFeattagFormat(const AjPStr name, const AjPTable table,
9964 AjPStr* retstr)
9965 {
9966 const AjPStr tagstr = NULL;
9967 const char* cp;
9968 const char* cq;
9969 ajint i;
9970
9971 tagstr = ajTableFetchS(table, name);
9972
9973 cp = ajStrGetPtr(tagstr);
9974
9975 ajStrAssignClear(retstr);
9976
9977 cq = cp;
9978 i=0;
9979
9980 while(*cp && (*cp++ != ';'))
9981 i++;
9982
9983 ajStrAssignLenC(retstr, cq, i);
9984
9985 /* ajDebug("ajFeattagFormat '%S' type '%S' (%S)\n",
9986 name, *retstr, tagstr); */
9987
9988 return;
9989 }
9990
9991
9992
9993
9994 /* @func ajFeattagGetLimit ****************************************************
9995 **
9996 ** Returns the controlled vocabulary list for a limited value.
9997 **
9998 ** @param [r] name [const AjPStr] Tag name
9999 ** @param [r] table [const AjPTable] Tag table
10000 ** @param [w] retstr [AjPStr*] string with formatted value.
10001 ** @return [void]
10002 **
10003 ** @release 6.4.0
10004 ** @@
10005 ******************************************************************************/
10006
ajFeattagGetLimit(const AjPStr name,const AjPTable table,AjPStr * retstr)10007 void ajFeattagGetLimit(const AjPStr name, const AjPTable table,
10008 AjPStr* retstr)
10009 {
10010 const AjPStr tagstr;
10011 const char* cp = NULL;
10012
10013 ajStrAssignClear(retstr);
10014 tagstr = ajTableFetchS(table, name);
10015 cp = ajStrGetPtr(tagstr);
10016
10017 while(*cp && (*cp != ';'))
10018 cp++;
10019
10020 if(!*cp)
10021 return;
10022
10023 ajStrAssignC(retstr, cp);
10024
10025 return;
10026 }
10027
10028
10029
10030
10031 /* @func ajFeatUnused *********************************************************
10032 **
10033 ** Dummy function to prevent compiler warnings
10034 **
10035 ** @return [void]
10036 **
10037 ** @release 1.0.0
10038 ******************************************************************************/
10039
ajFeatUnused(void)10040 void ajFeatUnused(void)
10041 {
10042 AjBool knowntag = ajTrue;
10043
10044 featTagDna(NULL, &knowntag);
10045 featTagProt(NULL, &knowntag);
10046 ajFeattagGetNameC(NULL, NULL, &knowntag);
10047 }
10048
10049
10050
10051
10052 /* @funcstatic featFeatureNew *************************************************
10053 **
10054 ** Constructor for a feature
10055 **
10056 ** @return [AjPFeature] New empty feature
10057 **
10058 ** @release 2.1.0
10059 ******************************************************************************/
10060
featFeatureNew(void)10061 static AjPFeature featFeatureNew(void)
10062 {
10063 AjPFeature ret;
10064
10065 AJNEW0(ret);
10066
10067 ret->Subfeatures = ajListNew() ; /* Assume empty until otherwise needed */
10068 ret->Tags = ajListNew() ; /* Assume empty until otherwise needed */
10069 ret->GffTags = ajListNew() ; /* Assume empty until otherwise needed */
10070
10071 return ret;
10072 }
10073
10074
10075
10076
10077 /* @funcstatic featTableNew ***************************************************
10078 **
10079 ** Constructor for a feature table object.
10080 **
10081 ** The type is left uninitialised
10082 **
10083 ** @return [AjPFeattable] New empty feature table
10084 **
10085 ** @release 2.1.0
10086 ******************************************************************************/
10087
featTableNew(void)10088 static AjPFeattable featTableNew(void)
10089 {
10090 AjPFeattable ret;
10091
10092 AJNEW0(ret);
10093
10094 ret->Features = ajListNew() ; /* assume empty until otherwise needed */
10095
10096 return ret;
10097 }
10098
10099
10100
10101
10102 /* @funcstatic featTableNewS **************************************************
10103 **
10104 ** Constructor for a feature table object with a defined name
10105 **
10106 ** The type is left uninitialised
10107 **
10108 ** @param [r] name [const AjPStr] Name for new feature table
10109 ** (or NULL for unnamed)
10110 ** @return [AjPFeattable] New empty feature table
10111 **
10112 ** @release 2.1.0
10113 ******************************************************************************/
10114
featTableNewS(const AjPStr name)10115 static AjPFeattable featTableNewS(const AjPStr name)
10116 {
10117 AjPFeattable ret;
10118
10119 ret = featTableNew();
10120 featTableInit(ret, name);
10121
10122 return ret;
10123 }
10124
10125
10126
10127
10128 /* @func ajFeatTypeIsCds ******************************************************
10129 **
10130 ** Tests whether the feature is a CDS feature
10131 **
10132 ** @param [r] gf [const AjPFeature] Feature
10133 ** @return [AjBool] ajTrue on success
10134 **
10135 ** @release 6.0.0
10136 ** @@
10137 ******************************************************************************/
10138
ajFeatTypeIsCds(const AjPFeature gf)10139 AjBool ajFeatTypeIsCds(const AjPFeature gf)
10140 {
10141 if(ajStrMatchC(gf->Type, "SO:0000316"))
10142 return ajTrue;
10143
10144 return ajFalse;
10145 }
10146
10147
10148
10149
10150 /* @func ajFeatTypeMatchC *****************************************************
10151 **
10152 ** Tests whether the feature type matches a given string
10153 ** including testing for alternative names
10154 **
10155 ** @param [r] gf [const AjPFeature] Feature
10156 ** @param [r] txt [const char*] Feature type name to test
10157 ** @return [AjBool] ajTrue on success
10158 **
10159 ** @release 6.1.0
10160 ** @@
10161 ******************************************************************************/
10162
ajFeatTypeMatchC(const AjPFeature gf,const char * txt)10163 AjBool ajFeatTypeMatchC(const AjPFeature gf, const char* txt)
10164 {
10165 AjBool ret = ajFalse;
10166 AjPStr tmpstr;
10167 const AjPStr tmptype = NULL;
10168
10169 if(ajStrMatchC(gf->Type, txt))
10170 return ajTrue;
10171
10172 tmpstr = ajStrNewC(txt);
10173
10174 if(gf->Protein)
10175 {
10176 tmptype = featTypeProtLimit(tmpstr);
10177 if(tmptype)
10178 ret = ajStrMatchS(featTypeProtLimit(gf->Type),
10179 tmptype);
10180 ajDebug("ajFeatTypeMatch: %B '%S' prot: '%S' <=> '%S'\n",
10181 ret, tmpstr, tmptype, gf->Type);
10182 }
10183
10184 else
10185 {
10186 tmptype = featTypeDnaLimit(tmpstr);
10187 if(tmptype)
10188 ret = ajStrMatchS(featTypeDnaLimit(gf->Type),
10189 tmptype);
10190 ajDebug("ajFeatTypeMatch: %B '%S' dna: '%S' <=> '%S'\n",
10191 ret, tmpstr, tmptype, gf->Type);
10192 }
10193
10194 ajStrDel(&tmpstr);
10195
10196 return ret;
10197 }
10198
10199
10200
10201
10202 /* @func ajFeatTypeMatchS *****************************************************
10203 **
10204 ** Tests whether the feature type matches a given string
10205 ** including testing for alternative names
10206 **
10207 ** @param [r] gf [const AjPFeature] Feature
10208 ** @param [r] str [const AjPStr] Feature type name to test
10209 ** @return [AjBool] ajTrue on success
10210 **
10211 ** @release 6.1.0
10212 ** @@
10213 ******************************************************************************/
10214
ajFeatTypeMatchS(const AjPFeature gf,const AjPStr str)10215 AjBool ajFeatTypeMatchS(const AjPFeature gf, const AjPStr str)
10216 {
10217 AjBool ret = ajFalse;
10218
10219 if(ajStrMatchS(gf->Type, str))
10220 return ajTrue;
10221
10222 if(gf->Protein)
10223 {
10224 ret = ajStrMatchS(featTypeProtLimit(gf->Type),featTypeProtLimit(str));
10225 ajDebug("ajFeatTypeMatch: %B '%S' '%S' prot: '%S' <=> '%S'\n",
10226 ret, str, gf->Type,
10227 featTypeProtLimit(str), featTypeProtLimit(gf->Type));
10228 }
10229
10230 else
10231 {
10232 ret = ajStrMatchS(featTypeDnaLimit(gf->Type),featTypeDnaLimit(str));
10233 ajDebug("ajFeatTypeMatch: %B '%S' '%S' dna: '%S' <=> '%S'\n",
10234 ret, str, gf->Type,
10235 featTypeDnaLimit(str), featTypeDnaLimit(gf->Type));
10236 }
10237
10238 return ret;
10239 }
10240
10241
10242
10243
10244 /* @func ajFeatTypeMatchWildS *************************************************
10245 **
10246 ** Tests whether the feature type matches a given wildcard string
10247 ** including testing for alternative names
10248 **
10249 ** @param [r] gf [const AjPFeature] Feature
10250 ** @param [r] str [const AjPStr] Feature type name to test
10251 ** @return [AjBool] ajTrue on success
10252 **
10253 ** @release 6.2.0
10254 ** @@
10255 ******************************************************************************/
10256
ajFeatTypeMatchWildS(const AjPFeature gf,const AjPStr str)10257 AjBool ajFeatTypeMatchWildS(const AjPFeature gf, const AjPStr str)
10258 {
10259 AjBool ret = ajFalse;
10260 AjPStr mystr = NULL;
10261
10262 mystr = ajStrNewS(str);
10263 ajStrFmtLower(&mystr);
10264
10265 if(gf->Protein)
10266 {
10267 ret = featTypeTestProtWild(gf->Type, mystr);
10268
10269 if(!ret)
10270 {
10271 if(ajStrIsWild(mystr))
10272 ajStrTrimEndC(&mystr, "*");
10273 ret = ajFeatTypeMatchS(gf, mystr);
10274 }
10275
10276 ajDebug("ajFeatTypeMatchWildS: %B '%S' '%S' prot:'%S'\n",
10277 ret, mystr, gf->Type,
10278 featTypeProtLimit(gf->Type));
10279 }
10280
10281 else
10282 {
10283 ret = featTypeTestDnaWild(gf->Type, mystr);
10284
10285 if(!ret)
10286 {
10287 if(ajStrIsWild(mystr))
10288 ajStrTrimEndC(&mystr, "*");
10289 ret = ajFeatTypeMatchS(gf, mystr);
10290 }
10291
10292 ajDebug("ajFeatTypeMatchWildS: %B '%S' '%S' dna: '%S'\n",
10293 ret, mystr, gf->Type,
10294 featTypeDnaLimit(gf->Type));
10295 }
10296 ajStrDel(&mystr);
10297
10298 return ret;
10299 }
10300
10301
10302
10303
10304 /* @func ajFeatIsLocal ********************************************************
10305 **
10306 ** Tests whether the feature is local to the sequence.
10307 ** Returns AJTRUE if it is local, AJFALSE if remote.
10308 **
10309 ** @param [r] gf [const AjPFeature] Feature
10310 ** @return [AjBool] ajTrue on success
10311 **
10312 ** @release 2.1.0
10313 ** @@
10314 ******************************************************************************/
10315
ajFeatIsLocal(const AjPFeature gf)10316 AjBool ajFeatIsLocal(const AjPFeature gf)
10317 {
10318 return !(gf->Flags & AJFEATFLAG_REMOTEID);
10319 }
10320
10321
10322
10323
10324 /* @func ajFeatIsLocalRange ***************************************************
10325 **
10326 ** Tests whether the feature is local and in the specified range of the
10327 ** sequence.
10328 ** Returns AJTRUE if it is local and within the range.
10329 ** (Any label location is assumed to be outside the range.)
10330 **
10331 ** @param [r] gf [const AjPFeature] Feature
10332 ** @param [r] start [ajuint] start of range
10333 ** @param [r] end [ajuint] end of range
10334 ** @return [AjBool] ajTrue on success
10335 **
10336 ** @release 2.1.0
10337 ** @@
10338 ******************************************************************************/
10339
ajFeatIsLocalRange(const AjPFeature gf,ajuint start,ajuint end)10340 AjBool ajFeatIsLocalRange(const AjPFeature gf, ajuint start, ajuint end)
10341 {
10342 if(gf->Flags & AJFEATFLAG_REMOTEID)
10343 return AJFALSE;
10344
10345 if(gf->Flags & AJFEATFLAG_LABEL)
10346 return AJFALSE;
10347
10348 if(gf->End < start || gf->Start > end)
10349 return AJFALSE;
10350
10351 return AJTRUE;
10352 }
10353
10354
10355
10356
10357 /* @func ajFeatIsMultiple *****************************************************
10358 **
10359 ** Tests whether the feature is a member of a join, group order or one_of
10360 **
10361 ** @param [r] gf [const AjPFeature] Feature
10362 ** @return [AjBool] Returns AJTRUE if it is a member
10363 **
10364 ** @release 2.5.0
10365 ** @@
10366 ******************************************************************************/
10367
ajFeatIsMultiple(const AjPFeature gf)10368 AjBool ajFeatIsMultiple(const AjPFeature gf)
10369 {
10370 return (gf->Flags & AJFEATFLAG_MULTIPLE);
10371 }
10372
10373
10374
10375
10376 /* @func ajFeatIsCompMult *****************************************************
10377 **
10378 ** Tests whether the feature is a member of a complement around a
10379 ** multiple (join, etc.)
10380 **
10381 ** @param [r] gf [const AjPFeature] Feature
10382 ** @return [AjBool] Returns AJTRUE if it is a complemented multiple
10383 **
10384 ** @release 2.5.0
10385 ** @@
10386 ******************************************************************************/
10387
ajFeatIsCompMult(const AjPFeature gf)10388 AjBool ajFeatIsCompMult(const AjPFeature gf)
10389 {
10390 return (gf->Flags & AJFEATFLAG_COMPLEMENT_MAIN);
10391 }
10392
10393
10394
10395
10396 /* @func ajFeattablePos *******************************************************
10397 **
10398 ** Converts a string position into a true position. If ipos is negative,
10399 ** it is counted from the end of the string rather than the beginning.
10400 **
10401 ** For strings, the result can go off the end to the terminating NULL.
10402 ** For sequences the maximum is the last base.
10403 **
10404 ** @param [r] thys [const AjPFeattable] Target feature table.
10405 ** @param [r] ipos [ajint] Position.
10406 ** @return [ajuint] string position between 1 and length.
10407 **
10408 ** @release 2.5.0
10409 ** @@
10410 ******************************************************************************/
10411
ajFeattablePos(const AjPFeattable thys,ajint ipos)10412 ajuint ajFeattablePos(const AjPFeattable thys, ajint ipos)
10413 {
10414 return ajFeattablePosII(ajFeattableGetLen(thys), 1, ipos);
10415 }
10416
10417
10418
10419
10420 /* @func ajFeattablePosI ******************************************************
10421 **
10422 ** Converts a string position into a true position. If ipos is negative,
10423 ** it is counted from the end of the string rather than the beginning.
10424 **
10425 ** imin is a minimum relative position, also counted from the end
10426 ** if negative. Usually this is the start position when the end of a range
10427 ** is being tested.
10428 **
10429 ** @param [r] thys [const AjPFeattable] Target feature table.
10430 ** @param [r] imin [ajuint] Start position.
10431 ** @param [r] ipos [ajint] Position.
10432 ** @return [ajuint] string position between 1 and length.
10433 **
10434 ** @release 2.5.0
10435 ** @@
10436 ******************************************************************************/
10437
ajFeattablePosI(const AjPFeattable thys,ajuint imin,ajint ipos)10438 ajuint ajFeattablePosI(const AjPFeattable thys, ajuint imin, ajint ipos)
10439 {
10440 return ajFeattablePosII(ajFeattableGetLen(thys), imin, ipos);
10441 }
10442
10443
10444
10445
10446 /* @func ajFeattablePosII *****************************************************
10447 **
10448 ** Converts a position into a true position. If ipos is negative,
10449 ** it is counted from the end of the sequence rather than the beginning.
10450 **
10451 ** imin is a minimum relative position, also counted from the end
10452 ** if negative. Usually this is the start position when the end of a range
10453 ** is being tested.
10454 **
10455 ** For strings, the result can go off the end to the terminating NULL.
10456 ** For sequences the maximum is the last base.
10457 **
10458 ** @param [r] ilen [ajuint] maximum length.
10459 ** @param [r] imin [ajuint] Start position.
10460 ** @param [r] ipos [ajint] Position.
10461 ** @return [ajuint] string position between 1 and length.
10462 **
10463 ** @release 2.5.0
10464 ** @@
10465 ******************************************************************************/
10466
ajFeattablePosII(ajuint ilen,ajuint imin,ajint ipos)10467 ajuint ajFeattablePosII(ajuint ilen, ajuint imin, ajint ipos)
10468 {
10469 ajuint jpos;
10470
10471 if(ipos < 0)
10472 jpos = ilen + ipos + 1;
10473 else
10474 {
10475 if(ipos)
10476 jpos = ipos;
10477 else
10478 jpos = 1;
10479 }
10480
10481 if(jpos > ilen)
10482 jpos = ilen;
10483
10484 if(jpos < imin)
10485 jpos = imin;
10486
10487 /*ajDebug("ajFeattablePosII(ilen: %d imin: %d ipos: %d) = %d\n",
10488 ilen, imin, ipos, jpos);*/
10489
10490 return jpos;
10491 }
10492
10493
10494
10495
10496 /* @func ajFeattableTrimOff ***************************************************
10497 **
10498 ** Trim a feature table using the Begin and Ends.
10499 **
10500 ** Called where a sequence has been trimmed, so we have to allow for
10501 ** missing sequence positions at the start (ioffset) or at the end (ilen).
10502 **
10503 ** @param [u] thys [AjPFeattable] Target feature table.
10504 ** @param [r] ioffset [ajuint] Offset from start of sequence
10505 ** @param [r] ilen [ajuint] Length of sequence
10506 ** @return [AjBool] AjTrue returned if successful.
10507 **
10508 ** @release 2.7.0
10509 ** @@
10510 ******************************************************************************/
10511
ajFeattableTrimOff(AjPFeattable thys,ajuint ioffset,ajuint ilen)10512 AjBool ajFeattableTrimOff(AjPFeattable thys, ajuint ioffset, ajuint ilen)
10513 {
10514 AjBool ok = ajTrue;
10515 AjBool dobegin = ajFalse;
10516 AjBool doend = ajFalse;
10517 ajuint begin = 0;
10518 ajuint end = 0;
10519 ajuint iseqlen;
10520 AjIList iter = NULL ;
10521 AjPFeature ft = NULL ;
10522
10523 /*ajDebug("ajFeattableTrimOff offset %d len %d\n", ioffset, ilen);*/
10524 /*ajDebug("ajFeattableTrimOff table Start %d End %d Len %d Features %Lu\n",
10525 thys->Start, thys->End, thys->Len,
10526 ajListGetLength(thys->Features));*/
10527
10528 if(thys->Trimmed)
10529 {
10530 ajWarn("ajFeattableTrimOff: Features '%S' already trimmed",
10531 ajFeattableGetName(thys));
10532
10533 return ajFalse;
10534 }
10535
10536 iseqlen = ilen + ioffset;
10537
10538 begin = ajFeattablePos(thys, thys->Start);
10539
10540 if(thys->End)
10541 end = ajFeattablePosI(thys, thys->End, iseqlen);
10542 else
10543 end = thys->Len;
10544 if(end > iseqlen)
10545 end = iseqlen;
10546
10547 if(begin <= ioffset)
10548 begin = ajFeattablePosI(thys, (ioffset+1), end);
10549
10550 if(begin > 1)
10551 dobegin = ajTrue;
10552
10553 if(end < thys->Len)
10554 doend = ajTrue;
10555
10556 /*ajDebug(" ready to trim dobegin %B doend %B begin %d end %d\n",
10557 dobegin, doend, begin, end);*/
10558
10559 iter = ajListIterNew(thys->Features) ;
10560
10561 while(!ajListIterDone(iter))
10562 {
10563 ft = (AjPFeature)ajListIterGet(iter);
10564
10565 if(!ajFeatTrimOffRange(ft, ioffset, begin, end, dobegin, doend))
10566 {
10567 ajFeatDel(&ft);
10568 ajListIterRemove(iter);
10569 }
10570 }
10571
10572 ajListIterDel(&iter);
10573 thys->Offset = ioffset;
10574
10575 if(thys->Rev)
10576 ajFeattableReverse(thys);
10577
10578 thys->Trimmed = ajTrue;
10579
10580 return ok;
10581 }
10582
10583
10584
10585
10586 /* @func ajFeattableTrim ******************************************************
10587 **
10588 ** Trim a feature table using the Begin and Ends.
10589 **
10590 ** @param [u] thys [AjPFeattable] Target feature table.
10591 ** @return [AjBool] AjTrue returned if successful.
10592 **
10593 ** @release 6.3.0
10594 ** @@
10595 ******************************************************************************/
10596
ajFeattableTrim(AjPFeattable thys)10597 AjBool ajFeattableTrim(AjPFeattable thys)
10598 {
10599 AjBool ok = ajTrue;
10600 AjBool dobegin = ajFalse;
10601 AjBool doend = ajFalse;
10602 ajuint begin = 0;
10603 ajuint end = 0;
10604 AjIList iter = NULL ;
10605 AjPFeature ft = NULL ;
10606
10607 /*ajDebug("ajFeattableTrim table Start %d End %d Len %d Features %Lu\n",
10608 thys->Start, thys->End, thys->Len,
10609 ajListGetLength(thys->Features));*/
10610
10611 if(thys->Trimmed)
10612 {
10613 ajWarn("Features '%S' already trimmed", ajFeattableGetName(thys));
10614
10615 return ajFalse;
10616 }
10617
10618 begin = ajFeattablePos(thys, thys->Start);
10619
10620 if(thys->End)
10621 end = ajFeattablePosI(thys, begin, thys->End);
10622 else
10623 end = thys->Len;
10624
10625 if(begin > 1)
10626 dobegin = ajTrue;
10627
10628 if(end < thys->Len)
10629 doend = ajTrue;
10630
10631 /*ajDebug(" ready to trim dobegin %B doend %B begin %d end %d\n",
10632 dobegin, doend, begin, end);*/
10633
10634 iter = ajListIterNew(thys->Features) ;
10635
10636 while(!ajListIterDone(iter))
10637 {
10638 ft = (AjPFeature)ajListIterGet(iter);
10639
10640 if(!ajFeatTrimOffRange(ft, 0, begin, end, dobegin, doend))
10641 {
10642 ajFeatDel(&ft);
10643 ajListIterRemove(iter);
10644 }
10645 }
10646
10647 ajListIterDel(&iter);
10648
10649 thys->Offset = 0;
10650 thys->Len = 1 + thys->End - thys->Start;
10651
10652 if(thys->Rev)
10653 ajFeattableReverse(thys);
10654
10655 thys->Trimmed = ajTrue;
10656
10657 return ok;
10658 }
10659
10660
10661
10662
10663 /* @func ajFeatTrimOffRange ***************************************************
10664 **
10665 ** Trim a feature table using the Begin and Ends.
10666 **
10667 ** Called where a sequence has been trimmed, so we have to allow for
10668 ** missing sequence positions at the start (ioffset)
10669 **
10670 ** @param [u] ft [AjPFeature] Target feature
10671 ** @param [r] ioffset [ajuint] Offset from start of sequence
10672 ** @param [r] begin [ajuint] Range start of sequence
10673 ** @param [r] end [ajuint] Range end of sequence
10674 ** @param [r] dobegin [AjBool] Reset begin
10675 ** @param [r] doend [AjBool] Reset end
10676 **
10677 ** @return [AjBool] AjTrue returned if successful.
10678 ** ajFalse returned if feature could not be trimmed
10679 **
10680 ** @release 2.7.0
10681 ** @@
10682 ******************************************************************************/
10683
ajFeatTrimOffRange(AjPFeature ft,ajuint ioffset,ajuint begin,ajuint end,AjBool dobegin,AjBool doend)10684 AjBool ajFeatTrimOffRange(AjPFeature ft, ajuint ioffset,
10685 ajuint begin, ajuint end,
10686 AjBool dobegin, AjBool doend)
10687 {
10688 AjBool ok = ajTrue;
10689 ajuint joffset;
10690 AjIList iter = NULL;
10691 AjPFeature subfeat = NULL;
10692
10693 ajDebug("ajFeatTrimOffRange ft flags %x %d..%d %d..%d\n",
10694 ft->Flags, ft->Start, ft->End, ft->Start2, ft->End2);
10695
10696 joffset = ioffset;
10697 if(dobegin && begin)
10698 joffset += (begin - 1);
10699
10700 if(ft->Flags & AJFEATFLAG_REMOTEID) /* feature in another sequence */
10701 return ajTrue;
10702
10703 if(ft->Flags & AJFEATFLAG_LABEL) /* label, no positions */
10704 return ajTrue;
10705
10706 if(doend)
10707 {
10708 if(ft->Start > end)
10709 /* beyond the end - delete this feature */
10710 return ajFalse;
10711
10712 if(ft->Start2 > end)
10713 ft->Start2 = end;
10714
10715 if(ft->End > end)
10716 {
10717 ft->End = end;
10718 ft->Flags |= AJFEATFLAG_END_AFTER_SEQ;
10719 }
10720
10721 if(ft->End2 > end)
10722 ft->End2 = end;
10723 }
10724
10725 if(dobegin)
10726 {
10727 if(ft->End < begin)
10728 return ajFalse;
10729
10730 if(ft->End2 && begin > (ioffset + 1) && ft->End2 < begin)
10731 ft->End2 = begin;
10732
10733 if(ft->Start && ft->Start < begin)
10734 {
10735 ft->Start = begin;
10736 ft->Flags |= AJFEATFLAG_START_BEFORE_SEQ;
10737 }
10738
10739 if(ft->Start2 && ft->Start2 < begin)
10740 ft->Start2 = begin;
10741 }
10742
10743 if(joffset) /* shift to sequence offset */
10744 {
10745 if(ft->Start)
10746 ft->Start -= joffset;
10747 if(ft->Start2)
10748 ft->Start2 -= joffset;
10749 if(ft->End)
10750 ft->End -= joffset;
10751 if(ft->End2)
10752 ft->End2 -= joffset;
10753 }
10754
10755 if(ft->Subfeatures)
10756 {
10757 iter = ajListIterNew(ft->Subfeatures);
10758 while(!ajListIterDone(iter))
10759 {
10760 subfeat = (AjPFeature)ajListIterGet(iter);
10761 if(!ajFeatTrimOffRange(subfeat, ioffset,
10762 begin, end, dobegin, doend))
10763 ok = ajFalse;
10764 }
10765 ajListIterDel(&iter);
10766 }
10767
10768 return ok;
10769 }
10770
10771
10772
10773
10774 /* @func ajFeattagIsNote ******************************************************
10775 **
10776 ** Tests whether the feature tag is a note (the default feature tag)
10777 **
10778 ** @param [r] tag [const AjPStr] Feature tag
10779 ** @return [AjBool] ajTrue on success
10780 **
10781 ** @release 6.0.0
10782 ** @@
10783 ******************************************************************************/
10784
ajFeattagIsNote(const AjPStr tag)10785 AjBool ajFeattagIsNote(const AjPStr tag)
10786 {
10787 if(ajStrMatchC(tag, "note"))
10788 return ajTrue;
10789
10790 return ajFalse;
10791 }
10792
10793
10794
10795
10796 /* @func ajFeatExit ***********************************************************
10797 **
10798 ** Cleans up feature table internal memory
10799 **
10800 ** @return [void]
10801 **
10802 ** @release 2.0.0
10803 ** @@
10804 ******************************************************************************/
10805
ajFeatExit(void)10806 void ajFeatExit(void)
10807 {
10808
10809 ajFeatreadExit();
10810 ajFeatwriteExit();
10811
10812 ajRegFree(&featRegSpecialAnticodon);
10813 ajRegFree(&featRegSpecialBiomaterial);
10814 ajRegFree(&featRegSpecialCodon);
10815 ajRegFree(&featRegSpecialCodonBad);
10816 ajRegFree(&featRegSpecialColdate);
10817 ajRegFree(&featRegSpecialCompare);
10818 ajRegFree(&featRegSpecialConssplice);
10819 ajRegFree(&featRegSpecialEstlen);
10820 ajRegFree(&featRegSpecialInference);
10821 ajRegFree(&featRegSpecialLatlon);
10822 ajRegFree(&featRegSpecialMobile);
10823 ajRegFree(&featRegSpecialPrimer);
10824 ajRegFree(&featRegSpecialRptRange);
10825 ajRegFree(&featRegSpecialRptRangeLab);
10826 ajRegFree(&featRegSpecialRptRangeComp);
10827 ajRegFree(&featRegSpecialRptunitSeq);
10828 ajRegFree(&featRegSpecialRptunitSeqPos);
10829 ajRegFree(&featRegSpecialTrans);
10830 ajRegFree(&featRegSpecialTransBad);
10831 ajRegFree(&featRegSpecialTransComp);
10832 ajRegFree(&featRegSpecialTransBadComp);
10833 ajRegFree(&featRegTagReplace);
10834
10835 ajTablestrFree(&FeatTypeTableEmbl);
10836 ajTablestrFree(&FeatTagsTableEmbl);
10837
10838 ajTablestrFree(&FeatTypeTableGff2);
10839 ajTablestrFree(&FeatTagsTableGff2);
10840
10841 ajTablestrFree(&FeatTypeTableGff3);
10842 ajTablestrFree(&FeatTagsTableGff3);
10843
10844 ajTablestrFree(&FeatTypeTablePir);
10845 ajTablestrFree(&FeatTagsTablePir);
10846
10847 ajTablestrFree(&FeatTypeTableGff2protein);
10848 ajTablestrFree(&FeatTagsTableGff2protein);
10849
10850 ajTablestrFree(&FeatTypeTableGff3protein);
10851 ajTablestrFree(&FeatTagsTableGff3protein);
10852
10853 ajTablestrFree(&FeatTypeTableSwiss);
10854 ajTablestrFree(&FeatTagsTableSwiss);
10855
10856 ajTablestrFree(&FeatTypeTableDna);
10857 ajTablestrFree(&FeatTagsTableDna);
10858
10859 ajTablestrFree(&FeatTypeTableProtein);
10860 ajTablestrFree(&FeatTagsTableProtein);
10861
10862 ajTablestrFree(&FeatTypeTableRefseqp);
10863 ajTablestrFree(&FeatTagsTableRefseqp);
10864
10865 ajTablestrFree(&FeatCategoryTable);
10866
10867 ajStrDel(&featTypeMiscfeat);
10868 ajStrDel(&featTypeEmpty);
10869 ajStrDel(&featDefSource);
10870 ajStrDel(&featFmtTmp);
10871 ajStrDel(&featTagTmp);
10872 ajStrDel(&featTagTmp2);
10873 ajStrDel(&featValTmp);
10874 ajStrDel(&featValTmp2);
10875 ajStrDel(&featTmpStr);
10876 ajStrDel(&featTagNote);
10877
10878 ajStrDel(&featTransBegStr);
10879 ajStrDel(&featTransEndStr);
10880 ajStrDel(&featTransAaStr);
10881 ajStrDel(&featTempQry);
10882
10883 ajStrTokenDel(&featVocabSplit);
10884
10885 return;
10886 }
10887
10888
10889
10890
10891 /* @func ajFeatWarn ***********************************************************
10892 **
10893 ** Formatted write as a warning message.
10894 **
10895 ** @param [r] fmt [const char*] Format string
10896 ** @param [v] [...] Format arguments.
10897 ** @return [void]
10898 **
10899 ** @release 6.4.0
10900 ** @@
10901 ******************************************************************************/
10902
ajFeatWarn(const char * fmt,...)10903 void ajFeatWarn(const char* fmt, ...)
10904 {
10905 va_list args;
10906 static AjBool dowarn = AJTRUE;
10907 AjPStr tmpstr = NULL;
10908 AjPStr errstr = NULL;
10909
10910 if(!featWarnCount)
10911 {
10912 if(ajNamGetValueC("featwarn", &tmpstr))
10913 {
10914 ajStrToBool(tmpstr, &dowarn);
10915 }
10916
10917 ajStrDel(&tmpstr);
10918 }
10919
10920 featWarnCount++;
10921
10922 if(!dowarn)
10923 return;
10924
10925 va_start(args, fmt) ;
10926 ajFmtVPrintS(&errstr, fmt, args);
10927 va_end(args) ;
10928
10929 ajWarn("%S", errstr);
10930 ajStrDel(&errstr);
10931
10932 return;
10933 }
10934
10935
10936
10937
10938 #ifdef AJ_COMPILE_DEPRECATED_BOOK
10939 #endif
10940
10941
10942
10943
10944 #ifdef AJ_COMPILE_DEPRECATED
10945 /* @obsolete ajFeattableBegin
10946 ** @rename ajFeattableGetBegin
10947 */
10948
ajFeattableBegin(const AjPFeattable thys)10949 __deprecated ajint ajFeattableBegin(const AjPFeattable thys)
10950 {
10951 return ajFeattableGetBegin(thys);
10952 }
10953
10954
10955
10956
10957 /* @obsolete ajFeattableEnd
10958 ** @rename ajFeattableGetEnd
10959 */
10960
ajFeattableEnd(const AjPFeattable thys)10961 __deprecated ajint ajFeattableEnd(const AjPFeattable thys)
10962 {
10963 return ajFeattableGetEnd(thys);
10964 }
10965
10966
10967
10968
10969 /* @obsolete ajFeattableLen
10970 ** @rename ajFeattableGetLen
10971 */
10972
ajFeattableLen(const AjPFeattable thys)10973 __deprecated ajint ajFeattableLen(const AjPFeattable thys)
10974 {
10975 return ajFeattableGetLen(thys);
10976 }
10977
10978
10979
10980
10981 /* @obsolete ajFeattableSize
10982 ** @rename ajFeattableGetSize
10983 */
10984
ajFeattableSize(const AjPFeattable thys)10985 __deprecated ajint ajFeattableSize(const AjPFeattable thys)
10986 {
10987 return ajFeattableGetSize(thys);
10988 }
10989
10990
10991
10992
10993 /* @obsolete ajFeatGetNoteI
10994 ** @rename ajFeatGetNoteSI
10995 */
ajFeatGetNoteI(const AjPFeature thys,const AjPStr name,ajint count,AjPStr * val)10996 __deprecated AjBool ajFeatGetNoteI(const AjPFeature thys,
10997 const AjPStr name, ajint count,
10998 AjPStr* val)
10999 {
11000 return ajFeatGetNoteSI(thys, name, count, val);
11001 }
11002
11003
11004
11005
11006 /* @obsolete ajFeatGetNote
11007 ** @rename ajFeatGetNoteS
11008 */
11009
ajFeatGetNote(const AjPFeature thys,const AjPStr name,AjPStr * val)11010 __deprecated AjBool ajFeatGetNote(const AjPFeature thys, const AjPStr name,
11011 AjPStr* val)
11012 {
11013 return ajFeatGetNoteS(thys, name, val);
11014 }
11015
11016
11017
11018
11019 /* @obsolete ajFeatTagAddC
11020 ** @rename ajFeatTagAddCS
11021 */
11022
ajFeatTagAddC(AjPFeature thys,const char * tag,const AjPStr value)11023 __deprecated AjBool ajFeatTagAddC(AjPFeature thys, const char* tag,
11024 const AjPStr value)
11025 {
11026 return ajFeatTagAddCS(thys, tag, value);
11027 }
11028
11029
11030
11031
11032 /* @obsolete ajFeatTagAdd
11033 ** @rename ajFeatTagAddS
11034 */
11035
ajFeatTagAdd(AjPFeature thys,const AjPStr tag,const AjPStr value)11036 __deprecated AjBool ajFeatTagAdd(AjPFeature thys,
11037 const AjPStr tag, const AjPStr value)
11038 {
11039 return ajFeatTagAddSS(thys, tag, value);
11040 }
11041
11042
11043
11044
11045 /* @obsolete ajFeatDefName
11046 ** @rename ajFeattableSetDefname
11047 */
11048
ajFeatDefName(AjPFeattable thys,const AjPStr setname)11049 __deprecated void ajFeatDefName(AjPFeattable thys, const AjPStr setname)
11050 {
11051 ajFeattableSetDefname(thys, setname);
11052 return;
11053 }
11054
11055
11056
11057
11058 /* @obsolete ajFeatGfftagAddC
11059 ** @rename ajFeatGfftagAddCS
11060 */
11061
ajFeatGfftagAddC(AjPFeature thys,const char * tag,const AjPStr value)11062 __deprecated ajuint ajFeatGfftagAddC(AjPFeature thys,
11063 const char* tag, const AjPStr value)
11064 {
11065 return ajFeatGfftagAddCS(thys, tag, value);
11066 }
11067
11068
11069
11070
11071 /* @obsolete ajFeatGfftagAdd
11072 ** @rename ajFeatGfftagAddSS
11073 */
11074
ajFeatGfftagAdd(AjPFeature thys,const AjPStr tag,const AjPStr value)11075 __deprecated ajuint ajFeatGfftagAdd(AjPFeature thys,
11076 const AjPStr tag, const AjPStr value)
11077 {
11078 return ajFeatGfftagAddSS(thys, tag, value);
11079 }
11080
11081
11082
11083
11084 /* @obsolete ajFeattableCopy
11085 ** @rename ajFeattableNewFtable
11086 */
11087
ajFeattableCopy(const AjPFeattable orig)11088 __deprecated AjPFeattable ajFeattableCopy(const AjPFeattable orig)
11089 {
11090 return ajFeattableNewFtable(orig);
11091 }
11092
11093
11094
11095
11096 /* @obsolete ajFeattableCopyLimit
11097 ** @rename ajFeattableNewFtableLimit
11098 */
11099
ajFeattableCopyLimit(const AjPFeattable orig,ajint limit)11100 __deprecated AjPFeattable ajFeattableCopyLimit(const AjPFeattable orig,
11101 ajint limit)
11102 {
11103 return ajFeattableNewFtableLimit(orig, limit);
11104 }
11105
11106
11107
11108
11109 /* @obsolete ajFeatCopy
11110 ** @rename ajFeatNewFeat
11111 */
11112
ajFeatCopy(const AjPFeature orig)11113 __deprecated AjPFeature ajFeatCopy(const AjPFeature orig)
11114 {
11115 return ajFeatNewFeat(orig);
11116 }
11117
11118
11119
11120
11121 /* @obsolete ajFeatIsChild
11122 ** @remove Always returns false, AJFEATFLAG_CHILD was no longer set
11123 */
11124
ajFeatIsChild(const AjPFeature gf)11125 __deprecated AjBool ajFeatIsChild(const AjPFeature gf)
11126 {
11127 (void) gf;
11128 /*return (gf->Flags & AJFEATFLAG_CHILD);*/
11129 return ajFalse;
11130 }
11131 #endif
11132