Пример #1
0
    def __init__(self):
        """
        Default values
        """
        # Input
        self.file = None
        self.data = Data1D(x=[], y=[], dx=None, dy=None)
        self.theory_lowQ = Data1D(x=[], y=[], dy=None)
        self.theory_lowQ.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
        self.theory_highQ = Data1D(x=[], y=[], dy=None)
        self.theory_highQ.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
        # self.is_time_machine = False
        self.saved_state = DEFAULT_STATE
        self.state_list = state_list
        self.bookmark_list = bookmark_list
        self.input_list = input_list
        self.output_list = output_list

        self.compute_num = 0
        self.state_num = 0
        self.timestamp = ('00:00:00', '00/00/0000')
        self.container = None
        # plot image
        self.wximbmp = None
        # report_html strings
        import sas.sasgui.perspectives.invariant as invariant
        path = invariant.get_data_path(media='media')
        path_report_html = os.path.join(path, "report_template.html")
        html_template = open(path_report_html, "r")
        self.template_str = html_template.read()
        self.report_str = self.template_str
        # self.report_str_save = None
        html_template.close()
Пример #2
0
    def transform_complete(self, transforms=None):
        """
        Called from FourierThread when calculation has completed
        """
        self._transform_btn.SetLabel("Transform")
        if transforms is None:
            msg = "Error calculating Transform."
            if self.transform_type == 'hilbert':
                msg = "Not yet implemented"
            wx.PostEvent(self._manager.parent,
                         StatusEvent(status=msg, info="Error"))
            self._extract_btn.Disable()
            return

        self._transformed_data = transforms
        (transform1, transform3, idf) = transforms
        plot_x = transform1.x[transform1.x <= 200]
        plot_y = transform1.y[transform1.x <= 200]
        self._manager.show_data(Data1D(plot_x, plot_y), TRANSFORM_LABEL1)
        # No need to shorten gamma3 as it's only calculated up to x=200
        self._manager.show_data(transform3, TRANSFORM_LABEL3)

        plot_x = idf.x[idf.x <= 200]
        plot_y = idf.y[idf.x <= 200]
        self._manager.show_data(Data1D(plot_x, plot_y), IDF_LABEL)

        # Only enable extract params button if a fourier trans. has been done
        if self.transform_type == 'fourier':
            self._extract_btn.Enable()
        else:
            self._extract_btn.Disable()
Пример #3
0
    def show_pr(self, out, pr, cov=None):
        """
        """
        # Show P(r)
        x = pylab.arange(0.0, pr.d_max, pr.d_max / self._pr_npts)

        y = np.zeros(len(x))
        dy = np.zeros(len(x))
        y_true = np.zeros(len(x))

        total = 0.0
        pmax = 0.0
        cov2 = np.ascontiguousarray(cov)

        for i in range(len(x)):
            if cov2 is None:
                value = pr.pr(out, x[i])
            else:
                (value, dy[i]) = pr.pr_err(out, cov2, x[i])
            total += value * pr.d_max / len(x)

            # keep track of the maximum P(r) value
            if value > pmax:
                pmax = value

            y[i] = value

        if self._normalize_output:
            y = y / total
            dy = dy / total
        elif self._scale_output_unity:
            y = y / pmax
            dy = dy / pmax

        if cov2 is None:
            new_plot = Data1D(x, y)
            new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
        else:
            new_plot = Data1D(x, y, dy=dy)
        new_plot.name = PR_FIT_LABEL
        new_plot.xaxis("\\rm{r}", 'A')
        new_plot.yaxis("\\rm{P(r)} ", "cm^{-3}")
        new_plot.title = "P(r) fit"
        new_plot.id = PR_FIT_LABEL
        # Make sure that the plot is linear
        new_plot.xtransform = "x"
        new_plot.ytransform = "y"
        new_plot.group_id = GROUP_ID_PR_FIT
        self.parent.update_theory(data_id=self.data_id, theory=new_plot)
        wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
                                               title="P(r) fit"))
        return x, pr.d_max
Пример #4
0
    def plot_theory(self, data=None, name=None):
        """
        Receive a data set and post a NewPlotEvent to parent.

        :param data: extrapolated data to be plotted
        :param name: Data's name to use for the legend
        """
        # import copy
        if data is None:
            id = str(self.__data.id) + name
            group_id = self.__data.group_id
            wx.PostEvent(
                self.parent,
                NewPlotEvent(id=id, group_id=group_id, action='Remove'))
            return

        new_plot = Data1D(x=[], y=[], dy=None)
        new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
        scale = self.invariant_panel.get_scale()
        background = self.invariant_panel.get_background()

        if scale != 0:
            # Put back the sacle and bkg for plotting
            data.y = (data.y + background) / scale
            new_plot = Data1D(x=data.x, y=data.y, dy=None)
            new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
        else:
            msg = "Scale can not be zero."
            raise ValueError(msg)
        if len(new_plot.x) == 0:
            return

        new_plot.name = name
        new_plot.xaxis(self.__data._xaxis, self.__data._xunit)
        new_plot.yaxis(self.__data._yaxis, self.__data._yunit)
        new_plot.group_id = self.__data.group_id
        new_plot.id = str(self.__data.id) + name
        new_plot.title = self.__data.title
        # Save theory_data in a state
        if data is not None:
            name_head = name.split('-')
            if name_head[0] == 'Low':
                self.invariant_panel.state.theory_lowQ = copy.deepcopy(
                    new_plot)
            elif name_head[0] == 'High':
                self.invariant_panel.state.theory_highQ = copy.deepcopy(
                    new_plot)

        self.parent.update_theory(data_id=self.__data.id, theory=new_plot)
        wx.PostEvent(self.parent,
                     NewPlotEvent(plot=new_plot, title=self.__data.title))
