<commit_before>var currentProjectName = "anolis";
var currentDatasetName = "anolis";

var pieheight = 40
var piewidth = 40
var pieradius = 15
var enablePie = true



function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function') {
		window.onload = func;
	} else {
		window.onload = function() {
			if (oldonload) {
				oldonload();
			}
			func();
		}
	}
}

function elbow(d, i) {
	return "M" + d.source.y + "," + d.source.x + "V" + d.target.x + "H" + d.target.y;
}

function nodeFromId (id) {
	return vis.selectAll("g.node").filter(function (d,i) { return d._id == id ? this : null; });
}

// Toggle clades.
function toggle(d, node, callback) {
	calledAlready = false;
	if (d.clades) {
		d._clades = d.clades;
		d.clades = null;
		d.children = null;
	} else if (d._clades) {
		if (typeof(d._clades[0]) === "string") {
			calledAlready = true;
			updateJSON({
				oldJSON:d,
				node:node,
				callback:callback
			});
		} else {
			d.clades = d._clades;
			d._clades = null;
		}
	// end-node
	} else {
		// first time selecting the node
		if (typeof d.selected === "undefined") {
			d.selected = true;
		} else {
			d.selected = d.selected ? false : true;
		}
	}
	// execute callback function
	if (!calledAlready && callback && typeof(callback) === "function") {
		callback(d);
	}
}

function toggleAll(d, callback) {
	// counter for async control
    togCount++;
	if (d.clades) {
		d.clades.forEach(function(el) {toggleAll(el);});
		toggle(d);
	}
	togCount--;
	// if done and we have a callback function, execute it
	if (togCount === 0 && callback && typeof(callback) === "function") {
	    callback();
	}
}

function testing()
{
	console.log("testing");
	increaseHeight(40);
}

function zoomGraph()
{
	vis.attr("transform", "translate(" + d3.event.translate.join(",") + ")scale(" + d3.event.scale + ")");
	if (d3.event.sourceEvent.type === "mousewheel") {
	        var verticalScale = localStorage.getItem('phylotree:verticalScale') || '2.0'
	        //var verticalScale = 0.5
		increaseHeight(d3.event.sourceEvent.wheelDelta * verticalScale);
		//console.log(d3.event.sourceEvent.wheelDelta);
	}
} // end zoomGraph

function off(d, callback) {
	// not an end node
	if (d.clades) {
		d._clades = d.clades;
		d.clades = null;
		d.children = null;
	}
	// end-node
	else if (!d._clades) {
		d.selected = false;
	}
	if (callback && typeof(callback) === "function") {
		callback(d);
	}
}

function offAll(d, callback) {
	// counter for async control
	togCount++;
	off(d);
	if (d._clades) {
		d._clades.forEach(function(el) {offAll(el);});
	}
	togCount--;
	// if done and we have a callback function, execute it
	if (togCount === 0 && callback && typeof(callback) === "function") {
	    callback();
	}
}

// turns on a specific node
function on(d, callback) {
	// do nothing if d.clades exists (not an end node)
	if (!d.clades && d._clades) {
		// ensure child is actually loaded in memory
		if (typeof(d._clades[0]) === "object") {
			d.clades = d._clades;
			d._clades = null;
		}
	} else if (!d.clades) {
		d.selected = true;
	}
	if (callback && typeof(callback) === "function") {
		callback(d);
	}
}

// turns on all nodes that have currently been loaded in memory
function onAll(d, callback) {
	// counter for async control
	togCount++;
	if (typeof(d.clades) === "object") {
		on(d);
		if (d.clades) {
			d.clades.forEach(function(el) {onAll(el);});
		}
	}

	togCount--;
	// if done and we have a callback function, execute it
	if (togCount === 0 && callback && typeof(callback) === "function") {
	    callback();
	}
}

// turns on all nodes in the tree, performs ajax calls to get more of the tree
// if necessary
// SGZ 4-11-13: Modified and consolidated to only use new updateJSON function
function onAllAndLoad(d, callback) {
	offAll(d, function() {
		updateJSON({
			oldJSON:d,
			maxDepth:100,
			callback:function(){onAll(d, function() {update(d);});}
		});
	});
}

function emptyTree() {
	offAll(root);
	update(root);
}

