canvas
Terminal rendering for chmpy, at two RGB pixels per character cell.
A character cell is drawn as an upper-half block with a foreground and a background colour, so one cell carries two independently coloured pixels and the pixels come out square. That is enough resolution to rasterise van der Waals spheres with a z-buffer, i.e. to actually render a structure rather than spell it out in letters.
Canvas
A character grid where each cell has a glyph, a fg and a bg colour.
Source code in chmpy/tui/canvas.py
render(colors='truecolor')
Emit the grid as text. colors selects the escape-sequence depth.
Source code in chmpy/tui/canvas.py
Pixels
An RGB image with a coverage mask, rendered two rows per text line.
Source code in chmpy/tui/canvas.py
Terminal
dataclass
What the attached terminal can actually do.
Source code in chmpy/tui/canvas.py
Theme
dataclass
Chrome colours chosen to read against the terminal's own background.
Source code in chmpy/tui/canvas.py
fill
property
A concrete colour for the few places that must composite.
ascii_art(px, ramp=ASCII_RAMP)
Render pixels as shaded text, for output that carries no colour.
Half blocks say nothing without colour - the glyph is identical everywhere and the picture lives entirely in the escape sequences - so a colourless terminal, a pipe or a log file needs brightness mapped to characters instead. Vertical pairs are averaged so one character is one cell, keeping the aspect ratio the same as every other output mode.
Source code in chmpy/tui/canvas.py
detect(stream=None, allow_graphics=True)
Inspect the environment for colour and inline-image support.
Detection is environment-based rather than by querying the terminal: a query needs raw tty mode and a read timeout, which misbehaves when output is piped or run under a test harness.
Source code in chmpy/tui/canvas.py
display(px, terminal=None, cols=None, background=None)
Render a Pixels image using the best mode the terminal supports.
Uncovered pixels stay transparent in both modes, so the terminal's own
background shows through. Pass background only to force an opaque fill.
Source code in chmpy/tui/canvas.py
draw_cylinders(px, starts, ends, radii, colors0, colors1, scale, origin, zbuffer=None, ambient=0.3, specular=0.45, shininess=18.0, depth_cue=None, fade_to=None, shading='lit')
Rasterise shaded cylinders by exact ray intersection, z-buffered.
A chain of spheres is the easy way to fake a bond, but a sphere's normal points radially outward in every direction, so each bead picks up its own highlight and the bond reads as a string of beads. A cylinder's normal is perpendicular to its axis; solving the intersection properly is what makes a bond look like a rod.
Source code in chmpy/tui/canvas.py
359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 | |
draw_spheres(px, centers, radii, colors, scale, origin, zbuffer=None, ambient=0.3, specular=0.45, shininess=18.0, depth_cue=None, fade_to=None, shading='lit')
Rasterise shaded spheres into px with a z-buffer.
centers are (N, 3) in world units with +z toward the viewer; scale is
pixels per world unit and origin is the world point at pixel (0, 0) of
the top-left, with screen y increasing downward.
Source code in chmpy/tui/canvas.py
kitty_image(px, background=None, cols=None)
Encode a Pixels image as a Kitty graphics protocol escape sequence.
This transmits real pixels rather than half-blocks, so the picture is not limited to two rows per character cell. Uncovered pixels are sent as transparent RGBA rather than filled with an assumed colour, so the image sits on whatever the terminal background actually is - matching how the half-block path behaves, where a clear pixel simply emits no background.
Pass background only to force an opaque fill.
Source code in chmpy/tui/canvas.py
shade_surface(normals, base, ambient, specular, shininess, shading='lit')
Shade fragments given per-fragment normals (M, 3) and colours (M, 3).
Source code in chmpy/tui/canvas.py
theme_for(background=None)
Derive readable chrome from a terminal background colour.
background of None means the terminal did not answer the OSC 11 query,
in which case assume dark, which is by far the more common default.
Source code in chmpy/tui/canvas.py
to_256(rgb)
Nearest xterm-256 index for an RGB triple.