This repository has been archived by the owner on Mar 25, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathsenseD3utils.js
228 lines (206 loc) · 9.62 KB
/
senseD3utils.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
var senseD3 = {
arcTween: function(d, x, y, radius, arc) {
var xd = d3.interpolate(x.domain(), [d.x, d.x + d.dx]),
yd = d3.interpolate(y.domain(), [d.y, 1]),
yr = d3.interpolate(y.range(), [d.y ? 20 : 0, radius]);
return function(d, i) {
return i ? function(t) {
return arc(d);
} : function(t) {
x.domain(xd(t));
y.domain(yd(t)).range(yr(t));
return arc(d);
};
};
},
computeTextRotation: function(d, x) {
return (x(d.x + d.dx / 2) - Math.PI / 2) / Math.PI * 180;
},
//create family is to be used for creating a tree type data structure which can be used in most D3 tree vizualizations.
//See more info about the tree layout here: https://github.com/mbostock/d3/wiki/Tree-Layout
// takes parameters for:
// dataset : qMatrix - actual data values
// numDims : int - number of dimensions used to create the chart
// familytype : string - nested (nested) or over multiple dimensions (multiDim)
// customColor : boolean - boolean if custom colors are included
createFamily: function(dataSet,numDims,familytype,customColor) {
var numDims;
if (arguments.length==1) {
familytype = "multiDim",
numDims = 2,
customColor=false;
} else if(arguments.length==2) {
familytype = "multiDim",
customColor=false;
} else if (arguments.length==3) {
customColor=false;
};
//create arrays of parents and children. this is so we can determine if there's any nodes without parents. these would be the top parents
var parentsA = [];
var kidsA = [];
//create array for data that will be added on each loop
var happyData = [];
//loop through each array in the dataset
for(s=0; s<dataSet.length; s++){
var d = dataSet[s];
//for each dim check if the record is a child or a parent and add to corresponding array
for(i=0; i<numDims-1; i++){
//set color dimension based on if color selection has been made
var color = customColor ? d[numDims].qAttrExps.qValues[0].qText : d[i].qElemNumber;
//check if the parent already exists, if it's new add the parent name and color to the parent array
if (parentsA.map(function (e) {return e.name}).indexOf(d[i].qText) === -1) {
var parentIter = {
name: d[i].qText,
color: color
};
parentsA.push(parentIter);
}
//if there is no text for the dimension you are evaluating, give it a value of root, otherwise use the text value
var parentVal = "";
if ((!(d[i].qText)) || (d[i].qText == "-") || (d[i].qText == "") || (d[i].qText) == " ") {
parentVal = "[root]";
} else {
parentVal = d[i].qText;
}
//if the kid doesn't exist, then add it to the array
if (kidsA.indexOf(d[i+1].qText) === -1) {
kidsA.push(d[i+1].qText);
}
//add each record to the happyData array
var newDataSet = {
name: d[i+1].qText,
parent: parentVal,
size: (d[numDims+1] || d[numDims]).qNum,
color: color,
leaf: (i+1) === (numDims-1) ? true : false
};
happyData.push(newDataSet);
}
}
//loop through the parent and child arrays and find the parents which aren't children. set those to have a parent of "[root]", indicating that they're the top parent
$.each(parentsA, function( index ) {
if (((kidsA.indexOf(this.name.toString()) === -1) && familytype == "nested") || familytype == "multiDim") {
var noParent = {
"name": this.name,
"color": this.color,
"parent": "[root]"
}
happyData.push(noParent);
}
});
//crawl through the data to create the family tree in JSON
function getChildren(name, familytype) {
if (familytype=="multiDim") {
var returnChildren = happyData.filter(function(d) {
return d.parent === name;
})
.map(function(d) {
var mapping;
if(d.leaf) {
mapping = {
name: d.name,
size: d.size,
color: d.color
};
}
else {
mapping = {
name: d.name,
size: d.size,
color: d.color,
children: getChildren(d.name, familytype)
};
}
return mapping;
});
} else{
var returnChildren = happyData.filter(function(d) {
return d.parent === name;
})
.map(function(d) {
return {
name: d.name,
size: d.size,
color: d.color,
children: getChildren(d.name, familytype)
};
});
};
return returnChildren;
}
var JSONtree = getChildren('[root]', familytype);
return JSONtree;
},
createJSONObj: function (layout, numOfDims) {
//check number of arguments passed- if nothing for number of dims, call it yourself
if (arguments.length<2) {
var numOfDims = this.findNumOfDims(layout);
}
//store raw dimensions and create variable for final labels
var rawDimLabels = layout.qHyperCube.qDimensionInfo,
rawMeasLabels = layout.qHyperCube.qMeasureInfo,
datapts = layout.qHyperCube.qDataPages[0].qMatrix
labels = [];
//loop through dimension and measure labels and add to array
for (var i = 0; i <= rawDimLabels.length - 1; i++) {
labels.push(rawDimLabels[i].qFallbackTitle);
};
for (var i = 0; i <= rawMeasLabels.length - 1; i++) {
labels.push(rawMeasLabels[i].qFallbackTitle);
};
var data = [];
for (var index = 0; index <= datapts.length - 1; index++) {
var tempDataArr ={};
for (var j = 0; j <= labels.length - 1; j++) {
// check if the iterator is less than the total number of the dimensions
if (j<numOfDims) {
//use standard dim number to store data
tempDataArr[ 'dim_' + j ] = datapts[index][j].qText;
//add id to object
tempDataArr[ 'dim_' + j + '_id' ] = datapts[index][j].qElemNumber;
//use variable names to store data
tempDataArr[ labels[j] ] = datapts[index][j].qText;
} else{
//use standard dim number to store data
tempDataArr['meas_' + (j-numOfDims) ] = isNaN(datapts[index][j].qNum) ? datapts[index][j].qText : datapts[index][j].qNum;
tempDataArr['meas_' + (j-numOfDims) + '_txt'] = datapts[index][j].qText;
//use variable names to store data
tempDataArr[labels[j]] = isNaN(datapts[index][j].qNum) ? datapts[index][j].qText : datapts[index][j].qNum;
tempDataArr[labels[j]+'_txt'] = datapts[index][j].qText;
//store attribute expressions
if (datapts[index][j].qAttrExps) {
for (var i = 0; i < datapts[index][j].qAttrExps.qValues.length; i++) {
let attrVal;
if (datapts[index][j].qAttrExps.qValues[i].qText) {
// get the value if it is a string
attrVal = datapts[index][j].qAttrExps.qValues[i].qText;
} else if (datapts[index][j].qAttrExps.qValues[i].qNum){
// pass the number and worry about the conversion of the code on the other side
attrVal = datapts[index][j].qAttrExps.qValues[i].qNum;
} else {
attrVal = '';
}
tempDataArr['meas_' + (j-numOfDims)+'_attr_' + i] = attrVal;
}
};
};
};
// console.log('tempDataArr',tempDataArr);
data.push(tempDataArr);
};
return data;
},
// Traverse the dataset to find the maximum value of a
// specified attribute from all of the nodes in the passed dataset
findMaxValue: function(attr, dataSet) {
var maxValue = 0;
dataSet.forEach(function(d) {
maxValue = (d[attr] > maxValue ? d[attr] : maxValue);
});
return maxValue;
},
findNumOfDims: function (layout) {
//return the number of dimensions
return layout.qHyperCube.qDimensionInfo.length;
}
};