-
Notifications
You must be signed in to change notification settings - Fork 3
Quipucamayoc
A high-level quipu visualization library for Python and Jupyter Notebook
In the end, if inequity and injustice are woven into the very fabric of society, then each twist, coil, and code offers a chance for us to weave new patterns, practices, and politics … new blueprints. The vastness of the problems we face will be their undoing when we accept that we are patternmakers. Whether in seemingly simple exchanges or more elaborate forms of community organizing and world-building, this is a microvision of change.
- Ruha Benjamin, Viral Justice: How We Grow the World We Want, 2022
This project is inspired by the many movements that use speculative design to foster decolonial imagination (e.g., Chicanafuturism, Afrofuturism. Visit Appendix B for more information.) Here I define “decolonial” efforts as those that seek to “undo the colonial erasure of non-Western ways of being and knowing” (Krishnan et al., n.d.).
This project seeks to apply ethical design principles to data visualization. This follows the Guidelines for Indigenous-centred AI Design, which state that every part of the “extended stack” (i.e., the technological development ecosystem) should be ethically designed (Lewis, 2020). Through its use in data analysis, data communication, and the development & implementation of artificial intelligence systems, data visualization is indeed a vital component of the extended stack.
The quipucamayoc
data visualization library reimagines the modern data science toolkit as one that includes indigenous modes of data communication. This library is based on Incan numeric quipus and works in the Jupyter Notebook environment, much like other popular data science tools.
The word “quipu” means “knot” in the Quechua language. A quipu is a record made of woven and knotted cords that originated in the Andes of South America. Prototypical quipus were developed and used by the Inca in the 15th through 17th centuries CE, but a precursor to this form was developed by the Wari as early as the 7th century CE (Gresham College & Medrano, 2021).
Although archaeologists are still working to decode quipus that might encode geometric and narrative information, we know that some quipus follow a known numeric base-10 system. These numeric quipus were used by the Inca for arithmetic and record-keeping related to accounting, inventorying, and demography at different levels of administration. The keepers of these cords were given the title of “quipucamayoc” (Gresham College & Medrano, 2021).
(Visit Appendix C for more information on quipus.)
Figure 1. Khipu found covered by peanuts in Inkawasi, Cañete
Note. Khipu found covered by peanuts in Inkawasi, Cañete [Twisted, knotted and embroidery]. (1400/1532). Located at the Museo de Arte de Lima, Lima, Peru. Image courtesy of Google Arts & Culture.
The basis of an Incan quipu is the primary cord from which all other parts emanate. On a numeric quipu, each pendant cord (which hangs from the primary cord) represents a data point (Gresham College & Medrano, 2021). (Figure 2 includes these and other quipu parts not covered by this library.)
Figure 2. Parts of an Inca-style quipu
Note. Image by Manuel Medrano, 2021. Image courtesy of Manuel Medrano’s lecture at Gresham College, 2021.
Incan numeric quipus use a base-10 number system. Each length/position of the pendant cord represents a whole number place value, ranging from the ones (at the end of the pendant cord) to the ten-thousands (nearest the primary cord) (Gresham College & Medrano, 2021).
A single pendant cord can represent a value anywhere between 0 to 99,999 inclusive. Numbers are represented by placing particular knots in these place value positions (Gresham College & Medrano, 2021):
- 0 is represented by an empty cord or empty place value position.
- The number 1, when placed in the ones place, is represented by a figure eight knot.
- The numbers 2 - 9, when placed in the ones place, are represented by a long knot with the respective number of turns.
- Values of 10 or more are represented by a corresponding number of overhand knots within their respective place value position.
Figure 3. Drawing with examples of quipu number system
Note. Drawing by Clarissa N. Pacyna. Image courtesy of Manuel Medrano’s lecture at Gresham College, 2021.
Today, the quipu lives on in Andean culture in ceremonies to inaugurate elected community leaders (Gresham College & Medrano, 2021), in modern art, and in funerary practices (Fowler Museum & Menéndez Pereda, 2022). You can find quipus in the digital space through tools that process academic databases of historical quipus (which have particular notations) and through digital tools that allow one to create new quipus (Visit Appendix D for examples). However, the author has yet to find a digital quipu tool that fits within the typical data science workflow.
To bring the Inca numeric quipu form into a data science ecosystem, the quipucamayoc
library needed to take a Pandas DataFrame (the quintessential data structure in a Python data science workflow) and use it to dynamically generate an image of a quipu inside of a Jupyter Notebook (another standard data science tool).
To minimize the effort required to start using the library, quipucamayoc
also needed a high level of abstraction. High-level visualization libraries can produce visualizations with a few lines of code (but the tradeoff is that they offer less customization) (Wongsuphasawat, 2022).
Lastly, the library’s visual design had to preserve the visual channel structures of the original quipus (where visual channels are ways of controlling the appearance of marks on an image [Munzner, 2014]): position, length, shape, and size.
The first step was to design the quipu chart’s visual elements and prototype their layouts using Figma, a web-based tool for drafting digital components. Each piece became an individual SVG (Scalable Vector Graphics) file. SVG images do not lose quality when resized, which is ideal for producing high-quality, resizable charts for the user. And because SVG images are essentially text files, the code could easily edit or combine SVGs through string manipulation.
Figure 4. Examples of quipucamayoc
SVG elements
Note. Examples of the library’s knot elements. Long knot with five “turns” representing the number 5 (left) and figure-eight knot representing the number 1 (right).
Because the Jupyter Notebook environment is a web application, rendering images in this environment is a matter of rendering images in the DOM (the Document Object Model, which is a representation of a web page that programming languages can interact with [MDN contributors, 2022]). To affect the DOM, the library has to use JavaScript.
- The process begins in the Jupyter Notebook environment, where the user instantiates a
Quipu()
instance with a Pandas DataFrame. Python then prepares the data for its transformation into a quipu.- The library checks the data for acceptable formatting (e.g., integer data type with all numbers less than or equal to 99,999). It also ensures that the user has used parameters to identify one nominal string column (for data labels) & one quantitative int column (for knots).
- If the given DataFrame fails any of the checks, the library returns a custom error.
- If the given DataFrame passes all the checks, Python converts it into a format resembling a JSON object so that JavaScript can process it later.
- IPython inputs the user's data into the main JavaScript (
index.js
) and runs that JavaScript.- Note: TypeScript, when compiled, turns into JavaScript. TypeScript is essentially JavaScript but with added type safety (meaning it has extra syntax for specifying the shape and type of data that every portion of the code should expect). Because each step of this library either processes or reshapes data into different complex data structures, leveraging type safety was essential for minimizing bugs in the code.
- TypeScript (JavaScript) starts by building a scene graph that describes the quipu chart's composition.
- This library's scene graph determines what SVG to display, where to place it, what transforms to perform, what labels to apply, and how to layer everything on top of each other.
- Note: More generally, a scene graph is a tree-like data structure used in computer graphics (e.g., animation and game engines) where code constructs images. Code can traverse these trees and draw the "scene" based on things like the mark, location, or transformations described by each node (Eck, 2021).
- TypeScript then traverses the scene graph and progressively constructs an SVG string.
- The width of the primary cord and background grid SVGs change to fit the number of pendant cords. To perform these transformations, TypeScript uses regular expressions to find the original dimensions, transforms the strings to numbers for calculation, and then replaces the original strings with the new dimensions.
- Ultimately, all these individual SVG elements sit inside one parent SVG. And because the parent SVG's size determines how to clip the image, the code must also keep track of the maximum width and height needed to show the entire quipu layout.
- Finally, TypeScript takes the completed SVG and inserts it into the HTML of the Jupyter Notebook output area.
- Luckily, IPython has a class called
Javascript
that makes this very easy. This class creates an HTML element (a simple container for webpage content [MDN contributors, 2022]) in Jupyter Notebook. The library can access this element and insert custom HTML (like the quipu chart SVG) inside.
- Luckily, IPython has a class called
(Visit Appendix E for more system design notes.)
Figure 5 shows how the different parts of the library interact with each other.
Figure 5. Data Flow Diagram
Note: Here, index.js
is both a process (a piece of code that performs actions) and a data object (in its stringified form, it is input into the Quipu class method _create_js_string
. Visit Appendix E, Figure 6 for a diagram key that gives high-level descriptions of shapes and arrows used here.
Every JavaScript project has npm (the package manager for JavaScript) at its core. Here, npm was responsible for installing and running the Parcel build tool. Parcel then builds JavaScript; it converts TypeScript to JavaScript and bundles all imports into a single output file. (Parcel also allows TypeScript/JavaScript to interact with the SVG files as if they were strings. Visit Appendix E for more information.)
On the Python side, the quipucamayoc
library needed to become a pip package for ease of use. The package installer pip was responsible for running Setuptools (a tool for creating Python packages). Setuptools builds the quipucamayoc
library; it brings all the Python files together with the JavaScript build
file. The challenge with this library was getting Setuptools to recognize files outside the Python module (i.e., the JavaScript files). The solution was to use a custom configuration file to tell Setuptools where to find additional package files (i.e., the JavaScript files). The result is a quipucamayoc
pip package that can be easily installed and ready to use.
Let’s observe how this quipu performs with real-world data. The following uses quipucamayoc
to chart the change in Iowa electricity sourced from fossil fuels since the state implemented more renewable energy sources (Altair, 2019).
import quipucamayoc as qp
import pandas as pd
from vega_datasets import data # (Altair, 2019)
# get Iowa net generation of electricity from fossil fuels,
# in thousand megawatt hours, 2001 - 2017
iowa_electricity_df = data.iowa_electricity()
iowa_fossil_df = iowa_electricity_df[iowa_electricity_df['source'] == 'Fossil Fuels'].copy()
# change type of `year` column from datetime to string
iowa_fossil_df['year'] = iowa_fossil_df['year'].dt.strftime("%Y-%m-%d")
# preview data
iowa_fossil_df
# create quipu for Iowa net generation of electricity from fossil fuels, in thousand megawatt hours, 2001 - 2017
iowa_quipu = qp.Quipu(data=iowa_fossil_df, label='year', value='net_generation')
iowa_quipu.display()
Because the quipu divides information by orders of magnitude, the viewer can focus on the highest levels of the quipu chart to immediately identify the scale of change. Here we can focus on the ten thousands range (which amounts to ten millions megawatt hours according to this data’s unit of measure). Energy sourced from fossil fuels rose since 2001, reaching a peak between 2007-2010. This increase did not go unnoticed, and Iowa enacted new energy legislation in 2007 (Iowa Legislative Services Agency, 2011). By 2011, fossil fuels as energy sources were on the decline, so much so that by 2017 fossil fuels generated about ten million fewer megawatt hours of electricity than in 2001.
There's still more work to be done.
- Add more channels for expressiveness:
- Implement top cords and subsidiary cords
- Custom chart titles
- Primary cord label to communicate the unit of measurement (e.g., thousand megawatt hours)
- Custom colors
- The ability to visually group the data's subgroups (e.g., in the above example, a separate group of pendants could have shown the increase in megawatt hours from renewable sources over the same period)
- Interactions (e.g., scroll over the pendant cords to reveal their numeric values)
- Make the pip package more easily accessible by adding it to the Python Package Index
- Translate this and other documentation into Spanish and Quechua
Building my first data visualization library taught me a lot about computer graphics data structures, communicating between Python & TypeScript, and what it takes to make software packages. But more importantly, working on this project made me aware of the gap between our tools and the things we analyze with them. Our dominant forms of representation tend to seem ahistorical while the subjects of our studies are not, and alternate forms can make this mismatch explicit. Alternate forms force us to consider the objects of our analysis in other historical contexts. Ethical concerns do not just apply to data science outcomes; they must also apply to our tools and their design.
I hope quipucamayoc
inspires data scientists to approach their discipline as the weaving together of historical modes of representation with historical problems.
Altair. (2019, December13). vega_datasets/dataset_info.json. GitHub. https://github.com/altair-viz/vega_datasets/blob/master/vega_datasets/dataset_info.json
Benjamin, R. (2022). Viral Justice: How We Grow the World We Want. Princeton University Press.
Eck, D. J. (2021). Introduction to Computer Graphics [eBook edition]. https://math.hws.edu/graphicsbook/index.html
Fowler Museum at UCLA. (2022, May 4). Lunch & Learn: An Inka Khipu [Video of lecture by Alba Menéndez Pereda]. YouTube. https://www.youtube.com/watch?v=24lVgTu-G_E
Iowa Legislative Services Agency. (2011). Energy Information Report, 2011. https://publications.iowa.gov/id/eprint/15254
MDN contributors. (2022, September 20). Element - MDN Web Docs Glossary. MDN Web Docs. https://developer.mozilla.org/en-US/docs/Glossary/Element
MDN contributors. (2022, September 29). Introduction to the DOM. MDN Web Docs. https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction
Gresham College. (2021, November 9). Knot Just Numbers: Andean Khipu Strings [Video of lecture by Manuel Medrano]. YouTube. https://www.youtube.com/watch?v=Al5Qq-EDk_k
Khipu found covered by peanuts in Inkawasi, Cañete [Twisted, knotted and embroidery]. (1400/1532). Google Arts & Culture. https://artsandculture.google.com/asset/khipu-found-covered-by-peanuts-in-inkawasi-ca%C3%B1ete-inca-culture/ZAEHxlOpqhGaxg
Krishnan, A., Abdilla, A., Moon, AJ., Affonso Souza, C., Adamson, C., M. Lach, E., Ghazal, F., Fjeld, J., Taylor, J., C. Havens, J., Jayaram, M., Morrow, M., Rizk, N., Ricaurte Quijano, P., Buse Çetin, R., Chatila, R., Dotan, R., Mhlambi, S., Jordan, S., & Rosenstock, S. (n.d.). Decolonial AI Manyfesto. Decolonial AI Manyfesto. https://manyfesto.ai/
Lewis, J.E. (Ed.). (2020). Indigenous Protocol and Artificial Intelligence Position Paper. The Initiative for Indigenous Futures and the Canadian Institute for Advanced Research (CIFAR). https://doi.org/10.11573/spectrum.library.concordia.ca.00986506
Munzner, T. (2014). Visualization Analysis and Design [eBook edition]. A K Peters/CRC Press. https://www.oreilly.com/library/view/visualization-analysis-and/9781466508910/
Wongsuphasawat, K. (2020, September 22). Navigating the Wide World of Data Visualization Libraries. Medium. https://medium.com/nightingale/navigating-the-wide-world-of-web-based-data-visualization-libraries-798ea9f536e7
This was an independent project.
References for learning more about speculative design:
- Bray, K., & Harrington, C. (2021). Speculative Blackness: Considering Afrofuturism in the Creation of Inclusive Speculative Design Probes. In W. Ju, L. Oehlberg, S. Follmer, S. Fox, & S. Kuznetsov (Eds.), DIS '21: Designing Interactive Systems Conference 2021 (pp. 1793–1806). Association for Computing Machinery. https://doi.org/10.1145/3461778.3462002
- Dunne, A. & Raby, F. (2013). Speculative everything: Design, Fiction, and Social Dreaming. MIT Press.
- Harrington, C. N., Klassen, S., & Rankin, Y. A. (2022). “All that You Touch, You Change”: Expanding the Canon of Speculative Design Towards Black Futuring. In S. Barbosa, C. Lampe, C. Appert, D.A. Shamma, S. Drucker, J. Williamson, & K. Yatani (Eds.), CHI Conference on Human Factors in Computing Systems (CHI '22), April 29-May 5, 2022, New Orleans, LA, USA. Association for Computing Machinery. Article 450. https://doi.org/10.1145/3491102.3502118
- Merla-Watson, C. J. & Olguín, B. V. (2015). Introduction: ¡Latin@futurism Ahora! Recovering, Remapping, and Recentering the Chican@ and Latin@ Speculative Arts. Aztlan: A Journal of Chicano Studies, 40(2), 135-146. https://www.ingentaconnect.com/content/csrc/aztlan/2015/00000040/00000002/art00009
Wari quipus use a mix of base number systems besides just base 10 (Gresham College & Medrano, 2021).
There are facets of quipus that archaeologists have yet to decipher. These include the color, spacing, spin, ply, and direction of the cords. However, not all quipus appear to encode information through these features. Even among quipus with these features, scholars are still working to determine if these features encode data according to some unifying standard (Gresham College & Medrano, 2021).
Examples of tools that produce digital quipus from academic databases or user input:
- Clarke, I. [isaac-art] (2018, January 13). GitHub - isaac-art/quipuMaker: an (unoptimized) quipu knot pattern maker processing sketch. Takes an ASCII file and converts to PDF. Each line of the input file is a quipu, each character a pendant. Sub-Pendants not currently supported. GitHub. https://github.com/isaac-art/quipuMaker
- Griffiths, D. [nebogeo] (2017, February 15). GitHub - nebogeo/coding-with-knots: Coding with knots, Inca style. GitHub. https://github.com/nebogeo/coding-with-knots
The Vega visualization library provided ample inspiration for this library’s technical approach. The following links were beneficial:
- Heer, J. (2021, April 11). How Vega Works. Observable. https://observablehq.com/@vega/how-vega-works
- Vega. (2022, January 20). ipyvega/base.py. GitHub. https://github.com/vega/ipyvega/blob/master/vega/base.py
- Vega. (2022, January 20). ipyvega/utils.py. GitHub. https://github.com/vega/ipyvega/blob/master/vega/utils.py
- Vega. (2022, April 15). vega/packages/vega-scenegraph. GitHub. https://github.com/vega/vega/tree/main/packages/vega-scenegraph
For more about running JavaScript through IPython, visit:
- The IPython Development Team. (2022, Nov 28). Module: display. IPython Documentation. https://ipython.readthedocs.io/en/stable/api/generated/IPython.display.html#IPython.display.Javascript.__init__
- VanderPlas, J. (2013, June 1). IPython Notebook: Javascript/Python Bi-directional Communication. Pythonic Perambulations. https://jakevdp.github.io/blog/2013/06/01/ipython-notebook-javascript-python-communication/
Visit the following links for more information on how to use Parcel to construct a library or to handle SVG files as in-line code within JavaScript:
- Parcel Bundler. (n.d.). Building a library with Parcel. https://parceljs.org/getting-started/library/
- Parcel Bundler. (n.d.). SVG. https://parceljs.org/languages/svg/#inlining-as-a-string
Figure E. Key for Interpreting Shapes and Arrows of Figure 5: Data Flow Diagram