Skip to content

Instantly share code, notes, and snippets.

@chadlawlis
Last active November 12, 2016 18:12
Show Gist options
  • Save chadlawlis/7a23516c787d719c4ef2 to your computer and use it in GitHub Desktop.
Save chadlawlis/7a23516c787d719c4ef2 to your computer and use it in GitHub Desktop.
USAID | DELIVER PROJECT Web Mapping Technical Documentation

USAID | DELIVER PROJECT
Mapping PPMR Data Technical Documentation

ppmr-title-screen

Overview

The PPMR web map serves as a health logistics data visualization tool to highlight the reach and impact of the USAID | DELIVER PROJECT. The map highlights the Average Monthly Consumption (AMC) of eleven unique contraceptive methods by country, displaying the breakdown of AMC by donor program alongside its respective data source.

All data from this initial round of mapping is from the May 2012 quarterly report. Data from subsequent quarterly reports is to be added once it is available, along with the technical infrastructure to allow for layer switching between months.

Content

This documentation will address the following:

  1. Software requirements for project replication
  2. Data processing
  3. Geospatial file alteration and production
  4. Map production and design
  5. MapBox hosting
  6. Microsite template alteration and design
  7. Logo alteration for site integration

Software Requirements

To replicate the process of map production the following software is required:

  1. Quantum GIS - referred to as QGIS
  2. SQLite - also known as Base
  3. TileMill
  4. Apache OpenOffice or Microsoft Excel
  5. Inkscape - for logo alteration

All software listed above is open source and free of charge, and is both Windows and Mac OS X compatible.

Data Processing

All data was processed using a combination of Base and OpenOffice.

To begin, the original data file PPMR_Data_Flat_Output_2012-07-11.csv was imported into Base as table data and saved as database ppmr.sqlite. The schema for table data was altered such that each column containing numerical data was identified as type 'INTEGER' and each column containing text was identified as type 'TEXT'. This is done by right clicking on the table data in the sidebar, selecting 'Alter...' and entering the appropriate label into each 'Type' field, as in the picture below:

data-schema

Rows labeled with country names 'Anyland' and 'Multiple' were deleted and the column month_name was added for the purpose of displaying the date in the map interactivity, using the following script:

    delete from data where country_name = 'Anyland' or country_name = 'Multiple';
    alter table data add column month_name text;
    update data set month_name = 'May' where month = 5;

The table may_final was created from the table data, filtering all data by month (May) and status (Final):

    create table may_final as select * from data where month = 5 and status_id = 2;

Unique data tables were then created for each contraceptive method from the table may_final:

    create table may_injectable as select * from may_final where method_id = 1;
    create table may_comb_oral_contra as select * from may_final where method_id = 2;
    create table may_implant as select * from may_final where method_id = 3;
    create table may_iud as select * from may_final where method_id = 4;
    create table may_3_mo_inject as select * from may_final where method_id = 5 or product_name = '3-month Injectable' or product_name = 'All Injectables';
    create table may_emerg_contra as select * from may_final where method_id = 6;
    create table may_fem_condom as select * from may_final where method_id = 7;
    create table may_prog_oral_contra as select * from may_final where method_id = 8;
    create table may_male_condom as select * from may_final where method_id = 9;
    create table may_other as select * from may_final where method_id = 10;
    create table may_1_mo_inject as select * from may_final where method_id = 11 or product_name = '1-month Injectable';
    create table may_2_mo_inject as select * from may_final where method_id = 12 or product_name = '2-month Injectable';

Each method table was then processed for integration with TileMill. First, the Average Monthly Consumption (AMC) for each method was calculated by country as column country_amc_total. The overall supply chain level for each country was also produced as column country_supply_chain_level_id with associated country_supply_chain_level_name column, for purposes of the Supply Chain Level layer on the map. In this case the table data is to be replaced with the appropriate method table name from above, e.g. may_male_condom, and repeated for each method.

    create table data_2 as select *, sum(amc) as country_amc_total, 
    	group_concat(distinct supply_chain_level_id) as supply_concat  
        from data 
        group by country_name;
    
    alter table data_2 add column country_supply_chain_level_id integer;
    
    update data_2 set country_supply_chain_level_id = 1 where supply_concat = '1';
    update data_2 set country_supply_chain_level_id = 4 where supply_concat like '%4%';
    update data_2 set country_supply_chain_level_id = 2 where supply_concat not like '%4%' and supply_concat != '1';
    
    alter table data_2 add column country_supply_chain_level_name text;
    update data_2 set country_supply_chain_level_name = 'All' where country_supply_chain_level_id = 4;
    update data_2 set country_supply_chain_level_name = 'Central' where country_supply_chain_level_id = 1;
    update data_2 set country_supply_chain_level_name = 'Central + Other' where country_supply_chain_level_id = 2;

The AMC total per program was then calculated by country as column program_amc_total. Again, the table data is to be replaced with the appropriate method table name and repeated for each method:

    create table data_3 as select *, sum(amc) as program_amc_total
        from data 
        group by country_name, program_name;

Tables data_2 and data_3 were then joined on column country_id to produce table data_4 with both columns country_amc_total and program_amc_total, along with all other columns to be used:

    create table data_4 as select
    a.country_id,
    a.country_name,
    a.program_id,
    a.program_name,
    a.program_amc_total,
    a.data_source_id,
    a.data_source_name,
    a.method_id,
    a.method_name,
    a.year,
    a.month_name,
    b.country_amc_total,
    b.country_supply_chain_level_id,
    b.country_supply_chain_level_name
    from data_3 a
    join data_2 b on a.country_id = b.country_id;

In order to add comma separators to the country_amc_total and program_amc_total columns for map interactivity, table data_4 was exported as a text file data_4.txt, converted to CSV as data_4.csv and opened in OpenOffice for alteration. To export a table in Base select the table you wish to export, click on the 'Export' feature in the upper left and select 'Text' from the export prompt:

base-export

In OpenOffice the column country_amc_total was copied and the duplicate renamed country_amc_tooltip. All cells for columns country_amc_tooltip and program_amc_total were then formatted as comma separated values and the file was imported back into the ppmr.sqlite database replacing the original table data_4. To do this, the original table data_4 was dropped by right clicking it in the sidebar and selecting 'Drop...', selecting the 'Import' feature in the upper left, navigating to the altered file and adding it as new table data_4:

base-import

Table data_5 (renamed for each method, adding '_final' to each original table name e.g. may_male_condom_final for the male condom method) was then produced including all necessary columns for map integration, including the program_amc_tooltip column as a concatenation of each program with the associated AMC total and data source for the purpose of the AMC breakdown table for map interactivity. Tables data_2, data_3, and data_4 are automatically dropped, leaving only the final table for each method in the database:

    create table data_5 as select
    	country_id,
    	country_name,
    	method_id,
    	method_name,
    	year,
    	month_name,
    	country_amc_total,
    	country_amc_tooltip,
    	group_concat('<tr><td align="left">' || program_name || '</td><td align="right">' || program_amc_total || '</td><td align="left">' || data_source_name || '</td></tr>', ' ') as program_amc_tooltip,
    	country_supply_chain_level_id,
    	country_supply_chain_level_name
    	
    	from data_4
    	group by country_id;
    
    DROP TABLE data_4;
    DROP TABLE data_3;
    DROP TABLE data_2;

Finally, the may_country_supply_chain_level table for the Supply Chain level map was produced from table may_final so as to include all countries with data for the month of May:

    create table may_country_supply_chain_level as select country_id, country_name, 
    	group_concat(distinct supply_chain_level_id) as supply_concat,
    	month_name,
    	year  
        from may_final 
        group by country_name;
    
    alter table may_country_supply_chain_level add column country_supply_chain_level_id integer;
    
    update may_country_supply_chain_level set country_supply_chain_level_id = 1 where supply_concat = '1';
    update may_country_supply_chain_level set country_supply_chain_level_id = 4 where supply_concat like '%4%';
    update may_country_supply_chain_level set country_supply_chain_level_id = 2 where supply_concat not like '%4%' and supply_concat != '1';
    
    alter table may_country_supply_chain_level add column country_supply_chain_level_name text;
    update may_country_supply_chain_level set country_supply_chain_level_name = 'All' where country_supply_chain_level_id = 4;
    update may_country_supply_chain_level set country_supply_chain_level_name = 'Central' where country_supply_chain_level_id = 1;
    update may_country_supply_chain_level set country_supply_chain_level_name = 'Central + Other' where country_supply_chain_level_id = 2;

Geospatial File Alterations/Production

World.sqlite

Housing the data in .sqlite file format is convenient because it allows for an easy join with geospatial files that are also in .sqlite format in TileMill, meaning the original ne_10m_admin_0_countries.shp world shapefile needed to be converted. To do so, open the file in QGIS, right click on the layer and select 'Save as...' making sure the format is set to 'SQLite', name the file (I used world.sqlite) and select 'OK':

qgis-convert-sqlite

Next, there needs to be a field on which to join the world.sqlite file with the data to be visualized in the ppmr.sqlite database. For this purpose the country_id column was added to the world.sqlite file's attribute table, matching the country_id with the appropriate country code using the following script:

    alter table attributes add column country_id integer;
    update attributes set country_id = 1 where ne_10m_adm = "AFG";
    update attributes set country_id = 3 where ne_10m_adm = "BGD";
    update attributes set country_id = 4 where ne_10m_adm = "BFA";
    update attributes set country_id = 8 where ne_10m_adm = "CIV";
    update attributes set country_id = 10 where ne_10m_adm = "COD";
    update attributes set country_id = 13 where ne_10m_adm = "ETH";
    update attributes set country_id = 15 where ne_10m_adm = "GMB";
    update attributes set country_id = 16 where ne_10m_adm = "GHA";
    update attributes set country_id = 18 where ne_10m_adm = "HTI";
    update attributes set country_id = 20 where ne_10m_adm = "KEN";
    update attributes set country_id = 21 where ne_10m_adm = "LBR";
    update attributes set country_id = 24 where ne_10m_adm = "MLI";
    update attributes set country_id = 25 where ne_10m_adm = "MRT";
    update attributes set country_id = 26 where ne_10m_adm = "MOZ";
    update attributes set country_id = 28 where ne_10m_adm = "NPL";
    update attributes set country_id = 31 where ne_10m_adm = "NGA";
    update attributes set country_id = 32 where ne_10m_adm = "PAK";
    update attributes set country_id = 34 where ne_10m_adm = "RWA";
    update attributes set country_id = 37 where ne_10m_adm = "UGA";
    update attributes set country_id = 38 where ne_10m_adm = "ZMB";
    update attributes set country_id = 39 where ne_10m_adm = "TZA";
    update attributes set country_id = 40 where ne_10m_adm = "TGO";
    update attributes set country_id = 41 where ne_10m_adm = "ZWE";
    update attributes set country_id = 45 where ne_10m_adm = "BEN";

If additional countries are to be visualized for subsequent quarterly reports this process will have to be updated accordingly. The world.sqlite spatial file is now ready for integration with TileMill.

World_centroid.sqlite

The world.sqlite file alone, however, will not allow for the production of country labels to be overlayed on top of the choropleth base maps. So, a world_centroid.sqlite file was created for this purpose. To begin, repeat the process of converting the ne_10m_admin_0_countries.shp world shapefile to .sqlite format, this time keeping the original name ne_10m_admin_0_countries.sqlite. Next, open the newly created file in QGIS by selecting 'Layer' in the toolbar, 'Add Vector Layer', 'Browse' by 'Files of type: SQLite' and select the file.

Select the newly added layer in the 'Layers' sidebar then select 'Vector' in the toolbar, 'Geometry Tools', 'Polygon centroids':

qgis-centroids

Save as shapefile (only temporary), click 'OK', and select 'Yes' when prompted to add layer to the TOC, which should produce an image like this:

world-centroid

Select the newly created centroids layer and repeat the process to save it in .sqlite format as world_centroid.sqlite, then repeat the process for adding the country_id column as well. The world_centroid.sqlite file is now ready for integration with TileMill, to be used as a country label layer.

Map Production and Design

Base Map

The first step to map production is creating the base map. With one stable world base map underlying the data specific to each method the site will operate as efficiently as possible, avoiding refreshing the entire world map every time the user switches between layers. For this purpose the base map was kept simple, with minimal styling to avoid bogging down map performance or cluttering the workspace.

To begin, open TileMill and select 'New Project' in the upper left hand corner. Label the filename deliver-base-map and the project name DELIVER | Base Map:

new-project-base-map

For this map, no additional layers needed to be added, only styling changes need to be made as follows:

    Map {
      background-color: #abd8e2;
    }
    
    #countries {
      line-color: #888;
      line-width: 2;
      line-join: round;
      polygon-pattern-file:url('../../polygon-pattern/stripe.png');
      [zoom <= 3] {line-width:1;} 
    }

The line polygon-pattern-file:url('../../polygon-pattern/stripe.png'); is what produces the striped polygon-fill for the map, generated from the stripe.png file housed in the polygon-pattern folder in the MapBox folder /documents/MapBox/polygon-pattern/stripe.png. This file is only housed here, rather than each project folder, as it allows for each project to refer back to it in the polygon-pattern-file:url();. The base map is ready to go.

Method Maps

Each method map is a combination of a choropleth layer, with each country distinguished by a unique color associated with a range of data classifications (in this case the darker the color the higher the AMC), with an overlaying country labels layer on top. Let's use the 2-month injectable method as an example, the process for which is to be repeated for each additional method.

To begin, select 'New Project' as before and this time label the filename deliver-2-month-injectable-may and the project name DELIVER | 2 Month Injectable May. The filename and project name are standardized for each method, with the filename following the structure deliver-method-name-may and the project name following the structure DELIVER | Project Name May.

In the newly created map navigate to toolbar in the lower left hand corner, select the 'Layers' feature at the bottom of the stack and delete the preloaded #countries layer by clicking on the trash can icon:

delete-countries-layer

Navigate back to the 'Layers' feature and this time select 'Add layer' and select the 'SQLite' tab on the top of the menu. The 'ID' field is the layer's unique name to which you will assign styling commands in Carto (TileMill's styling language) in the style.mss sidebar to alter the appearance of the layer - label this 2-mo-inject. For 'Datasource' navigate to the world.sqlite spatial file created earlier, and for 'Attach DB' enter the filepath to the ppmr.sqlite database created earlier as well, which should look something like this: ppmr@/Users/chad/Documents/deliver-usaid/data/ppmr.sqlite. Notice how the name of the database with the '@' symbol preceding the filepath. For the 'SRS' projection remember to select WGS84 as this is the projection used by Natural Earth Data - the source of world spatial data. So far, the menu should look something like this:

2-mo-inject-layer-1

Finally, the 'Table or subquery' field is where the join between .sqlite files is made, along with the assignment of data classifications. Each method map is assigned a range of six data classifications, with class6 = 0 and classes 1-5 representing a range appropriate to the data for each method:

    (select *, cast(`country_amc_total` as real)<0 as class0,
    cast(`country_amc_total` as real)<1000 as class1, 
    cast(`country_amc_total` as real)>=1000 and 
    cast(`country_amc_total` as real)<5000 as class2, 
    cast(`country_amc_total` as real)>=5000 and 
    cast(`country_amc_total` as real)<10000 as class3, 
    cast(`country_amc_total` as real)>=10000 and 
    cast(`country_amc_total` as real)<15000 as class4, 
    cast(`country_amc_total` as real)>=15000 as class5, 
    cast(`country_amc_total` as real)=0 as class6 from 
    attributes join ppmr.may_2_mo_inject_final on 
    may_2_mo_inject_final.country_id = attributes.country_id 
    order by cast(`country_amc_total` as real) desc)

The attribute table from the world.sqlite spatial file is joined with the appropriate method table, in this case may_2_mo_inject_final, from the ppmr.sqlite database on the country_id column. This way, only the countries with data for each method will show up in the method map, while the underlying base map (once hosted together on the site) will show 'No Data' for all others.

For each method, the range of data classifications is to be adjusted in the 'Table' field, while the table name associated with the ppmr.sqlite database is to be changed accordingly as well. Otherwise, this query will stay the same. Once the query is set, click 'Save' and the layer is added, although the map will remain blank until styling has been assigned in the style.mss sidebar.

Before doing so, navigate back to the 'Layers' feature and add another layer - what will be the country labels layer. This time label the ID country-labels and for 'Datasource' navigate to the world_centroid.sqlite file. Keep the 'Attach DB' and 'SRS' fields the same as the #2-mo-inject layer. For 'Table or subquery' this join is much more straightforward as data classifications are not involved. Simply join the attributes table from the world_centroid.sqlite spatial file to the appropriate method table, may_2_mo_inject_final in the ppmr.sqlite database on the country_id column:

    (select * from attributes join ppmr.may_2_mo_inject_final on 
    may_2_mo_inject_final.country_id = attributes.country_id)

