Exemplo n.º 1
0
def measurement(array, confidence=0.95, silent=False):
    """
    Give the measurement results with condifence interval
    assuming the standard deviation is unknown.

    Parameters
    ----------

    array : ndarray
        The array containing the measured values

    confidence : float, optional
        The desired confidence level. Must be _between 0 and 1.

    silent : bool, optional
        Whether to print results immediately. Default is `False`.

    Returns
    -------

    mean: float
        The mean of the given array

    conf: tuple-like (interval)
        The confidence interval

    Examples
    ---------
    >>> import numpy as np
    >>> from pysprint.utils import measurement
    >>> a = np.array([123.783, 121.846, 122.248, 125.139, 122.569])
    >>> mean, interval = measurement(a, 0.99)
    123.117000 ± 2.763022
    >>> mean
    123.117
    >>> interval
    (120.35397798230359, 125.88002201769642)

    Notes
    -----

    I decided to print the results immediately, because people often don't use
    it for further code. Of course, they are also returned if needed.
    """
    precision = _get_config_value("precision")
    mean = np.mean(array)
    conf = st.t.interval(confidence, len(array) - 1, loc=mean, scale=st.sem(array))
    if not silent:
        pprint_math_or_default(
            f"{mean:.{precision}f} ± {(mean - conf[0]):.{precision}f}"
        )
    return mean, conf
Exemplo n.º 2
0
    def __init__(self,
                 file: PathOrBuffer,
                 phase: Phase,
                 verbosity: Union[int, None] = None):
        self.file = file

        if not self.file.endswith((".log", ".txt")):
            self.file += ".log"

        # if os.path.exists(self.file):
        #     warnings.warn(f"File {self.file} exists, opening it in append mode.", PySprintWarning)

        self.phase = phase
        self.verbosity = verbosity or _get_config_value("verbosity")
Exemplo n.º 3
0
    def result_wrapper(self):
        precision = _get_config_value("precision")
        labels = ("GD", "GDD", "TOD", "FOD", "QOD", "SOD")
        params = self.p0[3:]
        for i, (label, param) in enumerate(zip(labels, params)):
            if run_from_ipython():
                from IPython.display import display, Math # noqa

                display(
                    Math(
                        f"{label} = {(params[i] * factorial(i + 1)):.{precision}f} \\ fs^{i + 1}"
                    )
                )
            else:
                print(f"{label} = {(params[i] * factorial(i + 1)):.{precision}f} fs^{i + 1}")
Exemplo n.º 4
0
    def run(self, r_extend_by, r_threshold, max_tries=5000, show_endpoint=True):
        precision = _get_config_value("precision")
        if not self._init_set:
            raise ValueError("Set the initial conditions.")
        self._fit()
        while self._fit_goodness() > r_threshold:

            # self.figure.savefig(f'{self.counter}.eps')
            # self.update_plot()

            self._extend_region(r_extend_by)
            self._fit()
            self.counter += 1
            self._step_up_func()
            if self._fit() is True:
                if show_endpoint:
                    self.update_plot()
                    # self.figure.savefig(f'{self.counter}.eps')

                self.result_wrapper()
                if run_from_ipython():
                    from IPython.display import display, Math # noqa

                    display(Math(f"with \\ R^2 = {(self._fit_goodness()):.{precision}f}."))
                else:
                    print(f"with R^2 = {(self._fit_goodness()):.{precision}f}.")
                return self.popt
            if self.counter == max_tries:
                if show_endpoint:
                    self.update_plot()
                print(
                    f"""Max tries (currently set to {max_tries}) reached without finding a suitable fit."""
                )
                return np.zeros_like(self.popt)

        while self._fit_goodness() < r_threshold:
            self._fit()
            # self._finetune()
            self.counter += 1
            if self.counter == max_tries:
                if show_endpoint:
                    self.update_plot()
                print(
                    f"""Max tries (currently set to {max_tries}) reached without finding a suitable fit."""
                )
                return np.zeros_like(self.popt)
