| 1 | // =============================================================== // |
|---|
| 2 | // // |
|---|
| 3 | // File : primer_design.cxx // |
|---|
| 4 | // Purpose : // |
|---|
| 5 | // // |
|---|
| 6 | // Coded by Wolfram Foerster in February 2001 // |
|---|
| 7 | // Institute of Microbiology (Technical University Munich) // |
|---|
| 8 | // http://www.arb-home.de/ // |
|---|
| 9 | // // |
|---|
| 10 | // =============================================================== // |
|---|
| 11 | |
|---|
| 12 | #include "primer_design.hxx" |
|---|
| 13 | #include "PRD_Design.hxx" |
|---|
| 14 | #include "PRD_SequenceIterator.hxx" |
|---|
| 15 | |
|---|
| 16 | #include <GEN.hxx> |
|---|
| 17 | |
|---|
| 18 | #include <awt_sel_boxes.hxx> |
|---|
| 19 | #include <awt_config_manager.hxx> |
|---|
| 20 | |
|---|
| 21 | #include <aw_awars.hxx> |
|---|
| 22 | #include <aw_msg.hxx> |
|---|
| 23 | #include <arb_progress.h> |
|---|
| 24 | #include <aw_root.hxx> |
|---|
| 25 | #include <aw_question.hxx> |
|---|
| 26 | #include <aw_select.hxx> |
|---|
| 27 | |
|---|
| 28 | #include <arbdbt.h> |
|---|
| 29 | #include <adGene.h> |
|---|
| 30 | |
|---|
| 31 | #include <string> |
|---|
| 32 | #include <cmath> |
|---|
| 33 | |
|---|
| 34 | using std::string; |
|---|
| 35 | |
|---|
| 36 | static AW_window_simple *pdrw = NULp; |
|---|
| 37 | static AW_selection_list *resultList = NULp; |
|---|
| 38 | |
|---|
| 39 | static double get_estimated_memory(AW_root *root) { |
|---|
| 40 | int bases = root->awar(AWAR_PRIMER_DESIGN_LEFT_LENGTH)->read_int() + root->awar(AWAR_PRIMER_DESIGN_RIGHT_LENGTH)->read_int(); |
|---|
| 41 | int length = root->awar(AWAR_PRIMER_DESIGN_LENGTH_MAX)->read_int(); |
|---|
| 42 | double mem = bases*length*0.9*(sizeof(Node)+16); |
|---|
| 43 | return mem; |
|---|
| 44 | } |
|---|
| 45 | |
|---|
| 46 | static void primer_design_event_update_memory(AW_root *root) { |
|---|
| 47 | double mem = get_estimated_memory(root); |
|---|
| 48 | const char *display = NULp; |
|---|
| 49 | |
|---|
| 50 | if (mem > 1073741824) { |
|---|
| 51 | mem = mem / 1073741824; |
|---|
| 52 | display = GBS_global_string("%.1f TB", mem); |
|---|
| 53 | } |
|---|
| 54 | else if (mem > 1048576) { |
|---|
| 55 | mem = mem / 1048576; |
|---|
| 56 | display = GBS_global_string("%.1f MB", mem); |
|---|
| 57 | } |
|---|
| 58 | else if (mem > 1024) { |
|---|
| 59 | mem = mem / 1024; |
|---|
| 60 | display = GBS_global_string("%.1f KB", mem); |
|---|
| 61 | } |
|---|
| 62 | else { |
|---|
| 63 | display = GBS_global_string("%.0f bytes", mem); |
|---|
| 64 | } |
|---|
| 65 | root->awar(AWAR_PRIMER_DESIGN_APROX_MEM)->write_string(display); |
|---|
| 66 | } |
|---|
| 67 | |
|---|
| 68 | static void primer_design_event_check_primer_length(AW_root *root, bool max_changed) { |
|---|
| 69 | static bool avoid_recursion = false; |
|---|
| 70 | |
|---|
| 71 | if (!avoid_recursion) { |
|---|
| 72 | avoid_recursion = true; |
|---|
| 73 | |
|---|
| 74 | int min_length = root->awar(AWAR_PRIMER_DESIGN_LENGTH_MIN)->read_int(); |
|---|
| 75 | int max_length = root->awar(AWAR_PRIMER_DESIGN_LENGTH_MAX)->read_int(); |
|---|
| 76 | |
|---|
| 77 | if (max_length<1) max_length = 1; |
|---|
| 78 | if (min_length<1) min_length = 1; |
|---|
| 79 | |
|---|
| 80 | if (min_length > max_length) { |
|---|
| 81 | if (max_changed) min_length = max_length; |
|---|
| 82 | else max_length = min_length; |
|---|
| 83 | } |
|---|
| 84 | |
|---|
| 85 | prd_assert(min_length>0); |
|---|
| 86 | |
|---|
| 87 | root->awar(AWAR_PRIMER_DESIGN_LENGTH_MIN)->write_int(min_length); |
|---|
| 88 | root->awar(AWAR_PRIMER_DESIGN_LENGTH_MAX)->write_int(max_length); |
|---|
| 89 | |
|---|
| 90 | avoid_recursion = false; |
|---|
| 91 | } |
|---|
| 92 | } |
|---|
| 93 | |
|---|
| 94 | void create_primer_design_variables(AW_root *aw_root, AW_default aw_def, AW_default global) { |
|---|
| 95 | aw_root->awar_int(AWAR_PRIMER_DESIGN_LEFT_POS, 0, aw_def); |
|---|
| 96 | aw_root->awar_int(AWAR_PRIMER_DESIGN_LEFT_LENGTH, 100, aw_def)->add_callback(primer_design_event_update_memory); |
|---|
| 97 | aw_root->awar_int(AWAR_PRIMER_DESIGN_RIGHT_POS, 1000, aw_def); |
|---|
| 98 | aw_root->awar_int(AWAR_PRIMER_DESIGN_RIGHT_LENGTH, 100, aw_def)->add_callback(primer_design_event_update_memory); |
|---|
| 99 | aw_root->awar_int(AWAR_PRIMER_DESIGN_LENGTH_MIN, 10, aw_def)->add_callback(makeRootCallback(primer_design_event_check_primer_length, false)); |
|---|
| 100 | aw_root->awar_int(AWAR_PRIMER_DESIGN_LENGTH_MAX, 20, aw_def)->add_callback(makeRootCallback(primer_design_event_check_primer_length, true)); |
|---|
| 101 | aw_root->awar_int(AWAR_PRIMER_DESIGN_DIST_MIN, 1050, aw_def); |
|---|
| 102 | aw_root->awar_int(AWAR_PRIMER_DESIGN_DIST_MAX, 1200, aw_def); |
|---|
| 103 | aw_root->awar_int(AWAR_PRIMER_DESIGN_GCRATIO_MIN, 10, aw_def); |
|---|
| 104 | aw_root->awar_int(AWAR_PRIMER_DESIGN_GCRATIO_MAX, 50, aw_def); |
|---|
| 105 | aw_root->awar_int(AWAR_PRIMER_DESIGN_TEMPERATURE_MIN, 30, aw_def); |
|---|
| 106 | aw_root->awar_int(AWAR_PRIMER_DESIGN_TEMPERATURE_MAX, 80, aw_def); |
|---|
| 107 | aw_root->awar_int(AWAR_PRIMER_DESIGN_ALLOWED_MATCH_MIN_DIST, 0, aw_def); |
|---|
| 108 | aw_root->awar_int(AWAR_PRIMER_DESIGN_EXPAND_IUPAC, 1, aw_def); |
|---|
| 109 | aw_root->awar_int(AWAR_PRIMER_DESIGN_MAX_PAIRS, 25, aw_def); |
|---|
| 110 | aw_root->awar_int(AWAR_PRIMER_DESIGN_GC_FACTOR, 50, aw_def); |
|---|
| 111 | aw_root->awar_int(AWAR_PRIMER_DESIGN_TEMP_FACTOR, 50, aw_def); |
|---|
| 112 | |
|---|
| 113 | aw_root->awar_string(AWAR_PRIMER_DESIGN_APROX_MEM, "", aw_def); |
|---|
| 114 | aw_root->awar_string(AWAR_PRIMER_TARGET_STRING, NULp, global); |
|---|
| 115 | |
|---|
| 116 | primer_design_event_update_memory(aw_root); |
|---|
| 117 | } |
|---|
| 118 | |
|---|
| 119 | static void create_primer_design_result_window(AW_window *aww) { |
|---|
| 120 | if (!pdrw) { |
|---|
| 121 | pdrw = new AW_window_simple; |
|---|
| 122 | pdrw->init(aww->get_root(), "PRD_RESULT", "Primer Design RESULT"); |
|---|
| 123 | pdrw->load_xfig("pd_reslt.fig"); |
|---|
| 124 | |
|---|
| 125 | pdrw->button_length(6); |
|---|
| 126 | pdrw->auto_space(10, 10); |
|---|
| 127 | |
|---|
| 128 | pdrw->at("help"); |
|---|
| 129 | pdrw->callback(makeHelpCallback("primer_result.hlp")); |
|---|
| 130 | pdrw->create_button("HELP", "HELP", "H"); |
|---|
| 131 | |
|---|
| 132 | pdrw->at("result"); |
|---|
| 133 | resultList = pdrw->create_selection_list(AWAR_PRIMER_TARGET_STRING, 40, 5); |
|---|
| 134 | |
|---|
| 135 | const StorableSelectionList *storable_primer_list = new StorableSelectionList(TypedSelectionList("prim", resultList, "primers", "primer")); // never freed |
|---|
| 136 | |
|---|
| 137 | pdrw->at("buttons"); |
|---|
| 138 | |
|---|
| 139 | pdrw->callback(AW_POPDOWN); |
|---|
| 140 | pdrw->create_button("CLOSE", "CLOSE", "C"); |
|---|
| 141 | |
|---|
| 142 | pdrw->callback(makeWindowCallback(awt_clear_selection_list_cb, resultList)); |
|---|
| 143 | pdrw->create_button("CLEAR", "CLEAR", "R"); |
|---|
| 144 | |
|---|
| 145 | pdrw->callback(makeCreateWindowCallback(create_load_box_for_selection_lists, storable_primer_list)); |
|---|
| 146 | pdrw->create_button("LOAD", "LOAD", "L"); |
|---|
| 147 | |
|---|
| 148 | pdrw->callback(makeCreateWindowCallback(create_save_box_for_selection_lists, storable_primer_list)); |
|---|
| 149 | pdrw->create_button("SAVE", "SAVE", "S"); |
|---|
| 150 | |
|---|
| 151 | pdrw->callback(makeWindowCallback(create_print_box_for_selection_lists, &storable_primer_list->get_typedsellist())); |
|---|
| 152 | pdrw->create_button("PRINT", "PRINT", "P"); |
|---|
| 153 | } |
|---|
| 154 | |
|---|
| 155 | pdrw->show(); |
|---|
| 156 | } |
|---|
| 157 | |
|---|
| 158 | static void primer_design_event_go(AW_window *aww, GBDATA *gb_main) { |
|---|
| 159 | AW_root *root = aww->get_root(); |
|---|
| 160 | GB_ERROR error = NULp; |
|---|
| 161 | char *sequence = NULp; |
|---|
| 162 | long int length = 0; |
|---|
| 163 | |
|---|
| 164 | if ((get_estimated_memory(root)/1024.0) > GB_get_usable_memory()) { |
|---|
| 165 | if (aw_question(NULp, "ARB may crash due to memory problems.", "Continue, Abort") == 1) { |
|---|
| 166 | return; |
|---|
| 167 | } |
|---|
| 168 | } |
|---|
| 169 | |
|---|
| 170 | { |
|---|
| 171 | GB_transaction ta(gb_main); |
|---|
| 172 | char *selected_species = root->awar(AWAR_SPECIES_NAME)->read_string(); |
|---|
| 173 | GBDATA *gb_species = GBT_find_species(gb_main, selected_species); |
|---|
| 174 | |
|---|
| 175 | if (!gb_species) { |
|---|
| 176 | error = "you have to select a species!"; |
|---|
| 177 | } |
|---|
| 178 | else { |
|---|
| 179 | char *alignment = GBT_get_default_alignment(gb_main); |
|---|
| 180 | if (!alignment) { |
|---|
| 181 | error = GB_await_error(); |
|---|
| 182 | } |
|---|
| 183 | else { |
|---|
| 184 | GBDATA *gb_seq = GBT_find_sequence(gb_species, alignment); |
|---|
| 185 | if (!gb_seq) { |
|---|
| 186 | error = GBS_global_string("Selected species has no sequence data in alignment '%s'", alignment); |
|---|
| 187 | } |
|---|
| 188 | else { |
|---|
| 189 | sequence = GB_read_string(gb_seq); |
|---|
| 190 | length = GB_read_count(gb_seq); |
|---|
| 191 | } |
|---|
| 192 | free(alignment); |
|---|
| 193 | } |
|---|
| 194 | } |
|---|
| 195 | } |
|---|
| 196 | |
|---|
| 197 | if (!error) { |
|---|
| 198 | arb_progress progress("Searching PCR primer pairs"); |
|---|
| 199 | PrimerDesign *PD = |
|---|
| 200 | new PrimerDesign(sequence, length, |
|---|
| 201 | Range(root->awar(AWAR_PRIMER_DESIGN_LEFT_POS)->read_int(), root->awar(AWAR_PRIMER_DESIGN_LEFT_LENGTH)->read_int()), |
|---|
| 202 | Range(root->awar(AWAR_PRIMER_DESIGN_RIGHT_POS)->read_int(), root->awar(AWAR_PRIMER_DESIGN_RIGHT_LENGTH)->read_int()), |
|---|
| 203 | Range(root->awar(AWAR_PRIMER_DESIGN_LENGTH_MIN)->read_int(), root->awar(AWAR_PRIMER_DESIGN_LENGTH_MAX)->read_int()), |
|---|
| 204 | Range(root->awar(AWAR_PRIMER_DESIGN_DIST_MIN)->read_int(), root->awar(AWAR_PRIMER_DESIGN_DIST_MAX)->read_int()), |
|---|
| 205 | Range(root->awar(AWAR_PRIMER_DESIGN_GCRATIO_MIN)->read_int(), root->awar(AWAR_PRIMER_DESIGN_GCRATIO_MAX)->read_int()), |
|---|
| 206 | Range(root->awar(AWAR_PRIMER_DESIGN_TEMPERATURE_MIN)->read_int(), root->awar(AWAR_PRIMER_DESIGN_TEMPERATURE_MAX)->read_int()), |
|---|
| 207 | root->awar(AWAR_PRIMER_DESIGN_ALLOWED_MATCH_MIN_DIST)->read_int(), |
|---|
| 208 | (bool)root->awar(AWAR_PRIMER_DESIGN_EXPAND_IUPAC)->read_int(), |
|---|
| 209 | root->awar(AWAR_PRIMER_DESIGN_MAX_PAIRS)->read_int(), |
|---|
| 210 | (float)root->awar(AWAR_PRIMER_DESIGN_GC_FACTOR)->read_int()/100, |
|---|
| 211 | (float)root->awar(AWAR_PRIMER_DESIGN_TEMP_FACTOR)->read_int()/100 |
|---|
| 212 | ); |
|---|
| 213 | |
|---|
| 214 | try { |
|---|
| 215 | PD->run(); |
|---|
| 216 | } |
|---|
| 217 | |
|---|
| 218 | catch (string& s) { |
|---|
| 219 | error = GBS_static_string(s.c_str()); |
|---|
| 220 | } |
|---|
| 221 | catch (...) { |
|---|
| 222 | error = "Unknown error (maybe out of memory ? )"; |
|---|
| 223 | } |
|---|
| 224 | if (!error) error = PD->get_error(); |
|---|
| 225 | |
|---|
| 226 | if (!error) { |
|---|
| 227 | if (!resultList) create_primer_design_result_window(aww); |
|---|
| 228 | prd_assert(resultList); |
|---|
| 229 | |
|---|
| 230 | // create result-list: |
|---|
| 231 | resultList->clear(); |
|---|
| 232 | int max_primer_length = PD->get_max_primer_length(); |
|---|
| 233 | int max_position_length = int(std::log10(double (PD->get_max_primer_pos())))+1; |
|---|
| 234 | int max_length_length = int(std::log10(double(PD->get_max_primer_length())))+1; |
|---|
| 235 | |
|---|
| 236 | if (max_position_length < 3) max_position_length = 3; |
|---|
| 237 | if (max_length_length < 3) max_length_length = 3; |
|---|
| 238 | |
|---|
| 239 | resultList->insert(GBS_global_string(" Rating | %-*s %-*s %-*s G/C Tmp | %-*s %-*s %-*s G/C Tmp", |
|---|
| 240 | max_primer_length, "Left primer", |
|---|
| 241 | max_position_length, "Pos", |
|---|
| 242 | max_length_length, "Len", |
|---|
| 243 | max_primer_length, "Right primer", |
|---|
| 244 | max_position_length, "Pos", |
|---|
| 245 | max_length_length, "Len"), |
|---|
| 246 | ""); |
|---|
| 247 | |
|---|
| 248 | int r; |
|---|
| 249 | |
|---|
| 250 | for (r = 0; ; ++r) { |
|---|
| 251 | const char *primers = NULp; |
|---|
| 252 | const char *result = PD->get_result(r, primers, max_primer_length, max_position_length, max_length_length); |
|---|
| 253 | if (!result) break; |
|---|
| 254 | resultList->insert(result, primers); |
|---|
| 255 | } |
|---|
| 256 | |
|---|
| 257 | resultList->insert_default(r ? "**** End of list" : "**** There are no results", ""); |
|---|
| 258 | resultList->update(); |
|---|
| 259 | |
|---|
| 260 | pdrw->show(); |
|---|
| 261 | } |
|---|
| 262 | } |
|---|
| 263 | if (sequence) free(sequence); |
|---|
| 264 | if (error) aw_message(error); |
|---|
| 265 | } |
|---|
| 266 | |
|---|
| 267 | |
|---|
| 268 | static void primer_design_event_check_temp_factor(AW_window *aww) { |
|---|
| 269 | AW_root *root = aww->get_root(); |
|---|
| 270 | |
|---|
| 271 | int temp = root->awar(AWAR_PRIMER_DESIGN_TEMP_FACTOR)->read_int(); |
|---|
| 272 | if (temp > 100) temp = 100; |
|---|
| 273 | if (temp < 0) temp = 0; |
|---|
| 274 | root->awar(AWAR_PRIMER_DESIGN_TEMP_FACTOR)->write_int(temp); |
|---|
| 275 | root->awar(AWAR_PRIMER_DESIGN_GC_FACTOR)->write_int(100-temp); |
|---|
| 276 | } |
|---|
| 277 | |
|---|
| 278 | static void primer_design_event_check_gc_factor(AW_window *aww) { |
|---|
| 279 | AW_root *root = aww->get_root(); |
|---|
| 280 | |
|---|
| 281 | int gc = root->awar(AWAR_PRIMER_DESIGN_GC_FACTOR)->read_int(); |
|---|
| 282 | if (gc > 100) gc = 100; |
|---|
| 283 | if (gc < 0) gc = 0; |
|---|
| 284 | root->awar(AWAR_PRIMER_DESIGN_GC_FACTOR)->write_int(gc); |
|---|
| 285 | root->awar(AWAR_PRIMER_DESIGN_TEMP_FACTOR)->write_int(100-gc); |
|---|
| 286 | } |
|---|
| 287 | |
|---|
| 288 | static void primer_design_event_init(AW_window *aww, GBDATA *gb_main, bool from_gene) { |
|---|
| 289 | GB_transaction ta(gb_main); |
|---|
| 290 | |
|---|
| 291 | AW_root *root = aww->get_root(); |
|---|
| 292 | GB_ERROR error = NULp; |
|---|
| 293 | char *selected_species = NULp; |
|---|
| 294 | char *selected_gene = NULp; |
|---|
| 295 | GBDATA *gb_species = NULp; |
|---|
| 296 | GBDATA *gb_gene = NULp; |
|---|
| 297 | GEN_position *genPos = NULp; |
|---|
| 298 | GBDATA *gb_seq = NULp; |
|---|
| 299 | bool is_genom_db = GEN_is_genome_db(gb_main, -1); |
|---|
| 300 | |
|---|
| 301 | if (is_genom_db && from_gene) { |
|---|
| 302 | selected_species = root->awar(AWAR_ORGANISM_NAME)->read_string(); |
|---|
| 303 | selected_gene = root->awar(AWAR_GENE_NAME)->read_string(); |
|---|
| 304 | |
|---|
| 305 | root->awar(AWAR_SPECIES_NAME)->write_string(selected_species); |
|---|
| 306 | } |
|---|
| 307 | else { |
|---|
| 308 | selected_species = root->awar(AWAR_SPECIES_NAME)->read_string(); |
|---|
| 309 | } |
|---|
| 310 | |
|---|
| 311 | gb_species = GBT_find_species(gb_main, selected_species); |
|---|
| 312 | |
|---|
| 313 | if (!gb_species) { |
|---|
| 314 | error = "You have to select a species!"; |
|---|
| 315 | } |
|---|
| 316 | else { |
|---|
| 317 | char *alignment = GBT_get_default_alignment(gb_main); |
|---|
| 318 | if (!alignment) { |
|---|
| 319 | error = GB_await_error(); |
|---|
| 320 | } |
|---|
| 321 | else { |
|---|
| 322 | gb_seq = GBT_find_sequence(gb_species, alignment); |
|---|
| 323 | if (!gb_seq) { |
|---|
| 324 | error = GB_export_errorf("Species '%s' has no data in alignment '%s'", selected_species, alignment); |
|---|
| 325 | } |
|---|
| 326 | free(alignment); |
|---|
| 327 | } |
|---|
| 328 | } |
|---|
| 329 | |
|---|
| 330 | if (!error && from_gene) { |
|---|
| 331 | prd_assert(is_genom_db); // otherwise button should not exist |
|---|
| 332 | |
|---|
| 333 | gb_gene = GEN_find_gene(gb_species, selected_gene); |
|---|
| 334 | if (!gb_gene) { |
|---|
| 335 | error = GB_export_errorf("Species '%s' has no gene named '%s'", selected_species, selected_gene); |
|---|
| 336 | } |
|---|
| 337 | else { |
|---|
| 338 | genPos = GEN_read_position(gb_gene); |
|---|
| 339 | if (!genPos) { |
|---|
| 340 | error = GB_await_error(); |
|---|
| 341 | } |
|---|
| 342 | else if (!genPos->joinable) { |
|---|
| 343 | error = GBS_global_string("Gene '%s' is not joinable", selected_gene); |
|---|
| 344 | } |
|---|
| 345 | } |
|---|
| 346 | } |
|---|
| 347 | |
|---|
| 348 | if (!error && gb_seq) { |
|---|
| 349 | SequenceIterator *i = NULp; |
|---|
| 350 | PRD_Sequence_Pos length = 0; |
|---|
| 351 | PRD_Sequence_Pos add_offset = 0; // offset to add to positions (used for genes) |
|---|
| 352 | char *sequence = NULp; |
|---|
| 353 | |
|---|
| 354 | if (gb_gene) { |
|---|
| 355 | size_t gene_length; |
|---|
| 356 | sequence = GBT_read_gene_sequence_and_length(gb_gene, false, 0, &gene_length); |
|---|
| 357 | if (!sequence) { |
|---|
| 358 | error = GB_await_error(); |
|---|
| 359 | } |
|---|
| 360 | else { |
|---|
| 361 | length = gene_length; |
|---|
| 362 | add_offset = genPos->start_pos[0]; |
|---|
| 363 | // @@@ does this work with split genes? warn about uncertainties? |
|---|
| 364 | } |
|---|
| 365 | } |
|---|
| 366 | else { |
|---|
| 367 | sequence = GB_read_string(gb_seq); |
|---|
| 368 | length = strlen(sequence); |
|---|
| 369 | } |
|---|
| 370 | |
|---|
| 371 | if (!error) { |
|---|
| 372 | long int dist_min; |
|---|
| 373 | long int dist_max; |
|---|
| 374 | |
|---|
| 375 | // find reasonable parameters |
|---|
| 376 | // left pos (first base from start) |
|---|
| 377 | |
|---|
| 378 | long int left_len = root->awar(AWAR_PRIMER_DESIGN_LEFT_LENGTH)->read_int(); |
|---|
| 379 | if (left_len == 0 || left_len<0) left_len = 100; |
|---|
| 380 | |
|---|
| 381 | i = new SequenceIterator(sequence, 0, SequenceIterator::IGNORE, left_len, SequenceIterator::FORWARD); |
|---|
| 382 | |
|---|
| 383 | i->nextBase(); // find first base from start |
|---|
| 384 | PRD_Sequence_Pos left_min = i->pos; // store pos. of first base |
|---|
| 385 | while (i->nextBase() != SequenceIterator::EOS) ; // step to 'left_len'th base from start |
|---|
| 386 | PRD_Sequence_Pos left_max = i->pos; // store pos. of 'left_len'th base |
|---|
| 387 | |
|---|
| 388 | root->awar(AWAR_PRIMER_DESIGN_LEFT_POS)->write_int(left_min+add_offset); |
|---|
| 389 | root->awar(AWAR_PRIMER_DESIGN_LEFT_LENGTH)->write_int(left_len); |
|---|
| 390 | |
|---|
| 391 | long int right_len = root->awar(AWAR_PRIMER_DESIGN_RIGHT_LENGTH)->read_int(); |
|---|
| 392 | if (right_len == 0 || right_len<0) right_len = 100; |
|---|
| 393 | |
|---|
| 394 | // right pos ('right_len'th base from end) |
|---|
| 395 | i->restart(length, 0, right_len, SequenceIterator::BACKWARD); |
|---|
| 396 | |
|---|
| 397 | i->nextBase(); // find last base |
|---|
| 398 | PRD_Sequence_Pos right_max = i->pos; // store pos. of last base |
|---|
| 399 | while (i->nextBase() != SequenceIterator::EOS) ; // step to 'right_len'th base from end |
|---|
| 400 | PRD_Sequence_Pos right_min = i->pos; // store pos of 'right_len'th base from end |
|---|
| 401 | |
|---|
| 402 | root->awar(AWAR_PRIMER_DESIGN_RIGHT_POS)->write_int(right_min+add_offset); |
|---|
| 403 | root->awar(AWAR_PRIMER_DESIGN_RIGHT_LENGTH)->write_int(right_len); |
|---|
| 404 | |
|---|
| 405 | // primer distance |
|---|
| 406 | if (right_min >= left_max) { // non-overlapping ranges |
|---|
| 407 | i->restart(left_max, right_min, SequenceIterator::IGNORE, SequenceIterator::FORWARD); |
|---|
| 408 | long int bases_between = 0; // count bases from right_min to left_max |
|---|
| 409 | while (i->nextBase() != SequenceIterator::EOS) ++bases_between; |
|---|
| 410 | dist_min = bases_between; // take bases between as min distance |
|---|
| 411 | } |
|---|
| 412 | else { // overlapping ranges |
|---|
| 413 | dist_min = right_min - left_min + 1; |
|---|
| 414 | } |
|---|
| 415 | dist_max = right_max - left_min; |
|---|
| 416 | root->awar(AWAR_PRIMER_DESIGN_DIST_MIN)->write_int(dist_min); |
|---|
| 417 | root->awar(AWAR_PRIMER_DESIGN_DIST_MAX)->write_int(dist_max); |
|---|
| 418 | |
|---|
| 419 | #if defined(DUMP_PRIMER) |
|---|
| 420 | printf ("primer_design_event_init : left_min %7li\n", left_min); |
|---|
| 421 | printf ("primer_design_event_init : left_max %7li\n", left_max); |
|---|
| 422 | printf ("primer_design_event_init : right_min %7li\n", right_min); |
|---|
| 423 | printf ("primer_design_event_init : right_max %7li\n", right_max); |
|---|
| 424 | printf ("primer_design_event_init : dist_min %7li\n", dist_min); |
|---|
| 425 | printf ("primer_design_event_init : dist_max %7li\n\n", dist_max); |
|---|
| 426 | #endif |
|---|
| 427 | } |
|---|
| 428 | delete i; |
|---|
| 429 | free(sequence); |
|---|
| 430 | } |
|---|
| 431 | |
|---|
| 432 | if (error) { |
|---|
| 433 | aw_message(error); |
|---|
| 434 | } |
|---|
| 435 | |
|---|
| 436 | GEN_free_position(genPos); |
|---|
| 437 | free(selected_gene); |
|---|
| 438 | free(selected_species); |
|---|
| 439 | } |
|---|
| 440 | |
|---|
| 441 | static AWT_config_mapping_def primer_design_config_mapping[] = { |
|---|
| 442 | { AWAR_PRIMER_DESIGN_LEFT_POS, "lpos" }, |
|---|
| 443 | { AWAR_PRIMER_DESIGN_LEFT_LENGTH, "llen" }, |
|---|
| 444 | { AWAR_PRIMER_DESIGN_RIGHT_POS, "rpos" }, |
|---|
| 445 | { AWAR_PRIMER_DESIGN_RIGHT_LENGTH, "rlen" }, |
|---|
| 446 | { AWAR_PRIMER_DESIGN_LENGTH_MIN, "lenmin" }, |
|---|
| 447 | { AWAR_PRIMER_DESIGN_LENGTH_MAX, "lenmax" }, |
|---|
| 448 | { AWAR_PRIMER_DESIGN_DIST_MIN, "distmin" }, |
|---|
| 449 | { AWAR_PRIMER_DESIGN_DIST_MAX, "distmax" }, |
|---|
| 450 | { AWAR_PRIMER_DESIGN_GCRATIO_MIN, "gcmin" }, |
|---|
| 451 | { AWAR_PRIMER_DESIGN_GCRATIO_MAX, "gcmax" }, |
|---|
| 452 | { AWAR_PRIMER_DESIGN_TEMPERATURE_MIN, "tempmin" }, |
|---|
| 453 | { AWAR_PRIMER_DESIGN_TEMPERATURE_MAX, "tempmax" }, |
|---|
| 454 | { AWAR_PRIMER_DESIGN_ALLOWED_MATCH_MIN_DIST, "minmatchdist" }, |
|---|
| 455 | { AWAR_PRIMER_DESIGN_EXPAND_IUPAC, "iupac" }, |
|---|
| 456 | { AWAR_PRIMER_DESIGN_MAX_PAIRS, "maxpairs" }, |
|---|
| 457 | { AWAR_PRIMER_DESIGN_GC_FACTOR, "gcfactor" }, |
|---|
| 458 | { AWAR_PRIMER_DESIGN_TEMP_FACTOR, "temp_factor" }, |
|---|
| 459 | { NULp, NULp } |
|---|
| 460 | }; |
|---|
| 461 | |
|---|
| 462 | AW_window *create_primer_design_window(AW_root *root, GBDATA *gb_main) { |
|---|
| 463 | bool is_genome_db; |
|---|
| 464 | { |
|---|
| 465 | GB_transaction ta(gb_main); |
|---|
| 466 | char *selected_species = root->awar(AWAR_SPECIES_NAME)->read_string(); |
|---|
| 467 | GBDATA *gb_species = GBT_find_species(gb_main, selected_species); |
|---|
| 468 | |
|---|
| 469 | if (!gb_species) { |
|---|
| 470 | aw_message("You have to select a species!"); |
|---|
| 471 | } |
|---|
| 472 | |
|---|
| 473 | is_genome_db = GEN_is_genome_db(gb_main, -1); |
|---|
| 474 | } |
|---|
| 475 | |
|---|
| 476 | AW_window_simple *aws = new AW_window_simple; |
|---|
| 477 | aws->init(root, "PRIMER_DESIGN", "PRIMER DESIGN"); |
|---|
| 478 | |
|---|
| 479 | aws->load_xfig("prd_main.fig"); |
|---|
| 480 | |
|---|
| 481 | aws->at("close"); |
|---|
| 482 | aws->callback(AW_POPDOWN); |
|---|
| 483 | aws->create_button("CLOSE", "CLOSE", "C"); |
|---|
| 484 | |
|---|
| 485 | aws->at("help"); |
|---|
| 486 | aws->callback(makeHelpCallback("primer_new.hlp")); |
|---|
| 487 | aws->create_button("HELP", "HELP", "H"); |
|---|
| 488 | |
|---|
| 489 | aws->at("init1"); |
|---|
| 490 | aws->callback(makeWindowCallback(primer_design_event_init, gb_main, false)); |
|---|
| 491 | aws->create_button("INIT_FROM_SPECIES", "Species", "I"); |
|---|
| 492 | |
|---|
| 493 | if (is_genome_db) { |
|---|
| 494 | aws->at("init2"); |
|---|
| 495 | aws->callback(makeWindowCallback(primer_design_event_init, gb_main, true)); |
|---|
| 496 | aws->create_button("INIT_FROM_GENE", "Gene", "I"); |
|---|
| 497 | } |
|---|
| 498 | |
|---|
| 499 | aws->at("design"); |
|---|
| 500 | aws->callback(makeWindowCallback(primer_design_event_go, gb_main)); |
|---|
| 501 | aws->create_button("GO", "GO", "G"); |
|---|
| 502 | aws->highlight(); |
|---|
| 503 | |
|---|
| 504 | aws->at("minleft"); |
|---|
| 505 | aws->create_input_field(AWAR_PRIMER_DESIGN_LEFT_POS, 7); |
|---|
| 506 | |
|---|
| 507 | aws->at("maxleft"); |
|---|
| 508 | aws->create_input_field(AWAR_PRIMER_DESIGN_LEFT_LENGTH, 9); |
|---|
| 509 | |
|---|
| 510 | aws->at("minright"); |
|---|
| 511 | aws->create_input_field(AWAR_PRIMER_DESIGN_RIGHT_POS, 7); |
|---|
| 512 | |
|---|
| 513 | aws->at("maxright"); |
|---|
| 514 | aws->create_input_field(AWAR_PRIMER_DESIGN_RIGHT_LENGTH, 9); |
|---|
| 515 | |
|---|
| 516 | aws->at("minlen"); |
|---|
| 517 | aws->create_input_field(AWAR_PRIMER_DESIGN_LENGTH_MIN, 7); |
|---|
| 518 | |
|---|
| 519 | aws->at("maxlen"); |
|---|
| 520 | aws->create_input_field(AWAR_PRIMER_DESIGN_LENGTH_MAX, 7); |
|---|
| 521 | |
|---|
| 522 | aws->at("mindist"); aws->create_input_field(AWAR_PRIMER_DESIGN_DIST_MIN, 7); |
|---|
| 523 | aws->at("maxdist"); aws->create_input_field(AWAR_PRIMER_DESIGN_DIST_MAX, 7); |
|---|
| 524 | aws->at("mingc"); aws->create_input_field(AWAR_PRIMER_DESIGN_GCRATIO_MIN, 7); |
|---|
| 525 | aws->at("maxgc"); aws->create_input_field(AWAR_PRIMER_DESIGN_GCRATIO_MAX, 7); |
|---|
| 526 | aws->at("mintemp"); aws->create_input_field(AWAR_PRIMER_DESIGN_TEMPERATURE_MIN, 7); |
|---|
| 527 | aws->at("maxtemp"); aws->create_input_field(AWAR_PRIMER_DESIGN_TEMPERATURE_MAX, 7); |
|---|
| 528 | aws->at("allowed_match"); aws->create_input_field(AWAR_PRIMER_DESIGN_ALLOWED_MATCH_MIN_DIST, 7); |
|---|
| 529 | aws->at("max_pairs"); aws->create_input_field(AWAR_PRIMER_DESIGN_MAX_PAIRS, 7); |
|---|
| 530 | |
|---|
| 531 | aws->at("expand_IUPAC"); |
|---|
| 532 | aws->create_toggle(AWAR_PRIMER_DESIGN_EXPAND_IUPAC); |
|---|
| 533 | |
|---|
| 534 | aws->at("GC_factor"); |
|---|
| 535 | aws->callback(primer_design_event_check_gc_factor); // @@@ used as INPUTFIELD_CB (see #559) |
|---|
| 536 | aws->create_input_field(AWAR_PRIMER_DESIGN_GC_FACTOR, 7); |
|---|
| 537 | |
|---|
| 538 | aws->at("temp_factor"); |
|---|
| 539 | aws->callback(primer_design_event_check_temp_factor); // @@@ used as INPUTFIELD_CB (see #559) |
|---|
| 540 | aws->create_input_field(AWAR_PRIMER_DESIGN_TEMP_FACTOR, 7); |
|---|
| 541 | |
|---|
| 542 | aws->at("config"); |
|---|
| 543 | AWT_insert_config_manager(aws, AW_ROOT_DEFAULT, "pcr_primer_design", primer_design_config_mapping); |
|---|
| 544 | |
|---|
| 545 | aws->at("aprox_mem"); |
|---|
| 546 | aws->button_length(11); |
|---|
| 547 | aws->create_button(NULp, AWAR_PRIMER_DESIGN_APROX_MEM, NULp, "+"); |
|---|
| 548 | |
|---|
| 549 | return aws; |
|---|
| 550 | } |
|---|