sclang: ServerShmInterface - try to avoid multiple destructor calls
[supercollider.git] / HelpSource / Classes / Plotter.schelp
blob3f1b730727c21528af4b9b42d19747e7b5173d1b
1 class:: Plotter
2 summary:: Plot numerical data on a window or view
3 categories:: GUI>GUI-Tools
4 related:: Reference/plot
6 description::
7 Plot data of up to three dimensions on a link::Classes/Window:: or link::Classes/UserView::.
9 subsection:: Keyboard shortcuts
11 When the plotter window has focus, the following keyboard shortcuts can be used to change the display:
12 table::
13 ## + / - || vertical zoom
14 ## = || compare plot channels
15 ## n || toggle normalize display (0..1) / (-1..1), or fit range
16 ## s || toggle superposition (see: superpose)
17 ## m || switch plot mode (see: link::Classes/Plotter#plotMode::)
18 ## e || toggle editing (see: link::Classes/Plotter#editMode::)
19 ## g || toggle horizontal (domain) grid
20 ## G || toggle vertical (codomain) grid
21 ## ctrl-+ / - || zoom font
22 ## alt-click || post value
25 subsection:: Method extensions
26 Plotter extends other classes with methods. To see what classes implements plot2, see link::Overviews/Methods#plot2::
28 method:: plot2 (args)
30 code::
31 // plot array
32 [1, 6, 2, -5, 2].plot2;
33 (0..100).normalize(0, 8pi).sin.plot2;
35 // nested arrays
36 { (0..100).normalize(0, 15.0.rand).sin }.dup(3).plot2;
37 { { (0..17).normalize(0, 15.0.rand).sin }.dup(4) }.dup(3).plot2;
39 // UGen functions
40 { SinOsc.ar([700, 357]) * SinOsc.ar([400, 476]) * 0.2 }.plot2;
42 // Buffer
43 Buffer.read(s, Help.dir +/+ "sounds/SinedPink.aiff").plot2;
45 // Env
46 Env.perc(0.4, 0.6).plot2;
49 method:: plotGraph2 (n,from,to,...)
51 code::
52 { |x| sin(x) }.plotGraph2(300,0,2*pi);
53 { |x| sin(1/x)*x }.plotGraph2(from:0.0001,to:0.2);
56 section:: Changing global defaults
58 The default styles are kept (and may be overridden) in code::GUI.skin.at(\plot)::. See also link::Classes/GUI:: help.
60 code::
61 // specify plot layout
63 GUI.skin.plot.gridLinePattern = FloatArray[1, 0];
64 GUI.skin.plot.fontColor = Color(0.5, 1, 0);
65 GUI.skin.plot.gridColorX = Color.yellow(0.5);
66 GUI.skin.plot.gridColorY = Color.yellow(0.5);
67 GUI.skin.plot.background = Color.black;
68 GUI.skin.plot.plotColor = (10..0).normalize(0.1, 1).collect { |i| Color.rand(i) };
69 GUI.skin.plot.labelX = "X";
70 GUI.skin.plot.labelY = "Y";
74 x = { |i| (0..60).scramble.clump(8) * (3.5 ** i) }.dup(3);
75 x.plot2("ARRAY:PLOT", Rect(200, 300, 600, 500));
78 GUI.skin.plot.put(\plotColor, { Color.rand(0.0, 0.8) } ! 8);
79 [(0..100), (20..120), (40..140)].squared.flop.bubble.plot2;
81 // reset the defaults:
82 Plot.initClass;
85 classmethods::
87 method:: new
88 argument:: name
89 Plot window title.
90 argument:: parent
91 Either a link::Classes/Window:: / link::Classes/View:: may be passed in - then the plot is embedded. Otherwise a new link::Classes/Window:: is created.
92 argument:: bounds
93 The window bounds (a link::Classes/Rect::).
94 discussion::
95 code::
97 a = Plotter("the plot", Rect(600, 30, 800, 250));
98 a.value = (0..1000).normalize(0, 14pi).curdle(0.01).scramble.flat.sin;
103 instancemethods::
105 subsection:: Accessing Instance Variables
107 method:: makeWindow
108 Open given plotter in a new window or within a given composite view.
109 argument:: parent
110 Either a link::Classes/Window:: or link::Classes/View:: may be passed in - then the plot is embedded. Otherwise a new link::Classes/Window:: is created.
111 argument:: bounds
112 The window bounds (a link::Classes/Rect::).
114 method:: plotMode
115 Set the style of data display.
116 argument:: symbol
117 Available modes:
118 table::
119 ## code::\linear:: || connecting data points with linear interpolation
120 ## code::\points:: || draw data points only
121 ## code::\plines:: || combination of lines and points
122 ## code::\levels:: || horizontal lines
123 ## code::\steps:: || connecting data points with step interpolation
125 discussion::
126 code::
127 a = (0..20).scramble.plot2;
128 a.plotMode = \points; a.refresh;
129 a.plotMode = \plines; a.refresh;
130 a.plotMode = \levels; a.refresh;
131 a.plotMode = \steps; a.refresh;
132 a.plotMode = \linear; a.refresh;
135 method:: setProperties
136 Set properties of all plot views. Defaults are taken from code::GUI.skin.at(\plot);::
137 argument:: pairs
138 A list of symbol,value pairs. Supported properties:
139 list::
140 ## font
141 ## fontColor
142 ## gridColorX
143 ## gridColorY
144 ## plotColor (an link::Classes/Array::)
145 ## backgroundColor
146 ## gridLinePattern
147 ## gridLineSmoothing ( link::Classes/Boolean:: )
148 ## labelX
149 ## labelY
150 ## gridOnX ( link::Classes/Boolean:: )
151 ## gridOnY ( link::Classes/Boolean:: )
153 discussion::
154 Example:
155 code::
157 a = { (0..30).scramble }.dup(2).plot2;
158 a.setProperties(
159         \fontColor, Color.red,
160         \plotColor, Color.blue,
161         \backgroundColor, Color.black,
162         \gridColorX, Color.white,
163         \labelX, "Humidity"
165 a.refresh;
168 GUI.skin.at(\plot); // defaults
171 method:: editMode
172 If the edit mode is set to true, the data may be edited via cursor.
173 code::
174 a = (0..20).plot2;
175 a.editMode = true; // now edit the data by clicking into the plot..
176 a.value; // the value
179 method:: resolution
180 Set the number of data points displayed maximally per pixel (default: 1)
181 code::
182 a = (0..200).scramble.plot2;
183 a.resolution = 8; a.refresh; // resizing the window shows interpolation
184 a.resolution = 1; a.refresh;
187 method:: findSpecs
188 If true (default: code::true::), specs are derived from new data (using min and max values) automatically.
190 method::superpose
191 If set to true, plotter displays channels on top of each other (keyboard shortcut: s)
192 code::
193 a = { (0..30).scramble }.dup(2).plot2;
194 a.superpose = true; a.refresh;
197 method:: value
198 Return or set the data values. Data may be numerical arrays of up to 3 dimensions.
199 code::
200 a = [1, 4, 2, 7, 4].dup(2).plot2;
201 a.value;
204 method:: data
205 Reference to the current internal data.
207 method:: cursorPos
208 Returns:: the last cursorPos (a link::Classes/Point::).
210 method:: plots
211 Returns:: the single subplots (a link::Classes/Plot::).
214 method:: specs
215 Set or get the spec for the y-axis (codomain).
216 code::
217 a = { (40..3000).scramble }.dup(2).plot2;
218 a.specs = \freq.asSpec; a.refresh;
221 method:: domainSpecs
222 Set or get the spec for the x-axis (domain).
223 code::
224 a = { (40..300).scramble }.dup(2).plot2;
225 a.domainSpecs = \freq.asSpec; a.refresh;
228 method:: editFunc
229 Supply a function which is evaluated when editing data. The function is called with the arguments: code::plotter::, code::plotIndex::, code::index::, code::val::, code::x::, code::y::.
230 discussion::
231 Example:
232 code::
234 a = { (0..10).scramble.normalize }.dup(2).plot2;
235 a.editMode = true;
236 a.editFunc = { |...args| args.postln };
239 // using plotter as a control interface
241 a = (0..10).scramble.normalize(300, 400).plot2;
242 a.specs = \freq; a.plotMode = \points;
243 a.editMode = true;
244 x = { SinOsc.ar(\freq.kr(a.value)).mean * 0.1 }.play;
245 a.editFunc = { |plotter, plotIndex, i, val|
246         x.setn(\freq, a.value)
248 a.parent.onClose = { x.release };
252 a = { (0..10).scramble.normalize(300, 400) }.dup.plot2;
253 a.specs = \freq; a.plotMode = \levels;
254 a.editMode = true;
255 x = {
256         var phase = SinOsc.ar(\rate.kr(a.value[1]));
257         SinOsc.ar(\freq.kr(a.value[0]), phase).mean * 0.1
258 }.play;
259 a.editFunc = { |plotter, plotIndex, i, val|
260         x.setn(\freq, a.value[0]);
261         x.setn(\rate, a.value[1]);
263 a.parent.onClose = { x.release };
267 examples::
269 code::
270 // embedding in another GUI
272 w = Window("plot panel", Rect(20, 30, 520, 250));
273 Slider.new(w, Rect(10, 10, 490, 20)).resize_(2).action_ { |v|
274         a.value = (0..(v.value * 80).asInteger).scramble;
275         w.refresh;
277 z = CompositeView(w, Rect(10, 35, 490, 200)).background_(Color.rand(0.7)).resize_(5);
278 a = Plotter("plot", parent: z).value_([0, 1, 2, 3, 4].scramble * 100);
279 w.front;
284 a = Plotter("the plot", Rect(600, 30, 600, 400));
285 a.value = (0..100).normalize(0, 8pi).sin;
288 a.value = { |i| (0..90) % (i + 12) + ( (0..90) % (i + 2 * 1) ) }.dup(3);
289 a.value = (0..12).squared;
290 a.plotMode = \points; a.refresh;
291 a.plotMode = \levels; a.refresh;
292 a.plotMode = \plines; a.refresh;
294 a.domainSpecs = [[0, 115, \lin, 1]]; a.refresh;
296 a.parent.close; // close window
297 a.makeWindow;   // open it again
299 a.value = { (0..70).scramble }.dup(3);
300 a.plotMode = \linear; a.refresh;
301 a.value = { |i| (0..2000).normalize(0, 4pi + i).sin } ! 4; // lots of values, test efficiency
302 a.value = { |i| (0..10000).normalize(0, 8pi + i).sin } ! 3; // lots of values, test efficiency
303 a.value = { (0..140).scramble } ! 7;
305 a.value = { |i| (0..90).normalize(0, 8pi + (i*2pi)).sin } ! 2 * [400, 560] + 700;
306 a.value = { |i| (_ + 2.0.rand).dup(100).normalize(0, 8pi + i).sin } ! 2 * 400 + 700;
309 // multi channel expansion of single values
310 a.value = { |i| (_ + 2.0.rand).dup(100).normalize(0, 8pi + i).sin *.t [1, 2, 3] } ! 2 * 400 + 700;
311 a.value = { |i| (0..10) **.t [1, 1.2, 1.3, 1.5] * (3.5 ** i) }.dup(3);
313 a.parent.bounds = Rect(400, 100, 500, 700);
314 a.parent.bounds = Rect(600, 30, 500, 300);
316 a.superpose = true;
317 a.value = { |i| (0..20) * (3.5 ** i) }.dup(5);
318 a.superpose = false;
320 // specs
322 a.value = (50..90).midicps.scramble;
323 a.specs = \freq; a.refresh;
324 a.value = (1..60).scramble.neg;
325 a.specs = \db; a.refresh;
327 a.value = { |i| { exprand(1e3, (10 ** (i + 8))) }.dup(90) }.dup(3);
328 a.value = { { exprand(1e3, 1e9) }.dup(90) }.dup(3);
329 a.specs = [[1e3, 1e10, \exp], [1e3, 1e20, \exp], [1e3, 1e30, \exp]]; a.refresh;
330 a.domainSpecs = [[0, 5], [-8, 100], [-1, 1]]; a.refresh;
333 // Array:plot
335 a = (4 ** (-5..0)).postln.plot2;
336 a.specs = \delay; a.refresh;
337 a.domainSpecs = [0, 10, \lin, 0, 0, " Kg"].asSpec; a.refresh;
340 a.domainSpecs = [0.1, 10, \exponential, 0, 0, " Kg"].asSpec; a.refresh;
341 a.domainSpecs = [-10, 10, \lin, 0, 0, " Kg"].asSpec; a.refresh;
344 a = [(0..100) * 9, (200..1300) * 2, (200..1000)/ 5].plot2;
345 a.superpose = true;
347 a = [[0, 1.2, 1.5], [0, 1.3, 1.5, 1.6], [0, 1.5, 1.8, 2, 6]].midiratio.plot2;
348 a.plotMode = \levels; a.refresh;
349 a.superpose = false;
352 // Function:plot
353 a = { SinOsc.ar([700, 357]) * SinOsc.ar([400, 476]) * 0.2 }.plot2;
354 a = { SinOsc.ar([700, 357] *0.02) * SinOsc.ar([400, 476]) * 0.3 }.plot2(0.2, minval: -1);
355 a = { SinOsc.ar(440) }.plot2(1);
358 // Env:plot
359 Env.perc(0.4, 0.6).plot2;
360 Env.new({ 1.0.rand2 }! 8, { 1.0.rand } ! 7, \sin).plot2;
362 // Buffer:plot
363 b = Buffer.read(s, Help.dir +/+ "sounds/SinedPink.aiff");
364                 // Help.dir +/+ "sounds/SinedPink.aiff" contains SinOsc on left, PinkNoise on right
365 b.plot2;
366 b.free;