ak_vis/color_palette/
jmol.rs

1use crate::{AtomMaterial, ColorPalette, DEFAULT_ATOM_MATERIAL};
2use bevy::color::Color;
3use std::sync::LazyLock;
4
5const METAL_MATERIAL: AtomMaterial = AtomMaterial::new(0.5, 0.2);
6
7pub const JMOL: ColorPalette = {
8    let mut colors = [None; 110];
9    let materials = [None; 110];
10    colors[1] = Some(Color::srgb_u8(255, 255, 255));
11    colors[2] = Some(Color::srgb_u8(217, 255, 255));
12    colors[3] = Some(Color::srgb_u8(204, 128, 255));
13    colors[4] = Some(Color::srgb_u8(194, 255, 0));
14    colors[5] = Some(Color::srgb_u8(255, 181, 181));
15    colors[6] = Some(Color::srgb_u8(144, 144, 144));
16    colors[7] = Some(Color::srgb_u8(48, 80, 248));
17    colors[8] = Some(Color::srgb_u8(255, 13, 13));
18    colors[9] = Some(Color::srgb_u8(144, 224, 80));
19    colors[10] = Some(Color::srgb_u8(179, 227, 245));
20    colors[11] = Some(Color::srgb_u8(171, 92, 242));
21    colors[12] = Some(Color::srgb_u8(138, 255, 0));
22    colors[13] = Some(Color::srgb_u8(191, 166, 166));
23    colors[14] = Some(Color::srgb_u8(240, 200, 160));
24    colors[15] = Some(Color::srgb_u8(255, 128, 0));
25    colors[16] = Some(Color::srgb_u8(255, 255, 48));
26    colors[17] = Some(Color::srgb_u8(31, 240, 31));
27    colors[18] = Some(Color::srgb_u8(128, 209, 227));
28    colors[19] = Some(Color::srgb_u8(143, 64, 212));
29    colors[20] = Some(Color::srgb_u8(61, 255, 0));
30    colors[21] = Some(Color::srgb_u8(230, 230, 230));
31    colors[22] = Some(Color::srgb_u8(191, 194, 199));
32    colors[23] = Some(Color::srgb_u8(166, 166, 171));
33    colors[24] = Some(Color::srgb_u8(138, 153, 199));
34    colors[25] = Some(Color::srgb_u8(156, 122, 199));
35    colors[26] = Some(Color::srgb_u8(224, 102, 51));
36    colors[27] = Some(Color::srgb_u8(240, 144, 160));
37    colors[28] = Some(Color::srgb_u8(80, 208, 80));
38    colors[29] = Some(Color::srgb_u8(200, 128, 51));
39    colors[30] = Some(Color::srgb_u8(125, 128, 176));
40    colors[31] = Some(Color::srgb_u8(194, 143, 143));
41    colors[32] = Some(Color::srgb_u8(102, 143, 143));
42    colors[33] = Some(Color::srgb_u8(189, 128, 227));
43    colors[34] = Some(Color::srgb_u8(255, 161, 0));
44    colors[35] = Some(Color::srgb_u8(166, 41, 41));
45    colors[36] = Some(Color::srgb_u8(92, 184, 209));
46    colors[37] = Some(Color::srgb_u8(112, 46, 176));
47    colors[38] = Some(Color::srgb_u8(0, 255, 0));
48    colors[39] = Some(Color::srgb_u8(148, 255, 255));
49    colors[40] = Some(Color::srgb_u8(148, 224, 224));
50    colors[41] = Some(Color::srgb_u8(115, 194, 201));
51    colors[42] = Some(Color::srgb_u8(84, 181, 181));
52    colors[43] = Some(Color::srgb_u8(59, 158, 158));
53    colors[44] = Some(Color::srgb_u8(36, 143, 143));
54    colors[45] = Some(Color::srgb_u8(10, 125, 140));
55    colors[46] = Some(Color::srgb_u8(0, 105, 133));
56    colors[47] = Some(Color::srgb_u8(192, 192, 192));
57    colors[48] = Some(Color::srgb_u8(255, 217, 143));
58    colors[49] = Some(Color::srgb_u8(166, 117, 115));
59    colors[50] = Some(Color::srgb_u8(102, 128, 128));
60    colors[51] = Some(Color::srgb_u8(158, 99, 181));
61    colors[52] = Some(Color::srgb_u8(212, 122, 0));
62    colors[53] = Some(Color::srgb_u8(148, 0, 148));
63    colors[54] = Some(Color::srgb_u8(66, 158, 176));
64    colors[55] = Some(Color::srgb_u8(87, 23, 143));
65    colors[56] = Some(Color::srgb_u8(0, 201, 0));
66    colors[57] = Some(Color::srgb_u8(112, 212, 255));
67    colors[58] = Some(Color::srgb_u8(255, 255, 199));
68    colors[59] = Some(Color::srgb_u8(217, 255, 199));
69    colors[60] = Some(Color::srgb_u8(199, 255, 199));
70    colors[61] = Some(Color::srgb_u8(163, 255, 199));
71    colors[62] = Some(Color::srgb_u8(143, 255, 199));
72    colors[63] = Some(Color::srgb_u8(97, 255, 199));
73    colors[64] = Some(Color::srgb_u8(69, 255, 199));
74    colors[65] = Some(Color::srgb_u8(48, 255, 199));
75    colors[66] = Some(Color::srgb_u8(31, 255, 199));
76    colors[67] = Some(Color::srgb_u8(0, 255, 156));
77    colors[68] = Some(Color::srgb_u8(0, 230, 117));
78    colors[69] = Some(Color::srgb_u8(0, 212, 82));
79    colors[70] = Some(Color::srgb_u8(0, 191, 56));
80    colors[71] = Some(Color::srgb_u8(0, 171, 36));
81    colors[72] = Some(Color::srgb_u8(77, 194, 255));
82    colors[73] = Some(Color::srgb_u8(77, 166, 255));
83    colors[74] = Some(Color::srgb_u8(33, 148, 214));
84    colors[75] = Some(Color::srgb_u8(38, 125, 171));
85    colors[76] = Some(Color::srgb_u8(38, 102, 150));
86    colors[77] = Some(Color::srgb_u8(23, 84, 135));
87    colors[78] = Some(Color::srgb_u8(208, 208, 224));
88    colors[79] = Some(Color::srgb_u8(255, 209, 35));
89    colors[80] = Some(Color::srgb_u8(184, 184, 208));
90    colors[81] = Some(Color::srgb_u8(166, 84, 77));
91    colors[82] = Some(Color::srgb_u8(87, 89, 97));
92    colors[83] = Some(Color::srgb_u8(158, 79, 181));
93    colors[84] = Some(Color::srgb_u8(171, 92, 0));
94    colors[85] = Some(Color::srgb_u8(117, 79, 69));
95    colors[86] = Some(Color::srgb_u8(66, 130, 150));
96    colors[87] = Some(Color::srgb_u8(66, 0, 102));
97    colors[88] = Some(Color::srgb_u8(0, 125, 0));
98    colors[89] = Some(Color::srgb_u8(112, 171, 250));
99    colors[90] = Some(Color::srgb_u8(0, 186, 255));
100    colors[91] = Some(Color::srgb_u8(0, 161, 255));
101    colors[92] = Some(Color::srgb_u8(0, 143, 255));
102    colors[93] = Some(Color::srgb_u8(0, 128, 255));
103    colors[94] = Some(Color::srgb_u8(0, 107, 255));
104    colors[95] = Some(Color::srgb_u8(84, 92, 242));
105    colors[96] = Some(Color::srgb_u8(120, 92, 227));
106    colors[97] = Some(Color::srgb_u8(138, 79, 227));
107    colors[98] = Some(Color::srgb_u8(161, 54, 212));
108    colors[99] = Some(Color::srgb_u8(179, 31, 212));
109    colors[100] = Some(Color::srgb_u8(179, 31, 186));
110    colors[101] = Some(Color::srgb_u8(179, 13, 166));
111    colors[102] = Some(Color::srgb_u8(189, 13, 135));
112    colors[103] = Some(Color::srgb_u8(199, 0, 102));
113    colors[104] = Some(Color::srgb_u8(204, 0, 89));
114    colors[105] = Some(Color::srgb_u8(209, 0, 79));
115    colors[106] = Some(Color::srgb_u8(217, 0, 69));
116    colors[107] = Some(Color::srgb_u8(224, 0, 56));
117    colors[108] = Some(Color::srgb_u8(230, 0, 46));
118    colors[109] = Some(Color::srgb_u8(235, 0, 38));
119
120    let fallback = Color::srgb_u8(255, 255, 255);
121    let fallback_material = DEFAULT_ATOM_MATERIAL;
122
123    ColorPalette {
124        colors,
125        materials,
126        fallback,
127        fallback_material,
128    }
129};
130
131pub static JMOL_METALLIC: LazyLock<ColorPalette> = LazyLock::new(|| {
132    let mut materials = [None; 110];
133
134    for atomic_number in [
135        3_u8, 4, 11, 12, 13, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 37, 38, 39, 40,
136        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
137        68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 87, 88, 89, 90, 91, 92, 93,
138        94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
139    ] {
140        materials[atomic_number as usize] = Some(METAL_MATERIAL);
141    }
142
143    ColorPalette {
144        colors: JMOL.colors,
145        materials,
146        fallback: JMOL.fallback,
147        fallback_material: JMOL.fallback_material,
148    }
149});
150
151#[cfg(test)]
152mod tests {
153    use super::{JMOL, JMOL_METALLIC};
154    use crate::AtomMaterial;
155    use ak_core::geometry::AtomicNumber;
156
157    #[test]
158    fn default_jmol_palette_uses_default_atom_material() {
159        let iron = AtomicNumber::new(26).unwrap();
160
161        assert_eq!(JMOL.material(iron), AtomMaterial::default());
162    }
163
164    #[test]
165    fn metallic_jmol_palette_marks_metals_without_affecting_nonmetals() {
166        let gold = AtomicNumber::new(79).unwrap();
167        let oxygen = AtomicNumber::new(8).unwrap();
168
169        assert!((JMOL_METALLIC.material(gold).metallic - 0.5).abs() < 1e-6);
170        assert_eq!(JMOL_METALLIC.material(oxygen), AtomMaterial::default());
171    }
172}