]> git.donarmstrong.com Git - wheel.git/blob - wheel/wheel.pl
* Added documentation for colors to the wheel source.
[wheel.git] / wheel / wheel.pl
1 #! /usr/bin/perl -w
2 # wheel.pl: Draw alpha helical wheel with hydrophobic moment using
3 # wif (modifiable to woct) scale.
4 # Copyright (C) 2001 Don Armstrong and Raphael Zidovetzki
5
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
20
21
22
23 my $VERSION=q$Id: wheel.pl,v 1.3 2004-10-21 22:32:38 don Exp $;
24
25 # Intial Released Version 0.10
26 # p01: Fixing displayed angle
27 # p02: Added arrowhead, fixed lack of return in xy2deg(), added no color option
28 # p03: Added round function, fixed rounding in angles, changed hm to line, added hm_up option
29 # p04: Removed bounding box
30 # p05: Changing user interface to allow simultaneous viewing of options and wheel
31 # p06: Released to public under GPL
32
33 use CGI::Carp qw(fatalsToBrowser);
34 use strict;
35 use CGI;
36
37 use Math::Trig;
38 use GD;
39 use GD::Text::Align;
40 use POSIX;
41
42
43 sub round($) {
44   my ($a) = @_;
45   return (floor $a+0.5);
46 }
47
48 sub min($$){
49   my ($a,$b)=@_;
50   if ($a>$b) {
51     return $b;
52   }
53   return $a;
54 }
55
56 sub max($$){
57   my ($a,$b)=@_;
58   if ($a<$b) {
59     return $b;
60   }
61   return $a;
62 }
63
64 my $q = new CGI;
65
66 sub xy2deg($$) {
67   my ($x,$y) = @_;
68   my $angle = rad2deg(atan($x/$y));
69   if ($y<0) {
70     $angle+=180;
71   }
72   elsif ($angle<0) {
73     $angle+=360;
74   }
75   return $angle;
76 }
77
78 sub calculate_hydrophobic_moment($$){
79   my ($sequence,$param)=@_;
80   my $phe=$param->{phe};
81   my $theta=$param->{theta};
82   my ($x,$y)=(0,0);
83   foreach my $amino_acid (split(//,$sequence)) {
84     $x+=-$param->{aa}->{$amino_acid}->{wif} * sin($phe);
85     $y+=+$param->{aa}->{$amino_acid}->{wif} * cos($phe);
86     $phe+=$theta;
87   }
88   return ($x,$y);
89 }
90
91
92 sub draw_wheel($$$){
93   my ($im,$aasequence,$param)=@_;
94   my $phe=$param->{phe};
95   my $aanumber=0;
96   my $point1;
97   my @points;
98   foreach my $aminoacid (split(//,$aasequence)) {
99     push @points, calculate_geometry($param,$phe);
100     $phe += $param->{theta};
101     $aanumber++;
102     last if ($aanumber>18);
103   }
104   for ($aanumber=0;$aanumber<19;$aanumber++) {
105     my $point = pop @points;
106     last if (!defined $point);
107     if ($aanumber>0) {
108       draw_connection($im,$aanumber,$point1,$point);
109     }
110     $point1 = $point;
111   }
112   $phe = $param->{phe};
113   $aanumber = 0;
114   foreach my $aminoacid (split(//,$aasequence)) {
115     $point1=calculate_geometry($param,$phe);
116     draw_aa($im,$aminoacid,
117             $param->{centerx}+($point1->{bx}-$param->{centerx})*
118             ($param->{d}+2.2*$param->{r}*POSIX::floor($aanumber/18))/
119             $param->{d},$param->{centery}+($point1->{by}-$param->{centery})*
120             ($param->{d}+2.2*$param->{r}*POSIX::floor($aanumber/18))/
121             $param->{d},$phe,$param,$aanumber);
122     $phe+=$param->{theta};
123     $aanumber++;
124   }
125   my ($hydro_x,$hydro_y) = calculate_hydrophobic_moment($aasequence,$param);
126   draw_hydrophobic_moment($im,$hydro_x,$hydro_y,$param);
127 }
128
129 sub draw_hydrophobic_moment($$$$){
130   my ($im,$x,$y,$param)=@_;
131   my $norm=($x*$x+$y*$y)**(0.5);
132   my $angle = xy2deg($x,-$y);
133   if ($norm !=0 and $param->{hmscale}!=0) {
134     $x=$x/$norm*$param->{hmscale};
135     $y=$y/$norm*$param->{hmscale};
136   }
137
138   # Draw Moment Line (Box, really)
139   my $poly = GD::Polygon->new;
140   print STDERR "$angle\n";
141   $poly->addPt($param->{centerx}-round(($param->{hmscale}/50)*sin(deg2rad($angle+90))),
142                $param->{centery}+round(($param->{hmscale}/50)*cos(deg2rad($angle+90))));
143   $poly->addPt($param->{centerx}+round($x*0.85-($param->{hmscale}/50)*sin(deg2rad($angle+90))),
144                $param->{centery}+round($y*0.85+($param->{hmscale}/50)*cos(deg2rad($angle+90))));
145   $poly->addPt($param->{centerx}+round($x*0.85-($param->{hmscale}/50)*sin(deg2rad($angle-90))),
146                $param->{centery}+round($y*0.85+($param->{hmscale}/50)*cos(deg2rad($angle-90))));
147   $poly->addPt($param->{centerx}-round(($param->{hmscale}/50)*sin(deg2rad($angle-90))),
148                $param->{centery}+round(($param->{hmscale}/50)*cos(deg2rad($angle-90))));
149   $im->filledPolygon($poly,$param->{black});
150
151   # Draw Arowhead
152   undef $poly;
153   $poly = GD::Polygon->new;
154   $poly->addPt($param->{centerx}+$x,$param->{centery}+$y);
155   $poly->addPt($param->{centerx}+$x-round(($param->{hmscale}/5)*sin(deg2rad($angle+20))),
156                $param->{centery}+$y+round(($param->{hmscale}/5)*cos(deg2rad($angle+20))));
157   $poly->addPt($param->{centerx}+$x-round(($param->{hmscale}/5)*sin(deg2rad($angle-20))),
158                $param->{centery}+$y+round(($param->{hmscale}/5)*cos(deg2rad($angle-20))));
159   $im->filledPolygon($poly,$param->{black});
160   my $text= GD::Text::Align->new($im,
161                                  valign => 'center',
162                                  halign => 'center',
163                                  color=> $param->{black},
164                                 );
165   $text->set_font('/usr/share/fonts/truetype/Florsn01.ttf',$param->{fontsize2});
166   if ($param->{disp_hm_angle}) {
167     $text->set_text(POSIX::floor($norm*100+.5)/100 . '@' . POSIX::floor(($angle*10+0.5))/10);
168   }
169   else {
170     $text->set_text(POSIX::floor($norm*100+.5)/100);
171   }
172   my $offset=-10-$param->{fontsize2}/2;
173   if ($y<0) {
174     $offset=-$offset;
175   }
176   $text->draw($param->{centerx},$param->{centery}+$offset);
177 }
178
179 sub draw_connection($$$$) {
180   my ($im,$aanumber,$point1,$point2) =  @_;
181   my $color=$im->colorAllocate(240*((18-$aanumber)/18),
182                                240*((18-$aanumber)/18),
183                                240*((18-$aanumber)/18)
184                               );
185   my $poly = GD::Polygon->new;
186   $poly->addPt($point1->{ex},$point1->{ey});
187   $poly->addPt($point2->{ex},$point2->{ey});
188   $poly->addPt($point2->{cx},$point2->{cy});
189   $poly->addPt($point1->{cx},$point1->{cy});
190   $im->filledPolygon($poly,$color);
191   return;
192 }
193
194 sub calculate_geometry($$){
195   my ($param,$phe)=@_;
196   return {bx=>($param->{d})*sin($phe)+$param->{centerx},
197           cx=>($param->{d}-($param->{w}/2)/sin((pi-$param->{theta})/2))*sin($phe)+$param->{centerx},
198           dx=>($param->{centerx}),
199           ex=>($param->{d}+($param->{w}/2)/sin((pi-$param->{theta})/2))*sin($phe)+$param->{centerx},
200           by=>-($param->{d})*cos($phe)+$param->{centery},
201           cy=>-($param->{d}-($param->{w}/2)/sin((pi-$param->{theta})/2))*cos($phe)+$param->{centery},
202           dy=>($param->{centery}),
203           ey=>-($param->{d}+($param->{w}/2)/sin((pi-$param->{theta})/2))*cos($phe)+$param->{centery},
204          };
205 }
206
207
208 sub draw_n_gon($$$$){
209   my ($x,$y,$r,$n)=@_;
210   my $ngon=GD::Polygon->new;
211   for (my $v = 0;$v<$n;$v++) {
212     $ngon->addPt($x+$r*sin((2*pi/$n)*$v),$y-$r*cos((2*pi/$n)*$v));
213   }
214   return($ngon);
215 }
216
217 sub draw_aa($$$$$$$){
218   my ($im,$aasymbol,$bx,$by,$phe,$param,$aanumber)=@_;
219   my $r=$param->{r};
220
221   my $ax=$bx;
222   my $ay=$by;
223   $_ = $param->{aa}->{$aasymbol}->{shape};
224   if (defined && /square/) {
225     $im->filledRectangle($ax-$r,$ay-$r,$ax+$r,$ay+$r,$param->{aa}->{$aasymbol}->{bcolor});
226     $im->rectangle($ax-$r,$ay-$r,$ax+$r,$ay+$r,$param->{aa}->{$aasymbol}->{fcolor});
227   }
228   elsif (defined && /triangle/) {
229     $im->filledPolygon(draw_n_gon($ax,$ay,1.25*$r,3),
230                        $param->{aa}->{$aasymbol}->{bcolor});
231     $im->polygon(draw_n_gon($ax,$ay,1.25*$r,3),
232                  $param->{aa}->{$aasymbol}->{fcolor});
233   }
234   elsif (defined && /hexagon/) {
235     $im->filledPolygon(draw_n_gon($ax,$ay,1.18*$r,6),
236                      $param->{aa}->{$aasymbol}->{bcolor});
237     $im->polygon(draw_n_gon($ax,$ay,1.18*$r,6),
238                  $param->{aa}->{$aasymbol}->{fcolor});
239   }
240   elsif (defined && /diamond/) {
241     $im->filledPolygon(draw_n_gon($ax,$ay,1.25*$r,4),
242                       $param->{aa}->{$aasymbol}->{bcolor});
243     $im->polygon(draw_n_gon($ax,$ay,1.25*$r,4),
244                  $param->{aa}->{$aasymbol}->{fcolor});
245   }
246   elsif (defined && /pentagon/) {
247     $im->filledPolygon(draw_n_gon($ax,$ay,1.2*$r,5),
248                       $param->{aa}->{$aasymbol}->{bcolor});
249     $im->polygon(draw_n_gon($ax,$ay,1.2*$r,5),
250                  $param->{aa}->{$aasymbol}->{fcolor});
251   }
252   elsif (defined && /octagon/){
253     $im->filledPolygon(draw_n_gon($ax,$ay,1.1*$r,8),
254                       $param->{aa}->{$aasymbol}->{bcolor});
255     $im->polygon(draw_n_gon($ax,$ay,1.1*$r,8),
256                  $param->{aa}->{$aasymbol}->{fcolor});
257   }
258   else {  #cicle
259     $im->filledPolygon(draw_n_gon($ax,$ay,$r*0.99,360),
260                       $param->{aa}->{$aasymbol}->{bcolor});
261     $im->arc($ax,$ay,2*$r,2*$r,0,360,$param->{aa}->{$aasymbol}->{fcolor});
262   }
263   $im->fill($ax,$ay,$param->{aa}->{$aasymbol}->{bcolor});
264   my $text= GD::Text::Align->new($im,
265                                  valign => 'center',
266                                  halign => 'center',
267                                  color=> $param->{black},
268                                 );
269   $text->set_font('/usr/share/fonts/truetype/Florsn01.ttf',$param->{fontsize});
270   my $label_text=$aasymbol  . abs($aanumber+$param->{indexaa});
271   $text->set_text($label_text);
272   $text->draw($ax,$ay,0);
273 }
274
275
276 if (defined $q->param('draw') and $q->param('draw')=~/yes/) {
277   my $param={
278              indexaa=>1,
279              d=>320,
280              centerx=>500,
281              centery=>500,
282              xsize=>1000,
283              ysize=>1000,
284              w=>14,
285              theta=>(100/180)*pi,
286              phe=>(0/180)*pi,
287              r=>40,
288              fontsize=>20,
289              fontsize2=>20,
290              hmscale=>50,
291              wifcolor=>1,
292              maxwif=>0.5802,
293              minwif=>-1.8502,
294              hmdisp=>'',
295             };
296   # Merge in query params
297   # DGwoct[woct] and DGwif[wif] are octanol and interface hydrophobicity values
298   # as seen on http://blanco.biomol.uci.edu/Whole_residue_HFscales.txt
299   # and used in MPEx.
300   # Wimley and White
301   # Nature Struc. Biol 3:842 (1996) [wif values]
302   # Wimley, Creamer and White
303   # Biochemistry 34:5108 (1996) [woct values]
304
305   $param->{aa} = {G=>{name=>'Glycine',
306                       abbr=>'gly',
307                       woct=>1.15,
308                       wif=>0.01,
309                      },
310                   A=>{name=>'Alanine',
311                       abbr=>'ala',
312                       woct=>0.50,
313                       wif=>0.17,
314                      },
315                   V=>{name=>'Valine',
316                       abbr=>'val',
317                       woct=>-0.46,
318                       wif=>0.07,
319                      },
320                   L=>{name=>'Leucine',
321                       abbr=>'leu',
322                       woct=>-1.25,
323                       wif=>-0.56,
324                       shape=>'diamond',
325                      },
326                   I=>{name=>'Isoleucine',
327                       abbr=>'ile',
328                       woct=>-1.12,
329                       wif=>-0.31,
330                       shape=>'diamond',
331                      },
332                   M=>{name=>'Methionine',
333                       abbr=>'met',
334                       woct=>-0.67,
335                       wif=>-0.23,
336                       shape=>'diamond',
337                      },
338                   P=>{name=>'Proline',
339                       abbr=>'pro',
340                       woct=>0.14,
341                       wif=>0.45,
342                      },
343                   F=>{name=>'Phenylalanine',
344                       abbr=>'phe',
345                       woct=>-1.71,
346                       wif=>-1.13,
347                       shape=>'diamond',
348                      },
349                   W=>{name=>'Tryptophan',
350                       abbr=>'trp',
351                       woct=>-2.09,
352                       wif=>-1.85,
353                       shape=>'diamond',
354                      },
355                   S=>{name=>'Serine',
356                       abbr=>'ser',
357                       woct=>0.46,
358                       wif=>0.13,
359                      },
360                   T=>{name=>'Threonine',
361                       abbr=>'thr',
362                       woct=>0.25,
363                       wif=>0.14,
364                      },
365                   N=>{name=>'Asparagine',
366                       abbr=>'asn',
367                       woct=>0.85,
368                       wif=>0.42,
369                      },
370                   Q=>{name=>'Glutamine',
371                       abbr=>'gln',
372                       woct=>0.77,
373                       wif=>0.58,
374                      },
375                   Y=>{name=>'Tyrosine',
376                       abbr=>'tyr',
377                       woct=>-0.71,
378                       wif=>-0.94,
379                       shape=>'diamond',
380                      },
381                   C=>{name=>'Cysteine',
382                       abbr=>'cys',
383                       woct=>-0.02,
384                       wif=>-0.24,
385                       shape=>'diamond',
386                      },
387                   K=>{name=>'Lysine',
388                       abbr=>'lys',
389                       woct=>2.80,
390                       wif=>0.99,
391                       shape=>'pentagon',
392                       fill=>[187,187,255],
393                       border=>[187,187,255],
394                      },
395                   R=>{name=>'Arginine',
396                       abbr=>'arg',
397                       woct=>1.81,
398                       wif=>0.81,
399                       shape=>'pentagon',
400                       fill=>[187,187,255],
401                       border=>[187,187,255],
402                      },
403                   H=>{name=>'Histidine',
404                       abbr=>'his',
405                       woct=>2.33,
406                       wif=>0.96,
407                       shape=>'pentagon',
408                       fill=>[187,187,255],
409                       border=>[187,187,255],
410                      },
411                   D=>{name=>'Aspartic Acid',
412                       abbr=>'asp',
413                       woct=>3.64,
414                       wif=>1.23,
415                       shape=>'triangle',
416                       fill=>[187,187,255],
417                       border=>[187,187,255],
418                      },
419                   E=>{name=>'Glutamic Acid',
420                       abbr=>'glu',
421                       woct=>3.63,
422                       wif=>2.02,
423                       shape=>'triangle',
424                       fill=>[187,187,255],
425                       border=>[187,187,255],
426                      },
427                  };
428   foreach my $param_key ($q->param) {
429     my $param_value=$q->param($param_key);
430     if ($param_value=~/^(\-{0,1}\d*\.{0,1}\d+)$/) {
431       $param->{$param_key}=$q->param($param_key);
432       if ($param_key=~/^(phe|theta|hmdisp)$/) {
433         $param->{$param_key}=$param->{$param_key}/180*pi;
434       }
435     }
436   }
437   if ($q->param('disp_hm_angle') =~ /on/) {
438     $param->{'disp_hm_angle'}=1;
439   }
440   else {
441     $param->{'disp_hm_angle'}=0;
442   }
443   if ($q->param('reverse_helix') =~ /on/) {
444     $param->{'reverse_helix'}=1;
445   }
446   else {
447     $param->{'reverse_helix'}=0;
448   }
449   if ($q->param('wo_color') =~ /on/) {
450     $param->{'wifcolor'}=0;
451   }
452   else {
453     $param->{'wifcolor'}=1;
454   }
455   my $im = new GD::Image($param->{xsize},$param->{ysize});
456   $param->{white} = $im->colorAllocate(255,255,255);
457   $param->{black} = $im->colorAllocate(0,0,0);
458   $param->{red} = $im->colorAllocate(255,0,0);
459   $param->{blue} = $im->colorAllocate(0,0,255);
460   foreach my $aminoacid (keys %{$param->{aa}}) {
461     if ($param->{wifcolor} && $param->{aa}->{$aminoacid}->{wif}<=$param->{maxwif} && !(defined $param->{aa}->{$aminoacid}->{charged} && $param->{aa}->{$aminoacid}->{charged})) {
462       $param->{aa}->{$aminoacid}->{fcolor} =
463         $im->colorAllocate(min(($param->{aa}->{$aminoacid}->{wif}-$param->{minwif})/
464                                (0-$param->{minwif})*255,255),
465                            255-max(($param->{aa}->{$aminoacid}->{wif})/
466                                    ($param->{maxwif}),0)*255,0);
467     }
468     elsif ($param->{wifcolor} && defined $param->{aa}->{$aminoacid}->{border}) {
469       $param->{aa}->{$aminoacid}->{fcolor} = $im->colorAllocate($param->{aa}->{$aminoacid}->{border}[0],
470                                                       $param->{aa}->{$aminoacid}->{border}[1],
471                                                       $param->{aa}->{$aminoacid}->{border}[2]);
472     }
473     else {
474       $param->{aa}->{$aminoacid}->{fcolor} = $param->{black};
475     }
476     if ($param->{wifcolor} && $param->{aa}->{$aminoacid}->{wif}<=$param->{maxwif} && !(defined $param->{aa}->{$aminoacid}->{charged} && $param->{aa}->{$aminoacid}->{charged})) {
477       $param->{aa}->{$aminoacid}->{bcolor} =
478         $im->colorAllocate(min(($param->{aa}->{$aminoacid}->{wif}-$param->{minwif})/
479                                (0-$param->{minwif})*255,255),
480                            255-max(($param->{aa}->{$aminoacid}->{wif})/
481                                    ($param->{maxwif}),0)*255,0);
482     }
483     elsif ($param->{wifcolor} && defined $param->{aa}->{$aminoacid}->{fill}) {
484       $param->{aa}->{$aminoacid}->{bcolor} = $im->colorAllocate($param->{aa}->{$aminoacid}->{fill}[0],
485                                                       $param->{aa}->{$aminoacid}->{fill}[1],
486                                                       $param->{aa}->{$aminoacid}->{fill}[2]);
487     }
488     else {
489       $param->{aa}->{$aminoacid}->{bcolor} = $param->{white};
490     }
491   }
492 # Draw Bounding Box
493 #  $im->rectangle(0,0,$param->{xsize}-1,$param->{ysize}-1,$param->{black});
494   my $aasequence = $q->param('sequence');
495   $aasequence =~ s/[^AC-IK-NP-TV-WY]//gs;
496   if ($param->{reverse_helix}) {
497     my $aaseq=$aasequence;
498     $param->{indexaa}*=-1;
499     my $numberofaa=0;
500     $aasequence='';
501     foreach my $aa(split(//,$aaseq)) {
502       $aasequence = $aa . $aasequence;
503       $numberofaa++;
504     }
505     $param->{indexaa}-=$numberofaa-1;
506     $param->{theta}*=-1;
507   }
508   print STDERR "hmdisp: $param->{hmdisp}\n";
509   if ($param->{'hmdisp'} =~ /^(\-{0,1}\d*\.{0,1}\d+)$/) {
510     my ($x,$y) = calculate_hydrophobic_moment($aasequence,$param);
511     $param->{phe} = - deg2rad(xy2deg($x,-$y)) + $param->{'hmdisp'};
512     print STDERR $param->{phe};
513   }
514   draw_wheel($im,$aasequence,$param);
515   print $q->header(-type=>'image/png');
516   print $im->png;
517
518 }
519
520 else {
521   print $q->header();
522   print $q->start_html('Helical Wheel Projections');
523   if (defined $q->param('submit') and $q->param('submit')=~/Submit/) {
524     print $q->h1('Wheel:'.$q->param('sequence'));
525     print $q->img({-src=>$q->self_url.'&draw=yes'});
526
527     print <<OUT
528 <table width="400"><tr><td>By default the output presents the
529 hydrophilic residues as circles, hydrophobic residues as diamonds,
530 potentially negatively charged as triangles, and potentially
531 positively charged as pentagons. Hydrophobicity is color coded as
532 well: the most hydrophobic residue is green, and the amount of green
533 is decreasing proportionally to the hydrophobicity, with zero
534 hydrophobicity coded as yellow. Hydrophilic residues are coded red
535 with pure red being the most hydrophilic (uncharged) residue, and the
536 amount of red decreasing proportionally to the hydrophilicity. The
537 potentially charged residues are light blue. (The color will not apply
538 if you turn off color.)</td></tr></table>
539 OUT
540
541   }
542   print $q->h1('Helical Wheel Projections'),
543     $q->start_form(-method=>'GET'),
544       $q->table($q->Tr([
545                         $q->td({-bgcolor=>'#ddddff'},['Sequence:',
546                                                       $q->textarea(-name=>'sequence',
547                                                                    -rows=>5,
548                                                                    -columns=>50)
549                                                      ]),
550                         $q->td({-bgcolor=>'#bbbbff'},['Initial AA Number:',
551                                                       $q->textfield(-name=>'indexaa',
552                                                                     -size=>5,
553                                                                     -maxlength=>5
554                                                                    )
555                                                      ]),
556                         $q->td({-bgcolor=>'#ddddff'},['Initial AA Rotation:',
557                                                       $q->textfield(-name=>'phe',
558                                                                     -size=>6,
559                                                                     -maxlength=>6)
560                                                      ]),
561                         $q->td({-bgcolor=>'#ddddff'},['Per AA Rotation:',
562                                                       $q->textfield(-name=>'theta',
563                                                                     -size=>6,
564                                                                     -maxlength=>6)
565                                                      ]),
566                           $q->td({-bgcolor=>'#bbbbff'},['Xsize:',
567                                                         $q->textfield(-name=>'xsize',
568                                                                       -size=>5,
569                                                                       -maxlength=>5)
570                                                        ]),
571                           $q->td({-bgcolor=>'#ddddff'},['Ysize:',
572                                                         $q->textfield(-name=>'ysize',
573                                                                       -size=>5,
574                                                                       -maxlength=>5)
575                                                        ]),
576                           $q->td({-bgcolor=>'#bbbbff'},['CenterX:',
577                                                         $q->textfield(-name=>'centerx',
578                                                                       -size=>5,
579                                                                       -maxlength=>5)
580                                                        ]),
581                           $q->td({-bgcolor=>'#ddddff'},['CenterY:',
582                                                         $q->textfield(-name=>'centery',
583                                                                       -size=>5,
584                                                                       -maxlength=>5)
585                                                        ]),
586                           $q->td({-bgcolor=>'#bbbbff'},['Connection Width:',
587                                                         $q->textfield(-name=>'w',
588                                                                       -size=>5,
589                                                                       -maxlength=>5)
590                                                        ]),
591                           $q->td({-bgcolor=>'#ddddff'},['Symbol Size:',
592                                                         $q->textfield(-name=>'r',
593                                                                       -size=>5,
594                                                                       -maxlength=>5)
595                                                        ]),
596                           $q->td({-bgcolor=>'#bbbbff'},['Font Size:',
597                                                         $q->textfield(-name=>'fontsize',
598                                                                       -size=>5,
599                                                                       -maxlength=>5)
600                                                        ]),
601                           $q->td({-bgcolor=>'#ddddff'},['Graph Radius:',
602                                                         $q->textfield(-name=>'d',
603                                                                       -size=>5,
604                                                                       -maxlength=>5)
605                                                        ]),
606                           $q->td({-bgcolor=>'#bbbbff'},['HM Font Size:',
607                                                         $q->textfield(-name=>'fontsize2',
608                                                                       -size=>5,
609                                                                       -maxlength=>5)
610                                                        ]),
611                           $q->td({-bgcolor=>'#ddddff'},['HM Scale:',
612                                                         $q->textfield(-name=>'hmscale',
613                                                                       -size=>5,
614                                                                       -maxlength=>5)
615                                                        ]),
616                           $q->td({-bgcolor=>'#bbbbff'},['Display HM Angle:',
617                                                         $q->checkbox(-name=>'disp_hm_angle',
618                                                                     -checked=>'checked',
619                                                                     -label=>'')
620                                                        ]),
621                           $q->td({-bgcolor=>'#ddddff'},['Reverse Helix:',
622                                                       $q->checkbox(-name=>'reverse_helix',
623                                                                   -label=>'')
624                                                       ]),
625                           $q->td({-bgcolor=>'#bbbbff'},['No Color:',
626                                                       $q->checkbox(-name=>'wo_color',
627                                                                   -label=>'')
628                                                       ]),
629                           $q->td({-bgcolor=>'#ddddff'},['Hydrophobic Moment Displacement:',
630                                                       $q->textfield(-name=>'hmdisp',
631                                                                    -size=>5,
632                                                                    -maxlength=>5)
633                                                       ]),
634                           $q->td({-bgcolor=>'#bbbbff',-colspan=>2},
635                                  [$q->center($q->submit(-name=>'submit',-value=>'Submit'))
636                                  ]),
637                          ])
638                  ),
639           $q->endform,
640             $q->hr,$q->i("Created by ".$q->a({-href=>"mailto:don\@donarmstrong.com"},'Don Armstrong')." and Raphael Zidovetzki. Version: ".$q->b($VERSION));
641 }
642