---
title: "LDAShiny: a complete guided workflow for topic modeling"
author: "Javier De la Hoz-M."
output:
  rmarkdown::html_vignette:
    toc: true
    toc_depth: 2
vignette: >
  %\VignetteIndexEntry{LDAShiny: a complete guided workflow for topic modeling}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment  = "#>",
  eval     = FALSE
)
```

# Introduction

`LDAShiny` is a web application built with Shiny (Chang et al., 2017) and the golem framework (Fay et al., 2022). It lets you run an exploratory review of the scientific literature with the Latent Dirichlet Allocation model (LDA; Blei, Ng and Jordan, 2003) without writing code: from loading bibliographic data to interpreting topics and tracking how they evolve over time.

This guide walks through every tab of the application in the recommended order:

| Step | App tab | What it does |
|:-----|:--------|:-------------|
| 0 | `About` | Description, technical specifications and how to cite the package. |
| 1 | `Import Data` | Imports and merges Scopus, Web of Science or bibliometrix files; cleans them with PRISMA criteria; summarizes the corpus. |
| 1b | `Geographic & Journal Analysis` | Production tables and chart by country and journal; world choropleth map; international collaboration network. |
| 2 | `Preprocess` | Cleans the text, builds the document-term matrix (DTM) and lets you refine stopwords. |
| 3 | `LDA Inference` | Fits LDA models over a range of K and selects the K with the highest coherence. |
| 4 | `Stability & Sensitivity` | Assesses how robust the choice of K is. |
| 5 | `Final LDA Model` | Trains the final model and provides tables, word clouds, the theta matrix and LDAvis. |
| 6 | `Topic Trends` | Classifies topics as increasing, declining or stable across years. |

# Installation and launch

The package requires R >= 4.1.0. Once installed, the application starts with a single function:

```{r launch}
library(LDAShiny)
run_LDAShiny()
```

Bibliographic files (for example, Scopus exports) can be large. Shiny limits file uploads to 5 MB by default; if your files are larger, raise the limit **before** launching the application:

```{r maxsize}
options(shiny.maxRequestSize = 1024 * 1024^2)  # 1 GB
run_LDAShiny()
```

## How the modules connect

Each step depends on the output of the previous one, so it is best to follow the order of the sidebar:

| Module | Receives | Provides |
|:-------|:---------|:---------|
| `Import Data` | Scopus / WoS / bibliometrix / Excel files | Cleaned table of documents (with a `country` column). |
| `Geographic & Journal Analysis` | Cleaned table of documents | Production tables, choropleth map and collaboration network. |
| `Preprocess` | Table of documents | Final DTM (sparse matrix) and term-frequency table. |
| `LDA Inference` | DTM | Coherence table and optimal K. |
| `Stability & Sensitivity` | DTM, coherence table, optimal K | Stability per K and sensitivity to the weights. |
| `Final LDA Model` | DTM, optimal K, table of documents | Final model, beta/gamma/theta matrices, topic-by-year intensity. |
| `Topic Trends` | Topic-by-year intensity | Trend classification for each topic. |

The download buttons of each module stay disabled until the corresponding analysis has been run.

# Step 0. About

The `About` tab summarizes what the application does, its technical specifications (version, framework and main packages), the recommended way to cite `LDAShiny`, and information about the research group and the author.

# Step 1. Importing data (`Import Data`)

First choose an action in the **Select an action** menu:

| Action | What it loads |
|:-------|:--------------|
| `Merge Scopus + Web of Science` | One or more Scopus CSV files and one or more Web of Science TXT files, merged into a single table. Click **Process and Merge**. |
| `Load Integrated Excel File` | An already integrated `.xlsx` file (for example, one previously downloaded from this same tab). It is processed as soon as it is uploaded. |
| `Load Bibliometrix File` | An `.xlsx` or `.RData` file exported from Biblioshiny or produced with `bibliometrix::convert2df()`. It is mapped automatically to the `LDAShiny` format. |

The fields used by the rest of the application are `title`, `abstract`, `year`, `Journal`, `doi` and `database`; the PRISMA cleaning also uses `affiliations`. For Excel files, column names are matched case-insensitively and the usual aliases are accepted (for example `TI`, `AB`, `PY`, `SO`, `DI`, `DB`, `C1`). The Excel file should include a `database` column, because the training module uses it to compute topic intensity by source.

## PRISMA cleaning

Every upload goes through a sequence of filters, inspired by the PRISMA scheme (Page et al., 2021), applied in order, and the counts are recorded:

| PRISMA phase | Criterion |
|:-------------|:----------|
| Identification | Records without a title. |
| Screening | Duplicate removal: by normalized DOI; records without a DOI are compared using a fingerprint made of the first 200 characters of the abstract, the year and the journal. |
| Screening | Records without an abstract (including placeholders such as "[No abstract available]"). |
| Eligibility | Records without an affiliation (only if the affiliations column exists). |
| Eligibility | Records without a year. |
| Eligibility | Records without a journal or source. |

After filtering, a `country` column is added (the first country in the affiliations). This column does not remove records and is not a PRISMA step. When the upload finishes, the application shows an import summary, and the current status appears in the **Instructions and Status** box.

## Exploring the corpus

Once the data are loaded, the other tabs of the module let you inspect them before moving on:

- **Summary Statistics**: a numerical summary; count tables (*Count Tables*) of documents per journal and per year; and customizable plots (*Customizable Plots*). The `Journal Count` plot supports a bar or lollipop style and between 5 and 50 journals; the `Year Count` plot shows production by year. The customization dropdown controls labels, theme, font, colors, point size and export options (PNG, TIFF, JPEG or PDF, with width, height and DPI).
- **Missing Values**: number of missing values per column.
- **Preview**: the first 10 records.
- **Download**: downloads the integrated dataset as Excel, including the `country` column.
- **Country Map**: map of documents by country, with palette, scale (logarithmic or linear), palette direction, title, border and no-data colors, map export, and a download of the country table in Excel.
- **PRISMA Flow**: summary table of the cleaning steps (downloadable as Excel) and a PRISMA flow diagram. You can set the database label and, optionally, the search query, and export the diagram as PNG, PDF or TIFF.

# Step 1b. Geographic and journal analysis (`Geographic & Journal Analysis`)

This module is available as soon as data have been imported. It provides three complementary views of the corpus and does not affect the modeling workflow.

## Tab 1 — Country & Journal

The left panel controls the **Settings** for all three views in this tab:

| Control | Description |
|:--------|:------------|
| Top N countries | Number of leading countries shown in the country table (5–50, default 20). |
| Top N journals | Number of leading journals shown in the journal table (5–50, default 20). |
| Variable | Whether the chart shows countries or journals. |
| Style | Bar or lollipop chart. |
| Top N to plot | Number of entries shown in the chart (5–30, default 15). |
| Customize chart | Dropdown with labels, theme, font size, colors, alpha and export options (PNG, TIFF, JPEG or PDF, with width, height and DPI). |

The **Results** panel has three inner tabs:

- **Country Table**: frequency of documents by country, downloadable as Excel.
- **Journal Table**: frequency of documents by journal, downloadable as Excel.
- **Chart**: bar or lollipop chart of the selected variable. Click **Update Chart** to apply any change in settings.

## Tab 2 — Country Map

A world choropleth map of documents by country. Options:

| Control | Description |
|:--------|:------------|
| Color Palette | viridis family (viridis, magma, plasma, inferno, cividis, mako, rocket, turbo) or ColorBrewer palettes (Blues, Reds, YlOrRd, YlGnBu, Spectral). |
| Color Scale | Logarithmic (log10) or linear. |
| Palette Direction | Normal or reversed. |
| Map Title | Editable title. |
| Color NA countries | Fill color for countries not present in the corpus. |
| Border color / Border width | Appearance of country borders. |

Export options let you download the map (PNG, TIFF, JPEG or PDF) and the underlying country frequency table (Excel).

## Tab 3 — Collaboration Network

This tab builds an international co-authorship network from the `affiliations` column. For each record the application extracts all countries mentioned in the affiliations, creates a pair (country A, country B) for every co-authored combination, aggregates the pairs across the corpus, and visualises the result as a graph.

**Filters and visual controls:**

| Control | Description |
|:--------|:------------|
| Min. collaborations | Minimum edge weight (number of co-authored records) for a link to appear. |
| Max. countries to show | The network keeps only the top N countries by degree, to avoid overplotting. |
| Network Layout | Seven options: Fruchterman-Reingold (default), Kamada-Kawai, Circle, Star, Grid, Sphere and Random. |
| Node size scale | Scales node area (proportional to weighted degree / strength). |
| Edge transparency | Alpha of the edges. |
| Node color / Edge color | Base colors when no metric is selected for the gradient. |
| Label size | Size of the country labels. |
| Color nodes by | Node color gradient based on a centrality metric (see table below). |
| Metric color palette | Palette for the node color gradient (viridis family or ColorBrewer). |

Click **Build Network** to compute the graph. The three inner tabs show:

- **Network Plot**: the co-authorship graph. Node size is proportional to strength (weighted degree); edge thickness is proportional to the number of co-publications.
- **Edge List**: co-authorship pairs and their collaboration count, downloadable as Excel.
- **Network Metrics**: a table with eight centrality metrics per country, with color bars for the three most informative ones, plus a bar chart of the selected metric for the top N countries. Downloadable as Excel.

**Available centrality metrics:**

| Metric | Description |
|:-------|:------------|
| Strength | Sum of edge weights (total co-publications). |
| Degree | Number of distinct partner countries. |
| Betweenness | Fraction of shortest paths passing through the node (normalized). Uses inverse weights so that stronger links are treated as shorter paths. |
| Closeness | Inverse of the average shortest-path length to all other nodes (normalized). |
| PageRank | Authority score based on the link structure, weighted by collaboration count. |
| Hub score | Kleinberg hub score: nodes that link to many important authorities. |
| Authority score | Kleinberg authority score: nodes linked to by many important hubs. |
| Clustering coefficient | Local transitivity: fraction of a node's neighbors that are also connected to each other. |

# Step 2. Preprocessing the text (`Preprocess`)

This module turns text into a document-term matrix. Everything is configured in the **Settings** tab and run with **Run Preprocessing**.

| Option | Description |
|:-------|:------------|
| Select text column | Column with the text to model. Default: `abstract`. |
| Select document ID column | Column that identifies each document. Default: `title` (or `doi` if there is no title). |
| Upload Additional Stopwords | `.xlsx` file with extra stopwords in the first column, one per row and no header. |
| Min n-gram / Max n-gram | n-gram size, from 1 to 3. Default 1 and 2 (single words and bigrams). |
| Apply stemming | Applies the Porter algorithm. On by default. |
| Remove numbers / Remove punctuation | Remove numbers and punctuation. On by default. |
| Sparse filter | Maximum sparsity allowed per term (0.90 to 0.9999; default 0.995). The lower the value, the more rare terms are removed. |
| Number of CPUs | Cores used to build the DTM. |

The text is always converted to lowercase and English stopwords are always removed, together with those from the uploaded file and any added interactively. For this reason the application is designed for corpora in English.

The other tabs of the module show and let you refine the result:

- **DTM Summary**: dimensions of the matrix before and after the sparsity filter. If the DTM ends up empty, or the filter removes every term, the application reports it; in the second case, try a less strict sparsity level.
- **Term Frequency (tf_mat)**: table of terms with their total frequency and document frequency.
- **Refine Stopwords**: table sorted by descending document frequency. Terms that appear in many documents are often candidates for stopwords. Select the rows, click **Add Selected & Reprocess**, and the DTM is rebuilt automatically. The cumulative list of words added during the session can be downloaded as Excel or cleared with **Clear Custom Stopwords**.
- **Downloads**: the full frequency table (`tf_mat.xlsx`) and the final DTM (`dtm_final_sparse.rds`).

# Step 3. Choosing the number of topics (`LDA Inference`)

The module fits an LDA model for each value of K in the chosen range, in parallel, and computes the coherence of every topic (Mimno et al., 2011). The summary measure for each model is the mean coherence of its topics.

| Option | Default |
|:-------|:--------|
| Minimum number of topics (k start) | 5 |
| Maximum number of topics (k end) | 40 |
| Step for k | 1 |
| Iterations | 500 |
| Burn-in | 50 |
| Alpha | 0.1 |
| Number of CPUs | depends on the machine |

Click **Run LDA Inference**. When it finishes, the status reports the K with the highest mean coherence and the elapsed time. Results appear in two tabs:

- **Coherence Table**: coherence value for each K, downloadable as Excel (`coherence_mat.xlsx`).
- **Coherence Plot**: coherence curve against K, with customization options (labels, theme, line color and width, points) and export as PNG, TIFF, JPEG or PDF.

The K with maximum coherence is a starting point, not a final decision. Coherence curves often have several regions with similar values, which is why the next step evaluates how robust the choice is.

# Step 4. Stability and sensitivity (`Stability & Sensitivity`)

This module checks whether the chosen K is robust, using three ideas:

1. **Stability against initialization.** For each candidate K several models are trained, and the variability of their coherence and the Adjusted Rand Index (ARI; Hubert and Arabie, 1985) between the dominant-topic assignments of each document are measured. Before comparing runs, the topics of each run are aligned with those of the first run using the cosine similarity of their term distributions.
2. **Composite score.** Each K receives a score that combines four criteria.
3. **Sensitivity to the weights.** The module checks whether the winning K changes under alternative weighting schemes.

## Configuration

| Option | Default | Description |
|:-------|:--------|:------------|
| Number of seeds | 5 (3 to 20) | Independent runs per K. |
| Base seed | 42 | First seed in the sequence. |
| Iterations per seed | 300 | Iterations of each run. |
| Burnin per seed | 150 | Warm-up iterations. |
| CPUs for parallel training | depends on the machine | Available cores. |
| Select K candidates | optimal K and its neighbors | Values of K to evaluate; the ones tested in `LDA Inference` are offered. You must select at least two. |

## Composite score criteria

All criteria are normalized to the range 0 to 1 across the evaluated K values:

| Criterion | Default weight | What it measures |
|:----------|:---------------|:-----------------|
| Plateau | 0.30 | Favors K values where coherence changes little relative to the previous K, that is, flat regions of the curve. |
| Stability | 0.30 | Mean ARI of the runs against the first run. |
| Parsimony | 0.20 | Favors smaller K values. |
| Interpretability | 0.20 | Approximation based on coherence (70%) and on low variability of coherence across runs (30%). |

Weights are rescaled automatically so that they sum to 1. Interpretability is a numerical approximation: it does not replace reading the terms of each topic.

## Results

Click **Run Stability Analysis**. Results are organized in five tabs:

- **Stability Table**: for each K, mean and minimum ARI (against the first run), mean coherence, standard deviation, minimum and maximum, and the score of each criterion, sorted by total score. Downloadable as Excel.
- **Coherence Boxplot**: distribution of coherence across runs for each K.
- **Coherence by Seed**: coherence of each run, by K.
- **Weight Sensitivity**: winning K under the scheme you declared and under four alternative schemes (equal weights, and schemes dominated by stability, parsimony or interpretability). A message summarizes whether the winner stays the same.
- **Radar Chart**: score of the four criteria (stability, parsimony, interpretability and plateau) for each evaluated K.

Plots are downloaded as PNG and tables as Excel. A K that wins under almost every scheme and has a high ARI is easier to defend than one that wins under a single set of weights.

# Step 5. Training the final model (`Final LDA Model`)

## Parameters

The number of topics (**Number of topics (K)**) is initialized with the optimal K from `LDA Inference`, but you can change it. When the optimal K is received, alpha is also updated automatically to `50 / K` (rounded to two decimals).

| Option | Default |
|:-------|:--------|
| Iterations | 500 |
| Burn-in | 50 |
| Alpha (Dirichlet prior on theta) | 0.1 (updated to 50/K when synchronized with the inference step) |
| Beta (Dirichlet prior on phi) | 0.05 |
| CPUs for Model Training | all but one |
| Optimize Alpha during run | on |
| Model Evaluation Metrics | likelihood and coherence (R-squared is optional) |

Click **Train Final LDA Model**. When it finishes, **Download Final LDA Model (.rds)** is enabled.

## Results

| Tab | Content | Download file |
|:----|:--------|:--------------|
| Model Evaluation Metrics | Model parameters and the selected global metrics (mean log-likelihood, mean coherence, R-squared). | `lda_model_metrics.xlsx` |
| Top Terms Matrix | One column per topic (`t_1`, `t_2`, ...) and one row per rank (1 = most important term). The number of terms (M) is configurable. | `lda_top_terms_matrix.xlsx` |
| Document Topic Assignment | Dominant topic of each document (the one with the highest gamma). | `toptopic.xlsx` |
| Top Documents per Topic | The documents with the highest gamma in each topic; the number is configurable. | `clasificacion.xlsx` |
| Topic-Term Weights (Beta) | Topic-term matrix in long format. The view shows the top 5 terms per topic; the download contains the full matrix. | `tidy_beta.xlsx` |
| Document-Topic Weights (Gamma) | Document-topic matrix in long format. The view shows a sample; the download contains the full matrix. | `tidy_gamma.xlsx` |
| Topic Word Cloud | Word cloud of the chosen topic, with maximum number of words, base color or RColorBrewer palette, and export (PNG, JPEG, PDF or TIFF, with width, height and DPI). | depends on the format |
| Theta Matrix (Full) | Full document-topic matrix with the `title`, `country` and `Journal` metadata and one column per topic. | `theta_matrix_full_K<K>_<date>.xlsx` |
| LDAvis | Interactive topic visualization (see below). | |

## Consistent topic numbering

Topics are named `t_1`, ..., `t_K`. The Top Terms Matrix, the Theta Matrix and LDAvis all use that same numbering: topic `t_3` in the terms table is topic 3 in LDAvis and column `t_3` of the Theta Matrix. To guarantee this, LDAvis is generated without reordering the topics by prevalence, which is its default behavior. Before opening it, the application checks that the top term of every topic in LDAvis matches the one in the table and warns you if it finds a difference.

## LDAvis

Click **Abrir LDAvis** and the visualization opens in a new browser tab (allow pop-ups). LDAvis (Sievert and Shirley, 2014) projects the topics into two dimensions and shows the most relevant terms for the selected topic.

- With λ = 1 (the value it opens with), terms are ordered by their probability within the topic, the same criterion used by the Top Terms Matrix. If you move the λ control inside LDAvis toward lower values, the most topic-exclusive terms are prioritized and the list changes, although the numbering stays the same.
- The size of each circle is proportional to the prevalence of the topic.

## The downloaded model

The file `lda_final_model.rds` contains the object returned by `textmineR::FitLdaModel()`, to which the application adds the prevalence of each topic (as a percentage), the labels and the parameters used. You can load it in R to continue the analysis:

```{r use-model}
model <- readRDS("lda_final_model.rds")

