metrics.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. const metrics = {
  2. sigma: { // RMS
  3. option: "RMS Deviation (σ)",
  4. displayName: String.raw`\sigma`,
  5. displayBody: p => String.raw`
  6. \sqrt{I\left(${p}\right) - 2\vec{q}\cdot\vec{\mu}\left(${p}\right) + \left|\left|\vec{q}\right|\right|^2}
  7. `,
  8. evaluate: (data, target) => Math.sqrt(data.inertia - 2 * vectorDot(data.mu.vector, target.vector) + target.sqMag),
  9. },
  10. bigTheta: { // mean of angle
  11. option: "Angular Difference (Θ)",
  12. displayName: String.raw`\Theta`,
  13. displayBody: p => String.raw`
  14. \cos^{-1}\left( \hat{q}\cdot\vec{\nu}\left(${p}\right) \right)
  15. `,
  16. evaluate: (data, target) => rad2deg * Math.acos(vectorDot(data.nu, target.unit)),
  17. },
  18. theta: { // angle of mean
  19. option: "Angular Difference (θ)",
  20. displayName: String.raw`\theta`,
  21. displayBody: p => String.raw`
  22. \cos^{-1}\left( \hat{q}\cdot\hat{\mu}\left(${p}\right) \right)
  23. `,
  24. evaluate: (data, target) => rad2deg * Math.acos(vectorDot(data.mu.unit, target.unit)),
  25. },
  26. phi: { // hue angle
  27. option: "Hue Difference (ϕ)",
  28. displayName: String.raw`\phi`,
  29. displayBody: (p, space) => String.raw`
  30. \angle \left(\text{oproj}_{\vec{${space === "jab" ? "J" : "L"}}}{\vec{q}}, \text{oproj}_{\vec{${space === "jab" ? "J" : "L"}}}{\vec{\mu}\left(${p}\right)} \right)
  31. `,
  32. evaluate: (data, target) => {
  33. const raw = Math.abs(data.mu.hue - target.hue);
  34. return Math.min(raw, 360 - raw);
  35. },
  36. },
  37. delta: { // euclidean
  38. option: "Euclidean Distance (δ)",
  39. displayName: String.raw`\delta`,
  40. displayBody: p => String.raw`
  41. \left|\left| \vec{q} - \vec{\mu}\left(${p}\right) \right|\right|
  42. `,
  43. evaluate: (data, target) => vectorMag(data.mu.vector.map((x, i) => x - target.vector[i])),
  44. },
  45. manhattan: { // manhattan distance
  46. option: "Manhattan Distance (M)",
  47. displayName: "M",
  48. displayBody: p => String.raw`
  49. \sum_{i} \left| \vec{\mu}\left(${p}\right)_i - \vec{q}_i \right|
  50. `,
  51. evaluate: (data, target) => data.mu.vector.map((x, i) => Math.abs(x - target.vector[i])).reduce((x, y) => x + y),
  52. },
  53. ch: { // chebyshev
  54. option: "Chebyshev Distance (Ч)",
  55. displayName: "Ч",
  56. displayBody: p => String.raw`
  57. \max_{i} \left| \vec{\mu}\left(${p}\right)_i - \vec{q}_i \right|
  58. `,
  59. evaluate: (data, target) => Math.max(...data.mu.vector.map((x, i) => Math.abs(x - target.vector[i]))),
  60. },
  61. lightnessDiff: {
  62. option: "Lightness Difference (ℓ)",
  63. displayName: String.raw`\ell`,
  64. displayBody: (p, space) => String.raw`
  65. \left| \text{comp}_{\vec{${space === "jab" ? "J" : "L"}}}{\vec{q}} - \text{comp}_{\vec{${space === "jab" ? "J" : "L"}}}{\vec{\mu}\left(${p}\right)} \right|
  66. `,
  67. evaluate: (data, target) => Math.abs(data.mu.lightness - target.lightness),
  68. },
  69. inertia: {
  70. option: "Inertia (I)",
  71. displayName: "I",
  72. displayBody: p => String.raw`
  73. \frac{1}{\left|${p}\right|} \sum_{p\in ${p}}{\left|\left|\vec{p}\right|\right|^2}
  74. `,
  75. evaluate: data => data.inertia,
  76. },
  77. lightness: {
  78. option: "Mean Lightness (ℒ)",
  79. displayName: String.raw`\mathcal{L}`,
  80. displayBody: (p, space) => String.raw`
  81. \text{comp}_{\vec{${space === "jab" ? "J" : "L"}}}{\vec{\mu}\left(${p}\right)}
  82. `,
  83. evaluate: data => data.mu.lightness,
  84. },
  85. muNuAngle: {
  86. option: "Mu-Nu Angle (V)",
  87. displayName: "V",
  88. displayBody: p => String.raw`\angle \left( \vec{\mu}\left(${p}\right), \vec{\nu}\left(${p}\right) \right)`,
  89. evaluate: data => data.muNuAngle,
  90. },
  91. size: {
  92. option: "Size (N)",
  93. displayName: "N",
  94. displayBody: p => String.raw`\left|${p}\right|`,
  95. evaluate: data => data.size,
  96. }
  97. };
  98. const applyMetrics = (data, target) => Object.fromEntries(
  99. Object.entries(metrics).map(([name, metric]) => [name, metric.evaluate(data, target)])
  100. );