Пример #1
0
class AnimationWindow(wx.Frame):
    def __init__(self,
                 parent,
                 data_list,
                 config=None,
                 yvals=None,
                 mode="1D",
                 pks=None,
                 pksmode="mz",
                 *args,
                 **kwargs):
        """
        A simple window for animating mulitple 1D or 2D plots in a sequence.
        :param parent: Parent window. Passed to wx.Frame.
        :param data_list: List of data to be plotted
        :param config: UniDecConfig object
        :param yvals: Titles for the plots.
        :param mode: 1 = 1D plots, 2 = 2D plots
        :param args:
        :param kwargs: 
        :return: None
        """
        wx.Frame.__init__(self, parent, title="Plot Animations", size=(-1, -1))
        # Initialize parameters
        if mode == "2D":
            self.mode = 2
        else:
            self.mode = 1
        if config is None:
            self.config = unidecstructure.UniDecConfig()
            self.config.initialize()
        else:
            self.config = config

        self.datalist = data_list
        self.pks = pks
        self.pksmode = pksmode

        if self.pksmode == "mz":
            self.xlabel = "m/z (Th)"
            self.testkda = False
        elif self.pksmode == "CCS":
            self.xlabel = "CCS"
            self.testkda = False
        else:
            self.xlabel = "Mass (Da)"
            self.testkda = True

        self.yvals = yvals
        if self.yvals is None:
            self.yvals = list(range(0, len(data_list)))

        self.dim = 1
        self.pos = -1
        self.play = False

        self.animation = None

        # Create GUI

        # Make the menu
        filemenu = wx.Menu()
        menu_save_fig = filemenu.Append(wx.ID_ANY, "Save Figures",
                                        "Save all figures at selected path")
        self.Bind(wx.EVT_MENU, self.on_save_fig, menu_save_fig)

        menu_bar = wx.MenuBar()
        menu_bar.Append(filemenu, "&File")
        self.SetMenuBar(menu_bar)

        self.CreateStatusBar(2)
        panel = wx.Panel(self)
        sizer = wx.BoxSizer(wx.VERTICAL)

        if self.mode == 1:
            self.plot = plot1d.Plot1d(panel)
        else:
            self.plot = plot2d.Plot2d(panel)
        sizer.Add(self.plot, 0, wx.EXPAND)

        controlsizer = wx.BoxSizer(wx.HORIZONTAL)

        sb = wx.StaticBox(panel, label='Frame Rate (ms/frame)')
        sbs = wx.StaticBoxSizer(sb, orient=wx.VERTICAL)
        frmax = 2000

        frmin = 1
        self.frslider = wx.Slider(
            panel, wx.ID_ANY, 500, frmin, frmax, (30, 60), (250, -1),
            wx.SL_HORIZONTAL | wx.SL_AUTOTICKS | wx.SL_LABELS)
        self.frslider.SetTickFreq(100)
        sbs.Add(self.frslider, 0, wx.EXPAND)
        self.Bind(wx.EVT_COMMAND_SCROLL_THUMBRELEASE, self.update_framerate,
                  self.frslider)
        controlsizer.Add(sbs, 0, wx.EXPAND)

        self.playbutton = wx.ToggleButton(panel, label="Play")
        self.nextbutton = wx.Button(panel, label="Next")
        self.backbutton = wx.Button(panel, label="Back")

        controlsizer.Add(self.backbutton, 0, wx.EXPAND)
        controlsizer.Add(self.playbutton, 0, wx.EXPAND)
        controlsizer.Add(self.nextbutton, 0, wx.EXPAND)

        self.Bind(wx.EVT_TOGGLEBUTTON, self.on_play, self.playbutton)
        self.Bind(wx.EVT_BUTTON, self.on_next, self.nextbutton)
        self.Bind(wx.EVT_BUTTON, self.on_back, self.backbutton)

        self.ctlautoscale = wx.CheckBox(panel, label="Autoscale")
        controlsizer.Add(self.ctlautoscale, 0, wx.EXPAND)
        if self.mode == 2:
            self.ctlautoscale.SetValue(True)

        sizer.Add(controlsizer, 0, wx.EXPAND)

        panel.SetSizer(sizer)
        sizer.Fit(self)

        self.Bind(wx.EVT_CLOSE, self.on_close, self)

        self.init()
        self.Centre()
        self.Show(True)

    def on_close(self, e):
        """
        Stop the animation and close the window.
        :param e: Unused event
        :return: None
        """
        print("Closing")
        try:
            self.animation._stop()
        except:
            pass
        self.Destroy()

    def update(self, frame_number):
        """
        Continues to increment the plot to the next value in the data_list. Will stop if self.play is False.
        :param frame_number: Required but unused. Filled by FuncAnimation.
        :return: 0
        """
        if self.play:
            self.pos += 1
            self.update_plot()
            return 0
        else:
            return 0

    def update_plot(self):
        """
        Increment to the next data set and update the plot with the new data.
        Tries to keep some of the old plotting parameters like the zoom the same.
        Stops the animation if an error occurs.
        :return: None
        """
        try:
            if self.pks is not None:
                self.refresh_plot()
                self.add_peaks()
                return
            self.pos %= len(self.datalist)
            newdata = self.datalist[self.pos]
            title = str(self.yvals[self.pos])

            if self.mode == 1:
                # 1D Plot
                line = self.plot.subplot1.lines[0]
                xlim = self.plot.subplot1.get_xlim()
                ylim = self.plot.subplot1.get_ylim()
                line.set_data(newdata[:, 0], newdata[:, 1])

                self.plot.subplot1.set_title(title)

                autoflag = self.ctlautoscale.GetValue()
                if autoflag:
                    self.plot.subplot1.set_autoscale_on(True)
                    self.plot.subplot1.relim()
                    self.plot.subplot1.autoscale_view(True, True, True)
                else:
                    self.plot.subplot1.set_xlim(xlim)
                    self.plot.subplot1.set_ylim(ylim)
                self.plot.repaint()

            else:
                # 2D plot
                xlim = self.plot.subplot1.get_xlim()
                ylim = self.plot.subplot1.get_ylim()
                self.plot.contourplot(newdata,
                                      self.config,
                                      xlab=self.xlabel,
                                      title=title,
                                      repaint=False)
                autoflag = self.ctlautoscale.GetValue()
                if not autoflag:
                    self.plot.subplot1.set_xlim(xlim)
                    self.plot.subplot1.set_ylim(ylim)
                self.plot.add_title(title)
                self.plot.repaint()
        except Exception as e:
            self.animation._stop()
            print(e)

    def init(self):
        """
        Create a fresh plot and start the animation.
        :return: None
        """
        self.pos = 0
        self.refresh_plot()
        self.animation = FuncAnimation(self.plot.figure,
                                       self.update,
                                       interval=500)
        self.animation._start()

    def on_play(self, e):
        """
        Toggles self.play on or off. Will break the while loop in self.update if self.play = False.
        :param e: Unused event
        :return: None
        """
        tog = self.playbutton.GetValue()
        if tog:
            self.play = True
        else:
            self.play = False
        pass

    def refresh_plot(self):
        """
        Create a fresh plot from the top.
        :return: None
        """
        self.pos %= len(self.datalist)
        newdata = self.datalist[self.pos]
        title = str(self.yvals[self.pos])

        if self.mode == 1:
            self.plot.plotrefreshtop(newdata[:, 0],
                                     newdata[:, 1],
                                     title,
                                     self.xlabel,
                                     "Intensity",
                                     "",
                                     self.config,
                                     test_kda=self.testkda)
            self.plot.add_title(title)
            if self.pks is not None:
                self.add_peaks()
        else:
            self.plot.contourplot(newdata,
                                  self.config,
                                  xlab=self.xlabel,
                                  title=title)
            self.plot.add_title(title)

    def on_next(self, e):
        """
        Plot the next data set in data_list.
        :param e: Unused event
        :return: None
        """
        self.pos += 1
        self.update_plot()
        pass

    def on_back(self, e):
        """
        Plot the previous data set in data_list.
        :param e: Unused event
        :return: None
        """
        self.pos -= 1
        self.update_plot()
        pass

    def update_framerate(self, e):
        """
        Change the frame rate. Restart the animation with fresh frame rate.
        :param e: Unused event
        :return: None
        """
        framerate = self.frslider.GetValue()
        # print "Updated framerate to:", framerate
        # self.animation._interval=framerate
        # self.animation.new_frame_seq()
        self.animation._stop()
        self.animation = FuncAnimation(self.plot.figure,
                                       self.update,
                                       interval=framerate)
        self.animation._start()

    def add_peaks(self, e=None):
        if self.pksmode == "mz":
            self.add_peaks_mz()
        else:
            self.add_peaks_mass()

    def add_peaks_mz(self, e=None):
        for p in self.pks.peaks:
            if p.ignore == 0:
                list1 = []
                list2 = []
                mztab = p.mztab[self.pos]
                mztab2 = p.mztab2[self.pos]
                if (not ud.isempty(mztab)) and (not ud.isempty(mztab2)):
                    mztab = np.array(mztab)
                    mztab2 = np.array(mztab2)
                    maxval = np.amax(p.mztab[:, :, 1])
                    for k in range(0, len(mztab)):
                        if mztab[k, 1] > self.config.peakplotthresh * maxval:
                            list1.append(mztab2[k, 0])
                            list2.append(mztab2[k, 1])
                            # print mztab[k]
                    self.plot.plotadddot(np.array(list1), np.array(list2),
                                         p.color, p.marker)
        self.plot.repaint()

    def add_peaks_mass(self, e=None):
        for p in self.pks.peaks:
            if p.ignore == 0:
                pos = ud.nearest(self.datalist[self.pos][:, 0], p.mass)
                data = self.datalist[self.pos][pos]
                if data[1] > self.config.peakplotthresh * np.amax(
                        self.datalist[self.pos][:, 1]):
                    self.plot.plotadddot(data[0], data[1], p.color, p.marker)
        self.plot.repaint()

    def on_save_fig(self, e=None):
        path = FileDialogs.save_file_dialog()
        base, ext = os.path.splitext(path)
        #self.init()
        #self.save_fig(base,ext)
        for i in range(0, len(self.datalist)):
            self.on_next(None)
            self.save_fig(base, ext)

    def save_fig(self, base, ext):
        path = base + str(self.pos) + ext
        print(self.pos, path)
        self.plot.save_figure(path)
Пример #2
0
class SpatialVariance(PlotsInterval):
    name = 'Spatial Variance'
    plot = Button('Plot variogram')
    normalize = Bool(True)
    robust = Bool(True)
    cloud = Bool(False)
    se = Bool(False)
    n_samps = Int(100)
    dist_bin = Float(0.5)
    estimator = Enum('ergodic', ('ergodic', 'spot'))

    # animated variogram
    anim_time_scale = Enum(50, [0.5, 1, 5, 10, 20, 50, 100])
    plot_anim = Button('Animate variogram')

    # Array map tool button
    vis_tool = Button('Covar map')

    # Correlation graph button
    plot_graph = Button('Plot graph')
    graph_stagger_x = Bool(False)
    graph_stagger_y = Bool(False)

    def _plot_graph_fired(self):
        t, y = self.curve_manager.interactive_curve.current_data()
        y = y[np.newaxis, :, :]
        label = '{0: .2f} sec'.format(t.mean())
        fig, axs = self._get_fig(ncols=2, figsize=(12, 5))
        fig = plot_site_corr(y,
                             self.chan_map,
                             label,
                             normed=self.normalize,
                             stagger_x=self.graph_stagger_x,
                             stagger_y=self.graph_stagger_y,
                             axs=axs)
        try:
            fig.canvas.draw_idle()
        except BaseException:
            pass
        return fig

    def _vis_tool_fired(self):
        _, y = self.curve_manager.interactive_curve.current_data()
        y *= 1e6
        if self.normalize:
            cov = np.corrcoef(y)
        else:
            cov = np.cov(y)
        chan_map = self.chan_map
        tool = ArrayVarianceTool(cov, chan_map)
        view = tool.default_traits_view()
        view.kind = 'live'
        tool.edit_traits(view=view)
        return tool

    def compute_variogram(self, array, chan_map, **kwargs):
        """
        Returns variogram points from the field defined by an array and channel map.
        The number of parameters returned depends on whether a variogram cloud is requested.
        If the cloud is not requested, then binned aggregates (x, y, se, Nd) are returned (that is: distance bins,
        mean semivariance at each distance, standard error of mean, and number of points in the original sample).
        Else, those binned aggregates are returned pre-pended by the non-aggregated (xcloud, ycloud) points.

        :param array:
        :param chan_map:
        :param kwargs:
        :return:
        """
        robust = kwargs.pop('robust', self.robust)
        n_samps = kwargs.pop('n_samps', self.n_samps)
        normed = kwargs.pop('normalize', self.normalize)
        cloud = kwargs.pop('cloud', self.cloud)
        if normed:
            array = array / np.std(array, axis=1, keepdims=1)

        pts = np.linspace(0, array.shape[1] - 1, n_samps).astype('i')
        if isinstance(chan_map, ChannelMap):
            combs = chan_map.site_combinations
        else:
            combs = chan_map

        # I think turn off binning if a cloud is requested
        bin_size = None if (self.dist_bin < 0 or cloud) else self.dist_bin
        # Turn off se if cloud is True
        se = not cloud
        counts = not cloud
        if self.estimator == 'ergodic':
            vg_method = partial(fast_semivariogram,
                                xbin=bin_size,
                                trimmed=True,
                                se=se,
                                cloud=cloud,
                                counts=counts)
        else:
            vg_method = partial(semivariogram,
                                robust=robust,
                                xbin=bin_size,
                                trimmed=True,
                                se=se,
                                cloud=cloud,
                                counts=counts)
        if cloud:
            bin_size = None if self.dist_bin < 0 else self.dist_bin
            xc, yc = vg_method(array[:, pts], combs)
            xb, yb = binned_variance(xc, yc, binsize=bin_size)
            # this will bring back mean and sem by default
            xb, yb, se, Nd = binned_variance_aggregate(xb, yb)
            return xc, yc, xb, yb, se, Nd
        x, y, Nd, se = vg_method(array[:, pts], combs)
        return x, y, se, Nd

    def _plot_anim_fired(self):
        if not hasattr(self, '_animating'):
            self._animating = False
        if self._animating:
            self._f_anim._stop()
            self._animating = False
            return

        t, y = self.curve_manager.interactive_curve.current_data()
        y *= 1e6
        if self.normalize:
            y = y / np.std(y, axis=1, keepdims=1)
            #y = y / np.std(y, axis=0, keepdims=1)

        cm = self.chan_map

        t0 = time.time()
        r = self.compute_variogram(y[:, 0][:, None],
                                   cm,
                                   n_samps=1,
                                   normalize=False,
                                   cloud=False)
        t_call = time.time() - t0
        scaled_dt = self.anim_time_scale * (t[1] - t[0])

        f_skip = 1
        t_pause = scaled_dt - t_call / float(f_skip)
        while t_pause < 0:
            f_skip += 1
            t_pause = scaled_dt - t_call / float(f_skip)
            print('skipping', f_skip, 'samples and pausing', t_pause, 'sec')

        # this figure lives outside of figure "management"
        fig, axes = subplots()
        c = FigureCanvas(fig)

        x, svg, svg_se, Nd = r
        # also compute how long it takes to draw the errorbars
        line = axes.plot(x, svg, marker='s', ms=6, ls='--')[0]
        t0 = time.time()
        #ec = axes.errorbar(x, svg, yerr=svg_se, fmt='none', ecolor='gray')
        t_call = t_call + (time.time() - t0)
        t_pause = scaled_dt - t_call / float(f_skip)
        while t_pause < 0:
            f_skip += 1
            t_pause = scaled_dt - t_call / float(f_skip)
            print('skipping', f_skip, 'samples and pausing', t_pause, 'sec')
        # average together frames at the skip rate?
        N = y.shape[1]
        blks = N // f_skip
        y = y[:, :blks * f_skip].reshape(-1, blks, f_skip).mean(-1)

        # print y.mean()

        def _step(n):
            c.draw()
            print('frame', n)
            x, svg, svg_se, Nd = self.compute_variogram(y[:, n:n + 1],
                                                        cm,
                                                        n_samps=1,
                                                        normalize=False)
            # ec.remove()
            line.set_data(x, svg)
            #ec = axes.errorbar(x, svg, yerr=svg_se, fmt='none', ecolor='gray')
            self.parent._qtwindow.vline.setPos(t[n * f_skip])
            if n == blks - 1:
                self._animating = False
            return (line, )

        c.show()

        max_var = 5.0 if self.normalize else y.var(0).max()
        axes.set_ylim(0, 1.05 * max_var)
        if not self.normalize:
            axes.axhline(max_var, color='k', ls='--', lw=2)

        #axes.autoscale(axis='both', enable=True)
        plotters.sns.despine(ax=axes)
        self._f_anim = FuncAnimation(fig,
                                     _step,
                                     blks,
                                     interval=scaled_dt * 1e3,
                                     blit=True)
        self._f_anim.repeat = False
        self._animating = True
        self._f_anim._start()

    def _plot_fired(self):
        t, y = self.curve_manager.interactive_curve.current_data()
        y *= 1e6
        r = self.compute_variogram(y, self.chan_map)
        if self.cloud:
            xc, yc, x, svg, svg_se, Nd = r
        else:
            x, svg, svg_se, Nd = r
        fig, ax = self._get_fig()
        label = 't ~ {0:.1f}'.format(t.mean())
        clr = self._colors[self._axplots[ax]]
        if self.cloud:
            ax.scatter(xc, yc, s=4, alpha=0.25, c=clr)
        ax.plot(x, svg, marker='s', ms=6, ls='--', color=clr, label=label)
        ax.errorbar(x, svg, svg_se, fmt='none', ecolor=clr)
        # if self.normalize:
        #     sill = 1.0
        #     ax.axhline(1.0, color=clr, ls='--')
        # else:
        #     sill = np.median(y.var(1))
        #     ax.axhline(sill, color=clr, ls='--')
        #ax.set_ylim(0, 1.05 * sill)
        ax.set_xlim(xmin=0)
        ax.autoscale(axis='y', enable=True)
        ax.set_ylim(ymin=0)
        ax.legend()
        ax.set_xlabel('Distance (mm)')
        ax.set_ylabel('Semivariance')
        plotters.sns.despine(ax=ax)
        fig.tight_layout()
        try:
            fig.canvas.draw_idle()
        except BaseException:
            pass

    def default_traits_view(self):
        v = View(
            HGroup(
                VGroup(
                    Label('Plot in new figure'), UItem('new_figure'),
                    UItem('plot'), UItem('vis_tool'),
                    HGroup(VGroup(
                        Item('graph_stagger_x', label='Stagger horizontal'),
                        Item('graph_stagger_y', label='Stagger vertical')),
                           UItem('plot_graph'),
                           label='Corr. graph')),
                VGroup(Item('estimator', label='Estimator'),
                       Item('cloud', label='Cloud'),
                       Item('se', label='Std Err'),
                       Item('n_samps', label='# of samples'),
                       Item('dist_bin', label='Distance bin (mm)'),
                       Item('normalize', label='Normalized'),
                       Item('robust', label='Robust'),
                       columns=2,
                       label='Estimation params'),
                VGroup(Item('anim_time_scale', label='Time stretch'),
                       UItem('plot_anim'),
                       label='Animate variogram')))
        return v
Пример #3
0
class RunAnalysisInput(QDialog):
    def __init__(self, project, analysis_ID, analysis_type_label, *args, **kwargs):
        super().__init__(*args, **kwargs)
        uic.loadUi('data/user_input/ui/Analysis/runAnalysisInput.ui', self)

        icons_path = 'data\\icons\\'
        self.icon = QIcon(icons_path + 'pulse.png')
        self.setWindowIcon(self.icon)

        self.setWindowFlags(Qt.WindowStaysOnTopHint)
        # self.setWindowModality(Qt.WindowModal)

        self.label_title = self.findChild(QLabel, 'label_title')
        self.label_message = self.findChild(QLabel, 'label_message')
        self.label_message.setWordWrap(True)
        self.config_title_font()
        self.config_message_font()

        self.project = project
        self.solve = None
        self.analysis_ID = analysis_ID
        self.analysis_type_label = analysis_type_label
        self.frequencies = self.project.frequencies
        self.damping = self.project.global_damping
        self.modes = self.project.modes
        self.solution_acoustic = None
        self.solution_structural = None
        self.convergence_dataLog = None
        self.natural_frequencies_acoustic = []
        self.natural_frequencies_structural = []
        self.complete = False

        LoadingScreen('SOLUTION IN PROGRESS', 'Processing the cross-sections',  target=self.process_cross_sections, project=project)
        if self.project.preprocessor.stop_processing:
            self.project.preprocessor.stop_processing = False
            return

        LoadingScreen('SOLUTION IN PROGRESS', 'Preparing the model to solve', target=self.preparing_mathematical_model_to_solve)  
        self.pre_non_linear_convergence_plot()

        LoadingScreen('SOLUTION IN PROGRESS', 'Solving the analysis',  target=self.process_analysis, project=project)
        self.post_non_linear_convergence_plot()  

        if self.project.preprocessor.stop_processing:
            self.reset_all_results()
            self.project.preprocessor.stop_processing = False
        else:
            LoadingScreen('SOLUTION IN PROGRESS', 'Post-processing the obtained results', target=self.post_process_results)
            self.exec()
            self.check_warnings()

    def pre_non_linear_convergence_plot(self):
        if isinstance(self.solve, SolutionAcoustic):
            if self.analysis_ID in [3,5,6]:
                if self.solve.non_linear:
                    fig = plt.figure(figsize=[8,6])
                    ax  = fig.add_subplot(1,1,1)
                    self.anime = FuncAnimation(fig, self.solve.graph_callback, fargs=(fig,ax), interval=2000)
                    self.anime._start()
                    plt.ion()
                    plt.show()

    def post_non_linear_convergence_plot(self):
        if isinstance(self.solve, SolutionAcoustic):
            if self.analysis_ID in [3,5,6]:
                if self.solve.non_linear:
                    self.anime._stop()

    def process_cross_sections(self):

        t0i = time()
        self.complete = False
        self.project.process_cross_sections_mapping()
        self.project.time_to_process_cross_sections = time() - t0i

    def preparing_mathematical_model_to_solve(self):

        t0 = time()
        if self.analysis_ID in [0,1,3,5,6]:
            if self.frequencies is None:
                return
            if len(self.frequencies) == 0:
                return

        if self.project.preprocessor._process_beam_nodes_and_indexes():
            if self.analysis_ID not in [0,1,2]:
                title = "INCORRECT ANALYSIS TYPE"
                message = "There are only BEAM_1 elements in the model, therefore, \nonly structural analysis are allowable."
                info_text = [title, message, window_title_2]
                PrintMessageInput(info_text)
                return

        if self.analysis_ID == 2:
            self.project.preprocessor.enable_fluid_mass_adding_effect(reset=True)
            self.solve = self.project.get_structural_solve()

        elif self.analysis_ID == 4:
            self.solve = self.project.get_acoustic_solve()

        elif self.analysis_ID == 3:
            self.solve = self.project.get_acoustic_solve()

        elif self.analysis_ID in [5,6]:
            self.project.preprocessor.enable_fluid_mass_adding_effect()
            self.solve = self.project.get_acoustic_solve()
            
        else:
            self.project.preprocessor.enable_fluid_mass_adding_effect(reset=True)
            self.solve = self.project.get_structural_solve()

        self.project.time_to_preprocess_model = time() - t0
       
    def process_analysis(self):
        
        t0 = time()

        if self.analysis_ID == 0:
            self.solution_structural = self.solve.direct_method(self.damping) # Structural Harmonic Analysis - Direct Method

        elif self.analysis_ID == 1: # Structural Harmonic Analysis - Mode Superposition Method
            self.solution_structural = self.solve.mode_superposition(self.modes, self.damping)

        elif self.analysis_ID == 3: # Acoustic Harmonic Analysis - Direct Method
            self.solution_acoustic, self.convergence_dataLog = self.solve.direct_method()

        elif self.analysis_ID == 5: # Coupled Harmonic Analysis - Direct Method
            
            t0_acoustic = time()
            self.solution_acoustic, self.convergence_dataLog = self.solve.direct_method() #Acoustic Harmonic Analysis - Direct Method
            self.project.time_to_solve_acoustic_model = time() - t0_acoustic
            
            self.project.set_acoustic_solution(self.solution_acoustic)
            self.solve = self.project.get_structural_solve()
            
            t0_structural = time()
            self.solution_structural = self.solve.direct_method(self.damping) #Coupled Harmonic Analysis - Direct Method
            self.project.time_to_solve_structural_model = time() - t0_structural
            
        elif self.analysis_ID == 6: # Coupled Harmonic Analysis - Mode Superposition Method
            
            t0_acoustic = time()
            self.solution_acoustic, self.convergence_dataLog = self.solve.direct_method() #Acoustic Harmonic Analysis - Direct Method
            self.project.time_to_solve_acoustic_model = time() - t0_acoustic
            
            self.project.set_acoustic_solution(self.solution_acoustic)
            self.solve = self.project.get_structural_solve()
            
            t0_structural = time()
            self.solution_structural = self.solve.mode_superposition(self.modes, self.damping)
            self.project.time_to_solve_structural_model = time() - t0_structural
            
        elif self.analysis_ID == 2: # Structural Modal Analysis
            self.natural_frequencies_structural, self.solution_structural = self.solve.modal_analysis(modes = self.modes, sigma=self.project.sigma)

        elif self.analysis_ID == 4: # Acoustic Modal Analysis
            self.natural_frequencies_acoustic, self.solution_acoustic = self.solve.modal_analysis(modes = self.modes, sigma=self.project.sigma)
        
        self.project.time_to_solve_model = time() - t0

        if isinstance(self.solve, SolutionAcoustic):
            if self.analysis_ID in [3,5,6]:
                if self.solve.non_linear:
                    sleep(2)

    def post_process_results(self): 

        t0 = time()
        self.project.set_perforated_plate_convergence_dataLog(self.convergence_dataLog)
        if self.analysis_ID == 2:
            
            if self.solution_structural is None:
                return

            self.project.set_structural_solution(self.solution_structural)
            self.project.set_structural_natural_frequencies(self.natural_frequencies_structural.tolist())

        elif self.analysis_ID == 4:
                    
            if self.solution_acoustic is None:
                return

            self.project.set_acoustic_solution(self.solution_acoustic)
            self.project.set_acoustic_natural_frequencies(self.natural_frequencies_acoustic.tolist())
        
        elif self.analysis_ID == 3:

            if self.solution_acoustic is None:
                return

            self.project.set_acoustic_solution(self.solution_acoustic)
        
        elif self.analysis_ID in [0,1,5,6]:
            
            if self.solution_structural is None:
                return

            self.project.set_structural_solve(self.solve)
            self.project.set_structural_solution(self.solution_structural)
            self.dict_reactions_at_constrained_dofs = self.solve.get_reactions_at_fixed_nodes(self.damping)
            self.dict_reactions_at_springs, self.dict_reactions_at_dampers = self.solve.get_reactions_at_springs_and_dampers()
            self.project.set_structural_reactions([ self.dict_reactions_at_constrained_dofs,
                                                    self.dict_reactions_at_springs,
                                                    self.dict_reactions_at_dampers  ])

        self.project.time_to_postprocess = time() - t0
        _times =  [self.project.time_to_process_cross_sections, self.project.time_to_preprocess_model, self.project.time_to_solve_model, self.project.time_to_postprocess]
        self.project.total_time = sum(_times)
        self.print_final_log()
        self.complete = True

    def check_warnings(self):
        # WARNINGS REACHED DURING SOLUTION
        title = self.analysis_type_label
        message = ""
        if self.analysis_type_label == "Harmonic Analysis - Structural":
            if self.solve.flag_ModeSup_prescribed_NonNull_DOFs:
                message = self.solve.warning_ModeSup_prescribedDOFs
            if self.solve.flag_Clump and self.analysis_ID==1:
                message = self.solve.warning_Clump[0]
        if self.analysis_type_label == "Modal Analysis - Structural":
            if self.solve.flag_Modal_prescribed_NonNull_DOFs:
                message = self.solve.warning_Modal_prescribedDOFs[0] 
        if message != "":
            PrintMessageInput([title, message, window_title_2])

    def reset_all_results(self):

        self.solution_structural = None
        self.solution_acoustic = None

        if self.analysis_ID == 2:
            self.project.set_structural_solution(None)
            self.project.set_structural_natural_frequencies(None)
        elif self.analysis_ID == 4: 
            self.project.set_acoustic_solution(None)
            self.project.set_acoustic_natural_frequencies(None)
        elif self.analysis_ID == 3:
            self.project.set_acoustic_solution(None)
        elif self.analysis_ID in [0,1,5,6]:
            self.project.set_acoustic_solution(None)
            self.project.set_structural_solution(None)
            self.project.set_structural_reactions([ {}, {}, {} ])

    def config_title_font(self):
        font = QFont()
        font.setPointSize(19)
        font.setBold(True)
        font.setItalic(True)
        font.setFamily("Arial")
        # font.setWeight(60)
        self.label_title.setFont(font)
        self.label_title.setStyleSheet("color:black")

    def config_message_font(self):
        font = QFont()
        font.setPointSize(17)
        font.setBold(True)
        # font.setItalic(True)
        font.setFamily("Arial")
        # font.setWeight(60)
        self.label_message.setFont(font)
        self.label_message.setStyleSheet("color:blue")

    def print_final_log(self):

        text = "Solution finished!\n\n"
        # text += "Time to check all entries: {} [s]\n".format(round(self.project.time_to_checking_entries, 6))
        text += "Time to load/create the project: {} [s]\n".format(round(self.project.time_to_load_or_create_project, 4))
        text += "Time to process cross-sections: {} [s]\n".format(round(self.project.time_to_process_cross_sections, 4))
        text += "Time elapsed in pre-processing: {} [s]\n".format(round(self.project.time_to_preprocess_model, 4))
        if self.analysis_ID in [5,6]:
            text += "Time to solve the acoustic model: {} [s]\n".format(round(self.project.time_to_solve_acoustic_model, 4))
            text += "Time to solve the structural model: {} [s]\n".format(round(self.project.time_to_solve_structural_model, 4))
        else:
            text += "Time to solve the model: {} [s]\n".format(round(self.project.time_to_solve_model, 4))
        text += "Time elapsed in post-processing: {} [s]\n\n".format(round(self.project.time_to_postprocess, 4))
        text += "Total time elapsed: {} [s]\n\n\n".format(round(self.project.total_time, 4))

        text += "Press ESC to continue..."
        self.label_message.setText(text)