Пример #5
0
 def setUp(self):
     # Create two data sets to play with
     x_0 = np.ones(5)
     for i in range(5):
         x_0[i] = x_0[i]*(i+1.0)
         
     y_0 = 2.0*np.ones(5)
     dy_0 = 0.5*np.ones(5)
     self.data = Data1D(x_0, y_0, dy=dy_0)
     
     x = self.data.x
     y = np.ones(5)
     dy = np.ones(5)
     self.data2 = Data1D(x, y, dy=dy)
Пример #6
0
    def _on_scale_unity(self, evt):
        """
        Scale the maximum P(r) value on each displayed plot to 1.

        :param evt: Menu event

        """
        self._scale_output_unity = True
        self._normalize_output = False

        self.show_pr(self._last_out, self._last_pr, self._last_cov)

        # Now scale the added plots too
        for plot in self._added_plots:
            _max = 0
            for y in self._added_plots[plot].y:
                if y > _max:
                    _max = y
            y = self._added_plots[plot].y / _max

            new_plot = Data1D(self._added_plots[plot].x, y)
            new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
            new_plot.name = self._added_plots[plot].name
            new_plot.xaxis("\\rm{r}", 'A')
            new_plot.yaxis("\\rm{P(r)} ", "cm^{-3}")
            self.parent.update_theory(data_id=self.data_id, theory=new_plot)
            wx.PostEvent(
                self.parent,
                NewPlotEvent(plot=new_plot,
                             update=True,
                             title=self._added_plots[plot].name))
Пример #7
0
    def _on_normalize(self, evt):
        """
        Normalize the area under the P(r) curve to 1.
        This operation is done for all displayed plots.

        :param evt: Menu event

        """
        self._normalize_output = True
        self._scale_output_unity = False

        self.show_pr(self._last_out, self._last_pr, self._last_cov)

        # Now scale the added plots too
        for plot in self._added_plots:
            total = np.sum(self._added_plots[plot].y)
            npts = len(self._added_plots[plot].x)
            total *= self._added_plots[plot].x[npts - 1] / npts
            y = self._added_plots[plot].y / total

            new_plot = Data1D(self._added_plots[plot].x, y)
            new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
            new_plot.group_id = self._added_plots[plot].group_id
            new_plot.id = self._added_plots[plot].id
            new_plot.title = self._added_plots[plot].title
            new_plot.name = self._added_plots[plot].name
            new_plot.xaxis("\\rm{r}", 'A')
            new_plot.yaxis("\\rm{P(r)} ", "cm^{-3}")
            self.parent.update_theory(data_id=self.data_id, theory=new_plot)
            wx.PostEvent(
                self.parent,
                NewPlotEvent(plot=new_plot,
                             update=True,
                             title=self._added_plots[plot].name))
Пример #8
0
    def show_shpere(self, x, radius=70.0, x_range=70.0):
        """
        """
        # Show P(r)
        y_true = np.zeros(len(x))

        sum_true = 0.0
        for i in range(len(x)):
            y_true[i] = self.pr_theory(x[i], radius)
            sum_true += y_true[i]

        y_true = y_true / sum_true * x_range / len(x)

        # Show the theory P(r)
        new_plot = Data1D(x, y_true)
        new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
        new_plot.name = "P_{true}(r)"
        new_plot.xaxis("\\rm{r}", 'A')
        new_plot.yaxis("\\rm{P(r)} ", "cm^{-3}")
        new_plot.id = "P_{true}(r)"
        new_plot.group_id = "P_{true}(r)"
        self.parent.update_theory(data_id=self.data_id, theory=new_plot)
        #Put this call in plottables/guitools
        wx.PostEvent(self.parent,
                     NewPlotEvent(plot=new_plot, title="Sphere P(r)"))
Пример #9
0
    def create_gui_data(self, data, path=None):
        """
        Receive data from loader and create a data to use for guiframe
        """

        if issubclass(Data2D, data.__class__):
            new_plot = Data2D(
                image=None, err_image=None
            )  # For now, isSesans for 2D data is always false
        else:
            new_plot = Data1D(x=[],
                              y=[],
                              dx=None,
                              dy=None,
                              lam=None,
                              dlam=None,
                              isSesans=data.isSesans)

        #elif data.meta_data['loader'] == 'SESANS':
        #    new_plot = Data1D(x=[], y=[], dx=None, dy=None, lam=None, dlam=None, isSesans=True)
        #else:
        #    new_plot = Data1D(x=[], y=[], dx=None, dy=None, lam=None, dlam=None) #SESANS check???

        new_plot.copy_from_datainfo(data)
        data.clone_without_data(clone=new_plot)
        #creating a name for data
        title = ""
        file_name = os.path.basename(
            path) if path is not None else data.filename
        if file_name:
            name = file_name
        elif data.run:
            name = data.run[0]
        else:
            name = "data"
        name = self.rename(name)
        #find title
        if data.title.strip():
            title = data.title
        if title.strip() == "":
            title = file_name

        if new_plot.filename.strip() == "":
            new_plot.filename = file_name

        new_plot.name = name
        new_plot.title = title
        ## allow to highlight data when plotted
        new_plot.interactive = True
        ## when 2 data have the same id override the 1 st plotted
        self.time_stamp += 1
        new_plot.id = str(name) + str(self.time_stamp)
        ##group_id specify on which panel to plot this data
        new_plot.group_id = str(name) + str(self.time_stamp)
        new_plot.is_data = True
        new_plot.path = path
        new_plot.list_group_id = []
        ##post data to plot
        # plot data
        return new_plot
