aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--SNPGUI.sc323
1 files changed, 215 insertions, 108 deletions
diff --git a/SNPGUI.sc b/SNPGUI.sc
index 8121af2..3027d81 100644
--- a/SNPGUI.sc
+++ b/SNPGUI.sc
@@ -2,18 +2,25 @@ SNPGUI {
var <speakerSetup;//Array holding the chromosome numbers for each speaker
var <mainView;// main view object
+ var <speakerView;// main view object
var <drawView;// main view object
var <speakerDict;//Dictionary of Views (per speaker)
var <textDict;//Dictionary of StaticText obbjects
- var <taskSNP;//task for updating the SNP texts of chromosomes
- var <snpDict; //Dictionary of texts for SNPs on chromosomes (replaceable)
+ var <updateSNPTextTask;//task for updating the SNP texts of chromosomes
+ var <snpTextFadeTasks; //Dictionary of tasks for SNP texts
+ var <>textFadeTime = 0.5; // time (in seconds) it takes for a SNP text to fade out
+ var <>textFadeSteps = 20; // amount of steps within textFadeTime in which to blend the color of a SNP text
+ var <>speakerViewMargin = 4; // the margin between speakerView border and a text within it
+ var <>speakerViewHeadMargin = 24; // the margin reserved for the speaker name
+ var <intermediateTextDict; //Dictionary of texts for SNPs on chromosomes (intermediate)
var <arcRadius = 200;//size of the arc, surrounded by speakers
var <radiusOffset = 75;//size of the arc, surrounded by speakers
var <mainWidth = 800;
var <mainHeight = 800;
- var <speakerHeight = 50;
- var <speakerWidth = 50;
- var <lineHeight = 12;
+ var <speakerHeight = 70;
+ var <speakerWidth = 70;
+ var <lineHeight = 16;
+ var <defaultFont = "Monaco";
*new{
arg setup;
@@ -22,154 +29,254 @@ SNPGUI {
snpGUIInit{
arg setup;
- setup.size.postln;
speakerSetup = setup;
- this.setupViews(setup.size);
- //create a dictionary the size of the setup
+ this.createDicts;
+ this.createViews;
+ this.createTasks;
}
+
// initialize Dictionaries for all things
- initDicts{
- arg setup;
- speakerDict = Dictionary.new(setup.size+1);
- //textDict = Dictionary.new(setup.size);
- textDict = Dictionary.new(25);//Dictionary holding all StaticText objects that can be modified
- snpDict = Dictionary.new(25);
- //taskDict = Dictionary.new(25);
- //add each speaker number
- setup.do({|speaker,i|
- var tmp = Dictionary.new(setup[0].size);
+ createDicts{
+ speakerDict = Dictionary.new(speakerSetup.size+1);
+ intermediateTextDict = Dictionary.new(SNPInfo.chromosomesLength.size.asInt); // Dictionary of intermediate Strings to be used for the StaticText objects in textDict
+ textDict = Dictionary.new(SNPInfo.chromosomesLength.size.asInt);//Dictionary holding all StaticText objects that can be modified
+ }
+
+ // creates all Views
+ createViews{
+ this.createMainView;
+// this.createDrawView;
+ this.createSpeakerViews;
+ }
+
+ // create the main View (the main window)
+ createMainView{
+ mainView = View.new();
+ mainView.minSize = mainWidth@mainHeight;
+ mainView.userCanClose = true;
+ mainView.enabled = true;
+ mainView.visible = true;
+ mainView.name = "The Sound Of People";
+ mainView.background = Color.fromHexString("#DBDBDB");
+ mainView.onResize = {
+ if((drawView.notNil), {
+ drawView.moveTo((mainView.absoluteBounds.width/2)-(drawView.bounds.width/2), (mainView.absoluteBounds.height/2)-(drawView.bounds.height/2));
+ });
+ speakerView.moveTo((mainView.absoluteBounds.width/2)-(speakerView.bounds.width/2), (mainView.absoluteBounds.height/2)-(speakerView.bounds.height/2));
+ };
+ }
+
+ //creates a UserView, draws a circle
+ createDrawView{
+ drawView = UserView.new(mainView, Rect(0, 0, mainView.bounds.width, mainView.bounds.height));
+ drawView.minSize = mainWidth@mainHeight;
+ drawView.background = Color.fromHexString("#DBDBDB");
+ drawView.background = Color.fromHexString("#e7ebe7");
+ // center to mid of mainView on resize
+ drawView.onResize = { drawView.moveTo(mainView.bounds.width/2-drawView.bounds.width/2, mainView.bounds.height/2-drawView.bounds.height/2)};
+ // draw a circle
+ drawView.drawFunc = {
+ Pen.translate(drawView.bounds.width/2, drawView.bounds.height/2);
+ Pen.strokeColor = Color.black;
+ Pen.color = Color.black;
+ Pen.addArc(0@0, arcRadius, 0, 2pi);
+ Pen.stroke;
+ };
+ }
+
+ // creates all speakerViews necessary for the setup defined in speakerSetup
+ createSpeakerViews{
+ speakerView = View.new(
+ mainView,
+ Rect(
+ 0,
+ 0,
+ mainWidth,
+ mainHeight
+ )
+ );
+ speakerView.minSize = mainWidth@mainHeight;
+ // create a speakerView for each speaker in the setup
+ speakerSetup.do({|speaker,i|
// Adds a View with speaker information to the speakerDict
- speakerDict.add((i+1).asSymbol -> this.initSpeakerView(i, setup.size, setup[0].size));
+ speakerDict.add((i+1).asSymbol -> this.createSpeakerView(i, speakerSetup.size, speakerSetup[0].size));
// iterate all chromosome information from original setup
speaker.do({|chromosome, j|
//add chromosome number -> replaceable SNP StaticText object to temporary Dictionary
- //tmp.add(chromosome.asSymbol -> this.initChromosomeText(chromosome.asSymbol, (i+1).asSymbol, j+1));
- textDict.add(chromosome.asSymbol -> this.initChromosomeText(chromosome.asSymbol, (i+1).asSymbol, j+1));
- snpDict.add(chromosome.asSymbol -> "");
+ textDict.add(chromosome.asSymbol -> this.createChromosomeTexts(chromosome.asSymbol, (i+1).asSymbol, j));
+ intermediateTextDict.add(chromosome.asSymbol -> "");
});
- //textDict.add((i+1).asSymbol -> tmp);
});
// Adds a View for MT chromosome with speaker information to the speakerDict
- speakerDict.add(\all -> this.initSpeakerView(-1, setup.size, 1));
+ speakerDict.add(\all -> this.createSpeakerView(-1, speakerSetup.size, 1));
// add chromosome text for MT to the speaker called all
- textDict.add(\25 -> this.initChromosomeText(\25, \all, 1));
- //
- snpDict.add(25.asSymbol -> "");
- //start a Task to update the SNP currently playing
- this.startSNPTask;
- //snpDict.postln;
- //speakerDict.postln;
- //textDict.postln;
- }
-
- //init a StaticText for a chromosome in its speaker View, returns its replaceable component (for SNPs)
- initChromosomeText{
- arg chromosome, number, position;
- var snpText, chromosomeText;
- chromosomeText = StaticText.new(speakerDict.at(number), Rect(0, lineHeight*position, (speakerDict.at(number).bounds.width/2), lineHeight));
- chromosomeText.string = (chromosome.asString++": ");
- chromosomeText.align = \left;
- snpText = StaticText.new(speakerDict.at(number), Rect((speakerDict.at(number).bounds.width/2), lineHeight*position, (speakerDict.at(number).bounds.width/2), lineHeight));
- snpText.string = "Test";
- snpText.align = \right;
- ^snpText;
+ textDict.add(SNPInfo.chromosomesLength.size.asSymbol -> this.createChromosomeTexts(SNPInfo.chromosomesLength.size.asSymbol, \all, 0));
+ intermediateTextDict.add(SNPInfo.chromosomesLength.size.asSymbol -> "");
}
- //inits a View for one speaker, adds its name as StaticText object and returns itself
- initSpeakerView{
- arg number, total, perSpeaker;
- var mid, radius, radianOffset, radian, x, y, speakerContainer, text;
- mid = Point.new(mainWidth/2,mainHeight/2);//mid of the circle
+ //creates a View for one speaker, adds its name as StaticText object and returns itself
+ createSpeakerView{
+ arg number, total, chromosomesOnSpeaker;
+ var mid, radius, radianOffset, radian, x, y, speakerContainer, speakerContainerInner, speakerText;
+ mid = Point.new((mainWidth/2)-(speakerWidth/2),(mainHeight/2)-(speakerHeight/2));//mid of the circle
radius = arcRadius+radiusOffset;//make a slightly bigger radius for the text objects
- radianOffset = 360/total*2;// radian offset used to make speaker 1 be positioned front left
- radian = 360/total*number;//segment of the circle the speaker is placed in
+ radianOffset = 360/(total*2);// radian offset used to make speaker 1 be positioned front left
+ radian = (360*(number/total))-90;//segment of the circle the speaker is placed in
//Calculating x and y coordinates for the View to be created
x = mid.x+(radius*cos(degrad(radian-radianOffset)));
y = mid.y+(radius*sin(degrad(radian-radianOffset)));
- //setting up the View container for a speaker
- speakerContainer = View.new(drawView, Rect(x, y, speakerWidth, (perSpeaker+1)*lineHeight));
+ //setting up the border for a speaker
+ speakerContainer = View.new(
+ speakerView,
+ Rect(
+ x,
+ y,
+ speakerWidth,
+ ((chromosomesOnSpeaker)*lineHeight)+(speakerViewMargin*2)+speakerViewHeadMargin
+ )
+ );
speakerContainer.visible = true;
- speakerContainer.background = Color.green;
+ speakerContainer.background = Color.fromHexString("#7f7f7f");
+ //setting up the View container for a speaker
+ speakerContainerInner = View.new(
+ speakerContainer,
+ Rect(
+ (speakerViewMargin/2),
+ (speakerViewMargin/2),
+ speakerWidth-speakerViewMargin,
+ ((chromosomesOnSpeaker)*lineHeight)+speakerViewMargin+speakerViewHeadMargin
+ )
+ );
+ speakerContainerInner.visible = true;
+ speakerContainerInner.background = Color.fromHexString("#EEEEEE");
- // adding the speaker number
- text = StaticText(speakerContainer, Rect(0, 0, speakerContainer.bounds.width, lineHeight));
- text.string = (number+1).asString;
- text.align = \center;
+ // add the speaker text (number of the speaker)
+ speakerText = StaticText(
+ speakerContainerInner,
+ Rect(
+ 0,
+ speakerViewMargin,
+ speakerContainer.bounds.width,
+ lineHeight
+ )
+ );
+ speakerText.align = \center;
+ speakerText.string = (number+1).asString;
+ speakerText.stringColor = Color.fromHexString("#4A52C4");
+ speakerText.font = Font(this.defaultFont,16,true);
//add exception for no/ all speaker
if(number<0,{
+ // rename the speaker
+ speakerText.string = "all";
//recalculate radius and offset
radius = radius+radiusOffset;
- radian = 360/total*0;
- //Calculating x and y coordinates for the View to be created
+ radian = -90+((360/total)/2);
+ //recalculate x and y coordinates to move the View
x = mid.x+(radius*cos(degrad(radian-radianOffset)));
y = mid.y+(radius*sin(degrad(radian-radianOffset)));
+ // move speakerContainer to new coordinates (top center)
speakerContainer.moveTo(x, y);
- text.string = "all";
});
-// ("Speaker: "++number.asString).postln;
-// ("cos("++radian.asString++"): "++cos(degrad(radian)).asString).postln;
-// ("sin("++radian.asString++"): "++sin(degrad(radian)).asString).postln;
^speakerContainer;
}
- /*
- * Setup the initial window and all of its StaticText elements
- */
- setupViews{
- arg numChannels;
- mainView = View.new(nil,Rect(50,50,mainWidth,mainHeight));
- //mainView.front;
- mainView.fixedSize=mainWidth@mainHeight;
- mainView.enabled = true;
- mainView.userCanClose = true;
- mainView.alwaysOnTop;
- mainView.visible = true;
- mainView.name = "The Sound Of People";
- mainView.background = Color.white;
- mainView.bounds.postln;
- //make a UserView for drawing with Pen
- drawView = UserView.new(mainView, Rect(0, 0, mainView.bounds.width, mainView.bounds.height));
- drawView.animate = true;
- drawView.frameRate = 60.0;
- // draw a circle
- drawView.drawFunc = {
- Pen.translate(drawView.bounds.width/2, drawView.bounds.height/2);
- Pen.strokeColor = Color.black;
- Pen.color = Color.black;
- Pen.addArc(0@0, arcRadius, 0, 2pi);
- Pen.stroke;
- };
- //add StaticText objects for names of speakers, names of chromosomes and names of SNPs
- this.initDicts(speakerSetup);
+ //create a StaticText for a chromosome in its speaker View, returns its replaceable component (for SNPs)
+ createChromosomeTexts{
+ arg chromosome, number, position;
+ var snpText, chromosomeText;
+ //create the name of the chromosome as StaticText
+ chromosomeText = StaticText.new(
+ speakerDict.at(number),
+ Rect(
+ speakerViewMargin,
+ (lineHeight*position)+speakerViewHeadMargin,
+ (speakerDict.at(number).bounds.width/2),
+ lineHeight
+ )
+ );
+ chromosomeText.align = \left;
+ chromosomeText.string = if((chromosome.asInt < 10), {("0"++chromosome.asString++": ")}, {chromosome.asString++": "});
+ chromosomeText.font = Font(this.defaultFont,13,true,true);
+
+ //create the snpText (its string will be set with a Task later)
+ snpText = StaticText.new(
+ speakerDict.at(number),
+ Rect((
+ speakerDict.at(number).bounds.width/2)-speakerViewMargin,
+ (lineHeight*position)+speakerViewHeadMargin,
+ (speakerDict.at(number).bounds.width/2),
+ lineHeight
+ )
+ );
+ snpText.align = \right;
+ snpText.string = "";
+ snpText.font = Font(this.defaultFont,13,true);
+ ^snpText;
}
+
+ //create all Tasks
+ createTasks{
+ this.createSNPTextFadeTasks(SNPInfo.chromosomesLength.size.asInt);
+ this.createUpdateSNPTextTask;
+ }
+
+ // create Tasks to fade out the text of all SNPs and blend its color gradually
+ createSNPTextFadeTasks{|size|
+ snpTextFadeTasks = Dictionary.new(size);
+ size.do({|item,i|
+ var textTask;
+ snpTextFadeTasks.put((i+1).asSymbol, textTask = Task({
+ var snp = (i+1).asSymbol;
+ var elapsed = 0.0;
+ // reset the intermediateTextDict text
+ this.setIntermediateText(snp, "");
+ // blend the original color of the chromosome's SNP by the amount of steps defined in textFadeSteps with black. Each step's length is defined by textFadeTime
+ this.textFadeSteps.do({|item,i|
+ textDict.at(snp.asSymbol).alpha_(textDict.at(snp.asSymbol).alpha-(textFadeTime/this.textFadeSteps));
+ textDict.at(snp.asSymbol).stringColor_(textDict.at(snp.asSymbol).stringColor.blend(Color.black(), textFadeTime/this.textFadeSteps));
+ (textFadeTime/this.textFadeSteps).wait;
+ });
+ textDict.at(snp.asSymbol).string_("");
+ })
+ );
+ });
+ }
+
//Starts a task to update texts for SNP of chromosomes on AppClock
- startSNPTask{
- taskSNP = Task.new({
+ createUpdateSNPTextTask{
+ updateSNPTextTask = Task.new({
{
//get all values from the dictionary and update the corresponding StaticText objects
- snpDict.keysValuesDo({|key, value|
- textDict.at(key.asSymbol).string_(value.asString);
+ intermediateTextDict.keysValuesDo({|key, value|
+ if((value.asString != ""),{
+ //set the text and color for the SNP here,as doing this within the fade Task would delay it too much
+ textDict.at(key.asSymbol).string_(value.asString);
+ // set different color for each base/ combination of bases
+ textDict.at(key.asSymbol).stringColor_(Color.fromHexString(SNPInfo.getColorFromBase(value.asString)));
+ //start or reset the snpTextTask belonging to this chromosome (to fade out its text)
+ if((snpTextFadeTasks.at(key.asSymbol).isPlaying), {
+ snpTextFadeTasks.at(key.asSymbol).reset;
+ },{
+ snpTextFadeTasks.at(key.asSymbol).start(AppClock);
+ });
+ });
});
0.02.wait;
}.loop;
});
- taskSNP.play(AppClock);
+ updateSNPTextTask.play(AppClock);
}
//set the text of a specific chromosome (aka.: which SNP is currently playing?)
- setSNPText{
+ setIntermediateText{
arg chromosome, text;
- //delete all strings first
-// snpDict.keysValuesChange{|key,value|
-// ^"";
-// };
- //add the current SNP text to the dictionary
- snpDict.put(chromosome.asSymbol, text.asString);
+ intermediateTextDict.put(chromosome.asSymbol, text.asString);
}
+
// get the current SNP text of a chromosome
- getSNPText{
+ getIntermediateText{
arg chromosome;
- var text = snpDict.at(chromosome.asSymbol);
+ var text = intermediateTextDict.at(chromosome.asSymbol);
^text;
}
}