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
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', )
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', )
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, )
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)
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
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
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"])