我正在尝试实现一个插件,该插件允许用户转储有关由 LinkedBrush 插件选择的点的相关信息。我认为我的问题与此示例有关。我通过 HTMLTooltip 插件将元信息绑定到每个点。理想情况下,我也能以某种方式倾倒它。在我链接到的示例中,信息是通过提示输出的。我希望能够将此信息保存到某种文本文件中。
稍有不同:如何确定散点图中的哪些点已被 LinkedBrush 工具选中,以便保存信息?
我正在尝试实现一个插件,该插件允许用户转储有关由 LinkedBrush 插件选择的点的相关信息。我认为我的问题与此示例有关。我通过 HTMLTooltip 插件将元信息绑定到每个点。理想情况下,我也能以某种方式倾倒它。在我链接到的示例中,信息是通过提示输出的。我希望能够将此信息保存到某种文本文件中。
稍有不同:如何确定散点图中的哪些点已被 LinkedBrush 工具选中,以便保存信息?
为了解决这个问题,我最终只编辑了 LinkedBrush 插件代码。我添加了一个按钮,当单击该按钮时,使用brush.extent() 输出画笔窗口的范围。这将打印最小和最大 x 和 y 坐标。我基本上会使用这些坐标来追溯输入数据集,并确定哪些点落入画笔的边界内。如果有人对如何解决这个问题有更好的想法,我会很欢迎。
class LinkedBrush(plugins.PluginBase):
JAVASCRIPT="""
mpld3.LinkedBrushPlugin = mpld3_LinkedBrushPlugin;
mpld3.register_plugin("linkedbrush", mpld3_LinkedBrushPlugin);
mpld3_LinkedBrushPlugin.prototype = Object.create(mpld3.Plugin.prototype);
mpld3_LinkedBrushPlugin.prototype.constructor = mpld3_LinkedBrushPlugin;
mpld3_LinkedBrushPlugin.prototype.requiredProps = [ "id" ];
mpld3_LinkedBrushPlugin.prototype.defaultProps = {
button: true,
enabled: null
};
function mpld3_LinkedBrushPlugin(fig, props) {
mpld3.Plugin.call(this, fig, props);
if (this.props.enabled === null) {
this.props.enabled = !this.props.button;
}
var enabled = this.props.enabled;
if (this.props.button) {
var BrushButton = mpld3.ButtonFactory({
buttonID: "linkedbrush",
sticky: true,
actions: [ "drag" ],
onActivate: this.activate.bind(this),
onDeactivate: this.deactivate.bind(this),
onDraw: function() {
this.setState(enabled);
},
icon: function() {
return mpld3.icons["brush"];
}
});
this.fig.buttons.push(BrushButton);
var my_icon = "data:image/png;base64,longstring_that_I_redacted";
var SaveButton = mpld3.ButtonFactory({
buttonID: "save",
sticky: false,
onActivate: this.get_selected.bind(this),
icon: function(){return my_icon;},
});
this.fig.buttons.push(SaveButton);
}
this.extentClass = "linkedbrush";
}
mpld3_LinkedBrushPlugin.prototype.activate = function() {
if (this.enable) this.enable();
};
mpld3_LinkedBrushPlugin.prototype.deactivate = function() {
if (this.disable) this.disable();
};
mpld3_LinkedBrushPlugin.prototype.get_selected = function() {
if (this.get_selected) this.get_selected();
};
mpld3_LinkedBrushPlugin.prototype.draw = function() {
var obj = mpld3.get_element(this.props.id);
if (obj === null) {
throw "LinkedBrush: no object with id='" + this.props.id + "' was found";
}
var fig = this.fig;
if (!("offsets" in obj.props)) {
throw "Plot object with id='" + this.props.id + "' is not a scatter plot";
}
var dataKey = "offsets" in obj.props ? "offsets" : "data";
mpld3.insert_css("#" + fig.figid + " rect.extent." + this.extentClass, {
fill: "#000",
"fill-opacity": .125,
stroke: "#fff"
});
mpld3.insert_css("#" + fig.figid + " path.mpld3-hidden", {
stroke: "#ccc !important",
fill: "#ccc !important"
});
var dataClass = "mpld3data-" + obj.props[dataKey];
var brush = fig.getBrush();
var dataByAx = [];
fig.axes.forEach(function(ax) {
var axData = [];
ax.elements.forEach(function(el) {
if (el.props[dataKey] === obj.props[dataKey]) {
el.group.classed(dataClass, true);
axData.push(el);
}
});
dataByAx.push(axData);
});
var allData = [];
var dataToBrush = fig.canvas.selectAll("." + dataClass);
var currentAxes;
function brushstart(d) {
if (currentAxes != this) {
d3.select(currentAxes).call(brush.clear());
currentAxes = this;
brush.x(d.xdom).y(d.ydom);
}
}
function brushmove(d) {
var data = dataByAx[d.axnum];
if (data.length > 0) {
var ix = data[0].props.xindex;
var iy = data[0].props.yindex;
var e = brush.extent();
if (brush.empty()) {
dataToBrush.selectAll("path").classed("mpld3-hidden", false);
} else {
dataToBrush.selectAll("path").classed("mpld3-hidden", function(p) {
return e[0][0] > p[ix] || e[1][0] < p[ix] || e[0][1] > p[iy] || e[1][1] < p[iy];
});
}
}
}
function brushend(d) {
if (brush.empty()) {
dataToBrush.selectAll("path").classed("mpld3-hidden", false);
}
}
this.get_selected = function(d) {
var brush = fig.getBrush();
var extent = brush.extent();
alert(extent);
}
this.enable = function() {
this.fig.showBrush(this.extentClass);
brush.on("brushstart", brushstart).on("brush", brushmove).on("brushend", brushend);
this.enabled = true;
};
this.disable = function() {
d3.select(currentAxes).call(brush.clear());
this.fig.hideBrush(this.extentClass);
this.enabled = false;
};
this.disable();
};
"""
def __init__(self, points, button=True, enabled=True):
if isinstance(points, mpl.lines.Line2D):
suffix = "pts"
else:
suffix = None
self.dict_ = {"type": "linkedbrush",
"button": button,
"enabled": False,
"id": utils.get_id(points, suffix)}