function entireTree() {
	onAll(root, function() {update(root);});
}

var pieslices = [[Math.random(),Math.random(),Math.random()],[Math.random(),Math.random(),Math.random()]];

function update(source) {
	// set animatio time, slow animation if alt key is pressed
	var duration = d3.event && d3.event.altKey ? 5000 : 500;

	// Compute the new tree layout
	nodes = cluster.nodes(root);

	// Update the nodes...
	var node = vis.selectAll("g.node")
		.data(nodes, function(d) {
			return d.id || (d.id = ++i);
		});

	// Enter any new nodes at the parent's previous position.
	var nodeEnter = node.enter().append("svg:g")
		.attr("class", "node")
		.attr("transform", function(d) {
			return "translate(" + source.y0 + "," + source.x0 + ")"; })
		.on("click", function(datum, index, el) {
			// if shift key is selected when on keypress
			if (d3.event.shiftKey || cladeSelectEnabled) {
				// display all nodes below this on map...
				mapAllChildNodes(datum, this);
			} else {
				toggle(datum, this, function() {
					update(datum);
					mapItem(datum);
				});
			}
		})
		.on("mouseover.text", function() {
			textOn(this);
		})
		.on("mouseout.text", function() {
			textOff(this, true);
		});

	nodeEnter.append("svg:circle")
		.attr("r", 1e-6)
		.style("fill", function(d) {
			return d._clades ? "lightsteelblue" : "#fff";
		})
		.append("title")
		.text(function(d) {
		  var msg = "";
		  if (d.name) {
                    msg += "name: " + d.name + "\n";
                  }
                  if (d.Species) {
                    msg += "Species: " + d.Species + "\n";
                  }
                   if (d.branch_length) {
                        msg += "branch_length: " + d.branch_length + "\n";
                  }
                  return msg;
		});


	nodeEnter.append("svg:text")
		.attr("x", function(d) {
			return d.clades || d._clades ? - 10 : 10; })
		.attr("dy", ".35em")
		.attr("text-anchor", function(d) {
			return d.clades || d._clades ? "end" : "start"; })
		.text(function(d) {
			// truncate ID's to last 4 characters
			if (d.name ) {
			    return d.name;
			} else if (d.Species) {
			    return d.Species;
			} else if (d.scientific_name) {
			    return d.scientific_name;
			} else if (d.display_name) {
			    return d.display_name;
			} else if (d.taxonomies && d.taxonomies[0].scientific_name) {
				return d.taxonomies[0].scientific_name;
			} else if (d.branch_length) {
				// round to 3 decimal places
				return d.branch_length.toString().substring(0,5);
			} else if (d._id) {
				return d._id.substring(d._id.length - 4);
			} else if (typeof (d) === "string") {
				return d.substring(d.length -4);
			}
		})
			//return d.taxonomies ? d.taxonomies[0].scientific_name : d._id.substring(d._id.length - 4); })
		.style("fill-opacity", 1e-6)
		.style("font-size", fontsize.toString()+"px")
		.style("visibility", function() {
			return d3.select("#nodeNames").property("checked") ? "visible" : "hidden";
		});

        var pievis = nodeEnter.append("svg:svg")              //create the SVG element inside the <body>
        .data(pieslices)
       .attr("width", piewidth)           //set the width and height of our visualization (these will be attributes of the <svg> tag
        .attr("height", pieheight)
        .attr("class","piechart")

        .append("svg:g")                //make a group to hold our pie chart
        .attr("transform", "translate(" + pieradius + "," + pieradius + ")")    //move the center of the pie chart from 0, 0 to radius, radius

        var arc = d3.svg.arc()              //this will create <path> elements for us using arc data
        .outerRadius(pieradius);

        var pie = d3.layout.pie()        //this will create arc data for us given a list of values
        .value(function (d) {return d});    //we must tell it out to access the value of each element in our data array

        var arcs = pievis.selectAll("g.slice")     //this selects all <g> elements with class slice (there aren't any yet)
        .data(pie)                          //associate the generated pie data (an array of arcs, each having startAngle, endAngle and value properties)
        .enter()                            //this will create <g> elements for every "extra" data element that should be associated with a selection. The result is creating a <g> for every object in the data array
        .append("svg:g")                    //create a group to hold each slice (we will have a <path> and a <text> element associated with each slice)
        .attr("class", "slice");            //allow us to style things in the slices (like text)

        piecolor = d3.scale.category20c();     //builtin range of colors

        arcs.append("svg:path")
                .attr("fill", function(d, i) { return piecolor(i); } ) //set the color for each slice to be chosen from the color function defined above
                .attr("d", arc);                                    //this creates the actual SVG path using the associated data (pie) with the arc drawing


	// Transition nodes to their new position.
	var nodeUpdate = node.transition()
		.duration(duration)
		.attr("transform", function(d) {
			return "translate(" + d.y + "," + d.x + ")";
		});

	nodeUpdate.select("circle")
		.attr("r", 4.5)
		.style("fill", function(d) {
			if (d._clades) {
				// non end-node color before it is clicked
				return "lightsteelblue";
			} else if (d.clades || d.selected) {
				// any node's color after being clicked
				return "#fff";
			} else {
				// end-node color that hasn't been clicked yet
				return "lightsteelblue";
			}
		});

	nodeUpdate.select("text")
		.style("fill-opacity", 1);

	// Transition existing nodes to their parent's new position.
	var nodeExit = node.exit().transition()
		.duration(duration)
		.attr("transform", function(d) {
			return "translate(" + source.y + "," + source.x + ")"; })
      	.remove();

	nodeExit.select("circle")
		.attr("r", 1e-6);

	nodeExit.select("text")
		.style("fill-opacity", 1e-6);

	// Update the links…
	var link = vis.selectAll("path.link")
	//	.data(tree.links(nodes), function(d) {
		.data(cluster.links(nodes), function(d) {
			return d.target.id;
		});

	// Enter any new links at the parent's previous position.
	link.enter().insert("svg:path", "g")
		.attr("class", "link")
		.attr("d", function(d) {
			var o = {x: source.x0 != null ? source.x0 : root.x , y: source.y0 != null ? source.y0 : root.y};
			return elbow({source: o, target: o});
		})
		.transition()
		.duration(duration)
		.attr("d", elbow);

	// Transition links to their new position.
	link.transition()
		.duration(duration)
		.attr("d", elbow);

	// Transition exiting nodes to the parent's new position.
	link.exit().transition()
		.duration(duration)
		.attr("d", function(d) {
			var o = {x: source.x, y: source.y};
			return elbow({source: o, target: o});
		})
		.remove();

	// Stash the old positions for transition.
	nodes.forEach(function(d) {
		d.x0 = d.x;
		d.y0 = d.y;
	});
}

//SGZ 4-11-13: Fixed this so it's just one call
// makes an async javascript call to load more tree levels
function updateJSON(options) {
	var oldJSON = options.oldJSON;
	var node = options.node || null;
	var callback = options.callback || null;
	var maxDepth = options.maxDepth || 3;

	if (node != null) {
		// on loading the data change the circle color to red
		d3.select(node.childNodes[0]).style("fill", "red");
	}

	d3.json('service/phylomongo-v2/' + mongo.server + '/' + currentProjectName + '/' +
			currentDatasetName + '?maxdepth=' + maxDepth + '&_id=' + oldJSON._id, function(json) {
		toggleAll (json, function() {
			oldJSON.clades = json._clades;
			oldJSON._clades = null;
			if (callback && typeof(callback) === "function") {
				callback();
			}
		});
	});
}<commit_msg>intermediate save of phylotree with ability to show hard-coded characters at the nodes in a piechart.  Saving this version before expanding to support a flexible character array at each node.  <commit_after>var currentProjectName = "anolis";
var currentDatasetName = "anolis";

var pieheight = 40
var piewidth = 40
var pieradius = 15
var enablePie = true
var attribArray = []



function addLoadEvent(func) {
	var oldonload = window.onload;
	if (typeof window.onload != 'function') {
		window.onload = func;
	} else {
		window.onload = function() {
			if (oldonload) {
				oldonload();
			}
			func();
		}
	}
}

function elbow(d, i) {
	return "M" + d.source.y + "," + d.source.x + "V" + d.target.x + "H" + d.target.y;
}

function nodeFromId (id) {
	return vis.selectAll("g.node").filter(function (d,i) { return d._id == id ? this : null; });
}

