From 7c7f58e02067d9098107bcb6e7786ce367917a98 Mon Sep 17 00:00:00 2001 From: Sergei Date: Tue, 7 Jan 2025 13:37:53 -0500 Subject: [PATCH] Fixes pertaining to https://github.com/veg/hivtrace-secure/issues/366 --- src/clusternetwork.js | 38 ++++++++++++---------- src/hiv_tx_network.js | 75 ++++++++++++++++++++++++++++++------------- src/misc.js | 36 +++++++++++++++++++++ 3 files changed, 110 insertions(+), 39 deletions(-) diff --git a/src/clusternetwork.js b/src/clusternetwork.js index 32d7d0b..396798d 100755 --- a/src/clusternetwork.js +++ b/src/clusternetwork.js @@ -2814,20 +2814,20 @@ var hivtrace_cluster_network_graph = function ( _.each(list, self._aux_process_category_values); }); - const colorStopsPath = [ + /*const colorStopsPath = [ kGlobals.network.GraphAttrbuteID, self.colorizer["category_id"], "color_stops", - ]; - - const color_stops = _.get( - graph_data, - colorStopsPath, - kGlobals.network.ContinuousColorStops - ); + ];*/ var valid_scales = _.filter( _.map(graph_data[kGlobals.network.GraphAttrbuteID], (d, k) => { + let color_stops = _.get( + self.json, + [kGlobals.network.GraphAttrbuteID, k, "color_stops"], + kGlobals.network.ContinuousColorStops + ); + function determine_scaling(d, values, scales) { var low_var = Infinity; _.each(scales, (scl, i) => { @@ -2862,16 +2862,20 @@ var hivtrace_cluster_network_graph = function ( ); // automatically determine the scale and see what spaces the values most evenly const range = d3.extent(values); + const scales_to_consider = [d3.scale.linear()]; - if (range[0] > 0) { - scales_to_consider.push(d3.scale.log()); - } - if (range[0] >= 0) { - scales_to_consider.push(d3.scale.pow().exponent(1 / 3)); - scales_to_consider.push(d3.scale.pow().exponent(1 / 4)); - scales_to_consider.push(d3.scale.pow().exponent(1 / 2)); - scales_to_consider.push(d3.scale.pow().exponent(1 / 8)); - scales_to_consider.push(d3.scale.pow().exponent(1 / 16)); + + if (!d.is_integer) { + if (range[0] > 0) { + scales_to_consider.push(d3.scale.log()); + } + if (range[0] >= 0) { + scales_to_consider.push(d3.scale.pow().exponent(1 / 3)); + scales_to_consider.push(d3.scale.pow().exponent(1 / 4)); + scales_to_consider.push(d3.scale.pow().exponent(1 / 2)); + scales_to_consider.push(d3.scale.pow().exponent(1 / 8)); + scales_to_consider.push(d3.scale.pow().exponent(1 / 16)); + } } determine_scaling(d, values, scales_to_consider); } else if (d.type === "Date") { diff --git a/src/hiv_tx_network.js b/src/hiv_tx_network.js index 42c26ae..0ded8af 100755 --- a/src/hiv_tx_network.js +++ b/src/hiv_tx_network.js @@ -849,7 +849,7 @@ class HIVTxNetwork { */ - attribute_node_value_by_id(d, id, number) { + attribute_node_value_by_id(d, id, number, is_date) { try { if (kGlobals.network.NodeAttributeID in d && id) { if (id in d[kGlobals.network.NodeAttributeID]) { @@ -867,6 +867,8 @@ class HIVTxNetwork { } else if (number) { v = Number(v); return _.isNaN(v) ? kGlobals.missing.label : v; + } else if (date) { + return v.getTime(); } } return v; @@ -1764,8 +1766,8 @@ class HIVTxNetwork { }); const pg_enum = [ - "Yes (dx≤12 months)", - "Yes (1236 months)", "No", ]; @@ -2117,10 +2119,6 @@ class HIVTxNetwork { _.has(this.json[kGlobals.network.GraphAttrbuteID], d) ) ) { - var extension = {}; - extension[key] = computed; - - _.extend(this.json[kGlobals.network.GraphAttrbuteID], extension); this.inject_attribute_description(key, computed); _.each(this.json.Nodes, (node) => { HIVTxNetwork.inject_attribute_node_value_by_id( @@ -2135,15 +2133,48 @@ class HIVTxNetwork { this.uniqValues[key] = computed.enum; } else { var uniq_value_set = new Set(); - _.each(this.json.Nodes, (n) => - uniq_value_set.add( - this.attribute_node_value_by_id(n, key, computed.Type === "Number") - ) - ); + + if (computed.type === "Date") { + _.each(this.json.Nodes, (n) => + uniq_value_set.add( + this.attribute_node_value_by_id(n, key).getTime() + ) + ); + } else { + _.each(this.json.Nodes, (n) => + uniq_value_set.add( + this.attribute_node_value_by_id( + n, + key, + computed.type === "Number" + ) + ) + ); + } + this.uniqValues[key] = [...uniq_value_set]; + if (computed.type === "Number" || computed.type == "Date") { + var color_stops = + computed["color_stops"] || kGlobals.network.ContinuousColorStops; + + if (color_stops > this.uniqValues[key].length) { + computed["color_stops"] = this.uniqValues[key].length; + } + + if (computed.type === "Number") { + computed.is_integer = _.every(this.uniqValues[key], (d) => + Number.isInteger(d) + ); + } + } } this.uniqs[key] = this.uniqValues[key].length; + var extension = {}; + extension[key] = computed; + + _.extend(this.json[kGlobals.network.GraphAttrbuteID], extension); + if (computed["overwrites"]) { if ( _.has( @@ -2196,13 +2227,13 @@ class HIVTxNetwork { const subcluster_enum = [ "No, dx>36 months", // 0 - "No, but dx≤12 months", - "Yes (dx≤12 months)", - "Yes (12 { try { var value = this.parse_dates( @@ -2526,7 +2557,7 @@ class HIVTxNetwork { depends: ["age_dx"], overwrites: "age_dx", label: "Age at Diagnosis", - enum: ["<13", "13-19", "20-29", "30-39", "40-49", "50-59", "≥60"], + enum: ["<13", "13-19", "20-29", "30-39", "40-49", "50-59", "�60"], type: "String", color_scale: function () { return d3.scale @@ -2538,7 +2569,7 @@ class HIVTxNetwork { "30-39", "40-49", "50-59", - "≥60", + "�60", kGlobals.missing.label, ]) .range([ @@ -2555,13 +2586,13 @@ class HIVTxNetwork { map: (node) => { var vl_value = this.attribute_node_value_by_id(node, "age_dx"); if (vl_value === ">=60") { - return "≥60"; + return "�60"; } if (vl_value === "\ufffd60") { - return "≥60"; + return "�60"; } if (Number(vl_value) >= 60) { - return "≥60"; + return "�60"; } return vl_value; }, diff --git a/src/misc.js b/src/misc.js index 1c8d619..c178388 100644 --- a/src/misc.js +++ b/src/misc.js @@ -12,6 +12,42 @@ _.each(_.range(3, 20), (d) => { ]); }); +var hivtrace_generate_svg_ellipse = function () { + var self = this; + + self.ellipse = function () { + var path = + "M " + + self.radius + + " 0 A " + + self.radius * 1 + + " " + + self.radius * 0.75 + + " 0 1 0 " + + self.radius + + " 0.00001"; + return path; + }; + + self.ellipse.type = function () { + return self.ellipse; + }; + + self.ellipse.size = function (attr) { + if (_.isNumber(attr)) { + self.size = attr; + self.radius = Math.sqrt((1.25 * attr) / Math.PI); + return self.ellipse; + } + + return self.size; + }; + + self.ellipse.size(64); + + return self.ellipse; +}; + /** * Creates and returns an SVG polygon generator. *