Exemplo n.º 5
0
    def calculate(self, reference_point):
        """
        Cosine fit's calculate function.

        Parameters
        ----------
        reference_point: float
            Reference point on x axis.

        Returns
        -------
        dispersion : array-like
            [GD, GDD, TOD, FOD, QOD, SOD]
        dispersion_std : array-like
            Standard deviations due to uncertainty of the fit.
            They are only calculated if lmfit is installed.
            [GD_std, GDD_std, TOD_std, FOD_std, QOD_std, SOD_std]
        fit_report : str
            Not implemented yet. It returns an empty string for the time being.

        Notes
        ------
        Decorated with pprint_disp, so the results are
        immediately printed without explicitly saying so.
        """
        dispersion, self.fit = cff_method(
            self.x,
            self.y,
            self.ref,
            self.sam,
            ref_point=reference_point,
            p0=self.params,
            maxtries=self.mt,
        )
        precision = _get_config_value("precision")
        self.r_squared = self._get_r_squared()
        pprint_math_or_default(f"R^2 = {self.r_squared:.{precision}f}\n")
        dispersion = pad_with_trailing_zeros(dispersion, 6)
        return (
            dispersion,
            [0, 0, 0, 0, 0, 0],
            "",
        )
Exemplo n.º 6
0
 def plot_result(self):
     """
     If the curve fitting is done, draws the fitted curve on the original
     dataset. Also prints the coeffitient of determination of the
     fit (a.k.a. r^2).
     """
     precision = _get_config_value("precision")
     try:
         self._get_r_squared()
         pprint_math_or_default(f"R^2 = {self.r_squared:.{precision}f}")
     except NotCalculatedException as e:
         raise ValueError("There's nothing to plot.") from e
     if self.fit is not None:
         self.plt.plot(self.x, self.fit, "k--", label="fit", zorder=99)
         self.plt.legend()
         self.plot()
         self.show()
     else:
         self.plot()
         self.show()
Exemplo n.º 7
0
    def wrapping(*args, **kwargs):
        disp, disp_std, stri = f(*args, **kwargs)
        labels = ("GD", "GDD", "TOD", "FOD", "QOD", "SOD")
        disp = np.trim_zeros(disp, "b")
        disp_std = disp_std[:len(disp)]
        precision = _get_config_value("precision")
        for i, (label, disp_item,
                disp_std_item) in enumerate(zip(labels, disp, disp_std)):
            if run_from_ipython():
                from IPython.display import display, Math  # noqa

                display(
                    Math(
                        f"{label} = {disp_item:.{precision}f} ± {disp_std_item:.{precision}f} fs^{i + 1}"
                    ))
            else:
                print(
                    f"{label} = {disp_item:.{precision}f} ± {disp_std_item:.{precision}f} fs^{i + 1}"
                )
        return disp, disp_std, stri
Exemplo n.º 8
0
 def __str__(self):
     _unit = self._render_unit(self.unit)
     precision = _get_config_value("precision")
     string = dedent(f"""
     {type(self).__name__}
     ----------
     Parameters
     ----------
     Datapoints: {len(self.x)}
     Predicted domain: {'wavelength' if self.probably_wavelength else 'frequency'}
     Range: from {np.min(self.x):.{precision}f} to {np.max(self.x):.{precision}f} {_unit}
     Normalized: {self._is_normalized}
     Delay value: {str(self._format_delay()) + ' fs' if self._delay is not None else 'Not given'}
     SPP position(s): {str(self._format_positions()) + ' PHz' if np.all(self._positions) else 'Not given'}
     ----------------------------
     Metadata extracted from file
     ----------------------------
     """)
     string = re.sub('^\s+', '', string, flags=re.MULTILINE)
     string += json.dumps(self.meta, indent=4, sort_keys=True)
     return string
