AstroToolkit 1.5.1__tar.gz → 1.5.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. {astrotoolkit-1.5.1/src/AstroToolkit.egg-info → astrotoolkit-1.5.2}/PKG-INFO +1 -1
  2. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/pyproject.toml +1 -1
  3. astrotoolkit-1.5.2/src/AstroToolkit/Configuration/baseconfig.py +162 -0
  4. astrotoolkit-1.5.2/src/AstroToolkit/Data/bin_lightcurves.py +106 -0
  5. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Data/dataquery.py +2 -1
  6. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Data/fetch_crts.py +1 -1
  7. astrotoolkit-1.5.2/src/AstroToolkit/Data/fetch_tess.py +75 -0
  8. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Data/lightcurvequery.py +75 -3
  9. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Examples/datapage.py +0 -9
  10. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Plotting/imageplotting.py +1 -1
  11. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Plotting/lightcurveplotting.py +20 -11
  12. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Plotting/plotmap.py +10 -5
  13. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Timeseries/lomb_scargle.py +37 -8
  14. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Tools.py +8 -7
  15. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2/src/AstroToolkit.egg-info}/PKG-INFO +1 -1
  16. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit.egg-info/SOURCES.txt +3 -0
  17. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/LICENSE +0 -0
  18. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/MANIFEST.in +0 -0
  19. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/README.md +0 -0
  20. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/setup.cfg +0 -0
  21. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Config.py +0 -0
  22. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Data/hrdquery.py +0 -0
  23. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Data/imageoverlay.py +0 -0
  24. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Data/imagequery.py +0 -0
  25. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Data/photquery.py +0 -0
  26. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Data/reddeningquery.py +0 -0
  27. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Data/rename_headers.py +0 -0
  28. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Data/sedquery.py +0 -0
  29. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Data/sigmaclip.py +0 -0
  30. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Data/spectrumquery.py +0 -0
  31. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/DatapageElements/datapage_buttons.py +0 -0
  32. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/DatapageElements/metadata_table.py +0 -0
  33. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Datapages.py +0 -0
  34. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Examples/hrd.py +0 -0
  35. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Examples/image.py +0 -0
  36. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Examples/lightcurve.py +0 -0
  37. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Examples/localfiles.py +0 -0
  38. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Examples/sed.py +0 -0
  39. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Examples/spectrum.py +0 -0
  40. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Examples/timeseries.py +0 -0
  41. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/FileHandling/file_naming.py +0 -0
  42. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/FileHandling/file_reading.py +0 -0
  43. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/FileHandling/file_writing.py +0 -0
  44. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Input/input_validation.py +0 -0
  45. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Misc/coordinate_conversions.py +0 -0
  46. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Misc/fitsfiles.py +0 -0
  47. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Misc/gridsetup.py +0 -0
  48. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Misc/identifier_generation.py +0 -0
  49. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Misc/pmcorrection.py +0 -0
  50. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Misc/search.py +0 -0
  51. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Plotting/backdrop_hrd_allmags.fits +0 -0
  52. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Plotting/hrdplotting.py +0 -0
  53. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Plotting/sedplotting.py +0 -0
  54. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Plotting/spectrumplotting.py +0 -0
  55. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit/Timeseries/timeseries_formatting.py +0 -0
  56. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit.egg-info/dependency_links.txt +0 -0
  57. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit.egg-info/requires.txt +0 -0
  58. {astrotoolkit-1.5.1 → astrotoolkit-1.5.2}/src/AstroToolkit.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: AstroToolkit
3
- Version: 1.5.1
3
+ Version: 1.5.2
4
4
  Summary: A package for the gathering and plotting of astronomical data.
5
5
  Author-email: Ethan Moorfield <ethan.moorfield@hotmail.co.uk>
6
6
  Project-URL: Homepage, https://github.com/WD-planets/AstroToolkit
@@ -7,7 +7,7 @@ include-package-data = true
7
7
 
8
8
  [project]
9
9
  name = "AstroToolkit"
10
- version = "1.5.1"
10
+ version = "1.5.2"
11
11
  authors = [
12
12
  { name="Ethan Moorfield", email="ethan.moorfield@hotmail.co.uk"},
13
13
  ]
