Thursday, March 26, 2015

Nix Stuff I Always Forget



Bash .profile additions


Count all files in the current directory
  • alias count='ls -l | wc -l'
Count all the xml files
  • alias countxml='ls -l *.xml | wc -l'
Remove all files of type "xml" from the current directory
  • alias remallxml="find . -maxdepth 1 -name '*.xml' -delete"


"cat" files and "grep" contents while listing the name of the file (in this case "huxley")
  • cat * | grep "hux" *
More friendly size listing with ls -l
Remove all files More user friendly way to see file sizes with ls -l

  • ls -l --block-size=MB
  • du -h /folder




Plate Carree: Geoserver and ArcIMS Compatibility

Anyone trying to connect Geoserver to an ArcSDE dataset stored as (ESRI) EPSG: 54001 will quickly find that not all Plate Carree's are created equal. Geoserver does not like ESRI's choice of ellipsoid, which means tweaking the parameters slightly. 

Follow these simple steps to make EPSG:54001 operational in Geoserver.
1. Edit ../webapps/geoserver/data/user_projections/epsg.properties in your Tomcat context.
2. Add a new line at the end of the file and append the following text as 1 line. Syntax is critical.

54001= PROJCS["WGS 84 / Plate Carree", GEOGCS["WGS 84", DATUM["World Geodetic System 1984", SPHEROID["WGS 84", 6378137.0, 298.257223563, AUTHORITY["EPSG","7030"]], AUTHORITY["EPSG","6326"]], PRIMEM["Greenwich", 0.0, AUTHORITY["EPSG","8901"]], UNIT["degree", 0.017453292519943295], AXIS["Geodetic longitude", EAST], AXIS["Geodetic latitude", NORTH], AUTHORITY["EPSG","4326"]], PROJECTION["Equidistant Cylindrical (Spherical)", AUTHORITY["EPSG","9823"]], PARAMETER["central_meridian", 0.0], PARAMETER["latitude_of_origin", 0.0], PARAMETER["standard_parallel_1", 0.0],PARAMETER["false_easting", 0.0],PARAMETER["false_northing", 0.0],UNIT["m", 1.0],AXIS["Easting",EAST],AXIS["Northing", NORTH],AUTHORITY["EPSG","54001"]]

3. Restart Geoserver.
4. In your Geoserver Admin page select "Demos" and click on the "SRS List" link.
5. Search for either "54001" or "Plate Carree" and view the results.


Your projection should be in this list. Remember to keep an eye out on the Geoserver log for errors.

Generating Heat Maps for Point Data Using OpenLayers and Solr


Something that's been absent from OpenLayers for some time was a reliable and simple method of heat mapping smaller volumes ( ~25,000 records) of point data. What follows is a an example implementation that I've set up for testing purposes with the goal of integration into the Harvard Geospatial Library. The data used is a set of geotagged records from Harvard's HOLLIS catalog. While testing the heat mapping functionality could be a lot simpler by using an array of points, I chose to use data I had previously processed for another Library Project - Geotagging Catalog Records. So, I will start with an explanation of the process used to create that data source.

The records were pulled from Library Cloud using curl and saved as text files formatted as JSON.

Pulling data for "Joshua Chamberlain":


curl -v -o chamberlainandbowdoin0_end.json --basic -u xx:xx 'http://localhost:8080/solr/lccore/select?
indent=on&version=2.2&q=collection:hollis_catalog+AND+keyword:chamberlain+AND+keyword:bowdoin&start=0&rows=2
500&fl=call_num,creator,creator_exact,creator_keyword,data_source,dataset_tag,format,height,height_numeric,h
olding_libs,id,id_inst,id_isbn,id_lccn,id_oclc,keyword,language,lcsh,lcsh_exact,loc_call_num_sort_order,loc_
call_num_subject,note,note_keyword,online_avail,pages,pages_numeric,pub_date,pub_date_numeric,pub_location,p
ublisher,rsrc_key,rsrc_value,score_checkouts_undergrad,score_checkouts_grad,score_checkouts_fac,score_reserv
es,score_recalls,score_course_texts,score_holding_libs,score_extra_copies,score_total,shelfrank,sub_title,su
bject_keyword,title,title_exact,title_keyword,title_link_friendly,title_sort,toc,url,ut_count,ut_id,wp_categ
ories,wp_categories_exact,collection,520a,lcsh_keyword,score&wt=json&omitHeader=true'


The JSON output looks like this:




The JSON is then run through MetaCarta's geotagger:

geotag chamberlainandbowdoin0_end.json -d chamberlainandbowdoin0_end.tagged -e 

The output is XML and looks like this:



From here we parse the data using a ruby script and generate both XML and .csv files. We match the geotagged data with it's original input IDs to reconstruct the original Library Cloud record, adding the geotagged data to it.

The data is imported to Solr (blog post to follow) and has the following format.
















































From here we use AJAX to retrieve data from Solr and push it through OpenLayers to create a heat map. The heat map code class used can be found here.



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">

<head>

<title>OpenLayers Heatmap Layer (using &lt;canvas&gt;)</title>
<script src="http://openlayers.org/api/OpenLayers.js" type="text/javascript"></script>
<script src="HeatmapLayer.js" type="text/javascript"></script>

</head>

<body>
    <h3>Solr Search - HEATMAP2-1</h3>

    Query: <input id="query" /> 
    <button id="search">Search</button>
    <hr/>
    <div id="map" style='height:400px;width=400' ></div>
    <hr/>
    <div id="results">
    </div>
</body>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>

<script>

 function on_search(data) {

  var query = $('#query').val();
         if (query.length == 0) {
             return;
     }

   var url = "http://sanger.hul.harvard.edu:8080/solr/ghcore/select?indent=on&version=2.2&q="+query+"&start=0&rows=9000&fl=Geocoded_Field,title,id_inst,Anchor,cLoc1,primLoc&wt=json";

   var ajaxParams = 
     {
       type: "GET",
       url: url,
       dataType: 'jsonp',
       jsonp: 'json.wrf',
           crossDomain: true,
       success: function(data){
           on_data(data);
         },
       error: function(arg){
           errorFunction(arg);
         }
     };
   $.ajax(ajaxParams);
 }

    function on_data(data) {
    

  // Remove the heat2 layer if it already exists so that they do not overlap
  if (this.map.getLayersByName("Heatmap2")[0] !== undefined)
        this.map.removeLayer(this.map.getLayersByName("Heatmap2")[0]);
      
     var heat2 = new Heatmap.Layer("Heatmap2");
     console.log(query);

        $('#results').empty();
        var docs = data.response.docs;
        var total = 'Found ' + docs.length + ' results';
        $('#results').prepend('<div>' + total + '</div>');
        
        var coordinates = [
   [ 54.7408333333,9.43472222222 ],
   [ 55.4700375,19.51416 ]
  ];
  
  $.each(docs, function(j, item) {
   //console.log(item.title+"  "+item.primLoc);
   if (item.primLoc != null) {
          var junk = item.primLoc.split(",");
          var x = parseFloat(junk[0].trim());
          var y = parseFloat(junk[1].trim());
    coordinates.push([x,y]);
   }
  });
  
  for (var latlng in coordinates) {
    var point = new Heatmap.Source(new OpenLayers.LonLat(coordinates[latlng][1], coordinates[latlng][0]));
    heat2.addSource(point);
  }
  
  heat2.defaultIntensity = 0.1;
  heat2.setOpacity(0.33);
     map.addLayer(heat2);
     map.zoomToExtent(heat2.getDataExtent());
     
}

    function on_ready() {
        $('#search').click(on_search);
        /* Hook enter to search */
        $('body').keypress(function(e) {
            if (e.keyCode == '13') {
                on_search();
            }
        });
        
  map = new OpenLayers.Map('map', {
                    controls: [
                        new OpenLayers.Control.Navigation(),
                        new OpenLayers.Control.PanZoomBar(),
                        new OpenLayers.Control.LayerSwitcher({'ascending':false}),
                        new OpenLayers.Control.MousePosition(),
                    ],
  });

  // MAP STUFF HERE - Populate an initial set to view.

    heat.addSource(new Heatmap.Source(new OpenLayers.LonLat(9.434, 54.740)));
    heat.addSource(new Heatmap.Source(new OpenLayers.LonLat(9.833, 54.219)));

  var wms = new OpenLayers.Layer.WMS("OpenLayers WMS", "http://labs.metacarta.com/wms/vmap0", {layers: 'basic'});
   layer = new OpenLayers.Layer.WMS( "OpenLayers WMS",
                    "http://vmap0.tiles.osgeo.org/wms/vmap0", {layers: 'basic'} );
  map.addLayers([layer, heat]);
  map.zoomTo(2);

    }

 var map;
 var heat = new Heatmap.Layer("Heatmap");
    $(document).ready(on_ready);
</script>

Formatting from HiLite.Me.

The result allows me to test the display of geotagged HOLLIS records based on a Solr query such as "title_key:chamberlain".




While not always available, you can try it yourself here. (http://sanger.hul.harvard.edu:8080/geohollis/heat2.html)


Next Steps



Live View: