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 points to make them more salient. ARGUMENT:: identifier The identifier of the point to make salient. An array of identifiers will highlight them all. If nil is passed, current highlighted points will be return to normal. 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); ::