1 """
2 Application-class that implements pyFoamListCases.py
3 """
4 from optparse import OptionGroup
5 from os import path,listdir,stat
6 import time
7 from stat import ST_MTIME
8 import string
9 import subprocess
10 import re
11
12 from PyFoamApplication import PyFoamApplication
13
14 from PyFoam.RunDictionary.SolutionDirectory import SolutionDirectory
15
16 from PyFoam import configuration
17
20 description="""
21 List the valid OpenFOAM-cases in a number of directories along with some
22 basic information (number of timesteps, last timestep, etc). Currently
23 doesn't honor the parallel data
24 """
25 PyFoamApplication.__init__(self,
26 args=args,
27 description=description,
28 usage="%prog [<directories>]",
29 interspersed=True,
30 changeVersion=False,
31 nr=0,
32 exactNr=False)
33
34 sortChoices=["name","first","last","mtime","nrSteps","procs","diskusage","pFirst","pLast","nrParallel"]
35
37 what=OptionGroup(self.parser,
38 "What",
39 "Define what should be shown")
40 self.parser.add_option_group(what)
41
42 what.add_option("--dump",
43 action="store_true",
44 dest="dump",
45 default=False,
46 help="Dump the information as Python-dictionaries")
47
48 what.add_option("--disk-usage",
49 action="store_true",
50 dest="diskusage",
51 default=False,
52 help="Show the disk-usage of the case (in MB) - may take a long time")
53
54 what.add_option("--parallel-info",
55 action="store_true",
56 dest="parallel",
57 default=False,
58 help="Print information about parallel runs (if present): number of processors and processor first and last time. The mtime will be that of the processor-directories")
59
60 how=OptionGroup(self.parser,
61 "How",
62 "How the things should be shown")
63 self.parser.add_option_group(how)
64
65 how.add_option("--sort-by",
66 type="choice",
67 action="store",
68 dest="sort",
69 default=configuration().get("CommandOptionDefaults","sortListCases",default="name"),
70 choices=self.sortChoices,
71 help="Sort the cases by a specific key (Keys: "+string.join(self.sortChoices,", ")+") Default: %default")
72 how.add_option("--reverse-sort",
73 action="store_true",
74 dest="reverse",
75 default=False,
76 help="Sort in reverse order")
77
78 behave=OptionGroup(self.parser,
79 "Behaviour",
80 "Additional output etc")
81 self.parser.add_option_group(behave)
82
83 behave.add_option("--progress",
84 action="store_true",
85 dest="progress",
86 default=False,
87 help="Print the directories while they are being processed")
88
90 dirs=self.parser.getArgs()
91
92 if len(dirs)==0:
93 dirs=[path.curdir]
94
95 cData=[]
96 totalDiskusage=0
97
98 for d in dirs:
99 for n in listdir(d):
100 cName=path.join(d,n)
101 if path.isdir(cName):
102 try:
103 sol=SolutionDirectory(cName,archive=None,paraviewLink=False)
104 if sol.isValid():
105 if self.opts.progress:
106 print "Processing",cName
107
108 data={}
109
110 data["mtime"]=stat(cName)[ST_MTIME]
111 times=sol.getTimes()
112 try:
113 data["first"]=times[0]
114 except IndexError:
115 data["first"]="None"
116 try:
117 data["last"]=times[-1]
118 except IndexError:
119 data["last"]="None"
120 data["nrSteps"]=len(times)
121 data["procs"]=sol.nrProcs()
122 data["pFirst"]=-1
123 data["pLast"]=-1
124 data["nrParallel"]=-1
125 if self.opts.parallel:
126 pTimes=sol.getParallelTimes()
127 data["nrParallel"]=len(pTimes)
128 if len(pTimes)>0:
129 data["pFirst"]=pTimes[0]
130 data["pLast"]=pTimes[-1]
131 data["name"]=cName
132 data["diskusage"]=-1
133 if self.opts.diskusage:
134 data["diskusage"]=int(subprocess.Popen(["du","-sm",cName], stdout=subprocess.PIPE).communicate()[0].split()[0])
135 totalDiskusage+=data["diskusage"]
136 if self.opts.parallel:
137 for f in listdir(cName):
138 if re.compile("processor[0-9]+").match(f):
139 data["mtime"]=max(stat(path.join(cName,f))[ST_MTIME],data["mtime"])
140
141 cData.append(data)
142 except OSError:
143 print cName,"is unreadable"
144
145 if self.opts.progress:
146 print "Sorting data"
147
148 if self.opts.reverse:
149 cData.sort(lambda x,y:cmp(y[self.opts.sort],x[self.opts.sort]))
150 else:
151 cData.sort(lambda x,y:cmp(x[self.opts.sort],y[self.opts.sort]))
152
153 if len(cData)==0:
154 print "No cases found"
155 return
156
157 if self.opts.dump:
158 print cData
159 return
160
161 lens={}
162 for k in cData[0].keys():
163 lens[k]=len(k)
164 for c in cData:
165 c["mtime"]=time.asctime(time.localtime(c["mtime"]))
166 for k,v in c.iteritems():
167 lens[k]=max(lens[k],len(str(v)))
168
169 format=""
170 spec=["mtime"," | ","first"," - ","last"," (","nrSteps",") "]
171 if self.opts.parallel:
172 spec+=["| ","procs"," : ","pFirst"," - ","pLast"," (","nrParallel",") | "]
173 if self.opts.diskusage:
174 spec+=["diskusage"," MB "]
175 spec+=["name"]
176
177 for i,l in enumerate(spec):
178 if not l in cData[0].keys():
179 format+=l
180 else:
181 if i<len(spec)-1:
182 format+="%%(%s)%ds" % (l,lens[l])
183 else:
184 format+="%%(%s)s" % (l)
185
186 if self.opts.progress:
187 print "Printing\n\n"
188
189 header=format % dict(zip(cData[0].keys(),cData[0].keys()))
190 print header
191 print "-"*len(header)
192
193 for d in cData:
194 for k in d.keys():
195 d[k]=str(d[k])
196 print format % d
197
198 if self.opts.diskusage:
199 print "Total disk-usage:",totalDiskusage,"MB"
200