Index: other-projects/maori-lang-detection/mongodb-data/geojson-features.json
===================================================================
--- other-projects/maori-lang-detection/mongodb-data/geojson-features.json	(revision 33794)
+++ other-projects/maori-lang-detection/mongodb-data/geojson-features.json	(revision 33794)
@@ -0,0 +1,1 @@
+{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[-127.712891,37.09024],[-127.712891,81.15274],[-63.712891,81.15274],[-63.712891,37.09024],[-127.712891,37.09024]]]},"properties":{"code":"US","count":705,"region":"United States"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[55.0,-70.0],[55.0,80.0],[59.0,80.0],[59.0,-70.0],[55.0,-70.0]]]},"properties":{"code":"UNKNOWN","count":150,"region":"UNKNOWN"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[172.885971,-40.900557],[172.885971,76.09944300000001],[176.885971,76.09944300000001],[176.885971,-40.900557],[172.885971,-40.900557]]]},"properties":{"code":"NZ","count":117,"region":"New Zealand"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[102.195397,35.86166],[102.195397,148.86166],[106.195397,148.86166],[106.195397,35.86166],[102.195397,35.86166]]]},"properties":{"code":"CN","count":113,"region":"China"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[0.21374899999999997,46.227638],[0.21374899999999997,117.227638],[4.213749,117.227638],[4.213749,46.227638],[0.21374899999999997,46.227638]]]},"properties":{"code":"FR","count":71,"region":"France"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[8.451526,51.165691],[8.451526,102.16569100000001],[12.451526,102.16569100000001],[12.451526,51.165691],[8.451526,51.165691]]]},"properties":{"code":"DE","count":51,"region":"Germany"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[131.775136,-25.274398],[131.775136,16.725602],[135.775136,16.725602],[135.775136,-25.274398],[131.775136,-25.274398]]]},"properties":{"code":"AU","count":42,"region":"Australia"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[3.2912660000000002,52.132633],[3.2912660000000002,83.132633],[7.291266,83.132633],[7.291266,52.132633],[3.2912660000000002,52.132633]]]},"properties":{"code":"NL","count":31,"region":"Netherlands"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[-108.346771,56.130366],[-108.346771,79.13036600000001],[-104.346771,79.13036600000001],[-104.346771,56.130366],[-108.346771,56.130366]]]},"properties":{"code":"CA","count":23,"region":"Canada"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[-5.435973000000001,55.378051],[-5.435973000000001,73.378051],[-1.4359730000000002,73.378051],[-1.4359730000000002,55.378051],[-5.435973000000001,55.378051]]]},"properties":{"code":"GB","count":18,"region":"United Kingdom"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[7.501785,56.26392],[7.501785,66.26392],[11.501785,66.26392],[11.501785,56.26392],[7.501785,56.26392]]]},"properties":{"code":"DK","count":10,"region":"Denmark"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[136.252924,36.204824],[136.252924,46.204824],[140.252924,46.204824],[140.252924,36.204824],[136.252924,36.204824]]]},"properties":{"code":"JP","count":10,"region":"Japan"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[-5.74922,40.463667],[-5.74922,48.463667],[-1.7492200000000002,48.463667],[-1.7492200000000002,40.463667],[-5.74922,40.463667]]]},"properties":{"code":"ES","count":8,"region":"Spain"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[13.472962,49.817492],[13.472962,57.817492],[17.472962000000003,57.817492],[17.472962000000003,49.817492],[13.472962,49.817492]]]},"properties":{"code":"CZ","count":8,"region":"Czech Republic"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[103.318756,61.52401],[103.318756,68.52401],[107.318756,68.52401],[107.318756,61.52401],[103.318756,61.52401]]]},"properties":{"code":"RU","count":7,"region":"Russia"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[112.109497,22.396428],[112.109497,27.396428],[116.109497,27.396428],[116.109497,22.396428],[112.109497,22.396428]]]},"properties":{"code":"HK","count":5,"region":"Hong Kong"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[29.16558,48.379433],[29.16558,52.379433],[33.16558,52.379433],[33.16558,48.379433],[29.16558,48.379433]]]},"properties":{"code":"UA","count":4,"region":"Ukraine"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[6.227512000000001,46.818188],[6.227512000000001,50.818188],[10.227512,50.818188],[10.227512,46.818188],[6.227512000000001,46.818188]]]},"properties":{"code":"CH","count":4,"region":"Switzerland"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[10.56738,41.87194],[10.56738,45.87194],[14.56738,45.87194],[14.56738,41.87194],[10.56738,41.87194]]]},"properties":{"code":"IT","count":4,"region":"Italy"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[76.96288,20.593684],[76.96288,23.593684],[80.96288,23.593684],[80.96288,20.593684],[76.96288,20.593684]]]},"properties":{"code":"IN","count":3,"region":"India"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[12.550072,47.516231],[12.550072,50.516231],[16.550072,50.516231],[16.550072,47.516231],[12.550072,47.516231]]]},"properties":{"code":"AT","count":3,"region":"Austria"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[-10.24389,53.41291],[-10.24389,56.41291],[-6.24389,56.41291],[-6.24389,53.41291],[-10.24389,53.41291]]]},"properties":{"code":"IE","count":3,"region":"Ireland"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[16.643501,60.128161],[16.643501,63.128161],[20.643501,63.128161],[20.643501,60.128161],[16.643501,60.128161]]]},"properties":{"code":"SE","count":3,"region":"Sweden"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[32.851612,31.046051],[32.851612,34.046051],[36.851612,34.046051],[36.851612,31.046051],[32.851612,31.046051]]]},"properties":{"code":"IL","count":3,"region":"Israel"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[22.96676,45.943161],[22.96676,47.943161],[26.96676,47.943161],[26.96676,45.943161],[22.96676,45.943161]]]},"properties":{"code":"RO","count":2,"region":"Romania"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[17.145136,51.919438],[17.145136,53.919438],[21.145136,53.919438],[21.145136,51.919438],[17.145136,51.919438]]]},"properties":{"code":"PL","count":2,"region":"Poland"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[-66.639968,18.420695],[-66.639968,20.420695],[-62.639967999999996,20.420695],[-62.639967999999996,18.420695],[-66.639968,18.420695]]]},"properties":{"code":"VG","count":2,"region":"British Virgin Islands"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[-161.777671,-21.236736],[-161.777671,-19.236736],[-157.777671,-19.236736],[-157.777671,-21.236736],[-161.777671,-21.236736]]]},"properties":{"code":"CK","count":2,"region":"Cook Islands"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[101.819836,1.352083],[101.819836,2.352083],[105.819836,2.352083],[105.819836,1.352083],[101.819836,1.352083]]]},"properties":{"code":"SG","count":1,"region":"Singapore"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[19.824312,39.074208],[19.824312,40.074208],[23.824312,40.074208],[23.824312,39.074208],[19.824312,39.074208]]]},"properties":{"code":"GR","count":1,"region":"Greece"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[-151.406843,-17.679742],[-151.406843,-16.679742],[-147.406843,-16.679742],[-147.406843,-17.679742],[-151.406843,-17.679742]]]},"properties":{"code":"PF","count":1,"region":"French Polynesia"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[23.48583,42.733883],[23.48583,43.733883],[27.48583,43.733883],[27.48583,42.733883],[23.48583,42.733883]]]},"properties":{"code":"BG","count":1,"region":"Bulgaria"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[125.766922,35.907757],[125.766922,36.907757],[129.766922,36.907757],[129.766922,35.907757],[125.766922,35.907757]]]},"properties":{"code":"KR","count":1,"region":"South Korea"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[20.937506,-30.559482],[20.937506,-29.559482],[24.937506,-29.559482],[24.937506,-30.559482],[20.937506,-30.559482]]]},"properties":{"code":"ZA","count":1,"region":"South Africa"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[-104.552784,23.634501],[-104.552784,24.634501],[-100.552784,24.634501],[-100.552784,23.634501],[-104.552784,23.634501]]]},"properties":{"code":"MX","count":1,"region":"Mexico"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[-10.224454,39.399872],[-10.224454,40.399872],[-6.224454,40.399872],[-6.224454,39.399872],[-10.224454,39.399872]]]},"properties":{"code":"PT","count":1,"region":"Portugal"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[51.688046,32.427908],[51.688046,33.427908],[55.688046,33.427908],[55.688046,32.427908],[51.688046,32.427908]]]},"properties":{"code":"IR","count":1,"region":"Iran"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[-22.0,50.0],[-22.0,51.0],[-18.0,51.0],[-18.0,50.0],[-22.0,50.0]]]},"properties":{"code":"EU","count":1,"region":"Europe"}},{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[23.748151,61.92411],[23.748151,62.92411],[27.748151,62.92411],[27.748151,61.92411],[23.748151,61.92411]]]},"properties":{"code":"FI","count":1,"region":"Finland"}}]}
Index: other-projects/maori-lang-detection/mongodb-data/multipoint.json
===================================================================
--- other-projects/maori-lang-detection/mongodb-data/multipoint.json	(revision 33794)
+++ other-projects/maori-lang-detection/mongodb-data/multipoint.json	(revision 33794)
@@ -0,0 +1,42 @@
+{"type":"MultiPoint","coordinates":
+[
+	[-95.712891,37.09024],
+	[57.0,-70.0],
+	[174.885971,-40.900557],
+	[104.195397,35.86166],
+	[2.213749,46.227638],
+	[10.451526,51.165691],
+	[133.775136,-25.274398],
+	[5.291266,52.132633],
+	[-106.346771,56.130366],
+	[-3.435973,55.378051],
+	[9.501785,56.26392],
+	[138.252924,36.204824],
+	[-3.74922,40.463667],
+	[15.472962,49.817492],
+	[105.318756,61.52401],
+	[114.109497,22.396428],
+	[31.16558,48.379433],
+	[8.227512,46.818188],
+	[12.56738,41.87194],
+	[78.96288,20.593684],
+	[14.550072,47.516231],
+	[-8.24389,53.41291],
+	[18.643501,60.128161],
+	[34.851612,31.046051],
+	[24.96676,45.943161],
+	[19.145136,51.919438],
+	[-64.639968,18.420695],
+	[-159.777671,-21.236736],
+	[103.819836,1.352083],
+	[21.824312,39.074208],
+	[-149.406843,-17.679742],
+	[25.48583,42.733883],
+	[127.766922,35.907757],
+	[22.937506,-30.559482],
+	[-102.552784,23.634501],
+	[-8.224454,39.399872],
+	[53.688046,32.427908],
+	[-20.0,50.0],
+	[25.748151,61.92411]
+]}
Index: other-projects/maori-lang-detection/src/org/greenstone/atea/CountryCodeCountsMapData.java
===================================================================
--- other-projects/maori-lang-detection/src/org/greenstone/atea/CountryCodeCountsMapData.java	(revision 33790)
+++ other-projects/maori-lang-detection/src/org/greenstone/atea/CountryCodeCountsMapData.java	(revision 33794)
@@ -14,7 +14,10 @@
 
 // For working with GeoJSON's Simple Features in Java
+import mil.nga.sf.geojson.Feature;
+import mil.nga.sf.geojson.FeatureCollection;
 import mil.nga.sf.geojson.FeatureConverter;
 import mil.nga.sf.geojson.Geometry;
 import mil.nga.sf.geojson.MultiPoint;
+import mil.nga.sf.geojson.Polygon;
 import mil.nga.sf.geojson.Position;
 
@@ -86,5 +89,5 @@
 	    JsonObject json = obj.getAsJsonObject();
 	    String countryCode = json.get("_id").getAsString();
-	    int count = (int)json.get("count").getAsDouble();	    
+	    int count = (int)json.get("count").getAsDouble();
 	    
 	    //logger.info("Got country code: " + countryCode);
@@ -101,8 +104,11 @@
 		Double lat = countryCodeJson.get("latitude").getAsDouble();
 		//logger.info("long: " + Double.toString(lng) + ", lat: " + Double.toString(lat));
+		String countryName = countryCodeJson.get("name").getAsString();
 		
 		// let's add lat and lng fields to countryCounts object
-		json.addProperty("lng", lng); // adds Number: https://javadoc.io/static/com.google.code.gson/gson/2.8.5/index.html?com/google/gson/Gson.html
+		json.addProperty("lng", lng); // adds Number: https://javadoc.io/static/com.google.code.gson/gson/2.8.5/com/google/gson/JsonObject.html
 		json.addProperty("lat", lat);
+		json.addProperty("region", countryName);
+		
 	    } else {
 		logger.info("No geolocation info found for country code " + countryCode);
@@ -111,5 +117,6 @@
 		    // add lat and lng for Europe
 		    json.addProperty("lng", EU_LNG); 
-		    json.addProperty("lat", EU_LAT);		    
+		    json.addProperty("lat", EU_LAT);
+		    json.addProperty("region", "Europe");
 		}
 		else if(countryCode.equals("UNKNOWN")) {
@@ -118,4 +125,5 @@
 		    json.addProperty("lng", ANTARCTICA_LNG); 
 		    json.addProperty("lat", ANTARCTICA_LAT);
+		    json.addProperty("region", "UNKNOWN");
 		} else {
 		    logger.error("ERROR: entirely unknown country code: " + countryCode);
@@ -184,5 +192,5 @@
 	List<Position> points = new LinkedList<Position>();
 	
-	for(JsonElement obj : countryCountsJsonArray) {
+	for(JsonElement obj : this.countryCountsJsonArray) {
 	    JsonObject json = obj.getAsJsonObject();
 	    Double lng = json.get("lng").getAsDouble();
@@ -198,5 +206,78 @@
     }
 
-
+    // https://javadoc.io/static/com.google.code.gson/gson/2.8.5/index.html
+    public FeatureCollection toFeatureCollection() {
+	final int HISTOGRAM_WIDTH = 4;
+	
+	FeatureCollection featureCollection = new FeatureCollection();
+	
+	for(JsonElement obj : this.countryCountsJsonArray) {
+	    JsonObject json = obj.getAsJsonObject();
+	    
+	    String countryCode = json.get("_id").getAsString();
+	    String region = json.get("region").getAsString();
+	    int count = json.get("count").getAsInt();
+
+	    // make a histogram for each country
+	    Geometry rectangle = this.toPolygon(json, count, HISTOGRAM_WIDTH);
+
+	    Feature countryFeature = new Feature(rectangle);
+	    Map<String, Object> featureProperties = new HashMap<String, Object>();
+	    featureProperties.put("count", new Integer(count));
+	    featureProperties.put("code", countryCode);
+	    featureProperties.put("region", region);
+	    countryFeature.setProperties(featureProperties);
+
+	    featureCollection.addFeature(countryFeature);
+	}
+
+	return featureCollection;
+    }
+
+
+    // create rectangular "histogram" for each country code
+    private Geometry toPolygon(JsonObject json, int count, int HISTOGRAM_WIDTH) {
+	int half_width = HISTOGRAM_WIDTH/2;
+	double vertical_factor = 1.0;
+	
+	Double lng = json.get("lng").getAsDouble();
+	Double lat = json.get("lat").getAsDouble();
+
+	String countryCode = json.get("_id").getAsString();
+
+	// US is a special case. Count is too high by a factor of 8.
+	// So reduce height by twice that factor, and width by twice that factor too.
+	// (A factor of 8 makes north at +125 too high for latitude,
+	// see http://www.learnz.org.nz/sites/learnz.org.nz/files/lat-long-geo-data-01_0.jpg)
+	if(countryCode.equals("US")) {
+	    half_width = 16 * half_width;
+	    vertical_factor = vertical_factor/16.0;
+	}
+	
+	List<List<Position>> outerList = new LinkedList<List<Position>>();
+	List<Position> points = new LinkedList<Position>();	
+	outerList.add(points);
+
+	//create the 4 corners of the rectangle
+	// West is negative, east is positive, south is negative, north is positive
+	// See http://www.learnz.org.nz/sites/learnz.org.nz/files/lat-long-geo-data-01_0.jpg
+	Double east = lng + half_width;
+	Double west = lng - half_width;
+	Double north = lat + (vertical_factor * count);
+	Double south = lat;
+	points.add(new Position(west, south)); // Position(lng, lat) not Position(lat, lng)
+	points.add(new Position(west, north));
+	points.add(new Position(east, north));
+	points.add(new Position(east, south));
+
+
+	Geometry rectangle = new Polygon(outerList);
+	
+	// Coords: a List of List of Positions, see https://ngageoint.github.io/simple-features-geojson-java/docs/api/
+	// https://www.here.xyz/api/concepts/geojsonbasics/#polygon
+
+	return rectangle;
+    }
+    
     public String writeMultiPointGeoJsonToFile(File folder) {
 	final String filename = "multipoint.json";
@@ -229,4 +310,32 @@
     }
     
+    public String writeFeaturesGeoJsonToFile(File folder) {
+	final String filename = "geojson-features.json";
+	File outFile = new File(folder, filename);
+
+	FeatureCollection featureColl = this.toFeatureCollection();
+	String featuresGeojsonString = FeatureConverter.toStringValue(featureColl);
+	System.err.println("\nMap data as featurecollection:\n" + featuresGeojsonString + "\n");
+	try (
+	     Writer writer = new BufferedWriter(new FileWriter(outFile));
+	     ) {
+
+	    
+	    //multiPointGeojsonString = multiPointGeojsonString.replace("[[", "\n[\n\t[");
+	    //multiPointGeojsonString = multiPointGeojsonString.replace("],[", "],\n\t[");
+	    //multiPointGeojsonString = multiPointGeojsonString.replace("]]", "]\n]");
+	    
+	    writer.write(featuresGeojsonString + "\n");
+	} catch(Exception e) {
+	    logger.error("Unable to write multipoint geojson:\n**********************");
+	    logger.error(featuresGeojsonString);
+	    logger.error("**********************\ninto file " + outFile.getAbsolutePath());
+	    logger.error(e.getMessage(), e);
+	}
+
+	return outFile.getAbsolutePath();
+	
+    }
+
     
     // Unfinished and unused
@@ -259,6 +368,9 @@
 	    //System.err.println("geometry: " + multiPointGeojsonString);
 
-	    String outFileName = mapData.writeMultiPointGeoJsonToFile(parentFolder);
-	    System.err.println("***********\nWrote mapdata to file " + outFileName);
+	    String multipointOutFileName = mapData.writeMultiPointGeoJsonToFile(parentFolder);	    
+	    String featuresOutFileName = mapData.writeFeaturesGeoJsonToFile(parentFolder);
+	    System.err.println("***********\nWrote mapdata to files " + multipointOutFileName
+			       + " and " + featuresOutFileName);
+
 	} catch(Exception e) {
 	    logger.error(e.getMessage(), e);