// Toggle clades.
function toggle(d, node, callback) {
	calledAlready = false;
	if (d.clades) {
		d._clades = d.clades;
		d.clades = null;
		d.children = null;
	} else if (d._clades) {
		if (typeof(d._clades[0]) === "string") {
			calledAlready = true;
			updateJSON({
				oldJSON:d,
				node:node,
				callback:callback
			});
		} else {
			d.clades = d._clades;
			d._clades = null;
		}
	// end-node
	} else {
		// first time selecting the node
		if (typeof d.selected === "undefined") {
			d.selected = true;
		} else {
			d.selected = d.selected ? false : true;
		}
	}
	// execute callback function
	if (!calledAlready && callback && typeof(callback) === "function") {
		callback(d);
	}
}

function toggleAll(d, callback) {
	// counter for async control
    togCount++;
	if (d.clades) {
		d.clades.forEach(function(el) {toggleAll(el);});
		toggle(d);
	}
	togCount--;
	// if done and we have a callback function, execute it
	if (togCount === 0 && callback && typeof(callback) === "function") {
	    callback();
	}
}

function testing()
{
	console.log("testing");
	increaseHeight(40);
}

function zoomGraph()
{
	vis.attr("transform", "translate(" + d3.event.translate.join(",") + ")scale(" + d3.event.scale + ")");
	if (d3.event.sourceEvent.type === "mousewheel") {
	        var verticalScale = localStorage.getItem('phylotree:verticalScale') || '2.0'
	        //var verticalScale = 0.5
		increaseHeight(d3.event.sourceEvent.wheelDelta * verticalScale);
		//console.log(d3.event.sourceEvent.wheelDelta);
	}
} // end zoomGraph

function off(d, callback) {
	// not an end node
	if (d.clades) {
		d._clades = d.clades;
		d.clades = null;
		d.children = null;
	}
	// end-node
	else if (!d._clades) {
		d.selected = false;
	}
	if (callback && typeof(callback) === "function") {
		callback(d);
	}
}

function offAll(d, callback) {
	// counter for async control
	togCount++;
	off(d);
	if (d._clades) {
		d._clades.forEach(function(el) {offAll(el);});
	}
	togCount--;
	// if done and we have a callback function, execute it
	if (togCount === 0 && callback && typeof(callback) === "function") {
	    callback();
	}
}

// turns on a specific node
function on(d, callback) {
	// do nothing if d.clades exists (not an end node)
	if (!d.clades && d._clades) {
		// ensure child is actually loaded in memory
		if (typeof(d._clades[0]) === "object") {
			d.clades = d._clades;
			d._clades = null;
		}
	} else if (!d.clades) {
		d.selected = true;
	}
	if (callback && typeof(callback) === "function") {
		callback(d);
	}
}

// turns on all nodes that have currently been loaded in memory
function onAll(d, callback) {
	// counter for async control
	togCount++;
	if (typeof(d.clades) === "object") {
		on(d);
		if (d.clades) {
			d.clades.forEach(function(el) {onAll(el);});
		}
	}

	togCount--;
	// if done and we have a callback function, execute it
	if (togCount === 0 && callback && typeof(callback) === "function") {
	    callback();
	}
}

// turns on all nodes in the tree, performs ajax calls to get more of the tree
// if necessary
// SGZ 4-11-13: Modified and consolidated to only use new updateJSON function
function onAllAndLoad(d, callback) {
	offAll(d, function() {
		updateJSON({
			oldJSON:d,
			maxDepth:100,
			callback:function(){onAll(d, function() {update(d);});}
		});
	});
}

function emptyTree() {
	offAll(root);
	update(root);
	attribArray = []
}

function entireTree() {
	onAll(root, function() {update(root);});
}


// this function is used to examine the nodes currently being rendered and build an array of the attributes on the nodes
// for rendering pie charts on the nodes.  

function updateAttribArray2(nodes) {
	attribValueArray = []
	attribNameArray = []
	for (var i = nodes.length - 1; i >= 0; i--) {
		//attribArray.push([nodes[i].awesomeness,nodes[i].width,nodes[i].length])
		var characterValues = []
		var characterNames = []
		for (var j = nodes[i].characters[j].length - 1; j >= 0; j--) {
			characterNames.push(nodes[i].characters[j].name)
			characterValues.push(nodes[i].characters[j].value)
		};
		attribValueArray.push(characterValues)
		attribNameArray.push(characterNames)
	};
	console.log("updated attribValueArray",attribValueArray);
	console.log("updated attribNameArray",attribNameArray);
}

