Read Mallivastaukset text version

Mallivastaukset

Tässä bioinformatiikan ohjelmointikurssin tentin 29.05.2002 malli vastauksia. Vastaukset eivät välttämättä ole erityisen mallikkaita, vaan suurinpiirtein tämän kaltaisia vastauksia odotin.

1. Mitä tekevät ja mahdollisesti tulostavat seuraavat ohjelman pätkät: a. use English; Kääntäjän 'pragma', jolla saa englantilaiset nimet erikoismuuttujille. while (<>) {if (/^SQ\s+/) { push @seqs=&getSeq($POSTMATCH)}} Tässä oli tahaton paino virhe, pitäisi olla push @seqs, &getSeq($POSTMATCH). Luetaan tiedostoista, jotka on annettu kutsuparametrina, rivejä. Jos rivin alussa on kirjaimet SQ ja vähintään yksi välilyönti, niin listaan @seqs lisätään aliohjelman getSeq tuottama arvo. getSeq saa parametrikseen rivin loppuosan. sub getSeq { my $str=shift; my $seq=""; Muuttujaan str siirretään välitetty rivin osa muuttuja seq alustetaan tyhjäksi. while ($str=~/([AGTCUagtcu]+)/g) { $seq=$seq.$1} Niin kauan kuin riviltä löytyy merkkejä A,G,T,C ,U,a,g,c,t,u niin ne lisätään muuttujaan $seq. Huom : tässä rivi voi sisältää muitakin merkkejä. Jos olisi haluttu ettei muita merkkejä ole ilmaus olisi ollut $str=~/^([AGTCUactcu]+)$/. return $seq } Palautetaan löytyneet merkit. Toiminta lyhyesti : SQ alkuisten rivien sisältämät nukleotidejä vastaavat merkit lisätään listaan @seqs yhtenä merkkijonona. b. @vec=([3,9,7],[8,7,6],[4,3,7,19]); Alustetaan vektori, jonka alkiot vektoreita. foreach $item (@vec { foreach $value (@{$item}) {print "$value - ";} print "\n";} Vektorin jokaisen alkion sisältämä lista käydään läpi ja tulostetaan listan alkio, välilyönti ja "-" merkki. Kun yksi lista on käyty läpi tulostetaan rivinvaihto. Tulostus: 3­9­78­7­64 ­ 3 ­ 7- 19 c. sub operoi { my ($frst,$scnd,$thrd,$oper)[email protected]_; if (&$oper($frst)<=&$oper($scnd) and &$oper($frst)<=&$oper($thrd)) { return $frst} elsif (&$oper($scnd))<=&$oper($frst) and &$oper($scnd)<=&$oper($thrd)) {return $scnd} else {return $thrd} } Aliohjelma operoi saa neljä kutsuparametria, joista viimeistä ($oper) käsitellään funktiona. Aliohjelmassa itsessään palautetaan kolmesta ensimmäisestä se parametri , joka antaa pienimmän arvon funktiolla $oper. print &operoi(2,-4,-3,sub { return (shift)**2}); Tulostetaan aliohjelman operoi arvo, kun parametriksi annetaan 2, -4, -3 ja nimetön funktio, joka palauttaa kutsuparametriensa ensimmäisen arvon toiseen potenssiin korotettuna. Koska 2x2 =4, -4 x -4 = 16 ja -3 x -3 =9 , niin tulostuu 2.

2. Seuraavassa ohjelman pätkässä on sekä loogisia, että syntaksivirheitä. Mitä ne ovat ja miten korjaisit virheet ? Kuten eräs tenttijä huomautti, varsinaisia syntaksivirheitä ei ole, sillä Perl-tulkki suorittaa ohjelman ilman nikottelua. Tarkoitus kyllä oli laittaa joukkoon aito syntaksivirhekin. Minun mokani, sori. sub revcomp { # antaa parametrina annetusta DNA-sekvenssistä # sen käänteisen komplementin Parametrilistan käsittely puuttuu. Missään kohtaan ei muuttujaan $mjono aseteta parametrilistasta @_ mitään arvoa. $mjono=s/G/T/g; Yllä oleva ei ole varsinaisesti syntaksivirhe, sillä tämä menee tulkin kääntämisvaiheesta läpi. Tässä G:n korvaus T:ksi tehdään erikoismuuttujaan $_ ja korvausten lukumäärä menee muuttujaan $mjono. $mjono=~s/C/G/g; $mjono=~s/T/A/g; $mjono=~s/A/T/g; Logiikka ei pelaa: jos ensin muuttaa T:t A:ksi, niin sen jälkeen ne muuttuvat takaisiin Tkirjaimiksi, kun A-kirjaimia muutetaan. Korvaus tehdään joko funtiolla tr tai jonkin muunnoksen kauttaa. Paha virhe on myös, että mitään arvoa ei funktiosta palauteta. Saatikka, että se olisi käänteinen komplementti. } my $dna="cgtgagcgatgttaggcttttgcagtgatgcgatga"; print "Sekvenssin $dna käänteinen komplementti revcomp($dna)\n"; Funktion kutsu ei interpoloidu lainauksessa. Ainut mahdollisuus on tuoda funktion kutsu lainausten ulkopuolelle. Kutsusta voisi myös päätellä, että funktion odotetaan toimivan myös pienin kirjaimin. Korjaava funktio sub revcomp { my $mjono=shift; $mjono=~tr/TCGAtcga/AGCTagct/; return reverse $mjono;} Oikea tapa kutsua funktio: print "Sekvenssin $dna käänteinen komplementti" , revcomp($dna),"\n";

3. Tee aliohjelma, joka laskee kodonien frekvenssit ensimmäisenä parametrina annetusta DNA-sekvenssistä

(merkkijono). Toisena parametrina aliohjelma saa lukukehyksen alkukohdan (kokonaisluku) tai kodonin (kolmen merkin mittainen merkkijono), jonka jälkeen tulevien kodonien frekvenssit lasketaan. Luonnollisin tapa tässä on laskea frekvenssi kunkin kodonin osalta assosiatiiviseen taulukkoon Eräs tapa tämän ratkaisemiseksi, olisi tehdä assosiatiivinen taulukko, joka sisältää kaikki oikeat kodonit ja niiden määräksi alustaa nollan. Silloin ei haittaa, vaikka merkkijonosta tulisi muitakin merkkejä. Toki voi myös testata merkkijonosta otettun kodonin laillisuutta. Kodonitaulukon alustuksen voi esimerkiksi tehdä helposti aliohjelmalla: sub setCodons { my @blist= qw / a c t g /; my %table=(); foreach my $b1 (@blist) { foreach my $b2 (@blist) { foreach my $b3 (@blist) { $table{$b1.$b2.$b3}=0} } } return %table; } Seuraavaksi täytyy tarkistaa onko parametriksi annettu kodoni vai luku. Sekvenssin merkit kannattaa laittaa joko iso-tai pienikirjaimisiksi, niin kodonit on helpompi laskea. sub codonFreq { my ($dna,$pos)[email protected]_; my %freqTable= setCodons; if ($pos=~/^[ACGTacgt]{3}$/) { $dna = ~ /$pos(.*)$/; # $1 sisältää loput kodonit # saman saisi $` eli # $POSTMATCH erikoismuuttujalla $dna= lc $1} elsif ($pos=~/^\d+$/) { $dna= lc substr $dna,$pos} else {die "Illegal value pos= $pos\n"} #l lopetetaan jos $pos ei kodoni tai numero while ($dna=~/([acgt]{3})/g) { $freqTable{$1}++;} return %freqTable; } Yllä olevassa koodissa testataan , että onko toinen parametri laillinen. Jos jätämme testaukset ja alustukset pois saamme hieman lyhyemmän ratkaisun: sub codonFreq($$) { my ($dna,$pos)[email protected]_; my %freq=(); if ($dna=~/$pos(.*)$/) {$dna=$1} else {$dna=substr $dna,$pos} foreach my $k ( $dna=~/[tcgaTCGA]{3}/g) { $freq{ lc $k }++} return %freq; } Tässä ratkaisussa on eräs ominaisuus, joka ei ehkä ole toivottu. Jos annettua kodonia ei löydy, lasketaan kodonifrekvenssi alusta alkaen.

Olet saanut amerikkalaiselta ystävältäsi tiedoston, jossa on mittaustuloksia. Tiedoston jokaisella rivillä on ensin mittauskohteen tunnus, sitten lämpötila Fahrenheit-asteina, sitten etäisyysmittoja tuumissa. Etäisyysmittojen lukumäärä voi vaihdella, mutta niitä on aina vähintään yksi joka rivillä. Mittaustulokset on pilkuilla erotettu toisistaan. Tee muunnosohjelma, joka tuottaa tiedoston, jossa lämpötilat ovat Celcius-asteina ja etäisyydet millimetreinä. (1 tuuma = 25.4 mm ja Fahrenheit-asteet muunnetaan Celcius-asteiksi kaavalla C=(F-32)/1.8 ). Tiedoston yksi rivi voisi siis olla vaikka: A234 34.5, 0.987, 1.23, 2.22, 1.989 Tämän tehtävän perusratkaisuksi odotin sellaista, että esim splitin avulla erotetaan kentät toisistaan, sitten tehdään muunnokset ja tulostetaan. Tehtävän voi tehdä myös säännöllisten ilmausten avulla korvaamalla ensin riviltä Fahrenheitit Celcius-asteilla ja sitten muuntaa tuumat milleiksi. Kun säännöllisiä ilmauksia käyttää, hyvä olisi huomata, että lämpötila voi saada negatiivisiakin arvoja. Perusratkaisu: Ensin kirjoitetaan aliohjelmat, jotkat tekevät muunokset, sitten kirjoitetaan tiedostojen avaukset. Luettu rivi paloitellaan split-funktiolla ensin pilkun mukaan, jolloin ensimmäisessä palassa on tunnus ja lämpötila välilyönnillä erotettuna etäisyydet menee vektoriin @millit. Tuo ensimmäinen pala jaetaan kahtia välilyönnin perusteella, jolloin tunnus ja lämpötila saadaan erikseen. Sitten tulostetaan tunnus, lämpötila, ja sub f2c ($) { return ($_[0]-32)/1.8} sub t2mm ($) { return 25.4*$_[0]} open (IN,"tuumat.txt") or die "Tiedosto ei aukea\n"; open (OUT,">millit.txt") or die "Ei kirjoitettavissa\n"; while (<IN>) { my $fahr; my ($first,@millit)=split /,/; my ($tunnus,$fahr)=split /\s+/, $first; print OUT "$tunnus ",f2c($fahr); foreach my $mm (@millit) { print ", ",t2mm($mm);} print OUT "\n"; } close OUT; close IN; Lyhyt: Säännöllisillä ilmauksilla ratkaisusta saa lyhyen, sillä tarvitaan vain viisi käskyä. En odottanut, että kukaan yrittäisi lyhyttä versiota. Ohjelma lukee parametrina annetun tiedoston kokonaan muistiin, joten jos tiedosto on hyvin suuri, alkaa kone takkuamaan, kun muisti täyttyy. Ohjelman tulostus pitää ohjata tiedostoon eli käyttö: perl milleiksi.pl tuumat.txt > millit.txt. Ratkaisussa ensin otetaan riviltä ensimmäisenä löytyvä tunnus ja sen perässä olevat välilyönnit (\S\s+) $1:een, sitten toisena löytyvä lämpötila ja sen perässä oleva pilkku (\S+) $2:een. Ne korvataan katenoimalla $1 $2:sta laskettavan Celsiusasteen kanssa ja sitten vielä perään katenoidaan pilkku $1.(($2-32)\/1.8).",". Optioina tarvitaan mge eli m = käsitellään $_:aa monena rivinä, g= kaikki löytyvät ja e=evaluoidaan oikea puoli. Sitten toisella ilmauksella korvataan tuumat millimetreillä. undef $/; $_=<>; s/^(\S+\s+)(\S+)/$1.(($2-32)\/1.8).","/mge; s/,\s*(\d+\.?\d*)/", ".(25.4*$1)/ge; print

4

Information

Mallivastaukset

4 pages

Report File (DMCA)

Our content is added by our users. We aim to remove reported files within 1 working day. Please use this link to notify us:

Report this file as copyright or inappropriate

853431