Exemplo n.º 9
0
    def _prepare_content(self):

        if self.phase.coef_array is None:
            raise NotCalculatedException

        precision = _get_config_value("precision")

        iter_num = len(self.phase.x)

        output = dedent(f"""
        ---------------------------------------------------------------------------------------
        Date: {datetime.datetime.now()}

        Datapoints used: {iter_num}

        R^2: {self.phase._get_r_squared():.{precision}f}

        Results:
        """)

        for i, (label,
                value) in enumerate(zip(self.LABELS, self.phase.coef_array)):
            if value is not None and value != 0:
                output += f"{label} = {value:.{precision}f} fs^{i + 1}\n"

        if self.verbosity > 0:
            with np.printoptions(
                    threshold=sys.maxsize,
                    linewidth=np.inf,
                    precision=precision,
            ):
                output += dedent(f"""
                Values used:
                x: {self.phase.x}

                y: {self.phase.y}
                """)
        return output
Exemplo n.º 10
0
 def __str__(self):
     precision = _get_config_value("precision")
     return f"Window(center={self.center:.{precision}f}, fwhm={self.fwhm}, order={self.order})"
Exemplo n.º 11
0
 def _repr_html_(self):  # TODO: move this to a separate template file
     _unit = self._render_unit(self.unit)
     precision = _get_config_value("precision")
     t = f"""
     <div id="header" class="row" style="height:10%;width:100%;">
     <div style='float:left' class="column">
     <table style="border:1px solid black;float:top;">
     <tbody>
     <tr>
     <td colspan=2 style="text-align:center">
     <font size="5">{type(self).__name__}</font>
     </td>
     </tr>
     <tr>
     <td colspan=2 style="text-align:center">
     <font size="3.5">Parameters</font>
     </td>
     </tr>
     <tr>
     <td style="text-align:center"><b>Datapoints<b></td>
         <td style="text-align:center"> {len(self.x)}</td>
     </tr>
     <tr>
         <td style="text-align:center"><b>Predicted domain<b> </td>
         <td style="text-align:center"> {'wavelength' if self.probably_wavelength else 'frequency'} </td>
     </tr>
     <tr>
     <td style="text-align:center"> <b>Range min</b> </td>
     <td style="text-align:center">{np.min(self.x):.{precision}f} {_unit}</td>
     </tr>
     <tr>
     <td style="text-align:center"> <b>Range max</b> </td>
     <td style="text-align:center">{np.max(self.x):.{precision}f} {_unit}</td>
     </tr>
     <tr>
     <td style="text-align:center"> <b>Normalized</b></td>
     <td style="text-align:center"> {self._is_normalized} </td>
     </tr>
     <tr>
     <td style="text-align:center"><b>Delay value</b></td>
     <td style="text-align:center">{str(self._format_delay()) + ' fs' if self._delay is not None else 'Not given'}</td>
     </tr>
     <tr>
     <td style="text-align:center"><b>SPP position(s)</b></td>
     <td style="text-align:center">{str(self._format_positions()) + ' PHz' if np.all(self._positions) else 'Not given'}</td>
     </tr>
     <tr>
     <td colspan=2 style="text-align:center">
     <font size="3.5">Metadata</font>
     </td>
     </tr>
     """
     jjstring = Template("""
     {% for key, value in meta.items() %}
        <tr>
     <th style="text-align:center"> <b>{{ key }} </b></th>
     <td style="text-align:center"> {{ value }} </td>
        </tr>
     {% endfor %}
         </tbody>
     </table>
     </div>
     <div style='float:leftt' class="column">""")
     rendered_fig = self._render_html_plot()
     return t + jjstring.render(meta=self.meta) + rendered_fig
