Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions core/webapp/vis/demo/demo_script.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var CD4PointLayer = new LABKEY.vis.Layer({
});

var CD4PathLayer = new LABKEY.vis.Layer({
geom: new LABKEY.vis.Geom.Path({size: 3, opacity: .4}),
geom: new LABKEY.vis.Geom.Path({size: 3, opacity: 0.8}),
name: 'CD4+ (cells/mm3)',
aes: {
y: function(row){return row.study_LabResults_CD4.value}
Expand All @@ -31,7 +31,7 @@ var hemoglobinPointLayer = new LABKEY.vis.Layer({
});

var hemoglobinPathLayer = new LABKEY.vis.Layer({
geom: new LABKEY.vis.Geom.Path({opacity: .4}),
geom: new LABKEY.vis.Geom.Path({opacity: 0.8}),
name: 'Hemoglobin',
aes: {
yRight: function(row){return row.study_LabResults_Hemoglobin.value}
Expand Down Expand Up @@ -104,6 +104,7 @@ var coffeePathLayer = new LABKEY.vis.Layer({
geom: new LABKEY.vis.Geom.Path({}),
aes: {
pathColor: 'person',
lineType: 'person',
group: 'person'
}
});
Expand All @@ -126,7 +127,7 @@ var coffeePlot = new LABKEY.vis.Plot({
yLeft: 'efficiency'
},
legendData: [
{text: 'LabKey Dev 1', color: '#0000A0'},
{text: 'LabKey Dev 1', color: '#0000A0', lineType: 'dotted'},
{text: 'LabKey Dev 2', color: '#ADD8E6'},
{text: 'No Coffee Consumed', shape: LABKEY.vis.Scale.Shape()[0]},
{text: 'Coffee Consumed', shape: LABKEY.vis.Scale.Shape()[1]}
Expand All @@ -138,6 +139,12 @@ var coffeePlot = new LABKEY.vis.Plot({
return group == 'LabKey Dev 1 Efficiency' ? '#0000A0' : '#ADD8E6';
}
},
lineType: {
scaleType: 'discrete',
scale: function(group) {
return group == 'LabKey Dev 1 Efficiency' ? 'dotted' : undefined;
}
},
xTop: {
scaleType: 'discrete'
},
Expand Down
6 changes: 6 additions & 0 deletions core/webapp/vis/src/geom.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ LABKEY.vis.Geom.XY.prototype.initAesthetics = function(scales, layerAes, parentA
this.colorAes = layerAes.color ? layerAes.color : parentAes.color;
this.colorScale = scales.color ? scales.color : null;

this.lineTypeAes = layerAes.lineType ? layerAes.lineType : parentAes.lineType;
this.lineTypeScale = scales.lineType ? scales.lineType : null;

if(!this.yAes){
console.error('y aesthetic is required for ' + this.type + ' geom to render.');
return false;
Expand Down Expand Up @@ -238,6 +241,7 @@ LABKEY.vis.Geom.Bin.prototype.render = function(renderer, grid, scales, data, la
* @param {Number} [config.opacity] (Optional) Number between 0 and 1, used to determine the opacity of all paths.
* Useful if there are many overlapping paths. Defaults to 1.
* @param {boolean} [config.dashed] (Optional) True for dashed path, false for solid path. Defaults to false.
* @param {boolean} [config.dotted] (Optional) True for dotted path, false for solid path. Defaults to false.
*/
LABKEY.vis.Geom.Path = function(config){
this.type = "Path";
Expand All @@ -249,6 +253,7 @@ LABKEY.vis.Geom.Path = function(config){
this.size = ('size' in config && config.size != null && config.size != undefined) ? config.size : 3;
this.opacity = ('opacity' in config && config.opacity != null && config.opacity != undefined) ? config.opacity : 1;
this.dashed = ('dashed' in config && config.dashed != null && config.dashed != undefined) ? config.dashed : false;
this.dotted = ('dotted' in config && config.dotted != null && config.dotted != undefined) ? config.dotted : false;

this._dataspaceBoxPlot = ('dataspaceBoxPlot' in config && config.dataspaceBoxPlot != null && config.dataspaceBoxPlot != undefined) ? config.dataspaceBoxPlot : false;

Expand All @@ -264,6 +269,7 @@ LABKEY.vis.Geom.Path.prototype.render = function(renderer, grid, scales, data, l
this.sortFnAes = layerAes.sortFn ? layerAes.sortFn : parentAes.sortFn;
this.sizeAes = layerAes.size ? layerAes.size : parentAes.size;
this.pathColorAes = layerAes.pathColor ? layerAes.pathColor : parentAes.pathColor;
this.lineTypeAes = layerAes.lineType ? layerAes.lineType : parentAes.lineType;
this.sizeScale = scales.size;

this.hoverTextAes = layerAes.hoverText ? layerAes.hoverText : parentAes.hoverText;
Expand Down
21 changes: 19 additions & 2 deletions core/webapp/vis/src/internal/D3Renderer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2562,8 +2562,25 @@ LABKEY.vis.internal.D3Renderer = function(plot) {
pathSel.append('title').text(geom.hoverTextAes.getValue);
}

if (geom.dashed) {
layer.selectAll('path').style("stroke-dasharray", ("3, 3"));
// these are our default values that can be referenced by name (dashed, dotted) but we allow for custom
// dash arrays as well via lineTypeScale
const dashed = "6,6";
const dotted = "0.1,6";

if (geom.lineTypeAes && geom.lineTypeScale) {
pathSel.style("stroke-dasharray", function(d) {
const val = geom.lineTypeScale.scale(geom.lineTypeAes.getValue(d.data) + geom.layerName);
return val === 'dashed' ? dashed : val === 'dotted' ? dotted : val;
});
pathSel.style("stroke-linecap", function(d) {
const val = geom.lineTypeScale.scale(geom.lineTypeAes.getValue(d.data) + geom.layerName);
return val === 'dotted' ? "round" : null;
});
} else if (geom.dashed) {
layer.selectAll('path').style("stroke-dasharray", dashed);
} else if (geom.dotted) {
layer.selectAll('path').style("stroke-dasharray", dotted);
layer.selectAll('path').style("stroke-linecap", "round");
}

bindMouseEvents(pathSel, geom, layer);
Expand Down
2 changes: 1 addition & 1 deletion core/webapp/vis/src/scale.js
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ LABKEY.vis.Scale.ValueMapDiscrete = function(valueMap) {
// copied from d3.scale.ordinal
scale.range = function(_) {
if (!arguments.length) return range.slice();
range = Array.from(_);
range = _ ? Array.from(_) : [];
return scale;
};

Expand Down
11 changes: 10 additions & 1 deletion visualization/resources/web/vis/chartWizard/genericChartPanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -899,7 +899,8 @@ Ext4.define('LABKEY.ext4.GenericChartPanel', {
{
// If we're not in edit mode or if this is the first load we need to only load the minimum amount of data.
columns = [];
var measures = this.getChartConfig().measures;
var config = this.getChartConfig();
var measures = config.measures;

if (measures.x)
{
Expand Down Expand Up @@ -931,6 +932,10 @@ Ext4.define('LABKEY.ext4.GenericChartPanel', {
columns.push(this.autoColumnName.toString());
}

if (config.geomOptions.trendlineParameters) {
columns.push(config.geomOptions.trendlineParameters);
}

Ext4.each(['ySub', 'xSub', 'color', 'shape', 'series'], function(name) {
if (measures[name]) {
this.addMeasureForColumnQuery(columns, measures[name]);
Expand Down Expand Up @@ -1033,6 +1038,10 @@ Ext4.define('LABKEY.ext4.GenericChartPanel', {
if (this.savedReportInfo?.visualizationConfig?.chartConfig?.legendPos)
config.legendPos = this.savedReportInfo.visualizationConfig.chartConfig.legendPos;

// Apps can set series specific measuresOptions, so we use the measuresOptions if it's set on the original config
if (this.savedReportInfo?.visualizationConfig?.chartConfig?.measuresOptions)
config.measuresOptions = this.savedReportInfo.visualizationConfig.chartConfig.measuresOptions;

return config;
},

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1132,6 +1132,7 @@ LABKEY.vis.GenericChartHelper = new function(){
if (hasSeries) {
pathAes.pathColor = generateGroupingAcc(chartConfig.measures.series.name);
pathAes.group = generateGroupingAcc(chartConfig.measures.series.name);
pathAes.lineType = generateGroupingAcc(chartConfig.measures.series.name);
pathAes.hoverText = function (row) { return chartConfig.measures.series.label + ': ' + row.group };
}
// if no series measures but we have multiple y-measures, force the color and grouping to be distinct for each measure
Expand All @@ -1146,6 +1147,7 @@ LABKEY.vis.GenericChartHelper = new function(){
const layerAes = { x: 'x', y: 'y' };
if (hasSeries) {
layerAes.pathColor = function () { return trendline.name };
layerAes.lineType = function () { return trendline.name };
}

layerAes.hoverText = generateTrendlinePathHover(trendline);
Expand Down Expand Up @@ -1212,9 +1214,11 @@ LABKEY.vis.GenericChartHelper = new function(){
if (!LABKEY.Utils.isEmptyObj(chartConfig.measuresOptions?.series)) {
const colorValueMap = {};
const shapeValueMap = {};
const lineTypeValueMap = {};
Object.entries(chartConfig.measuresOptions.series).forEach(([key, val]) => {
if (val.color) colorValueMap[key] = val.color;
if (val.shape) shapeValueMap[key] = LABKEY.vis.Scale.ShapeMap[val.shape];
if (val.lineType) lineTypeValueMap[key] = val.lineType;
});

if (!LABKEY.Utils.isEmptyObj(colorValueMap)) {
Expand All @@ -1225,6 +1229,10 @@ LABKEY.vis.GenericChartHelper = new function(){
if (!scales.shape) scales.shape = { scaleType: 'discrete' };
scales.shape.scale = LABKEY.vis.Scale.ValueMapDiscrete(shapeValueMap);
}
if (!LABKEY.Utils.isEmptyObj(lineTypeValueMap)) {
if (!scales.lineType) scales.lineType = { scaleType: 'discrete' };
scales.lineType.scale = LABKEY.vis.Scale.ValueMapDiscrete(lineTypeValueMap);
}
}

if ((renderType === 'line_plot' || renderType === 'scatter_plot') && yMeasures.length > 0) {
Expand Down