Skip to content

Commit 1458308

Browse files
authored
Merge pull request #53 from duxfrederic/minor_dev
- added option to skip background subtraction - common star footprint star query fixed - switching from panstarrs dr2 to dr1 due to problems in querying dr2. - oversized keywords handling for lsst headers - gaia star position plot: plotting roi as well
2 parents 8ddef0d + 27221d7 commit 1458308

11 files changed

Lines changed: 66 additions & 29 deletions

File tree

lightcurver/pipeline/example_config_file/config.yaml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,12 @@ telescope:
7070
############################################# Background estimation ####################################################
7171

7272
# We need to very precisely subtract the background. The quality of the photometry depends immensely on this.
73-
# `sep` does a great job at this, but we offer the possibility to first mask the sources before estimating the
74-
# background (in case of crowded fields)
73+
do_background_subtraction: true # set to false if images are already background subtracted.
74+
# `sep` does a great job at background subraction, but we offer the possibility to first mask the sources before
75+
# background estimation (in case of crowded fields)
7576
mask_sources_before_background: false
7677
# also, if you have strong gradients, you might want to allow your image to be subdivided in more boxes.
77-
background_estimation_n_boxes: 10
78+
background_estimation_n_boxes: 3
7879
# (this is how many boxes we divide the side of the image in, so in total there'll be the square of this number boxes)
7980

8081

