|
|
TITLE:: FluidDataSet
|
|
|
summary:: Container that associates data points with identifiers
|
|
|
categories:: Libraries>FluidCorpusManipulation
|
|
|
related:: Classes/FluidLabelSet, Classes/FluidKDTree, Classes/FluidKMeans
|
|
|
|
|
|
DESCRIPTION::
|
|
|
FluidDataSet is a container that associates data points with identifiers
|
|
|
|
|
|
CLASSMETHODS::
|
|
|
|
|
|
PRIVATE:: asUGenInput
|
|
|
|
|
|
METHOD:: new
|
|
|
Create a new instance of the DataSet, with the given name. If a DataSet with this name already exists, an exception will be thrown (see link::Classes/FluidDataSet#at:: to access an existing DataSet).
|
|
|
|
|
|
ARGUMENT:: server
|
|
|
The link::Classes/Server:: on which to create the data set.
|
|
|
|
|
|
|
|
|
returns:: The new instance
|
|
|
|
|
|
INSTANCEMETHODS::
|
|
|
|
|
|
PRIVATE:: init,id,cache
|
|
|
|
|
|
METHOD:: addPoint
|
|
|
Add a new point to the FluidDataSet. The dimensionality of the FluidDataSet is governed by the size of the first point added. If the identifier already exists, or if the size of the data does not match the dimensionality of the FluidDataSet an error will be reported.
|
|
|
Will report an error if the identifier already exists, or if the size of the data does not match the dimensionality of the DataSet.
|
|
|
ARGUMENT:: identifier
|
|
|
The identifier for the point.
|
|
|
ARGUMENT:: buffer
|
|
|
A link::Classes/Buffer:: containing the data for the point.
|
|
|
ARGUMENT:: action
|
|
|
A function to run when the point has been added.
|
|
|
|
|
|
METHOD:: updatePoint
|
|
|
Update an existing identifier's data. If the identifier does not exist, or if the size of the data does not match the dimensionality of the FluidDataSet an error will be reported.
|
|
|
ARGUMENT:: identifier
|
|
|
The identifier for the point.
|
|
|
ARGUMENT:: buffer
|
|
|
A link::Classes/Buffer:: containing the data for the point.
|
|
|
ARGUMENT:: action
|
|
|
A function to run when the operation completes.
|
|
|
|
|
|
METHOD:: getPoint
|
|
|
Retrieve a point from the data set into a link::Classes/Buffer::. If the identifier does not exist an error will be reported.
|
|
|
ARGUMENT:: identifier
|
|
|
The identifier for the point.
|
|
|
ARGUMENT:: buffer
|
|
|
A link::Classes/Buffer:: where the retrieved data will be stored.
|
|
|
ARGUMENT:: action
|
|
|
A function to run when the operation completes.
|
|
|
|
|
|
METHOD:: deletePoint
|
|
|
Remove a point from the data set. If the identifier doesn't exist an error will be reported.
|
|
|
ARGUMENT:: identifier
|
|
|
The identifier to be deleted.
|
|
|
ARGUMENT:: action
|
|
|
A function to run when the operation completes.
|
|
|
|
|
|
METHOD:: setPoint
|
|
|
Set the point. If the identifier exists, this method behaves like updatePoint. If the identifier doesn't exist, it behaves like addPoint.
|
|
|
ARGUMENT:: identifier
|
|
|
The identifier for the point.
|
|
|
ARGUMENT:: buffer
|
|
|
A link::Classes/Buffer:: containing the data for the point.
|
|
|
ARGUMENT:: action
|
|
|
A function to run when the operation completes.
|
|
|
|
|
|
METHOD:: clear
|
|
|
Empty the data set.
|
|
|
|
|
|
METHOD:: toBuffer
|
|
|
Dump the content of the dataset to a link::Classes/Buffer::, with optional transposition, and a map of frames/channels to the original IDs as a link::Classes/FluidLabelSet::.
|
|
|
ARGUMENT:: buffer
|
|
|
The buffer to write to. It will be resized.
|
|
|
ARGUMENT:: transpose
|
|
|
If 0, each dataset point becomes a buffer frame, and each dataset dimension becomes a buffer channel. If 1, points become channels, and dimensions become frames.
|
|
|
ARGUMENT:: labelSet
|
|
|
The link::Classes/FluidLabelSet:: in which to dump the point's IDs associated with their reference frame number (or channel number if transposed).
|
|
|
ARGUMENT:: action
|
|
|
A function to run when the dump is done.
|
|
|
|
|
|
METHOD:: fromBuffer
|
|
|
Import to the dataset the content of a link::Classes/Buffer::, with optional transposition, and a map of frames/channels to the original IDs as a link::Classes/FluidLabelSet::.
|
|
|
ARGUMENT:: buffer
|
|
|
The buffer to read from. The dataset will be resized.
|
|
|
ARGUMENT:: transpose
|
|
|
If 0, each buffer frame becomes a dataset point, and each buffer channel becomes a dataset dimension. If 1, channels become points, and frames become dimensions.
|
|
|
ARGUMENT:: labelSet
|
|
|
The link::Classes/FluidLabelSet:: from which to retrieve the point's IDs associated with their reference frame number (or channel number if transposed).
|
|
|
ARGUMENT:: action
|
|
|
A function to run when the import is done.
|
|
|
|
|
|
METHOD:: getIds
|
|
|
Export to the dataset IDs to a link::Classes/FluidLabelSet::.
|
|
|
ARGUMENT:: labelSet
|
|
|
The link::Classes/FluidLabelSet:: to export to. Its content will be replaced.
|
|
|
ARGUMENT:: action
|
|
|
A function to run when the export is done.
|
|
|
|
|
|
METHOD:: merge
|
|
|
Merge sourceDataSet in the current DataSet. It will update the value of points with the same identifier if overwrite is set to 1. To add columns instead, see the 'transformJoin' method of link::Classes/FluidDataSetQuery::
|
|
|
|
|
|
METHOD:: free
|
|
|
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.
|
|
|
|
|
|
returns:: A link::Classes/Synth::
|
|
|
|
|
|
METHOD:: server
|
|
|
The server instance the object uses
|
|
|
|
|
|
returns:: A link::Classes/Server::
|
|
|
|
|
|
EXAMPLES::
|
|
|
|
|
|
CODE::
|
|
|
// Create a simple a one-dimensional data set, three ways
|
|
|
// Using routine
|
|
|
s.reboot;
|
|
|
(
|
|
|
fork{
|
|
|
~ds = FluidDataSet.new(s);
|
|
|
~point = Buffer.alloc(s,1,1);
|
|
|
s.sync;
|
|
|
10.do{|i|
|
|
|
~point.set(0,i);
|
|
|
~ds.addPoint(i.asString,~point,{("addPoint"+i).postln});
|
|
|
s.sync;
|
|
|
};
|
|
|
~ds.dump;
|
|
|
s.sync;
|
|
|
~ds.free;
|
|
|
};
|
|
|
)
|
|
|
|
|
|
//Using Dictionary
|
|
|
(
|
|
|
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);
|
|
|
~ds.load(d); s.sync;
|
|
|
~ds.dump; s.sync; ~ds.free;
|
|
|
}
|
|
|
)
|
|
|
|
|
|
// Using a synth
|
|
|
(
|
|
|
~ds = FluidDataSet.new(s);
|
|
|
{
|
|
|
var trig = Impulse.kr(20);
|
|
|
var count = PulseCount.kr(trig) - 1;
|
|
|
var buf = LocalBuf(1);
|
|
|
BufWr.kr(count, buf);
|
|
|
FluidDataSetWr.kr(~ds.asUGenInput, idNumber: count, buf: buf, trig: trig);
|
|
|
FreeSelf.kr(count - 8);
|
|
|
}.play.onFree{~ds.dump{|o| o.postln;~ds.free}}
|
|
|
)
|
|
|
::
|
|
|
|
|
|
STRONG:: Buffer Interface::
|
|
|
|
|
|
As the content of the dataset has a similar structure to buffers, namely arrays of floats in parallel, it is possible to transfer the content between the two. Careful consideration of the rotation of the buffer, as well as the relation of points to channel numbers, are needed.
|
|
|
|
|
|
code::
|
|
|
(
|
|
|
//Make a dummy data set
|
|
|
d = FluidDataSet(s);
|
|
|
~data = Dictionary.with(*Array.iota(20).reshape(4,5).collect{|a,i| ("row"++i)->a});
|
|
|
~dsdata = Dictionary.newFrom([\cols,5,\data,~data]);
|
|
|
d.load(~dsdata);
|
|
|
d.print;
|
|
|
)
|
|
|
|
|
|
//convert to separate buffer and labelset
|
|
|
b = Buffer(s);
|
|
|
l = FluidLabelSet(s);
|
|
|
d.toBuffer(b,0,l);
|
|
|
|
|
|
//check the result: by default, dataset points become frames, with their associated data columns as channels
|
|
|
b.query
|
|
|
b.getn(0,20,{|x|x.postln})
|
|
|
l.print
|
|
|
|
|
|
//you can also transpose your query, where dataset points are each a buffer channel, and each data column becomes a buffer frame
|
|
|
d.toBuffer(b,1,l);
|
|
|
b.query
|
|
|
b.getn(0,20,{|x|x.postln})
|
|
|
//note that the IDs are still one per item, as columns are unamed in datasets
|
|
|
l.print
|
|
|
|
|
|
//Convert back to DS again
|
|
|
e = FluidDataSet(s);
|
|
|
|
|
|
//Let's use the transposed data we just got
|
|
|
e.print;
|
|
|
e.fromBuffer(b,1,l);
|
|
|
e.print;
|
|
|
//if we didn't transpose, we would get an error as the labelset is mismatched with the number of items
|
|
|
e.clear
|
|
|
e.print
|
|
|
e.fromBuffer(b,0,l)
|
|
|
::
|
|
|
|
|
|
STRONG:: Merging Datasets::
|
|
|
code::
|
|
|
//this is how to add items between 2 datasets.
|
|
|
//create 2 datasets
|
|
|
(
|
|
|
~dsA = FluidDataSet.new(s);
|
|
|
~dsB = FluidDataSet.new(s);
|
|
|
)
|
|
|
|
|
|
//feed them items with same dimensions but different identifiers
|
|
|
~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])]));
|
|
|
~dsA.print;
|
|
|
~dsB.print;
|
|
|
|
|
|
// merge and check. it works.
|
|
|
~dsB.merge(~dsA)
|
|
|
~dsB.print;
|
|
|
|
|
|
//change the content of the dataset to shared identifiers
|
|
|
~dsA.load(Dictionary.newFrom([\cols, 1, \data, Dictionary.newFrom([\three,333,\four,444])]));
|
|
|
~dsB.load(Dictionary.newFrom([\cols, 1, \data, Dictionary.newFrom([\three,3,\four,4])]));
|
|
|
~dsA.print;
|
|
|
~dsB.print;
|
|
|
|
|
|
//try to merge, it does not update
|
|
|
~dsB.merge(~dsA)
|
|
|
~dsB.print;
|
|
|
|
|
|
// add the overwrite flag, and it works
|
|
|
~dsB.merge(~dsA,1)
|
|
|
~dsB.print;
|
|
|
::
|