metrics.js 3.7 KB

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