Пример #4
0
class UI:
    def __init__(self, visual_que, event_que, audio_sampler, audio_detector,
                 args):
        # user interface setting
        self.window_height = 1000
        self.window_width = int((1 / 2) * self.window_height)  # H:W = 2:1
        self.bgColor = "#009ADC"
        self.eventColor = "red"

        self.visual_que = visual_que
        self.event_que = event_que
        self.sampler = audio_sampler
        self.detector = audio_detector
        self.args = args
        self.threadLock = threading.RLock()
        self.is_recording = False
        self.buffer_size = int(
            (args.sr // args.ws) * args.ws * args.msc * args.frame)
        self.num_windows = self.buffer_size // (args.ws)
        self.num_frames = self.buffer_size // (args.sr * args.msc)
        self.audio_buffer = deque(np.zeros(self.buffer_size),
                                  maxlen=self.buffer_size)
        self.colored_buffer = []
        self.backColor_buffer = deque(np.zeros(5), maxlen=5)
        self.count = 0

        self.fig = Figure(facecolor=self.bgColor)
        self.ax = self.fig.add_subplot(111)
        self.ax_position = self.ax.get_position()
        self.ax.set_ylim(-1.0, 1.0)
        self.ax.axis('off')
        self.TIME = np.linspace(0,
                                self.buffer_size // args.sr,
                                num=self.buffer_size)
        self.line, = self.ax.plot(self.TIME,
                                  np.array(self.audio_buffer),
                                  color='white')
        # wsData_pos and wsData_in_buffer_pos_map are for tracking group of same window size data in audio buffer
        self.wsData_pos = deque(np.zeros(self.num_windows),
                                maxlen=self.num_windows)
        self.wsData_pos_map = np.linspace(0,
                                          self.ax_position.x1,
                                          num=self.num_windows,
                                          endpoint=False)

        ## User Interface widgets
        self.root = tk.Tk()
        self.root.title("Sound Event {}".format(args.pmp))
        self.root.geometry("{}x{}".format(self.window_width,
                                          self.window_height))

        def on_closing_window():
            self.sampler.stop()
            self.detector.stop()
            self.root.destroy()

        self.root.protocol("WM_DELETE_WINDOW", on_closing_window)
        self.animate = None
        self.bgFrame = tk.Frame(self.root, background=self.bgColor)
        self.audio_graph = FigureCanvasTkAgg(self.fig, master=self.bgFrame)
        self.img = ImageTk.PhotoImage(
            Image.open("./img/baby_cry.png").convert("RGBA"))
        self.baby_cry_img = tk.Label(self.bgFrame,
                                     image=self.img,
                                     background=self.eventColor)
        # place the widgets on the window
        self.bgFrame.place(relwidth=1.0, relheight=1.0)
        self.audio_graph.get_tk_widget().place(relwidth=1.0, relheight=0.4)
        self.baby_cry_img.place(relx=0.25, rely=0.5)
        self.start()
        self.root.mainloop()

    def fill_audio_buffer_with_que(self):
        while self.is_recording:
            while not self.visual_que.empty():
                data, timeStamp = self.visual_que.get()
                self.audio_buffer.extendleft(data)
                with self.threadLock:  # wsData_pos
                    self.wsData_pos.appendleft(timeStamp)
                if len(self.colored_buffer) > 0:
                    for rect in self.colored_buffer:
                        pos = rect.get_x()
                        if pos <= self.ax_position.x1:
                            rect.set_x(pos +
                                       self.ax_position.x1 / self.num_windows)
                        else:
                            rect.remove()
                            self.colored_buffer.remove(rect)

    def mark_audio_frame_by_audio_event(self):
        while self.is_recording:
            while not self.event_que.empty():
                event, frame_start_time = self.event_que.get()
                self.backColor_buffer.appendleft(event)
                ii = 0
                for i in self.backColor_buffer:
                    if (i == 1):
                        ii += 1
                self.count = ii
                print(self.count)

    def plot_audio_in_buffer(self, frame):
        plot_data = np.array(self.audio_buffer)
        self.line.set_data(self.TIME, plot_data)
        # change UI color based on event
        if self.count >= 3:
            self.bgFrame.after(
                50, self.bgFrame.configure(background=self.eventColor))
            self.fig.set_facecolor(self.eventColor)
            self.baby_cry_img.place(relx=0.25, rely=0.5)
        else:
            self.bgFrame.after(50,
                               self.bgFrame.configure(background=self.bgColor))
            self.fig.set_facecolor(self.bgColor)
            self.baby_cry_img.place_forget()
        return [self.line, self.fig] + self.colored_buffer

    def pause_animation(self):
        while not self.visual_que.empty():
            pass
        self.animate.event_source.stop()

    def start(self):
        if self.is_recording == False:
            self.is_recording = True
            self.sampler.start()
            self.detector.start()
            threading.Thread(target=self.fill_audio_buffer_with_que,
                             daemon=True).start()
            threading.Thread(target=self.mark_audio_frame_by_audio_event,
                             daemon=True).start()
            if self.animate is None:
                self.animate = FuncAnimation(self.fig,
                                             self.plot_audio_in_buffer,
                                             frames=self.buffer_size,
                                             interval=50,
                                             blit=False,
                                             repeat=False)
                self.animate._start()
            else:
                self.animate.event_source.start()

    def stop(self):
        if self.is_recording == True:
            threading.Thread(target=self.pause_animation).start()
            self.sampler.stop()
            self.detector.stop()
            self.is_recording = False