CSC334 DNA Align2 pde
Revision as of 20:03, 23 July 2008 by Thiebaut (talk | contribs) (New page: Back to Lab 3 <hr> <code> <pre> // DNA_Align.pde // D. Thiebaut // A Processing program for displaying exact matches of // FASTA-formatted DNA sequences //...)
// DNA_Align.pde // D. Thiebaut // A Processing program for displaying exact matches of // FASTA-formatted DNA sequences //--------------------------------------------------------------------- // ___ _ _ _ // / __| |___| |__ __ _| |___ //| (_ | / _ \ '_ \/ _` | (_-< // \___|_\___/_.__/\__,_|_/__/ // //--------------------------------------------------------------------- DNAString dna1, dna2; statusClass status; String FASTA0 = "gi|194306025|dbj|AB426820.1| Escherichia coli ompT mRNA for outer membrane protease T, partial cds, strain: JCM 5491\n" +"TGGGAATAGTCCTGACAACCCCTATTGCGATCAGCTCTTTTGCTTCTACCGAGACTTTATCGTTTACTCC" +"TGACAACATAAATGCGGACATTAGTCTTGGAACTCTGAGCGGAAAAACAAAAGAGCGTGTTTATCTAGCC" +"GAAGAAGGAGGCCGAAAGGTCAGTCAACTTGACTGGAAATTCAATAACGCTGCAATTATTAAAGGTGCAA" +"TTAATTGGGATTTGATGCCCCAGATATCTATCGGGGCTGCTGGCTGGACAACTCTCGGTAGCCGAGGTGG" +"CAATATGGTCGATCGGGACTGGATGGATTCCAGTAACCCCGGAACCTGGACGGATGAAAGTAGACACCCT" +"GATACACAACTCAATTATGCCAACGAATTTGATCTGAATATCAGAGGCTGGCTCCCCAACGAACCCAATT" +"ACCGCCTGGGACTCATGGCCGGATATCAGGAAAGCCGTTATAGCTTTACAGCCAGAGGGGGTTCCTATAT" +"CTACAGTTCTGAGGAGGGATTCAGAGATGATATCGGCTCCTTCCCGAATGGAGAAAGAGCAATCGGCTAC" +"AAACAACGTTTTAAAATGCCCTACATTGGCTTGACTGGAAGTTATCGTTATGAAGATTTTGAGCTAGGTG" +"GTACATTTAAATACAGCGGCTGGGTGGAAGCATTTGATAACGATGAACACTATGACCCAGGAAAAAGAAT" +"CACTTATCGCAGTAAAGTCAAAGACCAAAATTACTATTCTGTTGCAGTCAATGCAGGTTATTACGTAACG" +"CCTAATGCAAAAGTTTATATTGAAGGCGCATGGAATCGGGTTACGAATAAAAAAGGTGATACTTCACTTT" +"ATGATCACAATGATAACACTTCTGACTACAGCAAAAATGGTGCAGGCATAGAAAACTATAACTTCATCAC" +"TACTGCTGGTC"; String FASTA1 = "gi|194306025|dbj|AB426820.1| Escherichia coli ompT mRNA for outer membrane protease T, partial cds, strain: JCM 5491\n" +"TGGGAATAGTCCTGACAACCCCTATTGCGATCAGCTCTTTTGCTTCTACCGAGACTTTATCGTTTACTCC"; String FASTA2 = "gi|194306025|dbj|AB426820.1| Escherichia coli ompT mRNA for outer membrane protease T, partial cds, strain: JCM 5491\n" +"TGACAACATAAATGCGGACATTAGTCTTGGAACTCTGAGCGGAAAAACAAAAGAGCGTGTTTATCTAGCC"; //--------------------------------------------------------------------- // GEOMETRY //--------------------------------------------------------------------- int WIDTH = 1000; int MIDWIDTH = WIDTH/2; int HEIGHT = 400; int BORDER = 20; int TITLELINE = 50; int ALINE = 100; int BLINE = 130; int MLINE = 160; int STATUSTOP = 190; int STATUSWIDTH = (WIDTH-2*BORDER)/2; int STATUSHEIGHT = HEIGHT-BORDER-STATUSTOP; int LEGLENGTH = (BLINE-ALINE)/2; // length of leg below symbol String MATCH = "Match:"; PFont font; // the font used to display the symbols //--------------------------------------------------------------------- // ___ _ _ _ ___ _ _ //| \| \| | /_\ / __|_ _ _ __ | |__ ___| | //| |) | .` |/ _ \\__ \ || | ' \| '_ \/ _ \ | //|___/|_|\_/_/ \_\___/\_, |_|_|_|_.__/\___/_| // |__/ // DNA Symbol Class //--------------------------------------------------------------------- class DNASymbol { char symbol; // the symbol color symColor; // color of symbol int currX; // current X coordinates int currY; // current Y coordinates DNASymbol() { setSymbol( 'X' ); } DNASymbol( char x ) { setSymbol( x ); } char getSymbol( ) { return symbol; } //--- set a symbol to a char representation and selects its color --- void setSymbol( char x ) { symbol = x; if ( x=='C' ) symColor = color( 249, 16, 85 ); else if ( x=='G' ) symColor = color( 148, 73, 232 ); else if ( x=='T' ) symColor = color( 122, 186, 221 ); else if ( x=='A' ) symColor = color( 169, 209, 169 ); else symColor = color( 200, 200, 200 ); } //--- draws the symbol at location x,y --- void draw( int x, int y ) { currX = x; currY = y; fill( symColor ); text( str( symbol ), x, y ); } //--- drawBarDown: draws a line below the symbol --- void drawBarDown() { fill( 255 ); stroke( 255 ); line( currX+textWidth( symbol )/2, currY+2, currX+textWidth( symbol )/2, currY+LEGLENGTH ); } } //--------------------------------------------------------------------- // ___ _ _ _ ___ _ _ //| \| \| | /_\ / __| |_ _ _(_)_ _ __ _ //| |) | .` |/ _ \\__ \ _| '_| | ' \/ _` | //|___/|_|\_/_/ \_\___/\__|_| |_|_||_\__, | // |___/ // DNAString Class: a class holding a DNA sequence, both as a text string // and as an array of DNASymbol objects. //--------------------------------------------------------------------- class DNAString { String symbols; // the string of chars int noSymbols; // the # of symbols DNASymbol[] array; // the array of symbol objects (char, color) boolean[] legs; // indicate if each symbol has a leg or not int offsetX; // x-value of left-most position on screen int offsetY; // y-value of screen position int leftPadding; // amount of left padding when sequence shifts // this is relative to leftmost position, in integer // number of symbols int maxLeftPadding; //--- default constructor --- DNAString( ) { symbols = ""; noSymbols = 0; offsetX = int( 2*BORDER+textWidth( MATCH )); offsetY = ALINE; leftPadding = 0; } //--- constructor --- DNAString( String fastaString ) { String[] list = split( fastaString, '\n' ); symbols = list[1]; noSymbols = symbols.length(); array = new DNASymbol[ noSymbols ]; legs = new boolean[ noSymbols ]; for ( int i=0; i< noSymbols; i++ ) { array[i] = new DNASymbol( symbols.charAt(i) ); legs[i] = false; } offsetX = int( 2*BORDER+textWidth( MATCH )); offsetY = ALINE; leftPadding = (int) ( (WIDTH-BORDER-offsetX-textWidth( symbols ) ) / 2 / textWidth( "A" ) ) ; } void setMaxPadding( int mmax ) { maxLeftPadding = mmax; } int getLeftPadding() { return leftPadding; } void shiftLeft() { leftPadding = max(0, leftPadding-1); } void shiftRight() { leftPadding = min(leftPadding+1, maxLeftPadding ); } void setOffsets( int x, int y ) { offsetX = x; offsetY = y; } //--- returns the string of symbols --- String getText() { return symbols; } int length() { return noSymbols; } //--- display text using default method --- void drawText() { float tw = textWidth( "A" ); text( symbols, offsetX, offsetY ); } //--- displays symbols as individual items --- void drawSymbols() { float tw = textWidth( "A" ); for ( int i=0; i<noSymbols; i++ ) { array[i].draw( offsetX+int( (i+leftPadding) * tw ), offsetY ); if ( legs[i] ) array[i].drawBarDown(); } } //--- setLeg: add a leg to symbol at index i --- void setLeg( int i ) { legs[i] = true; } //--- erase the symbols and the legs, if any --- void erase() { int tw = int( textWidth( "A" ) ); fill( 0 ); stroke( 0 ); rect( offsetX+leftPadding*tw, offsetY-12, noSymbols*tw, 12+LEGLENGTH ); for ( int i=0; i<noSymbols; i++ ) legs[i] = false; } } //--------------------------------------------------------------------- // _ _ ___ _ // __| |_ __ _| |_ _ _ ___/ __| |__ _ ______ //(_-< _/ _` | _| || (_-< (__| / _` (_-<_-< ///__/\__\__,_|\__|\_,_/__/\___|_\__,_/__/__/ // //--------------------------------------------------------------------- class statusClass { String[] lines; int[] X; int[] Y; color myColor = color( 99, 66, 204 ); statusClass() { lines = new String[5]; X = new int[5]; Y = new int[5]; for ( int i=0; i<5; i++ ) { lines[i] = str( i+1 ) + "."; X[i] = BORDER + int( textWidth( "A" ) ); Y[i] = STATUSTOP+22 + i * (STATUSHEIGHT / (5+1) ); } draw(); } void print( int i, String s ) { lines[i] = s; draw(); } void draw() { //--- erase the rectangle first --- fill( 0 ); stroke( myColor ); rect( BORDER, STATUSTOP, STATUSWIDTH, STATUSHEIGHT ); fill( myColor ); fill( 0 ); stroke( 0 ); int tw = int( textWidth( "Status" ) ); rect( BORDER+5, STATUSTOP, tw, 12 ); fill( myColor ); text( "Status", BORDER+5, STATUSTOP+4 ); for ( int i=0; i<5; i++ ) text( lines[i], X[i], Y[i] ); } } //--------------------------------------------------------------------- // ___ _ _ //| __| _ _ _ __| |_(_)___ _ _ ___ //| _| || | ' \/ _| _| / _ \ ' \(_-< //|_| \_,_|_||_\__|\__|_\___/_||_/__/ //--------------------------------------------------------------------- //--------------------------------------------------------------------- // INITFONT: initialize the fonts (must be nonproportional --- //--------------------------------------------------------------------- void initFont( ) { font = loadFont( "Monaco-12.vlw" ); textFont( font ); } //--------------------------------------------------------------------- // INITWINDOW: Draw the fixed text in the window //--------------------------------------------------------------------- void initWindow( String title ) { color myColor = color( 99, 66, 204 ); fill( myColor ); text( title, BORDER, TITLELINE ); textSize( 12 ); text( "A:", BORDER, ALINE ); text( "B:", BORDER, BLINE ); text( "Match:", BORDER, MLINE ); //--- setup Status box --- status = new statusClass(); status.print( 0, "Status Box" ); } //--------------------------------------------------------------------- // SETUP: <=== STARTUP POINT. PROCESSING STARTS HERE!!! //--------------------------------------------------------------------- void setup() { size( WIDTH, HEIGHT ); initFont(); background( 0 ); noStroke(); //--- initialize the window --- initWindow( "DNA Alignment" ); //--- create the first DNA string, and position it in window --- dna1 = new DNAString( FASTA1 ); dna1.setOffsets( int( 2*BORDER+textWidth( MATCH )) , ALINE ); //--- create 2nd DNA string and position it in window --- dna2 = new DNAString( FASTA2 ); dna2.setOffsets( int( 2*BORDER+textWidth( MATCH )) , BLINE ); //--- make each sequence know the length of the other, so that shifting //--- is limited. dna1.setMaxPadding( dna2.length() ); dna2.setMaxPadding( dna1.length() ); //--- find exact matches between the 2 sequences --- findMatching(); //--- draw both sequences --- dna1.drawSymbols(); dna2.drawSymbols(); } //--------------------------------------------------------------------- // DRAW: This is called many times a second. Use it to do animation. //--------------------------------------------------------------------- void draw() { } //--------------------------------------------------------------------- // FINDMATCHING: finds matching symbols between the two sequences in // their current alignment. //--------------------------------------------------------------------- void findMatching() { int pad1 = dna1.getLeftPadding(); int pad2 = dna2.getLeftPadding(); int start1 = 0; // where we start comparing Sequence 1 int start2 = 0; // where we start comparing Sequence 2 int end1 = dna1.length()-1; // where we end looking at Sequence 1 int end2 = dna2.length()-1; // where we end looking at Sequence 2 String dnaChar1 = dna1.getText(); // String representation of Sequence 1 String dnaChar2 = dna2.getText(); // " " " " 2 //println( "pad1="+pad1+" start1="+start1+" end1="+end1); //println( "pad2="+pad2+" start2="+start2+" end2="+end2); //--- figure out which sequence extends past the other --- if ( pad1 > pad2 ) start2 = pad1 - pad2; if ( pad2 > pad1 ) start1 = pad2 - pad1; if ( pad1+end1 > pad2+end2 ) end1 = pad2+end2+1; if ( pad1+end1 < pad2+end2 ) end2 = pad1+end1+1; //--- find the exact matches, and create a line between matching symbols --- int noMatches = 0; for ( int i=start1, j=start2; i<=end1 && j<=end2; i++, j++ ) if ( dnaChar1.charAt( i )==dnaChar2.charAt( j ) ) { dna1.setLeg( i ); noMatches += 1; } //--- display result in status box --- status.print( 0, "Number of maching symbols: " + str( noMatches ) ); } //--------------------------------------------------------------------- // KEYPRESSED(): called every time a key is pressed. if + or = are pressed // shift dna strings one way, if - or _ are pressed, shift the other way. //--------------------------------------------------------------------- boolean ping=true; // do not shift both of them at once! void keyPressed() { //--- + or = are pressed... shift top one right, bottom one left --- if (key=='+' || key=='=' ) { dna1.erase(); dna2.erase(); if ( ping ) dna1.shiftLeft(); else dna2.shiftRight(); findMatching(); dna1.drawSymbols(); dna2.drawSymbols(); } //--- - or _ have been pressed. Shift top one left, bottom one right--- if (key=='-' || key=='_' ) { dna1.erase(); dna2.erase(); if ( ping ) dna2.shiftLeft(); else dna1.shiftRight(); findMatching(); dna1.drawSymbols(); dna2.drawSymbols(); } //--- make sure next time we alternate the shifting --- ping = !ping; }