function updateAttribArray(nodes) {
	attribArray = []
	for (var i = nodes.length - 1; i >= 0; i--) {
		attribArray.push([nodes[i].awesomeness,nodes[i].width,nodes[i].length])
	};
	console.log("updated attribArray",attribArray);
}

function update(source) {
	// set animatio time, slow animation if alt key is pressed
	var duration = d3.event && d3.event.altKey ? 5000 : 500;


	// Compute the new tree layout
	nodes = cluster.nodes(root);
	updateAttribArray(nodes);

	// Update the nodes...
	var node = vis.selectAll("g.node")
		.data(nodes, function(d) {
			return d.id || (d.id = ++i);
		});

	//console.log('nodes:',nodes)

	// Enter any new nodes at the parent's previous position.
	var nodeEnter = node.enter().append("svg:g")
		.attr("class", "node")
		.attr("transform", function(d) {
			return "translate(" + source.y0 + "," + source.x0 + ")"; })
		.on("click", function(datum, index, el) {
			// if shift key is selected when on keypress
			if (d3.event.shiftKey || cladeSelectEnabled) {
				// display all nodes below this on map...
				mapAllChildNodes(datum, this);
			} else {
				toggle(datum, this, function() {
					update(datum);
					mapItem(datum);
				});
			}
		})
		.on("mouseover.text", function() {
			textOn(this);
		})
		.on("mouseout.text", function() {
			textOff(this, true);
		});



	nodeEnter.append("svg:circle")
		.attr("r", 1e-6)
		.style("fill", function(d) {
			return d._clades ? "lightsteelblue" : "#fff";
		})
		.append("title")
		.text(function(d) {
		  var msg = "";
		  if (d.name) {
                    msg += "name: " + d.name + "\n";
                  }
                  if (d.Species) {
                    msg += "Species: " + d.Species + "\n";
                  }
                   if (d.branch_length) {
                        msg += "branch_length: " + d.branch_length + "\n";
                  }
                  return msg;
		});


	nodeEnter.append("svg:text")
		.attr("x", function(d) {
			return d.clades || d._clades ? - 10 : 10; })
		.attr("dy", ".35em")
		.attr("text-anchor", function(d) {
			return d.clades || d._clades ? "end" : "start"; })
		.text(function(d) {
			// truncate ID's to last 4 characters
			if (d.name ) {
			    return d.name;
			} else if (d.Species) {
			    return d.Species;
			} else if (d.scientific_name) {
			    return d.scientific_name;
			} else if (d.display_name) {
			    return d.display_name;
			} else if (d.taxonomies && d.taxonomies[0].scientific_name) {
				return d.taxonomies[0].scientific_name;
			} else if (d.branch_length) {
				// round to 3 decimal places
				return d.branch_length.toString().substring(0,5);
			} else if (d._id) {
				return d._id.substring(d._id.length - 4);
			} else if (typeof (d) === "string") {
				return d.substring(d.length -4);
			}
		})
			//return d.taxonomies ? d.taxonomies[0].scientific_name : d._id.substring(d._id.length - 4); })
		.style("fill-opacity", 1e-6)
		.style("font-size", fontsize.toString()+"px")
		.style("visibility", function() {
			return d3.select("#nodeNames").property("checked") ? "visible" : "hidden";
		});

	// add a piechart at each node that displays
	// the value of characters at this node

        	var pievis = nodeEnter.append("svg:svg")              //create the SVG element inside the <body>
        		.data(attribArray)
       		.attr("width", piewidth)           //set the width and height of our visualization (these will be attributes of the <svg> tag
        		.attr("height", pieheight)
        		.attr("class","piechart")
        		.append("svg:g")                //make a group to hold our pie chart
        		.attr("transform", "translate(" + pieradius + "," + pieradius + ")")    //move the center of the pie chart from 0, 0 to radius, radius

        	var arc = d3.svg.arc()              //this will create <path> elements for us using arc data
        		.outerRadius(pieradius);

        	var pie = d3.layout.pie()        //this will create arc data for us given a list of values
        		.value(function (d) {return d});    //we must tell it out to access the value of each element in our data array

       	 var arcs = pievis.selectAll("g.slice")     //this selects all <g> elements with class slice (there aren't any yet)
        		.data(pie)                          //associate the generated pie data (an array of arcs, each having startAngle, endAngle and value properties)
        		.enter()                            //this will create <g> elements for every "extra" data element that should be associated with a selection. The result is creating a <g> for every object in the data array
        		.append("svg:g")                    //create a group to hold each slice (we will have a <path> and a <text> element associated with each slice)
        		.attr("class", "slice");            //allow us to style things in the slices (like text)

        	piecolor = d3.scale.category20c();     //builtin range of colors

        	arcs.append("svg:path")
                	.attr("fill", function(d, i) { return piecolor(i); } ) //set the color for each slice to be chosen from the color function defined above
                	.attr("d", arc);                                    //this creates the actual SVG path using the associated data (pie) with the arc drawing


	// Transition nodes to their new position.
	var nodeUpdate = node.transition()
		.duration(duration)
		.attr("transform", function(d) {
			return "translate(" + d.y + "," + d.x + ")";
		});

	nodeUpdate.select("circle")
		.attr("r", 4.5)
		.style("fill", function(d) {
			if (d._clades) {
				// non end-node color before it is clicked
				return "lightsteelblue";
			} else if (d.clades || d.selected) {
				// any node's color after being clicked
				return "#fff";
			} else {
				// end-node color that hasn't been clicked yet
				return "lightsteelblue";
			}
		});

	nodeUpdate.select("text")
		.style("fill-opacity", 1);

	// Transition existing nodes to their parent's new position.
	var nodeExit = node.exit().transition()
		.duration(duration)
		.attr("transform", function(d) {
			return "translate(" + source.y + "," + source.x + ")"; })
      		.remove();

	nodeExit.select("circle")
		.attr("r", 1e-6);

	nodeExit.select("text")
		.style("fill-opacity", 1e-6);

	// Update the links…
	var link = vis.selectAll("path.link")
	//	.data(tree.links(nodes), function(d) {
		.data(cluster.links(nodes), function(d) {
			return d.target.id;
		});

	// Enter any new links at the parent's previous position.
	link.enter().insert("svg:path", "g")
		.attr("class", "link")
		.attr("d", function(d) {
			var o = {x: source.x0 != null ? source.x0 : root.x , y: source.y0 != null ? source.y0 : root.y};
			return elbow({source: o, target: o});
		})
		.transition()
		.duration(duration)
		.attr("d", elbow);

	// Transition links to their new position.
	link.transition()
		.duration(duration)
		.attr("d", elbow);

	// Transition exiting nodes to the parent's new position.
	link.exit().transition()
		.duration(duration)
		.attr("d", function(d) {
			var o = {x: source.x, y: source.y};
			return elbow({source: o, target: o});
		})
		.remove();

	// Stash the old positions for transition.
	nodes.forEach(function(d) {
		d.x0 = d.x;
		d.y0 = d.y;
	});
}



//SGZ 4-11-13: Fixed this so it's just one call
// makes an async javascript call to load more tree levels
function updateJSON(options) {
	var oldJSON = options.oldJSON;
	var node = options.node || null;
	var callback = options.callback || null;
	var maxDepth = options.maxDepth || 3;

	if (node != null) {
		// on loading the data change the circle color to red
		d3.select(node.childNodes[0]).style("fill", "red");
	}

	d3.json('service/phylomongo-v2/' + mongo.server + '/' + currentProjectName + '/' +
			currentDatasetName + '?maxdepth=' + maxDepth + '&_id=' + oldJSON._id, function(json) {
		toggleAll (json, function() {
			oldJSON.clades = json._clades;
			oldJSON._clades = null;
			if (callback && typeof(callback) === "function") {
				callback();
			}
		});
	});
}
{'fraction_non_alphanumeric': 0.16105381888495005, 'fraction_numerical': 0.007774734128262972, 'mean_word_length': 2.813949915501613, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 22, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2105001', 'n_tokens_mistral': 9129, 'n_tokens_neox': 8263, 'n_words': 2286}