Пример #10
0
    def write(self, filename, datainfo=None, state=None):
        """
        Write the content of a Data1D as a CanSAS file.

        : param filename: Name of the file to write
        : param datainfo: Data1D object
        : param state: CorfuncState object
        """
        # Prepare datainfo
        if datainfo is None:
            datainfo = Data1D(x=[], y=[])
        elif not (isinstance(datainfo, Data1D)
                  or isinstance(datainfo, LoaderData1D)):
            msg = ("The CanSAS writer expects a Data1D instance. {} was "
                   "provided").format(datainfo.__class__.__name__)
            raise RuntimeError, msg
        if datainfo.title is None or datainfo.title == '':
            datainfo.title = datainfo.name
        if datainfo.run_name is None or datainfo.run_name == '':
            datainfo.run = [str(datainfo.name)]
            datainfo.run_name[0] = datainfo.name

        # Create the XMl doc
        doc, sasentry = self._to_xml_doc(datainfo)
        if state is not None:
            doc = state.toXML(doc=doc, entry_node=sasentry)

        # Write the XML doc to a file
        fd = open(filename, 'w')
        fd.write(doc.toprettyxml())
        fd.close()
Пример #11
0
    def _post_data(self, nbins=None):
        """
        compute sector averaging of data2D into data1D

        :param nbins: the number of point to plot for the average 1D data
        """
        ## get the data2D to average
        data = self.base.data2D
        # If we have no data, just return
        if data == None:
            return
        ## Averaging
        from sas.sascalc.dataloader.manipulations import SectorQ
        radius = self.qmax
        phimin = -self.left_line.phi + self.main_line.theta
        phimax = self.left_line.phi + self.main_line.theta
        if nbins == None:
            nbins = 20
        sect = SectorQ(r_min=0.0,
                       r_max=radius,
                       phi_min=phimin + math.pi,
                       phi_max=phimax + math.pi,
                       nbins=nbins)

        sector = sect(self.base.data2D)
        ##Create 1D data resulting from average

        if hasattr(sector, "dxl"):
            dxl = sector.dxl
        else:
            dxl = None
        if hasattr(sector, "dxw"):
            dxw = sector.dxw
        else:
            dxw = None
        new_plot = Data1D(x=sector.x, y=sector.y, dy=sector.dy, dx=sector.dx)
        new_plot.dxl = dxl
        new_plot.dxw = dxw
        new_plot.name = "SectorQ" + "(" + self.base.data2D.name + ")"
        new_plot.source = self.base.data2D.source
        #new_plot.info=self.base.data2D.info
        new_plot.interactive = True
        new_plot.detector = self.base.data2D.detector
        ## If the data file does not tell us what the axes are, just assume...
        new_plot.xaxis("\\rm{Q}", "A^{-1}")
        new_plot.yaxis("\\rm{Intensity}", "cm^{-1}")
        if hasattr(data, "scale") and data.scale == 'linear' and \
                self.base.data2D.name.count("Residuals") > 0:
            new_plot.ytransform = 'y'
            new_plot.yaxis("\\rm{Residuals} ", "/")

        new_plot.group_id = "2daverage" + self.base.data2D.name
        new_plot.id = "SectorQ" + self.base.data2D.name
        new_plot.is_data = True
        self.base.parent.update_theory(data_id=data.id, theory=new_plot)
        wx.PostEvent(
            self.base.parent,
            NewPlotEvent(plot=new_plot,
                         title="SectorQ" + self.base.data2D.name))
