1 /****************************************************************\
2 *                                                                *
3 *  Module for various affine gapped models                       *
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 <string.h> /* For strlen() */
17 #include "affine.h"
18 
Affine_ArgumentSet_create(Argument * arg)19 Affine_ArgumentSet *Affine_ArgumentSet_create(Argument *arg){
20     register ArgumentSet *as;
21     static Affine_ArgumentSet aas;
22     if(arg){
23         as = ArgumentSet_create("Affine Model Options");
24         ArgumentSet_add_option(as, 'o', "gapopen", "penalty",
25             "Affine gap open penalty", "-12",
26             Argument_parse_int, &aas.gap_open);
27         ArgumentSet_add_option(as, 'e', "gapextend", "penalty",
28             "Affine gap extend penalty", "-4",
29             Argument_parse_int, &aas.gap_extend);
30         ArgumentSet_add_option(as, '\0', "codongapopen", "penalty",
31             "Codon affine gap open penalty", "-18",
32             Argument_parse_int, &aas.codon_gap_open);
33         ArgumentSet_add_option(as, '\0', "codongapextend", "penalty",
34             "Codon affine gap extend penalty", "-8",
35             Argument_parse_int, &aas.codon_gap_extend);
36         Argument_absorb_ArgumentSet(arg, as);
37         if(aas.gap_open > 0)
38             g_warning("Gap open penalty [%d] should be negative",
39                     aas.gap_open);
40         if(aas.gap_extend > 0)
41             g_warning("Gap extend penalty [%d] should be negative",
42                     aas.gap_extend);
43         if(aas.codon_gap_open > 0)
44             g_warning("Codon gap open penalty [%d] should be negative",
45                     aas.codon_gap_open);
46         if(aas.codon_gap_extend > 0)
47             g_warning("Codon gap extend penalty [%d] should be negative",
48                     aas.codon_gap_extend);
49         }
50     return &aas;
51     }
52 
53 /**/
54 
Affine_Data_init(Affine_Data * ad,Sequence * query,Sequence * target,gboolean translate_both)55 void Affine_Data_init(Affine_Data *ad,
56                       Sequence *query, Sequence *target,
57                       gboolean translate_both){
58     register Match_Type match_type
59         = Match_Type_find(query->alphabet->type,
60                           target->alphabet->type,
61                           translate_both);
62     Ungapped_Data_init(&ad->ud, query, target, match_type);
63     if(!ad->aas)
64         ad->aas = Affine_ArgumentSet_create(NULL);
65     return;
66     }
67 
Affine_Data_create(Sequence * query,Sequence * target,gboolean translate_both)68 Affine_Data *Affine_Data_create(Sequence *query, Sequence *target,
69                                 gboolean translate_both){
70     register Affine_Data *ad = g_new0(Affine_Data, 1);
71     Affine_Data_init(ad, query, target, translate_both);
72     return ad;
73     }
74 
Affine_Data_clear(Affine_Data * ad)75 void Affine_Data_clear(Affine_Data *ad){
76     Ungapped_Data_clear(&ad->ud);
77     return;
78     }
79 
Affine_Data_destroy(Affine_Data * ad)80 void Affine_Data_destroy(Affine_Data *ad){
81     Affine_Data_clear(ad);
82     g_free(ad);
83     return;
84     }
85 
86 /**/
87 
affine_gap_open_calc_func(gint query_pos,gint target_pos,gpointer user_data)88 static C4_Score affine_gap_open_calc_func(gint query_pos,
89                                           gint target_pos,
90                                           gpointer user_data){
91     register Affine_Data *ad = (Affine_Data*)user_data;
92     return ad->aas->gap_open;
93     }
94 
95 static gchar *affine_gap_open_calc_macro = "(ad->aas->gap_open)";
96 
affine_gap_extend_calc_func(gint query_pos,gint target_pos,gpointer user_data)97 static C4_Score affine_gap_extend_calc_func(gint query_pos,
98                                             gint target_pos,
99                                             gpointer user_data){
100     register Affine_Data *ad = (Affine_Data*)user_data;
101     return ad->aas->gap_extend;
102     }
103 
104 static gchar *affine_gap_extend_calc_macro = "(ad->aas->gap_extend)";
105 
106 /**/
107 
affine_codon_gap_open_calc_func(gint query_pos,gint target_pos,gpointer user_data)108 static C4_Score affine_codon_gap_open_calc_func(gint query_pos,
109                                                 gint target_pos,
110                                                 gpointer user_data){
111     register Affine_Data *ad = (Affine_Data*)user_data;
112     return ad->aas->codon_gap_open;
113     }
114 
115 static gchar *affine_codon_gap_open_calc_macro = "(ad->aas->codon_gap_open)";
116 
affine_codon_gap_extend_calc_func(gint query_pos,gint target_pos,gpointer user_data)117 static C4_Score affine_codon_gap_extend_calc_func(gint query_pos,
118                                                   gint target_pos,
119                                                   gpointer user_data){
120     register Affine_Data *ad = (Affine_Data*)user_data;
121     return ad->aas->codon_gap_extend;
122     }
123 
124 static gchar *affine_codon_gap_extend_calc_macro = "(ad->aas->codon_gap_extend)";
125 
126 /**/
127 
Affine_Model_Type_get_name(Affine_Model_Type type)128 gchar *Affine_Model_Type_get_name(Affine_Model_Type type){
129     register gchar *model_name = NULL;
130     switch(type){
131         case Affine_Model_Type_GLOBAL:
132             model_name = "global";
133             break;
134         case Affine_Model_Type_BESTFIT:
135             model_name = "bestfit";
136             break;
137         case Affine_Model_Type_LOCAL:
138             model_name = "local";
139             break;
140         case Affine_Model_Type_OVERLAP:
141             model_name = "overlap";
142             break;
143         default:
144             g_error("Unknown affine model type [%d]", type);
145             break;
146         }
147     return model_name;
148     }
149 
Affine_create(Affine_Model_Type type,Alphabet_Type query_type,Alphabet_Type target_type,gboolean translate_both)150 C4_Model *Affine_create(Affine_Model_Type type,
151                         Alphabet_Type query_type,
152                         Alphabet_Type target_type,
153                         gboolean translate_both){
154     register C4_Scope scope = C4_Scope_ANYWHERE;
155     register C4_Model *affine;
156     register C4_State *insert_state, *delete_state;
157     register C4_Transition *match_transition;
158     register C4_Calc *gap_open_calc, *gap_extend_calc;
159     register Affine_ArgumentSet *aas = Affine_ArgumentSet_create(NULL);
160     register Match_Type match_type = Match_Type_find(query_type,
161                                        target_type, translate_both);
162     register C4_CalcFunc gap_open_calc_func = NULL,
163                          gap_extend_calc_func = NULL;
164     register gchar *gap_open_calc_macro = NULL,
165                    *gap_extend_calc_macro = NULL;
166     register gchar *model_name = Affine_Model_Type_get_name(type);
167     affine = Ungapped_create(match_type);
168     switch(type){
169         case Affine_Model_Type_GLOBAL:
170             scope = C4_Scope_CORNER;
171             break;
172         case Affine_Model_Type_BESTFIT:
173             scope = C4_Scope_QUERY;
174             break;
175         case Affine_Model_Type_LOCAL:
176             scope = C4_Scope_ANYWHERE;
177             break;
178         case Affine_Model_Type_OVERLAP:
179             scope = C4_Scope_EDGE;
180             break;
181         default:
182             g_error("Unknown affine model type [%d]", type);
183             break;
184         }
185     g_assert(model_name);
186     model_name = g_strdup_printf("affine:%s:%s", model_name,
187                                  Match_Type_get_name(match_type));
188     C4_Model_rename(affine, model_name);
189     g_free(model_name);
190     C4_Model_configure_start_state(affine, scope, NULL, NULL);
191     C4_Model_configure_end_state(affine, scope, NULL, NULL);
192     C4_Model_open(affine);
193     insert_state = C4_Model_add_state(affine, "insert");
194     delete_state = C4_Model_add_state(affine, "delete");
195     match_transition = C4_Model_select_single_transition(affine,
196                                                  C4_Label_MATCH);
197     g_assert(match_transition);
198     if(MAX(match_transition->advance_query,
199            match_transition->advance_target) == 3){
200         gap_open_calc_func = affine_codon_gap_open_calc_func;
201         gap_extend_calc_func = affine_codon_gap_extend_calc_func;
202         gap_open_calc_macro = affine_codon_gap_open_calc_macro;
203         gap_extend_calc_macro = affine_codon_gap_extend_calc_macro;
204     } else {
205         gap_open_calc_func = affine_gap_open_calc_func;
206         gap_extend_calc_func = affine_gap_extend_calc_func;
207         gap_open_calc_macro = affine_gap_open_calc_macro;
208         gap_extend_calc_macro = affine_gap_extend_calc_macro;
209         }
210     gap_open_calc = C4_Model_add_calc(affine, "gap open",
211         aas->gap_open,
212         gap_open_calc_func, gap_open_calc_macro,
213         NULL, NULL, NULL, NULL, C4_Protect_NONE);
214     gap_extend_calc = C4_Model_add_calc(affine, "gap extend",
215         aas->gap_extend,
216         gap_extend_calc_func, gap_extend_calc_macro,
217         NULL, NULL, NULL, NULL, C4_Protect_NONE);
218 /**/
219     /* Transitions from match */
220     C4_Model_add_transition(affine, "match to insert",
221                        match_transition->input, insert_state,
222                        match_transition->advance_query, 0,
223                        gap_open_calc, C4_Label_GAP, NULL);
224     C4_Model_add_transition(affine, "match to delete",
225                        match_transition->input, delete_state,
226                        0, match_transition->advance_target,
227                        gap_open_calc, C4_Label_GAP, NULL);
228     /* Transitions from insert */
229     C4_Model_add_transition(affine, "insert",
230                     insert_state, insert_state,
231                     match_transition->advance_query, 0,
232                     gap_extend_calc, C4_Label_GAP, NULL);
233     C4_Model_add_transition(affine, "insert to match",
234                     insert_state, match_transition->output, 0, 0,
235                     NULL, C4_Label_NONE, NULL);
236     /* Transitions from delete */
237     C4_Model_add_transition(affine, "delete",
238                     delete_state, delete_state,
239                     0, match_transition->advance_target,
240                     gap_extend_calc, C4_Label_GAP, NULL);
241     C4_Model_add_transition(affine, "delete to match",
242                     delete_state, match_transition->output, 0, 0,
243                     NULL, C4_Label_NONE, NULL);
244 /**/
245     C4_Model_add_portal(affine, "match portal",
246                         match_transition->calc,
247                         match_transition->advance_query,
248                         match_transition->advance_target);
249 /**/
250     C4_Model_append_codegen(affine,
251       "#include \"affine.h\"\n",
252       "register Affine_Data *ad = (Affine_Data*)user_data;\n", NULL);
253     C4_Model_close(affine);
254     return affine;
255     }
256 
257