PageRenderTime 57ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/code_comm/RecentFuncs.c

http://research-code-base-animesh.googlecode.com/
C | 627 lines | 469 code | 63 blank | 95 comment | 99 complexity | 8dbf6d72dbf028cb86eee7a16b0c90c2 MD5 | raw file
  1. /* tacg - a command line tool for the analysis of nucleic acids and protein */
  2. /* Copyright Š 1994-2001 Harry J Mangalam, tacg Informatics
  3. (mangalam@tacgi.com | mangalam@home.com, | 949 856 2847) */
  4. /* $Id: RecentFuncs.c,v 1.18 2001/11/05 02:48:42 hjm Exp $ */
  5. /* The use of this software (except that by Harald T. Alvestrand, which is described in 'udping.c')
  6. and that by James Knight, which is described in 'seqio.c' is bound by the notice that appears
  7. in the file 'tacg.h' which should accompany this file. In the event that 'tacg.h' is not bundled
  8. with this file, please contact the author.
  9. */
  10. #include <stdio.h>
  11. #include <ctype.h>
  12. #include <string.h>
  13. #include <stdlib.h>
  14. #include <regex.h>
  15. #include <math.h>
  16. #include <sys/types.h>
  17. #include <sys/stat.h>
  18. #include <unistd.h>
  19. #include "seqio.h"
  20. #include "tacg.h"
  21. /* #include <pcre.h> */
  22. /* GrafMap is the 1st take on the long-delayed graphical plasmid/linear maps function */
  23. /* on calling, runs thru RE and makes a 1st pass guestimate of how to map all the hits. If there
  24. are too many hits, it should truncate at a level which does not leave a pattern partially
  25. mapped. As can be determined by examining the Postscript generated, I'm a PS newbie and the PS
  26. could be made significantly more compact by encoding the tic routines in PS for example and letting
  27. the PS engine do all the calculations. It's also full of debug info, which will remain until the
  28. code solidifies more. The PDF output tho is quite robust.
  29. */
  30. void GrafMap(long *Degen_Log, int NumProtos, int *Protos, char *Description, char datestamp[80], float FrACGT[4]) {
  31. int i, j, n, bi, ti, sli, HPc, REi, slotted, FCnt, ORF_line_width, f, ORFNum,
  32. skip_this_map=0, need_prolog=0, NLabels, RWCincr, previ, start, end, run,
  33. sep, center, abegin, HPEnd = NUM_PLASMID_LABELS+30,
  34. debug=0, dstart=0, dend=15; /* set the debug vars */
  35. long HPi=0, HPMax=0, RWC, ldiff, BasesPerLabel,
  36. seq_len = F.Seq_Len, temp,
  37. HP[3][HPEnd], /* Holding Pen for counting sites 0=site 1 = REi 2=adj*/
  38. mdbl; /* min dist between labels */
  39. char *MapFileName,
  40. *ptmp,
  41. *rstr, *o, star, *arrow,
  42. Label[20];
  43. float ORF_density, x_left, x_right, y_top, y_bot, yoffset;
  44. /* some constants, measurements in inches, arcs in degrees, */
  45. double Radius = 3.0,
  46. CenterX = 4.25,
  47. CenterY = 4.5,
  48. /* xold, yold, */
  49. AnglePerLabel,
  50. /* pi = 3.141592653589, */
  51. topx, topy, arc_end, hairline_radius,
  52. PtCenterX, PtCenterY, PtRadius;
  53. FILE *PS; /* output postscript file */
  54. FILE *PROLOG; /* prolog file */
  55. struct NextHit_struct NH;
  56. struct stat *Fbuf;
  57. /* mangle the file name to be compatible with a cgi call if it was so called */
  58. if ((MapFileName = calloc(64, sizeof(char))) == NULL) { BadMem("RecentFuncs:MapFileName", 1); }
  59. if (F.HTML != -1) { /* then we need the /tmp-named files */
  60. sprintf(MapFileName, "%s/tacg_Map.ps", F.tmppath);
  61. } else {
  62. MapFileName = "tacg_Map.ps"; /* name by itself to write into the $PWD */
  63. }
  64. PtCenterX = CenterX * 72;
  65. PtCenterY = CenterY * 72;
  66. PtRadius = Radius * 72;
  67. x_left = y_bot = 25; /* ~1/3" up from the margin to start */
  68. x_right = 576; /* ~8" right margin */
  69. y_top = 756; /* ~10.5" top margin */
  70. NLabels = NUM_PLASMID_LABELS; /* how many Label slots there are */
  71. mdbl = seq_len / (long)NLabels;
  72. AnglePerLabel = 360 / NUM_PLASMID_LABELS;
  73. BasesPerLabel = (long)((long)AnglePerLabel * seq_len / 360);
  74. for (i=0;i<HPEnd;i++) { for (j=0; j<3; j++) {HP[j][i] = 0;} }
  75. if ((rstr = calloc(MAX_LEN_RULESTRING,sizeof(char))) == NULL) { BadMem("Can't init mem for 'rstr'", 1); }
  76. if ((Fbuf = calloc(1, sizeof(*Fbuf))) == NULL) { BadMem("RecentFuncs:Fbuf",1); }
  77. if ((ptmp = (SearchPaths("psprolog", "PSPROLOG file"))) == NULL) {
  78. fprintf(stderr,"Can't open the 'psprolog' file!! - Check spelling, ownership, existance, etc - Bye!!\n");
  79. exit (1);
  80. }
  81. if ((PROLOG=fopen(ptmp,"r")) == NULL) { /* or the standard/optional one from SetFlags() */
  82. fprintf(stderr,"Cannot open the postscript prolog file 'psprolog' for reading!!\n");
  83. exit(1); /* print an error and die gracefully */
  84. }
  85. /* if file doesn't exist, need to write in prolog */
  86. if (stat(MapFileName, Fbuf) == -1) { need_prolog = 1; }
  87. if ((PS=fopen(MapFileName,"a")) == NULL) { /* or the standard/optional one from SetFlags() */
  88. fprintf(stderr,"Cannot open the output postscript file \"%s\" for writing!!\n", MapFileName);
  89. exit(1); /* print an error and die gracefully */
  90. }
  91. if (need_prolog) {
  92. /* use the Illustrator PS prolog as it has a number of useful defs, so copy PROLOG into PS */
  93. while (fgets(rstr, 512, PROLOG)) { fprintf(PS, "%s", rstr); }
  94. }
  95. /* ------------------------ write the title, date, etc --------------------------------------- */
  96. /* write a header at top left */
  97. yoffset = y_top;
  98. fprintf(PS, "\n\n/Helvetica-Bold findfont 12 scalefont setfont\n");
  99. fprintf(PS, "newpath %f %f moveto\n (Description: %s) show \n",
  100. x_left, yoffset, Description);
  101. yoffset -= 12;
  102. fprintf(PS, "%f %f moveto\n (Date: %s) show\n", x_left, yoffset, datestamp );
  103. fprintf(PS, "\n\n/Helvetica findfont 10 scalefont setfont\n");
  104. yoffset -= 10;
  105. fprintf(PS, "newpath %f %f moveto\n (Map by tacg v. %s (http://24.0.123.214/tacg3)) show\n",
  106. x_left, yoffset, TACG_VERSION);
  107. fprintf(PS, "\n\n/Helvetica findfont 10 scalefont setfont\n");
  108. yoffset -= 10;
  109. fprintf(PS, "newpath %f %f moveto\n (Suggestions to Harry Mangalam (mangalam@home.com)) show\n",
  110. x_left, yoffset);
  111. /* print a little legend at bottom left */
  112. yoffset = 30;
  113. fprintf(PS, "\n/Helvetica findfont 8 scalefont setfont\n");
  114. fprintf(PS, "newpath %f %f moveto\n (Label = Name[base#]overhang (*), where: ) show\n", x_left, (y_bot+yoffset));
  115. yoffset -= 8;
  116. fprintf(PS, " %f %f moveto\n (Name = Name of the RE or pattern, ) show\n", x_left, (y_bot+yoffset));
  117. yoffset -= 8;
  118. fprintf(PS, " %f %f moveto\n ([base#] = cut site of the RE or ~center of the pattern) show\n", x_left, (y_bot+yoffset));
  119. yoffset -= 8;
  120. fprintf(PS, " %f %f moveto\n (overhang: \\\\ = 5', / = 3', | = blunt. '*' = 1 hit only.) show\n", x_left, (y_bot+yoffset));
  121. /* assume an 8x10.5 US letter page; will probably have to correct to various media later */
  122. /* set the line width and then draw a circle at the center of the page */
  123. fprintf(PS, "1 setlinewidth\nnewpath %f %f %f 0 360 arc stroke\n", PtCenterX, PtCenterY, PtRadius);
  124. /* outline circle to set off degens */
  125. fprintf(PS, "0.3 setlinewidth\nnewpath %f %f %f 0 360 arc stroke\n", PtCenterX, PtCenterY, PtRadius+3);
  126. /* write a small + at the center for a registration mark */
  127. fprintf(PS, " .3 setlinewidth %f %f moveto\n 10 0 rlineto stroke\n %f %f moveto\n 0 10 rlineto stroke\n",
  128. (PtCenterX - 5), PtCenterY, PtCenterX, (PtCenterY - 5));
  129. /* -------------------------- and the sequence stats ----------------------------------- */
  130. fprintf(PS, "\n/Helvetica-Bold findfont 10 scalefont setfont\n");
  131. fprintf(PS, "newpath %f %f moveto\n", (PtCenterX - 30), PtCenterY+30);
  132. fprintf(PS, " (%ld bases) show\n", seq_len) ;
  133. fprintf(PS, "\n/Helvetica findfont 6 scalefont setfont\n");
  134. fprintf(PS, "newpath %f %f moveto\n", (PtCenterX - 100), PtCenterY+10);
  135. fprintf(PS, " (%ld A(%.2f %%) %ld C(%.2f %%) %ld G(%.2f %%) %ld T(%.2f %%)) show\n",
  136. F.NBases[0], FrACGT[0]*100, F.NBases[1], FrACGT[1]*100, F.NBases[2],
  137. FrACGT[2]*100, F.NBases[3], FrACGT[3]*100);
  138. if (seq_len > (temp = F.NBases[0] + F.NBases[1] +F.NBases[2] + F.NBases[3])) {
  139. fprintf(PS, "newpath %f %f moveto\n", (PtCenterX - 90), PtCenterY-15);
  140. fprintf (PS, "\n(NB: sequence length > A+C+G+T due to %ld IUPAC degeneracies.) show\n", seq_len-temp);
  141. fprintf(PS, "newpath %f %f moveto\n", (PtCenterX - 80), PtCenterY-22);
  142. fprintf (PS, "(# of: N:%ld Y:%ld R:%ld W:%ld S:%ld K:%ld M:%ld B:%ld D:%ld H:%ld V:%ld) show \n",
  143. F.NBases[14], F.NBases[5], F.NBases[6], F.NBases[7], F.NBases[8], F.NBases[9], F.NBases[10],
  144. F.NBases[10], F.NBases[11], F.NBases[12], F.NBases[13]);
  145. }
  146. /* write out the alternating light/dark 1KB bands ? not yet.. */
  147. /* start counting the number of sites and enter them into a local array */
  148. HPc = 0; j=2;
  149. RWCincr = seq_len / NLabels;
  150. while (HPc < NLabels && j < (*DD).Dat[0] && ((*DD).Dat[j] < seq_len)) {
  151. RWC = (*DD).Dat[j];
  152. REi = (int)labs((*DD).Dat[j+1]);
  153. if (RE_Filters_OK(REi)) { /* if the RE is allowed by the filter */
  154. /* fprintf(stderr,"%s accepted!\n", RE[(int)labs((*DD).Dat[j+1])].E_nam); */
  155. /* try to place the info in the appro slot in HP */
  156. slotted = 0;
  157. HPi = (int)((float)(*DD).Dat[j] / (float)seq_len * NLabels); /* HPi points to the relative position of the hit */
  158. /* bc circular sequences are padded, possible to find hits
  159. before and beyond actual sequence, so have to check for over/underruns */
  160. /* if (HPi > HPEnd) { HPi = HPEnd;}
  161. if (HPi < 0) { HPi = 0;}
  162. */
  163. if (HP[0][HPi] == 0) { /* if there isn't anything already there */
  164. HP[0][HPi] = RWC; /* the RWC of the hit */
  165. HP[1][HPi] = REi; /* the RE index */
  166. ldiff = HP[0][HPi-1] - HP[0][HPi];
  167. if (HPc > 0 && ldiff > 0 && ldiff < mdbl) {
  168. HP[2][HPi] += RWCincr;
  169. }
  170. slotted = 1;
  171. } else { /* have to find a nearby open slot in the appro position */
  172. /* since this is taken from DD.Dat, the sites WILL BE in order, so should just
  173. have to step to the NEXT open slot */
  174. /* this routine does not guarantee that the lines won't cross, altho it should work in most cases
  175. in order to guarantee this, would have to make it into a linked list structure - possible
  176. but lets wait to see how it behaves in real life. */
  177. /* fprintf(stderr,"\nCOLLISION @ %d!\n", HPi); */
  178. while (HP[0][HPi] != 0 && HPi < HPEnd) { /* incr until it finds an empty slot */
  179. HPi++;
  180. }
  181. if (HPi >= HPEnd) {
  182. /* then we ran into the end, but there are probably empty slots left before this
  183. so let's see if we can find them */
  184. sli=HPi;
  185. while (HP[0][HPi] != 0) {sli--;}
  186. if (sli <= 0) { /* we really did use them all up, so die */
  187. fprintf(stderr, "\nLooks like we ran out of Label Slots in GrafMap:HP\n");
  188. skip_this_map = 1;
  189. exit(1); /* should skip, not exit, to handle multiple maps, but not yet */
  190. } else { /* we found one before [0], but to use it, have to move all the
  191. trailing data UP 1 so move everything from here to end up one */
  192. ti=sli; bi=sli+1;
  193. while (bi < HPEnd) {
  194. for (i=0; i<3; i++) { HP[i][ti++] = HP[i][bi++]; }
  195. }
  196. /* so we should have moved everything up by 1..?
  197. and HPi should still be pointing at the same (previously occupied) el. */
  198. }
  199. }
  200. HP[0][HPi] = RWC; /* the RWC of the hit */
  201. HP[1][HPi] = REi; /* the RE index */
  202. HP[2][HPi] += RWCincr; /* the increment caused by the too-close labels */
  203. slotted = 1;
  204. /* fprintf(stderr,"\nHPi relocated to %d \n", HPi); */
  205. }
  206. HP[2][HPi] += HP[0][HPi]; /* this makes the [2] teh entire diff instead of the increment */
  207. HPc++;
  208. } else {
  209. /* fprintf(stderr,"\t%s rejected!\n", RE[(int)labs((*DD).Dat[j+1])].E_nam); */
  210. }
  211. j+=2;
  212. }
  213. /* this should end with the (size NLabels) Holding Pen (HP) populated with
  214. RWC's (HP[0][x]) and REi's (HP[1][x]) of REs / patterns */
  215. if (HPi == HPEnd ) {
  216. fprintf(stdout, "\n\tMore than %d patterns met crits for plasmid map.\n"
  217. "\tIncrease the stringency and try again.\n", NLabels);
  218. exit(1);
  219. } else { HPMax = HPi + 1;}
  220. if (debug > 0) {
  221. /* -------------------- DEBUG---------------------- */
  222. fprintf(stderr, "\n\nPass %d\n", debug++);
  223. for (i=dstart; i<dend; i++) {
  224. fprintf(stderr, "\n%3d: ", i);
  225. for (j=0; j<3; j++) { fprintf(stderr, " %5ld ", HP[j][i]); }
  226. }
  227. /* -----------------------DEBUG -------------------------*/
  228. }
  229. previ = 0;
  230. /* 2nd pass - increase spacing of labels that have mapped too closely */
  231. HPi = 1;
  232. while (HPi < HPEnd) {
  233. /* for (HPi=1; HPi<HPEnd; HPi++) */ /* original */
  234. if ( HP[0][HPi] != 0 && HP[0][HPi+1] != 0) { /* skip if not 2 in a row */
  235. start=HPi;
  236. while ((HPi < HPEnd) && ((HP[0][HPi] != 0) || ((HP[0][HPi] != 0) && (HP[0][HPi+1] - HP[0][HPi] > mdbl)))) {
  237. /* could also examine the run itself to detect those spots where instead of taking the
  238. next position, they are remapped to a spot corresponding to their original offset -
  239. this happens at the end of a long run where the last few els are actually separated
  240. by a long distance from the rest of the run, but get mapped into the run bc they
  241. aren't separated by any empty els */
  242. /* fprintf(stderr, "\nHPi = %ld is in a run \n", HPi); */
  243. previ++;
  244. HPi++;
  245. } /* how many in a row? */
  246. end = --HPi; run = end - start + 1;
  247. if (debug > 0) {
  248. fprintf(stderr, "\n at HPi= %ld, start=%d end=%d run = %d\n", HPi, start, end, run );
  249. for (j=0; j<3; j++) { fprintf(stderr, " %5ld ", HP[j][HPi]); }
  250. }
  251. /* calculate the separation betw labels to be equal */
  252. sep = (HP[2][end] - HP[2][start] ) / run; /* sep = average separation in bp distance */
  253. center = ((HP[0][end] - HP[0][start]) / 2) + HP[0][start];
  254. abegin = center - (BasesPerLabel * (run/2)) ; /* back up the right amount */
  255. if (run == 1) {abegin = abegin - (BasesPerLabel*0.5);}
  256. if (run > 2) {abegin -= BasesPerLabel;} /* if have a larger run, back up some more */
  257. if (abegin < 0) { abegin = 0; }
  258. HP[2][start] = abegin; /* + BasesPerLabel; mark the 1st at the backup position */
  259. /* abegin += BasesPerLabel; was sep */
  260. for (i = start+1; i <= end; i++) {
  261. abegin += BasesPerLabel;
  262. HP[2][i] = abegin; /* they should now be spread evenly across the group spread */
  263. } /* and the NEXT round should detect a collision with this one. */
  264. previ = HPi;
  265. }
  266. HPi++;
  267. }
  268. if (debug > 0) {
  269. /* -------------------- DEBUG---------------------- */
  270. fprintf(stderr, "\n\nPass %d\n", debug++);
  271. for (i=dstart; i<dend; i++) {
  272. fprintf(stderr, "\n%3d: ", i);
  273. for (j=0; j<3; j++) { fprintf(stderr, " %5ld ", HP[j][i]); }
  274. }
  275. /* -----------------------DEBUG -------------------------*/
  276. }
  277. /* 3rd pass */
  278. i = 2;
  279. while (i < HPEnd) {
  280. if ((HP[2][i-1] == 0) && (HP[2][i] - HP[2][i-2] < BasesPerLabel)) { /* then there was mistake */
  281. /* and the empty el should then carry the corrected value */
  282. HP[2][i-1] = HP[2][i-2] + BasesPerLabel;
  283. HP[0][i-1] = HP[0][i];
  284. HP[1][i-1] = HP[1][i];
  285. HP[2][i] = 0; /* and set the bad slot to 0s so we don't get dups */
  286. HP[0][i] = 0;
  287. HP[1][i] = 0;
  288. }
  289. i++;
  290. }
  291. if (debug > 0) {
  292. /* -------------------- DEBUG---------------------- */
  293. fprintf(stderr, "\n\nPass %d\n", debug++);
  294. for (i=dstart; i<dend; i++) {
  295. fprintf(stderr, "\n%3d: ", i);
  296. for (j=0; j<3; j++) { fprintf(stderr, " %5ld ", HP[j][i]); }
  297. }
  298. /* -----------------------DEBUG -------------------------*/
  299. }
  300. /* now go thru all the sites in HP and mark the labels where they're supposed to go. for each, have to
  301. calculate the degree of offset, draw a tic, draw a line to the label, write the label in a small font. */
  302. fprintf(PS, "/Helvetica findfont 6 scalefont setfont\n");
  303. NH.radius = PtRadius;
  304. NH.xc = PtCenterX;
  305. NH.yc = PtCenterY; /* init NH struct */
  306. NH.xet = NH.yet = 0;
  307. NH.alpha = NH.beta = NH.delta = 0;
  308. topx = NH.x1 = PtCenterX;
  309. topy = NH.y1 = PtCenterY + PtRadius;
  310. /* ------------------------------ Major and minor tics ---------------------------------------- */
  311. /* make the major tics - this should be mechanized, no */
  312. if (seq_len <= 10000000) {
  313. if (seq_len <= 10000000 && seq_len > 1000000) {
  314. tacg_Draw_Seq_Tics(10, 0.5, seq_len, &NH, 1, 1000000, -1, "/Helvetica findfont 6 scalefont setfont", PS);
  315. tacg_Draw_Seq_Tics(5, 0.2, seq_len, &NH, 1, 100000, 1000000, "/Helvetica findfont 4 scalefont setfont", PS);
  316. tacg_Draw_Seq_Tics(2, 0.2, seq_len, &NH, 0, 10000, 100000, "/Helvetica findfont 4 scalefont setfont", PS);
  317. } else if (seq_len <= 1000000 && seq_len > 100000) {
  318. tacg_Draw_Seq_Tics(10, 0.5, seq_len, &NH, 1, 100000, -1, "/Helvetica findfont 6 scalefont setfont", PS);
  319. tacg_Draw_Seq_Tics(5, 0.2, seq_len, &NH, 1, 10000, 100000, "/Helvetica findfont 4 scalefont setfont", PS);
  320. tacg_Draw_Seq_Tics(2, 0.2, seq_len, &NH, 0, 1000, 10000, "/Helvetica findfont 4 scalefont setfont", PS);
  321. } else if (seq_len <= 100000 && seq_len > 10000) {
  322. tacg_Draw_Seq_Tics(10, 0.5, seq_len, &NH, 1, 10000, -1, "/Helvetica findfont 6 scalefont setfont", PS);
  323. tacg_Draw_Seq_Tics(5, 0.2, seq_len, &NH, 1, 1000, 10000, "/Helvetica findfont 4 scalefont setfont", PS);
  324. tacg_Draw_Seq_Tics(2, 0.2, seq_len, &NH, 0, 100, 1000, "/Helvetica findfont 4 scalefont setfont", PS);
  325. } else if (seq_len <= 10000 && seq_len > 1000) {
  326. tacg_Draw_Seq_Tics(10, 0.5, seq_len, &NH, 1, 1000, -1, "/Helvetica findfont 6 scalefont setfont", PS);
  327. tacg_Draw_Seq_Tics(5, 0.2, seq_len, &NH, 1, 100, 1000, "/Helvetica findfont 4 scalefont setfont", PS);
  328. tacg_Draw_Seq_Tics(2, 0.2, seq_len, &NH, 0, 10, 100, "/Helvetica findfont 4 scalefont setfont", PS);
  329. } else {
  330. tacg_Draw_Seq_Tics(10, 0.5, seq_len, &NH, 1, 100, -1, "/Helvetica findfont 6 scalefont setfont", PS);
  331. tacg_Draw_Seq_Tics(5, 0.2, seq_len, &NH, 1, 10, 100, "/Helvetica findfont 4 scalefont setfont", PS);
  332. }
  333. } else {
  334. fprintf(stderr, "\nSequence is > 10,000,000; tics jammed too close for this now\n\n");
  335. }
  336. /* & minor tics */
  337. i = 1;
  338. /*
  339. if (seq_len > 20000) {i = 0;}
  340. tacg_Draw_Seq_Tics(5, 0.2, seq_len, &NH, i, 100, 1000, "/Helvetica findfont 4 scalefont setfont", PS);
  341. if (seq_len < 6000) {
  342. tacg_Draw_Seq_Tics(2, 0.1, seq_len, &NH, 0, 10, 100, "/Helvetica findfont 4 scalefont setfont", PS);
  343. }
  344. */
  345. NH.x1 = PtCenterX;
  346. NH.y1 = PtCenterY + PtRadius;
  347. /* ------------------------------ RE labeling ---------------------------------------- */
  348. HPi = 0;
  349. while (HPi < HPMax) {
  350. NH.radius = PtRadius+3; /* '+3' to allow a band to show degeneracies */
  351. while (HP[0][HPi] == 0 && HPi < HPMax) { HPi++; } /* walk up to the next populated slot */
  352. if (HPi < HPMax) { /* we're not to the end, so finish ... */
  353. RWC = HP[0][HPi]; /* get RWC */
  354. n = HP[1][HPi]; /* get REi */
  355. /* fprintf(stderr, "\nDEBUG:HPi=%ld RWC = %ld RE=%s RWC adj=%ld\n", HPi, RWC, RE[n].E_nam, HP[2][HPi]); */
  356. /* calc the coordinates for the next hit position */
  357. fprintf(PS, "\n\ngsave\n newpath ");
  358. NH.alpha = ((double)RWC / (double)seq_len) * 360; /* calc the offset in degrees */
  359. Calc_Next_Hit_Coords (&NH); /* now the new coords are in NH.xn, NH.yn */
  360. /* place a ticmark there */
  361. fprintf(PS, " %6.2f %6.2f moveto %% RE#: %d hit=%ld, angle=%f\n",
  362. NH.xn, NH.yn, n, RE[n].Sites[i], NH.alpha); /* do a direct moveto */
  363. /* write the tic */
  364. /* NH.alpha = 0; */
  365. NH.radius += 10;
  366. Calc_Next_Hit_Coords (&NH); /* now the new coords are in NH.xn, NH.yn */
  367. NH.xet = NH.xn;
  368. NH.yet = NH.yn;
  369. fprintf(PS, " 1 setlinewidth %6.2f %6.2f lineto stroke %% draw tic\n", NH.xet, NH.yet);
  370. if (HP[0][HPi] != 0) { /* HP[2][HPi] or put in a very small nonzero */
  371. NH.alpha = ((double)(HP[2][HPi]) / (double)seq_len) * 360; /* calc the Label offset in degrees */
  372. NH.radius += 15;
  373. Calc_Next_Hit_Coords (&NH); /* now the new coords are in NH.xn, NH.yn */
  374. /* offset them by the correct amount */
  375. fprintf(PS, " %6.2f %6.2f moveto 0.1 setlinewidth %6.2f %6.2f lineto stroke %% angle=%f\n",
  376. NH.xet, NH.yet, NH.xn, NH.yn, NH.alpha );
  377. fprintf(PS, " %6.2f %6.2f moveto %6.2f rotate ",
  378. NH.xn, NH.yn, (90 - NH.alpha));
  379. }
  380. /* compose & print the label */
  381. if (RE[n].E_olap > 0) { o = "\\\\";}
  382. else if (RE[n].E_olap > 0) { o = "/";}
  383. else { o = "|";}
  384. star = ' ';
  385. if (RE[n].E_Ncuts == 1) { star = '*';}
  386. sprintf(Label, "%s [%ld] %s %c", RE[n].E_nam, RWC, o, star);
  387. if (NH.alpha > 180) {
  388. fprintf(PS, " gsave\n 180 rotate\n "); /* */
  389. fprintf(PS, " (%s) stringwidth neg exch neg exch rmoveto\n (%s) show\n grestore \n grestore\n \n" , Label, Label);
  390. } else {
  391. fprintf(PS, "(%s) show\ngrestore\n", Label); /* show the label in correct position */
  392. }
  393. HPi++;
  394. }
  395. }
  396. /* ------------------------------ Plot ORFs ---------------------------------------- */
  397. /* now if ORFs were requested, print out the ORFS greater than the requested minimum */
  398. fprintf(PS, "\n gsave\n");
  399. NH.radius = PtRadius - 30; /* start point for the ORF arcs */
  400. ORFNum = 0;
  401. ORF_density = 0.0;
  402. FCnt = 0;
  403. ORF_line_width = 3; /* temp est */
  404. /* this has to be modified to do 1-3 1st and 3-6 after, compacting output so that if 1246, it will draw
  405. 1,2 then go directly to 4 then to 6, eliminating circles for 3,5. Do this by sorting the ORFs and compact
  406. to be contiguous. Also have to reverse the arrowhead symbol for frames 3-6 */
  407. fprintf(PS, "\n\n/Helvetica findfont 8 scalefont setfont\n");
  408. while (F.ORFs2Do[FCnt] != 0) { /* do all at first, then follow the F.ORFs2Do array as to which to print */
  409. f = F.ORFs2Do[FCnt] - 1;
  410. ORFNum = 0;
  411. NH.radius -= 10 ; /* make radius a bit smaller for each frame. */
  412. hairline_radius = NH.radius + 7;
  413. /* draw the hairline circle as a separator */
  414. NH.alpha = 0;
  415. Calc_Next_Hit_Coords (&NH);
  416. if (f<3) { arrow = ">"; }
  417. else { arrow = "<"; }
  418. fprintf(PS, "\n newpath %6.2f %6.2f moveto (%d%s) show \n", NH.xn, (NH.yn-2), (f+1), arrow);
  419. fprintf(PS, "\n newpath 0.1 setlinewidth 0.5 setgray\n %f %f %f 0 360 arc stroke\n",
  420. NH.xc, NH.yc, hairline_radius-2 );
  421. ORF_density += 0.07;
  422. /* ORF_struct ORFs contains 6 elements, populated in order..? that contain the ORFs found.
  423. at each ORF iter, have to move to the appro radius and draw the arcs with the appro shading
  424. or hatching (identifying table at the side*/
  425. while (ORFs[f][ORFNum].orflength > 0) { /* indicator that there are no more ORFs in this frame */
  426. /* calc ORF angular offsets in degrees for the beginning of the ORF */
  427. if (f > 2) {
  428. temp = ORFs[f][ORFNum].E_offsetBP;
  429. ORFs[f][ORFNum].E_offsetBP = ORFs[f][ORFNum].B_offsetBP;
  430. ORFs[f][ORFNum].B_offsetBP = temp;
  431. }
  432. NH.alpha = ((double)ORFs[f][ORFNum].E_offsetBP / (double)seq_len) * 360; /* calc the offset in degrees */
  433. Calc_Next_Hit_Coords (&NH); /* now the new coords are in NH.xn, NH.yn */
  434. arc_end = NH.alpha;
  435. /* and move there */
  436. fprintf(PS, "\n %f %f moveto\n", NH.xn, NH.yn); /* unless we have to reset to the origin 1st */
  437. /* possibly add an arrowhead here to show direction of transcription/translation */
  438. NH.alpha = ((double)ORFs[f][ORFNum].B_offsetBP / (double)seq_len) * 360; /* same thing with the End */
  439. Calc_Next_Hit_Coords (&NH); /* now the new coords are in NH.xn, NH.yn */
  440. /* now write the arc from the ORF origin to the end at line width and density set already */
  441. fprintf(PS, "%d setlinewidth %f setgray\n newpath %f %f %f %f %f arc "
  442. "%% frame=%d ORF=%d begin=%ld end=%ld len=%d\n stroke\n",
  443. ORF_line_width, ORF_density, NH.xc, NH.yc, NH.radius, 90-arc_end, 90-NH.alpha,
  444. f, ORFNum, ORFs[f][ORFNum].B_offsetBP, ORFs[f][ORFNum].E_offsetBP, ORFs[f][ORFNum].orflength);
  445. ORFNum++;
  446. }
  447. FCnt++;
  448. }
  449. /* and plot a final hairline to finish off the ORF */
  450. NH.radius -= 4 ; /* make radius a bit smaller */
  451. NH.alpha = 0;
  452. Calc_Next_Hit_Coords (&NH);
  453. fprintf(PS, " newpath 0 setgray 0.2 setlinewidth\n %f %f %f 0 360 arc stroke\n",
  454. NH.xc, NH.yc, NH.radius);
  455. /* ------------------------------ Plot degeneracies ---------------------------------------- */
  456. fprintf(PS, "\n\n%% Marking degeneracies\n3 setlinewidth 0.0 setgray\n");
  457. if (F.LogDegens) {
  458. NH.radius = PtRadius +1.5;
  459. NH.x1 = NH.xc;
  460. NH.y1 = NH.yc + NH.radius;
  461. for (i=2; (i<Degen_Log[1] && Degen_Log[i] < seq_len); i+=2) {
  462. NH.alpha = ((double)Degen_Log[i] / (double)seq_len) * 360; /* calc the offset in degrees to the START of the degen run */
  463. Calc_Next_Hit_Coords (&NH);
  464. arc_end = NH.alpha;
  465. fprintf(PS, "\n newpath %6.2f %6.2f moveto newpath %% Base %ld \n",
  466. NH.xn, NH.yn, Degen_Log[i]);
  467. NH.alpha = ((double)Degen_Log[i+1] / (double)seq_len) * 360; /* offset to END of the degen run */
  468. fprintf(PS, " %f %f %f %f %f arc stroke\n\n", NH.xc, NH.yc, NH.radius, 90-NH.alpha, 90-arc_end ); /* 90-NH.alpha, 90-arc_end */
  469. }
  470. }
  471. fprintf(PS, "\nshowpage\n");
  472. fclose(PS);
  473. }
  474. /* int tic_size - the length of the tics in pts
  475. float line_width - the width of the line in pts
  476. long seq_len - the sequence length in base pairs
  477. struct NextHit_struct *NH - the Next Hit struct
  478. int drawlabels - whether to print labels or just write the tics
  479. long repeat_period - the tic period (1000 -> 1000, 2000, 3000, etc)
  480. int skip_period - what period should be skipped. If already done repeat_period -> 1000 and
  481. doing minor tics at 100, don't want to overwrite the 1000 label
  482. int font_string - the font characteristics as Postscript likes it:
  483. FILE *PS - the file pointer to the file we're writing to
  484. */
  485. void tacg_Draw_Seq_Tics(int tic_size, float line_width, long seq_len, struct NextHit_struct *NH, int drawlabels,
  486. long repeat_period, int skip_period, char *font_string, FILE *PS ){
  487. int i, ntics, nk;
  488. /* label_offset = -35; how far should we move towards the center to compensate for the label */
  489. char *Label;
  490. if ((Label = calloc(128,sizeof(char))) == NULL) { BadMem("tacg_Draw_Seq_Tics:Label", 1); }
  491. tic_size *= -1; /* tics go towards center */
  492. ntics = (int)(seq_len / repeat_period);
  493. /* if ((seq_len % 1000) < 0.00001) { ntics--; } knock off the last tic if it overlaps with the origin. */
  494. nk=0; /* num of k's, 1000s were the orig tic counter */
  495. fprintf(PS, "gsave\n %f setlinewidth %s\n", line_width, font_string);
  496. for (i=0; i<= ntics; i++) { /* && ((*NH).alpha < 359) */
  497. (*NH).alpha = (double)nk / (double)seq_len * 360;
  498. if ((*NH).alpha < 360 ) { /* && (*NH).alpha > 0 */
  499. fprintf(PS, "\n\nnewpath\n gsave\n ");
  500. Calc_Next_Hit_Coords (NH);
  501. fprintf(PS, " %f %f moveto \t%% tic mark: %d, angle=%f\n",
  502. (*NH).xn, (*NH).yn, nk, (*NH).alpha);
  503. fprintf(PS, " %f rotate\n gsave\n", (90-(*NH).alpha)); /* rotate */
  504. if (nk > 0) sprintf(Label, "%d", nk);
  505. else if (skip_period < 0 ) sprintf(Label, " 0 ");
  506. else sprintf(Label, " ");
  507. fprintf(PS, " %d 0 rlineto \n stroke\n grestore\n", tic_size);
  508. if (drawlabels) { /* for the TICS */
  509. if ((*NH).alpha > 180) {
  510. fprintf(PS, " gsave\n 180 rotate\n ");
  511. fprintf(PS, " (%s) stringwidth neg exch .5 mul exch rmoveto\n (%s) show\n grestore\n grestore\n" , Label, Label);
  512. } else {
  513. fprintf(PS, " (%s) stringwidth neg exch dup 2.5 mul sub exch rmoveto\n", Label);
  514. fprintf(PS, "(%s) show\n grestore\n\n", Label); /* show the label in correct position */
  515. }
  516. } else { fprintf(PS, " grestore\n"); }
  517. nk += repeat_period;
  518. if (skip_period > 0 && nk % abs(skip_period) < 0.00001) { nk += repeat_period; } /* skip the skip period */
  519. }
  520. }
  521. fprintf(PS, " grestore\n"); /* to restore the context for whatever was set before */
  522. }
  523. /* passed the pointer of the populated struct, it calculates the x,y coords of the next hit and passes them
  524. back as struct elements xn,yn */
  525. void Calc_Next_Hit_Coords (struct NextHit_struct *NH) {
  526. double pi = 3.141592653589, reflect = 1;
  527. if ((*NH).alpha > 180) {reflect = -1; }
  528. (*NH).x1 = (*NH).x1 - (*NH).xc;
  529. if ( fabs((*NH).x1) > (*NH).radius) {
  530. /* fprintf(stderr, "abs(x1) (%f) > radius (%f)?? \n", (*NH).x1, (*NH).radius); */
  531. (*NH).x1 = (*NH).radius; /* make sure it gets reset before next iteration */
  532. }
  533. (*NH).y1 = (*NH).y1 - (*NH).yc;
  534. (*NH).beta = (pi * asin((*NH).x1 / (*NH).radius)) / 180;
  535. (*NH).delta = 90 - (*NH).alpha - (*NH).beta;
  536. /* fprintf(stderr, "\n\tbeta=%f delta=%f alpha=%f asin=%f\n",
  537. (*NH).beta, (*NH).delta, (90 - (*NH).beta - (*NH).delta), asin((*NH).x1 / (*NH).radius)); */
  538. (*NH).yn = (sin((*NH).delta / (360 / (2 * pi))) * (*NH).radius); /* don't re-add the center value yet */
  539. (*NH).xn = (*NH).xc + (sqrt((*NH).radius * (*NH).radius - (*NH).yn * (*NH).yn) * reflect);
  540. (*NH).yn = (*NH).yc + (*NH).yn; /* now add it back */
  541. (*NH).x1 = (*NH).xn; (*NH).y1 = (*NH).yn; /* update the 'old' coords as well for the next round */
  542. }