Branching to roll Release Candidate v5 for 0.1-incubating

git-svn-id: https://svn.apache.org/repos/asf/incubator/climate/branches/0.1-incubating@1507020 13f79535-47bb-0310-9956-ffa450edef68

Former-commit-id: 418ced716599893d4da7a6ccc3a3fe9691141743
diff --git a/CHANGES.txt.REMOVED.git-id b/CHANGES.txt.REMOVED.git-id
index 2b8d037..4ca45d4 100644
--- a/CHANGES.txt.REMOVED.git-id
+++ b/CHANGES.txt.REMOVED.git-id
@@ -1 +1 @@
-e5a124f85553ed7bf4d0806f438889e9d0bdc589
\ No newline at end of file
+533b25ac6cfed3b2e89d2435b7618dc305f4acea
\ No newline at end of file
diff --git a/LICENSE.txt.REMOVED.git-id b/LICENSE.txt.REMOVED.git-id
index 862a03c..76c39f4 100644
--- a/LICENSE.txt.REMOVED.git-id
+++ b/LICENSE.txt.REMOVED.git-id
@@ -1 +1 @@
-d645695673349e3947e8e5ae42332d0ac3164cd7
\ No newline at end of file
+4755709d3ec39bfe811dd2ccd26c11470e850d0f
\ No newline at end of file
diff --git a/easy-rcmet/install.sh b/easy-rcmet/install.sh
index 26b3785..31c22f6 100755
--- a/easy-rcmet/install.sh
+++ b/easy-rcmet/install.sh
@@ -174,9 +174,9 @@
     http://www.virtualenv.org/en/latest/
     http://virtualenvwrapper.readthedocs.org/en/latest/
 
-Additonally, you should set your PYTHON_PATH environment variable to point to the
+Additonally, you should set your PYTHONPATH environment variable to point to the
 RCMET code base that was downloaded into ./src/rcmes. For example:
     
-    export PYTHON_PATH=/path/to/this/script/src/rcmes:$PYTHON_PATH
+    export PYTHONPATH=/path/to/this/script/src/rcmes:$PYTHONPATH
 
 OUTRO
diff --git a/rcmet/LICENSE.txt.REMOVED.git-id b/rcmet/LICENSE.txt.REMOVED.git-id
index 862a03c..ca77b59 100644
--- a/rcmet/LICENSE.txt.REMOVED.git-id
+++ b/rcmet/LICENSE.txt.REMOVED.git-id
@@ -1 +1 @@
-d645695673349e3947e8e5ae42332d0ac3164cd7
\ No newline at end of file
+511958f703b21cc4a4080f4f5b6d34ead5e63371
\ No newline at end of file
diff --git a/rcmet/src/main/python/rcmes/cli/rcmet_ui.py b/rcmet/src/main/python/rcmes/cli/rcmet_ui.py
index f715fed..8cee16c 100755
--- a/rcmet/src/main/python/rcmes/cli/rcmet_ui.py
+++ b/rcmet/src/main/python/rcmes/cli/rcmet_ui.py
@@ -50,6 +50,11 @@
     workDir, cacheDir = misc.getDirSettings()
     temporalGrid = misc.getTemporalGrid()
     spatialGrid = misc.getSpatialGrid()
+    
+    # PER CLIMATE-179 - Guard against a bad spatialGrid Selection
+    while spatialGrid == False:
+        spatialGrid = misc.getSpatialGrid()
+        
     jobProperties = JobProperties(workDir, cacheDir, spatialGrid, temporalGrid)
     
     # Section 1a: Enter model file/s
diff --git a/rcmet/src/main/python/rcmes/services/directory_helpers.py b/rcmet/src/main/python/rcmes/services/directory_helpers.py
index a4dc5a9..0479f09 100644
--- a/rcmet/src/main/python/rcmes/services/directory_helpers.py
+++ b/rcmet/src/main/python/rcmes/services/directory_helpers.py
@@ -48,6 +48,31 @@
     else:
         return returnJSON
 
+WORK_DIR = "/tmp/rcmet"
+
+@route('/getResultDirInfo')
+def getResultDirInfo():
+    dirPath = WORK_DIR
+    dirPath = dirPath.replace('/../', '/')
+    dirPath = dirPath.replace('/./', '/')
+
+    if os.path.isdir(dirPath):
+        listing = os.listdir(dirPath)
+        listingNoHidden = [f for f in listing if f[0] != '.']
+        joinedPaths = [os.path.join(dirPath, f) for f in listingNoHidden]
+        onlyFilesNoDirs = [f for f in joinedPaths if os.path.isfile(f)]
+        finalPaths = [p.replace(WORK_DIR, '') for p in onlyFilesNoDirs]
+        sorted(finalPaths, key=lambda s: s.lower())
+        returnJSON = finalPaths
+    else:
+        returnJSON = []
+
+    returnJSON = json.dumps(returnJSON)
+    if request.query.callback:
+        return "%s(%s)" % (request.query.callback, returnJSON)
+    else:
+        return returnJSON
+
 @route('/getPathLeader/')
 def getPathLeader():
     returnJSON = {"leader": PATH_LEADER}
