Black Lives Matter. Please consider donating to Black Girls Code today.
Dash HoloViews is now available! Check out the docs.

The lines overlap in scatter plot(time series)

Hello all, I have the below problem can anyone help me with this please.

(Plotly.JS) I have created a time series scatter plot with markers , lines and text. The issue I am facing is I have multiple nodes which is connected to other nodes with trace lines.The lines drawn or trace lines drawn are overlapping each which makes it hard to find to which nodes the trace lines are connected to.
I am attaching the code which I have used .
The plotly graph:

The above part is the code for trace lines.

The below is the code used to draw plotlyJSscatter plot (time series)

I’m not 100% sure I understand what you’re asking. The nodes you’re talking about, those come from the scatter trace? Or from the all_shapes array of shapes? Pasting a fully reproducible example would help.

I suspect two things:

  • Plotly.addTraces will indeed add traces on top of existing traces. You might want to use its 3rd argument to place the new traces at the beginning of the data array e.g. Plotly.addTraces(graphDiv, {y: [1, 5, 7]}, 0); as shows here

  • Layout shapes are drawn above data traces by default. You can try setting layer: 'below' as described here to drawn them below the traces.





I have attached the code which explains more about data used.

My major concern is I am drawing Trace lines connecting markers /nodes . Is there any way I could avoid lines overlapping ? The spline would also not work here and it would almost be like linear line .

Wow. I hope you’re not expecting anyone to copy the code from your screenshot. Pro tip: pasting your code as plain text makes things easier.

Thank you very much for the help.Please find the code part below.

var temp_y1 = ‘’;
var start_date = timeforxaxisrange.sort()[0];
var date = new Date(start_date);
milliseconds_start_date = (date.getTime());

				 var end_date = timeforxaxisrange.sort()[timeforxaxisrange.length-1]; 
				 var date1 = new Date(end_date);
				 milliseconds_end_date = (date1.getTime()); 
					
				 testing_milliseconds=((milliseconds_end_date-milliseconds_start_date)/(24*60*60*1000));
				 
				 var uniqueAuthors = [];
				 
				 $.each(realdataauthor_left, function(i, el){
				     if($.inArray(el, uniqueAuthors) === -1) uniqueAuthors.push(el);
				 });
				 for(var i=0; i<uniqueAuthors.length;i++){
					 var y0 = +realdataauthor_left.indexOf(uniqueAuthors[i])-0.5;
					 range_yaxis2.push(realdataauthor_left.indexOf(uniqueAuthors[i]));
					 var y1 = +realdataauthor_left.indexOf(uniqueAuthors[i+1])-0.5;
					 temp_y1 = +realdataauthor_left.indexOf(uniqueAuthors[i+1]);
					 if(y1==-1.5){
						 y1=realdataauthor_left.length;
					 }
					 if(temp_y1==-1){
						 temp_y1 = +realdataauthor_left.length;
					 }
					 range_yaxis2.push(temp_y1);
					 
					 if(i % 5 == 0){
						 stripeColor = stripes_colors[0];
					 }
					 else if(i % 5 == 1){
						 stripeColor = stripes_colors[1];
					 }
					 else if(i % 5 == 2){
						 stripeColor = stripes_colors[2];
					 }
					 else if(i % 5 == 3){
						 stripeColor = stripes_colors[3];
					 }
					 else
					 {
						 stripeColor = stripes_colors[4];
					 }
					 var final_milliseconds_start_date;
					 var final_milliseconds_end_date;
					 
					 
					 
					 if(testing_milliseconds<5){
						 final_milliseconds_start_date = milliseconds_start_date-(0.75*24*60*60*1000);
						 final_milliseconds_end_date = milliseconds_end_date+(1*24*60*60*1000);
					 }
					 else if(testing_milliseconds>=5 || testing_milliseconds<20){
						 final_milliseconds_start_date = milliseconds_start_date-(5*24*60*60*1000);
						 final_milliseconds_end_date = milliseconds_end_date+(2*24*60*60*1000);
					 }
					 else if(testing_milliseconds>=20 || testing_milliseconds<50){
						 final_milliseconds_start_date = milliseconds_start_date-(7*24*60*60*1000);
						 final_milliseconds_end_date = milliseconds_end_date+(3*24*60*60*1000);
					 }
					 else if(testing_milliseconds>=50 || testing_milliseconds<100){
						 final_milliseconds_start_date = milliseconds_start_date-(7*24*60*60*1000);
						 final_milliseconds_end_date = milliseconds_end_date+(4*24*60*60*1000);
					 }
					 else if(testing_milliseconds>=100){
						 final_milliseconds_start_date = milliseconds_start_date-(7*24*60*60*1000);
						 final_milliseconds_end_date = milliseconds_end_date+(4.5*24*60*60*1000);
					 }
					 
					 var shape = "shape"+""+i;
					 shape = {
						type: 'rect',
					    xref: 'x',
					    yref: 'y',
					    x0: final_milliseconds_start_date,
					    x1: final_milliseconds_end_date,
					    y0: y0,
					    y1: y1,
					    fillcolor: stripeColor,
					    opacity: 0.2,
					    line: {
					    	color: "brown",
					    	width: 1
					        }
					    }
					 all_shapes.push(shape);
					 
					 
					 var trace_milliseconds_end_date;
					 trace_milliseconds_end_date = milliseconds_end_date+(2.5*24*60*60*1000);
					 if(testing_milliseconds<5){
						 trace_milliseconds_end_date = milliseconds_end_date+(1*24*60*60*1000);
					 }
					 
					 var trace = "trace"+""+i;
					 trace = {
							 x: [trace_milliseconds_end_date, trace_milliseconds_end_date],
							 y: [(y0+y1)/2,y1],
							 text: [uniqueAuthors[i]], 
							 type : 'line',
							 mode: 'text',
							 textposition:'right', 
							 hoverinfo: "text",
							 textfont: {
								    color: 'rgb(148, 103, 189)',
								    size: 12										          
								 },
					         opacity:0.1
					    }
					 all_yaxis2_traces.push(trace); 
				 }
				 var data = [];
				 
				 
				
				 if(note_view_length>0){
						var trace_left = {
								x : realdatatime_left,
								y : realdataweight_left,
								text : realdatatitle_left,
								mode : 'markers+text',
								type : 'scatter',
								textposition : 'left',
								marker : {
									size : 13,
									color : 'blue',
									opacity:0.6
									
								},
								hoverinfo: 'x+text'
							};
						var trace_author_right = {
								  x: realdatatime_left,
								  y: realdataauthor_left,
								  mode : 'none',
								  yaxis: 'y2',
								  type: 'scatter'
								};
						
						var trace_right = {
							x : realdatatime_left1,
							y : realdataweight_left1,
							mode : 'markers+text',
							type : 'scatter',
							textposition : 'left',
							marker : {
								size : 15,
								color : 'red'
							},
						hoverinfo: 'none'
						};
						var tempdata = [trace_left, trace_right]
						data=tempdata.concat(all_yaxis2_traces);
					 }
					 else{
						 var trace_left = {
									x : realdatatime_left,
									y : realdataweight_left,
									text : realdatatitle_left,
									mode : 'markers+text',
									type : 'scatter',
									textposition : 'left',
									marker : {
										size : 14,
										color : 'blue',
										opacity:0.6
									},
									hoverinfo: 'x+text'
								};
						 var trace_author_right = {
								  x: realdatatime_left,
								  y: realdataauthor_left,
								  mode : 'none',
								  yaxis: 'y2',
								  type: 'scatter'
								};
						 var tempdata = [trace_left];
						 
					 }
					 
				 thread_title = "This thread includes " + realdataweight_left.length +" note(s) by "+ uniqueAuthors.length+" author(s).";
					 
				 var highlightdata = {
							"database" :localdb ,
							"token" : token,
							"threadid" : threadid
						}
						$.ajax({
							url : "/WSG/highlight/get/byauthor/bythread",
							type : "POST",
							data : JSON.stringify(highlightdata),
							dataType : "json",
							success : function(data) {
								if(data.code=="success"){
									var json_highlighted = $.parseJSON(data.obj);
									
									for(var m=0;m<json_highlighted.length;m++){
										var x0=json_highlighted[m].create_time;
										var date_x0 = new Date(x0);
										realdatacreatedtime_highlighted.push(date_x0);
										
										var temp_index = realdatanoteid.indexOf(json_highlighted[m].note_id);
										highlighted_note_weighted_position.push(temp_index);
										}
										 
										 var notes_highlighted_trace = {
												 	x : realdatacreatedtime_highlighted,
													y : highlighted_note_weighted_position,
													mode : 'markers',
													type : 'scatter',
													marker : {
														size : 13,
														color : 'red'
													},
												hoverinfo: 'none'
										 }
										all_yaxis2_traces.push(notes_highlighted_trace)
									
								}
								
								var selectorOptions = {
									    buttons: [{
									    	
									        step: 'month',
									        stepmode: 'backward',
									        count: 1,
									        label: '1 month'
									    }, 
									    {
									        step: 'month',
									        stepmode: 'backward',
									        count: 2,
									        label: '2 months'
									    },{
									        step: 'month',
									        stepmode: 'backward',
									        count: 3,
									        label: '3 months'
									    },
									    {
									        step: 'month',
									        stepmode: 'backward',
									        count: 4,
									        label: '4 months'
									    },
									    {
									        step: 'month',
									        stepmode: 'backward',
									        count: 5,
									        label: '5 months'
									    },{
									        step: 'month',
									        stepmode: 'backward',
									        count: 6,
									        label: '6 months'
									    }, {
									        step: 'year',
									        stepmode: 'todate',
									        count: 1,
									        label: 'Year to date'
									    }, {
									        step: 'year',
									        stepmode: 'backward',
									        count: 1,
									        label: '1 year'
									    }, {
									        step: 'all',
									    }],
									};
								
								data=tempdata.concat(all_yaxis2_traces);
								Plotly.newPlot(TESTER, data, {
									title: thread_title,
									shapes:  all_shapes,
									layer:'below',
								    
									xaxis:{
										showgrid: true,
										side: 'top',
										zeroline : true,
										zerolinecolor: 'rgb(148, 103, 189)',
										showline : true,
										tick0: 0,
										tickfont : {
											color : 'rgb(148, 103, 189)',
											size : 18
										},
										rangeselector: selectorOptions,
										
									    
									},
									yaxis : {
										showgrid: false,
										autorange : false,
										zeroline : false,
										showline : false,
										autotick : true,
										showticklabels : false,
										range: [-0.5, realdataweight_left.length],
										
									},
									
									
									hovermode : 'closest',
									showlegend : false
									}, 
									
									{
									showLink : false,
									displayModeBar :false,
									scrollZoom: true
									
								}
								
								
								);
								

								
								
						
								var dragLayer = document.getElementsByClassName('nsewdrag')[0];
								
								TESTER.on('plotly_hover', function(data){
									dragLayer.style.cursor = 'pointer'
									var marker_y = data.points[0].y;
									if(buildonallids.indexOf(realdatanoteid[marker_y])!==-1){
										
										var traceIndices = [];
										
										for(var i = 0; i < TESTER.data.length; i++) {
										   if(i !== data.points[0].curveNumber && data.points["0"].data.type=="line") {
										    traceIndices.push(i);
										    
										  }
										}
										Plotly.restyle(TESTER, 'opacity', 0.1, traceIndices);
									}
							})
								
								TESTER.on('plotly_unhover', function(data){
									dragLayer.style.cursor = ''
										var update = {
										    opacity: 1
										};
									Plotly.restyle(TESTER,update);
									
								})
								
								show_buildon();
								$("#showbuildon").addClass('showed');
								$("#showbuildon").attr('checked',true);

The Above is the code part I have used to plot scatter plot.

The code below is shown which I am using to draw trace lines connected to nodes/markers.

function show_buildon(){
.ajax({ url : "/WSG/buildon/get/bythread", type : "POST", data : JSON.stringify(projectdata), dataType : "json", success : function(data) { var json = .parseJSON(data.obj);
var final_buildon_trace = [];
if(json!=null){
for (var i = 0; i < json.length; i++) {

				var from_id = 0;
				var to_id = 0;
				
				for (var j = 0; j <= realdatanoteid.length; j++) {
					if (json[i].from_note_id == realdatanoteid[j])
						from_id = j
					if (json[i].to_note_id == realdatanoteid[j])
						to_id = j
				}
				
				var realdatatitle_to = '<--'+ realdatatitle_left[from_id];	
				buildonallids.push(realdatanoteid[from_id]);
				buildonallids.push(realdatanoteid[to_id]);
				buildonfromtoid.push(realdatanoteid[from_id]+"@#$"+realdatanoteid[to_id]);
				
				var x0=realdatatime_left[from_id];
				var date_x0 = new Date(x0); 
				var milliseconds_x0 = date_x0.getTime(); 
				
				var x1=realdatatime_left[to_id];
				var date_x1 = new Date(x1); 
				var milliseconds_x1 = date_x1.getTime(); 
				
				var y0 = realdataweight_left[from_id];
				var y1 = realdataweight_left[to_id]
				
				
				
				var max = 250;
		        var min = 10;
		        var green = Math.floor(Math.random() * (max - min + 1)) + min;
				var color = 'hsl(' + green + ', ' + 99 + '%, ' + 65 + '%)';
				
				/* var trace_arrow = {
				x : [milliseconds_x1],
				y : [y1],
				text : [realdatatitle_to],
				mode : 'text',
				type : 'scatter',
				textposition : 'right',
				marker : {
					size : 8,
					color : color
				},
				textfont: {
					size: 10,
				    color: color
				 },
				 hoverinfo:'none',
				 hovermode: 'closest'
			} */
		
		var trace_lines = {
						
				
				x : [milliseconds_x1, milliseconds_x0],
			
				y: [y1, y0],
				type : 'line',
			
				text : [realdatatitle_to],
				mode: 'markers+lines',
				
				textposition : 'right',
				line: {
					
					shape: 'vhv',
					
					dash:'dot',
				    color: color,
				    //fillcolor:color,
				    width: 2,
				    
				   
				  },
				  marker : {
						size : 8,
						color : color
						
					},
					textfont: {
						size: 10,
					    color: color
					 },
					 opacity:0.2,
				 hoverinfo:'none'
		
			};
		
		
		final_buildon_trace.push(trace_lines);
				
				
			}
			Plotly.addTraces(TESTER, final_buildon_trace);
		}