|
@@ -1,3 +1,5 @@
|
|
|
+// ---- Color Controls ----
|
|
|
+
|
|
|
const targetColor = U.obs();
|
|
|
const randomizeTargetColor = () => {
|
|
|
targetColor.value = d3
|
|
@@ -33,27 +35,29 @@ targetColor.subscribe((hex, { previous }) => {
|
|
|
|
|
|
randomizeTargetColor();
|
|
|
|
|
|
-const addMetricForm = (legendText, initialKind, initialMetric) => {
|
|
|
+// ---- Metric Controls ----
|
|
|
+
|
|
|
+const addMetricForm = (formName, legendText, initialKind, initialMetric) => {
|
|
|
const metricKind = U.obs(initialKind);
|
|
|
let metric;
|
|
|
|
|
|
U.template("metric-select-template", ({ form, legend }) => {
|
|
|
+ form.name = formName;
|
|
|
legend.innerText = legendText;
|
|
|
form.elements[initialKind].disabled = false;
|
|
|
- // form.elements.sortMetric = form.elements[initialKind].value = initialMetric;
|
|
|
+ form.elements[initialKind].value = initialMetric;
|
|
|
form.elements.metricKind.value = initialKind;
|
|
|
|
|
|
U.reactive(() => {
|
|
|
form.elements.whole.disabled = metricKind.value !== "whole";
|
|
|
form.elements.mean.disabled = metricKind.value !== "mean";
|
|
|
- form.elements.statistic.disabled = metricKind.value !== "statistic";
|
|
|
- // metric.value = form.elements[metricKindObs.value].value;
|
|
|
+ form.elements.stat.disabled = metricKind.value !== "stat";
|
|
|
});
|
|
|
|
|
|
const metrics = U.obs([
|
|
|
U.field(form.elements.whole),
|
|
|
U.field(form.elements.mean),
|
|
|
- U.field(form.elements.statistic),
|
|
|
+ U.field(form.elements.stat),
|
|
|
]);
|
|
|
|
|
|
U.form(form, {
|
|
@@ -65,8 +69,8 @@ const addMetricForm = (legendText, initialKind, initialMetric) => {
|
|
|
});
|
|
|
|
|
|
metric = U.obs(() => {
|
|
|
- const [whole, mean, statistic] = metrics.value;
|
|
|
- return { whole, mean, statistic }[metricKind.value];
|
|
|
+ const [whole, mean, stat] = metrics.value;
|
|
|
+ return { whole, mean, stat }[metricKind.value];
|
|
|
});
|
|
|
|
|
|
return "sidebar";
|
|
@@ -75,5 +79,95 @@ const addMetricForm = (legendText, initialKind, initialMetric) => {
|
|
|
return metric;
|
|
|
};
|
|
|
|
|
|
-const sortMetric = addMetricForm("Sort Metric", "whole", "alpha");
|
|
|
-const clusterMetric = addMetricForm("Cluster Metric", "statistic", "importance");
|
|
|
+const sortMetric = addMetricForm("sortMetric", "Sort Metric", "whole", "alpha");
|
|
|
+const clsMetric = addMetricForm("clsMetric", "Cluster Metric", "stat", "importance");
|
|
|
+
|
|
|
+// ---- Sorting Function Controls ----
|
|
|
+
|
|
|
+// terrible hack
|
|
|
+const getMetricSymbol = (metric) =>
|
|
|
+ document.querySelector(`option[value=${metric}]`).textContent.at(-2);
|
|
|
+const sortMetricSymbol = U.obs(() => getMetricSymbol(sortMetric.value));
|
|
|
+const clsMetricSymbol = U.obs(() => getMetricSymbol(clsMetric.value));
|
|
|
+
|
|
|
+const setupMinMaxWithLabel = (checkboxField, labelElem, maxLabel, minLabel) => {
|
|
|
+ const sortOrderToggle = U.field(checkboxField);
|
|
|
+ const sortOrder = U.obs(() => (sortOrderToggle.value ? maxLabel : minLabel));
|
|
|
+ U.reactive(() => {
|
|
|
+ labelElem.innerText = sortOrder.value;
|
|
|
+ });
|
|
|
+ return sortOrder;
|
|
|
+};
|
|
|
+
|
|
|
+U.template(
|
|
|
+ "function-template",
|
|
|
+ ({ form, minmaxLabel, metricSymbol, metricSymbolCls, clusterName, clusterNameInv }) => {
|
|
|
+ form.name = "sortFunction";
|
|
|
+
|
|
|
+ form.elements.useWholeImage.checked = true;
|
|
|
+ form.elements.totalSize.checked = true;
|
|
|
+ form.elements.useBestCluster.checked = true;
|
|
|
+ form.elements.invClusterSize.checked = true;
|
|
|
+
|
|
|
+ const sortOrder = setupMinMaxWithLabel(
|
|
|
+ form.elements.sortOrder,
|
|
|
+ minmaxLabel,
|
|
|
+ "max",
|
|
|
+ "min"
|
|
|
+ );
|
|
|
+
|
|
|
+ // TODO field controls for the rest of the toggles
|
|
|
+
|
|
|
+ U.reactive(() => {
|
|
|
+ metricSymbol.innerText = sortMetricSymbol.value;
|
|
|
+ metricSymbolCls.innerText = `${sortMetricSymbol.value}(B)`;
|
|
|
+ });
|
|
|
+
|
|
|
+ clusterName.innerText = clusterNameInv.innerText = "B";
|
|
|
+
|
|
|
+ U.form(form);
|
|
|
+
|
|
|
+ return "sidebar";
|
|
|
+ }
|
|
|
+);
|
|
|
+
|
|
|
+U.template(
|
|
|
+ "function-template",
|
|
|
+ ({
|
|
|
+ form,
|
|
|
+ minmaxLabel,
|
|
|
+ useWholeImageLabel,
|
|
|
+ metricSymbolCls,
|
|
|
+ clusterName,
|
|
|
+ clusterNameInv,
|
|
|
+ }) => {
|
|
|
+ form.name = "clusterFunction";
|
|
|
+
|
|
|
+ form.elements.sortOrder.checked = true;
|
|
|
+
|
|
|
+ const sortOrder = setupMinMaxWithLabel(
|
|
|
+ form.elements.sortOrder,
|
|
|
+ minmaxLabel,
|
|
|
+ "argmax",
|
|
|
+ "argmin"
|
|
|
+ );
|
|
|
+
|
|
|
+ // TODO field controls for the rest of the toggles
|
|
|
+
|
|
|
+ // not needed for cluster function
|
|
|
+ useWholeImageLabel.nextSibling.remove();
|
|
|
+ useWholeImageLabel.remove();
|
|
|
+ // and this can't be disabled so just replace the field with the span
|
|
|
+ metricSymbolCls.parentElement.replaceWith(metricSymbolCls);
|
|
|
+
|
|
|
+ U.reactive(() => {
|
|
|
+ metricSymbolCls.innerText = `${clsMetricSymbol.value}(K)`;
|
|
|
+ });
|
|
|
+
|
|
|
+ clusterName.innerText = clusterNameInv.innerText = "K";
|
|
|
+
|
|
|
+ U.form(form);
|
|
|
+
|
|
|
+ return "sidebar";
|
|
|
+ }
|
|
|
+);
|