9
175
Fork
You've already forked wallust
21

Refactor Cam16UcsJmh weights and set up trial testing to determine best salience sorting #199

Merged
explosion-mental merged 1 commit from usaradark/wallust:new-histo into v4-alpha 2026年03月27日 00:46:38 +01:00
Contributor
Copy link

This PR introduces a new unit test salience::salience_sort(). You can run it with cargo test --test salience saliece_sort -- --show-output.

This unit test will generate a set of standardized or random colors to sort with. You will be able to adjust how salience puts weight on the Jmh components for calculation purposes. We are interested on these lines of code.

fn salience_sort(){
// IMPORTANT: Adjust the component weights to figure out what seem best.
//
// Mess around with a color picker here to get a feel on how these
// components work: https://apps.colorjs.io/picker/cam16-jmh
//
// j: lightness
// m: colorfulness
// h: hue
letcustom_weights: WeightsType=[
1.0,
1.0,
1.0
];
// IMPORTANT: Set this to whatever your background terminal is.
letbg="#010605";
// Here we generate the colors. See GenRange.
letj=GenRange::new(10.0,100.0,0.25);
letm=GenRange::new(0.0,100.0,0.25);
leth=GenRange::new(0.0,180.0,0.25);
let(mutcols,view)=setup_cols(ColorOrder::LightFirst,j,m,h);
letrgb_bg: Srgb<u8>=bg.parse().unwrap();
letcam16=Cam16::from_xyz(rgb_bg.into_linear().into_color(),view);
letbg=Spec::from_color(cam16);
// // Or alternatively, use the naive variant. Make sure you change the
// // sort to naive as well
// let bg = DARKEST_COL;
// // See what initial colors we're working with
// print_visual(&cols, view);
// println!("============================================");
// let w = Weights::Salience.value();
letw=custom_weights;
// // Uncomment me if you're using naive sorting
// let ord: ColorOrder = ColorOrder::LightFirst;
// cols.sort_by(|a, b| a.sal_naive(&ord, false, w).partial_cmp(&b.sal_naive(&ord, false, w)).unwrap_or(Ordering::Equal));
cols.sort_by(|a,b|a.sal(&bg,false,w).partial_cmp(&b.sal(&bg,false,w)).unwrap_or(Ordering::Equal));
print_visual(&cols,view);
}

Please adjust the weights, run the test, and re-adjust weights until you find the "correct" weights were sorting looks the best to you. As a reminder, the objective of the sort is to bring the most attention-grabbing colors to the right, and the least attention-grabbing to the left.

I wrote more comments as to what else you can adjust. For example, you can and should change the bg variable to match your terminal background.

You should consider your monitor's viewing angles. Make sure you're at the best angle.

It currently currently leverages implementation salience calculations, so there is no experimental local salience for more experimental calculations. I might add this in later if I deem that the component-delta model needs to be more complex, but considering Cam16's properties, it doesn't need to be... yet.

This PR doesn't HAVE to be merged in, as it's mainly just trying to determine the best weights for salience calculations, but if it does become merged, it can be leveraged to gather more data points on what might be the proper weights for this "salience" thing.

I will be experimenting in the coming days to determine the best weights. From brief experimentation, colorfulness or m needs a slight boost.

Here is a visual demo with normal generation and weights [1.0, 1.0, 1.0].
image

Notice how those pure white should be sorted later... and other incorrect sorting...

This PR introduces a new unit test `salience::salience_sort()`. You can run it with `cargo test --test salience saliece_sort -- --show-output`. This unit test will generate a set of standardized or random colors to sort with. You will be able to adjust how salience puts weight on the Jmh components for calculation purposes. We are interested on these lines of code. https://codeberg.org/usaradark/wallust/src/commit/5829257a5764ff6ba919819afafa0d46a87373a7/tests/salience.rs#L74-L120 Please adjust the weights, run the test, and re-adjust weights until you find the "correct" weights were sorting looks the best to you. As a reminder, the objective of the sort is to bring the most attention-grabbing colors to the right, and the least attention-grabbing to the left. I wrote more comments as to what else you can adjust. For example, you can and should change the `bg` variable to match your terminal background. You should consider your monitor's viewing angles. Make sure you're at the best angle. It currently currently leverages implementation salience calculations, so there is no experimental local `salience` for more experimental calculations. I might add this in later if I deem that the component-delta model needs to be more complex, but considering Cam16's properties, it doesn't need to be... yet. This PR doesn't HAVE to be merged in, as it's mainly just trying to determine the best weights for salience calculations, but if it does become merged, it can be leveraged to gather more data points on what might be the proper weights for this "salience" thing. I will be experimenting in the coming days to determine the best weights. From brief experimentation, `colorfulness` or `m` needs a slight boost. Here is a visual demo with normal generation and weights `[1.0, 1.0, 1.0]`. ![image](/attachments/5d4bebf0-c35f-4ecc-93a8-e00cd167dc7d) Notice how those pure white should be sorted later... and other incorrect sorting...
127 KiB
usaradark changed title from (削除) Refactor Cam16UcsJmh weights and set up trial testing to determine best salience sorting (削除ここまで) to WIP: Refactor Cam16UcsJmh weights and set up trial testing to determine best salience sorting 2025年12月14日 08:26:52 +01:00
Author
Contributor
Copy link