diff --git a/rcmet/src/main/python/rcmes/services/list_vars_in_file.py b/rcmet/src/main/python/rcmes/services/list_vars_in_file.py
index 3e32861..3a16777 100755
--- a/rcmet/src/main/python/rcmes/services/list_vars_in_file.py
+++ b/rcmet/src/main/python/rcmes/services/list_vars_in_file.py
@@ -59,8 +59,8 @@
       print 'Error_reading_file '+filename
     
     if success:  #make some json
-      var_name_list = json.dumps({'variables':f.variables.keys().encode() }, \
-                                 sort_keys=True, indent=2)
+      var_name_list = json.dumps({'variables': f.variables.keys()}, 
+                                  sort_keys=True, indent=2)
       if (request.query.callback):
           return "%s(%s)" % (request.query.callback, var_name_list)
       return var_name_list
diff --git a/rcmet/src/main/python/rcmes/storage/files.py.REMOVED.git-id b/rcmet/src/main/python/rcmes/storage/files.py.REMOVED.git-id
index 863f145..4e755e3 100644
--- a/rcmet/src/main/python/rcmes/storage/files.py.REMOVED.git-id
+++ b/rcmet/src/main/python/rcmes/storage/files.py.REMOVED.git-id
@@ -1 +1 @@
-4d1d834b058d4dba5c1289af634d361e575d6892
\ No newline at end of file
+f5116f16a7c8ffa36de8b6e10a6116943900c1cc
\ No newline at end of file
diff --git a/rcmet/src/main/python/rcmes/toolkit/do_data_prep.py.REMOVED.git-id b/rcmet/src/main/python/rcmes/toolkit/do_data_prep.py.REMOVED.git-id
index 892ff99..e76ae53 100644
--- a/rcmet/src/main/python/rcmes/toolkit/do_data_prep.py.REMOVED.git-id
+++ b/rcmet/src/main/python/rcmes/toolkit/do_data_prep.py.REMOVED.git-id
@@ -1 +1 @@
-89973b309365e54af318af96cb31afd8e80e6f41
\ No newline at end of file
+f9f5c2982515e671210c4db858f8adb2a3a3f5f2
\ No newline at end of file
diff --git a/rcmet/src/main/python/rcmes/toolkit/metrics.py.REMOVED.git-id b/rcmet/src/main/python/rcmes/toolkit/metrics.py.REMOVED.git-id
index 32af9ac..21cec8b 100644
--- a/rcmet/src/main/python/rcmes/toolkit/metrics.py.REMOVED.git-id
+++ b/rcmet/src/main/python/rcmes/toolkit/metrics.py.REMOVED.git-id
@@ -1 +1 @@
-69bab556012d8e82535248091cdaa0d0a9c9722b
\ No newline at end of file
+e432930085da59f77d6867a36b85a1148824e7f0
\ No newline at end of file
diff --git a/rcmet/src/main/python/rcmes/toolkit/process.py.REMOVED.git-id b/rcmet/src/main/python/rcmes/toolkit/process.py.REMOVED.git-id
index d676a5d..9b73f68 100644
--- a/rcmet/src/main/python/rcmes/toolkit/process.py.REMOVED.git-id
+++ b/rcmet/src/main/python/rcmes/toolkit/process.py.REMOVED.git-id
@@ -1 +1 @@
-c1f8bf1d26380195a38cdb8108128c3f23fc5205
\ No newline at end of file
+11dd9a55f5fb56da8a690876536f5872b1a70404
\ No newline at end of file
diff --git a/rcmet/src/main/python/rcmes/utils/misc.py.REMOVED.git-id b/rcmet/src/main/python/rcmes/utils/misc.py.REMOVED.git-id
index 7162413..7804d4f 100644
--- a/rcmet/src/main/python/rcmes/utils/misc.py.REMOVED.git-id
+++ b/rcmet/src/main/python/rcmes/utils/misc.py.REMOVED.git-id
@@ -1 +1 @@
-48777becb23e692f2dd693f448fbd42c8296f4e5
\ No newline at end of file
+14b6a2e95149f999a128c633e393a4bc834a5021
\ No newline at end of file
diff --git a/rcmet/src/main/python/tests/test_metrics.py b/rcmet/src/main/python/tests/test_metrics.py
new file mode 100644
index 0000000..07ac33e
--- /dev/null
+++ b/rcmet/src/main/python/tests/test_metrics.py
@@ -0,0 +1,52 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+
+import unittest
+
+import toolkit.metrics
+
+import numpy as np
+import numpy.ma as ma
+
+
+class TestCalcPdf(unittest.TestCase):
+    
+    def testUsingSettingsKwarg(self):
+
+        # declare and initialize 1d arrays (mimick timeseries)
+        good_pdf = '0.091'
+      
+        # declare and initialize  3d(time,lat,lon) type array
+        evaluationDataset = np.arange(0, 12, 0.5)
+        evaluationDataset = evaluationDataset.reshape(4, 2, 3)
+        evaluationDataset = ma.array(evaluationDataset)
+    
+        referenceDataset = np.arange(10, 34)
+        referenceDataset = referenceDataset.reshape(4, 2, 3)
+        referenceDataset = ma.array(referenceDataset)
+
+        settings = (3, 10, 20)
+
+        pdf =  '%.3f' % toolkit.metrics.calcPdf(evaluationDataset, referenceDataset, settings)
+        # Checking accuracy to 3 decimal places using a simple string comparison
+        self.assertEqual(pdf, good_pdf)
+        
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/rcmet/src/main/ui/app/css/app.css b/rcmet/src/main/ui/app/css/app.css
index 5b88486..c2a7c91 100755
--- a/rcmet/src/main/ui/app/css/app.css
+++ b/rcmet/src/main/ui/app/css/app.css
@@ -17,16 +17,22 @@
  * under the License.
 **/
 
-body 
+#datasetDiv
 {
-	margin-left: 3%;
-	margin-top: 3%;
+	height: 750px;
+	overflow-y: auto;
+	overflow-x: hidden;
 }
 
 #map 
 {
 	height: 500px;
-	width: 100%;
+}
+
+/* Small preview map that is displayed alongside dataset information */
+.preview-map {
+	height: 100px;
+	width: 100px;
 }
 
 .small-alert 
@@ -37,15 +43,32 @@
 	margin-left: 10px;
 }
 
+.colorSquare
+{
+	margin-top: 3px;
+	height: 10px; 
+	width: 10px;
+}
+
 ul 
 {
 	list-style-type: none;
 }
 
-.btn-link.no-color-link {color:#000000;}
-.btn-link.no-color-link:hover {color:#000000; text-decoration: none;}     
-.btn-link.no-color-link:visited {color:#000000;}     
-.btn-link.no-color-link:active {color:#000000;}     
+.no-color-link {color:#000000;}
+.no-color-link:hover {color:#000000; text-decoration: none;}     
+.no-color-link:visited {color:#000000;}     
+.no-color-link:active {color:#000000;}     
+
+/* Remove the grayed out close button in modal headers */
+.modal-header .close {
+	opacity: 1;
+}
+
+/* Remove the grayed out close button in modal footers */
+.modal-footer .close {
+	opacity: 1;
+}
 
 /** 
   * Timeline 
diff --git a/rcmet/src/main/ui/app/img/globe.png.REMOVED.git-id b/rcmet/src/main/ui/app/img/globe.png.REMOVED.git-id
new file mode 100644
index 0000000..a0d131b
--- /dev/null
+++ b/rcmet/src/main/ui/app/img/globe.png.REMOVED.git-id
@@ -0,0 +1 @@
+5099b4e2d911e5e0a4e7b33b289bf7aa1d2eab55
\ No newline at end of file
diff --git a/rcmet/src/main/ui/app/index.html.REMOVED.git-id b/rcmet/src/main/ui/app/index.html.REMOVED.git-id
index f7fd2a9..5040707 100644
--- a/rcmet/src/main/ui/app/index.html.REMOVED.git-id
+++ b/rcmet/src/main/ui/app/index.html.REMOVED.git-id
@@ -1 +1 @@
-985d4326ab13e30e26980927a3d7a5c2d9e369a4
\ No newline at end of file
+f2b99de30e98bcf70cd141f25cd145ba8d0372ec
\ No newline at end of file
diff --git a/rcmet/src/main/ui/app/js/app.js b/rcmet/src/main/ui/app/js/app.js
index fd5841a..09ea536 100755
--- a/rcmet/src/main/ui/app/js/app.js
+++ b/rcmet/src/main/ui/app/js/app.js
@@ -28,7 +28,7 @@
 App.Controllers = angular.module('ocw.controllers', []);
 App.Filters = angular.module('ocw.filters', []);
 
-angular.module('ocw', ['ocw.services', 'ocw.directives', 'ocw.controllers', 'ocw.filters', 'ui.date']).
+angular.module('ocw', ['ocw.services', 'ocw.directives', 'ocw.controllers', 'ocw.filters', 'ui.date', 'ui.bootstrap']).
 	config(['$routeProvider', function($routeProvider) {
 		$routeProvider.
 			when('/obs', {templateUrl: 'partials/selectObservation.html', controller: 'ObservationSelectCtrl'}).
diff --git a/rcmet/src/main/ui/app/js/controllers/ParameterSelectCtrl.js b/rcmet/src/main/ui/app/js/controllers/ParameterSelectCtrl.js
index fed07d5..3fd47c7 100644
--- a/rcmet/src/main/ui/app/js/controllers/ParameterSelectCtrl.js
+++ b/rcmet/src/main/ui/app/js/controllers/ParameterSelectCtrl.js
@@ -163,7 +163,7 @@
 			$scope.runningEval = false;
 
 			$timeout(function() {
-				$('#evaluationResults').trigger('modalOpen', true, true);
+				window.location = "/app/results.html";
 			}, 100);
 		}).error(function() {
 			$scope.runningEval = false;
diff --git a/rcmet/src/main/ui/app/js/controllers/RcmedSelectionCtrl.js b/rcmet/src/main/ui/app/js/controllers/RcmedSelectionCtrl.js
index bee3c3a..0f8430b 100644
--- a/rcmet/src/main/ui/app/js/controllers/RcmedSelectionCtrl.js
+++ b/rcmet/src/main/ui/app/js/controllers/RcmedSelectionCtrl.js
@@ -76,8 +76,10 @@
 		// Save the parameter id (the important part) and name (for display purposes)
 		newDataset['param'] = $scope.parameterSelection['parameter_id'];
 		newDataset['paramName'] = $scope.parameterSelection['longname'];
-		// Save the (fake) lat/lon information. Our datasets cover the entire globe (I think...)
-		newDataset['latlonVals'] = {"latMin": -90, "latMax": 90, "lonMin": -180, "lonMax": 180};
+		// Save the (fake) lat/lon information. We test with the TRMM dataset. RCMED currently
+		// doesn't return bounding information. This functionality is being added soon. When that
+		// is the case these hard coded values should be removed.
+		newDataset['latlonVals'] = {"latMin": -49.875, "latMax": 49.875, "lonMin": -179.875, "lonMax": 179.875};
 		// Set some defaults for lat/lon variable names. This just helps us display stuff later.
 		newDataset['lat'] = "N/A";
 		newDataset['lon'] = "N/A";
diff --git a/rcmet/src/main/ui/app/js/controllers/ResultCtrl.js b/rcmet/src/main/ui/app/js/controllers/ResultCtrl.js
new file mode 100644
index 0000000..414ad2a
--- /dev/null
+++ b/rcmet/src/main/ui/app/js/controllers/ResultCtrl.js
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    http: *www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+**/
+
+// Controller for result page
+App.Controllers.controller('ResultCtrl', ['$rootScope', '$scope', '$http',
+function($rootScope, $scope, $http) {
+
+	// Grab all figures 
+	$scope.figures = [];
+	$http.jsonp($rootScope.baseURL + '/getResultDirInfo?callback=JSON_CALLBACK').
+		success(function(data) {
+			$scope.figures = data;
+	});
+}]);
diff --git a/rcmet/src/main/ui/app/js/controllers/SettingsCtrl.js b/rcmet/src/main/ui/app/js/controllers/SettingsCtrl.js
index 7c24945..a32a9cb 100755
--- a/rcmet/src/main/ui/app/js/controllers/SettingsCtrl.js
+++ b/rcmet/src/main/ui/app/js/controllers/SettingsCtrl.js
@@ -17,7 +17,8 @@
  * under the License.
 **/
 
-App.Controllers.controller('SettingsCtrl', ['$scope', 'evaluationSettings',
-function($scope, evaluationSettings) {
+App.Controllers.controller('SettingsCtrl', ['$scope', 'evaluationSettings', 'selectedDatasetInformation',
+function($scope, evaluationSettings, selectedDatasetInformation) {
 	$scope.settings = evaluationSettings.getSettings();
+	$scope.datasets = selectedDatasetInformation.getDatasets();
 }]);
diff --git a/rcmet/src/main/ui/app/js/controllers/TimelineCtrl.js b/rcmet/src/main/ui/app/js/controllers/TimelineCtrl.js
index 283e384..9485aa4 100644
--- a/rcmet/src/main/ui/app/js/controllers/TimelineCtrl.js
+++ b/rcmet/src/main/ui/app/js/controllers/TimelineCtrl.js
@@ -28,68 +28,58 @@
  		}
 
 		// Don't process if no datasets have been added
-		if ($scope.datasets.length == 0)
+		if ($scope.datasets.length == 0 || !("timeline" in $rootScope))
 			return;
  		
- 		if ("timeline" in $rootScope) {
- 			
- 			// Create DataTable to add data to timeline
- 			var data = new google.visualization.DataTable();
- 			data.addColumn('datetime', 'start');
-			data.addColumn('datetime', 'end');
-			data.addColumn('string', 'content');
+		// Create DataTable to add data to timeline
+		var data = new google.visualization.DataTable();
+		data.addColumn('datetime', 'start');
+		data.addColumn('datetime', 'end');
+		data.addColumn('string', 'content');
 
-			// Loop through datasets and add data to timeline 
-			var i = -1;
- 			angular.forEach($scope.datasets, function(dataset) {
+		// Loop through datasets and find the overlapping start/end time range
+		var start = $scope.datasets[0].timeVals.start;
+		var end = $scope.datasets[0].timeVals.end;
+		for (var i = 0; i < $scope.datasets.length; i++) {
+			var possibleNewStart = $scope.datasets[i].timeVals.start;
+			var possibleNewEnd = $scope.datasets[i].timeVals.end;
 
- 				// Keep track of dataset count for displaying colors
-				i++;
-				
- 				/* TODO should "disable overlay" also disable timeline? */
+			start = (possibleNewStart > start) ? possibleNewStart : start;
+			end = (possibleNewEnd < end) ? possibleNewEnd : end;
+		}
 
- 				// Get time bounds from dataset 
- 				var start = dataset.timeVals.start;
- 				var end	= dataset.timeVals.end;
+		// Set the timeline extent to the overlapping time range
+		//
+		// NOTE: The month value substring is expected to be 0-based (hence the -1)
+		$rootScope.timeline.setVisibleChartRange(new Date(start.substr(0, 4), start.substr(5, 2) - 1, start.substr(8, 2)),
+												 new Date(end.substr(0, 4), end.substr(5, 2) - 1, end.substr(8, 2)));
 
- 				// Add different color to each bar
- 				var style = 'background-color:' + $rootScope.fillColors[i] +
- 							'; border-color:' + $rootScope.surroundColors[i] + ';';
- 				var ocwBar = '<div class="ocw-bar timeline-event-range" style="' + style + '"></div>';
-        
- 				// Add row to DataTable: object with start and end date
- 				// note: subtract one from month since indexes from 0 to 11
- 				data.addRow([new Date(start.substr(0,4), start.substr(5,2)-1, start.substr(8,2)), 
- 							new Date(end.substr(0,4), end.substr(5,2)-1, end.substr(8,2)),
- 							ocwBar ]);
- 			});
+		// Add user selected bounds to timeline
+		if ($scope.regionParams.areValid) {
 
-			// Add user selected bounds to timeline
-			if ($scope.regionParams.areValid) {
+			var userStart 	= $scope.regionParams.start;
+			var userEnd 	= $scope.regionParams.end;
 
-				var userStart 	= $scope.regionParams.start;
-				var userEnd 	= $scope.regionParams.end;
-
-				// Add color to user selected bounds
-				var style = 'background-color: #000000; border: 2px solid;';
- 				var ocwBar = '<div class="ocw-bar timeline-event-range" style="' + style + '"></div>';
- 				
-				// Add row to DataTable: object with start and end date
- 				// note: subtract one from month since indexes from 0 to 11
- 				data.addRow([new Date(userStart.substr(0,4), userStart.substr(5,2)-1, userStart.substr(8,2)), 
- 							new Date(userEnd.substr(0,4), userEnd.substr(5,2)-1, userEnd.substr(8,2)),
- 							ocwBar ]);
-			}
- 			
-			var options = {
-	                'minHeight': "200px",
-	                'width':  "99.8%",
-	                'zoomable': false
-            };
+			// Add color to user selected bounds
+			var style = 'background-color: #000000; border: 2px solid;';
+			var ocwBar = '<div class="ocw-bar timeline-event-range" style="' + style + '"></div>';
 			
- 			// Draw timeline with data (DataTable) and options (a name-value map) 
-			$rootScope.timeline.draw(data, options);
- 		}
+			// Add row to DataTable: object with start and end date
+			// note: subtract one from month since indexes from 0 to 11
+			data.addRow([new Date(userStart.substr(0,4), userStart.substr(5,2)-1, userStart.substr(8,2)), 
+						new Date(userEnd.substr(0,4), userEnd.substr(5,2)-1, userEnd.substr(8,2)),
+						ocwBar ]);
+		}
+		
+		var options = {
+				"width": "100%",
+				"showCurrentTime": false,
+				"moveable": false,
+				"zoomable": false,
+		};
+		
+		// Draw timeline with data (DataTable) and options (a name-value map) 
+		$rootScope.timeline.draw(data, options);
 	};
 
 	$scope.$on('redrawOverlays', function(event, parameters) {
diff --git a/rcmet/src/main/ui/app/js/controllers/WorldMapCtrl.js b/rcmet/src/main/ui/app/js/controllers/WorldMapCtrl.js
index 782ccdd..3de155c 100644
--- a/rcmet/src/main/ui/app/js/controllers/WorldMapCtrl.js
+++ b/rcmet/src/main/ui/app/js/controllers/WorldMapCtrl.js
@@ -29,56 +29,60 @@
  			$rootScope.rectangleGroup.clearLayers();
  		}
 
-		// Don't process if we don't have any datasets added!!
-		if ($scope.datasets.length == 0)
+		// Don't process if we don't have any datasets added or if the map doesn't exist!!
+		if ($scope.datasets.length == 0 || !("map" in $rootScope))
 			return;
  		
- 		if ("map" in $rootScope) {
- 			// Create Group to add all rectangles to map
- 			$rootScope.rectangleGroup = L.layerGroup();
- 			
- 			// Loop through datasets and add rectangles to Group 
-			var i = -1;
- 			angular.forEach($scope.datasets, function(dataset) {
-				// Keep track of dataset count for displaying colors
-				i++;
+		// Create a group that we'll draw overlays to
+		$rootScope.rectangleGroup = L.layerGroup();
+		// Add rectangle Group to map
+		$rootScope.rectangleGroup.addTo($rootScope.map);
 
-				// If the user disabled the overlay then get out of here!
-				if (!dataset.shouldDisplay)
-					return;
+		// Calculate the overlap region and set the map to show the new overlap
+		var latMin = -90,
+			latMax = 90,
+			lonMin = -180,
+			lonMax = 180;
 
- 				// Get bounds from dataset 
- 				var maplatlon = dataset.latlonVals;
- 				var bounds = [[maplatlon.latMax, maplatlon.lonMin], [maplatlon.latMin, maplatlon.lonMax]];
+		// Get the valid lat/lon range in the selected datasets.
+		for (var i = 0; i < selectedDatasetInformation.getDatasetCount(); i++) {
+			var curDataset = $scope.datasets[i];
 
- 				var polygon = L.rectangle(bounds,{
-					stroke: false,
-					fillColor: $rootScope.fillColors[i],
- 				    fillOpacity: 0.3
- 				});
+			latMin = (curDataset['latlonVals']['latMin'] > latMin) ? curDataset['latlonVals']['latMin'] : latMin;
+			latMax = (curDataset['latlonVals']['latMax'] < latMax) ? curDataset['latlonVals']['latMax'] : latMax;
+			lonMin = (curDataset['latlonVals']['lonMin'] > lonMin) ? curDataset['latlonVals']['lonMin'] : lonMin;
+			lonMax = (curDataset['latlonVals']['lonMax'] < lonMax) ? curDataset['latlonVals']['lonMax'] : lonMax;
+		}
 
- 				// Add layer to Group
- 				$rootScope.rectangleGroup.addLayer(polygon);
- 			});
+		var overlapBounds = [[latMax, lonMin], [latMin, lonMax]];
+		$rootScope.map.fitBounds(overlapBounds, {padding: [0, 0]});
 
-			// Draw user selected region
-			if ($scope.regionParams.areValid) {
+		// Draw border around overlap region
+		var overlapBorder = L.rectangle(overlapBounds, {
+			color: '#000000',
+			opacity: 1.0,
+			fill: false,
+			weight: 2,
+			dashArray: "10 10",
+		});
 
-				var bounds = [[$scope.regionParams.latMax, $scope.regionParams.lonMin],
-							  [$scope.regionParams.latMin, $scope.regionParams.lonMax]];
+		$rootScope.rectangleGroup.addLayer(overlapBorder);
 
-				var polygon = L.rectangle(bounds, {
-					color: '#000000',
-					opacity: 1.0,
-					fill: false,
-				});
+		// Draw user selected region
+		if ($scope.regionParams.areValid) {
 
-				$rootScope.rectangleGroup.addLayer(polygon);
-			}
+			var bounds = [[$scope.regionParams.latMax, $scope.regionParams.lonMin],
+						  [$scope.regionParams.latMin, $scope.regionParams.lonMax]];
 
- 			// Add rectangle Group to map
- 			$rootScope.rectangleGroup.addTo($rootScope.map);
- 		}
+			var polygon = L.rectangle(bounds, {
+				color: '#000000',
+				opacity: .3,
+				stroke: false,
+				fill: true,
+			});
+
+			$rootScope.rectangleGroup.addLayer(polygon);
+		}
 	};
 
 	$scope.$on('redrawOverlays', function(event, parameters) {
diff --git a/rcmet/src/main/ui/app/js/directives/LeafletMap.js b/rcmet/src/main/ui/app/js/directives/LeafletMap.js
index dcdea74..bd56801 100644
--- a/rcmet/src/main/ui/app/js/directives/LeafletMap.js
+++ b/rcmet/src/main/ui/app/js/directives/LeafletMap.js
@@ -28,11 +28,12 @@
 				center: [40, 0],
 				zoom: 2,
 				scrollWheelZoom: false,
+				attributionControl: false,
+				worldCopyJump: true,
 			});
+
 			//create a CloudMade tile layer and add it to the map
-			L.tileLayer('http://{s}.tile.cloudmade.com/57cbb6ca8cac418dbb1a402586df4528/997/256/{z}/{x}/{y}.png', {
-				maxZoom: 4, minZoom: 2,
-			}).addTo($rootScope.map);
+			L.tileLayer('http://{s}.tile.cloudmade.com/57cbb6ca8cac418dbb1a402586df4528/997/256/{z}/{x}/{y}.png', {}).addTo($rootScope.map);
 		}
 	};
 });
diff --git a/rcmet/src/main/ui/app/js/directives/PreviewMap.js b/rcmet/src/main/ui/app/js/directives/PreviewMap.js
new file mode 100644
index 0000000..f46b897
--- /dev/null
+++ b/rcmet/src/main/ui/app/js/directives/PreviewMap.js
@@ -0,0 +1,69 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    http: *www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+**/
+
+App.Directives.directive('previewMap', function($rootScope) {
+	return {
+		restrict: 'A',
+		replace: true,
+		scope: {dataset: '=previewMap', index: '=index'},
+		template: '<div id="{{dataset.name}}" class="preview-map"></div>',
+		replace: true,
+		link: function(scope, element, attrs) {
+
+			// Any attribute that contains {{}} interpolation will be set to null in the attrs
+			// parameter during the link function since the first $digest since the compilation
+			// has yet to run to evaluate it! We can't run a $digest in the middle of compilation,
+			// so using an $observe (or $watch) is the best way to get the values.
+			attrs.$observe('id', function(newId) {
+				var map = L.map(attrs.id, {
+					zoom: 0,
+					scrollWheelZoom: false,
+					zoomControl: false,
+					attributionControl: false,
+					worldCopyJump: true,
+				});
+
+				//create a CloudMade tile layer and add it to the map
+				L.tileLayer('http://{s}.tile.cloudmade.com/57cbb6ca8cac418dbb1a402586df4528/997/256/{z}/{x}/{y}.png', {}).addTo(map);
+
+				// Zoom the map to the dataset bound regions (or at least try our best to do so)
+				var datasetBounds = [[scope.dataset.latlonVals.latMax, scope.dataset.latlonVals.lonMin], 
+									 [scope.dataset.latlonVals.latMin, scope.dataset.latlonVals.lonMax]];
+				map.fitBounds(datasetBounds, {});
+
+				// Draw a colored overlay on the region of the map
+				var maplatlon = scope.dataset.latlonVals;
+				var bounds = [[maplatlon.latMax, maplatlon.lonMin], [maplatlon.latMin, maplatlon.lonMax]];
+
+				var polygon = L.rectangle(bounds,{
+					stroke: false,
+					fillColor: $rootScope.fillColors[1],
+					fillOpacity: 0.6
+				});
+
+				// Add layer to Group
+				var rectangleGroup = L.layerGroup();
+				rectangleGroup.addLayer(polygon);
+
+				// Add the overlay to the map
+				rectangleGroup.addTo(map);
+			});
+		}
+	};
+});
diff --git a/rcmet/src/main/ui/app/js/directives/Timeline.js b/rcmet/src/main/ui/app/js/directives/Timeline.js
index a47966c..fa7abe4 100644
--- a/rcmet/src/main/ui/app/js/directives/Timeline.js
+++ b/rcmet/src/main/ui/app/js/directives/Timeline.js
@@ -16,7 +16,7 @@
 //
 
 // Directive for dealing with the Leaflet map
-App.Directives.directive('timeline', function($rootScope) {
+App.Directives.directive('timeline', function($rootScope, $window) {
 	return {
 		restrict: 'C',
 		replace: true,
@@ -29,6 +29,20 @@
 	    	function initTimeline() {
 	            // Instantiate timeline object.
 	            $rootScope.timeline = new links.Timeline(document.getElementById('OCWtimeline'));
+
+				// Redraw the timeline whenever the window is resized
+				angular.element($window).bind('resize', function() {
+					$rootScope.timeline.checkResize();
+				});
+
+				var options = {
+						"width": "100%",
+						"showCurrentTime": false,
+						"moveable": false,
+						"zoomable": false
+				};
+
+				$rootScope.timeline.draw([], options);
 	        }
 		}
 	}
diff --git a/rcmet/src/main/ui/app/js/lib/angular-ui/angular-ui-0.4-tpls.js.REMOVED.git-id b/rcmet/src/main/ui/app/js/lib/angular-ui/angular-ui-0.4-tpls.js.REMOVED.git-id
new file mode 100644
index 0000000..e99ceab
--- /dev/null
+++ b/rcmet/src/main/ui/app/js/lib/angular-ui/angular-ui-0.4-tpls.js.REMOVED.git-id
@@ -0,0 +1 @@
+76dd8f424aec88e2b44b83907f3031f161e1a190
\ No newline at end of file
diff --git a/rcmet/src/main/ui/app/js/services/EvaluationSettings.js b/rcmet/src/main/ui/app/js/services/EvaluationSettings.js
index 7dd8e69..c2330b6 100755
--- a/rcmet/src/main/ui/app/js/services/EvaluationSettings.js
+++ b/rcmet/src/main/ui/app/js/services/EvaluationSettings.js
@@ -27,6 +27,7 @@
 			'options': ['daily', 'monthly', 'yearly'],
 			'selected': 'monthly',
 		},
+		'spatialSelect': '',
 	};
 
 	return {
diff --git a/rcmet/src/main/ui/app/js/services/SelectedDatasetInformation.js b/rcmet/src/main/ui/app/js/services/SelectedDatasetInformation.js
index af3eaba..8378212 100644
--- a/rcmet/src/main/ui/app/js/services/SelectedDatasetInformation.js
+++ b/rcmet/src/main/ui/app/js/services/SelectedDatasetInformation.js
@@ -33,7 +33,7 @@
 		addDataset: function(dataset) {
 			// All datasets need a shouldDisplay attribute that is used when rendering
 			// the overlays on the map!
-			dataset.shouldDisplay = true;
+			dataset.shouldDisplay = false;
 			// The regrid attribute indicates which dataset should be used for spatial regridding
 			dataset.regrid = false;
 
diff --git a/rcmet/src/main/ui/app/results.html b/rcmet/src/main/ui/app/results.html
new file mode 100755
index 0000000..69a7c66
--- /dev/null
+++ b/rcmet/src/main/ui/app/results.html
@@ -0,0 +1,68 @@
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements.  See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership.  The ASF licenses this file
+ ~ to you under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance
+ ~ with the License.  You may obtain a copy of the License at
+ ~
+ ~    http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing,
+ ~ software distributed under the License is distributed on an
+ ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ ~ KIND, either express or implied.  See the License for the
+ ~ specific language governing permissions and limitations
+ ~ under the License.
+ -->
+
+<!doctype html>
+<html lang="en" ng-app="ocw" ng-controller="ResultCtrl">
+<head>
+  <meta charset="utf-8">
+  <meta name="viewport" content="width=device-width, initial-scale=1.0">
+  <title>OCW UI - Results</title>
+  <link rel="stylesheet" href="css/lib/bootstrap.min.css"/>
+  <link rel="stylesheet" href="css/lib/bootstrap-responsive.min.css"/>
+  <link rel="stylesheet" href="css/lib/font-awesome.min.css"/>
+  <link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/themes/ui-lightness/jquery-ui.min.css" type="text/css"/> 
+  <!--[if lte IE 8]>
+    <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.5/leaflet.ie.css" />
+  <![endif]-->
+  <link rel="stylesheet" href="css/app.css"/>
+</head>
+<body>
+
+<div class="container-fluid">
+	<div class="row-fluid">
+	  <div class="row span12 text-center">
+	    <h2>Apache Open Climate Workbench UI - Results</h2>
+	    <hr />
+	  </div>
+	  <div class="row-fluid text-center">
+	  <ul>
+	  	<li ng-repeat="figure in figures">
+	  	<img src="{{baseURL}}/static/evalResults{{figure}}" alt="" />
+	  	</li>
+	  </ul>
+	  </div>
+	</div>
+</div>
+
+  <!--Libraries-->
+  <script src="js/lib/jquery/jquery-1.10.1.js"></script>
+  <script src="js/lib/jquery/jquery-ui/jquery-ui-1.10.3.min.js"></script>
+  <script src="js/lib/angular/angular.min.js"></script>
+  <script src="js/lib/angular-ui/angular-ui-0.4-tpls.js"></script>
+  <script src="js/lib/jquery/jquery-ui/datepicker-wrapper/date.js"></script>
+  <script src="js/lib/bootstrap/bootstrap.js"></script>
+  
+  <!--General-->
+  <script src="js/app.js"></script>
+
+  <!--Controllers-->
+  <script src="js/controllers/ResultCtrl.js"></script>
+
+</body>
+</html>
diff --git a/rcmet/src/main/ui/config/karma.conf.js b/rcmet/src/main/ui/config/karma.conf.js
index e9491a5..65b5013 100755
--- a/rcmet/src/main/ui/config/karma.conf.js
+++ b/rcmet/src/main/ui/config/karma.conf.js
@@ -26,6 +26,7 @@
   'app/js/lib/bootstrap/bootstrap.js',
   'app/js/lib/angular/angular.js',
   'app/js/lib/angular/angular-*.js',
+  'app/js/lib/angular-ui/*.js',
   'test/lib/angular/angular-mocks.js',
   'app/js/lib/jquery/jquery-ui/datepicker-wrapper/date.js',
   'app/js/lib/leaflet/leaflet-0.5.js',
diff --git a/rcmet/src/main/ui/test/unit/controllers/SettingsCtrlTest.js b/rcmet/src/main/ui/test/unit/controllers/SettingsCtrlTest.js
index f3a558e..12c133d 100644
--- a/rcmet/src/main/ui/test/unit/controllers/SettingsCtrlTest.js
+++ b/rcmet/src/main/ui/test/unit/controllers/SettingsCtrlTest.js
@@ -30,7 +30,17 @@
 				var scope = $rootScope.$new();
 				var ctrl = $controller("SettingsCtrl", {$scope: scope});
 
-				expect(Object.keys(scope.settings)).toEqual(["metrics", "temporal"]);
+				expect(Object.keys(scope.settings)).toEqual(["metrics", "temporal", "spatialSelect"]);
+			});
+		});
+
+		it('should pull the dataset information', function() {
+			inject(function($rootScope, $controller) {
+				var scope = $rootScope.$new();
+				var ctrl = $controller("SettingsCtrl", {$scope: scope});
+
+				expect(typeof scope.datasets).toBe('object');
+				expect(Object.keys(scope.datasets).length).toBe(0);
 			});
 		});
 	});
diff --git a/rcmet/src/main/ui/test/unit/controllers/WorldMapCtrlTest.js b/rcmet/src/main/ui/test/unit/controllers/WorldMapCtrlTest.js
index a6659eb..805dc88 100644
--- a/rcmet/src/main/ui/test/unit/controllers/WorldMapCtrlTest.js
+++ b/rcmet/src/main/ui/test/unit/controllers/WorldMapCtrlTest.js
@@ -35,7 +35,8 @@
 				// Don't try to add the user defined region since we don't have one
 				scope.regionParams.areValid = false;
 				// We need to fake the map object. The only thing we care about is faking the "addLayer" function
-				$rootScope.map = {addLayer: function(){}};
+				// and the "fitBounds" functions which our map controllers makes use of.
+				$rootScope.map = {addLayer: function(){}, fitBounds: function(){}};
 				$rootScope.fillColors = ['#ff0000'];
 
 				expect("rectangleGroup" in $rootScope).toBe(false);
diff --git a/rcmet/src/main/ui/test/unit/directives/PreviewMapTest.js b/rcmet/src/main/ui/test/unit/directives/PreviewMapTest.js
new file mode 100644
index 0000000..a7991e6
--- /dev/null
+++ b/rcmet/src/main/ui/test/unit/directives/PreviewMapTest.js
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+**/
+
+'use strict';
+
+describe('directives', function() {
+	beforeEach(module('ocw'));
+
+	describe('preview-map directive', function() {
+		it('should set the proper class', function() {
+			inject(function($compile, $rootScope) {
+				$rootScope.dataset = {latlonVals: {latMax: 90, lonMax: 90, latMin: -90, lonMin: -90}, name: "TRMM"};
+
+				var element = $compile('<div preview-map="dataset"></div>')($rootScope);
+
+				expect(element.hasClass("preview-map")).toBeTruthy();
+			});
+		});
+
+		it('should set the id of the template to the name of the dataset', function() {
+			inject(function($compile, $rootScope) {
+				$rootScope.dataset = {latlonVals: {latMax: 90, lonMax: 90, latMin: -90, lonMin: -90}, name: "TRMM"};
+
+				var element = $compile('<div preview-map="dataset"></div>')($rootScope);
+
+				expect(element.attr('id')).toEqual("{{dataset.name}}");
+			});
+		});
+	});
+});
diff --git a/rcmet/src/main/ui/test/unit/services/SelectedDatasetInfomationTest.js b/rcmet/src/main/ui/test/unit/services/SelectedDatasetInfomationTest.js
index fa0e027..aeada3d 100644
--- a/rcmet/src/main/ui/test/unit/services/SelectedDatasetInfomationTest.js
+++ b/rcmet/src/main/ui/test/unit/services/SelectedDatasetInfomationTest.js
@@ -53,7 +53,7 @@
 		it('should set the shouldDisplay attribute when adding a dataset', function() {
 			inject(function(selectedDatasetInformation) {
 				selectedDatasetInformation.addDataset({});
-				expect(selectedDatasetInformation.getDatasets()[0].shouldDisplay).toBe(true);
+				expect(selectedDatasetInformation.getDatasets()[0].shouldDisplay).toBe(false);
 			});
 		});