1
2 import os
3 import sys
4 import re
5 import shutil
6 import empro
7 from empro.toolkit import fileutil
8 from empro.toolkit.simulation import ENGINES, FDTD, FEM
11 """
12 A Python representation of an EMPro Project by path name
13 """
15 """
16 @type path string
17 @param path path to project, e.g. foo/bar.ep
18 """
19 assert os.path.isdir(path)
20 self._path = path
21
22 @property
25
26 @property
29
31 """
32 self.activate() -> None
33
34 Loads as active project.
35 After this call, empro.activeProject will hold this project,
36 until another project is loaded.
37 """
38 r = empro.activeProject.loadActiveProjectFrom(self.path)
39 assert r, "Failed to load project %r" % self.path
40
41 @property
43 from empro.toolkit import result_tree
44 return result_tree.ProjectResultTree(self.path)
45
53
55 """
56 returns directory containing project.xsim
57 @type simId string
58 @param simId id of simulation
59 """
60 if self._isLegacy:
61 return os.path.join(self.path, "Simulations", simId)
62 return os.path.join(self.path, simId)
63
65 """
66 return engine type of simulation
67 """
68 dirname = self.simulationDir(simId)
69 if os.path.exists(os.path.join(dirname, "emds_dsn")):
70 return FEM
71 return FDTD
72
73 - def copyTo(self, destPath, clean=False, shallow=False):
74 """
75 Copy file tree of project to new location.
76 @type destPath string
77 @param destPath new location of copy, e.g. foo/bar.ep
78 @type clean bool
79 @param clean if true, the new location is first cleaned.
80 @type shallow bool
81 @param shallow if True, the simulations are skipped during copying
82 """
83 assert os.path.isdir(self.path)
84 if clean:
85 fileutil.safeRemoveTree(destPath)
86 if shallow:
87 self._copyShallow(destPath)
88 else:
89 fileutil.copyTree(self.path, destPath)
90 return EMProProject(destPath)
91
93 """
94 self.createNewSimulation([engine]) -> simId
95
96 Loads as active project and creates a new simulation without adding it
97 to the queue.
98
99 It assumes the project is preconfigured so new simulations can be created
100 without additional information. Setting up simulation configuration without
101 creating is done with the 'New FDTD Simulation' or 'New FEM Simulation'
102 dialogs as usual, but by clicking 'Done' instead of 'Create & Queue Simulation'
103 or 'Create Simulation Only'.
104
105 Whether an FDTD or an FEM simulation will be created depends on which dialog
106 was used as last. To change this, open either 'New FDTD Simulation' or
107 'New FEM Simulation' and simply click 'Done'. Then save the project.
108 """
109 self.activate()
110 if engine:
111 empro.activeProject.createSimulationData().engine = engine
112 oldSimIds = self.simulationIds()
113 status, msg = empro.activeProject.addSimulationDataToProject(False)
114 assert status == 'Ok', "Failed to create new simulation: %(status)s: %(msg)s" % vars()
115 newSimIds = tuple(set(self.simulationIds()) - set(oldSimIds))
116 assert len(newSimIds) == 1, "Cannot retrieve sim ID, as more than one new simulation was created: %(newSimIds)r" % newSimIds
117 return newSimIds[0]
118
119
120 - def createSimulationProcess(self, simId, threads=1, hardwareOnly=False, storeMinidump=False,
121 handleMinidump=None, stdout=None, stderr=None, extraOptions=None,
122 distributed=False):
123 """
124 Starts a subprocess running a simulation.
125 It returns a tuple (process, dirname, command):
126 - process: instance of subprocess.Popen
127 - dirname: string
128 - command: string
129 """
130 import subprocess
131 maker = EMProProject._commandMakers[self.simulationEngine(simId)]
132 command = maker(self, simId, threads, hardwareOnly, storeMinidump, handleMinidump,
133 extraOptions, distributed)
134 dirname = self.simulationDir(simId)
135 process = subprocess.Popen(command, stdout=stdout, stderr=stderr, cwd=dirname, universal_newlines=True)
136 return process, dirname, command
137
138
140 """
141 Starts a simulation, and wait until it is finished.
142 Raises an exception if the simulation failed.
143 Arguments are the same as for createSimulationProcess
144 """
145 import subprocess
146 process, dirname, command = self.createSimulationProcess(*args, **kwargs)
147 ret = process.wait()
148 if ret:
149 raise subprocess.CalledProcessError(ret, command)
150 return dirname, command
151
153 self._copyHelper(self.path, destPath,
154 fnames = [
155 'eesof_empro.xml',
156 'Project.xml',
157 'ProjectInfo.xml',
158 '.nextSimulationNumber',
159 os.path.join('Simulations', '.nextSimulationNumber')],
160 dirnames = [
161 'empro',
162 'em%Model',
163 'emModel',
164 'footprint',
165 'layout',
166 'lookalike',
167 'rfpro',
168 'pepro',
169 'symbol',
170 'OptionalData',
171 'RequiredData'])
172
173 - def _copyHelper(self, srcDir, destDir, fnames, dirnames):
174 assert os.path.isdir(srcDir)
175 fileutil.safeMakeDirs(destDir)
176 for fname in fnames:
177 src = os.path.join(srcDir, fname)
178 if os.path.exists(src):
179 fileutil.copyFile(src, os.path.join(destDir, fname))
180 for dirname in dirnames:
181 if os.path.isdir(os.path.join(srcDir, dirname)):
182 fileutil.copyTree(os.path.join(srcDir, dirname), os.path.join(destDir, dirname))
183
184 - def _commandFDTD(self, simId, threads, hardwareOnly, storeMinidump, handleMinidump,
185 extraOptions, distributed):
186 cmd = self._fdtdEngine(distributed)
187 if threads and not hardwareOnly:
188 cmd += ['-proc', str(threads)]
189 if hardwareOnly:
190 cmd.append('-hardwareonly')
191 cmd += self._extrasList(extraOptions)
192 cmd.append("project.xsim")
193 return cmd
194
195 - def _commandFEM(self, simId, threads, hardwareOnly, storeMinidump, handleMinidump,
196 extraOptions, distributed):
197 cmd = self._femEngine(distributed)
198 cmd += [
199 '--dim=3',
200 '--no-display',
201 ]
202 if threads:
203 cmd.append('--nbThreads=%d' % threads)
204 cmd += self._extrasList(extraOptions)
205 cmd += [
206 os.path.join("emds_dsn", "design"),
207 "design"
208 ]
209 return cmd
210
212 if distributed:
213 return [self._python, "-mcommand_line.distributed_fdtd"]
214 engine_name = "emprfdtd70"
215 if "win" in sys.platform:
216 engine_name = engine_name + ".exe"
217 for subdir in ['', 'ax8']:
218 path = os.path.join(os.environ['EMPROHOME'], subdir, engine_name)
219 if os.path.isfile(path):
220 return [path]
221 raise AssertionError("%(engine_name)r not found" % vars())
222
224 if distributed:
225 return [self._python, '-mcommand_line.distributed_fem']
226 else:
227 return [self._python, '-mempro.toolkit.engine_support.fem.state_machine.emprfem']
228
229 @property
231 from empro.toolkit import engine_master
232 python = engine_master.pythonExeLocation()
233 assert os.path.isfile(python)
234 return python
235
237 if not extraOptions:
238 return []
239 if isinstance(extraOptions, basestring):
240 import shlex
241 return list(shlex.split(str(extraOptions)))
242 return list(extraOptions)
243
244 @property
246 return self.path.rstrip('/\\').endswith('.ep')
247
248 _commandMakers = {
249 FDTD: _commandFDTD,
250 FEM: _commandFEM,
251 }
252