names(model)            # model components
dim(model$phi)          # K topics x terms
dim(model$theta)        # documents x K topics
round(model$prevalence, 1)

# Top ten terms of each topic
textmineR::GetTopTerms(model$phi, M = 10)
```

# Step 6. Temporal trends (`Topic Trends`)

This module starts from the intensity of each topic by year, computed as the average gamma of the documents in that year, and evaluates its evolution with two complementary tests:

- **Ordinary least squares (OLS) regression** of intensity on year: slope (reported multiplied by 1000), R-squared and p-value.
- **Mann-Kendall test** (Mann, 1945), non-parametric: coefficient τ and p-value.

## Options

| Option | Default | Description |
|:-------|:--------|:------------|
| Significance Level (α) | 0.05 | Significance threshold. |
| Exclude last year | on | Excludes the last year of the corpus, which is often only partially indexed. |
| Apply FDR correction | on | Adjusts p-values for multiple comparisons with the Benjamini-Hochberg method (1995). |
| Select Topic for Plotting | first topic | Topic to plot; it appears after the analysis has been run. |

Click **Run Trend Analysis**. A topic needs at least four years of data to be evaluated; with fewer, it is classified as stable because of insufficient data.

## Classification

The classification requires the two tests to converge:

| Result | Condition |
|:-------|:----------|
| `Increasing` / `Declining` | The OLS slope and τ have the same sign and **both** tests are significant. |
| `Increasing*` / `Declining*` | Both tests agree in sign, but only **one** is significant. |
| `Stable` | Neither is significant, the signs differ, or there is not enough data. |

## Results

- **Topic-Year Data**: mean intensity of each topic by year (`topic_year_intensity_data.xlsx`).
- **Regression Results Table**: for each topic, trend, mean prevalence (%), OLS slope, R-squared, p-values (with and without FDR correction), τ and its p-value (`topic_trend_regression_results.xlsx`).
- **Topic Trend Plot**: intensity of the chosen topic across years with its trend line. It supports customization (title, labels, theme, font, line and point style) and export in several formats.

# Files generated by the application

| Module | File |
|:-------|:-----|
| `Import Data` | Integrated Excel file, country table, PRISMA table, PRISMA diagram and plots |
| `Geographic & Journal Analysis` | Country table, journal table, production chart, choropleth map, country frequency table, edge list and network metrics (all as Excel or image files) |
| `Preprocess` | `tf_mat.xlsx`, `dtm_final_sparse.rds`, `custom_stopwords_<date>.xlsx` |
| `LDA Inference` | `coherence_mat.xlsx` and coherence plot |
| `Stability & Sensitivity` | `Stability_Results_<date>.xlsx`, `Weight_Sensitivity_<date>.xlsx` and PNG plots |
| `Final LDA Model` | `lda_final_model.rds`, `lda_model_metrics.xlsx`, `lda_top_terms_matrix.xlsx`, `toptopic.xlsx`, `clasificacion.xlsx`, `tidy_beta.xlsx`, `tidy_gamma.xlsx`, `theta_matrix_full_K<K>_<date>.xlsx`, word clouds |
| `Topic Trends` | `topic_year_intensity_data.xlsx`, `topic_trend_regression_results.xlsx` and plot |

# Tips and troubleshooting

- **Document your decisions.** Keep the PRISMA table, the list of added stopwords, the chosen K and the model parameters (`Model Evaluation Metrics` tab), and store the `.rds` file of the final model.
- **Read the topics, not just the metrics.** Coherence and the composite score guide the choice of K, but the final decision should rest on reading the terms and the representative documents of each topic.
- **Refine stopwords iteratively.** After a first fit, use `Refine Stopwords` to remove generic domain terms and run the workflow again.
- **The DTM is empty or has no terms.** Check the chosen text column and relax the sparsity filter (`Sparse filter`).
- **A large file cannot be uploaded.** Raise `shiny.maxRequestSize` before launching the application (see "Installation and launch").
- **LDAvis does not open.** Allow pop-ups in the browser for the application address.
- **`Topic Trends` shows no results.** Train the final model first: this module uses the topic-by-year intensity computed in `Final LDA Model`, which requires the imported data to have `year` and `database` columns.
- **Computations take a long time.** `LDA Inference` and `Stability & Sensitivity` train many models. Narrow the range of K, use a step larger than 1 for a first exploration, and assign more CPUs.

# How to cite

If you use `LDAShiny` in your research, please cite:

De la Hoz-M., J., Fernandez-Gomez, M. J. and Mendes, S. (2021). LDAShiny: An R Package for Exploratory Review of Scientific Literature Based on a Bayesian Probabilistic Model and Machine Learning Tools. *Mathematics*, 9(14), 1671. <https://doi.org/10.3390/math9141671>

# References

Benjamini, Y. and Hochberg, Y. (1995). Controlling the false discovery rate: a practical and powerful approach to multiple testing. *Journal of the Royal Statistical Society: Series B*, 57(1), 289-300.

Blei, D. M., Ng, A. Y. and Jordan, M. I. (2003). Latent Dirichlet Allocation. *Journal of Machine Learning Research*, 3, 993-1022.

Chang, W., Cheng, J., Allaire, J. J., Sievert, C., Schloerke, B., Xie, Y., et al. *shiny: Web Application Framework for R*. R package.

Fay, C., Rochette, S., Guyader, V. and Girard, C. (2022). *Engineering Production-Grade Shiny Apps*. Chapman & Hall/CRC.

Hubert, L. and Arabie, P. (1985). Comparing partitions. *Journal of Classification*, 2, 193-218.

Mann, H. B. (1945). Nonparametric tests against trend. *Econometrica*, 13(3), 245-259.

Mimno, D., Wallach, H., Talley, E., Leenders, M. and McCallum, A. (2011). Optimizing semantic coherence in topic models. *Proceedings of EMNLP*, 262-272.

Page, M. J. et al. (2021). The PRISMA 2020 statement: an updated guideline for reporting systematic reviews. *BMJ*, 372, n71.

Sievert, C. and Shirley, K. (2014). LDAvis: A method for visualizing and interpreting topics. *Proceedings of the Workshop on Interactive Language Learning, Visualization, and Interfaces*, 63-70.
