From 42519292ff9f4c23ca9b1b63d76c39997e10123a Mon Sep 17 00:00:00 2001 From: David Runge Date: Mon, 30 Mar 2015 01:34:11 +0200 Subject: SNPGUI.sc: Modularizing and renaming functionality.\ Adding multi-color support, fade out functionality for SNP texts.\ Changing fonts and sizes.\ Fixing positions of speakerViews on all available speaker setups.\ Renaming functions and variables to more readable names. --- SNPGUI.sc | 323 +++++++++++++++++++++++++++++++++++++++++--------------------- 1 file 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 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 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; } } -- cgit v1.2.3-70-g09d2