<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Azavea Labs</title>
	<atom:link href="http://www.azavea.com/blogs/labs/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.azavea.com/blogs/labs</link>
	<description>Insight on what our engineers are doing</description>
	<lastBuildDate>Mon, 15 Apr 2013 16:59:21 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.4.1</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>Viewing Raster Data with GeoTrellis 0.8.1</title>
		<link>http://www.azavea.com/blogs/labs/2013/04/viewing-raster-data-with-geotrellis-0-8-1/</link>
		<comments>http://www.azavea.com/blogs/labs/2013/04/viewing-raster-data-with-geotrellis-0-8-1/#comments</comments>
		<pubDate>Mon, 15 Apr 2013 16:59:21 +0000</pubDate>
		<dc:creator>Rob Emanuele</dc:creator>
				<category><![CDATA[Posts]]></category>

		<guid isPermaLink="false">http://www.azavea.com/blogs/labs/?p=2576</guid>
		<description><![CDATA[GeoTrellis 0.8.1 is out, and with it is a new way to view your Raster data in an easy an informative way. In this blog post, we&#8217;ll take a look at some Pennsylvania elevation data using the new GeoTrellis admin tool. The data that we&#8217;ll be viewing is from the National Elevation Database (ND) developed [...]]]></description>
			<content:encoded><![CDATA[<p>GeoTrellis 0.8.1 is out, and with it is a new way to view your Raster data in an easy an informative way. In this blog post, we&#8217;ll take a look at some Pennsylvania elevation data using the new GeoTrellis admin tool.</p>
<p>The data that we&#8217;ll be viewing is from the <a href="http://www.pasda.psu.edu/uci/MetadataDisplay.aspx?entry=PASDA&amp;file=ned_10meter_quads.xml&amp;dataset=10">National Elevation Database (ND) developed by the U.S. Geological Survey</a>. In a<a title="GeoTIFF Tutorial" href="http://geotrellis.github.com/tutorials/geotiff.html" target="_blank"> tutorial on the GeoTrellis documentation site</a>, we saw how to get the data and convert the GeoTIFF rasters into the ARG format required by GeoTrellis. With GeoTrellis 0.8.1, when you use the geotrellis-server project to develop REST services with GeoTrellis, you have the option to also serve an administration tool on the /admin path of the Jetty server. You only have to make sure that some options in your application configuration are set correctly (or not set, as these are the defaults). The settings are<strong><em> geotrellis.admin.serve-site = &#8220;yes&#8221; </em></strong>and <em><strong>geotrellis.admin.serve-from-jar = &#8220;yes&#8221;</strong></em>. The first setting tells the GeoTrellis server to start the services required by the admin site. The second tells the GeoTrellis server to serve up the static files that make up the admin site. The javascript, css and html files that make up the site are packaged into the goetrellis-server JAR.</p>
<h2>Starting the admin tool</h2>
<p>If we run the server (see the tutorial or the <a title="GeoTIFF Tutorial Codebase" href="https://github.com/lossyrob/gt-ned-tutorial" target="_blank">README on the github page for the code</a> for how to run the server), we can go to http://localhost:8880/admin/ and get to the admin site:</p>
<p><a href="http://www.azavea.com/blogs/labs/2013/04/viewing-raster-data-with-geotrellis-0-8-1/gta-start/" rel="attachment wp-att-2581"><img class="alignnone size-medium wp-image-2581" title="gta-start" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2013/04/gta-start-475x265.png" alt="" width="475" height="265" /></a></p>
<p>In this case, the admin site is showing data from a catalog that I have locally. The catalog&#8217;s name is &#8220;Catalog of Rob&#8217;s Data&#8221;, and it has a number of data stores (indicated by the folders on the left). The catalog that the admin site displays is the one set in the configuration as <strong><em>geotrellis.catalog</em></strong>. For more information about the GeoTrellis catalog, see <a title="The Catalog" href="http://geotrellis.github.com/overviews/thecatalog.html">the overview section</a> on the subject in the documentation.</p>
<p>We can open up the &#8216;NED data&#8217; data store and select Philadelphia to visualize the raster:</p>
<p><a href="http://www.azavea.com/blogs/labs/2013/04/viewing-raster-data-with-geotrellis-0-8-1/gta-firstselect/" rel="attachment wp-att-2586"><img class="alignnone size-medium wp-image-2586" title="gta-firstselect" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2013/04/gta-firstselect-475x265.png" alt="" width="475" height="265" /></a></p>
<p>The raster fits over the base map perfectly. This is because both the base layer and the raster have a projection of Web Mercator (ESPG:3857); if the raster was not in that projection, it would be places in an incorrect spot on the map (although you would still be able to view it).</p>
<h2>Changing the base layer</h2>
<p>We can choose another base layer using the Leaflet layer chooser on the right side of the map:</p>
<p><a href="http://www.azavea.com/blogs/labs/2013/04/viewing-raster-data-with-geotrellis-0-8-1/gta-baselayerselect/" rel="attachment wp-att-2578"><img class="alignnone size-medium wp-image-2578" title="gta-baselayerselect" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2013/04/gta-baselayerselect-475x340.png" alt="" width="475" height="340" /></a></p>
<p>Let&#8217;s change it to the Stamen Toner layer, and increase the opacity of the raster using the Opacity slider, in order to get a more clear view of the coloring:</p>
<div><a href="http://www.azavea.com/blogs/labs/2013/04/viewing-raster-data-with-geotrellis-0-8-1/gta-tonerandopaque/" rel="attachment wp-att-2582"><img class="alignnone size-medium wp-image-2582" title="gta-tonerandopaque" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2013/04/gta-tonerandopaque-475x335.png" alt="" width="475" height="335" /></a></div>
<div></div>
<div>Now we can zoom the map to a region we&#8217;re interested in. Here I&#8217;ve zoomed to the Walnut street bridge from center city to West Philly. Anyone who&#8217;s biked that way can tell you that the elevation increase looks correct!</div>
<div></div>
<div><a href="http://www.azavea.com/blogs/labs/2013/04/viewing-raster-data-with-geotrellis-0-8-1/gta-zoomedin/" rel="attachment wp-att-2585"><img class="alignnone size-medium wp-image-2585" title="gta-zoomedin" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2013/04/gta-zoomedin-475x339.png" alt="" width="475" height="339" /></a></div>
<div></div>
<h2>Changing the Color Ramp</h2>
<div>To see the raster in a different color ramp, we can use the &#8216;Color Ramps&#8217; chooser:</div>
<div></div>
<div><a href="http://www.azavea.com/blogs/labs/2013/04/viewing-raster-data-with-geotrellis-0-8-1/gta-color-ramps/" rel="attachment wp-att-2579"><img class="alignnone size-medium wp-image-2579" title="gta-color ramps" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2013/04/gta-color-ramps-475x344.png" alt="" width="475" height="344" /></a></div>
<div><a href="http://www.azavea.com/blogs/labs/2013/04/viewing-raster-data-with-geotrellis-0-8-1/gta-otherramp/" rel="attachment wp-att-2580"><img class="alignnone size-medium wp-image-2580" title="gta-otherramp" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2013/04/gta-otherramp-475x340.png" alt="" width="475" height="340" /></a></div>
<div></div>
<div>Here I&#8217;ve selected a much brighter ramp. Notice the legend in the top left, showing the relative values of the different color breaks.</div>
<div></div>
<h2>Seeing Raster Values</h2>
<div></div>
<div>Often when viewing a raster, you want some way to see the underlying values at a certain point. With the GeoTrellis admin tool, this is easy. Just click the map and you&#8217;ll get a 7&#215;7 grid of values centered at the point where you clicked. The highlighted cell is the value directly under the mouse click. Here I&#8217;m looking at values on the hill&#8230;</div>
<div></div>
<div><a href="http://www.azavea.com/blogs/labs/2013/04/viewing-raster-data-with-geotrellis-0-8-1/gta-values/" rel="attachment wp-att-2583"><img class="alignnone size-medium wp-image-2583" title="gta-values" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2013/04/gta-values-475x255.png" alt="" width="475" height="255" /></a></div>
<div>&#8230;which as we would expect read higher than the values by the water:</div>
<div><a href="http://www.azavea.com/blogs/labs/2013/04/viewing-raster-data-with-geotrellis-0-8-1/gta-values2/" rel="attachment wp-att-2584"><img class="alignnone size-medium wp-image-2584" title="gta-values2" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2013/04/gta-values2-475x255.png" alt="" width="475" height="255" /></a></div>
<div></div>
<div>That wraps up our tour of the GeoTrellis admin tool. Happy mapping!</div>
<div></div>
]]></content:encoded>
			<wfw:commentRss>http://www.azavea.com/blogs/labs/2013/04/viewing-raster-data-with-geotrellis-0-8-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>GeoTrellis 0.8 Has Arrived!</title>
		<link>http://www.azavea.com/blogs/labs/2013/03/geotrellis-0-8-has-arrived/</link>
		<comments>http://www.azavea.com/blogs/labs/2013/03/geotrellis-0-8-has-arrived/#comments</comments>
		<pubDate>Tue, 05 Mar 2013 20:37:31 +0000</pubDate>
		<dc:creator>Josh Marcus</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[GeoTrellis]]></category>
		<category><![CDATA[Map Algebra]]></category>
		<category><![CDATA[Open Source]]></category>

		<guid isPermaLink="false">http://www.azavea.com/blogs/labs/?p=2552</guid>
		<description><![CDATA[The GeoTrellis team is very excited to announce the availability of GeoTrellis 0.8 (codename &#8220;Atlantis&#8221;), which is a major new release that is a huge step forward towards our goal of a general purpose, high performance geoprocessing library and runtime designed to perform and scale for the web. First of all, you should check out [...]]]></description>
			<content:encoded><![CDATA[<div>
<div id="attachment_2553" class="wp-caption aligncenter" style="width: 485px"><a href="http://www.azavea.com/blogs/labs/2013/03/geotrellis-0-8-has-arrived/the_lost_city_of-_atlantis/" rel="attachment wp-att-2553"><img class="size-medium wp-image-2553" title="The_Lost_City_of _Atlantis" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2013/03/The_Lost_City_of-_Atlantis-475x299.jpeg" alt="The Mythical City of Atlantis" width="475" height="299" /></a><p class="wp-caption-text">The Mythical City of Atlantis &#8211; just as legendary as GeoTrellis 0.8&#8242;s advanced geoprocessing power! (<a href="http://guitarstringsandowlwings.blogspot.com/2012/12/the-lost-city-of-atlantis.html" target="_blank">image credit</a>)</p></div>
</div>
<p>The GeoTrellis team is very excited to announce the availability of GeoTrellis 0.8 (codename &#8220;Atlantis&#8221;), which is a major new release that is a huge step forward towards our goal of a general purpose, high performance geoprocessing library and runtime designed to perform and scale for the web.</p>
<p>First of all, you should check out our <a href="http://geotrellis.github.com/" target="_blank">new documentation site</a> &#8212; <a href="http://geotrellis.github.com/" target="_blank">http://geotrellis.github.com/</a> &#8212; which features a great deal of new documentation and tutorial material. Credit is due to <a href="http://www.azavea.com/about-us/staff-profiles/rob-emanuele/" target="_blank">Rob Emanuele</a> for the terrific new organization and layout.</p>

<!-- iframe plugin v.2.5 wordpress.org/extend/plugins/iframe/ -->
<iframe src="http://207.245.89.238/labs1-demo/index.html" width="100%" height="480" scrolling="no" class="iframe-class" frameborder="0"></iframe>
<p>Secondly, take a look at <a title="Developing a Kernel Density Service with GeoTrellis" href="http://www.azavea.com/blogs/labs/2013/03/developing-a-kernel-density-service-with-geotrellis/">the Azavea Labs blog Adam Hinz recently published</a> (example running above) which describes process of building a kernel density service using GeoTrellis that features some of the new 0.8 functionality. Adam&#8217;s post details step-by-step the development of a WMS service that should be helpful as you think about how you might develop your own services with GeoTrellis. It is a companion blog to the <a title="Applying Map Algebra: Part 1" href="http://www.azavea.com/blogs/atlas/2013/01/applying-map-algebra-part-1/" target="_blank">Azavea Atlas</a> <a title="Applying Map Algebra: Part 2" href="http://www.azavea.com/blogs/atlas/2013/02/applying-map-algebra-part-2/" target="_blank">blog series</a> being written by <a href="http://www.azavea.com/about-us/staff-profiles/john-branigan/" target="_blank">John Branigan</a> that explores <a href="http://www.azavea.com/blogs/newsletter/v3i1/what-the-heck-ismap-algebra/" target="_blank">map algebra</a> concepts through the process of creating a site suitability model using wildlife habitat preferences.</p>
<p>As you delve into GeoTrellis 0.8 in more depth, here are some new features you may want to explore:</p>
<ul>
<li>A new suite of raster operations in the focal category of map algebra.
<ul>
<li>For more information, see: <a href="http://geotrellis.github.com/operations/raster/focal.html" target="_blank">http://geotrellis.github.com/operations/raster/focal.html</a></li>
</ul>
</li>
<li>Simplified raster rendering with a built-in suite of color ramps for data cartography.
<ul>
<li>For more information, see: <a href="http://geotrellis.github.com/overviews/rendering.html" target="_blank">http://geotrellis.github.com/overviews/rendering.html</a></li>
</ul>
</li>
<li>Zonal summary (by feature) operations, including a caching mechanism for tiled rasters for improved performance.
<ul>
<li>For more information, see: <a href="http://geotrellis.github.com/operations/raster/zonal.html" target="_blank">http://geotrellis.github.com/operations/raster/zonal.html</a></li>
</ul>
</li>
<li>New vector feature framework for operations on points, lines, polygons with a suite of vector operations, as well as re-engineered rasterization operations.
<ul>
<li>For more information, see: <a href="http://geotrellis.github.com/overviews/vector.html" target="_blank">http://geotrellis.github.com/overviews/vector.html</a> and <a href="http://geotrellis.github.com/operations/feature.html" target="_blank">http://geotrellis.github.com/operations/feature.html</a></li>
</ul>
</li>
</ul>
<p>Please let the team know &#8212; via the <a title="Freenode Web IRC Client" href="http://webchat.freenode.net/" target="_blank">#geotrellis channel on Freenode IRC</a> or the <a href="https://groups.google.com/forum/?fromgroups#!forum/geotrellis-user" target="_blank">geotrellis-user Google Group</a> mailing list &#8212; if you have any comments or suggestions. We will likely release a minor bugfix release (0.8.1) in the future.</p>
<p>Github: http://github.com/geotrellis/geotrellis<br />
Maven repository: https://oss.sonatype.org/content/repositories/releases/<br />
API Scaladocs: http://geotrellis.github.com/geotrellis/latest/api<br />
Issue tracker: https://github.com/geotrellis/geotrellis/issues?milestone=3&amp;state=open<br />
Mailing list: https://groups.google.com/group/geotrellis-user<br />
IRC: #geotrellis on freenode</p>
<p>GeoTrellis is released under the GPL V3 license.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.azavea.com/blogs/labs/2013/03/geotrellis-0-8-has-arrived/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Developing a Kernel Density Service with GeoTrellis</title>
		<link>http://www.azavea.com/blogs/labs/2013/03/developing-a-kernel-density-service-with-geotrellis/</link>
		<comments>http://www.azavea.com/blogs/labs/2013/03/developing-a-kernel-density-service-with-geotrellis/#comments</comments>
		<pubDate>Fri, 01 Mar 2013 19:44:03 +0000</pubDate>
		<dc:creator>ahinz</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[GeoTrellis]]></category>
		<category><![CDATA[Map Algebra]]></category>
		<category><![CDATA[opensource]]></category>
		<category><![CDATA[scala]]></category>

		<guid isPermaLink="false">http://www.azavea.com/blogs/labs/?p=2435</guid>
		<description><![CDATA[To go along with the recent Azavea Atlas post, we&#8217;re going to build a WMS service for the Western Jackalope using GeoTrellis. GeoTrellis is a high performance geoprocessing engine and programming toolkit developed here at Azavea. There&#8217;s an example showing the Western Jackalope sightings running at http://207.245.89.238/labs1-demo/index.html. Scala Environment We&#8217;re using the same made-up dataset that John used [...]]]></description>
			<content:encoded><![CDATA[<p>To go along with the recent <a title="Applying Map Algebra" href="http://www.azavea.com/blogs/atlas/2013/01/applying-map-algebra-part-1/" target="_blank">Azavea Atlas</a> post, we&#8217;re going to build a WMS service for the Western Jackalope using GeoTrellis.</p>
<p><a title="GeoTrellis" href="http://geotrellis.github.com"><em>GeoTrellis</em></a> is a high performance geoprocessing engine and programming toolkit developed here at Azavea.</p>
<p>There&#8217;s an example showing the Western Jackalope sightings running at <a href="http://207.245.89.238/labs1-demo/index.html">http://207.245.89.238/labs1-demo/index.html</a>.</p>

<!-- iframe plugin v.2.5 wordpress.org/extend/plugins/iframe/ -->
<iframe src="http://207.245.89.238/labs1-demo/index.html" width="100%" height="480" scrolling="no" class="iframe-class" frameborder="0"></iframe>
<h1>Scala Environment</h1>
<p>We&#8217;re using the same made-up dataset that John used in the Atlas Article. The first step is getting our environment setup. If performance is key, we&#8217;ve found the Oracle JVM to be a bit faster than OpenJDK. For simplicity, we&#8217;re going to use the OpenJDK found in the standard apt repo:</p>
<script src = "http://gist-it.sudarmuthu.com/github/ahinz/labs1-demo/blob/blog/INSTALL.md?slice=1:2&footer=minimal"></script>
<p>To build scala projects we use &#8220;sbt&#8221;. If you don&#8217;t have it, you can install it:</p>
<script src = "http://gist-it.sudarmuthu.com/github/ahinz/labs1-demo/blob/blog/INSTALL.md?slice=2:3&footer=minimal"></script>
<p>To get moving we need two boilerplate files. The first is our project definition (which lives in the root in build.sbt)</p>
<script src = "http://gist-it.sudarmuthu.com/github/ahinz/labs1-demo/blob/blog/build.sbt?footer=minimal"></script>
<p>The second file is needed to explain to GeoTrellis what classes we want exposed and on what port by updating the settings in the application.conf file</p>
<script src = "http://gist-it.sudarmuthu.com/github/ahinz/labs1-demo/blob/blog/src/main/resources/application.conf?footer=minimal"></script>
<p>To make sure everything is looking good we&#8217;re going to setup a simple hello world service. We&#8217;re using Jersey/JAXRS for web services in this tutorial but you should feel free to use whatever.</p>
<h1>Testing Service</h1>
<script src = "http://gist-it.sudarmuthu.com/github/ahinz/labs1-demo/blob/blog/src/main/scala/demo/azavea/Hello.scala?footer=minimal"></script>
<p>At this point we can do &#8220;./sbt run&#8221; and see our service startup by going to <a title="http://localhost:8888/hello" href="http://localhost:8888/hello" target="_blank" class="broken_link" rel="nofollow">http://localhost:8888/hello</a> and you should see &#8220;Hello World&#8221;. Jersey uses annotation to determine what methods to expose. We use the &#8220;@Path(&#8230;)&#8221; annotation to represent that path of a server (&#8220;/hello&#8221; in this example). Decorating our method with @GET exposes it via GET requests.</p>
<h1>Formatting Our Data</h1>
<p>Before we can analyze the data we need to grab some data and prep our environment. We use GeoTools to parse our shapefile in to GeoTrellis features.</p>
<script src = "http://gist-it.sudarmuthu.com/github/ahinz/labs1-demo/blob/blog/src/main/scala/demo/azavea/Resource.scala?slice=1:52&footer=minimal"></script>
<p>The last few lines set up our GeoTrellis server executor. Usually GeoTrellis reads a catalog file to determine where relevant raster data is on the server. Since we&#8217;re only generating rasters (not reading them) we used a blank catalog. The server is responsible for running operations.</p>
<p>The last few lines setup our color handling. All of the regular color ramps have their alpha values set to 100%. For our heat map we want low values to fade away. In the above case the lowest values are dropped completely (0&#215;00000000) and the remaining values are set to 50% opacity.</p>
<h1>Kernel Density</h1>
<p>Here&#8217;s a kernel density service that we&#8217;ll be using:</p>
<script src = "http://gist-it.sudarmuthu.com/github/ahinz/labs1-demo/blob/blog/src/main/scala/demo/azavea/Resource.scala?slice=53:112&footer=minimal"></script>
<p>We start out grabbing our bounding box (xmin, ymin, xmax, ymax), the width and height, size of our kernel and the kernel&#8217;s spread (standard deviation in meters). &#8220;Context&#8221; is a global object in &#8220;demo.azavea&#8221; that we use to store some static stuff, like our feature and server.</p>
<p>GeoTrellis provides a few operations for converting strings to relevant objects:</p>
<ul>
<li><a title="ParseRasterExtent" href="http://geotrellis.github.com/scaladocs/0.8/#geotrellis.rest.op.string.ParseRasterExtent$" target="_blank">ParseRasterExtent</a></li>
<li><a title="ParseInt" href="http://geotrellis.github.com/scaladocs/0.8/#geotrellis.rest.op.string.ParseInt" target="_blank">ParseInt</a></li>
<li><a title="ParseDouble" href="http://geotrellis.github.com/scaladocs/0.8/#geotrellis.rest.op.string.ParseDouble" target="_blank">ParseDouble</a></li>
</ul>
<p>More can be found in the &#8220;<a title="geotrellis.rest.op.string" href="http://geotrellis.github.com/scaladocs/0.8/#geotrellis.rest.op.string.package" target="_blank">geotrellis.rest.op.string</a>&#8221; package</p>
<p>A common kernel to use for Kernel Density operations is the Gaussian, which we create using <a title="CreateGaussianRaster" href="http://geotrellis.github.com/scaladocs/0.8/#geotrellis.raster.op.focal.CreateGaussianRaster" target="_blank">CreateGaussianRaster</a>. In our example we allow the standard deviation to be set by the service and set the amplitude to 100.</p>
<p>The main show is the <a title="KernelDensity" href="http://geotrellis.github.com/scaladocs/0.8/#geotrellis.raster.op.focal.KernelDensity" target="_blank">KernelDensity</a> operation. We&#8217;re using the feature set that we loaded from the shapefile. The second argument is a function to convert our feature value in a number. In our case each feature is a <a title="Point[Int]" href="http://geotrellis.github.com/scaladocs/0.8/#geotrellis.feature.Point" target="_blank">Point[Int]</a> so we use the identity function.</p>
<p>This kernel density server represents everything in meters and kilometers so we need to scale the values appropriately before we dive in to the rendering (spreadOp and sizeOp).</p>
<p>The last 10 lines render the PNG and and return it. Since we&#8217;re generating tiles on the fly we&#8217;re not going to use quantile breaks because the tile edges won&#8217;t line up. Instead, we create our own break array and use <a title="RenderPng" href="http://geotrellis.github.com/scaladocs/0.8/#geotrellis.io.RenderPng">RenderPng</a> directly.</p>
<h1>Resources</h1>
<p>For more information checkout <a href="http://geotrellis.github.com/">http://geotrellis.github.com/</a> or chat with us at #geotrellis on freenode.</p>
<p>The code can be found on github at <a href="https://github.com/geotrellis/labs1-demo">https://github.com/geotrellis/labs1-demo</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.azavea.com/blogs/labs/2013/03/developing-a-kernel-density-service-with-geotrellis/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Unit Testing Apps With JSTest.NET and require.js</title>
		<link>http://www.azavea.com/blogs/labs/2013/02/unit-testing-apps-with-jstest-net-and-require-js/</link>
		<comments>http://www.azavea.com/blogs/labs/2013/02/unit-testing-apps-with-jstest-net-and-require-js/#comments</comments>
		<pubDate>Thu, 21 Feb 2013 22:48:45 +0000</pubDate>
		<dc:creator>David Zwarg</dc:creator>
				<category><![CDATA[Posts]]></category>

		<guid isPermaLink="false">http://www.azavea.com/blogs/labs/?p=2500</guid>
		<description><![CDATA[In case you haven&#8217;t heard, Azavea likes to build beautiful and functional web applications. Particularly, geospatial applications.  Currently, each app involves a great deal of JavaScript for user interactions and dynamic content. This has presented a unique set of challenges when it came to code quality tools and best practices with respect to unit testing [...]]]></description>
			<content:encoded><![CDATA[<p>In case you haven&#8217;t heard, Azavea likes to build beautiful and functional web applications. Particularly, geospatial applications.  Currently, each app involves a great deal of JavaScript for user interactions and dynamic content. This has presented a unique set of challenges when it came to code quality tools and best practices with respect to unit testing and <a href="http://en.wikipedia.org/wiki/Test-driven_development">Test Driven Development</a> (TDD). I&#8217;ll address JavaScript unit testing in .NET in this post, since many of our projects use these two technologies.</p>
<h1>Unit Testing / TDD</h1>
<p>As it turns out, there aren&#8217;t a whole lot of great tools in the .NET ecosystem that will unit test JavaScript source files.  Sure, you could install <a href="http://nodejs.org/">nodejs</a> on a windows box, or even run your tests in the browser through <a href="http://qunitjs.com/">QUnit</a>.  It really comes down to a matter of taste, and my preference is to have fewer moving pieces in the build chain if possible.  It turns out that <a href="https://github.com/cbaxter/JSTest.NET">JSTest.NET</a> fits into our .NET ecosystem nicely, so I wanted to give it a shot (it also helps that it&#8217;s a package available in <a href="http://nuget.org/">NuGet</a>).</p>
<p>One of the interesting parts about JSTest.NET is that it runs in the <a href="http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/wsh_overview.mspx?mfr=true">Windows Scripting Host</a>, which is a neat way to run JavaScript programs from the command line in Windows. If you&#8217;ve ever double-clicked on a JavaScript file, and received a cryptic error, you probably ran the file through the Windows Scripting Host without realizing it. Since the executing process is this scripting host, you don&#8217;t have access to normal browser stuff, like &#8220;window&#8221; or &#8220;document&#8221;. This turns out to be important, especially in web applications.</p>
<p><span id="more-2500"></span></p>
<h1>JSTest.NET + require.js</h1>
<p><a href="http://requirejs.org/">Require.js</a> is a great way to write modular JavaScript code in client and server environments. Part of the design of require.js is to enforce an <a href="http://requirejs.org/docs/whyamd.html">Asynchonous Module Definition</a> (AMD) API style in your JavaScript source.  This helps developers in many ways; I&#8217;m not here to sing its praises, but it has helped our teams build reliable apps.</p>
<p>Part of AMD&#8217;s architectural design means that the browser will asynchronously load JavaScript modules when they are needed, based on the name of the module and an optional URL mapping. It&#8217;s up to the engineer&#8217;s discretion, but these modules could be quite atomic and have no dependencies (including the global &#8216;window&#8217; object in every browser). Unit testing libraries that operate outside the browser (and therefore don&#8217;t have any real URLs associated with them), seems to throw a wrench in the whole AMD process.</p>
<p>As it turns out, it&#8217;s no wrench at all. Require.js loads modules only once, and keeps defined modules around until they are explicitly discarded. With this knowledge, it&#8217;s trivial to create a set of tests by manually including module dependencies. It&#8217;s best to see this by example. Let&#8217;s get started.</p>
<h2>Processor Example</h2>
<p>Assume I have a JavaScript library module that processes data in some fashion:</p>
<script>document.write('<link href=\"https://gist.github.com/assets/embed-17ab34a51711628d8f5449c4663a9318.css\" media=\"screen\" rel=\"stylesheet\" />')
document.write('<div id=\"gist5007506\" class=\"gist\">\n      <div class=\"gist-file\">\n        <div class=\"gist-data gist-syntax\">\n\n\n\n  <div class=\"file-data\">\n    <table cellpadding=\"0\" cellspacing=\"0\" class=\"lines highlight\">\n      <tr>\n        <td class=\"line-numbers\">\n          <span class=\"line-number\" id=\"file-processor-js-L1\" rel=\"file-processor-js-L1\">1<\/span>\n          <span class=\"line-number\" id=\"file-processor-js-L2\" rel=\"file-processor-js-L2\">2<\/span>\n          <span class=\"line-number\" id=\"file-processor-js-L3\" rel=\"file-processor-js-L3\">3<\/span>\n          <span class=\"line-number\" id=\"file-processor-js-L4\" rel=\"file-processor-js-L4\">4<\/span>\n          <span class=\"line-number\" id=\"file-processor-js-L5\" rel=\"file-processor-js-L5\">5<\/span>\n          <span class=\"line-number\" id=\"file-processor-js-L6\" rel=\"file-processor-js-L6\">6<\/span>\n          <span class=\"line-number\" id=\"file-processor-js-L7\" rel=\"file-processor-js-L7\">7<\/span>\n          <span class=\"line-number\" id=\"file-processor-js-L8\" rel=\"file-processor-js-L8\">8<\/span>\n          <span class=\"line-number\" id=\"file-processor-js-L9\" rel=\"file-processor-js-L9\">9<\/span>\n          <span class=\"line-number\" id=\"file-processor-js-L10\" rel=\"file-processor-js-L10\">10<\/span>\n          <span class=\"line-number\" id=\"file-processor-js-L11\" rel=\"file-processor-js-L11\">11<\/span>\n        <\/td>\n        <td class=\"line-data\">\n          <pre class=\"line-pre\"><div class=\"line\" id=\"file-processor-js-LC1\"><span class=\"cm\">/*global define:true */<\/span><\/div><div class=\"line\" id=\"file-processor-js-LC2\"><span class=\"nx\">define<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;processor&#39;<\/span><span class=\"p\">,<\/span> <span class=\"p\">[<\/span><span class=\"s1\">&#39;module&#39;<\/span><span class=\"p\">],<\/span> <span class=\"kd\">function<\/span> <span class=\"p\">(<\/span><span class=\"nx\">module<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span><\/div><div class=\"line\" id=\"file-processor-js-LC3\">    <span class=\"s1\">&#39;use strict&#39;<\/span><span class=\"p\">;<\/span><\/div><div class=\"line\" id=\"file-processor-js-LC4\">&nbsp;<\/div><div class=\"line\" id=\"file-processor-js-LC5\">    <span class=\"kd\">var<\/span> <span class=\"nx\">processor<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span><\/div><div class=\"line\" id=\"file-processor-js-LC6\">        <span class=\"nx\">config<\/span><span class=\"o\">:<\/span> <span class=\"nx\">module<\/span><span class=\"p\">.<\/span><span class=\"nx\">config<\/span><span class=\"p\">()<\/span><\/div><div class=\"line\" id=\"file-processor-js-LC7\">        <span class=\"cm\">/* ... really awesome code here ... */<\/span><\/div><div class=\"line\" id=\"file-processor-js-LC8\">    <span class=\"p\">};<\/span><\/div><div class=\"line\" id=\"file-processor-js-LC9\">&nbsp;<\/div><div class=\"line\" id=\"file-processor-js-LC10\">    <span class=\"k\">return<\/span> <span class=\"nx\">processor<\/span><span class=\"p\">;<\/span><\/div><div class=\"line\" id=\"file-processor-js-LC11\"><span class=\"p\">});<\/span><\/div><\/pre>\n        <\/td>\n      <\/tr>\n    <\/table>\n  <\/div>\n\n        <\/div>\n\n        <div class=\"gist-meta\">\n          <a href=\"https://gist.github.com/dzwarg/5007506/raw/50c7d7cb32bb5e8bd805483d73c19f6cf8379a87/processor.js\" style=\"float:right\">view raw<\/a>\n          <a href=\"https://gist.github.com/dzwarg/5007506#file-processor-js\" style=\"float:right; margin-right:10px; color:#666;\">processor.js<\/a>\n          <a href=\"https://gist.github.com/dzwarg/5007506\">This Gist<\/a> brought to you by <a href=\"http://github.com\">GitHub<\/a>.\n        <\/div>\n      <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>/*global define:true */
define('processor', ['module'], function (module) {
    'use strict';

    var processor = {
        config: module.config()
        /* ... really awesome code here ... */
    };

    return processor;
});</pre></code></noscript></div>
<p>This module defines itself as &#8216;processor&#8217;. This is not strictly necessary when using require.js, but it is quite important in the require.js loading mechanism (it is the only way to retrieve a module from require.js after it has been loaded). This module also includes the special module id &#8216;module&#8217; as the only dependency.</p>
<p><code></code>To test this module with require, we need a JavaScript &#8220;test suite&#8221; file, and a C# test file which will be executed by our test runner. This puts all of our code and tests in JavaScript, and the C# source file merely manages the suite setup for all tests in the JavaScript &#8220;test suite&#8221;. Our &#8220;test suite&#8221; is pretty simple right now; let&#8217;s test that the loading of the module went swimmingly:</p>
<script>document.write('<link href=\"https://gist.github.com/assets/embed-17ab34a51711628d8f5449c4663a9318.css\" media=\"screen\" rel=\"stylesheet\" />')
document.write('<div id=\"gist5007506\" class=\"gist\">\n      <div class=\"gist-file\">\n        <div class=\"gist-data gist-syntax\">\n\n\n\n  <div class=\"file-data\">\n    <table cellpadding=\"0\" cellspacing=\"0\" class=\"lines highlight\">\n      <tr>\n        <td class=\"line-numbers\">\n          <span class=\"line-number\" id=\"file-processor-suite-js-L1\" rel=\"file-processor-suite-js-L1\">1<\/span>\n          <span class=\"line-number\" id=\"file-processor-suite-js-L2\" rel=\"file-processor-suite-js-L2\">2<\/span>\n          <span class=\"line-number\" id=\"file-processor-suite-js-L3\" rel=\"file-processor-suite-js-L3\">3<\/span>\n          <span class=\"line-number\" id=\"file-processor-suite-js-L4\" rel=\"file-processor-suite-js-L4\">4<\/span>\n          <span class=\"line-number\" id=\"file-processor-suite-js-L5\" rel=\"file-processor-suite-js-L5\">5<\/span>\n          <span class=\"line-number\" id=\"file-processor-suite-js-L6\" rel=\"file-processor-suite-js-L6\">6<\/span>\n          <span class=\"line-number\" id=\"file-processor-suite-js-L7\" rel=\"file-processor-suite-js-L7\">7<\/span>\n          <span class=\"line-number\" id=\"file-processor-suite-js-L8\" rel=\"file-processor-suite-js-L8\">8<\/span>\n        <\/td>\n        <td class=\"line-data\">\n          <pre class=\"line-pre\"><div class=\"line\" id=\"file-processor-suite-js-LC1\"><span class=\"cm\">/*global require:true, assert:true */<\/span><\/div><div class=\"line\" id=\"file-processor-suite-js-LC2\"><span class=\"nx\">require<\/span><span class=\"p\">([<\/span><span class=\"s1\">&#39;processor&#39;<\/span><span class=\"p\">]);<\/span><\/div><div class=\"line\" id=\"file-processor-suite-js-LC3\">&nbsp;<\/div><div class=\"line\" id=\"file-processor-suite-js-LC4\"><span class=\"kd\">var<\/span> <span class=\"nx\">processor<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">require<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;processor&#39;<\/span><span class=\"p\">);<\/span><\/div><div class=\"line\" id=\"file-processor-suite-js-LC5\">&nbsp;<\/div><div class=\"line\" id=\"file-processor-suite-js-LC6\"><span class=\"kd\">function<\/span> <span class=\"nx\">processorExists<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span><\/div><div class=\"line\" id=\"file-processor-suite-js-LC7\">    <span class=\"nx\">assert<\/span><span class=\"p\">.<\/span><span class=\"nx\">isNotNull<\/span><span class=\"p\">(<\/span><span class=\"nx\">processor<\/span><span class=\"p\">,<\/span> <span class=\"s2\">&quot;&#39;processor&#39; is not defined&quot;<\/span><span class=\"p\">);<\/span><\/div><div class=\"line\" id=\"file-processor-suite-js-LC8\"><span class=\"p\">}<\/span><\/div><\/pre>\n        <\/td>\n      <\/tr>\n    <\/table>\n  <\/div>\n\n        <\/div>\n\n        <div class=\"gist-meta\">\n          <a href=\"https://gist.github.com/dzwarg/5007506/raw/a4b6890b71c81589c4c01a9f237333cf09a06987/processor-suite.js\" style=\"float:right\">view raw<\/a>\n          <a href=\"https://gist.github.com/dzwarg/5007506#file-processor-suite-js\" style=\"float:right; margin-right:10px; color:#666;\">processor-suite.js<\/a>\n          <a href=\"https://gist.github.com/dzwarg/5007506\">This Gist<\/a> brought to you by <a href=\"http://github.com\">GitHub<\/a>.\n        <\/div>\n      <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>/*global require:true, assert:true */
require(['processor']);

var processor = require('processor');

function processorExists() {
    assert.isNotNull(processor, &quot;'processor' is not defined&quot;);
}</pre></code></noscript></div>
<p>Wait, what? Why are there two &#8220;require&#8221; calls in there?  The first invocation of require (with an array argument) is the form that registers a module that has previously been declared with &#8220;define&#8221;.  The second invocation of require (with a module name argument) is the form that retrieves the cached module by that same name. You can test this out in any web page that uses require: if you use open up a JavaScript console in the browser, you can use the form &#8220;require(&#8216;modulename&#8217;)&#8221; to get the currently loaded module (that is, if you know the module names that the application developer is using). The two of these calls together effectively 1) register the module, then 2) return the loaded url from require&#8217;s cache. Now that we&#8217;ve convinced require not to load any modules via XMLHttpRequests, we can start testing our modules.</p>
<p>Next, we need something to pilot the tests: a C# class loads up the scripts and starts the tests:</p>
<script>document.write('<link href=\"https://gist.github.com/assets/embed-17ab34a51711628d8f5449c4663a9318.css\" media=\"screen\" rel=\"stylesheet\" />')
document.write('<div id=\"gist5007506\" class=\"gist\">\n      <div class=\"gist-file\">\n        <div class=\"gist-data gist-syntax\">\n\n\n\n  <div class=\"file-data\">\n    <table cellpadding=\"0\" cellspacing=\"0\" class=\"lines highlight\">\n      <tr>\n        <td class=\"line-numbers\">\n          <span class=\"line-number\" id=\"file-processortest-cs-L1\" rel=\"file-processortest-cs-L1\">1<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L2\" rel=\"file-processortest-cs-L2\">2<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L3\" rel=\"file-processortest-cs-L3\">3<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L4\" rel=\"file-processortest-cs-L4\">4<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L5\" rel=\"file-processortest-cs-L5\">5<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L6\" rel=\"file-processortest-cs-L6\">6<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L7\" rel=\"file-processortest-cs-L7\">7<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L8\" rel=\"file-processortest-cs-L8\">8<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L9\" rel=\"file-processortest-cs-L9\">9<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L10\" rel=\"file-processortest-cs-L10\">10<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L11\" rel=\"file-processortest-cs-L11\">11<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L12\" rel=\"file-processortest-cs-L12\">12<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L13\" rel=\"file-processortest-cs-L13\">13<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L14\" rel=\"file-processortest-cs-L14\">14<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L15\" rel=\"file-processortest-cs-L15\">15<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L16\" rel=\"file-processortest-cs-L16\">16<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L17\" rel=\"file-processortest-cs-L17\">17<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L18\" rel=\"file-processortest-cs-L18\">18<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L19\" rel=\"file-processortest-cs-L19\">19<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L20\" rel=\"file-processortest-cs-L20\">20<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L21\" rel=\"file-processortest-cs-L21\">21<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L22\" rel=\"file-processortest-cs-L22\">22<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L23\" rel=\"file-processortest-cs-L23\">23<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L24\" rel=\"file-processortest-cs-L24\">24<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L25\" rel=\"file-processortest-cs-L25\">25<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L26\" rel=\"file-processortest-cs-L26\">26<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L27\" rel=\"file-processortest-cs-L27\">27<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L28\" rel=\"file-processortest-cs-L28\">28<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L29\" rel=\"file-processortest-cs-L29\">29<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L30\" rel=\"file-processortest-cs-L30\">30<\/span>\n          <span class=\"line-number\" id=\"file-processortest-cs-L31\" rel=\"file-processortest-cs-L31\">31<\/span>\n        <\/td>\n        <td class=\"line-data\">\n          <pre class=\"line-pre\"><div class=\"line\" id=\"file-processortest-cs-LC1\"><span class=\"k\">using<\/span> <span class=\"nn\">JSTest<\/span><span class=\"p\">;<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC2\"><span class=\"k\">using<\/span> <span class=\"nn\">JSTest.ScriptElements<\/span><span class=\"p\">;<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC3\"><span class=\"k\">using<\/span> <span class=\"nn\">JSTest.ScriptLibraries<\/span><span class=\"p\">;<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC4\"><span class=\"k\">using<\/span> <span class=\"nn\">NUnit.Framework<\/span><span class=\"p\">;<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC5\">&nbsp;<\/div><div class=\"line\" id=\"file-processortest-cs-LC6\"><span class=\"k\">namespace<\/span> <span class=\"nn\">JSLib.Test<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC7\"><span class=\"p\">{<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC8\"><span class=\"na\">    [TestFixture]<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC9\">    <span class=\"k\">public<\/span> <span class=\"k\">class<\/span> <span class=\"nc\">ProcessorTests<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC10\">    <span class=\"p\">{<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC11\"><span class=\"na\">        [Datapoints]<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC12\">        <span class=\"k\">public<\/span> <span class=\"k\">readonly<\/span> <span class=\"n\">TestCase<\/span><span class=\"p\">[]<\/span> <span class=\"n\">LibraryTests<\/span> <span class=\"p\">=<\/span> <span class=\"n\">TestCase<\/span><span class=\"p\">.<\/span><span class=\"n\">LoadFrom<\/span><span class=\"p\">(<\/span><span class=\"s\">@&quot;..\\..\\Test\\processor-suite.js&quot;<\/span><span class=\"p\">);<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC13\">&nbsp;<\/div><div class=\"line\" id=\"file-processortest-cs-LC14\"><span class=\"na\">        [Theory]<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC15\">        <span class=\"k\">public<\/span> <span class=\"k\">void<\/span> <span class=\"nf\">Test<\/span><span class=\"p\">(<\/span><span class=\"n\">TestCase<\/span> <span class=\"n\">testCase<\/span><span class=\"p\">)<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC16\">        <span class=\"p\">{<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC17\">            <span class=\"kt\">var<\/span> <span class=\"n\">script<\/span> <span class=\"p\">=<\/span> <span class=\"k\">new<\/span> <span class=\"n\">TestScript<\/span> <span class=\"p\">{<\/span> <span class=\"n\">IncludeDefaultBreakpoint<\/span> <span class=\"p\">=<\/span> <span class=\"k\">false<\/span> <span class=\"p\">};<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC18\">&nbsp;<\/div><div class=\"line\" id=\"file-processortest-cs-LC19\">            <span class=\"c1\">// Append required JavaScript libraries.<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC20\">            <span class=\"n\">script<\/span><span class=\"p\">.<\/span><span class=\"n\">AppendBlock<\/span><span class=\"p\">(<\/span><span class=\"k\">new<\/span> <span class=\"n\">JsAssertLibrary<\/span><span class=\"p\">());<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC21\">&nbsp;<\/div><div class=\"line\" id=\"file-processortest-cs-LC22\">            <span class=\"c1\">// Append required JavaScript Files.<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC23\">            <span class=\"n\">script<\/span><span class=\"p\">.<\/span><span class=\"n\">AppendFile<\/span><span class=\"p\">(<\/span><span class=\"s\">@&quot;..\\..\\Scripts\\require.js&quot;<\/span><span class=\"p\">);<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC24\">            <span class=\"n\">script<\/span><span class=\"p\">.<\/span><span class=\"n\">AppendFile<\/span><span class=\"p\">(<\/span><span class=\"s\">@&quot;..\\..\\Scripts\\processor.js&quot;<\/span><span class=\"p\">);<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC25\">            <span class=\"n\">script<\/span><span class=\"p\">.<\/span><span class=\"n\">AppendFile<\/span><span class=\"p\">(<\/span><span class=\"n\">testCase<\/span><span class=\"p\">.<\/span><span class=\"n\">TestFile<\/span><span class=\"p\">);<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC26\">&nbsp;<\/div><div class=\"line\" id=\"file-processortest-cs-LC27\">            <span class=\"c1\">// Run &#39;Test&#39;.<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC28\">            <span class=\"n\">script<\/span><span class=\"p\">.<\/span><span class=\"n\">RunTest<\/span><span class=\"p\">(<\/span><span class=\"n\">testCase<\/span><span class=\"p\">);<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC29\">        <span class=\"p\">}<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC30\">    <span class=\"p\">}<\/span><\/div><div class=\"line\" id=\"file-processortest-cs-LC31\"><span class=\"p\">}<\/span><\/div><\/pre>\n        <\/td>\n      <\/tr>\n    <\/table>\n  <\/div>\n\n        <\/div>\n\n        <div class=\"gist-meta\">\n          <a href=\"https://gist.github.com/dzwarg/5007506/raw/2763c045acbd93c681944c67bc2d983b88c0cfd3/ProcessorTest.cs\" style=\"float:right\">view raw<\/a>\n          <a href=\"https://gist.github.com/dzwarg/5007506#file-processortest-cs\" style=\"float:right; margin-right:10px; color:#666;\">ProcessorTest.cs<\/a>\n          <a href=\"https://gist.github.com/dzwarg/5007506\">This Gist<\/a> brought to you by <a href=\"http://github.com\">GitHub<\/a>.\n        <\/div>\n      <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>using JSTest;
using JSTest.ScriptElements;
using JSTest.ScriptLibraries;
using NUnit.Framework;

namespace JSLib.Test
{
    [TestFixture]
    public class ProcessorTests
    {
        [Datapoints]
        public readonly TestCase[] LibraryTests = TestCase.LoadFrom(@&quot;..\..\Test\processor-suite.js&quot;);

        [Theory]
        public void Test(TestCase testCase)
        {
            var script = new TestScript { IncludeDefaultBreakpoint = false };

            // Append required JavaScript libraries.
            script.AppendBlock(new JsAssertLibrary());

            // Append required JavaScript Files.
            script.AppendFile(@&quot;..\..\Scripts\require.js&quot;);
            script.AppendFile(@&quot;..\..\Scripts\processor.js&quot;);
            script.AppendFile(testCase.TestFile);

            // Run 'Test'.
            script.RunTest(testCase);
        }
    }
}
</pre></code></noscript></div>
<p>I&#8217;ll walk you through what&#8217;s happening:</p>
<ol>
<li>JSTest loads all the global function calls in the suite on line 12 into a set of <a href="http://nunit.org/index.php?p=home">NUnit</a> <a href="http://nunit.org/index.php?p=datapoint&amp;r=2.6.2">DataPoints</a>.</li>
<li>NUnit runs the Test method (since it&#8217;s a <a href="http://nunit.org/index.php?p=theory&amp;r=2.6.2">Theory</a>, and not a <a href="http://nunit.org/index.php?p=test&amp;r=2.6.2">Test</a>) against all the discovered DataPoint types in the class &#8212; in our case, it&#8217;s an array of TestCase objects, where each one is the name of a global function to execute.</li>
<li>JSTest starts composing a TestScript, and includes the JsAssert library on line 20 (this provides the &#8216;assert&#8217; object)</li>
<li>We added our own lines below that add the require.js and processor.js JavaScript sources to the TestScript on line 23 and 24</li>
<li>JSTest then adds the test suite to the TestScript on line 25</li>
<li>JSTest runs this TestScript.</li>
</ol>
<p>This process makes it clear that:</p>
<ul>
<li>JsAssert is the first JavaScript source loaded.</li>
<li>Require.js is loaded prior to our modules.</li>
<li>Our test suite is the last JavaScript source loaded.</li>
<li>The test method will be run once for each global function found in the test suite.</li>
</ul>
<h2>Processor/Renderer Example</h2>
<p>This is all well and good, but what happens when we start adding module dependencies?  Let&#8217;s say we have a second module, which depends on our processor:</p>
<script>document.write('<link href=\"https://gist.github.com/assets/embed-17ab34a51711628d8f5449c4663a9318.css\" media=\"screen\" rel=\"stylesheet\" />')
document.write('<div id=\"gist5007506\" class=\"gist\">\n      <div class=\"gist-file\">\n        <div class=\"gist-data gist-syntax\">\n\n\n\n  <div class=\"file-data\">\n    <table cellpadding=\"0\" cellspacing=\"0\" class=\"lines highlight\">\n      <tr>\n        <td class=\"line-numbers\">\n          <span class=\"line-number\" id=\"file-renderer-js-L1\" rel=\"file-renderer-js-L1\">1<\/span>\n          <span class=\"line-number\" id=\"file-renderer-js-L2\" rel=\"file-renderer-js-L2\">2<\/span>\n          <span class=\"line-number\" id=\"file-renderer-js-L3\" rel=\"file-renderer-js-L3\">3<\/span>\n          <span class=\"line-number\" id=\"file-renderer-js-L4\" rel=\"file-renderer-js-L4\">4<\/span>\n          <span class=\"line-number\" id=\"file-renderer-js-L5\" rel=\"file-renderer-js-L5\">5<\/span>\n          <span class=\"line-number\" id=\"file-renderer-js-L6\" rel=\"file-renderer-js-L6\">6<\/span>\n          <span class=\"line-number\" id=\"file-renderer-js-L7\" rel=\"file-renderer-js-L7\">7<\/span>\n          <span class=\"line-number\" id=\"file-renderer-js-L8\" rel=\"file-renderer-js-L8\">8<\/span>\n          <span class=\"line-number\" id=\"file-renderer-js-L9\" rel=\"file-renderer-js-L9\">9<\/span>\n          <span class=\"line-number\" id=\"file-renderer-js-L10\" rel=\"file-renderer-js-L10\">10<\/span>\n          <span class=\"line-number\" id=\"file-renderer-js-L11\" rel=\"file-renderer-js-L11\">11<\/span>\n          <span class=\"line-number\" id=\"file-renderer-js-L12\" rel=\"file-renderer-js-L12\">12<\/span>\n          <span class=\"line-number\" id=\"file-renderer-js-L13\" rel=\"file-renderer-js-L13\">13<\/span>\n          <span class=\"line-number\" id=\"file-renderer-js-L14\" rel=\"file-renderer-js-L14\">14<\/span>\n          <span class=\"line-number\" id=\"file-renderer-js-L15\" rel=\"file-renderer-js-L15\">15<\/span>\n          <span class=\"line-number\" id=\"file-renderer-js-L16\" rel=\"file-renderer-js-L16\">16<\/span>\n          <span class=\"line-number\" id=\"file-renderer-js-L17\" rel=\"file-renderer-js-L17\">17<\/span>\n        <\/td>\n        <td class=\"line-data\">\n          <pre class=\"line-pre\"><div class=\"line\" id=\"file-renderer-js-LC1\"><span class=\"cm\">/*global define:true */<\/span><\/div><div class=\"line\" id=\"file-renderer-js-LC2\"><span class=\"nx\">define<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;renderer&#39;<\/span><span class=\"p\">,<\/span> <span class=\"p\">[<\/span><span class=\"s1\">&#39;processor&#39;<\/span><span class=\"p\">,<\/span> <span class=\"s1\">&#39;module&#39;<\/span><span class=\"p\">],<\/span> <span class=\"kd\">function<\/span> <span class=\"p\">(<\/span><span class=\"nx\">processor<\/span><span class=\"p\">,<\/span> <span class=\"nx\">module<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span><\/div><div class=\"line\" id=\"file-renderer-js-LC3\">    <span class=\"s1\">&#39;use strict&#39;<\/span><span class=\"p\">;<\/span><\/div><div class=\"line\" id=\"file-renderer-js-LC4\">&nbsp;<\/div><div class=\"line\" id=\"file-renderer-js-LC5\">    <span class=\"kd\">var<\/span> <span class=\"nx\">renderer<\/span> <span class=\"o\">=<\/span> <span class=\"kd\">function<\/span> <span class=\"p\">(<\/span><span class=\"nx\">options<\/span><span class=\"p\">)<\/span> <span class=\"p\">{<\/span><\/div><div class=\"line\" id=\"file-renderer-js-LC6\">        <span class=\"cm\">/* ... initialization stuff ... */<\/span><\/div><div class=\"line\" id=\"file-renderer-js-LC7\">        <span class=\"nx\">renderer<\/span><span class=\"p\">.<\/span><span class=\"nx\">processor<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">processor<\/span> <span class=\"o\">||<\/span> <span class=\"nx\">options<\/span><span class=\"p\">.<\/span><span class=\"nx\">processor<\/span><span class=\"p\">;<\/span><\/div><div class=\"line\" id=\"file-renderer-js-LC8\">    <span class=\"p\">};<\/span><\/div><div class=\"line\" id=\"file-renderer-js-LC9\">&nbsp;<\/div><div class=\"line\" id=\"file-renderer-js-LC10\">    <span class=\"nx\">renderer<\/span><span class=\"p\">.<\/span><span class=\"nx\">prototype<\/span> <span class=\"o\">=<\/span> <span class=\"p\">{<\/span><\/div><div class=\"line\" id=\"file-renderer-js-LC11\">        <span class=\"nx\">config<\/span><span class=\"o\">:<\/span> <span class=\"nx\">module<\/span><span class=\"p\">.<\/span><span class=\"nx\">config<\/span><span class=\"p\">()<\/span><\/div><div class=\"line\" id=\"file-renderer-js-LC12\">&nbsp;<\/div><div class=\"line\" id=\"file-renderer-js-LC13\">        <span class=\"cm\">/* ... module stuff ... */<\/span><\/div><div class=\"line\" id=\"file-renderer-js-LC14\">    <span class=\"p\">};<\/span><\/div><div class=\"line\" id=\"file-renderer-js-LC15\">&nbsp;<\/div><div class=\"line\" id=\"file-renderer-js-LC16\">    <span class=\"k\">return<\/span> <span class=\"nx\">renderer<\/span><span class=\"p\">;<\/span><\/div><div class=\"line\" id=\"file-renderer-js-LC17\"><span class=\"p\">});<\/span><\/div><\/pre>\n        <\/td>\n      <\/tr>\n    <\/table>\n  <\/div>\n\n        <\/div>\n\n        <div class=\"gist-meta\">\n          <a href=\"https://gist.github.com/dzwarg/5007506/raw/3b99aea36adb07d5aa6a421a855a08d8d38f8ec6/renderer.js\" style=\"float:right\">view raw<\/a>\n          <a href=\"https://gist.github.com/dzwarg/5007506#file-renderer-js\" style=\"float:right; margin-right:10px; color:#666;\">renderer.js<\/a>\n          <a href=\"https://gist.github.com/dzwarg/5007506\">This Gist<\/a> brought to you by <a href=\"http://github.com\">GitHub<\/a>.\n        <\/div>\n      <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>/*global define:true */
define('renderer', ['processor', 'module'], function (processor, module) {
    'use strict';

    var renderer = function (options) {
        /* ... initialization stuff ... */
        renderer.processor = processor || options.processor;
    };

    renderer.prototype = {
        config: module.config()

        /* ... module stuff ... */
    };

    return renderer;
});</pre></code></noscript></div>
<p>This module loads the &#8216;processor&#8217; module as a dependency. To test this in JSTest, simply create the &#8220;test suite&#8221; in JavaScript:</p>
<script>document.write('<link href=\"https://gist.github.com/assets/embed-17ab34a51711628d8f5449c4663a9318.css\" media=\"screen\" rel=\"stylesheet\" />')
document.write('<div id=\"gist5007506\" class=\"gist\">\n      <div class=\"gist-file\">\n        <div class=\"gist-data gist-syntax\">\n\n\n\n  <div class=\"file-data\">\n    <table cellpadding=\"0\" cellspacing=\"0\" class=\"lines highlight\">\n      <tr>\n        <td class=\"line-numbers\">\n          <span class=\"line-number\" id=\"file-renderer-suite-js-L1\" rel=\"file-renderer-suite-js-L1\">1<\/span>\n          <span class=\"line-number\" id=\"file-renderer-suite-js-L2\" rel=\"file-renderer-suite-js-L2\">2<\/span>\n          <span class=\"line-number\" id=\"file-renderer-suite-js-L3\" rel=\"file-renderer-suite-js-L3\">3<\/span>\n          <span class=\"line-number\" id=\"file-renderer-suite-js-L4\" rel=\"file-renderer-suite-js-L4\">4<\/span>\n          <span class=\"line-number\" id=\"file-renderer-suite-js-L5\" rel=\"file-renderer-suite-js-L5\">5<\/span>\n          <span class=\"line-number\" id=\"file-renderer-suite-js-L6\" rel=\"file-renderer-suite-js-L6\">6<\/span>\n          <span class=\"line-number\" id=\"file-renderer-suite-js-L7\" rel=\"file-renderer-suite-js-L7\">7<\/span>\n          <span class=\"line-number\" id=\"file-renderer-suite-js-L8\" rel=\"file-renderer-suite-js-L8\">8<\/span>\n        <\/td>\n        <td class=\"line-data\">\n          <pre class=\"line-pre\"><div class=\"line\" id=\"file-renderer-suite-js-LC1\"><span class=\"cm\">/*global require:true, assert:true */<\/span><\/div><div class=\"line\" id=\"file-renderer-suite-js-LC2\"><span class=\"nx\">require<\/span><span class=\"p\">([<\/span><span class=\"s1\">&#39;renderer&#39;<\/span><span class=\"p\">]);<\/span><\/div><div class=\"line\" id=\"file-renderer-suite-js-LC3\">&nbsp;<\/div><div class=\"line\" id=\"file-renderer-suite-js-LC4\"><span class=\"kd\">var<\/span> <span class=\"nx\">renderer<\/span> <span class=\"o\">=<\/span> <span class=\"nx\">require<\/span><span class=\"p\">(<\/span><span class=\"s1\">&#39;renderer&#39;<\/span><span class=\"p\">);<\/span><\/div><div class=\"line\" id=\"file-renderer-suite-js-LC5\">&nbsp;<\/div><div class=\"line\" id=\"file-renderer-suite-js-LC6\"><span class=\"kd\">function<\/span> <span class=\"nx\">rendererExists<\/span><span class=\"p\">()<\/span> <span class=\"p\">{<\/span><\/div><div class=\"line\" id=\"file-renderer-suite-js-LC7\">    <span class=\"nx\">assert<\/span><span class=\"p\">.<\/span><span class=\"nx\">isNotNull<\/span><span class=\"p\">(<\/span><span class=\"nx\">renderer<\/span><span class=\"p\">,<\/span> <span class=\"s2\">&quot;&#39;renderer&#39; is not defined&quot;<\/span><span class=\"p\">);<\/span><\/div><div class=\"line\" id=\"file-renderer-suite-js-LC8\"><span class=\"p\">}<\/span><\/div><\/pre>\n        <\/td>\n      <\/tr>\n    <\/table>\n  <\/div>\n\n        <\/div>\n\n        <div class=\"gist-meta\">\n          <a href=\"https://gist.github.com/dzwarg/5007506/raw/6cb8f7a3ea60460415a39f040802d17d032afc4c/renderer-suite.js\" style=\"float:right\">view raw<\/a>\n          <a href=\"https://gist.github.com/dzwarg/5007506#file-renderer-suite-js\" style=\"float:right; margin-right:10px; color:#666;\">renderer-suite.js<\/a>\n          <a href=\"https://gist.github.com/dzwarg/5007506\">This Gist<\/a> brought to you by <a href=\"http://github.com\">GitHub<\/a>.\n        <\/div>\n      <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>/*global require:true, assert:true */
require(['renderer']);

var renderer = require('renderer');

function rendererExists() {
    assert.isNotNull(renderer, &quot;'renderer' is not defined&quot;);
}</pre></code></noscript></div>
<p>&#8230; and create the C# test pilot, and notice that we are including processor.js <em>manually</em>:</p>
<script>document.write('<link href=\"https://gist.github.com/assets/embed-17ab34a51711628d8f5449c4663a9318.css\" media=\"screen\" rel=\"stylesheet\" />')
document.write('<div id=\"gist5007506\" class=\"gist\">\n      <div class=\"gist-file\">\n        <div class=\"gist-data gist-syntax\">\n\n\n\n  <div class=\"file-data\">\n    <table cellpadding=\"0\" cellspacing=\"0\" class=\"lines highlight\">\n      <tr>\n        <td class=\"line-numbers\">\n          <span class=\"line-number\" id=\"file-renderertest-cs-L1\" rel=\"file-renderertest-cs-L1\">1<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L2\" rel=\"file-renderertest-cs-L2\">2<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L3\" rel=\"file-renderertest-cs-L3\">3<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L4\" rel=\"file-renderertest-cs-L4\">4<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L5\" rel=\"file-renderertest-cs-L5\">5<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L6\" rel=\"file-renderertest-cs-L6\">6<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L7\" rel=\"file-renderertest-cs-L7\">7<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L8\" rel=\"file-renderertest-cs-L8\">8<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L9\" rel=\"file-renderertest-cs-L9\">9<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L10\" rel=\"file-renderertest-cs-L10\">10<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L11\" rel=\"file-renderertest-cs-L11\">11<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L12\" rel=\"file-renderertest-cs-L12\">12<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L13\" rel=\"file-renderertest-cs-L13\">13<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L14\" rel=\"file-renderertest-cs-L14\">14<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L15\" rel=\"file-renderertest-cs-L15\">15<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L16\" rel=\"file-renderertest-cs-L16\">16<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L17\" rel=\"file-renderertest-cs-L17\">17<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L18\" rel=\"file-renderertest-cs-L18\">18<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L19\" rel=\"file-renderertest-cs-L19\">19<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L20\" rel=\"file-renderertest-cs-L20\">20<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L21\" rel=\"file-renderertest-cs-L21\">21<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L22\" rel=\"file-renderertest-cs-L22\">22<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L23\" rel=\"file-renderertest-cs-L23\">23<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L24\" rel=\"file-renderertest-cs-L24\">24<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L25\" rel=\"file-renderertest-cs-L25\">25<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L26\" rel=\"file-renderertest-cs-L26\">26<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L27\" rel=\"file-renderertest-cs-L27\">27<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L28\" rel=\"file-renderertest-cs-L28\">28<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L29\" rel=\"file-renderertest-cs-L29\">29<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L30\" rel=\"file-renderertest-cs-L30\">30<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L31\" rel=\"file-renderertest-cs-L31\">31<\/span>\n          <span class=\"line-number\" id=\"file-renderertest-cs-L32\" rel=\"file-renderertest-cs-L32\">32<\/span>\n        <\/td>\n        <td class=\"line-data\">\n          <pre class=\"line-pre\"><div class=\"line\" id=\"file-renderertest-cs-LC1\"><span class=\"k\">using<\/span> <span class=\"nn\">JSTest<\/span><span class=\"p\">;<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC2\"><span class=\"k\">using<\/span> <span class=\"nn\">JSTest.ScriptElements<\/span><span class=\"p\">;<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC3\"><span class=\"k\">using<\/span> <span class=\"nn\">JSTest.ScriptLibraries<\/span><span class=\"p\">;<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC4\"><span class=\"k\">using<\/span> <span class=\"nn\">NUnit.Framework<\/span><span class=\"p\">;<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC5\">&nbsp;<\/div><div class=\"line\" id=\"file-renderertest-cs-LC6\"><span class=\"k\">namespace<\/span> <span class=\"nn\">JSLib.Test<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC7\"><span class=\"p\">{<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC8\"><span class=\"na\">    [TestFixture]<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC9\">    <span class=\"k\">public<\/span> <span class=\"k\">class<\/span> <span class=\"nc\">RendererTests<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC10\">    <span class=\"p\">{<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC11\"><span class=\"na\">        [Datapoints]<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC12\">        <span class=\"k\">public<\/span> <span class=\"k\">readonly<\/span> <span class=\"n\">TestCase<\/span><span class=\"p\">[]<\/span> <span class=\"n\">LibraryTests<\/span> <span class=\"p\">=<\/span> <span class=\"n\">TestCase<\/span><span class=\"p\">.<\/span><span class=\"n\">LoadFrom<\/span><span class=\"p\">(<\/span><span class=\"s\">@&quot;..\\..\\Test\\renderer-suite.js&quot;<\/span><span class=\"p\">);<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC13\">&nbsp;<\/div><div class=\"line\" id=\"file-renderertest-cs-LC14\"><span class=\"na\">        [Theory]<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC15\">        <span class=\"k\">public<\/span> <span class=\"k\">void<\/span> <span class=\"nf\">Test<\/span><span class=\"p\">(<\/span><span class=\"n\">TestCase<\/span> <span class=\"n\">testCase<\/span><span class=\"p\">)<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC16\">        <span class=\"p\">{<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC17\">            <span class=\"kt\">var<\/span> <span class=\"n\">script<\/span> <span class=\"p\">=<\/span> <span class=\"k\">new<\/span> <span class=\"n\">TestScript<\/span> <span class=\"p\">{<\/span> <span class=\"n\">IncludeDefaultBreakpoint<\/span> <span class=\"p\">=<\/span> <span class=\"k\">false<\/span> <span class=\"p\">};<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC18\">&nbsp;<\/div><div class=\"line\" id=\"file-renderertest-cs-LC19\">            <span class=\"c1\">// Append required JavaScript libraries.<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC20\">            <span class=\"n\">script<\/span><span class=\"p\">.<\/span><span class=\"n\">AppendBlock<\/span><span class=\"p\">(<\/span><span class=\"k\">new<\/span> <span class=\"n\">JsAssertLibrary<\/span><span class=\"p\">());<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC21\">&nbsp;<\/div><div class=\"line\" id=\"file-renderertest-cs-LC22\">            <span class=\"c1\">// Append required JavaScript Files.<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC23\">            <span class=\"n\">script<\/span><span class=\"p\">.<\/span><span class=\"n\">AppendFile<\/span><span class=\"p\">(<\/span><span class=\"s\">@&quot;..\\..\\Scripts\\require.js&quot;<\/span><span class=\"p\">);<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC24\">            <span class=\"n\">script<\/span><span class=\"p\">.<\/span><span class=\"n\">AppendFile<\/span><span class=\"p\">(<\/span><span class=\"s\">@&quot;..\\..\\Scripts\\processor.js&quot;<\/span><span class=\"p\">);<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC25\">            <span class=\"n\">script<\/span><span class=\"p\">.<\/span><span class=\"n\">AppendFile<\/span><span class=\"p\">(<\/span><span class=\"s\">@&quot;..\\..\\Scripts\\renderer.js&quot;<\/span><span class=\"p\">);<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC26\">            <span class=\"n\">script<\/span><span class=\"p\">.<\/span><span class=\"n\">AppendFile<\/span><span class=\"p\">(<\/span><span class=\"n\">testCase<\/span><span class=\"p\">.<\/span><span class=\"n\">TestFile<\/span><span class=\"p\">);<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC27\">&nbsp;<\/div><div class=\"line\" id=\"file-renderertest-cs-LC28\">            <span class=\"c1\">// Run &#39;Test&#39;.<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC29\">            <span class=\"n\">script<\/span><span class=\"p\">.<\/span><span class=\"n\">RunTest<\/span><span class=\"p\">(<\/span><span class=\"n\">testCase<\/span><span class=\"p\">);<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC30\">        <span class=\"p\">}<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC31\">    <span class=\"p\">}<\/span><\/div><div class=\"line\" id=\"file-renderertest-cs-LC32\"><span class=\"p\">}<\/span><\/div><\/pre>\n        <\/td>\n      <\/tr>\n    <\/table>\n  <\/div>\n\n        <\/div>\n\n        <div class=\"gist-meta\">\n          <a href=\"https://gist.github.com/dzwarg/5007506/raw/61086b2bfbd6ad61f600e4b6658839670e8290fa/RendererTest.cs\" style=\"float:right\">view raw<\/a>\n          <a href=\"https://gist.github.com/dzwarg/5007506#file-renderertest-cs\" style=\"float:right; margin-right:10px; color:#666;\">RendererTest.cs<\/a>\n          <a href=\"https://gist.github.com/dzwarg/5007506\">This Gist<\/a> brought to you by <a href=\"http://github.com\">GitHub<\/a>.\n        <\/div>\n      <\/div>\n<\/div>\n')
</script><div style='margin-bottom:1em;padding:0;'><noscript><code><pre style='overflow:auto;margin:0;padding:0;border:1px solid #DDD;'>using JSTest;
using JSTest.ScriptElements;
using JSTest.ScriptLibraries;
using NUnit.Framework;

namespace JSLib.Test
{
    [TestFixture]
    public class RendererTests
    {
        [Datapoints]
        public readonly TestCase[] LibraryTests = TestCase.LoadFrom(@&quot;..\..\Test\renderer-suite.js&quot;);

        [Theory]
        public void Test(TestCase testCase)
        {
            var script = new TestScript { IncludeDefaultBreakpoint = false };

            // Append required JavaScript libraries.
            script.AppendBlock(new JsAssertLibrary());

            // Append required JavaScript Files.
            script.AppendFile(@&quot;..\..\Scripts\require.js&quot;);
            script.AppendFile(@&quot;..\..\Scripts\processor.js&quot;);
            script.AppendFile(@&quot;..\..\Scripts\renderer.js&quot;);
            script.AppendFile(testCase.TestFile);

            // Run 'Test'.
            script.RunTest(testCase);
        }
    }
}
</pre></code></noscript></div>
<p>It is a little annoying that you need to list all dependencies of an individual module, but we&#8217;re lucky to have relatively small numbers of modules dependent on one another &#8212; a page may load many modules, but the unit tests are discrete enough that those dependencies aren&#8217;t a big pain (yet).</p>
<p>Now that we can start unit testing our JavaScript from NUnit, we&#8217;re going to get crazy!  But what happens when your module uses something like jQuery?  Remember how I mentioned at the beginning of this article that there is no &#8220;window&#8221; or &#8220;document&#8221; object?  Well, there&#8217;s a way to do that, too.  Tune in for the next installment, and I&#8217;ll demonstrate how you can use a headless browser to test!</p>
<p>(All these code examples are available in <a href="https://gist.github.com/dzwarg/5007506">gist form</a>, and you are free to start using them to run your own tests.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.azavea.com/blogs/labs/2013/02/unit-testing-apps-with-jstest-net-and-require-js/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>WMS On Android</title>
		<link>http://www.azavea.com/blogs/labs/2013/01/wms-on-android/</link>
		<comments>http://www.azavea.com/blogs/labs/2013/01/wms-on-android/#comments</comments>
		<pubDate>Mon, 14 Jan 2013 20:52:57 +0000</pubDate>
		<dc:creator>Sam Halperin</dc:creator>
				<category><![CDATA[Posts]]></category>

		<guid isPermaLink="false">http://www.azavea.com/blogs/labs/?p=2473</guid>
		<description><![CDATA[Implemented Using a Google Maps Android API v2, TileLayer Intro This brief article documents some early exploration into using WMS (Web Map Service) with the new Google Maps V2 API. It is intended as a reference to help someone trying to get WMS tiles (IE from GeoServer) onto an Android map. WMS is used to [...]]]></description>
			<content:encoded><![CDATA[<h1>Implemented Using a Google Maps Android API v2, TileLayer</h1>
<h2>Intro</h2>
<p><span style="font-size: 13px;">This brief article documents some early exploration into using WMS (Web Map Service) with the new Google Maps V2 API. It is intended as a reference to help someone trying to get WMS tiles (IE from GeoServer) onto an Android map.</span></p>
<p>WMS is used to serve map tiles over HTTP by back end frameworks like GeoServer.  Some set of geo-referenced data, typically shape files or data stored in a PostGIS database, are returned as raster map tiles.  In the past, this data has been consumed by web applications using a client library such as Leaflet or OpenLayers.  With Google&#8217;s v2 mapping API for android, it is now relatively straightforward to build Android apps that combine WMS tiles with Google&#8217;s base maps and other data such as vector shapes and map markers.</p>
<p>For basic <em>getting started</em> info for v2 Maps, see the <a href="https://developers.google.com/maps/documentation/android/?hl=fr-FR">Google Developer&#8217;s site for the v2 API</a>. This article assumes a working v2 setup with the sample code running without error. After downloading the google play SDK and setting up the library make sure you can view the TileOverlayDemo ($ANDROID_SDK_ROOT/extras/google/google_play_services/samples/maps)</p>
<div id="attachment_2495" class="wp-caption aligncenter" style="width: 316px"><a href="http://www.azavea.com/blogs/labs/2013/01/wms-on-android/ptm-phone/" rel="attachment wp-att-2495"><img class="size-medium wp-image-2495 " title="Philly Tree Map (Projected Release Spring 2013)" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2013/01/ptm-phone-306x600.png" alt="" width="306" height="600" /></a><p class="wp-caption-text">PhillyTreeMap Android App (Proj. Release Spring 2013) showing WMS technique described in the article.</p></div>
<h2> <span style="font-size: 1.5em;">Extending the UrlTileProvider class.</span></h2>
<p>The v2 API provides the UrlTileProvider class, a partial implementation of the TileProvider class which allows developers to pull in map tiles by composing a URL string.</p>
<p>The API to UrlTileProvider is its getTileUrl method. To request a WMS tile,<br />
we override this method to compose the right URL, and the Android mapping SDK does the rest for us. It seems simple enough, but the problem is that the signature of getTileUrl which is <strong style="font-family: monospace;">getTileUrl(int x, int y, int zoom)</strong> provides tile indexes (x and y) and a zoom level, but WMS requires that we provide a bounding box (xmin, ymin, xmax, ymax) in the request URL. The x, y, zoom parameters provide us enough information to figure this out, but we have to do a little bit of math.</p>
<h2>Calculating the map bounds</h2>
<p>We know the bounds of the entire map which is square. (roughly -20037508m to 20037508m in both directions using Web Mercator. See the graphic below or the <a href="http://www.maptiler.org/google-maps-coordinates-tile-bounds-projection/">map tiler site</a> for exact values.) We don&#8217;t use Latitude/Longitude though, because it is unprojected, and this will cause map distortions.</p>
<p>From the <a href="https://developers.google.com/maps/documentation/android/reference/com/google/android/gms/maps/model/TileOverlay">google api docs for TileOverlay</a>:</p>
<p><em> Note that the world is projected using the Mercator projection (see <a href="http://en.wikipedia.org/wiki/Mercator_projection">Wikipedia</a>) with the left (west) side of the map corresponding to -180 degrees of longitude and the right (east) side of the map corresponding to 180 degrees of longitude. To make the map square, the top (north) side of the map corresponds to 85.0511 degrees of latitude and the bottom (south) side of the map corresponds to -85.0511 degrees of latitude. Areas outside this latitude range are not rendered.</em></p>
<h2>Dividing by the number of tiles for a given zoom level.</h2>
<p>The number of tiles in either x or z at any zoom level is n = 2^z. With this, and the bounds of the map, we can figure out the size of the tile. Using this information combined with the maps origin (see graphic) and the x, y, zoom data for a given tile, we can find out its bounding box.</p>
<p>Again from the <a href="https://developers.google.com/maps/documentation/android/reference/com/google/android/gms/maps/model/TileOverlay">google api docs for TileOverlay</a>:</p>
<p><em>At each zoom level, the map is divided into tiles and only the tiles that overlap the screen are downloaded and rendered. Each tile is square and the map is divided into tiles as follows:</em></p>
<ul>
<li>At zoom level 0, one tile represents the entire world. The coordinates of that tile are (x, y) = (0, 0).</li>
<li>At zoom level 1, the world is divided into 4 tiles arranged in a 2 x 2 grid.</li>
<li>&#8230;</li>
<li>At zoom level N, the world is divided into 4N tiles arranged in a 2^N x 2^N grid.&#8221;</li>
</ul>
<p>&nbsp;</p>
<p><a href="http://www.azavea.com/blogs/labs/2013/01/wms-on-android/wms-android/" rel="attachment wp-att-2474"><img class="aligncenter size-medium wp-image-2474" title="wms-android" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2013/01/wms-android-475x585.gif" alt="" width="475" height="585" /></a></p>
<h2>Summary</h2>
<ul>
<li style="margin-bottom: 12px;">zoom level: z = [0..21]<br />
<em>(See GoogleMap.get[Min|Max]ZoomLevel)</em></li>
<li style="margin-bottom: 12px;">map size: S = 20037508.34789244 * 2<br />
<em>This constant comes from converting the lat/long values above to EPSG:900913, Web Mercator. Again, see <a href="http://www.maptiler.org/google-maps-coordinates-tile-bounds-projection/">this page on maptiler</a> for a fantastic visual explanation.</em></li>
<li style="margin-bottom: 12px;">tile size = S / Math.pow(2, z)<br />
<em> So @ zoom level 0, S is the full map, at zoom level 1 there are 2&#215;2 tiles, and at zoom 3 there are 8&#215;8 tiles and so forth.</em></li>
<li style="margin-bottom: 12px;">tile origin = (-20037508.34789244, 20037508.34789244)</li>
<li style="margin-bottom: 12px;">minX of the tiles bbox (for tile index x,y) = origin.x + x * S<br />
<em>Where x is the tile index in the east-west direction passed to the getTileUrl function discussed above. </em></li>
<li style="margin-bottom: 12px;">maxX of the tiles bbox (for tile index x,y) = origin.x + (x+1) * S<br />
<em>x+1 because we are looking for the right edge of the tile.</em></li>
<li style="margin-bottom: 12px;">minY of the tiles bbox (for tile index x,y) = origin.y + y * S</li>
<li style="margin-bottom: 12px;">maxY of the tiles bbox (for tile index x,y)= origin.y + (y+1) * S</li>
</ul>
<h2>Demo Code</h2>
<p>In addition to the following code snippets, I&#8217;ve put <a href="https://github.com/shalperin/android-wms-demo">a sample project on github.</a></p>
<p>Here is a WMSTileProvider class, which inherits from UrlTileProvider. It supports the above bounding box calculation.</p>
<pre>import com.google.android.gms.maps.model.UrlTileProvider;

public abstract class WMSTileProvider extends UrlTileProvider {

    // Web Mercator n/w corner of the map.
    private static final double[] TILE_ORIGIN = {-20037508.34789244, 20037508.34789244};
    //array indexes for that data
    private static final int ORIG_X = 0; 
    private static final int ORIG_Y = 1; // "

    // Size of square world map in meters, using WebMerc projection.
    private static final double MAP_SIZE = 20037508.34789244 * 2;

    // array indexes for array to hold bounding boxes.
    protected static final int MINX = 0;
    protected static final int MAXX = 1;
    protected static final int MINY = 2;
    protected static final int MAXY = 3;

    // Construct with tile size in pixels, normally 256, see parent class.
    public WMSTileProvider(int x, int y) {
    	super(x, y);
    }

    // Return a web Mercator bounding box given tile x/y indexes and a zoom
    // level.
    protected double[] getBoundingBox(int x, int y, int zoom) {
    	double tileSize = MAP_SIZE / Math.pow(2, zoom);
    	double minx = TILE_ORIGIN[ORIG_X] + x * tileSize;
    	double maxx = TILE_ORIGIN[ORIG_X] + (x+1) * tileSize;
    	double miny = TILE_ORIGIN[ORIG_Y] - (y+1) * tileSize;
    	double maxy = TILE_ORIGIN[ORIG_Y] - y * tileSize;

    	double[] bbox = new double[4];
    	bbox[MINX] = minx;
    	bbox[MINY] = miny;
    	bbox[MAXX] = maxx;
    	bbox[MAXY] = maxy;

    	return bbox;
    }

}</pre>
<p>You might use this class in a <em>factory</em> class as follows:</p>
<pre>import java.net.MalformedURLException;
import java.net.URL;
import java.util.Locale;
import android.util.Log;
import com.google.android.gms.maps.model.TileProvider;

public class TileProviderFactory {

	private static final String GEOSERVER_FORMAT =
    		"http://yourApp.org/geoserver/wms" +
    		"?service=WMS" +
    		"&amp;version=1.1.1" +  			
    		"&amp;request=GetMap" +
    		"&amp;layers=yourLayer" +
    		"&amp;bbox=%f,%f,%f,%f" +
    		"&amp;width=256" +
    		"&amp;height=256" +
    		"&amp;srs=EPSG:900913" +
    		"&amp;format=image/png" +				
    		"&amp;transparent=true";	

	// return a geoserver wms tile layer
	private static TileProvider getTileProvider() {
		TileProvider tileProvider = new WMSTileProvider(256,256) {

	        @Override
	        public synchronized URL getTileUrl(int x, int y, int zoom) {
	        	double[] bbox = getBoundingBox(x, y, zoom);
	            String s = String.format(Locale.US, GEOSERVER_FORMAT, bbox[MINX], 
	            		bbox[MINY], bbox[MAXX], bbox[MAXY]);
	            URL url = null;
	            try {
	                url = new URL(s);
	            } catch (MalformedURLException e) {
	                throw new AssertionError(e);
	            }
	            return url;
	        }
		};
		return tileProvider;
	}

}</pre>
<p>So your Activity code (again see the sample Google maps code referenced above) would have the following calls to add the overlay:</p>
<pre>public class MapDisplay extends android.support.v4.app.FragmentActivity {

	//...

	private void setUpMap() {
	    TileProvider tileProvider = TileProviderFactory.getTileProvider();
	    mMap.addTileOverlay(new TileOverlayOptions().tileProvider(tileProvider));    
	}</pre>
<h2>Conclusion</h2>
<p>This article presented a demonstration of a simple WMS client using Google&#8217;s Android v2 Maps API. It covered the math involved with converting from tile index/zoom level to Web Mercator bounding box, and showed how to compose a URL using these values and an instance of Google&#8217;s UrlTileProvider class.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.azavea.com/blogs/labs/2013/01/wms-on-android/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Learn Early, Learn Often &#8212; Early Learning Resources in Chicago</title>
		<link>http://www.azavea.com/blogs/labs/2012/12/learn-early-learn-often/</link>
		<comments>http://www.azavea.com/blogs/labs/2012/12/learn-early-learn-often/#comments</comments>
		<pubDate>Tue, 11 Dec 2012 15:35:17 +0000</pubDate>
		<dc:creator>David Zwarg</dc:creator>
				<category><![CDATA[Posts]]></category>

		<guid isPermaLink="false">http://www.azavea.com/blogs/labs/?p=2399</guid>
		<description><![CDATA[We are proud of the recent launch of the Chicago Early Learning portal. Its launch was well covered, and the portal has been well received.  The development of the site was in collaboration with the SmartChicago Collaborative, a start-up that formed as a partnership between the City of Chicago, the John D. and Catherine T. [...]]]></description>
			<content:encoded><![CDATA[<p>We are proud of the recent launch of the <a href="http://www.chicagoearlylearning.org/">Chicago Early Learning</a> portal. Its <a href="http://www.examiner.com/article/mayor-emanuel-unveils-online-early-learning-portal-to-help-parents-and-families">launch</a> was well <a href="http://chicago.cbslocal.com/2012/11/29/city-offers-early-learning-info-online/">covered</a>, and the portal has been well received.  The development of the site was in collaboration with the <a href="http://www.smartchicagocollaborative.org/">SmartChicago Collaborative</a>, a start-up that formed as a partnership between the <a href="http://www.cityofchicago.org/">City of Chicago</a>, the <a href="http://www.macfound.org/">John D. and Catherine T. MacArthur Foundation</a>, and <a href="http://cct.org/">The Chicago Community Trust</a>.</p>
<p>The Early Learning portal has information about early childhood learning centers in and around Chicago.  It used to be difficult for parents and families to collect, explore, and share this information. Now that all the early learning centers in the city are mapped and listed in one place, it&#8217;s easier for parents and families to discover what services are available.</p>
<p>The portal addresses a simple data problem once the information has been collected. There is very little geographic processing that occurs in the application, and the portal&#8217;s main function is  to display location data.  It&#8217;s not that often that a school will move, so most of the data is relatively static.</p>
<p>Working on a web application with only a small amount of geographic processing was a little unusual for us. While unusual, we were pretty excited about it because we focused heavily on the user experience of the portal, in order to make it easier to use.  We chose technologies that were open and made the portal usable on desktops, tablets, and smartphones. The Google <a href="https://developers.google.com/maps/">Maps API</a> (which includes Geocoding and Directions), along with <a href="http://twitter.github.com/bootstrap/">Twitter Bootstrap</a> and <a href="http://www.twilio.com/">Twilio</a> enables the application to play friendly with many different devices and capabilities.</p>
<p>Not only that, but we&#8217;re excited about what&#8217;s coming next with the City of Chicago. The SmartChicago Collaborative is also working with the City of Chicago on <a href="http://www.smartchicagocollaborative.org/projects/windy-grid/" class="broken_link" rel="nofollow">Windy Grid</a>, a massive, real-time data infrastructure. Building that infrastructure will enable much deeper analysis and hopefully connect many different agencies and their data tools together.</p>
<p>Deep analytics and big data at the city level would be really exciting, and we&#8217;re really happy to see the City of Chicago embracing these goals.  It means that web applications like the <a href="http://www.chicagoearlylearning.org/">Chicago Early Learning</a> portal are just the tip of the iceberg, and we&#8217;re anticipating great things in the future, both from the SmartChicago Collaborative, and the City of Chicago.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.azavea.com/blogs/labs/2012/12/learn-early-learn-often/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Cicero How-To #1: Make Embeddable Web Maps of Political Districts</title>
		<link>http://www.azavea.com/blogs/labs/2012/11/cicero-how-to-1-make-embeddable-web-maps-of-political-districts/</link>
		<comments>http://www.azavea.com/blogs/labs/2012/11/cicero-how-to-1-make-embeddable-web-maps-of-political-districts/#comments</comments>
		<pubDate>Fri, 09 Nov 2012 21:36:44 +0000</pubDate>
		<dc:creator>Andrew Thompson</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[Cicero]]></category>
		<category><![CDATA[Google Maps]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.azavea.com/blogs/labs/?p=2261</guid>
		<description><![CDATA[Developers can get a wealth of political information from our Cicero API, including address-based geocoding and coordinate-matching to congressional and other legislative districts, Census blocks and watersheds, legislator contact information, and election events from around the world. However, one of my favorite features of Cicero, the map call, is actually one of our least used. [...]]]></description>
			<content:encoded><![CDATA[<p>Developers can get a wealth of political information from our Cicero API, including address-based geocoding and coordinate-matching to congressional and other legislative districts, Census blocks and watersheds, legislator contact information, and election events from around the world. However, one of my favorite features of Cicero, the map call, is actually one of our least used.</p>
<p>With <a href="http://cicero.azavea.com/docs/map.html" target="_blank">the Cicero API&#8217;s map call</a>, you can get a customizable image of a district&#8217;s boundaries, and easily embed one or many of these into an interactive map on your website with just a bit of JavaScript.</p>
<p>In this blog post, I&#8217;ll explain how to:</p>
<ol>
<li><a href="#secureaccount">secure your Cicero account info</a>, <a href="#phpcurl">set up PHP cURL</a>, and <a href="#gettoken">get a token from Cicero</a></li>
<li><a href="#districtinfo">get information on a legislative district that represents a particular address</a></li>
<li><a href="#boundaryimage">get a boundary image of that district</a></li>
<li><a href="#googlemaps">and display that image in a Google Maps widget.</a></li>
</ol>
<p>I&#8217;ll be using a mix of PHP, HTML, and JavaScript. Really though, you could do this using any language, and any web mapping framework &#8211; such as the excellent open-source <a href="http://leaflet.cloudmade.com/" target="_blank">Leaflet</a>.</p>
<p>This blog post is written for the absolute beginner. I expect you&#8217;ve done some programming and seen some <a href="http://en.wikipedia.org/wiki/PHP" target="_blank">PHP</a>, <a href="http://en.wikipedia.org/wiki/HTML" target="_blank">HTML</a>, and <a href="http://en.wikipedia.org/wiki/JavaScript" target="_blank">JavaScript</a> code before, and have a handle on at least the concept of a <a href="http://en.wikipedia.org/wiki/Application_programming_interface#Web_APIs" target="_blank">ReST API</a>. You will need a webserver running PHP, even if that&#8217;s only a local test server like <a href="http://www.apachefriends.org/en/xampp.html" target="_blank">XAMPP</a>. Of course, you could follow these steps on a production webserver as well. I will do my best to make no other assumptions, but if you get stuck you can always <a href="http://www.azavea.com/about-us/staff-profiles/andrew-thompson/" target="_blank">ask me for help</a>. More advanced readers may want to save time and skip ahead to <a href="#gettoken">step 3</a> or <a href="#districtinfo">4</a>, where we start actually using Cicero. Many people, beginners and advanced users alike, may want to skim over significant portions of this post. It may be long, but I assure you, it&#8217;s not actually that hard!</p>
<p>All the example files I refer to in this post are available in <a href="https://github.com/andrewbt/cicero-examples" target="_blank">the cicero-examples GitHub repository</a>.</p>
<p>Finally, in a few weeks, I&#8217;ll be writing a second blog post that expands on the simple example code I use in this one, by employing <a href="http://www.jquery.com/" target="_blank">JQuery</a> and extra features of the Google Maps API to make your district maps even more interactive. Stay tuned!</p>
<h1><a name="secureaccount"></a>Step 1: Secure your Cicero Account Details</h1>
<p>To get a token from Cicero, you&#8217;ll need to pass your username and password to the API via an <a href="http://www.jmarshall.com/easy/http/#postmethod" target="_blank">HTTP POST request</a>. We&#8217;re going to use an extension PHP has called cURL to do that in <a href="#phpcurl">step 2</a>. First we need to secure your account info. While visitors can&#8217;t see PHP, in some circumstances (if logging is on by mistake, etc) they could find out your Cicero details if you don&#8217;t put some protection in place. I recommend making a separate PHP file with just your Cicero username and password set to constants. Put that file in a folder outside of your website&#8217;s main web-accessible directory and then use PHP&#8217;s <a href="http://php.net/manual/en/function.include.php" target="_blank">include()</a> or <a href="http://php.net/manual/en/function.require.php" target="_blank">require()</a> statements to bring that separate file into your main PHP code. You can direct PHP to look for include files in other directories either through your <a href="http://www.php.net/manual/en/ini.core.php#ini.include-path" target="_blank">php.ini file&#8217;s include path</a> or simply specifying a <a href="http://php.net/manual/en/function.include.php" target="_blank">relative path in your include statement</a>. If you don&#8217;t have access to a protected directory outside your main web-accessible one, if you&#8217;re running the Apache webserver, you can protect include files via <a href="http://stackoverflow.com/questions/12769478/how-can-i-secure-my-database-credentials-when-using-shared-hosting-and-no-access" target="_blank">clever use of the .htaccess file</a> (hint: it&#8217;s the second post in that article).</p>
<p><a href="https://github.com/andrewbt/cicero-examples/blob/master/Maps_call_blog/include.php" target="_blank">Here (github)</a> is my include.php file:</p>
<script src = "http://gist-it.sudarmuthu.com/github/andrewbt/cicero-examples/blob/master/Maps_call_blog/include.php?footer=minimal"></script>
<h2>Penny for Your Address?</h2>
<p>Notice the third variable I put into this file, $search_loc. It doesn&#8217;t actually have anything to do with your Cicero account details. This will be the address we will pull the elected official and map info from in this example. We&#8217;ll use Azavea&#8217;s Philadelphia office for this post, but you can experiment later and set this to a different address. More data (state, country and zip code, as well as city and street) will ensure a greater chance of successful geocoding and could make response time faster. Obviously, in a more complete web application, you might be getting this address from a user-submitted form rather than hardcoding it like we are for our example.</p>
<h1><a name="phpcurl"></a>Step 2: Setup PHP cURL</h1>
<p>Moving along! We said earlier we&#8217;d be using PHP&#8217;s cURL extension to make POST and GET requests to Cicero. There are <a href="http://rest.elkstein.org/2008/02/using-rest-in-php.html" target="_blank">other ways to do this</a>, but cURL is widely used and fairly easy &#8211; depending on your server. Sometimes, it&#8217;s not enabled by default in certain PHP installations. You can find out if you have it installed by making and navigating to a PHP page with the <a href="http://php.net/manual/en/function.phpinfo.php" target="_blank">phpinfo()</a> function:</p>
<pre>&lt;?php
phpinfo();
?&gt;</pre>
<p>Search the page (Ctrl+F works well) for &#8220;curl&#8221; info. If it&#8217;s there, congrats! If not, and you have access to your <a href="http://php.net/manual/en/configuration.file.php" target="_blank">php.ini file</a>, search for something like the following line:</p>
<pre>;extension=php_curl.dll</pre>
<p>If your line has a semicolon in front of it like above (that&#8217;s PHP&#8217;s line comment symbol), go ahead and delete just the ; to enable the extension. If you can&#8217;t find the line, just add it to the file without the semicolon. If you&#8217;re using Linux or Mac OS X, the extension will be named <strong>php_curl.so</strong> instead of .dll &#8211; .dll is for Windows.</p>
<p>Next, we&#8217;ll need to write a function to use cURL to send data up to Cicero and process the responses we get back. I&#8217;ve shamlessly stolen the function in <a href="https://github.com/andrewbt/cicero-examples/blob/master/Maps_call_blog/get_cicero_info.php" target="_blank">my get_cicero_info.php file (on github)</a> from my colleague Joe Tricarico&#8217;s excellent <a href="http://cicero.azavea.com/docs/hello_world_php.html" target="_blank">Hello World &#8211; PHP</a> example in the Cicero documentation:</p>
<script src = "http://gist-it.sudarmuthu.com/github/andrewbt/cicero-examples/blob/master/Maps_call_blog/get_cicero_info.php?slice=4:17&footer=minimal"></script>
<p>All get_response() does is take any URL, and optionally any data to be used in a POST request ($postfields), initializes cURL, makes the appropriate POST or GET request to the url specified, reads the resulting response into the variable named $json, and then runs $json through a PHP library function called <a href="http://us1.php.net/manual/en/function.json-decode.php" target="_blank">json_decode</a> to give us a variable with data we can manipulate and use in PHP.</p>
<p>JSON stands for JavaScript Object Notation, and if you do anything with APIs like Cicero, it should be your best friend because it is just <em>So. Much. Easier.</em> to read as a human and use in programs than it&#8217;s older cousin, XML (eXtensible Markup Language). Cicero supports both JSON and XML responses, but we&#8217;ll use JSON in this tutorial. If you want to learn more about JSON and how to use it with PHP, <a href="http://nitschinger.at/Handling-JSON-like-a-boss-in-PHP" target="_blank">Michael Nitschinger has a fantastic blog post on the subject</a>.</p>
<h1><a name="gettoken"></a>Step 3: Get a Cicero Token</h1>
<p>OK, we finally get to do something with the API in this step! Also in <a href="https://github.com/andrewbt/cicero-examples/blob/master/Maps_call_blog/get_cicero_info.php" target="_blank">my get_cicero_info.php file</a>, I&#8217;ve written another function, get_cicero_token(), to do exactly that:</p>
<script src = "http://gist-it.sudarmuthu.com/github/andrewbt/cicero-examples/blob/master/Maps_call_blog/get_cicero_info.php?slice=18:36&footer=minimal"></script>
<p>This function I also based off parts of <a href="http://cicero.azavea.com/docs/hello_world_php.html" target="_blank">Joe&#8217;s Hello World &#8211; PHP example</a>, with a few modifications. We take the $username and $password from our previously-included separate file, and use <a href="http://us1.php.net/manual/en/function.urlencode.php" target="_blank">PHP&#8217;s urlencode() function</a> to properly encode them before we send them over HTTP to Cicero. (Some characters like commas, apostrophes, and the like can cause problems if they were sent without first URL encoding them.) Then, we use our get_response() function written earlier, give it the url to get a new token, and the username and password as &#8220;postfields&#8221;, joined by an ampersand (&amp;) just like you might see in a URL. (PHP string interpolation works easily enough we can just put $username and $password into the postfields string &#8211; great!). Now that we (hopefully) have a response, we check that the &#8220;success&#8221; attribute of the response object that Cicero gave us is True. If it&#8217;s not, we&#8217;ll exit the PHP program because we can&#8217;t do anything without a token. Your code may have a bug, or your Internet connection may be down, or Cicero may be temporarily unavailable. If we did get a successful response, this function makes a $token_info array with both our token value and Cicero user ID. We&#8217;ll use this array for other API calls.</p>
<h1><a name="districtinfo"></a>Step 4: Query Cicero for Officials</h1>
<h2>(i.e, Where are You and What do You Want?)</h2>
<p>This is where it gets exciting. Now we&#8217;ll write a PHP function to query Cicero for elected official data, and get what we need to later request a district boundary image from Cicero in <a href="#boundaryimage">step 5</a> and build a Google Maps widget in <a href="#googlemaps">step 6</a>.</p>
<p>Let&#8217;s take a look at <a href="https://github.com/andrewbt/cicero-examples/blob/master/Maps_call_blog/get_cicero_info.php" target="_blank">my get_cicero_info.php file&#8217;s</a> get_map_info_by_location_and_district_type() function below (boy, that&#8217;s a mouthful):</p>
<script src = "http://gist-it.sudarmuthu.com/github/andrewbt/cicero-examples/blob/master/Maps_call_blog/get_cicero_info.php?slice=37:62&footer=minimal"></script>
<p>This function takes the $token_info array our last function made, as well as the $search_loc that we hardcoded in our <a href="https://github.com/andrewbt/cicero-examples/blob/master/Maps_call_blog/include.php" target="_blank">include.php file</a>, and $district_type (new) &#8211; which I&#8217;ve set in this example to <a href="http://cicero.azavea.com/docs/district_type.html#cicero.webservice.models.DistrictType.name_short" target="_blank">STATE_LOWER</a>, one of the many district types available in Cicero. If you wanted something else (like your US House district), just use the appropriate <a href="http://cicero.azavea.com/docs/district_type.html#cicero.webservice.models.DistrictType.name_short" target="_blank">Cicero district type name</a> in place of what I&#8217;ve used. Some addresses may belong to multiple districts of a certain district type (the LOCAL type is a good example, when a city might have several at-large seats like a Mayor and Controller, etc), so even when filtering this way you may need to put in extra program logic to find exactly the right one you want. When it returns more than one, Cicero orders officials by last name alphabetically.</p>
<p>Once again, we URL encode the data we&#8217;ll pass to Cicero (useful in particular for the $search_loc address, as it converts spaces to +&#8217;s and other appropriate URL formatting changes). Our function then builds a $query_string from our information, and specifies that we want JSON output (with &#8220;format=json&#8221;). Note that since $token_info is an array, we have to add curly braces to our string interpolation syntax here to get at our token and user ID elements:</p>
<script src = "http://gist-it.sudarmuthu.com/github/andrewbt/cicero-examples/blob/master/Maps_call_blog/get_cicero_info.php?slice=40:44&footer=minimal"></script>
<p>We then append our $query_string to the main URL for Cicero&#8217;s <a href="http://cicero.azavea.com/docs/official.html" target="_blank">official call</a>, and get a response:</p>
<script src = "http://gist-it.sudarmuthu.com/github/andrewbt/cicero-examples/blob/master/Maps_call_blog/get_cicero_info.php?slice=44:45&footer=minimal"></script>
<p>With Cicero calls that use geocoding, like official, a list of &#8220;candidates&#8221; objects will be part of the response. Sometimes a given address will geocode to multiple lat/long points &#8211; the official information for each of these points will be a candidate object in the list. Usually, only one candidate object is returned though, so we assume that in this example. In our code, there&#8217;s a check to make sure that Cicero was able to find at least one geocoded candidate location and get the officials from the address you gave it:</p>
<script src = "http://gist-it.sudarmuthu.com/github/andrewbt/cicero-examples/blob/master/Maps_call_blog/get_cicero_info.php?slice=46:50&footer=minimal"></script>
<p>Since $candidates is a list, even if it only contains one object like our example right now, we have to reference the 0th element in the rest of our code.</p>
<p>We want to get the geocoded point Cicero produced for our address, because we&#8217;ll use this later in the Google Maps widget as the center of the map. To do this, we&#8217;ll get the x and y values of the 0th candidate Cicero gave us, and make a new array ($lat_long_of_search_loc) that contains them:</p>
<script src = "http://gist-it.sudarmuthu.com/github/andrewbt/cicero-examples/blob/master/Maps_call_blog/get_cicero_info.php?slice=51:54&footer=minimal"></script>
<p>This function also gets our crucial $unique_district_id for the district we want to display on the map, too. Each district in Cicero has a unique district ID (also called a &#8220;primary key&#8221;), and while you can request a district map with <a href="http://cicero.azavea.com/docs/map.html" target="_blank">other information</a>, after you&#8217;ve gotten an official object this is the easiest and most fool-proof:</p>
<script src = "http://gist-it.sudarmuthu.com/github/andrewbt/cicero-examples/blob/master/Maps_call_blog/get_cicero_info.php?slice=55:56&footer=minimal"></script>
<p>Finally, we&#8217;ll stuff our address&#8217;s lat/long and the unique district ID into a new PHP array, $map_info, so we can use them in <a href="#boundaryimage">our final PHP function</a>:</p>
<script src = "http://gist-it.sudarmuthu.com/github/andrewbt/cicero-examples/blob/master/Maps_call_blog/get_cicero_info.php?slice=57:60&footer=minimal"></script>
<h1><a name="boundaryimage"></a>Step 5: Grab a District Map and Get Ready for JavaScript</h1>
<p>So we have a latitude and longitude to center a map on, and we have a unique district ID from Cicero. We&#8217;re almost done with our PHP server-side programming.</p>
<p>Let&#8217;s take a look at the <a href="https://github.com/andrewbt/cicero-examples/blob/master/Maps_call_blog/get_cicero_info.php" target="_blank">get_cicero_info.php file</a>&#8216;s get_district_map() function, and the last few lines in the file:</p>
<script src = "http://gist-it.sudarmuthu.com/github/andrewbt/cicero-examples/blob/master/Maps_call_blog/get_cicero_info.php?slice=61:82&footer=minimal"></script>
<p>What&#8217;s going on here? This function takes our $token_info array again, along with our new $map_info array. We build a new $query_string and $map_url for the <a href="http://cicero.azavea.com/docs/map.html" target="_blank">map call</a> this time. There are a few parameters in this one that we haven&#8217;t seen until now:</p>
<ul>
<li><strong>include_image_data</strong> &#8211; This tells Cicero to send along the <a href="http://en.wikipedia.org/wiki/Base64" target="_blank">base64 image data</a> as well as a link to a PNG image hosted on our servers. This is optional, but has advantages over using the hosted image URL which is why we use it in this example. If you take a look at the JSON response, you&#8217;ll see the base64 data as a huge stream of seemingly senseless characters &#8211; it&#8217;s how we can represent an image in text form. You can actually put this base64 stream in the src= part of the HTML image tag, and browsers will render it as an image. Pretty cool, huh? If you use the URL given to the district map image given in Cicero&#8217;s response instead, be warned that image is only guaranteed to stay on our servers for 7 days. The advantage to using base64 data is that we will already have it handy when it comes time to display the map,  so we won&#8217;t need to download the PNG then which saves us time and bandwidth.</li>
<li><strong>srs=4326</strong> &#8211; If you&#8217;re not a geographer, you might not know what a <a href="http://en.wikipedia.org/wiki/Spatial_reference_system" target="_blank">Spatial Reference System (SRS)</a> is, nor would you know what <a href="http://cicero.azavea.com/docs/epsg_codes.html" target="_blank">EPSG codes</a> or other <a href="http://en.wikipedia.org/wiki/SRID">SRIDs</a> are. But you don&#8217;t really need to! Just know for now that Google Maps takes latitude and longitude data, which is EPSG code 4326, and the one we&#8217;ll be using. If you don&#8217;t set this, Cicero defaults to a <a href="http://en.wikipedia.org/wiki/Map_projection" target="_blank">map projection system</a> called &#8220;Web Mercator,&#8221; which might play nice with other mapping frameworks, but not Google Maps. (Even though Google Maps is based on Web Mercator, the Image Overlay function we&#8217;ll be using assumes regular latitude and longitude.)</li>
<li><strong>width=500&amp;height=500</strong> &#8211; These specify the dimensions of the map image Cicero will return, and are only two of a slew of other <a href="http://cicero.azavea.com/docs/map.html?highlight=srs#styling" target="_blank">map style options</a> &#8211; including colors! The max is 3300 pixels, but 500 or 1000 loads faster and the visual difference is negligible except when a user zooms in closely. In my upcoming second blog post, we&#8217;ll discuss dynamically getting district overlay images of different sizes depending on the user&#8217;s browser window size and as a user zooms into the map, which will maintain image quality much better. For now though, we&#8217;ll keep it simple and hardcode 500 pixels, and limit the maximum zoom level in Google Maps in <a href="#googlemaps">step 6.</a></li>
</ul>
<p>Our function gets a response from Cicero, verifies that a map actually was returned in the response (exits the script if not), and then gets the data for the map object (including the image URL, and the lat/long data to properly position it on our map widget) and sets that to the $district_map_image_data array.</p>
<p>Since we&#8217;ll need to use this data in JavaScript code next, we return a new <a href="http://us1.php.net/manual/en/function.json-encode.php" target="_blank">json_encoded</a> PHP array of the lat/long of our center point, and the $district_map_image_data. Finally, the last three lines execute all our PHP functions and create a final $map_data_for_javascript variable with the info we&#8217;ll need as we move to client-side JavaScript in step 6!</p>
<h1><a name="googlemaps"></a>Step 6: To the Browser!</h1>
<p>At last! Let&#8217;s write a few lines of HTML and JavaScript, and we&#8217;ll finally get to see a district map from Cicero.</p>
<p>I&#8217;ve used Google&#8217;s <a href="https://developers.google.com/maps/documentation/javascript/overlays#GroundOverlays" target="_blank">Ground Overlay tutorial</a> and <a href="https://developers.google.com/maps/documentation/javascript/v2/examples/groundoverlay-simple" target="_blank">code sample file</a> as a base for <a href="https://github.com/andrewbt/cicero-examples/blob/master/Maps_call_blog/display_gmaps_overlay.php" target="_blank">my display_gmaps_overlay.php</a> file. I&#8217;ll highlight important parts here, but you should really take a look yourself and follow along.</p>
<p>NOTE: My demo file uses the Google Maps JavaScript API without an API key. Google will let you do this for development, but if you want to put this code on a live site, you&#8217;ll need to <a href="https://developers.google.com/maps/documentation/javascript/tutorial">register with them and get a key</a>. If you&#8217;re using my file, you will need to add your key in the &#8220;googleapis.com&#8221; URL.</p>
<p>Since PHP is executed on the server (server-side), and JavaScript is executed in the browser (client-side), there&#8217;s a small kludge to get them to work together. (I&#8217;ll improve this using JQuery in my next blog.) Even though it is mostly HTML and JavaScript, display_gmaps_overlay.php is still a PHP file. We need to include <a href="https://github.com/andrewbt/cicero-examples/blob/master/Maps_call_blog/get_cicero_info.php" target="_blank">get_cicero_info.php</a>:</p>
<script src = "http://gist-it.sudarmuthu.com/github/andrewbt/cicero-examples/blob/master/Maps_call_blog/display_gmaps_overlay.php?slice=0:3&footer=minimal"></script>
<p>to give us access to the output of the functions we just made, and then also set our PHP variable $map_data_for_javascript to a JavaScript variable. We can do this, oddly enough, with a &#8220;php echo&#8221; statement:</p>
<script src = "http://gist-it.sudarmuthu.com/github/andrewbt/cicero-examples/blob/master/Maps_call_blog/display_gmaps_overlay.php?slice=16:19&footer=minimal"></script>
<p>The PHP in this file and the included one is processed on the server, and the new JavaScript var map_data_from_php is set to the output of PHP&#8217;s echo of $map_data_for_javascript (which, as you should remember, we made as a JSON-formatted string with json_encode), and the client is none the wiser. We&#8217;ve taken a PHP object and made it a JavaScript object!</p>
<p>Following Google&#8217;s <a href="https://developers.google.com/maps/documentation/javascript/overlays#GroundOverlays" target="_blank">code sample</a>, we next need to create a map object centered at our address&#8217;s geocoded latitude/longitude. Because map_data_from_php is JSON, we can navigate the fields using simple dot syntax:</p>
<script src = "http://gist-it.sudarmuthu.com/github/andrewbt/cicero-examples/blob/master/Maps_call_blog/display_gmaps_overlay.php?slice=19:22&footer=minimal"></script>
<p>Next comes a tricky part: defining the bounds of our district image &#8211; the lat/long of where it starts and ends. If we didn&#8217;t define these, Google Maps would have no idea where to put our image. If we define them incorrectly, Google Maps either won&#8217;t show our district image at all or it will be horribly contorted:</p>
<script src = "http://gist-it.sudarmuthu.com/github/andrewbt/cicero-examples/blob/master/Maps_call_blog/display_gmaps_overlay.php?slice=22:27&footer=minimal"></script>
<p>Let&#8217;s step through this, because the ordering of your arguments is very important here. There are two Google Maps API calls used &#8211; google.maps.LatLngBounds(), and google.maps.LatLng(). The first takes two (lat,long) pairs as arguments and makes what we geographers call a &#8220;bounding box&#8221;. Assuming North is &#8220;up&#8221;, Google specifies these pairs <em>must</em> be given in the order of southwest (&#8220;bottom left&#8221;) first, northeast (&#8220;top right&#8221;) second. IE, LatLngBounds(southwest point, northeast point). For example, if you wanted to draw a bounding box over most of the state of New Jersey, you&#8217;d put Philadelphia&#8217;s lat/long point first, and New York City&#8217;s lat/long point second. The second API call, LatLng(), makes *one* (lat,long) pair given two decimal numbers.</p>
<p>We&#8217;re using values from the &#8220;extent&#8221; object of the &#8220;district_map_image_data&#8221; object of the &#8220;map_data_from_php&#8221; variable to make all of these points. In JavaScript&#8217;s dot syntax, that&#8217;s map_data_from_php.district_map_image_data.extent.whateverValue. y_min, x_min, y_max, and x_max are all values in the extent object, that we got from the Cicero API with their default names &#8211; even though they took a trip through PHP, they&#8217;re essentially unchanged.<br />
<a name="latlongnote"><br />
<h2>A note about Latitude and Longitude</h2>
<p></a><br />
Let&#8217;s look at the extent object (note, this is not in the example files):</p>
<pre>"extent":{"x_min":-75.167614,"srid":4326,"y_max":40.002104,"y_min":39.927964,"x_max":-75.093474}</pre>
<p>Like every location in the lower 48 contiguous United States, Philadelphia has a positive, northern latitude and a negative, western longitude. The decimal degree numbers in the extent object above may be confusing if you&#8217;re more familiar with the degrees/minutes/seconds way of measuring latitude and longitude (ie, 39°N 59&#8242; 59&#8243;), but they represent the same thing and are <a href="http://transition.fcc.gov/mb/audio/bickel/DDDMMSS-decimal.html">easily converted.</a> Computation is much easier with decimal degrees, which is why Google Maps and Cicero use that format.</p>
<p>The following can be counter-intuitive to many people: Latitude is Y, Longitude is X. That&#8217;s not the way the lines seem to appear on a globe, but <a href="http://www.nationalatlas.gov/articles/mapping/a_latlong.html">it&#8217;s true if you think about which axis each is measuring.</a></p>
<p>So, Google Maps is looking for LatLngBounds(southwest point, northeast point), in that order. Use the extent values Cicero gave you to construct those points: the Southwesterly vertex of the map image will use the pairing (y_min, x_min), and the Northeasterly vertex will use the point (y_max, x_max). Doesn&#8217;t make sense? Remember: since the X/longitude values are <em>negative</em> in the Western hemisphere, x_min=-75.16&#8230; is actually <em>further West</em> than x_max=-75.09&#8230;.</p>
<h2>Near the finish line&#8230;</h2>
<p>Next we need to set some map options and initialize the map, which I&#8217;ve kept mostly the same as in Google&#8217;s code sample. Set our &#8220;azavea&#8221; var to the center, and set the maxZoom at 16. Zooming in any higher would make our simple 500 pixel image overlay fuzzy. Note that we&#8217;ll improve this later in my next blog:</p>
<script src = "http://gist-it.sudarmuthu.com/github/andrewbt/cicero-examples/blob/master/Maps_call_blog/display_gmaps_overlay.php?slice=28:36&footer=minimal"></script>
<p>If you want a marker at your address, create it:</p>
<script src = "http://gist-it.sudarmuthu.com/github/andrewbt/cicero-examples/blob/master/Maps_call_blog/display_gmaps_overlay.php?slice=36:42&footer=minimal"></script>
<p>Finally, we&#8217;ll make our &#8220;districtoverlay&#8221; variable using the image URL given to us by Cicero, the imageBounds we defined above (and I explained at length), and add the overlay to the map:</p>
<script src = "http://gist-it.sudarmuthu.com/github/andrewbt/cicero-examples/blob/master/Maps_call_blog/display_gmaps_overlay.php?slice=42:47&footer=minimal"></script>
<p>That just about covers it! If you put <a href="https://github.com/andrewbt/cicero-examples/tree/master/Maps_call_blog" target="_blank">these github files</a> on a server with PHP, and navigate to display_gmaps_overlay.php using a browser, you should see an interactive Google map widget with your district image load! Congratulations! If you&#8217;re integrating this into a larger web application, perhaps this page could pop up when a representative&#8217;s name is clicked, or the map size could be shrunk down and otherwise embedded into the page. Either way, now you&#8217;ll be able to give your politically-minded website viewers some interactive, geographic context as to who their elected officials are.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.azavea.com/blogs/labs/2012/11/cicero-how-to-1-make-embeddable-web-maps-of-political-districts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Loosely Coupled, Reusable UI Components in Backbone.js</title>
		<link>http://www.azavea.com/blogs/labs/2012/11/loosely-coupled-reusable-ui-components-in-backbone-js-4/</link>
		<comments>http://www.azavea.com/blogs/labs/2012/11/loosely-coupled-reusable-ui-components-in-backbone-js-4/#comments</comments>
		<pubDate>Fri, 02 Nov 2012 14:57:22 +0000</pubDate>
		<dc:creator>Sam Halperin</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[Backbone.js]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[UI]]></category>

		<guid isPermaLink="false">http://www.azavea.com/blogs/labs/?p=2371</guid>
		<description><![CDATA[This article assumes a fairly good understanding of the Backbone.js MV* library. There is a lot of good material on the web for learning Backbone, including the Backbone home page at backbonejs.org. Intro One of the things that differentiates Backbone from other frameworks is that it is extremely lightweight. It specifies the framework for doing [...]]]></description>
			<content:encoded><![CDATA[<p>This article assumes a fairly good understanding of the Backbone.js MV* library. There is a lot of good material on the web for learning Backbone, including the Backbone home page at <a href="http://backbonejs.org">backbonejs.org.</a></p>
<h2 id="intro">Intro</h2>
<p>One of the things that differentiates Backbone from other frameworks is that it is extremely lightweight. It specifies the framework for doing complex things, including making complex interactive user interfaces, but it doesn&#8217;t come with any usable UI widgets. The purpose of this article is to talk about some Backbone and JavaScript techniques that might make it possible to build reusable interface libraries to use with custom Backbone apps.</p>
<h2 id="a-typical-pattern-tight-view-and-model-binding">A typical pattern, tight view and model binding:</h2>
<p>In a recent application, I added UI to modify the opacity and color ramp palette in a map raster layer. It essentially provides a user interface so that when the user slides the opacity slider, the data displayed becomes transparent, revealing the underlying base map. The application took advantage of Backbone Views, Models and event bindings to structure the components and interaction.</p>
<p><center><br />
<a href="http://www.azavea.com/blogs/labs/2012/11/loosely-coupled-reusable-ui-components-in-backbone-js-4/raster-ui/" rel="attachment wp-att-2372"><img class="alignnone size-medium wp-image-2372" title="raster-ui" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2012/11/raster-ui-475x406.png" alt="" width="475" height="406" /></a></center>&nbsp;</p>
<p>I am wary of trivial Backbone examples, but a simplified example is an opacity control in some sort of image editing app:</p>
<p style="text-align: center;"> <a href="http://www.azavea.com/blogs/labs/2012/11/loosely-coupled-reusable-ui-components-in-backbone-js-4/tightlycoupledmodelview/" rel="attachment wp-att-2373"><img class="size-medium wp-image-2373 aligncenter" title="tightlyCoupledModelView" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2012/11/tightlyCoupledModelView-377x600.png" alt="" width="377" height="600" /></a></p>
<p>&nbsp;</p>
<p>When the user slides the slider in the opacity view, it sets the opacity attribute of the image model. This fires a &#8220;change&#8221; event on the image model, which causes the image display view to update to the right opacity.</p>
<p>The problem with this structure is that what is basically a generic control, used for controlling the level of any numerical attribute, has been tightly couple to an image model, where it only controls opacity. What we&#8217;d really like to do is build a generic UI component called slider control, that we could then use for the example above. If we can do this, then we can create plug and play controls that conform to specifications. IE you might replace a slider control with a list-based control that still sets a numerical value.</p>
<p>So as a first shot at generalizing this interface, perhaps we could -parameterize- the Opacity Controller View. Perhaps its constructor takes not only a reference to its model, but also to an attribute parameter to change on that model. So for example, you might have the following instances:</p>
<pre>var imageOpacityControlView = new LevelControlView({
    model: imageView,
    attribute: opacity,
});

var imageBrightnessControlView = new LevelControlView({
    model: imageView,
    attribute: brightness,
});

var image ContrastControlView = new LevelControlView({
    model: imageView,
    attribute: contrast,
})</pre>
<p>The implementation of this LevelControlView could look like this:</p>
<pre>views.LevelControlView = Backbone.View.extend({
    initialize: function initLevelControlview() {
        this.template = this.options.template;
        this.model = this.options.model;
        this.attribute = this.options.attribute;
    },

    events: {
        "change .slider" : "setLevel"
    },

    render: function {
        this.$el.html(this.template({}));
    },

    setLevel: function(evt) {
        // in a more advanced version we could map to a parameterized range 
        // of values.  For now just set the parameterized attribute 
        //(whether // thats opacity, contrast or brightness or something else). 
        this.model.set(this.attribute, this.$el.find(".slider").val());
    }
});</pre>
<p>&nbsp;</p>
<p>This is a pretty good first shot, but it&#8217;s slightly inflexible. If the view controls more than one model, or a model and a collection, they all have to be added explicitly. When our app changes, and the views must change to accommodate. This is true because there is too tight of a coupling between the views and their models. It also means that we overload people who are good at UI design and engineering with system integration and application architecture tasks. What you really want is to be able to write the view and view model once, in a generic, reusable way, and then forget about it, regardless if other aspects of your app changes.</p>
<h2 id="the-solution">The Solution</h2>
<p>The solution is in two parts, first: lets create a model for our UI view that is dumb and doesn&#8217;t know anything about the application logic. For the level control above, the model has exactly 1 attribute, level. We then need to wire this up to our image model, so that it can update its own view.</p>
<p>It&#8217;s tempting to bind the models together directly, but this is probably not a good idea. The problem with this is that now we need to make either the Level Model, or the Image Model smart enough to respond to a change event in another model. There&#8217;s really no good place for this binding code with this architecture. It&#8217;s also not good for maintainability and managing complexity.</p>
<p><a href="http://www.azavea.com/blogs/labs/2012/11/loosely-coupled-reusable-ui-components-in-backbone-js-4/modelmodelbinding/" rel="attachment wp-att-2375"><img class="aligncenter size-full wp-image-2375" title="modelModelBinding" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2012/11/modelModelBinding.png" alt="" width="457" height="463" /></a></p>
<p>&nbsp;</p>
<p>View to view model coupling is a pattern that we use a lot, and is well understood. On the other hand it is not good for our models to start listening to other models for change events. You end up with an application graph that looks like a total complex mess because there are no rules for how objects can communicate.</p>
<p>The second part of the solution is to bring the notion of a Controller back into Backbone application development. Let&#8217;s introduce an Image Controller. Its instance has references to the level model, and to the image model, and it wires these two models together.</p>
<pre>controllers.ImageController = {
    initialize: function(options) {

        this.opacityControl = options.opacityControlModel;
        this.image = options.imageDisplayModel;

        // this binding is what wires the 2 models together through
        // the setOpacity method.
        this.opacityControl.on("change", this.onOpacityChange, this);
    },

    onOpacityChange: function() {
        this.image.set("opacity", this.opacityControl.get("level");)
    }

    /* We can do exactly the same thing for an arbitrary number of UI
       controls like rotation, brightness, contrast, etc.  (Of course
       it is beyond the scope of this exercise, and probably quite difficult
       to programmatically change some of these parameters because they are not
       exposed through CSS the way opacity and rotation are.
    */

};</pre>
<p>So what you end up with is</p>
<p><a href="http://www.azavea.com/blogs/labs/2012/11/loosely-coupled-reusable-ui-components-in-backbone-js-4/looselycoupledwithcontroller/" rel="attachment wp-att-2376"><img class="aligncenter size-medium wp-image-2376" title="looselyCoupledWithController" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2012/11/looselyCoupledWithController-475x548.png" alt="" width="475" height="548" /></a></p>
<p>&nbsp;</p>
<p>It&#8217;s pretty clear how you could use this to wire up lots of disparate generic UI&#8217;s to their targets. You could have a levelControlModel, a brightnessControlModel and a contrastControlModel all wired up in the ImageController in similar fashion. (It would be up to your excellent, focused UI developer to figure out how you actually create a parameterized image view where you can set contrast and brightness.. no mean feat!)</p>
<h2 id="conclusion">Conclusion</h2>
<p>This does a couple of things for us. First off, when it comes time to debug this application, we know that View -&gt; Model bindings are where they always used to be, but that if there is a more complex binding, we probably need to look to the controller for the feature. The other advantage is that are user interfaces are now entirely decoupled from our application, and can therefor be extracted out to reusable UI libraries, and developed by people who focus on HCI engineering exclusively.</p>
<p>Going a step further, it would be entirely possible to create libraries of reusable UI components that other people could plug into their own apps. Everyone structures their backbone apps a little bit differently, some using Require.js, some using global namespaces. I think if you had a library that played as nicely as possible with all of these different approaches, you could produce a product that would be useful to a lot of different developers. Also it would be produced in a way that the UI was beautiful and highly decoupled from application logic by necessity.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.azavea.com/blogs/labs/2012/11/loosely-coupled-reusable-ui-components-in-backbone-js-4/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Cicero API &#8211; Accepting Credit and Debit Card Payments with Stripe</title>
		<link>http://www.azavea.com/blogs/labs/2012/08/cicero-api-accepting-credit-and-debit-card-payments-with-stripe/</link>
		<comments>http://www.azavea.com/blogs/labs/2012/08/cicero-api-accepting-credit-and-debit-card-payments-with-stripe/#comments</comments>
		<pubDate>Wed, 01 Aug 2012 19:33:46 +0000</pubDate>
		<dc:creator>Joe Tricarico</dc:creator>
				<category><![CDATA[Posts]]></category>
		<category><![CDATA[Cicero]]></category>

		<guid isPermaLink="false">http://www.azavea.com/blogs/labs/?p=2133</guid>
		<description><![CDATA[Until recently any client who wanted to purchase Cicero API credits would contact us directly and request that the credits be added to their account. We then issued the client an invoice to be paid by check.  In order to enable customers to purchase credits immediately (at any time of day), eliminate the need for us [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.azavea.com/cicero"><img class="wp-image-2182 alignleft" title="2010_Cicero_Logo_whitebg" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2012/08/2010_Cicero_Logo_whitebg.gif" alt="" width="250" height="55" /></a></p>
<p>Until recently any client who wanted to purchase Cicero API credits would contact us directly and request that the credits be added to their account. We then issued the client an invoice to be paid by check.  In order to enable customers to purchase credits immediately (at any time of day), eliminate the need for us to process orders by phone, and deposit paper checks, we decided to implement online payment processing accessible via the user account pages.</p>
<p><a href="http://www.azavea.com/blogs/labs/2012/08/cicero-api-accepting-credit-and-debit-card-payments-with-stripe/blueprints/" rel="attachment wp-att-2190"><img class="alignright size-thumbnail wp-image-2190" title="blueprints" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2012/08/blueprints-150x150.png" alt="" width="150" height="150" /></a>We considered PayPal, Google Payments and several other online payment processing services, but after extensive research we decided to go with <a href="https://stripe.com/" target="_blank">Stripe</a>, a secure online payment system. Despite being the &#8220;new kid on the block&#8221;, Stripe has quickly established itself as a super secure and easy-to-use alternative to some of the more well-known payment processing services available.</p>
<p>Processing online payments with Stripe is simple and secure. Great documentation, easy-to-use wrappers, and an extensive testing framework make developing applications a pleasure. The intuitive online dashboard makes it easy to manage and visualize customers, payments, and refunds.</p>
<h2>How it works</h2>
<p>After creating an account and obtaining an API key, you create a form on your website to collect your user&#8217;s payment information. Stripe&#8217;s JavaScript API is used to securely submit this data to Stripe&#8217;s servers. If the card info is valid, Stripe returns a single-use token that can be passed onto your backend to charge the customer. With this process, none of the user&#8217;s card information is sent to your servers, and the customer is never redirected to a third-party site to pay.</p>
<p><a href="https://stripe.com/docs/libraries">Stripe API libraries</a> exist for over a dozen programming applications and frameworks. We use <a href="http://pypi.python.org/pypi/stripe/">Stripe&#8217;s Python library</a> to create and update customer records with contact and card information. As part of this step, Stripe checks the billing address against the information on the card (although not all banks support this).</p>
<p>If any of the fraud checks fail, we do not attempt to charge the customer. Otherwise, the card is charged and <a href="http://www.azavea.com/products/cicero/pricing/">API credits</a> are added to the user&#8217;s account.</p>
<p>For added redundancy, we also take advantage of Stripe&#8217;s <a href="https://stripe.com/docs/webhooks">webhooks</a>. They send a web request to our Cicero servers, and we mark the payment confirmed. In the unlikely event that, say, the plug got pulled on our server right as a charge was being made, we would be able to add the credits upon receiving notification from Stripe that the payment went through successfully. (If our servers were to be down, Stripe would keep retrying the request until they come back up and an &#8220;OK&#8221; response is received.)</p>
<h2>Testing</h2>
<p>There is a way to test just about anything without anyone being charged real money. Developers can use a test account dashboard, API keys, and credit card numbers. Writing unit tests is easy because there are special card numbers to test each type of error, such as a declined card or mismatched ZIP code.</p>
<h2>Pricing</h2>
<p>The fee is 30 cents plus 2.9%. The customer&#8217;s country and type of card used do not matter. Volume discounts are offered for merchants that charge over $1 million per year.</p>
<h2>Stripe Caveats</h2>
<ul>
<li>Only a customer&#8217;s last card used is stored in Stripe. This makes it easy to allow the user to use their previous card instead of reentering all of the information. However, if he or she wanted to use the a card used for an order before the last, it would have to be reentered.</li>
<li>Payments are disbursed with a seven-day float. This is not a major issue for us, but could be for a reseller taking a high-volume special order with a short lead time, for example. Waiting a week to get paid is certainly better than other providers that can sometimes freeze your account without warning.</li>
<li>Stripe is not yet available outside the United States.</li>
</ul>
<div>Overall, Stripe&#8217;s transparency and ease-of-use from both a development and billing perspective makes it a great option. It is certainly worth looking into for anyone looking to accept payments online.</div>
]]></content:encoded>
			<wfw:commentRss>http://www.azavea.com/blogs/labs/2012/08/cicero-api-accepting-credit-and-debit-card-payments-with-stripe/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Asgard Calling: GeoTrellis Release Candidate 0.7.0-RC2</title>
		<link>http://www.azavea.com/blogs/labs/2012/08/asgard-calling-geotrellis-release-candidate-0-7-0-rc2/</link>
		<comments>http://www.azavea.com/blogs/labs/2012/08/asgard-calling-geotrellis-release-candidate-0-7-0-rc2/#comments</comments>
		<pubDate>Wed, 01 Aug 2012 15:47:46 +0000</pubDate>
		<dc:creator>Josh Marcus</dc:creator>
				<category><![CDATA[Posts]]></category>

		<guid isPermaLink="false">http://www.azavea.com/blogs/labs/?p=2154</guid>
		<description><![CDATA[Erik and I are extremely excited to announce that the new release candidate (0.7.0-RC2) for GeoTrellis for version 0.7, also known as Asgard, is now available for review and testing. This is the code that will become GeoTrellis 0.7.0 unless issues turn up during user testing, so we’d love to hear any feedback, answer any [...]]]></description>
			<content:encoded><![CDATA[<p>Erik and I are extremely excited to announce that the new release candidate (0.7.0-RC2) for GeoTrellis for version 0.7, also known as Asgard, is now available for review and testing. This is the code that will become GeoTrellis 0.7.0 unless issues turn up during user testing, so we’d love to hear any feedback, answer any questions, or resolve any issues that you find. The <a title="Getting Started documentation" href="http://azavea.github.com/geotrellis/getting_started/GeoTrellis.html" target="_blank">Getting Started documentation</a> and the <a title="API documentation" href="http://azavea.github.com/geotrellis/0.7/api" target="_blank">API documentation</a> have been updated to reflect the new release.</p>
<p>Some fun big picture statistics: between 0.6 and 0.7, there have been 301 files changed, 10,566 lines of code added, and 7,385 lines of code deleted.</p>
<div id="attachment_2157" class="wp-caption aligncenter" style="width: 485px"><a href="http://www.azavea.com/blogs/labs/2012/08/asgard-calling-geotrellis-release-candidate-0-7-0-rc2/800px-asgard/" rel="attachment wp-att-2157"><img class="size-medium wp-image-2157" title="800px-asgard" src="http://www.azavea.com/blogs/labs/wp-content/uploads/2012/08/800px-asgard-475x191.jpg" alt="The rainbow bridge to GeoTrellis 0.7" width="475" height="191" /></a><p class="wp-caption-text">The rainbow bridge to GeoTrellis Asgard</p></div>
<p>Here is a summary of some important changes:</p>
<ul>
<li>Powerful new support for extremely large rasters through tiled raster data classes</li>
<li>New map/reduce-style definition of operations for data parallelism on large raster data</li>
<li>Support for a range of new raster data types for efficient memory utilization and performance improvements</li>
<li>Significant speed improvements through lazy evaluation</li>
<li>Improved geoprocessing operation hierarchy and operation naming scheme</li>
<li>Modernized benchmark structure with many new performance benchmarks, including tiled raster tests</li>
<li>First class support for floating point raster data values, with floating point raster interface, support in core operations for floating point values, and implementation of floating point ARG formats</li>
<li>The getting started documentation has been significantly expanded and improved (<a title="http://azavea.github.com/geotrellis/getting_started/GeoTrellis.html" href="http://azavea.github.com/geotrellis/getting_started/GeoTrellis.html" target="_blank">http://azavea.github.com/geotrellis/getting_started/GeoTrellis.html</a>)</li>
<li>Executable geotrellis tools can now be installed via <a title="Conscript" href="https://github.com/n8han/conscript/" target="_blank">conscript</a></li>
<li>The geotrellis template has moved to the github repository <a title="geotrellis.g8" href="http://github.com/azavea/geotrellis.g8" target="_blank">geotrellis.g8</a>, and can now be installed using giter8</li>
</ul>
<p>Another exciting development since the 0.6 release: support for the ARG raster format was contributed to GDAL by David Zwarg. Using a recent build of GDAL, users can convert from other raster formats into ARG and also use GDAL’s full suite of raster conversion tools on existing ARG files. Future releases of GDAL will contain this ARG-support, as well as tools like QGIS which use GDAL internally.</p>
<p>Best,<br />
GeoTrellis Team</p>
<p>Release Notes: <a title="http://notes.implicit.ly/post/30455035622/geotrellis-0-7-0" target="_blank">http://notes.implicit.ly/post/30455035622/geotrellis-0-7-0</a><br />
Github: <a title="http://github.com/azavea/geotrellis" href="http://github.com/azavea/geotrellis" target="_blank">http://github.com/azavea/geotrellis</a><br />
Maven repository: <a title="https://oss.sonatype.org/content/repositories/releases/" href="https://oss.sonatype.org/content/repositories/releases/" target="_blank">https://oss.sonatype.org/content/repositories/releases/</a><br />
Documentation: <a title="http://azavea.github.com/geotrellis/getting_started/GeoTrellis.html" href="http://azavea.github.com/geotrellis/getting_started/GeoTrellis.html" target="_blank">http://azavea.github.com/geotrellis/getting_started/GeoTrellis.html</a><br />
API Scaladocs: <a title="http://azavea.github.com/geotrellis/0.7/api" href="http://azavea.github.com/geotrellis/0.7/api" target="_blank">http://azavea.github.com/geotrellis/0.7/api</a><br />
Issue tracker: <a title="https://github.com/azavea/geotrellis/issues?state=open" href="https://github.com/azavea/geotrellis/issues?state=open" target="_blank" class="broken_link" rel="nofollow">https://github.com/azavea/geotrellis/issues?milestone=3&amp;state=open</a><br />
Mailing list: <a title="https://groups.google.com/group/geotrellis-user" href="https://groups.google.com/group/geotrellis-user" target="_blank">https://groups.google.com/group/geotrellis-user</a><br />
IRC: #geotrellis on freenode</p>
]]></content:encoded>
			<wfw:commentRss>http://www.azavea.com/blogs/labs/2012/08/asgard-calling-geotrellis-release-candidate-0-7-0-rc2/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
