Skip to content

Commit

Permalink
Merge pull request #796 from StingraySoftware/update_docs
Browse files Browse the repository at this point in the history
Update and reorder tutorials
  • Loading branch information
matteobachetti committed Feb 21, 2024
2 parents 72816e0 + bdc25cd commit 9675204
Show file tree
Hide file tree
Showing 17 changed files with 703 additions and 343 deletions.
17 changes: 3 additions & 14 deletions docs/dataexplo.rst
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
Data Exploration
****************
More Data Exploration
*********************

These notebook tutorials show some ways to explore data with
Stingray.


A quick look at a NuSTAR observation
====================================

Expand All @@ -16,18 +17,6 @@ In this Tutorial, we will show an example quicklook of a NuSTAR observation.
notebooks/DataQuickLook/Quicklook NuSTAR data with Stingray.ipynb


Spectral timing exploration with NICER
======================================

In this Tutorial, we will show an example spectral timing exploration of a
black hole binary using NICER data.

.. toctree::
:maxdepth: 2

notebooks/Spectral Timing/Spectral Timing Exploration.ipynb


Studying very slow variability with the Lomb-Scargle periodogram
================================================================

Expand Down
23 changes: 18 additions & 5 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -271,15 +271,31 @@ the stingray source directory.
Using Stingray
===============

Getting started
---------------
A Spectral timing exploration
-----------------------------

In this Tutorial, we will show an example spectral timing exploration of a
black hole binary using NICER data. The tutorial includes a hardness-intensity
diagram, the modeling of the power density spectrum, power colors, lag-frequency,
lag-energy, and rms/covariance spectra.

.. toctree::
:maxdepth: 1

notebooks/Spectral Timing/Spectral Timing Exploration.ipynb


Stingray fundamentals
---------------------
.. toctree::
:maxdepth: 2

core
dataexplo
pulsar
modeling
simulator
deadtime

Advanced
--------
Expand All @@ -288,9 +304,6 @@ Advanced
:maxdepth: 2

timeseries
modeling
simulator
deadtime
api

Additional information
Expand Down
2 changes: 1 addition & 1 deletion docs/notebooks
2 changes: 0 additions & 2 deletions stingray/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
import pickle
import warnings
import copy
import logging

import numpy as np
from astropy.table import Table
Expand Down Expand Up @@ -38,7 +37,6 @@
bin_intervals_from_gtis,
time_intervals_from_gtis,
)

from typing import TYPE_CHECKING, Type, TypeVar, Union

if TYPE_CHECKING:
Expand Down
3 changes: 2 additions & 1 deletion stingray/crossspectrum.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@
from .fourier import avg_cs_from_iterables, error_on_averaged_cross_spectrum
from .fourier import avg_cs_from_timeseries, poisson_level
from .fourier import normalize_periodograms, raw_coherence
from .fourier import get_flux_iterable_from_segments, power_color
from .fourier import get_flux_iterable_from_segments
from .fourier import get_rms_from_unnorm_periodogram
from .power_colors import power_color

from scipy.special import factorial

Expand Down
1 change: 0 additions & 1 deletion stingray/events.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
:class:`EventList` is used to handle photon arrival times.
"""

import logging
import warnings

import numpy as np
Expand Down
221 changes: 1 addition & 220 deletions stingray/fourier.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
generate_indices_of_segment_boundaries_binned,
generate_indices_of_segment_boundaries_unbinned,
)

from .utils import (
fft,
fftfreq,
Expand Down Expand Up @@ -105,226 +106,6 @@ def integrate_power_in_frequency_range(
return power_integrated, power_err_integrated


def power_color(
frequency,
power,
power_err=None,
freq_edges=[1 / 256, 1 / 32, 0.25, 2.0, 16.0],
df=None,
m=1,
freqs_to_exclude=None,
poisson_power=0,
return_log=False,
):
"""
Calculate two power colors from a power spectrum.
Power colors are an alternative to spectral colors to understand the spectral state of an
accreting source. They are defined as the ratio of the power in two frequency ranges,
analogously to the colors calculated from electromagnetic spectra.
This function calculates two power colors, using the four frequency ranges contained
between the five frequency edges in ``freq_edges``. Given [f0, f1, f2, f3, f4], the
two power colors are calculated as the following ratios of the integrated power
(which are variances):
+ PC0 = Var([f0, f1]) / Var([f2, f3])
+ PC1 = Var([f1, f2]) / Var([f3, f4])
Errors are calculated using simple error propagation from the integrated power errors.
See Heil et al. 2015, MNRAS, 448, 3348
Parameters
----------
frequency : iterable
The frequencies of the power spectrum
power : iterable
The power at each frequency
Other Parameters
----------------
power_err : iterable
The power error bar at each frequency
freq_edges : iterable, optional, default ``[0.0039, 0.031, 0.25, 2.0, 16.0]``
The five edges defining the four frequency intervals to use to calculate the power color.
If empty, the power color is calculated using the frequencies from Heil et al. 2015.
df : float or float iterable, optional, default None
The frequency resolution of the input data. If None, it is calculated
from the median difference of input frequencies.
m : int, optional, default 1
The number of segments and/or contiguous frequency bins averaged to obtain power
freqs_to_exclude : 1-d or 2-d iterable, optional, default None
The ranges of frequencies to exclude from the calculation of the power color.
For example, the frequencies containing strong QPOs.
A 1-d iterable should contain two values for the edges of a single range. (E.g.
``[0.1, 0.2]``). ``[[0.1, 0.2], [3, 4]]`` will exclude the ranges 0.1-0.2 Hz and 3-4 Hz.
poisson_power : float or iterable, optional, default 0
The Poisson noise level of the power spectrum. If iterable, it should have the same
length as ``frequency``. (This might apply to the case of a power spectrum with a
strong dead time distortion
return_log : bool, optional, default False
Return the base-10 logarithm of the power color and the errors
Returns
-------
PC0 : float
The first power color
PC0_err : float
The error on the first power color
PC1 : float
The second power color
PC1_err : float
The error on the second power color
"""
freq_edges = np.asarray(freq_edges)
if len(freq_edges) != 5:
raise ValueError("freq_edges must have 5 elements")

frequency = np.asarray(frequency)
power = np.asarray(power)

if df is None:
df = np.median(np.diff(frequency))
input_frequency_low_edges = frequency - df / 2
input_frequency_high_edges = frequency + df / 2

if freq_edges.min() < input_frequency_low_edges[0]:
raise ValueError("The minimum frequency is larger than the first frequency edge")
if freq_edges.max() > input_frequency_high_edges[-1]:
raise ValueError("The maximum frequency is lower than the last frequency edge")

if power_err is None:
power_err = power / np.sqrt(m)
else:
power_err = np.asarray(power_err)

if freqs_to_exclude is not None:
if len(np.shape(freqs_to_exclude)) == 1:
freqs_to_exclude = [freqs_to_exclude]

if (
not isinstance(freqs_to_exclude, Iterable)
or len(np.shape(freqs_to_exclude)) != 2
or np.shape(freqs_to_exclude)[1] != 2
):
raise ValueError("freqs_to_exclude must be of format [[f0, f1], [f2, f3], ...]")
for f0, f1 in freqs_to_exclude:
frequency_mask = (input_frequency_low_edges > f0) & (input_frequency_high_edges < f1)
idx0, idx1 = np.searchsorted(frequency, [f0, f1])
power[frequency_mask] = np.mean([power[idx0], power[idx1]])

var00, var00_err = integrate_power_in_frequency_range(
frequency,
power,
freq_edges[:2],
power_err=power_err,
df=df,
m=m,
poisson_power=poisson_power,
)
var01, var01_err = integrate_power_in_frequency_range(
frequency,
power,
freq_edges[2:4],
power_err=power_err,
df=df,
m=m,
poisson_power=poisson_power,
)
var10, var10_err = integrate_power_in_frequency_range(
frequency,
power,
freq_edges[1:3],
power_err=power_err,
df=df,
m=m,
poisson_power=poisson_power,
)
var11, var11_err = integrate_power_in_frequency_range(
frequency,
power,
freq_edges[3:5],
power_err=power_err,
df=df,
m=m,
poisson_power=poisson_power,
)
pc0 = var00 / var01
pc1 = var10 / var11
pc0_err = pc0 * (var00_err / var00 + var01_err / var01)
pc1_err = pc1 * (var10_err / var10 + var11_err / var11)
if return_log:
pc0_err = 1 / pc0 * pc0_err
pc1_err = 1 / pc1 * pc1_err
pc0 = np.log10(pc0)
pc1 = np.log10(pc1)
return pc0, pc0_err, pc1, pc1_err


def hue_from_power_color(pc0, pc1, center=[4.51920, 0.453724]):
"""Measure the angle of a point in the log-power color diagram wrt the center.
Angles are measured in radians, **in the clockwise direction**, with respect to a line oriented
at -45 degrees wrt the horizontal axis.
See Heil et al. 2015, MNRAS, 448, 3348
Parameters
----------
pc0 : float
The (linear, not log!) power color in the first frequency range
pc1 : float
The (linear, not log!) power color in the second frequency range
Other Parameters
----------------
center : iterable, optional, default [4.51920, 0.453724]
The coordinates of the center of the power color diagram
Returns
-------
hue : float
The angle of the point wrt the center, in radians
"""
pc0 = np.log10(pc0)
pc1 = np.log10(pc1)

center = np.log10(np.asarray(center))

return hue_from_logpower_color(pc0, pc1, center=center)


def hue_from_logpower_color(log10pc0, log10pc1, center=(np.log10(4.51920), np.log10(0.453724))):
"""Measure the angle of a point in the log-power color diagram wrt the center.
Angles are measured in radians, **in the clockwise direction**, with respect to a line oriented
at -45 degrees wrt the horizontal axis.
See Heil et al. 2015, MNRAS, 448, 3348
Parameters
----------
log10pc0 : float
The log10 power color in the first frequency range
log10pc1 : float
The log10 power color in the second frequency range
Other Parameters
----------------
center : iterable, optional, default ``log10([4.51920, 0.453724])``
The coordinates of the center of the power color diagram
Returns
-------
hue : float
The angle of the point wrt the center, in radians
"""
hue = 3 / 4 * np.pi - np.arctan2(log10pc1 - center[1], log10pc0 - center[0])
return hue


def positive_fft_bins(n_bin, include_zero=False):
"""
Give the range of positive frequencies of a complex FFT.
Expand Down
1 change: 0 additions & 1 deletion stingray/gti.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import re
import numpy as np
import logging
import warnings
from collections.abc import Iterable
import copy
Expand Down
7 changes: 1 addition & 6 deletions stingray/io.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import logging
import math
import copy
import os
Expand Down Expand Up @@ -734,16 +733,12 @@ def __init__(self):


def mkdir_p(path): # pragma: no cover
"""Safe ``mkdir`` function, found at [so-mkdir]_.
"""Safe ``mkdir`` function
Parameters
----------
path : str
The absolute path to the directory to be created
Notes
-----
.. [so-mkdir] http://stackoverflow.com/questions/600268/mkdir-p-functionality-in-python
"""
import os

Expand Down
2 changes: 1 addition & 1 deletion stingray/loggingconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ def setup_logger():
formatter = CustomFormatter()
handler.setFormatter(formatter)
logger.addHandler(handler)
logger.setLevel(logging.DEBUG)
logger.setLevel(logging.WARNING)

return logger

0 comments on commit 9675204

Please sign in to comment.