[Bio] / FigWebServices / pir.cgi Repository:
ViewVC logotype

Annotation of /FigWebServices/pir.cgi

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.22 - (view) (download)

1 : redwards 1.1 # -*- perl -*-
2 :    
3 :     =pod
4 :    
5 :     =head1
6 :    
7 :     Compare some data between SEED and PIR. We probably need to add things like p2p or automatic ftp gets or something like that
8 :    
9 :     =cut
10 :    
11 :     use strict;
12 :     use FIG;
13 :     use HTML;
14 :     use raelib;
15 :     use CGI;
16 :     my $cgi=new CGI;
17 : redwards 1.22 use LWP::Simple qw(!head); # see the caveat in perldoc LWP about importing two head methods.
18 : redwards 1.1
19 :     my $fig;
20 :     eval {
21 :     $fig = new FIG;
22 :     };
23 :    
24 :     if ($@ ne "")
25 :     {
26 :     my $err = $@;
27 :    
28 :     my(@html);
29 :    
30 :     push(@html, $cgi->p("Error connecting to SEED database."));
31 :     if ($err =~ /Could not connect to DBI:.*could not connect to server/)
32 :     {
33 :     push(@html, $cgi->p("Could not connect to relational database of type $FIG_Config::dbms named $FIG_Config::db on port $FIG_Config::dbport."));
34 :     }
35 :     else
36 :     {
37 :     push(@html, $cgi->pre($err));
38 :     }
39 :     &HTML::show_page($cgi, \@html, 1);
40 :     exit;
41 :     }
42 :    
43 :    
44 :    
45 :     $ENV{"PATH"} = "$FIG_Config::bin:$FIG_Config::ext_bin:" . $ENV{"PATH"};
46 :    
47 : redwards 1.22
48 :     # these should probably be in FIG::Config. Oh well.
49 :     my $pir_file_from_pir="$FIG_Config::data/Global/pirsfinfo.dat";
50 :     my $pir_correspondence_file="$FIG_Config::data/Global/pirsfcorrespondence.txt";
51 :     my $pir_source_file="ftp://ftp.pir.georgetown.edu/pir_databases/pirsf/data/pirsfinfo.dat";
52 :    
53 :     # ha ha ha ha ha
54 :     # I am an idiot, and can't spell. so we need to correct that and make sure we always use an e
55 :     if (-e "$FIG_Config::data/Global/pirsfcorrespondance.txt") {rename("$FIG_Config::data/Global/pirsfcorrespondance.txt", $pir_correspondence_file)}
56 :    
57 :    
58 :    
59 : redwards 1.1 my $html = [];
60 :     my $user = $cgi->param('user');
61 :    
62 : redwards 1.19 unshift(@$html, "<TITLE>The SEED - PIR/SEED comparisons </TITLE>\n");
63 : redwards 1.1 # make sure that we read the file at the beginning
64 : redwards 1.22 my ($pegbypir, $pirid) =&read_pir_file("initial");
65 :    
66 :     # if we are going to update the data, we do that and then we present the blank form with the new data
67 :     # this will also reset $pegbypir and $pirid
68 :     if ($cgi->param('submit') =~ m/^Update/) {
69 :     # this should catch Update Data and Updata Anyway
70 :     ($html, $pegbypir, $pirid)=&update_data($html);
71 :     }
72 : redwards 1.1
73 :    
74 :    
75 :    
76 : redwards 1.17 if ($cgi->param('submit') eq "Tabulate summary") {
77 : redwards 1.9 $html=&table_annotations($html, $pegbypir, $pirid);
78 : redwards 1.22 push @$html, $cgi->p({class=>"diagnostic"}, ("\n<small>Generating this table took approximately " . (time-$^T) . " seconds\n</small>"));
79 :     }
80 :     elsif ($cgi->param('submit') eq "Check for updates") {
81 :     $html=&check_updates($html);
82 :     push @$html, $cgi->p({class=>"diagnostic"}, ("\n<small>Checking for updates took approximately " . (time-$^T) . " seconds\n</small>"));
83 : redwards 1.5 }
84 : redwards 1.17 elsif ($cgi->param('pirsf') && !($cgi->param('submit') eq "Update view")) {
85 : overbeek 1.21 # we want to display one of the correspondences
86 : redwards 1.5 my $selfurl=$cgi->url;
87 : redwards 1.22 push @$html, $cgi->p, "<a href=\"/FIG/Html/pir.html#correspondence\" class=\"help\" target=\"_blank\">Help on this correspondence table</a>";
88 :     if ($cgi->param('ssonly')) {push @$html, "<a href=\"$selfurl?pirsf=" . $cgi->param("pirsf") . "&user=$user\">Show All Matches</a>\n"}
89 :     else {push @$html, "<a href=\"$selfurl?pirsf=" . $cgi->param("pirsf") . "&ssonly='1'&user=$user\">Show only matches with a subsystem</a>\n"}
90 : redwards 1.5
91 : overbeek 1.21 my $col_hdrs = ["PIR Superfamily<br><small>Link goes to PIR<small>", "Genome", "UniProt","PEG", "FIG Function", "FIG Subsystem"];
92 : redwards 1.1 my $tab = [];
93 : redwards 1.22
94 :     # figure out the colors
95 :     my %function_cnt; my $max;
96 :     foreach my $peg (@{$pegbypir->{$cgi->param('pirsf')}}) {
97 :     my $fn=scalar $fig->function_of($peg);
98 :     $function_cnt{$fn}++;
99 :     if ($function_cnt{$fn} > $max) {$max=$function_cnt{$fn}}
100 :     }
101 :    
102 :     my @color=&cool_colors();
103 :    
104 :    
105 : redwards 1.2 foreach my $peg (@{$pegbypir->{$cgi->param('pirsf')}}) {
106 : redwards 1.1 my @sslinks;
107 :     foreach my $subsys ($fig->subsystems_for_peg($peg)) {
108 : redwards 1.22 my $spaced=$$subsys[0];
109 :     $spaced =~ s/_/ /g;
110 :     push @sslinks, $cgi->a({href => "subsys.cgi?&user=$user&ssa_name=" . $$subsys[0] . "&request=show_ssa"}, $spaced);
111 : redwards 1.1 }
112 :    
113 :     my $pirlink=$cgi->param('pirsf');
114 : redwards 1.2 $pirlink =~ /^PIR(SF\d+)/;
115 :     $pirlink="<a href='http://pir.georgetown.edu/sfcs-cgi/new/pirclassif.pl?id=$1'>PIR$1</a>" . $pirid->{$cgi->param('pirsf')};
116 : redwards 1.4 next if ($cgi->param("ssonly") && !(scalar @sslinks));
117 : redwards 1.22 my $colornumber=$max - $function_cnt{scalar $fig->function_of($peg)}; # the most abundant function gets the first color
118 :     my $color="#FFFFFF";
119 :     if ($colornumber <= $#color) {$color=$color[$colornumber]}
120 :     push (@$tab,
121 :     [$pirlink,
122 :     $fig->genus_species($fig->genome_of($peg)),
123 :     &HTML::uni_link($cgi,$fig->to_alias($peg,"uni")),
124 :     &HTML::fid_link($cgi, $peg, 1),
125 :     [scalar $fig->function_of($peg), "td style=\"background: $color\""],
126 :     (join ", ", @sslinks)]
127 :     );
128 : redwards 1.1 }
129 : redwards 1.22 push(@$html,&HTML::make_table($col_hdrs,$tab,"\nCorrespondence between SEED and PIR"));
130 : redwards 1.1 }
131 :     else {
132 :     unshift @$html, "<TITLE>The SEED - PIR comparison page</TITLE>\n";
133 :     &show_initial($fig,$cgi,$html);
134 :     }
135 :    
136 :     &HTML::show_page($cgi,$html,1);
137 :     exit;
138 :    
139 :    
140 :    
141 :    
142 :    
143 :     sub show_initial {
144 :     my ($fig,$cgi,$html)=@_;
145 :     # generate a blank page
146 :     # we want a list of all functions that have >= 1 peg unless we want all
147 :     my $min=10;
148 :     if ($cgi->param("min")) {$min=$cgi->param("min")}
149 :     if ($cgi->param("showall")) {$min=0}
150 :     my $full=1;
151 :     if ($cgi->param("preliminary")) {$full=0}
152 :     # count different subsystems per sf
153 :     my $ss; my @pirsf;
154 : redwards 1.2 foreach my $sf (keys %$pegbypir) {
155 :     next unless ($pegbypir->{$sf});
156 :     next unless (scalar @{$pegbypir->{$sf}} >= $min);
157 :     next if ($full && $pirid->{$sf} =~ /\(preliminary\)/i);
158 :     next if (!$full && $pirid->{$sf} =~ /\(full/i);
159 : redwards 1.1 push @pirsf, $sf;
160 :     if ($cgi->param('showsubsys')) {
161 : redwards 1.2 foreach my $peg (@{$pegbypir->{$sf}}) {
162 : redwards 1.1 foreach my $subsys ($fig->subsystems_for_peg($peg)) {
163 :     $ss->{$sf}->{$$subsys[0]}++;
164 :     }
165 :     }
166 :     }
167 :     }
168 :    
169 :     # now generate the labels
170 :     my $display;
171 :     foreach my $sf (@pirsf) {
172 :     next unless ($sf);
173 : redwards 1.2 my $displayname=$pirid->{$sf};
174 : redwards 1.1 if (length($displayname) > 50) {$displayname=substr($displayname, 0, 50)}
175 : redwards 1.2 if ($cgi->param('showsubsys')) {$display->{$sf}=$displayname . " [". scalar @{$pegbypir->{$sf}} . "/". (scalar keys %{$ss->{$sf}}) . "]"}
176 :     else {$display->{$sf}=$displayname . " [". scalar @{$pegbypir->{$sf}} . "]"}
177 : redwards 1.1 }
178 :     unshift @pirsf, ''; $display->{''}='';
179 :    
180 : redwards 1.22
181 : redwards 1.1 push (@$html, $cgi->start_form(-action => "pir.cgi"),
182 :     $cgi->h2("Please choose your super family"),
183 : redwards 1.22 "\nFirst, please enter a username: ", $cgi->textfield(-name=>"user", -value=>$user), $cgi->p,
184 :     "\n<a href=\"/FIG/Html/pir.html\" class=\"help\" target=\"_blank\">Help on SEED/PIR Correspondence</a>",
185 :     "\nThe list shows the PIR superfamilies. If only one number is shown (default) this is the number of PEGs that map to that superfamily. ",
186 :     "\nIf you choose to show subsystem counts in this menu, you will get two numbers. The first of the two numbers in parenthesis is the number ",
187 :     "\nof PEGs that map to that superfamily, and the second number in parenthesis is the number of <em>different</em> ",
188 :     "\nsubsystems that those PEGs are in.\n", $cgi->p,"\n",
189 :     $cgi->scrolling_list(-name=>'pirsf', -values=>[keys %$display], -labels=>$display, -size=>10), $cgi->p,"\n",
190 :     "\nNummber of superfamilies shown: ", scalar keys %$display, $cgi->p,"\n",
191 :     "\n<a href=\"/FIG/Html/pir.html#menu\" class=\"help\" target=\"_blank\">Help on the menu contents</a>","\n",
192 :     "\nMinimum number of pegs per PIR superfamily shown in list &nbsp; <input type='text' name='min' value='$min' size=3 />","\n",
193 :     "\nor show all PIR superfamilies: ", $cgi->checkbox(-name=>"showall", -label=>""), $cgi->p,"\n",
194 :     $cgi->checkbox(-name=>"showsubsys", -label=>"Show subsystem counts in list"), $cgi->p,"\n",
195 :     $cgi->checkbox(-name=>"preliminary", -label=>"Show only preliminary PIR superfamilies"), $cgi->p,"\n",
196 :     $cgi->submit('submit', 'Update view'),"\n",
197 :     $cgi->submit('submit', 'Show Correspondence'),"\n",
198 :     $cgi->reset,"\n",
199 :     $cgi->p, $cgi->hr, $cgi->p,"\n",
200 :     $cgi->p("<strong>Generate Data Tables</strong>"),
201 :     "<a href=\"/FIG/Html/pir.html#datatables\" class=\"help\" target=\"_blank\">Help on Generating Data Tables</a>",
202 :     $cgi->p("The data tables are an alternative way to view the data in summary form. For the summary of the comparisons between PIR and SEED annotations, please check here:\n"),
203 :     $cgi->checkbox(-name=>"onlyss", -label=>"Show only those PEGs that are in a subsystem and a superfamily", -checked=>"on"), $cgi->p,"\n",
204 :     $cgi->checkbox(-name=>"totalsort", -label=>"Sort by the total number of different annotations"), $cgi->p,"\n",
205 :     $cgi->submit('submit', 'Tabulate summary'),"\n",
206 :     $cgi->reset,"\n",
207 :     $cgi->p, $cgi->hr, "\n",
208 :     $cgi->p("<strong>Check for Updates</strong>"),"\n",
209 :     "<a href=\"/FIG/Html/pir.html#updates\" class=\"help\" target=\"_blank\">Help on updates</a>", "\n",
210 :     $cgi->p("Please click the button to check the PIR site and see whether there is a new version of the PIR superfamily data you should use"),"\n",
211 :     $cgi->submit('submit', 'Check for updates'),"\n",
212 : redwards 1.1 $cgi->end_form,
213 :     );
214 :    
215 :     }
216 :    
217 :    
218 :    
219 :     =head1 read_pir_file
220 :    
221 :     Read the PIR data file that describes superfamilies and the PIR proteins that have those families.
222 :     The PIR data file is from ftp://ftp.pir.georgetown.edu/pir_databases/pirsf/data/pirsfinfo.dat and
223 :     contains the family name beginning with a > and then a list of PIR ids.
224 :    
225 : redwards 1.2 I split this using the PIRSF\d+ and return two hashes. One that correlates PIRSF\d+ to fig id and one
226 :     that correlates it to superfamily names.
227 : redwards 1.1
228 :     =cut
229 :    
230 :     sub read_pir_file {
231 : redwards 1.22 my ($caller)=@_;
232 :     # make sure that we have the files, and if not use the update mechanism to get them. This is a little recursive
233 :     # since the update method calls this method, so we have a check for this
234 :     unless (-e $pir_file_from_pir) {
235 :     if ($caller eq "update_data") {
236 :     die "read_pir_file was called from the update method, but there is no file to read, and so we were going to enter an endless loop";
237 :     }
238 :    
239 :     # because this is receursive, update_data will call this method and use the output from that. I think this could be a horrible nightmare,
240 :     # but we'll see what happens. Fun, eh?
241 :     my ($pegbypir, $pirid);
242 :     ($html, $pegbypir, $pirid)=update_data($html);
243 :     return ($pegbypir, $pirid);
244 :     }
245 : redwards 1.1
246 : redwards 1.22
247 :     # just read the file, convert it to an HTML table and return it
248 :     unless (-e $pir_correspondence_file) {
249 :     #print STDERR "Can't find the correspondence file pirsfcorrespondence.txt so we are going to make it\n";
250 :     raelib->pirsfcorrespondence($pir_file_from_pir, $pir_correspondence_file);
251 : redwards 1.1 }
252 : redwards 1.22 open (IN, $pir_correspondence_file) || die "Can't open $pir_correspondence_file";
253 : redwards 1.1 my $pir;
254 : redwards 1.2 my $functions;
255 :     my $id;
256 : redwards 1.1 my $added;
257 :     while (<IN>) {
258 :     chomp;
259 :     if (s/^>//) {
260 :     unless ($added) {
261 :     # we didn't find anything that maps here
262 : redwards 1.2 $pir->{$id}=undef;
263 : redwards 1.1 }
264 : redwards 1.2 /^(PIRSF\d+)\s+(.*?)$/;
265 :     $id=$1;
266 :     $functions->{$id}=$2;
267 : redwards 1.1 undef $added;
268 :     }
269 :     else {
270 : redwards 1.2 my ($pirid, $peg)=split /\t/;
271 : redwards 1.1 next unless ($peg);
272 : redwards 1.2 push @{$pir->{$id}}, $peg;
273 : redwards 1.1 $added=1;
274 :     }
275 :     }
276 : redwards 1.2 return $pir, $functions;
277 : redwards 1.1 }
278 : redwards 1.5
279 : redwards 1.9 =head1 table_annotations
280 : redwards 1.5
281 : redwards 1.9 Return a table sorted by the number of annotations, and list a bunch of stuff
282 : redwards 1.5
283 :     =cut
284 :    
285 : redwards 1.9 sub table_annotations {
286 :     my ($html, $pegbypir, $pirid)=@_;
287 : redwards 1.12 my $count; my $subsystems; my $countinss;
288 : redwards 1.9 foreach my $sf (keys %$pegbypir) {
289 : redwards 1.12 my $function; my $ss; my $functionandss;
290 : redwards 1.9 foreach my $peg (@{$pegbypir->{$sf}}) {
291 : redwards 1.13 my $fn=scalar $fig->function_of($peg);
292 : redwards 1.16 my $newss=0; # this is a boolean to see whether this peg has a subsys associated with it.
293 :     foreach my $subsys ($fig->subsystems_for_peg($peg)) {$ss->{$$subsys[0]}++; $newss++}
294 : redwards 1.13 $function->{$fn}++;
295 : redwards 1.16 $functionandss->{$fn}++ if ($newss);
296 : redwards 1.5 }
297 : redwards 1.9 $subsystems->{$sf}=join "; ", keys %$ss;
298 :     $count->{$sf}=scalar keys %$function;
299 : redwards 1.12 $countinss->{$sf}=scalar keys %$functionandss;
300 : redwards 1.5 }
301 :    
302 : redwards 1.12 my $col_hdrs = ["Number of annotations in subsystems", "Number of SEED annotations", "PIRSF<br><small>(Link goes to SEED/PIR comparison)</small>",
303 : redwards 1.6 "Superfamily name", "Subsystems in superfamily"];
304 : redwards 1.10 my $tab; my $lastcount; my $row;
305 : redwards 1.12 # note we are going to make a new table every 200 or so rows because that way the browsers don't get messed up. We actually increment between two identical counts
306 :     my @superfamilies=sort {$countinss->{$b} <=> $countinss->{$a}} keys %$count;
307 :     if ($cgi->param('totalsort')) {@superfamilies=sort {$count->{$b} <=> $count->{$a}} keys %$count}
308 :     foreach my $sf (@superfamilies) {
309 :     next if ($cgi->param('onlyss') && !($countinss->{$sf}));
310 : redwards 1.10 $row++;
311 : redwards 1.9 if ($lastcount ne $count->{$sf}) {
312 :     $lastcount=$count->{$sf};
313 : redwards 1.12 if ($tab && ($row > 200)) {
314 : redwards 1.10 push(@$html,&HTML::make_table($col_hdrs,$tab,""));
315 : redwards 1.18 my $et=time-$^T;
316 :     print STDERR "pir.cgi: Added to table at $lastcount after $et total seconds\n";
317 : redwards 1.10 $row=0;
318 :     undef $tab;
319 :     }
320 : redwards 1.9 }
321 :     push @$tab, [
322 : redwards 1.22 "\n".$countinss->{$sf},
323 : redwards 1.9 $count->{$sf},
324 : redwards 1.22 "<a href=\"/FIG/pir.cgi?pirsf=$sf&ssonly='1'&user='$user'\">$sf</a>",
325 : redwards 1.9 $pirid->{$sf},
326 :     $subsystems->{$sf},
327 :     ];
328 : redwards 1.5 }
329 : redwards 1.6 push(@$html,&HTML::make_table($col_hdrs,$tab,""));
330 : redwards 1.5 return $html;
331 :     }
332 : redwards 1.22
333 :    
334 :     =pod
335 :    
336 :     =head2 check_updates()
337 :    
338 :     Check the PIR remote site and see whether there are updates that we need to get
339 :    
340 :     =cut
341 :    
342 :     sub check_updates {
343 :     my $html=shift;
344 :    
345 :     # first lets see if we can get the times of the updates to see if we have a newer file
346 :     # using LWP::Simple. this is straight from the perldoc
347 :     my ($content_type, $document_length, $remotemtime, $expires, $server)=LWP::Simple::head($pir_source_file);
348 :     my $localmtime=0;
349 :     # if we don't have the file yet, we don't want to panic!
350 :     if (-e $pir_file_from_pir) {
351 :     my @stat=stat($pir_file_from_pir);
352 :     $localmtime=$stat[8];
353 :     }
354 :     # now we are going to translate the difference in times into some English for the website
355 :     if (!$remotemtime) {
356 :     push @$html, $cgi->p({class=>"error"}, "Could not connect to PIR to check the status of the PIR file. Please check the location of $pir_source_file");
357 :     }
358 :     elsif ($remotemtime > $localmtime) {
359 :     # the remote version is newer
360 :     push @$html, $cgi->p("\nThe remote file $pir_source_file is newer than your current file. You should proceed with the update."),
361 :     $cgi->p("\nThe remote file was modified on ". scalar(localtime($remotemtime))),
362 :     $cgi->p("\nThe local file was modified on ". scalar(localtime($localmtime))),
363 :     $cgi->start_form(), $cgi->hidden(-name=>"user", -value=>$user), $cgi->submit('submit', 'Update Data'), $cgi->end_form();
364 :     }
365 :     else {
366 :     # the local version is as new as the remote one.
367 :     push @$html, $cgi->p("\nThe local file is up to date and there is no need to update your source PIR superfamilies."),
368 :     $cgi->p("\nThe remote file was modified on ". scalar(localtime($remotemtime))),
369 :     $cgi->p("\nThe local file was modified on ". scalar(localtime($localmtime))),
370 :     $cgi->start_form(), $cgi->hidden(-name=>"user", -value=>$user), $cgi->submit('submit', 'Update Anyway'), $cgi->end_form();
371 :     }
372 :    
373 :     return $html;
374 :     }
375 :    
376 :    
377 :     =pod
378 :    
379 :     =head2 update_data()
380 :    
381 :     Download the new data file from pir, and generate the correspondence
382 :    
383 :     =cut
384 :    
385 :     sub update_data {
386 :     # rename the old correspondence file. We are going to add a number to the old file so that we keep it, but this should allow us
387 :     # to save the information for a while in case something happens. At somepoint we should probably move these to /tmp or delete them
388 :     # or something.
389 :     my $html=shift;
390 :     my $count=1;
391 :     while (-e "$pir_file_from_pir.$count") {$count++}
392 :     rename($pir_file_from_pir, "$pir_file_from_pir.$count");
393 :     rename($pir_correspondence_file, "$pir_correspondence_file.$count");
394 :    
395 :     # now use LWP to get the data
396 :     my $gotit=LWP::Simple::getstore($pir_source_file, $pir_file_from_pir);
397 :    
398 :     unless ($gotit) {
399 :     push @$html, "<h1>WARNING: There was an error downloading the data from $pir_source_file to $pir_file_from_pir. The old data was retained</h1>";
400 :     rename("$pir_file_from_pir.$count", $pir_file_from_pir);
401 :     rename("$pir_correspondence_file.$count", $pir_correspondence_file);
402 :     }
403 :    
404 :     # now we just need to instantiate the new data
405 :     # we can just delegate this to read_pir_file for us
406 :     ($pegbypir, $pirid) =&read_pir_file("update_data");
407 :    
408 :     push @$html, "<h1 style=\"background: lightblue\">SUCCESS. The new data was installed and is shown in the table below</h1>";
409 :     return $html, $pegbypir, $pirid;
410 :     }
411 :    
412 :    
413 :    
414 :    
415 :    
416 :    
417 :     sub cool_colors {
418 :     # just an array of "websafe" colors or whatever colors we want to use. Feel free to remove bad colors (hence the lines not being equal length!)
419 :     return (
420 :     '#C0C0C0', '#FF40C0', '#FF8040', '#FF0080', '#FFC040', '#40C0FF', '#40FFC0', '#C08080', '#C0FF00', '#00FF80', '#00C040',
421 :     "#6B8E23", "#483D8B", "#2E8B57", "#008000", "#006400", "#800000", "#00FF00", "#7FFFD4",
422 :     "#87CEEB", "#A9A9A9", "#90EE90", "#D2B48C", "#8DBC8F", "#D2691E", "#87CEFA", "#E9967A", "#FFE4C4", "#FFB6C1",
423 :     "#E0FFFF", "#FFA07A", "#DB7093", "#9370DB", "#008B8B", "#FFDEAD", "#DA70D6", "#DCDCDC", "#FF00FF", "#6A5ACD",
424 :     "#00FA9A", "#228B22", "#1E90FF", "#FA8072", "#CD853F", "#DC143C", "#FF6347", "#98FB98", "#4682B4",
425 :     "#D3D3D3", "#7B68EE", "#FF7F50", "#FF69B4", "#BC8F8F", "#A0522D", "#DEB887", "#00DED1",
426 :     "#6495ED", "#800080", "#FFD700", "#F5DEB3", "#66CDAA", "#FF4500", "#4B0082", "#CD5C5C",
427 :     "#EE82EE", "#7CFC00", "#FFFF00", "#191970", "#FFFFE0", "#DDA0DD", "#00BFFF", "#DAA520",
428 :     "#00FF7F", "#9400D3", "#BA55D3", "#D8BFD8", "#8B4513", "#3CB371", "#5F9EA0", "#4169E1", "#20B2AA", "#8A2BE2", "#ADFF2F",
429 :     "#F0FFFF", "#B0E0E6", "#FF1493", "#B8860B", "#FF0000", "#F08080", "#7FFF00", "#8B0000",
430 :     "#40E0D0", "#0000CD", "#48D1CC", "#8B008B", "#696969", "#AFEEEE", "#FF8C00", "#EEE8AA", "#A52A2A",
431 :     "#FFE4B5", "#B0C4DE", "#FAF0E6", "#9ACD32", "#B22222", "#FAFAD2", "#808080", "#0000FF",
432 :     "#000080", "#32CD32", "#FFFACD", "#9932CC", "#FFA500", "#F0E68C", "#E6E6FA", "#F4A460", "#C71585",
433 :     "#BDB76B", "#00FFFF", "#FFDAB9", "#ADD8E6", "#778899",
434 :     );
435 :     }
436 :    

MCS Webmaster
ViewVC Help
Powered by ViewVC 1.0.3