Пример #12
0
    def onCircular(self, event, ismask=False):
        """
        perform circular averaging on Data2D

        :param event: wx.menu event

        """
        # Find the best number of bins
        npt = math.sqrt(len(self.data2D.data[np.isfinite(self.data2D.data)]))
        npt = math.floor(npt)
        from sas.sascalc.dataloader.manipulations import CircularAverage
        # compute the maximum radius of data2D
        self.qmax = max(math.fabs(self.data2D.xmax),
                        math.fabs(self.data2D.xmin))
        self.ymax = max(math.fabs(self.data2D.ymax),
                        math.fabs(self.data2D.ymin))
        self.radius = math.sqrt(
            math.pow(self.qmax, 2) + math.pow(self.ymax, 2))
        # Compute beam width
        bin_width = (self.qmax + self.qmax) / npt
        # Create data1D circular average of data2D
        Circle = CircularAverage(r_min=0,
                                 r_max=self.radius,
                                 bin_width=bin_width)
        circ = Circle(self.data2D, ismask=ismask)
        from sas.sasgui.guiframe.dataFitting import Data1D
        if hasattr(circ, "dxl"):
            dxl = circ.dxl
        else:
            dxl = None
        if hasattr(circ, "dxw"):
            dxw = circ.dxw
        else:
            dxw = None

        new_plot = Data1D(x=circ.x, y=circ.y, dy=circ.dy, dx=circ.dx)
        new_plot.dxl = dxl
        new_plot.dxw = dxw
        new_plot.name = "Circ avg " + self.data2D.name
        new_plot.source = self.data2D.source
        # new_plot.info = self.data2D.info
        new_plot.interactive = True
        new_plot.detector = self.data2D.detector

        # If the data file does not tell us what the axes are, just assume...
        new_plot.xaxis("\\rm{Q}", "A^{-1}")
        if hasattr(self.data2D, "scale") and \
                    self.data2D.scale == 'linear':
            new_plot.ytransform = 'y'
            new_plot.yaxis("\\rm{Residuals} ", "normalized")
        else:
            new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")

        new_plot.group_id = "2daverage" + self.data2D.name
        new_plot.id = "Circ avg " + self.data2D.name
        new_plot.is_data = True
        self.parent.update_theory(data_id=self.data2D.id, theory=new_plot)
        wx.PostEvent(self.parent,
                     NewPlotEvent(plot=new_plot, title=new_plot.name))
Пример #13
0
    def show_data(self, path=None, data=None, reset=False):
        """
        Show data read from a file

        :param path: file path
        :param reset: if True all other plottables will be cleared

        """
        #if path is not None:
        if data is not None:
            try:
                pr = self._create_file_pr(data)
            except:
                status = "Problem reading data: %s" % sys.exc_value
                wx.PostEvent(self.parent, StatusEvent(status=status))
                raise RuntimeError, status

            # If the file contains nothing, just return
            if pr is None:
                raise RuntimeError, "Loaded data is invalid"

            self.pr = pr

        # Make a plot of I(q) data
        if self.pr.err is None:
            new_plot = Data1D(self.pr.x, self.pr.y)
            new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
        else:
            new_plot = Data1D(self.pr.x, self.pr.y, dy=self.pr.err)
        new_plot.name = IQ_DATA_LABEL
        new_plot.xaxis("\\rm{Q}", 'A^{-1}')
        new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")
        new_plot.interactive = True
        new_plot.group_id = GROUP_ID_IQ_DATA
        new_plot.id = self.data_id
        new_plot.title = "I(q)"
        wx.PostEvent(self.parent,
                     NewPlotEvent(plot=new_plot, title="I(q)", reset=reset))

        self.current_plottable = new_plot
        # Get Q range
        self.control_panel.q_min = min(self.pr.x)
        self.control_panel.q_max = max(self.pr.x)
Пример #14
0
    def show_data(self, data, label, reset=False, active_ctrl=None):
        """
        Show data read from a file

        :param data: The data to plot (Data1D)
        :param label: What to label the plot. Also used as the plot ID
        :param reset: If True, all other plottables will be cleared
        """
        new_plot = Data1D(data.x, copy.deepcopy(data.y), dy=data.dy)
        group_id = ""
        if label == IQ_DATA_LABEL or label == IQ_EXTRAPOLATED_DATA_LABEL:
            new_plot.xaxis("\\rm{Q}", 'A^{-1}')
            new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")
            new_plot.y -= self.corfunc_panel.background
            # Show data on a log(Q)/I scale
            new_plot.ytransform = 'y'
            group_id = GROUP_ID_IQ_DATA
            if label == IQ_EXTRAPOLATED_DATA_LABEL:
                # Show the extrapolation as a curve instead of points
                new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
        elif label == TRANSFORM_LABEL1 or label == TRANSFORM_LABEL3:
            new_plot.xaxis("{x}", 'A')
            new_plot.yaxis("{\\Gamma}", '')
            # Show transform on a linear scale
            new_plot.xtransform = 'x'
            new_plot.ytransform = 'y'
            group_id = GROUP_ID_TRANSFORM
            # Show the transformation as a curve instead of points
            new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
        elif label == IDF_LABEL:
            new_plot.xaxis("{x}", 'A')
            new_plot.yaxis("{g_1}", '')
            # Linear scale
            new_plot.xtransform = 'x'
            new_plot.ytransform = 'y'
            group_id = GROUP_ID_IDF
            # Show IDF as a curve instead of points
            new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
        new_plot.id = label
        new_plot.name = label
        new_plot.group_id = group_id
        new_plot.interactive = True
        new_plot.title = group_id.replace('$', '').replace('\\', '')
        wx.PostEvent(self.parent,
                     NewPlotEvent(plot=new_plot, title=new_plot.title,
                        reset=reset))
        if label == IQ_DATA_LABEL or label == IQ_EXTRAPOLATED_DATA_LABEL:
            wx.CallAfter(self.corfunc_panel.plot_qrange, active=active_ctrl,
                leftdown=True)
        if label == IQ_EXTRAPOLATED_DATA_LABEL:
            # Zoom in to the region we're interested in
            xlim = (min(self.corfunc_panel._extrapolated_data.x), self.corfunc_panel.qmax[1]*1.2)
            wx.CallAfter(wx.PostEvent, self.parent, PlotLimitEvent(id=IQ_DATA_LABEL, group_id=GROUP_ID_IQ_DATA, xlim=xlim))
