root/cached_images/trunk/cached_images/cacheJob.pl

Revision 35 (checked in by jcleary, 4 years ago)

various changes for Cached Obs Image migration milestone

Line 
1 #!/usr/bin/perl -wT
2 ##!/afs/isis/pkg/perl/bin/perl -wT
3
4 =head1 Copyright (E<copy>) 2004 University of North Carolina at Chapel Hill
5
6                 Department of Marine Science
7                 All Rights Reserved
8
9 =head1 NAME
10
11 cacheJob.pl - generate a set of map images for serving from a cache
12
13 =head1 AUTHOR
14
15 Jesse Cleary E<lt>F<jcleary@email.unc.edu>E<gt> and Chris Calloway E<lt>F<cbc@unc.edu>E<gt>
16
17 =head1 SYNOPSIS
18
19 in B</etc/syslog.conf> add B<local6.none> to the B</var/log/messages> rule
20
21 in B</etc/syslog.conf> add B<local6.*> to a new rule for B</var/log/cachebot.log>
22
23 in B</etc/logrotate.conf> add the following to the bottom of the file:
24
25 =begin html
26
27 <pre>
28         /var/log/cachebot.log {
29                 weekly
30                 create 0644 root root
31                 rotate 4
32         }
33 </pre>
34
35 =end html
36
37 restart syslogd by issuing B<sudo /etc/init.d/syslog restart>
38
39 B<sudo mkdir /var/www/html/images> and <sudo chown root:root> and B<sudo chmod 755>
40
41 B<sudo mkdir /var/www/html/images/mapCache> and B<sudo chown root:root> and B<sudo chmod 755>
42
43 in B<cacheJob.pl> make sure B<my $output_dir = '/var/www/html/images/mapCache';>
44
45 in B<cacheJob.pl> make sure B<use lib '/usr/local/bin';>
46
47 B<sudo mkdir /usr/local/bin/secoora> and B<sudo chown root:root> and B<sudo chmod 755>
48
49 B<sudo cp CacheBot.pm /usr/local/bin/secoora> and B<sudo chown root:root> and B<sudo chmod 755>
50
51 B<sudo cp cacheJob.pl /usr/local/bin> and B<sudo chown root:root> and B<sudo chmod 755>
52
53 B<sudo mkdir /etc/cron.hourlyCache> and B<sudo chown root:root> and B<sudo chmod 755>
54
55 B<sudo ln -s /usr/local/bin/cacheJob.pl /etc/cron.hourlyCache/cacheMapImages>
56
57 in B</etc/crontab> add rule for B<25 * * * * root run-parts /etc/cron.hourlyCache>
58
59 restart crond by issuing B<sudo /etc/init.d/crond restart>
60
61 keep tabs on progress with B<tail -f /var/log/cachebot.log>
62
63 =head1 DESCRIPTION
64
65 cacheJob.pl is a Perl script to generate a set of map images for serving from a cache.
66
67 The set of images is described by a metadata schema stored in arrays of hashes within this script.
68 Properly developed these hashes should be the target of an XSLT backed by a database.
69
70 Each array describes a metalayer in a physical file hierarchy resulting in the cache.
71 Each hash in the array describes a possible instantiation of a metalayer in the cache.
72
73 The metatlayers, in hierarchical order, are:
74
75 =over 4
76
77 =item data_type
78
79 The synoptic and diachronic classification of the image data.
80
81 Common metalayers represent possible instantiations of B<real-time observations>, B<near real-time observations>, and B<models>.
82
83 =item data_method
84
85 The mechanism by which the image data was acquired or generated.
86
87 Common metalayers represent possible instantiations of B<in-situ data>, B<remotely-sensed data>, B<curvalinear models>, B<finite element models>, B<vertical step models>, and B<hybrid coordinate models>.
88
89 =item subregion
90
91 The domain of the image data.
92
93 Common metalayers represent possible instantiations of the entire B<secoora> domain, the B<South Atlantic Bight>, the B<East Florida Shelf>, the B<West Florida Shelf>, and other extensions and near-shore permutations.
94
95 =item data_layer
96
97 The qualification of the image data.
98
99 Common metalayers represent possible instantiations of B<synoptic wind vectors>, B<synoptic normalized wind vectors>, B<scatterometer read wind fields>, B<synoptic sea surface temperature>, B< radiometer read sea surface temperature fields>, B<spectroradiometer read sea surface temperature fields>, B<optimally interpolated cloud free sea surface temperature fields>, B<spectroradiometer derived upper ocean color>, B<color derived chlorophyll concentrations>.
100
101 =item geo_layer
102
103 The cartography of the image data.
104
105 Common metalayers represent possible instantiation combinations of B<shore outlines>, B<political outlines>, B<political features>, B<bathymetry contours>, and B<coordinate systems>.
106
107 =item legend_layer
108
109 The quantification of the image data.
110
111 Common metalayers represent possible instantiation combinations data layer specific quantifications of B<legend> or B<no legend>.
112
113 =item image_size
114
115 The geospatial scale of the image data representation.
116
117 Common metalayers represent possible instantiations of B<thumbnail>, B<small>, B<medium>, and B<large>.
118
119 =item image_time
120
121 The temporal scale visualization of the image data sample.
122
123 Common metalayers represent possible instantiations of B<[1 .. 24] hours into the past>.
124
125 =item logo_layer
126
127 The image data attribution and ownership assertions.
128
129 Common metalayers represent possible instantiations  of B<logo> or B<no logo>.
130
131 =item stamp_layer
132
133 A temporal audit trail for the image data.
134
135 Common metalayers represent possible instantiations of B<stamp> or B<no stamp>.
136
137 =back
138
139 =head2 Schema
140
141 Within each metalayer, attributes are specified in the metadata.
142 The Dublin Core metadata for B<'id'>, B<'title'>, and B<'description> are implemented.
143 Other attributes are specialized (e.g., I<'west'>, I<'south'>, I<'east'>, and I<'north'> for I<subregion>).
144
145 Within each metalayer of the schema is the potential for a bidirectional relational cache policy represented as attributes.
146 The implementation of a policy instantiates a hash value as anonymous arrays.
147 Elements within each anonymous array specify a parent/child relationship with another metalayer in the hierarchy by means of I<'id'> attribute identity,
148 although parent/child relations within policies are permitted to be promiscuous, modeling both multiple inheritance and interfaces.
149
150 Downward policies within the hierarchy tend to be permissive. For instance, metadata specifies wind observations (I<data layer>) may resolve to I<'thumbnail'>, I<'small'>, I<'medium'>, and I<'large'> (I<image size>) instances (where attributes further specify the instantiation of I<image size>).
151 Downward policies may be thought of as implementing the "has a" design pattern.
152
153 Upward policies within the hierarchy tend to be selective. For instance, a map legend metalayer instance suitable for in-situ sea surface temperature (SST) selects the in-situ SST data layer, while another map legend metalayer instance suit for remotely-sensed SST selects the remotely-sensed SST data layer.
154 Yet both map legend metalayer instances possess the same I<'id'> attribute, which the data metalayer instances both simply refer to as I<'legend'>.
155 Upward policies may be thought of as implementing the "is a" design pattern.
156
157 Finally, there is a policy for each and every metalayer instance which functions as an absolute permission.
158 The attribute for that permission is keyed as I<'active'> and a metalayer instance may either be active or inactive.
159 Efficiency is maintained without a cost to flexibility through this brute force metalayer pseudo-constructor.
160
161 Cycling through all the possible metalayer combinations is shunted by the binding of narrowly permissive and selective policies.
162 Thusly are the query parameters for secoora::CacheBot accumulated and corresponding cache file titles constructed by convention.
163
164 The cache file naming convention is:
165
166 B<dataType_dataMethod_subregions_dataLayer_imageTime_imageSize.png>
167
168 the other metalayer attributes having been instantiated in such a way as to make background, legend, logo, and timestamp uniquely exclusive.
169
170 The I<'title'> attributes of each component of the file naming convention are a matter of source browsing and are subject to rapid flux.
171 The structure of the file naming convention is reasonably stable.
172
173 Messing with the metadata attribute values carries a not neglible risk of ending up in a ditch.
174 There isn't a combinatorial model included to restrain the possibility of either overwriting an image of interest with several specifications of decoration.
175 Nor wouldn't a less judicious restriction of image size to time relationships prevent the loss of a desirable image set.
176 What the cacheJob schema allows is a complete description of what image data could be made available and a mechanism to channel specific descriptions at image repositories with conjectural queries.
177
178 =head2 Load Control
179
180 Secoora::CacheBot::cache_php_map_image not only provides management of image decoration, but encourages local queue management of image history.
181 For PHP front-end fetches, only the most recent data is requested.
182 Historical accumulation of image time series is performed hourly over 24 hours by local queue management in the cache directory.
183
184 =head2 Logging
185
186 cacheJob is monitored by syslogd with results in /var/log/cachebot.log.
187 Properly developed log alerts should be forwarded to a team visible listserv.
188
189 =head1 EXAMPLES
190
191         nrtobs_is_efs_normwind_1_large.png
192         nrtobs_is_secoora_sst_3_medium.png
193         nrtobs_rs_sab_modisergb_8_large.png
194         nrtobs_rs_wfs_quikscat_6_medium.png
195
196 =head1 SOURCE
197
198 =begin html
199
200 View the <a href="cacheJob.pl">source</a>
201
202 =end html
203
204 =head1 SEE RELATED
205
206 =begin html
207
208 <a href="CacheBot.html">Secoora::CacheBot</a>
209
210 =end html
211
212 =head1 TO DO:
213
214 =begin html
215
216 <b>As of 01/27/05 (in no particular order)</b>
217 <ul>
218 <li>Make sure ImageMagick 6 is working without corruption from 5.8.0.  Dissolve function fixed in 6 -> is PerlMagick pointing to 5.8 or 6?
219 <br><br>
220 <li>Add dynamic spacing for textboxes - with "Font-metrics" to run on text string?
221 <br>
222 <br>
223 <li>Versioning repository for CacheBot and CacheJob scripts.
224 <br>
225 <br>
226 <li>Maintain perldocs for Bot and Job.
227 <br>
228 <br>
229 <li>Replace hardcoded input parameters with XML file.  Need module to parse XML and pass parameters into perl.
230 <br>
231 <br>
232 <li>Call "Image Not Available" images when 404s/501s/blank images are returned.
233 <br>
234 <br>
235 <li>Reconfigure naming convention to use actual timestamp instead of "-3" hours.  ZPT becomes aware of time stamps which helps with
236 display logic.
237 <br>
238 <br>
239 <li>Rewrite as Python with PIL.
240 </ul>
241
242 =end html
243
244 =head1 CHANGE HISTORY:
245
246  version        date            author  change
247
248  1.00           07/16/04        CBC     initial version
249
250  1.01           07/22/04        CBC     add remotely sensed obs
251
252  1.02           07/23/04        CBC     PODified
253
254  1.03           07/26/04        CBC     made in-situ use php interface
255
256  1.04           08/14/04        CBC     added logrotate to pod
257
258  1.05           08/24/04        CBC     made $queue_length a variable (48 hours)
259
260  1.06           11/07/04        CBC     completed annotate_image
261
262  1.07       01/14/05    JC  upated text box size/fixed composite, but dissolve still broken
263                             updated MODIS RGB layers (no filled world.US)
264
265  1.08           01/27/05        JC      added water_level_obs.  worked around dissolve wierdness with opaque legend.
266                                                 Tweaked textbox, legends, & scalebar locations for visual clarity
267
268  2.00           05/04/05        JC      reverted to new WMS service at USC.  Changes to legend handling, image sizes, time stamp
269                             placement and format, region extents.  rm'd some PHP only logic (scalebar).  added pre and
270                             post data layer handling
271
272  2.01           06/21/05        JC      Added small image size with legend and logo handling as needed.  Thumbnail size is ready as
273                                                 well but doesn't look great - too small
274                         
275  2.1            12/20/07    JC  changed all SEACOOS to Secoora 
276 =cut
277
278 use warnings;
279 use strict;
280 use lib '.';
281 use lib '/home/jcleary/cachebot';
282
283 use Sys::Syslog qw(:DEFAULT setlogsock);
284 use File::Copy;
285 use Fcntl ':mode';
286 use Image::Magick;
287 use LWP::Simple;
288 use Secoora::CacheBot;
289
290 my $ident               = 'cacheJob';
291 my $facility            = 'local6';
292 my $debug_priority      = 'debug';
293 my $info_priority       = 'info';
294 my $notice_priority     = 'notice';
295 my $warn_priority       = 'warn';
296 my $crit_priority       = 'crit';
297 my $alert_priority      = 'alert';
298 setlogsock('unix');
299 openlog($ident, 'cons,pid', $facility);
300
301 my $no_scale    = '0';
302 my $active      = 'yes';
303 my $inactive    = 'no';
304 my $debug       = '';
305 if (grep(/^debug$/, @ARGV)) {$debug = $active;}
306 my $catchup_active = $inactive;
307 if (grep(/^catchup$/, @ARGV)) {$catchup_active = $active;}
308
309 ##############################################################################
310 #
311 # begin image metadata
312 #
313
314 # please, no trailing slash on web services
315
316 my $secoora_wms = 'http://maury.marine.unc.edu/cgi-bin/all_secoora';
317
318 # please, no trailing slash on output directory
319 my $output_dir  = '/var/www/html/images/mapCache';
320 # please, no dot prefix
321 my $image_ext   = 'png';
322
323 # for now (no SECOORA logo exisists), point logo path to blank gif, same as no logo
324 my $logo_image  = '/home/jcleary/cachebot/support_files/blank.gif';
325 my $no_logo     = '/home/jcleary/cachebot/support_files/blank.gif';
326
327 # please, no trailing slash on font directory
328 my $font_dir    = '/home/jcleary/cachebot/support_files';
329 my $stamp_font  = 'forgotte.ttf';
330
331 my $near_real_time_obs_id       = 'nrtobs';
332 my $model_ouput_id              = 'model';
333 # only data_types with the active flag set to $active will be processed
334 my @data_types = (
335         {id             => $near_real_time_obs_id,
336         active          => $active,
337         title           => 'nrtobs',
338         description     => 'Near real-time observations',
339         data_methods    => [qw/ is rs /],
340         },
341         {id             => $model_ouput_id,
342         active          => $inactive,
343         title           => 'model',
344         description     => 'Model output',
345         data_methods    => [qw/ model /],
346         },
347 );
348
349 my $in_situ_id = 'is';
350 my $remotely_sensed_id = 'rs';
351 my $ocean_circulation_id = 'model';
352 # only data_methods with the active flag set to $active will be processed
353 my @data_methods = (
354         {id             => $in_situ_id,
355         active          => $active,
356         title           => 'is',
357         description     => 'In-situ',
358         subregions      => [qw/ secoora sab efs wfs scwera nccodar usfcodar miamiwera /],
359         },
360         {id             => $remotely_sensed_id,
361         active          => $active,
362         title           => 'rs',
363         description     => 'Remotely sensed',
364         subregions      => [qw/ secoora sab efs wfs scwera nccodar usfcodar miamiwera /],
365         },
366         {id             => $ocean_circulation_id,
367         active          => $inactive,
368         title           => 'model',
369         description     => 'Ocean circulation model',
370         subregions      => [qw/ secoora sab sabnc sabscga /],
371         },
372 );
373
374 # only subregions with the active flag set to $active will be processed
375 my @subregions = (
376         {id                     => 'secoora',
377         active          => $active,
378         title           => 'secoora',
379         description     => 'Entire SECOORA domain',
380         west            => '-88.05',
381         south           => '22.85',
382         east            => '-69.7',
383         north           => '37.50',
384         data_layers     => [qw/ waterlevel win sst nwn cur drift modisca quikscat oisst avhrrsst modissst modisergb modisrgb /],
385         },
386         {id                     => 'sab',
387         active          => $inactive,
388         title           => 'sab',
389         description     => 'South Atlantic Bight',
390         west            => '-82.20',
391         south           => '28.15',
392         east            => '-70.17',
393         north           => '37.72',
394         data_layers     => [qw/ waterlevel win sst nwn cur drift modisca quikscat oisst avhrrsst modissst modisergb modisrgb /],
395         },
396         {id                     => 'efs',
397         active          => $inactive,
398         title           => 'efs',
399         description     => 'East Florida Shelf',
400         west            => '-82.35',
401         south           => '24.15',
402         east            => '-71.01',
403         north           => '33.21',
404         data_layers     => [qw/ waterlevel win sst nwn cur drift modisca quikscat oisst avhrrsst modissst modisergb modisrgb /],
405         },
406         {id                     => 'wfs',
407         active          => $inactive,
408         title           => 'wfs',
409         description     => 'West Florida Shelf',
410         west            => '-88.70',
411         south           => '23.72',
412         east            => '-79.61',
413         north           => '30.98',
414         data_layers     => [qw/ waterlevel win sst nwn cur drift modisca quikscat oisst avhrrsst modissst modisergb modisrgb /],
415         },
416     {id             => 'scwera',
417     active          => $active,
418     title           => 'scwera',
419     description     => 'South Carolina WERA',
420     west            => '-81.30',
421     south           => '30.06',
422     east            => '-78.0',
423     north           => '32.70',
424     data_layers     => [qw/ cur /],
425     },
426     {id             => 'nccodar',
427     active          => $active,
428     title           => 'nccodar',
429     description     => 'North Carolina CODAR',
430     west            => '-76.10',
431     south           => '34.50',
432     east            => '-72.85',
433     north           => '37.10',
434     data_layers     => [qw/ cur /],
435     },
436     {id             => 'usfcodar',
437     active          => $active,
438     title           => 'usfcodar',
439     description     => 'USF CODAR',
440     west            => '-85.30',
441     south           => '25.20',
442     east            => '-81.44',
443     north           => '28.29',
444     data_layers     => [qw/ cur /],
445     },
446     {id             => 'miamiwera',
447     active          => $active,
448     title           => 'miamiwera',
449     description     => 'Miami WERA',
450     west            => '-80.45',
451     south           => '24.75',
452     east            => '-78.82',
453     north           => '26.05',
454     data_layers     => [qw/ cur /],
455     },
456 );
457
458 my $celsius_units       = 'C';
459 my $fahrenheit_units    = 'F';
460 my $knots_units         = 'KNOTS';
461 my $mph_units           = 'MPH';
462 my $mps_units           = 'MPS';
463 # added unit and datums for Water Level Obs
464 my $msl_datum           = 'MSL';
465 my $mllw_datum          = 'MLLW';
466 my $navd88_datum        = 'NAVD88';
467 my $meters_units        = 'M';
468 my $feet_units          = 'FT';
469
470 # changed all to $secoora_wms
471 my @data_layers = (
472 # only data_layers with the active flag set to $active will be processed
473         {id             => 'waterlevel',
474         active          => $active,
475         title           => 'waterlevel',
476         description     => 'Observed Water Levels',
477         layers          => 'water_level_obs_hourly',
478         water_level_datum => $msl_datum,
479         elevation_units => $meters_units,
480         source          => $secoora_wms,
481         data_methods    => [qw/ is /],
482         geo_layers      => [qw/ std /],
483         legend_layers   => [qw/ legend /],
484         image_times     => [qw/ 2 /],
485         },
486         {id             => 'waterlevel',
487         active          => $active,
488         title           => 'waterlevel',
489         description     => 'Observed Water Levels',
490         layers          => 'water_level_obs_hourly',
491         water_level_datum => $msl_datum,
492         elevation_units => $meters_units,
493         source          => $secoora_wms,
494         data_methods    => [qw/ is /],
495         geo_layers      => [qw/ minimal /],
496         legend_layers   => [qw/ nolegend /],
497         image_times     => [qw/ 2 /],
498         },
499         {id             => 'win',
500         active          => $active,
501         title           => 'wind',
502         description     => 'Wind',
503         layers          => 'wind_obs_hourly',
504         velocity_units  => $knots_units,
505         source          => $secoora_wms,
506         data_methods    => [qw/ is /],
507         geo_layers     => [qw/ std minimal /],
508         legend_layers   => [qw/ nolegend /],
509         image_times     => [qw/ 2 /],
510         },
511         {id             => 'sst',
512         active          => $active,
513         title           => 'sst',
514         description     => 'Sea surface temperature',
515         layers          => 'sst_obs_hourly',
516         degree_units    => $celsius_units,
517         source          => $secoora_wms,
518         data_methods    => [qw/ is /],
519         geo_layers      => [qw/ std /],
520         legend_layers   => [qw/ legend /],
521         image_times     => [qw/ 2 /],
522         },
523         {id             => 'sst'
524         active          => $active,
525         title           => 'sst'
526         description     => 'Sea surface temperature',
527         layers          => 'sst_obs_hourly',
528         degree_units    => $celsius_units,
529         source          => $secoora_wms,       
530         data_methods    => [qw/ is /],     
531         geo_layers      => [qw/ minimal /],
532         legend_layers   => [qw/ nolegend /],
533         image_times     => [qw/ 2 /],
534         },
535         {id             => 'nwn',
536         active          => $active,
537         title           => 'normwind',
538         description     => 'Normalized wind',
539         layers          => 'wind_obs_normalized_hourly',
540         velocity_units  => $knots_units,
541         source          => $secoora_wms,
542         data_methods    => [qw/ is /],
543         geo_layers      => [qw/ std minimal /],
544         legend_layers   => [qw/ nolegend /],
545         image_times     => [qw/ 2 /],
546         },
547         {id             => 'cur',
548         active          => $active,
549         title           => 'currents',
550         description     => 'In Situ and Surface Currents',
551         layers          => 'surface_currents',
552         velocity_units  => $knots_units,
553         source          => $secoora_wms,
554         data_methods    => [qw/ is /],
555         geo_layers      => [qw/ minimal /],
556         legend_layers   => [qw/ nolegend /],
557         image_times     => [qw/ 2 3 /],
558         },
559         {id             => 'cur',
560         active          => $active,
561         title           => 'currents',
562         description     => 'In Situ and Surface Currents',
563         layers          => 'surface_currents',
564         velocity_units  => $knots_units,
565         source          => $secoora_wms,
566         data_methods    => [qw/ is /],
567         geo_layers      => [qw/ std /],
568         legend_layers   => [qw/ legend /],
569         image_times     => [qw/ 2 3 /],
570         },
571         {id             => 'drift',
572         active          => $active,
573         title           => 'drifters',
574         description     => 'Drifter trajectories',
575         layers          => 'drifter_trajectory',
576         velocity_units  => $knots_units,
577         source          => $secoora_wms,
578         data_methods    => [qw/ is /],
579         geo_layers      => [qw/ minimal std /],
580         legend_layers   => [qw/ nolegend /],
581         image_times     => [qw/ 2 /],
582         },
583         {id             => 'modisca',
584         active          => $inactive,
585         title           => 'modisca',
586         description     => 'MODerate Resolution Imaging Spectroradiometer satellite chlorophyll-a',
587         layers          => 'modis_chl',
588         source          => $secoora_wms,
589         data_methods    => [qw/ rs /],
590         geo_layers      => [qw/ std /],
591         legend_layers   => [qw/ legend /],
592         image_times     => [qw/ 2 /],
593         },
594         {id             => 'modisca',
595         active          => $inactive,
596         title           => 'modisca',
597         description     => 'MODerate Resolution Imaging Spectroradiometer satellite chlorophyll-a',
598         layers          => 'modis_chl',
599         source          => $secoora_wms,
600         data_methods    => [qw/ rs /],
601         geo_layers      => [qw/ min_avhrr /],       
602         legend_layers   => [qw/ nolegend /],
603         image_times     => [qw/ 2 /],
604         },
605         {id             => 'quikscat',
606         active          => $active,
607         title           => 'quikscat',
608         description     => 'QuikSCAT satellite scatterometer wind',
609         layers          => 'quikscat_wind',
610         velocity_units  => $knots_units,
611         source          => $secoora_wms,
612         data_methods    => [qw/ rs /],
613         geo_layers      => [qw/ std minimal /],
614         legend_layers   => [qw/ nolegend /],
615         image_times     => [qw/ 2 3 /],
616         },
617         {id             => 'oisst',
618         active          => $active,
619         title           => 'oisst',
620         description     => 'Cloud-free optimal interpolated (merged) sea surface temperature',
621         layers          => 'oi_sst',
622         degree_units    => $celsius_units,
623         source          => $secoora_wms,
624         data_methods    => [qw/ rs /],
625         geo_layers      => [qw/ std /],
626         legend_layers   => [qw/ legend /],
627         image_times     => [qw/ 2 /],
628         },
629         {id             => 'oisst',
630         active          => $active,
631         title           => 'oisst',
632         description     => 'Cloud-free optimal interpolated (merged) sea surface temperature',
633         layers          => 'oi_sst',
634         degree_units    => $celsius_units,
635         source          => $secoora_wms,
636         data_methods    => [qw/ rs /],
637         geo_layers      => [qw/ minimal /],
638         legend_layers   => [qw/ nolegend /],
639         image_times     => [qw/ 2 /],
640         },
641         {id             => 'avhrrsst',
642         active          => $active,
643         title           => 'avhrrsst',
644         description     => 'POES satellite advanced very high resolution radiometer sea surface temperature',
645         layers          => 'avhrr_sst',
646         degree_units    => $celsius_units,
647         source          => $secoora_wms,
648         data_methods    => [qw/ rs /],
649         geo_layers      => [qw/ avhrr /],
650         legend_layers   => [qw/ legend /],
651         image_times     => [qw/ 2 /],
652         },
653         {id             => 'avhrrsst',
654         active          => $active, 
655         title           => 'avhrrsst',
656         description     => 'POES satellite advanced very high resolution radiometer sea surface temperature',
657         layers          => 'avhrr_sst',
658         degree_units    => $celsius_units,
659         source          => $secoora_wms,   
660         data_methods    => [qw/ rs /],   
661         geo_layers      => [qw/ min_avhrr /],
662         legend_layers   => [qw/ nolegend /], 
663         image_times     => [qw/ 2 /], 
664         },
665         {id             => 'modissst',
666         active          => $active,
667         title           => 'modissst',
668         description     => 'MODerate Resolution Imaging Spectroradiometer satellite sea surface temperature',
669         layers          => 'modis_sst',
670         degree_units    => $celsius_units,
671         source          => $secoora_wms,
672         data_methods    => [qw/ rs /],
673         geo_layers      => [qw/ avhrr /],
674         legend_layers   => [qw/ legend /],
675         image_times     => [qw/ 2 /],
676         },
677         {id             => 'modissst',
678         active          => $active,
679         title           => 'modissst',
680         description     => 'MODerate Resolution Imaging Spectroradiometer satellite sea surface temperature',
681         layers          => 'modis_sst',
682         degree_units    => $celsius_units,
683         source          => $secoora_wms,
684         data_methods    => [qw/ rs /],
685         geo_layers      => [qw/ min_avhrr /],
686         legend_layers   => [qw/ nolegend /],
687         image_times     => [qw/ 2 /],
688         },
689         {id             => 'modisergb',
690         active          => $inactive,
691         title           => 'modisergb',
692         description     => 'MODerate Resolution Imaging Spectroradiometer satellite enhanced sea surface color',
693         layers          => 'modis_ergb',
694         source          => $secoora_wms,
695         data_methods    => [qw/ rs /],
696         geo_layers      => [qw/ rgb /],
697         legend_layers   => [qw/ nolegend /],
698         image_times     => [qw/ 2 /],
699         },
700         {id             => 'modisrgb',
701         active          => $active,
702         title           => 'modisrgb',
703         description     => 'MODerate Resolution Imaging Spectroradiometer satellite sea surface color',
704         layers          => 'modis_rgb_composite_low',
705         source          => $secoora_wms,
706         data_methods    => [qw/ rs /],
707         geo_layers      => [qw/ rgb min_rgb /],
708         legend_layers   => [qw/ nolegend /],
709         image_times     => [qw/ 2 /],
710         },
711         {id             => 'waterlevel',
712         active          => $catchup_active,
713         title           => 'waterlevel',
714         description     => 'Observed Water Levels',
715         layers          => 'water_level_obs_hourly',
716         water_level_datum => $msl_datum,
717         elevation_units => $meters_units,
718         source          => $secoora_wms,
719         data_methods    => [qw/ is /],
720         geo_layers      => [qw/ std /],
721         legend_layers   => [qw/ legend /],
722         image_times     => [qw/ 3 4 5 /],
723         },
724         {id             => 'win',
725         active          => $catchup_active,
726         title           => 'wind',
727         description     => 'Wind',
728         layers          => 'wind_obs_hourly',
729         velocity_units  => $knots_units,
730         source          => $secoora_wms,
731         data_methods    => [qw/ is /],
732         geo_layers      => [qw/ std /],
733         legend_layers   => [qw/ nolegend /],
734         image_times     => [qw/ 3 4 5 /],
735         },
736         {id             => 'sst',
737         active          => $catchup_active,
738         title           => 'sst',
739         description     => 'Sea surface temperature',
740         layers          => 'sst_obs_hourly',
741         degree_units    => $celsius_units,
742         source          => $secoora_wms,
743         data_methods    => [qw/ is /],
744         geo_layers      => [qw/ std /],
745         legend_layers   => [qw/ legend /],
746         image_times     => [qw/ 3 4 5 /],
747         },
748         {id             => 'nwn',
749         active          => $catchup_active,
750         title           => 'normwind',
751         description     => 'Normalized wind',
752         layers          => 'wind_obs_normalized_hourly',
753         velocity_units  => $knots_units,
754         source          => $secoora_wms,
755         data_methods    => [qw/ is /],
756         geo_layers      => [qw/ std /],
757         legend_layers   => [qw/ nolegend /],
758         image_times     => [qw/ 3 4 5 /],
759         },
760         {id             => 'cur',
761         active          => $catchup_active,
762         title           => 'currents',
763         description     => 'In Situ and Surface Currents',
764         layers          => 'surface_currents',
765         velocity_units  => $knots_units,
766         source          => $secoora_wms,
767         data_methods    => [qw/ is /],
768         geo_layers      => [qw/ std /],
769         legend_layers   => [qw/ legend /],
770         image_times     => [qw/ 4 5 /],
771         },
772         {id             => 'drift',
773         active          => $catchup_active,
774         title           => 'drifters',
775         description     => 'Drifter trajectories',
776         layers          => 'drifter_trajectory',
777         velocity_units  => $knots_units,
778         source          => $secoora_wms,
779         data_methods    => [qw/ is /],
780         geo_layers      => [qw/ std /],
781         legend_layers   => [qw/ nolegend /],
782         image_times     => [qw/ 3 4 5 /],
783         },
784         {id             => 'modisca',
785         active          => $inactive,
786         title           => 'modisca',
787         description     => 'MODerate Resolution Imaging Spectroradiometer satellite chlorophyll-a',
788         layers          => 'modis_chl',
789         source          => $secoora_wms,
790         data_methods    => [qw/ rs /],
791         geo_layers      => [qw/ std /],
792         legend_layers   => [qw/ legend /],
793         image_times     => [qw/ 3 4 5 /],
794         },
795         {id             => 'quikscat',
796         active          => $catchup_active,
797         title           => 'quikscat',
798         description     => 'QuikSCAT satellite scatterometer wind',
799         layers          => 'quikscat_wind',
800         velocity_units  => $knots_units,
801         source          => $secoora_wms,
802         data_methods    => [qw/ rs /],
803         geo_layers      => [qw/ std /],
804         legend_layers   => [qw/ nolegend /],
805         image_times     => [qw/ 3 4 5 /],
806         },
807         {id             => 'oisst',
808         active          => $catchup_active,
809         title           => 'oisst',
810         description     => 'Cloud-free optimal interpolated (merged) sea surface temperature',
811         layers          => 'oi_sst',
812         degree_units    => $celsius_units,
813         source          => $secoora_wms,
814         data_methods    => [qw/ rs /],
815         geo_layers      => [qw/ std /],
816         legend_layers   => [qw/ legend /],
817         image_times     => [qw/ 3 4 5 /],
818         },
819         {id             => 'avhrrsst',
820         active          => $catchup_active,
821         title           => 'avhrrsst',
822         description     => 'POES satellite advanced very high resolution radiometer sea surface temperature',
823         layers          => 'avhrr_sst',
824         degree_units    => $celsius_units,
825         source          => $secoora_wms,
826         data_methods    => [qw/ rs /],
827         geo_layers      => [qw/ avhrr /],
828         legend_layers   => [qw/ legend /],
829         image_times     => [qw/ 3 4 5 /],
830         },
831         {id             => 'modissst',
832         active          => $catchup_active,
833         title           => 'modissst',
834         description     => 'MODerate Resolution Imaging Spectroradiometer satellite sea surface temperature',
835         layers          => 'modis_sst',
836         degree_units    => $celsius_units,
837         source          => $secoora_wms,
838         data_methods    => [qw/ rs /],
839         geo_layers      => [qw/ avhrr /],
840         legend_layers   => [qw/ legend /],
841         image_times     => [qw/ 3 4 5 /],
842         },
843         {id             => 'modisergb',
844         active          => $inactive,
845         title           => 'modisergb',
846         description     => 'MODerate Resolution Imaging Spectroradiometer satellite enhanced sea surface color',
847         layers          => 'modis_ergb',
848         source          => $secoora_wms,
849         data_methods    => [qw/ rs /],
850         geo_layers      => [qw/ rgb /],
851         legend_layers   => [qw/ nolegend /],
852         image_times     => [qw/ 3 4 5 /],
853         },
854         {id             => 'modisrgb',
855         active          => $catchup_active,
856         title           => 'modisrgb',
857         description     => 'MODerate Resolution Imaging Spectroradiometer satellite sea surface color',
858         layers          => 'modis_rgb_composite_low',
859         source          => $secoora_wms,
860         data_methods    => [qw/ rs /],
861         geo_layers      => [qw/ rgb /],
862         legend_layers   => [qw/ nolegend /],
863         image_times     => [qw/ 3 4 5 /],
864         },
865 );
866
867 # only geo_layers with the active flag set to $active will be processed
868 # added $secoora_wms where needed, reordered layer names, added new bathy layer name
869 my @geo_layers = (
870         {id                             => 'noback',
871         active                  => $inactive,
872         description             => 'No background',
873         pre_layers              => '',
874         post_layer              => '',
875         sources                 => [$secoora_wms],
876         image_sizes             => '',
877         },
878     {id             => 'minimal',
879     active          => $active,
880     description     => 'Minimal background',
881     pre_layers      => 'world_filled,us_filled,world_outline,us_outline',
882         post_layers             => '',
883     sources         => [$secoora_wms],
884         image_sizes             => [qw/ small thumb /],
885     },
886     {id             => 'min_avhrr',
887     active          => $active,   
888     description     => 'Minimal background for RS SST images',
889     pre_layers      => '',
890     post_layers     => 'world_filled,us_filled,world_outline,us_outline',
891     sources         => [$secoora_wms],
892     image_sizes     => [qw/ small thumb /],
893     },
894     {id             => 'min_rgb',
895     active          => $active,       
896     description     => 'Minimal background for RGBs',
897     pre_layers      => 'world_filled,us_filled',
898     post_layers     => 'world_outline,us_outline',
899     sources         => [$secoora_wms],
900     image_sizes     => [qw/ small thumb /], 
901     },
902         {id                             => 'std',
903         active                  => $active,
904         description             => 'Standard background',
905         pre_layers              => 'world_filled,us_filled,world_outline,us_outline,country_names,world_capitals',
906         post_layers     => '',
907         sources                 => [$secoora_wms],
908         image_sizes             => [qw/ medium /],
909         },
910         {id                             => 'rgb',
911         active                  => $active,
912         description             => 'RGB background',
913         pre_layers              => 'country_names,world_capitals,us_big_cities',
914         post_layers             => 'world_outline,us_outline',
915         sources                 => [$secoora_wms],
916         image_sizes             => [qw/ medium /],
917         },
918         {id             => 'avhrr',
919     active          => $active,
920     description     => 'RS background',
921     pre_layers      => '',
922     post_layers     => 'world_filled,us_filled,world_outline,us_outline,country_names,world_capitals',
923     sources         => [$secoora_wms],
924     image_sizes     => [qw/ medium /],
925     },
926         {id                             => 'std',
927         active                  => $active,
928         description             => 'Standard background',
929         pre_layers              => 'world_filled,us_filled,world_outline,us_outline,country_names,world_capitals,us_big_cities',
930     post_layers         => '',
931         sources                 => [$secoora_wms],
932         image_sizes             => [qw/ large /],
933         },
934     {id             => 'avhrr',
935     active          => $active,
936     description     => 'RS background',
937     pre_layers      => '',
938     post_layers     => 'world_filled,us_filled,world_outline,us_outline,country_names,world_capitals,us_big_cities',
939     sources         => [$secoora_wms],
940     image_sizes     => [qw/ large /],
941     },
942         {id                             => 'rgb',
943         active                  => $active,
944         description             => 'RGB background',
945         pre_layers              => 'world_filled,us_filled,country_names,world_capitals,us_big_cities',
946     post_layers         => 'world_outline,us_outline',
947         sources                 => [$secoora_wms],
948         image_sizes             => [qw/ large /],
949         },
950 );
951
952 # only legend_layers with the active flag set to $active will be processed
953 # no need for separate in-situ vs. RS SST legends (no zoomed legend), so now they are combined
954 my @legend_layers = (
955         {id             => 'nolegend',
956         active          => $active,
957         description     => 'No legend',
958         layers          => '',
959         subregions      => [qw/ secoora sab efs wfs scwera nccodar usfcodar miamiwera /],
960         data_layers     => [qw/ waterlevel sst oisst avhrrsst modissst win nwn cur drift quikscat modisergb modisrgb /],
961         image_sizes     => [qw/ thumb small medium large /],
962         },
963         {id             => 'legend',
964         active          => $active,
965         description     => 'Medium secoora sea surface temperature legend',
966         layers          => 'sst_legend_full_range',
967         sst_legend_x    => '-0',
968         sst_legend_y    => '-25',
969         subregions      => [qw/ secoora /],
970         data_layers     => [qw/ sst oisst avhrrsst modissst /],
971         image_sizes     => [qw/ medium /],
972         },
973         {id             => 'legend',
974         active          => $active,
975         description     => 'Medium SAB sea surface temperature legend',
976         layers          => 'sst_legend_full_range',
977         sst_legend_x    => '-5',
978         sst_legend_y    => '-25',
979         subregions      => [qw/ sab /],
980         data_layers     => [qw/ sst oisst avhrrsst modissst /],
981         image_sizes     => [qw/ medium /],
982         },
983         {id             => 'legend',
984         active          => $active,
985         description     => 'Medium WFS sea surface temperature legend',
986         layers          => 'sst_legend_full_range',
987         sst_legend_x    => '-270',
988         sst_legend_y    => '-15',
989         subregions      => [qw/ wfs /],
990         data_layers     => [qw/ sst oisst avhrrsst modissst /],
991         image_sizes     => [qw/ medium /],
992         },
993     {id             => 'legend',
994     active          => $active,
995     description     => 'Medium EFS sea surface temperature legend',
996     layers          => 'sst_legend_full_range',
997     sst_legend_x        => '-15',
998         sst_legend_y    => '-25',
999     subregions      => [qw/ efs /],
1000     data_layers     => [qw/ sst oisst avhrrsst modissst /],
1001     image_sizes     => [qw/ medium /],
1002     },
1003         {id             => 'legend',
1004         active          => $active,
1005         description     => 'Large non-WFS sea surface temperature legend',
1006         layers          => 'sst_legend_full_range',
1007         sst_legend_x    => '-23',
1008         sst_legend_y    => '-30',
1009         subregions      => [qw/ secoora sab efs /],
1010         data_layers     => [qw/ sst oisst avhrrsst modissst /],
1011         image_sizes     => [qw/ large /],
1012         },
1013         {id             => 'legend',
1014         active          => $active,
1015         description     => 'Large WFS sea surface temperature legend',
1016         layers          => 'sst_legend_full_range',
1017         sst_legend_x    => '-475',
1018         sst_legend_y    => '-52',
1019         subregions      => [qw/ wfs /],
1020         data_layers     => [qw/ sst oisst avhrrsst modissst /],
1021         image_sizes     => [qw/ large /],
1022         },
1023         {id             => 'legend',
1024         active          => $inactive,
1025         description     => 'Modis chlorophyll-a legend',
1026         layers          => 'modis_chl_legend_carib',
1027         offsets         => '100,100',
1028         subregions      => [qw/ secoora sab efs wfs /],
1029         data_layers     => [qw/ modisca /],
1030         image_sizes     => [qw/ medium large /],
1031         },
1032         {id             => 'legend',
1033         active          => $active,
1034         description     => 'Medium non-WFS water level legend',
1035         layers          => 'water_level_legend',
1036         wl_legend_x     => '-5',
1037         wl_legend_y     => '-25',
1038         subregions      => [qw/ secoora sab efs /],
1039         data_layers     => [qw/ waterlevel /],
1040         image_sizes     => [qw/ medium /],
1041         },
1042         {id             => 'legend',
1043         active          => $active,
1044         description     => 'Medium WFS water level legend',
1045         layers          => 'water_level_legend',
1046         wl_legend_x     => '-245',
1047         wl_legend_y     => '-15',
1048         subregions      => [qw/ wfs /],
1049         data_layers     => [qw/ waterlevel /],
1050         image_sizes     => [qw/ medium /],
1051         },
1052         {id             => 'legend',
1053         active          => $active,
1054         description     => 'Large WFS water level legend',
1055         layers          => 'water_level_legend',
1056         wl_legend_x     => '-452',
1057         wl_legend_y     => '-52',
1058         subregions      => [qw/ wfs /],
1059         data_layers     => [qw/ waterlevel /],
1060         image_sizes     => [qw/ large /],
1061         },
1062         {id             => 'legend',
1063         active          => $active,
1064         description     => 'Large non-WFS water level legend',
1065         layers          => 'water_level_legend',
1066         wl_legend_x     => '-10',
1067         wl_legend_y     => '-25',
1068         subregions      => [qw/ secoora sab efs /],
1069         data_layers     => [qw/ waterlevel /],
1070         image_sizes     => [qw/ large /],
1071         },
1072         {id             => 'legend',
1073         active          => $active,
1074         description     => 'Medium WFS Currents legend',
1075         layers          => 'current_velocity_legend',
1076         cur_legend_x    => '-245',
1077         cur_legend_y    => '-0',
1078         subregions      => [qw/ wfs usfcodar /],
1079         data_layers     => [qw/ cur /],
1080         image_sizes     => [qw/ medium /],
1081         },
1082         {id             => 'legend',
1083         active          => $active,
1084         description     => 'Large WFS Currents legend',
1085         layers          => 'current_velocity_legend',
1086         cur_legend_x    => '-455',
1087         cur_legend_y    => '-25',
1088         subregions      => [qw/ wfs usfcodar /],
1089         data_layers     => [qw/ cur /],
1090         image_sizes     => [qw/ large /],
1091         },
1092         {id             => 'legend',
1093         active          => $active,
1094         description     => 'All non-WFS Currents legends',
1095         layers          => 'current_velocity_legend',
1096         cur_legend_x    => '5',
1097         cur_legend_y    => '-25',
1098         subregions      => [qw/ secoora sab efs scwera nccodar miamiwera /],
1099         data_layers     => [qw/ cur /],
1100         image_sizes     => [qw/ medium large /],
1101         },
1102 );
1103
1104 # only image_sizes with the active flag set to $active will be processed
1105 # slightly changed medium amd large image sizes
1106 my @image_sizes = (
1107         {id             => 'thumb',
1108         active          => $inactive,
1109         title           => 'thumb',
1110         description     => 'Thumbnail',
1111         width           => '90',
1112         time_out        => '30',
1113         data_layers     => [qw/ waterlevel win sst nwn cur drift modisca quikscat oisst avhrrsst modissst modisergb modisrgb /],
1114         geo_layers      => [qw/ minimal min_rgb min_avhrr /],
1115         legend_layers   => [qw/ nolegend /],
1116         scalebars       => [qw/ noscale /],
1117         logo_layers     => [qw/ nologo /],
1118         stamp_layers    => [qw/ nostamp /],
1119         },
1120         {id             => 'small',
1121         active          => $active,
1122         title           => 'small',
1123         description     => 'Small image',
1124         width           => '175',
1125         time_out        => '45',
1126         data_layers     => [qw/ waterlevel win sst nwn cur drift modisca quikscat oisst avhrrsst modissst modisergb modisrgb /],
1127         geo_layers      => [qw/ minimal min_rgb min_avhrr /],
1128         legend_layers   => [qw/ nolegend /],
1129         scalebars       => [qw/ scale /],
1130         logo_layers     => [qw/ nologo /],
1131         stamp_layers    => [qw/ stamped /],
1132         },
1133         {id             => 'medium',
1134         active          => $active,
1135         title           => 'medium',
1136         description     => 'Medium image',
1137         width           => '313',
1138         time_out        => '60',
1139         data_layers     => [qw/ waterlevel win sst nwn cur drift modisca quikscat oisst avhrrsst modissst modisergb modisrgb /],
1140         geo_layers      => [qw/ std rgb avhrr /],
1141         legend_layers   => [qw/ nolegend legend /],
1142         scalebars       => [qw/ scale /],
1143         logo_layers     => [qw/ nologo watermark /],
1144         stamp_layers    => [qw/ nostamp stamped /],
1145         },
1146         {id             => 'large',
1147         active          => $active,
1148         title           => 'large',
1149         description     => 'Large image',
1150         width           => '526',
1151         time_out        => '60',
1152         data_layers     => [qw/ waterlevel win sst nwn cur drift modisca quikscat oisst avhrrsst modissst modisergb modisrgb /],
1153         geo_layers      => [qw/ std rgb avhrr /],
1154         legend_layers   => [qw/ nolegend legend /],
1155         scalebars       => [qw/ scale /],
1156         logo_layers     => [qw/ nologo watermark /],
1157         stamp_layers    => [qw/ nostamp stamped /],
1158         },
1159 );
1160 # no longer can specify scalebar placement so I eliminated all of this code dealing with placement.
1161 # requisite parameter calls elsewhere have been edited as well
1162
1163 # only image_times with the active flag set to $active will be processed
1164 my @image_times = (
1165         {id             => '1',
1166         active          => $inactive,
1167         title           => '1',
1168         description     => '1.5 hours ago',
1169         elapsed         => '1.5',
1170         image_sizes     => [qw/ medium large /],
1171         },
1172         {id             => '2',
1173         active          => $active,
1174         title           => '2',
1175         description     => '2 hours ago',
1176         elapsed         => '2',
1177         image_sizes     => [qw/ thumb small medium large /],
1178         },
1179         {id             => '3',
1180         active          => $active,
1181         title           => '3',
1182         description     => '3 hours ago',
1183         elapsed         => '3',
1184         image_sizes     => [qw/ small medium large /],
1185         },
1186         {id             => '4',
1187         active          => $inactive,
1188         title           => '4',
1189         description     => '4 hours ago',
1190         elapsed         => '4',
1191         image_sizes     => [qw/ medium large /],
1192         },
1193         {id             => '5',
1194         active          => $inactive,
1195         title           => '5',
1196         description     => '5 hours ago',
1197         elapsed         => '5',
1198         image_sizes     => [qw/ medium large /],
1199         },
1200         {id             => '6',
1201         active          => $inactive,
1202         title           => '6',
1203         description     => '6 hours ago',
1204         elapsed         => '6',
1205         image_sizes     => [qw/ medium large /],
1206         },
1207         {id             => '7',
1208         active          => $inactive,
1209         title           => '7',
1210         description     => '7 hours ago',
1211         elapsed         => '7',
1212         image_sizes     => [qw/ medium large /],
1213         },
1214         {id             => '8',
1215         active          => $inactive,
1216         title           => '8',
1217         description     => '8 hours ago',
1218         elapsed         => '8',
1219         image_sizes     => [qw/ medium large /],
1220         },
1221         {id             => '9',
1222         active          => $inactive,
1223         title           => '9',
1224         description     => '9 hours ago',
1225         elapsed         => '9',
1226         image_sizes     => [qw/ medium large /],
1227         },
1228         {id             => '12',
1229         active          => $inactive,
1230         title           => '12',
1231         description     => '12 hours ago',
1232         elapsed         => '12',
1233         image_sizes     => [qw/ medium large /],
1234         },
1235         {id             => '24',
1236         active          => $inactive,
1237         title           => '24',
1238         description     => '24 hours ago',
1239         elapsed         => '24',
1240         image_sizes     => [qw/ medium large /],
1241         },
1242         {id             => '48',
1243         active          => $inactive,
1244         title           => '48',
1245         description     => '48 hours ago',
1246         elapsed         => '48',
1247         image_sizes     => [qw/ medium large /],
1248         },
1249         {id             => '72',
1250         active          => $inactive,
1251         title           => '72',
1252         description     => '72 hours ago',
1253         elapsed         => '72',
1254         image_sizes     => [qw/ medium large /],
1255         },
1256         {id             => '168',
1257         active          => $inactive,
1258         title           => '168',
1259         description     => 'This time last week',
1260         elapsed         => '168',
1261         image_sizes     => [qw/ medium large /],
1262         },
1263 );
1264
1265 # only logo_layers with the active flag set to $active will be processed
1266 my @logo_layers = (
1267         {id             => 'nologo',
1268         active          => $active,
1269         description     => 'No logo',
1270         xorigin         => '0',
1271         yorigin         => '0',
1272         source          => $no_logo,
1273         gravity         => 'northeast',
1274         opacity         => '20',
1275         subregions      => [qw/ secoora sab efs wfs scwera nccodar usfcodar miamiwera /],
1276         image_sizes     => [qw/ thumb small /],
1277         },
1278         {id             => 'watermark',
1279         active          => $active,
1280         description     => 'Medium non-WFS watermark logo',
1281         xorigin         => '0',
1282         yorigin         => '0',
1283         source          => $logo_image,
1284         gravity         => 'northwest',
1285         opacity         => '20',
1286         subregions      => [qw/ secoora sab efs scwera nccodar miamiwera /],
1287         image_sizes     => [qw/ medium small /],
1288         },
1289         {id             => 'watermark',
1290         active          => $active,
1291         description     => 'Medium WFS watermark logo',
1292         xorigin         => '0',
1293         yorigin         => '0',
1294         source          => $logo_image,
1295         gravity         => 'northeast',
1296         opacity         => '20',
1297         subregions      => [qw/ wfs usfcodar /],
1298         image_sizes     => [qw/ medium /],
1299         },
1300         {id             => 'watermark',
1301         active          => $active,
1302         description     => 'Large non-WFS watermark logo',
1303         xorigin         => '10',
1304         yorigin         => '10',
1305         source          => $logo_image,
1306         gravity         => 'northwest',
1307         opacity         => '20',
1308         subregions      => [qw/ secoora sab efs scwera nccodar miamiwera /],
1309         image_sizes     => [qw/ large /],
1310         },
1311         {id             => 'watermark',
1312         active          => $active,
1313         description     => 'Large WFS watermark logo',
1314         xorigin         => '10',
1315         yorigin         => '10',
1316         source          => $logo_image,
1317         gravity         => 'northeast',
1318         opacity         => '20',
1319         subregions      => [qw/ wfs usfcodar /],
1320         image_sizes     => [qw/ large /],
1321         },
1322 );
1323
1324 # only stamp_layers with the active flag set to $active will be processed
1325 # these parameters have been tested - some minor tweaking is expected
1326 my @stamp_layers = (
1327         {id             => 'nostamp',
1328         active          => $active,
1329         description     => 'No time stamp',
1330         stamp           => '%02d/%02d/%04d %02d:00',
1331         color           => '',
1332         point           => '',
1333         xorigin         => '',
1334         yorigin         => '',
1335         font            => '',
1336         border          => '',
1337         stroke          => '',
1338         fill            => '',
1339         subregions      => [qw/ secoora /],
1340         image_sizes     => [qw/ thumb /],
1341         data_method     => [qw/ rs is /],
1342         },
1343         {id             => 'stamped',
1344         active          => $active,
1345         description     => 'Small IS SECOORA time stamp',
1346         stamp           => '%02d/%02d/%04d %02d:00 UTC',
1347         color           => 'rgb(75,129,212)',
1348         point           => '12',
1349         xorigin         => '1',
1350         yorigin         => '1',
1351         font            => $stamp_font,
1352         border          => '0,0 102,11',
1353         stroke          => 'rgb(211,198,165)',
1354         fill            => 'rgb(211,198,165)',
1355         subregions      => [qw/ secoora /],
1356         image_sizes     => [qw/ small /],
1357         data_method     => [qw/ is /],
1358         },
1359     {id             => 'stamped',   
1360         active          => $active,
1361     description     => 'Small RS SECOORA time stamp',
1362     stamp           => '%02d/%02d/%04d Estimate',
1363     color           => 'rgb(75,129,212)',
1364     point           => '12',       
1365     xorigin         => '1',
1366     yorigin         => '1',     
1367     font            => $stamp_font,
1368     border          => '0,0 97,11',
1369     stroke          => 'rgb(211,198,165)',
1370         fill            => 'rgb(211,198,165)',
1371     subregions      => [qw/ secoora /],
1372     image_sizes     => [qw/ small /],
1373     data_method     => [qw/ rs /],
1374     },
1375         {id             => 'stamped',
1376         active          => $active,
1377         description     => 'IS Medium SECOORA/SAB time stamp',
1378         stamp           => '%02d/%02d/%04d %02d:00 UTC',
1379         color           => 'rgb(75,129,212)',
1380         point           => '15',
1381         xorigin         => '1',
1382         yorigin         => '1',
1383         font            => $stamp_font,
1384         border          => '0,0 126,15',
1385         stroke          => 'rgb(211,198,165)',
1386         fill            => 'rgb(211,198,165)',
1387         subregions      => [qw/ secoora sab /],
1388         image_sizes     => [qw/ medium /],
1389         data_method     => [qw/ is /],
1390         },
1391         {id             => 'stamped',
1392         active          => $active,
1393         description     => 'IS Medium WFS time stamp',
1394         stamp           => '%02d/%02d/%04d %02d:00 UTC',
1395         color           => 'rgb(75,129,212)',
1396         point           => '15',
1397         xorigin         => '99',
1398         yorigin         => '1',
1399         border          => '98,0 224,13',
1400         font            => $stamp_font,
1401         stroke          => 'rgb(211,198,165)',
1402         fill            => 'rgb(211,198,165)',
1403         subregions      => [qw/ wfs /],
1404         image_sizes     => [qw/ medium /],
1405         data_method     => [qw/ is /],
1406         },
1407     {id             => 'stamped',
1408     active          => $active,
1409     description     => 'IS Medium USF CODAR time stamp',
1410     stamp           => '%02d/%02d/%04d %02d:00 UTC',
1411     color           => 'rgb(74,74,74)',
1412     point           => '15',
1413     xorigin         => '1',
1414     yorigin         => '1',
1415     border          => '0,0 126,13',
1416     font            => $stamp_font,
1417     stroke          => 'rgb(181,207,240)',
1418     fill            => 'rgb(181,207,240)',
1419     subregions      => [qw/ usfcodar /],
1420     image_sizes     => [qw/ medium /],
1421     data_method     => [qw/ is /],
1422     },
1423     {id             => 'stamped',
1424     active          => $active,
1425     description     => 'IS Medium EFS and SAB time stamp',
1426     stamp           => '%02d/%02d/%04d %02d:00 UTC',
1427     color           => 'rgb(74,74,74)',
1428     point           => '15',
1429     xorigin         => '188',
1430     yorigin         => '1',
1431     border          => '187,0 313,13',
1432     font            => $stamp_font,
1433     stroke          => 'rgb(181,207,240)',
1434     fill            => 'rgb(181,207,240)',
1435     subregions      => [qw/ efs scwera nccodar miamiwera /],
1436     image_sizes     => [qw/ medium /],
1437         data_method         => [qw/ is /],
1438     },
1439         {id                 => 'stamped',
1440         active          => $active,
1441         description     => 'IS Large SECOORA/SAB time stamp',
1442         stamp           => '%02d/%02d/%04d %02d:00 UTC',
1443         color           => 'rgb(75,129,212)',
1444         point           => '20',
1445         xorigin         => '1',
1446         yorigin         => '1',
1447         font            => $stamp_font,
1448         border          => '0,0 179,17',
1449         stroke          => 'rgb(211,198,165)',
1450         fill            => 'rgb(211,198,165)',
1451         subregions      => [qw/ secoora sab /],
1452         image_sizes     => [qw/ large /],
1453         data_method     => [qw/ is /],
1454         },
1455         {id                 => 'stamped',
1456         active          => $active,
1457         description     => 'IS Large EFS time stamp',
1458         stamp           => '%02d/%02d/%04d %02d:00 UTC',
1459         color           => 'rgb(74,74,74)',
1460         point           => '20',
1461         xorigin         => '351',
1462         yorigin         => '1',
1463         font            => $stamp_font,
1464         border          => '350,0 526,17',
1465         stroke          => 'rgb(181,207,240)',
1466         fill            => 'rgb(181,207,240)',
1467         subregions      => [qw/ efs scwera nccodar miamiwera /],
1468         image_sizes     => [qw/ large /],
1469         data_method     => [qw/ is /],
1470         },
1471         {id             => 'stamped',
1472         active          => $active,
1473         description     => 'IS Large WFS time stamp',
1474         stamp           => '%02d/%02d/%04d %02d:00 UTC',
1475         color           => 'rgb(75,129,212)',
1476         point           => '20',
1477         xorigin         => '214',
1478         yorigin         => '1',
1479         font            => $stamp_font,
1480         border          => '213,0 392,17',
1481         stroke          => 'rgb(211,198,165)',
1482         fill            => 'rgb(211,198,165)',
1483         subregions      => [qw/ wfs /],
1484         image_sizes     => [qw/ large /],
1485         data_method     => [qw/ is /],
1486         },
1487     {id             => 'stamped',
1488     active          => $active,
1489     description     => 'IS Large USF CODAR time stamp',
1490     stamp           => '%02d/%02d/%04d %02d:00 UTC',
1491     color           => 'rgb(74,74,74)',
1492     point           => '20',
1493     xorigin         => '1',
1494     yorigin         => '1',
1495     font            => $stamp_font,
1496     border          => '0,0 179,17',
1497     stroke          => 'rgb(181,207,240)',
1498     fill            => 'rgb(181,207,240)',
1499     subregions      => [qw/ usfcodar /],
1500     image_sizes     => [qw/ large /],
1501     data_method     => [qw/ is /],
1502     },
1503         {id             => 'stamped',
1504         active          => $active,
1505         description     => 'RS Medium SECOORA/SAB time stamp',
1506         stamp           => '%02d/%02d/%04d Estimate',
1507         color           => 'rgb(75,129,212)',
1508         point           => '15',
1509         xorigin         => '1',
1510         yorigin         => '1',
1511         font            => $stamp_font,
1512         border          => '0,0 126,15',
1513         stroke          => 'rgb(211,198,165)',
1514         fill            => 'rgb(211,198,165)',
1515         subregions      => [qw/ secoora sab /],
1516         image_sizes     => [qw/ medium /],
1517         data_method     => [qw/ rs /],
1518         },
1519         {id             => 'stamped',
1520         active          => $active,
1521         description     => 'RS Medium WFS time stamp',
1522         stamp           => '%02d/%02d/%04d Estimate',
1523         color           => 'rgb(75,129,212)',
1524         point           => '15',
1525         xorigin         => '99',
1526         yorigin         => '1',
1527         border          => '98,0 224,13',
1528         font            => $stamp_font,
1529         stroke          => 'rgb(211,198,165)',
1530         fill            => 'rgb(211,198,165)',
1531         subregions      => [qw/ wfs /],
1532         image_sizes     => [qw/ medium /],
1533         data_method     => [qw/ rs /],
1534         },
1535     {id             => 'stamped',
1536     active          => $active,
1537     description     => 'RS Medium EFS time stamp',
1538     stamp           => '%02d/%02d/%04d Estimate',
1539     color           => 'rgb(74,74,74)',
1540     point           => '15',
1541     xorigin         => '188',
1542     yorigin         => '1',
1543     border          => '187,0 313,13',
1544     font            => $stamp_font,
1545     stroke          => 'rgb(181,207,240)',
1546     fill            => 'rgb(181,207,240)',
1547     subregions      => [qw/ efs /],
1548     image_sizes     => [qw/ medium /],
1549         data_method         => [qw/ rs /],
1550     },
1551         {id                 => 'stamped',
1552         active          => $active,
1553         description     => 'RS Large SECOORA/SAB time stamp',
1554         stamp           => '%02d/%02d/%04d Estimate',
1555         color           => 'rgb(75,129,212)',
1556         point           => '20',
1557         xorigin         => '1',
1558         yorigin         => '1',
1559         font            => $stamp_font,
1560         border          => '0,0 179,17',
1561         stroke          => 'rgb(211,198,165)',
1562         fill            => 'rgb(211,198,165)',
1563         subregions      => [qw/ secoora sab /],
1564         image_sizes     => [qw/ large /],
1565         data_method     => [qw/ rs /],
1566         },
1567         {id             => 'stamped',
1568         active          => $active,
1569         description     => 'RS Large EFS time stamp',
1570         stamp           => '%02d/%02d/%04d Estimate',
1571         color           => 'rgb(74,74,74)',
1572         point           => '20',
1573         xorigin         => '351',
1574         yorigin         => '1',
1575         font            => $stamp_font,
1576         border          => '350,0 526,17',
1577         stroke          => 'rgb(181,207,240)',
1578         fill            => 'rgb(181,207,240)',
1579         subregions      => [qw/ efs /],
1580         image_sizes     => [qw/ large /],
1581         data_method     => [qw/ rs /],
1582         },
1583         {id             => 'stamped',
1584         active          => $active,
1585         description     => 'RS Large WFS time stamp',
1586         stamp           => '%02d/%02d/%04d Estimate',
1587         color           => 'rgb(75,129,212)',
1588         point           => '20',
1589         xorigin         => '214',
1590         yorigin         => '1',
1591         font            => $stamp_font,
1592         border          => '213,0 392,17',
1593         stroke          => 'rgb(211,198,165)',
1594         fill            => 'rgb(211,198,165)',
1595         subregions      => [qw/ wfs /],
1596         image_sizes     => [qw/ large /],
1597         data_method     => [qw/ rs /],
1598         },
1599 );
1600
1601 ##############################################################################
1602 #
1603 # end image metadata
1604 #
1605
1606 #removed foreach loop $my_scalebar and re-aligned text
1607
1608 my $image_count         = 0;
1609 my $remote_errors       = 0;
1610 my $move_errors         = 0;
1611 my $grant_errors        = 0;
1612 my $begin_time          = time();
1613 syslog($notice_priority, '********** started at '.gmtime($begin_time).' GMT **********');
1614
1615 foreach my $data_type (@data_types) {
1616         next if $data_type->{'active'} ne $active;
1617
1618         foreach my $data_method (@data_methods) {
1619                 next if $data_method->{'active'} ne $active;
1620                 next if !grep(/^$data_method->{'id'}$/, @{$data_type->{'data_methods'}});
1621
1622                 foreach my $subregion (@subregions) {
1623                         next if $subregion->{'active'} ne $active;
1624                         next if !grep(/^$subregion->{'id'}$/, @{$data_method->{'subregions'}});
1625
1626                         foreach my $data_layer (@data_layers) {
1627                                 next if $data_layer->{'active'} ne $active;
1628                                 next if !grep(/^$data_layer->{'id'}$/,  @{$subregion->{'data_layers'}});
1629                                 next if !grep(/^$data_method->{'id'}$/, @{$data_layer->{'data_methods'}});
1630
1631                                 foreach my $geo_layer (@geo_layers) {
1632                                         next if $geo_layer->{'active'} ne $active;
1633                                         next if !grep(/^$geo_layer->{'id'}$/,     @{$data_layer->{'geo_layers'}});
1634                                         next if !grep(/^$data_layer->{'source'}$/, @{$geo_layer->{'sources'}});
1635
1636                                         foreach my $legend_layer (@legend_layers) {
1637                                                 next if $legend_layer->{'active'} ne $active;
1638                                                 next if !grep(/^$legend_layer->{'id'}$/, @{$data_layer->{'legend_layers'}});
1639                                                 next if !grep(/^$subregion->{'id'}$/,    @{$legend_layer->{'subregions'}});
1640                                                 next if !grep(/^$data_layer->{'id'}$/,   @{$legend_layer->{'data_layers'}});
1641
1642                                                 foreach my $image_size (@image_sizes) {
1643                                                         next if $image_size->{'active'} ne $active;
1644                                                         next if !grep(/^$image_size->{'id'}$/,   @{$geo_layer->{'image_sizes'}});
1645                                                         next if !grep(/^$image_size->{'id'}$/,   @{$legend_layer->{'image_sizes'}});
1646                                                         next if !grep(/^$data_layer->{'id'}$/,   @{$image_size->{'data_layers'}});
1647                                                         next if !grep(/^$geo_layer->{'id'}$/,   @{$image_size->{'geo_layers'}});
1648                                                         next if !grep(/^$legend_layer->{'id'}$/, @{$image_size->{'legend_layers'}});
1649
1650                                                         foreach my $image_time (@image_times) {
1651                                                                 next if $image_time->{'active'} ne $active;
1652                                                                 next if !grep(/^$image_time->{'id'}$/, @{$data_layer->{'image_times'}});
1653                                                                 next if !grep(/^$image_size->{'id'}$/, @{$image_time->{'image_sizes'}});
1654
1655                                                                 foreach my $logo_layer (@logo_layers) {
1656                                                                         next if $logo_layer->{'active'} ne $active;
1657                                                                         next if !grep(/^$logo_layer->{'id'}$/, @{$image_size->{'logo_layers'}});
1658                                                                         next if !grep(/^$subregion->{'id'}$/, @{$logo_layer->{'subregions'}});
1659                                                                         next if !grep(/^$image_size->{'id'}$/, @{$logo_layer->{'image_sizes'}});
1660
1661                                                                         foreach my $stamp_layer (@stamp_layers) {
1662                                                                                 next if $stamp_layer->{'active'} ne $active;
1663                                                                                 next if !grep(/^$stamp_layer->{'id'}$/, @{$image_size->{'stamp_layers'}});
1664                                                                                 next if !grep(/^$subregion->{'id'}$/,   @{$stamp_layer->{'subregions'}});
1665                                                                                 next if !grep(/^$image_size->{'id'}$/,  @{$stamp_layer->{'image_sizes'}});
1666                                                                                 next if !grep(/^$data_method->{'id'}$/, @{$stamp_layer->{'data_method'}});
1667
1668                                                                                 my $layers  =  construct_layers($geo_layer,$data_layer,$legend_layer);
1669                                                                                 my ($pre_output, $output, $post_output) = construct_filepath($output_dir, $data_type, $data_method, $subregion, $data_layer, $image_time, $image_size, $image_ext);
1670
1671                                                                                 if ($data_layer->{'source'} eq $secoora_wms) {
1672                                                                                         $move_errors = queue_images($image_time, $pre_output, $post_output, $move_errors, $alert_priority);
1673                                                                                         cache_wms_map_image($subregion, $layers, $image_time, $image_size, $data_layer, $legend_layer, $output, $debug);
1674                                                                                 }
1675                                                                                 if ($@) {
1676                                                                                         $remote_errors++;
1677                                                                                         debug_msg($@);
1678                                                                                         syslog($alert_priority, 'Error: '.$@.' on cache attempt of '.$output);
1679                                                                                 } else {
1680                                                                                         annotate_image($image_time, $output, $logo_layer, $stamp_layer,$data_layer);
1681
1682                                                                                         $grant_errors = grant_access($output, $grant_errors, $alert_priority);
1683
1684                                                                                         $image_count++;
1685                                                                                         syslog($info_priority, "Info: cache'd %s", $output);
1686                                                                                 }
1687                                                                         }
1688                                                                 }
1689                                                         }
1690                                                 }
1691                                         }
1692                                 }
1693                         }
1694                 }
1695         }
1696 }
1697
1698 my $elapsed_time        = time() - $begin_time;
1699 my $average_time        = $elapsed_time/$image_count;
1700 my $end_message         = 'Notice: %s images cached in %s seconds (%s seconds per image)';
1701
1702 syslog($notice_priority, 'Notice: %u remote errors', round($remote_errors));
1703 syslog($notice_priority, 'Notice: %u move errors',   round($move_errors));
1704 syslog($notice_priority, 'Notice: %u grant errors',  round($grant_errors));
1705
1706 if ($image_count) {
1707         debug_msg(sprintf($end_message,        round($image_count), round($elapsed_time), $average_time));
1708         syslog($notice_priority, $end_message, round($image_count), round($elapsed_time), $average_time);
1709 } else {
1710         syslog($alert_priority, "Error: No images cache'd");
1711 }
1712
1713 closelog;
1714 exit;
1715
1716 sub construct_layers {
1717         my ($geo_layer,$data_layer,$legend_layer) = @_;
1718         debug_msg(sprintf("%s%s", 'construct_layer $geo_layer pre value = ', $geo_layer->{'pre_layers'}));
1719         debug_msg(sprintf("%s%s", 'construct_layer $data_layer value = ', $data_layer->{'layers'}));
1720         debug_msg(sprintf("%s%s", 'construct_layer $legend_layer value = ', $legend_layer->{'layers'}));
1721         debug_msg(sprintf("%s%s", 'construct_layer $geo_layer post value = ', $geo_layer->{'post_layers'}));
1722
1723         my $layers  = $geo_layer->{'pre_layers'} ? $geo_layer->{'pre_layers'}.',' : '';
1724         debug_msg(sprintf("%s%s", 'construct_layer $layers value = ', $layers));
1725            $layers .= $data_layer->{'layers'} ? $data_layer->{'layers'}.',' : '';
1726         debug_msg(sprintf("%s%s", 'construct_layer $layers value = ', $layers));
1727            $layers .= $legend_layer->{'layers'} ? $legend_layer->{'layers'}.',' : '';
1728         debug_msg(sprintf("%s%s", 'construct_layer $layers value = ', $layers));
1729            $layers .= $geo_layer->{'post_layers'};
1730         debug_msg(sprintf("%s%s", 'construct_layer $layers value = ', $layers));
1731
1732         ## chop off ending comma if present
1733         if (substr($layers,-1,1) eq ",")
1734         {
1735         chop($layers);
1736         }
1737         else {}
1738         ## end comma chop code
1739
1740         return $layers;
1741 }
1742
1743 sub construct_filepath {
1744         my ($output_dir, $data_type, $data_method, $subregion, $data_layer, $image_time, $image_size, $image_ext) = @_;
1745         my $pre_output   =     $output_dir.'/' if $output_dir;
1746            $pre_output  .=     $data_type->{'title'};
1747            $pre_output  .= '_'.$data_method->{'title'};
1748            $pre_output  .= '_'.$subregion->{'title'};
1749            $pre_output  .= '_'.$data_layer->{'title'}.'_';
1750         my $post_output  = '_'.$image_size->{'title'};
1751            $post_output .= '.'.$image_ext if $image_ext;
1752         my $output       = $pre_output;
1753            $output      .= $image_time->{'title'};
1754            $output      .= $post_output;
1755         return ($pre_output, $output, $post_output);
1756 }
1757
1758 sub cache_wms_map_image {
1759         my ($subregion, $layers, $image_time, $image_size, $data_layer, $legend_layer, $output, $debug) =
1760 @_;
1761         my %query_parameters = (west=>$subregion->{'west'},
1762                                 south=>$subregion->{'south'},
1763                                 east=>$subregion->{'east'},
1764                                 north=>$subregion->{'north'},
1765                                 layers=>$layers,
1766                                 elapsed=>$image_time->{'elapsed'},
1767                                 width=>$image_size->{'width'},
1768                                 web_service=>$data_layer->{'source'},
1769                                 time_out=>$image_size->{'time_out'},
1770                                 output=>$output,
1771                                 debug=>$debug);
1772                
1773         #cp'd from PHP                 
1774         if ($data_layer->{'degree_units'}) {$query_parameters{'degree_units'} = $data_layer->{'degree_units'};}
1775         if ($data_layer->{'velocity_units'}) {$query_parameters{'velocity_units'} = $data_layer->{'velocity_units'};}
1776         if ($data_layer->{'elevation_units'}) {$query_parameters{'elevation_units'} = $data_layer->{'elevation_units'};}
1777         if ($data_layer->{'water_level_datum'}) {$query_parameters{'water_level_datum'} = $data_layer->{'water_level_datum'};}
1778        
1779         if ($legend_layer->{'sst_legend_x'}) {$query_parameters{'sst_legend_x'} = $legend_layer->{'sst_legend_x'};}
1780         if ($legend_layer->{'sst_legend_y'}) {$query_parameters{'sst_legend_y'} = $legend_layer->{'sst_legend_y'};}
1781         if ($legend_layer->{'wl_legend_x'}) {$query_parameters{'wl_legend_x'} = $legend_layer->{'wl_legend_x'};}
1782         if ($legend_layer->{'wl_legend_y'}) {$query_parameters{'wl_legend_y'} = $legend_layer->{'wl_legend_y'};}       
1783         if ($legend_layer->{'cur_legend_x'}) {$query_parameters{'cur_legend_x'} = $legend_layer->{'cur_legend_x'};}
1784         if ($legend_layer->{'cur_legend_y'}) {$query_parameters{'cur_legend_y'} = $legend_layer->{'cur_legend_y'};}
1785        
1786        
1787         eval {Secoora::CacheBot::cache_wms_map_image(%query_parameters);};
1788 }
1789
1790 sub cache_php_map_image {
1791         my ($subregion, $layers, $scalebar, $image_size, $data_layer, $legend_layer, $output, $debug, $image_time) = @_;
1792         my %query_parameters = (west=>$subregion->{'west'},
1793                                 south=>$subregion->{'south'},
1794                                 east=>$subregion->{'east'},
1795                                 north=>$subregion->{'north'},
1796                                 layers=>$layers,
1797                                 elapsed=>$image_time->{'elapsed'},
1798                                 width=>$image_size->{'width'},
1799                                 web_service=>$data_layer->{'source'},
1800                                 time_out=>$image_size->{'time_out'},
1801                                 output=>$output,
1802                                 debug=>$debug);
1803
1804         if ($legend_layer->{'offsets'}) {$query_parameters{'legend_offsets'} = $legend_layer->{'offsets'};}
1805
1806         if (($scalebar->{'use_scale'} ne $no_scale) && $scalebar->{'units'})    {$query_parameters{'scale_units'} = $scalebar->{'units'};}
1807         if (($scalebar->{'use_scale'} ne $no_scale) && $scalebar->{'width'})    {$query_parameters{'scale_width'} = $scalebar->{'width'};}
1808         if (($scalebar->{'use_scale'} ne $no_scale) && $scalebar->{'position'}) {$query_parameters{'scale_position'} = $scalebar->{'position'};}
1809
1810         if ($data_layer->{'degree_units'}) {$query_parameters{'degree_units'} = $data_layer->{'degree_units'};}
1811         if ($data_layer->{'velocity_units'}) {$query_parameters{'velocity_units'} = $data_layer->{'velocity_units'};}
1812         if ($data_layer->{'elevation_units'}) {$query_parameters{'elevation_units'} = $data_layer->{'elevation_units'};}
1813         if ($data_layer->{'water_level_datum'}) {$query_parameters{'water_level_datum'} = $data_layer->{'water_level_datum'};}
1814        
1815         eval {secoora::CacheBot::cache_php_map_image(%query_parameters);};
1816 }
1817
1818 sub queue_images {
1819         my ($image_time, $pre_output, $post_output, $move_errors, $priority) = @_;
1820         my $queue_depth = 5;
1821
1822         if ($image_time->{'id'} eq '2') {
1823                 foreach my $time_slot (reverse(2 .. $queue_depth)) {
1824
1825                         my $move_input  = $pre_output.round($time_slot).$post_output;
1826                         my $move_output = $pre_output.(round($time_slot + 1)).$post_output;
1827
1828                         if (-e $move_input) {
1829                                 if (!move($move_input, $move_output)) {
1830                                         my $move_error  = $!;
1831                                            $move_errors++;
1832                                         my $move_report = 'Error: %s on move attempt of %s';
1833                                         debug_msg(sprintf($move_report, $move_error, $move_input));
1834                                         syslog($priority, $move_report, $move_error, $move_input);
1835                                 }
1836                         }
1837                 }
1838         }
1839
1840         return $move_errors;
1841 }
1842
1843 sub annotate_image {
1844         my ($image_time, $output, $logo_layer, $stamp_layer,$data_layer) = @_;
1845         my $rc;
1846
1847         my $image     = Image::Magick->new;
1848         $rc = $image->Read($output);
1849
1850         if ($rc) {
1851                 debug_msg($rc);
1852                 syslog($alert_priority, 'Error: '.$rc.' on cache attempt of '.$output);
1853         }
1854
1855         my $composite = Image::Magick->new;
1856         $rc = $composite->Read($output);
1857
1858         if ($rc) {
1859                 debug_msg($rc);
1860                 syslog($alert_priority, 'Error: '.$rc.' on cache attempt of '.$output);
1861         }
1862
1863         my $watermark = Image::Magick->new;
1864         $rc = $watermark->Read($logo_layer->{'source'});
1865
1866         if ($rc) {
1867                 debug_msg($rc);
1868                 syslog($alert_priority, 'Error: '.$rc.' on cache attempt of '.$output);
1869         }
1870
1871         $rc = $composite->Composite(image=>$watermark,
1872                                     gravity=>$logo_layer->{'gravity'},
1873                                     x=>'0',
1874                                     y=>'0');
1875                                    
1876         if ($rc) {
1877                 debug_msg($rc);
1878                 syslog($alert_priority, 'Error: '.$rc.' on cache attempt of '.$output);
1879         }
1880
1881         my ($stamp);
1882        
1883
1884         ### New timstamp code   
1885         if ($data_layer->{'id'}=~ /avhrrsst|modisca|quikscat|modissst|modisergb|modisrgb/) {
1886                 my $offset = $image_time->{'elapsed'};
1887                 my $fetch_layer = $data_layer->{'id'};
1888
1889                 my $dest_dir='/home/jcleary/cachebot/support_files/';
1890
1891                 ### get TDS text file of interest from secoora3
1892                 my $url_base='http://cromwell.marine.unc.edu/rs_timestamps/'.$fetch_layer.$offset.'.txt';
1893                 my $target = $dest_dir.$fetch_layer.$offset.'.txt';
1894                 getstore($url_base,$target);
1895
1896                 open (RAW, $target);
1897                 $stamp = readline RAW;
1898                 close RAW;
1899
1900         }
1901
1902         else   {
1903
1904                 my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday) = gmtime(time() - (3600 * ($image_time->{'elapsed'})));
1905                 $mon  += 1;
1906                 $year += 1900;
1907                 $stamp = sprintf($stamp_layer->{'stamp'}, $mon, $mday, $year, $hour);
1908         }
1909
1910         my $font_path = $font_dir;
1911            $font_path .= '/';
1912            $font_path .= $stamp_layer->{'font'};
1913
1914         if ($stamp_layer->{'border'}) {
1915                 $rc = $composite->Draw(primitive=>'rectangle',
1916                                        points=>$stamp_layer->{'border'},
1917                                        stroke=>$stamp_layer->{'stroke'},
1918                                        fill=>$stamp_layer->{'fill'});
1919
1920                 if ($rc) {
1921                         debug_msg($rc);
1922                         syslog($alert_priority, 'Error: '.$rc.' on cache attempt of '.$output);
1923                 }
1924         }
1925
1926         $rc = $composite->Annotate(font=>$font_path,
1927                                    fill=>$stamp_layer->{'color'},
1928                                    pointsize=>$stamp_layer->{'point'},
1929                                    gravity=>'NorthWest',
1930                                    x=>$stamp_layer->{'xorigin'},
1931                                    y=>$stamp_layer->{'yorigin'},
1932                                    text=>$stamp);
1933
1934         if ($rc) {
1935                 debug_msg($rc);
1936                 syslog($alert_priority, 'Error: '.$rc.' on cache attempt of '.$output);
1937         }
1938
1939         $rc = $composite->Write($output);
1940
1941         if ($rc) {
1942                 debug_msg($rc);
1943                 syslog($alert_priority, 'Error: '.$rc.' on cache attempt of '.$output);
1944         }
1945 }
1946
1947 sub grant_access {
1948         my ($output, $grant_errors, $priority) = @_;
1949
1950         if (!chmod(S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH, $output)) {
1951                 my $grant_error = $!;
1952                    $grant_errors++;
1953                 my $grant_report = 'Error: %s on grant attempt of %s';
1954                 debug_msg(sprintf($grant_report, $grant_error, $output));
1955                 syslog($priority, $grant_report, $grant_error, $output);
1956         }
1957
1958         return $grant_errors;
1959 }
1960
1961 sub round {
1962     return int(shift(@_) + 0.5);
1963 }
1964
1965 sub debug_msg {
1966         print shift(@_)."\n" if $debug;
1967 }
Note: See TracBrowser for help on using the browser.