Click 'Save' and the layer is added, although again the map will remain blank until styling has been assigned, which we will move onto now. The Carto for all method maps is the same:

    #country-labels {
      text-name:"[country_name]";
      text-face-name: "Gill Sans MT Bold";
      text-fill: #111;
      text-halo-fill: #eee;
      text-halo-radius: 1px;
      text-allow-overlap: true;
      text-opacity: 1;
      [zoom = 2]{ text-size: 8; text-allow-overlap: false;}
      [zoom = 3]{ text-size: 9; text-allow-overlap: false;}
      [zoom = 4]{ text-size: 12; }
      [zoom = 5]{ text-size: 15; }
      [zoom = 6]{ text-size: 18; }
      [zoom = 7]{ text-size: 22; }
      [zoom = 8]{ text-size: 30; }
      }
    
    @c1: #FDE3B8;
    @c2: #FCCB8B;
    @c3: #FC8D59;
    @c4: #D46B36;
    @c5: #BB3C01;
    @c6: #fef7ea;
    
    #2-mo-inject {
      polygon-fill:#f6f6f6;
      polygon-gamma:0.5;
      [class0 = 1]{polygon-fill:#fff;}
      line-width:1;
      [zoom < 6]{line-opacity:0.5;}
      
    [class1 = 1]{polygon-fill:@c1; line-color:darken(@c1,75);}
    [class2 = 1]{polygon-fill:@c2; line-color:darken(@c2,65);}
    [class3 = 1]{polygon-fill:@c3; line-color:darken(@c3,60);}
    [class4 = 1]{polygon-fill:@c4; line-color:darken(@c4,55);}
    [class5 = 1]{polygon-fill:@c5; line-color:darken(@c4,55);}
    [class6 = 1]{polygon-fill:@c6; line-color:darken(@c6,90);}
    }

The only thing to be changed for each map is the method layer name, in this case #2-mo-inject. To clarify a couple of commands:

    [zoom = 2]{ text-size: 8; text-allow-overlap: false;}
    [zoom = 3]{ text-size: 9; text-allow-overlap: false;}

This prevents the #country-labels layer from overlapping the country names at zoom 2 and 3, intended to reduce clutter and make the map easier to read. As the user zooms in beyond Z3 text-allow-overlap: true; is initiated and all country labels appear.

    @c1: #FDE3B8;
    @c2: #FCCB8B;
    @c3: #FC8D59;
    @c4: #D46B36;
    @c5: #BB3C01;
    @c6: #fef7ea;

These are the color designations for each data classification, @c6 representing class 6 (0), and @c1-@c5 representing classes 1-5.

    [class1 = 1]{polygon-fill:@c1; line-color:darken(@c1,75);}
    [class2 = 1]{polygon-fill:@c2; line-color:darken(@c2,65);}
    [class3 = 1]{polygon-fill:@c3; line-color:darken(@c3,60);}
    [class4 = 1]{polygon-fill:@c4; line-color:darken(@c4,55);}
    [class5 = 1]{polygon-fill:@c5; line-color:darken(@c4,55);}
    [class6 = 1]{polygon-fill:@c6; line-color:darken(@c6,90);}

These commands assign the polygon-fill for each classification, with the country borders for each styled as a darker shade of the original polygon-fill.

The map should now look like this:

tilemill-2-mo-inject

Tooltips/Interactivity

To activate and assign tooltips, or the box that appears when you interact with the map and hover over active countries (what I refer to as interactivity), navigate to the toolbar in the lower left hand corner and select the interaction editor on the top of the stack. Select 'Teaser' in the menu, navigate to the layer list for interaction data and select the 2-mo-inject layer:

tooltip-layer

The HTML for the interactivity is the same for all method maps, the style for which is assigned in the style.css of the microsite template. The data displayed is automated through 'Mustache tags', e.g. {{{country_name}}}, feeding the data for the activated country directly from the database and into the interactivity on the map.

    <div class='my-tooltip'>
    <div class='tooltip-title'>{{{country_name}}}</div>
    <div class='tooltip-date'>{{{month_name}}}, {{{year}}}</div>
    <div class='tooltip-subtitle'>Average Monthly Consumption: <span>{{{country_amc_tooltip}}}</span></div>
    <table><th>Program Name</th><th>AMC</th><th>Source</th>
    {{{program_amc_tooltip}}}
    </table>
    </div>

Legend

To produce the legend navigate to the interaction editor again which should automatically bring you to the 'Legend' menu. The HTML for the legend is also the same for all method maps, the style for which is also assigned in the style.css of the microsite template.

    <div class='my-legend'>
    <div class='legend-title'>Method: 2-Month Injectable</div>
    <div class='legend-amc'>Average Monthly Consumption (Thousands)</div>
    <div class='legend-scale'>
      <ul class='legend-labels'>
        <li><span style='background:#fef7ea;'></span>0</li>
        <li><span style='background:#FDE3B8;'></span>< 1</li>
        <li><span style='background:#FCCB8B;'></span>< 5</li>
        <li><span style='background:#FC8D59;'></span>< 10</li>
        <li><span style='background:#D46B36;'></span>< 15</li>
        <li><span style='background:#BB3C01;'></span>15+</li>
        <span class='space'>
        <li><img src='https://img.skitch.com/20111222-q65jt21u1qmxh8j2bsf1hdhkpq.jpg'>No Data</li>
        </span>
      </ul>
    </div>
    <div class='legend-source'>Compiled by: <a href="http://deliver.jsi.com/">USAID | DELIVER PROJECT</a></div>
    </div>

The only changes that need to be made with each method is the method name in the legend-title div class, in this case labeled Method: 2-Month Injectable, and the data ranges for classes 1-5:

    <li><span style='background:#FDE3B8;'></span>< 1</li>
    <li><span style='background:#FCCB8B;'></span>< 5</li>
    <li><span style='background:#FC8D59;'></span>< 10</li>
    <li><span style='background:#D46B36;'></span>< 15</li>
    <li><span style='background:#BB3C01;'></span>15+</li>

Once the interactivity and legend fields have been completed select 'Save' and the completed map should now look like this (with the mouse hovering over the DRC):

2-mo-inject-tilemill-complete

Supply Chain Level Map

Finally, for the supply chain level map, create a new project with filename deliver-supply-chain-level-may and a project name DELIVER | Supply Chain Level May. Add the method layer as before, this time labeling it #supply-chain and replacing the query with the following:

    (select * from attributes join ppmr.may_country_supply_chain_level on 
    may_country_supply_chain_level.country_id = attributes.country_id)