Plans to do another refactor on weights, separating unit tests for de vs sal vs sal_naive, and offset vs random modes of color generation.

Plans to do another refactor on weights, separating unit tests for `de` vs `sal` vs `sal_naive`, and `offset` vs `random` modes of color generation.

This is as a util rather than a test? You could write it as a 'script' or another binary

This is as a `util` rather than a test? You could write it as a 'script' or [another binary](https://doc.rust-lang.org/cargo/reference/cargo-targets.html?highlight=binaries#binaries)
Author
Contributor
Copy link

That is a good point... I'll transfer the script over to that.

Could you elaborate on what you mean as a 'script'?

That is a good point... I'll transfer the script over to that. Could you elaborate on what you mean as a 'script'?
Author
Contributor
Copy link

Just a heads up, if you're waiting for this before moving on with #195, don't worry about it unless you want salience calculations to be "perfect." I think what we have right now works "good enough", and any patches to how salience is calculated should be trivial once the infrastructure is finalized. Even with what we have now it should be a trivial patch.

With the holidays coming near, I will be busy on my end on other projects (and family). I'd imagine it's the same with others.

Just a heads up, if you're waiting for this before moving on with #195, don't worry about it unless you want salience calculations to be "perfect." I think what we have right now works "good enough", and any patches to how salience is calculated should be trivial once the infrastructure is finalized. Even with what we have now it should be a trivial patch. With the holidays coming near, I will be busy on my end on other projects (and family). I'd imagine it's the same with others.

Thinking of making another xmas edition ;p

Thinking of making another [xmas edition](https://codeberg.org/explosion-mental/wallust/releases/tag/2.9.0) ;p

@usaradark wrote in #199 (comment):

That is a good point... I'll transfer the script over to that.

Could you elaborate on what you mean as a 'script'?

I don't recall where I saw it, prob something to do with cargo xtasks so another bin inside src/bins/ should be enough :)

@usaradark wrote in https://codeberg.org/explosion-mental/wallust/pulls/199#issuecomment-8919174: > That is a good point... I'll transfer the script over to that. > > Could you elaborate on what you mean as a 'script'? I don't recall where I saw it, prob something to do with `cargo xtasks` so another bin inside `src/bins/` should be enough :)
Author
Contributor
Copy link

Here's that thing to try to figure out the best values for Jmh.

It's a start with still work to do, stuff like:

  • neatly output final weights
  • show seed when doing random
  • let adjust amount of colors gen
  • experiment with having weights for salience Jab
    • this might be the most accurate way of doing salience, but also probably the most tedious, requiring tuning of -a, +a, -b, and +b

With my very rough and brain-dead trials, something like 1.0 0.5 0.5 seems to sort well. I think right now master uses 1.0 1.5 1.5 and new-histo uses 1.0 5.0 1.0. For all, I believe their salience calculations are slightly different, which may result in weights being incomparable at extreme colors.

You can run the binary with cargo run --bin salsort -- 0 0 0, and use --help to see flags and the like. The interactive wizard should be somewhat self explanatory after playing with it. The only potentially confusing part is the repeat offset () command. To run it, just press Enter and it will repeat the previous command (should apply the previous offset... but w/e will fix later).

That's all for today. Tomorrow I'll probably work these final bits of polish for UX, rebase, then maybe merge.

I have an idea of how I might work with Lab salience, but I want to finalize this for now before moving to that.

Once this is done, I plan to have some friends do some trials to see what weights they seem to agree with. Likewise, you can also try to work out what weights your eyes agree with, and we can maybe find some average of what weights results in well-sorted attention.

Here's that thing to try to figure out the best values for Jmh. <video src="/attachments/c08e5cea-77ba-43a8-a751-926a05816c79" title="2026年01月13日 21-43-21_web" controls></video> It's a start with still work to do, stuff like: - neatly output final weights - show seed when doing random - let adjust amount of colors gen - experiment with having weights for salience Jab - this might be the most accurate way of doing salience, but also probably the most tedious, requiring tuning of -a, +a, -b, and +b With my very rough and brain-dead trials, something like `1.0 0.5 0.5` seems to sort well. I think right now `master` uses `1.0 1.5 1.5` and `new-histo` uses `1.0 5.0 1.0`. For all, I believe their `salience` calculations are slightly different, which may result in weights being incomparable at extreme colors. You can run the binary with `cargo run --bin salsort -- 0 0 0`, and use `--help` to see flags and the like. The interactive wizard should be somewhat self explanatory after playing with it. The only potentially confusing part is the `repeat offset ()` command. To run it, just press `Enter` and it will repeat the previous command (should apply the previous offset... but w/e will fix later). That's all for today. Tomorrow I'll probably work these final bits of polish for UX, rebase, then maybe merge. I have an idea of how I might work with Lab salience, but I want to finalize this for now before moving to that. Once this is done, I plan to have some friends do some trials to see what weights they seem to agree with. Likewise, you can also try to work out what weights your eyes agree with, and we can maybe find some average of what weights results in well-sorted attention.
usaradark force-pushed new-histo from 6676d4dd51
Some checks are pending
ci/woodpecker/pr/check Pipeline is pending approval
to dd324e2c01 2026年01月15日 02:01:06 +01:00
Compare
Author
Contributor
Copy link

Final thing I would probably want to do left is to be able to toggle which row gets printed on the table below the colors, as it can get bloated, especially when the user has many rows of colors. That, and allow going into settings during modification.

And then the experimental salience Jab... that's going to be interesting...

With the current salience calculations... or rather due to the innate nature of Jmh and the limiting factor of monitors and their colorspaces...
image
This image shows colors being sorted with colorfulness first, then lightness. On the right side, that brown with the 9 on top (index 19), that color has terrible contrast compared to its nearby colors of similar properties.

I believe this is because while the true Cam16 color sorts correctly, it cannot be displayed properly, hence a fallback color is displayed. Perhaps some better default values could be used for testing, to narrow the range of colors generated (i.e. colorfulness between 10-50). I don't know what would be a good range that mimics a real-life colors or for illustrations. Similar problem with lightness. I'll research into that later, or if you have suggestions for ranges I'm all ears.

For that table, I need to change it to deltas rather than raw values. At least have an optional row for it. Deltas against bg are much more useful for sorting rather than raw color values.

I also have not testing on Windows or other terminal emulators (I use foot), but at least it works on my end (heh).

With some more testing, weights that might be more stable are (1, 1, 0.2). ofc more experimentation is needed.

Final thing I would probably want to do left is to be able to toggle which row gets printed on the table below the colors, as it can get bloated, especially when the user has many rows of colors. That, and allow going into settings during modification. And then the experimental salience Jab... that's going to be interesting... With the current salience calculations... or rather due to the innate nature of Jmh and the limiting factor of monitors and their colorspaces... ![image](/attachments/e002c2e3-0207-4f15-8659-293148174256) This image shows colors being sorted with colorfulness first, then lightness. On the right side, that brown with the 9 on top (index 19), that color has terrible contrast compared to its nearby colors of similar properties. I believe this is because while the true Cam16 color sorts correctly, it cannot be displayed properly, hence a fallback color is displayed. Perhaps some better default values could be used for testing, to narrow the range of colors generated (i.e. colorfulness between 10-50). I don't know what would be a good range that mimics a real-life colors or for illustrations. Similar problem with lightness. I'll research into that later, or if you have suggestions for ranges I'm all ears. For that table, I need to change it to deltas rather than raw values. At least have an optional row for it. Deltas against bg are much more useful for sorting rather than raw color values. I also have not testing on Windows or other terminal emulators (I use `foot`), but at least it works on my end (heh). With some more testing, weights that might be more stable are `(1, 1, 0.2)`. ofc more experimentation is needed.

btw what's missing from this? I think the scripts are a good idea, to visualize better the results of some function calls, a much better alternative than raw println!s

btw what's missing from this? I think the scripts are a good idea, to visualize better the results of some function calls, a much better alternative than raw `println!`s
Author
Contributor
Copy link

Not much is missing, at least for what is core. If you think it's good enough to merge then it's good.

I think some things I wanted to do was to let the user (tester) decide how many colors to generate on the fly, but it's not core.

Not much is missing, at least for what is core. If you think it's good enough to merge then it's good. I think some things I wanted to do was to let the user (tester) decide how many colors to generate on the fly, but it's not core.

Yeah, it would be much cleaner to move all the debug printing into here. you could simply move it down by creating new methods on debug which only exist on the script itself. This way, while actually testsing wallust, the printing wont appear. If you want the printing, you could select one of the scripts, and so on. Ofc, your sample impl was going even a bit deeper than that

Yeah, it would be much cleaner to move all the debug printing into here. you could simply move it down by creating new methods on debug which only exist on the script itself. This way, while actually testsing wallust, the printing wont appear. If you want the printing, you could select one of the scripts, and so on. Ofc, your sample impl was going even a bit deeper than that
usaradark force-pushed new-histo from dd324e2c01 to f610f10a2f
Some checks failed
ci/woodpecker/pr/check Pipeline failed
2026年03月12日 19:23:21 +01:00
Compare
Author
Contributor
Copy link

Good enough to merge and start using it to finetune salience weighting and calculations.

Some more rough testing of weights find J=1.0 and M=0.35 to work quite well. However, the current salience calculations start to break down as J->0 and M->100. I speculate this is because these colors are unrealistic, or at the very least cannot be rendered on standard computer monitors. If you set the color to low J and high M, this website warns that it's outside of SRGB gamut, and is auto-corrected back to standard gamut.

I haven't messed with hue yet due to the biological factor of being sensitive to specific (wamer) colors. Salience-based Cam16Jab might solve this instead of using Cam16Jmh, as Cam16Jab uses components similar of the cones of the eye.

A better test would be to have wallust histogram colors from an image, and use that as a reference for sorting rather than generating a random set of colors. That way colors appropriately map to a real, renderable colors rather than something unrenderable. That said, this is still a step in the right direction.

Once this merges (or not), the next todo's could be...

  • continue to work with Cam16Jmh and determine best-effort weights for bucketing and sorting
  • experiment with Cam16Jab to try to account for biological salience
  • pull palettes generated from images to test component weights with rather than artificially generated colors
    • will require histogram bucketing to be functional
  • clean up, reorganize, and refactor my mess of a testing script, but not too important right now
Good enough to merge and start using it to finetune salience weighting and calculations. Some more rough testing of weights find J=1.0 and M=0.35 to work quite well. However, the current salience calculations start to break down as J->0 and M->100. I speculate this is because these colors are unrealistic, or at the very least cannot be rendered on standard computer monitors. If you set the color to low J and high M, this [website](https://apps.colorjs.io/picker/cam16-jmh) warns that it's outside of SRGB gamut, and is auto-corrected back to standard gamut. I haven't messed with hue yet due to the biological factor of being sensitive to specific (wamer) colors. Salience-based Cam16Jab might solve this instead of using Cam16Jmh, as Cam16Jab uses components similar of the cones of the eye. A better test would be to have wallust histogram colors from an image, and use that as a reference for sorting rather than generating a random set of colors. That way colors appropriately map to a real, renderable colors rather than something unrenderable. That said, this is still a step in the right direction. Once this merges (or not), the next todo's could be... - continue to work with Cam16Jmh and determine best-effort weights for bucketing and sorting - experiment with Cam16Jab to try to account for biological salience - pull palettes generated from images to test component weights with rather than artificially generated colors - will require histogram bucketing to be functional - clean up, reorganize, and refactor my mess of a testing script, but not too important right now
explosion-mental changed title from (削除) WIP: Refactor Cam16UcsJmh weights and set up trial testing to determine best salience sorting (削除ここまで) to Refactor Cam16UcsJmh weights and set up trial testing to determine best salience sorting 2026年03月20日 05:06:40 +01:00
Sign in to join this conversation.
No reviewers
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
2 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
explosion-mental/wallust!199
Reference in a new issue
explosion-mental/wallust
No description provided.
Delete branch "usaradark/wallust:new-histo"

Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?