Exemplo n.º 12
0
    def GD_lookup(self,
                  reference_point=None,
                  engine="cwt",
                  silent=False,
                  **kwargs):
        """
        Quick GD lookup: it finds extremal points near the
        `reference_point` and returns an average value of 2*pi
        divided by distances between consecutive minimal or maximal values.
        Since it's relying on peak detection, the results may be irrelevant
        in some cases. If the parent class is `~pysprint.CosFitMethod`, then
        it will set the predicted value as initial parameter for fitting.

        Parameters
        ----------
        reference_point : float
            The reference point for the algorithm.
        engine : str, optional
            The backend to use. Must be "cwt", "normal" or "fft".
            "cwt" will use `scipy.signal.find_peaks_cwt` function to
            detect peaks, "normal" will use `scipy.signal.find_peaks`
            to detect peaks. The "fft" engine uses Fourier-transform and
            looks for the outer peak to guess delay value. It's not
            reliable when working with low delay values.
        silent : bool, optional
            Whether to print the results immediately. Default in `False`.
        kwargs : dict, optional
            Additional keyword arguments to pass for peak detection
            algorithms. These are:
            pmin, pmax, threshold, width, floor_thres, etc..
            Most of them are described in the `find_peaks` and
            `find_peaks_cwt` docs.
        """
        precision = _get_config_value("precision")

        if engine not in ("cwt", "normal", "fft"):
            raise ValueError("Engine must be `cwt`, `fft` or `normal`.")

        if reference_point is None and engine != "fft":
            warnings.warn(
                f"Engine `{engine}` isn't available without reference point, falling back to FFT based prediction.",
                PySprintWarning)
            engine = "fft"

        if engine == "fft":
            pred, _ = find_center(*ifft_method(self.x, self.y))
            if pred is None:
                if not silent:
                    print("Prediction failed, skipping.")
                return
            print(f"The predicted GD is ± {pred:.{precision}f} fs.")

            if hasattr(self, "params"):
                self.params[3] = pred
            return

        if engine == "cwt":
            widths = kwargs.pop("widths", np.arange(1, 20))
            floor_thres = kwargs.pop("floor_thres", 0.05)
            x_min, _, x_max, _ = self.detect_peak_cwt(widths=widths,
                                                      floor_thres=floor_thres)

            # just validation
            _ = kwargs.pop("pmin", 0.1)
            _ = kwargs.pop("pmax", 0.1)
            _ = kwargs.pop("threshold", 0.35)

        else:
            pmin = kwargs.pop("pmin", 0.1)
            pmax = kwargs.pop("pmax", 0.1)
            threshold = kwargs.pop("threshold", 0.35)
            x_min, _, x_max, _ = self.detect_peak(pmin=pmin,
                                                  pmax=pmax,
                                                  threshold=threshold)

            # just validation
            _ = kwargs.pop("widths", np.arange(1, 10))
            _ = kwargs.pop("floor_thres", 0.05)

        if kwargs:
            raise TypeError(f"Invalid argument:{kwargs}")

        try:
            closest_val, idx1 = find_nearest(x_min, reference_point)
            m_closest_val, m_idx1 = find_nearest(x_max, reference_point)
        except (ValueError, IndexError):
            if not silent:
                print("Prediction failed, skipping.. ")
            return
        try:
            truncated = np.delete(x_min, idx1)
            second_closest_val, _ = find_nearest(truncated, reference_point)
        except (IndexError, ValueError):
            if not silent:
                print("Prediction failed, skipping.. ")
            return
        try:
            m_truncated = np.delete(x_max, m_idx1)
            m_second_closest_val, _ = find_nearest(m_truncated,
                                                   reference_point)
        except (IndexError, ValueError):
            if not silent:
                print("Prediction failed, skipping.. ")
            return

        lowguess = 2 * np.pi / np.abs(closest_val - second_closest_val)
        highguess = 2 * np.pi / np.abs(m_closest_val - m_second_closest_val)

        #  estimate the GD with that
        if hasattr(self, "params"):
            self.params[3] = (lowguess + highguess) / 2

        if not silent:
            print(
                f"The predicted GD is ± {((lowguess + highguess) / 2):.{precision}f} fs"
                f" based on reference point of {reference_point:.{precision}f}."
            )