@@ -0,0 +1,162 @@
1
+ import configparser
2
+ import os
3
+
4
+
5
+ class ConfigStruct(object):
6
+ def __init__(self):
7
+ from importlib_resources import files
8
+
9
+ self.config_file = files("AstroToolkit.Configuration").joinpath("ATKConfig.ini")
10
+ if not os.path.isfile(self.config_file):
11
+ print("No ATKConfig.ini found. Making new one with default values\n")
12
+ self.set_default_config()
13
+ self.write_config()
14
+
15
+ @property
16
+ def supported_keys(self):
17
+ keys = []
18
+ for key, val in vars(self).items():
19
+ if key != "config_file":
20
+ keys.append(key)
21
+ return keys
22
+
23
+ def set_default_config(self):
24
+ from ..Data.dataquery import SurveyInfo
25
+
26
+ overlay_info = SurveyInfo().overlay_param_names
27
+
28
+ self.enable_notifications = "True"
29
+ self.query_data_radius = "3"
30
+ self.query_phot_radius = "3"
31
+ self.query_bulkphot_radius = "3"
32
+ self.query_lightcurve_radius = "3"
33
+ self.query_spectrum_radius = "3"
34
+ self.query_sed_radius = "3"
35
+ self.query_reddening_radius = "5"
36
+ self.query_image_size = "30"
37
+ self.query_image_overlays = "gaia"
38
+ self.query_image_band = "g"
39
+ self.query_lightcurve_atlas_username = "None"
40
+ self.query_lightcurve_atlas_password = "None"
41
+ self.unit_size = "400"
42
+ self.search_radius = "3"
43
+ self.datapage_search_button_radius = "3"
44
+ self.gaia_overlay_mag = overlay_info["gaia"]["default_overlay_mag"]
45
+ self.galex_overlay_mag = overlay_info["galex"]["default_overlay_mag"]
46
+ self.wise_overlay_mag = overlay_info["wise"]["default_overlay_mag"]
47
+ self.sdss_overlay_mag = overlay_info["sdss"]["default_overlay_mag"]
48
+ self.twomass_overlay_mag = overlay_info["twomass"]["default_overlay_mag"]
49
+ self.skymapper_overlay_mag = overlay_info["skymapper"]["default_overlay_mag"]
50
+ self.panstarrs_overlay_mag = overlay_info["panstarrs"]["default_overlay_mag"]
51
+ self.datapage_datatable_radius = "3"
52
+ self.datapage_grid_size = "250"
53
+
54
+ def read_config(self):
55
+ Config = configparser.ConfigParser()
56
+ Config.read(self.config_file)
57
+
58
+ sections = []
59
+ sections.append(Config["global_settings"])
60
+ sections.append(Config["query_settings"])
61
+ sections.append(Config["image_overlay_settings"])
62
+ sections.append(Config["search_settings"])
63
+ sections.append(Config["datapage_settings"])
64
+
65
+ for section in sections:
66
+ for key, val in section.items():
67
+ setattr(self, key, val)
68
+
69
+ def write_config(self):
70
+ config = configparser.ConfigParser()
71
+
72
+ config.add_section("global_settings")
73
+ config.set("global_settings", "enable_notifications", self.enable_notifications)
74
+ config.set("global_settings", "unit_size", self.unit_size)
75
+
76
+ config.add_section("query_settings")
77
+ config.set("query_settings", "query_data_radius", self.query_data_radius)
78
+ config.set("query_settings", "query_phot_radius", self.query_phot_radius)
79
+ config.set(
80
+ "query_settings", "query_bulkphot_radius", self.query_bulkphot_radius
81
+ )
82
+ config.set(
83
+ "query_settings", "query_lightcurve_radius", self.query_lightcurve_radius
84
+ )
85
+ config.set(
86
+ "query_settings", "query_spectrum_radius", self.query_spectrum_radius
87
+ )
88
+ config.set("query_settings", "query_sed_radius", self.query_sed_radius)
89
+ config.set(
90
+ "query_settings", "query_reddening_radius", self.query_reddening_radius
91
+ )
92
+ config.set("query_settings", "query_image_size", self.query_image_size)
93
+ config.set("query_settings", "query_image_overlays", self.query_image_overlays)
94
+ config.set("query_settings", "query_image_band", self.query_image_band)
95
+ config.set(
96
+ "query_settings",
97
+ "query_lightcurve_atlas_username",
98
+ self.query_lightcurve_atlas_username,
99
+ )
100
+ config.set(
101
+ "query_settings",
102
+ "query_lightcurve_atlas_password",
103
+ self.query_lightcurve_atlas_password,
104
+ )
105
+
106
+ config.add_section("image_overlay_settings")
107
+ config.set("image_overlay_settings", "gaia_overlay_mag", self.gaia_overlay_mag)
108
+ config.set(
109
+ "image_overlay_settings", "galex_overlay_mag", self.galex_overlay_mag
110
+ )
111
+ config.set("image_overlay_settings", "wise_overlay_mag", self.wise_overlay_mag)
112
+ config.set("image_overlay_settings", "sdss_overlay_mag", self.sdss_overlay_mag)
113
+ config.set(
114
+ "image_overlay_settings", "twomass_overlay_mag", self.twomass_overlay_mag
115
+ )
116
+ config.set(
117
+ "image_overlay_settings",
118
+ "skymapper_overlay_mag",
119
+ self.skymapper_overlay_mag,
120
+ )
121
+ config.set(
122
+ "image_overlay_settings",
123
+ "panstarrs_overlay_mag",
124
+ self.panstarrs_overlay_mag,
125
+ )
126
+
127
+ config.add_section("search_settings")
128
+ config.set("search_settings", "search_radius", self.search_radius)
129
+
130
+ config.add_section("datapage_settings")
131
+ config.set(
132
+ "datapage_settings",
133
+ "datapage_search_button_radius",
134
+ self.datapage_search_button_radius,
135
+ )
136
+ config.set(
137
+ "datapage_settings",
138
+ "datapage_datatable_radius",
139
+ self.datapage_datatable_radius,
140
+ )
141
+ config.set("datapage_settings", "datapage_grid_size", self.datapage_grid_size)
142
+
143
+ with open(self.config_file, "w") as file:
144
+ config.write(file)
145
+
146
+ def edit_config(self, key, value):
147
+ self.read_config()
148
+ if not isinstance(value, str):
149
+ try:
150
+ value = str(value)
151
+ except:
152
+ raise Exception("ATKConfig.ini options must be strings.")
153
+ setattr(self, key, value)
154
+ self.write_config()
155
+
156
+ self.output_config()
157
+
158
+ def output_config(self):
159
+ self.read_config()
160
+ for key, val in vars(self).items():
161
+ if key != "config_file":
162
+ print(f"{key} = {val}")
@@ -0,0 +1,106 @@
1
+ def binning(data, bins=None, bin_size=None):
2
+ import numpy as np
3
+
4
+ ra = data["ra"]
5
+ dec = data["dec"]
6
+
7
+ mag = data["mag"]
8
+ mag_err = data["mag_err"]
9
+ if "mjd_ori" in data:
10
+ time = data["mjd_ori"]
11
+ time_unit = "mjd_ori"
12
+ else:
13
+ time = data["hjd_ori"]
14
+ time_unit = "hjd_ori"
15
+
16
+ bin_edges_arr = []
17
+
18
+ if bins:
19
+ bin_edge_lower = 0
20
+ bin_size = int(len(time) / bins)
21
+ bin_edge_higher = bin_size
22
+
23
+ while True:
24
+ reached_end = False
25
+ if bin_edge_higher + bin_size >= len(time):
26
+ bin_edge_higher = len(time) - 1
27
+ reached_end = True
28
+
29
+ bin_edges_arr.append([bin_edge_lower, bin_edge_higher])
30
+ bin_edge_lower = bin_edge_higher
31
+ bin_edge_higher += bin_size
32
+
33
+ if reached_end:
34
+ break
35
+
36
+ for i, val in enumerate(bin_edges_arr):
37
+ bin_edges_arr[i][0] = time[val[0]]
38
+ bin_edges_arr[i][1] = time[val[1]]
39
+
40
+ elif bin_size:
41
+ bin_edge_lower = min(time)
42
+
43
+ try:
44
+ bin_unit = bin_size[-1]
45
+ bin_size = float(bin_size[:-1])
46
+ except:
47
+ raise Exception("No binsize unit given.")
48
+
49
+ if bin_unit == "d":
50
+ bin_size = bin_size
51
+ elif bin_unit == "h":
52
+ bin_size = bin_size / 24
53
+ elif bin_unit == "m":
54
+ bin_size = bin_size / (24 * 60)
55
+ else:
56
+ raise Exception("Invalid binsize unit.")
57
+
58
+ bin_edge_higher = bin_edge_lower + bin_size
59
+
60
+ while True:
61
+ reached_end = False
62
+ if bin_edge_higher + bin_size >= max(time):
63
+ bin_edge_higher = max(time)
64
+ reached_end = True
65
+
66
+ bin_edges_arr.append([bin_edge_lower, bin_edge_higher])
67
+ bin_edge_lower = bin_edge_higher
68
+ bin_edge_higher += bin_size
69
+
70
+ if reached_end:
71
+ break
72
+
73
+ final_mags, final_times, final_errors, final_ra, final_dec = [], [], [], [], []
74
+ for bin_edges in bin_edges_arr:
75
+ mask = [i for i, val in enumerate(time) if bin_edges[0] <= val < bin_edges[1]]
76
+
77
+ if len(mask) == 0:
78
+ continue
79
+
80
+ binned_mags = [val for i, val in enumerate(mag) if i in mask]
81
+ binned_ra = [val for i, val in enumerate(ra) if i in mask]
82
+ binned_dec = [val for i, val in enumerate(dec) if i in mask]
83
+
84
+ weights = [1 / pow(err, 2) for i, err in enumerate(mag_err) if i in mask]
85
+
86
+ weighted_mean, norm = np.average(binned_mags, weights=weights, returned=True)
87
+
88
+ mean_ra = sum(binned_ra) / len(binned_ra)
89
+ mean_dec = sum(binned_dec) / len(binned_dec)
90
+
91
+ final_mags.append(weighted_mean)
92
+ final_ra.append(mean_ra)
93
+ final_dec.append(mean_dec)
94
+ final_times.append((bin_edges[1] + bin_edges[0]) / 2)
95
+ final_errors.append(1 / np.sqrt(norm))
96
+
97
+ base_time_unit = time_unit[:-4]
98
+
99
+ data["mag"] = final_mags
100
+ data[time_unit] = final_times
101
+ data["mag_err"] = final_errors
102
+ data[base_time_unit] = [t - min(final_times) for t in final_times]
103
+ data["ra"] = final_ra
104
+ data["dec"] = final_dec
105
+
106
+ return data
@@ -46,6 +46,7 @@ class SurveyInfo:
46
46
  "gaia_lc": [2016, 0],
47
47
  "asassn": [2015, 0],
48
48
  "crts": [2000, 0],
49
+ "tess": [2020, 0],
49
50
  }
50
51
  self.catalogues = {
51
52
  "gaia": "I/355/gaiadr3",
@@ -255,7 +256,7 @@ class SurveyInfo:
255
256
  "ztf",
256
257
  ]
257
258
 
258
- self.lightcurve_surveys = ["atlas", "ztf", "crts", "asassn", "gaia"]
259
+ self.lightcurve_surveys = ["atlas", "ztf", "crts", "asassn", "gaia", "tess"]
259
260
 
260
261
  self.reddening_surveys = ["stilism", "gdre"]
261
262
 
@@ -19,7 +19,7 @@ if not os.path.isfile(str(TIMER)):
19
19
  timer.write(current_time)
20
20
 
21
21
 
22
- # Adapted from codee given by Keith, as CRTS interface is not well-suited to scripted queries
22
+ # Adapted from code given by Keith, as CRTS interface is not well-suited to scripted queries
23
23
  def get_CRTS_lightcurve(pos, radius):
24
24
  ra, dec = pos[0], pos[1]
25
25
 
@@ -0,0 +1,75 @@
1
+ # Adapted from code given by Keith
2
+ def get_TESS_lightcurve(pos, radius):
3
+ """
4
+ Note on converting to magnitudes:
5
+
6
+ https://heasarc.gsfc.nasa.gov/docs/tess/observing-technical.html
7
+ says that 15000 e/s gives a magnitude of 10
8
+
9
+ Tess returns data in astropy quantities - flux in e/s
10
+
11
+ u.Magnitude(lc['flux']) is the same as -2.5*log10(lc['flux'])
12
+
13
+ so plugging in 15000 and m=10 gives zp=20.44*u.ABmag
14
+ """
15
+
16
+ import warnings
17
+
18
+ import astropy.units as u
19
+ import lightkurve as lk
20
+ import numpy as np
21
+ from astropy.table import Table, vstack
22
+
23
+ ra, dec = pos
24
+
25
+ Search = lk.search_lightcurve(
26
+ str(ra) + " " + str(dec), mission="TESS", radius=radius
27
+ )
28
+
29
+ if len(Search) > 0:
30
+ lcurve = []
31
+ for s in Search:
32
+ try:
33
+ lqq = s.download_all()
34
+ lcurve += lqq
35
+ except:
36
+ print("Note: experiencing issues with TESS.")
37
+ sectors = []
38
+ LC = Table([])
39
+ for lc in lcurve:
40
+ if lc.meta["SECTOR"] not in sectors:
41
+ sectors += [lc.meta["SECTOR"]]
42
+ warnings.simplefilter("ignore")
43
+ lc = lc[lc["flux"] > 0]
44
+ lc["mag"] = u.Magnitude(lc["flux"]) + 20.44 * u.ABmag
45
+ lc["mjd"] = lc["time"].mjd.astype("float")
46
+ try:
47
+ tab = lc.to_table()[
48
+ [
49
+ "time",
50
+ "flux",
51
+ "flux_err",
52
+ "sap_flux",
53
+ "quality",
54
+ "mag",
55
+ "mjd",
56
+ ]
57
+ ]
58
+ except:
59
+ tab = lc.to_table()[
60
+ ["time", "flux", "flux_err", "quality", "mag", "mjd"]
61
+ ]
62
+ tab["sap_flux"] = 0
63
+ has_nan = np.zeros(len(tab), dtype=bool)
64
+ for col in tab.itercols():
65
+ if col.info.dtype.kind in ["f", "i"]:
66
+ has_nan |= np.isnan(col)
67
+ tab_nonan = tab[~has_nan]
68
+ if len(LC) == 0:
69
+ LC = tab_nonan
70
+ else:
71
+ LC = vstack([LC, tab_nonan])
72
+ return LC.to_pandas()
73
+ else:
74
+ print("Note: TESS query returned no data.")
75
+ return None
@@ -12,10 +12,12 @@ class LightcurveStruct(object):
12
12
  def __str__(self):
13
13
  return "<ATK Lightcurve Structure>"
14
14
 
15
- def plot(self, kind="lightcurve", colours=None, bands=None, freq=None):
15
+ def plot(self, kind="lightcurve", colours=None, bands=None, freq=None, bins=None):
16
16
  from ..Plotting.plotmap import map_to_plot
17
17
 
18
- return map_to_plot(self, kind=kind, colours=colours, bands=bands, freq=freq)
18
+ return map_to_plot(
19
+ self, kind=kind, colours=colours, bands=bands, freq=freq, bins=bins
20
+ )
19
21
 
20
22
  def sigmaclip(self, sigma=3):
21
23
  from .sigmaclip import sigma_clip
@@ -27,6 +29,21 @@ class LightcurveStruct(object):
27
29
  ]
28
30
  return self
29
31
 
32
+ def bin(self, bins=None, binsize=None):
33
+ from .bin_lightcurves import binning
34
+
35
+ if not bins and not binsize:
36
+ raise Exception("Must provide bins or binsize.")
37
+ elif bins and binsize:
38
+ raise Exception("Both bins and binsize provided.")
39
+
40
+ if self.data:
41
+ self.data = [
42
+ binning(band, bins, binsize) if band is not None else None
43
+ for band in self.data
44
+ ]
45
+ return self
46
+
30
47
 