The Carto for the #country-labels layer remains the same as for the method maps, while it is as follows for the #supply-chain layer:

    #supply-chain {
      polygon-fill:#f6f6f6;
      polygon-gamma:0.5;
      [zoom < 6]{line-opacity:0.5;}
      
      [country_supply_chain_level_id = 1]
        {polygon-fill:@c1; line-color:darken(@c1,75);}
      
      [country_supply_chain_level_id = 2]
        {polygon-fill:@c3; line-color:darken(@c3,60);}
      
      [country_supply_chain_level_id = 4]
        {polygon-fill:@c5; line-color:darken(@c4,55);}
      
    }

The color designation is the same for countries with supply chain level 'Central' as it is for data class 1 in the method maps, while 'Central + All' is the same as class 3, and 'All' is the same as class 5. Notice the darker the color, the more detailed or comprehensive the supply chain level.

The HTML for the interactivity is as follows, with the #supply-chain layer activated:

    <div class='my-tooltip'>
    <div class='tooltip-title'>{{{country_name}}}</div>
    <div class='tooltip-date'>{{{month_name}}}, {{{year}}}</div>
    <div class='tooltip-subtitle'>Supply Chain Level: <span>{{{country_supply_chain_level_name}}}</span></div>

While the HTML for the legend is as follows:

    <div class='supply-legend'>
    <div class='legend-supply-title'>Supply Chain Level</div>
    <div class='legend-supply-scale'>
      <ul class='legend-supply-labels'>
        <li><span style='background:#FDE3B8;'></span>Central</li>
        <li><span style='background:#FC8D59;'></span>Central + Other</li>
        <li><span style='background:#BB3C01;'></span>All</li>
        <span class='space'>
        <li><img src='https://img.skitch.com/20111222-q65jt21u1qmxh8j2bsf1hdhkpq.jpg'>No Data</li>
        </span>
      </ul>
    </div>
    <div class='legend-supply-source'>Compiled by: <a href="http://deliver.jsi.com/">USAID | DELIVER PROJECT</a></div>
    </div>

As with the method maps, the supply chain level map's legend and interactivity styling is assigned through the style.css in the microsite template. The supply chain level map should now look like this (again with the mouse hovering over the DRC):

supply-chain-level-tilemill

Uploading to MapBox Hosting

To authorize TileMill to upload maps directly to the MapBox account, navigate to 'Settings' in the main menu and select 'Authorize' next to 'MapBox':

tilemill-settings

A prompt should then appear with a menu to log in:

mapbox-login

Followed by another prompt asking for authorization - select 'Authorize'. If successful, the following prompt will appear on the main menu upon completion:

account-authorized

Upon successfully authorizing the account, navigate to the map to be uploaded, select 'Export' in the upper right hand corner and click 'Upload':

export-upload

Set the zoom extent to 2-8 and the bounds -180,-85.0511,180,85.0511. The center of the map will vary based on the method, which will be addressed during the microsite template overview:

upload-1

Select 'Upload' and the 'View Exports' list will appear:

upload-2

Once completed the upload time bar will disappear and the layer will display a check mark next to it, as in the DELIVER | Supply Chain Level May and DELIVER | Progestin-Only Oral Contraceptive May maps shown in the screenshot above. To view these maps online, open a web browser and navigate to http://mapbox.com. Select 'Login' in the upper right hand corner of the landing page and enter the appropriate username (usaid-deliver-project) and password (JohnSnow). The account page should appear like so:

mapbox-hosting

Repeat for each map, and once uploaded they are ready for integration with the microsite template.

Microsite Template Alteration and Design

This project uses the Data Exploration map site template produced by MapBox, the source code for which is hosted on github and available for public use. The project comes with a variety of folders, a number of which are not necessary for the purposes of this project including: fonts, graphic-src, and tilemill. The readme.md file is not necessary to the function of the site, but serves as a good reference when deciphering what elements to alter in order to redesign the site as desired. The index.html and style.css are the only two documents that will need to be altered for the purposes of this project.

Index.html

Removed

Let's start with what was removed from the original index.html.

The site's shortcut icon (accompanying the tab title in a web browser) was removed:

<link rel="shortcut icon" href="img/favicon.ico" type="image/x-icon" />

The entire 'content' section, alongside 'branding' and 'about' were removed:

    <div id="content">
        <div id='branding'></div>
        <div id="about">
            <h1>DC's Changing Landscape</h1>
            <p>Over the past few years, Washington DC has been undergoing economic, social, and demographic shifts. Property values in particular have been changing rapidly as parts of the city undergo aggressive development. See how these factors are shaping DC.</p>
            <div data-control="geocode" id="search">
                <form class="geocode">
                    <input placeholder="Search for an address" type="text">
                    <input type="submit" />
                    <div id="geocode-error"></div>
                </form>
            </div>
        </div>
    </div>

The legend was removed:

    <div class="wax-legends">
        <div class="wax-legend" style="display: block; ">
            <div class="scale">
                <label><a href="http://data.dc.gov/Main_DataCatalog.aspx?id=10">% Change in property value '10-'11</a></label>
                <div><img src="img/grid-scale-2.png" /></div>
                <div>
                    <span>< -20</span>
                    <span>< -10</span>
                    <span>< -5</span>
                    <span>< 0</span>
                    <span>0</span>
                    <span>> 0</span>
                    <span>> 5</span>
                    <span>> 10</span>
                    <span>> 20</span>
                </div>
            </div>
            <div>
                <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAa0lEQVQIHWNkaPjPpPhitcn/f4xZDP8ZXjD8/tLBIvhsNe9/BqZ1jAwM0gyMDL8ZWHhYmLj/fmIGCzCAwH/mf8wM6kzizH8////PMBEsxvD/HdPf/5MY/wNFGMNWM0tzfhdgZeL7e39+wAcAdhYlGm+mTIMAAAAASUVORK5CYII=" style="margin-bottom: 2px;">
                <label><a href="http://data.dc.gov/Main_DataCatalog.aspx?id=5">Construction project</a></label>
            </div>
            <div>
                <img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAV0lEQVQIHWP8//8/AxgwMjIyQDmM/52D4xkYmGYzMDIwAwX7GfasLgEKhn4GCvBAlDP8Y3h/j4MJKPAXKsAAVPmP4ezZP0wM/xkigIIfgfR3BgbGcpC5AExlIK8M2/cpAAAAAElFTkSuQmCC" style="margin-bottom: 2px;">
                <label><a href="http://data.dc.gov/Main_DataCatalog.aspx?id=3">Crime incident</a></label>
            </div>
        </div>
    </div>

