Changeset 269

Show
Ignore:
Timestamp:
01/19/08 02:51:20 (10 months ago)
Author:
t
Message:

interface to build PWM from list of input sites

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/cartwheel-server/lib/cartwheel/website/IUPACMotif.py

    r266 r269  
    1616        return "motif: %s; match %d/%d by default" % \ 
    1717               (self.motif, len(self.motif) - self.mismatches, len(self.motif)) 
     18 
     19    def simple_key(self): 
     20        return self.motif 
  • trunk/cartwheel-server/lib/cartwheel/website/NamedMotif.py

    r266 r269  
    55    mymembers = ('name', 'motif_type', 'folder_id', 'visible') 
    66 
    7     def search(self, sequence): 
     7    def search(self, sequence):         # actually runs the search 
    88        raise NotImplementedError 
    99 
    10     def extra_information(self): 
     10    def extra_information(self):        # info box output 
    1111        raise NotImplementedError 
     12 
     13    def simple_key(self):               # key for display tagging 
     14        raise NotImplementedError 
  • trunk/cartwheel-server/lib/cartwheel/website/PWMMotif.py

    r261 r269  
     1""" 
     2A PWM motif created from a list of sites. 
     3""" 
    14from cartwheel.website.NamedMotif import NamedMotif 
    25 
     
    47    table = 'pwm_motifs' 
    58    mymembers = ('source_motifs', 'default_threshold') 
     9 
     10    def search(self, sequence): 
     11        """ 
     12        sequence is FolderSequence. 
     13        """ 
     14        import motility 
     15 
     16        sites = self.source_motifs.split("\n") 
     17        pwm = motility.make_pwm(sites) 
     18 
     19        return pwm.find(sequence.seq, self.default_threshold) 
     20 
     21    def extra_information(self): 
     22        import motility 
     23         
     24        sites = self.source_motifs.split("\n") 
     25        consensus = motility.make_iupac_motif(sites) 
     26         
     27        return "PWM consensus: %s; default threshold %f" % (consensus, 
     28                                                       self.default_threshold) 
     29    def simple_key(self): 
     30        import motility 
     31         
     32        sites = self.source_motifs.split("\n") 
     33        consensus = motility.make_iupac_motif(sites) 
     34        return consensus 
  • trunk/cartwheel-server/tests/functional-tests/test-with-user/test-web/test-folder-motifs.py

    r268 r269  
    167167    find('18 matches, sorted by position.') 
    168168    back() 
     169 
     170    ## end 
     171    back() 
     172    follow('Return to folder menu') 
     173 
     174def test_add_pwm_motif(): 
     175    show() 
     176    follow("manage motifs") 
     177    follow("build_pwm_from_list") 
     178 
     179    fv('1', 'name', 'test_pwm_gata') 
     180    fv('1', 'aligned', 'AGATAG\nTGATAG\nTGATAA') 
     181 
     182    submit() 
     183 
     184    show() 
     185 
     186    find("Matrix motif 'test_pwm_gata' created.") 
     187    find("lowest recommended threshold: 10.58") 
     188    find("prob/base with this score: 7.324219e-04") 
     189 
     190    follow("Return to motif list") 
     191 
     192    ## end 
     193    follow('Return to folder menu') 
  • trunk/cartwheel-server/website/canal/motif/__init__.py

    r266 r269  
    55import cartwheel.website 
    66from canal.motif.analyze import AnalyzeSequenceHandler 
    7 from pages import add_iupac, _q_index 
     7from pages import add_iupac, _q_index, build_pwm_from_list 
    88 
    9 _q_exports = ['add_iupac', 'delete', 'edit', 'go_analyze' ] 
     9_q_exports = ['add_iupac', 'delete', 'edit', 'go_analyze', 
     10              'build_pwm_from_list'] 
    1011 
    1112def edit(request): 
  • trunk/cartwheel-server/website/canal/motif/analyze.ptl

    r268 r269  
    2626        for motif in motifs: 
    2727            motif = self.manager.load(motif.id) 
     28            key = motif.simple_key() 
     29             
    2830            """ 
    2931            %s: %d matches <a href='matches_detail?motif_id=%d' 
    3032                              id='detail-%s'>detail</a><br> 
    3133            """ % (motif.name, len(motif.search(self.seq)), motif.id, 
    32                    motif.motif
     34                   key
    3335             
    3436    template matches_detail(self, request): 
  • trunk/cartwheel-server/website/canal/motif/pages.ptl

    r266 r269  
    22from canal.templates import header, footer 
    33from cartwheel.website.IUPACMotif import IUPACMotif 
     4from cartwheel.website.PWMMotif import PWMMotif 
    45from canal.group.utils import make_sequence_list_widget 
    56 
     
    78import motility 
    89 
    9 nice_motif_types = dict(IUPAC='simple motif (IUPAC notation)') 
     10nice_motif_types = dict(IUPAC='simple motif (IUPAC notation)', 
     11                        PWM='matrix motif (PWM)') 
    1012 
    1113template _q_index(request): 
     
    3840              <td align='right'> 
    3941                <font size='-1'> 
    40                   <a href='delete?motif_id=%d'>delete</a> | 
    41                   <a href='edit?motif_id=%d'>edit</a> 
     42                  <a href='delete?motif_id=%d' id='delete-%s'>delete</a> | 
     43                  <a href='edit?motif_id=%d' id='edit-%s'>edit</a> 
    4244                </font> 
    4345              </td> 
     
    4648                   nice_motif_types[motif.motif_type], 
    4749                   motif.extra_information(), 
    48                    motif.id, motif.id)  
     50                   motif.id, motif.simple_key(), 
     51                   motif.id, motif.simple_key()) 
    4952 
    5053        """ 
     
    5861    """ 
    5962    <hr> 
    60  
    61     <A href="add_iupac">Add a simple motif</a> 
     63    <A href="add_iupac">Add a simple motif</a> | 
     64    <a href="build_pwm_from_list">build a matrix (PWM) 
     65                                  from a list of known sites</a> | 
     66    <font color='red'>import a matrix from JASPAR (not yet!)</font> 
    6267    <p> 
    6368    """ 
     
    155160 
    156161    return d 
     162 
     163def build_pwm_from_list(request): 
     164    if not request.form: 
     165        return """\ 
     166<form method="POST"> 
     167<h3>Build a matrix motif (PWM) from a list of known sites</h3> 
     168Name: <input type='text' name='name'> 
     169<p> 
     170Aligned sequences:<br> 
     171<textarea name='aligned' rows='5' cols='30'></textarea> 
     172<p> 
     173<input type='submit' value='build PWM'> 
     174</form> 
     175<hr> 
     176<b>Instructions:</b> 
     177<p> 
     178To build a matrix motif (a.k.a. Position-Weight Matrix, or PWM),  
     179enter a list of ungapped, aligned sequences.  For example, here is a list 
     180of GATA-type motifs: 
     181<pre> 
     182AGATAG 
     183TGATAG 
     184TGATAA 
     185</pre> 
     186 
     187After submitting this list, a matrix motif will be built and you can 
     188then define a threshold for searches. 
     189""" 
     190 
     191    errors = [] 
     192 
     193    name = request.form['name'].strip() 
     194 
     195    if not name: 
     196        errors.append("you must enter a name!") 
     197 
     198    sequences = request.form['aligned'].split('\n') 
     199    sequences = [ s.strip().upper() for s in sequences ] 
     200    sequences = [ s for s in sequences if len(s) ] 
     201 
     202    if len(sequences) <= 1: 
     203        errors.append('you must enter at least two sequences') 
     204 
     205    lens = [ len(s) for s in sequences ] 
     206    if max(lens) != min(lens): 
     207        errors.append('all sequences must be the same length') 
     208 
     209    for s in sequences: 
     210        if '-' in s: 
     211            errors.append('one or more of your sequences contains a gap!') 
     212            break 
     213 
     214    # check for only ATCG 
     215    d = {} 
     216    for s in sequences: 
     217        for ch in s: 
     218            d[ch] = 1 
     219 
     220    for ch in 'A', 'T', 'C', 'G', '-':  # already covered gap error, above 
     221        if ch in d: 
     222            del d[ch] 
     223 
     224    if len(d): 
     225        errors.append("there is at least one non-DNA character in your sequences; here's a list: %s" % (", ".join(d.keys()))) 
     226 
     227    if errors: 
     228        return "ERROR:<p><ul><li> %s</ul>" % ("<li>".join(errors,)) 
     229 
     230    ### ok, validation good so far.  build the PWM & display... 
     231     
     232    return display_pwm_from_sites(request, name, sequences) 
     233 
     234template display_pwm_from_sites(request, name, sequences): 
     235    header("Motif '%s' created" % (name,)) 
     236     
     237    "<h2>Matrix motif '%s' created.</h2>" % (name,) 
     238     
     239    pwm = motility.make_pwm(sequences) 
     240 
     241    x = [] 
     242 
     243    # build index header 
     244    xx = [] 
     245    for i in range(len(pwm)): 
     246        xx.append("<td align='center'><i><font size='-1'>%d</font></i></td>" % (i + 1,)) 
     247    x.append("<tr><td></td>" + "".join(xx) + "</tr>") 
     248 
     249    dna = 'A', 'C', 'G', 'T' 
     250    maxes = [ max(pwm.matrix[j]) for j in range(len(pwm)) ] 
     251 
     252    for i in range(4): 
     253        xx = ["<td><font size='-1'><i>%s</i></font></td>" % (dna[i],)] 
     254 
     255        for j in range(len(pwm)): 
     256            val = pwm.matrix[j][i] 
     257            if val == maxes[j]: 
     258                xx.append("<td align='center'><b>%.2f</b></td>" % (val,)) 
     259            elif val == 0: 
     260                xx.append("<td align='center'>-</td>") 
     261            else: 
     262                xx.append("<td align='center'>%.2f</td>" % (val,)) 
     263 
     264        x.append("<tr>" + "".join(xx) + "</tr>") 
     265 
     266    # display table 
     267    "<h3>Matrix:</h3>" 
     268    "<table border='1'>" + "\n".join(x) + "</table>" 
     269 
     270    ### 
     271 
     272    min_score = pwm.min_score() 
     273    max_score = pwm.max_score() 
     274 
     275    site_scores = [ (pwm.calc_score(s),s) for s in sequences ] 
     276    site_scores.sort() 
     277    site_scores.reverse() 
     278 
     279    x = [] 
     280    for score, site in site_scores: 
     281        x.append('<tr><td>%s:</td><td>%.2f</td>' % (site, score,)) 
     282 
     283 
     284    ### 
     285         
     286    "<p>" 
     287    """ 
     288    <table border='1'> 
     289    <tr><th>Input site</th><th>PWM score</th></tr> 
     290    """ 
     291     
     292    "".join(x) 
     293     
     294    "</table>" 
     295 
     296    ### 
     297 
     298    lowest_score = site_scores[-1][0] 
     299 
     300    """ 
     301    <p> 
     302    lowest recommended threshold: %.2f; 
     303    prob/base with this score: %e 
     304    """ % (lowest_score, pwm.weight_sites_over(lowest_score)) 
     305 
     306    ### 
     307 
     308    manager = cartwheel.website.get_object_manager() 
     309 
     310    folder_id = request.session.get_current_folder().id 
     311 
     312    manager.create(PWMMotif, name=name, source_motifs="\n".join(sequences), 
     313                   motif_type='PWM', 
     314                   default_threshold=lowest_score, 
     315                   folder_id=folder_id) 
     316 
     317    manager.commit() 
     318 
     319    """ 
     320    <p> 
     321    <a href='./'>Return to motif list</a> 
     322    """ 
     323 
     324    footer()