1 /******************************************************************************
2 
3   ####   #    #  #####    ####   #    #   ####            ####
4  #    #  #    #  #    #  #    #  ##  ##  #               #    #
5  #       ######  #    #  #    #  # ## #   ####           #
6  #       #    #  #####   #    #  #    #       #   ###    #
7  #    #  #    #  #   #   #    #  #    #  #    #   ###    #    #
8   ####   #    #  #    #   ####   #    #   ####    ###     ####
9 
10 ******************************************************************************/
11 /* This file is part of MAPMAKER 3.0b, Copyright 1987-1992, Whitehead Institute
12    for Biomedical Research. All rights reserved. See READ.ME for license. */
13 
14 #define INC_LIB
15 #define INC_MISC
16 #define INC_SHELL
17 #include "mapm.h"
18 
19 SAVED_LIST *chromosome;
20 ASSIGNMENT **assignment;
21 PLACEMENT  **placement;
22 int current_chrom;
23 bool do_assignment();
24 int  get_anchors();
25 
26 
27 /* do_assignments anchor_locus framework_marker set_anchor_loci */
28 
29 /**************** Chromosomes ****************/
30 
make_new_chrom(name,num)31 bool make_new_chrom(name,num)
32 char *name;
33 int *num;
34 {
35     int n, m;
36 
37     if ((n=chromosome->num_maps)==MAX_CHROMOSOMES-1)
38       error("too many chromosomes - can't make any more");
39     if (isa_chrom(name,&m)) return(FALSE);
40 
41     strcpy(chromosome->map_list[n]->map_name,name);
42     chromosome->map_list[n]->num_loci=0;
43     chromosome->num_maps+=1;
44     *num=n;
45     return(TRUE);
46 }
47 
48 
isa_chrom(name,chrom)49 bool isa_chrom(name,chrom)
50 char *name;
51 int *chrom; /* side-effected */
52 {
53     int i;
54 
55     *chrom= NO_CHROM;
56     if (xstreq(name,"any")) { *chrom=NO_CHROM; return(TRUE); }
57     for (i=0; i<chromosome->num_maps; i++)
58       if (xstreq(name,chromosome->map_list[i]->map_name)) { *chrom=i; break; }
59     return (*chrom==NO_CHROM ? FALSE:TRUE);
60 }
61 
62 
get_chrom_frame(chrom,num_loci)63 MAP *get_chrom_frame(chrom,num_loci)
64 int chrom;
65 int *num_loci; /* side-effected,  can be 0, or 1, or greater */
66 {
67     if (num_loci!=NULL) *num_loci= chromosome->map_list[chrom]->num_loci;
68     return(chromosome->map_list[chrom]);
69 }
70 
71 
framework_marker(locus)72 bool framework_marker(locus)
73 int locus;
74 {
75     int j, k, found_in_frame;
76     MAP *frame;
77 
78     /* force_haplo_sanity(&locus,FALSE); */
79     if (!assigned(locus)) return(FALSE);
80 
81     frame=chromosome->map_list[assignment_chrom(locus)];
82     for (j=0; j<frame->num_loci; j++) {
83 	if (locus==frame->locus[j]) return(TRUE);
84 	/* if (!check_haplos) continue;
85 	   for (k=haplo_first[frame->locus[j]]; k!=NO_LOCUS; k=haplo_next[k])
86 	   if (locus==k) return(TRUE); */
87     }
88     return(FALSE);
89 }
90 
91 
92 #define FRAME_OTHER_CHROM \
93   "bad framework for %s - %s is assigned to %s"
94 #define FRAME_NO_CHROM \
95   "bad framework - %s is not assigned to a chromosome"
96 #define FRAME_DUPS \
97   "bad framework - one or more loci are repeated in sequence"
98 
set_chrom_frame(chrom,new)99 void set_chrom_frame(chrom,new)
100 int chrom;
101 MAP *new;   /* warning: side-effected! */
102 /* When this is called, new MUST be equal to get_map_to_bash(chromosome), amd
103    assigned_to(*,chrom) must have be true for all loci in new map. We also
104    assume haplo_sanity is true for old framework, and force it for new one. */
105 {
106     int i, j, found, other;
107     MAP *old;
108 
109     old=get_chrom_frame(chrom,NULL);
110 
111     /* check for problems: markers on other chroms, haplo_sanity, duplicates */
112     for (j=0; j<new->num_loci; j++) {
113 	/* force_haplo_sanity(new->locus+j,TRUE); */
114 	if (!assigned(new->locus[j])) {
115 	    sf(ps,FRAME_NO_CHROM,loc2str(new->locus[j])); error(ps);
116 	} else if ((other=assignment_chrom(new->locus[j]))!=chrom) {
117 	    sf(ps,FRAME_OTHER_CHROM,chrom2str(chrom),loc2str(new->locus[j]),
118 	       chrom2str(other)); error(ps);
119 	}
120     }
121 
122     /* unplace markers which WERE on the framework */
123     for (i=0; i<old->num_loci; i++) {
124 	found=FALSE;
125 	for (j=0; j<new->num_loci; j++)
126 	  if (old->locus[i]==new->locus[j]) { found=TRUE; break; }
127 	if (!found) unplace_this(old->locus[i],NO_CHROM,M_UNKNOWN,FALSE);
128     }
129 
130     /* unplace ALL markers which were placed relative to the old framework */
131     for (j=0; j<raw.num_markers; j++)
132       if (assigned_to(j,chrom) && placed_locus(j))
133 	unplace_this(j,NO_CHROM,M_UNKNOWN,FALSE);
134 
135     /* quasi-place new markers in the new framework on this chrom */
136     for (i=0; i<new->num_loci; i++) {
137 	found=FALSE;
138 	for (j=0; j<old->num_loci; j++)
139 	  if (old->locus[i]==new->locus[j]) { found=TRUE; break; }
140 	if (!found) unplace_this(new->locus[i],chrom,M_FRAMEWORK,FALSE);
141     }
142 
143     /* save the framework */
144     strcpy(new->map_name,chromosome->map_list[chrom]->map_name);
145     overwrite_map_num(chromosome,&new,chrom);
146     chromosome->map_list[chrom]->modified= TRUE;
147 }
148 
149 
get_chrom_loci(chrom,locus,which_loci,num_loci,num_framework)150 void get_chrom_loci(chrom,locus,which_loci,num_loci,num_framework)
151 int chrom, *locus, which_loci, *num_loci, *num_framework;
152 {
153     int i, j, k, n, primary;
154     bool framework=FALSE, non_frame=FALSE, haplos_anyway=FALSE;
155 
156     if (which_loci>=HAPLOS)    { haplos_anyway=TRUE; which_loci-=HAPLOS; }
157     if (which_loci>=NON_FRAME) { non_frame=TRUE; which_loci-=NON_FRAME;  }
158     if (which_loci>=FRAMEWORK) { framework=TRUE; which_loci-=FRAMEWORK;  }
159 
160     n=0;
161     if (framework)
162       for (j=0; j<chromosome->map_list[chrom]->num_loci; j++) {
163 	  i=chromosome->map_list[chrom]->locus[j];
164 	  if (use_haplotypes && haplos_anyway && haplotyped(i)) {
165 	      for (k=haplo_first[j]; k!=NO_LOCUS; k=haplo_next[k])
166 		locus[n++]=k;
167 	  } else { /* ignore haplos, and assume chrom frame is sane */
168 	      locus[n++]= i;
169 	  }
170       }
171     if (num_framework!=NULL) *num_framework=n;
172 
173     if (non_frame)
174       for (i=0; i<raw.num_markers; i++) {
175 	  if (use_haplotypes && !haplos_anyway && haplotyped(i) &&
176 	      haplo_first[i]!=i) continue; /* then skip non-primaries */
177 	  else if (use_haplotypes && haplotyped(i)) primary=haplo_first[i];
178 	  else primary=i;
179 	  if (assigned_to(primary,chrom) && !framework_marker(primary))
180 	    locus[n++]=i;
181       }
182     if (num_loci!=NULL) *num_loci=n; /* the total! */
183 }
184 
185 
count_chrom_loci(chrom,n_anchor,n_frame,n_total,n_placed,n_unique,n_region,haplos_too,temp)186 void count_chrom_loci(chrom,n_anchor,n_frame,n_total,n_placed,n_unique,
187 		      n_region,haplos_too,temp)
188 int chrom;
189 int *n_anchor, *n_frame, *n_total, *n_placed, *n_unique, *n_region;
190 bool haplos_too;
191 int *temp; /* at most raw.num_markers long, alloced outside */
192 {
193     int which, i, locus, primary;
194     int frame, total, anchor, placed, unique, region;
195 
196     if (use_haplotypes && haplos_too) which=ALL_LOCI+HAPLOS;
197       else which=ALL_LOCI;
198     get_chrom_loci(chrom,temp,which,&total,&frame);
199 
200     anchor=placed=unique=region=0;
201     for (i=frame; i<total; i++) { /* Loop over non-frame markers */
202 	locus=temp[i];
203 	/* if !haplos_too then only primaries will be in the list */
204 	if (use_haplotypes && haplotyped(locus)) primary=haplo_first[locus];
205 	  else primary=locus;
206 	if (anchor_locus(primary)) anchor++;
207 	if (placed_locus(primary)) {
208 	    placed++;
209 	    if (placement_state(primary)==M_UNIQUE) unique++;
210 	      else if (placement_state(primary)==M_REGION) region++;
211 	}
212     }
213     if (n_anchor!=NULL) *n_anchor=anchor;
214     if (n_frame!=NULL)  *n_frame= frame;
215     if (n_total!=NULL)  *n_total= total;
216     if (n_placed!=NULL) *n_placed=placed;
217     if (n_unique!=NULL) *n_unique=unique;
218     if (n_region!=NULL) *n_region=region;
219 }
220 
221 
222 /**************** Assignments ****************/
223 
assigned(locus)224 bool assigned(locus)
225 int locus;
226 { force_haplo_sanity(&locus,FALSE); return(assignment[locus]->status>0); }
227 
assignment_state(locus)228 int assignment_state(locus)
229 int locus;
230 { force_haplo_sanity(&locus,FALSE); return(assignment[locus]->status); }
231 
assignment_chrom(locus)232 int assignment_chrom(locus)
233 int locus;
234 {
235   force_haplo_sanity(&locus,FALSE);
236   return(assignment[locus]->status>0 ? assignment[locus]->chromosome:NO_CHROM);
237 }
238 
assigned_to(locus,chrom)239 bool assigned_to(locus,chrom)
240 int locus, chrom;
241 {
242   force_haplo_sanity(&locus,FALSE);
243   return(assignment[locus]->status>0 && assignment[locus]->chromosome==chrom);
244 }
245 
anchor_locus(locus)246 bool anchor_locus(locus)
247 int locus;
248 { return(assignment_state(locus)==A_ANCHOR); } /* does force_haplo_sanity */
249 
250 
251 #define ASS_ANCHOR  "%s- anchor locus on %s...cannot re-assign\n"
252 #define ASS_REFRAME "%s- framework marker on %s...cannot re-assign to %s\n"
253 #define ASS_UNFRAME "%s- framework marker on %s...cannot un-assign\n"
254 #define ASS_ISFRAME "%s- framework marker on %s...remains attached\n"
255 #define ASS_INSANE  \
256   "%s- not the name of its haplotype-group, can't assign or unassign\n"
257 
is_assignable(locus,chrom,fix_frames)258 bool is_assignable(locus,chrom,fix_frames)
259 int locus, chrom; /* maybe NO_CHROM */
260 bool fix_frames;
261 {
262     int old;
263 
264     /* if (!force_haplo_sanity(&locus,FALSE)) {
265 	sf(ps,ASS_INSANE,loc2str(locus)); pr();
266 	return(FALSE);
267     } */
268 
269     if (!assigned(locus)) return(TRUE);
270     old= assignment_chrom(locus);
271 
272     if (anchor_locus(locus) && old!=chrom) {
273 	sf(ps,ASS_ANCHOR,loc2str(locus),chrom2str(old)); pr();
274 	return(FALSE); /* don't touch assignment */
275     }
276     if (framework_marker(locus) && old!=chrom) {
277 	/* includes chrom==NO_CHROM case, eg unassigning */
278 	if (!fix_frames) {
279 	    if (chrom==NO_CHROM)
280 	      sf(ps,ASS_UNFRAME,loc2str(locus),chrom2str(old));
281 	    else
282 	      sf(ps,ASS_REFRAME,loc2str(locus),chrom2str(old),
283 		 chrom2str(chrom));
284 	    pr();
285 	    return(FALSE);
286 	} else {
287 	    /* need to change assignment - lod has disappeared */
288 	    /* keep old assignment[locus]->chromosome */
289 	    assignment[locus]->status= A_FRAMEWORK;
290 	    assignment[locus]->LODscore= NO_LOD;
291 	    assignment[locus]->theta= NO_THETA;
292 	    assignment[locus]->linked_to= NO_LOCUS;
293 	    assignment[locus]->modified= TRUE;
294 	    /* no need to unplace - it's (still) a framework marker */
295 	    sf(ps,ASS_ISFRAME,loc2str(locus),chrom2str(old)); pr();
296 	    return(FALSE); /* ??? */
297 	}
298     }
299     return(TRUE);
300 }
301 
302 
303 #define ASS_NONE    "%s- unassigned\n"
304 #define ASS_UNASS   "%s- unassigned (previously assigned to chrom %s)\n"
305 #define ASS_UNANCH  "%s- unassigned (previously anchor locus on %s)\n"
306 #define ASS_NEWANCH "%s- unassigned (anchor loci on %s have been changed)\n"
307 
308 #define ASS_FRAME   "%s- framework locus...remains attached to %s\n"
309 #define ASS_ASSIGN  "%s- assigned to %s at LOD %4.1lf\n"
310 #define ASS_BORDER  "%s- assigned to %s at LOD *%4.1lf*\n"
311 #define ASS_ATTACH  "%s- attached to %s\n"
312 
313 #define CHG_ASSIGN "%s- assigned to %s at LOD %4.1lf (previously assigned to %s)\n"
314 #define CHG_ATTACH "%s- attached to %s (previously assigned to %s)\n"
315 #define CHG_BORDER "%s- assigned to %s at LOD *%.1lf* (previously assigned to %s)\n"
316 
317 /* this will unassign anchors, but not reassign them correctly, and it will
318    certainly not make loci anchors - this is OK for now */
assign_this(locus,state,chrom,lod,theta,linked_locus,msg)319 void assign_this(locus,state,chrom,lod,theta,linked_locus,msg)
320 int locus, state, chrom;
321 real lod, theta;
322 int linked_locus;
323 char *msg; /* pre-empts other message, only for A_PROBLEM as yet */
324 {
325     int old_chrom= (assigned(locus) ? assignment_chrom(locus):NO_CHROM);
326 
327     if (state<=0) { /* set to an unassigned state */
328 	if (!nullstr(msg)) /* problem state: use this msg */
329 	  strcpy(ps,msg);
330 	else if (anchor_locus(locus))
331 	  sf(ps,ASS_UNANCH,loc2str(locus),chrom2str(assignment_chrom(locus)));
332 	else if (assigned(locus))
333 	  sf(ps,ASS_UNASS,loc2str(locus),chrom2str(assignment_chrom(locus)));
334 	else
335 	  sf(ps,ASS_NONE,loc2str(locus));
336 	pr();
337 	unplace_this(locus,NO_CHROM,M_UNKNOWN,FALSE);
338 
339     } else { /* assign to a chrom */
340 	if (assigned(locus) && assignment_chrom(locus)!=chrom) { /* changed */
341 	    if (framework_marker(locus)) send(CRASH);
342 	    if (state==A_ATTACH) /* no lod state */
343 	      sf(ps,CHG_ATTACH,loc2str(locus),chrom2str(chrom),
344 		    chrom2str(assignment_chrom(locus)));
345 	    else if (state==A_FRAMEWORK) send(CRASH);
346 	    else if (state==A_BORDERLINE)
347 	      sf(ps,CHG_BORDER,loc2str(locus),chrom2str(chrom),lod,
348 		 chrom2str(assignment_chrom(locus)));
349 	    else /* state==A_ASSIGNED */
350 	      sf(ps,CHG_ASSIGN,loc2str(locus),chrom2str(chrom),lod,
351 		 chrom2str(assignment_chrom(locus)));
352 	    unplace_this(locus,NO_CHROM,M_UNKNOWN,FALSE);
353 
354 	} else { /* assignment has not been changed */
355 	    if (state==A_ATTACH) /* no lod states */
356 	      sf(ps,ASS_ATTACH,loc2str(locus),chrom2str(chrom));
357 	    else if (state==A_FRAMEWORK) /* no lod states */
358 	      sf(ps,ASS_FRAME,loc2str(locus),chrom2str(chrom));
359 	    else if (state==A_BORDERLINE)
360 	      sf(ps,ASS_BORDER,loc2str(locus),chrom2str(chrom),lod);
361 	    else
362 	      sf(ps,ASS_ASSIGN,loc2str(locus),chrom2str(chrom),lod);
363 	}
364 	pr();
365     }
366 
367     assignment[locus]->chromosome= chrom;
368     assignment[locus]->status= state;
369     assignment[locus]->LODscore= lod;
370     assignment[locus]->theta= theta;
371     assignment[locus]->linked_to= linked_locus;
372     assignment[locus]->modified= TRUE;
373 }
374 
375 
unassign_this(locus,state)376 void unassign_this(locus,state)
377 int locus, state;
378 { assign_this(locus,state,NO_CHROM,NO_LOD,NO_THETA,NO_LOCUS,""); }
379 
380 
attach_this(locus,state,chrom)381 void attach_this(locus,state,chrom)
382 int locus, state;
383 { assign_this(locus,state,chrom,NO_LOD,NO_THETA,NO_LOCUS,""); }
384 
385 
386 #define ANCHOR_ISFRAME \
387   "%s is a framework marker on %s...cannot re-assign to %s\n"
388 #define ANCHOR_ISANCH  \
389   "%s is a framework marker on %s...cannot re-assign to %s\n"
390 #define ANCHOR_ISNOW "%s- anchor locus on %s\n"
391 #define ANCHOR_DUPS  "bad framework\none or more loci are repeated in sequence"
392 
set_chrom_anchors(chrom,locus,num_loci)393 void set_chrom_anchors(chrom,locus,num_loci)
394 int chrom, *locus, num_loci; /* maybe 0 */
395 {
396     int i, j, old_chrom;
397     bool still_got_it;
398 
399     /* check for problems: FW/anchor markers on other chroms,
400        need to assume haplo_sanity */
401     for (j=0; j<num_loci; j++) {
402 	old_chrom=(assigned(locus[j]) ? assignment_chrom(locus[j]):NO_CHROM);
403 	if (old_chrom!=chrom && framework_marker(locus[j])) {
404 	    sf(ps,ANCHOR_ISFRAME,loc2str(locus[j]),chrom2str(old_chrom));
405 	    error(ps);
406 	}
407 	if (old_chrom!=chrom && anchor_locus(locus[j])) {
408  	    sf(ps,ANCHOR_ISANCH,loc2str(locus[j]),chrom2str(old_chrom));
409 	    error(ps);
410 	}
411     }
412 
413     /* unassign old anchors */
414     for (i=0; i<raw.num_markers; i++)
415       if (assigned_to(i,chrom) && anchor_locus(i)) {
416 	  still_got_it=FALSE;
417 	  for (j=0; j<num_loci; j++)
418 	    if (locus[j]==i) { still_got_it=TRUE; break; }
419  	  if (!still_got_it) {
420 	      if (framework_marker(i)) attach_this(i,A_FRAMEWORK,chrom);
421 	        else unassign_this(i,A_CHANGED);
422 	  }
423       }
424 
425     /* assign new anchors */
426     for (j=0; j<num_loci; j++) {
427 	if (assigned(locus[j]) && assignment_chrom(locus[j])!=chrom)
428 	  unplace_this(locus[j],NO_CHROM,M_UNKNOWN,FALSE);
429 	sf(ps,ANCHOR_ISNOW,loc2str(locus[j]),chrom2str(chrom)); pr();
430 	assignment[locus[j]]->chromosome= chrom;
431 	assignment[locus[j]]->status=     A_ANCHOR;
432 	assignment[locus[j]]->LODscore=   NO_LOD;
433 	assignment[locus[j]]->theta=      NO_THETA;
434 	assignment[locus[j]]->linked_to=  NO_LOCUS;
435 	assignment[locus[j]]->modified=   TRUE;
436     }
437 }
438 
439 
440 #define DOASS_NOANCHS "no anchor loci have yet been assigned to chromosomes\n"
441 #define DOASS_NOCHROMS "no chromosomes have yet been defined\n"
442 
do_assignments(locus,num_loci,lod1,unlinked_lod1,theta1,lod2,unlinked_lod2,theta2,haplo)443 void do_assignments(locus,num_loci,lod1,unlinked_lod1,theta1,
444 		    lod2,unlinked_lod2,theta2,haplo)
445 int *locus, num_loci;  /* is_assignable must have been verified */
446 real lod1, unlinked_lod1, theta1, lod2, unlinked_lod2, theta2;
447 bool haplo;
448 {
449     int i, j, state, num_chroms;
450     bool assigned_any, do_changed_only;
451     int **anchor=NULL, *count=NULL;
452     real lod, unlinked_lod, theta;
453 
454     run {
455 	if ((num_chroms=chromosome->num_maps)==0) error(DOASS_NOCHROMS);
456 	matrix(anchor,num_chroms,raw.num_markers,int);
457 	array(count,num_chroms,int); for (i=0; i<num_chroms; i++) count[i]=0;
458 	if (!get_anchors(anchor,count,locus,num_loci,haplo))
459 	  error(DOASS_NOANCHS);
460 
461 	lod=lod1; unlinked_lod=unlinked_lod1; theta=theta1;
462 	assigned_any=TRUE;
463 	/* when we start loop with assigned_any=FALSE, we switch lods */
464 	do {
465 	    if (!assigned_any) {
466 		lod=lod2; unlinked_lod=unlinked_lod2; theta=theta2;
467 	    }
468 	    assigned_any=FALSE;
469 	    for (i=0; i<num_loci; i++) {
470 		if (locus[i]!=NO_LOCUS &&
471 		    do_assignment(locus[i],lod,unlinked_lod,theta,
472 				  anchor,count,num_chroms)) {
473 		    /* msg is printed */
474 		    locus[i]=NO_LOCUS;
475 		    assigned_any=TRUE;
476 		}
477 	    }
478 	} while (assigned_any || lod!=lod2);
479 
480 	/* if a locus made it to here, its unlinked */
481 	for (i=0; i<num_loci; i++) if (locus[i]!=NO_LOCUS) {
482 	    state=assignment_state(i);
483 	    if (state!=A_FRAMEWORK && state!=A_ATTACH)
484 	      unassign_this(locus[i],A_UNLINKED);
485 	    else attach_this(locus[i],state,assignment_chrom(locus[i]));
486 	}
487     } on_exit {
488 	unmatrix(anchor,num_chroms,int);
489 	unarray(count,int);
490     }
491 }
492 
493 
494 
495 #define ASS_MULTI  "%s- conflicting data (%s LOD %.2lf, %s LOD %.2lf)\n"
496 
do_assignment(locus,lodbound,minlodbound,thetabound,anchor,count,num_groups)497 bool do_assignment(locus,lodbound,minlodbound,thetabound,
498 		   anchor,count,num_groups)
499 int locus;
500 real lodbound, minlodbound, thetabound;
501 int **anchor;   /* [num_groups][0..count[this_group]-1] */
502 int *count;     /* [num_groups] */
503 int num_groups;
504 {
505     int assigned_locus, j, k, state;
506     int this_locus, pos_locus, this_chrom, pos_chrom, alt_chrom, pos_group;
507     real lod, theta, this_lod, pos_lod, alt_lod, this_theta, pos_theta;
508     bool this_group;
509     char *temp= get_temp_string();
510 
511     /* this actually does a bit of i/o (well, one line per locus) by
512        virtue of calling assign_this(), which is gabby */
513 
514     /* this has slightly special behavior for loci with A_FRAMEWORK or
515        A_ATTACH, in that it will not unlink them if there is no evidence for
516        assignment (it will try to RELINK them however) THIS NEEDS WORK */
517 
518     if (sex_specific) send(CRASH);
519 
520     pos_chrom= alt_chrom= NO_CHROM;
521     pos_lod= alt_lod= 0.0;
522 
523     for (j=0; j<num_groups; j++) {
524 	/* if (do_changed_only && !changed[j]) continue; */
525 	this_group=FALSE; this_lod= 0.0;
526 	for (k=0; k<count[j]; k++) {
527 	    assigned_locus= anchor[j][k];
528 	    get_two_pt(locus,assigned_locus,&lod,&theta);
529 	    if (lod>=minlodbound && theta<=thetabound) {
530 		this_group= TRUE;
531 		this_chrom= j;
532 		if (lod>this_lod) {
533 		    this_lod= lod;
534 		    this_theta= theta;
535 		    this_locus= assigned_locus;
536 		}
537 	    }
538 	}
539 	if (this_group) { /* matched one in this group */
540 	    if (pos_chrom==NO_CHROM ||
541 		   (pos_chrom==this_chrom && this_lod>pos_lod)) {
542 		/* we've matched no other chroms in this or other groups */
543 		pos_chrom= this_chrom; pos_locus= assigned_locus; pos_group= j;
544 		pos_lod= this_lod;     pos_theta= this_theta;
545 
546 	    } else if (this_lod>pos_lod) {
547 		/* we've matched another chrom, but this one is best */
548 		if (pos_lod>alt_lod) /* if ex-best chr is now second best */
549 		  { alt_chrom= pos_chrom; alt_lod= pos_lod; }
550 		pos_chrom= this_chrom; pos_locus= assigned_locus; pos_group= j;
551 		pos_lod= this_lod;     pos_theta= this_theta;
552 
553 	    } else if (alt_chrom!=NO_CHROM && this_lod>alt_lod) {
554 		/* we've matched another, better, chrom, this is 2nd best */
555 		alt_chrom= this_chrom; alt_lod= this_lod;
556 	    }
557 	}
558     }
559 
560     if (pos_lod>=lodbound && alt_chrom!=NO_CHROM &&
561 	((state=assignment_state(locus))!=A_FRAMEWORK && state!=A_ATTACH)) {
562 	/* really linked, but there is evidence of linkage to other chroms */
563 	sf(temp,ASS_MULTI,loc2str(locus),
564 	   chrom2str(pos_chrom),pos_lod,
565 	   chrom2str(alt_chrom),alt_lod);
566 	assign_this(locus,A_PROBLEM,NO_CHROM,NO_LOD,NO_THETA,NO_LOCUS,temp);
567 	return(TRUE);
568 
569     } else if (pos_lod>=lodbound) {
570 	/* really linked, only to this chrom */
571 	assign_this(locus,A_ASSIGNED,pos_chrom,pos_lod,pos_theta,pos_locus,"");
572 	anchor[pos_group][(count[pos_group])++]=locus;
573 	return(TRUE);
574 
575     } else return(FALSE);
576 }
577 
578 
579 
get_anchors(anchor,count,locus,num_loci,haplo)580 bool get_anchors(anchor,count,locus,num_loci,haplo) /* internal use only */
581 int **anchor, *count; /* side-effected if non-null */
582 int *locus, num_loci; /* markers to assign now */
583 bool haplo;   /* take only haplo_firsts */
584 {
585     int i, j, state, chrom, found, n=0;
586 
587     for (i=0; i<raw.num_markers; i++) if (assigned(i)) {
588 	state=assignment_state(i); chrom=assignment_chrom(i);
589 	if ((state==A_ANCHOR || state==A_BORDERLINE || state==A_ASSIGNED) &&
590 	      (!haplo || haplo_first[i]==NO_CHROM || haplo_first[i]==i)) {
591 	    for (found=FALSE, j=0; j<num_loci; j++)
592 	      if (locus[j]==i) { found=TRUE; break; }
593 	    if (!found)	{ anchor[chrom][(count[chrom])++]=i; n++; }
594 	}
595     }
596     return(n);
597 }
598 
599 
600 
601 /**************** Placements ****************/
602 
placed_locus(locus)603 bool placed_locus(locus)
604 int locus;
605 { force_haplo_sanity(&locus,FALSE); return(placement[locus]->status>0); }
606 
placement_state(locus)607 bool placement_state(locus)
608 int locus;
609 { force_haplo_sanity(&locus,FALSE); return(placement[locus]->status); }
610 
611 
612 #define PLACE_ISFRAME \
613   " %4d  %-9s - framework marker on chromosome %s, can't place\n"
614 #define PLACE_NOTASS  \
615   " %4d  %-9s - not assigned to a chromosome, can't place\n"
616 #define PLACE_NOTCHR  \
617   " %4d  %-9s - not assigned to chromosome %s, can't place\n"
618 #define PLACE_INSANE  \
619   " %4d  %-9s - not the name of its haplotype-group, can't place\n"
620 
621 #define PLACE_PROBLEM \
622   " %4d  %-9s - no locations allowed, can't place\n"
623 #define PLACE_UNKNOWN \
624   " %4d  %-9s - unplaced"
625 #define PLACE_FRAMEWORK \
626   " %4d  %-9s - framework marker"
627 #define PLACE_TOOMANY \
628   " %4d  %-9s - too many possible locations, can't place\n"
629 
630 #define PLACE_OFFEND  \
631   " %4d  %-9s - placed %soff %send of framework, like%s%.2lf\n"
632 #define PLACE_UNIQUE  \
633   " %4d  %-9s - placed %sin one interval, like%s%.2lf\n"
634 #define PLACE_ZERO    \
635   " %4d  %-9s - placed %sat zero distance, like%s%.2lf\n"
636 #define PLACE_REGION  \
637   " %4d  %-9s - placed %sin %d intervals, like%s%.2lf 2nd%s%.2lf\n"
638 /*234  123456789 - placed *with errors* in 24 intervals, like=-9.24, 2nd=-5.*/
639 
is_placeable(locus,chrom)640 bool is_placeable(locus,chrom)
641 int locus, chrom;
642 {
643     int framework, old_chrom, k;
644 
645     /* unplace_this() helps to clean up the placement structure, when this
646        is called by place or place_together */
647 
648     if (!force_haplo_sanity(&locus,FALSE)) {
649 	sf(ps,PLACE_INSANE,locus+1,locname(locus,TRUE));
650 	pr(); return(FALSE);
651 
652     } else if (framework_marker(locus)) {
653 	sf(ps,PLACE_ISFRAME,locus+1,locname(locus,TRUE),
654 	   chrom2str(assignment_chrom(locus)));	pr();
655 	/* unplace_this(locus,NO_CHROM,M_UNKNOWN,FALSE); WHY? */
656 	return(FALSE);
657 
658     } else if (!assigned(locus)) {
659 	sf(ps,PLACE_NOTASS,locus+1,locname(locus,TRUE)); pr();
660 	/* unplace_this(locus,NO_CHROM,M_UNKNOWN,FALSE); */
661 	return(FALSE);
662 
663     } else if (chrom!=ANY_CHROM && !assigned_to(locus,chrom)) {
664 	/* not used yet */
665 	sf(ps,PLACE_NOTCHR,locus+1,locname(locus,TRUE),chrom2str(chrom)); pr();
666 	/* unplace_this(locus,NO_CHROM,M_UNKNOWN,FALSE); */
667 	return(FALSE);
668 
669     } else return(TRUE);
670 }
671 
672 
place_this(locus,chrom,place,like_thresh,one_err_thresh,net_err_thresh,excluded)673 int place_this(locus,chrom,place,like_thresh,one_err_thresh,net_err_thresh,
674 	       excluded)
675 int locus, chrom;
676 PLACE **place;   /* better be ralative to chrom's fw order */
677 real like_thresh, one_err_thresh, net_err_thresh;
678 bool *excluded;  /* used as a temp for npt_exclusions() */
679 {
680     int j, n, num, good;
681     real second_best, support, error_lod;
682     bool zero, off_end, is_single_error;
683     char *sgn, *sgn2, *witherr;
684 
685     num= chromosome->map_list[chrom]->num_loci;
686 
687     good= npt_exclusions(place,num,like_thresh,one_err_thresh,net_err_thresh,
688 			 excluded,&zero,&off_end,&error_lod,&is_single_error,
689 			 &second_best,&support);
690 
691     placement[locus]->modified= TRUE;
692     placement[locus]->chromosome=chrom;
693     placement[locus]->threshold= like_thresh;
694     placement[locus]->error_lod= error_lod; /* maybe NO_ERRORS */
695     placement[locus]->single_error= is_single_error;
696 
697     n=0;
698     for (j=0; j<=num; j++) if (!excluded[j]) {
699 	if (place[j]->like>PLACEMENT_THRESHOLD) {
700 	    if (n<MAX_STORED_PLACES) {
701 		placement[locus]->interval[n]= j;
702 		placement[locus]->like_ratio[n]= place[j]->like;
703 		placement[locus]->distance[n]=   place[j]->dist;
704 		placement[locus]->num_intervals= ++n;
705 	    } else { /* we are full */
706 		placement[locus]->num_intervals= 0;
707 		placement[locus]->threshold= 0.0;
708 		placement[locus]->status= M_PROBLEM;
709 		sf(ps,PLACE_TOOMANY,locus+1,locname(locus,TRUE)); pr();
710 		return(0);
711 	    }
712 	}
713     }
714 
715     sgn=ptr_to("=");
716     if (support==NO_LIKE) { sgn=ptr_to("<"); support=-5.0; }
717     witherr=ptr_to("");
718     if (error_lod!=NO_ERRORS) witherr=ptr_to("*with errors* ");
719 
720     if (off_end) {
721 	placement[locus]->status= (error_lod!=NO_ERRORS ? M_ERROR:M_OFFEND);
722 	sf(ps,PLACE_OFFEND,locus+1,locname(locus,TRUE),witherr,
723 	   (off_end==2 ? "*either* ":""),sgn,support);
724 	pr();
725 	/* print the errors? */
726 
727     } else if (good==1) {
728 	if (zero) {
729 	    placement[locus]->status=(error_lod!=NO_ERRORS ? M_ERROR:M_ZERO);
730 	    sf(ps,PLACE_ZERO,locus+1,locname(locus,TRUE),witherr,
731 	       sgn,support); pr();
732 
733 	} else {
734 	    placement[locus]->status=(error_lod!=NO_ERRORS ? M_ERROR:M_UNIQUE);
735 	    sf(ps,PLACE_UNIQUE,locus+1,locname(locus,TRUE),witherr,
736 	       sgn,support); pr();
737 	}
738 
739     } else { /* good>1 */
740 	sgn2=ptr_to("=");
741 	if (second_best==NO_LIKE) { sgn2=ptr_to("<"); second_best=-5.0; }
742 	placement[locus]->status= (error_lod!=NO_ERRORS ? M_ERROR:M_REGION);
743 	sf(ps,PLACE_REGION,locus+1,locname(locus,TRUE),witherr,good,
744 	   sgn,support,sgn2,second_best);
745 	pr();
746 	/* print possible errors? */
747     }
748 
749     return(good);
750 }
751 
752 
unplace_this(locus,chrom,status,verbose)753 void unplace_this(locus,chrom,status,verbose)
754 int locus, chrom, status;
755 bool verbose;
756 {
757     placement[locus]->modified= TRUE;
758     placement[locus]->num_intervals= 0;
759     placement[locus]->threshold= 0.0;
760     placement[locus]->error_lod=  NO_ERRORS;
761     placement[locus]->single_error= TRUE;
762     placement[locus]->chromosome= chrom;
763     placement[locus]->status= status;
764     if (verbose) {
765 	if (status==M_PROBLEM)
766 	  { sf(ps,PLACE_PROBLEM,locus+1,locname(locus,TRUE)); pr(); }
767 	else if (status==M_FRAMEWORK)
768 	  { sf(ps,PLACE_FRAMEWORK,locus+1,locname(locus,TRUE)); pr(); }
769 	else
770 	  { sf(ps,PLACE_UNKNOWN,locus+1,locname(locus,TRUE)); pr(); }
771     }
772 }
773 
774 
775 /* These have no error traps - only use them if valid data are stored! */
best_placement(locus)776 int best_placement(locus)
777 int locus;
778 {
779     int i;
780 
781     if (placement[locus]->num_intervals==0) send(CRASH);
782     for (i=0; i<placement[locus]->num_intervals; i++)
783       if (placement[locus]->like_ratio[i]==0.0) break;
784     if (i==placement[locus]->num_intervals) send(CRASH);
785     return(i);
786 }
787 
788 
second_best_placement(locus,like)789 int second_best_placement(locus,like) /* only ok for M_REGION */
790 int locus;
791 real *like;
792 {
793     int i, j, pos; /* need to add many error traps */
794     real best;
795 
796     for (i=0; i<placement[locus]->num_intervals; i++)
797       if (placement[locus]->like_ratio[i]==0.0) break;
798     best= -VERY_BIG;
799     for (j=0; j<placement[locus]->num_intervals; j++)
800       if (j!=i && placement[locus]->like_ratio[j]>best)
801 	{ best=placement[locus]->like_ratio[j]; pos=j; }
802     if (like!=NULL) *like=best;
803     if (best== -VERY_BIG) return(-1);
804     return(j);
805 }
806 
807 
808 
809 /************ Load/Save/Reset ************/
810 
811 
bash_mapping_data(changed,num_changed)812 void bash_mapping_data(changed,num_changed)
813 int *changed, num_changed; /* changed markers */
814 {
815     int i, j, n;
816     MAP *map;
817     bool bash[MAX_CHROMOSOMES];
818     for (j=0; j<chromosome->num_maps; j++) bash[j]=FALSE;
819 
820     for (i=0; i<num_changed; i++) {
821 	n=changed[i];
822 	sf(ps,"%-8s - unassigned and unplaced (changed)\n",
823 	   locname(n,FALSE)); pr();
824     }
825     for (i=0; i<num_changed; i++) {
826 	n=changed[i];
827 	if (assignment[n]->status==A_ANCHOR) {
828 	    sf(ps,"warning: %s WAS an anchor locus for chromosome %s\n",
829 	       locname(n,FALSE),chrom2str(assignment[n]->chromosome)); pr();
830 	}
831     }
832     for (i=0; i<num_changed; i++) {
833 	n=changed[i];
834 	if (assignment[n]->status!=A_UNKNOWN)
835 	  assignment[n]->status=   A_CHANGED;
836 	assignment[n]->chromosome= NO_CHROM;
837 	assignment[n]->linked_to=  NO_LOCUS;
838 	assignment[n]->LODscore=   NO_LOD;
839 	assignment[n]->theta=      NO_THETA;
840 	assignment[n]->modified=   FALSE;
841 
842 	if (placement[n]->status==M_FRAMEWORK)
843 	  bash[assignment[n]->chromosome]=TRUE;
844 	placement[n]->status= M_UNKNOWN;
845 	placement[n]->num_intervals= 0;
846 	placement[n]->threshold= 0.0;
847 	placement[n]->error_lod= NO_ERRORS;
848 	placement[n]->single_error= TRUE;
849 	placement[n]->chromosome= NO_CHROM;
850 	placement[n]->modified= FALSE;
851     }
852 
853     for (j=0; j<chromosome->num_maps; j++)
854       if (bash[j] && chromosome->map_list[j]->num_loci>0) {
855 	  sf("chromosome %s framework cleared, all loci unplaced\n",
856 	     chrom2str(j)); pr();
857 	map=get_map_to_bash(chromosome);
858 	clean_map(map); /* num_loci -> 0 */
859 	set_chrom_frame(j,map);
860     }
861 }
862 
863 
allocate_mapping_data(num_markers)864 void allocate_mapping_data(num_markers)
865 int num_markers;
866 {
867     int locus;
868 
869     chromosome=
870       allocate_map_list(MAX_CHROMOSOMES,MAX_CHROM_LOCI,UNSORTED,NULL);
871     parray(assignment,num_markers,ASSIGNMENT);
872     parray(placement, num_markers,PLACEMENT);
873 
874     for (locus=0; locus<num_markers; locus++) {
875 	assignment[locus]->status=    A_UNKNOWN;
876 	assignment[locus]->chromosome=NO_CHROM;
877 	assignment[locus]->linked_to= NO_LOCUS;
878 	assignment[locus]->LODscore=  NO_LOD;
879 	assignment[locus]->theta=     NO_THETA;
880 	assignment[locus]->modified= FALSE;
881 
882 	placement[locus]->status= M_UNKNOWN;
883 	placement[locus]->num_intervals= 0;
884 	placement[locus]->threshold= 0.0;
885 	placement[locus]->error_lod= NO_ERRORS;
886 	placement[locus]->single_error= TRUE;
887 	placement[locus]->chromosome= NO_CHROM;
888 	placement[locus]->modified= FALSE;
889     }
890 }
891 
892 
free_mapping_data(num_markers)893 void free_mapping_data(num_markers)
894 int num_markers;
895 {
896     free_map_list(chromosome);
897     unparray(assignment,num_markers,ASSIGNMENT);
898     unparray(placement, num_markers,PLACEMENT);
899 }
900 
901 
write_mapping_data(fp)902 void write_mapping_data(fp)
903 FILE *fp;
904 {
905     int locus, i, j;
906 
907     sf(ps,"*Chromosomes: %d\n", chromosome->num_maps); fpr(fp);
908     for (i=0; i < chromosome->num_maps; i++) {
909         write_map(fp, chromosome->map_list[i]);
910     }
911 
912     fprint(fp,WRS("*Assignments and Placements:\n"));
913     for (locus=0; locus< raw.num_markers; locus++) {
914         sf(ps,"*%-8s %2d",raw.locus_name[locus],assignment[locus]->status);
915 	fpr(fp);
916 	if (assignment[locus]->status==M_UNKNOWN) { fnl(fp); continue; }
917 
918 	sf(ps," %d %d %lf %lf | %d %lf %lf %d %d \n",
919 	   assignment[locus]->chromosome, assignment[locus]->linked_to,
920 	   assignment[locus]->LODscore,   assignment[locus]->theta,
921 	   placement[locus]->status,      placement[locus]->threshold,
922 	   placement[locus]->error_lod,	  placement[locus]->single_error,
923 	   placement[locus]->num_intervals); fpr(fp);
924 
925 	if (placement[locus]->num_intervals==0) continue;
926 
927 	for (j=0; j < placement[locus]->num_intervals; j++) {
928 	    sf(ps," %d %lf %lf",
929 	       placement[locus]->interval[j], placement[locus]->like_ratio[j],
930 	       placement[locus]->distance[j]); fpr(fp);
931 	}
932 	fnl(fp);
933     }
934 }
935 
936 
read_mapping_data(fp)937 void read_mapping_data(fp)
938 FILE *fp;
939 {
940     int locus, num, chrom_num, i, j, num_chroms;
941     real rnum, rnum2;
942     char word[TOKLEN+1], temp_locus_name[NAME_LEN+2];
943     MAP  *map;
944 
945     /* chromosomes */
946     fgetln_(fp);
947     stoken(&ln,sREQUIRED,word);
948     if (!streq(word,"*Chromosomes:") || !itoken(&ln,iREQUIRED,&num_chroms)) {
949         baddata("error finding *Chromosomes:");
950     }
951     for (i=0; i < num_chroms; i++) {
952         map= get_map_to_bash(chromosome);
953 	read_map(fp,map);
954 	insert_map_into_list(chromosome,&map);
955     }
956     if (chromosome->num_maps != num_chroms) {
957         baddata("listed number of chromosomes and actual number do not agree");
958     }
959 
960     fgetln_(fp);
961     if (!streq(ln,"*Assignments and Placements:"))
962         baddata("error finding *Assignments and Placements:");
963     for (locus=0; locus < raw.num_markers; locus++) {
964         getdataln(fp);
965 
966 	if (!nstoken(&ln,sREQUIRED,temp_locus_name,NAME_LEN+1) ||
967 	    temp_locus_name[0]!='*' || len(temp_locus_name)<2)
968 	  baddata("expected *name");
969 	else if (!streq(raw.locus_name[locus],&temp_locus_name[1]))
970 	  baddata("locus names don't match");
971 
972 	/* assignment info */
973 	itoken(&ln,iREQUIRED,&num);
974 	assignment[locus]->status=num;
975 	if (num==A_UNKNOWN) continue; /* next locus */
976 
977 	if (sscanf(ln,"%d %d %lf %lf %s %d %lf %lf %d %d",
978 		   &assignment[locus]->chromosome,
979 		   &assignment[locus]->linked_to,
980 		   &assignment[locus]->LODscore,
981 		   &assignment[locus]->theta,
982 		   word,
983 		   &placement[locus]->status,
984 		   &placement[locus]->threshold,
985 		   &placement[locus]->error_lod,
986 		   &placement[locus]->single_error,
987 		   &placement[locus]->num_intervals)!=10 || !streq(word,"|"))
988 	  baddata("unable to parse assignment/placement line");
989 
990 	placement[locus]->chromosome= assignment[locus]->chromosome;
991 	if (placement[locus]->num_intervals==0) continue; /* next locus */
992 
993 	getdataln(fp); /* get next line */
994 	for (j=0; j < placement[locus]->num_intervals; j++) {
995 	    itoken(&ln,iREQUIRED,&num);
996 	    placement[locus]->interval[j]=num;
997 	    rtoken(&ln,rREQUIRED,&rnum);
998 	    placement[locus]->like_ratio[j]=rnum;
999 	    rtoken(&ln,rREQUIRED,&rnum);
1000 	    placement[locus]->distance[j]=rnum;
1001 	}
1002     }
1003 }
1004