Пример #15
0
    def post_data(self, new_sector):
        """ post data averaging in Q"""
        if self.inner_circle.get_radius() < self.outer_circle.get_radius():
            rmin = self.inner_circle.get_radius()
            rmax = self.outer_circle.get_radius()
        else:
            rmin = self.outer_circle.get_radius()
            rmax = self.inner_circle.get_radius()
        if self.right_edge.get_angle() < self.left_edge.get_angle():
            phimin = self.right_edge.get_angle()
            phimax = self.left_edge.get_angle()
        else:
            phimin = self.left_edge.get_angle()
            phimax = self.right_edge.get_angle()
        # print "phimin, phimax, rmin ,rmax",math.degrees(phimin),
        # math.degrees(phimax), rmin ,rmax
        # from sas.sascalc.dataloader.manipulations import SectorQ

        sect = new_sector(r_min=rmin,
                          r_max=rmax,
                          phi_min=phimin,
                          phi_max=phimax)
        sector = sect(self.base.data2D)

        from sas.sasgui.guiframe.dataFitting import Data1D
        if hasattr(sector, "dxl"):
            dxl = sector.dxl
        else:
            dxl = None
        if hasattr(sector, "dxw"):
            dxw = sector.dxw
        else:
            dxw = None
        new_plot = Data1D(x=sector.x,
                          y=sector.y,
                          dy=sector.dy,
                          dxl=dxl,
                          dxw=dxw)
        new_plot.name = str(new_sector.__name__) + \
                        "(" + self.base.data2D.name + ")"
        new_plot.source = self.base.data2D.source
        new_plot.interactive = True
        # print "loader output.detector",output.source
        new_plot.detector = self.base.data2D.detector
        # If the data file does not tell us what the axes are, just assume...
        new_plot.xaxis("\\rm{Q}", 'rad')
        new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")
        new_plot.group_id = str(new_sector.__name__) + self.base.data2D.name
        self.base.parent.update_theory(data_id=self.base.data2D.id, \
                                       theory=new_plot)
        wx.PostEvent(
            self.base.parent,
            NewPlotEvent(plot=new_plot, title=str(new_sector.__name__)))
Пример #16
0
    def _simulation_completed_1D(self, output, elapsed, error=None):
        """
            Called by the computation thread when the simulation is complete.
            This method processes the simulation output, plots it, and updates
            the simulation time estimate.
            
            @param output: simulated distribution I(q)
            @param elapsed: simulation time, in seconds
            @param error: standard deviation on the I(q) points
        """
        # Create the plotting event to pop up the I(Q) plot.
        new_plot = Data1D(x=self.x, y=output, dy=error)
        new_plot.name = "I(Q) Simulation"
        new_plot.group_id = "simulation_output"
        new_plot.xaxis("\\rm{Q}", 'A^{-1}')
        new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")
        wx.PostEvent(self.parent,
                     NewPlotEvent(plot=new_plot, title="Simulation I(Q)"))

        # Create the plotting event to pop up the P(r) plot.
        r, pr = self.volCanvas.getPrData()
        new_plot = Data1D(x=r, y=pr, dy=[0] * len(r))
        new_plot.name = "P(r) Simulation"
        new_plot.group_id = "simulated_pr"
        new_plot.xaxis("\\rm{r}", 'A')
        new_plot.yaxis("\\rm{P(r)} ", "cm^{-3}")

        wx.PostEvent(self.parent,
                     NewPlotEvent(plot=new_plot, title="Simulated P(r)"))

        # Notify the user of the simlation time and update the basic
        # simulation estimate that will allow us to estimate simulation time
        # next time we are asked to simulate.
        msg = "Calculation completed in %g secs! [%g points]" % (
            elapsed, self.volCanvas.npts)
        wx.PostEvent(self.parent, StatusEvent(status=msg))
        if self.volCanvas.npts > 0:
            self.speed = elapsed / self.volCanvas.npts**2
Пример #17
0
    def __init__(self,
                 parent=None,
                 base=None,
                 data=None,
                 dimension=1,
                 id=ID,
                 *args,
                 **kwds):
        kwds["style"] = wx.DEFAULT_DIALOG_STYLE
        kwds["size"] = wx.Size(PANEL_SIZE * 1.5, PANEL_SIZE * 1.5)
        wx.Dialog.__init__(self, parent, id=id, *args, **kwds)

        if data is not None:
            # Font size
            kwds = []
            self.SetWindowVariant(variant=FONT_VARIANT)
            self.SetTitle("Plot " + data.name)
            self.parent = base
            self.data = data
            self.str = self.data.__str__()
            # # when 2 data have the same id override the 1 st plotted
            self.name = self.data.name
            self.dimension = dimension
            # Panel for 2D plot
            self.plotpanel = Maskplotpanel(self,
                                           -1,
                                           dimension,
                                           style=wx.TRANSPARENT_WINDOW)
            self.plotpanel._SetInitialSize()
            self.plotpanel.prevXtrans = "x"
            self.plotpanel.prevYtrans = "y"

            self.cmap = DEFAULT_CMAP
            # # Create Artist and bind it
            self.subplot = self.plotpanel.subplot
            self._setup_layout()
            if self.dimension == 1:
                self.newplot = Data1D(x=data.x,
                                      y=data.y,
                                      dx=data.dx,
                                      dy=data.dy)
                self.newplot.name = data.name
            else:
                self.newplot = Data2D(image=self.data.data)
                self.newplot.setValues(self.data)
                # Compute and get the image plot
            self.get_plot()
            # self.plotpanel.add_image(self.newplot)
            self.Centre()
            self.Layout()
