Note
Go to the end to download the full example code.
Compute a spectrogram
Compute the spectrogram of a set of SFTs. This is useful to produce visualizations of the Doppler modulation of a CW signal.
9 import os
10
11 import matplotlib.pyplot as plt
12 import numpy as np
13
14 import pyfstat
15
16 # not github-action compatible
17 # plt.rcParams["font.family"] = "serif"
18 # plt.rcParams["font.size"] = 18
19 # plt.rcParams["text.usetex"] = True
20
21 # workaround deprecation warning
22 # see https://github.com/matplotlib/matplotlib/issues/21723
23 plt.rcParams["axes.grid"] = False
24
25 label = "PyFstatExampleSpectrogramNormPower"
26 outdir = os.path.join("PyFstat_example_data", label)
27 logger = pyfstat.set_up_logger(label=label, outdir=outdir)
28
29 signal = True # turn off for pure noise spectrogram
30 binary = True # turn off for simpler isolated neutron star signal
31 transient = False # turn on for a time-limited signal
32
33 # this sets how strong the signal is compared to the noise (higher value -> weaker)
34 depth = 5
35
36 # Define the tstart and duration of each segment of data,
37 # including some gaps like in real observing runs.
38 gap_duration = 10 * 86400
39 Tsft = 1800
40 segments = [
41 {"tstart": 1000000000, "duration": 120 * 86400},
42 {"tstart": 1000000000 + 120 * 86400 + gap_duration, "duration": 300 * 86400},
43 {"tstart": 1000000000 + 420 * 86400 + 2 * gap_duration, "duration": 120 * 86400},
44 ]
45
46 # Generate timestamps for each segment and concatenate them.
47 timestamps = {
48 "H1": np.concatenate(
49 [
50 segment["tstart"] + Tsft * np.arange(segment["duration"] // Tsft)
51 for segment in segments
52 ]
53 )
54 }
55
56 # general parameters to configure the data to simulate
57 data_parameters = {
58 "sqrtSX": 1e-23,
59 "timestamps": timestamps,
60 "detectors": "H1",
61 "Tsft": 1800,
62 }
63 # For pure noise, we need to select the frequency range ourselves.
64 # For signals, PyFstat auto-estimates this.
65 if not signal:
66 data_parameters.update(
67 {
68 "F0": 100.0,
69 "Band": 0.1,
70 }
71 )
72
73 # parameters for a signal to inject (if signal==True)
74 signal_parameters = {
75 "F0": 100.0,
76 "F1": 0,
77 "F2": 0,
78 "Alpha": 0.0,
79 "Delta": 0.5,
80 "tref": segments[0]["tstart"],
81 "h0": data_parameters["sqrtSX"] / depth if signal else 0.0,
82 "cosi": 1.0,
83 }
84 # optionally add binary orbital parameters
85 if binary:
86 signal_parameters.update(
87 {
88 "tp": segments[0]["tstart"],
89 "asini": 25.0,
90 "period": 50 * 86400,
91 }
92 )
93
94 # optionally add transient parameters
95 if transient:
96 signal_parameters.update(
97 {
98 "transientStartTime": segments[1]["tstart"],
99 "transientTau": segments[1]["duration"],
100 "transientWindowType": "exp", # exponentially decaying signal amplitude
101 }
102 )
103 # making data
104 data = pyfstat.Writer(
105 label=label,
106 outdir=outdir,
107 **data_parameters,
108 signal_parameters=signal_parameters,
109 )
110 data.make_data()
111
112 # make the plot
113 ax = pyfstat.utils.plot_spectrogram(
114 sftfilepattern=data.sftfilepath,
115 detector=data_parameters["detectors"],
116 sqrtSX=data_parameters["sqrtSX"],
117 quantity="normpower",
118 savefig=True,
119 outdir=outdir,
120 label=label,
121 )