1 /* @Source acdrelations application
2 **
3 ** Add relations: attribute to ACD files
4 ** Any existing relations: attributes are replaced.
5 **
6 ** @author: Copyright (C) Jon Ison (jison@ebi.ac.uk)
7 ** @@
8 **
9 ** This program is free software; you can redistribute it and/or
10 ** modify it under the terms of the GNU General Public License
11 ** as published by the Free Software Foundation; either version 2
12 ** of the License, or (at your option) any later version.
13 **
14 ** This program is distributed in the hope that it will be useful,
15 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ** GNU General Public License for more details.
18 **
19 ** You should have received a copy of the GNU General Public License
20 ** along with this program; if not, write to the Free Software
21 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22 **
23 *******************************************************************************
24 **
25 ** ACDRELATIONS documentation
26 ** See http://wwww.emboss.org
27 **
28 ** Please cite the authors and EMBOSS.
29 **
30 ** Email jison@ebi.ac.uk.
31 **
32 ** acdrelations reads ACD files and writes exact copies but (depending on the
33 ** mode it is run in) with relations: attributes either modified (mode 1) or
34 ** added (mode 2).
35 ** Mode 1
36 ** relations: lines in this format:
37 ** relations: "/edam/data/0001773 Tool-specific parameter"
38 ** are replaced with this format:
39 ** relations: "EDAM:0001773 data Tool-specific parameter"
40 **
41 **
42 ** Mode 2
43 ** acdrelations reads ACD files and writes exact copies but with a relations:
44 ** attribute added to each data definition. Any existing relations: attributes
45 ** are replaced. Text for relations: is from the EDAM ontology.
46 **
47 ** acdrelations parameters:
48 ** knowntypes.standards (EMBOSS data file)
49 ** edamtoacd.dat (acdrelations data file)
50 ** ACD file input directory
51 ** ACD file output directory
52 **
53 ** knowntypes.standards and edamtoacd.dat define the relations: value.
54 ** Values given in knowntypes.standards take precedence over edamtoacd.dat
55 **
56 ** knowntypes.standards is the standard EMBOSS data file of known types which is annotated with EDAM terms.
57 ** An excerpt:
58 ** aaindex_data | file | "EDAM: Amino acid index" | AAINDEX entry
59 ** aaindex_database | file | "EDAM: AAindex database" | AAINDEX database
60 ** abi_trace | file | "EDAM: ABI sequencing trace" | ABI sequencing trace
61 **
62 ** edamtoacd.dat is a data file defining terms from the EDAM ontology to use
63 ** as values for relations: attribute in ACD files, for different combinations
64 ** of ACD datatypes / attributes.
65 ** For example:
66 ** #
67 ** align | "EDAM: Sequence alignment data" |
68 ** align | "EDAM: Nucleotide sequence alignment data" | type:"nucleotide"
69 ** align | "EDAM: Protein sequence alignment data" | type:"protein"
70 ** align | "EDAM: Multiple sequence alignment data" | minseqs:"3"
71 ** align | "EDAM: Pairwise sequence alignment data" | minseqs:"2"; maxseqs:"2"
72 ** align | "EDAM: Multiple protein sequence alignment data" | type:"protein"; minseqs:"3"
73 ** align | "EDAM: Multiple nucleotide sequence alignment data" | type:"nucleotide"; minseqs:"3"
74 ** align | "EDAM: Pairwise nucleotide sequence alignment data" | type:"nucleotide"; minseqs:"2"; maxseqs:"2"
75 ** align | "EDAM: Pairwise protein sequence alignment data" | type:"protein"; minseqs:"2"; maxseqs:"2"
76 ** array | "EDAM: Generic float array" |
77 ** #
78 ** arraychar | "EDAM: Generic character array" |
79 ** #
80 ** arrayword | "EDAM: Generic string array" |
81 ** #
82 **
83 **
84 ** Meaning of columns is:
85 ** ACD datatype | Attributes that must be specified | Value of relation: attribute | Note
86 **
87 ** IMPORTANT
88 ** For acdrelations to work correctly, edamtoacd.dat must be correctly formatted and laid out:
89 ** 1. Lines for a given datatype *must* be given in order of number of attributes in the third column (lowest number first)
90 ** 2. The first line for each datatype gives the default value of the relations: attribute and should have no attributes defined.
91 ** 3. The attribute:value pairs must be delimited by ';'.
92 **
93 ******************************************************************************/
94
95 #include "emboss.h"
96
97
98
99
100
101 /******************************************************************************
102 **
103 ** DATA STRUCTURES
104 **
105 ******************************************************************************/
106
107
108
109
110 /* @datastatic PEdamdat *******************************************************
111 **
112 ** edamdat object
113 ** Holds a single line from the data file edamtoacd.dat
114 **
115 ** @alias SEdamdat
116 ** @alias OEdamdat
117 **
118 ** @attr acdtype [AjPStr] ACD datatype, e.g. "align"
119 ** @attr acdattr [AjPStr*] Array of ACD attribute:value strings e.g. minseqs:"3"
120 ** Strings must contain no whitespace!
121 ** @attr edam [AjPStr] Text to be given after relations: attribute,
122 ** e.g. "EDAM: Multiple sequence alignment data"
123 ** if all relations in acdattr are defined for acdtype.
124 ** @attr n [ajint] Size of acdattr array
125 ** @attr Padding [ajint] Padding to alignment boundaty
126 ******************************************************************************/
127 typedef struct SEdamdat
128 {
129 AjPStr acdtype;
130 AjPStr* acdattr;
131 AjPStr edam;
132 ajint n;
133 ajint Padding;
134 } OEdamdat;
135 #define PEdamdat OEdamdat*
136
137
138
139
140 /* @datastatic PEdam **********************************************************
141 **
142 ** edam object
143 ** Holds all lines from the data file edamtoacd.dat
144 **
145 ** @alias SEdam
146 ** @alias OEdam
147 **
148 ** @attr dat [PEdamdat*] Array of PEdamdat objects
149 ** @attr n [ajint] Size of dat array
150 ** @attr Padding [ajint] Padding to alignment boundaty
151 ******************************************************************************/
152 typedef struct SEdam
153 {
154 PEdamdat *dat;
155 ajint n;
156 ajint Padding;
157 } OEdam;
158 #define PEdam OEdam*
159
160
161
162
163 /* @datastatic PKtypedat ******************************************************
164 **
165 ** ktypedat object
166 ** Holds a single line from the data file knowntypes.standard
167 **
168 ** @alias SKtypedat
169 ** @alias OKtypedat
170 **
171 ** @attr acdtype [AjPStr] ACD datatype, e.g. "align"
172 ** @attr ktype [AjPStr] Value of knowntype: attribute: no whitespace!
173 ** @attr edam [AjPStr] Text to be given after relations: attribute,
174 ** e.g. "EDAM: Multiple sequence alignment data"
175 ** if ktype is defined for acdtype.
176 ******************************************************************************/
177 typedef struct SKtypedat
178 {
179 AjPStr acdtype;
180 AjPStr ktype;
181 AjPStr edam;
182 } OKtypedat;
183 #define PKtypedat OKtypedat*
184
185
186
187
188 /* @datastatic PKtype *********************************************************
189 **
190 ** ktype object
191 ** Holds all lines from the data file knowntypes.standard
192 **
193 ** @alias SKtype
194 ** @alias OKtype
195 **
196 ** @attr dat [PKtypedat*] Array of PKtypedat objects
197 ** @attr n [ajint] Size of dat array
198 ** @attr Padding [ajint] Padding to alignment boundaty
199 ******************************************************************************/
200 typedef struct SKtype
201 {
202 PKtypedat *dat;
203 ajint n;
204 ajint Padding;
205 } OKtype;
206 #define PKtype OKtype*
207
208
209
210
211
212 /******************************************************************************
213 **
214 ** PROTOTYPES
215 **
216 ******************************************************************************/
217
218 static void acdrelations_writerelations
219 (AjPFile outf,
220 AjPStr acdtype,
221 AjPStr *strarr,
222 ajint n,
223 PEdam P,
224 PKtype T);
225
226 static void acdrelations_readdatfile
227 (AjPFile inf,
228 PEdam *P);
229
230 static void acdrelations_readtypefile
231 (AjPFile inf,
232 PKtype *P);
233
234 static void acdrelations_procacdfile1
235 (AjPFile inf,
236 AjPFile outf);
237
238 static void acdrelations_procacdfile2
239 (AjPFile inf,
240 AjPFile outf,
241 PEdam P,
242 PKtype T);
243
244
245 static PEdamdat acdrelations_EdamdatNew(void);
246 static PEdam acdrelations_EdamNew(void);
247
248 static void acdrelations_EdamdatDel(PEdamdat *P);
249 static void acdrelations_EdamDel(PEdam *P);
250
251 static PKtypedat acdrelations_KtypedatNew(void);
252 static PKtype acdrelations_KtypeNew(void);
253
254 static void acdrelations_KtypedatDel(PKtypedat *P);
255 static void acdrelations_KtypeDel(PKtype *P);
256
257
258
259
260 /* @prog acdrelations ********************************************************
261 **
262 ** Add relations: attribute to ACD files.
263 **
264 *****************************************************************************/
265
main(ajint argc,char ** argv)266 int main(ajint argc, char **argv)
267 {
268 /* Variable declarations */
269 AjPFile inf_edam = NULL; /* Name of EDAM data (input) file */
270 AjPFile acdoutf = NULL; /* Name of ACD (output) file */
271 AjPStr mode = NULL;
272
273 ajint modei;
274 AjPList acdinlist = NULL; /* List of ACD file names (input) */
275 AjPFile acdinf = NULL; /* Name of ACD (input) file */
276 AjPStr acdname = NULL; /* Name of current acd file */
277 AjPDirout acdoutdir = NULL; /* Directory for ACD files (output) */
278
279 AjPFile inf_ktype = NULL; /* Name of knowntypes.standard file */
280
281 PEdam edam = NULL; /* EDAM relations data */
282 PKtype ktype = NULL; /* Data from knowntype.standard */
283
284
285
286 /* Read data from acd. */
287 /* embInitP("acdrelations",argc,argv,"MYEMBOSS"); */
288 embInit("acdrelations",argc,argv);
289
290 /* ACD data handling */
291 mode = ajAcdGetListSingle("mode");
292 inf_edam = ajAcdGetDatafile("inedamfile");
293 inf_ktype = ajAcdGetInfile("intypefile");
294 acdinlist = ajAcdGetDirlist("indir");
295 acdoutdir = ajAcdGetOutdir("outdir");
296
297 ajStrToInt(mode, &modei);
298
299 /* Read data file */
300 if(modei==2)
301 {
302 edam = acdrelations_EdamNew();
303 ktype = acdrelations_KtypeNew();
304 acdrelations_readdatfile(inf_edam, &edam);
305 acdrelations_readtypefile(inf_ktype, &ktype);
306 }
307
308
309 /* Main application loop. Process each ACD file in turn. */
310 while(ajListPop(acdinlist,(void **)&acdname))
311 {
312 if(!(acdinf = ajFileNewInNameS(acdname)))
313 ajFatal("Cannot open input ACD file %S\n", acdname);
314
315 ajFilenameTrimPath(&acdname);
316
317 if(!(acdoutf = ajFileNewOutNameDirS(acdname, acdoutdir)))
318 ajFatal("Cannot open output ACD file %S\n", acdname);
319
320 if(modei==1)
321 acdrelations_procacdfile1(acdinf, acdoutf);
322 else if(modei==2)
323 acdrelations_procacdfile2(acdinf, acdoutf, edam, ktype);
324 else
325 ajFatal("Unknown mode");
326
327 ajFileClose(&acdinf);
328 ajFileClose(&acdoutf);
329 }
330
331 /* Clean up and exit */
332 ajStrDel(&mode);
333
334 if(modei==2)
335 {
336 ajFileClose(&inf_edam);
337 ajFileClose(&inf_ktype);
338 acdrelations_EdamDel(&edam);
339 acdrelations_KtypeDel(&ktype);
340 }
341
342 ajListFree(&acdinlist);
343 ajDiroutDel(&acdoutdir);
344
345
346
347 ajExit();
348 return 0;
349 }
350
351
352
353
354 /******************************************************************************
355 **
356 ** FUNCTIONS
357 **
358 ******************************************************************************/
359
360
361
362
363 /* @funcstatic acdrelations_readdatfile ***************************************
364 **
365 ** Read the data file edamtoacd.dat and write edam object.
366 **
367 ** @param [u] inf [AjPFile] Handle on edamtoacd.dat
368 ** @param [u] P [PEdam*] edam object to write
369 ** @return [void]
370 ** @@
371 ******************************************************************************/
372
acdrelations_readdatfile(AjPFile inf,PEdam * P)373 static void acdrelations_readdatfile
374 (AjPFile inf,
375 PEdam *P)
376 {
377 AjPStr line = NULL;
378 const AjPStr tok = NULL;
379 const AjPStr subtok = NULL;
380 AjPStr strtmp = NULL;
381 AjPList strlist = NULL;
382
383 AjPStr acdtype = NULL;
384 AjPStr relations = NULL;
385
386 PEdamdat dattmp = NULL;
387 AjPList datlist = NULL;
388
389 if(!P)
390 ajFatal("Null arg error 1 in acdrelations_readdatfile");
391 if(!inf)
392 ajFatal("Null arg error 3 in acdrelations_readdatfile");
393
394
395 /* Allocate memory */
396 line = ajStrNew();
397 acdtype = ajStrNew();
398 relations = ajStrNew();
399 datlist = ajListNew();
400
401 /* Read data from file */
402 while(ajReadline(inf,&line))
403 {
404 /* Discard comment lines */
405 if(ajStrPrefixC(line,"#"))
406 continue;
407
408
409
410 /* Tokenise line, delimited by '|'.
411 Parse first token (ACD datatype ) */
412 ajStrAssignS(&acdtype, ajStrParseC(line, "|"));
413
414 /* Parse second token (EDAM relations: value ) */
415 ajStrAssignS(&relations, ajStrParseC(NULL, "|"));
416
417 /* Parse third token (attribute:value strings block) */
418 tok = ajStrParseC(NULL, "|");
419
420
421 /* Create new string list */
422 strlist = ajListstrNew();
423
424 /* Tokenise third token itself into tokens delimited by ' ' (space)
425 Parse tokens (individual attribute:value strings)*/
426 if((subtok=ajStrParseC(tok, ";")))
427 {
428 strtmp = ajStrNew();
429 ajStrAssignS(&strtmp, subtok);
430 ajStrRemoveWhite(&strtmp);
431 ajListstrPushAppend(strlist, strtmp);
432
433 while((subtok=ajStrParseC(NULL, ";")))
434 {
435 strtmp = ajStrNew();
436 ajStrAssignS(&strtmp, subtok);
437 ajStrRemoveWhite(&strtmp);
438 ajListstrPushAppend(strlist, strtmp);
439 }
440 }
441
442 /* Write PEdamdat structure & push onto list */
443 dattmp = acdrelations_EdamdatNew();
444 ajStrRemoveWhite(&acdtype);
445 ajStrAssignS(&dattmp->acdtype, acdtype);
446 ajStrAssignS(&dattmp->edam, relations);
447 dattmp->n = (ajuint) ajListstrToarray(strlist, &dattmp->acdattr);
448 ajListPushAppend(datlist, dattmp);
449
450 /* Clear nodes (but not strings) from string list */
451 ajListstrFree(&strlist);
452 }
453
454
455 /* Write PEdam structure */
456 ((*P)->n) = (ajuint) ajListToarray(datlist, (void***) &((*P)->dat));
457
458 /* Free memory */
459 ajStrDel(&line);
460 ajStrDel(&acdtype);
461 ajStrDel(&relations);
462 ajListFree(&datlist);
463
464 return;
465 }
466
467
468
469
470
471 /* @funcstatic acdrelations_readtypefile **************************************
472 **
473 ** Read the data file knowntypes.standard and write ktype object
474 **
475 ** @param [u] inf [AjPFile] Handle on knowntypes.standard
476 ** @param [u] T [PKtype*] ktype object to write
477 ** @return [void]
478 ** @@
479 ******************************************************************************/
480
acdrelations_readtypefile(AjPFile inf,PKtype * T)481 static void acdrelations_readtypefile
482 (AjPFile inf,
483 PKtype *T)
484 {
485 AjPStr line = NULL;
486 PKtypedat dattmp = NULL;
487 AjPList datlist = NULL;
488
489 if(!T)
490 ajFatal("Null arg error 1 in acdrelations_readtypefile");
491 if(!inf)
492 ajFatal("Null arg error 3 in acdrelations_readtypefile");
493
494
495 /* Allocate memory */
496 line = ajStrNew();
497 datlist = ajListNew();
498
499
500 /* Read data from file */
501 while(ajReadline(inf,&line))
502 {
503 /* Discard comment lines */
504 if(ajStrPrefixC(line,"#"))
505 continue;
506
507 /* Create object for holding line */
508 dattmp = acdrelations_KtypedatNew();
509
510 /* Tokenise line delimited by '|'
511 Parse first token (value of knowntype: attribute) */
512 ajStrAssignS(&dattmp->ktype, ajStrParseC(line, "|"));
513 ajStrRemoveSetC(&dattmp->ktype, "_");
514 ajStrRemoveWhite(&dattmp->ktype);
515
516 /* Parse second token (ACD datatype) */
517 ajStrAssignS(&dattmp->acdtype, ajStrParseC(NULL, "|"));
518
519 /* Parse third token (EDAM relations: value ) */
520 ajStrAssignS(&dattmp->edam, ajStrParseC(NULL, "|"));
521
522 /* Push line onto list */
523 ajListPushAppend(datlist, dattmp);
524 }
525
526
527 /* Write PKtype structure */
528 ((*T)->n) = (ajuint) ajListToarray(datlist, (void***) &((*T)->dat));
529
530
531 /* Free memory */
532 ajStrDel(&line);
533 ajListFree(&datlist);
534
535 return;
536 }
537
538
539
540
541
542 /* @funcstatic acdrelations_procacdfile1 ***************************************
543 **
544 ** Process ACD file and write new ACD file with relations: attributes in new
545 ** format (mode '1' operation).
546 **
547 ** @param [u] inf [AjPFile] ACD input file
548 ** @param [u] outf [AjPFile] ACD output file
549 ** @return [void]
550 ** @@
551 ******************************************************************************/
acdrelations_procacdfile1(AjPFile inf,AjPFile outf)552 static void acdrelations_procacdfile1
553 (AjPFile inf,
554 AjPFile outf)
555 {
556 AjPStr line = NULL;
557 AjPStr tmp = NULL;
558 AjPStr tok = NULL;
559 AjPStr id = NULL;
560 AjPStr name = NULL;
561 AjPStr namespace = NULL;
562 AjPStrTok parse = NULL;
563 ajint pos;
564
565
566 /* Allocate memory */
567 line = ajStrNew();
568 tmp = ajStrNew();
569 tok = ajStrNew();
570 id = ajStrNew();
571 name = ajStrNew();
572 namespace = ajStrNew();
573
574
575 /* Read next line */
576 while(ajReadline(inf,&line))
577 {
578 ajFmtScanS(line, "%S", &tok);
579
580 /* Write reformatted relations: line */
581 if(ajStrMatchC(tok, "relations:"))
582 {
583 /* Tokenise line segment (from after "relations:") by '"', ' ' and '/'
584 Discard unwanted tokens */
585 pos = (ajuint) ajStrFindAnyK(line, ':');
586 ajStrAssignC(&tmp, line->Ptr+pos);
587
588 parse = ajStrTokenNewC(tmp, "\" /");
589 ajStrTokenNextParse(parse, &tok);
590 ajStrTokenNextParse(parse, &tok);
591
592 /* Get namespace and id tokens */
593 ajStrTokenNextParse(parse, &namespace);
594 ajStrTokenNextParse(parse, &id);
595
596 /* Get rest of string (name)
597 Strip whitespace at start and trailing " from name. */
598 ajStrTokenRestParse(parse, &name);
599 ajStrRemoveWhiteExcess(&name);
600 ajStrRemoveSetC(&name, "\"\n");
601 ajStrTokenDel(&parse);
602
603 /* Position of last '/' and last '"' characters respectively. */
604 ajFmtPrintF(outf, " relations: \"EDAM:%S %S %S\"\n", id, namespace, name);
605 }
606
607 /* Write other lines out as-is */
608 else
609 ajFmtPrintF(outf, "%S", line);
610 }
611
612
613 /* Free memory */
614 ajStrDel(&line);
615 ajStrDel(&tmp);
616 ajStrDel(&tok);
617 ajStrDel(&id);
618 ajStrDel(&name);
619 ajStrDel(&namespace);
620
621 return;
622 }
623
624
625
626
627 /* @funcstatic acdrelations_procacdfile2 ***************************************
628 **
629 ** Process ACD file and write new ACD file with new relations: attributes
630 ** added (replaced if necessary) using mode '2' operation.
631 **
632 ** @param [u] inf [AjPFile] ACD input file
633 ** @param [u] outf [AjPFile] ACD output file
634 ** @param [u] P [PEdam] edam object
635 ** @param [u] T [PKtype] ktype object
636 ** @return [void]
637 ** @@
638 ******************************************************************************/
acdrelations_procacdfile2(AjPFile inf,AjPFile outf,PEdam P,PKtype T)639 static void acdrelations_procacdfile2
640 (AjPFile inf,
641 AjPFile outf,
642 PEdam P,
643 PKtype T)
644 {
645 AjPStr line = NULL;
646 AjPStr tok = NULL;
647 AjPStr acdtype = NULL;
648 AjPStr strtmp = NULL;
649 AjPList strlist = NULL;
650 AjPStr *strarr = NULL;
651 ajint nstr = 0;
652
653
654 /* Allocate memory */
655 line = ajStrNew();
656 tok = ajStrNew();
657 acdtype = ajStrNew();
658 strlist = ajListstrNew();
659
660
661 /* Read next line */
662 while(ajReadline(inf,&line))
663 {
664 ajFmtScanS(line, "%S", &tok);
665
666 /* Write application definition or section definition out as-is */
667 if(ajStrMatchC(tok, "application:") ||
668 ajStrMatchC(tok, "section:"))
669 {
670 ajFmtPrintF(outf, "%S", line);
671 while(ajReadline(inf,&line))
672 {
673 ajFmtPrintF(outf, "%S", line);
674 ajFmtScanS(line, "%S", &tok);
675 if(ajStrMatchC(tok, "]"))
676 break;
677 }
678 }
679 /* Write variables, endsection definitions and comments out as-is */
680 else if(ajStrMatchC(tok, "variable:") ||
681 ajStrMatchC(tok, "endsection:") ||
682 ajStrMatchC(tok, "#"))
683 ajFmtPrintF(outf, "%S", line);
684
685 /* Write out blank lines as-is */
686 else if (!ajFmtScanS(line, "%S", &tok))
687 ajFmtPrintF(outf, "%S", line);
688 /* Process data definition */
689 else
690 /* First line of data definition */
691 {
692 /* Process and write datatype line */
693 ajFmtPrintF(outf, "%S", line);
694 ajFmtScanS(line, "%S", &acdtype);
695 ajStrRemoveSetC(&acdtype, ":");
696
697 /* Process subsequent (attribute) lines */
698 while(ajReadline(inf,&line))
699 {
700 strtmp = ajStrNew();
701 ajStrAssignS(&strtmp, line);
702 ajStrRemoveWhite(&strtmp);
703 ajListstrPushAppend(strlist, strtmp);
704
705 ajFmtScanS(line, "%S", &tok);
706
707 /* Reached end of data definition */
708 if(ajStrMatchC(tok, "]"))
709 {
710 nstr = (ajuint) ajListstrToarray(strlist, &strarr);
711
712 /* Write relations: line */
713 acdrelations_writerelations(outf, acdtype, strarr, nstr, P, T);
714
715 AJFREE(strarr);
716 ajListstrFreeData(&strlist);
717 strlist = ajListstrNew();
718
719 ajFmtPrintF(outf, "%S", line);
720 break;
721 }
722 /* Ignore existing relations: lines */
723 else if(ajStrMatchC(tok, "relations:"))
724 continue;
725
726 ajFmtPrintF(outf, "%S", line);
727 }
728 }
729 }
730
731
732 /* Free memory */
733 ajStrDel(&line);
734 ajStrDel(&tok);
735 ajStrDel(&acdtype);
736 ajListstrFreeData(&strlist);
737
738 return;
739 }
740
741
742
743
744
745 /* @funcstatic acdrelations_writerelations ************************************
746 **
747 ** Writes relations: attribute for an ACD data definition
748 ** The relations: values given in knowntypes.standard have highest precedence,
749 ** then the values given in edamtoacd.dat
750 ** Attribute values for a given datatype in edamtoacd.dat are in order of
751 ** increasing precedence, i.e. the last line is highest and the relations:
752 ** value will be used if all conditions are met.
753 **
754 ** @param [u] outf [AjPFile] ACD output file
755 ** @param [u] acdtype [AjPStr] ACD datatype, e.g. "align"
756 ** @param [u] strarr [AjPStr*] All ACD attribute lines (whitespace removed)
757 ** for the the current ACD data item (of type
758 ** acdtype). One line per array element.
759 ** @param [r] n [ajint] Size of strarr
760 ** @param [u] P [PEdam] edam object to write
761 ** @param [u] T [PKtype] ktype object to read
762 ** @return [void]
763 ** @@
764 ******************************************************************************/
acdrelations_writerelations(AjPFile outf,AjPStr acdtype,AjPStr * strarr,ajint n,PEdam P,PKtype T)765 static void acdrelations_writerelations
766 (AjPFile outf,
767 AjPStr acdtype,
768 AjPStr *strarr,
769 ajint n,
770 PEdam P,
771 PKtype T)
772 {
773 ajint i = 0;
774 ajint j = 0;
775 ajint k = 0;
776 ajint nmatch = 0;
777 AjPStr relations = NULL;
778 AjPStr ktype = NULL; /* Value of knowntype: attribute */
779 AjBool done = ajFalse;
780 AjBool donetype = ajFalse;
781 AjPStr tmpstr = NULL;
782
783
784 if(!outf || !acdtype || !strarr || !n || !P)
785 ajFatal("NULL args passed to acdrelations_writerelations");
786
787 /* Memory allocation */
788 relations = ajStrNew();
789 ktype = ajStrNew();
790 tmpstr = ajStrNew();
791
792
793 /* Loop through all lines in edamtoacd.dat */
794 for(i=0; i<P->n ;i++)
795 {
796 /* Found matching datatype */
797 if(ajStrMatchS(acdtype, P->dat[i]->acdtype))
798 {
799 /* Copy first relations: string defined for this datatype (default) */
800 ajStrAssignS(&relations, P->dat[i]->edam);
801 done = ajTrue;
802 i++;
803
804 /* Check next line in edamtoacd.dat */
805 for( ; i<P->n; i++)
806 {
807 /* Datatype still matches */
808 if(ajStrMatchS(acdtype, P->dat[i]->acdtype))
809 {
810 /* Loop through all required attributes for this datatype */
811 for(nmatch=0, j=0; j<P->dat[i]->n; j++)
812 {
813 /* Loop through all attribute lines for the data defininition */
814 for(k=0; k<n; k++)
815 if(ajStrMatchS(P->dat[i]->acdattr[j], strarr[k]))
816 {
817 nmatch++;
818 break;
819 }
820 }
821 /* All attribute values match */
822 if(nmatch == P->dat[i]->n)
823 ajStrAssignS(&relations, P->dat[i]->edam);
824 /* Should never happen */
825 else if (nmatch > P->dat[i]->n)
826 ajFatal("Terminal weirdness in acdrelations_writerelations");
827 }
828 else
829 break;
830 }
831 break;
832 }
833 }
834
835 /* Check for match of knowntype: attribute against knowntypes.standard.
836 These have higher precedence than the rules defined in edamtoacd.dat */
837 for(donetype=ajFalse, i=0; i<n; i++)
838 {
839 if(ajStrPrefixC(strarr[i], "knowntype:"))
840 {
841
842 for(j=0;j<T->n; j++)
843 {
844 /* No check is made on the "Type" column in knowntypes.standard
845 as these are not proper ACD datatype names
846 To check these add
847 if(ajStrMatchS(acdtype, T->dat[j]->acdtype)) */
848
849 ajFmtPrintS(&tmpstr, "knowntype:\"%S\"", T->dat[j]->ktype);
850
851 if(ajStrMatchS(tmpstr, strarr[i]))
852 {
853 ajStrAssignS(&relations, T->dat[j]->edam);
854 donetype=ajTrue;
855 break;
856 }
857 }
858 if(donetype)
859 break;
860 }
861 else
862 continue;
863 }
864
865
866 if(!done)
867 ajFatal("No matching datatype (%S) in acdrelations_writerelations", acdtype);
868
869
870 /* Write relations: attribute line to file */
871 ajFmtPrintF(outf, " relations:%S\n", relations);
872
873
874 /* Free memory */
875 ajStrDel(&relations);
876 ajStrDel(&ktype);
877 ajStrDel(&tmpstr);
878
879 return;
880 }
881
882
883
884
885
886 /* @funcstatic acdrelations_EdamdatNew ****************************************
887 **
888 ** edamdat constructor
889 ** The array is NOT allocated
890 **
891 ** @return [PEdamdat] New object
892 ** @@
893 ******************************************************************************/
acdrelations_EdamdatNew(void)894 static PEdamdat acdrelations_EdamdatNew(void)
895 {
896 PEdamdat ret;
897
898 AJNEW0(ret);
899 ret->acdtype = ajStrNew();
900 ret->edam = ajStrNew();
901 ret->acdattr = NULL;
902 ret->n = 0;
903
904 return ret;
905 }
906
907
908
909
910
911 /* @funcstatic acdrelations_EdamNew *******************************************
912 **
913 ** edam constructor
914 ** The array is NOT allocated
915 **
916 ** @return [PEdam] New object
917 ** @@
918 ******************************************************************************/
acdrelations_EdamNew(void)919 static PEdam acdrelations_EdamNew(void)
920 {
921 PEdam ret;
922
923 AJNEW0(ret);
924
925 ret->dat = NULL;
926 ret->n = 0;
927
928 return ret;
929 }
930
931
932
933
934
935 /* @funcstatic acdrelations_EdamdatDel ****************************************
936 **
937 ** edamdat destructor
938 **
939 ** @param [d] P [PEdamdat*] edamdat object to delete
940 ** @return [void]
941 ** @@
942 ******************************************************************************/
acdrelations_EdamdatDel(PEdamdat * P)943 static void acdrelations_EdamdatDel(PEdamdat *P)
944 {
945 int i;
946
947 if(!P)
948 ajFatal("Null arg error 1 in acdrelations_EdamdatDel");
949 else if(!(*P))
950 ajFatal("Null arg error 2 in acdrelations_EdamdatDel");
951
952 ajStrDel(&(*P)->acdtype);
953 ajStrDel(&(*P)->edam);
954
955 if((*P)->n)
956 {
957 for(i=0;i<(*P)->n;i++)
958 ajStrDel(&(*P)->acdattr[i]);
959 AJFREE((*P)->acdattr);
960 }
961
962 AJFREE(*P);
963 *P=NULL;
964
965 return;
966 }
967
968
969
970
971
972 /* @funcstatic acdrelations_EdamDel *******************************************
973 **
974 ** edam destructor
975 **
976 ** @param [d] P [PEdam*] edam object to delete
977 ** @return [void]
978 ** @@
979 ******************************************************************************/
acdrelations_EdamDel(PEdam * P)980 static void acdrelations_EdamDel(PEdam *P)
981 {
982 int i;
983
984 if(!P)
985 ajFatal("Null arg error 1 in acdrelations_EdamDel");
986 else if(!(*P))
987 ajFatal("Null arg error 2 in acdrelations_EdamDel");
988
989 if((*P)->n)
990 {
991 for(i=0;i<(*P)->n;i++)
992 acdrelations_EdamdatDel(&(*P)->dat[i]);
993 AJFREE((*P)->dat);
994 }
995
996 AJFREE(*P);
997 *P=NULL;
998
999 return;
1000 }
1001
1002
1003
1004
1005
1006 /* @funcstatic acdrelations_KtypedatNew ***************************************
1007 **
1008 ** ktypedat constructor
1009 **
1010 ** @return [PKtypedat] New object
1011 ** @@
1012 ******************************************************************************/
1013
acdrelations_KtypedatNew(void)1014 static PKtypedat acdrelations_KtypedatNew(void)
1015 {
1016 PKtypedat ret;
1017
1018 AJNEW0(ret);
1019 ret->acdtype = ajStrNew();
1020 ret->edam = ajStrNew();
1021 ret->ktype = ajStrNew();
1022
1023 return ret;
1024 }
1025
1026
1027
1028
1029
1030 /* @funcstatic acdrelations_KtypeNew ******************************************
1031 **
1032 ** ktype constructor
1033 **
1034 ** @return [PKtype] New object
1035 ** @@
1036 ******************************************************************************/
acdrelations_KtypeNew(void)1037 static PKtype acdrelations_KtypeNew(void)
1038 {
1039 PKtype ret;
1040
1041 AJNEW0(ret);
1042
1043 ret->dat = NULL;
1044 ret->n = 0;
1045
1046 return ret;
1047 }
1048
1049
1050
1051
1052
1053 /* @funcstatic acdrelations_KtypedatDel ***************************************
1054 **
1055 ** ktypedat destructor
1056 **
1057 ** @param [d] P [PKtypedat*] ktypedat object to delete
1058 ** @return [void]
1059 ** @@
1060 ******************************************************************************/
acdrelations_KtypedatDel(PKtypedat * P)1061 static void acdrelations_KtypedatDel(PKtypedat *P)
1062 {
1063 if(!P)
1064 ajFatal("Null arg error 1 in acdrelations_KtypedatDel");
1065 else if(!(*P))
1066 ajFatal("Null arg error 2 in acdrelations_KtypedatDel");
1067
1068 ajStrDel(&(*P)->acdtype);
1069 ajStrDel(&(*P)->edam);
1070 ajStrDel(&(*P)->ktype);
1071
1072 AJFREE(*P);
1073 *P=NULL;
1074
1075 return;
1076 }
1077
1078
1079
1080
1081
1082 /* @funcstatic acdrelations_KtypeDel ******************************************
1083 **
1084 ** ktype destructor
1085 **
1086 ** @param [d] P [PKtype*] ktype object to delete
1087 ** @return [void]
1088 ** @@
1089 ******************************************************************************/
acdrelations_KtypeDel(PKtype * P)1090 static void acdrelations_KtypeDel(PKtype *P)
1091 {
1092 int i;
1093
1094 if(!P)
1095 ajFatal("Null arg error 1 in acdrelations_KtypeDel");
1096 else if(!(*P))
1097 ajFatal("Null arg error 2 in acdrelations_KtypeDel");
1098
1099 if((*P)->n)
1100 {
1101 for(i=0;i<(*P)->n;i++)
1102 acdrelations_KtypedatDel(&(*P)->dat[i]);
1103 AJFREE((*P)->dat);
1104 }
1105
1106 AJFREE(*P);
1107 *P=NULL;
1108
1109 return;
1110 }
1111