Пример #18
0
    def _fit_pr(self, evt):
        """
        """
        # Generate P(r) for sphere
        radius = 60.0
        d_max = 2 * radius

        r = pylab.arange(0.01, d_max, d_max / 51.0)
        M = len(r)
        y = np.zeros(M)
        pr_err = np.zeros(M)

        total = 0.0
        for j in range(M):
            value = self.pr_theory(r[j], radius)
            total += value
            y[j] = value
            pr_err[j] = math.sqrt(y[j])

        y = y / total * d_max / len(r)

        # Perform fit
        pr = Invertor()
        pr.d_max = d_max
        pr.alpha = 0
        pr.x = r
        pr.y = y
        pr.err = pr_err
        out, cov = pr.pr_fit()
        for i in range(len(out)):
            print("%g +- %g" % (out[i], math.sqrt(cov[i][i])))

        # Show input P(r)
        title = "Pr"
        new_plot = Data1D(pr.x, pr.y, dy=pr.err)
        new_plot.name = "P_{obs}(r)"
        new_plot.xaxis("\\rm{r}", 'A')
        new_plot.yaxis("\\rm{P(r)} ", "cm^{-3}")
        new_plot.group_id = "P_{obs}(r)"
        new_plot.id = "P_{obs}(r)"
        new_plot.title = title
        self.parent.update_theory(data_id=self.data_id, theory=new_plot)
        wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title=title))

        # Show P(r) fit
        self.show_pr(out, pr)

        # Show I(q) fit
        q = pylab.arange(0.001, 0.1, 0.01 / 51.0)
        self.show_iq(out, pr, q)
Пример #19
0
    def test_clone_theory1D(self):
        """
            Test basic cloning
        """
        theory = Data1D(x=[], y=[], dy=None)
        theory.clone_without_data(clone=self.data)
        theory.copy_from_datainfo(data1d=self.data)
        for i in range(len(self.data.detector)):
            self.assertEqual(
                self.data.detector[i].distance, theory.detector[i].distance)

        for i in range(len(self.data.x)):
            self.assertEqual(self.data.x[i], theory.x[i])
            self.assertEqual(self.data.y[i], theory.y[i])
            self.assertEqual(self.data.dy[i], theory.dy[i])
Пример #20
0
    def convert_1d_data(self, qdata, iqdata):
        """
        Formats a 1D array of q_axis data and a 2D array of I axis data (where
        each row of iqdata is a separate row), into an array of Data1D objects
        """
        frames = []
        increment = 1
        single_file = True
        n_frames = iqdata.shape[0]
        # Standard file has 3 frames: SAS, calibration and WAS
        if n_frames > 3:
            # File has multiple frames - ask the user which ones they want to
            # export
            params = self.ask_frame_range(n_frames)
            frames = params['frames']
            increment = params['inc']
            single_file = params['file']
            if frames == []: return
        else:  # Only interested in SAS data
            frames = [0]

        output_path = self.output.GetPath()
        metadata = self.get_metadata()

        frame_data = {}
        for i in frames:
            data = Data1D(x=qdata, y=iqdata[i])
            frame_data[i] = data
        if single_file:
            # Only need to set metadata on first Data1D object
            frame_data = frame_data.values(
            )  # Don't need to know frame numbers
            frame_data[0].filename = output_path.split('\\')[-1]
            for key, value in metadata.iteritems():
                setattr(frame_data[0], key, value)
        else:
            # Need to set metadata for all Data1D objects
            for datainfo in frame_data.values():
                datainfo.filename = output_path.split('\\')[-1]
                for key, value in metadata.iteritems():
                    setattr(datainfo, key, value)

        _, ext = os.path.splitext(output_path)
        if ext == '.xml':
            self.convert_to_cansas(frame_data, output_path, single_file)
        else:  # ext == '.h5'
            w = NXcanSASWriter()
            w.write(frame_data, output_path)
Пример #21
0
    def write_toXML(self, datainfo=None, state=None):
        """
        Write toXML, a helper for write()

        : return: xml doc
        """
        if datainfo is None:
            datainfo = Data1D(x=[], y=[])
        elif not issubclass(datainfo.__class__, Data1D):
            msg = "The cansas writer expects a Data1D "
            msg += "instance: %s" % str(datainfo.__class__.__name__)
            raise RuntimeError(msg)

        # Create basic XML document
        doc, sasentry = self._to_xml_doc(datainfo)

        # Add the invariant information to the XML document
        if state is not None:
            doc = state.toXML(doc=doc, entry_node=sasentry)

        return doc
