source: sasview/sansmodels/src/igor_wrapper/igorGenerator.py @ ce07fa8

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since ce07fa8 was ae3ce4e, checked in by Mathieu Doucet <doucetm@…>, 17 years ago

Moving sansmodels to trunk

  • Property mode set to 100644
File size: 12.8 KB
Line 
1#!/usr/bin/env python
2""" WrapperGenerator class to generate model code automatically.
3 
4  This code was written as part of the DANSE project
5  http://danse.us/trac/sans/wiki/WikiStart
6 
7"""
8
9import os, sys
10
11class WrapperGenerator:
12    """ Python wrapper generator for C models
13   
14        The developer must provide a header file describing
15        the new model.
16               
17        @author: Mathieu Doucet / UTK
18        @contact: mathieu.doucet@nist.gov
19    """
20   
21    def __init__(self, filename, args):
22        """ Initialization
23            @param filename: path of header file to wrap
24            @param args: list of parameters to disperse
25        """
26       
27        ## Name of .h file to generate wrapper from
28        self.file = filename
29       
30        # Info read from file
31       
32        ## Name of python class to write
33        self.pythonClass = None
34        ## Parser in struct section
35        self.inStruct = False
36        ## Name of struct for the c object
37        self.structName = None
38        ## Dictionary of parameters
39        self.params = {}
40        ## ModelCalculation module flag
41        self.modelCalcFlag = False
42        ## List of default parameters (text)
43        self.default_list = ""
44        ## Base struct name
45        self.base_struct = ""
46        ## Base header file name
47        self.base_header = ""
48        ## Bindings to parameter array
49        self.translation_list = ""
50        self.counter = 0
51        self.disperse_count = 0
52        self.disperse_code = ""
53        self.added_list = ""
54        self.phi_index = -1
55        self.theta_index = -1
56       
57        self.disp_list = args
58           
59       
60    def read(self):
61        """ Reads in the .h file to catch parameters of the wrapper """
62       
63        # Check if the file is there
64        if not os.path.isfile(self.file):
65            raise ValueError, "File %s is not a regular file" % self.file
66       
67        # Read file
68        f = open(self.file,'r')
69        buf = f.read()
70       
71        self.default_list = "    // List of default parameters:\n"
72        #lines = string.split(buf,'\n')
73        lines = buf.split('\n')
74        for line in lines:
75           
76            # Catch class name
77            key = "[PYTHONCLASS]"
78            if line.count(key)>0:
79                try:
80                    index = line.index(key)
81                    #toks = string.split( line[index:], "=" )
82                    toks = line[index:].split("=" )
83                    self.pythonClass = toks[1].lstrip().rstrip()
84                except:
85                    raise ValueError, "Could not parse file %s" % self.file
86               
87            # Catch struct name
88            if line.count("typedef struct")>0:
89                # We are entering a struct block
90                self.inStruct = True
91           
92            if self.inStruct and line.count("}")>0:
93                # We are exiting a struct block
94                self.inStruct = False
95   
96                # Catch the name of the struct
97                index = line.index("}")
98                #toks = string.split(line[index+1:],";")
99                toks = line[index+1:].split(";")
100                # Catch pointer definition
101                #toks2 = string.split(toks[0],',')
102                toks2 = toks[0].split(',')
103                self.structName = toks2[0].lstrip().rstrip()
104               
105            # Catch struct content
106            key = "[DEFAULT]"
107            if self.inStruct and line.count(key)>0:
108                # Found a new parameter
109                try:
110                    index = line.index(key)
111                    toks = line[index:].split("=")
112                    toks2 = toks[2].split()
113                    val = float(toks2[0])
114                   
115                    # Find in dispersed list
116                    if toks[1] in self.disp_list:
117                        print "Found ", toks[1]
118                        self.disperse_code += "    // %s\n" % toks[1]
119                        self.disperse_code += "    paramList[%i] = %i;\n" % (self.disperse_count, self.counter)
120                        self.disperse_count += 1
121                       
122                    #self.pythonClass = toks[1].lstrip().rstrip()
123                    units = ""
124                    if len(toks2) >= 2:
125                        units = toks2[1]
126                    self.default_list += "    //         pars[%i]:   %-15s = %s %s\n" % \
127                        (self.counter, toks[1], val, units)
128                       
129                    # Identify theta and phi indices, if present
130                    if toks[1].count('phi'):
131                        self.phi_index = self.counter
132                    if toks[1].count('theta'):
133                        self.theta_index = self.counter
134                       
135                    # Bindings
136                    self.translation_list += "    danse_pars.%s = pars[%i];\n" % ( toks[1], self.counter)
137                    self.counter += 1
138                 
139                except:
140                    raise ValueError, "Could not parse input file %s \n  %s" % \
141                        (self.file, sys.exc_value)
142               
143               
144    def write_c_wrapper(self):
145        """
146        Writes the C file to create the dispersed model function
147        """
148       
149        toks = os.path.basename(self.file).split('.')
150        file = open("src/disp_"+toks[0]+'.c', 'w')
151        template = open("templates/disperse_template.c", 'r')
152       
153        tmp_buf = template.read()
154        #tmp_lines = string.split(tmp_buf,'\n')
155        tmp_lines = tmp_buf.split('\n')
156       
157       
158        self.translation_list = self.default_list+self.translation_list
159       
160        sigma_txt = "\n"
161        for i in range(len(self.disp_list)):
162            ipar = self.counter+i
163            sigma_txt += "    sigmaList[%i] = dp[%i];\n" % (i, ipar)
164           
165        ipar = self.counter+len(self.disp_list)
166        sigma_txt += "\n    npts = (int)(floor(dp[%i]));\n" % ipar
167                     
168        self.disperse_code += sigma_txt
169       
170        # Document the added (dispersed) parameters
171        added_pars_txt = "\n"
172        for i in range(len(self.disp_list)):
173            ipar = self.counter+i
174            added_pars_txt += "    //         pars[%i]:   dispersion of %s\n" % (ipar, self.disp_list[i])
175           
176        ipar = self.counter+len(self.disp_list)
177        added_pars_txt += "    //         pars[%s]:   number of points in dispersion curve\n" % \
178                    str(self.counter+len(self.disp_list))                             
179       
180       
181        for tmp_line in tmp_lines:
182           
183            # Catch class name
184            newline = self.replaceToken(tmp_line, 
185                                        "[PYTHONCLASS]", 'C'+self.pythonClass)
186           
187            # Catch class name
188            newline = self.replaceToken(newline, 
189                                        "[MODELSTRUCT]", self.structName)
190           
191            # Dictionary initialization
192            param_str = "// bindings to parameter array\n"
193            newline = self.replaceToken(newline, 
194                                        "[BINDINGS]", self.translation_list)
195                           
196            newline = self.replaceToken(newline, 
197                                        "[DISPERSE]", self.disperse_code)
198           
199            # Name of .c file
200            #toks = string.split(self.file,'.')
201            toks = os.path.basename(self.file).split('.')
202            newline = self.replaceToken(newline, "[C_FILENAME]", toks[0])
203           
204            # Include file
205            newline = self.replaceToken(newline, 
206                                        "[INCLUDE_FILE]", os.path.basename(self.file))
207           
208            # Include file
209            newline = self.replaceToken(newline, 
210                                        "[NDISPERSE]", str(len(self.disp_list)))
211           
212            # Number of parameters
213            newline = self.replaceToken(newline, 
214                                        "[NPARS]", str(self.counter+len(self.disp_list)+1))
215           
216            # Documentation
217            newline = self.replaceToken(newline, 
218                                        "[PARS_LIST]", self.default_list+added_pars_txt)
219           
220            # Write new line to the wrapper .c file
221            file.write(newline+'\n')
222           
223           
224        file.close()
225       
226       
227    def write_weight_function(self):
228        """
229            Writes the C file to create the dispersed model function
230            with angular distributions
231        """
232        # If we dont' have any angle, just return
233        if self.phi_index<0 and self.theta_index<0:
234            return
235       
236       
237        toks = os.path.basename(self.file).split('.')
238        file = open("src/weighted_"+toks[0]+'.c', 'w')
239        template = open("templates/weighted_template.c", 'r')
240       
241        tmp_buf = template.read()
242        tmp_lines = tmp_buf.split('\n')
243           
244        #self.translation_list = self.default_list+self.translation_list
245        added_pars_txt = "\n"
246        for i in range(len(self.disp_list)):
247            ipar = self.counter+i
248            added_pars_txt += "    //         pars[%i]:   dispersion of %s\n" % (ipar, self.disp_list[i])
249           
250        ipar = self.counter+len(self.disp_list)
251        added_pars_txt += "    //         pars[%s]:   number of points in dispersion curve\n" % \
252                    str(self.counter+len(self.disp_list))
253        added_pars_txt += " * \n"
254        added_pars_txt += " * NOTE: DO NOT USE THETA AND PHI PARAMETERS WHEN\n"
255        added_pars_txt += " *       USING THIS FUNCTION TO APPLY ANGULAR DISTRIBUTIONS." 
256                             
257       
258       
259        for tmp_line in tmp_lines:
260           
261            # Catch class name
262            newline = self.replaceToken(tmp_line, 
263                                        "[PYTHONCLASS]", self.pythonClass)
264           
265            # Dictionary initialization
266            param_str = "// bindings to parameter array\n"
267            newline = self.replaceToken(newline, 
268                                        "[PARS_LIST]", self.default_list+added_pars_txt)
269                           
270            # Name of .c file
271            #toks = string.split(self.file,'.')
272            toks = os.path.basename(self.file).split('.')
273            newline = self.replaceToken(newline, "[MODEL_NAME]", toks[0])
274           
275            toks = os.path.basename(self.file).split('.')
276            newline = self.replaceToken(newline, "[C_FILE_NAME]", "disp_%s.c" % toks[0])
277           
278            # Include file
279            newline = self.replaceToken(newline, 
280                                        "[INCLUDE_FILE]", os.path.basename(self.file))
281           
282            # Include file
283            #newline = self.replaceToken(newline,
284            #                            "[NDISPERSE]", str(len(self.disp_list)))
285           
286            # Number of parameters
287            newline = self.replaceToken(newline, 
288                                        "[NPARS]",  str(self.counter+len(self.disp_list)+1))
289           
290            # Theta index
291            newline = self.replaceToken(newline, 
292                                        "[THETA_INDEX]",  str(self.theta_index))
293           
294            # Phi index
295            newline = self.replaceToken(newline, 
296                                        "[PHI_INDEX]",  str(self.phi_index))
297           
298            # Write new line to the wrapper .c file
299            file.write(newline+'\n')
300           
301           
302        file.close()
303       
304    def replaceToken(self, line, key, value): #pylint: disable-msg=R0201
305        """ Replace a token in the template file
306            @param line: line of text to inspect
307            @param key: token to look for
308            @param value: string value to replace the token with
309            @return: new string value
310        """
311        lenkey = len(key)
312        newline = line
313        while newline.count(key)>0:
314            index = newline.index(key)
315            newline = newline[:index]+value+newline[index+lenkey:]
316        return newline
317       
318       
319# main
320if __name__ == '__main__':
321    if len(sys.argv)>1:
322        print "Will look for file %s" % sys.argv[1]
323        app = WrapperGenerator(sys.argv[1], sys.argv[2:])
324        app.read()
325        app.write_c_wrapper()
326        app.write_weight_function()
327    else:
328        print "Usage: python igorGenerator.py [header file] [list of parameters to disperse]"
329        print ""
330        print "Example: "
331        print "    python igorGenerator.py cylinder.h cyl_phi cyl_theta"
332   
333# End of file       
Note: See TracBrowser for help on using the repository browser.