lightcurver/plotting/sources_plotting.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ def plot_footprints_with_stars(footprint_arrays, stars, save_path=None):
9696
"""
9797
fig, ax = plot_footprints(footprint_arrays, common_footprint=None, largest_footprint=None, save_path=None)
9898
for _, star in stars.iterrows():
99+
if star['name'] == 'roi':
100+
ax.plot(star['ra'], star['dec'], 'o', color='red', markersize=10, mfc='None')
99101
ax.plot(star['ra'], star['dec'], 'o', color='red', markersize=5, mfc='None')
100102
ax.text(star['ra'], star['dec'], star['name'], fontsize=8, ha='right')
101103

lightcurver/processes/frame_importation.py

Lines changed: 30 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -77,29 +77,47 @@ def process_new_frame(fits_file, user_config):
7777
cutout_data *= mjd_gain_exptime_dict['gain'] / mjd_gain_exptime_dict['exptime']
7878
# unit: electron per second
7979

80-
# ok, now subtract sky!
80+
# ok, now estimate and subtract sky!
8181
cutout_data_sub, bkg = subtract_background(cutout_data,
8282
mask_sources_first=user_config['mask_sources_before_background'],
8383
n_boxes=user_config['background_estimation_n_boxes'])
84+
# we keep doing this because it is a nice way of getting the background RMS.
85+
# however, if the user specifies that the background is already subtracted, just use the
86+
# original data.
87+
if not user_config['do_background_subtraction']:
88+
cutout_data_sub = cutout_data
89+
# read the background stats:
8490
sky_level_electron_per_second = float(bkg.globalback)
8591
background_rms_electron_per_second = float(bkg.globalrms)
8692
logger.info(f' file {fits_file}: background estimated.')
8793

88-
# before we write, let's keep as much as we can from our previous header
89-
new_header = wcs.to_header()
90-
# then copy non-WCS entries from the original header
91-
for key in header:
92-
if key not in new_header and not key.startswith('WCSAXES') and not key.startswith(
93-
'CRPIX') and not key.startswith('CRVAL') and not key.startswith('CDELT') and not key.startswith(
94-
'CTYPE') and not key.startswith('CUNIT') and not key.startswith('CD') and key not in ['COMMENT',
95-
'HISTORY']:
96-
if key.strip(): # some headers are weird
97-
new_header[key] = header[key]
94+
new_header = header.copy()
95+
# here we branch: if already plate solved, we keep the header intact.
96+
# if not, we delete wcs keywords and populate an initial one from astropy
97+
if not user_config['already_plate_solved']:
98+
wcs_header = wcs.to_header()
99+
# then copy non-WCS entries from the original header
100+
for key in header:
101+
if (
102+
key in wcs_header
103+
or key.startswith('WCSAXES')
104+
or key.startswith('CRPIX')
105+
or key.startswith('CRVAL')
106+
or key.startswith('CDELT')
107+
or key.startswith('CTYPE')
108+
or key.startswith('CUNIT')
109+
or key.startswith('CD')
110+
or key.startswith('A_')
111+
or key.startswith('B_')
112+
):
113+
del new_header[key]
114+
#
115+
new_header.update(wcs_header)
98116
# now we can write the file
99117
write_file = user_config['workdir'] / copied_image_relpath
100118
logger.info(f' Writing file: {write_file}')
101119
fits.writeto(write_file, cutout_data_sub.astype(np.float32),
102-
header=new_header, overwrite=True)
120+
header=new_header, overwrite=True, output_verify="silentfix")
103121
# and find sources
104122
# (do plots if toggle set)
105123
do_plot = user_config.get('source_extraction_do_plots', False)

lightcurver/processes/psf_modelling.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,12 +173,17 @@ def model_all_psfs():
173173
psf_plots_dir.mkdir(exist_ok=True, parents=True)
174174
frame_name = Path(frame['image_relpath']).stem
175175
seeing = frame['seeing_pixels'] * frame['pixel_scale']
176+
# what's the fitted fwhm here?
177+
kwargs_moffat = result['kwargs_psf']['kwargs_moffat']
178+
fwhm_moffat_arcseconds = 0.5 * (kwargs_moffat['fwhm_x'] + kwargs_moffat['fwhm_y']) * frame['pixel_scale']
179+
fwhm_moffat_arcseconds = float(fwhm_moffat_arcseconds.item()) # from jax array to float
176180
loss_history = result['adabelief_extra_fields']['loss_history']
181+
diagnostic_text = f"{frame_name}\nseeing estimation: {seeing:.02f}\nseeing moffat: {fwhm_moffat_arcseconds:.02f}"
177182
plot_psf_diagnostic(datas=datas, noisemaps=noisemaps, residuals=result['residuals'],
178183
full_psf=result['full_psf'],
179184
loss_curve=loss_history,
180185
masks=masks, names=names,
181-
diagnostic_text=f"{frame_name}\nseeing: {seeing:.02f}",
186+
diagnostic_text=diagnostic_text,
182187
save_path=psf_plots_dir / f"{frame['id']}_{frame_name}.jpg")
183188

184189
# now we can do the bookkeeping stuff
@@ -202,10 +207,11 @@ def model_all_psfs():
202207
end_change = np.nanmax(loss_history[loss_index:]) - np.nanmin(loss_history[loss_index:])
203208
relative_loss_differential = float(end_change / initial_change)
204209
insert_params = (frame['id'], float(result['chi2']), relative_loss_differential, psf_ref,
205-
combined_footprint_hash, user_config['subsampling_factor'])
210+
combined_footprint_hash, user_config['subsampling_factor'], fwhm_moffat_arcseconds)
206211
insert_query = f"""
207212
REPLACE INTO PSFs
208-
(frame_id, chi2, relative_loss_differential, psf_ref, combined_footprint_hash, subsampling_factor)
213+
(frame_id, chi2, relative_loss_differential, psf_ref,
214+
combined_footprint_hash, subsampling_factor, fwhm_moffat_arcseconds)
209215
VALUES ({','.join(['?'] * len(insert_params))})
210216
"""
211217
execute_sqlite_query(insert_query, insert_params, is_select=False)

lightcurver/processes/roi_file_preparation.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,12 @@ def fetch_and_adjust_zeropoints(combined_footprint_hash):
108108
zp_scatter_normalized = zeropoints_data['adjusted_zeropoint'].std()
109109
global_zp = zeropoints_data['adjusted_zeropoint'].median()
110110

111-
message = "The scatter in zeropoints before normalizing is lower than after normalizing? Not normal, investigate."
112-
#assert zp_scatter_normalized < zp_scatter_not_normalized, message
111+
if zp_scatter_normalized > zp_scatter_not_normalized:
112+
# This shouldn't happen in well controlled case. (normalising should result in a very stable zeropoint)
113+
# If might happen harmlessly for very low frame numbers.
114+
message = "The scatter in zeropoints before normalizing is lower than after normalizing? Not normal, investigate."
115+
logger = logging.getLogger('lightcurver.roi_file_preparation')
116+
logger.warning(message)
113117

114118
return global_zp, zp_scatter_normalized
115119

lightcurver/processes/star_photometry.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,9 @@ def update_star_fluxes(flux_data):
231231

232232
def do_star_photometry():
233233
"""
234-
Here we do a joint deconvolution of all the frames at once, for each star.
234+
Here we do a joint modelling of all the frames at once, for each star.
235235
This is equivalent to PSF photometry, but we do it in the same way
236-
as the final deconvolution to eliminate potential systematics.
236+
as the final modelling to eliminate potential systematics.
237237
Returns:
238238
239239
"""
@@ -325,11 +325,11 @@ def do_star_photometry():
325325
starlet_global_background=user_config['star_photometry_starlet_global_background']
326326
)
327327
# ok, plot the diagnostic
328-
plot_deconv_dir = user_config['plots_dir'] / 'deconvolutions' / str(combined_footprint_hash)
329-
plot_deconv_dir.mkdir(exist_ok=True, parents=True)
328+
plot_star_modelling_dir = user_config['plots_dir'] / 'star_modelling' / str(combined_footprint_hash)
329+
plot_star_modelling_dir.mkdir(exist_ok=True, parents=True)
330330
loss_history = result['loss_curve']
331331

332-
plot_file = plot_deconv_dir / f"{time_now}_joint_deconv_star_{star['name']}.jpg"
332+
plot_file = plot_star_modelling_dir / f"{time_now}_joint_modelling_star_{star['name']}.jpg"
333333

334334
kwargs_plot = {
335335
'datas': data,

lightcurver/processes/star_querying.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
from astropy.coordinates import SkyCoord
33
import json
44
import numpy as np
5+
import pandas as pd
56

67
from ..utilities.footprint import load_combined_footprint_from_db, get_frames_hash
78
from ..structure.user_config import get_user_config
@@ -120,5 +121,9 @@ def query_gaia_stars():
120121
results = execute_sqlite_query(query)
121122
polygon_list = [np.array(json.loads(result[1])) for result in results]
122123
save_path = user_config['plots_dir'] / 'footprints_with_gaia_stars.jpg'
123-
plot_footprints_with_stars(footprint_arrays=polygon_list, stars=stars_table.to_pandas(), save_path=save_path)
124+
stars_table = stars_table.to_pandas()
125+
roi_coord = user_config['ROI_SkyCoord']
126+
roi_row = {'name': 'roi', 'ra': roi_coord.ra.value, 'dec': roi_coord.dec.value}
127+
stars_table = pd.concat([stars_table, pd.DataFrame([roi_row])], ignore_index=True)
128+
plot_footprints_with_stars(footprint_arrays=polygon_list, stars=stars_table, save_path=save_path)
124129
logger.info(f'Plot of the queried reference Gaia stars saved at {save_path}.')

lightcurver/structure/database.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@ def initialize_database(db_path=None):
385385
psf_ref TEXT, -- convention: sorted concatenation of all star names used in the model.
386386
subsampling_factor INTEGER, -- we do starred (pixelated) PSFs.
387387
relative_loss_differential REAL, -- absolute change in last 10% of the iterations vs beginning
388+
fwhm_moffat_arcseconds REAL DEFAULT NULL, -- keeping track of image quality
388389
FOREIGN KEY (frame_id) REFERENCES frames(id),
389390
FOREIGN KEY (combined_footprint_hash) REFERENCES combined_footprint(hash),
390391
PRIMARY KEY (combined_footprint_hash, frame_id, psf_ref)

lightcurver/utilities/absolute_magnitudes_from_panstarrs.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ def search_panstarrs_around_coordinates(gaia_id):
7373
coord = SkyCoord(ra=ra * u.deg, dec=dec * u.deg, frame='icrs')
7474
radius = 1.5 * u.arcsecond # this is generous given the magnitude of the proper motion of most stars.
7575
try:
76-
result = Catalogs.query_region(coord, radius=radius, catalog="PanSTARRS", data_release="dr2")
76+
result = Catalogs.query_region(coord, radius=radius, catalog="PanSTARRS", data_release="dr1")
7777
except ValueError as e:
7878
# The MAST API occasionally returns 'None' strings in float columns, which astroquery
7979
# fails to convert. Treat this as no result found.

lightcurver/utilities/footprint.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def get_combined_footprint_hash(user_config, frames_id_list):
2222
"""
2323
if user_config['star_selection_strategy'] != 'ROI_disk':
2424
# then it depends on the frames we're considering.
25-
frames_hash = get_frames_hash(frames_id_list)
25+
return get_frames_hash(frames_id_list)
2626
else:
2727
# if ROI_disk, it does not depend on the frames: unique region defined by its radius.
2828
return hash(user_config['ROI_disk_radius_arcseconds'])

0 commit comments

Comments
 (0)