From b003b7a759d844fe227e5715b399e96c773d83e2 Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Wed, 16 Dec 2020 12:09:14 +0000 Subject: [PATCH 01/24] FluidRobustScale: first copying of normalise's code --- release-packaging/Classes/FluidRobustScale.sc | 68 ++++++++ .../HelpSource/Classes/FluidNormalize.schelp | 2 +- .../Classes/FluidRobustScale.schelp | 157 ++++++++++++++++++ .../Classes/FluidStandardize.schelp | 2 +- .../HelpSource/Guides/FluidDataTools.schelp | 2 + src/FluidManipulation/FluidManipulation.cpp | 5 +- 6 files changed, 233 insertions(+), 3 deletions(-) create mode 100644 release-packaging/Classes/FluidRobustScale.sc create mode 100644 release-packaging/HelpSource/Classes/FluidRobustScale.schelp diff --git a/release-packaging/Classes/FluidRobustScale.sc b/release-packaging/Classes/FluidRobustScale.sc new file mode 100644 index 0000000..644cd81 --- /dev/null +++ b/release-packaging/Classes/FluidRobustScale.sc @@ -0,0 +1,68 @@ +FluidRobustScale : FluidRealTimeModel { + + var <>min, <>max, <>invert; + + *new {|server, min = 0, max = 1, invert = 0| + ^super.new(server,[min,max,invert]) + .min_(min).max_(max).invert_(invert); + } + + prGetParams{ + ^[this.min,this.max,this.invert,-1,-1]; + } + + + fitMsg{|dataSet| + ^this.prMakeMsg(\fit,id,dataSet.id) + } + + fit{|dataSet, action| + actions[\fit] = [nil,action]; + this.prSendMsg(this.fitMsg(dataSet)); + } + + transformMsg{|sourceDataSet, destDataSet| + ^this.prMakeMsg(\transform,id,sourceDataSet.id,destDataSet.id); + } + + transform{|sourceDataSet, destDataSet, action| + actions[\transform] = [nil,action]; + this.prSendMsg(this.transformMsg(sourceDataSet, destDataSet)); + } + + fitTransformMsg{|sourceDataSet, destDataSet| + ^this.prMakeMsg(\fitTransform,id,sourceDataSet.id,destDataSet.id) + } + + fitTransform{|sourceDataSet, destDataSet, action| + actions[\fitTransform] = [nil,action]; + this.prSendMsg(this.fitTransformMsg(sourceDataSet, destDataSet)); + } + + transformPointMsg{|sourceBuffer, destBuffer| + ^this.prMakeMsg(\transformPoint,id, + this.prEncodeBuffer(sourceBuffer), + this.prEncodeBuffer(destBuffer), + ["/b_query",destBuffer.asUGenInput] + ); + } + + transformPoint{|sourceBuffer, destBuffer, action| + actions[\transformPoint] = [nil,{action.value(destBuffer)}]; + this.prSendMsg(this.transformPointMsg(sourceBuffer, destBuffer)); + } + + kr{|trig, inputBuffer,outputBuffer,min,max,invert| + + min = min ? this.min; + max = max ? this.max; + invert = invert ? this.invert; + + this.min_(min).max_(max).invert_(invert); + + ^FluidProxyUgen.kr(this.class.name.asString++'/query', K2A.ar(trig), + id, this.min, this.max, this.invert, this.prEncodeBuffer(inputBuffer), this.prEncodeBuffer(outputBuffer)); + } + + +} diff --git a/release-packaging/HelpSource/Classes/FluidNormalize.schelp b/release-packaging/HelpSource/Classes/FluidNormalize.schelp index 9fce5bb..9838cec 100644 --- a/release-packaging/HelpSource/Classes/FluidNormalize.schelp +++ b/release-packaging/HelpSource/Classes/FluidNormalize.schelp @@ -1,7 +1,7 @@ TITLE:: FluidNormalize summary:: Normalize a FluidDataSet categories:: FluidManipulation -related:: Classes/FluidStandardize, Classes/FluidDataSet +related:: Classes/FluidStandardize, Classes/FluidRobustScale, Classes/FluidDataSet DESCRIPTION:: Normalize the entries of a link::Classes/FluidDataSet::, or normalize a data point according to the learned bounds of a data set. On the server. diff --git a/release-packaging/HelpSource/Classes/FluidRobustScale.schelp b/release-packaging/HelpSource/Classes/FluidRobustScale.schelp new file mode 100644 index 0000000..4086461 --- /dev/null +++ b/release-packaging/HelpSource/Classes/FluidRobustScale.schelp @@ -0,0 +1,157 @@ +TITLE:: FluidRobustScale +summary:: Apply Robust Scaling to FluidDataSet +categories:: FluidManipulation +related:: Classes/FluidStandardize, Classes/FluidDataSet + +DESCRIPTION:: +Normalize the entries of a link::Classes/FluidDataSet::, or normalize a data point according to the learned bounds of a data set. On the server. + +See http://www.faqs.org/faqs/ai-faq/neural-nets/part2/section-16.html + +CLASSMETHODS:: + +private:: kr + +METHOD:: new +Create a new instance +ARGUMENT:: server +The link::Classes/Server:: on which to run +ARGUMENT:: min +Minimum output value, default 0 +ARGUMENT:: max +Maximum output value, default 1 +ARGUMENT:: invert +The direction in which the normalization will occur for transform and transformpoint. The default 0 is taking in the range of the input used to fit and transforms it towards the normalised range. A value of 1 will expect an input of the normalized range to transform back to the original range. + + +INSTANCEMETHODS:: + +METHOD:: fit +Compute the normalization factors from a link::Classes/FluidDataSet:: for later. +ARGUMENT:: dataSet +The link::Classes/FluidDataSet:: to normalize +ARGUMENT:: action +A function to run when processing is complete + +METHOD:: transform +Normalize a link::Classes/FluidDataSet:: into another link::Classes/FluidDataSet::, using the learned extrema from a previous call to link::Classes/FluidRobustScale#fit:: +ARGUMENT:: sourceDataSet +The link::Classes/FluidDataSet:: to normalize +ARGUMENT:: destDataSet +The link::Classes/FluidDataSet:: to populate with normalized data +ARGUMENT:: action +A function to run when processing is complete + + +METHOD:: fitTransform +Normalize a link::Classes/FluidDataSet:: +ARGUMENT:: sourceDataSet +The link::Classes/FluidDataSet:: to normalize +ARGUMENT:: destDataSet +The link::Classes/FluidDataSet:: to populate with normalized data +ARGUMENT:: action +A function to run when processing is complete + + +METHOD:: transformPoint +Normalize a new data point, using the learned extrema from a previous call to link::Classes/FluidRobustScale#fit:: +ARGUMENT:: sourceBuffer +A link::Classes/Buffer:: with the new data point +ARGUMENT:: destBuffer +A link::Classes/Buffer:: to contain the normalized value +ARGUMENT:: action +A function to run when processing is complete + +EXAMPLES:: +code:: +s.boot; +//Preliminaries: we want some audio, a couple of FluidDataSets, some Buffers and a FluidRobustScale +// FluidRobustScale.dumpAllMethods +( +~audiofile = File.realpath(FluidBufPitch.class.filenameSymbol).dirname +/+ "../AudioFiles/Tremblay-ASWINE-ScratchySynth-M.wav"; +~raw = FluidDataSet(s,\norm_help_raw); +~norm = FluidDataSet(s,\norm_help_normd); +~pitch_feature = Buffer.new(s); +~stats = Buffer.alloc(s, 7, 2); +~normalizer = FluidRobustScale(s); +) + +// Load audio and run a pitch analysis, which gives us pitch and pitch confidence (so a 2D datum) +( +~audio = Buffer.read(s,~audiofile); +FluidBufPitch.process(s,~audio, features: ~pitch_feature); +) + +// Divide the time series in to 10, and take the mean of each segment and add this as a point to +// the 'raw' FluidDataSet +( +{ + var trig = LocalIn.kr(1, 1); + var buf = LocalBuf(2, 1); + var count = PulseCount.kr(trig) - 1; + var chunkLen = (~pitch_feature.numFrames / 10).asInteger; + var stats = FluidBufStats.kr( + source: ~pitch_feature, startFrame: count * chunkLen, + numFrames: chunkLen, stats: ~stats, trig: (trig * (count <=9)), blocking:1 + ); + var rd = BufRd.kr(2, ~stats, DC.kr(0), 0, 1);// pick only mean pitch and confidence + var wr1 = BufWr.kr(rd[0], buf, DC.kr(0)); + var wr2 = BufWr.kr(rd[1], buf, DC.kr(1)); + var dsWr = FluidDataSetWr.kr(~raw, buf: buf, trig: Done.kr(stats)); + LocalOut.kr( Done.kr(dsWr)); + Poll.kr(trig,count,\count); + FreeSelf.kr(count - 9); +}.play; +) + +// Normalize and load to language-side array +( +~rawarray = Array.new(10); +~normedarray= Array.new(10); +~normalizer.fitTransform(~raw,~norm, { + ~raw.dump{|x| 10.do{|i| + ~rawarray.add(x["data"][i.asString]) + }}; + ~norm.dump{|x| 10.do{|i| + ~normedarray.add(x["data"][i.asString]) + }}; +}); +) + +//Plot side by side. Before normalization the two dimensions have radically different scales +//which can be unhelpful in many cases + +( +~rawarray.flatten(1).unlace.plot("Unnormalized",Rect(0,0,400,400),minval:0,maxval:[5000,1]).plotMode=\bars; +~plot2 = ~normedarray.flatten(1).unlace.plot("Normalized",Rect(410,0,400,400)).plotMode=\bars; +) + +// single point transform on arbitrary value +~inbuf = Buffer.loadCollection(s,0.5.dup); +~outbuf = Buffer.new(s); +~normalizer.transformPoint(~inbuf,~outbuf,{|x|x.postln;x.getn(0,2,{|y|y.postln;};)}); +OSCFunc.trace(false,true) + +//Server side queries +( +{ + var audio = BufRd.ar(1,~audio,LFSaw.ar(BufDur.ir(~audio).reciprocal).range(0, BufFrames.ir(~audio))); + var counter = Stepper.ar(Impulse.ar(ControlRate.ir),max:99); + var trig = A2K.kr(HPZ1.ar(counter) < 0); + //average 100 frames: one could use the MovingAverage extension here + var avg; + var inputPoint = LocalBuf(2); + var outputPoint = LocalBuf(2); + var avgBuf = LocalBuf(100,2); + //running average of pitch features + BufWr.kr(FluidPitch.kr(audio),avgBuf,phase:counter); + avg = Mix.new(BufRd.kr(2, avgBuf, phase:100.collect{|x|x})) * 0.01; + //assemble data point + BufWr.kr(avg[0],inputPoint,0); + BufWr.kr(avg[1],inputPoint,1); + ~normalizer.kr(trig,inputPoint,outputPoint); + Poll.kr(trig,BufRd.kr(1,inputPoint,[0,1]),["pitch (raw)", "confidence (raw)"]); + Poll.kr(trig,BufRd.kr(1,outputPoint,[0,1]),["pitch (normalized)", "confidence (normalized)"]) +}.play; +) +:: diff --git a/release-packaging/HelpSource/Classes/FluidStandardize.schelp b/release-packaging/HelpSource/Classes/FluidStandardize.schelp index 02493c3..8dca74f 100644 --- a/release-packaging/HelpSource/Classes/FluidStandardize.schelp +++ b/release-packaging/HelpSource/Classes/FluidStandardize.schelp @@ -1,7 +1,7 @@ TITLE:: FluidStandardize summary:: Standardize a FluidDataSet categories:: FluidManipulation -related:: Classes/FluidDataSet, Classes/FluidStandardize +related:: Classes/FluidDataSet, Classes/FluidStandardize, Classes/FluidRobustScale DESCRIPTION:: Standardize a link::Classes/FluidDataSet::, i.e. rescale using its mean(s) and standard deviation(s) in each dimension. diff --git a/release-packaging/HelpSource/Guides/FluidDataTools.schelp b/release-packaging/HelpSource/Guides/FluidDataTools.schelp index 01589f3..672d922 100644 --- a/release-packaging/HelpSource/Guides/FluidDataTools.schelp +++ b/release-packaging/HelpSource/Guides/FluidDataTools.schelp @@ -36,6 +36,8 @@ link::Classes/FluidNormalize:: link::Classes/FluidStandardize:: +link::Classes/FluidRobustScale:: + section:: Dimension Reduction Compress data to fewer dimensions for visualisation / efficiency / preprocessing diff --git a/src/FluidManipulation/FluidManipulation.cpp b/src/FluidManipulation/FluidManipulation.cpp index 8e829aa..7b23652 100644 --- a/src/FluidManipulation/FluidManipulation.cpp +++ b/src/FluidManipulation/FluidManipulation.cpp @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -33,9 +34,11 @@ PluginLoad(FluidSTFTUGen) makeSCWrapper("FluidKNNClassifier",ft); makeSCWrapper("FluidKNNRegressor",ft); makeSCWrapper("FluidNormalize",ft); + makeSCWrapper("FluidRobustScale",ft); makeSCWrapper("FluidStandardize",ft); makeSCWrapper("FluidPCA",ft); - makeSCWrapper("FluidMDS",ft); makeSCWrapper("FluidUMAP",ft); + makeSCWrapper("FluidMDS",ft); + makeSCWrapper("FluidUMAP",ft); makeSCWrapper("FluidAudioTransport",ft); makeSCWrapper("FluidBufAudioTransp",ft); makeSCWrapper("FluidDataSetWr", ft); From 7f41959d636cf481e1274a73ec5426dd1b746580 Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Wed, 16 Dec 2020 14:05:08 +0000 Subject: [PATCH 02/24] FluidRobustScale: works with the old interface --- release-packaging/Classes/FluidRobustScale.sc | 20 ++++++++++--------- .../Classes/FluidRobustScale.schelp | 4 ++++ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/release-packaging/Classes/FluidRobustScale.sc b/release-packaging/Classes/FluidRobustScale.sc index 644cd81..1a8a7d1 100644 --- a/release-packaging/Classes/FluidRobustScale.sc +++ b/release-packaging/Classes/FluidRobustScale.sc @@ -1,14 +1,14 @@ FluidRobustScale : FluidRealTimeModel { - var <>min, <>max, <>invert; + var <>min, <>max, <>low, <>high, <>invert; - *new {|server, min = 0, max = 1, invert = 0| - ^super.new(server,[min,max,invert]) - .min_(min).max_(max).invert_(invert); + *new {|server, min = 0, max = 1, low = 0, high = 100, invert = 0| + ^super.new(server,[min,max,low,high,invert]) + .min_(min).max_(max).low_(low).high_(high).invert_(invert); } prGetParams{ - ^[this.min,this.max,this.invert,-1,-1]; + ^[this.min,this.max,this.low,this.high,this.invert,-1,-1]; } @@ -52,16 +52,18 @@ FluidRobustScale : FluidRealTimeModel { this.prSendMsg(this.transformPointMsg(sourceBuffer, destBuffer)); } - kr{|trig, inputBuffer,outputBuffer,min,max,invert| + kr{|trig, inputBuffer,outputBuffer,min,max,low,high,invert| min = min ? this.min; max = max ? this.max; - invert = invert ? this.invert; + low = low ? this.low; + high = high ? this.high; + invert = invert ? this.invert; - this.min_(min).max_(max).invert_(invert); + this.min_(min).max_(max).low_(low).high_(high).invert_(invert); ^FluidProxyUgen.kr(this.class.name.asString++'/query', K2A.ar(trig), - id, this.min, this.max, this.invert, this.prEncodeBuffer(inputBuffer), this.prEncodeBuffer(outputBuffer)); + id, this.min, this.max, this.low, this.high, this.invert, this.prEncodeBuffer(inputBuffer), this.prEncodeBuffer(outputBuffer)); } diff --git a/release-packaging/HelpSource/Classes/FluidRobustScale.schelp b/release-packaging/HelpSource/Classes/FluidRobustScale.schelp index 4086461..9bdd102 100644 --- a/release-packaging/HelpSource/Classes/FluidRobustScale.schelp +++ b/release-packaging/HelpSource/Classes/FluidRobustScale.schelp @@ -20,6 +20,10 @@ ARGUMENT:: min Minimum output value, default 0 ARGUMENT:: max Maximum output value, default 1 +ARGUMENT:: low +Maximum output value, default 1 +ARGUMENT:: high +Maximum output value, default 1 ARGUMENT:: invert The direction in which the normalization will occur for transform and transformpoint. The default 0 is taking in the range of the input used to fit and transforms it towards the normalised range. A value of 1 will expect an input of the normalized range to transform back to the original range. From e043d406fb9b6babc0f73d56eeabfbcfe105b73e Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Thu, 17 Dec 2020 09:02:57 +0000 Subject: [PATCH 03/24] FluidRobustScale: Now with proper interface --- release-packaging/Classes/FluidRobustScale.sc | 18 ++++++++---------- .../HelpSource/Classes/FluidRobustScale.schelp | 4 ---- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/release-packaging/Classes/FluidRobustScale.sc b/release-packaging/Classes/FluidRobustScale.sc index 1a8a7d1..0b69c5e 100644 --- a/release-packaging/Classes/FluidRobustScale.sc +++ b/release-packaging/Classes/FluidRobustScale.sc @@ -1,14 +1,14 @@ FluidRobustScale : FluidRealTimeModel { - var <>min, <>max, <>low, <>high, <>invert; + var <>low, <>high, <>invert; - *new {|server, min = 0, max = 1, low = 0, high = 100, invert = 0| - ^super.new(server,[min,max,low,high,invert]) - .min_(min).max_(max).low_(low).high_(high).invert_(invert); + *new {|server, low = 0, high = 100, invert = 0| + ^super.new(server,[low,high,invert]) + .low_(low).high_(high).invert_(invert); } prGetParams{ - ^[this.min,this.max,this.low,this.high,this.invert,-1,-1]; + ^[this.low,this.high,this.invert,-1,-1]; } @@ -52,18 +52,16 @@ FluidRobustScale : FluidRealTimeModel { this.prSendMsg(this.transformPointMsg(sourceBuffer, destBuffer)); } - kr{|trig, inputBuffer,outputBuffer,min,max,low,high,invert| + kr{|trig, inputBuffer,outputBuffer,low,high,invert| - min = min ? this.min; - max = max ? this.max; low = low ? this.low; high = high ? this.high; invert = invert ? this.invert; - this.min_(min).max_(max).low_(low).high_(high).invert_(invert); + this.low_(low).high_(high).invert_(invert); ^FluidProxyUgen.kr(this.class.name.asString++'/query', K2A.ar(trig), - id, this.min, this.max, this.low, this.high, this.invert, this.prEncodeBuffer(inputBuffer), this.prEncodeBuffer(outputBuffer)); + id, this.low, this.high, this.invert, this.prEncodeBuffer(inputBuffer), this.prEncodeBuffer(outputBuffer)); } diff --git a/release-packaging/HelpSource/Classes/FluidRobustScale.schelp b/release-packaging/HelpSource/Classes/FluidRobustScale.schelp index 9bdd102..137c929 100644 --- a/release-packaging/HelpSource/Classes/FluidRobustScale.schelp +++ b/release-packaging/HelpSource/Classes/FluidRobustScale.schelp @@ -16,10 +16,6 @@ METHOD:: new Create a new instance ARGUMENT:: server The link::Classes/Server:: on which to run -ARGUMENT:: min -Minimum output value, default 0 -ARGUMENT:: max -Maximum output value, default 1 ARGUMENT:: low Maximum output value, default 1 ARGUMENT:: high From b066e6fcd7a7e46ad8493c327d247ebfff8174f8 Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Thu, 17 Dec 2020 09:32:08 +0000 Subject: [PATCH 04/24] helpfile corrected and right default values --- release-packaging/Classes/FluidRobustScale.sc | 2 +- .../Classes/FluidRobustScale.schelp | 63 ++++++++++--------- 2 files changed, 34 insertions(+), 31 deletions(-) diff --git a/release-packaging/Classes/FluidRobustScale.sc b/release-packaging/Classes/FluidRobustScale.sc index 0b69c5e..db53de9 100644 --- a/release-packaging/Classes/FluidRobustScale.sc +++ b/release-packaging/Classes/FluidRobustScale.sc @@ -2,7 +2,7 @@ FluidRobustScale : FluidRealTimeModel { var <>low, <>high, <>invert; - *new {|server, low = 0, high = 100, invert = 0| + *new {|server, low = 25, high = 75, invert = 0| ^super.new(server,[low,high,invert]) .low_(low).high_(high).invert_(invert); } diff --git a/release-packaging/HelpSource/Classes/FluidRobustScale.schelp b/release-packaging/HelpSource/Classes/FluidRobustScale.schelp index 137c929..b00aec6 100644 --- a/release-packaging/HelpSource/Classes/FluidRobustScale.schelp +++ b/release-packaging/HelpSource/Classes/FluidRobustScale.schelp @@ -1,12 +1,12 @@ TITLE:: FluidRobustScale summary:: Apply Robust Scaling to FluidDataSet categories:: FluidManipulation -related:: Classes/FluidStandardize, Classes/FluidDataSet +related:: Classes/FluidStandardize, Classes/FluidNormalize, Classes/FluidDataSet DESCRIPTION:: -Normalize the entries of a link::Classes/FluidDataSet::, or normalize a data point according to the learned bounds of a data set. On the server. +Scales the entries of a link::Classes/FluidDataSet::, or scales a data point according to the learned values of a data set. It will centre the median of each dimension to 0, and will scale the data to +/- the provided centiles, by default providing the first and third qartile (25 and 75).All happens on the server. -See http://www.faqs.org/faqs/ai-faq/neural-nets/part2/section-16.html +See https://scikit-learn.org/stable/auto_examples/preprocessing/plot_all_scaling.html#robustscaler CLASSMETHODS:: @@ -17,48 +17,48 @@ Create a new instance ARGUMENT:: server The link::Classes/Server:: on which to run ARGUMENT:: low -Maximum output value, default 1 +The low centile boundary, default 25. ARGUMENT:: high -Maximum output value, default 1 +The high centile boundary, default 75. ARGUMENT:: invert -The direction in which the normalization will occur for transform and transformpoint. The default 0 is taking in the range of the input used to fit and transforms it towards the normalised range. A value of 1 will expect an input of the normalized range to transform back to the original range. +The direction in which the scaling will occur for transform and transformpoint. The default 0 is taking in the range of the input used to fit and transforms it towards the robust scaling range. A value of 1 will expect an input of the scaling range to transform back to the original range. INSTANCEMETHODS:: METHOD:: fit -Compute the normalization factors from a link::Classes/FluidDataSet:: for later. +Compute the scaling factors from a link::Classes/FluidDataSet:: for later. ARGUMENT:: dataSet -The link::Classes/FluidDataSet:: to normalize +The link::Classes/FluidDataSet:: to scale ARGUMENT:: action A function to run when processing is complete METHOD:: transform -Normalize a link::Classes/FluidDataSet:: into another link::Classes/FluidDataSet::, using the learned extrema from a previous call to link::Classes/FluidRobustScale#fit:: +Scale a link::Classes/FluidDataSet:: into another link::Classes/FluidDataSet::, using the learned extrema from a previous call to link::Classes/FluidRobustScale#fit:: ARGUMENT:: sourceDataSet -The link::Classes/FluidDataSet:: to normalize +The link::Classes/FluidDataSet:: to scale ARGUMENT:: destDataSet -The link::Classes/FluidDataSet:: to populate with normalized data +The link::Classes/FluidDataSet:: to populate with scaled data ARGUMENT:: action A function to run when processing is complete METHOD:: fitTransform -Normalize a link::Classes/FluidDataSet:: +Scale a link::Classes/FluidDataSet:: ARGUMENT:: sourceDataSet -The link::Classes/FluidDataSet:: to normalize +The link::Classes/FluidDataSet:: to scale ARGUMENT:: destDataSet -The link::Classes/FluidDataSet:: to populate with normalized data +The link::Classes/FluidDataSet:: to populate with scaled data ARGUMENT:: action A function to run when processing is complete METHOD:: transformPoint -Normalize a new data point, using the learned extrema from a previous call to link::Classes/FluidRobustScale#fit:: +Scale a new data point, using the learned scaling from a previous call to link::Classes/FluidRobustScale#fit:: ARGUMENT:: sourceBuffer A link::Classes/Buffer:: with the new data point ARGUMENT:: destBuffer -A link::Classes/Buffer:: to contain the normalized value +A link::Classes/Buffer:: to contain the scaled value ARGUMENT:: action A function to run when processing is complete @@ -69,11 +69,11 @@ s.boot; // FluidRobustScale.dumpAllMethods ( ~audiofile = File.realpath(FluidBufPitch.class.filenameSymbol).dirname +/+ "../AudioFiles/Tremblay-ASWINE-ScratchySynth-M.wav"; -~raw = FluidDataSet(s,\norm_help_raw); -~norm = FluidDataSet(s,\norm_help_normd); +~raw = FluidDataSet(s); +~scaled = FluidDataSet(s); ~pitch_feature = Buffer.new(s); ~stats = Buffer.alloc(s, 7, 2); -~normalizer = FluidRobustScale(s); +~robust = FluidRobustScale(s); ) // Load audio and run a pitch analysis, which gives us pitch and pitch confidence (so a 2D datum) @@ -91,7 +91,7 @@ FluidBufPitch.process(s,~audio, features: ~pitch_feature); var count = PulseCount.kr(trig) - 1; var chunkLen = (~pitch_feature.numFrames / 10).asInteger; var stats = FluidBufStats.kr( - source: ~pitch_feature, startFrame: count * chunkLen, + source: ~pitch_feature, startFrame: count * chunkLen, numFrames: chunkLen, stats: ~stats, trig: (trig * (count <=9)), blocking:1 ); var rd = BufRd.kr(2, ~stats, DC.kr(0), 0, 1);// pick only mean pitch and confidence @@ -104,16 +104,19 @@ FluidBufPitch.process(s,~audio, features: ~pitch_feature); }.play; ) -// Normalize and load to language-side array +~raw.print; +~raw.clear; + +// Scale and load to language-side array ( ~rawarray = Array.new(10); -~normedarray= Array.new(10); -~normalizer.fitTransform(~raw,~norm, { +~scaledarray= Array.new(10); +~robust.fitTransform(~raw,~scaled, { ~raw.dump{|x| 10.do{|i| ~rawarray.add(x["data"][i.asString]) }}; - ~norm.dump{|x| 10.do{|i| - ~normedarray.add(x["data"][i.asString]) + ~scaled.dump{|x| 10.do{|i| + ~scaledarray.add(x["data"][i.asString]) }}; }); ) @@ -122,14 +125,14 @@ FluidBufPitch.process(s,~audio, features: ~pitch_feature); //which can be unhelpful in many cases ( -~rawarray.flatten(1).unlace.plot("Unnormalized",Rect(0,0,400,400),minval:0,maxval:[5000,1]).plotMode=\bars; -~plot2 = ~normedarray.flatten(1).unlace.plot("Normalized",Rect(410,0,400,400)).plotMode=\bars; +~rawarray.flatten(1).unlace.plot("Raw Data",Rect(0,0,400,400),minval:0,maxval:[5000,1]).plotMode=\bars; +~plot2 = ~scaledarray.flatten(1).unlace.plot("Scaled",Rect(410,0,400,400)).plotMode=\bars; ) // single point transform on arbitrary value ~inbuf = Buffer.loadCollection(s,0.5.dup); ~outbuf = Buffer.new(s); -~normalizer.transformPoint(~inbuf,~outbuf,{|x|x.postln;x.getn(0,2,{|y|y.postln;};)}); +~robust.transformPoint(~inbuf,~outbuf,{|x|x.postln;x.getn(0,2,{|y|y.postln;};)}); OSCFunc.trace(false,true) //Server side queries @@ -149,9 +152,9 @@ OSCFunc.trace(false,true) //assemble data point BufWr.kr(avg[0],inputPoint,0); BufWr.kr(avg[1],inputPoint,1); - ~normalizer.kr(trig,inputPoint,outputPoint); + ~robust.kr(trig,inputPoint,outputPoint); Poll.kr(trig,BufRd.kr(1,inputPoint,[0,1]),["pitch (raw)", "confidence (raw)"]); - Poll.kr(trig,BufRd.kr(1,outputPoint,[0,1]),["pitch (normalized)", "confidence (normalized)"]) + Poll.kr(trig,BufRd.kr(1,outputPoint,[0,1]),["pitch (scaled)", "confidence (scaled)"]) }.play; ) :: From 39a0e9f26ae06cac4f1cdbd26b83dd318ba21d48 Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Thu, 17 Dec 2020 12:04:43 +0000 Subject: [PATCH 05/24] typo in the file --- release-packaging/HelpSource/Classes/FluidRobustScale.schelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release-packaging/HelpSource/Classes/FluidRobustScale.schelp b/release-packaging/HelpSource/Classes/FluidRobustScale.schelp index b00aec6..ff2c313 100644 --- a/release-packaging/HelpSource/Classes/FluidRobustScale.schelp +++ b/release-packaging/HelpSource/Classes/FluidRobustScale.schelp @@ -34,7 +34,7 @@ ARGUMENT:: action A function to run when processing is complete METHOD:: transform -Scale a link::Classes/FluidDataSet:: into another link::Classes/FluidDataSet::, using the learned extrema from a previous call to link::Classes/FluidRobustScale#fit:: +Scale a link::Classes/FluidDataSet:: into another link::Classes/FluidDataSet::, using the learned range from a previous call to link::Classes/FluidRobustScale#fit:: ARGUMENT:: sourceDataSet The link::Classes/FluidDataSet:: to scale ARGUMENT:: destDataSet From eb020dd3910ec3363a8188dab28e615019bc96d4 Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Thu, 17 Dec 2020 16:06:23 +0000 Subject: [PATCH 06/24] robustscale cleaned the helpfile --- release-packaging/HelpSource/Classes/FluidRobustScale.schelp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/release-packaging/HelpSource/Classes/FluidRobustScale.schelp b/release-packaging/HelpSource/Classes/FluidRobustScale.schelp index ff2c313..6606576 100644 --- a/release-packaging/HelpSource/Classes/FluidRobustScale.schelp +++ b/release-packaging/HelpSource/Classes/FluidRobustScale.schelp @@ -104,8 +104,8 @@ FluidBufPitch.process(s,~audio, features: ~pitch_feature); }.play; ) +//check the dataset ~raw.print; -~raw.clear; // Scale and load to language-side array ( @@ -133,7 +133,6 @@ FluidBufPitch.process(s,~audio, features: ~pitch_feature); ~inbuf = Buffer.loadCollection(s,0.5.dup); ~outbuf = Buffer.new(s); ~robust.transformPoint(~inbuf,~outbuf,{|x|x.postln;x.getn(0,2,{|y|y.postln;};)}); -OSCFunc.trace(false,true) //Server side queries ( From 886a3006bf72e2188e72d0e2807cc9b2d7e55e21 Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Fri, 18 Dec 2020 09:01:33 +0000 Subject: [PATCH 07/24] UMAP: removed batchSize, added fit and transform method and examples --- release-packaging/Classes/FluidUMAP.sc | 30 +++++-- .../HelpSource/Classes/FluidUMAP.schelp | 88 +++++++++++++++++-- 2 files changed, 102 insertions(+), 16 deletions(-) diff --git a/release-packaging/Classes/FluidUMAP.sc b/release-packaging/Classes/FluidUMAP.sc index 9083a3f..00c459e 100644 --- a/release-packaging/Classes/FluidUMAP.sc +++ b/release-packaging/Classes/FluidUMAP.sc @@ -1,15 +1,14 @@ FluidUMAP : FluidModelObject { - var <>numDimensions, <>numNeighbours, <>minDist, <>iterations, <>learnRate, <>batchSize; + var <>numDimensions, <>numNeighbours, <>minDist, <>iterations, <>learnRate; - *new {|server,numDimensions = 2, numNeighbours = 15, minDist = 0.1, iterations = 200, learnRate = 0.1, batchSize = 50| - ^super.new(server,[numDimensions, numNeighbours, minDist, iterations, learnRate, batchSize]) + *new {|server,numDimensions = 2, numNeighbours = 15, minDist = 0.1, iterations = 200, learnRate = 0.1| + ^super.new(server,[numDimensions, numNeighbours, minDist, iterations, learnRate]) .numDimensions_(numDimensions) .numNeighbours_(numNeighbours) .minDist_(minDist) .iterations_(iterations) - .learnRate_(learnRate) - .batchSize_(batchSize); + .learnRate_(learnRate); } prGetParams{ @@ -18,8 +17,7 @@ FluidUMAP : FluidModelObject { this.numNeighbours, this.minDist, this.iterations, - this.learnRate, - this.batchSize + this.learnRate ] } @@ -32,6 +30,24 @@ FluidUMAP : FluidModelObject { this.prSendMsg(this.fitTransformMsg(sourceDataSet,destDataSet)); } + fitMsg{|dataSet| + ^this.prMakeMsg(\fit,id, dataSet.id); + } + + fit{|dataSet, action| + actions[\fit] = [nil, action]; + this.prSendMsg(this.fitMsg(dataSet)); + } + + transformMsg{|sourceDataSet, destDataSet| + ^this.prMakeMsg(\transform, id, sourceDataSet.id, destDataSet.id); + } + + transform{|sourceDataSet, destDataSet, action| + actions[\transform] = [nil, action]; + this.prSendMsg(this.transformMsg(sourceDataSet,destDataSet)); + } + // not implemented cols {|action|} read{|filename,action|} diff --git a/release-packaging/HelpSource/Classes/FluidUMAP.schelp b/release-packaging/HelpSource/Classes/FluidUMAP.schelp index 381dea1..16d27a2 100644 --- a/release-packaging/HelpSource/Classes/FluidUMAP.schelp +++ b/release-packaging/HelpSource/Classes/FluidUMAP.schelp @@ -1,7 +1,7 @@ TITLE:: FluidUMAP summary:: Dimensionality Reduction with Uniform Manifold Approximation and Projection categories:: Dimensionality Reduction, Data Processing -related:: Classes/FluidMDS, Classes/FluidDataSet +related:: Classes/FluidMDS, Classes/FluidPCA, Classes/FluidDataSet DESCRIPTION:: @@ -53,7 +53,7 @@ code:: ~normalized = FluidDataSet(s); ~standardizer = FluidStandardize(s); ~normalizer = FluidNormalize(s); -~umap = FluidUMAP(s).numDimensions_(2).numNeighbours_(5).minDist_(0.2).iterations_(50). learnRate_(0.2).batchSize_(50); +~umap = FluidUMAP(s).numDimensions_(2).numNeighbours_(5).minDist_(0.2).iterations_(50).learnRate_(0.2); ) @@ -78,15 +78,15 @@ code:: //Visualise the 2D projection of our original 4D data ( -w = Window("scatter", Rect(128, 64, 200, 200)); +w = Window("a perspective", Rect(128, 64, 200, 200)); w.drawFunc = { - Pen.use { - ~normalizedDict.keysValuesDo{|key, val| + Pen.use { + ~normalizedDict.keysValuesDo{|key, val| Pen.fillColor = Color.new(~colours[key.asSymbol][0], ~colours[key.asSymbol][1],~colours[key.asSymbol][2]); Pen.fillOval(Rect((val[0] * 200), (val[1] * 200), 5, 5)); - ~colours[key.asSymbol].flat.postln; - } - } + ~colours[key.asSymbol].flat; + } + } }; w.refresh; w.front; @@ -95,5 +95,75 @@ w.front; //play with parameters ~umap.numNeighbours = 10; ~umap.minDist =5; -~umap.batchSize = 10; + +//rerun the UMAP +~umap.fitTransform(~standardized,~reduced,action:{"Finished UMAP".postln}); + +//draw to compare +( +~normalizer.fitTransform(~reduced,~normalized,action:{ + "Normalized Output".postln; + ~normalized.dump{|x| + ~normalizedDict = x["data"]; + + { + w = Window("another perspective", Rect(328, 64, 200, 200)); + w.drawFunc = { + Pen.use { + ~normalizedDict.keysValuesDo{|key, val| + Pen.fillColor = Color.new(~colours[key.asSymbol][0], ~colours[key.asSymbol][1],~colours[key.asSymbol][2]); + Pen.fillOval(Rect((val[0] * 200), (val[1] * 200), 5, 5)); + ~colours[key.asSymbol].flat; + }; + }; + }; + w.refresh; + w.front; + + }.defer; + + }; +}); +) + +// now run new random points on the same training material. Colours should be scattered around the same space (BUT THEY DON'T RIGHT NOW) + +~newDS = FluidDataSet(s); +~colours2 = Dictionary.newFrom(400.collect{|i|[("entry"++i).asSymbol, 3.collect{1.0.rand}]}.flatten(1)); +~newDS.load(Dictionary.newFrom([\cols, 3, \data, ~colours2])); + +//we need to standardize to the same space +~newDSstan = FluidDataSet(s); +~standardizer.transform(~newDS, ~newDSstan); + +//then we can run the umap +~newDSmap = FluidDataSet(s); +~umap.transform(~newDSstan, ~newDSmap); + +//then we can draw and look +( +~normalizer.transform(~newDSmap,~normalized,action:{ + "Normalized Output".postln; + ~normalized.dump{|x| + ~normalizedDict = x["data"]; + { + w = Window("new material", Rect(528, 64, 200, 200)); + w.drawFunc = { + Pen.use { + ~normalizedDict.keysValuesDo{|key, val| + Pen.fillColor = Color.new(~colours2[key.asSymbol][0], ~colours2[key.asSymbol][1],~colours2[key.asSymbol][2]); + Pen.fillOval(Rect((val[0] * 200), (val[1] * 200), 5, 5)); + ~colours2[key.asSymbol].flat; + }; + }; + }; + w.refresh; + w.front; + }.defer; + }; +}); +) + +//same process as above in 2 passes maybe? + :: From 0e5ad59d325d7f95459e4ac6f6f82c2f28d60a83 Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Fri, 18 Dec 2020 12:39:59 +0000 Subject: [PATCH 08/24] UMAP: updated the example --- .../HelpSource/Classes/FluidUMAP.schelp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/release-packaging/HelpSource/Classes/FluidUMAP.schelp b/release-packaging/HelpSource/Classes/FluidUMAP.schelp index 16d27a2..2eac53e 100644 --- a/release-packaging/HelpSource/Classes/FluidUMAP.schelp +++ b/release-packaging/HelpSource/Classes/FluidUMAP.schelp @@ -107,8 +107,8 @@ w.front; ~normalizedDict = x["data"]; { - w = Window("another perspective", Rect(328, 64, 200, 200)); - w.drawFunc = { + u = Window("another perspective", Rect(328, 64, 200, 200)); + u.drawFunc = { Pen.use { ~normalizedDict.keysValuesDo{|key, val| Pen.fillColor = Color.new(~colours[key.asSymbol][0], ~colours[key.asSymbol][1],~colours[key.asSymbol][2]); @@ -117,8 +117,8 @@ w.front; }; }; }; - w.refresh; - w.front; + u.refresh; + u.front; }.defer; @@ -147,8 +147,8 @@ w.front; ~normalized.dump{|x| ~normalizedDict = x["data"]; { - w = Window("new material", Rect(528, 64, 200, 200)); - w.drawFunc = { + t = Window("new material", Rect(528, 64, 200, 200)); + t.drawFunc = { Pen.use { ~normalizedDict.keysValuesDo{|key, val| Pen.fillColor = Color.new(~colours2[key.asSymbol][0], ~colours2[key.asSymbol][1],~colours2[key.asSymbol][2]); @@ -157,8 +157,8 @@ w.front; }; }; }; - w.refresh; - w.front; + t.refresh; + t.front; }.defer; }; }); From 25381e65839b9ccb8bf299c641be764096cfb829 Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Fri, 18 Dec 2020 15:51:46 +0000 Subject: [PATCH 09/24] pre-release cleaning of the helpfiles --- .../Classes/FluidAudioTransport.sc | 2 +- .../HelpSource/Classes/FluidBufAmpGate.schelp | 1 - .../Classes/FluidBufAmpSlice.schelp | 20 +++++++++---------- .../Classes/FluidBufAudioTransport.schelp | 1 - .../HelpSource/Classes/FluidBufCompose.schelp | 5 +++-- .../HelpSource/Classes/FluidBufFlatten.schelp | 11 +++++++++- .../HelpSource/Classes/FluidBufHPSS.schelp | 2 +- .../HelpSource/Classes/FluidBufNMF.schelp | 2 +- .../Classes/FluidBufNMFCross.schelp | 1 + .../HelpSource/Classes/FluidBufScale.schelp | 2 +- .../HelpSource/Classes/FluidBufStats.schelp | 1 - .../HelpSource/Classes/FluidBufThresh.schelp | 4 ++-- .../HelpSource/Classes/FluidDataSet.schelp | 3 +-- .../Classes/FluidDataSetQuery.schelp | 4 +--- .../HelpSource/Classes/FluidKDTree.schelp | 4 ++-- .../HelpSource/Classes/FluidKMeans.schelp | 7 ------- .../Classes/FluidKNNClassifier.schelp | 6 +++--- .../HelpSource/Classes/FluidMFCC.schelp | 2 +- .../Classes/FluidMLPClassifier.schelp | 5 ++--- .../HelpSource/Classes/FluidNMFMatch.schelp | 4 ++-- .../HelpSource/Classes/FluidNormalize.schelp | 1 - .../Classes/FluidRobustScale.schelp | 1 - 22 files changed, 42 insertions(+), 47 deletions(-) diff --git a/release-packaging/Classes/FluidAudioTransport.sc b/release-packaging/Classes/FluidAudioTransport.sc index e55384f..cc41b92 100644 --- a/release-packaging/Classes/FluidAudioTransport.sc +++ b/release-packaging/Classes/FluidAudioTransport.sc @@ -1,7 +1,7 @@ FluidAudioTransport : UGen { init { |...theInputs| - theInputs.postln; + theInputs; inputs = theInputs; this.specialIndex = 1; //two audio inputs // ^this.initOutputs(1,rate); diff --git a/release-packaging/HelpSource/Classes/FluidBufAmpGate.schelp b/release-packaging/HelpSource/Classes/FluidBufAmpGate.schelp index f9acdc3..b2add49 100644 --- a/release-packaging/HelpSource/Classes/FluidBufAmpGate.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufAmpGate.schelp @@ -182,7 +182,6 @@ b.play // create a new buffer as destinations c = Buffer.new(s); -OSCFunc.trace(false) //run the process on them ( // with basic params diff --git a/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp b/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp index b01fccd..68226c3 100644 --- a/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufAmpSlice.schelp @@ -145,16 +145,16 @@ b.play c = Buffer.new(s); //run the process on them - ( - // with basic params - Routine{ - var t = Main.elapsedTime; - var proc = FluidBufAmpSlice.process(s,b, indices: c, fastRampUp: 10,fastRampDown: 2205,slowRampUp: 4410,slowRampDown: 4410, onThreshold: 10,offThreshold: 5); - proc.wait; - c.query; - (Main.elapsedTime - t).postln; - }.play - ) +( + // with basic params + Routine{ + var t = Main.elapsedTime; + var proc = FluidBufAmpSlice.process(s,b, indices: c, fastRampUp: 10,fastRampDown: 2205,slowRampUp: 4410,slowRampDown: 4410, onThreshold: 10,offThreshold: 5); + proc.wait; + c.query; + (Main.elapsedTime - t).postln; + }.play +) // list the indicies of detected attacks - the two input channels have been summed. c.getn(0,c.numFrames,{|item|(item * 2).postln;}) diff --git a/release-packaging/HelpSource/Classes/FluidBufAudioTransport.schelp b/release-packaging/HelpSource/Classes/FluidBufAudioTransport.schelp index 2955970..a202579 100644 --- a/release-packaging/HelpSource/Classes/FluidBufAudioTransport.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufAudioTransport.schelp @@ -92,7 +92,6 @@ FluidBufAudioTransport.process(s,b,source2:c,destination:d,interpolation:0.5,act // listen to the source and the result b.play c.play -d.updateInfo d.play // more interesting sources: two cardboard bowing gestures diff --git a/release-packaging/HelpSource/Classes/FluidBufCompose.schelp b/release-packaging/HelpSource/Classes/FluidBufCompose.schelp index 626b58f..e28bb58 100644 --- a/release-packaging/HelpSource/Classes/FluidBufCompose.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufCompose.schelp @@ -72,8 +72,9 @@ d = Buffer.new(s); // with basic params (basic summing of each full buffer in all dimensions) ( Routine{ - FluidBufCompose.process(s, source: b, destination: d).wait; - FluidBufCompose.process(s, source: c, destination: d, destGain: 1.0).wait; + FluidBufCompose.process(s, source: b, destination: d); + FluidBufCompose.process(s, source: c, destination: d, destGain: 1.0); + s.sync; d.query; d.play; }.play; diff --git a/release-packaging/HelpSource/Classes/FluidBufFlatten.schelp b/release-packaging/HelpSource/Classes/FluidBufFlatten.schelp index 8d404a5..cd857eb 100644 --- a/release-packaging/HelpSource/Classes/FluidBufFlatten.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufFlatten.schelp @@ -83,7 +83,7 @@ b = Buffer.read(s,~randomsoundfile.path,action:{"Sound Loaded".postln}); ~flatdata = Buffer.new; ) -//Pitch analysis, writes pitches as frequecnies to chan 0, confidences [0-1] to chan 1 +//Pitch analysis, writes pitches as frequencies to chan 0, confidences [0-1] to chan 1 FluidBufPitch.process(s,b,numFrames:512 * 10,numChans:1,features:~pitchdata,action:{"Pitch Analysis Done".postln}); // Flatten and print the flat buffer. We expect to see larger numbers (20-2000) interleaved with smaller (0-1) @@ -94,4 +94,13 @@ FluidBufFlatten.process(s,~pitchdata,~flatdata,axis:1,action:{ }) }) ) + +//changing the axis, we see all large numbers first +( +FluidBufFlatten.process(s,~pitchdata,~flatdata,axis:0,action:{ + ~flatdata.loadToFloatArray(action:{ |a| + a.postln; + }) +}) +) :: diff --git a/release-packaging/HelpSource/Classes/FluidBufHPSS.schelp b/release-packaging/HelpSource/Classes/FluidBufHPSS.schelp index 11fe72f..c2b361c 100644 --- a/release-packaging/HelpSource/Classes/FluidBufHPSS.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufHPSS.schelp @@ -125,7 +125,7 @@ code:: d = Buffer.new(s); e = Buffer.new(s); ) -OSCFunc.trace(true, true) + // run with basic parameters ( Routine{ diff --git a/release-packaging/HelpSource/Classes/FluidBufNMF.schelp b/release-packaging/HelpSource/Classes/FluidBufNMF.schelp index 9f43e75..8d27b7d 100644 --- a/release-packaging/HelpSource/Classes/FluidBufNMF.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufNMF.schelp @@ -175,7 +175,7 @@ y = Buffer.new(s); ~fft_size = 1024; ~frame_size = 512; ~hop_size = 256; -~which_component = 3; +~which_component = 1; ) // matrix factorisation, requesting everything - wait for the computation time to appear. diff --git a/release-packaging/HelpSource/Classes/FluidBufNMFCross.schelp b/release-packaging/HelpSource/Classes/FluidBufNMFCross.schelp index 998b946..d5be65f 100644 --- a/release-packaging/HelpSource/Classes/FluidBufNMFCross.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufNMFCross.schelp @@ -72,5 +72,6 @@ b = Buffer.read(s,~path+/+"Nicol-LoopE-M.wav") t = Buffer.read(s,~path+/+"Tremblay-SA-UprightPianoPedalWide.wav") o = Buffer.new FluidBufNMFCross.process(s,t,b,o,action:{"Ding".postln}) +//wait for it to be done. It is a long process. o.play :: diff --git a/release-packaging/HelpSource/Classes/FluidBufScale.schelp b/release-packaging/HelpSource/Classes/FluidBufScale.schelp index a57c4a3..7107e5c 100644 --- a/release-packaging/HelpSource/Classes/FluidBufScale.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufScale.schelp @@ -70,7 +70,7 @@ Routine{ // play with the scaling FluidBufScale.process(s, b, destination: c, inputLow: 0, inputHigh: 1, outputLow: 20, outputHigh:10).wait; // retrieve the buffer and enjoy the results. - c.getn(0,10,{|x|x.postln;}) + c.getn(0,10,{|x|x.round(0.000001).postln;}) }.play ) diff --git a/release-packaging/HelpSource/Classes/FluidBufStats.schelp b/release-packaging/HelpSource/Classes/FluidBufStats.schelp index 74ac2e6..0a6a0e3 100644 --- a/release-packaging/HelpSource/Classes/FluidBufStats.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufStats.schelp @@ -186,7 +186,6 @@ c = Buffer.new(s); // run the stats and send back the values FluidBufStats.process(s, b, stats:c, numDerivs:1, action:{c.getn(0,c.numFrames * c.numChannels,{|item|d = item; d.postln})}); -OSCFunc.allEnabled //looking at the result is not easy to grasp, since it is interleaved: first number is mean of L, second is mean of R, third is stddev of L, fourth is stddev or R //this will make it tidier - the first value of each line is Left, the second is Right diff --git a/release-packaging/HelpSource/Classes/FluidBufThresh.schelp b/release-packaging/HelpSource/Classes/FluidBufThresh.schelp index 172f641..f905faa 100644 --- a/release-packaging/HelpSource/Classes/FluidBufThresh.schelp +++ b/release-packaging/HelpSource/Classes/FluidBufThresh.schelp @@ -59,7 +59,7 @@ c = Buffer(s) // play with the threshold FluidBufThresh.process(s, b, destination: c, threshold: 0.5) // retrieve the buffer and enjoy the results. -c.getn(0,11,{|x|x.postln;}) +c.getn(0,11,{|x|x.round(0.000001).postln;}) // also works in multichannel - explore the following buffer b = Buffer.sendCollection(s,0.0.series(0.1,2.0).scramble,2) @@ -77,5 +77,5 @@ FluidBufThresh.process(s, b,startFrame: 3,numFrames: 4,startChan: 1,numChans: 1, //enjoy c.plot(separately: true).plotMode_(\points) c.query -c.getn(0,4,{|x|x.postln;}) +c.getn(0,4,{|x|x.round(0.000001).postln;}) :: diff --git a/release-packaging/HelpSource/Classes/FluidDataSet.schelp b/release-packaging/HelpSource/Classes/FluidDataSet.schelp index 4e6818e..7895827 100644 --- a/release-packaging/HelpSource/Classes/FluidDataSet.schelp +++ b/release-packaging/HelpSource/Classes/FluidDataSet.schelp @@ -123,7 +123,6 @@ fork{ :: STRONG:: Merging Datasets:: -s.dumpOSC code:: //this is how to add items between 2 datasets. //create 2 datasets @@ -131,7 +130,7 @@ code:: ~dsA = FluidDataSet.new(s); ~dsB = FluidDataSet.new(s); ) -Dictionary.new + //feed them items with same dimensions but different labels ~dsA.load(Dictionary.newFrom([\cols, 1, \data, Dictionary.newFrom([\one,1,\two,2])])); ~dsB.load(Dictionary.newFrom([\cols, 1, \data, Dictionary.newFrom([\three,3,\four,4])])); diff --git a/release-packaging/HelpSource/Classes/FluidDataSetQuery.schelp b/release-packaging/HelpSource/Classes/FluidDataSetQuery.schelp index 9b1d57d..9132ac1 100644 --- a/release-packaging/HelpSource/Classes/FluidDataSetQuery.schelp +++ b/release-packaging/HelpSource/Classes/FluidDataSetQuery.schelp @@ -120,9 +120,8 @@ fork{ s.sync; ~points.do{|x,i| ~tmpbuf.setn(0,x); - s.sync; ~dataSet.addPoint(i,~tmpbuf); - // s.sync + s.sync; } } ) @@ -137,7 +136,6 @@ fork{ // prepare a simple query ~query.filter(0,"<",0.04); ~query.addColumn(2); -s.dumpOSC ~query.transform(~dataSet, ~out); // check the result diff --git a/release-packaging/HelpSource/Classes/FluidKDTree.schelp b/release-packaging/HelpSource/Classes/FluidKDTree.schelp index cb25c2f..4ea497a 100644 --- a/release-packaging/HelpSource/Classes/FluidKDTree.schelp +++ b/release-packaging/HelpSource/Classes/FluidKDTree.schelp @@ -98,7 +98,7 @@ fork{ // Limit the search to an acceptable distance in a radius // Define a point, and observe typical distance values -~p = [ 0.2,0.2]; +~p = [ 0.4,0.4]; ( ~tmpbuf = Buffer.loadCollection(s, ~p, 1, { ~tree.kNearestDist(~tmpbuf,{ |a|a.postln;~nearest = a;}); @@ -129,7 +129,7 @@ For instance, whilst fitting the tree against some n-dimensional descriptor data code:: - ,( +( Routine{ var inputBuffer = Buffer.alloc(s,2); var outputBuffer = Buffer.alloc(s,10);//5 neighbours * 2D data points diff --git a/release-packaging/HelpSource/Classes/FluidKMeans.schelp b/release-packaging/HelpSource/Classes/FluidKMeans.schelp index 547a21d..4de6839 100644 --- a/release-packaging/HelpSource/Classes/FluidKMeans.schelp +++ b/release-packaging/HelpSource/Classes/FluidKMeans.schelp @@ -67,7 +67,6 @@ A function to run when complete, taking an array of the counts for each category EXAMPLES:: -Server.default.options.outDevice = "Built-in Output" code:: ( @@ -106,10 +105,6 @@ fork{ ~kmeans.size; ~kmeans.dump; - ~clusters.getLabel(0,{|clusterID| - (0.asString+clusterID).postln; -}); - // Retrieve labels of clustered points ( ~assignments = Array.new(128); @@ -157,8 +152,6 @@ subsection:: Queries in a Synth This is the equivalent of predictPoint, but wholly on the server code:: - -outputPoint.getToFloatArray(action:{|a|a.postln}) ( { var trig = Impulse.kr(5); diff --git a/release-packaging/HelpSource/Classes/FluidKNNClassifier.schelp b/release-packaging/HelpSource/Classes/FluidKNNClassifier.schelp index 9f882a1..9166851 100644 --- a/release-packaging/HelpSource/Classes/FluidKNNClassifier.schelp +++ b/release-packaging/HelpSource/Classes/FluidKNNClassifier.schelp @@ -62,7 +62,7 @@ code:: ~test = FluidDataSet(s); ~mapping = FluidLabelSet(s); ) -s.dumpOSC + //Make some clumped 2D points and place into a DataSet ( ~examplepoints = [[0.5,0.5],[-0.5,0.5],[0.5,-0.5],[-0.5,-0.5]]; @@ -93,7 +93,7 @@ d = Dictionary.with( ~classifier.predict(~test, ~mapping, 1); ) -//Return labels of clustered points +//Return labels of clustered points - wait for the dump to be done ( ~assignments = Array.new(~testpoints.size); fork{ @@ -175,7 +175,7 @@ code:: var outputPoint = LocalBuf(1); point.collect{|p,i| BufWr.kr([p],inputPoint,i)}; ~classifier.kr(trig,inputPoint,outputPoint); - SinOsc.ar((BufRd.kr(1,outputPoint,0,interpolation:0) + 69).midicps,mul: 0.1); + SinOsc.ar((BufRd.kr(1,outputPoint,0,interpolation:0) + 69).midicps, mul: 0.1); }.play ) :: diff --git a/release-packaging/HelpSource/Classes/FluidMFCC.schelp b/release-packaging/HelpSource/Classes/FluidMFCC.schelp index b799bbb..dac7a3f 100644 --- a/release-packaging/HelpSource/Classes/FluidMFCC.schelp +++ b/release-packaging/HelpSource/Classes/FluidMFCC.schelp @@ -89,7 +89,7 @@ x = {arg type = 0; // change the wave types, observe the amplitude invariance of the descriptors, apart from the leftmost coefficient x.set(\type, 1) -~winRange = 50; //adjust the range above and below 0 to zoom in or out on the MFCC +~winRange = 5; //adjust the range above and below 0 to zoom in or out on the MFCC x.set(\type, 2) x.set(\type, 0) // free this source diff --git a/release-packaging/HelpSource/Classes/FluidMLPClassifier.schelp b/release-packaging/HelpSource/Classes/FluidMLPClassifier.schelp index 6522cd9..f58b84f 100644 --- a/release-packaging/HelpSource/Classes/FluidMLPClassifier.schelp +++ b/release-packaging/HelpSource/Classes/FluidMLPClassifier.schelp @@ -124,10 +124,9 @@ code:: //Run the test data through the network, into the predicted labelset ~classifier.predict(~testdata,~predictedlabels,action:{"Test complete".postln}); -OSCFunc.trace(true,true) -OSCFunc.allEnabled + //get labels from server -~predictedlabels.dump(action:{|d|~labelsdict = d["data"]};~labelsdict.postln); +~predictedlabels.dump(action:{|d| ~labelsdict = d["data"]; ~labelsdict.postln}); //Visualise: we're hoping to see colours neatly mapped to quandrants... ( diff --git a/release-packaging/HelpSource/Classes/FluidNMFMatch.schelp b/release-packaging/HelpSource/Classes/FluidNMFMatch.schelp index 9c44521..a98d2bd 100644 --- a/release-packaging/HelpSource/Classes/FluidNMFMatch.schelp +++ b/release-packaging/HelpSource/Classes/FluidNMFMatch.schelp @@ -112,7 +112,7 @@ c = Buffer.new(s); // train only 2 seconds ( Routine { - FluidBufNMF.process(s,b,0,88200,0,1, c, ~bases, components:10,fftSize:2048); + FluidBufNMF.process(s,b,0,88200,0,1, c, ~bases, components:10,fftSize:2048).wait; c.query; }.play; ) @@ -197,7 +197,7 @@ c = Buffer.new(s); // train only 2 seconds ( Routine { - FluidBufNMF.process(s,b,0,88200,0,1, c, ~bases, components:8, hopSize:256, fftSize:2048); + FluidBufNMF.process(s,b,0,88200,0,1, c, ~bases, components:8, hopSize:256, fftSize:2048).wait; c.query; }.play; ) diff --git a/release-packaging/HelpSource/Classes/FluidNormalize.schelp b/release-packaging/HelpSource/Classes/FluidNormalize.schelp index 9838cec..b073ce3 100644 --- a/release-packaging/HelpSource/Classes/FluidNormalize.schelp +++ b/release-packaging/HelpSource/Classes/FluidNormalize.schelp @@ -130,7 +130,6 @@ FluidBufPitch.process(s,~audio, features: ~pitch_feature); ~inbuf = Buffer.loadCollection(s,0.5.dup); ~outbuf = Buffer.new(s); ~normalizer.transformPoint(~inbuf,~outbuf,{|x|x.postln;x.getn(0,2,{|y|y.postln;};)}); -OSCFunc.trace(false,true) //Server side queries ( diff --git a/release-packaging/HelpSource/Classes/FluidRobustScale.schelp b/release-packaging/HelpSource/Classes/FluidRobustScale.schelp index 6606576..6e4c1b0 100644 --- a/release-packaging/HelpSource/Classes/FluidRobustScale.schelp +++ b/release-packaging/HelpSource/Classes/FluidRobustScale.schelp @@ -66,7 +66,6 @@ EXAMPLES:: code:: s.boot; //Preliminaries: we want some audio, a couple of FluidDataSets, some Buffers and a FluidRobustScale -// FluidRobustScale.dumpAllMethods ( ~audiofile = File.realpath(FluidBufPitch.class.filenameSymbol).dirname +/+ "../AudioFiles/Tremblay-ASWINE-ScratchySynth-M.wav"; ~raw = FluidDataSet(s); From 4f4b87e85d2f914cb7d2e477192575be58d509f9 Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Sat, 19 Dec 2020 20:39:46 +0000 Subject: [PATCH 10/24] UMAP: updated parameters curated by @groma --- release-packaging/HelpSource/Classes/FluidUMAP.schelp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/release-packaging/HelpSource/Classes/FluidUMAP.schelp b/release-packaging/HelpSource/Classes/FluidUMAP.schelp index 2eac53e..9d1ac1e 100644 --- a/release-packaging/HelpSource/Classes/FluidUMAP.schelp +++ b/release-packaging/HelpSource/Classes/FluidUMAP.schelp @@ -94,7 +94,9 @@ w.front; //play with parameters ~umap.numNeighbours = 10; -~umap.minDist =5; +~umap.minDist = 0.5; +~umap.learnRate = 0.1; +~umap.iterations = 100; //rerun the UMAP ~umap.fitTransform(~standardized,~reduced,action:{"Finished UMAP".postln}); @@ -126,7 +128,7 @@ w.front; }); ) -// now run new random points on the same training material. Colours should be scattered around the same space (BUT THEY DON'T RIGHT NOW) +// now run new random points on the same training material. Colours should be scattered around the same space ~newDS = FluidDataSet(s); ~colours2 = Dictionary.newFrom(400.collect{|i|[("entry"++i).asSymbol, 3.collect{1.0.rand}]}.flatten(1)); From caff6c3c297ec2ec6a198f1024ffb032954df3ba Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Mon, 21 Dec 2020 09:24:15 +0000 Subject: [PATCH 11/24] umap: improved class definition and help example --- release-packaging/Classes/FluidUMAP.sc | 3 -- .../HelpSource/Classes/FluidUMAP.schelp | 40 ++++++++++++++++--- 2 files changed, 34 insertions(+), 9 deletions(-) diff --git a/release-packaging/Classes/FluidUMAP.sc b/release-packaging/Classes/FluidUMAP.sc index 00c459e..bf4f252 100644 --- a/release-packaging/Classes/FluidUMAP.sc +++ b/release-packaging/Classes/FluidUMAP.sc @@ -50,8 +50,5 @@ FluidUMAP : FluidModelObject { // not implemented cols {|action|} - read{|filename,action|} - write{|filename,action|} size { |action|} - } diff --git a/release-packaging/HelpSource/Classes/FluidUMAP.schelp b/release-packaging/HelpSource/Classes/FluidUMAP.schelp index 9d1ac1e..9c63a7c 100644 --- a/release-packaging/HelpSource/Classes/FluidUMAP.schelp +++ b/release-packaging/HelpSource/Classes/FluidUMAP.schelp @@ -52,7 +52,7 @@ code:: ~reduced = FluidDataSet(s); ~normalized = FluidDataSet(s); ~standardizer = FluidStandardize(s); -~normalizer = FluidNormalize(s); +~normalizer = FluidNormalize(s, 0.05, 0.95); ~umap = FluidUMAP(s).numDimensions_(2).numNeighbours_(5).minDist_(0.2).iterations_(50).learnRate_(0.2); ) @@ -93,10 +93,7 @@ w.front; ) //play with parameters -~umap.numNeighbours = 10; -~umap.minDist = 0.5; -~umap.learnRate = 0.1; -~umap.iterations = 100; +~umap.numNeighbours_(10).minDist_(0.5).iterations_(100).learnRate_(0.1); //rerun the UMAP ~umap.fitTransform(~standardized,~reduced,action:{"Finished UMAP".postln}); @@ -166,6 +163,37 @@ w.front; }); ) -//same process as above in 2 passes maybe? +//if we process the original dataset, we will see small differences in positions +~reduced2 = FluidDataSet(s); +~umap.transform(~standardized, ~reduced2, action: {\done.postln;}); + +//then we can draw and look +( +~normalizer.transform(~reduced2,~normalized,action:{ + "Normalized Output".postln; + ~normalized.dump{|x| + ~normalizedDict = x["data"]; + { + t = Window("old material", Rect(728, 64, 200, 200)); + t.drawFunc = { + Pen.use { + ~normalizedDict.keysValuesDo{|key, val| + Pen.fillColor = Color.new(~colours[key.asSymbol][0], ~colours[key.asSymbol][1],~colours[key.asSymbol][2]); + Pen.fillOval(Rect((val[0] * 200), (val[1] * 200), 5, 5)); + ~colours[key.asSymbol].flat; + }; + }; + }; + t.refresh; + t.front; + }.defer; + }; +}); +) + +//this is because the fitTransform method has the advantage of being certain that the data it transforms is the one that has been used to fit the model. This allows for more accurate distance measurement. + +//poking at the data structure within +~umap.dump{|x|x.keys.do{|i|"%: %\n".postf(i,x[i]);}} :: From ecd26f436dff41debec8041ad74523f48b6e8dee Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Mon, 21 Dec 2020 09:27:46 +0000 Subject: [PATCH 12/24] umap: updated helpfile with fit and transform --- .../HelpSource/Classes/FluidUMAP.schelp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/release-packaging/HelpSource/Classes/FluidUMAP.schelp b/release-packaging/HelpSource/Classes/FluidUMAP.schelp index 9c63a7c..a756ca9 100644 --- a/release-packaging/HelpSource/Classes/FluidUMAP.schelp +++ b/release-packaging/HelpSource/Classes/FluidUMAP.schelp @@ -32,6 +32,22 @@ INSTANCEMETHODS:: PRIVATE:: init +METHOD:: fit +Train this model on a link::Classes/FluidDataSet:: but don't transform the data +ARGUMENT:: dataSet +A link::Classes/FluidDataSet:: to analyse +ARGUMENT:: action +Run when done + +METHOD:: transform +Given a trained model, apply the reduction to a source link::Classes/FluidDataSet:: and write to a destination. Can be the same for both (in-place) +ARGUMENT:: sourceDataSet +Source data, or the DataSet name +ARGUMENT:: destDataSet +Destination data, or the DataSet name +ARGUMENT:: action +Run when done. + METHOD:: fitTransform Fit the model to a link::Classes/FluidDataSet:: and write the new projected data to a destination FluidDataSet. ARGUMENT:: sourceDataSet From 2eec5f7cd7ab17400921ce8ab3cbe395bb75b9ad Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Mon, 21 Dec 2020 09:58:12 +0000 Subject: [PATCH 13/24] std, norm and scaler: now we can see all elements (and other typo corrections) --- release-packaging/HelpSource/Classes/FluidNormalize.schelp | 4 ++-- .../HelpSource/Classes/FluidRobustScale.schelp | 4 ++-- .../HelpSource/Classes/FluidStandardize.schelp | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/release-packaging/HelpSource/Classes/FluidNormalize.schelp b/release-packaging/HelpSource/Classes/FluidNormalize.schelp index b073ce3..4e21707 100644 --- a/release-packaging/HelpSource/Classes/FluidNormalize.schelp +++ b/release-packaging/HelpSource/Classes/FluidNormalize.schelp @@ -122,8 +122,8 @@ FluidBufPitch.process(s,~audio, features: ~pitch_feature); //which can be unhelpful in many cases ( -~rawarray.flatten(1).unlace.plot("Unnormalized",Rect(0,0,400,400),minval:0,maxval:[5000,1]).plotMode=\bars; -~plot2 = ~normedarray.flatten(1).unlace.plot("Normalized",Rect(410,0,400,400)).plotMode=\bars; +(~rawarray ++ 0).flop.plot("Unnormalized",Rect(0,0,400,400),minval:0,maxval:[5000,1]).plotMode=\bars; +(~normedarray ++ 0).flop.plot("Normalized",Rect(410,0,400,400)).plotMode=\bars; ) // single point transform on arbitrary value diff --git a/release-packaging/HelpSource/Classes/FluidRobustScale.schelp b/release-packaging/HelpSource/Classes/FluidRobustScale.schelp index 6e4c1b0..85848a0 100644 --- a/release-packaging/HelpSource/Classes/FluidRobustScale.schelp +++ b/release-packaging/HelpSource/Classes/FluidRobustScale.schelp @@ -124,8 +124,8 @@ FluidBufPitch.process(s,~audio, features: ~pitch_feature); //which can be unhelpful in many cases ( -~rawarray.flatten(1).unlace.plot("Raw Data",Rect(0,0,400,400),minval:0,maxval:[5000,1]).plotMode=\bars; -~plot2 = ~scaledarray.flatten(1).unlace.plot("Scaled",Rect(410,0,400,400)).plotMode=\bars; +(~rawarray ++ 0).flop.plot("Raw Data",Rect(0,0,400,400),minval:0,maxval:[5000,1]).plotMode=\bars; +(~scaledarray ++ 0).flop.plot("Scaled",Rect(410,0,400,400), minval:-2,maxval:2).plotMode=\bars; ) // single point transform on arbitrary value diff --git a/release-packaging/HelpSource/Classes/FluidStandardize.schelp b/release-packaging/HelpSource/Classes/FluidStandardize.schelp index 8dca74f..c4d3b2b 100644 --- a/release-packaging/HelpSource/Classes/FluidStandardize.schelp +++ b/release-packaging/HelpSource/Classes/FluidStandardize.schelp @@ -1,7 +1,7 @@ TITLE:: FluidStandardize summary:: Standardize a FluidDataSet categories:: FluidManipulation -related:: Classes/FluidDataSet, Classes/FluidStandardize, Classes/FluidRobustScale +related:: Classes/FluidDataSet, Classes/FluidNormalize, Classes/FluidRobustScale DESCRIPTION:: Standardize a link::Classes/FluidDataSet::, i.e. rescale using its mean(s) and standard deviation(s) in each dimension. @@ -112,8 +112,8 @@ FluidBufPitch.process(s,~audio, features: ~pitch_feature,action:{"Analysed Pitch ) ( -~rawarray.flatten(1).unlace.plot("Unstandardized",Rect(0,0,400,400),minval:0,maxval:[5000,1]).plotMode=\bars; -~plot2 = ~stdarray.flatten(1).unlace.plot("Standardized",Rect(410,0,400,400)).plotMode=\bars; +(~rawarray ++ 0).flop.plot("Unstandardized",Rect(0,0,400,400),minval:0,maxval:[5000,1]).plotMode=\bars; +(~stdarray ++ 0).flop.plot("Standardized",Rect(410,0,400,400), minval:-2,maxval:2).plotMode=\bars; ) // single point transform on arbitrary value From 82d6a2b355fede109698332222781859e104ce0f Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Mon, 21 Dec 2020 11:50:41 +0000 Subject: [PATCH 14/24] UMAP: transformPoint method def, and example in help file --- release-packaging/Classes/FluidUMAP.sc | 14 ++++++++++++++ .../HelpSource/Classes/FluidUMAP.schelp | 17 +++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/release-packaging/Classes/FluidUMAP.sc b/release-packaging/Classes/FluidUMAP.sc index bf4f252..48a9cbb 100644 --- a/release-packaging/Classes/FluidUMAP.sc +++ b/release-packaging/Classes/FluidUMAP.sc @@ -48,6 +48,20 @@ FluidUMAP : FluidModelObject { this.prSendMsg(this.transformMsg(sourceDataSet,destDataSet)); } + + transformPointMsg{|sourceBuffer, destBuffer| + ^this.prMakeMsg(\transformPoint,id, + this.prEncodeBuffer(sourceBuffer), + this.prEncodeBuffer(destBuffer), + ["/b_query",destBuffer.asUGenInput] + ); + } + + transformPoint{|sourceBuffer, destBuffer, action| + actions[\transformPoint] = [nil,{action.value(destBuffer)}]; + this.prSendMsg(this.transformPointMsg(sourceBuffer,destBuffer)); + } + // not implemented cols {|action|} size { |action|} diff --git a/release-packaging/HelpSource/Classes/FluidUMAP.schelp b/release-packaging/HelpSource/Classes/FluidUMAP.schelp index a756ca9..699bf22 100644 --- a/release-packaging/HelpSource/Classes/FluidUMAP.schelp +++ b/release-packaging/HelpSource/Classes/FluidUMAP.schelp @@ -209,6 +209,23 @@ w.front; //this is because the fitTransform method has the advantage of being certain that the data it transforms is the one that has been used to fit the model. This allows for more accurate distance measurement. +//to check, let's retrieve a single point and predict its position +( +~sourcePoint = Buffer(s); +~original = Buffer(s); +~standed = Buffer(s); +~umaped = Buffer(s); +) + +//retrieve the 3D original +~raw.getPoint("entry50",~sourcePoint) +//retrieve the fitTransformed point as the most accurate point +~reduced.getPoint("entry50",~original, {~original.getn(0,2,{|x|x.postln})}) +//retreive the transformed point, via the standardizer +~standardizer.transformPoint(~sourcePoint,~standed); +~umap.transformPoint(~standed, ~umaped, {~umaped.getn(0,2,{|x|x.postln})}) + + //poking at the data structure within ~umap.dump{|x|x.keys.do{|i|"%: %\n".postf(i,x[i]);}} From dc3157c5ebdd8da8ab22fb886b5e06ff7444d635 Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Mon, 21 Dec 2020 15:57:45 +0000 Subject: [PATCH 15/24] UMAP: added KR and example testing --- release-packaging/Classes/FluidUMAP.sc | 21 ++++++++++-- .../HelpSource/Classes/FluidUMAP.schelp | 34 +++++++++++++++---- src/FluidManipulation/FluidManipulation.cpp | 2 +- 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/release-packaging/Classes/FluidUMAP.sc b/release-packaging/Classes/FluidUMAP.sc index 48a9cbb..9a2835d 100644 --- a/release-packaging/Classes/FluidUMAP.sc +++ b/release-packaging/Classes/FluidUMAP.sc @@ -1,4 +1,4 @@ -FluidUMAP : FluidModelObject { +FluidUMAP : FluidRealTimeModel { var <>numDimensions, <>numNeighbours, <>minDist, <>iterations, <>learnRate; @@ -17,7 +17,8 @@ FluidUMAP : FluidModelObject { this.numNeighbours, this.minDist, this.iterations, - this.learnRate + this.learnRate, + -1,-1 ] } @@ -62,6 +63,22 @@ FluidUMAP : FluidModelObject { this.prSendMsg(this.transformPointMsg(sourceBuffer,destBuffer)); } + kr{|trig, inputBuffer,outputBuffer,numDimensions| + + numDimensions = numDimensions ? this.numDimensions; + this.numDimensions_(numDimensions); + + ^FluidProxyUgen.kr(this.class.name.asString++'/query', K2A.ar(trig), + id, + this.numDimensions, + this.numNeighbours, + this.minDist, + this.iterations, + this.learnRate, + this.prEncodeBuffer(inputBuffer), + this.prEncodeBuffer(outputBuffer)); + } + // not implemented cols {|action|} size { |action|} diff --git a/release-packaging/HelpSource/Classes/FluidUMAP.schelp b/release-packaging/HelpSource/Classes/FluidUMAP.schelp index 699bf22..16774e0 100644 --- a/release-packaging/HelpSource/Classes/FluidUMAP.schelp +++ b/release-packaging/HelpSource/Classes/FluidUMAP.schelp @@ -190,8 +190,8 @@ w.front; ~normalized.dump{|x| ~normalizedDict = x["data"]; { - t = Window("old material", Rect(728, 64, 200, 200)); - t.drawFunc = { + z = Window("old material", Rect(728, 64, 200, 200)); + z.drawFunc = { Pen.use { ~normalizedDict.keysValuesDo{|key, val| Pen.fillColor = Color.new(~colours[key.asSymbol][0], ~colours[key.asSymbol][1],~colours[key.asSymbol][2]); @@ -200,8 +200,8 @@ w.front; }; }; }; - t.refresh; - t.front; + z.refresh; + z.front; }.defer; }; }); @@ -218,15 +218,35 @@ w.front; ) //retrieve the 3D original -~raw.getPoint("entry50",~sourcePoint) +~raw.getPoint("entry49",~sourcePoint) //retrieve the fitTransformed point as the most accurate point -~reduced.getPoint("entry50",~original, {~original.getn(0,2,{|x|x.postln})}) +~reduced.getPoint("entry49",~original, {~original.getn(0,2,{|x|x.postln})}) //retreive the transformed point, via the standardizer ~standardizer.transformPoint(~sourcePoint,~standed); ~umap.transformPoint(~standed, ~umaped, {~umaped.getn(0,2,{|x|x.postln})}) - //poking at the data structure within ~umap.dump{|x|x.keys.do{|i|"%: %\n".postf(i,x[i]);}} +// one can also retrieve in control rate with Server Side Queries +// Let's map our learned UMAP dimensions to the controls of a processor + +( +{ + var trig = Impulse.kr(1); + var point = WhiteNoise.kr(1.dup(3)); + var inputPoint = LocalBuf(3); + var standPoint = LocalBuf(3); + var outputPoint = LocalBuf(2); + var cue1, cue2; + Poll.kr(trig, point, [\pointX,\pointY,\pointZ]); + point.collect{ |p,i| BufWr.kr([p],inputPoint,i)}; + cue1 = ~standardizer.kr(trig,inputPoint,standPoint); + Poll.kr(cue1,BufRd.kr(1,standPoint,(0..2),interpolation:0),[\stdX,\stdY, \stdZ]); + cue2 = ~umap.kr(cue1, standPoint, outputPoint); + Poll.kr(cue2,BufRd.kr(1,outputPoint,[0,1],interpolation:0),[\newDimA,\newDimB]); + Silent.ar; +}.play; +) + :: diff --git a/src/FluidManipulation/FluidManipulation.cpp b/src/FluidManipulation/FluidManipulation.cpp index 7b23652..9442611 100644 --- a/src/FluidManipulation/FluidManipulation.cpp +++ b/src/FluidManipulation/FluidManipulation.cpp @@ -38,7 +38,7 @@ PluginLoad(FluidSTFTUGen) makeSCWrapper("FluidStandardize",ft); makeSCWrapper("FluidPCA",ft); makeSCWrapper("FluidMDS",ft); - makeSCWrapper("FluidUMAP",ft); + makeSCWrapper("FluidUMAP",ft); makeSCWrapper("FluidAudioTransport",ft); makeSCWrapper("FluidBufAudioTransp",ft); makeSCWrapper("FluidDataSetWr", ft); From f932628538fef70077fdeb94032f1593205d0108 Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Mon, 21 Dec 2020 17:55:17 +0000 Subject: [PATCH 16/24] new interface for DataSet and LabelSet helpfiles --- .../HelpSource/Classes/FluidDataSet.schelp | 17 ++--------------- .../HelpSource/Classes/FluidLabelSet.schelp | 11 +---------- 2 files changed, 3 insertions(+), 25 deletions(-) diff --git a/release-packaging/HelpSource/Classes/FluidDataSet.schelp b/release-packaging/HelpSource/Classes/FluidDataSet.schelp index 7895827..790f42f 100644 --- a/release-packaging/HelpSource/Classes/FluidDataSet.schelp +++ b/release-packaging/HelpSource/Classes/FluidDataSet.schelp @@ -1,7 +1,7 @@ TITLE:: FluidDataSet summary:: Container for labelled, multidimensional data categories:: UGens>FluidManipulation -related:: Classes/FluidLabelSet, Classes/FluidKDTree, Classes/FluidKNN, Classes/FluidKMeans +related:: Classes/FluidLabelSet, Classes/FluidKDTree, Classes/FluidKMeans ​ DESCRIPTION:: A server-side container associating labels with multi-dimensional data. FluidDataSet is identified by its name. @@ -15,20 +15,10 @@ Create a new instance of the DataSet, with the given name. If a DataSet with thi ARGUMENT:: server The link::Classes/Server:: on which to create the data set. -ARGUMENT:: name -A symbol with the name of the DataSet. + ​ returns:: The new instance -METHOD:: at -Retrieves a cached instance of a FluidDataSet with the given name, or returns nil if no such object exists. - -ARGUMENT:: server -The server associated with this DataSet instance. -ARGUMENT:: name -The name of the DataSet to retrieve from the cache. - - INSTANCEMETHODS:: ​ PRIVATE:: init,id,cache @@ -63,9 +53,6 @@ Destroy the object on the server. METHOD:: print Post an abbreviated content of the DataSet in the window by default, but you can supply a custom action instead. -​​ -METHOD:: synth -The internal synth the object uses to communicate with the server returns:: A link::Classes/Synth:: ​ diff --git a/release-packaging/HelpSource/Classes/FluidLabelSet.schelp b/release-packaging/HelpSource/Classes/FluidLabelSet.schelp index a29d3d6..91ee776 100644 --- a/release-packaging/HelpSource/Classes/FluidLabelSet.schelp +++ b/release-packaging/HelpSource/Classes/FluidLabelSet.schelp @@ -13,15 +13,6 @@ METHOD:: new Make a new instance of a label set, uniquely identified by its name. Creating an instance with a name already in use will throw an exception. Use link::Classes/FluidLabelSet#*at:: or free the existing instance. ARGUMENT:: server The link::Classes/Server:: on which to create the label set. -ARGUMENT:: name -symbol with the label set's name. - -METHOD:: at -Retrieve a label set from the cache. -ARGUMENT:: server -The link::Classes/Server:: on which to create the label set. -ARGUMENT:: name -symbol or string with the label set's name. INSTANCEMETHODS:: @@ -30,7 +21,7 @@ PRIVATE:: init, id METHOD:: addLabel Add a label to the label set. -ARGUMENT:: id +ARGUMENT:: identifier symbol or string with the ID for this label. ARGUMENT:: label symbol or string with the label to add. From d4049a4f6c28a1941e7d01d138f09c51d9cea989 Mon Sep 17 00:00:00 2001 From: Owen Green Date: Mon, 21 Dec 2020 18:28:46 +0000 Subject: [PATCH 17/24] Fix data object cache lookup --- release-packaging/Classes/FluidServerObject.sc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release-packaging/Classes/FluidServerObject.sc b/release-packaging/Classes/FluidServerObject.sc index 6cc9458..bbb342e 100644 --- a/release-packaging/Classes/FluidServerObject.sc +++ b/release-packaging/Classes/FluidServerObject.sc @@ -229,7 +229,7 @@ FluidDataObject : FluidServerObject } *cachedInstanceAt{|server,id| - this.initCache; + this.initCache(server); ^serverCaches[this].at(server,id); } From 473d6e3cdf1206310aa6b64400f1329649381338 Mon Sep 17 00:00:00 2001 From: Gerard Date: Mon, 21 Dec 2020 22:46:45 +0100 Subject: [PATCH 18/24] JSON: replace null for nil --- release-packaging/Classes/FluidManipulationJSON.sc | 1 + 1 file changed, 1 insertion(+) diff --git a/release-packaging/Classes/FluidManipulationJSON.sc b/release-packaging/Classes/FluidManipulationJSON.sc index 875902b..3638c12 100644 --- a/release-packaging/Classes/FluidManipulationJSON.sc +++ b/release-packaging/Classes/FluidManipulationJSON.sc @@ -46,6 +46,7 @@ $},{ if(inString.not){parsed[pos] = $)} } ) }); + parsed = parsed.replace("null","nil"); ^this.toDict(parsed.interpret); } From afa65115a070ec970692d3dc41a665861eb508ad Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Tue, 22 Dec 2020 08:58:13 +0000 Subject: [PATCH 19/24] UMAP: removed batchSize from help --- release-packaging/HelpSource/Classes/FluidUMAP.schelp | 2 -- 1 file changed, 2 deletions(-) diff --git a/release-packaging/HelpSource/Classes/FluidUMAP.schelp b/release-packaging/HelpSource/Classes/FluidUMAP.schelp index 16774e0..dce0210 100644 --- a/release-packaging/HelpSource/Classes/FluidUMAP.schelp +++ b/release-packaging/HelpSource/Classes/FluidUMAP.schelp @@ -25,8 +25,6 @@ ARGUMENT:: iterations The number of iterations that the algorithm will go through to optimise the new representation ARGUMENT:: learnRate The learning rate of the algorithm, aka how much of the error it uses to estimate the next iteration. -ARGUMENT:: batchSize -The training batch size. INSTANCEMETHODS:: From e1e74cad496b11929e17fcb5571d4bd21a13a40d Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Tue, 22 Dec 2020 09:00:08 +0000 Subject: [PATCH 20/24] PCA: reformulate variance explanation --- release-packaging/HelpSource/Classes/FluidPCA.schelp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/release-packaging/HelpSource/Classes/FluidPCA.schelp b/release-packaging/HelpSource/Classes/FluidPCA.schelp index 3b897fb..e7b43e2 100644 --- a/release-packaging/HelpSource/Classes/FluidPCA.schelp +++ b/release-packaging/HelpSource/Classes/FluidPCA.schelp @@ -36,7 +36,7 @@ Source data, or the DataSet name ARGUMENT:: destDataSet Destination data, or the DataSet name ARGUMENT:: action -Run when done. The variance is passed as an argument, aka the fidelity of the new representation: a value near 1.0 means a higher fidelity to the original. +Run when done. The fraction of accounted variance is passed as an argument, aka the fidelity of the new representation: a value near 1.0 means a higher fidelity to the original. METHOD:: fitTransform link::Classes/FluidPCA#fit:: and link::Classes/FluidPCA#transform:: in a single pass @@ -45,7 +45,7 @@ Source data, or the DataSet name ARGUMENT:: destDataSet Destination data, or the DataSet name ARGUMENT:: action -Run when done. The variance is passed as an argument, aka the fidelity of the new representation: a value near 1.0 means a higher fidelity to the original. +Run when done. The fraction of accounted variance is passed as an argument, aka the fidelity of the new representation: a value near 1.0 means a higher fidelity to the original. METHOD:: transformPoint Given a trained model, transform the data point in a link::Classes/Buffer:: and write to an output From de2f9ec2a1a1453c39c5812842749d47a8554e6f Mon Sep 17 00:00:00 2001 From: Gerard Date: Tue, 22 Dec 2020 11:38:42 +0100 Subject: [PATCH 21/24] Revert "JSON: replace null for nil" This reverts commit 473d6e3cdf1206310aa6b64400f1329649381338. --- release-packaging/Classes/FluidManipulationJSON.sc | 1 - 1 file changed, 1 deletion(-) diff --git a/release-packaging/Classes/FluidManipulationJSON.sc b/release-packaging/Classes/FluidManipulationJSON.sc index 3638c12..875902b 100644 --- a/release-packaging/Classes/FluidManipulationJSON.sc +++ b/release-packaging/Classes/FluidManipulationJSON.sc @@ -46,7 +46,6 @@ $},{ if(inString.not){parsed[pos] = $)} } ) }); - parsed = parsed.replace("null","nil"); ^this.toDict(parsed.interpret); } From 5cbe109c93b688a91210b96c8c7d4193cd1f9de3 Mon Sep 17 00:00:00 2001 From: Owen Green Date: Tue, 22 Dec 2020 13:26:29 +0000 Subject: [PATCH 22/24] Add /flush to force server cache reset with internal Server --- include/wrapper/NonRealtime.hpp | 7 +++++++ release-packaging/Classes/FluidServerObject.sc | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/include/wrapper/NonRealtime.hpp b/include/wrapper/NonRealtime.hpp index adc74d8..dfe8084 100644 --- a/include/wrapper/NonRealtime.hpp +++ b/include/wrapper/NonRealtime.hpp @@ -898,6 +898,13 @@ namespace impl { RegisterUnitIf()(ft); Client::getMessageDescriptors().template iterate(); + + + static std::string flushCmd = std::string(Wrapper::getName()) + "/flush"; + + ft->fDefinePlugInCmd(flushCmd.c_str(),[](World*, void*, struct sc_msg_iter*, void* ){ + mCache.clear(); + },nullptr); } diff --git a/release-packaging/Classes/FluidServerObject.sc b/release-packaging/Classes/FluidServerObject.sc index bbb342e..f2b7e0b 100644 --- a/release-packaging/Classes/FluidServerObject.sc +++ b/release-packaging/Classes/FluidServerObject.sc @@ -15,6 +15,7 @@ FluidServerObject serverCaches[this] ?? {serverCaches[this] = FluidServerCache.new}; serverCaches[this].initCache(server); NotificationCenter.register(server,\newAllocators,this,{ count = 0; }); + ServerBoot.add({this.flush(Server.internal)},Server.internal); } *newMsg{|id, params| @@ -81,6 +82,9 @@ FluidServerObject *objectClassName { ^this.name.asSymbol } + *flushMsg { ^['/cmd',this.objectClassName ++ '/flush'] } + + *flush {|server| server.listSendMsg(this.flushMsg)} } FluidBufProcessor : FluidServerObject From 20e718668feb6c55cb8bbc117912e0103c0c88ba Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Tue, 22 Dec 2020 18:06:12 +0000 Subject: [PATCH 23/24] prerelease tidy up --- .../1a-starting-1D-example.scd | 2 +- .../2a-starting-1D-example2.scd | 2 +- .../7a-making-datasets-with-json.scd | 4 +-- .../8c-mlp-regressor-as-dim-redux.scd | 4 +-- .../HelpSource/Classes/FluidAmpSlice.schelp | 2 +- .../HelpSource/Classes/FluidDataSet.schelp | 2 +- .../Classes/FluidDataSetQuery.schelp | 6 ++--- .../HelpSource/Classes/FluidDataSetWr.schelp | 2 +- .../HelpSource/Classes/FluidKDTree.schelp | 27 +++++++++---------- .../HelpSource/Classes/FluidKMeans.schelp | 2 +- .../Classes/FluidKNNRegressor.schelp | 6 ++--- .../HelpSource/Classes/FluidMDS.schelp | 6 ++--- .../HelpSource/Classes/FluidNormalize.schelp | 4 +-- .../HelpSource/Classes/FluidPCA.schelp | 4 +-- .../Classes/FluidProcessSlices.schelp | 2 +- .../HelpSource/Classes/FluidUMAP.schelp | 3 --- 16 files changed, 36 insertions(+), 42 deletions(-) diff --git a/release-packaging/Examples/dataset/1-learning examples/1a-starting-1D-example.scd b/release-packaging/Examples/dataset/1-learning examples/1a-starting-1D-example.scd index 5c72f38..02fb085 100644 --- a/release-packaging/Examples/dataset/1-learning examples/1a-starting-1D-example.scd +++ b/release-packaging/Examples/dataset/1-learning examples/1a-starting-1D-example.scd @@ -43,7 +43,7 @@ Routine{ }.play ) -~labels = FluidLabelSet(s,\simple1label); +~labels = FluidLabelSet(s); ~kmeans.predict(~ds,~labels, {|x| ("Size of each cluster" + x).postln}) diff --git a/release-packaging/Examples/dataset/1-learning examples/2a-starting-1D-example2.scd b/release-packaging/Examples/dataset/1-learning examples/2a-starting-1D-example2.scd index a6475b3..faa0ada 100644 --- a/release-packaging/Examples/dataset/1-learning examples/2a-starting-1D-example2.scd +++ b/release-packaging/Examples/dataset/1-learning examples/2a-starting-1D-example2.scd @@ -47,7 +47,7 @@ Routine{ }.play ) -~labels = FluidLabelSet(s,\simple1label); +~labels = FluidLabelSet(s); ~kmeans.predict(~ds,~labels, {|x| ("Size of each cluster" + x).postln}) diff --git a/release-packaging/Examples/dataset/1-learning examples/7a-making-datasets-with-json.scd b/release-packaging/Examples/dataset/1-learning examples/7a-making-datasets-with-json.scd index 01b29e9..829e474 100644 --- a/release-packaging/Examples/dataset/1-learning examples/7a-making-datasets-with-json.scd +++ b/release-packaging/Examples/dataset/1-learning examples/7a-making-datasets-with-json.scd @@ -8,7 +8,7 @@ ~dict.add(\cols -> 10) //create a dataset, then loading the dictionary -~ds = FluidDataSet.new(s,\simple1data); +~ds = FluidDataSet(s); ~ds.load(~dict) ~ds.print @@ -33,7 +33,7 @@ ~dict2.add(\cols -> 1) // creating a labelset and loading the dictionary -~ls = FluidLabelSet.new(s,\simplelabel); +~ls = FluidLabelSet(s); ~ls.load(~dict2) ~ls.print diff --git a/release-packaging/Examples/dataset/1-learning examples/8c-mlp-regressor-as-dim-redux.scd b/release-packaging/Examples/dataset/1-learning examples/8c-mlp-regressor-as-dim-redux.scd index 9ca0eaa..6bf9101 100644 --- a/release-packaging/Examples/dataset/1-learning examples/8c-mlp-regressor-as-dim-redux.scd +++ b/release-packaging/Examples/dataset/1-learning examples/8c-mlp-regressor-as-dim-redux.scd @@ -34,10 +34,10 @@ FluidBufMelBands.process(s,~audio, features: ~melfeatures,action: {\done.postln; dsWr = FluidDataSetWr.kr(~raw, buf: buf, trig: Done.kr(stats)); LocalOut.kr( Done.kr(dsWr)); FreeSelf.kr(count - 99); - Poll.kr(trig,count); + Poll.kr(trig,(100-count)); }.play; ) -// wait for the post window to acknoledge the job is done. Check the dataset if curious (loads of small numbers) +// wait for the count to reaches 0 in the post window. Check the dataset if curious (loads of small numbers) ~raw.print; // normalize the input diff --git a/release-packaging/HelpSource/Classes/FluidAmpSlice.schelp b/release-packaging/HelpSource/Classes/FluidAmpSlice.schelp index 2343f2d..e22dac7 100644 --- a/release-packaging/HelpSource/Classes/FluidAmpSlice.schelp +++ b/release-packaging/HelpSource/Classes/FluidAmpSlice.schelp @@ -70,7 +70,7 @@ code:: // another solution: minslicelength ( {var env, source = SinOsc.ar(320,0,LFSaw.ar(20, 0, -0.4, 0.6)); - env = FluidAmpSlice.ar(source,fastRampUp: 5,fastRampDown: 50,slowRampUp: 220,slowRampDown: 220, onThreshold: 10, offThreshold: 7,floor: -60, minSliceLength: 220); + env = FluidAmpSlice.ar(source,fastRampUp: 5,fastRampDown: 50,slowRampUp: 220,slowRampDown: 220, onThreshold: 10, offThreshold: 7,floor: -60, minSliceLength: 441); [source, env] }.plot(0.08); ) diff --git a/release-packaging/HelpSource/Classes/FluidDataSet.schelp b/release-packaging/HelpSource/Classes/FluidDataSet.schelp index 790f42f..8816b16 100644 --- a/release-packaging/HelpSource/Classes/FluidDataSet.schelp +++ b/release-packaging/HelpSource/Classes/FluidDataSet.schelp @@ -89,7 +89,7 @@ d = Dictionary.new; d.add(\cols -> 1); d.add(\data -> Dictionary.newFrom(10.collect{|i|[i.asString, [i.asFloat]]}.flatten)); fork{ - ~ds = FluidDataSet.new(s); s.sync; + ~ds = FluidDataSet.new(s); ~ds.load(d); s.sync; ~ds.dump; s.sync; ~ds.free; } diff --git a/release-packaging/HelpSource/Classes/FluidDataSetQuery.schelp b/release-packaging/HelpSource/Classes/FluidDataSetQuery.schelp index 9132ac1..80f0336 100644 --- a/release-packaging/HelpSource/Classes/FluidDataSetQuery.schelp +++ b/release-packaging/HelpSource/Classes/FluidDataSetQuery.schelp @@ -160,9 +160,9 @@ code:: //this is how to join 2 datasets, adding columns to items with the same label //create 3 datasets ( -~dsA = FluidDataSet.new(s,\joinA); -~dsB = FluidDataSet.new(s,\joinB); -~dsC = FluidDataSet.new(s,\joinC); +~dsA = FluidDataSet(s); +~dsB = FluidDataSet(s); +~dsC = FluidDataSet(s); ) //feed them items with almost overlaping label lists but with different dimensions diff --git a/release-packaging/HelpSource/Classes/FluidDataSetWr.schelp b/release-packaging/HelpSource/Classes/FluidDataSetWr.schelp index 3605a23..e797c52 100644 --- a/release-packaging/HelpSource/Classes/FluidDataSetWr.schelp +++ b/release-packaging/HelpSource/Classes/FluidDataSetWr.schelp @@ -45,7 +45,7 @@ EXAMPLES:: code:: s.reboot; ( -~ds = FluidDataSet(s,\FluidDataSetWr); +~ds = FluidDataSet(s); ) ( diff --git a/release-packaging/HelpSource/Classes/FluidKDTree.schelp b/release-packaging/HelpSource/Classes/FluidKDTree.schelp index 4ea497a..7c037c7 100644 --- a/release-packaging/HelpSource/Classes/FluidKDTree.schelp +++ b/release-packaging/HelpSource/Classes/FluidKDTree.schelp @@ -52,12 +52,11 @@ code:: s.reboot; ( fork{ - ~ds = FluidDataSet.new(s,\kdtree_help_rand2d); - d = Dictionary.with( - *[\cols -> 2,\data -> Dictionary.newFrom( - 100.collect{|i| [i, [ 1.0.linrand,1.0.linrand]]}.flatten)]); - s.sync; - ~ds.load(d, {~ds.print}); + d = Dictionary.with( + *[\cols -> 2,\data -> Dictionary.newFrom( + 100.collect{|i| [i, [ 1.0.linrand,1.0.linrand]]}.flatten)]); + ~ds = FluidDataSet(s); + ~ds.load(d, {~ds.print}); } ) @@ -106,7 +105,7 @@ fork{ ) // enter a valid radius. -~tree.radius = 0.05; +~tree.radius = 0.1; // FluidKDTree will return only values that are within that radius, up to numNeighbours values ( ~tmpbuf = Buffer.loadCollection(s, ~p, 1, { @@ -139,7 +138,7 @@ Routine{ var point = 2.collect{TRand.kr(0,1,trig)}; point.collect{|p,i| BufWr.kr([p],inputBuffer,i)}; ~tree.kr(trig,inputBuffer,outputBuffer,5,nil); - Poll.kr(trig, BufRd.kr(1,outputBuffer,Array.iota(5)),5.collect{|i| "Neighbour" + i}); + Poll.kr(trig, BufRd.kr(1,outputBuffer,Array.iota(10)),10.collect{|i| "Neighbour" + (i/2).asInteger ++ "-" ++ (i.mod(2))}); Silent.ar; }.play; }.play; @@ -148,12 +147,11 @@ Routine{ //Using a lookup data set instead: //here we populate with numbers that are in effect the indicies, but it could be anything numerical that will be returned on the server-side and would be usable on that side ( -~dsL = FluidDataSet.new(s); fork{ - d = Dictionary.with( - *[\cols -> 1,\data -> Dictionary.newFrom( - 100.collect{|i| [i, [ i ]]}.flatten)]); - s.sync; + d = Dictionary.with( + *[\cols -> 1,\data -> Dictionary.newFrom( + 100.collect{|i| [i, [ i ]]}.flatten)]); + ~dsL = FluidDataSet.new(s); ~dsL.load(d, {~dsL.print}); } ) @@ -169,10 +167,9 @@ Routine{ var point = 2.collect{TRand.kr(0,1,trig)}; point.collect{|p,i| BufWr.kr([p],inputBuffer,i)}; ~tree.kr(trig,inputBuffer,outputBuffer,5,~dsL); - Poll.kr(trig, BufRd.kr(1,outputBuffer,Array.iota(5)),5.collect{|i| "Neighbour" + i}); + Poll.kr(trig, BufRd.kr(1,outputBuffer,Array.iota(5)),5.collect{|i| "Neighbour" + i}); Silent.ar; }.play; }.play; ) :: - diff --git a/release-packaging/HelpSource/Classes/FluidKMeans.schelp b/release-packaging/HelpSource/Classes/FluidKMeans.schelp index 4de6839..28f0ef3 100644 --- a/release-packaging/HelpSource/Classes/FluidKMeans.schelp +++ b/release-packaging/HelpSource/Classes/FluidKMeans.schelp @@ -75,7 +75,7 @@ code:: 64.collect{(1.sum3rand) + [1,-1].choose}.clump(2) }).flatten(1) * 0.5; fork{ - ~dataSet = FluidDataSet.new(s,\kmeans_help_rand2d); + ~dataSet = FluidDataSet(s); d = Dictionary.with( *[\cols -> 2,\data -> Dictionary.newFrom( ~points.collect{|x, i| [i, x]}.flatten)]); diff --git a/release-packaging/HelpSource/Classes/FluidKNNRegressor.schelp b/release-packaging/HelpSource/Classes/FluidKNNRegressor.schelp index 9bde42d..b950e07 100644 --- a/release-packaging/HelpSource/Classes/FluidKNNRegressor.schelp +++ b/release-packaging/HelpSource/Classes/FluidKNNRegressor.schelp @@ -106,7 +106,7 @@ d = Dictionary.with( //We should see a single cycle of a chirp ~outputdata.plot; -s.dumpOSC + // single point transform on arbitrary value ~inbuf = Buffer.loadCollection(s,[0.5]); ~regressor.predictPoint(~inbuf,{|x|x.postln;}); @@ -115,7 +115,7 @@ s.dumpOSC subsection:: Server Side Queries code:: -//Setup +//we are here querying with a saw in control rate, all on the server, via a buffer interface ( { var input = Saw.kr(2).linlin(-1,1,0,1); @@ -124,7 +124,7 @@ code:: var outputPoint = LocalBuf(1); BufWr.kr(input,inputPoint,0); ~regressor.kr(trig,inputPoint,outputPoint); - BufRd.kr(1,outputPoint,0);//,"mapped value") + BufRd.kr(1,outputPoint,0); }.scope ) diff --git a/release-packaging/HelpSource/Classes/FluidMDS.schelp b/release-packaging/HelpSource/Classes/FluidMDS.schelp index 914098e..c5444f2 100644 --- a/release-packaging/HelpSource/Classes/FluidMDS.schelp +++ b/release-packaging/HelpSource/Classes/FluidMDS.schelp @@ -1,7 +1,7 @@ TITLE:: FluidMDS summary:: Dimensionality Reduction with Multidimensional Scaling categories:: Dimensionality Reduction, Data Processing -related:: Classes/FluidMDS, Classes/FluidDataSet +related:: Classes/FluidPCA, Classes/FluidDataSet DESCRIPTION:: @@ -99,10 +99,10 @@ FluidBufMFCC.process(s,~audio, features: ~mfcc_feature); dsWr = FluidDataSetWr.kr(~raw, buf: buf, trig: Done.kr(stats),blocking:1); LocalOut.kr(Done.kr(dsWr)); FreeSelf.kr(count - 99); - Poll.kr(trig,count); + Poll.kr(trig,(100-count)); }.play; ) -// wait for the post window to acknoledge the job is done. +// wait for the count to reaches 0 in the post window. //First standardize our DataSet, so that the MFCC dimensions are on comensurate scales //Then apply the MDS in-place on the standardized data to get 2 dimensions, using a Euclidean distance metric diff --git a/release-packaging/HelpSource/Classes/FluidNormalize.schelp b/release-packaging/HelpSource/Classes/FluidNormalize.schelp index 4e21707..d0b4043 100644 --- a/release-packaging/HelpSource/Classes/FluidNormalize.schelp +++ b/release-packaging/HelpSource/Classes/FluidNormalize.schelp @@ -69,8 +69,8 @@ s.boot; // FluidNormalize.dumpAllMethods ( ~audiofile = File.realpath(FluidBufPitch.class.filenameSymbol).dirname +/+ "../AudioFiles/Tremblay-ASWINE-ScratchySynth-M.wav"; -~raw = FluidDataSet(s,\norm_help_raw); -~norm = FluidDataSet(s,\norm_help_normd); +~raw = FluidDataSet(s); +~norm = FluidDataSet(s); ~pitch_feature = Buffer.new(s); ~stats = Buffer.alloc(s, 7, 2); ~normalizer = FluidNormalize(s); diff --git a/release-packaging/HelpSource/Classes/FluidPCA.schelp b/release-packaging/HelpSource/Classes/FluidPCA.schelp index e7b43e2..aaf6a00 100644 --- a/release-packaging/HelpSource/Classes/FluidPCA.schelp +++ b/release-packaging/HelpSource/Classes/FluidPCA.schelp @@ -102,10 +102,10 @@ FluidBufMFCC.process(s,~audio, features: ~mfcc_feature,action:{"Done MFCCs".post dsWr = FluidDataSetWr.kr(~raw, buf: buf, trig: Done.kr(stats)); LocalOut.kr( Done.kr(dsWr)); FreeSelf.kr(count - 99); - Poll.kr(trig,count); + Poll.kr(trig,(100 - count)); }.play; ) -// wait for the post window to acknoledge the job is done. +// wait for the count to reaches 0 in the post window. //First standardize our DataSet, so that the MFCC dimensions are on comensurate scales //Then apply the PCA in-place on the standardized data diff --git a/release-packaging/HelpSource/Classes/FluidProcessSlices.schelp b/release-packaging/HelpSource/Classes/FluidProcessSlices.schelp index 4fcee45..9e27f2e 100644 --- a/release-packaging/HelpSource/Classes/FluidProcessSlices.schelp +++ b/release-packaging/HelpSource/Classes/FluidProcessSlices.schelp @@ -93,7 +93,7 @@ s.reboot; ~slicer = FluidSliceCorpus({ |src,start,num,dest| FluidBufOnsetSlice.kr(src,start,num,indices:dest, threshold:2) }); -~pitchdata = FluidDataSet(s,\FluidProcessSlicesHelp); +~pitchdata = FluidDataSet(s); ~pitchbufs = 4.collect{Buffer.new}; ~statsbufs = 4.collect{Buffer.new}; ) diff --git a/release-packaging/HelpSource/Classes/FluidUMAP.schelp b/release-packaging/HelpSource/Classes/FluidUMAP.schelp index dce0210..ab1be2b 100644 --- a/release-packaging/HelpSource/Classes/FluidUMAP.schelp +++ b/release-packaging/HelpSource/Classes/FluidUMAP.schelp @@ -223,9 +223,6 @@ w.front; ~standardizer.transformPoint(~sourcePoint,~standed); ~umap.transformPoint(~standed, ~umaped, {~umaped.getn(0,2,{|x|x.postln})}) -//poking at the data structure within -~umap.dump{|x|x.keys.do{|i|"%: %\n".postf(i,x[i]);}} - // one can also retrieve in control rate with Server Side Queries // Let's map our learned UMAP dimensions to the controls of a processor From 44947ef732addc03176134acb6e94e0133d3c2f0 Mon Sep 17 00:00:00 2001 From: Pierre Alexandre Tremblay Date: Tue, 22 Dec 2020 18:07:06 +0000 Subject: [PATCH 24/24] other further explanation --- .../13-massive-parallelisation-example.scd | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/release-packaging/Examples/dataset/1-learning examples/13-massive-parallelisation-example.scd b/release-packaging/Examples/dataset/1-learning examples/13-massive-parallelisation-example.scd index 4db597a..e7d7059 100644 --- a/release-packaging/Examples/dataset/1-learning examples/13-massive-parallelisation-example.scd +++ b/release-packaging/Examples/dataset/1-learning examples/13-massive-parallelisation-example.scd @@ -274,7 +274,7 @@ fork{ ~inBuf = Buffer.readChannel(s, Platform.resourceDir +/+ "sounds/a11wlk01.wav", numFrames:15000, channels:[0]); ~inBuf.play -//OR one from within +//OR one from within (but just the begining so beware of the difference!) ~inBuf = Buffer.alloc(s,15000); ~randomSlice = ~slices["data"].keys.asArray.scramble[0]; ~audio_buffers[~slices["data"][~randomSlice][0]].copyData(~inBuf,srcStartAt: ~slices["data"][~randomSlice][1], numSamples: 15000.min(~slices["data"][~randomSlice][2] - (~slices["data"][~randomSlice][1]))); @@ -323,8 +323,3 @@ fork{ }; } ) - - - - -