1 /****************************************************************\
2 * *
3 * Module of splice site and intron modelling *
4 * *
5 * Guy St.C. Slater.. mailto:guy@ebi.ac.uk *
6 * Copyright (C) 2000-2009. All Rights Reserved. *
7 * *
8 * This source code is distributed under the terms of the *
9 * GNU General Public License, version 3. See the file COPYING *
10 * or http://www.gnu.org/licenses/gpl.txt for details *
11 * *
12 * If you use this code, please keep this notice intact. *
13 * *
14 \****************************************************************/
15
16 #include "intron.h"
17 #include "ungapped.h"
18
Intron_ArgumentSet_create(Argument * arg)19 Intron_ArgumentSet *Intron_ArgumentSet_create(Argument *arg){
20 register ArgumentSet *as;
21 static Intron_ArgumentSet ias;
22 if(arg){
23 as = ArgumentSet_create("Intron Modelling Options");
24 ArgumentSet_add_option(as, 0, "minintron", "length",
25 "Minimum intron length", "30",
26 Argument_parse_int, &ias.min_intron);
27 ArgumentSet_add_option(as, 0, "maxintron", "length",
28 "Maximum intron length", "200000",
29 Argument_parse_int, &ias.max_intron);
30 ArgumentSet_add_option(as, 'i', "intronpenalty", "score",
31 "Intron Opening penalty", "-30",
32 Argument_parse_int, &ias.intron_open_penalty);
33 Argument_absorb_ArgumentSet(arg, as);
34 ias.sps = NULL;
35 if(ias.intron_open_penalty > 0)
36 g_warning("Intron open penalty should be negative [%d]",
37 ias.intron_open_penalty);
38 } else {
39 if(!ias.sps)
40 ias.sps = SplicePredictorSet_create();
41 /* FIXME: this should be freed somewhere */
42 }
43 return &ias;
44 }
45
46 /**/
47
Intron_ChainData_get_seq_func(gint start,gint len,gpointer user_data)48 static gchar *Intron_ChainData_get_seq_func(gint start,
49 gint len,
50 gpointer user_data){
51 register Sequence *s = user_data;
52 return Sequence_get_substr(s, start, len);
53 }
54
Intron_ChainData_init_splice_prediction(Intron_ChainData * icd,Sequence * s,SplicePredictorSet * sps,SpliceType type,gboolean use_single)55 void Intron_ChainData_init_splice_prediction(Intron_ChainData *icd,
56 Sequence *s, SplicePredictorSet *sps, SpliceType type,
57 gboolean use_single){
58 if(!icd->sps)
59 icd->sps = g_new0(SplicePrediction_Set, 1);
60 icd->sps = SplicePrediction_Set_add(icd->sps, sps, type, s->len,
61 Intron_ChainData_get_seq_func, use_single, s);
62 return;
63 }
64
Intron_ChainData_init(Intron_ChainData * icd)65 static void Intron_ChainData_init(Intron_ChainData *icd){
66 icd->curr_intron_start = 0;
67 return;
68 }
69
Intron_ChainData_create(void)70 static Intron_ChainData *Intron_ChainData_create(void){
71 register Intron_ChainData *icd = g_new0(Intron_ChainData, 1);
72 Intron_ChainData_init(icd);
73 return icd;
74 }
75
Intron_ChainData_destroy(Intron_ChainData * icd)76 static void Intron_ChainData_destroy(Intron_ChainData *icd){
77 if(icd->sps)
78 SplicePrediction_Set_destroy(icd->sps);
79 g_free(icd);
80 return;
81 }
82
83 /**/
84
Intron_Data_create(void)85 Intron_Data *Intron_Data_create(void){
86 register Intron_Data *id = g_new0(Intron_Data, 1);
87 id->ias = Intron_ArgumentSet_create(NULL);
88 id->query_data = Intron_ChainData_create();
89 id->target_data = Intron_ChainData_create();
90 return id;
91 }
92
Intron_Data_destroy(Intron_Data * id)93 void Intron_Data_destroy(Intron_Data *id){
94 Intron_ChainData_destroy(id->query_data);
95 Intron_ChainData_destroy(id->target_data);
96 g_free(id);
97 return;
98 }
99
100 /**/
101
intron_init_func(Region * region,gpointer user_data)102 static void intron_init_func(Region *region, gpointer user_data){
103 register Ungapped_Data *ud = user_data;
104 register Intron_Data *id = Ungapped_Data_get_Intron_Data(ud);
105 if(!id->curr_region){
106 id->curr_region = Region_share(region);
107 Intron_ChainData_init(id->query_data);
108 Intron_ChainData_init(id->target_data);
109 }
110 return;
111 }
112
113 static gchar *intron_init_macro =
114 "if(!id->curr_region){\n"
115 " id->curr_region = Region_share(region);\n"
116 " Intron_ChainData_init(id->query_data);\n"
117 " Intron_ChainData_init(id->target_data);\n"
118 " }\n";
119
intron_exit_func(Region * region,gpointer user_data)120 static void intron_exit_func(Region *region, gpointer user_data){
121 register Ungapped_Data *ud = user_data;
122 register Intron_Data *id = Ungapped_Data_get_Intron_Data(ud);
123 if(id->curr_region){
124 Region_destroy(id->curr_region);
125 id->curr_region = NULL;
126 }
127 return;
128 }
129
130 static gchar *intron_exit_macro =
131 "if(id->curr_region){\n"
132 " Region_destroy(id->curr_region);\n"
133 " id->curr_region = NULL;\n"
134 " }\n";
135
136 /**/
137
138 #define Intron_CalcFunc(site, chain, is_pre) \
139 static C4_Score Intron_calc_##site##_##chain( \
140 gint query_pos, gint target_pos, gpointer user_data){ \
141 register Ungapped_Data *ud = user_data; \
142 register Intron_Data *id \
143 = Ungapped_Data_get_Intron_Data(ud); \
144 register C4_Score score = 0; \
145 register gint intron_length; \
146 g_assert(id->chain##_data->sps->site); \
147 g_assert(id->curr_region); \
148 if(is_pre){ \
149 score = id->ias->intron_open_penalty; \
150 } else { \
151 intron_length = chain##_pos \
152 - id->chain##_data->curr_intron_start \
153 + 2; \
154 if((intron_length < id->ias->min_intron) \
155 || (intron_length > id->ias->max_intron)) \
156 return C4_IMPOSSIBLY_LOW_SCORE; \
157 } \
158 score += SplicePrediction_get(id->chain##_data->sps->site, \
159 chain##_pos); \
160 return score; \
161 }
162
163 #define Intron_JointCalcFunc(site, is_pre) \
164 static C4_Score Intron_joint_calc_##site( \
165 gint query_pos, gint target_pos, gpointer user_data){ \
166 register Ungapped_Data *ud = user_data; \
167 register Intron_Data *id \
168 = Ungapped_Data_get_Intron_Data(ud); \
169 register C4_Score score = 0; \
170 register gint intron_length; \
171 g_assert(id->query##_data->sps->site); \
172 g_assert(id->target##_data->sps->site); \
173 g_assert(id->curr_region); \
174 if(is_pre){ \
175 score = id->ias->intron_open_penalty; \
176 } else { \
177 intron_length = query_pos \
178 - id->query_data->curr_intron_start \
179 + 2; \
180 if((intron_length < id->ias->min_intron) \
181 || (intron_length > id->ias->max_intron)) \
182 return C4_IMPOSSIBLY_LOW_SCORE; \
183 intron_length = target_pos \
184 - id->target_data->curr_intron_start \
185 + 2; \
186 if((intron_length < id->ias->min_intron) \
187 || (intron_length > id->ias->max_intron)) \
188 return C4_IMPOSSIBLY_LOW_SCORE; \
189 } \
190 score += SplicePrediction_get(id->query##_data->sps->site, \
191 query_pos); \
192 score += SplicePrediction_get(id->target##_data->sps->site, \
193 target_pos); \
194 return score; \
195 }
196
Intron_get_calc_macro_splice(gboolean on_query,gchar * site)197 static gchar *Intron_get_calc_macro_splice(gboolean on_query,
198 gchar *site){
199 register gchar *chain = on_query?"query":"target";
200 register gchar *chain_macro = on_query?"QP":"TP";
201 return g_strdup_printf("SplicePrediction_get(id->%s_data->sps->%s, %%%s)",
202 chain, site, chain_macro);
203 }
204
Intron_get_calc_macro_length(gboolean on_query,gchar * input_macro)205 static gchar *Intron_get_calc_macro_length(gboolean on_query,
206 gchar *input_macro){
207 register gchar *chain = on_query?"query":"target";
208 register gchar *chain_macro = on_query?"QP":"TP";
209 register gchar *intron_length = g_strdup_printf(
210 "(%%%s - id->%s_data->curr_intron_start + 2)",
211 chain_macro, chain);
212 register gchar *macro = g_strdup_printf(
213 "(((%s < id->ias->min_intron)"
214 "||(%s > id->ias->max_intron))"
215 "?C4_IMPOSSIBLY_LOW_SCORE:%s)",
216 intron_length, intron_length, input_macro);
217 g_free(intron_length);
218 return macro;
219 }
220
Intron_get_calc_macro(gboolean is_5_prime,gboolean is_forward,gboolean on_query,gboolean on_target,gboolean is_pre)221 static gchar *Intron_get_calc_macro(gboolean is_5_prime,
222 gboolean is_forward,
223 gboolean on_query,
224 gboolean on_target,
225 gboolean is_pre){
226 register gchar *macro = NULL;
227 register gchar *site = g_strdup_printf("ss%d_%s", is_5_prime?5:3,
228 is_forward?"forward":"reverse");
229 register gchar *splice_calc;
230 register gchar *a, *b;
231 if(on_query && on_target){ /* joint */
232 a = Intron_get_calc_macro_splice(TRUE, site);
233 b = Intron_get_calc_macro_splice(FALSE, site);
234 splice_calc = g_strdup_printf("(%s + %s)", a, b);
235 g_free(a);
236 g_free(b);
237 } else { /* single */
238 splice_calc = Intron_get_calc_macro_splice(on_query, site);
239 }
240 /**/
241 if(is_pre){
242 macro = g_strdup_printf("(%s + %s)",
243 "id->ias->intron_open_penalty", splice_calc);
244 } else {
245 if(on_query && on_target){ /* joint */
246 a = Intron_get_calc_macro_length(TRUE, splice_calc);
247 macro = Intron_get_calc_macro_length(FALSE, a);
248 g_free(a);
249 } else { /* single */
250 macro = Intron_get_calc_macro_length(on_query, splice_calc);
251 }
252 }
253 g_free(splice_calc);
254 g_free(site);
255 g_assert(macro);
256 return macro;
257 }
258
259 #define Intron_InitFunc(site, chain) \
260 static void Intron_init_##site##_##chain( \
261 Region *region, gpointer user_data){ \
262 register Ungapped_Data *ud = user_data; \
263 register Intron_Data *id = Ungapped_Data_get_Intron_Data(ud); \
264 Intron_ChainData_init_splice_prediction(id->chain##_data, ud->chain, \
265 id->ias->sps, \
266 SpliceType_##site, \
267 FALSE); \
268 return; \
269 }
270
271 #define Intron_JointInitFunc(site) \
272 static void Intron_joint_init_##site( \
273 Region *region, gpointer user_data){ \
274 Intron_init_##site##_query(region, user_data); \
275 Intron_init_##site##_target(region, user_data); \
276 return; \
277 }
278
Intron_get_strand_init_macro(gboolean is_5_prime,gboolean is_forward,gboolean on_query)279 static gchar *Intron_get_strand_init_macro(gboolean is_5_prime,
280 gboolean is_forward,
281 gboolean on_query){
282 register gchar *chain = on_query?"query":"target";
283 register gchar *site = g_strdup_printf("ss%d_%s",
284 is_5_prime?5:3, is_forward?"forward":"reverse");
285 register gchar *macro = g_strdup_printf(
286 "Intron_ChainData_init_splice_prediction(id->%s_data, ud->%s, id->ias->sps,"
287 " SpliceType_%s,"
288 " ((id->curr_region->%s_start == 0)"
289 " && (id->curr_region->%s_length == ud->%s->len)));",
290 chain, chain, site, chain, chain, chain);
291 g_free(site);
292 return macro;
293 }
294
Intron_get_init_macro(gboolean is_5_prime,gboolean is_forward,gboolean on_query,gboolean on_target)295 static gchar *Intron_get_init_macro(gboolean is_5_prime,
296 gboolean is_forward,
297 gboolean on_query,
298 gboolean on_target){
299 register gchar *qy_macro, *tg_macro, *macro;
300 if(on_query && on_target){
301 qy_macro = Intron_get_strand_init_macro(is_5_prime, is_forward,
302 TRUE);
303 tg_macro = Intron_get_strand_init_macro(is_5_prime, is_forward,
304 FALSE);
305 macro = g_strdup_printf("%s;%s", qy_macro, tg_macro);
306 g_free(qy_macro);
307 g_free(tg_macro);
308 } else {
309 macro = Intron_get_strand_init_macro(is_5_prime, is_forward,
310 on_query);
311 }
312 return macro;
313 }
314
315 #if 0
316 #define Intron_InitMacro(site, chain, chainmacro) \
317 static gchar *intron_## site ##_## chain ##_init_macro = \
318 "if(!id->"#chain"_data->"#site"){\n" \
319 " id->"#chain"_data->"#site" = SplicePrediction_create(" \
320 " id->ias->sps->"# site ",\n" \
321 " ud->"#chain"->seq,\n" \
322 " ud->"#chain"->len,\n" \
323 " %"#chainmacro"S, %"#chainmacro"L);\n" \
324 " }\n";
325 /* FIXME: do not give len when doing DP over unknown region
326 * or give hint, eg: computing_full_dp
327 */
328 #endif /* 0 */
329
330 #if 0
331 #define Intron_ExitFunc(site, chain) \
332 static void Intron_exit_##site##_##chain( \
333 Region *region, gpointer user_data){ \
334 register Ungapped_Data *ud = user_data; \
335 register Intron_Data *id = Ungapped_Data_get_Intron_Data(ud); \
336 if(id->chain##_data->site){ \
337 SplicePrediction_destroy(id->chain##_data->site); \
338 id->chain##_data->site = NULL; \
339 } \
340 return; \
341 }
342
343 #define Intron_JointExitFunc(site) \
344 static void Intron_joint_exit_##site( \
345 Region *region, gpointer user_data){ \
346 Intron_exit_##site##_query(region, user_data); \
347 Intron_exit_##site##_target(region, user_data); \
348 return; \
349 }
350 #endif /* 0 */
351
352 #if 0
353 #define Intron_ExitMacro(site, chain) \
354 static gchar *intron_##site##_##chain##_exit_macro = \
355 "if(id->"#chain"_data->"#site"){\n" \
356 " SplicePrediction_destroy(id->"#chain"_data->"#site");\n" \
357 " id->"#chain"_data->"#site" = NULL;" \
358 " }\n";
359 #endif /* 0 */
360
361 #if 0
362 static gchar *Intron_get_strand_exit_macro(gboolean is_5_prime,
363 gboolean is_forward,
364 gboolean on_query){
365 register gchar *chain = on_query?"query":"target";
366 register gchar *site = g_strdup_printf("ss%d_%s",
367 is_5_prime?5:3, is_forward?"forward":"reverse");
368 return g_strdup_printf(
369 "if(id->%s_data->%s){\n"
370 " SplicePrediction_destroy(id->%s_data->%s);\n"
371 " id->%s_data->%s = NULL;"
372 " }\n",
373 chain, site, chain, site, chain, site);
374 }
375
376 static gchar *Intron_get_exit_macro(gboolean is_5_prime,
377 gboolean is_forward,
378 gboolean on_query,
379 gboolean on_target){
380 register gchar *qy_macro, *tg_macro, *macro;
381 if(on_query && on_target){
382 qy_macro = Intron_get_strand_exit_macro(is_5_prime, is_forward,
383 TRUE);
384 tg_macro = Intron_get_strand_exit_macro(is_5_prime, is_forward,
385 FALSE);
386 macro = g_strdup_printf("%s;%s", qy_macro, tg_macro);
387 g_free(qy_macro);
388 g_free(tg_macro);
389 } else {
390 macro = Intron_get_strand_exit_macro(is_5_prime, is_forward,
391 on_query);
392 }
393 return macro;
394 }
395 #endif /* 0 */
396
397 /**/
398
399 #define Intron_CalcElements(site, chain, chainmacro, is_pre) \
400 Intron_CalcFunc(site, chain, is_pre) \
401 Intron_InitFunc(site, chain)
402
403 /* Intron_ExitFunc(site, chain) */
404
405 #define Intron_JointCalcElements(site, is_pre) \
406 Intron_JointCalcFunc(site, is_pre) \
407 Intron_JointInitFunc(site)
408
409
410 /* Intron_JointExitFunc(site) */
411
412 /* pre */
Intron_CalcElements(ss5_forward,query,Q,TRUE)413 Intron_CalcElements(ss5_forward, query, Q, TRUE)
414 Intron_CalcElements(ss5_forward, target, T, TRUE)
415 Intron_JointCalcElements(ss5_forward, TRUE)
416
417 /* post */
418 Intron_CalcElements(ss3_forward, query, Q, FALSE)
419 Intron_CalcElements(ss3_forward, target, T, FALSE)
420 Intron_JointCalcElements(ss3_forward, FALSE)
421
422 /* pre */
423 Intron_CalcElements(ss3_reverse, query, Q, TRUE)
424 Intron_CalcElements(ss3_reverse, target, T, TRUE)
425 Intron_JointCalcElements(ss3_reverse, FALSE)
426
427 /* post */
428 Intron_CalcElements(ss5_reverse, query, Q, FALSE)
429 Intron_CalcElements(ss5_reverse, target, T, FALSE)
430 Intron_JointCalcElements(ss5_reverse, FALSE)
431
432 #define Intron_assign_calc_elements(site, chain) \
433 calc_func = Intron_calc_##site##_##chain; \
434 init_func = Intron_init_##site##_##chain;
435
436 /* exit_func = Intron_exit_##site##_##chain; */
437
438 /**/
439
440 #define Intron_assign_joint_calc_elements(site) \
441 calc_func = Intron_joint_calc_##site; \
442 init_func = Intron_joint_init_##site;
443
444 /* exit_func = Intron_joint_exit_##site; */
445
446 /**/
447
448 /*
449 Functions and macros for intron length shadow:
450
451 Intron_{query,target}_{start,end}_{func,macro}
452 */
453
454 #define Intron_StartFunc(chain) \
455 static C4_Score Intron_##chain##_start_func( \
456 gint query_pos, gint target_pos, gpointer user_data){ \
457 return (C4_Score)chain##_pos; \
458 }
459
460 #define Intron_StartMacro(chain, chainmacro) \
461 static gchar *Intron_##chain##_start_macro \
462 = "(C4_Score)(%"#chainmacro"P)";
463
464 #define Intron_StartElements(chain, chainmacro) \
465 Intron_StartFunc(chain) \
466 Intron_StartMacro(chain, chainmacro)
467
468 #define Intron_EndFunc(chain) \
469 static void Intron_##chain##_end_func(C4_Score score, \
470 gint query_pos, gint target_pos, gpointer user_data){ \
471 register Ungapped_Data *ud = user_data; \
472 register Intron_Data *id = Ungapped_Data_get_Intron_Data(ud); \
473 g_assert(id); \
474 id->chain##_data->curr_intron_start = (gint)score; \
475 return; \
476 }
477
478 #define Intron_EndMacro(chain) \
479 static gchar *Intron_##chain##_end_macro \
480 = "id->"#chain"_data->curr_intron_start = (gint)%SS";
481
482 /**/
483
484 #define Intron_EndElements(chain) \
485 Intron_EndFunc(chain) \
486 Intron_EndMacro(chain)
487
488 #define Intron_ShadowElements(chain, chainmacro) \
489 Intron_StartElements(chain, chainmacro) \
490 Intron_EndElements(chain)
491
492 Intron_ShadowElements(query, Q)
493 Intron_ShadowElements(target, T)
494
495 /**/
496
497 static C4_Calc *Intron_add_calc(C4_Model *model,
498 gchar *prefix, gchar *suffix,
499 gboolean use_pre,
500 gboolean is_forward,
501 gboolean on_query, gboolean on_target){
502 register gchar *name = g_strconcat(prefix, " ", suffix, NULL);
503 register Intron_ArgumentSet *ias
504 = Intron_ArgumentSet_create(NULL);
505 register SplicePredictor *sp;
506 register C4_Calc *calc;
507 register C4_CalcFunc calc_func;
508 register C4_PrepFunc init_func;
509 register gchar *calc_macro, *init_macro;
510 register C4_Score bound = 0;
511 register gboolean is_5_prime = is_forward?(use_pre?TRUE:FALSE)
512 :(use_pre?FALSE:TRUE);
513 if(is_forward){
514 if(use_pre){
515 sp = ias->sps->ss5_forward;
516 bound = ias->intron_open_penalty;
517 if(on_query){
518 if(on_target){
519 Intron_assign_joint_calc_elements(ss5_forward);
520 } else {
521 Intron_assign_calc_elements(ss5_forward, query);
522 }
523 } else {
524 Intron_assign_calc_elements(ss5_forward, target);
525 }
526 } else {
527 sp = ias->sps->ss3_forward;
528 if(on_query){
529 if(on_target){
530 Intron_assign_joint_calc_elements(ss3_forward);
531 } else {
532 Intron_assign_calc_elements(ss3_forward, query);
533 }
534 } else {
535 Intron_assign_calc_elements(ss3_forward, target);
536 }
537 }
538 } else {
539 if(use_pre){
540 sp = ias->sps->ss3_reverse;
541 bound = ias->intron_open_penalty;
542 if(on_query){
543 if(on_target){
544 Intron_assign_joint_calc_elements(ss3_reverse);
545 } else {
546 Intron_assign_calc_elements(ss3_reverse, query);
547 }
548 } else {
549 Intron_assign_calc_elements(ss3_reverse, target);
550 }
551 } else {
552 sp = ias->sps->ss5_reverse;
553 if(on_query){
554 if(on_target){
555 Intron_assign_joint_calc_elements(ss5_reverse);
556 } else {
557 Intron_assign_calc_elements(ss5_reverse, query);
558 }
559 } else {
560 Intron_assign_calc_elements(ss5_reverse, target);
561 }
562 }
563 }
564 bound += SplicePredictor_get_max_score(sp);
565 if(on_query && on_target) /* Double for joint intron */
566 bound += SplicePredictor_get_max_score(sp);
567 calc_macro = Intron_get_calc_macro(is_5_prime, is_forward,
568 on_query, on_target, use_pre);
569 init_macro = Intron_get_init_macro(is_5_prime, is_forward,
570 on_query, on_target);
571 /*
572 exit_macro = Intron_get_exit_macro(is_5_prime, is_forward,
573 on_query, on_target);
574 */
575 calc = C4_Model_add_calc(model, name, bound,
576 calc_func, calc_macro,
577 init_func, init_macro,
578 NULL, NULL,
579 C4_Protect_UNDERFLOW);
580 g_assert(calc_macro);
581 g_assert(init_macro);
582 g_free(calc_macro);
583 g_free(init_macro);
584 g_free(name);
585 return calc;
586 }
587
Intron_create(gchar * suffix,gboolean on_query,gboolean on_target,gboolean is_forward)588 C4_Model *Intron_create(gchar *suffix, gboolean on_query,
589 gboolean on_target, gboolean is_forward){
590 register gchar *name, *pre_name, *post_name;
591 register C4_Model *model;
592 register C4_State *intron_state;
593 register gint qy_splice_advance, tg_splice_advance;
594 register C4_Calc *pre_calc, *post_calc;
595 register C4_Label pre_label, post_label;
596 register Intron_ArgumentSet *ias
597 = Intron_ArgumentSet_create(NULL);
598 g_assert(on_query || on_target);
599 name = g_strconcat("intron ", suffix, NULL);
600 model = C4_Model_create(name);
601 g_free(name);
602 if(is_forward){
603 pre_name = "5'ss forward";
604 post_name = "3'ss forward";
605 pre_label = C4_Label_5SS;
606 post_label = C4_Label_3SS;
607 } else {
608 pre_name = "3'ss reverse";
609 post_name = "5'ss reverse";
610 pre_label = C4_Label_3SS;
611 post_label = C4_Label_5SS;
612 }
613 if(on_query){
614 if(on_target){ /* Joint intron */
615 qy_splice_advance = 2;
616 tg_splice_advance = 2;
617 } else {
618 qy_splice_advance = 2;
619 tg_splice_advance = 0;
620 }
621 } else { /* on target */
622 qy_splice_advance = 0;
623 tg_splice_advance = 2;
624 }
625 /* Add calcs */
626 pre_calc = Intron_add_calc(model, pre_name, suffix, TRUE,
627 is_forward, on_query, on_target);
628 post_calc = Intron_add_calc(model, post_name, suffix, FALSE,
629 is_forward, on_query, on_target);
630 /* Add intron state */
631 name = g_strconcat("intron ", suffix, NULL);
632 intron_state = C4_Model_add_state(model, name);
633 g_free(name);
634 /* Add transition START->intron */
635 name = g_strconcat("(START) to ", intron_state->name, NULL);
636 C4_Model_add_transition(model, name, NULL, intron_state,
637 qy_splice_advance, tg_splice_advance, pre_calc, pre_label, NULL);
638 g_free(name);
639 /* Add transition intron->intron */
640 if(on_query){
641 name = g_strconcat("query intron loop ", suffix, NULL);
642 C4_Model_add_transition(model, name, intron_state, intron_state,
643 1, 0, NULL, C4_Label_INTRON, NULL);
644 g_free(name);
645 }
646 if(on_target){
647 name = g_strconcat("target intron loop ", suffix, NULL);
648 C4_Model_add_transition(model, name, intron_state, intron_state,
649 0, 1, NULL, C4_Label_INTRON, NULL);
650 g_free(name);
651 }
652 /* Add transition intron->(END)*/
653 name = g_strconcat(intron_state->name, " to (END)", NULL);
654 C4_Model_add_transition(model, name,
655 intron_state, NULL, qy_splice_advance, tg_splice_advance,
656 post_calc, post_label, NULL);
657 g_free(name);
658 /* Add span state */
659 name = g_strconcat("intron span", suffix, NULL);
660 if(on_query){
661 if(on_target){
662 C4_Model_add_span(model, name, intron_state,
663 ias->min_intron, ias->max_intron,
664 ias->min_intron, ias->max_intron);
665 } else {
666 C4_Model_add_span(model, name, intron_state,
667 ias->min_intron, ias->max_intron, 0, 0);
668 }
669 } else {
670 C4_Model_add_span(model, name, intron_state,
671 0, 0, ias->min_intron, ias->max_intron);
672 }
673 g_free(name);
674 /* Add shadows */
675 if(on_query){
676 name = g_strconcat("query intron ", suffix, NULL);
677 C4_Model_add_shadow(model, name, NULL, NULL,
678 Intron_query_start_func, Intron_query_start_macro,
679 Intron_query_end_func, Intron_query_end_macro);
680 g_free(name);
681 }
682 if(on_target){
683 name = g_strconcat("target intron ", suffix, NULL);
684 C4_Model_add_shadow(model, name, NULL, NULL,
685 Intron_target_start_func, Intron_target_start_macro,
686 Intron_target_end_func, Intron_target_end_macro);
687 g_free(name);
688 }
689 /* Add DP init/exit funcs/macros */
690 C4_Model_configure_extra(model,
691 intron_init_func, intron_init_macro,
692 intron_exit_func, intron_exit_macro);
693 C4_Model_append_codegen(model, NULL,
694 "register Intron_Data *id = ud->intron_data;\n", NULL);
695 C4_Model_close(model);
696 return model;
697 }
698
699