<commit_before>/* Coordinate systems in the plots:
(note: paper and viewbox have y0 at large y because pixels start at upper left,
not lower left)

Data coordinates: xd,yd
    visible range: xd0-xd1, yd0-yd1 (gl.xaxis.range[0-1], gl.yaxis.range[0-1]

Paper coordinates: xp,yp (where axes are drawn, minus gl.margin:.l,.t)
    plot box: xp0-xp1, yp0-yp1 (0 - gd.plotwidth, gd.plotheight - 0)
    transform: xp = mx*xd+bx, yp = my*yd+by
        mx = gl.xaxis.m = gd.plotwidth/(gl.xaxis.range:[1]-[0])
        bx = gl.xaxis.b = -mx*gl.xaxis.range[0]
        my = gl.yaxis.m = gd.plotheight/(gl.yaxis.range:[0]-[1])
        by = gl.yaxis.b = -my*gl.yaxis.range[1]
Viewbox coordinates: xv,yv (where data are drawn)
    plot box: xv0-xv1, yv0-yv1 (gd.viewbox: .x - .x+.w, .y+.h - .y)
        initial viewbox: 0 - gd.plotwidth, gd.plotheight - 0
    transform: xv = xp+b2x, yv = yp+b2y
        panning: subtract dx,dy from viewbox:.x,.y
        zooming: viewbox will not scale x and y differently, at least in Chrome, so for
            zoom we will move the individual points.
*/

function plot(divid, data, layout) {
    // Get the container div: we will store all variables as properties of this div
    // (for extension to multiple graphs per page)
    // some callers send this in by dom element, others by id (string)
    var gd=(typeof divid == 'string') ? document.getElementById(divid) : divid;
	var defaultColors=['#00e','#a00','#0c0','#000']

/*  data should be an array of objects, one per trace. allowed keys:

    type: (string) scatter (default)

    x: (float array), or x0:(float) and dx:(float)
        if neither x, x0, or dx exists, defaults is x0:0, dx:1

    y: (float array), or y0:(float) and dy:(float)
        if neither y, y0, or dy exists, defaults to y0:0, dy:1
        you may provide x and/or y arrays, but not neither

    marker: (object):
        symbol: (string) circle (default)
        color: (cstring), or (cstring array)
        line: (object):
            color: (cstring), or (cstring array)
            width: (float px), default 0

    line: (object):
        color: (cstring), or (cstring array)
        width: (float px), default 1
        
    text: (string array) hover text for each point

    name: <string for legend>
    
    cstring is a string with any valid HTML color
    if any one color is provided, all others not provided will copy it
    if no colors are provided, choose one from a default set based on the trace number

    eventually I'd like to make all of the marker and line properties accept arrays
    to modify properties point-by-point
    
    any array also has a corresponding src attribute, ie xsrc for x
    this is a string:
    	<id>/<colname> for your own data, 
    	<user>/<id>/<colname> for shared data
    
*/  

    // if there is already data on the graph, append the new data
    // if you only want to redraw, pass non-object (null, '', whatever) for data
    if(typeof data=='object') {
        if(typeof gd.data==='undefined') gd.data=data;
        else gd.data.push.apply(gd.data,data);
    }

    // make the graph container and axes, if they don't already exist
    // note: if they do already exist, the new layout gets ignored (as it should)
    if(typeof gd.layout==='undefined') newPlot(divid, layout);  

    var gl=gd.layout, vb=gd.viewbox, gdd=gd.data, gp=gd.plot;
    var xa=gl.xaxis, ya=gl.yaxis, xdr=gl.xaxis.drange, ydr=gl.yaxis.drange;
    var x, xy, y, i, serieslen;
    xdr=[null,null];
    ydr=[null,null];

    //remove all existing plotted data, make the drawing containers
    for(curve in gdd) {
        if(typeof gdd[curve].drawing!=='undefined')
            for(i in gdd[curve].drawing) gdd[curve].drawing[i].remove();
        gdd[curve].drawing={};
    }

    //plot all the data
    // go through all the data twice, first for finding the range, second for plotting
    for(iter=Math.max(xa.autorange,ya.autorange)?0:1; iter<2; iter++) {
        for(curve in gdd) { 
            if('color' in gdd[curve]) color=gdd[curve].color;
            else color=defaultColors[curve % defaultColors.length];
            
            //default type is scatter
            if(!('type' in gdd[curve]) || (gdd[curve].type=='scatter')) {
                // verify that data exists, and make scaled data if necessary
                if(!('y' in gdd[curve]) && !('x' in gdd[curve])) continue; // no data!
                
                if('y' in gdd[curve]) y=gdd[curve].y;
                else if(!('y0' in gdd[curve]) && !('dy' in gdd[curve])) continue; // no scaling!
                else {
                    y=[];
                    for(i in x) y.push(gdd[curve].y0+i*gdd[curve].dy);
                }
    
                if('x' in gdd[curve]) x=gdd[curve].x;
                else if(!('x0' in gdd[curve]) && !('dx' in gdd[curve])) continue; // no scaling!
                else {
                    x=[];
                    for(i in y) x.push(gdd[curve].x0+i*gdd[curve].dx);
                }
                serieslen=Math.min(x.length,y.length);
                if(iter==0) {
                	xdr=[aggNums(Math.min,xdr[0],x,serieslen),aggNums(Math.max,xdr[1],x,serieslen)];
                	ydr=[aggNums(Math.min,ydr[0],y,serieslen),aggNums(Math.max,ydr[1],y,serieslen)];
//                     if(curve==0) {
//                         xdr=[Math.min.apply(null,x),Math.max.apply(null,x)];
//                         ydr=[Math.min.apply(null,y),Math.max.apply(null,y)];
//                     }
//                     else {
//                         xdr=[Math.min(xdr[0],Math.min.apply(null,x)),Math.max(xdr[1],Math.max.apply(null,x))];
//                         ydr=[Math.min(ydr[0],Math.min.apply(null,y)),Math.max(ydr[1],Math.max.apply(null,y))];
//                     }
                }
                else {
                    // lines
                    gp.setStart();
                    for(i=1; i<serieslen; i++) {
                    	if(i>0 && $.isNumeric(x[i-1]) && $.isNumeric(x[i]) &&
                    		$.isNumeric(y[i-1]) && $.isNumeric(y[i])){
                    			gp.path(Raphael.format('M{0},{1}L{2},{3}',
                        		xa.b+xa.m*x[i-1]+vb.x,ya.b+ya.m*y[i-1]+vb.y,
                        		xa.b+xa.m*x[i]+vb.x,ya.b+ya.m*y[i]+vb.y));
                        }
                    }
                    gdd[curve].drawing['lines']=gp.setFinish();
                    gdd[curve].drawing['lines'].attr({'stroke':color});
                    
                    // points
                    gp.setStart();
                    for(i=0; i<serieslen; i++) {
                    	if($.isNumeric(x[i]) && $.isNumeric(y[i]))
	                    	gp.circle(xa.b+xa.m*x[i]+vb.x,ya.b+ya.m*y[i]+vb.y,3);
                    }
                    gdd[curve].drawing['points']=gp.setFinish();
                    gdd[curve].drawing['points'].attr({'fill':color,'stroke-width':0});
                }
            }
        }
        if((iter==0) && (xdr[0]!==null)) {
            if(xa.autorange) xa.range=[1.05*xdr[0]-0.05*xdr[1],1.05*xdr[1]-0.05*xdr[0]];
            if(ya.autorange) ya.range=[1.05*ydr[0]-0.05*ydr[1],1.05*ydr[1]-0.05*ydr[0]];
            doXTicks(gd);doYTicks(gd);doXGrid(gd);doYGrid(gd);
            gd.axdrags.toFront();
        }
    }
    return('*ta-da*')
}

function aggNums(fcn,val,arr,len) {
	var out=($.isNumeric(val)) ? val : null;
	for(var i=0; i<len; i++) {
		if($.isNumeric(arr[i])) out=($.isNumeric(out)) ? fcn(out,arr[i]) : arr[i];
	}
	return out
// 	var x=[];
// 	if($.isNumeric(val)) x.push(val);
// 	for(var i in arr) {if($.isNumeric(arr[i])) x.push(arr[i]);}
// 	return fcn.apply(null,x);
}

function newPlot(divid, layout) {
    // Get the container div: we will store all variables as properties of this div
    // (for extension to multiple graphs per page)
    // some callers send this in already by dom element
    var gd=(typeof divid == 'string') ? document.getElementById(divid) : divid;

    // Get the layout info (hard code this for now)
    gd.layout={title:'Glass Washer',
        xaxis:{range:[-5,5],tick0:0,dtick:2,ticklen:5,
            autorange:1,autotick:1,drange:[null,null],<commit_msg>fixed plotting to multi tabs<commit_after>/* Coordinate systems in the plots:
(note: paper and viewbox have y0 at large y because pixels start at upper left,
not lower left)

Data coordinates: xd,yd
    visible range: xd0-xd1, yd0-yd1 (gl.xaxis.range[0-1], gl.yaxis.range[0-1]

Paper coordinates: xp,yp (where axes are drawn, minus gl.margin:.l,.t)
    plot box: xp0-xp1, yp0-yp1 (0 - gd.plotwidth, gd.plotheight - 0)
    transform: xp = mx*xd+bx, yp = my*yd+by
        mx = gl.xaxis.m = gd.plotwidth/(gl.xaxis.range:[1]-[0])
        bx = gl.xaxis.b = -mx*gl.xaxis.range[0]
        my = gl.yaxis.m = gd.plotheight/(gl.yaxis.range:[0]-[1])
        by = gl.yaxis.b = -my*gl.yaxis.range[1]
Viewbox coordinates: xv,yv (where data are drawn)
    plot box: xv0-xv1, yv0-yv1 (gd.viewbox: .x - .x+.w, .y+.h - .y)
        initial viewbox: 0 - gd.plotwidth, gd.plotheight - 0
    transform: xv = xp+b2x, yv = yp+b2y
        panning: subtract dx,dy from viewbox:.x,.y
        zooming: viewbox will not scale x and y differently, at least in Chrome, so for
            zoom we will move the individual points.
*/

function plot(divid, data, layout) {
    // Get the container div: we will store all variables as properties of this div
    // (for extension to multiple graphs per page)
    // some callers send this in by dom element, others by id (string)
    var gd=(typeof divid == 'string') ? document.getElementById(divid) : divid;
	var defaultColors=['#00e','#a00','#0c0','#000']

/*  data should be an array of objects, one per trace. allowed keys:

    type: (string) scatter (default)

    x: (float array), or x0:(float) and dx:(float)
        if neither x, x0, or dx exists, defaults is x0:0, dx:1

    y: (float array), or y0:(float) and dy:(float)
        if neither y, y0, or dy exists, defaults to y0:0, dy:1
        you may provide x and/or y arrays, but not neither

    marker: (object):
        symbol: (string) circle (default)
        color: (cstring), or (cstring array)
        line: (object):
            color: (cstring), or (cstring array)
            width: (float px), default 0

    line: (object):
        color: (cstring), or (cstring array)
        width: (float px), default 1
        
    text: (string array) hover text for each point

    name: <string for legend>
    
    cstring is a string with any valid HTML color
    if any one color is provided, all others not provided will copy it
    if no colors are provided, choose one from a default set based on the trace number

    eventually I'd like to make all of the marker and line properties accept arrays
    to modify properties point-by-point
    
    any array also has a corresponding src attribute, ie xsrc for x
    this is a string:
    	<id>/<colname> for your own data, 
    	<user>/<id>/<colname> for shared data
    
*/  

    // if there is already data on the graph, append the new data
    // if you only want to redraw, pass non-object (null, '', whatever) for data
    if(typeof data=='object') {
        if(typeof gd.data==='undefined') gd.data=data;
        else gd.data.push.apply(gd.data,data);
    }

    // make the graph container and axes, if they don't already exist
    // note: if they do already exist, the new layout gets ignored (as it should)
    if(typeof gd.layout==='undefined') newPlot(divid, layout);  

    var gl=gd.layout, vb=gd.viewbox, gdd=gd.data, gp=gd.plot;
    var xa=gl.xaxis, ya=gl.yaxis, xdr=gl.xaxis.drange, ydr=gl.yaxis.drange;
    var x, xy, y, i, serieslen;
    xdr=[null,null];
    ydr=[null,null];

    //remove all existing plotted data, make the drawing containers
    for(curve in gdd) {
        if(typeof gdd[curve].drawing!=='undefined')
            for(i in gdd[curve].drawing) gdd[curve].drawing[i].remove();
        gdd[curve].drawing={};
    }

    // plot all the data
    // go through all the data twice, first for finding the range, second for plotting
    for(iter=Math.max(xa.autorange,ya.autorange)?0:1; iter<2; iter++) {
        for(curve in gdd) { 
            if('color' in gdd[curve]) color=gdd[curve].color;
            else color=defaultColors[curve % defaultColors.length];
            
            //default type is scatter
            if(!('type' in gdd[curve]) || (gdd[curve].type=='scatter')) {
                // verify that data exists, and make scaled data if necessary
                if(!('y' in gdd[curve]) && !('x' in gdd[curve])) continue; // no data!
                
                if('y' in gdd[curve]) y=gdd[curve].y;
                else if(!('y0' in gdd[curve]) && !('dy' in gdd[curve])) continue; // no scaling!
                else {
                    y=[];
                    for(i in x) y.push(gdd[curve].y0+i*gdd[curve].dy);
                }
    
                if('x' in gdd[curve]) x=gdd[curve].x;
                else if(!('x0' in gdd[curve]) && !('dx' in gdd[curve])) continue; // no scaling!
                else {
                    x=[];
                    for(i in y) x.push(gdd[curve].x0+i*gdd[curve].dx);
                }
                serieslen=Math.min(x.length,y.length);
                if(iter==0) {
                	xdr=[aggNums(Math.min,xdr[0],x,serieslen),aggNums(Math.max,xdr[1],x,serieslen)];
                	ydr=[aggNums(Math.min,ydr[0],y,serieslen),aggNums(Math.max,ydr[1],y,serieslen)];
                }
                else {
                    // lines
                    gp.setStart();
                    for(i=1; i<serieslen; i++) {
                    	if(i>0 && $.isNumeric(x[i-1]) && $.isNumeric(x[i]) &&
                    		$.isNumeric(y[i-1]) && $.isNumeric(y[i])){
                    			gp.path(Raphael.format('M{0},{1}L{2},{3}',
                        		xa.b+xa.m*x[i-1]+vb.x,ya.b+ya.m*y[i-1]+vb.y,
                        		xa.b+xa.m*x[i]+vb.x,ya.b+ya.m*y[i]+vb.y));
                        }
                    }
                    gdd[curve].drawing['lines']=gp.setFinish();
                    gdd[curve].drawing['lines'].attr({'stroke':color});
                    
                    // points
                    gp.setStart();
                    for(i=0; i<serieslen; i++) {
                    	if($.isNumeric(x[i]) && $.isNumeric(y[i]))
	                    	gp.circle(xa.b+xa.m*x[i]+vb.x,ya.b+ya.m*y[i]+vb.y,3);
                    }
                    gdd[curve].drawing['points']=gp.setFinish();
                    gdd[curve].drawing['points'].attr({'fill':color,'stroke-width':0});
                }
            }
        }
        if((iter==0) && ($.isNumeric(xdr[0]))) {
            if(xa.autorange) xa.range=[1.05*xdr[0]-0.05*xdr[1],1.05*xdr[1]-0.05*xdr[0]];
            if(ya.autorange) ya.range=[1.05*ydr[0]-0.05*ydr[1],1.05*ydr[1]-0.05*ydr[0]];
            doXTicks(gd);doYTicks(gd);doXGrid(gd);doYGrid(gd);
            gd.axdrags.toFront();
        }
    }
    return('*ta-da*')
}

function aggNums(f,v,a,len) {
	var r=($.isNumeric(v)) ? v : null;
	for(var i=0; i<len; i++) if($.isNumeric(a[i])) r=($.isNumeric(r)) ? f(r,a[i]) : a[i];
	return r;
}

function newPlot(divid, layout) {
    // Get the container div: we will store all variables as properties of this div
    // (for extension to multiple graphs per page)
    // some callers send this in already by dom element
    var gd=(typeof divid == 'string') ? document.getElementById(divid) : divid;

    // Get the layout info (hard code this for now)
    gd.layout={title:'Glass Washer',
        xaxis:{range:[-5,5],tick0:0,dtick:2,ticklen:5,
            autorange:1,autotick:1,drange:[null,null],
{'fraction_non_alphanumeric': 0.1567915392456677, 'fraction_numerical': 0.015354230377166158, 'mean_word_length': 2.060440631702086, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6337084', 'n_tokens_mistral': 5642, 'n_tokens_neox': 5327, 'n_words': 1337}