ꘇ dat.replace
Bulk-rename cells, and mind the substring you didn't mean
- input
- table
- text
What it is
ꘇ dat.replace is find-and-replace across every cell of a GENERETI_DAT table. Three inputs: the input table, a find string defaulting to speed, and a replace string defaulting to frequency. Two outputs, the usual table and text.
The defaults are a hint about the intended use: renaming channel names. Because dat.tochop takes channel names from the first row of a table, a table whose header says speed becomes a table whose header says frequency - and since the CHOP layer addresses channels by name, that rename is functional, not cosmetic. Downstream CHOP nodes that select or reference frequency will now find it.
The mechanism, and the sharp edge
It's a literal str.replace() applied to every cell in the table, with no regex, no word boundaries, and no case sensitivity change. So:
- Every occurrence, not just the first. A cell containing
speed speedbecomesfrequency frequency. - Substrings match.
speedupbecomesfrequencyup.groupspeedbecomesgroupfrequency. If your tables carry compound names -lfo_speed,speed_scale,minspeed- a naive replace quietly rewrites all three, and if you then push the table intodat.tochopor a CHOPselectpattern, you get channels that don't match what you typed elsewhere. - It's applied to all cells, not just the header. So if
0.5means something you'd rather not rewrite and some cell literally contains the text you're replacing, it gets rewritten too. Values that are pure numbers usually don't collide with word-like finds, but it's not guaranteed.
There's no regex mode and no "replace in header only" switch, which is honest for a node this size - but if you need precision you have two better tools in the same family: dat.select to slice the table down to just the header row before replacing, or dat.expression, which evaluates a small arithmetic language per numeric cell and is the right node when you want to change numbers rather than rewrite strings.
Why a rename is a real operation
It's easy to file this under "cosmetic". In practice, renaming is how you make one source's output fit another source's expectation without editing the data by hand. The pack's CHOP family addresses channels by name - chop.select takes a whitespace-separated glob pattern, and chop.arpeggiator looks for channels whose names end in note<digits> to read an incoming chord. If the incoming table's column happens to be called pitch rather than note1, dat.replace is a one-node bridge: rename pitch → note1, convert with dat.tochop, and the arpeggiator now sees a chord where before it saw nothing.
That's the pattern. Table in, rename, convert to channels, drive something. The alternative - editing the CSV text every time you swap sources - is worse.
Inputs, outputs, wiring
input-GENERETI_DAT, required.find-STRING, the substring to look for.replace-STRING, what to put in its place. An empty string deletes the match, which is a legitimate way to strip prefixes.table-GENERETI_DAT, the rewritten table. This is what you wire onward.text- the CSV of the rewritten table, good for eyeballing or for the document/export path the DAT nodes share.
A sanity-check habit worth building: put dat.inspect on text while you tune find. It bounds the preview and gives you the whole table as JSON, so you can confirm the rename did what you meant before it reaches a tochop that turns a mistake into a silent zero-channel.
Install
Only ships in the Genereti pack. Manager → search Genereti (publisher liuboto) → install → restart → refresh the browser tab. Manual:
cd ComfyUI/custom_nodes
git clone https://github.com/languel/genereti.git genereti
cd ../
./.venv/bin/python -m pip install -r custom_nodes/genereti/requirements.txt
Use the interpreter that belongs to your ComfyUI - .venv on a checkout, python_embeded\python.exe on Windows Portable. Requirements are one line, comfyui-frontend-package>=1.53.6: no models, no compiled extras, no new node packs. ComfyUI 0.38.2+ and Python 3.11+ are the floors.
Gotchas
- Substring matching is the big one. Be specific with
find. - No undo inside the graph. The table type is immutable, so your original survives upstream - but the moment you wire the replaced output into a
tochop, the rename is baked into the run. - Multiple nodes = multiple passes. Chaining two
dat.replacenodes applies both rules in sequence, so the output of the first is the input of the second. Order can matter if one rule's output contains the other'sfind. - Alpha software. The pack's README says "super alpha - early classroom testing… back up your workflows before updating." That applies to the whole data family; this node's semantics are simple enough that churn is unlikely, but pin your Comfy version if a project depends on it.
Inputs (3)
| Name | Type | Default | Description |
|---|---|---|---|
| input | GENERETI_DAT | — | |
| find | STRING | speed | — |
| replace | STRING | frequency | — |
Outputs (2)
| Name | Type | Description |
|---|---|---|
| table | GENERETI_DAT | — |
| text | STRING | — |