Skip to content

Commit 57e7181

Browse files
authored
Merge pull request #32 from GernotMaier/light-curve-plotting
Improved light curve plotting
2 parents 4d33c15 + dbcaf51 commit 57e7181

File tree

6 files changed

+123
-78
lines changed

6 files changed

+123
-78
lines changed

README.md

+20-3
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Activate the environment to start the analysis:
3636

3737
```bash
3838
conda activate v2dl5
39-
export PYTHONPATH=$PYTHONPATH:"${PWD}"
39+
pip install -e .
4040
```
4141

4242
## Run list generator
@@ -46,10 +46,27 @@ It generates a lot of printout which should be used to fine tune the run selecti
4646

4747
Example:
4848

49-
```bash
50-
49+
```console
5150
python v2dl5/scripts/generate_runlist.py \
5251
--obs_table ../../../VTS/DL3/v490/dl3_pointlike_moderate2tel/obs-index.fits.gz \
5352
--config examples/run_selection.yml \
5453
--output_dir my_output_dir
5554
```
55+
56+
## Reflected region analysis
57+
58+
```console
59+
python v2dl5/scripts/reflected_region_analysis.py \
60+
--obs_table ../../../VTS/DL3/v490/dl3_pointlike_moderate2tel/obs-index.fits.gz \
61+
--runlist my_output_dir/runlist.txt \
62+
--config examples/reflected_region_analysis.yml \
63+
--output_dir my_output_dir
64+
```
65+
66+
## Binary light curve plotting
67+
68+
```console
69+
python v2dl5/scripts/plot_binary_light_curves.py \
70+
--instrument VERITAS \
71+
--configuration examples/binary_lightcurve_plotting.yml
72+
```
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
data:
2+
- instrument: VERITAS
3+
file_name: results/light_curve_nightly.ecsv
4+
plot_instrument: true
5+
plot_variable: flux
6+
flux_axis_label: "Flux E>350 GeV (1/(cm$^2$s))"
7+
marker_type: 'o'
8+
marker_color: 'r'

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ dependencies = [
3030
"astroquery",
3131
"gammapy",
3232
"Ipython",
33-
"pydantic<2",
33+
"pydantic",
3434
]
3535

3636
[project.optional-dependencies]

v2dl5/light_curves/binary_plotting.py

+40-17
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,22 @@ def plot_flux_vs_time(self, time_axis="MJD", mjd_min=None, mjd_max=None, file_ty
5050
colors = plotting_utilities.get_color_list(len(self.data))
5151

5252
for idx, (instrument, data) in enumerate(self.data.items()):
53-
x, y, e = self._get_light_curve_in_MJD_limits(data, time_axis, mjd_min, mjd_max)
53+
x, y, e, x_ul, y_ul = self._get_light_curve_in_MJD_limits(
54+
data, time_axis, mjd_min, mjd_max
55+
)
5456

5557
if instrument in self.config and self.config["plot_instrument"] is False:
5658
continue
57-
59+
color = (
60+
colors[idx]
61+
if self.config[idx].get("marker_color") is None
62+
else self.config[idx]["marker_color"]
63+
)
64+
marker = (
65+
plotting_utilities.get_marker_list()[idx]
66+
if self.config[idx].get("marker_type") is None
67+
else self.config[idx]["marker_type"]
68+
)
5869
plt.errorbar(
5970
x,
6071
y,
@@ -65,21 +76,26 @@ def plot_flux_vs_time(self, time_axis="MJD", mjd_min=None, mjd_max=None, file_ty
6576
if self.config[idx].get("plot_label") is None
6677
else self.config[idx]["plot_label"]
6778
),
68-
color=(
69-
colors[idx]
70-
if self.config[idx].get("marker_color") is None
71-
else self.config[idx]["marker_color"]
72-
),
73-
marker=(
74-
plotting_utilities.get_marker_list()[idx]
75-
if self.config[idx].get("marker_type") is None
76-
else self.config[idx]["marker_type"]
77-
),
79+
color=color,
80+
marker=marker,
7881
linestyle="none",
7982
fillstyle="none",
8083
linewidth=plotting_utilities.get_line_width(),
8184
markersize=plotting_utilities.get_marker_size(),
8285
)
86+
if len(y_ul) > 0:
87+
plt.errorbar(
88+
x_ul,
89+
y_ul,
90+
yerr=0.1 * max(y_ul),
91+
color=color,
92+
fmt="_",
93+
linestyle="none",
94+
fillstyle="none",
95+
uplims=True,
96+
linewidth=plotting_utilities.get_line_width(),
97+
markersize=plotting_utilities.get_marker_size(),
98+
)
8399

84100
plt.xlabel(self._get_time_axis_label(time_axis))
85101
if mjd_min is not None and mjd_max is not None:
@@ -127,21 +143,28 @@ def _get_light_curve_in_MJD_limits(self, data, time_axis, mjd_min, mjd_max):
127143
x = []
128144
y = []
129145
e = []
146+
x_ul = []
147+
y_ul = []
130148
for i in range(len(data["MJD"])):
131149
if mjd_min is not None and data["MJD"][i] < mjd_min:
132150
continue
133151
if mjd_max is not None and data["MJD"][i] > mjd_max:
134152
continue
135153
if time_axis == "MJD":
136-
x.append(data["MJD"][i])
154+
w_x = data["MJD"][i]
137155
elif time_axis == "orbital phase":
138-
x.append(data["phase"][i])
156+
w_x = data["phase"][i]
139157
else:
140158
self._logger.error(f"Unknown time axis: {time_axis}")
141159
raise ValueError
142-
y.append(data["flux"][i])
143-
e.append(data["flux_err"][i])
144-
return x, y, e
160+
if "flux_ul" in data and data["flux_ul"][i] > 0:
161+
x_ul.append(w_x)
162+
y_ul.append(data["flux_ul"][i])
163+
elif "flux_ul" not in data or data["flux_ul"][i] < 0:
164+
x.append(w_x)
165+
y.append(data["flux"][i])
166+
e.append(data["flux_err"][i])
167+
return x, y, e, x_ul, y_ul
145168

146169

147170
#

v2dl5/light_curves/data_reader.py

+53-56
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
import csv
21
import logging
32

43
import astropy.units as u
4+
import numpy as np
55
import yaml
6+
from astropy.table import Table
67

78
import v2dl5.light_curves.orbital_period as orbit
89

@@ -66,65 +67,11 @@ def _read_fluxes_from_file(self, data_config):
6667
if data_config["file_name"].endswith(".csv") or data_config["file_name"].endswith(
6768
".ecsv"
6869
):
69-
return self._read_fluxes_from_csv_file(data_config)
70+
return self._read_fluxes_from_ecsv_file(data_config)
7071
except KeyError:
7172
self._logger.error("File name not found in configuration file")
7273
raise KeyError
7374

74-
def _read_fluxes_from_csv_file(self, data_config, TimeMinMax=True, MJD_min=-1.0, MJD_max=-1.0):
75-
"""
76-
Read gamma-ray fluxes from csv file (open gamma-ray format)
77-
- ignore all lines with '#'
78-
- accept a random number of spaces as delimiter
79-
80-
Parameters:
81-
-----------
82-
data_config: dict
83-
configuration dictionary
84-
TimeMinMax: bool
85-
flag to read time_min and time_max
86-
MJD_min: float
87-
MJD min value for MJD cut
88-
MJD_max: float
89-
MJD max value for MJD cut
90-
91-
"""
92-
fp = open(data_config["file_name"])
93-
rdr = csv.DictReader(
94-
filter(lambda row: row[0] != "#", fp), delimiter=" ", skipinitialspace=True
95-
)
96-
f = {}
97-
f["time_min"] = []
98-
f["time_max"] = []
99-
f["flux"] = []
100-
f["flux_err"] = []
101-
for row in rdr:
102-
if TimeMinMax:
103-
t_min = float(row["time_min"])
104-
t_max = float(row["time_max"])
105-
else:
106-
t_min = float(row["time"])
107-
t_max = float(row["time"]) + 0.1
108-
if MJD_min > 0 and t_min < MJD_min:
109-
continue
110-
if MJD_max > 0 and t_max > MJD_max:
111-
continue
112-
113-
f["time_min"].append(t_min)
114-
f["time_max"].append(t_max)
115-
116-
f["flux"].append(float(row["flux"]))
117-
if "flux_err" in row:
118-
f["flux_err"].append(float(row["flux_err"]))
119-
elif "flux_up" in row:
120-
f["flux_err"].append(0.5 * abs(float(row["flux_up"]) - float(row["flux_down"])))
121-
fp.close()
122-
123-
f["MJD"] = [0.5 * (a + b) for a, b in zip(f["time_min"], f["time_max"])]
124-
f["MJD_err"] = [0.5 * (b - a) for a, b in zip(f["time_min"], f["time_max"])]
125-
126-
return f
127-
12875
def _add_orbital_parameters(self, data):
12976
"""
13077
Add orbital phase to light-curve data data.
@@ -165,3 +112,53 @@ def convert_photon_to_energy_flux(C_v, C_e, E_0, gamma):
165112
# conversion to erg
166113
f = f * (E_0.to(u.erg)).value
167114
return [v * f for v in C_v], [e * f for e in C_e]
115+
116+
def _read_fluxes_from_ecsv_file(self, data_config, TimeMinMax=True, MJD_min=-1.0, MJD_max=-1.0):
117+
"""
118+
Read gamma-ray fluxes from ecsv file (open gamma-ray format)
119+
120+
Parameters:
121+
-----------
122+
data_config: dict
123+
configuration dictionary
124+
TimeMinMax: bool
125+
flag to read time_min and time_max
126+
MJD_min: float
127+
MJD min value for MJD cut
128+
MJD_max: float
129+
MJD max value for MJD cut
130+
131+
"""
132+
table = Table.read(data_config["file_name"])
133+
f = {}
134+
if not TimeMinMax:
135+
table["time_min"] = table["time"].data
136+
table["time_max"] = table["time"].data + 0.1
137+
138+
# MJD filter
139+
condition = np.ones(len(table), dtype=bool)
140+
if MJD_min > -1:
141+
condition &= table["time_min"] > MJD_min
142+
if MJD_max > -1:
143+
condition &= table["time_max"] < MJD_max
144+
table = table[condition]
145+
146+
f = {}
147+
f["time_min"] = table["time_min"].data.tolist()
148+
f["time_max"] = table["time_max"].data.tolist()
149+
f["flux"] = table["flux"].data.flatten().tolist()
150+
if "flux_err" in table.colnames:
151+
f["flux_err"] = table["flux_err"].data.flatten().tolist()
152+
else:
153+
up = table["flux_up"].data.flatten().tolist()
154+
down = table["flux_down"].data.flatten().tolist()
155+
f["flux_err"] = [0.5 * abs(u - d) for u, d in zip(up, down)]
156+
f["MJD"] = [0.5 * (a + b) for a, b in zip(f["time_min"], f["time_max"])]
157+
f["MJD_err"] = [0.5 * (b - a) for a, b in zip(f["time_min"], f["time_max"])]
158+
if "flux_ul" in table.colnames:
159+
flux_ul = table["flux_ul"].data.flatten().tolist()
160+
is_ul = table["is_ul"].data.flatten().tolist()
161+
f["flux_ul"] = [flux if is_ul else -1.0 for flux, is_ul in zip(flux_ul, is_ul)]
162+
else:
163+
f["flux_ul"] = [-1.0 for _ in f["flux"]]
164+
return f

v2dl5/plot.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ def plot_light_curve(self, light_curve, plot_name):
207207
)
208208

209209
try:
210-
light_curve.plot(ax=ax, marker="o", label=plot_name, sed_type="flux")
210+
light_curve.plot(ax=ax, marker="o", label=plot_name, sed_type="flux", time_format="mjd")
211211
ax.set_yscale("linear")
212212
self._plot(
213213
plot_name="light_curve_" + plot_name.replace(" ", "_"), output_dir=self.output_dir

0 commit comments

Comments
 (0)