And the markers.js support was removed <script src="ext/mmg.js"></script> alongside the mmg.js file in the ext folder (this javascript library is only necessary if dropping markers on the map, which is unnecessary for this project).

Altered

Now, for what was altered in the original index.html.

The title <title>DC's Changing Landscape</title> was changed to <title>USAID | DELIVER PROJECT</title>.

The layer elements were altered from this:

    <div id="projects" class="layers">
       <a data-control="layer" href="#building">Building Permits, 2011</a>
       <a data-control="layer" href="#construction">City Construction Projects, 2011</a>
    </div>
    <div id="crime" class="layers">
       <a data-control="layer" href="#crime">Total Crime, 2011</a>
       <a data-control="layer" href="#robbery">Robbery, 2011</a>
       <a data-control="layer" href="#theft">Theft, 2011</a>
       <a data-control="layer" href="#auto">Theft from Auto, 2011</a>
    </div>

To this:

    <div id="projects" class="layers">
       <a class='active' data-control="layer" href="#supply_chain">Supply Chain Level</a>
    </div>
    <div id="method" class="layers">
       <a data-control="layer" href="#inject_1">1-Month Injectable</a>
       <a data-control="layer" href="#inject_2">2-Month Injectable</a>
       <a data-control="layer" href="#inject_3">3-Month Injectable</a>
       <a data-control="layer" href="#comb_oral">Combined Oral Contraceptive</a>
       <a data-control="layer" href="#emerg_contra">Emergency Contraceptive</a>
       <a data-control="layer" href="#fem_condom">Female Condom</a>
       <a data-control="layer" href="#implant">Implant</a>
       <a data-control="layer" href="#iud">IUD</a>
       <a data-control="layer" href="#male_condom">Male Condom</a>
       <a data-control="layer" href="#other">Cycle Beads</a>
       <a data-control="layer" href="#prog_oral">Progestin-Only Oral Contraceptive</a>
    </div>

Creating a layer for each method, with the supply chain level map differentiated from the method maps. The layer script was altered from this:

    <script type="text/javascript">
    
        var main = Map('map', {
            api: 'http://a.tiles.mapbox.com/v3/examples.map-20v6611k,mapbox.dc-property-values.jsonp',
            center: {
                lat: 38.9090033656251,      
                lon: -77.014396158891,      
                zoom: 13                    
            },                              
            zoomRange: [0, 15],             
            features: [                     
                'zoomwheel',
                'movetips',
                'zoombox',
                'zoompan',
                'share'
            ]
        });
        
        main.layers({
            building: {                     
                api: 'http://a.tiles.mapbox.com/v3/mapbox.dc-building.jsonp',
                center: {                  
                    lat: 38.910606275724,  
                    lon: -77.00126406355,  
                    zoom: 14,              
                    ease: 500              
                }                          
            },
            construction: { 
                api: 'http://a.tiles.mapbox.com/v3/mapbox.dc-construction.jsonp',
                center: { zoom: 12, ease: 1000 }
            },
            crime: { 
                api: 'http://a.tiles.mapbox.com/v3/mapbox.dc-crime.jsonp',
                center: { zoom: 13, ease: 1000 }
             },
            robbery: { api: 'http://a.tiles.mapbox.com/v3/mapbox.dc-crime-robbery.jsonp' },
            theft: { api: 'http://a.tiles.mapbox.com/v3/mapbox.dc-crime-theft.jsonp' },
            auto: { api: 'http://a.tiles.mapbox.com/v3/mapbox.dc-crime-auto.jsonp' }
         });
                 
    </script>