31
48
  class GeneralQuery(object):
32
49
  def __init__(self, survey, radius, pos, username, password, pmra, pmdec):
@@ -256,6 +273,10 @@ class AtlasQuery(GeneralQuery):
256
273
  data["duJy"].tolist(),
257
274
  )
258
275
 
276
+ chi_arr = [float(x) for x in chi_arr]
277
+ flux = [float(x) for x in flux]
278
+ flux_err = [float(x) for x in flux_err]
279
+
259
280
  # abs(flux) < 3
260
281
  bad_indices_flux = set(
261
282
  [i for i, element in enumerate(flux) if abs(element) < 3]
@@ -751,6 +772,57 @@ class CrtsQuery(GeneralQuery):
751
772
  return [data_dict]
752
773
 
753
774
 
775
+ class TessQuery(GeneralQuery):
776
+ def get_data(self):
777
+ from .fetch_tess import get_TESS_lightcurve
778
+
779
+ data = get_TESS_lightcurve(self.pos, self.radius)
780
+ return data
781
+
782
+ def format_data(self, data):
783
+ import math
784
+
785
+ import numpy as np
786
+
787
+ mjd_ori = data["mjd"].tolist()
788
+ mjd = [t - min(mjd_ori) for t in mjd_ori]
789
+ mag = data["mag"].tolist()
790
+ ra_arr = [self.pos[0]] * len(mag)
791
+ dec_arr = [self.pos[1]] * len(mag)
792
+ flux = data["flux"].tolist()
793
+ flux_err = data["flux_err"].tolist()
794
+
795
+ mag_err = (
796
+ (2.5 / np.log(10)) * (np.asarray(flux_err) / np.asarray(flux))
797
+ ) ** 2 + 0.05**2
798
+ mag_err = [math.sqrt(x) for x in mag_err]
799
+
800
+ mask = [i for i, val in enumerate(mag_err) if val > 1]
801
+
802
+ def filter_data(arr, mask):
803
+ filtered_arr = [val for i, val in enumerate(arr) if i not in mask]
804
+ return filtered_arr
805
+
806
+ mjd_ori = filter_data(mjd_ori, mask)
807
+ mjd = filter_data(mjd, mask)
808
+ mag = filter_data(mag, mask)
809
+ mag_err = filter_data(mag_err, mask)
810
+ ra_arr = filter_data(ra_arr, mask)
811
+ dec_arr = filter_data(dec_arr, mask)
812
+
813
+ data_dict = {
814
+ "band": "i",
815
+ "ra": ra_arr,
816
+ "dec": dec_arr,
817
+ "mjd": mjd,
818
+ "mjd_ori": mjd_ori,
819
+ "mag": mag,
820
+ "mag_err": mag_err,
821
+ }
822
+
823
+ return [data_dict]
824
+
825
+
754
826
  def query(survey, source, pos, radius, username=None, password=None):
755
827
  f_return = LightcurveStruct(survey=survey, source=source, pos=pos, data=None)
756
828
 
@@ -770,7 +842,7 @@ def query(survey, source, pos, radius, username=None, password=None):
770
842
  data = query_object.get_data(source=source)
771
843
  else:
772
844
  data = query_object.get_data(pos=pos)
773
- elif survey == "crts":
845
+ elif survey in ["crts", "tess"]:
774
846
  data = query_object.get_data()
775
847
  else:
776
848
  query_object.set_url()
@@ -32,14 +32,6 @@ lightcurves = query(kind="lightcurve", survey="ztf", source=source).plot(
32
32
  # get SIMBAD and Vizier buttons
33
33
  buttons = buttons(source=source, grid_size=grid_size)
34
34
 
35
- # make a custom metadatatable entry
36
- custom_entry = {
37
- "parameters": ["one"],
38
- "values": ["two"],
39
- "errors": ["three"],
40
- "notes": ["four"],
41
- }
42
-
43
35
  # get a metadata table with default parameters for various surveys
44
36
  metadata = datatable(
45
37
  source=source,
@@ -51,7 +43,6 @@ metadata = datatable(
51
43
  "sdss": "default",
52
44
  "wise": "default",
53
45
  "twomass": "default",
54
- "custom": custom_entry,
55
46
  },
56
47
  )
57
48
 
@@ -6,7 +6,7 @@ from bokeh.plotting import figure
6
6
 
7
7
  def plot_image(struct):
8
8
  plot = figure(
9
- width=400, height=400, title=f'{struct.survey} Image ({struct.data['size']}")'
9
+ width=400, height=400, title=f'{struct.survey} Image ({struct.data["size"]}")'
10
10
  )
11
11
 
12
12
  plot.min_border = 75
@@ -65,12 +65,10 @@ class SupportedColours(object):
65
65
 
66
66
 
67
67
  def plot_data(plot, band, colour, time_min, survey):
68
- if "hjd_ori" in band:
69
- time = band["hjd_ori"]
70
- elif "mjd_ori" in band:
71
- time = band["mjd_ori"]
72
-
73
- time = [x - time_min for x in time]
68
+ if using_original_times:
69
+ time = [x - time_min for x in band[time_unit]]
70
+ else:
71
+ time = band[time_unit]
74
72
 
75
73
  palette, error_colour = SupportedColours(colour).get_cmap
76
74
  source = ColumnDataSource(data={"time": time, "mag": band["mag"]})
@@ -127,14 +125,25 @@ def plot_lightcurve(struct, colours, bands):
127
125
  y_axis_label=f"{lightcurve_bands}",
128
126
  )
129
127
 
128
+ global using_original_times, time_unit
129
+ using_original_times = False
130
+
131
+ if "hjd_ori" in band:
132
+ time_unit = "hjd"
133
+ if band["hjd_ori"]:
134
+ time_unit += "_ori"
135
+ using_original_times = True
136
+ elif "mjd_ori" in band:
137
+ time_unit = "mjd"
138
+ if band["mjd_ori"]:
139
+ time_unit += "_ori"
140
+ using_original_times = True
141
+
130
142
  combined_times = []
131
143
  for band in data:
132
- if "hjd_ori" in band:
133
- combined_times += band["hjd_ori"]
134
- elif "mjd_ori" in band:
135
- combined_times += band["mjd_ori"]
144
+ combined_times += band[time_unit]
136
145
 
137
- time_min = min(combined_times)
146
+ time_min = min(combined_times)
138
147
 
139
148
  for band, colour in zip(data, colours):
140
149
  plot = plot_data(plot, band, colour, time_min, struct.survey)
@@ -12,6 +12,7 @@ def map_to_plot(
12
12
  spectrum_overlay=False,
13
13
  survey=None,
14
14
  freq=None,
15
+ bins=None,
15
16
  ):
16
17
  if not struct.data:
17
18
  print("Note: Plot() missing data, suggests that no data was returned")
@@ -20,6 +21,7 @@ def map_to_plot(
20
21
  else:
21
22
  plot_success = True
22
23
 
24
+ suffix = None
23
25
  if plot_success:
24
26
  if struct.kind == "lightcurve":
25
27
  if kind == "lightcurve":
@@ -32,11 +34,13 @@ def map_to_plot(
32
34
 
33
35
  plot = lomb_scargle(struct.data, freq).powspec_plot
34
36
  dimensions = Dimensions(height=1, width=1)
37
+ suffix = "powspec"
35
38
  elif kind == "phase":
36
39
  from ..Timeseries.lomb_scargle import lomb_scargle
37
40
 
38
- plot = lomb_scargle(struct.data, freq).phasefold_plot
41
+ plot = lomb_scargle(struct.data, freq, bins).phasefold_plot
39
42
  dimensions = Dimensions(height=1, width=1)
43
+ suffix = "phasefold"
40
44
  else:
41
45
  raise Exception("Invalid plotting kind for ATK Lightcurve data.")
42
46
  elif struct.kind == "image":
@@ -77,10 +81,11 @@ def map_to_plot(
77
81
  plot.height = int(config.unit_size) * dimensions.height
78
82
  plot.output_backend = "svg"
79
83
 
80
- if hasattr(struct, "subkind"):
81
- suffix = struct.subkind
82
- else:
83
- suffix = struct.kind
84
+ if not suffix:
85
+ if hasattr(struct, "subkind"):
86
+ suffix = struct.subkind
87
+ else:
88
+ suffix = struct.kind
84
89
 
85
90
  if hasattr(struct, "source"):
86
91
  if struct.source:
@@ -8,7 +8,7 @@ from bokeh.plotting import figure
8
8
  newline = "\n"
9
9
 
10
10
 
11
- def lomb_scargle(data, freq=None):
11
+ def lomb_scargle(data, freq=None, bins=None):
12
12
  class timeseries_data(object):
13
13
  def __init__(self, time, mag, mag_err, power, frequency, freq):
14
14
  self.time = time
@@ -17,6 +17,7 @@ def lomb_scargle(data, freq=None):
17
17
  self.power = power
18
18
  self.frequency = frequency
19
19
  self.phase_freq = freq
20
+ self.phase_bins = bins
20
21
 
21
22
  @property
22
23
  def powspec_plot(self):
@@ -54,18 +55,41 @@ def lomb_scargle(data, freq=None):
54
55
 
55
56
  @property
56
57
  def phasefold_plot(self):
58
+ # code for this function adapted from Keith
59
+ def do_binning(bins, phase, mag, mag_err):
60
+ bin_phase = []
61
+ bin_y = []
62
+ bin_y_err = []
63
+
64
+ mag = np.asarray(mag)
65
+ mag_err = np.asarray(mag_err)
66
+
67
+ for bphase in np.linspace(0, 1 - 1 / bins, num=bins):
68
+ mask = (phase < bphase + 1 / bins) & (phase >= bphase)
69
+ if len(mag[mask]) > 0:
70
+ bin_phase += [bphase + 0.5 / bins]
71
+ weights = 1 / (mag_err[mask] ** 2)
72
+ baverage, norm = np.average(
73
+ mag[mask], weights=weights, returned=True
74
+ )
75
+ bin_y += [baverage]
76
+ bin_y_err += [1 / np.sqrt(norm)]
77
+
78
+ return bin_phase, bin_y, bin_y_err
79
+
57
80
  if not self.phase_freq:
58
81
  best_frequency = self.frequency[np.nanargmax(self.power)]
59
82
  else:
60
83
  best_frequency = self.phase_freq / u.day
61
84
 
62
- t_fit = np.linspace(0, 1, 1000) * u.day
85
+ t_fit = np.linspace(0, 1 / best_frequency.value, 1000) * u.day
63
86
  ls = LombScargle(self.time, self.mag, self.mag_err)
64
87
  y_fit = ls.model(t=t_fit, frequency=best_frequency)
65
88
 
66
89
  phase = (self.time % (1 / best_frequency)) * best_frequency
67
90
 
68
91
  t_fit = t_fit * best_frequency
92
+
69
93
  cut_indices = [i for i, val in enumerate(t_fit) if val > 1]
70
94
 
71
95
  t_fit_formatted = [
@@ -83,10 +107,14 @@ def lomb_scargle(data, freq=None):
83
107
  y_fit_formatted = [x.value - median_mag for x in y_fit_formatted]
84
108
  self.mag_err = [x.value for x in self.mag_err]
85
109
 
110
+ mag = self.mag
111
+ mag_err = self.mag_err
112
+
113
+ if self.phase_bins:
114
+ phase, mag, mag_err = do_binning(self.phase_bins, phase, mag, mag_err)
115
+
86
116
  err_xs = [[x, x] for x in phase]
87
- err_ys = [
88
- [y - y_err, y + y_err] for y, y_err in zip(self.mag, self.mag_err)
89
- ]
117
+ err_ys = [[y - y_err, y + y_err] for y, y_err in zip(mag, mag_err)]
90
118
 
91
119
  plot = figure(
92
120
  width=400,
@@ -94,14 +122,15 @@ def lomb_scargle(data, freq=None):
94
122
  x_axis_label="Phase",
95
123
  y_axis_label="Magnitude (relative to median)",
96
124
  )
97
- plot.scatter(x=phase, y=self.mag, level="guide")
125
+ plot.scatter(x=phase, y=mag, level="guide")
98
126
  plot.line(
99
127
  x=t_fit_formatted,
100
128
  y=y_fit_formatted,
101
- line_width=2,
129
+ line_width=3,
102
130
  line_color="black",
103
- level="underlay",
131
+ level="overlay",
104
132
  legend_label=f"Period: {round(24/(best_frequency.value),2)} h",
133
+ alpha=0.75,
105
134
  )
106
135
  plot.multi_line(
107
136
  xs=err_xs,
@@ -2,17 +2,18 @@ from .Configuration.baseconfig import ConfigStruct
2
2
 
3
3
  """
4
4
  Changelog:
5
- - fixed bug with CRTS light curve queries
6
- - Can now choose a frequency to plot in phase folded light curves
7
- - fixed a bug in input checking that made readfits unusable
8
- - fixed ATLAS light curve queries, extended MJD
9
- - changed GALEX time from [2007,0] to [2006,8], seems to fit high PM object detections better.
5
+ - fixed a bug which seemed to only affect linux where " and ' in an f-string would raise an error
6
+ - improved phase fold plots, sine wave now always goes from 0 to 1. High periods previously truncated this line
7
+ - added support for TESS light curve queries
8
+ - added light curve binning + phase fold binning functionality
10
9
  - other bug fixes
11
- - added reddening to README, forgot in last version
12
10
  """
13
11
 
14
12
  """
15
13
  To-Do:
14
+ - add a special thanks to Keith in the README
15
+ - turn savedata into a method on plot objects
16
+ - include survey name in plot file names, also change name based on subkind
16
17
  - fix (especially tracer) query radius in overlays
17
18
  - update README
18
19
  - input validation for config values
@@ -21,10 +22,10 @@ To-Do:
21
22
  - add check for missing data in savedata
22
23
  - currently, incorrect username/password in ATLAS just says experiencing issues
23
24
  - allow user to choose a file name to save file as
24
- - check atlas query + powspec
25
25
  - add piggyback radius to config for image detection overlays
26
26
  - add a config option for font size
27
27
  - add a config option for svg/png output
28
+ - raw data output (add raw flag that overrides any data filtering, plot tools might need to do some basic filtering to work)
28
29
  """
29
30
 
30
31
  config = ConfigStruct()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: AstroToolkit
3
- Version: 1.5.1
3
+ Version: 1.5.2
4
4
  Summary: A package for the gathering and plotting of astronomical data.
5
5
  Author-email: Ethan Moorfield <ethan.moorfield@hotmail.co.uk>
6
6
  Project-URL: Homepage, https://github.com/WD-planets/AstroToolkit
@@ -10,8 +10,11 @@ src/AstroToolkit.egg-info/SOURCES.txt
10
10
  src/AstroToolkit.egg-info/dependency_links.txt
11
11
  src/AstroToolkit.egg-info/requires.txt
12
12
  src/AstroToolkit.egg-info/top_level.txt
13
+ src/AstroToolkit/Configuration/baseconfig.py
14
+ src/AstroToolkit/Data/bin_lightcurves.py
13
15
  src/AstroToolkit/Data/dataquery.py
14
16
  src/AstroToolkit/Data/fetch_crts.py
17
+ src/AstroToolkit/Data/fetch_tess.py
15
18
  src/AstroToolkit/Data/hrdquery.py
16
19
  src/AstroToolkit/Data/imageoverlay.py
17
20
  src/AstroToolkit/Data/imagequery.py
File without changes
File without changes
File without changes
File without changes