You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

353 lines
9.5 KiB
Plaintext

TITLE:: FluidPlotter
summary:: A view for plotting data
categories:: Libraries>FluidCorpusManipulation
related:: Classes/FluidDataSet, Classes/FluidLabelSet, Classes/FluidKDTree, Classes/FluidKMeans
DESCRIPTION::
FluidPlotter is a viewer for plotting data.
Holding option/alt and clicking and dragging over a section of the plotter will zoom into that space. Hold control and click to return to the original x and y ranges.
CLASSMETHODS::
METHOD:: new
Creates a new instance of FluidPlotter
ARGUMENT:: parent
A parent view to embed the FluidPlotter in. If no parent is passed, FluidPlotter will create a window for itself at the given bounds. To create a view without STRONG::parent:: and STRONG::bounds:: (e.g. for GUIs with link::Guides/GUI-Layout-Management::), see the STRONG::standalone:: argument below.
ARGUMENT:: bounds
Where to show the FluidPlotter, either within the parent or on the screen (if no parent is passed).
ARGUMENT:: dict
A link::Classes/Dictionary:: from a FluidDataSet dump method (or a similarly formatted Dictionary) that contains the data to be plotted.
ARGUMENT:: mouseMoveAction
A function to execute on mouse down or mouse drag. This funtion is passed the strong::view:: (itself), strong::x position:: (scaled according to the xmin and xmax arguments of FluidPlotter), strong::y position:: (scaled according to the ymin and ymax arguments of FluidPlotter), strong::modifiers::, strong::button number::, and strong::click count::. The last two arguments are only useful on mouse down, not on mouse drag.
ARGUMENT:: xmin
Minimum of the X range to display. Default is 0.
ARGUMENT:: xmax
Maximum of the X range to display. Default is 1.
ARGUMENT:: ymin
Minimum of the Y range to display. Default is 0.
ARGUMENT:: ymax
Maximum of the Y range to display. Default is 1.
ARGUMENT:: standalone
If strong::false::, creates a link::Classes/View:: without parent or bounds, so that it can be used as part of a larger GUI, e.g. with link::Guides/GUI-Layout-Management::.
returns::
An instance of FluidPlotter
INSTANCEMETHODS::
METHOD:: background
Set the background link::Classes/Color::.
METHOD:: pointSize
Set the size of a specific point.
ARGUMENT:: identifier
Which point to set the size of.
ARGUMENT:: size
What size the point should be. This is a multiplier applied to the default point size which is 6 pixels. A point size of "2" will render a point with a diameter of 12 pixels. A point size of "0.5" will render a point with a diameter of 3 pixels.
METHOD:: refresh
Refresh the link::Classes/UserView:: inside the FluidPlotter.
METHOD:: xmin
Set xmin property and refresh the plotter.
METHOD:: xmax
Set xmax property and refresh the plotter.
METHOD:: ymin
Set ymin property and refresh the plotter.
METHOD:: ymax
Set ymax property and refresh the plotter.
METHOD:: zoomxmin
Get the x lower bound of the current zoom.
METHOD:: zoomxmax
Get the x upper bound of the current zoom.
METHOD:: zoomymin
Get the y lower bound of the current zoom.
METHOD:: zoomymax
Get the y upper bound of the current zoom.
METHOD:: addPoint
Manually add a single point to the FluidPlotter. Similar to the strong::addPoint:: method of link::Classes/FluidDataSet::, addPoint_ will not overwrite a point that already exists at the given identifier. Instead, a warning will be thrown.
ARGUMENT:: identifier
The identifier associated with this point.
ARGUMENT:: x
X position of the point.
ARGUMENT:: y
Y position of the point.
ARGUMENT:: color
What link::Classes/Color:: to make the point. If nothing is provided the point will default to link::Classes/Color::.black.
ARGUMENT:: size
What size to make the point. This is a multiplier that modifies the default point size of 6 pixels. The default is 1. See strong::pointSize:: method above.
METHOD:: setPoint
Similar to the strong::setPoint:: method of link::Classes/FluidDataSet::, setPoint_ will add a new point to the FluidPlotter. If a point already exists at the given identifier, it will be overwritten.
ARGUMENT:: identifier
The identifier associated with this point.
ARGUMENT:: x
X position of the point.
ARGUMENT:: y
Y position of the point.
ARGUMENT:: color
What link::Classes/Color:: to make the point. If nothing is provided the point will default to link::Classes/Color::.black.
ARGUMENT:: size
What size to make the point. This is a multiplier that modifies the default point size of 6 pixels. The default is 1. See strong::pointSize:: method above.
METHOD:: highlight
Increase the size of a point to make it more salient. Only one point can be "highlighted" at a time. To increase the size of multiple points, use method strong::pointSize::.
ARGUMENT:: identifier
The identifier of the point to make salient. If nil is passes, not points' sizes will be changed.
METHOD:: dict
Set a new link::Classes/Dictionary:: of points. Overwrites all previous points and Dictionaries.
ARGUMENT:: d
METHOD:: shape
Change the shape of the points, the options are \circle or \square. The default is \circle.
ARGUMENT:: sh
(describe argument here)
METHOD:: pointSizeScale
Scale all the points by a multiplier. See strong::pointSize_:: method above. The default is 1.
ARGUMENT:: ps
(describe argument here)
METHOD:: close
Close the plotter and/or its parent.
METHOD:: pointColor
Change the link::Classes/Color:: of a point.
ARGUMENT:: identifier
Identifier of the point to change the color of.
ARGUMENT:: color
The link::Classes/Color:: to change the point to.
METHOD:: parent
returns:: The parent link::Classes/View:: of the FluidPlotter
METHOD:: categories
Set categories to display as colors.
ARGUMENT:: labelSetDict
This must be a link::Classes/Dictionary:: from a link::Classes/FluidLabelSet:: dump method, or a similarly formatted Dictionary.
EXAMPLES::
code::
(
// make some dummy data and plot it
~dummy_data = {
arg xmin = 20, xmax = 20000, ymin = -130, ymax = 0;
Dictionary.newFrom([
"cols",2,
"data",Dictionary.newFrom(Array.fill(200,{
arg i;
var return;
if((i % 2) == 0,{
return = "example-%".format((i/2).asInteger);
},{
return = [rrand(xmin,xmax),rrand(ymin,ymax)];
});
// return.postln;
return;
}))
]);
};
Window.closeAll;
// self window
d = ~dummy_data.value;
// d.postln;
~fp = FluidPlotter(bounds:Rect(200,200,600,600),dict:d,mouseMoveAction:{
arg view, x, y, modifiers, buttonNumber, clickCount;
[view, x, y, modifiers, buttonNumber, clickCount].postln;
"current zoom:\n\tx: % to %\n\ty: % to %".format(view.zoomxmin,view.zoomxmax,view.zoomymin,view.zoomymax).postln;
"".postln;
},xmin:20,xmax:20000,ymin:-130,ymax:0);
)
// click and drag on the plotter to report stuff in the mouseMoveAction callback function
// hold option / alt and click and drag to zoom in on a section
// hold command / control and click to return to the original zoom
// change point size of just one point
~fp.pointSize_("example-5",10);
// change it back
~fp.pointSize_("example-5",1);
// change all points size bigger...
~fp.pointSizeScale_(2);
// ...smaller...
~fp.pointSizeScale_(0.5);
// ...back to normal
~fp.pointSizeScale_(1);
(
// change 10 random points red
10.do({
~fp.pointColor_("example-%".format(rrand(0,99)),Color.red);
});
)
// "highlight" a point (makes it a little bigger)
~fp.highlight_("example-95");
// a different one
~fp.highlight_("example-94");
// highlight a few
~fp.highlight_(["example-1","example-2","example-3"]);
// none
~fp.highlight_(nil);
// put some different data in
~fp.dict_(~dummy_data.value);
// change the ranges
(
~fp.ymin_(-140);
~fp.ymax_(10);
~fp.xmin_(-200);
~fp.xmax_(21000);
)
// change the point shapes
~fp.shape_(\square);
// change back to circles
~fp.shape_(\circle);
// change the background color
~fp.background_(Color.red)
~fp.background_(Color.white)
// ==== perform KMeans on the data and colorize the categories ======
(
s.waitForBoot{
Routine{
var labelset = FluidLabelSet(s);
var kmeans = FluidKMeans(s);
var ds = FluidDataSet(s);
s.sync;
ds.load(~fp.dict,{
kmeans.fitPredict(ds,labelset,{
labelset.dump({
arg lsdict;
defer{~fp.categories_(lsdict)};
"done".postln;
});
});
});
}.play;
}
)
// close it or it's parent
~fp.close;
// a FluidPlotter inside a parent with parent
(
Window.closeAll;
d = Dictionary.newFrom([
"cols",2,
"data",Dictionary.newFrom(Array.fill(200,{
arg i;
var return;
if((i%2) == 0,{
return = "example-%".format((i/2).asInteger);
},{
return = [exprand(20,20000),rrand(-130,0)];
});
return;
}))
]);
w = Window("test",Rect(50,50,800,600)).front;
~fp = FluidPlotter(w,Rect(50,50,400,400),dict:d,mouseMoveAction:{
arg view, x, y, modifiers;
[view, x, y, modifiers].postln;
"".postln;
},xmin:20,xmax:20000,ymin:-130,ymax:0);
)
// two FluidPlotter side by side with standalone=false
(
Window.closeAll;
// make two different data dictionaries
d = 2.collect { Dictionary.newFrom([
"cols",2,
"data",Dictionary.newFrom(Array.fill(200,{
arg i;
var return;
if((i%2) == 0,{
return = "example-%".format((i/2).asInteger);
},{
return = [exprand(20,20000),rrand(-130,0)];
});
return;
}))
])};
w = Window("test",Rect(50,50,1200,600)).front;
// make two plotters, one for each data dictionary
~fluidPlotters = d.collect { |data|
FluidPlotter(dict: data, standalone: false, mouseMoveAction:{
arg view, x, y, modifiers;
[view, x, y, modifiers].postln;
"".postln;
},xmin:20,xmax:20000,ymin:-130,ymax:0)
};
// assign plotters to window's layout
w.layout = HLayout(~fluidPlotters[0], ~fluidPlotters[1]);
)
// you can make an empty one and then set the dict later
(
Window.closeAll;
~fp = FluidPlotter(bounds:Rect(100,100,500,500))
)
// now set data
~fp.dict_(~dummy_data.(0.01,1,0.0,1.0).postln);
::