Examples¶
The following chapter demonstrates a few code examples of how to use the Tangible library.
A Simple Tower¶
This example describes a simple round tower (CircleTower1D) where the radius of the layers corresponds to the datapoint. The dataset describes the number of web site visits on http://blog.dbrgn.ch/ during the month of September 2013. The value range is normalized to a range between 10 and 50 using a linear scale.
Code
from tangible import scales
from tangible.shapes.vertical import CircleTower1D
from tangible.backends.openscad import OpenScadBackend
# Normalize raw data
visits = [53, 69, 86, 92, 81, 76, 37, 36, 62, 76, 72, 67, 55, 61, 54,
72, 92, 84, 78, 75, 45, 48, 85, 81, 83, 69, 68, 66, 62, 115]
scale = scales.linear([min(visits), max(visits)], [10, 50])
datapoints = map(scale, visits)
# Create shape
tower = CircleTower1D(datapoints, layer_height=10)
# Render OpenSCAD code
code = tower.render(backend=OpenScadBackend)
print code
Result
Multi Dimensional Data¶
Here we have two dimensional data, represented as two lists of integers. The first list should be mapped to the angle of the “pie slices”, while the second list should be mapped to the height of each slice. Additionally, we’ll add a center radius to make the model look like a donut, and we’ll explode the slices.
Code
from tangible.shapes.pie import AngleHeightPie2D
from tangible.backends.openscad import OpenScadBackend
# Data
datapoints = [
[30, 30, 5, 5, 20], # Angle
[18, 23, 20, 15, 10], # Height
]
# Create shape
pie = AngleHeightPie2D(datapoints, inner_radius=4, explode=1)
# Render OpenSCAD code
code = pie.render(backend=OpenScadBackend)
print code
Result
Reading Data from CSV¶
Often the data that you want to visualize is not already available as a Python datastructure, but in formats like JSON or CSV. Here’s a small example where website visitor data is read from the CSV exported by Google Analytics. Then the number of visits and the average visit duration are mapped to the distance between opposing corners of a rhombus tower.
Code
import csv
from datetime import timedelta
from tangible.shapes.vertical import RhombusTower2D
from tangible.backends.openscad import OpenScadBackend
# Read data into list
datapoints = [[], []]
with open('analytics-sep-13.csv', 'r') as datafile:
reader = csv.DictReader(datafile)
for row in reader:
datapoints[0].append(int(row['Visits']))
h, m, s = map(int, row['AvgDuration'].split(':'))
duration = timedelta(hours=h, minutes=m, seconds=s)
datapoints[1].append(duration.total_seconds())
# Create shape
tower = RhombusTower2D(datapoints, layer_height=10)
# Render OpenSCAD code
code = tower.render(backend=OpenScadBackend)
print code
CSV
Day,Visits,AvgDuration
9/1/13,53,00:00:51
9/2/13,69,00:01:01
9/3/13,86,00:01:24
...
Result
Grouped Data¶
Some one dimensional datasets don’t work well when visualized directly. An example would be daily website visitor statistics during a full year, a single bar graph would be much too wide. But by grouping the data from the CSV example into months, a BarsND graph can be constructed:
Code
import csv
from itertools import chain
from tangible import scales
from tangible.shapes.bars import BarsND
from tangible.backends.openscad import OpenScadBackend
# Read data into list
datapoints = [list() for i in xrange(9)]
with open('analytics-full-13.csv', 'r') as datafile:
reader = csv.DictReader(datafile)
for row in reader:
date = row['Day']
month = int(date.split('/', 1)[0])
visits = int(row['Visits'])
datapoints[month - 1].append(visits)
# Normalize data
all_datapoints = list(chain.from_iterable(datapoints))
scale = scales.linear([min(all_datapoints), max(all_datapoints)],
[10, 150])
datapoints = map(lambda x: map(scale, x), datapoints)
# Create shape
bars = BarsND(datapoints, bar_width=7, bar_depth=7)
# Render OpenSCAD code
code = bars.render(backend=OpenScadBackend)
print code
Result
Creating Custom Shapes from AST¶
It’s not necessary to rely on the provided shape classes only, you can also create your own shapes by using the AST objects directly.
The easiest and cleanest way to do this, is to create a subclass of the BaseShape class and to override its _build_ast method:
Code
from tangible.shapes.base import BaseShape
from tangible import ast
from tangible.backends.openscad import OpenScadBackend
# Create custom shape
class Cogwheel(BaseShape):
def _build_ast(self):
cogs = []
for i in xrange(18):
cog = ast.Rectangle(2, 2)
translated = ast.Translate(9.5, -1, 0, cog)
rotated = ast.Rotate(i * 30, (0, 0, 1), translated)
cogs.append(rotated)
return ast.Union([ast.Circle(radius=10)] + cogs)
# Render shape
f = Cogwheel()
code = f.render(backend=OpenScadBackend)
print code
Result