G::Tools GMap
SummaryIncluded librariesPackage variablesDescriptionGeneral documentationMethods
Summary
  G::Tools::GMap - Map generation using Google Map API with large images.
Package variables
No package variables defined.
Included modules
G::Messenger
SelfLoader
SubOpt
Inherit
Exporter
Synopsis
No synopsis!
Description
  This class is a part of G-language Genome Analysis Environment, 
  providing functions using Google Map API.
Methods
generateGMapDescriptionCode
Methods description
generateGMapcode    nextTop
  Name: generateGMap   -   generate Google Map View from given image file

  Description:
    This method generates a zoomable AJAX viewer interface for the
    given image, by splitting the image and generating the HTML page,
    using Google Maps API v.2. Open the "index.html" file with your
    browser when the directory containing split images and the HTML
    is generated. 

    Note that it will take a very long time to generate images 
    with levels greater than 6. 

  Usage: 
    generateGMap("imageFileName.png");
    Here the image format can be anything supported by ImageMagick.
    For best viewing experience, square image is preferred.

    When you wish to make the generated map public, obtain a Google
    Map API Key from 
       http://www.google.com/apis/maps/signup.html
and replace the string "YOUR_GOOGLE_MAP_KEY_HERE" within the
generated HTML.
Options: -level maximum zoom level. (default: 6) This value should be larger than 3. Image width size is 2^(level - 1) * 256, so width at level = 6 is 8192. -javascript string of javascript code to place within the generated HTML file -colors number of colors (default: 255) -apikey specify your Google Maps API key with this option References: 1. Google Maps API Documentation. http://www.google.com/apis/maps/documentation/
2. Arakawa K et al. "Genome Projector: zoomable genome map with multiple views."
BMC Bioinformatics 2009 10:31
Author: Kazuharu Arakawa (gaou@sfc.keio.ac.jp)
History: 20090716-01 added -apikey option 20090710-01 added cgr option to use internally with cgr() and kmer_table() 20090709-01 3D map controller, and added xy2latlng function 20080911-01 replaced -posterize option with -colors 20080909-01 slightly changed the algorithm to make it about twice faster 20080509-01 added -posterize option 20070707-01 stopped tiling in the x-direction by default 20070621-01 initial posting
Methods code
generateGMapdescriptionprevnextTop
sub generateGMap {
    opt_default(level=>6, posterize=>16, colors=>255, cgr=>0, apikey=>"YOUR_GOOGLE_MAP_KEY_HERE");
    my @argv       = opt_get(@_);
    my $file       = shift @argv;
    my $level      = opt_val("level");
    my $javascript = opt_val("javascript");
    my $posterize  = opt_val("colors");
    my $cgr        = opt_val("cgr");
    my $apikey     = opt_val("apikey");
    $posterize = 16 if($cgr);

    $level = 3 if ($level < 3);

    my $filename = basename($file);
    my $name = $filename;
    
    if($name =~ /(.*)\..*$/){
	$name = $1;
    }

    mkdir($name);

    my ($width, $height);
    if(`identify $file` =~ /\s(\d+)x(\d+)\s/){
	$width = $1;
	$height = $2;
    }else{
	die("Either ImageMagick is not available, or the given file is not a proper image.");
    }
    
    my $maxwidth = 256 * 2 ** ($level - 1);
    
    if($width == $height){
	if($width == $maxwidth && $file =~ /png$/){
	    system(sprintf("cp %s %s/level%d.png", $file, $name, $level - 1));
	}else{
	    system(sprintf("convert +dither -colors $posterize -size %dx%d -resize %dx%d %s %s/level%d.png", $width, $height, $maxwidth, $maxwidth, $file, $name, $level - 1));
	}
    }else{
	my ($xdif, $ydif, $size) = (0,0, $width);
	
	if($width > $height){
	    $size = $width;
	    $ydif = int(($width - $height) / 2);
}else{ $size = $height; $xdif = int(($height - $width) / 2);
} system(sprintf("convert +dither -colors $posterize -extent %dx%d -roll +%s+%s %s %s/%s.png", $size, $size, $xdif, $ydif, $file, $name, $name)); system(sprintf("convert +dither -colors $posterize %s/%s.png -size %dx%d -resize %dx%d %s/level%d.png", $name, $name, $size, $size, $maxwidth, $maxwidth, $name, $level - 1)); } chdir($name); my $maxlevel = $level - 1; for(my $i = $maxlevel; $i >= 0; $i --){ my $tiles = 2 ** $i; my $size = $tiles * 256; my $pid = fork(); if($pid){ }elsif(defined $pid){ my $j = $i - 1; exit if ($j < 0); system(sprintf("convert +dither -colors $posterize level%d.png -size %dx%d -resize %dx%d level%d.png", $i, $size, $size, $size/2, $size/2, $j)) unless(-e "level$j.png"); exit; }else{ die("fork failed."); } system("convert +dither -colors $posterize level$i.png -crop 256x256 level$i-%d.png"); for(my $y = 1; $y <= $tiles; $y ++){ for(my $x = 1; $x <= $tiles; $x ++){ rename(sprintf("level%d-%d.png", $i, ($y - 1) * $tiles + ($x - 1)), sprintf("level%d-%d-%d.png", $i, $x - 1, $y - 1)); } } waitpid($pid, 0); } open(OUT, '>' . 'index.html') || die($!); print OUT << "__HTML__"

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
<title>Google Map View of $name - generated by G-language GAE</title>

<script src="http://maps.google.com/maps?file=api&amp;v=2.156&amp;key=$apikey"
type="text/javascript" charset="utf-8"></script>
<script src="http://googlemaps.googlermania.com/gmapkit/api?js=gmapkitmapcontrols3d.js" type="text/javascript"></script>

<script type="text/javascript">
//<![CDATA[

var map;

function customGetTileURL(a,b) {
return "level" + b + "-" + a.x + "-" + a.y + ".png"
}

function resize(){
var map_obj=document.getElementById("map");
var disp=getDispSize();
map_obj.style.width=(disp.width - 20)+"px";
map_obj.style.height=(disp.height - 20)+"px";
if( map ){
map.checkResize();
map.panTo(new GLatLng(0, 0));
}
}

function getDispSize(){
if(document.all){
if(window.opera){
return {width:document.body.clientWidth,height:document.body.clientHeight};
}else{
return {width:document.documentElement.clientWidth,height:document.documentElement.clientHeight};
}
} else if(document.layers || document.getElementById){
return {width:window.innerWidth,height:window.innerHeight};
}
}

function xy2latlng(x,y) {
var pi = Math.PI;
var rd = pi / 180;
var length = 8192;

var lng = (x * 360) / length - 180;
var tmp = (2 * pi * y / length) - pi;
var lat = (pi / 4 - Math.atan2(Math.exp(tmp), 1)) * 2 / rd;

if (lat > 85.05) lat = 85.05;
if (lat < -85.05) lat = -85.05;
return [lat, lng];
}

function load() {
if (GBrowserIsCompatible()) {
resize();

var copyright = new GCopyright(1,
new GLatLngBounds(new GLatLng(-90, -180), new GLatLng(90, 180)), 0,
"<a href=\\"http://www.g-language.org/\\" target=\\"_blank\\"><img src=\\"http://restauro-g.iab.keio.ac.jp/Res-Pic/glang.png\\" border=0></a>");
var copyrightCollection = new GCopyrightCollection();
copyrightCollection.addCopyright(copyright);

// Create a new Mercator projection instance
var zoomlevel = $maxlevel;
var projection = new GMercatorProjection(18);

// add an exposed copy of the tileBounds array
projection.tileBounds = [];
var c = 1;
for(var d = 0; d <= 17; d++){
projection.tileBounds.push(c);
c *= 2
}

// == a method that checks if the y value is in range
// == but *doesnt* wrap the x value ==
projection.tileCheckRange = function(a,b,c){
var d=this.tileBounds[b];
if (a.y<0||a.y>=d) {
return false;
}

if(a.x<0||a.x>=d){
return false;
}
return true
}

// == a method that returns the width of the tilespace ==
projection.getWrapWidth = function(zoom) {
return 99999999999999;
}

//create a custom picture layer
var pic_tileLayers = [ new GTileLayer(copyrightCollection , 0, 17)];
pic_tileLayers[0].getTileUrl = customGetTileURL;
pic_tileLayers[0].isPng = function(){ return true};
pic_tileLayers[0].getOpacity = function() { return 1.0; };
var pic_customMap = new GMapType(pic_tileLayers, projection, "View1",
{maxResolution:zoomlevel, minResolution:1, errorMessage:"Data not available"});

//Now create the custom map. Would normally be G_NORMAL_MAP,G_SATELLITE_MAP,G_HYBRID_MAP
map = new GMap2(document.getElementById("map"), {mapTypes:[pic_customMap]});
map.addControl(new GMapKitMapControls3d()); //GLargeMapControl());
map.addControl(new GMapTypeControl());
map.addControl(new GOverviewMapControl());
map.enableDoubleClickZoom();
map.enableContinuousZoom();
map.enableScrollWheelZoom();
map.setCenter(new GLatLng(0, 0), 2, pic_customMap);

/////////////////////////////////////////////////////////////////////////////////////
//Add any markers here e.g.
// map.addOverlay(new GMarker(new GLatLng(x,y)));
/////////////////////////////////////////////////////////////////////////////////////


$javascript;
}
}
__HTML__
if($cgr){ print OUT << "__HTML__"

function doSearch() {
map.clearOverlays();

var seq = document.getElementById('query').value.toLowerCase();
if(seq.length < 1) return;
if(seq.match(/[^atgcnATGCN]/)) return;

var i = 0;
var j = 0;

for(i = 0; i <= seq.length; i ++){
if(seq.substr(i,1) == 'n')
j ++;
}

var sequences = new Array();
sequences.push(seq);

for(i = 0; i<j; i++){
for(var n = 0; n < sequences.length; n ++){
if(sequences[n].match(/n/)){
sequences.push(sequences[n].replace(/n/, 't'));
sequences.push(sequences[n].replace(/n/, 'g'));
sequences.push(sequences[n].replace(/n/, 'c'));
sequences[n] = sequences[n].replace(/n/, 'a');
}
}
}

for (i = 0; i <= sequences.length; i ++){
if(sequences[i] == null){continue;}
var width = 4096/Math.pow(2, seq.length - 1);
var ud = sequences[i];
var rl = sequences[i];
ud = ud.replace(/[ac]/g, 0);
ud = ud.replace(/[gt]/g, 1);
rl = rl.replace(/[ag]/g, 0);
rl = rl.replace(/[ct]/g, 1);

var x = parseInt(ud, 2) * width;
var y = parseInt(rl, 2) * width;

var x1 = xy2latlng(x,y);
var x2 = xy2latlng(x + width, y);
var x3 = xy2latlng(x + width, y + width);
var x4 = xy2latlng(x + width/2, y + width);
var x5 = xy2latlng(x, y + width);

var polygon = new GPolygon([
new GLatLng(x1[0], x1[1]),
new GLatLng(x2[0], x2[1]),
new GLatLng(x3[0], x3[1]),
new GLatLng(x4[0], x4[1]),
new GLatLng(x4[0], x5[1]),
new GLatLng(x1[0], x1[1])
]);

if(seq.length > 6)
map.addOverlay(new GMarker(new GLatLng(x1[0], x1[1])));

map.addOverlay(polygon, '#000000', 3, 0.5, '#FF0000', 0.5);
}
}


//]]>
</script>
</head>
<body onresize="resize()" onload="load()" onunload="GUnload()">
<div style="z-index:100;position:absolute;left:40%;margin-top:10px;">
Search: <input type="search" name="query" id="query" placeholder="Search" autosave="gbt" results="10" size=30 onKeyUp="doSearch()"/>
</div>
<div id="map" style="z-index:0;position:absolute"></div>
</body>
</html>

__HTML__
}else{ print OUT << "__HTML__"
//]]>
</script>
</head>
<body onresize="resize()" onload="load()" onunload="GUnload()">
<div id="map"></div>
</body>
</html>

__HTML__
} close(OUT); chdir("../"); msg_error("Google Map View is generated in $name directory.\n");
}
General documentation
No general documentation available.