erange 4.0a dev release with integrated cistematic
[erange.git] / cistematic / programs / meme.py
1 ###########################################################################
2 #                                                                         #
3 # C O P Y R I G H T   N O T I C E                                         #
4 #  Copyright (c) 2003-10 by:                                              #
5 #    * California Institute of Technology                                 #
6 #                                                                         #
7 #    All Rights Reserved.                                                 #
8 #                                                                         #
9 # Permission is hereby granted, free of charge, to any person             #
10 # obtaining a copy of this software and associated documentation files    #
11 # (the "Software"), to deal in the Software without restriction,          #
12 # including without limitation the rights to use, copy, modify, merge,    #
13 # publish, distribute, sublicense, and/or sell copies of the Software,    #
14 # and to permit persons to whom the Software is furnished to do so,       #
15 # subject to the following conditions:                                    #
16 #                                                                         #
17 # The above copyright notice and this permission notice shall be          #
18 # included in all copies or substantial portions of the Software.         #
19 #                                                                         #
20 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,         #
21 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF      #
22 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND                   #
23 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS     #
24 # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN      #
25 # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN       #
26 # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE        #
27 # SOFTWARE.                                                               #
28 ###########################################################################
29 #
30 # meme.py
31 import os
32 import time
33 import string
34 from cistematic.programs import Program
35 from cistematic.core.motif import Motif
36 from erange.commoncode import getConfigParser, getConfigOption
37
38 SUPPORTED_MODELS = ["oops", "zoops", "tcm"]
39
40 class Meme(Program):
41     
42
43     def __init__(self):
44         parser = getConfigParser()
45         memeProgramName = getConfigOption(parser, "programs", "meme", default="meme.3.0.8")
46         self.memePath = string.join([Program.programRoot, memeProgramName], "/")
47         self.model = "zoops"
48         self.background = ""
49         self.numMotifs = 10
50         self.minWidth = 6
51         self.maxWidth = 15
52         self.bfile = ""
53         self.motifs = []
54         self.contents = []
55
56
57     def getSettings(self):
58         return (self.model, self.background, self.numMotifs, self.bfile)
59
60
61     def setSettings(self, settings):
62         self.clearMotifList()
63         try:
64             (self.model, self.background, self.numMotifs, self.bfile) = settings
65         except ValueError:
66             print "Error unpacking settings for Meme. No parameters changed."
67
68
69     def setGenExpOptions(self, optionArray):
70         for option in optionArray:
71             try:
72                 (optionName, optionValue) = option.split(":")
73             except ValueError:
74                 continue
75
76             if optionName == "model":
77                 self.setModel(optionValue)
78
79             if optionName == "nmotifs":
80                 self.setNumMotifs(optionValue)
81
82             if optionName == "maxwidth":
83                 self.setMaxWidth(optionValue)
84
85
86     def buildCommand(self):
87         argList = ["%s/bin/meme" % self.memePath,
88                    self.inputFilePath,
89                    "-dna -maxsize 1000000",
90                    "-maxw %d" % self.maxWidth,
91                    "-minw %d" % self.minWidth,
92                    "-mod %s" % self.model,
93                    "-revcomp -nmotifs %d" % self.numMotifs
94         ]
95
96         if self.bfile != "":
97             argList.append("-bfile %s" % self.bfile)
98
99         cmd = string.join(argList, " ")
100
101         return cmd
102
103
104     def setModel(self, modelType):
105         if modelType in SUPPORTED_MODELS:
106             self.model = modelType
107
108
109     def setNumMotifs(self, motifNum):
110         self.numMotifs = motifNum
111
112
113     def setMinWidth(self, width):
114         self.minWidth = width
115
116
117     def setMaxWidth(self, width):
118         self.maxWidth = width
119
120
121     def setBackground(self, backgroundFileName):
122         self.bfile = backgroundFileName
123
124
125     def clearMotifList(self):
126         self.motifs = []
127
128
129     def setContents(self, motifFile):
130         self.contents = motifFile.readlines()
131
132
133     def run(self):
134         startTime = time.time()
135         memeResultFile = os.popen(Meme.buildCommand(self))
136         self.setContents(memeResultFile)
137         stopTime = time.time()
138     
139         print "\nThis run took %.3f seconds and produced %d lines" % (stopTime - startTime, len(self.contents))
140  
141  
142     def getMotifs(self):
143         index = 0
144         self.clearMotifList()
145         try:
146             for motif in range(0, self.numMotifs):
147                 PWM = []
148                 seqList = []
149                 index = self.locateMotifSeqs(index)
150                 info = self.contents[index]
151                 index += 1
152                 while string.find(self.contents[index], "//") < 0:
153                     fields = self.contents[index].split()
154                     seqList.append(fields[-2])
155                     index += 1
156
157                 motifName = "%s-meme-%d" % (self.tagID, motif + 1)
158                 self.motifs.append(Motif(motifName, "", PWM, seqList, 0.0, info))
159         except:
160             pass
161
162         return self.motifs
163
164
165     def locateMotif(self, startingLineNum):
166         return self.getDataLineNumberAfterHeader("pspm_doc", startingLineNum)
167
168
169     def locateMotifSeqs(self, startingLineNum):
170         return self.getDataLineNumberAfterHeader("BLOCKS_doc", startingLineNum)
171
172
173     def getDataLineNumberAfterHeader(self, headerText, startingLineNum):
174         currentLineNum = startingLineNum
175         numLines = len(self.contents)
176         while currentLineNum < numLines and string.find(self.contents[currentLineNum], headerText) < 0:
177             currentLineNum += 1
178
179         if currentLineNum < numLines:
180             return currentLineNum + 3
181
182         return -1