Пример #22
0
 def transform_complete(self, transform=None):
     """
     Called from FourierThread when calculation has completed
     """
     self._transform_btn.SetLabel("Transform")
     if transform is None:
         msg = "Error calculating Transform."
         if self.transform_type == 'hilbert':
             msg = "Not yet implemented"
         wx.PostEvent(self._manager.parent,
                      StatusEvent(status=msg, info="Error"))
         self._extract_btn.Disable()
         return
     self._transformed_data = transform
     import numpy as np
     plot_x = transform.x[np.where(transform.x <= 200)]
     plot_y = transform.y[np.where(transform.x <= 200)]
     self._manager.show_data(Data1D(plot_x, plot_y), TRANSFORM_LABEL1)
     # Only enable extract params button if a fourier trans. has been done
     if self.transform_type == 'fourier':
         self._extract_btn.Enable()
     else:
         self._extract_btn.Disable()
Пример #23
0
    def __init__(self,
                 parent=None,
                 base=None,
                 data=None,
                 axes=['Radius'],
                 id=-1,
                 *args,
                 **kwds):
        kwds["style"] = wx.DEFAULT_DIALOG_STYLE
        kwds["size"] = wx.Size(_STATICBOX_WIDTH, PANEL_SIZE)
        wx.Dialog.__init__(self, parent, id=id, *args, **kwds)

        if data != None:
            #Font size
            kwds = []
            self.SetWindowVariant(variant=FONT_VARIANT)

            self.SetTitle("Scattering Length Density Profile")
            self.parent = parent
            self._mgr = None
            self.data = data
            self.str = self.data.__str__()
            ## when 2 data have the same id override the 1 st plotted
            self.name = self.data.name
            # Panel for plot
            self.plotpanel = SLDplotpanel(self,
                                          axes,
                                          -1,
                                          style=wx.TRANSPARENT_WINDOW)
            self.cmap = DEFAULT_CMAP
            ## Create Artist and bind it
            self.subplot = self.plotpanel.subplot
            # layout
            self._setup_layout()

            # plot
            data_plot = deepcopy(self.data)
            data_plot.dy = self._set_dy_data()
            # unit increase to M times for users
            data_plot.y = self._set_y_data()

            self.newplot = Data1D(data_plot.x, data_plot.y, data_plot.dy)
            self.newplot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
            self.newplot.dy = None
            self.newplot.name = 'SLD'
            self.newplot.is_data = False

            self.newplot.id = self.newplot.name
            self.plotpanel.add_image(self.newplot)

            self.plotpanel.resizing = False
            self.plotpanel.canvas.set_resizing(self.plotpanel.resizing)

            self.plotpanel.subplot.set_ylim(
                min(data_plot.y) - _Y_OFF,
                max(data_plot.y) + _Y_OFF)
            self.plotpanel.subplot.set_xlim(
                min(data_plot.x) - _X_OFF,
                max(data_plot.x) + _X_OFF)
            self.plotpanel.graph.render(self.plotpanel)
            self.plotpanel.canvas.draw()
Пример #24
0
    def _post_data(self, nbins=None):
        """
        Uses annulus parameters to plot averaged data into 1D data.

        :param nbins: the number of points to plot

        """
        # Data to average
        data = self.base.data2D
        # If we have no data, just return
        if data == None:
            return

        from sas.sascalc.dataloader.manipulations import Ring
        rmin = min(math.fabs(self.inner_circle.get_radius()),
                   math.fabs(self.outer_circle.get_radius()))
        rmax = max(math.fabs(self.inner_circle.get_radius()),
                   math.fabs(self.outer_circle.get_radius()))
        # if the user does not specify the numbers of points to plot
        # the default number will be nbins= 36
        if nbins == None:
            self.nbins = 36
        else:
            self.nbins = nbins
        # # create the data1D Q average of data2D
        sect = Ring(r_min=rmin, r_max=rmax, nbins=self.nbins)
        sector = sect(self.base.data2D)

        if hasattr(sector, "dxl"):
            dxl = sector.dxl
        else:
            dxl = None
        if hasattr(sector, "dxw"):
            dxw = sector.dxw
        else:
            dxw = None
        new_plot = Data1D(x=(sector.x - math.pi) * 180 / math.pi,
                          y=sector.y,
                          dy=sector.dy)
        new_plot.dxl = dxl
        new_plot.dxw = dxw
        new_plot.name = "AnnulusPhi" + "(" + self.base.data2D.name + ")"

        new_plot.source = self.base.data2D.source
        # new_plot.info=self.base.data2D.info
        new_plot.interactive = True
        new_plot.detector = self.base.data2D.detector
        # If the data file does not tell us what the axes are, just assume...
        new_plot.xaxis("\\rm{\phi}", 'degrees')
        new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")
        if hasattr(data, "scale") and data.scale == 'linear' and \
                self.base.data2D.name.count("Residuals") > 0:
            new_plot.ytransform = 'y'
            new_plot.yaxis("\\rm{Residuals} ", "/")

        new_plot.group_id = "AnnulusPhi" + self.base.data2D.name
        new_plot.id = "AnnulusPhi" + self.base.data2D.name
        new_plot.is_data = True
        new_plot.xtransform = "x"
        new_plot.ytransform = "y"
        self.base.parent.update_theory(data_id=data.id, theory=new_plot)
        wx.PostEvent(self.base.parent,
                     NewPlotEvent(plot=new_plot, title="AnnulusPhi"))
