Cartogram

class visigoth.map_layers.cartogram.Cartogram(data, palette, iterations=30, stroke='black', stroke_width=1, font_height=24, text_attributes={}, link_stroke='grey', link_stroke_width=2, f1=0.01, f2=0.5)

Create a Cartogram plot layer in which a list of points with assigned radii are peturbed from their original positions to avoid overlap.

Hover over a point to see a link to the original position

Parameters
  • data (tuple) – data in the form (lon,lat,category,label,radius)

  • palette (list) – a DiscretePalette assigning categories to colours

Keyword Arguments
  • iterations (int) – number of iterations to run

  • stroke (str) – stroke color for circumference of circles

  • stroke_width (int) – stroke width for circumference of circles

  • font_height (int) – the height of the font for text labels

  • text_attributes (dict) – SVG attribute name value pairs to apply to labels

  • link_stroke (str) – colour to draw links to original position

  • link_stroke_width (int) – the width of links

  • f1 (float) – relative force attracting each point to its original location

  • f2 (float) – relative force repelling overlapping points

Notes:

Example

Screenshot (Link to open SVG for interactive features):

../_images/example21.png

Source Code (Link to Github):



import os.path
import sys
import argparse
import random
import json
import math

from visigoth.diagram import Diagram
from visigoth.containers.map import Map
from visigoth.containers.box import Box
from visigoth.common.legend import Legend
from visigoth.map_layers.cartogram import Cartogram
from visigoth.utils.mapping.projections import Projections
from visigoth.utils.colour import DiscretePalette

if __name__ == "__main__":

    parser = argparse.ArgumentParser()
    parser.add_argument("--outpath", help="path for output SVG", default="example.svg")
    parser.add_argument("--iterations", help="number of iterations to run", default=200,type=int)

    args = parser.parse_args()

    d = Diagram(fill="white")

    rng = random.Random(3)

    cluster_count = 6

    def gen(px,py,maxdist,minr,maxr):
        angle = rng.random()*2*math.pi
        d = rng.random()*maxdist
        dx = d*math.sin(angle)
        dy = d*math.cos(angle)
        radius = minr+rng.random()*(maxr-minr)
        cat = random.choice(["cat1", "cat2", "cat3"])
        label = "cat: "+cat
        return (px+dx,py+dy,cat,label,radius)

    palette = DiscretePalette()
    palette.addCategory("cat1","red")
    palette.addCategory("cat2","green")
    palette.addCategory("cat3","blue")

    cluster_centers = [(0.05+0.9*rng.random(),0.05+0.9*rng.random()) for x in range(0,cluster_count)]
    data = [gen(cx,cy,0.1,10,25) for (cx,cy) in cluster_centers for x in range(0,10)]

    bounds  = ((0.0,0.0),(1.0,1.0))
    m = Map(512,bounds,projection=Projections.IDENTITY)
    c = Cartogram(data, palette, iterations=args.iterations, stroke_width=0.5)
    m.addLayer(c)
    legend = Legend(palette, width=500, legend_columns=3)
    d.add(Box(m))
    d.add(legend)

    d.connect(c,legend,"brushing")
    d.connect(legend,c,"brushing")

    svg = d.draw()

    f = open(args.outpath, "wb")
    f.write(svg)
    f.close()