diff --git a/.travis.yml b/.travis.yml index 2f49c849..b8a054c7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -39,7 +39,7 @@ addons: install: - travis_wait 50 pip install -U -f https://extras.wxpython.org/wxPython4/extras/linux/gtk3/ubuntu-14.04 wxPython - travis_wait 50 python setup.py install - - pip install PyPubSub pyyaml ruamel.yaml + - pip install PyPubSub pyyaml ruamel.yaml matplotlib # command to run script: travis_wait 20 python devsimpy.py examples/model0.dsp 10 start quit \ No newline at end of file diff --git a/PlotGUI.py b/PlotGUI.py index 80122639..8d2967e3 100644 --- a/PlotGUI.py +++ b/PlotGUI.py @@ -31,7 +31,12 @@ _ = wx.GetTranslation import wx.lib.agw.aui as aui - + +import matplotlib as mpl +from matplotlib.backends.backend_wxagg import ( + FigureCanvasWxAgg as FigureCanvas, + NavigationToolbar2WxAgg as NavigationToolbar) + # for spectrum try: from numpy import * @@ -92,32 +97,32 @@ def PlotManager(parent, label, atomicModel, xl, yl): frame.Show() class PlotPanel(wx.Panel): - def __init__(self, parent, id=-1, dpi=None, **kwargs): - wx.Panel.__init__(self, parent, id=id, **kwargs) - self.figure = mpl.figure.Figure(dpi=dpi, figsize=(2, 2)) - self.canvas = FigureCanvas(self, -1, self.figure) - self.toolbar = NavigationToolbar(self.canvas) - self.toolbar.Realize() - - sizer = wx.BoxSizer(wx.VERTICAL) - sizer.Add(self.canvas, 1, wx.EXPAND) - sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND) - self.SetSizer(sizer) - self.SetAutoLayout(True) + def __init__(self, parent, id=-1, dpi=None, **kwargs): + wx.Panel.__init__(self, parent, id=id, **kwargs) + self.figure = mpl.figure.Figure(dpi=dpi, figsize=(2, 2)) + self.canvas = FigureCanvas(self, -1, self.figure) + self.toolbar = NavigationToolbar(self.canvas) + self.toolbar.Realize() + + sizer = wx.BoxSizer(wx.VERTICAL) + sizer.Add(self.canvas, 1, wx.EXPAND) + sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND) + self.SetSizer(sizer) + self.SetAutoLayout(True) class PlotNotebook(wx.Panel): - def __init__(self, parent, id=-1): - wx.Panel.__init__(self, parent, id=id) - self.nb = aui.AuiNotebook(self) - sizer = wx.BoxSizer() - sizer.Add(self.nb, 1, wx.EXPAND) - self.SetSizer(sizer) - self.SetAutoLayout(True) - - def add(self, name="plot"): - page = PlotPanel(self.nb) - self.nb.AddPage(page, name) - return page.figure + def __init__(self, parent, id=-1): + wx.Panel.__init__(self, parent, id=id) + self.nb = aui.AuiNotebook(self) + sizer = wx.BoxSizer() + sizer.Add(self.nb, 1, wx.EXPAND) + self.SetSizer(sizer) + self.SetAutoLayout(True) + + def add(self, name="plot"): + page = PlotPanel(self.nb) + self.nb.AddPage(page, name) + return page.figure class PlotFrame(wx.Frame): def __init__(self, parent=None, id=wx.NewIdRef(), title="Time Plotting"): diff --git a/ZipManager.py b/ZipManager.py index 1ab4a79a..4597aac1 100644 --- a/ZipManager.py +++ b/ZipManager.py @@ -35,7 +35,7 @@ def get_from_modules(name:str)->types.ModuleType: """ get module with the correct name from the name that come from dir(). """ for s,m in sys.modules.items(): - if name in s: + if name == s or "%s.%s"%(name,name) == s: return m return None @@ -357,35 +357,38 @@ def ReImport(self): Zip.ClearCache(self.fn) # import module -# try: + try: - ### reload submodule from module dependencies! - fullname = "".join([os.path.basename(os.path.dirname(self.fn)), getPythonModelFileName(self.fn).split('.py')[0]]) - module = sys.modules[fullname] - domain_name = os.path.basename(os.path.dirname(self.fn)) - for name in dir(module): - if type(getattr(module, name)) == types.ModuleType: - ### TODO: only reload the local package (not 'sys' and so one) - importlib.reload(get_from_modules(name)) - - ### clear to clean the import after exporting model (amd or cmd) and reload within the same instance of DEVSimPy - zipimport._zip_directory_cache.clear() - - ### reload module - module = self.ImportModule() - return module - -# except Exception as info: -# msg_i = _("Error in execution: ") -# msg_o = listf(format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2])) -# try: -# sys.stderr.write( msg_i + str(sys.exc_info()[0]) +"\r\n" + msg_o) -# except UnicodeDecodeError: -# sys.stderr.write( msg_i + str(sys.exc_info()[0]).decode('latin-1').encode("utf-8") +"\r\n" + msg_o) -# return info -# else: + ### reload submodule from module dependencies! + fullname = "".join([os.path.basename(os.path.dirname(self.fn)), getPythonModelFileName(self.fn).split('.py')[0]]) + module = sys.modules[fullname] + domain_name = os.path.basename(os.path.dirname(self.fn)) + for name in dir(module): + if type(getattr(module, name)) == types.ModuleType: + ### TODO: only reload the local package (not 'sys' and so one) + m = get_from_modules(name) + if m : + importlib.reload(m) + else: + sys.stdout.write('%s module is not reloaded before saving the code!'%name) + ### clear to clean the import after exporting model (amd or cmd) and reload within the same instance of DEVSimPy + zipimport._zip_directory_cache.clear() + + ### reload module + module = self.ImportModule() # return module + except Exception as info: + msg_i = _("Error in execution: ") + msg_o = listf(format_exception(sys.exc_info()[0], sys.exc_info()[1], sys.exc_info()[2])) + try: + sys.stderr.write( msg_i + str(sys.exc_info()[0]) +"\r\n" + msg_o) + except UnicodeDecodeError: + sys.stderr.write( msg_i + str(sys.exc_info()[0]).decode('latin-1').encode("utf-8") +"\r\n" + msg_o) + return info + else: + return module + @staticmethod def ClearCache(fn:str)->None: """Clear out cached entries from _zip_directory_cache""" diff --git a/plugins/state_trajectory.py b/plugins/state_trajectory.py index de91b246..1d569a35 100644 --- a/plugins/state_trajectory.py +++ b/plugins/state_trajectory.py @@ -24,10 +24,15 @@ import importlib import wx.lib.agw.aui as aui -#import wx.lib.mixins.inspection as wit + +import matplotlib as mpl +from matplotlib.backends.backend_wxagg import ( + FigureCanvasWxAgg as FigureCanvas, + NavigationToolbar2WxAgg as NavigationToolbar) class PlotPanel(wx.Panel): def __init__(self, parent, id=-1, dpi=None, **kwargs): + wx.Panel.__init__(self, parent, id=id, **kwargs) self.figure = mpl.figure.Figure(dpi=dpi, figsize=(2, 2)) self.canvas = FigureCanvas(self, -1, self.figure) @@ -76,14 +81,23 @@ def wrapped(*args, **kwargs): ### DEVS instance devs = func.__self__ + ### create + func_name = func.__name__ + + #if func_name not in devs.state_trajectory: + # devs.state_trajectory[func_name] = {} + ### condition cond = hasattr(devs, 'state') and 'status' in devs.state.keys() - ### is DEVS model has no state_trajectory attribute, we create it only for init! if not hasattr(devs, 'state_trajectory'): - in_state = devs.state['status'] if cond else 'Undefined' - setattr(devs,'state_trajectory', {0.0: in_state}) + in_state = devs.getStatus() if cond else 'Undefined' + setattr(devs,'state_trajectory', {func_name:{0.0: in_state}}) + + ### if transition function is not yet introduced + if func_name not in devs.state_trajectory: + devs.state_trajectory[func_name] = {} r = func(*args, **kwargs) @@ -96,9 +110,9 @@ def wrapped(*args, **kwargs): ts = devs.timeNext[0] #ts = devs.timeLast[0] + devs.elapsed - ### Add the output state - out_state = devs.state['status'] if cond else 'Undefined' - devs.state_trajectory[ts] = out_state + ### Add the output state at time ts for the func_name transition function + out_state = devs.getStatus() if cond else 'Undefined' + devs.state_trajectory[func_name][ts] = out_state return r @@ -153,37 +167,41 @@ def PlotStateTrajectory(m): if hasattr(m, 'state_trajectory'): - st = m.state_trajectory + frame = wx.Frame(None, -1, '%s State Trajectory'%label) + plotter = PlotNotebook(frame) - states = list(set(st.values())) + ### tabs of plot depend on the transition function selected + for func_name,st in m.state_trajectory.items(): + #states = list(set(st.values())) - x = [] - y = [] + x = [] + y = [] - ### adapted to PyPDEVS - times_lst = list(map(lambda a: a[0] if isinstance(a, tuple) else a, st.keys())) + ### adapted to PyPDEVS + times_lst = list(map(lambda a: a[0] if isinstance(a, tuple) else a, st.keys())) - states_lst = [states.index(st[k]) for k in st] + #states_lst = [states.index(st[k]) for k in st] - items = zip(times_lst, states_lst) - - sorted_items = sorted(items, key=lambda x: (x[0], x[1])) - - x, y = zip(*sorted_items) + states_lst = list(st.values()) - assert len(x)==len(y) + items = zip(times_lst, states_lst) + + sorted_items = sorted(items, key=lambda x: (x[0], x[1])) + + print(st) - frame = wx.Frame(None, -1, 'Plotter') - plotter = PlotNotebook(frame) - axes1 = plotter.add('%s State Trajectory'%label).gca() - axes1.set_xlabel('Time',fontsize=16) - axes1.set_ylabel('State',fontsize=16) - axes1.step(x, y) - axes1.grid(True) - axes1.set_title(label) - - #axes2 = plotter.add('figure 2').gca() - #axes2.plot([1, 2, 3, 4, 5], [2, 1, 4, 2, 3]) + print(sorted_items) + + x, y = zip(*sorted_items) + + assert len(x)==len(y) + + axes = plotter.add(func_name).gca() + axes.set_xlabel('Time',fontsize=16) + axes.set_ylabel('State',fontsize=16) + axes.step(x, y) + axes.grid(True) + axes.set_title('%s (%s)'%(label,func_name)) frame.Show() @@ -191,7 +209,7 @@ def PlotStateTrajectory(m): dial = wx.MessageDialog(None, _('Select at least one decorate transition function for %s.')%label, _('Plot Manager'), - wx.OK | wx.ICON_EXCLAION) + wx.OK | wx.ICON_EXCLAMATION) dial.ShowModal() else: dial = wx.MessageDialog(None,