|
6 | 6 | from astropy.io import fits
|
7 | 7 | from astropy.time import Time
|
8 | 8 | from itertools import product
|
| 9 | +import pandas as pd |
9 | 10 |
|
10 | 11 | from kbmod.core.image_stack_py import LayeredImagePy
|
11 | 12 |
|
@@ -114,3 +115,121 @@ def load_deccam_layered_image(filename, psf):
|
114 | 115 | )
|
115 | 116 |
|
116 | 117 | return img
|
| 118 | + |
| 119 | + |
| 120 | +def get_unique_obstimes(all_obstimes): |
| 121 | + """Get the unique observation times and their indices. |
| 122 | + Used to group observations for mosaicking. |
| 123 | +
|
| 124 | + Parameters |
| 125 | + ---------- |
| 126 | + all_obstimes : `np.ndarray` |
| 127 | + The array of observation times. |
| 128 | +
|
| 129 | + Returns |
| 130 | + ------- |
| 131 | + unique_obstimes : `np.ndarray` |
| 132 | + The unique observation times. |
| 133 | + unique_indices : `list` |
| 134 | + A list of lists, where each sublist contains the indices of the grouping. |
| 135 | + """ |
| 136 | + unique_obstimes = np.unique(all_obstimes) |
| 137 | + unique_indices = [list(np.where(all_obstimes == time)[0]) for time in unique_obstimes] |
| 138 | + return unique_obstimes, unique_indices |
| 139 | + |
| 140 | + |
| 141 | +def get_magnitude(flux, zero_point): |
| 142 | + """Convert a flux value to a magnitude using the zero point. |
| 143 | +
|
| 144 | + Parameters |
| 145 | + ---------- |
| 146 | + flux : `float` |
| 147 | + The flux value to convert. |
| 148 | + zero_point : `float` |
| 149 | + The zero point of the observations. |
| 150 | +
|
| 151 | + Returns |
| 152 | + ------- |
| 153 | + mag : `float` |
| 154 | + The calculated magnitude. |
| 155 | + """ |
| 156 | + mag = -2.5 * np.log10(flux) + zero_point |
| 157 | + return mag |
| 158 | + |
| 159 | + |
| 160 | +def unravel_results(results, image_collection, obscode="X05", batch_id=None): |
| 161 | + """Take a results file and transform it into a table of individual observations. |
| 162 | +
|
| 163 | + Parameters |
| 164 | + ---------- |
| 165 | + results : `kbmod.results.Results` |
| 166 | + The results. |
| 167 | + image_collection : `kbmod.image_collection.ImageCollection` |
| 168 | + The image collection containing the images used in the results. |
| 169 | + obscode : `str`, optional |
| 170 | + The observatory code to use for the observations. |
| 171 | + Default: "X05" (LSST). |
| 172 | + batch_id : `str`, optional |
| 173 | + The batch ID to use for this result set. |
| 174 | + individual observation ids will be in the format of |
| 175 | + "{batch_id}-{result #}-{observation #}". |
| 176 | +
|
| 177 | + Returns |
| 178 | + ------- |
| 179 | + final_df : `pandas.DataFrame` |
| 180 | + A DataFrame containing the individual observations with columns: |
| 181 | + - id: The unique identifier for the observation. |
| 182 | + - ra: The right ascension of the observation in degrees. |
| 183 | + - dec: The declination of the observation in degrees. |
| 184 | + - magnitude: The magnitude of the observation. |
| 185 | + - mjd: The modified Julian date of the observation. |
| 186 | + - band: The band of the observation. |
| 187 | + - obscode: The observatory code for the observation. |
| 188 | + """ |
| 189 | + zp = np.mean(image_collection["zeroPoint"]) |
| 190 | + |
| 191 | + ids = [] |
| 192 | + ras = [] |
| 193 | + decs = [] |
| 194 | + mags = [] |
| 195 | + mjds = [] |
| 196 | + bands = [] |
| 197 | + obscodes = [] |
| 198 | + |
| 199 | + all_times = results.table.meta["mjd_mid"] |
| 200 | + all_bands = image_collection["band"] |
| 201 | + |
| 202 | + _, unique_indices = get_unique_obstimes(image_collection["mjd_mid"]) |
| 203 | + first_of_each_frame = np.array([i[0] for i in unique_indices]) |
| 204 | + |
| 205 | + for i, row in enumerate(results): |
| 206 | + if "obs_valid" in results.table.colnames: |
| 207 | + valid_obs = row["obs_valid"] |
| 208 | + else: |
| 209 | + valid_obs = np.full(row["obs_count"], True) |
| 210 | + num_valid = row["obs_count"] |
| 211 | + |
| 212 | + # need to figure out a better way to do this |
| 213 | + if batch_id is not None: |
| 214 | + ids.append([f"{batch_id}-{i}-{j}" for j in range(num_valid)]) |
| 215 | + else: |
| 216 | + ids.append([f"{i}-{j}" for j in range(num_valid)]) |
| 217 | + |
| 218 | + ras.append(row["img_ra"][valid_obs]) |
| 219 | + decs.append(row["img_dec"][valid_obs]) |
| 220 | + |
| 221 | + mags.append([get_magnitude(row["flux"], zp)] * num_valid) |
| 222 | + mjds.append(all_times[valid_obs]) |
| 223 | + bands.append(all_bands[first_of_each_frame][valid_obs]) |
| 224 | + obscodes.append([obscode] * num_valid) |
| 225 | + |
| 226 | + final_df = pd.DataFrame() |
| 227 | + final_df["id"] = np.concatenate(ids) |
| 228 | + final_df["ra"] = np.concatenate(ras) |
| 229 | + final_df["dec"] = np.concatenate(decs) |
| 230 | + final_df["magnitude"] = np.concatenate(mags) |
| 231 | + final_df["mjd"] = np.concatenate(mjds) |
| 232 | + final_df["band"] = np.concatenate(bands) |
| 233 | + final_df["obscode"] = np.concatenate(obscodes) |
| 234 | + |
| 235 | + return final_df |
0 commit comments