Skip to content

Add image-dot-chart-from-list#1863

Merged
jpolitz merged 5 commits into
horizonfrom
add-image-dot-chart
May 1, 2026
Merged

Add image-dot-chart-from-list#1863
jpolitz merged 5 commits into
horizonfrom
add-image-dot-chart

Conversation

@blerner

@blerner blerner commented Apr 30, 2026

Copy link
Copy Markdown
Member
  • Update chart-lib.js to the new js-numbers configuration
  • Fix a few mistakes in charts.arr where the old rawarray-based methods were not working
  • Clean up redundant "type-checking" iterations in charts.arr, since the annotations are doing that in JS
  • Simplify image-num-dot-chart-from-list to simply compose image-dot-chart-from-list and the image-labels method
  • Same for labeled-num-dot-chart-from-list
  • Add image-dot-chart-from-list, and rewrote categoricalDotChart to handle image marks accordingly.

Various examples:

include charts
include gdrive-sheets
include table
import csv as csv

animals-url = "https://docs.google.com/spreadsheets/d/1VeR2_bhpLvnRUZslmCAcSRKfZWs_5RNVujtZgEl6umA/export?format=csv"


animals-table =
  load-table: name, species, sex, age, fixed, legs, pounds, weeks
  source: csv.csv-table-url(animals-url, {
    header-row: true,
    infer-content: true
  })
end

dog-img      = text("🐶", 20, "black")
cat-img      = text("😺", 20, "black")
lizard-img   = text("🦎", 20, "black")
tarantula-img= text("🕷️", 20, "black")
snail-img    = text("🐌", 20, "black")
rabbit-img   = text("🐰", 20, "black")


fun animal-img(r): 
  if      (r["species"] == "dog"):       dog-img
  else if (r["species"] == "cat"):       cat-img
  else if (r["species"] == "tarantula"): tarantula-img
  else if (r["species"] == "lizard"):    lizard-img
  else if (r["species"] == "rabbit"):    rabbit-img
  else if (r["species"] == "snail"):     snail-img
  end
end

names   = animals-table.column("name")
ages    = animals-table.column("age")
fixeds  = animals-table.column("fixed")
species = animals-table.column("species")
images  = animals-table.all-rows().map(animal-img)

"Dot charts"
render-chart(from-list.dot-chart(species)).display()
render-chart(from-list.dot-chart(species).labels(names)).display()
render-chart(from-list.dot-chart(species).image-labels(images)).display()
render-chart(from-list.dot-chart(species).labels(names).image-labels(images)).display()
render-chart(from-list.dot-chart(fixeds.map(to-string)).labels(names).image-labels(images)).display()
render-chart(from-list.image-dot-chart(images, species)).display()
render-chart(from-list.image-dot-chart(images, species).labels(names)).display()
"Num dot charts"
render-chart(from-list.num-dot-chart(ages)).display()
render-chart(from-list.num-dot-chart(ages).labels(names)).display()
render-chart(from-list.num-dot-chart(ages).labels(names).image-labels(images)).display()
render-chart(from-list.labeled-num-dot-chart(names, ages)).display()
render-chart(from-list.labeled-num-dot-chart(names, ages).image-labels(images)).display()
"Image num dot charts"
render-chart(from-list.image-num-dot-chart(images, ages)).display()
render-chart(from-list.image-num-dot-chart(images, ages).labels(names)).display()
render-chart(from-list.image-num-dot-chart(images, ages).point-size(40).use-image-sizes(false).labels(names)).display()

- Fix a few mistakes in charts.arr where the old rawarray-based methods were not working
- Clean up redundant "type-checking" iterations in charts.arr, since the annotations are doing that in JS
- Simplify image-num-dot-chart-from-list to simply compose image-dot-chart-from-list and the image-labels method
- Same for labeled-num-dot-chart-from-list
- Add image-dot-chart-from-list, and rewrote categoricalDotChart to handle image marks accordingly.

Various examples:

render-chart(from-list.dot-chart(species)).display()
render-chart(from-list.dot-chart(species).labels(names)).display()
render-chart(from-list.dot-chart(species).image-labels(images)).display()
render-chart(from-list.dot-chart(species).labels(names).image-labels(images)).display()
render-chart(from-list.dot-chart(fixeds.map(to-string)).labels(names).image-labels(images)).display()
render-chart(from-list.image-dot-chart(images, species)).display()
render-chart(from-list.image-dot-chart(images, species).labels(names)).display()
render-chart(from-list.num-dot-chart(ages)).display()
render-chart(from-list.num-dot-chart(ages).labels(names)).display()
render-chart(from-list.num-dot-chart(ages).labels(names).image-labels(images)).display()
render-chart(from-list.labeled-num-dot-chart(names, ages)).display()
render-chart(from-list.labeled-num-dot-chart(names, ages).image-labels(images)).display()
render-chart(from-list.image-num-dot-chart(images, ages)).display()
render-chart(from-list.image-num-dot-chart(images, ages).labels(names)).display()
render-chart(from-list.image-num-dot-chart(images, ages).point-size(40).use-image-sizes(false).labels(names)).display()
@blerner blerner requested a review from jpolitz April 30, 2026 19:21
Joe says:

I think this is a regression? The composition makes it so this test has a
surprising result IMO. How much is the user supposed to think about sort orderings?

Claude says:

Adds a regression test that catches mis-pairing between images and
categories in image-dot-chart-from-list. The same logical (image,
category) bag rendered twice in different input orders should produce
identical images, since dot-chart-from-list sorts categories internally
and a categorical chart should depend only on the bag, not on input
order.

Each image is built with text(...) carrying its own category name, so
a save-image of a failing run shows exactly which image landed under
which column label.

Currently fails on this branch: a scrambled-input render rotates each
image one slot off its category.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@jpolitz

jpolitz commented May 1, 2026

Copy link
Copy Markdown
Member

These are the two images from the test I just pushed:
image
image

…ring

Joe says:

I think this is just a Vega config-format issue (thinko/typo in which kind of
update/signal goes in). I think these images should be different.

Claude says:

The two sizing settings must produce visibly different charts, since
use-image-sizes(true) means "use the image's natural dimensions" and
use-image-sizes(false) means "size them via the chart's dotSize
signal." If both render byte-identically, the false branch is a no-op.

Currently fails on this branch: the ImageMarks width/height encoding
uses {update: "..."} as a value reference, which is not valid Vega
encoding syntax (the standard form is {signal: "..."}), so Vega
silently ignores both width and height and falls back to natural
sizing in either mode. The dotsize/dotSize typo on the height line
is real but masked by this larger problem.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Comment thread src/js/trove/charts-lib.js Outdated
}),
}));
const counts = [...rawCounts.entries().map((kv) => ({ category: kv[0], count: kv[1] }))];
debugger

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably stray debugger.

@jpolitz

jpolitz commented May 1, 2026

Copy link
Copy Markdown
Member

The two tests I committed + the stray debugger are the full feedback I have, otherwise looks good!

Ben Lerner added 2 commits May 1, 2026 13:10
moves the sorting into the Vega processing, rather than Pyret, so that the lists stay in order throughout Pyret's computation
@jpolitz jpolitz merged commit 29be123 into horizon May 1, 2026
2 checks passed
@blerner blerner deleted the add-image-dot-chart branch May 1, 2026 22:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants