+"""
+YASA code for evaluating the agreement between two scorers (e.g., human vs YASA), either at the
+epoch-by-epoch level or at the level of summary sleep statistics.
+
+Analyses are influenced by the standardized framework proposed in Menghini et al., 2021, SLEEP.
+See the following resources:
+- https://doi.org/10.1093/sleep/zsaa170
+- https://sri-human-sleep.github.io/sleep-trackers-performance
+- https://github.com/SRI-human-sleep/sleep-trackers-performance
+"""
+
+importlogging
+
+importnumpyasnp
+importpandasaspd
+importscipy.statsassps
+importsklearn.metricsasskm
+
+
+logger=logging.getLogger("yasa")
+
+__all__=[
+ "EpochByEpochAgreement",
+ "SleepStatsAgreement",
+]
+
+
+################################################################################
+# EPOCH BY EPOCH
+################################################################################
+
+
+
[docs]classEpochByEpochAgreement:
+ """Evaluate agreement between two hypnograms or two collections of hypnograms.
+
+ Evaluation includes averaged agreement scores, one-vs-rest agreement scores, agreement scores
+ summarized across all sleep and summarized by sleep stage, and various plotting options to
+ visualize the two hypnograms simultaneously. See examples for more detail.
+
+ .. versionadded:: 0.7.0
+
+ Parameters
+ ----------
+ ref_hyps : iterable of :py:class:`yasa.Hypnogram`
+ A collection of reference hypnograms (i.e., those considered ground-truth).
+
+ Each :py:class:`yasa.Hypnogram` in ``ref_hyps`` must have the same
+ :py:attr:`~yasa.Hypnogram.scorer`.
+
+ If a ``dict``, key values are use to generate unique sleep session IDs. If any other
+ iterable (e.g., ``list`` or ``tuple``), then unique sleep session IDs are automatically
+ generated.
+ obs_hyps : iterable of :py:class:`yasa.Hypnogram`
+ A collection of observed hypnograms (i.e., those to be evaluated).
+
+ Each :py:class:`yasa.Hypnogram` in ``obs_hyps`` must have the same
+ :py:attr:`~yasa.Hypnogram.scorer`, and this scorer must be different than the scorer of
+ hypnograms in ``ref_hyps``.
+
+ If a ``dict``, key values must match those of ``ref_hyps``.
+
+ .. important::
+ It is assumed that the order of hypnograms are the same in ``ref_hyps`` and ``obs_hyps``.
+ For example, the third hypnogram in ``ref_hyps`` and ``obs_hyps`` must come from the same
+ sleep session, and they must only differ in that they have different scorers.
+
+ .. seealso:: For comparing just two hypnograms, use :py:meth:`yasa.Hynogram.evaluate`.
+
+ Notes
+ -----
+ Many steps here are influenced by guidelines proposed in Menghini et al., 2021 [Menghini2021]_.
+ See https://sri-human-sleep.github.io/sleep-trackers-performance/AnalyticalPipeline_v1.0.0.html
+
+ References
+ ----------
+ .. [Menghini2021] Menghini, L., Cellini, N., Goldstone, A., Baker, F. C., & de Zambotti, M.
+ (2021). A standardized framework for testing the performance of sleep-tracking
+ technology: step-by-step guidelines and open-source code. SLEEP, 44(2),
+ zsaa170. https://doi.org/10.1093/sleep/zsaa170
+
+ Examples
+ --------
+ >>> import yasa
+ >>> ref_hyps = [yasa.simulate_hypnogram(tib=600, scorer="Human", seed=i) for i in range(10)]
+ >>> obs_hyps = [h.simulate_similar(scorer="YASA", seed=i) for i, h in enumerate(ref_hyps)]
+ >>> ebe = yasa.EpochByEpochAgreement(ref_hyps, obs_hyps)
+ >>> agr = ebe.get_agreement()
+ >>> agr.head(5).round(2)
+ accuracy balanced_acc kappa mcc precision recall f1
+ sleep_id
+ 1 0.31 0.26 0.07 0.07 0.31 0.31 0.31
+ 2 0.33 0.33 0.14 0.14 0.35 0.33 0.34
+ 3 0.35 0.24 0.06 0.06 0.35 0.35 0.35
+ 4 0.22 0.21 0.01 0.01 0.21 0.22 0.21
+ 5 0.21 0.17 -0.06 -0.06 0.20 0.21 0.21
+
+ >>> ebe.get_agreement_bystage().head(12).round(3)
+ fbeta precision recall support
+ stage sleep_id
+ WAKE 1 0.391 0.371 0.413 189.0
+ 2 0.299 0.276 0.326 184.0
+ 3 0.234 0.204 0.275 255.0
+ 4 0.268 0.285 0.252 321.0
+ 5 0.228 0.230 0.227 181.0
+ 6 0.407 0.384 0.433 284.0
+ 7 0.362 0.296 0.467 287.0
+ 8 0.298 0.519 0.209 263.0
+ 9 0.210 0.191 0.233 313.0
+ 10 0.369 0.420 0.329 362.0
+ N1 1 0.185 0.185 0.185 124.0
+ 2 0.121 0.131 0.112 160.0
+
+ >>> ebe.get_confusion_matrix(sleep_id=1)
+ YASA WAKE N1 N2 N3 REM
+ Human
+ WAKE 78 24 50 3 34
+ N1 23 23 43 15 20
+ N2 60 58 183 43 139
+ N3 30 10 50 5 32
+ REM 19 9 121 50 78
+
+ .. plot::
+
+ >>> import matplotlib.pyplot as plt
+ >>> fig, ax = plt.subplots(figsize=(6, 3), constrained_layout=True)
+ >>> ebe.plot_hypnograms(sleep_id=10)
+
+ .. plot::
+
+ >>> fig, ax = plt.subplots(figsize=(6, 3))
+ >>> ebe.plot_hypnograms(
+ >>> sleep_id=8, ax=ax, obs_kwargs={"color": "red", "lw": 2, "ls": "dotted"}
+ >>> )
+ >>> plt.tight_layout()
+
+ .. plot::
+
+ >>> session = 8
+ >>> fig, ax = plt.subplots(figsize=(6.5, 2.5), constrained_layout=True)
+ >>> style_a = dict(alpha=1, lw=2.5, ls="solid", color="gainsboro", label="Michel")
+ >>> style_b = dict(alpha=1, lw=2.5, ls="solid", color="cornflowerblue", label="Jouvet")
+ >>> legend_style = dict(
+ >>> title="Scorer", frameon=False, ncol=2, loc="lower center", bbox_to_anchor=(0.5, 0.9)
+ >>> )
+ >>> ax = ebe.plot_hypnograms(
+ >>> sleep_id=session, ref_kwargs=style_a, obs_kwargs=style_b, legend=legend_style, ax=ax
+ >>> )
+ >>> acc = ebe.get_agreement().multiply(100).at[session, "accuracy"]
+ >>> ax.text(
+ >>> 0.01, 1, f"Accuracy = {acc:.0f}%", ha="left", va="bottom", transform=ax.transAxes
+ >>> )
+
+ When comparing only 2 hypnograms, use the :py:meth:`~yasa.Hynogram.evaluate` method:
+
+ >>> hypno_a = yasa.simulate_hypnogram(tib=90, scorer="RaterA", seed=8)
+ >>> hypno_b = hypno_a.simulate_similar(scorer="RaterB", seed=9)
+ >>> ebe = hypno_a.evaluate(hypno_b)
+ >>> ebe.get_confusion_matrix()
+ RaterB WAKE N1 N2 N3
+ RaterA
+ WAKE 71 2 20 8
+ N1 1 0 9 0
+ N2 12 4 25 0
+ N3 24 0 1 3
+ """
+
+
[docs]def__init__(self,ref_hyps,obs_hyps):
+ fromyasa.hypnoimportHypnogram# Avoiding circular import, bc hypno imports this class
+
+ asserthasattr(ref_hyps,"__iter__"),"`ref_hyps` must be a an iterable"
+ asserthasattr(obs_hyps,"__iter__"),"`obs_hyps` must be a an iterable"
+ asserttype(ref_hyps)istype(obs_hyps),"`ref_hyps` and `obs_hyps` must be the same type"
+ assertlen(ref_hyps)==len(
+ obs_hyps
+ ),"`ref_hyps` and `obs_hyps` must have the same number of hypnograms"
+
+ ifisinstance(ref_hyps,dict):
+ # If user provides dictionaries, split into sleep IDs and hypnograms
+ assert(
+ ref_hyps.keys()==obs_hyps.keys()
+ ),"keys in `ref_hyps` must be the same as keys in `obs_hyps`"
+ sleep_ids,ref_hyps=zip(*ref_hyps.items())
+ obs_hyps=tuple(obs_hyps.values())
+ else:
+ # Create hypnogram_ids
+ sleep_ids=tuple(range(1,1+len(ref_hyps)))
+
+ assertall(
+ isinstance(hyp,Hypnogram)forhypinref_hyps+obs_hyps
+ ),"`ref_hyps` and `obs_hyps` must only contain YASA hypnograms"
+ assertall(
+ h.scorerisnotNoneforhinref_hyps+obs_hyps
+ ),"all hypnograms in `ref_hyps` and `obs_hyps` must have a scorer name"
+ forh1,h2inzip((ref_hyps+obs_hyps)[:-1],(ref_hyps+obs_hyps)[1:]):
+ asserth1.freq==h2.freq,"all hypnograms must have the same freq"
+ asserth1.labels==h2.labels,"all hypnograms must have the same labels"
+ asserth1.mapping==h2.mapping,"all hypnograms must have the same mapping"
+ asserth1.n_stages==h2.n_stages,"all hypnograms must have the same n_stages"
+ assertall(
+ h1.scorer==h2.scorerforh1,h2inzip(ref_hyps[:-1],ref_hyps[1:])
+ ),"all `ref_hyps` must have the same scorer"
+ assertall(
+ h1.scorer==h2.scorerforh1,h2inzip(obs_hyps[:-1],obs_hyps[1:])
+ ),"all `obs_hyps` must have the same scorer"
+ assertall(
+ h1.scorer!=h2.scorerforh1,h2inzip(ref_hyps,obs_hyps)
+ ),"each `ref_hyps` and `obs_hyps` pair must have unique scorers"
+ assertall(
+ h1.n_epochs==h2.n_epochsforh1,h2inzip(ref_hyps,obs_hyps)
+ ),"each `ref_hyps` and `obs_hyps` pair must have the same n_epochs"
+ # Convert ref_hyps and obs_hyps to dictionaries with sleep_id keys and hypnogram values
+ ref_hyps={s:hfors,hinzip(sleep_ids,ref_hyps)}
+ obs_hyps={s:hfors,hinzip(sleep_ids,obs_hyps)}
+
+ # Merge all hypnograms into a single MultiIndexed dataframe
+ ref=pd.concat(pd.concat({s:h.as_int()},names=["sleep_id"])fors,hinref_hyps.items())
+ obs=pd.concat(pd.concat({s:h.as_int()},names=["sleep_id"])fors,hinobs_hyps.items())
+ data=pd.concat([ref,obs],axis=1)
+
+ # Generate some mapping dictionaries to be used later in class methods
+ skm_labels=np.unique(data).tolist()# all unique YASA integer codes in this hypno
+ skm2yasa_map={i:lfori,linenumerate(skm_labels)}# skm order to YASA integers
+ yasa2yasa_map=ref_hyps[sleep_ids[0]].mapping_int.copy()# YASA integer to YASA string
+
+ # Set attributes
+ self._data=data
+ self._sleep_ids=sleep_ids
+ self._ref_hyps=ref_hyps
+ self._obs_hyps=obs_hyps
+ self._ref_scorer=ref_hyps[sleep_ids[0]].scorer
+ self._obs_scorer=obs_hyps[sleep_ids[0]].scorer
+ self._skm_labels=skm_labels
+ self._skm2yasa_map=skm2yasa_map
+ self._yasa2yasa_map=yasa2yasa_map
+
+ def__repr__(self):
+ # TODO v0.8: Keep only the text between < and >
+ s="s"ifself.n_sleeps>1else""
+ return(
+ f"<EpochByEpochAgreement | Observed hypnogram{s} scored by {self.obs_scorer} "
+ f"evaluated against reference hypnogram{s} scored by {self.ref_scorer}, "
+ f"{self.n_sleeps} sleep session{s}>\n"
+ " - Use `.get_agreement()` to get agreement measures as a pandas DataFrame or Series\n"
+ " - Use `.plot_hypnograms()` to plot two overlaid hypnograms\n"
+ "See the online documentation for more details."
+ )
+
+ def__str__(self):
+ returnself.__repr__()
+
+ @property
+ defdata(self):
+ """A :py:class:`pandas.DataFrame` including all hypnograms."""
+ returnself._data
+
+ @property
+ defn_sleeps(self):
+ """The number of unique sleep sessions."""
+ returnlen(self._sleep_ids)
+
+ @property
+ defref_scorer(self):
+ """The name of the reference scorer."""
+ returnself._ref_scorer
+
+ @property
+ defobs_scorer(self):
+ """The name of the observed scorer."""
+ returnself._obs_scorer
+
+
[docs]@staticmethod
+ defmulti_scorer(df,scorers):
+ """
+ Compute multiple agreement scores from a 2-column dataframe (an optional 3rd column may
+ contain sample weights).
+
+ This function offers convenience when calculating multiple agreement scores using
+ :py:meth:`pandas.DataFrame.groupby.apply`. Scikit-learn doesn't include a function that
+ returns multiple scores, and the GroupBy implementation of ``apply`` in pandas does not
+ accept multiple functions.
+
+ Parameters
+ ----------
+ df : :py:class:`pandas.DataFrame`
+ A :py:class:`~pandas.DataFrame` with 2 columns and length of *n_samples*.
+ The first column contains reference values and second column contains observed values.
+ If a third column, it must contain sample weights to be passed to underlying
+ :py:mod:`sklearn.metrics` functions as ``sample_weight`` where applicable.
+ scorers : dictionary
+ The scorers to be used for evaluating agreement. A dictionary with scorer names (str) as
+ keys and functions as values.
+
+ Returns
+ -------
+ scores : dict
+ A dictionary with scorer names (``str``) as keys and scores (``float``) as values.
+ """
+ assertisinstance(df,pd.DataFrame),"`df` must be a pandas DataFrame"
+ assertdf.shape[1]in[2,3],"`df` must have either 2 or 3 columns"
+ assertisinstance(scorers,dict),"`scorers` must be a dictionary"
+ assertall(
+ isinstance(k,str)andcallable(v)fork,vinscorers.items()
+ ),"Each key of `scorers` must be a string, and each value must be a callable function"
+ ifdf.shape[1]==3:
+ true,pred,weights=zip(*df.values)
+ elifdf.shape[1]==2:
+ true,pred=zip(*df.values)# Same as (df["col1"], df["col2"]) but teensy bit faster
+ weights=None
+ scores={s:f(true,pred,weights)fors,finscorers.items()}
+ returnscores
+
+
[docs]defget_agreement(self,sample_weight=None,scorers=None):
+ """
+ Return a :py:class:`pandas.DataFrame` of weighted (i.e., averaged) agreement scores.
+
+ Parameters
+ ----------
+ self : :py:class:`~yasa.evaluation.EpochByEvaluation`
+ A :py:class:`~yasa.evaluation.EpochByEvaluation` instance.
+ sample_weight : None or :py:class:`pandas.Series`
+ Sample weights passed to underlying :py:mod:`sklearn.metrics` functions where possible.
+ If a :py:class:`pandas.Series`, the index must match exactly that of
+ :py:attr:`~yasa.Hypnogram.data`.
+ scorers : None, list, or dictionary
+ The scorers to be used for evaluating agreement. If None (default), default scorers are
+ used. If a list, the list must contain strings that represent metrics from the sklearn
+ metrics module (e.g., ``accuracy``, ``precision``). If more customization is desired, a
+ dictionary can be passed with scorer names (str) as keys and custom functions as values.
+ The custom functions should take 3 positional arguments (true values, predicted values,
+ and sample weights).
+
+ Returns
+ -------
+ agreement : :py:class:`pandas.DataFrame`
+ A :py:class:`~pandas.DataFrame` with agreement metrics as columns and sessions as rows.
+ """
+ assertisinstance(
+ sample_weight,(type(None),pd.Series)
+ ),"`sample_weight` must be None or pandas Series"
+ assertisinstance(scorers,(type(None),list,dict))
+ ifisinstance(scorers,list):
+ assertall(isinstance(x,str)forxinscorers)
+ elifisinstance(scorers,dict):
+ assertall(isinstance(k,str)andcallable(v)fork,vinscorers.items())
+ ifscorersisNone:
+ # Create dictionary of default scorer functions
+ scorers={
+ "accuracy":lambdat,p,w:skm.accuracy_score(
+ t,p,normalize=True,sample_weight=w
+ ),
+ "balanced_acc":lambdat,p,w:skm.balanced_accuracy_score(
+ t,p,adjusted=False,sample_weight=w
+ ),
+ "kappa":lambdat,p,w:skm.cohen_kappa_score(
+ t,p,labels=None,weights=None,sample_weight=w
+ ),
+ "mcc":lambdat,p,w:skm.matthews_corrcoef(t,p,sample_weight=w),
+ "precision":lambdat,p,w:skm.precision_score(
+ t,p,average="weighted",sample_weight=w,zero_division=0
+ ),
+ "recall":lambdat,p,w:skm.recall_score(
+ t,p,average="weighted",sample_weight=w,zero_division=0
+ ),
+ "f1":lambdat,p,w:skm.f1_score(
+ t,p,average="weighted",sample_weight=w,zero_division=0
+ ),
+ }
+ elifisinstance(scorers,list):
+ # Convert the list to a dictionary of sklearn scorers
+ scorers={s:skm.__getattribute__(f"{s}_scorer")forsinscorers}
+ # Make a copy of data since weights series might be added to it
+ df=self.data.copy()
+ ifsample_weightisnotNone:
+ assertsample_weight.index==self.data.index,(
+ "If not `None`, `sample_weight` Series must be a pandas Series with the same index "
+ "as `self.data`"
+ )
+ # Add weights as a third column for multi_scorer to use
+ df["weights"]=sample_weight
+ # Get individual-level averaged/weighted agreement scores
+ agreement=df.groupby(level=0).apply(self.multi_scorer,scorers=scorers).apply(pd.Series)
+ # Set attribute for later access
+ self._agreement=agreement
+ # Convert to Series if just one session being evaluated
+ ifself.n_sleeps==1:
+ agreement=agreement.squeeze().rename("agreement")
+ returnagreement
+
+
[docs]defget_agreement_bystage(self,beta=1.0):
+ """
+ Return a :py:class:`pandas.DataFrame` of unweighted (i.e., one-vs-rest) agreement scores.
+
+ Parameters
+ ----------
+ self : :py:class:`~yasa.evaluation.EpochByEvaluation`
+ A :py:class:`~yasa.evaluation.EpochByEvaluation` instance.
+ beta : float
+ See :py:func:`sklearn.metrics.precision_recall_fscore_support`.
+
+ Returns
+ -------
+ agreement : :py:class:`pandas.DataFrame`
+ A :py:class:`~pandas.DataFrame` with agreement metrics as columns and a
+ :py:class:`~pandas.MultiIndex` with session and sleep stage as rows.
+ """
+
+ defscorer(df):
+ returnskm.precision_recall_fscore_support(
+ *df.values.T,beta=beta,labels=self._skm_labels,average=None,zero_division=0
+ )
+
+ agreement=(
+ self.data
+ # Get precision, recall, f1, and support for each individual sleep session
+ .groupby(level=0)
+ .apply(scorer)
+ # Unpack arrays
+ .explode()
+ .apply(pd.Series)
+ # Add metric labels column and prepend it to index, creating MultiIndex
+ .assign(metric=["precision","recall","fbeta","support"]*self.n_sleeps)
+ .set_index("metric",append=True)
+ # Convert stage column names to string labels
+ .rename_axis(columns="stage")
+ .rename(columns=self._skm2yasa_map)
+ .rename(columns=self._yasa2yasa_map)
+ # Remove all-zero columns (i.e., stages that were not present in the hypnogram)
+ .pipe(lambdadf:df.loc[:,df.any()])
+ # Reshape so metrics are columns
+ .stack()
+ .unstack("metric")
+ .rename_axis(columns=None)
+ # Swap MultiIndex levels and sort so stages are in standard YASA order
+ .swaplevel()
+ .sort_index(
+ level="stage",
+ key=lambdax:x.map(lambday:list(self._yasa2yasa_map.values()).index(y)),
+ )
+ )
+ # Set attribute for later access
+ self._agreement_bystage=agreement
+ # Remove the MultiIndex if just one session being evaluated
+ ifself.n_sleeps==1:
+ agreement=agreement.reset_index(level=1,drop=True)
+ returnagreement
+
+
[docs]defget_confusion_matrix(self,sleep_id=None,agg_func=None,**kwargs):
+ """
+ Return a ``ref_hyp``/``obs_hyp``confusion matrix from either a single session or all
+ sessions concatenated together.
+
+ Parameters
+ ----------
+ self : :py:class:`yasa.EpochByEpochAgreement`
+ A :py:class:`yasa.EpochByEpochAgreement` instance.
+ sleep_id : None or a valid sleep ID
+ If None (default), cross-tabulation is derived from the entire group dataset.
+ If a valid sleep ID, cross-tabulation is derived using only the reference and observed
+ scored hypnograms from that sleep session.
+ agg_func : None or str
+ If None (default), group results returns a :py:class:`~pandas.DataFrame` complete with
+ all individual session results. If not None, group results returns a
+ :py:class:`~pandas.DataFrame` aggregated across sessions where ``agg_func`` is passed as
+ ``func`` parameter in :py:meth:`pandas.DataFrame.groupby.agg`. For example, set
+ ``agg_func="sum"`` to get a single confusion matrix across all epochs that does not take
+ session into account.
+ **kwargs : key, value pairs
+ Additional keyword arguments are passed to :py:func:`sklearn.metrics.confusion_matrix`.
+
+ Returns
+ -------
+ conf_matr : :py:class:`pandas.DataFrame`
+ A confusion matrix with stages from the reference scorer as indices and stages from the
+ test scorer as columns.
+
+ Examples
+ --------
+ >>> import yasa
+ >>> ref_hyps = [yasa.simulate_hypnogram(tib=90, scorer="Rater1", seed=i) for i in range(3)]
+ >>> obs_hyps = [h.simulate_similar(scorer="Rater2", seed=i) for i, h in enumerate(ref_hyps)]
+ >>> ebe = yasa.EpochByEpochAgreement(ref_hyps, obs_hyps)
+ >>> ebe.get_confusion_matrix(sleep_id=2)
+ Rater2 WAKE N1 N2 N3 REM
+ Rater1
+ WAKE 1 2 23 0 0
+ N1 0 9 13 0 0
+ N2 0 6 71 0 0
+ N3 0 13 42 0 0
+ REM 0 0 0 0 0
+
+ >>> ebe.get_confusion_matrix()
+ Rater2 WAKE N1 N2 N3 REM
+ sleep_id Rater1
+ 1 WAKE 30 0 3 0 35
+ N1 3 2 7 0 0
+ N2 21 12 7 0 4
+ N3 0 0 0 0 0
+ REM 2 8 29 0 17
+ 2 WAKE 1 2 23 0 0
+ N1 0 9 13 0 0
+ N2 0 6 71 0 0
+ N3 0 13 42 0 0
+ REM 0 0 0 0 0
+ 3 WAKE 16 0 7 19 19
+ N1 0 7 2 0 5
+ N2 0 10 12 7 5
+ N3 0 0 16 11 0
+ REM 0 15 11 18 0
+
+ >>> ebe.get_confusion_matrix(agg_func="sum")
+ Rater2 WAKE N1 N2 N3 REM
+ Rater1
+ WAKE 47 2 33 19 54
+ N1 3 18 22 0 5
+ N2 21 28 90 7 9
+ N3 0 13 58 11 0
+ REM 2 23 40 18 17
+ """
+ assert(
+ sleep_idisNoneorsleep_idinself._sleep_ids
+ ),"`sleep_id` must be None or a valid sleep ID"
+ assertisinstance(agg_func,(type(None),str)),"`agg_func` must be None or a str"
+ assertnot(
+ (self.n_sleeps==1orsleep_idisnotNone)andagg_funcisnotNone
+ ),"`agg_func` must be None if plotting a single session."
+ kwargs={"labels":self._skm_labels}|kwargs
+ # Generate a DataFrame with a confusion matrix for each session
+ # Seems easier to just generate this whole thing and then either
+ # extract a single one or aggregate across them all, depending on user request
+ confusion_matrices=(
+ self.data
+ # Get confusion matrix for each individual sleep session
+ .groupby(level=0)
+ .apply(lambdadf:skm.confusion_matrix(*df.values.T,**kwargs))
+ # Expand results matrix out from single cell
+ .explode()
+ .apply(pd.Series)
+ # Convert to MultiIndex with reference scorer as new level
+ .assign(**{self.ref_scorer:self._skm_labels*self.n_sleeps})
+ .set_index(self.ref_scorer,append=True)
+ .rename_axis(columns=self.obs_scorer)
+ # Convert sleep stage columns and indices to strings
+ .rename(columns=self._skm2yasa_map)
+ .rename(columns=self._yasa2yasa_map)
+ .rename(index=self._skm2yasa_map,level=self.ref_scorer)
+ .rename(index=self._yasa2yasa_map,level=self.ref_scorer)
+ )
+ ifself.n_sleeps==1:
+ # If just one session, use the only session ID as the key, for simplified returned df
+ sleep_id=self._sleep_ids[0]
+ ifsleep_idisNone:
+ ifagg_funcisNone:
+ mat=confusion_matrices
+ else:
+ mat=confusion_matrices.groupby(self.ref_scorer,sort=False).agg(agg_func)
+ else:
+ mat=confusion_matrices.loc[sleep_id]
+ returnmat
+
+
[docs]defget_sleep_stats(self):
+ """
+ Return a :py:class:`pandas.DataFrame` of sleep statistics for each hypnogram derived from
+ both reference and observed scorers.
+
+ .. seealso:: :py:meth:`yasa.Hypnogram.sleep_statistics`
+
+ .. seealso:: :py:class:`yasa.SleepStatsAgreement`
+
+ Parameters
+ ----------
+ self : :py:class:`yasa.EpochByEpochAgreement`
+ A :py:class:`yasa.EpochByEpochAgreement` instance.
+
+ Returns
+ -------
+ sstats : :py:class:`pandas.DataFrame`
+ A :py:class:`~pandas.DataFrame` with sleep statistics as columns and two rows for each
+ individual (one for reference scorer and another for test scorer).
+ """
+ # Get all sleep statistics
+ ref_sstats=pd.DataFrame({s:h.sleep_statistics()fors,hinself._ref_hyps.items()})
+ obs_sstats=pd.DataFrame({s:h.sleep_statistics()fors,hinself._obs_hyps.items()})
+ # Reshape and name axis
+ ref_sstats=ref_sstats.T.rename_axis("sleep_id")
+ obs_sstats=obs_sstats.T.rename_axis("sleep_id")
+ # Convert to MultiIndex with new scorer level
+ ref_sstats=pd.concat({self.ref_scorer:ref_sstats},names=["scorer"])
+ obs_sstats=pd.concat({self.obs_scorer:obs_sstats},names=["scorer"])
+ # Concatenate into one DataFrame
+ sstats=pd.concat([ref_sstats,obs_sstats])
+ # Remove the MultiIndex if just one session being evaluated
+ ifself.n_sleeps==1:
+ sstats=sstats.reset_index(level=1,drop=True)
+ returnsstats
+
+
[docs]defplot_hypnograms(self,sleep_id=None,legend=True,ax=None,ref_kwargs={},obs_kwargs={}):
+ """Plot the two hypnograms of one session overlapping on the same axis.
+
+ .. seealso:: :py:func:`yasa.plot_hypnogram`
+
+ Parameters
+ ----------
+ self : :py:class:`yasa.EpochByEpochAgreement`
+ A :py:class:`yasa.EpochByEpochAgreement` instance.
+ sleep_id : a valid sleep ID or None
+ The sleep session to plot. If multiple sessions are included in the
+ :py:class:`~yasa.EpochByEpochAgreement` instance, a ``sleep_id`` must be provided. If
+ only one session is present, ``None`` (default) will plot the two hypnograms of the
+ only session.
+ legend : bool or dict
+ If True (default) or a dictionary, a legend is added. If a dictionary, all key/value
+ pairs are passed as keyword arguments to the :py:func:`matplotlib.pyplot.legend` call.
+ ax : :py:class:`matplotlib.axes.Axes` or None
+ Axis on which to draw the plot, optional.
+ ref_kwargs : dict
+ Keyword arguments passed to :py:func:`yasa.plot_hypnogram` when plotting the reference
+ hypnogram.
+ obs_kwargs : dict
+ Keyword arguments passed to :py:func:`yasa.plot_hypnogram` when plotting the observed
+ hypnogram.
+
+ Returns
+ -------
+ ax : :py:class:`matplotlib.axes.Axes`
+ Matplotlib Axes
+
+ Examples
+ --------
+ .. plot::
+
+ >>> from yasa import simulate_hypnogram
+ >>> hyp = simulate_hypnogram(scorer="Anthony", seed=19)
+ >>> ax = hyp.evaluate(hyp.simulate_similar(scorer="Alan", seed=68)).plot_hypnograms()
+ """
+ assert(
+ sleep_idisNoneorsleep_idinself._sleep_ids
+ ),"`sleep_id` must be None or a valid sleep ID"
+ assertisinstance(legend,(bool,dict)),"`legend` must be True, False, or a dictionary"
+ assertisinstance(ref_kwargs,dict),"`ref_kwargs` must be a dictionary"
+ assertisinstance(obs_kwargs,dict),"`obs_kwargs` must be a dictionary"
+ assert(
+ "ax"notinref_kwargs|obs_kwargs
+ ),"'ax' can't be supplied to `ref_kwargs` or `obs_kwargs`, use the `ax` keyword instead"
+ assertnot(sleep_idisNoneandself.n_sleeps>1),(
+ "Multi-session plotting is not currently supported. `sleep_id` must not be None when "
+ "multiple sessions are present"
+ )
+ # Select the session hypnograms to plot
+ ifsleep_idisNoneandself.n_sleeps==1:
+ ref_hyp=self._ref_hyps[self._sleep_ids[0]]
+ obs_hyp=self._obs_hyps[self._sleep_ids[0]]
+ else:
+ ref_hyp=self._ref_hyps[sleep_id]
+ obs_hyp=self._obs_hyps[sleep_id]
+ # Set default plotting kwargs and merge with user kwargs
+ plot_ref_kwargs={
+ "label":self.ref_scorer,
+ "highlight":None,
+ "color":"black",
+ "alpha":0.8,
+ }
+ plot_obs_kwargs={
+ "label":self.obs_scorer,
+ "highlight":None,
+ "color":"green",
+ "alpha":0.8,
+ "ls":"dashed",
+ }
+ plot_ref_kwargs.update(ref_kwargs)
+ plot_obs_kwargs.update(obs_kwargs)
+ # Draw the hypnograms
+ ax=ref_hyp.plot_hypnogram(ax=ax,**plot_ref_kwargs)
+ ax=obs_hyp.plot_hypnogram(ax=ax,**plot_obs_kwargs)
+ # Add legend if desired
+ iflegend:
+ ifisinstance(legend,dict):
+ ax.legend(**legend)
+ else:
+ ax.legend()
+ returnax
+
+
[docs]defsummary(self,by_stage=False,**kwargs):
+ """Return group-level agreement scores.
+
+ Default aggregated measures are
+
+ Parameters
+ ----------
+ self : :py:class:`~yasa.evaluation.EpochByEpochAgreement`
+ A :py:class:`~yasa.evaluation.EpochByEpochAgreement` instance.
+ by_stage : bool
+ If ``False`` (default), ``summary`` will include agreement scores derived from
+ average-based metrics. If ``True``, returned ``summary`` :py:class:`~pandas.DataFrame`
+ will include agreement scores for each sleep stage, derived from one-vs-rest metrics.
+ **kwargs : key, value pairs
+ Additional keyword arguments are passed to :py:meth:`pandas.DataFrame.groupby.agg`.
+ This can be used to customize the descriptive statistics returned.
+
+ Returns
+ -------
+ summary : :py:class:`pandas.DataFrame`
+ A :py:class:`pandas.DataFrame` summarizing agreement scores across the entire dataset
+ with descriptive statistics.
+
+ >>> ebe = yasa.EpochByEpochAgreement(...)
+ >>> agreement = ebe.get_agreement()
+ >>> ebe.summary()
+
+ This will give a :py:class:`~pandas.DataFrame` where each row is an agreement metric and
+ each column is a descriptive statistic (e.g., mean, standard deviation).
+ To control the descriptive statistics included as columns:
+
+ >>> ebe.summary(func=["count", "mean", "sem"])
+ """
+ assertself.n_sleeps>1,"Summary scores can not be computed with only one hypnogram pair."
+ assertisinstance(by_stage,bool),"`by_stage` must be True or False"
+ ifby_stage:
+ asserthasattr(
+ self,"_agreement_bystage"
+ ),"Must run `self.get_agreement_bystage` before obtaining by_stage summary results."
+ else:
+ asserthasattr(
+ self,"_agreement"
+ ),"Must run `self.get_agreement` before obtaining summary results."
+
+ # Create a function for getting mean absolute deviation
+ defmad(df):
+ return(df-df.mean()).abs().mean()
+
+ # Merge default and user kwargs
+ agg_kwargs={"func":[mad,"mean","std","min","median","max"]}|kwargs
+ ifby_stage:
+ summary=(
+ self.agreement_bystage.groupby("stage")
+ .agg(**agg_kwargs)
+ .stack(level=0)
+ .rename_axis(["stage","metric"])
+ )
+ else:
+ summary=self._agreement.agg(**agg_kwargs).T.rename_axis("metric")
+ returnsummary
[docs]classSleepStatsAgreement:
+ """
+ Evaluate agreement between sleep statistics reported by two different scorers.
+ Evaluation includes bias and limits of agreement (as well as both their confidence intervals),
+ various plotting options, and calibration functions for correcting biased values from the
+ observed scorer.
+
+ Features include:
+ * Get summary calculations of bias, limits of agreement, and their confidence intervals.
+ * Test statistical assumptions of bias, limits of agreement, and their confidence intervals,
+ and apply corrective procedures when the assumptions are not met.
+ * Get bias and limits of agreement in a string-formatted table.
+ * Calibrate new data to correct for biases in observed data.
+ * Return individual calibration functions.
+ * Visualize discrepancies for outlier inspection.
+ * Visualize Bland-Altman plots.
+
+ .. seealso:: :py:meth:`yasa.Hypnogram.sleep_statistics`
+
+ .. versionadded:: 0.7.0
+
+ Parameters
+ ----------
+ ref_data : :py:class:`pandas.DataFrame`
+ A :py:class:`pandas.DataFrame` with sleep statistics from the reference scorer.
+ Rows are unique observations and columns are unique sleep statistics.
+ obs_data : :py:class:`pandas.DataFrame`
+ A :py:class:`pandas.DataFrame` with sleep statistics from the observed scorer.
+ Rows are unique observations and columns are unique sleep statistics.
+ Shape, index, and columns must be identical to ``ref_data``.
+ ref_scorer : str
+ Name of the reference scorer.
+ obs_scorer : str
+ Name of the observed scorer.
+ agreement : float
+ Multiple of the standard deviation to plot agreement limits. The default is 1.96, which
+ corresponds to a 95% confidence interval if the differences are normally distributed.
+
+ .. note:: ``agreement`` gets adjusted for regression-modeled limits of agreement.
+ confidence : float
+ The percentage confidence interval for the confidence intervals that are applied to bias and
+ limits of agreement. The same confidence interval percentage is applied to both standard and
+ bootstrapped confidence intervals.
+ alpha : float
+ Alpha cutoff used for all assumption tests.
+ verbose : bool or str
+ Verbose level. Default (False) will only print warning and error messages. The logging
+ levels are 'debug', 'info', 'warning', 'error', and 'critical'. For most users the choice is
+ between 'info' (or ``verbose=True``) and warning (``verbose=False``).
+
+ Notes
+ -----
+ Sleep statistics that are identical between scorers are removed from analysis.
+
+ Many steps here are influenced by guidelines proposed in Menghini et al., 2021 [Menghini2021]_.
+ See https://sri-human-sleep.github.io/sleep-trackers-performance/AnalyticalPipeline_v1.0.0.html
+
+ References
+ ----------
+ .. [Menghini2021] Menghini, L., Cellini, N., Goldstone, A., Baker, F. C., & de Zambotti, M.
+ (2021). A standardized framework for testing the performance of sleep-tracking
+ technology: step-by-step guidelines and open-source code. SLEEP, 44(2),
+ zsaa170. https://doi.org/10.1093/sleep/zsaa170
+
+ Examples
+ --------
+ >>> import pandas as pd
+ >>> import yasa
+ >>>
+ >>> # Generate fake reference and observed datasets with similar sleep statistics
+ >>> ref_scorer = "Henri"
+ >>> obs_scorer = "Piéron"
+ >>> ref_hyps = [yasa.simulate_hypnogram(tib=600, scorer=ref_scorer, seed=i) for i in range(20)]
+ >>> obs_hyps = [h.simulate_similar(scorer=obs_scorer, seed=i) for i, h in enumerate(ref_hyps)]
+ >>> # Generate sleep statistics from hypnograms using EpochByEpochAgreement
+ >>> eea = yasa.EpochByEpochAgreement(ref_hyps, obs_hyps)
+ >>> sstats = eea.get_sleep_stats()
+ >>> ref_sstats = sstats.loc[ref_scorer]
+ >>> obs_sstats = sstats.loc[obs_scorer]
+ >>> # Create SleepStatsAgreement instance
+ >>> ssa = yasa.SleepStatsAgreement(ref_sstats, obs_sstats)
+ >>> ssa.summary().round(1).head(3)
+ variable bias_intercept ... uloa_parm
+ interval center lower upper ... center lower upper
+ sleep_stat ...
+ %N1 -5.4 -13.9 3.2 ... 6.1 3.7 8.5
+ %N2 -27.3 -49.1 -5.6 ... 12.4 7.2 17.6
+ %N3 -9.1 -23.8 5.5 ... 20.4 12.6 28.3
+
+ >>> ssa.get_table().head(3)[["bias", "loa"]]
+ bias loa
+ sleep_stat
+ %N1 0.25 Bias ± 2.46 * (-0.00 + 1.00x)
+ %N2 -27.34 + 0.55x Bias ± 2.46 * (0.00 + 1.00x)
+ %N3 1.38 Bias ± 2.46 * (0.00 + 1.00x)
+
+ >>> ssa.assumptions.head(3)
+ unbiased normal constant_bias homoscedastic
+ sleep_stat
+ %N1 True True True False
+ %N2 True True False False
+ %N3 True True True False
+
+ >>> ssa.auto_methods.head(3)
+ bias loa ci
+ sleep_stat
+ %N1 parm regr parm
+ %N2 regr regr parm
+ %N3 parm regr parm
+
+ >>> ssa.get_table(bias_method="parm", loa_method="parm").head(3)[["bias", "loa"]]
+ bias loa
+ sleep_stat
+ %N1 0.25 -5.55, 6.06
+ %N2 -0.23 -12.87, 12.40
+ %N3 1.38 -17.67, 20.44
+
+ >>> new_hyps = [h.simulate_similar(scorer="Kelly", seed=i) for i, h in enumerate(obs_hyps)]
+ >>> new_sstats = pd.Series(new_hyps).map(lambda h: h.sleep_statistics()).apply(pd.Series)
+ >>> new_sstats = new_sstats[["N1", "TST", "WASO"]]
+ >>> new_sstats.round(1).head(5)
+ N1 TST WASO
+ 0 42.5 439.5 147.5
+ 1 84.0 550.0 38.5
+ 2 53.5 489.0 103.0
+ 3 57.0 469.5 120.0
+ 4 71.0 531.0 69.0
+
+ >>> new_stats_calibrated = ssa.calibrate_stats(new_sstats, bias_method="auto")
+ >>> new_stats_calibrated.round(1).head(5)
+ N1 TST WASO
+ 0 42.9 433.8 150.0
+ 1 84.4 544.2 41.0
+ 2 53.9 483.2 105.5
+ 3 57.4 463.8 122.5
+ 4 71.4 525.2 71.5
+
+ .. plot::
+
+ >>> import matplotlib.pyplot as plt
+ >>> ax = ssa.plot_discrepancies_heatmap()
+ >>> ax.set_title("Sleep statistic discrepancies")
+ >>> plt.tight_layout()
+
+ .. plot::
+
+ >>> ssa.plot_blandaltman()
+ """
+
+
[docs]def__init__(
+ self,
+ ref_data,
+ obs_data,
+ *,
+ ref_scorer="Reference",
+ obs_scorer="Observed",
+ agreement=1.96,
+ confidence=0.95,
+ alpha=0.05,
+ verbose=True,
+ bootstrap_kwargs={},
+ ):
+
+ restricted_bootstrap_kwargs=["confidence_level","vectorized","paired"]
+
+ assertisinstance(ref_data,pd.DataFrame),"`ref_data` must be a pandas DataFrame"
+ assertisinstance(obs_data,pd.DataFrame),"`obs_data` must be a pandas DataFrame"
+ assertnp.array_equal(
+ ref_data.index,obs_data.index
+ ),"`ref_data` and `obs_data` index values must be identical"
+ assert(
+ ref_data.index.name==obs_data.index.name
+ ),"`ref_data` and `obs_data` index names must be identical"
+ assertnp.array_equal(
+ ref_data.columns,obs_data.columns
+ ),"`ref_data` and `obs_data` column values must be identical"
+ assertisinstance(ref_scorer,str),"`ref_scorer` must be a string"
+ assertisinstance(obs_scorer,str),"`obs_scorer` must be a string"
+ assertref_scorer!=obs_scorer,"`ref_scorer` and `obs_scorer` must be unique"
+ assert(
+ isinstance(agreement,(float,int))andagreement>0
+ ),"`agreement` must be a number greater than 0"
+ assert(
+ isinstance(confidence,(float,int))and0<alpha<1
+ ),"`confidence` must be a number between 0 and 1"
+ assert(
+ isinstance(alpha,(float,int))and0<=alpha<=1
+ ),"`alpha` must be a number between 0 and 1 inclusive"
+ assertisinstance(bootstrap_kwargs,dict),"`bootstrap_kwargs` must be a dictionary"
+ assertall(
+ knotinrestricted_bootstrap_kwargsforkinbootstrap_kwargs
+ ),f"None of {restricted_bootstrap_kwargs} can be set by the user"
+
+ # If `ref_data` and `obs_data` indices are unnamed, name them
+ session_key="session_id"ifref_data.index.nameisNoneelseref_data.index.name
+ ref_data.index.name=obs_data.index.name=session_key
+
+ # Reshape to long format DataFrame with 2 columns (observed, reference) and MultiIndex
+ data=(
+ pd.concat([obs_data,ref_data],keys=[obs_scorer,ref_scorer],names=["scorer"])
+ .melt(var_name="sleep_stat",ignore_index=False)
+ .pivot_table(index=["sleep_stat",session_key],columns="scorer",values="value")
+ .rename_axis(columns=None)
+ .sort_index()
+ )
+
+ # Get scorer differences (i.e., observed minus reference)
+ data["difference"]=data[obs_scorer]-data[ref_scorer]
+
+ # Remove sleep statistics that have no differences between scorers
+ stats_rm=data.groupby("sleep_stat")["difference"].any().loc[lambdax:~x].index.tolist()
+ data=data.drop(labels=stats_rm)
+ forsinstats_rm:
+ logger.warning(f"Removed {s} from evaluation because all scorings were identical.")
+
+ # Create grouper and n_sessions variables for convenience
+ grouper=data.groupby("sleep_stat")
+ n_sessions=data.index.get_level_values(session_key).nunique()
+
+ ########################################################################
+ # Generate parametric Bias and LoA for all sleep stats
+ ########################################################################
+ # Parametric Bias
+ parm_vals=grouper["difference"].mean().to_frame("bias_parm")
+ # Parametric LoA
+ parm_vals["lloa_parm"],parm_vals["uloa_parm"]=zip(
+ *grouper["difference"].apply(self._arr_to_loa,agreement=agreement)
+ )
+
+ ########################################################################
+ # Generate standard CIs for parametric Bias and LoA for all sleep stats
+ ########################################################################
+ # Get critical t and standard error used to calculate parametric CIs for parametric Bias/LoA
+ t_parm=sps.t.ppf((1+confidence)/2,n_sessions-1)
+ sem=grouper["difference"].sem(ddof=1)
+ # Parametric CIs for parametric Bias and LoA
+ parm_ci=pd.DataFrame(
+ {
+ "bias_parm-lower":parm_vals["bias_parm"]-sem*t_parm,
+ "bias_parm-upper":parm_vals["bias_parm"]+sem*t_parm,
+ "lloa_parm-lower":parm_vals["lloa_parm"]-sem*t_parm*np.sqrt(3),
+ "lloa_parm-upper":parm_vals["lloa_parm"]+sem*t_parm*np.sqrt(3),
+ "uloa_parm-lower":parm_vals["uloa_parm"]-sem*t_parm*np.sqrt(3),
+ "uloa_parm-upper":parm_vals["uloa_parm"]+sem*t_parm*np.sqrt(3),
+ }
+ )
+
+ ########################################################################
+ # Generate regression/modeled (slope and intercept) Bias and LoA for all sleep stats
+ ########################################################################
+ # Run regression used to (a) model bias and (b) test for proportional/constant bias
+ bias_regr=grouper[[ref_scorer,"difference"]].apply(self._linregr_dict).apply(pd.Series)
+ # Get absolute residuals from this regression bc they are used in the next regression
+ idx=data.index.get_level_values("sleep_stat")
+ slopes=bias_regr.loc[idx,"slope"].to_numpy()
+ intercepts=bias_regr.loc[idx,"intercept"].to_numpy()
+ predicted_values=data[ref_scorer].to_numpy()*slopes+intercepts
+ data["residuals"]=data[obs_scorer].to_numpy()-predicted_values
+ data["residuals_abs"]=data["residuals"].abs()
+ # Run regression used to (a) model LoA and (b) test for heteroscedasticity/homoscedasticity
+ loa_regr=grouper[[ref_scorer,"residuals_abs"]].apply(self._linregr_dict).apply(pd.Series)
+ # Stack the two regression dataframes together
+ regr=pd.concat({"bias":bias_regr,"loa":loa_regr},axis=0)
+
+ ########################################################################
+ # Generate parametric CIs for regression/modeled Bias and LoA for all sleep stats
+ ########################################################################
+ # Get critical t used used to calculate parametric CIs for regression Bias/LoA
+ t_regr=sps.t.ppf((1+confidence)/2,n_sessions-2)# dof=n-2 for regression
+ # Parametric CIs for modeled Bias and LoA
+ regr_ci=pd.DataFrame(
+ {
+ "intercept-lower":regr["intercept"]-regr["intercept_stderr"]*t_regr,
+ "intercept-upper":regr["intercept"]+regr["intercept_stderr"]*t_regr,
+ "slope-lower":regr["slope"]-regr["stderr"]*t_regr,
+ "slope-upper":regr["slope"]+regr["stderr"]*t_regr,
+ }
+ )
+
+ ########################################################################
+ # Test all statistical assumptions
+ ########################################################################
+ assumptions=pd.DataFrame(
+ {
+ "unbiased":(
+ grouper["difference"].apply(lambdaa:sps.ttest_1samp(a,0).pvalue).ge(alpha)
+ ),
+ "normal":grouper["difference"].apply(lambdaa:sps.shapiro(a).pvalue).ge(alpha),
+ "constant_bias":bias_regr["pvalue"].ge(alpha),
+ "homoscedastic":loa_regr["pvalue"].ge(alpha),
+ }
+ )
+
+ ########################################################################
+ # Setting attributes
+ ########################################################################
+
+ # Merge the parametric and regression values for Bias and LoA
+ regr_vals=regr.unstack(0)[["slope","intercept"]]
+ regr_vals.columns=regr_vals.columns.swaplevel().map("_".join)
+ vals=parm_vals.join(regr_vals).rename_axis("variable",axis=1)
+
+ # Merge the two CI dataframes for easier access
+ regr_ci=regr_ci.unstack(0)
+ regr_ci.columns=regr_ci.columns.swaplevel().map("_".join)
+ ci=parm_ci.join(regr_ci)
+ ci.columns=pd.MultiIndex.from_tuples(
+ tuples=ci.columns.str.split("-",expand=True),
+ names=["variable","interval"],
+ )
+ empty_df=pd.DataFrame().reindex_like(ci)
+ ci=pd.concat({"parm":ci,"boot":empty_df},names=["ci_method"],axis=1)
+ ci=ci.sort_index(axis=1)# Sort MultiIndex columns for cleanliness
+
+ # Set attributes
+ self._agreement=agreement
+ self._confidence=confidence
+ self._bootstrap_kwargs=bootstrap_kwargs
+ self._n_sessions=n_sessions
+ self._ref_scorer=ref_scorer
+ self._obs_scorer=obs_scorer
+ self._data=data
+ self._assumptions=assumptions
+ self._regr=regr
+ self._vals=vals
+ self._ci=ci
+ self._bias_method_opts=["parm","regr","auto"]
+ self._loa_method_opts=["parm","regr","auto"]
+ self._ci_method_opts=["parm","boot","auto"]
+
+ @property
+ defref_scorer(self):
+ """The name of the reference scorer."""
+ returnself._ref_scorer
+
+ @property
+ defobs_scorer(self):
+ """The name of the observed scorer."""
+ returnself._obs_scorer
+
+ @property
+ defn_sessions(self):
+ """The number of sessions."""
+ returnself._n_sessions
+
+ @property
+ defdata(self):
+ """A long-format :py:class:`pandas.DataFrame` containing all raw sleep statistics from
+ ``ref_data`` and ``obs_data``.
+ """
+ returnself._data.drop(columns=["difference","residuals","residuals_abs"])
+
+ @property
+ defsleep_statistics(self):
+ """Return a list of all sleep statistics included in the agreement analyses."""
+ returnself.data.index.get_level_values("sleep_stat").unique().to_list()
+
+ @property
+ defassumptions(self):
+ """A :py:class:`pandas.DataFrame` containing boolean values indicating the pass/fail status
+ of all statistical tests performed to test assumptions.
+ """
+ returnself._assumptions
+
+ @property
+ defauto_methods(self):
+ """
+ A :py:class:`pandas.DataFrame` containing the methods applied when ``'auto'`` is selected.
+ """
+ returnpd.concat(
+ [
+ self.assumptions["constant_bias"].map({True:"parm",False:"regr"}).rename("bias"),
+ self.assumptions["homoscedastic"].map({True:"parm",False:"regr"}).rename("loa"),
+ self.assumptions["normal"].map({True:"parm",False:"boot"}).rename("ci"),
+ ],
+ axis=1,
+ )
+
+ def__repr__(self):
+ # TODO v0.8: Keep only the text between < and >
+ return(
+ f"<SleepStatsAgreement | Observed scorer ('{self.obs_scorer}') evaluated against "
+ f"reference scorer ('{self.ref_scorer}'), {self.n_sessions} sleep sessions>\n"
+ " - Use `.summary()` to get a dataframe of bias and limits of agreement for each sleep "
+ "statistic\n"
+ " - Use `.plot_blandaltman()` to get a Bland-Altman-plot grid for sleep statistics\n"
+ "See the online documentation for more details."
+ )
+
+ def__str__(self):
+ returnself.__repr__()
+
+ ############################################################################
+ # Define some utility functions, mostly to aid with the use of df.apply and stats.bootstrap
+ ############################################################################
+
+ @staticmethod
+ def_arr_to_loa(x,agreement):
+ """Return a tuple with lower and upper limits of agreement."""
+ mean=np.mean(x)
+ bound=agreement*np.std(x,ddof=1)
+ returnmean-bound,mean+bound
+
+ @staticmethod
+ def_linregr_dict(*args,**kwargs):
+ """
+ A wrapper around :py:func:`scipy.stats.linregress` that returns a dictionary instead of a
+ named tuple. In the normally returned object, ``intercept_stderr`` is an extra field that is
+ not included when converting the named tuple, so this allows it to be included when using
+ something like groupby.
+ """
+ regr=sps.linregress(*args,**kwargs)
+ return{
+ "slope":regr.slope,
+ "intercept":regr.intercept,
+ "rvalue":regr.rvalue,
+ "pvalue":regr.pvalue,
+ "stderr":regr.stderr,
+ "intercept_stderr":regr.intercept_stderr,
+ }
+
+ def_generate_bootstrap_ci(self,sleep_stats):
+ """
+ Internal method to generate bootstrapped confidence intervals for bias and LoA.
+ This operates in-place by concatenating bootstrapped CIs to existing parametric CIs.
+ Note that parametric CIs are generated by default during init (bc they are quicker).
+
+ Parameters
+ ----------
+ sleep_stats : list
+ A list of sleep statistics to bootstrap confidence intervals for.
+ """
+ assertisinstance(sleep_stats,list),"`sleep_stats` must be a list"
+ assertlen(sleep_stats)==len(set(sleep_stats)),"elements of `sleep_stats` must be unique"
+ assertall(
+ isinstance(ss,str)forssinsleep_stats
+ ),"all elements of `sleep_stats` must be strings"
+ assertall(
+ ssinself.sleep_statisticsforssinsleep_stats
+ ),f"all elements of `sleep_stats` must be one of {self.sleep_statistics}"
+ # Update bootstrap keyword arguments with defaults
+ bs_kwargs={
+ "n_resamples":1000,
+ "method":"BCa",
+ "confidence_level":self._confidence,# should not change from parametric level
+ "vectorized":False,# should stay False, bc of how the custom get_vars function works
+ "paired":True,# should stay True, especially if method is BCa
+ }|self._bootstrap_kwargs
+
+ defget_vars(ref_arr,diff_arr,rabs_arr):
+ """A function to get all variables at once and avoid redundant stats.bootstrap calls."""
+ bias_parm=np.mean(diff_arr)
+ lloa_parm,uloa_parm=self._arr_to_loa(diff_arr,self._agreement)
+ bias_slope,bias_inter=sps.linregress(ref_arr,diff_arr)[:2]
+ # Note this is NOT recalculating residuals each time for the next regression
+ loa_slope,loa_inter=sps.linregress(ref_arr,rabs_arr)[:2]
+ returnbias_parm,lloa_parm,uloa_parm,bias_inter,bias_slope,loa_inter,loa_slope
+
+ # !! Column order MUST match the order of arrays boot_stats expects as INPUT
+ # !! Variable order MUST match the order of floats boot_stats returns as OUTPUT
+ interval_order=["lower","upper"]
+ column_order=["Reference","difference","residuals_abs"]
+ variable_order=[
+ "bias_parm",
+ "lloa_parm",
+ "uloa_parm",
+ "bias_intercept",
+ "bias_slope",
+ "loa_intercept",
+ "loa_slope",
+ ]
+ boot_ci=(
+ self._data.loc[
+ sleep_stats,column_order
+ ]# Extract the relevant sleep stats and columns
+ .groupby("sleep_stat")# Group so the bootstrapping is applied once to each sleep stat
+ # Apply the bootstrap function, where tuple(df.to_numpy().T) convert the 3 columns
+ # of the passed dataframe to a tuple of 3 1D arrays
+ .apply(lambdadf:sps.bootstrap(tuple(df.to_numpy().T),get_vars,**bs_kwargs))
+ .map(lambdares:res.confidence_interval)# Pull high/low CIs out of the results object
+ .explode()# Break high and low CIs into separate rows
+ .to_frame("value")# Convert to dataframe and name column
+ .assign(interval=interval_order*len(sleep_stats))# Add a column indicating interval
+ .explode("value")# Break low CI variables and high CI variables out of arrays
+ .assign(variable=variable_order*len(sleep_stats)*2)# Add column indicating variabl
+ .pivot(columns=["variable","interval"],values="value")# Go long to wide format
+ .sort_index(axis=1)# Sort MultiIndex columns for cleanliness
+ )
+ # Merge with existing CI dataframe
+ self._ci["boot"]=self._ci["boot"].fillna(boot_ci)
+
+
[docs]defget_table(self,bias_method="auto",loa_method="auto",ci_method="auto",fstrings={}):
+ """
+ Return a :py:class:`~pandas.DataFrame` with bias, loa, bias_ci, loa_ci as string equations.
+
+ Parameters
+ ----------
+ bias_method : str
+ If ``'parm'`` (i.e., parametric), bias is always represented as the mean difference
+ (observed minus reference).
+ If ``'regr'`` (i.e., regression), bias is always represented as a regression equation.
+ If ``'auto'`` (default), bias is represented as a regression equation for sleep
+ statistics where the score differences are proportionally biased and as the mean
+ difference otherwise.
+ loa_method : str
+ If ``'parm'`` (i.e., parametric), limits of agreement are always represented as
+ bias +/- 1.96 standard deviations (where 1.96 can be adjusted through the ``agreement``
+ parameter).
+ If ``'regr'`` (i.e., regression), limits of agreement are always represented as a
+ regression equation.
+ If ``'auto'`` (default), limits of agreement are represented as a regression equation
+ for sleep statistics where the score differences are proportionally biased and as
+ bias +/- 1.96 standard deviation otherwise.
+ ci_method : str
+ If ``'parm'`` (i.e., parametric), confidence intervals are always represented using a
+ standard t-distribution.
+ If ``'boot'`` (i.e., bootstrap), confidence intervals are always represented using a
+ bootstrap resampling procedure.
+ If ``'auto'`` (default), confidence intervals are represented using a bootstrap
+ resampling procedure for sleep statistics where the distribution of score differences is
+ non-normal and using a standard t-distribution otherwise.
+ fstrings : dict
+ Optional custom strings for formatting cells.
+
+ Returns
+ -------
+ table : :py:class:`pandas.DataFrame`
+ A :py:class:`~pandas.DataFrame` of string representations for bias, limits of agreement,
+ and their confidence intervals for all sleep statistics.
+ """
+ assertisinstance(bias_method,str),"`bias_method` must be a string"
+ assert(
+ bias_methodinself._bias_method_opts
+ ),f"`bias_method` must be one of {self._bias_method_opts}"
+ assertisinstance(loa_method,str),"`loa_method` must be a string"
+ assert(
+ loa_methodinself._loa_method_opts
+ ),f"`loa_method` must be one of {self._loa_method_opts}"
+ assertisinstance(fstrings,dict),"`fstrings` must be a dictionary"
+ # Agreement gets adjusted when LoA is modeled
+ loa_regr_agreement=self._agreement*np.sqrt(np.pi/2)
+ ifnotfstrings:
+ fstrings={
+ "bias_parm":"{bias_parm_center:.2f}",
+ "bias_regr":"{bias_intercept_center:.2f} + {bias_slope_center:.2f}x",
+ "loa_parm":"{lloa_parm_center:.2f}, {uloa_parm_center:.2f}",
+ "loa_regr":(
+ "Bias \u00B1{loa_regr_agreement:.2f} "
+ "* ({loa_intercept_center:.2f} + {loa_slope_center:.2f}x)"
+ ),
+ "bias_parm_ci":("[{bias_parm_lower:.2f}, {bias_parm_upper:.2f}]"),
+ "bias_regr_ci":(
+ "[{bias_intercept_lower:.2f}, {bias_intercept_upper:.2f}], "
+ "[{bias_slope_lower:.2f}, {bias_slope_upper:.2f}]"
+ ),
+ "loa_parm_ci":(
+ "[{lloa_parm_lower:.2f}, {lloa_parm_upper:.2f}], "
+ "[{uloa_parm_lower:.2f}, {uloa_parm_upper:.2f}]"
+ ),
+ "loa_regr_ci":(
+ "[{loa_intercept_lower:.2f}, {loa_intercept_upper:.2f}], "
+ "[{loa_slope_lower:.2f}, {loa_slope_upper:.2f}]"
+ ),
+ }
+ values=self.summary(ci_method=ci_method)
+ values.columns=values.columns.map("_".join)# Convert MultiIndex columns to Index
+ # Add a column of regr agreement so it can be used as variable
+ values["loa_regr_agreement"]=loa_regr_agreement
+
+ defformat_all_str(row,fstrings_dict):
+ return{var:fstr.format(**row)forvar,fstrinfstrings_dict.items()}
+
+ all_strings=values.apply(format_all_str,fstrings_dict=fstrings,axis=1).apply(pd.Series)
+ ifbias_method=="auto":
+ bias_parm_idx=self.auto_methods.query("bias == 'parm'").index.tolist()
+ elifbias_method=="parm":
+ bias_parm_idx=self.sleep_statistics
+ elifbias_method=="regr":
+ bias_parm_idx=[]
+ ifloa_method=="auto":
+ loa_parm_idx=self.auto_methods.query("loa == 'parm'").index.tolist()
+ elifloa_method=="parm":
+ loa_parm_idx=self.sleep_statistics
+ elifloa_method=="regr":
+ loa_parm_idx=[]
+ bias_regr_idx=[ssforssinself.sleep_statisticsifssnotinbias_parm_idx]
+ loa_regr_idx=[ssforssinself.sleep_statisticsifssnotinloa_parm_idx]
+ bias_parm=all_strings.loc[bias_parm_idx,["bias_parm","bias_parm_ci"]]
+ bias_regr=all_strings.loc[bias_regr_idx,["bias_regr","bias_regr_ci"]]
+ bias_parm.columns=bias_parm.columns.str.replace("_parm","")
+ bias_regr.columns=bias_parm.columns.str.replace("_regr","")
+ bias=pd.concat([bias_parm,bias_regr])
+ loa_parm=all_strings.loc[loa_parm_idx,["loa_parm","loa_parm_ci"]]
+ loa_regr=all_strings.loc[loa_regr_idx,["loa_regr","loa_regr_ci"]]
+ loa_parm.columns=loa_parm.columns.str.replace("_parm","")
+ loa_regr.columns=loa_regr.columns.str.replace("_regr","")
+ loa=pd.concat([loa_parm,loa_regr])
+ table=bias.join(loa,validate="1:1").sort_index(axis=0)
+ returntable
+
+
[docs]defsummary(self,ci_method="auto"):
+ """
+ Return a :py:class:`~pandas.DataFrame` that includes all calculated metrics:
+ * Parametric bias
+ * Parametric lower and upper limits of agreement
+ * Regression intercept and slope for modeled bias
+ * Regression intercept and slope for modeled limits of agreement
+ * Lower and upper confidence intervals for all metrics
+
+ Parameters
+ ----------
+ ci_method : str
+ If ``'parm'`` (i.e., parametric), confidence intervals are always represented using a
+ standard t-distribution.
+ If ``'boot'`` (i.e., bootstrap), confidence intervals are always represented using a
+ bootstrap resampling procedure.
+ If ``'auto'`` (default), confidence intervals are represented using a bootstrap
+ resampling procedure for sleep statistics where the distribution of score differences is
+ non-normal and using a standard t-distribution otherwise.
+
+ Returns
+ -------
+ summary : :py:class:`pandas.DataFrame`
+ A :py:class:`~pandas.DataFrame` of string representations for bias, limits of agreement,
+ and their confidence intervals for all sleep statistics.
+ """
+ assertisinstance(ci_method,str),"`ci_method` must be a string"
+ assertci_methodinself._ci_method_opts,f"`ci_method` must be in {self._ci_method_opts}"
+ # Make sure relevant sleep statistics have bootstrapped CIs, and generate them if not
+ ifci_methodin["boot","auto"]:
+ ifci_method=="boot":
+ sleep_stats_to_boot=self.sleep_statistics
+ elifci_method=="auto":
+ sleep_stats_to_boot=self.auto_methods.query("ci == 'boot'").index.tolist()
+ # Remove any sleep stats already bootstrapped CIs (eg if "boot" is callaed after "auto")
+ sleep_stats_booted=self._ci["boot"].dropna().index
+ sleep_stats_to_boot=[sforsinsleep_stats_to_bootifsnotinsleep_stats_booted]
+ ifsleep_stats_to_boot:
+ self._generate_bootstrap_ci(sleep_stats=sleep_stats_to_boot)
+ ifci_method=="auto":
+ parm_idx=self.auto_methods.query("ci == 'parm'").index.to_list()
+ boot_idx=[ssforssinself.sleep_statisticsifssnotinparm_idx]
+ parm_vals=self._ci.loc[parm_idx,"parm"]
+ boot_vals=self._ci.loc[boot_idx,"boot"]
+ ci_vals=pd.concat([parm_vals,boot_vals])
+ else:
+ ci_vals=self._ci[ci_method]
+ # Add an extra level to values columns, indicating they are the center interval
+ centr_vals=pd.concat({"center":self._vals},names=["interval"],axis=1).swaplevel(axis=1)
+ summary=centr_vals.join(ci_vals,how="left",validate="1:1").astype(float)
+ returnsummary.sort_index(axis=1)
+
+
[docs]defcalibrate(self,data,bias_method="auto",adjust_all=False):
+ """
+ Calibrate a :py:class:`~pandas.DataFrame` of sleep statistics from a new scorer based on
+ observed biases in ``obs_data``/``obs_scorer``.
+
+ Parameters
+ ----------
+ data : :py:class:`pandas.DataFrame`
+ A :py:class:`pandas.DataFrame` with sleep statistics from an observed scorer.
+ Rows are unique observations and columns are unique sleep statistics.
+ bias_method : str
+ If ``'parm'``, sleep statistics are always adjusted based on parametric bias.
+ If ``'regr'``, sleep statistics are always adjusted based on regression-modeled bias.
+ If ``'auto'`` (default), bias sleep statistics are adjusted by either ``'parm'`` or
+ ``'regr'``, depending on assumption violations.
+
+ .. seealso:: :py:meth:`~yasa.SleepStatsAgreement.summary`
+
+ adjust_all: bool
+ If False (default), only adjust values for sleep statistics that showed a statistically
+ significant bias in the ``obs_data``. If True, adjust values for all sleep statistics.
+
+ Returns
+ -------
+ calibrated_data : :py:class:`pandas.DataFrame`
+ A :py:class:`~pandas.DataFrame` with calibrated sleep statistics.
+
+ .. seealso:: :py:meth:`~yasa.SleepStatsAgreement.calibrate`
+ """
+ assertisinstance(data,pd.DataFrame),"`data` must be a pandas DataFrame"
+ assertall(
+ colinself.sleep_statisticsforcolindata
+ ),f"all columns of `data` must be valid sleep statistics: {self.sleep_statistics}"
+ assertisinstance(bias_method,str),"`bias_method` must be a string"
+ assert(
+ bias_methodinself._bias_method_opts
+ ),f"`bias_method` must be one of {self._bias_method_opts}"
+ assertisinstance(adjust_all,bool),"`adjust_all` must be True or False"
+ parm_adjusted=data+self._vals["bias_parm"]
+ regr_adjusted=data*self._vals["bias_slope"]+self._vals["bias_intercept"]
+ ifbias_method=="parm":
+ calibrated_data=parm_adjusted
+ elifbias_method=="regr":
+ calibrated_data=regr_adjusted
+ elifbias_method=="auto":
+ parm_idx=self.auto_methods.query("bias == 'parm'").index.to_list()
+ regr_idx=[ssforssinself.sleep_statisticsifssnotinparm_idx]
+ calibrated_data=parm_adjusted[parm_idx].join(regr_adjusted[regr_idx]).dropna(axis=1)
+ ifnotadjust_all:
+ # Put the raw values back for sleep stats that don't show statistical bias
+ unbiased_sstats=self.assumptions.query("unbiased == True").index.to_list()
+ calibrated_data[unbiased_sstats]=data[unbiased_sstats]
+ returncalibrated_data
+
+
[docs]defget_calibration_func(self,sleep_stat):
+ """
+ Return a function for calibrating a specific sleep statistic, based on observed biases in
+ ``obs_data``/``obs_scorer``.
+
+ .. seealso:: :py:meth:`~yasa.SleepStatsAgreement.calibrate`
+
+ Examples
+ --------
+ >>> ssa = yasa.SleepStatsAgreement(...)
+ >>> calibrate_rem = ssa.get_calibration_func("REM")
+ >>> new_obs_rem_vals = np.array([50, 40, 30, 20])
+ >>> calibrate_rem(new_obs_rem_vals)
+ >>> calibrate_rem(new_obs_rem_vals)
+ array([50, 40, 30, 20])
+ >>> calibrate_rem(new_obs_rem_vals, bias_test=False)
+ array([42.825, 32.825, 22.825, 12.825])
+ >>> calibrate_rem(new_obs_rem_vals, bias_test=False, method="regr")
+ array([ -9.33878878, -9.86815607, -10.39752335, -10.92689064])
+ """
+ assertisinstance(sleep_stat,str),"`sleep_stat` must be a string"
+ assertsleep_statinself.sleep_statistics,"`sleep_stat` must be a valid sleep statistic"
+ columns=["bias_parm","bias_slope","bias_intercept"]
+ parm,slope,intercept=self._vals.loc[sleep_stat,columns]
+ auto_method=self.auto_methods.at[sleep_stat,"bias"]
+ not_biased=self.assumptions.at[sleep_stat,"unbiased"]
+
+ defcalibration_func(x,method="auto",adjust_all=False):
+ """Calibrate values for sleep statistic.
+
+ Parameters
+ ----------
+ x : array
+ Values to be calibrated
+ method: str
+ Method of bias calculation for calibration (``'parm'``, ``'regr'``, or ``'auto'``).
+ adjust_all : bool
+ If False, only adjust sleep stat if observed bias was statistically significant.
+
+ Returns
+ -------
+ x_calibrated : :py:class:`numpy.array`
+ An array of calibrated x values.
+ """
+ x=np.asarray(x)
+ method=auto_methodifmethod=="auto"elsemethod
+ ifnot_biasedandnotadjust_all:# Return input if sleep stat is not statstclly biased
+ returnx
+ elifmethod=="parm":
+ returnx+parm
+ elifmethod=="regr":
+ returnx*slope+intercept
+
+ returncalibration_func
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/build/html/_modules/yasa/heart.html b/docs/build/html/_modules/yasa/heart.html
index 25a9297..23f0386 100644
--- a/docs/build/html/_modules/yasa/heart.html
+++ b/docs/build/html/_modules/yasa/heart.html
@@ -4,7 +4,7 @@
- yasa.heart — yasa 0.6.4 documentation
+ yasa.heart — yasa 0.6.5 documentation
@@ -43,7 +43,7 @@
yasa
- 0.6.4
+ 0.6.5
[docs]defplot_hypnogram(hyp,sf_hypno=1/30,highlight="REM",fill_color=None,ax=None,**kwargs):""" Plot a hypnogram.
@@ -116,16 +117,32 @@
Source code for yasa.plotting
Parameters ----------
- hyp : :py:class:`yasa.Hypnogram`
- A YASA hypnogram instance.
- lw : float
- Linewidth.
+ hyp : :py:class:`yasa.Hypnogram` or array_like
+ A YASA hypnogram instance, or a 1D integer array where:
+
+ * -2 = Unscored
+ * -1 = Artefact / Movement
+ * 0 = Wake
+ * 1 = N1 sleep
+ * 2 = N2 sleep
+ * 3 = N3 sleep
+ * 4 = REM sleep
+ sf_hypno : float
+ The current sampling frequency of the hypnogram, in Hz, e.g.
+
+ * 1/30 = 1 value per each 30 seconds of EEG data,
+ * 1 = 1 value per second of EEG data
+
+ This has no impact if `hyp` is a :py:class:`yasa.Hypnogram`. highlight : str or None Optional stage to highlight with alternate color. fill_color : str or None Optional color to fill space above hypnogram line. ax : :py:class:`matplotlib.axes.Axes` Axis on which to draw the plot, optional.
+ **kwargs : dict
+ Keyword arguments controlling hypnogram line display (e.g., ``lw``, ``linestyle``).
+ Passed to :py:func:`matplotlib.pyplot.stairs` and py:func:`matplotlib.pyplot.hlines`. Returns -------
@@ -160,9 +177,13 @@
Source code for yasa.plotting
>>> hyp_a.plot_hypnogram(lw=1, fill_color="whitesmoke", highlight=None, ax=axes[0]) >>> hyp_b.plot_hypnogram(lw=1, fill_color="whitesmoke", highlight=None, ax=axes[1]) """
- fromyasa.hypnoimportHypnogram# Avoiding circular import
+ fromyasa.hypnoimportHypnogram,hypno_int_to_str# Avoiding circular imports
- assertisinstance(hyp,Hypnogram),"`hypno` must be YASA Hypnogram."
+ ifnotisinstance(hyp,Hypnogram):
+ # Convert sampling frequency to pandas timefrequency string (e.g., "30s")
+ freq_str=pd.tseries.frequencies.to_offset(pd.Timedelta(1/sf_hypno,"S")).freqstr
+ # Create Hypnogram instance for plotting
+ hyp=Hypnogram(hypno_int_to_str(hyp),freq=freq_str)# Work with a copy of the Hypnogram to not alter the originalhyp=hyp.copy()
@@ -171,20 +192,25 @@
Source code for yasa.plotting
old_fontsize=plt.rcParams["font.size"]plt.rcParams.update({"font.size":18})
+ # Open the figure
+ ifaxisNone:
+ ax=plt.gca()
+
## Remap stages to be in desired y-axis order ### Start with default of all allowed labelsstage_order=hyp.labels.copy()
- stages_present=hyp.hypno.unique()
- # Remove Art/Uns from stage order, and place back individually at front to be higher on plot
- art_str=stage_order.pop(stage_order.index("ART"))
- uns_str=stage_order.pop(stage_order.index("UNS"))
- if"ART"instages_present:
- stage_order.insert(0,art_str)
- if"UNS"instages_present:
- stage_order.insert(0,uns_str)
+ stages_present=hyp.hypno.unique().tolist()
+ # Reverse order so WAKE is highest, and exclude ART/UNS which are always last
+ stage_order=stage_order[:-2][::-1]
+ # Add ART/UNS back above WAKE if they're present in the current hypnogram or existing axis
+ gca_ylabels=[x.get_text()forxinax.get_yticklabels()]
+ if"ART"instages_presentor"ART"ingca_ylabels:
+ stage_order+=["ART"]
+ if"UNS"instages_presentor"UNS"ingca_ylabels:
+ stage_order+=["UNS"]# Put REM after WAKE if all 5 standard stages are allowedifhyp.n_stages==5:
- stage_order.insert(stage_order.index("WAKE")+1,stage_order.pop(stage_order.index("REM")))
+ stage_order.insert(stage_order.index("WAKE")-1,stage_order.pop(stage_order.index("REM")))# Reset the Hypnogram mapping so any future returns have this orderhyp.mapping={stage:ifori,stageinenumerate(stage_order)}
@@ -208,18 +234,17 @@
Source code for yasa.plotting
# Make mask to draw the highlighted stageyvals_highlight=np.ma.masked_not_equal(yvalues,hyp.mapping.get(highlight))
- # Open the figure
- ifaxisNone:
- ax=plt.gca()
-
# Draw background fillingiffill_colorisnotNone:
- bline=hyp.mapping["WAKE"]# len(stage_order) - 1 to fill from bottom
- ax.stairs(yvalues.clip(bline),bins,baseline=bline,color=fill_color,fill=True,lw=0)
- # Draw main hypnogram line, highlighted stage line, and Artefact/Unscored line
- ax.stairs(yvalues,bins,baseline=None,color="black",lw=lw)
+ bline=hyp.mapping["WAKE"]
+ ax.stairs(yvalues.clip(max=bline),bins,baseline=bline,color=fill_color,fill=True,lw=0)
+ # Draw main hypnogram line and highlighted stage line
+ line_kwargs={"color":"black","linewidth":1.5,"label":hyp.scorer}
+ line_kwargs.update(kwargs)
+ ax.stairs(yvalues,bins,baseline=None,**line_kwargs)ifnotyvals_highlight.mask.all():
- ax.hlines(yvals_highlight,xmin=bins[:-1],xmax=bins[1:],color="red",lw=lw)
+ line_kwargs.update({"color":"red","label":None})
+ ax.hlines(yvals_highlight,xmin=bins[:-1],xmax=bins[1:],**line_kwargs)# Aestheticsax.use_sticky_edges=False
@@ -228,7 +253,6 @@
This file contains several helper functions to calculate spectral power from1D and 2D EEG data."""
+
importmneimportloggingimportnumpyasnpimportpandasaspdfromscipyimportsignal
-fromscipy.integrateimportsimps
+fromscipy.integrateimportsimpsonfromscipy.interpolateimportRectBivariateSplinefrom.ioimportset_log_level
@@ -326,7 +327,7 @@
Source code for yasa.spectral
ch_names=["CHAN"+str(i).zfill(3)foriinrange(nchan)]bp=np.zeros((nchan,len(bands)),dtype=np.float64)psd=psd[:,idx_good_freq]
- total_power=simps(psd,dx=res)
+ total_power=simpson(psd,dx=res)total_power=total_power[...,np.newaxis]# Check if there are negative values in PSD
@@ -345,7 +346,7 @@
ch_names=ch_names[keep_chan].tolist()ch_types=ch_types[keep_chan].tolist()# Keep only selected channels (creating a copy of Raw)
- raw_pick=raw.copy().pick_channels(ch_names,ordered=True)
+ raw_pick=raw.copy().pick(ch_names)# Downsample if sf != 100assertsf>80,"Sampling frequency must be at least 80 Hz."
@@ -296,7 +297,12 @@
Source code for yasa.staging
# Extract duration of recording in minutesduration_minutes=data.shape[1]/sf/60
- assertduration_minutes>=5,"At least 5 minutes of data is required."
+ ifduration_minutes<5:
+ msg=(
+ "Insufficient data. A minimum of 5 minutes of data is recommended "
+ "otherwise results may be unreliable."
+ )
+ logger.warning(msg)# Add to selfself.sf=sf
diff --git a/docs/build/html/_static/documentation_options.js b/docs/build/html/_static/documentation_options.js
index 55a69e0..ccfea1c 100644
--- a/docs/build/html/_static/documentation_options.js
+++ b/docs/build/html/_static/documentation_options.js
@@ -1,6 +1,6 @@
var DOCUMENTATION_OPTIONS = {
URL_ROOT: document.getElementById("documentation_options").getAttribute('data-url_root'),
- VERSION: '0.6.4',
+ VERSION: '0.6.5',
LANGUAGE: 'None',
COLLAPSE_INDEX: false,
BUILDER: 'html',
diff --git a/docs/build/html/api.html b/docs/build/html/api.html
index 16e1e4b..5fb84a2 100644
--- a/docs/build/html/api.html
+++ b/docs/build/html/api.html
@@ -5,7 +5,7 @@
- API reference — yasa 0.6.4 documentation
+ API reference — yasa 0.6.5 documentation
@@ -44,7 +44,7 @@
yasa
- 0.6.4
+ 0.6.5
Added the ax keyword-argument to yasa.plot_hypnogram() and removed figsize. Now select figure aesthetics (e.g., size, dpi) by opening a matplotlib.axes.Axes instance and passing to ax. PR 108
Added the ax keyword-argument to yasa.plot_hypnogram() and removed figsize. Now select figure aesthetics (e.g., size, dpi) by opening a matplotlib.axes.Axes instance and passing to ax. PR 108
Added the yasa.hypno_find_periods() function to find sequences of consecutive values in hypnogram that are longer than a certain duration. This is a flexible function that can be used to detect NREM/REM periods.
This release fixes a CRITICAL BUG with the spindles detection. Specifically, the yasa.spindles_detect() could return different results depending on the sampling rate of the data.
For example, downsampling the data from 256 Hz to 128 Hz may have significantly reduced the number of detected spindles. As explained in issue 54, this bug was caused by a floating-point error
-in numpy.convolve() when calculating the soft spindle threshold. Tests seem to indicate that only certain sampling frequencies were impacted, such as 200 Hz, 256 Hz or 400 Hz. Other sampling frequencies such as 100 Hz and 500 Hz were seemingly not affected by this bug. Please double-check any results obtained with yasa.spindles_detect()!
+in numpy.convolve() when calculating the soft spindle threshold. Tests seem to indicate that only certain sampling frequencies were impacted, such as 200 Hz, 256 Hz or 400 Hz. Other sampling frequencies such as 100 Hz and 500 Hz were seemingly not affected by this bug. Please double-check any results obtained with yasa.spindles_detect()!
Warning
We recommend all users to upgrade to this new version ASAP and check any results obtained with the yasa.spindles_detect() function!
This is a bugfix release. The latest pre-trained classifiers for yasa.SleepStaging were accidentally missing from the previous release. They have now been included in this release.
This is a major release with an important bugfix for the slow-waves detection as well as API-breaking changes in the automatic sleep staging module. We recommend all users to upgrade to this version with pip install –upgrade yasa.
Slow-waves detection
We have fixed a critical bug in yasa.sw_detect() in which the detection could keep slow-waves with invalid duration (e.g. several tens of seconds). We have now added extra safety checks to make sure that the total duration of the slow-waves does not exceed the maximum duration allowed by the dur_neg and dur_pos parameters (default = 2.5 seconds).
This is a major release with several new functions, the biggest of which is the addition of an automatic sleep staging module (yasa.SleepStaging). This means that YASA can now automatically score the sleep stages of your raw EEG data. The classifier was trained and validated on more than 3000 nights from the National Sleep Research Resource (NSRR) website.
Briefly, the algorithm works by calculating a set of features for each 30-sec epochs from a central EEG channel (required), as well as an EOG channel (optional) and an EMG channel (optional). For best performance, users can also specify the age and the sex of the participants. Pre-trained classifiers are already included in YASA. The automatic sleep staging algorithm requires the LightGBM and antropy package.
This is a major release with several API-breaking changes in the spindles, slow-waves and REMs detection.
First, the yasa.spindles_detect_multi() and yasa.sw_detect_multi() have been removed. Instead, the yasa.spindles_detect() and yasa.sw_detect() functions can now handle both single and multi-channel data.
Second, I was getting some feedback that it was difficult to get summary statistics from the detection dataframe. For instance, how can you get the average duration of the detected spindles, per channel and/or per stage? Similarly, how can you get the slow-waves count and density per stage and channel? To address these issues, I’ve now modified the output of the yasa.spindles_detect(), yasa.sw_detect() and yasa.rem_detect() functions, which is now a class (= object) and not a simple Pandas DataFrame. The advantage is that the new output allows you to quickly get the raw data or summary statistics grouped by channel and/or sleep stage using the .summary() method.
The coupling argument has been removed from the yasa.spindles_detect() function. Instead, slow-oscillations / sigma coupling can only be calculated from the slow-waves detection, which is 1) the most standard way, 2) better because PAC assumptions require a strong oscillatory component in the lower frequency range (slow-oscillations). This also avoids unecessary confusion between spindles-derived coupling and slow-waves-derived coupling. For more details, refer to the Jupyter notebooks.
-
Downsampling of data in detection functions has been removed. In other words, YASA will no longer downsample the data to 100 / 128 Hz before applying the events detection. If the detection is too slow, we recommend that you manually downsample your data before applying the detection. See for example mne.filter.resample().
+
Downsampling of data in detection functions has been removed. In other words, YASA will no longer downsample the data to 100 / 128 Hz before applying the events detection. If the detection is too slow, we recommend that you manually downsample your data before applying the detection. See for example mne.filter.resample().
yasa.trimbothstd() can now work with multi-dimensional arrays. The trimmed standard deviation will always be calculated on the last axis of the array.
Filtering and Hilbert transform are now applied at once on all channels (instead of looping across individual channels) in the yasa.spindles_detect() and yasa.sw_detect() functions. This should lead to some improvements in computation time.
Sleep efficiency in the yasa.sleep_statistics() is now calculated using time in bed (TIB) as the denominator instead of sleep period time (SPT), in agreement with the AASM guidelines. The old way of computing the efficiency (TST / SPT) has now been renamed Sleep Maintenance Efficiency (SME).
-
The yasa.sliding_window() now always return an array of shape (n_epochs, …, n_samples), i.e. the epochs are now always the first dimension of the epoched array. This is consistent with MNE default shape of mne.Epochs objects.
+
The yasa.sliding_window() now always return an array of shape (n_epochs, …, n_samples), i.e. the epochs are now always the first dimension of the epoched array. This is consistent with MNE default shape of mne.Epochs objects.
Added the coupling and freq_sp keyword-arguments to the yasa.sw_detect() function. If coupling=True, the function will return the phase of the slow-waves (in radians) at the most prominent peak of sigma-filtered band (PhaseAtSigmaPeak), as well as the normalized mean vector length (ndPAC).
Added an section in the 06_sw_detection.ipynb notebooks on how to use relative amplitude thresholds (e.g. z-scores or percentiles) instead of absolute thresholds in slow-waves detection.
The upper frequency band for yasa.sw_detect() has been changed from freq_sw=(0.3,3.5) to freq_sw=(0.3,2) Hz to comply with AASM guidelines.
# Apply a bandpass filter from 0.1 to 40 Hzraw.filter(0.1,40)# Select a subset of EEG channels
-raw.pick_channels(['C4-A1','C3-A2'])
+raw.pick(['C4-A1','C3-A2'])
Evaluate agreement between two hypnograms or two collections of hypnograms.
+
Evaluation includes averaged agreement scores, one-vs-rest agreement scores, agreement scores
+summarized across all sleep and summarized by sleep stage, and various plotting options to
+visualize the two hypnograms simultaneously. See examples for more detail.
If a dict, key values are use to generate unique sleep session IDs. If any other
+iterable (e.g., list or tuple), then unique sleep session IDs are automatically
+generated.
A collection of observed hypnograms (i.e., those to be evaluated).
+
Each yasa.Hypnogram in obs_hyps must have the same
+scorer, and this scorer must be different than the scorer of
+hypnograms in ref_hyps.
+
If a dict, key values must match those of ref_hyps.
+
+
.. important::
It is assumed that the order of hypnograms are the same in ref_hyps and obs_hyps.
+For example, the third hypnogram in ref_hyps and obs_hyps must come from the same
+sleep session, and they must only differ in that they have different scorers.
+
+
.. seealso:: For comparing just two hypnograms, use :py:meth:`yasa.Hynogram.evaluate`.
Menghini, L., Cellini, N., Goldstone, A., Baker, F. C., & de Zambotti, M.
+(2021). A standardized framework for testing the performance of sleep-tracking
+technology: step-by-step guidelines and open-source code. SLEEP, 44(2),
+zsaa170. https://doi.org/10.1093/sleep/zsaa170
Sample weights passed to underlying sklearn.metrics functions where possible.
+If a pandas.Series, the index must match exactly that of
+data.
+
+
scorersNone, list, or dictionary
The scorers to be used for evaluating agreement. If None (default), default scorers are
+used. If a list, the list must contain strings that represent metrics from the sklearn
+metrics module (e.g., accuracy, precision). If more customization is desired, a
+dictionary can be passed with scorer names (str) as keys and custom functions as values.
+The custom functions should take 3 positional arguments (true values, predicted values,
+and sample weights).
If None (default), cross-tabulation is derived from the entire group dataset.
+If a valid sleep ID, cross-tabulation is derived using only the reference and observed
+scored hypnograms from that sleep session.
+
+
agg_funcNone or str
If None (default), group results returns a DataFrame complete with
+all individual session results. If not None, group results returns a
+DataFrame aggregated across sessions where agg_func is passed as
+func parameter in pandas.DataFrame.groupby.agg(). For example, set
+agg_func="sum" to get a single confusion matrix across all epochs that does not take
+session into account.
Compute multiple agreement scores from a 2-column dataframe (an optional 3rd column may
+contain sample weights).
+
This function offers convenience when calculating multiple agreement scores using
+pandas.DataFrame.groupby.apply(). Scikit-learn doesn’t include a function that
+returns multiple scores, and the GroupBy implementation of apply in pandas does not
+accept multiple functions.
A DataFrame with 2 columns and length of n_samples.
+The first column contains reference values and second column contains observed values.
+If a third column, it must contain sample weights to be passed to underlying
+sklearn.metrics functions as sample_weight where applicable.
+
+
scorersdictionary
The scorers to be used for evaluating agreement. A dictionary with scorer names (str) as
+keys and functions as values.
+
+
+
+
Returns
+
+
scoresdict
A dictionary with scorer names (str) as keys and scores (float) as values.
The sleep session to plot. If multiple sessions are included in the
+EpochByEpochAgreement instance, a sleep_id must be provided. If
+only one session is present, None (default) will plot the two hypnograms of the
+only session.
+
+
legendbool or dict
If True (default) or a dictionary, a legend is added. If a dictionary, all key/value
+pairs are passed as keyword arguments to the matplotlib.pyplot.legend() call.
If False (default), summary will include agreement scores derived from
+average-based metrics. If True, returned summaryDataFrame
+will include agreement scores for each sleep stage, derived from one-vs-rest metrics.
+
+
**kwargskey, value pairs
Additional keyword arguments are passed to pandas.DataFrame.groupby.agg().
+This can be used to customize the descriptive statistics returned.
This will give a DataFrame where each row is an agreement metric and
+each column is a descriptive statistic (e.g., mean, standard deviation).
+To control the descriptive statistics included as columns:
freq will be passed to the pandas.date_range() function to create the time
+
freq will be passed to the pandas.date_range() function to create the time
index of the hypnogram.
startstr or datetime
An optional string indicating the starting datetime of the hypnogram
(e.g. “2022-12-15 22:30:00”). If start is specified and valid, the index of the
-hypnogram will be a pandas.DatetimeIndex. Otherwise it will be a
-pandas.RangeIndex, indicating the epoch number.
An optional string indicating the scorer name. If specified, this will be set as the name
-of the pandas.Series, otherwise the name will be set to “Stage”.
+of the pandas.Series, otherwise the name will be set to “Stage”.
We can access the actual values, which are stored as a pandas.Series, with:
+
We can access the actual values, which are stored as a pandas.Series, with:
>>> hyp.hypnoEpoch0 WAKE
@@ -239,7 +239,7 @@
yasa.Hypnogramyasa.simulate_hypnogram() to generate a plausible 5-stages hypnogram with a
30-seconds resolution. A random seed is specified to ensure that we get reproducible results.
Lastly, we set an actual start time to the hypnogram. As a result, the index of the resulting
-hypnogram is a pandas.DatetimeIndex.
+hypnogram is a pandas.DatetimeIndex.
Upsample an hypnogram to a given sampling frequency and fit the resulting hypnogram to corresponding EEG data, such that the hypnogram and EEG data have the exact same number of samples.
Evaluate agreement between two hypnograms of the same sleep session.
+
For example, the reference hypnogram (i.e., self) might be a manually-scored hypnogram
+and the reference hypnogram (i.e., ref_hyp) might be a hypnogram from actigraphy, a
+wearable device, or an automated scorer (e.g., yasa.SleepStaging.predict()).
Counts transition matrix (number of transitions from stage A to stage B). The
pre-transition states are the rows and the post-transition states are the columns.
Conditional probability transition matrix, i.e. given that current state is A, what is
the probability that the next state is B. probs is a right stochastic matrix, i.e. each row sums to 1.
Verbose level. Default (False) will only print warning and error messages. The logging
levels are ‘debug’, ‘info’, ‘warning’, ‘error’, and ‘critical’. For most users the
@@ -965,9 +1009,9 @@
The hypnogram values, stored in a pandas.Series. To reduce memory usage, the
-stages are stored as categories (pandas.Categorical). hypno
-inherits all the methods of a standard pandas.Series, e.g. .describe(),
+
The hypnogram values, stored in a pandas.Series. To reduce memory usage, the
+stages are stored as categories (pandas.Categorical). hypno
+inherits all the methods of a standard pandas.Series, e.g. .describe(),
.unique(), .to_csv(), and more.
Lookaround window, in seconds. The default is +/- 1.2 seconds around the
negative peak of the slow-wave, as in [1]. This means that YASA will look for a
@@ -289,7 +289,7 @@
Evaluate agreement between sleep statistics reported by two different scorers.
+Evaluation includes bias and limits of agreement (as well as both their confidence intervals),
+various plotting options, and calibration functions for correcting biased values from the
+observed scorer.
+
Features include:
+* Get summary calculations of bias, limits of agreement, and their confidence intervals.
+* Test statistical assumptions of bias, limits of agreement, and their confidence intervals,
+and apply corrective procedures when the assumptions are not met.
+* Get bias and limits of agreement in a string-formatted table.
+* Calibrate new data to correct for biases in observed data.
+* Return individual calibration functions.
+* Visualize discrepancies for outlier inspection.
+* Visualize Bland-Altman plots.
A pandas.DataFrame with sleep statistics from the observed scorer.
+Rows are unique observations and columns are unique sleep statistics.
+Shape, index, and columns must be identical to ref_data.
+
+
ref_scorerstr
Name of the reference scorer.
+
+
obs_scorerstr
Name of the observed scorer.
+
+
agreementfloat
Multiple of the standard deviation to plot agreement limits. The default is 1.96, which
+corresponds to a 95% confidence interval if the differences are normally distributed.
+
+
Note
+
agreement gets adjusted for regression-modeled limits of agreement.
+
+
+
confidencefloat
The percentage confidence interval for the confidence intervals that are applied to bias and
+limits of agreement. The same confidence interval percentage is applied to both standard and
+bootstrapped confidence intervals.
+
+
alphafloat
Alpha cutoff used for all assumption tests.
+
+
verbosebool or str
Verbose level. Default (False) will only print warning and error messages. The logging
+levels are ‘debug’, ‘info’, ‘warning’, ‘error’, and ‘critical’. For most users the choice is
+between ‘info’ (or verbose=True) and warning (verbose=False).
+
+
+
+
+
Notes
+
Sleep statistics that are identical between scorers are removed from analysis.
Menghini, L., Cellini, N., Goldstone, A., Baker, F. C., & de Zambotti, M.
+(2021). A standardized framework for testing the performance of sleep-tracking
+technology: step-by-step guidelines and open-source code. SLEEP, 44(2),
+zsaa170. https://doi.org/10.1093/sleep/zsaa170
Return a DataFrame that includes all calculated metrics: * Parametric bias * Parametric lower and upper limits of agreement * Regression intercept and slope for modeled bias * Regression intercept and slope for modeled limits of agreement * Lower and upper confidence intervals for all metrics
A pandas.DataFrame with sleep statistics from an observed scorer.
+Rows are unique observations and columns are unique sleep statistics.
+
+
bias_methodstr
If 'parm', sleep statistics are always adjusted based on parametric bias.
+If 'regr', sleep statistics are always adjusted based on regression-modeled bias.
+If 'auto' (default), bias sleep statistics are adjusted by either 'parm' or
+'regr', depending on assumption violations.
If False (default), only adjust values for sleep statistics that showed a statistically
+significant bias in the obs_data. If True, adjust values for all sleep statistics.
Return a DataFrame with bias, loa, bias_ci, loa_ci as string equations.
+
+
Parameters
+
+
bias_methodstr
If 'parm' (i.e., parametric), bias is always represented as the mean difference
+(observed minus reference).
+If 'regr' (i.e., regression), bias is always represented as a regression equation.
+If 'auto' (default), bias is represented as a regression equation for sleep
+statistics where the score differences are proportionally biased and as the mean
+difference otherwise.
+
+
loa_methodstr
If 'parm' (i.e., parametric), limits of agreement are always represented as
+bias +/- 1.96 standard deviations (where 1.96 can be adjusted through the agreement
+parameter).
+If 'regr' (i.e., regression), limits of agreement are always represented as a
+regression equation.
+If 'auto' (default), limits of agreement are represented as a regression equation
+for sleep statistics where the score differences are proportionally biased and as
+bias +/- 1.96 standard deviation otherwise.
+
+
ci_methodstr
If 'parm' (i.e., parametric), confidence intervals are always represented using a
+standard t-distribution.
+If 'boot' (i.e., bootstrap), confidence intervals are always represented using a
+bootstrap resampling procedure.
+If 'auto' (default), confidence intervals are represented using a bootstrap
+resampling procedure for sleep statistics where the distribution of score differences is
+non-normal and using a standard t-distribution otherwise.
Return a DataFrame that includes all calculated metrics:
+* Parametric bias
+* Parametric lower and upper limits of agreement
+* Regression intercept and slope for modeled bias
+* Regression intercept and slope for modeled limits of agreement
+* Lower and upper confidence intervals for all metrics
+
+
Parameters
+
+
ci_methodstr
If 'parm' (i.e., parametric), confidence intervals are always represented using a
+standard t-distribution.
+If 'boot' (i.e., bootstrap), confidence intervals are always represented using a
+bootstrap resampling procedure.
+If 'auto' (default), confidence intervals are represented using a bootstrap
+resampling procedure for sleep statistics where the distribution of score differences is
+non-normal and using a standard t-distribution otherwise.
The window length (= resolution) for artifact rejection, in seconds.
Default to 5 seconds. Shorter windows (e.g. 1 or 2-seconds) will
@@ -217,7 +217,7 @@
The main idea of this approach is to estimate a reference covariance
matrix \(\bar{C}\) (for each sleep stage separately if hypno is
diff --git a/docs/build/html/generated/yasa.bandpower.html b/docs/build/html/generated/yasa.bandpower.html
index ac4bd27..1bdb66c 100644
--- a/docs/build/html/generated/yasa.bandpower.html
+++ b/docs/build/html/generated/yasa.bandpower.html
@@ -5,7 +5,7 @@
-
1D or 2D EEG data. Can also be a mne.io.BaseRaw, in which case data,
sf, and ch_names will be automatically extracted, and data will also be
converted from Volts (MNE default) to micro-Volts (YASA).
sffloat
The sampling frequency of data AND the hypnogram. Can be omitted if data is a
-mne.io.BaseRaw.
List of channel names, e.g. [‘Cz’, ‘F3’, ‘F4’, …]. If None, channels will be labelled
-[‘CHAN000’, ‘CHAN001’, …]. Can be omitted if data is a mne.io.BaseRaw.
+[‘CHAN000’, ‘CHAN001’, …]. Can be omitted if data is a mne.io.BaseRaw.
hypnoarray_like
Sleep stage (hypnogram). If the hypnogram is loaded, the bandpower will be extracted for
each sleep stage defined in include.
If True, apply a standard FIR bandpass filter using the minimum and maximum frequencies
-in bands. Fore more details, refer to mne.filter.filter_data().
1D or 2D EEG data. Can also be a mne.io.BaseRaw, in which
case data, sf, and ch_names will be automatically
extracted, and data will also be converted from Volts (MNE default)
to micro-Volts (YASA).
sffloat
The sampling frequency of data AND the hypnogram.
-Can be omitted if data is a mne.io.BaseRaw.
List of channel names, e.g. [‘Cz’, ‘F3’, ‘F4’, …]. If None,
channels will be labelled [‘CHAN000’, ‘CHAN001’, …].
-Can be omitted if data is a mne.io.BaseRaw.
Verbose level. Default (False) will only print warning and error
messages. The logging levels are ‘debug’, ‘info’, ‘warning’, ‘error’,
@@ -153,13 +153,13 @@
Keyword arguments controlling hypnogram line display (e.g., lw, linestyle).
+Passed to matplotlib.pyplot.stairs() and py:func:matplotlib.pyplot.hlines.
The default unit of mne.io.BaseRaw is Volts.
+Therefore, if passing data from a mne.io.BaseRaw,
make sure to use units=”uV” to get the data in micro-Volts, e.g.:
>>> data=raw.get_data(units="uV")# Make sure that data is in uV
This will give a pandas.DataFrame where each row is a
detected REM and each column is a parameter (= property).
To get the average parameters sleep stage:
If None (default), transition probabilities come from Metzner et al., 2021 [Metzner2021].
-If pandas.DataFrame, must have “from”-stages as indices and
+If pandas.DataFrame, must have “from”-stages as indices and
“to”-stages as columns. Indices and columns must follow YASA string
hypnogram convention (e.g., WAKE, N1). Unscored/Artefact stages are not allowed.
Probabilites of each stage to initialize random walk.
If None (default), initialize with “from”-WAKE row of trans_probas.
-If pandas.Series, indices must be stages following YASA string
+If pandas.Series, indices must be stages following YASA string
hypnogram convention and identical to those of trans_probas.
seedint or None
Random seed for generating Markov sequence.
diff --git a/docs/build/html/generated/yasa.sleep_statistics.html b/docs/build/html/generated/yasa.sleep_statistics.html
index 827329f..3d75201 100644
--- a/docs/build/html/generated/yasa.sleep_statistics.html
+++ b/docs/build/html/generated/yasa.sleep_statistics.html
@@ -5,7 +5,7 @@
-
If the detection is taking too long, make sure to downsample
your data to 100 Hz (or 128 Hz). For more details, please refer to
-mne.filter.resample().
Sleep stage (hypnogram). If the hypnogram is loaded, the
detection will only be applied to the value defined in
@@ -178,7 +178,7 @@
yasa.spindles_detect
remove_outliersboolean
If True, YASA will automatically detect and remove outliers spindles
-using sklearn.ensemble.IsolationForest.
+using sklearn.ensemble.IsolationForest.
The outliers detection is performed on all the spindles
parameters with the exception of the Start, Peak, End,
Stage, and SOPhase columns.
@@ -203,7 +203,7 @@
This will give a pandas.DataFrame where each row is a
detected spindle and each column is a parameter (= feature or property)
of this spindle. To get the average spindles parameters per channel and
sleep stage:
If the detection is taking too long, make sure to downsample
your data to 100 Hz (or 128 Hz). For more details, please refer to
-mne.filter.resample().
This will give a pandas.DataFrame where each row is a
detected slow-wave and each column is a parameter (= property).
To get the average SW parameters per channel and sleep stage:
Counts transition matrix (number of transitions from stage A to
stage B). The pre-transition states are the rows and the
post-transition states are the columns.
Conditional probability transition matrix, i.e.
given that current state is A, what is the probability that
the next state is B.
probs is a right stochastic matrix,
@@ -162,7 +162,7 @@
Sleep staging (aka hypnogram) for this example night was performed by a trained technician following the standard rules of the American Academy of Sleep Medicine (AASM).
The output is saved in a .csv file, where each row represents 30 seconds of data. The stages are mapped to integers such that 0 = Wake, 1 = N1 sleep, 2 = N2 sleep, 3 = N3 sleep and 4 = REM sleep.
-We can load this file using the pandas.read_csv() function:
If desired, we can then export the bandpower dataframe to a CSV file using pandas.DataFrame.to_csv():
+
If desired, we can then export the bandpower dataframe to a CSV file using pandas.DataFrame.to_csv():
>>> bandpower.to_csv("bandpower.csv")
-
Finally, we can use the yasa.topoplot() function to visualize the spectral powers across all electrodes. In the example below, we only plot the spectral values of stage N3, using the pandas.DataFrame.xs() function. As expected, the relative delta power is higher in frontal channels.
+
Finally, we can use the yasa.topoplot() function to visualize the spectral powers across all electrodes. In the example below, we only plot the spectral values of stage N3, using the pandas.DataFrame.xs() function. As expected, the relative delta power is higher in frontal channels.
diff --git a/docs/build/html/searchindex.js b/docs/build/html/searchindex.js
index fad0663..ba2e394 100644
--- a/docs/build/html/searchindex.js
+++ b/docs/build/html/searchindex.js
@@ -1 +1 @@
-Search.setIndex({docnames:["api","changelog","contributing","faq","generated/yasa.Hypnogram","generated/yasa.REMResults","generated/yasa.SWResults","generated/yasa.SleepStaging","generated/yasa.SpindlesResults","generated/yasa.art_detect","generated/yasa.bandpower","generated/yasa.bandpower_from_psd","generated/yasa.bandpower_from_psd_ndarray","generated/yasa.compare_detection","generated/yasa.hrv_stage","generated/yasa.hypno_find_periods","generated/yasa.hypno_int_to_str","generated/yasa.hypno_str_to_int","generated/yasa.hypno_upsample_to_data","generated/yasa.hypno_upsample_to_sf","generated/yasa.irasa","generated/yasa.load_profusion_hypno","generated/yasa.moving_transform","generated/yasa.plot_hypnogram","generated/yasa.plot_spectrogram","generated/yasa.rem_detect","generated/yasa.simulate_hypnogram","generated/yasa.sleep_statistics","generated/yasa.sliding_window","generated/yasa.spindles_detect","generated/yasa.stft_power","generated/yasa.sw_detect","generated/yasa.topoplot","generated/yasa.transition_matrix","index","quickstart"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,"sphinx.ext.intersphinx":1,"sphinx.ext.viewcode":1,sphinx:56},filenames:["api.rst","changelog.rst","contributing.rst","faq.rst","generated/yasa.Hypnogram.rst","generated/yasa.REMResults.rst","generated/yasa.SWResults.rst","generated/yasa.SleepStaging.rst","generated/yasa.SpindlesResults.rst","generated/yasa.art_detect.rst","generated/yasa.bandpower.rst","generated/yasa.bandpower_from_psd.rst","generated/yasa.bandpower_from_psd_ndarray.rst","generated/yasa.compare_detection.rst","generated/yasa.hrv_stage.rst","generated/yasa.hypno_find_periods.rst","generated/yasa.hypno_int_to_str.rst","generated/yasa.hypno_str_to_int.rst","generated/yasa.hypno_upsample_to_data.rst","generated/yasa.hypno_upsample_to_sf.rst","generated/yasa.irasa.rst","generated/yasa.load_profusion_hypno.rst","generated/yasa.moving_transform.rst","generated/yasa.plot_hypnogram.rst","generated/yasa.plot_spectrogram.rst","generated/yasa.rem_detect.rst","generated/yasa.simulate_hypnogram.rst","generated/yasa.sleep_statistics.rst","generated/yasa.sliding_window.rst","generated/yasa.spindles_detect.rst","generated/yasa.stft_power.rst","generated/yasa.sw_detect.rst","generated/yasa.topoplot.rst","generated/yasa.transition_matrix.rst","index.rst","quickstart.rst"],objects:{"yasa.Hypnogram":[[4,1,1,"","__init__"],[4,1,1,"","as_annotations"],[4,1,1,"","as_int"],[4,1,1,"","consolidate_stages"],[4,1,1,"","copy"],[4,2,1,"","duration"],[4,1,1,"","find_periods"],[4,2,1,"","freq"],[4,2,1,"","hypno"],[4,2,1,"","labels"],[4,2,1,"","mapping"],[4,2,1,"","mapping_int"],[4,2,1,"","n_epochs"],[4,2,1,"","n_stages"],[4,1,1,"","plot_hypnogram"],[4,2,1,"","sampling_frequency"],[4,2,1,"","scorer"],[4,1,1,"","simulate_similar"],[4,1,1,"","sleep_statistics"],[4,2,1,"","start"],[4,2,1,"","timedelta"],[4,1,1,"","transition_matrix"],[4,1,1,"","upsample"],[4,1,1,"","upsample_to_data"]],"yasa.REMResults":[[5,1,1,"","__init__"],[5,1,1,"","get_mask"],[5,1,1,"","get_sync_events"],[5,1,1,"","plot_average"],[5,1,1,"","summary"]],"yasa.SWResults":[[6,1,1,"","__init__"],[6,1,1,"","compare_channels"],[6,1,1,"","compare_detection"],[6,1,1,"","find_cooccurring_spindles"],[6,1,1,"","get_coincidence_matrix"],[6,1,1,"","get_mask"],[6,1,1,"","get_sync_events"],[6,1,1,"","plot_average"],[6,1,1,"","plot_detection"],[6,1,1,"","summary"]],"yasa.SleepStaging":[[7,1,1,"","__init__"],[7,1,1,"","fit"],[7,1,1,"","get_features"],[7,1,1,"","plot_predict_proba"],[7,1,1,"","predict"],[7,1,1,"","predict_proba"]],"yasa.SpindlesResults":[[8,1,1,"","__init__"],[8,1,1,"","compare_channels"],[8,1,1,"","compare_detection"],[8,1,1,"","get_coincidence_matrix"],[8,1,1,"","get_mask"],[8,1,1,"","get_sync_events"],[8,1,1,"","plot_average"],[8,1,1,"","plot_detection"],[8,1,1,"","summary"]],yasa:[[4,0,1,"","Hypnogram"],[5,0,1,"","REMResults"],[6,0,1,"","SWResults"],[7,0,1,"","SleepStaging"],[8,0,1,"","SpindlesResults"],[9,3,1,"","art_detect"],[10,3,1,"","bandpower"],[11,3,1,"","bandpower_from_psd"],[12,3,1,"","bandpower_from_psd_ndarray"],[13,3,1,"","compare_detection"],[14,3,1,"","hrv_stage"],[15,3,1,"","hypno_find_periods"],[16,3,1,"","hypno_int_to_str"],[17,3,1,"","hypno_str_to_int"],[18,3,1,"","hypno_upsample_to_data"],[19,3,1,"","hypno_upsample_to_sf"],[20,3,1,"","irasa"],[21,3,1,"","load_profusion_hypno"],[22,3,1,"","moving_transform"],[23,3,1,"","plot_hypnogram"],[24,3,1,"","plot_spectrogram"],[25,3,1,"","rem_detect"],[26,3,1,"","simulate_hypnogram"],[27,3,1,"","sleep_statistics"],[28,3,1,"","sliding_window"],[29,3,1,"","spindles_detect"],[30,3,1,"","stft_power"],[31,3,1,"","sw_detect"],[32,3,1,"","topoplot"],[33,3,1,"","transition_matrix"]]},objnames:{"0":["py","class","Python class"],"1":["py","method","Python method"],"2":["py","property","Python property"],"3":["py","function","Python function"]},objtypes:{"0":"py:class","1":"py:method","2":"py:property","3":"py:function"},terms:{"0":[3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35],"00":[1,4,23,26,33,35],"000":4,"006":4,"009ddc":7,"01":[4,23,35],"010":4,"01196953210011":35,"013":4,"015":20,"016":15,"01_spindles_detect":29,"02":4,"0201":4,"021":[4,26],"029":4,"02912":26,"02_spindles_detection_multi":29,"033":4,"038":4,"03_spindles_detection_nrem_onli":29,"0448":20,"045":4,"04_spindles_slow_fast":29,"05":[20,31,33],"05_sw_detect":31,"06":4,"067":4,"06_sw_detect":1,"07897545357524":35,"07_rems_detect":25,"08":35,"08_bandpow":10,"0909":4,"09_irasa":20,"0min":[4,14,15],"0sec":[4,15],"1":[3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35],"10":[1,3,4,7,20,26,27,28,31,34],"100":[1,3,4,6,7,8,13,18,19,22,24,27,28,29,31,32,34,35],"1000":4,"1007":20,"1015":35,"1038":26,"106":1,"107":1,"108":1,"10_bandpow":1,"11":[4,15,23,28,29,35],"1101":[1,20],"115":1,"1151":7,"1164":7,"1176":4,"119":1,"12":[1,4,6,8,10,11,12,13,28,29,31,35],"120":4,"121":[4,27],"128":[1,29,31],"13":[4,20,28,35],"131":[4,27],"1351":7,"1358":7,"1390":25,"1396":25,"13_artifact_reject":9,"14":[4,15,28,32,33,35],"142":35,"14_automatic_sleep_stag":7,"15":[1,4,20,28,29,32],"150":[1,4,14,31],"151":1,"153":4,"15_topoplot":1,"15min":[4,14,15],"16":[4,8,10,11,12,15,28,31,35],"16_eeg":1,"16hz":1,"17":[28,35],"18":[1,13,27,28,35],"180":4,"19":[1,9,28,35],"1d":[4,9,10,14,15,16,17,18,19,20,21,24,25,27,28,29,31],"1hour":[4,14,15],"1hz":1,"1min":4,"2":[3,4,6,7,9,10,11,12,13,14,15,16,17,20,21,23,24,25,26,27,28,29,30,31,32,33,35],"20":[4,9,13,27,28,33],"200":[1,30,31,35],"2000":14,"2004":[3,31],"2005":25,"2007":[4,27],"2011":[3,31],"2013":9,"2016":[7,20,25],"2017":14,"2018":[1,3,7,29,35],"2019":[1,9],"2021":[3,6,7,8,20,26,34],"2022":[4,23],"21":[4,28],"214":35,"216":4,"22":[1,4,35],"23":[1,4,23,35],"24":[4,31],"240":4,"244":9,"247":4,"24min":23,"25":[4,7,15,20,24,27,29,33,35],"255":9,"256":[1,4,18,19],"258":14,"259":25,"26":[4,13,20,28],"266mb":35,"27":9,"28":28,"28920":35,"2892000":35,"29":[1,4,7,20,28],"299859v1":20,"2bfz":24,"2bpz":24,"2d":[4,10,18,20,28,30],"2f":33,"2min":[4,14,15],"3":[3,4,6,8,9,10,12,14,15,16,17,20,21,22,23,24,25,26,27,28,29,30,31,32,33,35],"30":[1,3,4,5,6,7,8,10,11,12,14,15,18,19,20,21,23,24,26,27,28,29,30,33,34,35],"300":[1,23],"3000":[1,7],"30sec":[4,14,15],"31":[4,23,27,28,31,35],"3166":4,"317":35,"32":4,"325":25,"33":[1,28,31],"33195020746888":35,"333":35,"3333":35,"34":[13,28],"35":20,"350":[1,31],"3508":4,"37":[4,28],"39":7,"398":4,"3f":35,"3kb":35,"4":[4,5,6,7,8,9,10,11,12,13,14,15,16,17,20,21,23,24,25,26,27,28,29,30,31,32,35],"40":[3,4,5,6,8,10,11,12,31,33,34,35],"400":[1,14],"41":[4,13,28],"418":4,"42":[4,25,28,29,31],"4221":4,"4271":4,"43":[28,33],"4306":4,"44":6,"447":4,"45":[4,20,35],"459":35,"46":[28,35],"464483":[1,20],"468":35,"47":[4,28],"477":4,"48":[4,28],"480":[4,26],"482":35,"49":[4,28],"497":4,"4hz":35,"5":[3,4,5,6,7,8,9,10,11,12,13,15,16,17,18,19,20,21,23,24,25,26,27,28,29,31,32,33,35],"50":[1,25,28,29,31,33],"500":[1,4,6,8,29],"5072":4,"51":28,"514":33,"52":[25,28],"53":4,"54":1,"540":[6,8],"55":[13,20,32],"5555555555555556":13,"57":[1,13,28],"572361262241564":35,"5784000":35,"59":[4,35],"5b":[1,26],"5hz":29,"5min":[4,14,15],"6":[4,5,6,8,10,14,15,20,23,26,27,28,29,31],"60":[4,15,24,28,33],"607181719260065":35,"625":13,"63":[13,28],"64":4,"65":[20,29],"66":[4,28],"6667":4,"67":4,"676":35,"68":[1,13,35],"6862":31,"6870":31,"69":[4,28],"7":[4,7,15,20,26,27,28,32],"70":1,"70092":[3,7,34],"71":[1,13,28],"7142857142857143":13,"7177":4,"72":25,"739":4,"74":28,"75":[1,20,27,29,31],"7538":4,"7554":[3,7,34],"758":31,"76":4,"766":31,"77":35,"7777777777777778":13,"79":[4,28],"8":[1,3,4,6,10,11,12,20,24,25,26,27,28,32,35],"80":[1,27,28,32],"808487486398259":35,"82":[4,25,35],"83":[4,28],"8342":4,"84":4,"85":[1,3,20,35],"86":28,"87":28,"875":13,"88":[4,28],"8889":4,"89":28,"9":[1,4,15,20,26,27,28,33,35],"90":[4,28],"91":28,"914":4,"9167":4,"92":[4,28],"9231":4,"929":4,"93":28,"933":4,"94":4,"95":35,"959":35,"96":4,"960":35,"961":35,"962":35,"963":35,"964":35,"97":[24,28],"9713":4,"98":[28,35],"98803046789989":35,"99":[4,23,28],"99d7f1":7,"\u00b5v":29,"\u03bcv":35,"barth\u00e9lemi":9,"boolean":[5,6,7,8,10,11,12,20,22,25,29,30,31],"break":1,"case":[4,6,7,8,9,10,18,20,29,31],"class":[1,3,4,5,6,7,8,9,35],"default":[1,3,4,5,6,7,8,9,10,11,12,13,14,15,18,20,21,22,24,25,26,27,28,29,30,31,35],"do":[2,3,6,7,8,13,31,35],"export":[3,7,35],"final":[3,13,33,35],"float":[1,4,5,6,8,9,10,14,15,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32],"function":[1,2,3,4,5,6,8,9,10,12,13,14,15,16,17,20,22,28,29,31,34,35],"import":[1,3,4,6,7,8,13,15,23,24,26,27,28,31,32,33,34,35],"int":[4,9,10,13,14,15,20,22,24,25,26,28,29,30,31,32],"long":[5,6,8,29,31,34],"new":[2,3,4,6,7,8,9,10,11,12,14,15,16,17,18,19,20,23,24,25,26,27,28,29,31,32,33,35],"public":[1,3,7,9,14,26,27,34,35],"return":[1,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33],"short":[9,29,34],"super":26,"switch":1,"true":[1,3,4,5,6,7,8,9,10,11,12,13,14,15,18,20,21,22,23,24,25,29,30,31,33,34,35],"try":[34,35],"while":[3,4,27],A:[3,4,6,7,8,9,13,14,15,22,23,25,26,27,28,29,30,32,33,34,35],AND:[10,20,24],As:[1,3,4,35],Be:7,By:14,For:[1,3,4,5,6,7,8,9,10,13,14,15,18,20,21,24,25,29,31,32,33,34,35],IN:6,If:[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,18,20,21,22,25,26,28,29,30,31,32,34,35],In:[1,3,4,7,9,15,20,24,35],Is:[6,8],It:[1,3,6,8,9,20,31,35],NO:34,NOT:7,OF:34,One:[1,6,8],Such:3,That:[1,4,14,15],The:[1,2,3,4,6,7,8,9,10,13,14,15,16,17,18,19,20,21,24,25,26,27,28,29,30,31,32,33,34,35],Then:[3,9],There:[2,3,13,15,35],These:[7,13],To:[1,2,3,4,6,8,9,10,14,15,24,25,29,31,33,34,35],With:28,_:33,__init__:[4,5,6,7,8],_ch_name:[5,6,8],_data:[5,6,8],_data_filt:[5,6,8],_event:[5,6,8],_hypno:[5,6,8],_sf:[5,6,8],a1:[3,34,35],a2:[3,34,35],aasm:[1,4,27,35],abbrevi:4,about:[1,2],abov:[9,22,23,29],absolut:[1,7,25,29,31,35],abspow:29,academi:[4,27,35],accept:[3,4,6,8],access:[1,4,35],accident:1,accompani:2,account:[1,9],accumul:4,accur:[3,9,26],accuraci:[1,3,7,35],accuracy_scor:35,across:[1,3,5,6,8,14,26,34,35],actigraphi:4,activ:[6,8,35],actual:[4,13,25],ad:[1,2,3,20,31],adapt:[3,9],add:[1,3,6,26,34],addit:[1,3,7],address:1,adequ:3,adjust:[3,35],adopt:1,adult:[3,4,27],advanc:14,advantag:[1,3],aesthet:1,affect:1,after:[2,4,5,6,8,13,27],ag:[1,7],against:[1,3,6,8,13,35],agarw:25,aggfunc:[1,5,6,8],agreement:[1,3,6,7,8,35],aka:[1,4,6,8,13,35],al:[1,3,4,7,26,35],algorithm:[1,3,7,25,29,31,34,35],alias:4,all:[1,2,3,4,5,6,8,9,13,14,15,25,27,29,30,32,34,35],allow:[1,4,26,35],almost:35,along:1,alpha:[10,11,12,35],alreadi:[1,3,4,27],also:[1,2,3,4,6,7,8,9,10,18,20,27,29,31,34,35],altern:[23,34],alwai:[1,3,4,6,7,8,35],am:[3,35],american:[4,7,27,35],amount:[3,4,24],amp_neg:31,amp_po:31,amp_ptp:31,amplitud:[1,5,6,8,22,25,29,31,34,35],an:[1,2,3,4,5,6,7,8,9,10,14,15,16,18,20,25,26,27,29,31,33,34,35],anaconda:[34,35],analys:[1,34],analysi:[1,3,14,20,26,34,35],analyz:35,ancoli:27,andreev:9,ani:[1,4,7,9,15,27,29,31,33,34],anim:3,annot:[1,3,4,6,8,13,21,33],anot:3,anoth:[1,6,8,34],answer:7,antropi:[1,7],anymor:4,anyth:15,aperiod:[20,34],api:[1,34],appear:3,appli:[1,3,5,6,7,8,9,10,14,25,29,31,34,35],approach:[1,3,4,9,25],approxim:20,appveyor:1,april:1,ar:[1,2,3,4,5,6,7,8,9,10,13,14,15,18,20,22,24,25,26,27,29,30,31,32,33,34,35],arai:12,arang:[3,28],argument:[1,4,5,6,8,10,13,20,24,26,32,35],arithmet:22,around:[1,4,6,8,9,15,16,17,28,31,32,35],arrai:[1,3,4,5,6,8,9,11,12,13,14,15,16,17,18,19,21,22,24,28,35],array_lik:[4,5,6,8,9,10,11,13,14,15,16,17,18,19,22,24,25,27,29,30,31,33],art:[1,4,16,17,23,27],art_detect:1,art_epoch:9,artefact:[1,3,4,9,10,14,24,25,26,27,29,31,33,34,35],articl:[1,3,20,34],artifact:[9,34],artifact_reject:34,artifect:9,as_annot:4,as_datafram:[1,6,8],as_int:[4,26],as_strid:28,asap:1,ascii:3,ask:3,assign:1,associ:[1,4,7,20,27,35],assum:[3,4,7,15,27,35],assumpt:1,attribut:[1,4,5,6,8,20,35],author:3,autism:6,auto:[7,20],autom:[3,7,34],automat:[1,3,4,7,9,10,18,20,25,29,31,34],automatic_stag:34,avail:[1,3,6,8,22],averag:[1,5,6,7,8,10,11,13,20,25,29,31,33,34,35],avoid:1,awai:20,ax1:26,ax2:26,ax:[1,4,23,26,33],axi:[1,4,7,23,28,35],b:[1,4,6,8,20,25,33,35],back:35,bad:9,band:[1,3,7,10,11,12,20,29,30,31,34],bandpa:31,bandpass:[1,3,5,6,8,10,31,34,35],bandpow:[1,11,12,34,35],bandpower_from_psd:[1,12],bandpower_from_psd_ndarrai:1,bandwidth:31,bandwis:30,bar:9,barach:9,barakat:31,barth:6,base:[1,4,9,25,26,29,31,32,34,35],baseraw:[4,7,9,10,18,20,25,29,31],basic:[1,34,35],bdf:3,beat:14,beaudri:29,becaus:[1,4,7,13,35],becom:1,bed:[1,4,26,27,33],been:[1,31],befor:[1,2,5,6,7,8,13],begin:[1,4,6,8,14,25,27,29,31],behavior:[1,29,31,35],being:1,below:[1,3,4,6,7,8,9,34,35],berkelei:34,best:[1,2,4,9,33,34],bet:2,beta:[7,10,11,12,35],better:[1,3,6,8,14,25,29,31],between:[1,4,6,8,9,10,11,12,13,14,18,20,22,25,26,28,29,31,34,35],bibtex:3,bid:4,big:1,biggest:1,bin:30,binari:[4,6,8,15],bio:25,biol:1,biologi:[9,26],biorxiv:20,bit:35,bivari:30,black:1,blatant:3,blink:9,blob:[1,7,9,10,20,25,29,31],blue:[7,35],bodi:9,bonnet:27,bool:[4,5,6,8,9,14,15,18,20,21,25,29,30,31],born:6,both:[1,3,6,8,20,24,25],bottom:34,bound:[6,8],box:34,bpm:14,brain:20,brainvis:[3,34],brand:1,briefli:1,bring:1,broad:[20,29,30],broadband:29,bug:[1,2,3,29,34],bugfix:1,bui:[2,3],build:1,built:[1,3],bundl:35,bytesio:24,c3:[3,7,32,34,35],c4:[3,7,32,34,35],c:[9,25,26,27,29],calcul:[1,4,6,7,8,9,10,13,14,20,24,25,27,28,29,31,33,34,35],call:[1,6,31,35],can:[1,2,3,4,6,7,8,9,10,14,15,18,20,26,27,29,31,32,33,34,35],canthi:25,captur:3,cardiac:14,care:7,carrier:[3,31],categor:[1,4],categori:4,caus:1,cbar:33,cbar_ax:33,cbar_kw:33,cbar_tick:32,cbar_titl:32,cbrnr:14,cell:26,center:[1,5,6,7,8,31],central:[1,7],certain:[1,3,4,15],ch_name:[1,5,6,8,10,11,20,29,31,35],challeng:20,chan000:[10,11,20],chan001:[10,11,20],chan:35,chang:[1,2,3,4,6,8,14,31],channel:[1,3,5,6,7,8,9,10,11,14,20,22,24,25,28,29,30,31,32,34,35],channel_prior:34,charact:1,check:[1,3,7,29,34,35],children:6,chin:7,choic:[4,9,14,18,20,25,29,31],chokroverti:27,ci:[1,35],circ_mean:31,circ_r:31,circular:31,cite:[3,7,26,34],classif:34,classifi:[1,3,7],click:3,clinic:[4,27],close:[6,8,13,29],closer:29,cluster:9,cmap:[24,32,33],co:[1,6],code:[1,3,7,34,35],codebas:2,coeffici:32,coffe:[2,3],cognit:35,coincid:[1,6,8],color:[6,8,23,24,32,35],color_palett:32,colorbar:32,colormap:[24,32],column:[1,3,4,6,8,10,11,14,25,26,29,31,33,35],com:[1,3,6,7,8,9,10,14,20,21,22,24,25,26,29,31,35],combin:[1,3],come:[1,3,4,7,26,34,35],command:[3,34,35],comment:[1,3],common:[4,7,35],commun:[1,26],comodulogram:[1,34],compar:[1,4,6,8,13],compare_channel:[1,6,8],compare_detect:[1,6,8],compare_heartbeat:13,comparison:13,compat:[1,3,4],complex:7,compli:[1,2],compliant:4,compon:[1,20,34],compress:1,compumed:[1,21],comput:[1,4,6,7,8,9,11,12,20,22,25,27,30,31,35],concat:4,concaten:29,concret:7,conda:34,condit:[4,33],confid:[3,7],config:34,conflict:1,confus:1,congedo:9,consecut:[1,4,15,26],consensu:3,conserv:[1,9],consid:[1,2,6,8,9,13],consist:[1,26,28],consolid:4,consolidate_stag:4,constrained_layout:23,contact:34,contain:[1,4,6,8,9,10,11,12,26],contamin:9,content:20,continu:25,contrast:24,contribut:[1,3,34],convent:26,convers:1,convert:[1,4,7,9,10,16,17,20,29,31,35],convolv:1,conzelmann:6,cooccurringspindl:6,cooccurringspindlepeak:6,copi:[4,7,13],corr:[22,29],correct:[1,13,14],correctli:2,correl:[22,29,32],correspond:[3,4,14,16,17,18,22,28],cost:[6,8],could:[1,3,4,13,29],count:[1,4,13,33,35],coupl:[1,6,31,34],coupling_param:[1,31],covar:[9,22],covari:[9,22],creat:[1,4,33,34],critic:[1,4,9,14,18,20,25,29,31],crop:[4,18,27,33],cross:[7,31],csv:[3,35],cubic:[22,30],current:[1,3,4,6,7,8,9,13,15,18,19,26,31,33,35],custom:[3,4,5,6,8,14,35],cz:[1,10,11,20,24,32,35],d:[1,3,9,12,25,28,31],damberg:27,data:[1,4,5,6,7,8,9,10,11,12,13,14,15,18,19,20,22,24,25,26,28,29,30,31,32,34],data_ecg_8hrs_200hz:1,data_filt:[5,6,8],data_full_6hrs_100hz_cz:24,data_full_6hrs_100hz_hypno_30:[24,26],databas:[1,3],datafram:[1,3,4,5,6,7,8,10,11,14,15,20,25,26,29,31,33,35],dataset:[1,34],date:4,date_rang:4,datetim:4,datetimeindex:4,db:[29,31],dean:7,debug:[4,9,14,18,20,25,29,31],decisecond:[6,8],decreas:35,deep:[4,35],defin:[1,4,6,8,9,10,11,12,13,14,15,24,25,29,31,32,35],definit:[4,9,27],deflect:31,degre:30,delet:3,delfrat:29,delimit:3,delta:[7,10,11,12,35],demonstr:34,denni:7,denomin:1,denot:1,densiti:[1,11,12,20],depend:[1,29],deprec:1,deriv:[1,7,29],describ:[1,4,7,20,35],descript:[3,4,9,34],design:3,desir:[4,15,19,26,35],despit:3,detail:[1,4,6,7,8,10,11,12,21,24,26,29,31,32,34,35],detect:[1,5,6,7,8,9,13,14,25,29,31,34],determin:[1,6,13],detrend:[1,29],dev:4,develop:2,developp:3,deviat:[1,7,9,14,29,31],df:4,df_sync:[5,6,8],diag:[33,35],diagon:[6,8,33,35],dialog:3,dict:[4,5,6,7,8,10,13,14,16,17,20,24,26,27,29,31,32],dictionari:[4,7,13,14],dictionnari:[16,17],did:7,differ:[1,3,4,6,7,8,9,14,15,20,27,35],difficult:1,dimens:[1,7,28],dimension:[1,12,35],direct:31,directli:[1,24],directori:2,disabl:[1,4,14,15,18,29,31,35],discard:[4,15],discoveri:7,discret:32,discuss:[2,20],disord:[3,6,7],displai:[1,34],distanc:[6,8,9,13],distancespindletosw:6,distribut:[9,20,24],dive:34,divid:[4,6,8,10,11,12,14,15],divis:[1,4,15,26],doc:[2,4],docstr:2,document:[1,3,4,6,7,8,26,34,35],doe:[1,3,4,6,8,35],doi:[1,3,7,20,26,34],domain:14,done:[2,3,5,6,8,30,33,35],doubl:[1,7],download:[34,35],downsampl:[1,3,7,29,31,34,35],downstat:6,dpi:[1,32],drastic:[9,29,35],draw:[1,23],driven:34,drop_channel:35,dtype:[1,4,13,15,26,33,35],duggan:25,dur_neg:[1,31],dur_po:[1,31],durat:[1,3,4,14,15,25,26,27,29,31],dure:[6,9,29,31],dynam:3,e1:7,e:[1,3,4,5,6,7,8,9,10,11,12,13,15,18,19,20,21,24,25,26,27,30,31,32,33,34,35],each:[1,3,4,5,6,7,8,9,10,11,12,13,14,15,18,19,22,25,26,27,28,29,30,31,33,35],easili:35,ecg:[1,14],edf:[3,7,21,34,35],edfbrows:[3,7,35],edit:[2,3,7],editor:[3,21,34],eeg:[1,3,4,6,7,8,9,10,11,15,18,19,20,24,26,28,29,34],eeg_nam:[7,35],eeglab:3,effect:[1,6,8,9,10,25,29,31],effici:[1,4,27],eigenvalu:9,either:[1,6,7,8,33],ekg:[9,35],elan:3,electrod:[7,9,32,35],element:[6,8,32],elif:[3,7,34,35],elifesci:3,emg1:[7,35],emg2:[7,35],emg:[1,7,9,35],emg_nam:7,emphasi:3,empti:13,emul:29,en:[6,8,9],enabl:[1,3],encod:[3,35],end:[4,15,24,25,29,31],engin:[9,25],enhanc:1,ensembl:[1,25,29,31],ensur:[2,4,22,25,29,30,31],enter:[34,35],entir:[34,35],entropi:[1,7],eog:[1,5,7,9,25,35],eog_nam:7,epoch:[1,3,4,7,9,14,21,22,26,27,28,31,33,34,35],equal:30,equal_length:[4,14,15],error:[1,3,4,9,14,18,20,25,29,31],especi:[3,7,34,35],essenti:[9,16,17],estim:[9,14,20],et:[1,3,4,7,26,35],etc:[2,3,4,14,35],ethnic:7,euclidean:9,european:[3,31,34,35],evalu:[3,6,8],even:[1,3,6,8,13],evenli:26,event:[1,4,5,6,8,13,27,34],everi:[9,20,22,30,35],exact:[4,10,14,15,18,24,35],exactli:[4,13,14,15],exampl:[1,2,3,4,6,7,8,9,10,13,14,15,20,23,24,25,26,27,28,29,31,32,33,34,35],exce:[1,4,14,15],exceed:[4,9,15],excel:35,except:[4,21,27,29],exclud:[1,4,9,27,33],exclus:[1,7],exist:[1,2],expect:[7,35],experi:[1,9],experiment:[1,4],expert:[3,29,35],explain:[1,3,35],explan:35,exponenti:20,express:[1,4,6,14,26,27,29,31,35],extens:3,extern:[3,7],extra:1,extract:[1,4,7,9,10,18,20,29,31],ey:[9,25,34],f1:[1,3,6,8,13],f3:[10,11,20,32,35],f4:[10,11,20,32,35],f7:35,f8:35,f:[14,20,30,31,33,34,35],facilit:1,factor:20,fake:[4,26],fake_hyp:26,fall:25,fals:[1,3,4,5,6,7,8,9,10,13,14,15,18,20,22,25,29,30,31,33,35],familiar:35,faq:[1,7,34],far:9,fast:[34,35],faster:[1,7,9,30],fastest:[22,30],featur:[1,3,7,14,29,34],feedback:1,feel:[4,7,15,34],fell:9,femal:[7,35],ferrarelli:31,few:[3,35],field:[9,35],fieldtrip:20,fig:[23,24,26,32,35],figsiz:[1,5,6,8,23,26,32,33],figur:[1,5,6,8,24,26,32],file:[1,3,4,7,26,34,35],filenam:21,filipini:31,fill:[14,23],fill_color:23,filt:[5,6,8],filter:[1,3,5,6,7,8,10,25,29,31,34,35],filter_data:[5,6,8,10],find:[1,3,4,6,7,8,15],find_cooccurring_spindl:[1,6],find_period:4,fine:3,fir:[1,10,29,31],first:[1,3,4,6,7,9,15,25,27,29,31,32,34,35],fit:[1,4,7,18,20],fit_param:20,fix:[1,29],flake8:[1,2],flat:1,flexibl:1,fmax:24,fmin:24,fmt:[3,33],fn:13,fname:21,focus:1,folder:[34,35],follow:[2,3,4,6,7,8,20,26,27,29,31,35],font:32,fontsiz:32,fooof:20,fore:10,forest:1,forg:34,form:6,format:[1,2,3,5,6,8,9,10,14,21,24,25,27,29,31,34,35],former:[4,27,34],found:[1,3,4,6,7,21,26,27,32,34],fourier:29,fp1:35,fp2:35,fp:13,fpz:7,fractal:[7,20,34],fraction:[6,8,33],fragment:[4,33,35],framework:3,free:[3,4,7,15,25,29,31,34,35],freeli:3,freq:[4,11,12,20,23,26],freq_broad:29,freq_rem:25,freq_so:1,freq_sp:[1,29,31],freq_sw:[1,31],frequenc:[1,3,4,5,6,7,8,9,10,11,12,13,14,15,18,19,20,21,22,24,25,27,28,29,30,31,33,34],from:[1,3,4,6,7,8,9,10,13,14,20,23,24,25,26,27,28,29,31,32,33,34,35],frontal:35,frontier:14,full:[1,3,4,7,21,24,25,29,31,34],fundament:20,further:[4,15],furthermor:[1,4,35],futur:1,fz:[32,35],g:[1,3,4,5,6,7,8,9,10,11,12,13,15,18,19,20,24,25,26,31,32,33,34],gamma:[10,11,12,35],gear:35,gender:7,gener:[1,4,15,26],generaliz:2,geometr:20,geometri:9,get:[1,4,7,14,24,25,26,29,31,35],get_bool_vector:1,get_centered_indic:1,get_coincidence_matrix:[1,6,8],get_data:[25,35],get_featur:7,get_mask:[1,5,6,8],get_sync_ev:[1,5,6,8],get_sync_sw:1,ginsberg:14,gist:6,github:[1,2,3,6,7,8,9,10,14,20,21,22,24,25,26,29,31,34],githubusercont:24,give:[1,3,4,6,8,13,15,25,29,31],given:[4,6,9,11,14,15,18,19,33,35],global:32,go:34,goal:20,good:[9,22,30],gotman:25,grab:3,gradual:1,grand:1,graphic:[3,7],greater:9,grid:30,grid_kw:33,gridspec_kw:33,grigg:27,grndtrth:13,ground:[1,6,8,13,35],groundtruth:13,group:[1,5,6,8],grp_chan:[1,6,8,29,31,35],grp_stage:[1,5,6,8,25,29,31,35],gui:3,guidanc:2,guidelin:[1,4,27],guo:7,h:[20,26,27],ha:[1,3,6,8,9,10,22,25,29,31,35],halfwai:29,ham:[10,20],handl:1,happen:14,harmon:[6,8,13,20],have:[1,3,4,7,9,10,14,15,18,24,25,26,27,29,31,34,35],hdeeg:9,header:3,health:[7,14],healthi:[3,35],heart:[1,14,34],heartbeat:[1,14],heatmap:33,height:32,height_ratio:33,help:[1,35],here:[3,4,13,15,27,35],hertz:35,heterogen:3,hi:1,high:[3,7,34,35],higher:[1,4,9,22,24,30,35],highest:[1,6,8,35],highli:2,highlight:[4,23],higuchi:7,hilbert:[1,29],hill:31,hirshkowitz:27,hjorth:7,homogen:1,horizont:33,hour:[1,4,26,35],how:[1,3,6,8,9,10,20,25,31,35],howev:[3,9,34,35],hr:[1,4,14],hr_mean:14,hr_std:14,hrv:[1,14,34],hrv_coupl:1,hrv_rmssd:14,hrv_stage:1,hset:20,hspace:33,html:[1,2,4,9,32,35],http:[1,3,4,6,7,8,9,10,14,20,21,22,24,25,26,29,31,32,34,35],huber:31,hue:[1,6,8],huge:[1,3],human:[3,4,6,7,8,13,29,35],hundr:1,hyp:[1,3,4,23,26],hyp_2:4,hyp_a:23,hyp_b:23,hyp_up:4,hypno:[1,3,4,5,6,7,8,9,10,14,15,16,17,18,19,21,24,25,26,27,29,31,33,35],hypno_export:3,hypno_find_period:1,hypno_int:3,hypno_int_to_str:26,hypno_pr:35,hypno_str_to_int:35,hypno_up:35,hypno_upsample_to_data:[1,9,10,14,24,25,29,31,35],hypnogram:[1,3,5,6,8,9,10,14,15,16,17,18,19,20,21,23,24,25,26,27,29,31,33,34],hz:[1,3,4,5,6,7,8,9,10,11,12,13,15,18,19,20,21,24,25,29,30,31,34,35],i:[1,3,4,5,6,8,9,13,15,21,26,27,30,31,33,35],iber:[4,27],idea:9,ideal:[3,10,20,29],ident:[21,26],identifi:[3,35],idxchannel:[5,6,8],ieee:[9,25],ill:[1,35],illustr:1,iloc:26,impact:[1,6,8,24],implement:[1,3,9,12,29,31],implent:26,importantli:[31,35],improv:[1,2,3],inch:[5,6,8,32],includ:[1,2,3,4,5,6,8,9,10,14,25,27,29,31,35],inconsist:3,incorrect:33,increas:[1,9,31,35],increment:20,inde:1,independ:[13,20],index:[3,4,5,6,8,9,13,14,15,32,35],indic:[1,3,4,5,6,8,13,14,26,29,32,35],indices_detect:13,indices_groundtruth:13,individu:[1,3,6,8],inf:[14,31],influenc:9,info:[4,9,14,18,20,25,29,31,35],inform:[1,4,26],informat:7,inherit:4,init_proba:26,initi:[1,7,26],input:[1,20,22,30],inspect:[7,9],inspir:[13,22],instal:[1,2,3,35],instanc:[1,5,6,7,8,23,28],instantan:29,instead:[1,4,29],int16:4,int64:[13,35],integ:[1,4,9,10,14,16,17,20,21,24,25,26,27,29,31,33,35],inter:[3,7,9],interact:[1,6,8,34],intercept:20,interest:[1,10,11,12,20,31],interfac:[3,7,34],intern:[1,4],interp2d:30,interp:[22,30],interpol:[14,22,30],interquartil:7,interv:14,intracrani:3,introduc:1,introduct:35,invalid:[1,14],invers:[10,20],invert:[6,8,13],involv:7,io:[3,4,6,7,8,9,10,18,20,24,25,29,31,34,35],ipynb:[1,7,9,10,20,25,29,31],ipywidget:[1,6,8],irasa:[1,34],irregular:20,isol:1,isolationforest:[1,25,29,31],israel:27,issu:[1,2,7,9,34],item:[4,15],iter:9,its:[1,4,7,20],j:[6,14,25,29,31],jcsm:27,joblib:7,joint:9,journal:[3,4,7,25,27,29,31],juli:1,jupyt:[1,6,7,8,14,24,29,31,34,35],just:29,k:[6,25,29],kapen:27,keenan:27,keep:[1,4,15],kei:[5,6,7,8],kept:[4,14,15,29],keyword:[1,4,10,20],kid:3,kind:[34,35],know:[1,35],knowledg:34,known:35,kramer:[6,8],krauss:26,kryger:27,kurtosi:7,kurz:6,kwarg:[4,5,6,8,24,26,32],kwargs_welch:[10,20],l:[9,20,25,35],lab:34,label:[3,4,6,8,10,11,20,33],lacours:[3,29,35],lafortun:31,lambda_i:9,landmark:[1,5,6,8],larg:[3,9,35],largest:1,laroch:25,last:[1,4,15,27,28],lastli:[4,15],lat_n1:[27,35],lat_n2:[27,35],lat_n3:[27,35],lat_rem:[4,27,35],latenc:[1,4,27],later:35,latest:[1,6,8,9,35],law:20,lead:1,learn:[1,2,25],least:[1,10,20,22,24,29],led:1,left:[7,9,25,34],legend:35,len:[3,35],length:[1,3,4,9,10,14,15,20,24,28,31,35],less:[4,9],let:[1,3,4,15,35],level:[4,9,14,18,20,25,29,31],leverag:3,lgbmclassifi:7,lib:28,librari:[14,35],life:31,light:[4,27],lightgbm:[1,7],like:[1,2,3,13],limit:[4,14,15,34,35],line:[1,3,6,8,23,24,34,35],linear:[1,14,20,34],lineplot:[1,5,6,8],linewidth:23,list:[1,4,5,6,8,9,10,11,12,14,20,25,29,31,32],liu:20,ll:35,load:[1,7,10,21,24,25,29,31,34],load_profusion_hypno:1,loadtxt:[24,26],loc:[1,5,7,25,33,35],locabsfallslop:25,locabsriseslop:25,locabsvalpeak:25,local:2,locat:[25,29,31],lock:1,log10:29,log:[4,9,14,18,20,25,29,31],longer:[1,4,14,15,18,24],longitudin:1,look:6,lookaround:[6,13],loop:[1,3],low:[3,7,35],lower:[1,4,10,11,12,14,20,24,30,31],lowercas:17,lowest:[1,6,7,8,35],lowpass:[5,6,8],lspopt:1,ltd:3,lv:9,lw:23,m1:[7,32],m2:[7,32],m:[6,7,9,25,26,27,31],machin:25,macroarchitectur:26,mai:[3,4,9,15,31],main:[1,7,9,34,35],mainli:35,maintain:34,mainten:[1,4,27],major:[1,7,9],majority_onli:7,make:[1,2,6,7,8,9,25,29,31,34,35],make_standard_montag:32,male:7,mani:[2,3],manipul:[1,4],manual:[1,3,4,6,7,8,14,27],map:[1,3,4,16,17,21,35],mapping_dict:[16,17],mapping_int:4,mark:[1,3,6,8,9,21],markov:[1,26],martin:31,mask:[1,5,6,8,10,14,25,29,31,32],massimini:[3,31],master:[1,7,9,10,20,24,25,26,29,31],mastoid:7,match:[3,4,6,8,13],matlab:3,matplotlib:[1,4,6,8,23,24,26,32,33],matric:[9,26],matrix:[1,4,6,8,9,26,28,33,34],matter:13,matthew:[3,34],max:[1,4,7,10,11,12,18,22,24,31,32],max_dist:[1,13],max_distance_sec:[6,8],maxim:3,maximum:[1,6,8,10,13,22,25,29,31,32],mayaud:9,mb:35,mcdevitt:25,me:[1,34],mean:[1,4,5,6,8,9,10,14,20,22,24,25,29,31,33,35],mean_direct:31,meant:26,measur:[6,8,14],median:[5,6,8,10,20,29],mediat:14,medic:[7,25],medicin:[4,7,9,27,35],mednick:25,memori:[4,6],mental:35,menu:3,merg:29,messag:[4,9,14,18,20,25,29,31],metadata:7,method:[1,3,4,5,6,7,8,9,20,22,25,29,31,34,35],metric:[6,8,13,14,33,35],metzner2021:26,metzner:[1,26],micro:[1,7,9,10,20,25,29,31],midcross:31,middl:[22,31,34],might:[3,13],million:35,millisecond:14,min:[1,7,10,11,12,22,24,32],min_dist:29,minim:25,minimum:[10,22,25,29,31,32],minor:1,minut:[1,4,14,15,26,27],misalign:35,miscellan:1,misclassif:7,misclassifi:3,miss:1,mix:4,mne:[1,3,4,5,6,7,8,9,10,18,20,25,29,31,32,34,35],mobil:7,mode:[6,8],model:[20,26],modifi:[1,3,4,6],modul:[1,3,7],montag:32,more:[1,2,4,6,7,8,9,10,11,12,14,15,21,24,25,26,29,31,32,34,35],most:[1,3,4,7,8,9,14,18,20,25,29,31,34,35],move:[1,3,22,29],movement:[9,10,14,24,25,27,29,31,34],ms:[6,8,14,22,29,30],mt:17,much:[9,30],multi:[1,6,8,9,24,29,31,34],multi_onli:29,multipl:20,multipli:25,multitap:[24,35],must:[2,4,6,8,9,10,11,12,13,14,24,25,26,29,31,32,33],my:[3,32],my_hypno_edfbrows:3,my_hypno_spisop:3,my_hypno_visbrain:3,myedffil:[3,34],myfil:7,n1:[3,4,7,9,10,14,16,17,21,23,24,25,26,27,29,31,33,35],n2:[3,4,7,9,10,14,16,17,21,23,24,25,26,27,29,31,35],n3:[3,4,9,10,14,16,17,21,23,24,25,27,29,31,35],n:[3,12,25,28,31],n_band:12,n_chan:[1,5,6,8,9,12,29,31],n_chan_reject:9,n_channel:[1,11,28],n_color:32,n_epoch:[1,4,9,12,21,28],n_event:[1,6,8],n_freq:[1,11,12],n_other:[6,8],n_sampl:[1,5,6,8,9,28,29,31],n_self:[6,8],n_stage:[1,4,23,26],n_time:[1,6,8],naiv:[26,34],name:[1,3,4,5,6,7,8,10,11,12,20,26,29,31,32,35],nan:[4,6,14],nap:7,nation:[1,7,21],nativ:21,nd:17,ndarrai:[1,7,12,14,20,24,30],ndpac:[1,31],nearest:[6,8],need:[1,2,4,18,34,35],neg:[1,6,13,25,31],negpeak:[1,6,31],nepoch_list:3,nepoch_nb:3,net:3,network:[1,6,8],neural:9,neurophysiolog:20,neurosci:[25,29,31,35],new_freq:4,new_n_stag:4,newer:1,newlin:3,next:[3,4,15,24,26,33,35],night:[1,3,7,9,24,34],niknazar:25,nois:9,non:[1,3,7,13,20,26,34],none:[1,4,5,6,7,8,9,10,11,14,18,20,22,23,24,25,26,28,29,30,31,32,35],nonlinear_featur:34,norm:[14,30],norm_direct_pac:31,normal:[1,7,14,24,29,30,31],note:[4,6,7,8,9,10,13,14,16,17,20,21,22,24,25,26,27,28,29,30,31,34],notebook:[1,3,7,9,10,14,20,24,25,26,29,31,32,34,35],notifi:3,now:[1,4,15,27,35],np:[1,3,4,6,8,10,14,22,24,26,28,31,33,35],nperseg:[22,30],npy:26,npz:[1,24],nrem:[1,4,27,29,31,35],nrow:[23,26],nsampling_period:3,nsrr:[1,21],numba:1,number:[1,4,5,6,7,8,9,10,14,15,18,24,25,26,29,31,32,33,35],numer:35,numpi:[1,2,3,6,7,8,12,14,20,24,26,28,30,33,34,35],numpydoc:2,nutshel:20,o1:35,o2:35,object:[1,4,9,26],obtain:[1,6,8,29],occur:[1,6,8,13,29],occurr:[1,6],octob:1,ocular:25,off:[9,26],offer:20,offici:27,offset:[4,20],often:3,ojeda:9,old:[1,35],older:3,omit:[4,9,10,18,20,29,31],onc:[1,3],one:[1,3,4,6,8,9,15,21,22,27,28,29,31,33,35],onli:[1,3,4,5,6,7,8,9,12,14,15,18,20,22,25,26,29,31,35],onlin:[1,4,9,26],onset:[1,3,4,13,27],open:[1,2,3,7,34,35],optim:[1,3,7],option:[1,4,5,6,7,8,10,13,20,22,23,24,34,35],order:[4,13],org:[1,3,4,7,20,26,32,34],orient:[1,4,33],origin:[4,8,20,29,33],oscil:[1,6,29,31,34],oscillatori:[1,20],other:[1,4,6,8,13,14,15,24,26,32],other_is_groundtruth:[6,8],otherwis:4,ouput:[5,6,8],our:[3,35],out:[1,3,4,22,27,34,35],outdat:1,outlier:[1,6,8,25,29,31],output:[1,4,5,6,8,14,15,18,22,25,29,30,31,35],outsid:[6,8,14],over:28,overal:[1,3,6,8],overlai:[1,6,8,34],overlap:[1,22,28,30],overnight:[1,34],overview:14,overwrit:24,own:[3,4,34,35],oz:32,p3:[32,35],p4:[32,35],p:[1,3,7,14,26,29,31,34],pac:[1,31],packag:[1,2,3,6,7,8,9,22,34,35],pad:[4,18],pair:[1,6,8,20],palett:[7,32,35],panda:[1,3,4,5,6,7,8,10,11,14,15,16,17,20,25,26,29,31,32,33,34,35],panel:34,paper:1,paquet:31,paramet:[1,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,35],part:[1,5,6,8],particip:[1,7],particular:3,pass:[1,2,4,5,6,8,9,10,18,20,24,25,26,31,32,35],past:[1,7],path:[7,21],path_to_model:7,patient:3,pd:[3,4,6,8,32,35],peak:[1,5,6,8,13,14,22,25,29,31,35],pearson:32,peer:7,penzel:27,pep8:2,peppard:29,per:[1,4,14,15,18,19,21,27,29,31,33,35],percentag:[4,27],percentil:[1,24],perfect:[6,8],perform:[1,3,6,7,8,9,13,14,22,29,30,31,34,35],period:[1,4,14,15,20,27,33,35],permut:7,persist:4,petrosian:7,pg:31,phase:[1,31,34],phaseatsigmapeak:[1,31],physic:1,pick_channel:[3,34],pingouin:31,pip:[1,2,3,34,35],pipelin:[1,3,34],place:[4,6,25,29,31],plai:[4,15],plausibl:4,pleas:[1,2,3,6,7,8,9,10,14,20,21,24,25,26,29,31,32,34,35],plot:[1,3,4,5,6,7,8,23,24,26,32,33,34],plot_averag:[1,5,6,8,35],plot_detect:[1,3,6,8],plot_hypnogram:[1,4,24,26,35],plot_predict_proba:7,plot_spectrogram:[1,3,35],plot_topomap:[1,32],plt:[23,26,33],pm:35,point:[1,3,6,7,8,9,29,30,31],pointwis:30,poirier:31,polysomnographi:[1,7,34],popul:3,portrai:26,posit:[1,6,8,9,13,29,31,32],pospeak:31,possibl:[1,3,6,8,13,14],post:[1,4,33],postdoctor:34,potato:9,potenti:[2,7],power:[1,7,10,11,12,20,29,30,34],pr42:1,pr:1,practic:1,pre:[1,4,7,9,11,33],precis:[1,6,8,13,22,30],pred:7,predict:[3,6,7,8,13,26,35],predict_proba:7,prefer:[6,8,13],preferenti:7,preload:[3,7,34,35],preprint:1,preprocess:[3,14,34],prerequisit:34,present:[6,8,9,29],pressman:27,previou:1,previous:[1,3,27,31],primari:14,primarili:1,primer:35,princip:35,print:[1,4,9,14,18,20,25,29,31,35],prior:[9,29],prob:[4,33,35],proba:7,probabilit:26,probabl:[1,4,7,26,33,34,35],process:1,produc:[6,8],product:[6,8,25],profus:[1,21],program:34,programm:3,promin:[1,8,25,29,35],prompt:[34,35],prop_above_zero:22,properli:2,properti:[4,25,29,31],proport:[4,6,8,22,29,35],propos:3,provid:[3,5,6,7,8,9,25,26,29,31,34,35],psd:[1,10,11,12,20,24],psd_aperiod:20,psd_oscillatori:20,psg:[7,35],ptp:[1,22,31],publish:[1,3],pull:34,purpl:7,purpos:[1,26],put:[1,29],py:1,pydata:[4,32],pyplot:[1,23,26,33],pyriemann:[1,9],pytest:2,python:[1,2,3,9,22,34,35],pz:[32,35],q:9,qiang:7,qualiti:[3,9],quantifi:35,question:[3,7],quickli:[1,3,6,8,35],quickstart:[1,34],r:[3,7,14,16,17,20,24,25,27,31,35],radian:[1,31],rais:1,randint:28,random:[4,25,26,28,29,31],rang:[1,7,14,20,24,25,29,30,31,32,35],rangeindex:4,raphael:[3,34],raphaelvallat:[1,3,7,9,10,20,24,25,26,29,31,35],rapid:[25,34],rate:[1,14,34],rater:[3,7],rather:3,ratio:[6,7,29],raw:[1,3,5,6,7,8,24,25,26,29,34,35],rawedf:35,rdbu_r:24,re:[1,3,24,35],reach:3,read:[24,34,35],read_csv:35,read_raw_edf:[3,7,34,35],readabl:1,reader:7,readm:1,readthedoc:[6,8,9],real:[26,34],real_hyp:26,realtim:3,reason:[3,7],recal:[1,6,8,13],recalcul:14,receiv:1,recent:1,reciproc:20,recommend:[1,2,3,9,33,34,35],record:[1,3,4,6,7,8,14,27,34,35],rectangular:30,rectbivariatesplin:30,redistribut:20,reduc:[1,4,6,8],refer:[1,4,6,7,8,9,10,13,14,20,21,24,25,26,27,29,31,32,34,35],referenc:7,reflect:14,regardless:[4,6,8],regress:22,rehabilit:9,reject:[9,34],rel:[1,7,10,11,12,25,29,35],rel_pow:29,relat:[31,35],relationship:[9,35],relative_promin:[1,25],releas:[1,3,29],relev:35,relpow:29,rem:[1,3,4,5,9,10,14,17,21,23,24,25,27,29,31,34,35],rem_detect:1,remain:[3,4,13,20],remaind:[4,15],remov:[1,3,4,9,15,25,29,31,35],remove_outli:[25,29,31],remrama:1,remresult:[1,25],rems_detect:34,renam:1,render:2,renner:6,reorgan:1,replac:[3,21],report:[2,3,4,27,34,35],repositori:34,repres:[3,4,31,35],represent:[34,35],reprocess:1,reproduc:[4,25,26,29,31,34],request:[24,34],requir:[1,3,6,7,8,25,26,35],resampl:[1,3,20,29,31,34,35],research:[1,7,21,34,35],resolut:[4,6,8,9,30,32],resourc:[1,7,21],respect:[4,6,8,15,18,31,35],restructuredtext:2,result:[1,3,4,6,7,8,9,13,14,18,20,25,26,28,29,31,33,35],return_fit:20,review:[1,7],rich:7,riemannian:9,right:[4,9,25,26,33,34],rise:25,rm:[1,22,29],rmssd:14,robillard:31,robust:7,roc:[1,5,25,35],rocabsfallslop:25,rocabsriseslop:25,rocabsvalpeak:25,rodent:3,roll:[1,7],root:[1,14,22,29],round:[4,6,8,26,33,35],row:[4,10,11,15,25,26,28,29,31,33,34,35],rpeak:14,rr:14,rr_limit:14,rule:[4,27,35],run:[1,2,3,6,7,8,9,15,25,31,34],run_visbrain:34,s10548:20,s1:[4,17],s2:17,s3:17,s42003:26,s4:[17,21],s:[2,3,4,6,7,8,11,15,20,25,26,27,29,31,34,35],safeti:1,sai:3,sake:[3,35],same:[1,3,4,6,8,9,10,13,14,15,18,20,22,24,25,29,30,31,35],sampl:[1,4,5,6,8,9,10,13,14,15,18,19,20,21,22,24,25,27,28,29,30,31,33,35],sampling_frequ:[1,4],sattari:25,save:[3,35],savetxt:3,scale:[1,6,7,8,24],scalp:3,schill:26,schulz:26,scienc:3,scientif:[7,35],scikit:1,scipi:[10,11,12,20,30],score:[1,3,4,6,7,8,9,13,27,29,31,35],scorer:[1,3,4,7],screenshot:3,scroll:[3,35],se:[4,27,35],seaborn:[1,5,6,8,32,33],search:13,sec:[1,4,6,7,15,22,24,31],second:[1,3,4,5,6,7,8,9,10,13,14,15,18,19,20,21,22,24,25,26,27,28,29,30,31,33,34,35],section:[1,7,35],see:[1,2,3,4,6,8,9,11,12,13,14,20,26,34,35],seed:[4,23,25,26,28,29,31],seem:1,seemingli:1,segment:[4,15],select:[1,3,29,34,35],self:[4,6,7,8],semilog:20,sens:34,sensit:[6,8,9,13],sep:3,separ:[3,9,14,20,34,35],sequenc:[1,4,15,26],sequenti:10,seri:[1,3,4,16,17,22,26,32],serv:3,set:[1,4,6,7,13,14,28,31,34],set_label_posit:33,set_titl:26,set_xlabel:33,set_ylabel:33,setup:3,sever:[1,3,33,35],sex:[1,7],sf:[1,4,5,6,8,9,10,14,20,22,24,25,28,29,30,31,35],sf_data:[4,18,19],sf_hyp:[21,27,35],sf_hypno:[15,18,19,35],sfi:4,sfreq:35,shaffer:14,shape:[1,4,5,6,8,9,11,12,18,28,29,30,31,35],shortcut:4,shorter:[4,9,18,26],should:[1,3,4,6,7,8,10,13,20,26,27,29,31,34,35],shoutout:1,show:[3,34,35],shown:[3,6,8,34,35],shyp:4,side:31,sigma:[1,8,10,11,12,29,31],sigma_coupl:34,sigmapeak:[1,31],signal:[1,6,7,8,9,10,11,12,20,22,25,28,29,31,35],signatur:9,signific:[1,32,35],significantli:1,silber:[4,27],similar:[3,26],similarli:[1,35],simpl:[1,3,13,34],simpler:1,simplest:[2,3],simpli:[1,3,6,8,9,20,26,34,35],simul:[1,4,26],simulate_hypno:1,simulate_hypnogram:[1,4,23],simulate_similar:[4,26],sinc:[27,31,35],singl:[1,9,14,22,24,29,30,31,34,35],situat:2,size:[1,5,6,8,22,28,30,32],skew:7,sklearn:[1,25,29,31,35],sl:[7,35],sleep:[1,4,5,6,7,8,9,10,14,15,16,17,18,19,21,24,25,26,27,29,31,33,34],sleep_statist:[1,4,26,35],sleepecg:[1,13,14],sleepstag:[1,3,35],slep:35,slide:[10,20,24,28],sliding_window:1,slight:1,slightli:[1,3,26],slope:[20,22,25,31,34],slow:[1,3,6,13,31,34],slower:[22,30],slowest:[22,30],sme:[1,4,27,35],smooth:[3,7],sn:33,so:[1,3,6,27,34],societi:9,soft:1,softwar:[3,34,35],sol:[4,27,35],sol_5min:4,sole:20,solv:1,some:[1,3,4,6,7,8,9,13,26,34],soon:9,sophas:29,sort:[5,6,8],sourc:[3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34],sp:[1,29,35],space:[20,23],span:35,specest:20,specif:[1,3,4,5,6,7,8,9,15,27,31,34],specifi:[1,4,10,11,30,31,35],specifici:26,spectra:20,spectral:[1,10,11,12,20,34],spectral_r:24,spectrogram:[3,24,34],spectrum:[6,20,34,35],speed:[1,3,35],spell:4,sphinx:2,sphinx_bootstrap_them:2,spindl:[1,3,6,8,13,29,31,34],spindles_detect:[1,34,35],spindles_detect_multi:1,spindles_detection_multi:34,spindles_detection_nrem_onli:34,spindles_slow_fast:34,spindlesresult:[1,6,29],spisop:3,spline:30,spt:[1,4,27,33,35],squar:[1,14,22,29,33],squeez:35,stabil:[33,35],stabl:1,stage:[1,4,5,6,7,8,9,10,14,15,16,17,18,19,23,24,25,26,27,29,31,33,34],stair:1,standard:[1,2,3,4,7,9,10,14,27,29,31,34,35],standard_1020:32,start:[1,2,3,4,6,8,13,14,15,23,25,28,29,31,33,35],stat:[4,27],state:[1,4,33,35],statist:[1,4,20,26,27,31,34],statu:7,std:9,step:[1,3,20,22,25,28,29,30,31,34,35],stft:30,still:1,stochast:[4,26,33],store:[1,3,4],str:[4,5,6,7,8,9,14,15,18,20,21,22,23,24,25,29,31,32],straightforward:[9,35],stratifi:34,stream:24,strict:34,stride:28,stride_trick:28,string:[1,4,16,17,26],strong:1,strongest:1,strongli:34,studi:[1,6,25,35],style:2,sub:[1,4,7,14,15,31],subject:26,submit:34,subplot:[23,26,33],subsequ:[14,26],subset:[3,34],succesfulli:[6,8],success:14,suggest:1,sum:[1,4,6,8,26,27,30,33],sum_i:9,summar:4,summari:[1,4,5,6,8,25,29,31,35],sunflow:7,supplementari:26,support:[1,3,4,7,9,12],sure:[1,2,6,7,8,9,25,29,31,34,35],sw:[1,6,31,35],sw_detect:[1,34,35],sw_detect_multi:1,sw_detection_multi:34,swresult:[1,31],sxx:30,symmetr:[6,8,9],symmetri:29,sync:35,synchron:[1,5,6,8],system:[1,7,9],t3:35,t4:35,t5:35,t6:35,t:[3,6,9,22,25,27,30],tab:3,take:[4,9,20,29,31,33,35],taken:1,takeuchi:25,taper:[24,34],technic:[4,27],technician:35,tell:[4,15,35],templat:[1,34],tempor:[1,3],ten:1,tend:1,tensorpac:[1,31],term:29,termin:[3,34,35],terminolog:[4,27],test:[1,2,6,8,26],teuniz:3,text:[3,20,35],than:[1,4,9,14,15,18,24,25,29,30,31,34,35],thei:[1,2,3,13,29,34,35],them:[2,13],therefor:[1,3,4,6,7,8,9,13,15,18,25,35],theta:[10,11,12,35],thi:[1,2,3,4,5,6,7,8,9,10,12,13,14,15,16,17,18,20,22,24,25,26,28,29,31,32,34,35],think:1,thistl:23,those:[1,2,6,8,26],though:13,thousand:3,three:[1,6,8,14],thresh:29,threshold:[1,3,4,6,8,9,14,15,25,29,31,35],through:[1,3,29,31,35],thu:[1,27],tib:[1,4,23,26,27,33,35],tick:32,tick_top:33,tight_layout:[23,26],time:[1,3,4,5,6,8,9,10,14,20,22,25,26,27,28,29,30,31,33,34,35],time_aft:[1,5,6,8],time_bas:3,time_befor:[1,5,6,8],timedelta:4,timedeltaindex:4,timepoint:[1,5,6,8],timeseri:4,timestamp:[1,6],titl:[3,32],to_csv:[3,4,35],to_numpi:3,tobi:9,togeth:3,toler:1,tononi:31,too:[1,9,29,31],tool:[3,7,9,20,34],toolbox:[3,34],top:[3,24,33,34,35],topograph:34,topographi:20,topoplot:[1,34,35],total:[1,4,7,10,11,12,26,27,29,35],totalabspow:1,toward:7,tp:13,train:[1,3,7,35],tramat_epoch:26,trans_proba:26,transact:[9,25],transform:[1,7,9,22,29],transform_sign:22,transit:[1,4,26,29,31,33,34],transition_matrix:[1,4,26,35],translat:21,travel:31,travi:1,traxdorf:26,triangular:7,trim:[1,24],trimbothstd:1,trimperc:24,trough:31,truth:[1,6,8,13,35],tst:[1,4,27,35],tune:3,tupl:[5,6,8,9,10,11,12,14,20,25,29,30,31,32],tutori:[1,31,32,34,35],tweak:[6,8],twice:24,twilight:7,two:[1,3,4,5,6,8,10,13,15,20,21,22,29,35],txt:[3,24,26],type:3,typic:9,u:22,uc:34,un:[1,4,16,17,23,26,27],underli:35,understand:14,unecessari:1,unfortun:1,uniqu:[4,6,8,26],unit:[1,9,25,29,31,35],unreli:[1,31],unscal:8,unscor:[1,4,9,10,14,24,25,26,27,29,31,33],until:3,up:[3,7,35],updat:[1,2,3,6],upgrad:[1,2,3,34,35],upon:1,upper:[1,4,10,11,12,14,24,31],uppercas:4,upsampl:[1,4,9,10,14,18,19,23,24,25,29,31,33,35],upsample_to_data:[1,4],url:[3,26],us:[1,2,3,4,5,6,7,8,9,10,13,14,15,20,22,24,25,26,27,29,30,31,32,33,34,35],usag:[1,4],user:[1,3,4,7,9,14,18,20,25,26,29,31,34,35],user_guid:4,userwarn:[4,18],usual:[6,8,22,30],utf:3,uv:[1,7,9,11,12,25,29,31,35],v0:4,vagal:14,val:4,valid:[1,3,4,7,32],vallat2021open:3,vallat:[3,7,34],valnegpeak:31,valpospeak:31,valu:[1,4,6,8,9,10,13,14,15,18,19,20,21,22,23,24,25,26,27,29,30,31,32,33,35],values_str:26,vandewal:31,vari:[3,20,29,35],variabl:[1,6,8,14,34,35],varianc:[9,14],variou:2,various:20,ve:[1,34],vector:[1,4,5,6,8,9,10,14,15,20,22,24,25,27,28,29,30,31],vector_length:31,verbos:[1,4,9,14,18,20,25,29,31,35],veri:[3,7,9,13,35],version:[3,4,6,7,8,9,10,11,12,14,15,16,17,18,19,20,23,24,25,26,27,28,29,31,32,33,35],versu:34,via:[1,3,30],vien:31,viewabl:26,visbrain:[1,3,34],visit:34,visual:[4,7,9,27,34,35],viz:[1,32],vmax:[1,24,32,33],vmin:[1,24,32,33],volt:[1,7,9,10,20,25,29,31],volum:3,w:[1,3,4,16,17,23,27,35],wa:[1,3,5,6,7,8,22,25,29,31,33,34,35],wai:[1,2,3,6,8],wake:[3,4,7,9,10,14,15,17,21,24,25,26,27,29,31,33,35],walk:26,walker:[3,7,34],walkthrough:29,want:[1,2,3,4,6,8,14,15,31,34],warbi:29,warmer:35,warn:[1,4,9,14,18,20,25,29,31],warranti:34,waso:[1,4,27,35],watch:3,wave:[1,3,6,13,31,34],we:[1,2,3,4,7,9,13,15,24,27,33,34,35],weak:1,wearabl:4,web:34,websit:[1,21],weight:7,welch:[10,11,12,20],welcom:34,well:[1,3,4,6,7,8,10,11,12,35],wen:20,were:[1,6,7,8],what:[4,6,8,14,33,34,35],when:[1,2,3,5,6,7,8,9,10,13,24,25,29,31],whenev:[3,35],where:[3,4,5,6,8,9,10,14,15,20,24,25,26,27,28,29,31,35],wherea:20,whether:[1,3,4,6],which:[1,3,4,5,6,7,8,9,10,11,12,13,15,18,20,21,23,28,29,30,31,35],whitehurst:25,whitesmok:23,whole:34,wide:[7,31],widget:[6,8],width:32,wiki:21,win:3,win_sec:[10,20,24],window:[1,3,6,9,10,13,20,22,24,28,30],wish:15,within:[1,2,4,6,8,27,31],without:33,wonambi:22,word:[1,3,4,15],work:[1,3,6,7,8,9,26,34],workshop:9,would:[3,13],wrapper:[1,6,8,9,16,17,28,32],www:[3,20],x:[4,6,8,22,26,28,35],xaxi:33,xkcd:7,xml:[1,21],xs:35,y:[6,8,22,35],yasa:[1,3,35],yasa_classifi:[3,7],yasa_example_night_young:35,yasa_example_night_young_hypno:35,year:[3,7,31,35],yet:34,yetton:25,ylorrd:33,you:[1,2,3,6,7,8,9,14,15,29,31,34,35],your:[1,2,3,7,9,10,14,24,25,29,31,34,35],z:[1,7,9,20,31],zero:[1,7,13,22,31],zhang:7,zink:6,zsaa290:6,zscore:9},titles:["API reference","What\u2019s new","Contribute to YASA","FAQ","yasa.Hypnogram","yasa.REMResults","yasa.SWResults","yasa.SleepStaging","yasa.SpindlesResults","yasa.art_detect","yasa.bandpower","yasa.bandpower_from_psd","yasa.bandpower_from_psd_ndarray","yasa.compare_detection","yasa.hrv_stage","yasa.hypno_find_periods","yasa.hypno_int_to_str","yasa.hypno_str_to_int","yasa.hypno_upsample_to_data","yasa.hypno_upsample_to_sf","yasa.irasa","yasa.load_profusion_hypno","yasa.moving_transform","yasa.plot_hypnogram","yasa.plot_spectrogram","yasa.rem_detect","yasa.simulate_hypnogram","yasa.sleep_statistics","yasa.sliding_window","yasa.spindles_detect","yasa.stft_power","yasa.sw_detect","yasa.topoplot","yasa.transition_matrix","Installation","Quickstart"],titleterms:{"0":1,"1":1,"2":1,"2020":1,"2021":1,"2022":1,"2024":1,"3":1,"4":1,"5":1,"6":1,"7":1,"do":34,"new":1,analys:[0,35],analysi:0,api:0,art_detect:9,august:1,automat:[0,35],band:35,bandpow:10,bandpower_from_psd:11,bandpower_from_psd_ndarrai:12,build:2,check:2,citat:34,code:2,compare_detect:13,content:[1,35],contribut:2,data:[3,35],decemb:1,detect:[0,3,35],dev:1,develop:34,document:2,eeg:35,event:[0,3,35],faq:3,februari:1,frequenc:35,full:35,galleri:34,get:34,guidelin:2,heart:0,how:34,hrv_stage:14,hypno_find_period:15,hypno_int_to_str:16,hypno_str_to_int:17,hypno_upsample_to_data:18,hypno_upsample_to_sf:19,hypnogram:[0,4,35],i:34,instal:34,irasa:20,januari:1,load:[3,35],load_profusion_hypno:21,mai:1,march:1,matrix:35,moving_transform:22,night:35,novemb:1,older:1,other:3,plot:35,plot_hypnogram:23,plot_spectrogram:24,polysomnographi:[3,35],power:35,preprocess:35,prerequisit:35,quickstart:35,rate:0,refer:0,rem_detect:25,remresult:5,s:1,simulate_hypnogram:26,sleep:[0,3,35],sleep_statist:27,sleepstag:7,sliding_window:28,slow:35,specif:35,spectral:[0,35],spectrogram:35,spindl:35,spindles_detect:29,spindlesresult:8,stage:[0,3,35],start:34,statist:[0,35],stft_power:30,sw_detect:31,swresult:6,tabl:1,topoplot:32,transit:35,transition_matrix:33,v0:1,version:1,visual:3,wave:35,what:1,yasa:[2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34]}})
\ No newline at end of file
+Search.setIndex({docnames:["api","changelog","contributing","faq","generated/yasa.EpochByEpochAgreement","generated/yasa.Hypnogram","generated/yasa.REMResults","generated/yasa.SWResults","generated/yasa.SleepStaging","generated/yasa.SleepStatsAgreement","generated/yasa.SpindlesResults","generated/yasa.art_detect","generated/yasa.bandpower","generated/yasa.bandpower_from_psd","generated/yasa.bandpower_from_psd_ndarray","generated/yasa.compare_detection","generated/yasa.hrv_stage","generated/yasa.hypno_find_periods","generated/yasa.hypno_int_to_str","generated/yasa.hypno_str_to_int","generated/yasa.hypno_upsample_to_data","generated/yasa.hypno_upsample_to_sf","generated/yasa.irasa","generated/yasa.load_profusion_hypno","generated/yasa.moving_transform","generated/yasa.plot_hypnogram","generated/yasa.plot_spectrogram","generated/yasa.rem_detect","generated/yasa.simulate_hypnogram","generated/yasa.sleep_statistics","generated/yasa.sliding_window","generated/yasa.spindles_detect","generated/yasa.stft_power","generated/yasa.sw_detect","generated/yasa.topoplot","generated/yasa.transition_matrix","index","quickstart"],envversion:{"sphinx.domains.c":2,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":4,"sphinx.domains.index":1,"sphinx.domains.javascript":2,"sphinx.domains.math":2,"sphinx.domains.python":3,"sphinx.domains.rst":2,"sphinx.domains.std":2,"sphinx.ext.intersphinx":1,"sphinx.ext.viewcode":1,sphinx:56},filenames:["api.rst","changelog.rst","contributing.rst","faq.rst","generated/yasa.EpochByEpochAgreement.rst","generated/yasa.Hypnogram.rst","generated/yasa.REMResults.rst","generated/yasa.SWResults.rst","generated/yasa.SleepStaging.rst","generated/yasa.SleepStatsAgreement.rst","generated/yasa.SpindlesResults.rst","generated/yasa.art_detect.rst","generated/yasa.bandpower.rst","generated/yasa.bandpower_from_psd.rst","generated/yasa.bandpower_from_psd_ndarray.rst","generated/yasa.compare_detection.rst","generated/yasa.hrv_stage.rst","generated/yasa.hypno_find_periods.rst","generated/yasa.hypno_int_to_str.rst","generated/yasa.hypno_str_to_int.rst","generated/yasa.hypno_upsample_to_data.rst","generated/yasa.hypno_upsample_to_sf.rst","generated/yasa.irasa.rst","generated/yasa.load_profusion_hypno.rst","generated/yasa.moving_transform.rst","generated/yasa.plot_hypnogram.rst","generated/yasa.plot_spectrogram.rst","generated/yasa.rem_detect.rst","generated/yasa.simulate_hypnogram.rst","generated/yasa.sleep_statistics.rst","generated/yasa.sliding_window.rst","generated/yasa.spindles_detect.rst","generated/yasa.stft_power.rst","generated/yasa.sw_detect.rst","generated/yasa.topoplot.rst","generated/yasa.transition_matrix.rst","index.rst","quickstart.rst"],objects:{"yasa.EpochByEpochAgreement":[[4,1,1,"","__init__"],[4,2,1,"","data"],[4,1,1,"","get_agreement"],[4,1,1,"","get_agreement_bystage"],[4,1,1,"","get_confusion_matrix"],[4,1,1,"","get_sleep_stats"],[4,1,1,"","multi_scorer"],[4,2,1,"","n_sleeps"],[4,2,1,"","obs_scorer"],[4,1,1,"","plot_hypnograms"],[4,2,1,"","ref_scorer"],[4,1,1,"","summary"]],"yasa.Hypnogram":[[5,1,1,"","__init__"],[5,1,1,"","as_annotations"],[5,1,1,"","as_int"],[5,1,1,"","consolidate_stages"],[5,1,1,"","copy"],[5,2,1,"","duration"],[5,1,1,"","evaluate"],[5,1,1,"","find_periods"],[5,2,1,"","freq"],[5,2,1,"","hypno"],[5,2,1,"","labels"],[5,2,1,"","mapping"],[5,2,1,"","mapping_int"],[5,2,1,"","n_epochs"],[5,2,1,"","n_stages"],[5,1,1,"","plot_hypnogram"],[5,2,1,"","sampling_frequency"],[5,2,1,"","scorer"],[5,1,1,"","simulate_similar"],[5,1,1,"","sleep_statistics"],[5,2,1,"","start"],[5,2,1,"","timedelta"],[5,1,1,"","transition_matrix"],[5,1,1,"","upsample"],[5,1,1,"","upsample_to_data"]],"yasa.REMResults":[[6,1,1,"","__init__"],[6,1,1,"","get_mask"],[6,1,1,"","get_sync_events"],[6,1,1,"","plot_average"],[6,1,1,"","summary"]],"yasa.SWResults":[[7,1,1,"","__init__"],[7,1,1,"","compare_channels"],[7,1,1,"","compare_detection"],[7,1,1,"","find_cooccurring_spindles"],[7,1,1,"","get_coincidence_matrix"],[7,1,1,"","get_mask"],[7,1,1,"","get_sync_events"],[7,1,1,"","plot_average"],[7,1,1,"","plot_detection"],[7,1,1,"","summary"]],"yasa.SleepStaging":[[8,1,1,"","__init__"],[8,1,1,"","fit"],[8,1,1,"","get_features"],[8,1,1,"","plot_predict_proba"],[8,1,1,"","predict"],[8,1,1,"","predict_proba"]],"yasa.SleepStatsAgreement":[[9,1,1,"","__init__"],[9,2,1,"","assumptions"],[9,2,1,"","auto_methods"],[9,1,1,"","calibrate"],[9,2,1,"","data"],[9,1,1,"","get_calibration_func"],[9,1,1,"","get_table"],[9,2,1,"","n_sessions"],[9,2,1,"","obs_scorer"],[9,2,1,"","ref_scorer"],[9,2,1,"","sleep_statistics"],[9,1,1,"","summary"]],"yasa.SpindlesResults":[[10,1,1,"","__init__"],[10,1,1,"","compare_channels"],[10,1,1,"","compare_detection"],[10,1,1,"","get_coincidence_matrix"],[10,1,1,"","get_mask"],[10,1,1,"","get_sync_events"],[10,1,1,"","plot_average"],[10,1,1,"","plot_detection"],[10,1,1,"","summary"]],yasa:[[4,0,1,"","EpochByEpochAgreement"],[5,0,1,"","Hypnogram"],[6,0,1,"","REMResults"],[7,0,1,"","SWResults"],[8,0,1,"","SleepStaging"],[9,0,1,"","SleepStatsAgreement"],[10,0,1,"","SpindlesResults"],[11,3,1,"","art_detect"],[12,3,1,"","bandpower"],[13,3,1,"","bandpower_from_psd"],[14,3,1,"","bandpower_from_psd_ndarray"],[15,3,1,"","compare_detection"],[16,3,1,"","hrv_stage"],[17,3,1,"","hypno_find_periods"],[18,3,1,"","hypno_int_to_str"],[19,3,1,"","hypno_str_to_int"],[20,3,1,"","hypno_upsample_to_data"],[21,3,1,"","hypno_upsample_to_sf"],[22,3,1,"","irasa"],[23,3,1,"","load_profusion_hypno"],[24,3,1,"","moving_transform"],[25,3,1,"","plot_hypnogram"],[26,3,1,"","plot_spectrogram"],[27,3,1,"","rem_detect"],[28,3,1,"","simulate_hypnogram"],[29,3,1,"","sleep_statistics"],[30,3,1,"","sliding_window"],[31,3,1,"","spindles_detect"],[32,3,1,"","stft_power"],[33,3,1,"","sw_detect"],[34,3,1,"","topoplot"],[35,3,1,"","transition_matrix"]]},objnames:{"0":["py","class","Python class"],"1":["py","method","Python method"],"2":["py","property","Python property"],"3":["py","function","Python function"]},objtypes:{"0":"py:class","1":"py:method","2":"py:property","3":"py:function"},terms:{"0":[3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37],"00":[1,5,9,25,28,35,37],"000":5,"006":5,"009ddc":8,"00x":9,"01":[4,5,25,37],"010":5,"01196953210011":37,"013":5,"015":22,"016":17,"01_spindles_detect":31,"02":5,"0201":5,"021":[5,28],"029":5,"02912":28,"02_spindles_detection_multi":31,"033":5,"03333333333333333":25,"038":5,"03_spindles_detection_nrem_onli":31,"0448":22,"045":5,"04_spindles_slow_fast":31,"05":[9,22,33,35],"05_sw_detect":33,"06":[4,5,9],"067":5,"06_sw_detect":1,"07":4,"07897545357524":37,"07_rems_detect":27,"08":37,"08_bandpow":12,"0909":5,"09_irasa":22,"0f":4,"0min":[5,16,17],"0sec":[5,17],"1":[3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37],"10":[1,3,4,5,8,9,22,28,29,30,33,36],"100":[1,3,4,5,7,8,10,15,20,21,24,26,29,30,31,33,34,36,37],"1000":5,"1007":22,"1015":37,"103":9,"1038":28,"105":9,"106":1,"107":1,"108":1,"1093":[4,9],"10_bandpow":1,"11":[4,5,17,25,30,31,37],"1101":[1,22],"112":4,"115":1,"1151":8,"1164":8,"1176":5,"119":1,"12":[1,4,5,7,9,10,12,13,14,15,30,31,33,37],"120":[5,9],"121":[4,5,29],"122":9,"124":4,"128":[1,31,33],"13":[4,5,9,22,30,37],"130":1,"131":[4,5,29],"1351":8,"1358":8,"139":4,"1390":27,"1396":27,"13_artifact_reject":11,"14":[4,5,17,30,34,35,37],"142":37,"147":9,"14_automatic_sleep_stag":8,"15":[1,4,5,22,30,31,34],"150":[1,5,9,16,33],"151":1,"153":5,"15_topoplot":1,"15min":[5,16,17],"16":[4,5,10,12,13,14,17,30,33,37],"160":4,"166":1,"16_eeg":1,"16hz":1,"17":[4,9,30,37],"171":1,"18":[1,4,15,29,30,37],"180":5,"181":4,"183":4,"184":4,"185":4,"189":4,"19":[1,4,11,30,37],"191":4,"1d":[5,11,12,16,17,18,19,20,21,22,23,25,26,27,29,30,31,33],"1hour":[5,16,17],"1hz":1,"1min":5,"2":[3,4,5,7,8,9,11,12,13,14,15,16,17,18,19,22,23,25,26,27,28,29,30,31,32,33,34,35,37],"20":[4,5,9,11,15,29,30,35],"200":[1,32,33,37],"2000":16,"2004":[3,33],"2005":27,"2007":[5,29],"2011":[3,33],"2013":11,"2016":[8,22,27],"2017":16,"2018":[1,3,8,31,37],"2019":[1,11],"2021":[3,4,7,8,9,10,22,28,36],"2022":[5,25],"204":4,"209":4,"21":[4,5,30],"210":4,"214":37,"216":5,"22":[1,4,5,9,37],"227":[4,5],"228":4,"23":[1,4,5,9,25,37],"230":4,"231":5,"233":4,"234":4,"24":[4,5,33],"240":5,"244":11,"247":5,"24min":25,"25":[4,5,8,9,17,22,26,29,31,35,37],"252":4,"255":[4,11],"256":[1,5,20,21],"258":16,"259":27,"26":[4,5,15,22,30],"263":4,"266mb":37,"268":4,"27":[9,11],"275":4,"276":4,"28":[4,9,30],"284":4,"285":4,"287":4,"28920":37,"2892000":37,"29":[1,4,5,8,22,30],"296":4,"298":4,"299":4,"299859v1":22,"2bfz":26,"2bpz":26,"2d":[5,12,20,22,30,32],"2f":35,"2min":[5,16,17],"3":[3,4,5,7,9,10,11,12,14,16,17,18,19,22,23,24,25,26,27,28,29,30,31,32,33,34,35,37],"30":[1,3,4,5,6,7,8,9,10,12,13,14,16,17,20,21,22,23,25,26,28,29,30,31,32,35,36,37],"300":[1,25],"3000":[1,8],"30sec":[5,16,17],"31":[4,5,25,29,30,33,37],"313":4,"3166":5,"317":37,"32":[4,5,9],"321":4,"325":27,"326":4,"329":4,"33":[1,4,30,33],"33195020746888":37,"333":37,"3333":37,"33878878":9,"34":[4,9,15,30],"35":[4,22],"350":[1,33],"3508":5,"355":5,"362":4,"369":4,"37":[5,30],"371":4,"38":9,"384":4,"39":8,"391":4,"39752335":9,"398":5,"3f":37,"3kb":37,"3rd":4,"4":[4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,22,23,25,26,27,28,29,30,31,32,33,34,37],"40":[3,4,5,6,7,9,10,12,13,14,33,35,36,37],"400":[1,16],"407":4,"41":[5,9,15,30],"413":4,"418":5,"42":[4,5,9,27,30,31,33],"420":4,"4221":5,"4271":5,"43":[4,30,35],"4306":5,"433":[4,9],"439":9,"44":[4,7,9],"447":5,"45":[5,22,37],"459":37,"46":[9,30,37],"463":9,"464483":[1,22],"467":4,"468":37,"469":9,"47":[4,5,30],"477":5,"48":[5,30],"480":[5,28],"482":37,"483":9,"489":9,"49":[5,9,30],"497":5,"4hz":37,"5":[3,4,5,6,7,8,9,10,11,12,13,14,15,17,18,19,20,21,22,23,26,27,28,29,30,31,33,34,35,37],"50":[1,4,9,27,30,31,33,35],"500":[1,5,7,10,31],"5072":5,"51":30,"514":35,"515":5,"519":4,"52":[27,30],"524":5,"525":9,"53":[5,9],"531":9,"54":[1,4],"540":[7,10],"544":9,"55":[9,15,22,34],"550":[5,9],"5555555555555556":15,"55x":9,"57":[1,9,15,30],"572361262241564":37,"5784000":37,"58":4,"59":[5,37],"5b":[1,28],"5hz":31,"5min":[5,16,17],"6":[4,5,6,7,9,10,12,16,17,22,25,28,29,30,31,33],"60":[4,5,17,26,30,35],"600":[4,9],"607181719260065":37,"625":15,"63":[15,30],"64":5,"65":[22,31],"66":[5,30],"6667":5,"67":[5,9],"676":37,"68":[1,4,15,37],"6862":33,"6870":33,"69":[5,9,30],"7":[4,5,8,9,17,22,28,29,30,34],"70":1,"70092":[3,8,36],"71":[1,4,9,15,30],"7142857142857143":15,"7177":5,"72":27,"739":5,"74":30,"75":[1,22,29,31,33],"7538":5,"7554":[3,8,36],"758":33,"76":5,"766":33,"77":37,"7777777777777778":15,"78":4,"79":[5,30],"8":[1,3,4,5,7,9,12,13,14,22,26,27,28,29,30,34,37],"80":[1,29,30,34],"808487486398259":37,"82":[5,27,37],"825":9,"83":[5,30],"8342":5,"84":[5,9],"85":[1,3,22,37],"86":30,"86815607":9,"87":[9,30],"875":15,"88":[5,30],"8889":5,"89":30,"9":[1,4,5,9,17,22,28,29,30,35,37],"90":[4,5,30],"91":30,"914":5,"9167":5,"92":[5,30],"9231":5,"92689064":9,"929":5,"93":30,"933":5,"94":5,"95":[9,37],"959":37,"96":[5,9],"960":37,"961":37,"962":37,"963":37,"964":37,"97":[26,30],"9713":5,"98":[30,37],"98803046789989":37,"99":[5,25,30],"99d7f1":8,"\u00b5v":31,"\u03bcv":37,"barth\u00e9lemi":11,"boolean":[6,7,8,9,10,12,13,14,22,24,27,31,32,33],"break":1,"case":[5,7,8,10,11,12,20,22,31,33],"class":[1,3,4,5,6,7,8,9,10,11,37],"default":[1,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,20,22,23,24,26,27,28,29,30,31,32,33,37],"do":[2,3,7,8,10,15,33,37],"export":[3,8,37],"final":[3,15,35,37],"float":[1,4,5,6,7,9,10,11,12,16,17,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34],"function":[1,2,3,4,5,6,7,9,10,11,12,14,15,16,17,18,19,22,24,30,31,33,36,37],"import":[1,3,4,5,7,8,9,10,15,17,25,26,28,29,30,33,34,35,36,37],"int":[5,11,12,15,16,17,22,24,26,27,28,30,31,32,33,34],"long":[6,7,9,10,31,33,36],"new":[2,3,4,5,7,8,9,10,11,12,13,14,16,17,18,19,20,21,22,25,26,27,28,29,30,31,33,34,35,37],"pi\u00e9ron":9,"public":[1,3,8,11,16,28,29,36,37],"return":[1,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35],"short":[11,31,36],"static":4,"super":28,"switch":1,"true":[1,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,20,22,23,24,25,26,27,31,32,33,35,36,37],"try":[36,37],"while":[3,5,29],A:[3,4,5,7,8,9,10,11,15,16,17,24,25,27,28,29,30,31,32,34,35,36,37],AND:[12,22,26],As:[1,3,5,37],Be:8,By:16,For:[1,3,4,5,6,7,8,9,10,11,12,15,16,17,20,22,23,26,27,31,33,34,35,36,37],IN:7,If:[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,20,22,23,24,27,28,30,31,32,33,34,36,37],In:[1,3,5,8,11,17,22,26,37],Is:[7,10],It:[1,3,4,7,10,11,22,33,37],NO:36,NOT:8,OF:36,One:[1,7,10],Such:3,That:[1,5,16,17],The:[1,2,3,4,5,7,8,9,10,11,12,15,16,17,18,19,20,21,22,23,25,26,27,28,29,30,31,32,33,34,35,36,37],Then:[3,11],There:[2,3,15,17,37],These:[8,15],To:[1,2,3,4,5,7,10,11,12,16,17,26,27,31,33,35,36,37],With:30,_:35,__init__:[4,5,6,7,8,9,10],_ch_name:[6,7,10],_data:[6,7,10],_data_filt:[6,7,10],_event:[6,7,10],_hypno:[6,7,10],_sf:[6,7,10],a1:[3,36,37],a2:[3,36,37],aasm:[1,5,29,37],abbrevi:5,about:[1,2],abov:[11,24,25,31],absolut:[1,8,27,31,33,37],abspow:31,academi:[5,29,37],acc:4,accept:[3,4,5,7,10],access:[1,5,37],accident:1,accompani:2,account:[1,4,11],accumul:5,accur:[3,11,28],accuraci:[1,3,4,5,8,37],accuracy_scor:37,across:[1,3,4,6,7,10,16,28,36,37],actigraphi:5,activ:[7,10,37],actual:[5,15,27],ad:[1,2,3,4,22,33],adapt:[3,11],add:[1,3,7,28,36],addit:[1,3,4,8],address:1,adequ:3,adjust:[3,9,37],adjust_al:9,adopt:1,adult:[3,5,29],advanc:16,advantag:[1,3],aesthet:1,affect:1,after:[2,5,6,7,10,15,29],ag:[1,8],against:[1,3,7,10,15,37],agarw:27,agg:4,agg_func:4,aggfunc:[1,6,7,10],aggreg:4,agr:4,agreement:[1,3,4,5,7,8,9,10,37],aka:[1,5,7,10,15,37],al:[1,3,4,5,8,9,28,37],alan:4,algorithm:[1,3,8,27,31,33,36,37],alias:5,all:[1,2,3,4,5,6,7,9,10,11,15,16,17,27,29,31,32,34,36,37],allow:[1,5,28,37],almost:37,along:1,alpha:[4,9,12,13,14,37],alreadi:[1,3,5,29],also:[1,2,3,5,7,8,10,11,12,20,22,29,31,33,36,37],altern:[25,36],altman:9,alwai:[1,3,5,7,8,9,10,37],am:[3,37],american:[5,8,29,37],amount:[3,5,26],amp_neg:33,amp_po:33,amp_ptp:33,amplitud:[1,6,7,10,24,27,31,33,36,37],an:[1,2,3,4,5,6,7,8,9,10,11,12,16,17,18,20,22,27,28,29,31,33,35,36,37],anaconda:[36,37],analys:[1,9,36],analysi:[1,3,9,16,22,28,36,37],analyticalpipeline_v1:[4,9],analyz:37,ancoli:29,andreev:11,ani:[1,4,5,8,11,17,29,31,33,35,36],anim:3,annot:[1,3,5,7,10,15,23,35],anot:3,anoth:[1,4,7,10,36],answer:8,anthoni:4,antropi:[1,8],anymor:5,anyth:17,aperiod:[22,36],api:[1,36],appear:3,appli:[1,3,4,6,7,8,9,10,11,12,16,27,31,33,36,37],applic:4,approach:[1,3,5,11,27],approxim:22,appveyor:1,april:1,ar:[1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,20,22,24,26,27,28,29,31,32,33,34,35,36,37],arai:14,arang:[3,30],argument:[1,4,5,6,7,10,12,15,22,25,26,28,34,37],arithmet:24,around:[1,5,7,10,11,17,18,19,30,33,34,37],arrai:[1,3,5,6,7,9,10,11,13,14,15,16,17,18,19,20,21,23,24,25,26,30,37],array_lik:[5,6,7,10,11,12,13,15,16,17,18,19,20,21,24,25,26,27,29,31,32,33,35],art:[1,5,18,19,25,29],art_detect:1,art_epoch:11,artefact:[1,3,5,11,12,16,25,26,27,28,29,31,33,35,36,37],articl:[1,3,22,36],artifact:[11,36],artifact_reject:36,artifect:11,as_annot:5,as_datafram:[1,7,10],as_int:[5,28],as_strid:30,asap:1,ascii:3,ask:3,assign:1,associ:[1,5,8,22,29,37],assum:[3,4,5,8,17,29,37],assumpt:[1,9],attribut:[1,4,5,6,7,9,10,22,37],author:3,autism:7,auto:[8,9,22],auto_method:9,autom:[3,5,8,36],automat:[1,3,4,5,8,11,12,20,22,27,31,33,36],automatic_stag:36,avail:[1,3,7,10,24],averag:[1,4,6,7,8,10,12,13,15,22,27,31,33,35,36,37],avoid:1,awai:22,ax1:28,ax2:28,ax:[1,4,5,9,25,28,35],axi:[1,4,5,8,25,30,37],b:[1,5,7,10,22,27,35,37],back:37,bad:11,baker:[4,9],balanced_acc:[4,5],band:[1,3,8,12,13,14,22,31,32,33,36],bandpa:33,bandpass:[1,3,6,7,10,12,33,36,37],bandpow:[1,13,14,36,37],bandpower_from_psd:[1,14],bandpower_from_psd_ndarrai:1,bandwidth:33,bandwis:32,bar:11,barach:11,barakat:33,barth:7,base:[1,4,5,9,11,27,28,31,33,34,36,37],baseraw:[5,8,11,12,20,22,27,31,33],basic:[1,36,37],bbox_to_anchor:4,bdf:3,beat:16,beaudri:31,becaus:[1,5,8,15,37],becom:1,bed:[1,5,28,29,35],been:[1,33],befor:[1,2,6,7,8,10,15],begin:[1,5,7,10,16,27,29,31,33],behavior:[1,31,33,37],being:1,below:[1,3,5,7,8,10,11,36,37],berkelei:36,best:[1,2,5,11,35,36],bet:2,beta:[4,8,12,13,14,37],better:[1,3,7,10,16,27,31,33],between:[1,4,5,7,9,10,11,12,13,14,15,16,20,22,24,27,28,30,31,33,36,37],bia:9,bias:9,bias_ci:9,bias_intercept:9,bias_method:9,bias_test:9,bibtex:3,bid:5,big:1,biggest:1,bin:32,binari:[5,7,10,17],bio:27,biol:1,biologi:[11,28],biorxiv:22,bit:37,bivari:32,black:1,bland:9,blatant:3,blink:11,blob:[1,8,11,12,22,27,31,33],blue:[8,37],bodi:11,bonnet:29,bool:[4,5,6,7,9,10,11,16,17,20,22,23,27,31,32,33],boot:9,bootstrap:9,bootstrap_kwarg:9,born:7,both:[1,3,4,7,9,10,22,26,27],bottom:[4,36],bound:[7,10],box:36,bpm:16,brain:22,brainvis:[3,36],brand:1,briefli:1,bring:1,broad:[22,31,32],broadband:31,bug:[1,2,3,31,36],bugfix:1,bui:[2,3],build:1,built:[1,3],bundl:37,by_stag:4,bytesio:26,c3:[3,8,34,36,37],c4:[3,8,34,36,37],c:[4,9,11,27,28,29,31],calcul:[1,4,5,7,8,9,10,11,12,15,16,22,26,27,29,30,31,33,35,36,37],calibr:9,calibrate_rem:9,calibrate_stat:9,calibrated_data:9,call:[1,4,7,33,37],can:[1,2,3,4,5,7,8,9,10,11,12,16,17,20,22,28,29,31,33,34,35,36,37],canthi:27,captur:3,cardiac:16,care:8,carrier:[3,33],categor:[1,5],categori:5,caus:1,cbar:35,cbar_ax:35,cbar_kw:35,cbar_tick:34,cbar_titl:34,cbrnr:16,cell:[9,28],cellini:[4,9],center:[1,4,6,7,8,9,10,33],central:[1,8],certain:[1,3,5,17],ch_name:[1,6,7,10,12,13,22,31,33,37],challeng:22,chan000:[12,13,22],chan001:[12,13,22],chan:37,chang:[1,2,3,5,7,10,16,33],channel:[1,3,6,7,8,10,11,12,13,16,22,24,26,27,30,31,32,33,34,36,37],channel_prior:36,charact:1,check:[1,3,8,31,36,37],children:7,chin:8,choic:[5,9,11,16,20,22,27,31,33],chokroverti:29,ci:[1,9,37],ci_method:9,circ_mean:33,circ_r:33,circular:33,cite:[3,8,28,36],classif:36,classifi:[1,3,8],click:3,clinic:[5,29],close:[7,10,15,31],closer:31,cluster:11,cmap:[26,34,35],co:[1,7],code:[1,3,4,8,9,36,37],codebas:2,coeffici:34,coffe:[2,3],cognit:37,coincid:[1,7,10],collect:4,color:[4,7,10,25,26,34,37],color_palett:34,colorbar:34,colormap:[26,34],column:[1,3,4,5,7,9,10,12,13,16,27,28,31,33,35,37],com:[1,3,7,8,10,11,12,16,22,23,24,26,27,28,31,33,37],combin:[1,3],come:[1,3,4,5,8,28,36,37],command:[3,36,37],comment:[1,3],common:[5,8,37],commun:[1,28],comodulogram:[1,36],compar:[1,4,5,7,10,15],compare_channel:[1,7,10],compare_detect:[1,7,10],compare_heartbeat:15,comparison:15,compat:[1,3,5],complet:[1,4],complex:8,compli:[1,2],compliant:5,compon:[1,22,36],compress:1,compumed:[1,23],comput:[1,4,5,7,8,10,11,13,14,22,24,27,29,32,33,37],concat:5,concaten:[4,31],concret:8,conda:36,condit:[5,35],conf_matr:4,confid:[3,8,9],config:36,conflict:1,confus:[1,4],confusion_matrix:4,congedo:11,consecut:[1,5,17,28],consensu:3,conserv:[1,11],consid:[1,2,4,7,10,11,15],consist:[1,28,30],consolid:5,consolidate_stag:5,constant_bia:9,constrained_layout:[4,25],contact:36,contain:[1,4,5,7,9,10,11,12,13,14,28],contamin:11,content:22,continu:27,contrast:26,contribut:[1,3,36],control:[4,25],conveni:4,convent:28,convers:1,convert:[1,5,8,11,12,18,19,22,31,33,37],convolv:1,conzelmann:7,cooccurringspindl:7,cooccurringspindlepeak:7,copi:[5,8,15],cornflowerblu:4,corr:[24,31],correct:[1,9,15,16],correctli:2,correl:[24,31,34],correspond:[3,5,9,16,18,19,20,24,30],cost:[7,10],could:[1,3,5,15,31],count:[1,4,5,15,35,37],coupl:[1,7,33,36],coupling_param:[1,33],covar:[11,24],covari:[11,24],creat:[1,5,9,35,36],critic:[1,5,9,11,16,20,22,27,31,33],crop:[5,20,29,35],cross:[4,8,33],csv:[3,37],cubic:[24,32],current:[1,3,5,7,8,10,11,15,17,20,21,25,28,33,35,37],custom:[3,4,5,6,7,9,10,16,37],cutoff:9,cz:[1,12,13,22,26,34,37],d:[1,3,11,14,27,30,33],damberg:29,data:[1,4,5,6,7,8,9,10,11,12,13,14,15,16,17,20,21,22,24,25,26,27,28,30,31,32,33,34,36],data_ecg_8hrs_200hz:1,data_filt:[6,7,10],data_full_6hrs_100hz_cz:26,data_full_6hrs_100hz_hypno_30:[26,28],databas:[1,3],datafram:[1,3,4,5,6,7,8,9,10,12,13,16,17,22,27,28,31,33,35,37],dataset:[1,4,9,36],date:5,date_rang:5,datetim:5,datetimeindex:5,db:[31,33],de:[4,9],dean:8,debug:[5,9,11,16,20,22,27,31,33],decisecond:[7,10],decreas:37,deep:[5,37],defin:[1,5,7,10,11,12,13,14,15,16,17,26,27,31,33,34,37],definit:[5,11,29],deflect:33,degre:32,delet:3,delfrat:31,delimit:3,delta:[8,12,13,14,37],demonstr:36,denni:8,denomin:1,denot:1,densiti:[1,13,14,22],depend:[1,9,31],deprec:1,deriv:[1,4,8,31],describ:[1,5,8,22,37],descript:[3,4,5,11,36],design:3,desir:[4,5,17,21,28,37],despit:3,detail:[1,4,5,7,8,10,12,13,14,23,26,28,31,33,34,36,37],detect:[1,6,7,8,10,11,15,16,27,31,33,36],determin:[1,7,15],detrend:[1,31],dev:5,develop:2,developp:3,deviat:[1,4,8,9,11,16,31,33],devic:5,df:[4,5],df_sync:[6,7,10],diag:[35,37],diagon:[7,10,35,37],dialog:3,dict:[4,5,6,7,8,9,10,12,15,16,18,19,22,25,26,28,29,31,33,34],dictionari:[4,5,8,15,16],dictionnari:[18,19],did:8,differ:[1,3,4,5,7,8,9,10,11,16,17,22,29,37],difficult:1,dimens:[1,8,30],dimension:[1,14,37],direct:33,directli:[1,26],directori:2,disabl:[1,5,16,17,20,31,33,37],discard:[5,17],discoveri:8,discrep:9,discret:34,discuss:[2,22],disord:[3,7,8],displai:[1,25,36],distanc:[7,10,11,15],distancespindletosw:7,distribut:[9,11,22,26],dive:36,divid:[5,7,10,12,13,14,16,17],divis:[1,5,17,28],doc:[2,5],docstr:2,document:[1,3,5,7,8,10,28,36,37],doe:[1,3,4,5,7,10,37],doesn:4,doi:[1,3,4,8,9,22,28,36],domain:16,done:[2,3,6,7,10,32,35,37],dot:4,doubl:[1,8],download:[36,37],downsampl:[1,3,8,31,33,36,37],downstat:7,dpi:[1,34],drastic:[11,31,37],draw:[1,4,25],driven:36,drop_channel:37,dtype:[1,5,15,17,28,35,37],duggan:27,dur_neg:[1,33],dur_po:[1,33],durat:[1,3,5,16,17,27,28,29,31,33],dure:[7,11,31,33],dynam:3,e1:8,e:[1,3,4,5,6,7,8,9,10,11,12,13,14,15,17,20,21,22,23,25,26,27,28,29,32,33,34,35,36,37],each:[1,3,4,5,6,7,8,10,11,12,13,14,15,16,17,20,21,24,25,27,28,29,30,31,32,33,35,37],easili:37,eb:[4,5],ecg:[1,16],edf:[3,8,23,36,37],edfbrows:[3,8,37],edit:[2,3,8],editor:[3,23,36],eea:9,eeg:[1,3,5,7,8,10,11,12,13,17,20,21,22,25,26,28,30,31,36],eeg_nam:[8,37],eeglab:3,effect:[1,7,10,11,12,27,31,33],effici:[1,5,29],eigenvalu:11,either:[1,4,7,8,9,10,35],ekg:[11,37],elan:3,electrod:[8,11,34,37],element:[7,10,34],elif:[3,8,36,37],elifesci:3,emg1:[8,37],emg2:[8,37],emg:[1,8,11,37],emg_nam:8,emphasi:3,empti:15,emul:31,en:[7,10,11],enabl:[1,3],encod:[3,37],end:[5,17,26,27,31,33],engin:[11,27],enhanc:1,ensembl:[1,27,31,33],ensur:[2,5,24,27,31,32,33],enter:[36,37],entir:[4,36,37],entropi:[1,8],enumer:[4,9],eog:[1,6,8,11,27,37],eog_nam:8,epoch:[1,3,4,5,8,11,16,23,24,28,29,30,33,35,36,37],epochbyepochagr:[1,5,9],epochbyevalu:4,equal:32,equal_length:[5,16,17],equat:9,error:[1,3,5,9,11,16,20,22,27,31,33],especi:[3,8,36,37],essenti:[11,18,19],estim:[11,16,22],et:[1,3,4,5,8,9,28,37],etc:[2,3,5,16,37],ethnic:8,euclidean:11,european:[3,33,36,37],evalu:[1,3,4,5,7,9,10],even:[1,3,7,10,15],evenli:28,event:[1,5,6,7,10,15,29,36],everi:[11,22,24,32,37],exact:[5,12,16,17,20,26,37],exactli:[4,5,15,16,17],exampl:[1,2,3,4,5,7,8,9,10,11,12,15,16,17,22,25,26,27,28,29,30,31,33,34,35,36,37],exce:[1,5,16,17],exceed:[5,11,17],excel:37,except:[5,23,29,31],exclud:[1,5,11,29,35],exclus:[1,8],exist:[1,2],expect:[8,37],experi:[1,11],experiment:[1,5],expert:[3,31,37],explain:[1,3,37],explan:37,exponenti:22,express:[1,5,7,16,28,29,31,33,37],extens:3,extern:[3,8],extra:1,extract:[1,5,8,11,12,20,22,31,33],ey:[11,27,36],f1:[1,3,4,7,10,15],f3:[12,13,22,34,37],f4:[12,13,22,34,37],f7:37,f8:37,f:[4,9,16,22,32,33,35,36,37],facilit:1,factor:22,fail:9,fake:[5,9,28],fake_hyp:28,fall:27,fals:[1,3,4,5,6,7,8,9,10,11,12,15,16,17,20,22,24,27,31,32,33,35,37],familiar:37,faq:[1,8,36],far:11,fast:[36,37],faster:[1,8,11,32],fastest:[24,32],fbeta:[4,5],featur:[1,3,8,9,16,31,36],feedback:1,feel:[5,8,17,36],fell:11,femal:[8,37],ferrarelli:33,few:[3,37],field:[11,37],fieldtrip:22,fig:[4,25,26,28,34,37],figsiz:[1,4,6,7,10,25,28,34,35],figur:[1,6,7,10,26,28,34],file:[1,3,5,8,28,36,37],filenam:23,filipini:33,fill:[16,25],fill_color:25,filt:[6,7,10],filter:[1,3,6,7,8,10,12,27,31,33,36,37],filter_data:[6,7,10,12],find:[1,3,5,7,8,10,17],find_cooccurring_spindl:[1,7],find_period:5,fine:3,fir:[1,12,31,33],first:[1,3,4,5,7,8,11,17,27,29,31,33,34,36,37],fit:[1,5,8,20,22],fit_param:22,fix:[1,31],flake8:[1,2],flat:1,flexibl:1,float64:5,fmax:26,fmin:26,fmt:[3,35],fn:15,fname:23,focus:1,folder:[36,37],follow:[2,3,5,7,8,10,22,28,29,31,33,37],font:34,fontsiz:34,fooof:22,fore:12,forest:1,forg:36,form:7,format:[1,2,3,6,7,9,10,11,12,16,23,26,27,29,31,33,36,37],former:[5,29,36],found:[1,3,5,7,8,23,28,29,34,36],fourier:31,fp1:37,fp2:37,fp:15,fpz:8,fractal:[8,22,36],fraction:[7,10,35],fragment:[5,35,37],frameon:4,framework:[3,4,9],free:[3,5,8,17,27,31,33,36,37],freeli:3,freq:[5,13,14,22,25,28],freq_broad:31,freq_rem:27,freq_so:1,freq_sp:[1,31,33],freq_sw:[1,33],frequenc:[1,3,5,6,7,8,10,11,12,13,14,15,16,17,20,21,22,23,24,25,26,27,29,30,31,32,33,35,36],from:[1,3,4,5,7,8,9,10,11,12,15,16,22,25,26,27,28,29,30,31,33,34,35,36,37],frontal:37,frontier:16,fstring:9,full:[1,3,5,8,23,26,27,31,33,36],func:[4,25],fundament:22,further:[5,17],furthermor:[1,5,37],futur:1,fz:[34,37],g:[1,3,4,5,6,7,8,10,11,12,13,14,15,17,20,21,22,25,26,27,28,33,34,35,36],gainsboro:4,gamma:[12,13,14,37],gear:37,gender:8,gener:[1,4,5,9,17,28],generaliz:2,geometr:22,geometri:11,get:[1,4,5,8,9,16,26,27,28,31,33,37],get_agr:[4,5],get_agreement_bystag:4,get_bool_vector:1,get_calibration_func:9,get_centered_indic:1,get_coincidence_matrix:[1,7,10],get_confusion_matrix:4,get_data:[27,37],get_featur:8,get_mask:[1,6,7,10],get_sleep_stat:[4,9],get_sync_ev:[1,6,7,10],get_sync_sw:1,get_tabl:9,ginsberg:16,gist:7,github:[1,2,3,4,7,8,9,10,11,12,16,22,23,24,26,27,28,31,33,36],githubusercont:26,give:[1,3,4,5,7,10,15,17,27,31,33],given:[5,7,11,13,16,17,20,21,35,37],global:34,go:36,goal:22,goldston:[4,9],good:[11,24,32],gotman:27,grab:3,gradual:1,grand:1,graphic:[3,8],greater:11,grid:32,grid_kw:35,gridspec_kw:35,grigg:29,grndtrth:15,ground:[1,4,5,7,10,15,37],groundtruth:15,group:[1,4,6,7,10],groupbi:4,grp_chan:[1,7,10,31,33,37],grp_stage:[1,6,7,10,27,31,33,37],gui:3,guidanc:2,guidelin:[1,4,5,9,29],guo:8,h:[4,9,22,28,29],ha:[1,3,4,7,10,11,12,24,25,27,31,33,37],halfwai:31,ham:[12,22],handl:1,happen:16,harmon:[7,10,15,22],have:[1,3,4,5,8,11,12,16,17,20,26,27,28,29,31,33,36,37],hdeeg:11,head:[4,9],header:3,health:[8,16],healthi:[3,37],heart:[1,16,36],heartbeat:[1,16],heatmap:35,height:34,height_ratio:35,help:[1,37],henri:9,here:[3,4,5,9,15,17,29,37],hertz:37,heterogen:3,hi:1,high:[3,8,36,37],higher:[1,5,11,24,26,32,37],highest:[1,7,10,37],highli:2,highlight:[5,25],higuchi:8,hilbert:[1,31],hill:33,hirshkowitz:29,hjorth:8,hline:25,homogen:1,homoscedast:9,horizont:35,hour:[1,5,28,37],how:[1,3,7,10,11,12,22,27,33,37],howev:[3,11,36,37],hr:[1,5,16],hr_mean:16,hr_std:16,hrv:[1,16,36],hrv_coupl:1,hrv_rmssd:16,hrv_stage:1,hset:22,hspace:35,html:[1,2,4,5,9,11,34,37],http:[1,3,4,5,7,8,9,10,11,12,16,22,23,24,26,27,28,31,33,34,36,37],huber:33,hue:[1,7,10],huge:[1,3],human:[1,3,4,5,7,8,9,10,15,31,37],hundr:1,hynogram:4,hyp:[1,3,4,5,25,28],hyp_2:5,hyp_a:[5,25],hyp_b:[5,25],hyp_up:5,hypno:[1,3,5,6,7,8,10,11,12,16,17,18,19,20,21,23,26,27,28,29,31,33,35,37],hypno_a:4,hypno_b:4,hypno_export:3,hypno_find_period:1,hypno_int:3,hypno_int_to_str:28,hypno_pr:37,hypno_str_to_int:37,hypno_up:37,hypno_upsample_to_data:[1,11,12,16,26,27,31,33,37],hypnogram:[1,3,4,6,7,9,10,11,12,16,17,18,19,20,21,22,23,25,26,27,28,29,31,33,35,36],hz:[1,3,5,6,7,8,10,11,12,13,14,15,17,20,21,22,23,25,26,27,31,32,33,36,37],i:[1,3,4,5,6,7,9,10,11,15,17,23,28,29,32,33,35,37],iber:[5,29],id:4,idea:11,ideal:[3,12,22,31],ident:[9,23,28],identifi:[3,37],idxchannel:[6,7,10],ieee:[11,27],ill:[1,37],illustr:1,iloc:28,impact:[1,7,10,25,26],implement:[1,3,4,11,14,31,33],implent:28,importantli:[33,37],improv:[1,2,3],inch:[6,7,10,34],includ:[1,2,3,4,5,6,7,9,10,11,12,16,27,29,31,33,37],inconsist:3,incorrect:35,increas:[1,11,33,37],increment:22,inde:1,independ:[15,22],index:[3,4,5,6,7,9,10,11,15,16,17,34,37],indic:[1,3,4,5,6,7,9,10,15,16,28,31,34,37],indices_detect:15,indices_groundtruth:15,individu:[1,3,4,7,9,10],inf:[16,33],influenc:[4,9,11],info:[5,9,11,16,20,22,27,31,33,37],inform:[1,5,28],informat:8,inherit:5,init_proba:28,initi:[1,8,28],input:[1,22,24,32],inspect:[8,9,11],inspir:[15,24],instal:[1,2,3,37],instanc:[1,4,6,7,8,9,10,25,30],instantan:31,instead:[1,5,31],int16:5,int64:[15,37],integ:[1,5,11,12,16,18,19,22,23,25,26,27,28,29,31,33,35,37],integr:1,inter:[3,8,11],interact:[1,7,10,36],intercept:[9,22],interest:[1,12,13,14,22,33],interfac:[3,8,36],intern:[1,5],interp2d:32,interp:[24,32],interpol:[16,24,32],interquartil:8,interv:[9,16],intracrani:3,introduc:1,introduct:37,invalid:[1,16],invers:[12,22],invert:[7,10,15],involv:8,io:[3,4,5,7,8,9,10,11,12,20,22,26,27,31,33,36,37],ipynb:[1,8,11,12,22,27,31,33],ipywidget:[1,7,10],irasa:[1,36],irregular:22,isol:1,isolationforest:[1,27,31,33],israel:29,issu:[1,2,8,11,36],item:[5,17],iter:[4,11],its:[1,5,8,22],j:[7,16,27,31,33],jcsm:29,joblib:8,joint:11,journal:[3,5,8,27,29,31,33],jouvet:4,jupyt:[1,7,8,10,16,26,31,33,36,37],just:[4,31],k:[7,27,31],kapen:29,kappa:[4,5],keenan:29,keep:[1,5,17],kei:[4,6,7,8,10],kelli:9,kept:[5,16,17,31],keyword:[1,4,5,12,22,25],kid:3,kind:[36,37],know:[1,37],knowledg:36,known:37,kramer:[7,10],krauss:28,kryger:29,kurtosi:8,kurz:7,kwarg:[4,5,6,7,10,25,26,28,34],kwargs_welch:[12,22],l:[4,9,11,22,27,37],lab:36,label:[3,4,5,7,10,12,13,22,35],lacours:[3,31,37],lafortun:33,lambda:9,lambda_i:11,landmark:[1,6,7,10],larg:[3,11,37],largest:1,laroch:27,last:[1,5,17,29,30],lastli:[5,17],lat_n1:[29,37],lat_n2:[29,37],lat_n3:[29,37],lat_rem:[5,29,37],latenc:[1,5,29],later:37,latest:[1,7,10,11,37],law:22,lead:1,learn:[1,2,4,27],least:[1,12,22,24,26,31],led:1,left:[4,8,11,27,36],legend:[4,37],legend_styl:4,len:[3,37],length:[1,3,4,5,11,12,16,17,22,26,30,33,37],less:[5,11],let:[1,3,5,17,37],level:[1,4,5,9,11,16,20,22,27,31,33],leverag:3,lgbmclassifi:8,lib:30,librari:[16,37],life:33,light:[5,29],lightgbm:[1,8],like:[1,2,3,15],limit:[5,9,16,17,36,37],line:[1,3,7,10,25,26,36,37],linear:[1,16,22,36],lineplot:[1,6,7,10],linestyl:25,list:[1,4,5,6,7,9,10,11,12,13,14,16,22,27,31,33,34],liu:22,ll:37,loa:9,loa_ci:9,loa_method:9,load:[1,8,12,23,26,27,31,33,36],load_profusion_hypno:1,loadtxt:[26,28],loc:[1,4,6,8,9,27,35,37],locabsfallslop:27,locabsriseslop:27,locabsvalpeak:27,local:2,locat:[27,31,33],lock:1,log10:31,log:[5,9,11,16,20,22,27,31,33],longer:[1,5,16,17,20,26],longitudin:1,look:7,lookaround:[7,15],loop:[1,3],low:[3,8,37],lower:[1,4,5,9,12,13,14,16,22,26,32,33],lowercas:19,lowest:[1,7,8,10,37],lowpass:[6,7,10],ls:4,lspopt:1,ltd:3,lv:11,lw:[4,25],m1:[8,34],m2:[8,34],m:[4,7,8,9,11,27,28,29,33],machin:27,macroarchitectur:28,mai:[3,4,5,11,17,33],main:[1,8,11,36,37],mainli:37,maintain:36,mainten:[1,5,29],major:[1,8,11],majority_onli:8,make:[1,2,7,8,10,11,27,31,33,36,37],make_standard_montag:34,male:8,mani:[2,3,4,9],manipul:[1,5],manual:[1,3,5,7,8,10,16,29],map:[1,3,5,9,18,19,23,37],mapping_dict:[18,19],mapping_int:5,mark:[1,3,7,10,11,23],markov:[1,28],martin:33,mask:[1,6,7,10,12,16,27,31,33,34],massimini:[3,33],master:[1,8,11,12,22,26,27,28,31,33],mastoid:8,match:[3,4,5,7,10,15],matlab:3,matplotlib:[1,4,5,7,9,10,25,26,28,34,35],matric:[11,28],matrix:[1,4,5,7,10,11,28,30,35,36],matter:15,matthew:[3,36],max:[1,5,8,12,13,14,20,24,26,33,34],max_dist:[1,15],max_distance_sec:[7,10],maxim:3,maximum:[1,7,10,12,15,24,27,31,33,34],mayaud:11,mb:37,mcc:[4,5],mcdevitt:27,me:[1,36],mean:[1,4,5,6,7,9,10,11,12,16,22,24,26,27,31,33,35,37],mean_direct:33,meant:28,measur:[4,7,10,16],median:[6,7,10,12,22,31],mediat:16,medic:[8,27],medicin:[5,8,11,29,37],mednick:27,memori:[5,7],menghini2021:[4,9],menghini:[4,9],mental:37,menu:3,merg:31,messag:[5,9,11,16,20,22,27,31,33],met:9,metadata:8,meth:4,method:[1,3,4,5,6,7,8,9,10,11,22,24,27,31,33,36,37],metric:[4,7,9,10,15,16,35,37],metzner2021:28,metzner:[1,28],michel:4,micro:[1,8,11,12,22,27,31,33],midcross:33,middl:[24,33,36],might:[3,5,15],million:37,millisecond:16,min:[1,8,12,13,14,24,26,34],min_dist:31,minim:27,minimum:[12,24,27,31,33,34],minor:1,minu:9,minut:[1,5,16,17,28,29],misalign:37,miscellan:1,misclassif:8,misclassifi:3,miss:1,mix:5,mne:[1,3,5,6,7,8,10,11,12,20,22,27,31,33,34,36,37],mobil:8,mode:[7,10],model:[9,22,28],modifi:[1,3,5,7],modul:[1,3,4,8],montag:34,more:[1,2,4,5,7,8,10,11,12,13,14,16,17,23,26,27,28,31,33,34,36,37],most:[1,3,5,8,9,10,11,16,20,22,27,31,33,36,37],move:[1,3,24,31],movement:[11,12,16,25,26,27,29,31,33,36],ms:[7,10,16,24,31,32],mt:19,much:[11,32],multi:[1,7,10,11,26,31,33,36],multi_onli:31,multi_scor:4,multiindex:4,multipl:[4,9,22],multipli:[4,27],multitap:[26,37],must:[2,4,5,7,9,10,11,12,13,14,15,16,26,27,28,31,33,34,35],my:[3,34],my_hypno_edfbrows:3,my_hypno_spisop:3,my_hypno_visbrain:3,myedffil:[3,36],myfil:8,n1:[3,4,5,8,9,11,12,16,18,19,23,25,26,27,28,29,31,33,35,37],n2:[3,4,5,8,9,11,12,16,18,19,23,25,26,27,28,29,31,33,37],n3:[3,4,5,9,11,12,16,18,19,23,25,26,27,29,31,33,37],n:[3,4,9,14,27,30,33],n_band:14,n_chan:[1,6,7,10,11,14,31,33],n_chan_reject:11,n_channel:[1,13,30],n_color:34,n_epoch:[1,5,11,14,23,30],n_event:[1,7,10],n_freq:[1,13,14],n_other:[7,10],n_sampl:[1,4,6,7,10,11,30,31,33],n_self:[7,10],n_session:9,n_sleep:4,n_stage:[1,5,25,28],n_time:[1,7,10],naiv:[28,36],name:[1,3,4,5,6,7,8,9,10,12,13,14,22,28,31,33,34,37],nan:[5,7,16],nap:8,nation:[1,8,23],nativ:23,ncol:4,nd:19,ndarrai:[1,8,14,16,22,26,32],ndpac:[1,33],nearest:[7,10],need:[1,2,5,20,36,37],neg:[1,7,15,27,33],negpeak:[1,7,33],nepoch_list:3,nepoch_nb:3,net:3,network:[1,7,10],neural:11,neurophysiolog:22,neurosci:[27,31,33,37],new_freq:5,new_hyp:9,new_n_stag:5,new_obs_rem_v:9,new_sstat:9,new_stats_calibr:9,newer:1,newlin:3,next:[3,5,17,26,28,35,37],night:[1,3,8,11,26,36],niknazar:27,nois:11,non:[1,3,8,9,15,22,28,36],none:[1,4,5,6,7,8,10,11,12,13,16,20,22,24,25,26,27,28,30,31,32,33,34,37],nonlinear_featur:36,norm:[16,32],norm_direct_pac:33,normal:[1,8,9,16,26,31,32,33],note:[4,5,7,8,9,10,11,12,15,16,18,19,22,23,24,26,27,28,29,30,31,32,33,36],notebook:[1,3,8,11,12,16,22,26,27,28,31,33,34,36,37],notifi:3,now:[1,5,17,29,37],np:[1,3,5,7,9,10,12,16,24,26,28,30,33,35,37],nperseg:[24,32],npy:28,npz:[1,26],nrem:[1,5,29,31,33,37],nrow:[25,28],nsampling_period:3,nsrr:[1,23],numba:1,number:[1,4,5,6,7,8,9,10,11,12,16,17,20,26,27,28,31,33,34,35,37],numer:37,numpi:[1,2,3,7,8,10,14,16,22,26,28,30,32,35,36,37],numpydoc:2,nutshel:22,o1:37,o2:37,object:[1,5,11,28],obs_data:9,obs_hyp:[4,5,9],obs_kwarg:4,obs_scor:[4,9],obs_sstat:9,observ:[4,5,9],obtain:[1,7,10,31],occur:[1,7,10,15,31],occurr:[1,7],octob:1,ocular:27,off:[11,28],offer:[4,22],offici:29,offset:[5,22],often:3,ojeda:11,old:[1,37],older:3,omit:[5,11,12,20,22,31,33],onc:[1,3],one:[1,3,4,5,7,10,11,17,23,24,29,30,31,33,35,37],onli:[1,3,4,5,6,7,8,9,10,11,14,16,17,20,22,24,27,28,31,33,37],onlin:[1,5,11,28],onset:[1,3,5,15,29],open:[1,2,3,4,8,9,36,37],optim:[1,3,8],option:[1,4,5,6,7,8,9,10,12,15,22,24,25,26,36,37],order:[4,5,15],org:[1,3,4,5,8,9,22,28,34,36],orient:[1,5,35],origin:[5,10,22,31,35],oscil:[1,7,31,33,36],oscillatori:[1,22],other:[1,4,5,7,10,15,16,17,26,28,34],other_is_groundtruth:[7,10],otherwis:[5,9],ouput:[6,7,10],our:[3,37],out:[1,3,5,24,29,36,37],outdat:1,outlier:[1,7,9,10,27,31,33],output:[1,5,6,7,10,16,17,20,24,27,31,32,33,37],outsid:[7,10,16],over:30,overal:[1,3,7,10],overlai:[1,7,10,36],overlap:[1,4,24,30,32],overnight:[1,36],overview:16,overwrit:26,own:[3,5,36,37],oz:34,p3:[34,37],p4:[34,37],p:[1,3,8,16,28,31,33,36],pac:[1,33],packag:[1,2,3,7,8,10,11,24,36,37],pad:[5,20],pair:[1,4,7,10,22],palett:[8,34,37],panda:[1,3,4,5,6,7,8,9,10,12,13,16,17,18,19,22,27,28,31,33,34,35,36,37],panel:36,paper:1,paquet:33,paramet:[1,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,37],parametr:9,parm:9,part:[1,6,7,10],particip:[1,8],particular:3,pass:[1,2,4,5,6,7,9,10,11,12,20,22,25,26,27,28,33,34,37],past:[1,8],path:[8,23],path_to_model:8,patient:3,pd:[3,5,7,9,10,34,37],peak:[1,6,7,10,15,16,24,27,31,33,37],pearson:34,peer:8,penzel:29,pep8:2,peppard:31,per:[1,5,16,17,20,21,23,25,29,31,33,35,37],percentag:[5,9,29],percentil:[1,26],perfect:[7,10],perform:[1,3,4,7,8,9,10,11,15,16,24,31,32,33,36,37],period:[1,5,16,17,22,29,35,37],permut:8,persist:5,petrosian:8,pg:33,phase:[1,33,36],phaseatsigmapeak:[1,33],physic:1,pick:[3,36],pingouin:33,pip:[1,2,3,36,37],pipelin:[1,3,36],place:[5,7,27,31,33],plai:[5,17],plausibl:5,pleas:[1,2,3,7,8,10,11,12,16,22,23,26,27,28,31,33,34,36,37],plot:[1,3,4,5,6,7,8,9,10,25,26,28,34,35,36],plot_averag:[1,6,7,10,37],plot_blandaltman:9,plot_detect:[1,3,7,10],plot_discrepancies_heatmap:9,plot_hypnogram:[1,4,5,26,28,37],plot_predict_proba:8,plot_spectrogram:[1,3,37],plot_topomap:[1,34],plt:[4,9,25,28,35],pm:37,point:[1,3,7,8,10,11,31,32,33],pointwis:32,poirier:33,polysomnographi:[1,8,36],popul:3,portrai:28,posit:[1,4,7,10,11,15,31,33,34],pospeak:33,possibl:[1,3,4,7,10,15,16],post:[1,5,35],postdoctor:36,potato:11,potenti:[2,8],power:[1,8,12,13,14,22,31,32,36],pr42:1,pr:1,practic:1,pre:[1,5,8,11,13,35],precis:[1,4,5,7,10,15,24,32],precision_recall_fscore_support:4,pred:8,predict:[3,4,5,7,8,10,15,28,37],predict_proba:8,prefer:[7,10,15],preferenti:8,preload:[3,8,36,37],preprint:1,preprocess:[3,16,36],prerequisit:36,present:[4,7,10,11,31],pressman:29,previou:1,previous:[1,3,29,33],primari:16,primarili:1,primer:37,princip:37,print:[1,5,9,11,16,20,22,27,31,33,37],prior:[11,31],prob:[5,35,37],proba:8,probabilit:28,probabl:[1,5,8,28,35,36,37],procedur:9,process:1,produc:[7,10],product:[7,10,27],profus:[1,23],program:36,programm:3,promin:[1,10,27,31,37],prompt:[36,37],prop_above_zero:24,properli:2,properti:[4,5,9,27,31,33],proport:[5,7,10,24,31,37],proportion:9,propos:[3,4,9],provid:[3,4,6,7,8,10,11,27,28,31,33,36,37],psd:[1,12,13,14,22,26],psd_aperiod:22,psd_oscillatori:22,psg:[8,37],ptp:[1,24,33],publish:[1,3],pull:36,purpl:8,purpos:[1,28],put:[1,31],py:[1,4,25],pydata:[5,34],pyplot:[1,4,9,25,28,35],pyriemann:[1,11],pytest:2,python:[1,2,3,11,24,36,37],pz:[34,37],q:11,qiang:8,qualiti:[3,11],quantifi:37,question:[3,8],quickli:[1,3,7,10,37],quickstart:[1,36],r:[3,8,16,18,19,22,26,27,29,33,37],radian:[1,33],rais:1,randint:30,random:[5,27,28,30,31,33],rang:[1,4,8,9,16,22,26,27,31,32,33,34,37],rangeindex:5,raphael:[3,36],raphaelvallat:[1,3,8,11,12,22,26,27,28,31,33,37],rapid:[27,36],rate:[1,16,36],rater1:4,rater2:4,rater:[3,8],ratera:4,raterb:4,rather:3,ratio:[7,8,31],raw:[1,3,6,7,8,9,10,26,27,28,31,36,37],rawedf:37,rdbu_r:26,re:[1,3,26,37],reach:3,read:[26,36,37],read_csv:37,read_raw_edf:[3,8,36,37],readabl:1,reader:8,readm:1,readthedoc:[7,10,11],real:[28,36],real_hyp:28,realtim:3,reason:[3,8],recal:[1,4,5,7,10,15],recalcul:16,receiv:1,recent:1,reciproc:22,recommend:[1,2,3,11,35,36,37],record:[1,3,5,7,8,10,16,29,36,37],rectangular:32,rectbivariatesplin:32,red:4,redistribut:22,reduc:[1,5,7,10],ref_data:9,ref_hyp:[4,5,9],ref_kwarg:4,ref_scor:[4,9],ref_sstat:9,refer:[1,4,5,7,8,9,10,11,12,15,16,22,23,26,27,28,29,31,33,34,36,37],referenc:8,reflect:16,regardless:[5,7,10],regr:9,regress:[9,24],rehabilit:11,reject:[11,36],rel:[1,8,12,13,14,27,31,37],rel_pow:31,relat:[33,37],relationship:[11,37],relative_promin:[1,27],releas:[1,3,31],relev:37,relpow:31,rem:[1,3,4,5,6,9,11,12,16,19,23,25,26,27,29,31,33,36,37],rem_detect:1,remain:[1,3,5,15,22],remaind:[5,17],remov:[1,3,5,9,11,17,27,31,33,37],remove_outli:[27,31,33],remrama:1,remresult:[1,27],rems_detect:36,renam:1,render:2,renner:7,reorgan:1,replac:[3,23],report:[2,3,5,9,29,36,37],repositori:36,repres:[3,4,5,9,33,37],represent:[9,36,37],reprocess:1,reproduc:[5,27,28,31,33,36],request:[26,36],requir:[1,3,7,8,10,27,28,37],resampl:[1,3,9,22,31,33,36,37],research:[1,8,23,36,37],resolut:[5,7,10,11,32,34],resourc:[1,8,23],respect:[5,7,10,17,20,33,37],rest:4,restructuredtext:2,result:[1,3,4,5,7,8,10,11,15,16,20,22,27,28,30,31,33,35,37],return_fit:22,review:[1,8],rich:8,riemannian:11,right:[5,11,27,28,35,36],rise:27,rm:[1,24,31],rmssd:16,robillard:33,robust:8,roc:[1,6,27,37],rocabsfallslop:27,rocabsriseslop:27,rocabsvalpeak:27,rodent:3,roll:[1,8],root:[1,16,24,31],round:[4,5,7,9,10,28,35,37],row:[4,5,9,12,13,17,27,28,30,31,33,35,36,37],rpeak:16,rr:16,rr_limit:16,rule:[5,29,37],run:[1,2,3,7,8,10,11,17,27,33,36],run_visbrain:36,s10548:22,s1:[5,19],s2:19,s3:19,s42003:28,s4:[19,23],s:[2,3,5,7,8,10,13,17,22,27,28,29,31,33,36,37],safeti:1,sai:3,sake:[3,37],same:[1,3,4,5,7,9,10,11,12,15,16,17,20,22,24,26,27,31,32,33,37],sampl:[1,4,5,6,7,10,11,12,15,16,17,20,21,22,23,24,25,26,27,29,30,31,32,33,35,37],sample_weight:4,sampling_frequ:[1,5],sattari:27,save:[3,37],savetxt:3,scale:[1,7,8,10,26],scalp:3,schill:28,schulz:28,scienc:3,scientif:[8,37],scikit:[1,4],scipi:[1,12,13,14,22,32],score:[1,3,4,5,7,8,9,10,11,15,29,31,33,37],scorer:[1,3,4,5,8,9],screenshot:3,scroll:[3,37],se:[5,29,37],seaborn:[1,6,7,10,34,35],search:15,sec:[1,5,7,8,17,24,26,33],second:[1,3,4,5,6,7,8,10,11,12,15,16,17,20,21,22,23,24,25,26,27,28,29,30,31,32,33,35,36,37],section:[1,8,37],see:[1,2,3,4,5,7,9,10,11,13,14,15,16,22,28,36,37],seealso:4,seed:[4,5,9,25,27,28,30,31,33],seem:1,seemingli:1,segment:[5,17],select:[1,3,9,31,36,37],self:[4,5,7,8,10],sem:4,semilog:22,sens:36,sensit:[7,10,11,15],sep:3,separ:[3,11,16,22,36,37],sequenc:[1,5,17,28],sequenti:12,seri:[1,3,4,5,9,18,19,24,28,34],serv:3,session:[4,5,9],set:[1,4,5,7,8,15,16,30,33,36],set_label_posit:35,set_titl:[9,28],set_xlabel:35,set_ylabel:35,setup:3,sever:[1,3,35,37],sex:[1,8],sf:[1,5,6,7,10,11,12,16,22,24,26,27,30,31,32,33,37],sf_data:[5,20,21],sf_hyp:[23,29,37],sf_hypno:[17,20,21,25,37],sfi:5,sfreq:37,shaffer:16,shape:[1,5,6,7,9,10,11,13,14,20,30,31,32,33,37],shortcut:5,shorter:[5,11,20,28],should:[1,3,4,5,7,8,10,12,15,22,28,29,31,33,36,37],shoutout:1,show:[3,9,36,37],shown:[3,7,10,36,37],shyp:5,side:33,sigma:[1,10,12,13,14,31,33],sigma_coupl:36,sigmapeak:[1,33],signal:[1,7,8,10,11,12,13,14,22,24,27,30,31,33,37],signatur:11,signific:[1,9,34,37],significantli:1,silber:[5,29],similar:[3,9,28],similarli:[1,37],simp:1,simpl:[1,3,15,36],simpler:1,simplest:[2,3],simpli:[1,3,7,10,11,22,28,36,37],simul:[1,5,28],simulate_hypno:1,simulate_hypnogram:[1,4,5,9,25],simulate_similar:[4,5,9,28],simultan:4,sinc:[29,33,37],singl:[1,4,11,16,24,26,31,32,33,36,37],situat:2,size:[1,6,7,10,24,30,32,34],skew:8,sklearn:[1,4,27,31,33,37],sl:[8,37],sleep:[1,4,5,6,7,8,9,10,11,12,16,17,18,19,20,21,23,25,26,27,28,29,31,33,35,36],sleep_id:4,sleep_stat:9,sleep_statist:[1,4,5,9,28,37],sleepecg:[1,15,16],sleepstag:[1,3,5,37],sleepstatsagr:[1,4],slep:37,slide:[12,22,26,30],sliding_window:1,slight:1,slightli:[1,3,28],slope:[9,22,24,27,33,36],slow:[1,3,7,15,33,36],slower:[24,32],slowest:[24,32],sme:[1,5,29,37],smooth:[3,8],sn:35,so:[1,3,7,29,36],societi:11,soft:1,softwar:[3,36,37],sol:[5,29,37],sol_5min:5,sole:22,solid:4,solv:1,some:[1,3,5,7,8,10,11,15,28,36],soon:11,sophas:31,sort:[6,7,10],sourc:[3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36],sp:[1,31,37],space:[22,25],span:37,specest:22,specif:[1,3,5,6,7,8,9,10,11,17,29,33,36],specifi:[1,5,12,13,32,33,37],specifici:28,spectra:22,spectral:[1,12,13,14,22,36],spectral_r:26,spectrogram:[3,26,36],spectrum:[7,22,36,37],speed:[1,3,37],spell:5,sphinx:2,sphinx_bootstrap_them:2,spindl:[1,3,7,10,15,31,33,36],spindles_detect:[1,36,37],spindles_detect_multi:1,spindles_detection_multi:36,spindles_detection_nrem_onli:36,spindles_slow_fast:36,spindlesresult:[1,7,31],spisop:3,spline:32,spt:[1,5,29,35,37],squar:[1,16,24,31,35],squeez:37,sri:[4,9],ssa:9,sstat:[4,9],stabil:[35,37],stabl:1,stage:[1,4,5,6,7,8,10,11,12,16,17,18,19,20,21,25,26,27,28,29,31,33,35,36],stair:[1,25],standard:[1,2,3,4,5,8,9,11,12,16,29,31,33,36,37],standard_1020:34,start:[1,2,3,5,7,10,15,16,17,25,27,30,31,33,35,37],stat:[5,29],state:[1,5,35,37],statist:[1,4,5,9,22,28,29,33,36],statu:[8,9],std:11,step:[1,3,4,9,22,24,27,30,31,32,33,36,37],stft:32,still:1,stochast:[5,28,35],store:[1,3,5],str:[4,5,6,7,8,9,10,11,16,17,20,22,23,24,25,26,27,31,33,34],straightforward:[11,37],stratifi:36,stream:26,strict:36,stride:30,stride_trick:30,string:[1,4,5,9,18,19,28],strong:1,strongest:1,strongli:36,studi:[1,7,27,37],style:2,style_a:4,style_b:4,sub:[1,5,8,16,17,33],subject:28,submit:36,subplot:[4,25,28,35],subsequ:[16,28],subset:[3,36],succesfulli:[7,10],success:16,suggest:1,sum:[1,4,5,7,10,28,29,32,35],sum_i:11,summar:[4,5],summari:[1,4,5,6,7,9,10,27,31,33,37],sunflow:8,supplementari:28,support:[1,3,4,5,8,11,14],sure:[1,2,7,8,10,11,27,31,33,36,37],sw:[1,7,33,37],sw_detect:[1,36,37],sw_detect_multi:1,sw_detection_multi:36,swresult:[1,33],sxx:32,symmetr:[7,10,11],symmetri:31,sync:37,synchron:[1,6,7,10],system:[1,8,11],t3:37,t4:37,t5:37,t6:37,t:[3,4,7,9,11,24,27,29,32],tab:3,tabl:9,tabul:4,take:[4,5,11,22,31,33,35,37],taken:1,takeuchi:27,taper:[26,36],task:1,technic:[5,29],technician:37,technolog:[4,9],tell:[5,17,37],templat:[1,36],tempor:[1,3],ten:1,tend:1,tensorpac:[1,33],term:31,termin:[3,36,37],terminolog:[5,29],test:[1,2,4,7,9,10,28],teuniz:3,text:[3,4,22,37],than:[1,4,5,11,16,17,20,26,27,31,32,33,36,37],thei:[1,2,3,4,15,31,36,37],them:[2,15],therefor:[1,3,5,7,8,10,11,15,17,20,27,37],theta:[12,13,14,37],thi:[1,2,3,4,5,6,7,8,10,11,12,14,15,16,17,18,19,20,22,24,25,26,27,28,30,31,33,34,36,37],think:1,third:4,thistl:25,those:[1,2,4,7,10,28],though:15,thousand:3,three:[1,7,10,16],thresh:31,threshold:[1,3,5,7,10,11,16,17,27,31,33,37],through:[1,3,9,31,33,37],thu:[1,29],tib:[1,4,5,9,25,28,29,35,37],tick:34,tick_top:35,tight_layout:[4,9,25,28],time:[1,3,5,6,7,10,11,12,16,22,24,27,28,29,30,31,32,33,35,36,37],time_aft:[1,6,7,10],time_bas:3,time_befor:[1,6,7,10],timedelta:5,timedeltaindex:5,timepoint:[1,6,7,10],timeseri:5,timestamp:[1,7],titl:[3,4,34],to_csv:[3,5,37],to_numpi:3,tobi:11,togeth:[3,4],toler:1,tononi:33,too:[1,11,31,33],tool:[3,8,11,22,36],toolbox:[3,36],top:[3,26,35,36,37],topograph:36,topographi:22,topoplot:[1,36,37],total:[1,5,8,12,13,14,28,29,31,37],totalabspow:1,toward:8,tp:15,track:[4,9],tracker:[4,9],train:[1,3,8,37],tramat_epoch:28,trans_proba:28,transact:[11,27],transax:4,transform:[1,4,8,11,24,31],transform_sign:24,transit:[1,5,28,31,33,35,36],transition_matrix:[1,5,28,37],translat:23,travel:33,travi:1,traxdorf:28,triangular:8,trim:[1,26],trimbothstd:1,trimperc:26,trough:33,truth:[1,4,5,7,10,15,37],tst:[1,5,9,29,37],tune:3,tupl:[4,6,7,10,11,12,13,14,16,22,27,31,32,33,34],tutori:[1,33,34,36,37],tweak:[7,10],twice:26,twilight:8,two:[1,3,4,5,6,7,9,10,12,15,17,22,23,24,31,37],txt:[3,26,28],type:3,typic:11,u:24,uc:36,uloa_parm:9,un:[1,5,18,19,25,28,29],unbias:9,underli:[4,37],understand:16,unecessari:1,unfortun:1,uniqu:[4,5,7,9,10,28],unit:[1,11,27,31,33,37],unreli:[1,33],unscal:10,unscor:[1,5,11,12,16,25,26,27,28,29,31,33,35],until:3,unweight:4,up:[3,8,37],updat:[1,2,3,7],upgrad:[1,2,3,36,37],upon:1,upper:[1,5,9,12,13,14,16,26,33],uppercas:5,upsampl:[1,5,11,12,16,20,21,25,26,27,31,33,35,37],upsample_to_data:[1,5],url:[3,28],us:[1,2,3,4,5,6,7,8,9,10,11,12,15,16,17,22,24,26,27,28,29,31,32,33,34,35,36,37],usag:[1,5],user:[1,3,5,8,9,11,16,20,22,27,28,31,33,36,37],user_guid:5,userwarn:[5,20],usual:[7,10,24,32],utf:3,uv:[1,8,11,13,14,27,31,33,37],v0:5,va:4,vagal:16,val:5,valid:[1,3,4,5,8,34],vallat2021open:3,vallat:[3,8,36],valnegpeak:33,valpospeak:33,valu:[1,4,5,7,9,10,11,12,15,16,17,20,21,22,23,24,25,26,27,28,29,31,32,33,34,35,37],values_str:28,vandewal:33,vari:[3,22,31,37],variabl:[1,7,9,10,16,36,37],varianc:[11,16],variou:[2,4,9],various:22,ve:[1,36],vector:[1,5,6,7,10,11,12,16,17,22,24,26,27,29,30,31,32,33],vector_length:33,verbos:[1,5,9,11,16,20,22,27,31,33,37],veri:[3,8,11,15,37],version:[3,4,5,7,8,9,10,11,12,13,14,16,17,18,19,20,21,22,25,26,27,28,29,30,31,33,34,35,37],versu:36,via:[1,3,32],vien:33,viewabl:28,violat:9,visbrain:[1,3,36],visit:36,visual:[4,5,8,9,11,29,36,37],viz:[1,34],vmax:[1,26,34,35],vmin:[1,26,34,35],volt:[1,8,11,12,22,27,31,33],volum:3,vs:[1,4],w:[1,3,5,18,19,25,29,37],wa:[1,3,6,7,8,10,24,27,31,33,35,36,37],wai:[1,2,3,7,10],wake:[3,4,5,8,11,12,16,17,19,23,25,26,27,28,29,31,33,35,37],walk:28,walker:[3,8,36],walkthrough:31,want:[1,2,3,5,7,10,16,17,33,36],warbi:31,warmer:37,warn:[1,5,9,11,16,20,22,27,31,33],warranti:36,waso:[1,5,9,29,37],watch:3,wave:[1,3,7,15,33,36],we:[1,2,3,5,8,11,15,17,26,29,35,36,37],weak:1,wearabl:5,web:36,websit:[1,23],weight:[4,8],welch:[12,13,14,22],welcom:36,well:[1,3,5,7,8,9,10,12,13,14,37],wen:22,were:[1,7,8,10],what:[5,7,10,16,35,36,37],when:[1,2,3,4,6,7,8,9,10,11,12,15,26,27,31,33],whenev:[3,37],where:[3,4,5,6,7,9,10,11,12,16,17,22,25,26,27,28,29,30,31,33,37],wherea:22,whether:[1,3,5,7],which:[1,3,4,5,6,7,8,9,10,11,12,13,14,15,17,20,22,23,25,30,31,32,33,37],whitehurst:27,whitesmok:25,whole:36,wide:[8,33],widget:[7,10],width:34,wiki:23,win:3,win_sec:[12,22,26],window:[1,3,7,11,12,15,22,24,26,30,32],wish:17,within:[1,2,5,7,10,29,33],without:35,wonambi:24,word:[1,3,5,17],work:[1,3,7,8,10,11,28,36],workshop:11,would:[3,15],wrapper:[1,7,10,11,18,19,30,34],www:[3,22],x:[5,7,10,24,28,30,37],xaxi:35,xkcd:8,xml:[1,23],xs:37,y:[7,10,24,37],yasa:[1,3,37],yasa_classifi:[3,8],yasa_example_night_young:37,yasa_example_night_young_hypno:37,year:[3,8,33,37],yet:36,yetton:27,ylorrd:35,you:[1,2,3,7,8,10,11,16,17,31,33,36,37],your:[1,2,3,8,11,12,16,26,27,31,33,36,37],z:[1,8,11,22,33],zambotti:[4,9],zero:[1,8,15,24,33],zhang:8,zink:7,zsaa170:[4,9],zsaa290:7,zscore:11},titles:["API reference","What\u2019s new","Contribute to YASA","FAQ","yasa.EpochByEpochAgreement","yasa.Hypnogram","yasa.REMResults","yasa.SWResults","yasa.SleepStaging","yasa.SleepStatsAgreement","yasa.SpindlesResults","yasa.art_detect","yasa.bandpower","yasa.bandpower_from_psd","yasa.bandpower_from_psd_ndarray","yasa.compare_detection","yasa.hrv_stage","yasa.hypno_find_periods","yasa.hypno_int_to_str","yasa.hypno_str_to_int","yasa.hypno_upsample_to_data","yasa.hypno_upsample_to_sf","yasa.irasa","yasa.load_profusion_hypno","yasa.moving_transform","yasa.plot_hypnogram","yasa.plot_spectrogram","yasa.rem_detect","yasa.simulate_hypnogram","yasa.sleep_statistics","yasa.sliding_window","yasa.spindles_detect","yasa.stft_power","yasa.sw_detect","yasa.topoplot","yasa.transition_matrix","Installation","Quickstart"],titleterms:{"0":1,"1":1,"2":1,"2020":1,"2021":1,"2022":1,"2024":1,"3":1,"4":1,"5":1,"6":1,"7":1,"do":36,"new":1,analys:[0,37],analysi:0,api:0,art_detect:11,august:1,automat:[0,37],band:37,bandpow:12,bandpower_from_psd:13,bandpower_from_psd_ndarrai:14,build:2,check:2,citat:36,code:2,compare_detect:15,content:[1,37],contribut:2,data:[3,37],decemb:1,detect:[0,3,37],dev:1,develop:36,document:2,eeg:37,epochbyepochagr:4,event:[0,3,37],faq:3,februari:1,frequenc:37,full:37,galleri:36,get:36,guidelin:2,heart:0,how:36,hrv_stage:16,hypno_find_period:17,hypno_int_to_str:18,hypno_str_to_int:19,hypno_upsample_to_data:20,hypno_upsample_to_sf:21,hypnogram:[0,5,37],i:36,instal:36,irasa:22,januari:1,juli:1,load:[3,37],load_profusion_hypno:23,mai:1,march:1,matrix:37,moving_transform:24,night:37,novemb:1,older:1,other:3,plot:37,plot_hypnogram:25,plot_spectrogram:26,polysomnographi:[3,37],power:37,preprocess:37,prerequisit:37,quickstart:37,rate:0,refer:0,rem_detect:27,remresult:6,s:1,simulate_hypnogram:28,sleep:[0,3,37],sleep_statist:29,sleepstag:8,sleepstatsagr:9,sliding_window:30,slow:37,specif:37,spectral:[0,37],spectrogram:37,spindl:37,spindles_detect:31,spindlesresult:10,stage:[0,3,37],start:36,statist:[0,37],stft_power:32,sw_detect:33,swresult:7,tabl:1,topoplot:34,transit:37,transition_matrix:35,v0:1,version:1,visual:3,wave:37,what:1,yasa:[2,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36]}})
\ No newline at end of file
diff --git a/docs/build/plot_directive/generated/yasa-EpochByEpochAgreement-4.png b/docs/build/plot_directive/generated/yasa-EpochByEpochAgreement-4.png
new file mode 100644
index 0000000..d1106de
Binary files /dev/null and b/docs/build/plot_directive/generated/yasa-EpochByEpochAgreement-4.png differ
diff --git a/docs/build/plot_directive/generated/yasa-Hypnogram-2.png b/docs/build/plot_directive/generated/yasa-Hypnogram-2.png
new file mode 100644
index 0000000..c766e36
Binary files /dev/null and b/docs/build/plot_directive/generated/yasa-Hypnogram-2.png differ
diff --git a/docs/changelog.rst b/docs/changelog.rst
index c89a363..cb78872 100644
--- a/docs/changelog.rst
+++ b/docs/changelog.rst
@@ -44,6 +44,16 @@ Please see the documentation of :py:class:`yasa.Hypnogram` for more details.
----------------------------------------------------------------------------------------
+v0.6.5 (July 2024)
+---------------------
+
+Minor release with a brand new Evaluation module and several minor bugfixes
+
+- `PR 130 `_: Add new :py:class:`yasa.EpochByEpochAgreement` and :py:class:`yasa.SleepStatsAgreement` modules for evaluating the agreement between two scorers (e.g. human vs YASA), either at the epoch-by-epoch level or at the level of summary sleep statistics. This is an experimental feature. Remaining tasks to complete the Evaluation pipeline are described in: https://github.com/raphaelvallat/yasa/issues/166
+- `PR 171 `_: Fix deprecated `scipy.integrate.simps``.
+
+----------------------------------------------------------------------------------------
+
v0.6.4 (January 2024)
---------------------
diff --git a/setup.py b/setup.py
index 5780c24..307a047 100644
--- a/setup.py
+++ b/setup.py
@@ -12,7 +12,7 @@
URL = "https://github.com/raphaelvallat/yasa/"
LICENSE = "BSD (3-clause)"
DOWNLOAD_URL = "https://github.com/raphaelvallat/yasa/"
-VERSION = "0.6.4"
+VERSION = "0.6.5"
PACKAGE_DATA = {"yasa.data.icons": ["*.svg"]}
INSTALL_REQUIRES = [
diff --git a/yasa/__init__.py b/yasa/__init__.py
index 7177a2f..a750a04 100644
--- a/yasa/__init__.py
+++ b/yasa/__init__.py
@@ -15,4 +15,4 @@
logging.basicConfig(format="%(asctime)s | %(levelname)s | %(message)s", datefmt="%d-%b-%y %H:%M:%S")
__author__ = "Raphael Vallat "
-__version__ = "0.6.4"
+__version__ = "0.6.5"
diff --git a/yasa/hypno.py b/yasa/hypno.py
index 4789eb1..e782361 100644
--- a/yasa/hypno.py
+++ b/yasa/hypno.py
@@ -606,10 +606,6 @@ def evaluate(self, obs_hyp):
recall 0.550
fbeta 0.524
Name: agreement, dtype: float64
-
- .. plot::
-
- >>> ebe.plot_hypnograms()
"""
return EpochByEpochAgreement([self], [obs_hyp])
@@ -821,7 +817,7 @@ def sleep_statistics(self):
The definition of REM latency in the AASM scoring manual differs from the REM latency
reported here. The former uses the time from first epoch of sleep, while YASA uses the
time from the beginning of the recording. The AASM definition of the REM latency can be
- found with `SOL - Lat_REM`.
+ found with `Lat_REM - SOL`.
References
----------
diff --git a/yasa/sleepstats.py b/yasa/sleepstats.py
index 5988350..99643cf 100644
--- a/yasa/sleepstats.py
+++ b/yasa/sleepstats.py
@@ -183,7 +183,7 @@ def sleep_statistics(hypno, sf_hyp):
The definition of REM latency in the AASM scoring manual differs from the REM latency
reported here. The former uses the time from first epoch of sleep, while YASA uses the
time from the beginning of the recording. The AASM definition of the REM latency can be
- found with `SOL - Lat_REM`.
+ found with `Lat_REM - SOL`.
References
----------