To this:

    <script type="text/javascript">
    
        var main = Map('map', {
            api: 'http://a.tiles.mapbox.com/v3/usaid-deliver-project.deliver-base-map.jsonp',
            center: {
                lat: 12.555,      
                lon: 8.4380,      
                zoom: 3           
            },                    
            zoomRange: [2, 8],    
            features: [           
                    'zoomwheel',
    				'tooltips',
    				'legend',
                    'zoombox',
                    'zoompan',
                    'share'
                ]
    		}, function() {
    		              main.setOverlay('supply_chain');
            });
    
         main.layers({
             supply_chain: {
                 api: 'http://a.tiles.mapbox.com/v3/usaid-deliver-project.deliver-supply-chain-level-may.jsonp',
                 center: {       
                     lat: 12.555,
                     lon: 8.4380,
                     zoom: 3,    
                     ease: 1000  
                 }
             },
             inject_1: { 
                 api: 'http://a.tiles.mapbox.com/v3/usaid-deliver-project.deliver-1-month-injectable-may.jsonp',
                 center: { 
    	 		lat: 11.006,
    	 		lon: -2.813,					
    	 		zoom: 5, 
    	 		ease: 1000
    	 		}
              },
             inject_2: { 
                 api: 'http://a.tiles.mapbox.com/v3/usaid-deliver-project.deliver-2-month-injectable-may.jsonp',
                 center: { 
    	 		lat: 10.532,
    	 		lon: 24.610,					
    	 		zoom: 3, 
    	 		ease: 1000
    	 		}
              },
    	      inject_3: { 
    	          api: 'http://a.tiles.mapbox.com/v3/usaid-deliver-project.deliver-3-month-injectable-may.jsonp',
    	          center: { 
    	 	 	lat: 12.555,
    	 	 	lon: 8.4380,					
    	 	 	zoom: 3,    
    	 	 	ease: 1000  
    	 	 	}
    	      },
    	      comb_oral: { 
    	          api: 'http://a.tiles.mapbox.com/v3/usaid-deliver-project.deliver-combined-oral-contraceptive-may.jsonp',
    	          center: { 
    	 	 	lat: 12.555,
    	 	 	lon: 8.4380,					
    	 	 	zoom: 3,    
    	 	 	ease: 1000  
    	 	 	}
    	      },
    	      emerg_contra: { 
    	          api: 'http://a.tiles.mapbox.com/v3/usaid-deliver-project.deliver-emergency-contraceptive-may.jsonp',
    	          center: { 
    	 	 	lat: 12.684,
    	 	 	lon: 24.609,					
    	 	 	zoom: 3, 
    	 	 	ease: 1000  
    	 	 	}
    	      },
    	      fem_condom: { 
    	          api: 'http://a.tiles.mapbox.com/v3/usaid-deliver-project.deliver-female-condom-may.jsonp',
    	          center: { 
    	 	 	lat: 4.478,
    	 	 	lon: 12.656,					
    	 	 	zoom: 4,    
    	 	 	ease: 1000  
    	 	 	}
    	      },
    	      implant: { 
    	          api: 'http://a.tiles.mapbox.com/v3/usaid-deliver-project.deliver-implant-may.jsonp',
    	          center: { 
    	 	 	lat: 12.555,
    	 	 	lon: 8.4380,					
    	 	 	zoom: 3,    
    	 	 	ease: 1000  
    	 	 	}
    	      },
    	      iud: { 
    	          api: 'http://a.tiles.mapbox.com/v3/usaid-deliver-project.deliver-iud-may.jsonp',
    	          center: { 
    	 	 	lat: 12.555,
    	 	 	lon: 8.4380,					
    	 	 	zoom: 3,    
    	 	 	ease: 1000  
    	 	 	}
    	      },
    	      male_condom: { 
    	          api: 'http://a.tiles.mapbox.com/v3/usaid-deliver-project.deliver-male-condom-may.jsonp',
    	          center: { 
    	 	 	lat: 12.555,
    	 	 	lon: 8.4380,					
    	 	 	zoom: 3,    
    	 	 	ease: 1000  
    	 	 	}
    	      },
    	      other: { 
    	          api: 'http://a.tiles.mapbox.com/v3/usaid-deliver-project.deliver-cycle-beads-may.jsonp',
    	          center: { 
    	 	 	lat: 9.796,
    	 	 	lon: -33.662,					
    	 	 	zoom: 3,    
    	 	 	ease: 1000  
    	 	 	}
    	      },
    	      prog_oral: { 
    	          api: 'http://a.tiles.mapbox.com/v3/usaid-deliver-project.deliver-progestin-only-oral-contraceptive-may.jsonp',
    	          center: { 
    	 	 	lat: 12.555,
    	 	 	lon: 8.4380,					
    	 	 	zoom: 3,    
    	 	 	ease: 1000  
    	 	 	}
    	      }
         });
    </script>

With the movetips feature removed (interactivity that moves along with your mouse) and the tooltips and legend features added, allowing for the interactivity to remain in one location at all times and for the legend to update depending on the active layer (as the legend varies per method because of the different data classifications).

