1 #!/usr/bin/env mpipython
4 # gpiv_series - Processes a set of numbered input data
6 # Copyright (C) 2008 Gerber van der Graaf
8 # This program is free software; you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation; either version 2, or (at your option)
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program; if not, write to the Free Software Foundation,
20 # Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23 #--------------------------------------------------------------------
26 # This version is MPI enabled for parallel processing
29 from Scientific
import MPI
30 communicator
= MPI
.world
.duplicate()
33 #----------- Command line arguments parser
35 from optparse
import OptionParser
37 usage
= "%prog [options] \"process\""
38 parser
= OptionParser(usage
)
39 parser
.add_option("-a", "--arg_n",
40 action
="store_true", dest
="arg_n", default
=False,
41 help="if the process needs the current number in its \
42 argument list instead of prepending/appending it to the \
43 filebase name, the number will be put before (-f) \
44 \"filename\" in the \"process\" string.")
45 parser
.add_option("-b", "--basename", type='string', dest
="basename",
46 help="File basename for reading", metavar
="FILE")
47 parser
.add_option("-e", "--ext", type='string', dest
="ext", metavar
="EXT",
48 help="add an extension after the file basename + number (without leading \".\")")
49 parser
.add_option("-f", "--first", type='int', dest
="first_nr", default
=0,
50 help="first numbered file (default: 0)", metavar
="N")
51 parser
.add_option("-l", "--last", type='int', dest
="last_nr", default
=0,
52 help="last numbered file(default: 0)", metavar
="N")
53 parser
.add_option("-i", "--incr", type='int', dest
="incr_nr", default
=1,
54 help="increment file number (default: 1)", metavar
="N")
55 parser
.add_option("-p", "--print",
56 action
="store_true", dest
="pri", default
=False,
57 help="prints process parameters/variables to stdout")
58 parser
.add_option("--pad", type='int', dest
="pad0", default
=0,
59 help="padding number with zero's (default: 0)", metavar
="N")
60 parser
.add_option("-s", "--subst_fname",
61 action
="store_true", dest
="subst_fname", default
=False,
62 help="substitutes all occurences \"FNAME\" in the \"process\" string by the actual \
63 file basename. The option --arg_n will not have effect")
64 parser
.add_option("-n", "--none",
65 action
="store_true", dest
="none", default
=False,
66 help="suppresses real execution")
67 parser
.add_option("-x", "--prefix", action
="store_true", dest
="prefix", default
=False,
68 help="prefix numbering to file basename")
70 (options
, args
) = parser
.parse_args()
72 parser
.error("incorrect number of arguments")
78 #----------- Function definitions
80 def pri_date(msg
= "Time stamp at start of series processing:"):
84 msg -- message to be printed before time stamp
86 if options
.pri
== True:
96 """Counts number of digits from a number
99 nr -- number to be questioned
109 """Created a string for zero padding
112 nr -- number of zeros to be padded
115 for i
in range(0, nr
):
121 def compose_name_nr(nr
):
122 """Creates proper name from basename and number.
125 nr -- number of filename to be processed
128 ndig
=count_digits(nr
)
129 null_str
=pad0(options
.pad0
- ndig
)
130 nr_str
=null_str
+str(nr
)
136 name
=str(options
.basename
)
138 name
=nr_str
+str(options
.basename
)
141 name
=str(options
.basename
)
143 name
=str(options
.basename
)+nr_str
145 if str(options
.ext
) != "None":
146 name
=str(name
)+str(".")+str(options
.ext
)
151 def compose_cmd(name
, nr
):
152 """Creates proper command.
155 name -- complete filename
158 # Eventually, substitutes "-f" with: "nr -f"
160 command_tmp
=re
.sub("-f", str(nr
)+" -f", command
)
161 if command_tmp
!= command
:
162 command
= str(command_tmp
)+" "+str(name
)
164 command
= str(command_tmp
)+" "+str(nr
)+" "+str(name
)
166 # Eventually, substitutes "FNAME" with the file base name
167 if options
.subst_fname
:
168 command
=re
.sub("FNAME", str(name
), str(process
))
170 command
=str(command
)+" "+str(name
)
175 def proc_series_par():
176 """Processes a series on identic numbered files in parallel
177 environment using mpipython.
181 # Total number of data and number of data per node
183 Nt
= (options
.last_nr
+1 - options
.first_nr
) / options
.incr_nr
184 Nn
= Nt
/ communicator
.size
187 # Bail out if number of nodes is larger than number of data
189 if communicator
.size
> Nt
:
190 print 'nprocs (',communicator
.size
,\
191 ') larger then number of data (',Nt
,")"
195 for i
in range(options
.first_nr
, options
.last_nr
+1, options
.incr_nr
):
196 for j
in range(0, communicator
.size
, 1):
197 if communicator
.rank
== j
:
198 if i
>= options
.first_nr
+ j
*Nn
*options
.incr_nr
:
199 if i
< options
.first_nr
+ (j
+1)*Nn
*options
.incr_nr
:
200 name_nr
= compose_name_nr(i
)
201 command
= compose_cmd(name_nr
, i
)
202 if options
.pri
== True: print "rank=",communicator
.rank
,command
203 elif options
.none
== True: print "rank=",communicator
.rank
,command
204 if options
.none
== False: os
.system(command
)
207 # The fraction of data left, if Nn is not an integer,
208 # is processed at the highest node
210 if j
== communicator
.size
- 1:
211 if i
>= options
.first_nr
+ (j
+1)*Nn
*options
.incr_nr
:
212 name_nr
= compose_name_nr(i
)
213 command
= compose_cmd(name_nr
, i
)
214 if options
.pri
== True: print "rank=",communicator
.rank
,command
215 elif options
.none
== True: print "rank=",communicator
.rank
,command
216 if options
.none
== False: os
.system(command
)
220 #----------- Calling functions
222 #if communicator.rank == 0:
223 # if options.pri == True: pri_date()
224 # elif options.none == True: pri_date()
228 #communicator.rank == 0:
229 # if options.pri == True: pri_date(msg = "Time stamp at end of series processing:")
230 # elif options.none == True: pri_date(msg = "Time stamp at end of series processing:")
233 #----------- That's all folks