Esempio n. 1
0
def measureTau(abf: pyabf.ABF,
               sweep: int,
               epoch: int = 3,
               percentile: float = .05,
               ax: plt.Axes = None):

    abf.setSweep(sweep)

    # use epoch table to determine puff times
    puffTimeStart = abf.sweepEpochs.p1s[epoch] / abf.sampleRate
    puffTimeEnd = abf.sweepEpochs.p2s[epoch] / abf.sampleRate

    # calculate baseline level
    baselineStart = puffTimeStart - .1
    baselineEnd = puffTimeStart
    baselineMean = getMean(abf, baselineStart, baselineEnd)

    # find antipeak
    antipeakIndex = getAntiPeakIndex(abf.sweepY, abf.sampleRate, puffTimeStart,
                                     puffTimeStart + .5)
    antipeakLevel = abf.sweepY[antipeakIndex]

    # find portion of curve to fit
    curveIndex1, curveIndex2 = getCurveIndexes(abf.sweepY, antipeakIndex,
                                               baselineMean, percentile)
    curveYs = -abf.sweepY[curveIndex1:curveIndex2]
    curveXs = np.arange(len(curveYs)) / abf.sampleRate

    try:
        p0 = (500, 15, 0)  # start with values near those we expect
        params, cv = scipy.optimize.curve_fit(monoExp, curveXs, curveYs, p0)
    except:
        print(f"FIT FAILED (sweep {sweep})")
        return None
    m, t, b = params
    curveYsIdeal = monoExp(curveXs, m, t, b)
    tauMS = 1000 / t
    if (tauMS < 0):
        return None

    if ax:
        yPad = abs(antipeakLevel - baselineMean) * .1
        ax.plot(abf.sweepX, abf.sweepY, alpha=.5)
        ax.grid(alpha=.5, ls='--')
        ax.axhline(baselineMean, ls='--', color='k')
        ax.plot(abf.sweepX[curveIndex1:curveIndex2], -curveYsIdeal, color='k')
        ax.set(title=f"first sweep tau = {tauMS:.02f} ms")
        ax.axis([
            baselineStart - .1, baselineStart + 1, antipeakLevel - yPad,
            baselineMean + yPad
        ])
        ax.axvspan(puffTimeEnd, puffTimeEnd + .5, color='g', alpha=.1)
        ax.axvspan(puffTimeEnd + .5, puffTimeEnd + .6, color='m', alpha=.1)

    return tauMS
Esempio n. 2
0
 def plot_signal_span(self, ax: plt.Axes) -> plt.Line2D:
     return ax.axvspan(
         xmin=self.time_exp_start[self.index_signal_first, 0].to_datetime(),
         xmax=self.time_exp_end[self.index_signal_last, 0].to_datetime(),
         alpha=0.3,
         color='green',
         label='light frames',
     )
Esempio n. 3
0
 def plot_dark_down_span(self, ax: plt.Axes) -> plt.Line2D:
     return ax.axvspan(
         xmin=self.time_exp_start[self.index_dark_down_first, 0].to_datetime(),
         xmax=self.time_exp_end[self.index_dark_down_last, 0].to_datetime(),
         alpha=0.4,
         color='gray',
         label='downleg dark frames',
     )
Esempio n. 4
0
def _plot_cluster(ax: plt.Axes, cluster: pd.Series) -> None:
    if len(cluster) >= 2:
        ax.axvspan(
            xmin=cluster.index[0],
            xmax=cluster.index[-1],
            alpha=0.25,
            edgecolor="None",
            facecolor="#D1D3D4",
            zorder=2.5,
        )
        for cluster_boundary in [cluster.index[0], cluster.index[-1]]:
            ax.axvline(
                cluster_boundary,
                ls="--",
                lw=0.5,
                color="#D1D3D4",
                zorder=5,
            )
Esempio n. 5
0
def histogram(
    mesh: BaseMesh,
    *,
    metric: str,
    ax: plt.Axes = None,
    **kwargs,
) -> plt.Axes:
    """Create a mesh plot with the cells are colored by the cell quality.

    Parameters
    ----------
    mesh : BaseMesh
        Input mesh
    metric : str
        Metric to calculate.
    ax : `matplotlib.Axes`
        If specified, `ax` will be used to create the subplot.
    vmin, vmax : int, float
        Set the lower/upper boundary for the color value.
    cmap : str
        Set the color map.
    **kwargs
        Keyword arguments passed on to `ax.hist`.

    Returns
    -------
    ax : `matplotlib.Axes`
    """
    kwargs.setdefault('bins', 50)
    kwargs.setdefault('rwidth', 0.8)

    descriptor = _metric_dispatch[metric]
    quality = descriptor.func(mesh)  # type: ignore

    fig, ax = plt.subplots()
    n, bins, patches = ax.hist(quality, **kwargs)
    ax.set_title(f'Histogram of {descriptor.name.lower()}')

    if optimal_range := descriptor.optimal:
        ax.axvspan(*optimal_range, color='limegreen', zorder=0, alpha=0.1)
Esempio n. 6
0
    def _add_shading_to_axes(self, ax: Axes) -> None:
        """
        Adds any required shading.
        """

        common_args = dict(zorder=-10, alpha=0.3, color="grey", linewidth=0)

        # First do horizontal
        if self.x_shade[0] is not None:
            ax.axvspan(self.x_lim[0], self.x_shade[0], **common_args)

        if self.x_shade[1] is not None:
            ax.axvspan(self.x_shade[1], self.x_lim[1], **common_args)

        # Vertical
        if self.y_shade[0] is not None:
            ax.axhspan(self.y_lim[0], self.y_shade[0], **common_args)

        if self.y_shade[1] is not None:
            ax.axhspan(self.y_shade[1], self.y_lim[1], **common_args)

        return
Esempio n. 7
0
def add_tukey_marks(
    data: pd.Series,
    ax: plt.Axes,
    annot: bool = True,
    iqr_color: str = "r",
    fence_color: str = "k",
    fence_style: str = "--",
    annot_quarts: bool = False,
) -> plt.Axes:
    """Add IQR box and fences to a histogram-like plot.

    Args:
        data (pd.Series): Data for calculating IQR and fences.
        ax (plt.Axes): Axes to annotate.
        iqr_color (str, optional): Color of shaded IQR box. Defaults to "r".
        fence_color (str, optional): Fence line color. Defaults to "k".
        fence_style (str, optional): Fence line style. Defaults to "--".
        annot_quarts (bool, optional): Annotate Q1 and Q3. Defaults to False.

    Returns:
        plt.Axes: Annotated Axes object.
    """
    q1 = data.quantile(0.25)
    q3 = data.quantile(0.75)
    ax.axvspan(q1, q3, color=iqr_color, alpha=0.2)
    iqr_mp = q1 + ((q3 - q1) / 2)
    lower, upper = outliers.tukey_fences(data)
    ax.axvline(lower, c=fence_color, ls=fence_style)
    ax.axvline(upper, c=fence_color, ls=fence_style)
    text_yval = ax.get_ylim()[1]
    text_yval *= 1.01
    if annot:
        ax.text(iqr_mp, text_yval, "IQR", ha="center")
        if annot_quarts:
            ax.text(q1, text_yval, "Q1", ha="center")
            ax.text(q3, text_yval, "Q3", ha="center")
        ax.text(upper, text_yval, "Fence", ha="center")
        ax.text(lower, text_yval, "Fence", ha="center")
    return ax
Esempio n. 8
0
def plot_expression_by_distance(
    ax: plt.Axes,
    data: Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray],
    feature: Optional[str] = None,
    include_background: bool = True,
    curve_label: Optional[str] = None,
    flavor: str = "normal",
    color_scheme: Optional[Dict[str, str]] = None,
    ratio_order: List[str] = ["central", "portal"],
    list_flavor_choices: bool = False,
    feature_type: str = "Feature",
    distance_scale_factor: float = 1.0,
    **kwargs,
) -> None:
    """Generate feature by distance plots

    Function for seamless production of feature
    by distance plots.

    Parameters:
    ----------

    ax : plt.Axes
        axes object to plot data in
    data : Tuple[np.ndarray,np.ndarray,np.ndarray,np.ndarray]
        Tuple of data to plot, should be in form :
        (xs,ys,y_hat,std_err), the output which
        utils.smooth_fit produces.
    feature : Optional[str] (None)
        Name of plotted feature, set to None to exclude this
        information.
    include_background : bool (True)
        Set to True to include data points used
        to fit the smoothed data
    curve_label : Optional[str] (None)
        label of plotted data. Set to None to exclude
        legend.
    flavor : str = "normal",
        flavor of data, choose between 'normal' or
        'logodds'.
    color_scheme : Optional[Dict[str,str]] (None)
        dictionary providing the color scheme to be used.
        Include 'background':'color' to change color
        original data, include 'envelope':'color' to set
        color of envelope, include 'feature_class':'color' to
        set color of class.
    ratio_order : List[str] (["central","portal"])
        if logodds flavor is used, then specify which
        element was nominator (first element) and
        denominator (second element).
    list_flavor_choices : bool (False)
        set to True to list flavor choices
    feature_type : str ("Feature")
        Name of feature to plot, will be prepended to title
        as Feature : X. Set to None to only plot name X. Set
        to None to exclude feature type from being indicated
        in title and y-axis.
    distance_scale_factor : float (1.0)
        scaling factor to multiply distances with

    Returns:
    -------

    Tuple with Matplotlib Figure and Axes object, containing
    feature by distance plots.

    """

    flavors = ["normal", "logodds", "single_vein"]
    if list_flavor_choices:
        print("Flavors to choose from are : {}".format(', '.join(flavors)))
        return None
    if flavor not in flavors:
        raise ValueError("Not a valid flavor")

    if len(data) != 4:
        raise ValueError("Data must be (xs,ys,ys_hat,stderr)")

    if color_scheme is None:
        color_scheme = {}

    scaled_distances = data[0] * (distance_scale_factor if \
                                  flavor != "logodds" else 1.0)

    if include_background:
        ax.scatter(
            scaled_distances,
            data[1],
            s=1,
            c=color_scheme.get("background", "gray"),
            alpha=0.4,
        )

    ax.fill_between(
        scaled_distances,
        data[2] - data[3],
        data[2] + data[3],
        alpha=0.2,
        color=color_scheme.get("envelope", "grey"),
    )

    ax.set_title(
        "{} : {}".format(("" if feature_type is None else feature_type),
                         ("" if feature is None else feature)),
        fontsize=kwargs.get("title_font_size", kwargs.get("fontsize", 15)),
    )
    ax.set_ylabel(
        "{} Value".format(("" if feature_type is None else feature_type)),
        fontsize=kwargs.get("label_font_size", kwargs.get("fontsize", 15)),
    )

    if flavor == "normal":
        unit = ("" if "distance_unit" not in\
                kwargs.keys() else " [{}]".format(kwargs["distance_unit"]))

        ax.set_xlabel(
            "Distance to vein{}".format(unit),
            fontsize=kwargs.get("label_font_size", kwargs.get("fontsize", 15)),
        )

    if flavor == "logodds":

        x_min, x_max = ax.get_xlim()

        ax.axvspan(
            xmin=x_min,
            xmax=0,
            color=color_scheme.get(ratio_order[0], "red"),
            alpha=0.2,
        )

        ax.axvspan(
            xmin=0,
            xmax=x_max,
            color=color_scheme.get(ratio_order[1], "blue"),
            alpha=0.2,
        )

        d1 = ratio_order[0][0]
        d2 = ratio_order[1][0]
        ax.set_xlabel(
            r"$\log(d_{}) - \log(d_{})$".format(d1, d2),
            fontsize=kwargs.get("label_font_size", kwargs.get("fontsize", 15)),
        )

    ax.plot(
        scaled_distances,
        data[2],
        c=color_scheme.get("fitted", "black"),
        linewidth=2,
        label=("none" if curve_label is None else curve_label),
    )

    if "tick_fontsize" in kwargs.keys():
        ax.tick_params(axis="both",
                       which="major",
                       labelsize=kwargs["tick_fontsize"])