/* * File: oligo.c * Version: * * Author: Simon Dear * MRC Laboratory of Molecular Biology * Hills Road * Cambridge CB2 2QH * United Kingdom * * Description: oligo selection module * * Created: 1991 * Updated: 6 November 1992 * * 6 November 1992 * Changes for distribution */ #include <stdio.h> #include <stdlib.h> /* getenv & malloc */ #include <string.h> #include <X11/StringDefs.h> #include <X11/Intrinsic.h> #include <X11/Shell.h> #include <X11/Xaw/Form.h> #include <X11/Xaw/Label.h> #include <X11/Xaw/Box.h> #include <X11/Xaw/Toggle.h> #include <X11/Xaw/Text.h> #include <X11/Xaw/Command.h> #include <X11/Xaw/MenuButton.h> #include <X11/Xaw/SimpleMenu.h> #include <X11/Xaw/SmeBSB.h> #include "edUtils.h" #include "myparams.h" #include "defn.h" #include "struct.h" #include "tagUtils.h" #include "oligo.h" #include "misc.h" #include "oligocom.h" /* * Compilation modes: * * NEMATODE - Make some features switchable by the environment variable SUBCLONES * VERBOSENESS - Allow for varying degress of verbose output, including debugging information */ #define NEMATODE #define VERBOSENESS /* nematode - the drink when you're not having a drink */ int nematode; #include "subclone.h" /* * Useful #defines */ #define FORWARDS True #define BACKWARDS False extern void messagef(char *format, ...); /* * Widgets and things */ static EdStruct *thisxx; /* the current EdStruct */ static int up = 0; static Widget oldFogieWid; static Widget oligoWid = NULL; static Widget form; static Widget label; static Widget bbox, strand; static int strand_state = FORWARDS; static Widget cbox, change; static Widget dbox, find, next; static Widget template; static Widget ebox, ok, quit; /* * Current state of selection */ static int p; /* cursor position for selection */ static int l,r; /* position of left and right ends of selection region */ static int num_oligos; /* number of oligo selected last time */ static int curr_oligo; /* number of current oligo being considered */ static Boolean oligo_sense; /* status of sense buttons when find-oligo button pressed */ static int template_index; /* gel number of current selected template */ static char template_name[DB_NAMELEN+1]; /* gel name of current selected template */ static char *consensus = NULL; /* consensus for region used to select oligo*/ /* * Parameters for template selection */ #ifdef VERBOSENESS static int verbose = 1; /* verbose output is required */ char verbosity[10]; /* space for string form of verbose */ #define verbose_debug (verbose==2 || verbose==3) #define verbose_panic (verbose==3) #endif /*VERBOSENESS*/ static int fwd_width = 40; /* how far ahead search window should stretch */ static int bkwd_width = 40; /* how far back search window should stretch */ static int def_insert_size = 1000; /* How far from start of template oligo can be */ static char filter[100] = "\\.[sSfFrR]1[^a-z]"; /* filter out templates from gel names */ static char clonelib[100]; /* library of subclone information: initialised in initialise()*/ static int ave_read_len = 400; /* average read length */ /* * A few necessary forward declarations */ static int findOligos(EdStruct *xx, int sense); static void nextOligo(EdStruct *xx, int oligo, int sense); static int create_new_oligo_tag(EdStruct *xx, int oligo, int pos, int len, int sense); static void destroy_oligo_popup(); static void destroy_temporary_tag(EdStruct *xx); static void display_template_details(); /*********************************************************************************/ /* * Start of code proper */ /* * Callback routines */ static void set_strand_state(Widget w, int strand_state) { Arg args[2]; Cardinal nargs; nargs = 0; XtSetArg(args[nargs], XtNlabel, (strand_state==FORWARDS)?"------>":"<------"); nargs++; XtSetValues(w,args,nargs); } static void strandCallback(Widget w, XtPointer client_data, XtPointer call_data) /* * Change strand */ { strand_state = (strand_state == FORWARDS)?BACKWARDS:FORWARDS; set_strand_state(w,strand_state); XtCallCallbacks(find, XtNcallback, (XtPointer) NULL); } /* * Move data[] outside scope of following function - non ANSI to perform * aggregate definitions inside a function */ Field_entry data_1[] = { {"Search window bases ahead", (char *)&fwd_width, t_int, sizeof(fwd_width)}, {"Search window bases back", (char *)&bkwd_width, t_int, sizeof(bkwd_width)}, {"Default insert size", (char *)&def_insert_size, t_int, sizeof(def_insert_size)}, {"Average read length", (char *)&ave_read_len, t_int, sizeof(ave_read_len)}, {"Filter to select templates", (char *)filter, t_char, sizeof(filter)}, {"Cosmid subclone library", (char *)clonelib, t_char, sizeof(clonelib)}, #ifdef VERBOSENESS {"Verbose output?", (char *)verbosity, t_char, sizeof(verbosity)} #endif /*VERBOSENESS*/ }; static void changeMineCallback(Widget w, XtPointer client_data, XtPointer call_data) /* * Change oligo selection parameters */ { #ifdef VERBOSENESS if (verbose_debug) message("Change my parameters\n"); /* Verbose output can be "yes", "no", "debug", or "panic"!!!! */ switch (verbose) { case 0: strcpy(verbosity,"No"); break; case 1: strcpy(verbosity,"Yes"); break; case 2: strcpy(verbosity,"Debug"); break; case 3: strcpy(verbosity,"Panic"); break; } #endif /*VERBOSENESS*/ change_params((Widget)w,NULL,data_1,nematode?XtNumber(data_1):4); #ifdef VERBOSENESS switch ( verbosity[0] ) { case 'p': case 'P': verbose = 3; break; case 'd': case 'D': verbose = 2; break; case 'y': case 'Y': verbose = 1; break; default: verbose = 0; break; } #endif /*VERBOSENESS*/ XtCallCallbacks(find, XtNcallback, (XtPointer) NULL); } static void changeParamsCallback(Widget w, XtPointer client_data, XtPointer call_data) /* * Change oligo selection parameters */ { #ifdef VERBOSENESS if (verbose_debug) message("Change selection parameters\n"); #endif /*VERBOSENESS*/ osp_change_parameters(w,&prm,0/*params*/); XtCallCallbacks(find, XtNcallback, (XtPointer) NULL); } static void changeWeightsCallback(Widget w, XtPointer client_data, XtPointer call_data) /* * Change oligo selection parameters */ { #ifdef VERBOSENESS if (verbose_debug) message("Change selection weights\n"); #endif /*VERBOSENESS*/ osp_change_parameters(w,&prm,1/*weights*/); XtCallCallbacks(find, XtNcallback, (XtPointer) NULL); } static void informationCallback(Widget w, XtPointer client_data, XtPointer call_data) /* * Change oligo selection parameters */ { #ifdef VERBOSENESS if (verbose_debug) message("Display information\n"); #endif /*VERBOSENESS*/ messagef("%s\n",score_info); } static void findCallback(Widget w, XtPointer client_data, XtPointer call_data) /* * Search for oligo */ { #ifdef VERBOSENESS if (verbose_debug) message("Find oligos\n"); #endif /*VERBOSENESS*/ oligo_sense = strand_state; (void) findOligos(thisxx,oligo_sense); /* * Reveal buttons depending on result */ XawFormDoLayout(form,False); if (num_oligos>0) { XtManageChild(ok); XtManageChild(template); } else { XtUnmanageChild(ok); XtUnmanageChild(template); } if (num_oligos > 1) XtManageChild(next); else XtUnmanageChild(next); XawFormDoLayout(form,True); curr_oligo = 0; if (num_oligos>0) nextOligo(thisxx,curr_oligo,oligo_sense); else destroy_temporary_tag(thisxx); } static void nextCallback(Widget w, XtPointer client_data, XtPointer call_data) /* * Search for oligo */ { #ifdef VERBOSENESS if (verbose_debug) message("Select next oligo\n"); #endif /*VERBOSENESS*/ curr_oligo++; if (curr_oligo+1 == num_oligos) { XawFormDoLayout(form,False); XtUnmanageChild(next); XawFormDoLayout(form,True); } nextOligo(thisxx,curr_oligo,oligo_sense); } static void okCallback(Widget w, XtPointer client_data, XtPointer call_data) /* * Select current oligo, * Create a tag for it and everything else... */ { int i = curr_oligo; /* * To create a new oligo a valid template must have been specified */ if (!template_index) { message("A valid template has not been specified\n"); return; } if (oligo_sense == BACKWARDS) { (void) create_new_oligo_tag(thisxx,i, r-OSP_RESULTS[i].end_position, OSP_RESULTS[i].end_position-OSP_RESULTS[i].start_position+1, oligo_sense); } else { (void) create_new_oligo_tag(thisxx,i, l+OSP_RESULTS[i].start_position, OSP_RESULTS[i].end_position-OSP_RESULTS[i].start_position+1, oligo_sense); } up = 0; destroy_oligo_popup(); } static void quitCallback(Widget w, XtPointer client_data, XtPointer call_data) /* * Leave without selecting an oligo */ { up = 0; destroy_oligo_popup(); } /*****************************************************************************************/ static void initialise() /* * Initialise miscellaneous variables */ { char *subclones; /* clonelib = subclones:$SUBCLONES */ if (is_file("subclones")) strcpy(clonelib,"subclones"); else { subclones = (char *) getenv("SUBCLONES"); if (subclones == NULL) clonelib[0] = '\0'; else if (is_file(subclones)) strcpy(clonelib,subclones); else clonelib[0] = '\0'; } #ifdef NEMATODE nematode=(getenv("SUBCLONES")!=NULL); #else /*NEMATODE*/ nematode=1; #endif /*NEMATODE*/ } static void destroy_temporary_tag(EdStruct *xx) /* * Flag temporary tag as deleted */ { if (DBgetTags(xx,0) != NULL) { _delete_tag(xx, 0/*consensus*/, DBgetTags(xx,0)); } } static void create_temporary_tag(EdStruct *xx,int pos, int len) /* * Create a temporary tag in the consensus to show position of oligo under consideration */ { char *defComment = "*** Temporary Annotation ***\n"; tagStruct *tempTag; tempTag = DBgetTags(xx,0); /* * Create a new tag and insert it with comment into bimbo falix */ if (tempTag == NULL) { tempTag = newTag(); strncpy(tempTag->tagrec.type.c,"OLIG",4); tempTag->newcomment = (char *)malloc(strlen(defComment)+1); strcpy(tempTag->newcomment,defComment); tempTag->flags = TAG_INSERTED | TAG_LENGTH_CHANGED | TAG_POSITION_CHANGED | TAG_TYPE_CHANGED | TAG_COMMENT_IN_MEMORY; insertTag(xx,0/*consensus*/,tempTag); } tempTag->tagrec.position = pos; tempTag->tagrec.length = len; /* * Jiggle about if tag is off screen */ if (xx->displayPos > pos || xx->displayPos + xx->displayWidth < pos + len ) xx->displayPos = (pos+pos+len-xx->displayWidth)/2; redisplaySequences (xx, xx->namesWid, xx->sequencesWid, xx->displayPos, xx->displayWidth); } static int gel_ok(EdStruct *xx, int pos, int len, int seq) /* * If gel overlaps region in contig, * return true */ { return (pos >= DBgetRelPos(xx,seq) && pos+len <= DBgetRelPos(xx,seq)+DBgetLength(xx,seq)); } static int find_gel_for_oligo(EdStruct *xx, int pos, int len, int sense, int trySeq) /* * Find a gel number for this oligo. Try * (A) gel trySeq first, (if valid) * (B) then any in the correct sense, * (C) otherwise any at all?? * The position here is a position in the contig */ { int i; #ifdef VERBOSENESS if (verbose_debug) messagef("Trying to find gel for oligo: pos=%d, len=%d, sense=%d\n",pos,len,sense); #endif /*VERBOSENESS*/ /**A**/ if (trySeq > 0) { #ifdef VERBOSENESS if (verbose_debug) messagef("find_gel_for_oligo: Trying gel %s (%d)...\n",DBgetName(xx,trySeq),trySeq); #endif /*VERBOSENESS*/ if ( gel_ok(xx,pos,len,trySeq) ) { #ifdef VERBOSENESS if (verbose_debug) messagef("Using gel %s (%d)...\n",DBgetName(xx,trySeq),trySeq); #endif /*VERBOSENESS*/ return trySeq; } } /**B**/ #ifdef VERBOSENESS if (verbose_debug) message("find_gel_for_oligo: Trying gels in correct sense\n"); #endif /*VERBOSENESS*/ for (i=1; i<=xx->DB_gelCount ; i++) { if (DBgetComp(xx,i) == COMPLEMENTED && sense == BACKWARDS || DBgetComp(xx,i) == UNCOMPLEMENTED && sense == FORWARDS) { if (gel_ok(xx,pos,len,i)) { #ifdef VERBOSENESS if (verbose_debug) messagef("Using gel %s (%d)...\n",DBgetName(xx,trySeq),trySeq); #endif /*VERBOSENESS*/ return i; } } } /**C**/ #ifdef VERBOSENESS if (verbose_debug) message("find_gel_for_oligo: Trying any gel\n"); #endif /*VERBOSENESS*/ for (i=1; i<=xx->DB_gelCount ; i++) { if (gel_ok(xx,pos,len,i)) { #ifdef VERBOSENESS if (verbose_debug) messagef("Using gel %s (%d)...\n",DBgetName(xx,trySeq),trySeq); #endif /*VERBOSENESS*/ return i; } } #ifdef VERBOSENESS if (verbose_debug) message("find_gel_for_oligo: Failed to find any suitable gel\n"); #endif /*VERBOSENESS*/ return 0; } static char *generate_oligo_comment(int oligo) { char s[200]; char seq[100]; char *c; int pos,len; #ifdef VERBOSENESS if (verbose_debug) message("creating comment for oligo:\n"); #endif /*VERBOSENESS*/ pos = OSP_RESULTS[oligo].start_position; len = OSP_RESULTS[oligo].end_position - pos + 1; strncpy(seq,&consensus[pos],len); seq[len]='\0'; sprintf(s,"serial#=\ntemplate=%s\nsequence=%s\nflags=\n",template_name,seq); #ifdef VERBOSENESS if (verbose_debug) messagef("(%s)\n",s); #endif /*VERBOSENESS*/ c = TAG_MALLOC(strlen(s)+1); strcpy(c,s); return c; } static int create_new_oligo_tag(EdStruct *xx, int oligo, int pos, int len, int sense) /* * This routine creates a new oligo tag, prior to leaving the * oligo selection window */ { tagStruct *new_oligo; int seq; seq = find_gel_for_oligo(xx,pos,len,sense,template_index); if (! seq) { messagef("NO SUITABLE GEL FOR THIS OLIGO TAG POSITION %d LENGTH %d\n",pos,len); return 1; } /* * Create a new tag and insert it with comment into bimbo falix */ new_oligo = newTag(); strncpy(new_oligo->tagrec.type.c,"OLIG",4); new_oligo->tagrec.position = normalisePos(xx,seq,pos-DBgetRelPos(xx,seq)+1,len); new_oligo->tagrec.length = len; new_oligo->flags = TAG_INSERTED | TAG_LENGTH_CHANGED | TAG_POSITION_CHANGED | TAG_TYPE_CHANGED; insertTag(xx,seq,new_oligo); new_oligo->flags |= TAG_COMMENT_IN_MEMORY; new_oligo->newcomment = generate_oligo_comment(oligo); /*set modified tag flag */ DBsetFlags(xx,seq,DBgetFlags(xx,seq)|DB_FLAG_TAG_MODIFIED); return 0; } int oligo_comp_pos(const void *pa, const void *pb) /* * we need to sort the oligos according to how far they are from the * cursor position (p) */ { const OSP_Results *a = (OSP_Results *)pa; const OSP_Results *b = (OSP_Results *)pb; #define absval(A) ( ( (A)<0 ) ? (-(A)) : (A) ) return absval((a->start_position+a->end_position)/2 - p) > absval((b->start_position+b->end_position)/2 - p); } static int findOligos(EdStruct *xx, int sense) /* * Find suitable oligos using OSP with current parameter settings. * Return ok status */ { int seq = xx->cursorSeq; int pos = xx->cursorPos; int position; /* in contig */ int contigLength; /* length of contig */ int consensusLength; int ok; /* return status from osp_analyse */ int i; #ifdef VERBOSENESS if (verbose_debug) message("Finding oligos...\n"); #endif /*VERBOSENESS*/ position = positionInContig(xx,seq,pos); contigLength = DBgetLength(xx,0/*consensus*/); /* * Conceptually we select off consensus. * Determine consensus around point... * the oligo will be selected from this region */ if (sense == FORWARDS) { l = (position > bkwd_width) ? position - bkwd_width : 1; r = (position + fwd_width < contigLength) ? position + fwd_width : contigLength; } else { l = (position > fwd_width) ? position - fwd_width : 1; r = (position + bkwd_width < contigLength) ? position + bkwd_width : contigLength; } p = bkwd_width; /* save position of cursor in consensus fragment */ consensusLength = (r-l)+1; /* allocate space for consensus */ if (consensus != NULL) free(consensus); consensus = (char *) malloc ( consensusLength ); DBcalcConsensus (xx,l, consensusLength, consensus, BOTH_STRANDS); if (sense == BACKWARDS) { /* we need to complement the consensus */ /* * Use Rodger's routines in subs89.f */ sqcom_(consensus, &consensusLength, consensusLength); sqrev_(consensus, &consensusLength, consensusLength); } #ifdef VERBOSENESS if (verbose_debug) messagef("Cursor position = %d\n",pos); if (verbose_debug) messagef("Seqence = %s (%d)\n",DBgetName(xx,seq),seq); if (verbose_debug) messagef("Consensus for region %d-%d = (%s)\n",l,r,consensus); if (verbose_debug) messagef("Sense = %s\n", (sense==FORWARDS)?"forward":"reverse"); #endif /*VERBOSENESS*/ /* * A cludge to get around bug in osp_analyse */ for (i=0;i<MAX_NUM_OLIGOS; i++) OSP_RESULTS[i].score = 0.0; ok=osp_analyse(OSP_RESULTS,consensus,&prm,screens,score_info); #ifdef VERBOSENESS if (verbose) messagef("osp_analyse returned with status %d\n", ok); #endif /*VERBOSENESS*/ /* * Determine number of suitable oligos */ if (ok) for (num_oligos=0; OSP_RESULTS[num_oligos].score>0.0; num_oligos++); else num_oligos=0; #ifdef VERBOSENESS if (verbose) messagef("%d suitable oligos found\n",num_oligos); #endif /*VERBOSENESS*/ /* sort? */ if (num_oligos>1) { /* yes - sort by position relative to cursor */ qsort(OSP_RESULTS,num_oligos,sizeof(OSP_Results),oligo_comp_pos); } return (ok); } static int check_sense(EdStruct *xx, int i/*template number*/, int sense) /* * templates that are in the wrong sense should fail * returns 0 - ok, 1 - wrong sense */ { return (DBgetComp(xx,i) == COMPLEMENTED && sense == FORWARDS || DBgetComp(xx,i) == UNCOMPLEMENTED && sense == BACKWARDS); } static int check_5prime(EdStruct *xx, int i/*template number*/, int sense, int pos, int len) /* * templates that have their 5' end after the oligo position are not usable */ { int relpos = DBgetRelPos(xx,i); int length = DBgetLength(xx,i); if (sense == FORWARDS) return (relpos > pos); else return (relpos+length < pos + len); } static int check_template_suitability(EdStruct *xx, int i, int sense, int pos, int len) /* * */ { int relpos = DBgetRelPos(xx,i); int length = DBgetLength(xx,i); int near_dist; CloneInfo info; char mtdname[4]; /* * Get mtd name from gel reading name */ strncpy(mtdname, DBgetGelName(xx,i), 3); mtdname[3] = '\0'; /* * Get size information from subclones file */ if (read_subclone_info(clonelib,mtdname,&info)) near_dist = def_insert_size; else near_dist = info.range_from; /* reject ones that are not near the required interval */ if (sense == FORWARDS) return (pos - relpos > (near_dist-ave_read_len)); else return (relpos+length-pos-len > (near_dist-ave_read_len)); } static int check_template_for_oligo(EdStruct *xx,int pos, int len, int sense, int i/*template no*/) /* * The template number here is actually the number of an existing gel for * that template * * The template: * 1. must be in the appropriate sense. * 2. must exists in our template library. * 3. must be found "near" the interval required. * 4. need not have a sequenced gel over the interval required, * but must be past the 5' end. */ { #define reject_wrong_sense 1 #define reject_mapped_after 2 #define reject_not_close 3 #define reject_not_in_library 4 /* reject ones that have a sense reverse to the one required */ if (check_sense(xx,i,sense)) { #ifdef VERBOSENESS if (verbose_panic) messagef(" %s rejected because it is in the wrong sense\n",DBgetName(xx,i)); #endif /*VERBOSENESS*/ return reject_wrong_sense; } /* reject ones with 5' end after our oligo position */ if (check_5prime(xx,i,sense,pos,len)){ #ifdef VERBOSENESS if (verbose_panic) messagef(" %s rejected because template starts after oligo primer\n",DBgetName(xx,i)); #endif /*VERBOSENESS*/ return reject_mapped_after; } /* * Check suitability of template according to position */ if (check_template_suitability(xx,i,sense,pos,len)){ #ifdef VERBOSENESS if (verbose_panic) messagef(" %s rejected because template isn't near oligo primer position\n",DBgetName(xx,i)); #endif /*VERBOSENESS*/ return reject_not_close; } /* * check that template exists in our template library */ if (0 /* ?? */) { #ifdef VERBOSENESS if (verbose_panic) messagef(" %s rejected because template not in template library\n",DBgetName(xx,i)); #endif /*VERBOSENESS*/ return reject_not_in_library; } #ifdef VERBOSENESS if (verbose_debug) messagef(" %s selected\n",DBgetName(xx,i)); #endif /*VERBOSENESS*/ return 0; } static int filter_template(char *template_name) /* * We are interested in templates rather than simply template gel sequences * Reject all but *.s1 *.f1 on this basis * We are lucky in that we have a rigid nomenclature for templates * Other people will do things differently. */ { char *error_message; error_message = (char *) re_comp(filter); if ( error_message != NULL ) { messagef(" Error using re_comp: %s\n",error_message); return 0; } return (re_exec(template_name) == 1); } static int *find_templates_for_oligo (EdStruct *xx, int pos, int len, int sense) /* * Once an oligo has been found for the consensus at position pos, length len, * search for a suitable template within the contig. * * Use existing gel readings as a basis to find a suitable template. * As there can be several readings from one template, filter out only the * initial reads for consideration */ { static int *templateList = NULL; int i; int count; if (templateList == NULL) templateList = (int *) malloc ( xx->DB_gelCount * sizeof(int)); #ifdef VERBOSENESS if (verbose_debug) message("Finding template for oligo:\n"); if (verbose_debug) messagef("position = %d, length = %d, forward sense=%d\n",pos,len,sense); #endif /*VERBOSENESS*/ count = 0; if (sense==BACKWARDS) { for(i=1;i<=xx->DB_gelCount;i++) { char *name; name = DBgetGelName(xx,i); /* only nematode extensions */ if (nematode && ! filter_template(name)) { #ifdef VERBOSENESS if (verbose_debug) messagef(" %s rejected because template doesn't match filter\n",DBgetName(xx,i)); #endif /*VERBOSENESS*/ continue; } if (! check_template_for_oligo(xx,pos,len,sense,i)) templateList[count++] = i; } } else { int ind; ind=posToIndex(xx,pos); /* optimise a bit */ if(!ind) ind=xx->DB_gelCount; for(;ind>0;ind--) { char *name; i = xx->DBorder[ind]; name = DBgetGelName(xx,i); if (nematode && ! filter_template(name)) { #ifdef VERBOSENESS if (verbose_debug) messagef(" %s rejected because template doesn't match filter\n",DBgetName(xx,i)); #endif /*VERBOSENESS*/ continue; } if (! check_template_for_oligo(xx,pos,len,sense,i)) templateList[count++] = i; } } templateList[count] = 0; return templateList; } #ifdef OBSELETE static void trim_suffix(char * name) /* * Remove tail from first dot onwards */ { char *suffix; /* truncate at suffix */ suffix = strchr(name,'.'); if (suffix != NULL) *suffix = '\0'; } #endif /*OBSELETE*/ static void get_template_name(char *name, EdStruct *xx, int i) /* * Get the template name for gel number 'i' */ { (void) strcpy(name, DBgetGelName(xx,i) ); #ifdef OBSELETE trim_suffix(name); #endif /*OBSELETE*/ } #ifdef OBSELETE static int score_reading_quality(EdStruct *xx, int seq) /* * Returns a score for the quality of the read, higher the better. * Ideally it would look at the traces, but for now * will assume length of read is a good meter for this */ { return DBgetLength(xx,seq); } #endif /*OBSELETE*/ static int score_template(EdStruct *xx, int seq) /* * Score this template */ { #ifdef OBSELETE return score_reading_quality(xx,seq); #else /*OBSELETE*/ return 1; /* this should force the first one to be chosen */ #endif /*OBSELETE*/ } static void set_default_template(EdStruct *xx, int *templateList) /* * Pick a default template from the list of available templates */ { template_index = 0; template_name[0] = '\0'; if (templateList[0]) { int i; int score, high_score; high_score = 0; /* search */ for (i=0; templateList[i]; i++) { score = score_template(xx, templateList[i]); if (high_score < score) { high_score = score; template_index = templateList[i]; } } /* set template name */ get_template_name(template_name, xx, template_index); } } #ifdef OBSELETE static int strcmp_ignorecase(char *a, char *b) { for ( ; tolower(*a) == tolower(*b); a++, b++) if (*a == '\0') return 0; return tolower(*a) - tolower(*b); } #endif static int strncmp_ignorecase(char *a, char *b, int n) { for ( ; n && tolower(*a) == tolower(*b); a++, b++, n--) if (*a == '\0') return 0; if (!n) return 0; else return tolower(*a) - tolower(*b); } static void check_template_name(EdStruct *xx, char *template_name, int pos, int len, int sense) /* * Check the template name is valid * + that it exists * + that is in the correct sense etc etc * If it's not valid, set template_index to be 0 */ { int i; int found_index; int template_len; int found; char this[DB_NAMELEN]; strcpy(this,template_name); #ifdef OBSELETE trim_suffix(this); #endif /*OBSELETE*/ /* * Check template_name exists */ found = 0; template_len= strlen(template_name); for (i=1; i<=xx->DB_gelCount ; i++) { char *name; name = DBgetGelName(xx,i); if (nematode && ! filter_template(name)) continue; if (strncmp_ignorecase(template_name, DBgetGelName(xx,i), template_len) == 0) { found++; found_index = i; #ifdef VERBOSENESS if (verbose_debug) messagef("%s matches %s\n",template_name,DBgetName(xx,i)); #endif /*VERBOSENESS*/ } } template_index = 0; if (! found) messagef("template %s not found\n", template_name); else { if (found > 1) { #ifdef VERBOSENESS if (verbose_debug) messagef("template %s found, but is not unique\n", template_name); #endif /*VERBOSENESS*/ } else { if (check_sense(xx, found_index, sense)) { messagef("template %s in the wrong sense\n", template_name); return; } if (check_5prime(xx,found_index,sense,pos,len)) { messagef("template %s starts after oligo position\n", template_name); return; } template_index = found_index; } } } /* * Move data[] outside scope of following function - non ANSI to perform * aggregate definitions inside a function */ Field_entry data_2[] = { {"Template", (char *)template_name, t_char, sizeof(template_name)}, }; static void menuSelectCallback(Widget w, XtPointer p_i, XtPointer junk) /* * A template has been selected off the menu * Deal with it */ { int i = (int) p_i; /* * i is either -1 (other) or the gel number corresponding to a template */ if (i<0) { #ifdef VERBOSENESS if (verbose_debug) message("Menu: Other selected\n"); #endif /*VERBOSENESS*/ template_name[0]='\0'; change_params((Widget)oligoWid,"Please specify...",data_2, XtNumber(data_2)); template_index = 0; if (oligo_sense == BACKWARDS) { check_template_name(thisxx, template_name, r-OSP_RESULTS[curr_oligo].end_position, OSP_RESULTS[curr_oligo].end_position-OSP_RESULTS[curr_oligo].start_position+1, oligo_sense); } else { check_template_name(thisxx, template_name, l+OSP_RESULTS[curr_oligo].start_position, OSP_RESULTS[curr_oligo].end_position-OSP_RESULTS[curr_oligo].start_position+1, oligo_sense); } } else { template_index = i; get_template_name(template_name,thisxx,i); #ifdef VERBOSENESS if (verbose_debug) messagef("Menu: %s selected\n", template_name); #endif /*VERBOSENESS*/ } display_template_details(); } static void create_template_menu(EdStruct *xx, int *list) /* * Create new list of available templates */ { static Widget menuWid = NULL; int i; Widget entryWid; Arg args[2]; Cardinal nargs; if (menuWid != NULL) XtDestroyWidget(menuWid); /* * Create the menu parent widget */ menuWid = XtCreatePopupShell("templateMenu", simpleMenuWidgetClass, template, NULL, 0); /* Put the individual items in. When selected, each entry will generate a callback with its associated number. */ for (i = 0; list[i]; i++) { char name[DB_NAMELEN]; #ifdef VERBOSENESS if (verbose_debug) messagef("Creating menu for %s\n",DBgetName(xx,list[i])); #endif /*VERBOSENESS*/ /* * Prepare clone name */ get_template_name(name, xx, list[i]); nargs = 0; XtSetArg(args[nargs], XtNlabel, name); nargs++; entryWid = XtCreateManagedWidget("entry", smeBSBObjectClass, menuWid, args, nargs); XtAddCallback(entryWid, XtNcallback, menuSelectCallback, (XtPointer) list[i]); } nargs = 0; XtSetArg(args[nargs], XtNlabel, "Other"); nargs++; entryWid = XtCreateManagedWidget("entry", smeBSBObjectClass, menuWid, args, nargs); XtAddCallback(entryWid, XtNcallback, menuSelectCallback, (XtPointer) -1); } static void display_template_details() /* * Display importand template details */ { if (template_index > 0) { messagef("Template: %s\n", template_name); } else { message("Template: none chosen\n"); } } static void display_oligo_details(EdStruct *xx, int sense, int oligo) /* * Display important oligo details * a. sequence * b. position, length * c. osp score, gc, tm */ { char seq[100]; int pos,len; int i; char *a; int consensus_start, consensus_end; pos = OSP_RESULTS[oligo].start_position; len = OSP_RESULTS[oligo].end_position - pos + 1; /* * Get consensus sequence with context */ a = seq; for (i=3;i;i--) *a++ = '.'; for (i=(pos>2)?2:pos;i;i--) *a++ = tolower(consensus[pos-i]); strncpy(a,&consensus[pos],len); a+=len; for (i=0;i<2&&consensus[pos+len+i];i++) *a++ = tolower(consensus[pos+len+i]); for (i=3;i;i--) *a++ = '.'; *a++ = '\0'; /* * Positions in contig */ if (sense == BACKWARDS) { consensus_start = r-OSP_RESULTS[oligo].end_position; consensus_end = consensus_start + len - 1; } else { consensus_start = l+OSP_RESULTS[oligo].start_position; consensus_end = consensus_start + len - 1; } messagef("Oligo: %s\n",seq); messagef("\ Primer # %2d PRIMER-SELF PRIMER-OTHER\n\ 5' end 3' end length Score G+C(%%) Tm 3' Internal 3' Internal\n\ %6d %6d %4d %4.1f %4.1f %4.1f %4.1f %4.1f %4.1f %4.1f\n", oligo+1, consensus_start, consensus_end, len, OSP_RESULTS[oligo].score, OSP_RESULTS[oligo].gc * 100.0, OSP_RESULTS[oligo].tm, OSP_RESULTS[oligo].psI_score, OSP_RESULTS[oligo].ps3_score, OSP_RESULTS[oligo].poI_score, OSP_RESULTS[oligo].po3_score); } static void nextOligo(EdStruct *xx, int oligo, int sense) /* * We cycle through the oligo list * curr-oligo gives the current oligo entry under consideration */ { /* * Hilight position of next oligo in contig editor temporarily */ int *templateList; int i = oligo; /* * Print out information on oligos */ #ifdef VERBOSENESS if (verbose_debug) messagef("************** %d ************\n",i); if (verbose_debug) messagef("stp %d, endp %d, score %f, gc %f, tm %f, psI %f ps3 %f poI %f po3 %f\n", OSP_RESULTS[i].start_position, OSP_RESULTS[i].end_position, OSP_RESULTS[i].score, OSP_RESULTS[i].gc, OSP_RESULTS[i].tm, OSP_RESULTS[i].psI_score, OSP_RESULTS[i].ps3_score, OSP_RESULTS[i].poI_score, OSP_RESULTS[i].po3_score); #endif /*VERBOSENESS*/ display_oligo_details(xx,sense,i); if (sense == BACKWARDS) { /* * Convert position returned from oligo selection to * position in contig */ templateList = find_templates_for_oligo(xx, r-OSP_RESULTS[i].end_position, OSP_RESULTS[i].end_position-OSP_RESULTS[i].start_position+1, sense); create_temporary_tag(xx, r-OSP_RESULTS[i].end_position, OSP_RESULTS[i].end_position-OSP_RESULTS[i].start_position+1); } else { /* * Convert position returned from oligo selection to * position in contig */ templateList = find_templates_for_oligo(xx, l+OSP_RESULTS[i].start_position, OSP_RESULTS[i].end_position-OSP_RESULTS[i].start_position+1, sense); create_temporary_tag(xx, l+OSP_RESULTS[i].start_position, OSP_RESULTS[i].end_position-OSP_RESULTS[i].start_position+1); } set_default_template(xx,templateList); create_template_menu(xx, templateList); display_template_details(); } /*****************************************************************************************/ /* * External routines */ void createOligoWidget(Widget parentWid) /* * Prtend to create it now */ { oldFogieWid = parentWid; } static void create_oligo_wid(Widget parentWid) /* * Create the window for oligo selection * This routine should be called just once, in the initialisation phase of xdap */ { Cardinal nargs; Arg args[10]; Position x, y; /* top-left hand corner of new widget */ Dimension height; /* height of parent widget */ /* * Determine the position on the screen for this widget */ #define fromVertWid (thisxx->edWid) nargs = 0; XtSetArg(args[nargs], XtNheight, &height); nargs++; XtGetValues(fromVertWid, args, nargs); XtTranslateCoords(fromVertWid, (Position) 0, (Position) height, &x, &y); /* * Create popup shell */ nargs = 0; XtSetArg(args[nargs], XtNx, x); nargs++; XtSetArg(args[nargs], XtNy, y); nargs++; oligoWid = XtCreatePopupShell("oligo", transientShellWidgetClass, parentWid, args, nargs); /* * Create main form */ nargs = 0; form = XtCreateManagedWidget("form", formWidgetClass, oligoWid, args, nargs); /* * Create title for form */ nargs = 0; XtSetArg(args[nargs], XtNborderWidth, 0); nargs++; XtSetArg(args[nargs], XtNlabel, "Select Oligos and Templates"); nargs++; label = XtCreateManagedWidget("label", labelWidgetClass, form, args, nargs); #define XtOrientHorizontal "horizontal" /* * Create buttons for oligo sense */ nargs = 0; XtSetArg(args[nargs], XtNfromVert, label); nargs++; XtSetArg(args[nargs], XtNborderWidth, 0); nargs++; XtSetArg(args[nargs], XtNorientation, XtOrientHorizontal); nargs++; bbox = XtCreateManagedWidget("bbox", boxWidgetClass, form, args, nargs); nargs = 0; XtSetArg(args[nargs], XtNborderWidth, 0); nargs++; XtSetArg(args[nargs], XtNlabel, "Direction:"); nargs++; (void) XtCreateManagedWidget("label", labelWidgetClass, bbox, args, nargs); nargs = 0; strand = XtCreateManagedWidget("strand", commandWidgetClass,bbox,args,nargs); XtAddCallback(strand, XtNcallback, strandCallback, (XtPointer) NULL); set_strand_state(strand,strand_state); /* * Create Change Parameter Buttons */ nargs = 0; XtSetArg(args[nargs], XtNfromVert, bbox); nargs++; XtSetArg(args[nargs], XtNborderWidth, 0); nargs++; XtSetArg(args[nargs], XtNorientation, XtOrientHorizontal); nargs++; cbox = XtCreateManagedWidget("cbox", boxWidgetClass, form, args, nargs); nargs = 0; XtSetArg(args[nargs], XtNlabel, "Parameters"); nargs++; change = XtCreateManagedWidget("change", commandWidgetClass, cbox, args, nargs); XtAddCallback(change, XtNcallback, changeMineCallback, (XtPointer) NULL); nargs = 0; XtSetArg(args[nargs], XtNlabel, "Oligo Selection Parameters"); nargs++; change = XtCreateManagedWidget("change", commandWidgetClass, cbox, args, nargs); XtAddCallback(change, XtNcallback, changeParamsCallback, (XtPointer) NULL); nargs = 0; XtSetArg(args[nargs], XtNlabel, "Oligo Selection Weights"); nargs++; change = XtCreateManagedWidget("change", commandWidgetClass, cbox, args, nargs); XtAddCallback(change, XtNcallback, changeWeightsCallback, (XtPointer) NULL); nargs = 0; XtSetArg(args[nargs], XtNlabel, "Display Selection Information"); nargs++; change = XtCreateManagedWidget("information", commandWidgetClass, cbox, args, nargs); XtAddCallback(change, XtNcallback, informationCallback, (XtPointer) NULL); /* * Create action button */ nargs = 0; XtSetArg(args[nargs], XtNfromVert, cbox); nargs++; XtSetArg(args[nargs], XtNborderWidth, 0); nargs++; XtSetArg(args[nargs], XtNorientation, XtOrientHorizontal); nargs++; XtSetArg(args[nargs], XtNresizable, True); nargs++; dbox = XtCreateManagedWidget("dbox", boxWidgetClass, form, args, nargs); nargs = 0; XtSetArg(args[nargs], XtNlabel, "Find Oligos"); nargs++; find = XtCreateManagedWidget("find", commandWidgetClass, dbox, args, nargs); XtAddCallback(find, XtNcallback, findCallback, (XtPointer) NULL); nargs = 0; XtSetArg(args[nargs], XtNlabel, "Select Next"); nargs++; next = XtCreateManagedWidget("next", commandWidgetClass, dbox, args, nargs); XtAddCallback(next, XtNcallback, nextCallback, (XtPointer) NULL); nargs = 0; XtSetArg(args[nargs], XtNlabel, "Choose Template for this Oligo"); nargs++; XtSetArg(args[nargs], XtNmenuName, "templateMenu"); nargs++; template = XtCreateManagedWidget("template", menuButtonWidgetClass, dbox, args, nargs); /* * Exit action */ nargs = 0; XtSetArg(args[nargs], XtNfromVert, dbox); nargs++; XtSetArg(args[nargs], XtNborderWidth, 0); nargs++; XtSetArg(args[nargs], XtNorientation, XtOrientHorizontal); nargs++; XtSetArg(args[nargs], XtNresizable, True); nargs++; ebox = XtCreateManagedWidget("ebox", boxWidgetClass, form, args, nargs); nargs = 0; XtSetArg(args[nargs], XtNlabel, "Create Tag for this Oligo"); nargs++; ok = XtCreateManagedWidget("ok", commandWidgetClass, ebox, args, nargs); XtAddCallback(ok, XtNcallback, okCallback, (XtPointer) NULL); nargs = 0; XtSetArg(args[nargs], XtNlabel, "Quit"); nargs++; quit = XtCreateManagedWidget("quit", commandWidgetClass, ebox, args, nargs); XtAddCallback(quit, XtNcallback, quitCallback, (XtPointer) NULL); } int invokeOligo(EdStruct *xx) /* * Pop up the oligo selection window */ { if (up) return 0; thisxx = xx; if (oligoWid == NULL) { initialise(); osp_initialise(); create_oligo_wid(oldFogieWid); } XtUnmanageChild(ok); XtUnmanageChild(next); XtUnmanageChild(template); XtPopup(oligoWid, XtGrabNone); up = 1; /* find oligos */ XtCallCallbacks(find, XtNcallback, (XtPointer) NULL); return 0; } int destroyOligo() /* * Shut this baby down */ { if (up) XtCallCallbacks(quit, XtNcallback, (XtPointer) NULL); return 0; } static void destroy_oligo_popup() /* * Popdown the oligo popup window, * free a few variables * then relax */ { EdStruct *xx = thisxx; XtPopdown(oligoWid); destroy_temporary_tag(xx); free (consensus); consensus = NULL; redisplaySequences (xx, xx->namesWid, xx->sequencesWid, xx->displayPos, xx->displayWidth); }