The var main = Map is the base map that is to stay activated throughout site navigation:

        var main = Map('map', {
            api: 'http://a.tiles.mapbox.com/v3/usaid-deliver-project.deliver-base-map.jsonp',
            center: {
                lat: 12.555,      
                lon: 8.4380,      
                zoom: 3           
            },

While the center lat, lon, and zoom are set for each layer, with the ease set for the speed of the transitions between each layer (the higher the number the longer the transition). The api specifies the MapBox hosting url that the site is to pull from for each map.

This function function() {main.setOverlay('supply_chain');} was added to assign the supply chain level map to activate upon navigating to the site (without this function only the base map would appear at first).

Added

Two elements were added to the original index.html. The USAID | DELIVER PROJECT logo, housed in the branding folder (the alteration of which is to be explained later):

    <div id='logo'>
    	<a href="http://deliver.jsi.com/" target="_blank"><img src="branding/logo.png" width="400"></a>
    </div>

And the TileMill and MapBox attribution:

    <div id='attribution'><h7>Maps designed in <a href="http://mapbox.com/tilemill">TileMill</a>, hosted on <a href="http://mapbox.com">MapBox</a></h7>.
    </div>

Both of these elements sit in the lower left hand corner of the site.

Adding New Layers

To add a new map layer to the site, simply add a new layer to the element list like this:

<a data-control="layer" href="#inject_1">1-Month Injectable</a>

Then add the script to the site configuration like this:

    inject_1: { 
        api: 'http://a.tiles.mapbox.com/v3/usaid-deliver-project.deliver-1-month-injectable-may.jsonp',
        center: { 
    	lat: 11.006,
    	lon: -2.813,					
    	zoom: 5, 
    	ease: 1000
    	}
     },

Making sure the names match up (#inject_1 in the element list, inject_1 in the script) and that the api and center coordinates are adjusted appropriately.

Style.css

For the style.css, let's walk through the different elements of the map and site framework that the CSS is controlling. Starting from the top, under Typography:

    h7 {
    	font: 90%/14px 'Gill Sans MT', 'Gill Sans', Calibri, 'Trebuchet MS', sans-serif;
    	text-align: left;
    	color: #333;
        }
    
    a {
        color:#888;
        text-decoration:none;
        }

h7 is assigning style to the attribution, as discussed in the index.html additions, while a is assigning style to the hyperlinks included in this element.

Under 'Layout':

    .layers {
        position: absolute;
        width: 120px;
        left: 10px;
        top: 10px;
        }
        
    .layers a {
        padding: 10px;
        margin: 2px 0;
    
        border: 1px solid #333;
        background: white;
        color: #333;
        }
    
    .layers a:hover, .layers a:focus, .layers a.active {
        background: #004990;
        color: white;
        }
    
    .layers#method {
        position: absolute;
        top: 60px;
        left: 10px;
        }
    
    #method.layers a:hover, #method.layers a:focus, #method.layers a.active {
        background: #004990;
        color: white;
        }
        
    .layers a {
    	font: bold 85% 'Gill Sans MT', 'Gill Sans', Calibri, 'Trebuchet MS', sans-serif;
        width: 110px;
        float: left;
        margin-right: 20px;
        }

These rules are assigning style to the layer list in the sidebar of the map, with .layers a representing active layers, .layers representing the size of the layer boxes and positioning of the supply chain level map layer box, and .layers#method representing the positioning of the method layers boxes.

Under Map:

    .wax-tooltip {
        top: 10px;
        right: 10px;
        overflow: visible;
        max-width: none;
        border: 1px solid #333;
        }
    
    .wax-tooltip .my-tooltip {
        font-family: 'Gill Sans MT', 'Gill Sans', Calibri, 'Trebuchet MS', sans-serif;
        }
        
    .wax-tooltip .tooltip-title {
        font-size: 150%;
        font-weight: bold;
        padding: 5px 0px 4px 5px;
        }
        
    .wax-tooltip .tooltip-subtitle {
        font-size: 100%;
        line-height: 16px;
        padding: 0px 0px 8px 5px;
        }
    
    .wax-tooltip .tooltip-subtitle span {
        font-weight: bold;
        }
        
    .wax-tooltip .tooltip-date {
        font-size: 100%;
        line-height: 16px;
        padding: 0px 0px 4px 5px;;
        }
        
    .wax-tooltip table {
        font: 90%/16px 'Gill Sans MT', 'Gill Sans', Calibri, 'Trebuchet MS', sans-serif;
        width: 100%;
        padding-bottom: 5px;
        border-collapse: collapse;
        border-style: hidden;
        }
        
    .wax-tooltip table th, table td {
        padding: 2px 5px 5px 5px;
        border: 1px solid black;
        vertical-align: top;
        font-size: 100%
        }
    
    .wax-tooltip table th {
        text-align: left;
    }
        
    .wax-tooltip table th {
        font-weight: bold;
        vertical-align: middle;
        }
        
    .wax-tooltip table td {
        vertical-align: top;
        }

These rules are assigning style to the HTML in the interactivity, while these:

    .wax-legend .my-legend {
        font-family: 'Gill Sans MT', 'Gill Sans', Calibri, 'Trebuchet MS', sans-serif;
        }
        
    .wax-legend .legend-title {
        font: bold 100%/16px 'Gill Sans MT', 'Gill Sans', Calibri, 'Trebuchet MS', sans-serif;
        text-align: left;
        }
        
    .wax-legend .legend-amc {
        text-align: left;
        font: regular 100%/16px 'Gill Sans MT', 'Gill Sans', Calibri, 'Trebuchet MS', sans-serif;
        margin-bottom: 4px;
        }
        
    .wax-legend .legend-scale ul {
        margin: 0;
        padding: 0;
        float: left;
        list-style: none;
        }
        
    .wax-legend .legend-scale ul li {
        display: block;
        float: left;
        width: 45px;
        text-align: center;
        font-size: 85%;
        list-style: none;
        }
        
    .wax-legend ul.legend-labels li span {
        display: block;
        float: left;
        height: 14px;
        width: 45px;
        }
        
    .wax-legend .legend-source {
        font-size: 100%;
        line-height: 16px;
        clear: both;
        }
        
    .wax-legend a {
        font-size: 90%;
        line-height: 14px;
        color: #327f8f;
        }
        
    .wax-legend .space {
        margin-left: 4px;
        float: right;
        font-size: 100%;
        line-height: 13px;
        }

Are assigning style to the HTML in the legend for all method maps, and these:

    .wax-legend .supply-legend {
        font-family: 'Gill Sans MT', 'Gill Sans', Calibri, 'Trebuchet MS', sans-serif;
        }
        
    .wax-legend .legend-supply-title {
        font: bold 100%/16px 'Gill Sans MT', 'Gill Sans', Calibri, 'Trebuchet MS', sans-serif;
        text-align: left;
        padding-bottom: 8px;
        }
      
    .wax-legend .legend-supply-scale ul {
        margin: 0;
        padding: 0;
        float: left;
        list-style: none;
        }
      
    .wax-legend .legend-supply-scale ul li {
        display: block;
        float: left;
        width: 52px;
        text-align: center;
        font-size: 85%;
        list-style: none;
        line-height: 14px;
        }
      
    .wax-legend ul.legend-supply-labels li span {
        display: block;
        float: left;
        height: 15px;
        width: 52px;
        }
      
    .wax-legend .legend-supply-source {
        font-size: 100%;
        line-height: 16px;
        clear: both;
        padding-top: 4px;
        }

Are assigning style to the HTML in the legend for the supply chain level map.

#logo is assigning positioning to the USAID | DELIVER PROJECT logo, while #attribution is assigning positioning to the TileMill and MapBox attribution. Everything else under the /* SHARE */ and /* EMBED */ headlines are assigning style and positioning to the share and map embed features, preloaded with the microsite template.

Logo Alteration

The final piece to this documentation is a quick tutorial on how to alter the original USAID | DELIVER PROJECT logo for map integration.

  1. To begin, open the original logo logo-original.jpg in Inkscape.
  2. Using the 'Select and transform objects' tool (represented by the mouse pointer icon) click and drag over the entire logo to select the image.
  3. Navigate to 'Path' in the top toolbar and select 'Trace Bitmap...'
  4. Under the 'Multiple scans' menu in the 'Mode' tab check the 'Colors' oval and the 'Remove background' box and deselect the 'Smooth' box.
  5. In the 'Options' tab deselect the 'Smooth corners' box, then click 'OK'.
  6. Click and drag the newly created layer away from the original layer underneath and remove the original layer by selecting the image and hitting delete.
  7. Select the new layer and navigate to 'File' in the top toolbar, 'Export Bitmap...', and set the 'Width' under 'Bitmap size' to 500.
  8. Enter logo.png into the 'Filename' field and click 'Export'.

The logo has now been converted to .png with the background removed, and it is now ready for map integration. See the 'Microsite Template Alternation and Design' section above for details on how this logo is integrated into the site.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment