{"id":448,"date":"2015-05-15T14:06:30","date_gmt":"2015-05-15T12:06:30","guid":{"rendered":"http:\/\/hannes.enjoys.it\/blog\/?p=448"},"modified":"2017-10-30T22:48:34","modified_gmt":"2017-10-30T21:48:34","slug":"a-geotiff-of-the-german-2011-census-population-density","status":"publish","type":"post","link":"https:\/\/hannes.enjoys.it\/blog\/2015\/05\/a-geotiff-of-the-german-2011-census-population-density\/","title":{"rendered":"A GeoTIFF of the German 2011 census population density"},"content":{"rendered":"<p>tl;dr: GMT is documented for people who use it since the 80s.<\/p>\n<p><strong>update 2: You can use gmtinfo to calculate the extents, using -I- will make it output the -R parameter! <code>xyz2grd $(gmtinfo -I- *.xyz) ...<\/code><\/strong><\/p>\n<p><strong>update: xyz2grd supports GeoTIFF via its GDAL driver (now?)! For example <code>-Gfile.tif=gd:GTiff<\/code>. See eg <a href=\"http:\/\/gmt.soest.hawaii.edu\/doc\/5.2.1\/grdconvert.html\">http:\/\/gmt.soest.hawaii.edu\/doc\/5.2.1\/grdconvert.html<\/a>. So the way below is overly complicated. I do not know how to apply the advanced settings of GDAL though like compression and prediction etc.<\/strong><\/p>\n<p><a href=\"http:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_berlin.png\"><img loading=\"lazy\" decoding=\"async\" width=\"250\" height=\"194\" src=\"http:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_berlin-250x194.png\" alt=\"zensus2011_berlin\" class=\"alignnone size-medium wp-image-452\" srcset=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_berlin-250x194.png 250w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_berlin-700x544.png 700w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_berlin-120x93.png 120w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_berlin.png 900w\" sizes=\"auto, (max-width: 250px) 100vw, 250px\" \/><\/a><a href=\"http:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_irgendwo.png\"><img loading=\"lazy\" decoding=\"async\" width=\"250\" height=\"194\" src=\"http:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_irgendwo-250x194.png\" alt=\"zensus2011_irgendwo\" class=\"alignnone size-medium wp-image-470\" srcset=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_irgendwo-250x194.png 250w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_irgendwo-700x544.png 700w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_irgendwo-120x93.png 120w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_irgendwo.png 900w\" sizes=\"auto, (max-width: 250px) 100vw, 250px\" \/><\/a><a href=\"http:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_bremen.png\"><img loading=\"lazy\" decoding=\"async\" width=\"250\" height=\"194\" src=\"http:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_bremen-250x194.png\" alt=\"zensus2011_bremen\" class=\"alignnone size-medium wp-image-474\" srcset=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_bremen-250x194.png 250w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_bremen-700x544.png 700w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_bremen-120x93.png 120w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_bremen.png 900w\" sizes=\"auto, (max-width: 250px) 100vw, 250px\" \/><\/a><\/p>\n<p>The Statistische \u00c4mter des Bundes und der L\u00e4nder offer a <a href=\"https:\/\/www.zensus2011.de\/SharedDocs\/Aktuelles\/Ergebnisse\/DemografischeGrunddaten.html\">100 meter grid of Germany&#8217;s population density<\/a>: <a href=\"https:\/\/www.zensus2011.de\/SharedDocs\/Downloads\/DE\/Pressemitteilung\/DemografischeGrunddaten\/csv_Bevoelkerung_100m_Gitter.zip?__blob=publicationFile&#038;v=3\">csv_Bevoelkerung_100m_Gitter.zip<\/a> (110MB). <a href=\"https:\/\/www.zensus2011.de\/SharedDocs\/Downloads\/DE\/Pressemitteilung\/DemografischeGrunddaten\/Datensatzbeschreibung_Bevoelkerung_100m_Gitter.xlsx?__blob=publicationFile&#038;v=2\">Datensatzbeschreibung_Bevoelkerung_100m_Gitter.xlsx<\/a> provides additional information.<\/p>\n<p>Let&#8217;s turn that dataset into a GeoTIFF so we can use it in our GIS. We will use free and open-source tools from <a href=\"http:\/\/gmt.soest.hawaii.edu\">GMT<\/a> and <a href=\"http:\/\/www.gdal.org\/\">GDAL<\/a>. GDAL loves to interpolate values but our data is discrete\/regular. We do not want any kind of interpolation. So <a href=\"http:\/\/gmt.soest.hawaii.edu\/doc\/latest\/xyz2grd.html\">xyz2grd<\/a> from GMT is the best choice for turning the xyz data into a &#8220;continuous&#8221; GIS format (tell me if not). <\/p>\n<h2>Getting to know the data<\/h2>\n<p>Inside the zip is a 1.3GB file Zensus_Bevoelkerung_100m-Gitter.csv with about 36 million lines.<\/p>\n<blockquote><p>Gitter_ID_100m;x_mp_100m;y_mp_100m;Einwohner<br \/>\n100mN26840E43341;4334150;2684050;-1<br \/>\n100mN26840E43342;4334250;2684050;-1<br \/>\n&#8230;<br \/>\n100mN27407E44044;4404450;2740750;3<br \/>\n100mN27407E44045;4404550;2740750;31<br \/>\n100mN27407E44046;4404650;2740750;13<br \/>\n100mN27407E44047;4404750;2740750;14<br \/>\n100mN27407E44048;4404850;2740750;10<\/p><\/blockquote>\n<p>Datensatzbeschreibung_Bevoelkerung_100m_Gitter.xlsx says the coordinates are in <em>ETRS89-LAEA Europe &#8211; EPSG:3035<\/em>.<\/p>\n<p>First we need to find out the geographic extends of the data, you could use your favourite cli tools for that, I wrote a quick .vrt file and used ogrinfo on that:<\/p>\n<p><code>$ cat Zensus_Bevoelkerung_100m-Gitter.csv.vrt<\/code><\/p>\n<blockquote>\n<pre>\r\n&lt;OGRVRTDataSource&gt;\r\n &lt;OGRVRTLayer name=&quot;Zensus_Bevoelkerung_100m-Gitter&quot;&gt;\r\n  &lt;LayerSRS&gt;EPSG:3035&lt;\/LayerSRS&gt;\r\n  &lt;SrcDataSource&gt;Zensus_Bevoelkerung_100m-Gitter.csv&lt;\/SrcDataSource&gt;\r\n  &lt;GeometryType&gt;wkbPoint&lt;\/GeometryType&gt;\r\n  &lt;GeometryField encoding=&quot;PointFromColumns&quot; x=&quot;x_mp_100m&quot; y=&quot;y_mp_100m&quot; \/&gt;\r\n &lt;\/OGRVRTLayer&gt;\r\n&lt;\/OGRVRTDataSource&gt;\r\n<\/pre>\n<\/blockquote>\n<p><code>$ ogrinfo -al Zensus_Bevoelkerung_100m-Gitter.csv.vrt<\/code><\/p>\n<blockquote><p>INFO: Open of `Zensus_Bevoelkerung_100m-Gitter.csv.vrt&#8217; using driver `VRT&#8217; successful.<\/p>\n<p>Layer name: Zensus_Bevoelkerung_100m-Gitter<br \/>\nGeometry: Point<br \/>\nFeature Count: 35785840<br \/>\nExtent: (4031350.000000, 2684050.000000) &#8211; (4672550.000000, 3551450.000000)<br \/>\n&#8230;<\/p><\/blockquote>\n<h2>Creating a netcdf\/grd file from the xyz data with xyz2grd<\/h2>\n<p>xyz2grd wants xyz, nothing else. The Gitter_ID_100m column is redundant in any case, you can calculate it yourself from the x and y fields if needed. So first let&#8217;s convert it to a &#8220;x y z&#8221; format with awk. The separator is ;<\/p>\n<p><code>awk 'FS=\";\" {print $2\" \"$3\" \"$4}' Zensus_Bevoelkerung_100m-Gitter.csv > Zensus_Bevoelkerung_100m-Gitter.xyz<\/code><\/p>\n<p>Now we can write our xyz2grd commandline.<\/p>\n<p>We have our extends:<br \/>\n<code>-R4031350\/4672550\/2684050\/3551450 <\/code><\/p>\n<p>We know the spacing is 100 units (meters):<br \/>\n<code>-I100<\/code><\/p>\n<p>There is one header line:<br \/>\n<code>-h1<\/code><\/p>\n<p>And of course we know that we want a &#8220;classic&#8221; netcdf4 chunk size, whatever that means. We knew that right away, not after googling helplessly for an hour and <a href=\"http:\/\/comments.gmane.org\/gmane.comp.gis.gmt.user\/20050\">eventually finding the hint on some mailing list<\/a>. Not knowing this might have lead to QGIS only seeing NaN values for z, R&#8217;s ncdf\/raster saying &#8220;Error in substr(w, 1, 3) : invalid multibyte string at &#8216;<89>HDF&#8221; and GDAL &#8220;0ERROR 1: nBlockYSize = 130, only 1 supported when reading bottom-up dataset&#8221;.<br \/>\n<code>--IO_NC4_CHUNK_SIZE=c<\/code><\/p>\n<p>The resulting commandline:<br \/>\n<code>xyz2grd -Vl -R4031350\/4672550\/2684050\/3551450 -I100 -h1 --IO_NC4_CHUNK_SIZE=c -GZensus_Bevoelkerung_100m-Gitter.cdf Zensus_Bevoelkerung_100m-Gitter.xyz<\/code><\/p>\n<p>You can inspect the file with grdinfo and gdalinfo now if you want.<\/p>\n<h2>Creating a GeoTIFF from the netcdf\/grd file<\/h2>\n<p>Let&#8217;s turn it into a GeoTIFF with <a href=\"http:\/\/www.gdal.org\/gdal_translate.html\">gdal_translate<\/a>. We will need a bunch of commandline parameters.<\/p>\n<p>The spatial reference system is EPSG:3035, so:<br \/>\n<code>-a_srs EPSG:3035<\/code><\/p>\n<p>Values of -1 mean &#8220;no data&#8221;:<br \/>\n<code>-a_nodata -1<\/code><\/p>\n<p>TIFF is uncompressed by default, we want good lossless compression:<br \/>\n<code>-co COMPRESS=DEFLATE<\/code><\/p>\n<p>The resulting commandline:<br \/>\n<code>gdal_translate -co COMPRESS=DEFLATE -a_srs EPSG:3035 -a_nodata -1 Zensus_Bevoelkerung_100m-Gitter.cdf Zensus_Bevoelkerung_100m-Gitter.tif<\/code><\/p>\n<p>The resulting file is about 8 Megabytes and should work in any reasonable GIS. Have fun!<\/p>\n<h2>Downloads<\/h2>\n<p><a href=\"http:\/\/hannes.enjoys.it\/opendata\/Zensus_Bevoelkerung_100m-Gitter.tif\">http:\/\/hannes.enjoys.it\/opendata\/Zensus_Bevoelkerung_100m-Gitter.tif<\/a><br \/>\nTODO: What license is this now?<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" width=\"800\" height=\"400\" src=\"http:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_hamburg.png\" alt=\"zensus2011_hamburg\" class=\"alignnone size-medium wp-image-453\" srcset=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_hamburg.png 800w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_hamburg-250x125.png 250w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_hamburg-700x350.png 700w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_hamburg-120x60.png 120w\" sizes=\"auto, (max-width: 800px) 100vw, 800px\" \/><br \/>\n<a href=\"http:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_altersheim.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"250\" height=\"188\" src=\"http:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_altersheim-250x188.jpg\" alt=\"zensus2011_altersheim\" class=\"alignnone size-medium wp-image-478\" srcset=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_altersheim-250x188.jpg 250w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_altersheim-120x90.jpg 120w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_altersheim.jpg 698w\" sizes=\"auto, (max-width: 250px) 100vw, 250px\" \/><\/a><a href=\"http:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_schreberg\u00e4rten.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"250\" height=\"188\" src=\"http:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_schreberg\u00e4rten-250x188.jpg\" alt=\"zensus2011_schreberg\u00e4rten\" class=\"alignnone size-medium wp-image-479\" srcset=\"https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_schreberg\u00e4rten-250x188.jpg 250w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_schreberg\u00e4rten-120x90.jpg 120w, https:\/\/hannes.enjoys.it\/blog\/wp-content\/uploads\/zensus2011_schreberg\u00e4rten.jpg 697w\" sizes=\"auto, (max-width: 250px) 100vw, 250px\" \/><\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>tl;dr: GMT is documented for people who use it since the 80s. update 2: You can use gmtinfo to calculate the extents, using -I- will make it output the -R parameter! xyz2grd $(gmtinfo -I- *.xyz) &#8230; update: xyz2grd supports GeoTIFF via its GDAL driver (now?)! For example -Gfile.tif=gd:GTiff. See eg http:\/\/gmt.soest.hawaii.edu\/doc\/5.2.1\/grdconvert.html. So the way below [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[9,22,29,10],"tags":[],"class_list":["post-448","post","type-post","status-publish","format-standard","hentry","category-cartography","category-commandline","category-gis","category-open-data"],"_links":{"self":[{"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/posts\/448","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/comments?post=448"}],"version-history":[{"count":30,"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/posts\/448\/revisions"}],"predecessor-version":[{"id":942,"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/posts\/448\/revisions\/942"}],"wp:attachment":[{"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/media?parent=448"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/categories?post=448"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/hannes.enjoys.it\/blog\/wp-json\/wp\/v2\/tags?post=448"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}