Package empro :: Package toolkit :: Module project
[frames] | no frames]

Source Code for Module empro.toolkit.project

  1  # Copyright 1983-2019 Keysight Technologies, Inc , Keysight Confidential 
  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 
9 10 -class EMProProject(object):
11 """ 12 A Python representation of an EMPro Project by path name 13 """
14 - def __init__(self, path):
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
23 - def path(self):
24 return self._path
25 26 @property
27 - def name(self):
28 return os.path.basename(self.path)
29
30 - def activate(self):
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
42 - def resultTree(self):
43 from empro.toolkit import result_tree 44 return result_tree.ProjectResultTree(self.path)
45
46 - def simulationIds(self):
47 """ 48 return all available simulation ids 49 """ 50 resultBrowser = empro.output.resultBrowser() 51 resultBrowser.addProject(self.path) 52 return resultBrowser.project(self.path).availableSimulationIds()
53
54 - def simulationDir(self, simId):
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
64 - def simulationEngine(self, simId):
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
92 - def createNewSimulation(self, engine=None):
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)) # we compare the current sim ids to the old ones, to figure out the new one 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
139 - def runSimulation(self, *args, **kwargs):
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
152 - def _copyShallow(self, destPath):
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
211 - def _fdtdEngine(self, distributed):
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
223 - def _femEngine(self, distributed):
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
230 - def _python(self):
231 from empro.toolkit import engine_master 232 python = engine_master.pythonExeLocation() 233 assert os.path.isfile(python) 234 return python
235
236 - def _extrasList(self, extraOptions):
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
245 - def _isLegacy(self):
246 return self.path.rstrip('/\\').endswith('.ep')
247 248 _commandMakers = { 249 FDTD: _commandFDTD, 250 FEM: _commandFEM, 251 }
252