Пример #25
0
    def post_data(self, new_slab=None, nbins=None, direction=None):
        """
        post data averaging in Qx or Qy given new_slab type

        :param new_slab: slicer that determine with direction to average
        :param nbins: the number of points plotted when averaging
        :param direction: the direction of averaging

        """
        if self.direction is None:
            self.direction = direction

        x_min = -1 * math.fabs(self.vertical_lines.x)
        x_max = math.fabs(self.vertical_lines.x)
        y_min = -1 * math.fabs(self.horizontal_lines.y)
        y_max = math.fabs(self.horizontal_lines.y)

        if nbins is not None:
            self.nbins = nbins
        if self.averager is None:
            if new_slab is None:
                msg = "post data:cannot average , averager is empty"
                raise ValueError(msg)
            self.averager = new_slab
        if self.direction == "X":
            if self.fold:
                x_low = 0
            else:
                x_low = math.fabs(x_min)
            bin_width = (x_max + x_low) / self.nbins
        elif self.direction == "Y":
            if self.fold:
                y_low = 0
            else:
                y_low = math.fabs(y_min)
            bin_width = (y_max + y_low) / self.nbins
        else:
            msg = "post data:no Box Average direction was supplied"
            raise ValueError(msg)
        # # Average data2D given Qx or Qy
        box = self.averager(x_min=x_min, x_max=x_max, y_min=y_min, y_max=y_max,
                            bin_width=bin_width)
        box.fold = self.fold
        boxavg = box(self.base.data2D)
        # 3 Create Data1D to plot
        if hasattr(boxavg, "dxl"):
            dxl = boxavg.dxl
        else:
            dxl = None
        if hasattr(boxavg, "dxw"):
            dxw = boxavg.dxw
        else:
            dxw = None
        new_plot = Data1D(x=boxavg.x, y=boxavg.y, dy=boxavg.dy)
        new_plot.dxl = dxl
        new_plot.dxw = dxw
        new_plot.name = str(self.averager.__name__) + \
                        "(" + self.base.data2D.name + ")"
        new_plot.source = self.base.data2D.source
        new_plot.interactive = True
        new_plot.detector = self.base.data2D.detector
        # # If the data file does not tell us what the axes are, just assume...
        new_plot.xaxis("\\rm{Q}", "A^{-1}")
        new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")

        data = self.base.data2D
        if hasattr(data, "scale") and data.scale == 'linear' and \
                self.base.data2D.name.count("Residuals") > 0:
            new_plot.ytransform = 'y'
            new_plot.yaxis("\\rm{Residuals} ", "/")

        new_plot.group_id = "2daverage" + self.base.data2D.name
        new_plot.id = (self.averager.__name__) + self.base.data2D.name
        new_plot.is_data = True
        self.base.parent.update_theory(data_id=self.base.data2D.id, \
                                       theory=new_plot)
        wx.PostEvent(self.base.parent,
                     NewPlotEvent(plot=new_plot, title=str(self.averager.__name__)))
Пример #26
0
    def show_iq(self, out, pr, q=None):
        """
            Display computed I(q)
        """
        qtemp = pr.x
        if q is not None:
            qtemp = q

        # Make a plot
        maxq = -1
        for q_i in qtemp:
            if q_i > maxq:
                maxq = q_i

        minq = 0.001

        # Check for user min/max
        if pr.q_min is not None:
            minq = pr.q_min
        if pr.q_max is not None:
            maxq = pr.q_max

        x = pylab.arange(minq, maxq, maxq / 301.0)
        y = np.zeros(len(x))
        err = np.zeros(len(x))
        for i in range(len(x)):
            value = pr.iq(out, x[i])
            y[i] = value
            try:
                err[i] = math.sqrt(math.fabs(value))
            except:
                err[i] = 1.0
                print("Error getting error", value, x[i])

        new_plot = Data1D(x, y)
        new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
        new_plot.name = IQ_FIT_LABEL
        new_plot.xaxis("\\rm{Q}", 'A^{-1}')
        new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")
        title = "I(q)"
        new_plot.title = title

        # If we have a group ID, use it
        if 'plot_group_id' in pr.info:
            new_plot.group_id = pr.info["plot_group_id"]
        new_plot.id = IQ_FIT_LABEL
        self.parent.update_theory(data_id=self.data_id, theory=new_plot)

        wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title=title))

        # If we have used slit smearing, plot the smeared I(q) too
        if pr.slit_width > 0 or pr.slit_height > 0:
            x = pylab.arange(minq, maxq, maxq / 301.0)
            y = np.zeros(len(x))
            err = np.zeros(len(x))
            for i in range(len(x)):
                value = pr.iq_smeared(out, x[i])
                y[i] = value
                try:
                    err[i] = math.sqrt(math.fabs(value))
                except:
                    err[i] = 1.0
                    print("Error getting error", value, x[i])

            new_plot = Data1D(x, y)
            new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM
            new_plot.name = IQ_SMEARED_LABEL
            new_plot.xaxis("\\rm{Q}", 'A^{-1}')
            new_plot.yaxis("\\rm{Intensity} ", "cm^{-1}")
            # If we have a group ID, use it
            if 'plot_group_id' in pr.info:
                new_plot.group_id = pr.info["plot_group_id"]
            new_plot.id = IQ_SMEARED_LABEL
            new_plot.title = title
            self.parent.update_theory(data_id=self.data_id, theory=new_plot)
            wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title=title))