Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
507d6b6
First working attempt at implementing per-EB solints
psheehan Feb 5, 2024
9a32ff7
Name the solints p0,p1,p2,...,ap0,ap1,...
psheehan Feb 6, 2024
4316601
Catch cases where spw_baseband == '' in check_spw_widest_in_bb
psheehan Jan 29, 2024
5de7f7c
Fixes to get per-EB solints working when EBs have different #s of sol…
psheehan Feb 22, 2024
ad13212
Merge branch 'main' into refactor_code_spwcombine+per_EB_solints
psheehan Mar 25, 2025
94649ed
Merge branch 'make_pip_installable' into make_pip_installable+per_EB_…
psheehan Mar 25, 2025
7f47723
Show solution interval per-EB in the weblog.
psheehan Apr 1, 2025
b22339a
Add option to use uniform solution intervals across all EBs
psheehan Jul 8, 2025
bf072a6
Merge remote-tracking branch 'origin/make_pip_installable' into make_…
psheehan Jul 8, 2025
4d9b729
Use uniform_solints=True for tests for now to match what was previous…
psheehan Jul 8, 2025
001b8b4
Merge remote-tracking branch 'origin/make_pip_installable' into make_…
psheehan Sep 24, 2025
0bdaea3
Merge remote-tracking branch 'upstream/make_pip_installable' into mak…
psheehan Sep 25, 2025
1562607
Add code to enable testing across the major changes brought by per_EB…
psheehan Sep 25, 2025
15edeea
Make sure the SNR_self_EB array is only as long as the vislist passed…
psheehan Sep 30, 2025
98c293f
Merge branch 'make_pip_installable+per_EB_solints' into make_pip_inst…
psheehan Sep 30, 2025
3b50cb0
Add some keywords to exclude from comparison due to expected changes …
psheehan Sep 30, 2025
2f961af
Merge remote-tracking branch 'upstream/make_pip_installable' into mak…
psheehan Nov 10, 2025
f0870b1
Merge remote-tracking branch 'upstream/make_pip_installable' into mak…
psheehan Nov 10, 2025
84a16b5
Merge branch 'make_pip_installable+per_EB_solints' into make_pip_inst…
psheehan Nov 10, 2025
400b94e
Merge remote-tracking branch 'upstream/main' into make_pip_installabl…
psheehan Apr 8, 2026
d23ce03
Ensure inf_EB and *_ap solints are mapped correctly now that we recor…
psheehan Apr 8, 2026
b836a11
Merge remote-tracking branch 'upstream/main' into make_pip_installabl…
psheehan Apr 23, 2026
c28ed09
Properly handle the key_map so that keys whose names changed are look…
psheehan Apr 24, 2026
38f5711
Track the sub-fields to selfcal/gaincal per-EB. Also store the origin…
psheehan May 7, 2026
4392918
No need to add _ap or _EB for solint matching now that we are trackin…
psheehan May 11, 2026
e733a4a
Make sure the ap solints actually use solmode ap
psheehan May 12, 2026
0de423a
Merge branch 'main' into make_pip_installable+per_EB_solints
psheehan May 12, 2026
5fe98a6
sub-fields-to-selfcal was not being properly updated per-vis after ev…
psheehan May 12, 2026
7da3c3f
Track Stop_Reason per EB as well.
psheehan May 12, 2026
2643132
vis should be vislist
psheehan May 13, 2026
bd14292
Merge branch 'main' into make_pip_installable+per_EB_solints
jjtobin May 22, 2026
a859177
Merge remote-tracking branch 'upstream/fix_cocal' into make_pip_insta…
psheehan Jun 2, 2026
9eb76be
Remove print statements that are superseded by updates on this branch.
psheehan Jun 2, 2026
39d1913
Fix a few issues with the merge.
psheehan Jun 8, 2026
c072274
Merge remote-tracking branch 'upstream/main' into make_pip_installabl…
psheehan Jun 17, 2026
c1c5039
Additional fixes to get the benchmark running through.
psheehan Jul 10, 2026
3271b18
Add solint_map for benchmark, along with excluding some relevant keys…
psheehan Jul 10, 2026
64eef5c
Properly handle marginal inf_EB cases for mosaics with the new per-EB…
psheehan Jul 22, 2026
6ffced7
Store Estimated_SNR_too_low reason on removal from vislist so it is h…
psheehan Aug 7, 2026
2b1b227
Only store a solint_snr_per_spw if the spw is actually in an EB.
psheehan Aug 7, 2026
6e7feab
Show the result per EB, as these can differ, and as long as one EB ha…
psheehan Aug 7, 2026
2a37316
Use uniform_solints=True for tests at the moment, and exclude a few a…
psheehan Aug 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions auto_selfcal/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
parser.add_argument('--do_amp_selfcal', default=True)
parser.add_argument('--usermask', default={}, type=ast.literal_eval) # require that it is a CRTF region (CASA region format)
parser.add_argument('--usermodel', default={}, type=ast.literal_eval)
parser.add_argument('--uniform_solints', default=False)
parser.add_argument('--inf_EB_gaincal_combine', default='scan', type=str) # should we get rid of this option?
parser.add_argument('--inf_EB_gaintype', default='G', type=str)
parser.add_argument('--inf_EB_override', action='store_true')
Expand Down
3 changes: 2 additions & 1 deletion auto_selfcal/auto_selfcal.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def auto_selfcal(
inf_EB_gaintype='G',
inf_EB_override=False,
optimize_spw_combine=True, # if False, will not attempt per spw or per baseband solutions for any solint except inf_EB
uniform_solints=False,
gaincal_minsnr=2.0,
gaincal_unflag_minsnr=5.0,
minsnr_to_proceed=2.95,
Expand Down Expand Up @@ -451,7 +452,7 @@ def auto_selfcal(
vis_for_targets[target][band]['vislist'],
spectral_average=spectral_average, sort_targets_and_EBs=sort_targets_and_EBs, scale_fov=scale_fov, inf_EB_gaincal_combine=inf_EB_gaincal_combine,
inf_EB_gaintype=inf_EB_gaintype, apply_cal_mode_default=apply_cal_mode_default, do_amp_selfcal=do_amp_selfcal,
usermask=usermask, usermodel=usermodel,guess_scan_combine=guess_scan_combine,max_solint=max_solint,
uniform_solints=uniform_solints, usermask=usermask, usermodel=usermodel,guess_scan_combine=guess_scan_combine,max_solint=max_solint,
iscalibrator=iscalibrator, do_delay_cal=do_delay_cal, shorter_amp_solints=shorter_amp_solints,
imsize=imsize, cell=cell, refant=refant, debug=debug)

Expand Down
40 changes: 23 additions & 17 deletions auto_selfcal/gaincal_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from .selfcal_helpers import *
from .mosaic_helpers import scan_inf_scan_combine

def gaincal_wrapper(selfcal_library, selfcal_plan, target, band, vis, solint, solint_interval, applymode, iteration,
def gaincal_wrapper(selfcal_library, selfcal_plan, target, band, vis, solint, applymode, iteration,
gaincal_minsnr, gaincal_unflag_minsnr=5.0, minsnr_to_proceed=3.0, rerank_refants=False, unflag_only_lbants=False, unflag_only_lbants_onlyap=False,
calonly_max_flagged=0.0, second_iter_solmode="", unflag_fb_to_prev_solint=False, \
refantmode="flex", mode="selfcal", calibrators="", gaincalibrator_dict={}, allow_gain_interpolation=False,spectral_solution_fraction=0.3,
Expand All @@ -27,6 +27,8 @@ def gaincal_wrapper(selfcal_library, selfcal_plan, target, band, vis, solint, so
## Solve gain solutions per MS, target, solint, and band
##

print(selfcal_plan['solmode'])
print(iteration)
os.system('rm -rf '+sani_target+'_'+vis+'_'+band+'_'+solint+'_'+str(iteration)+'_'+selfcal_plan['solmode'][iteration]+'*.g')

## Reset the gaincal return dictionaries, in case this is a repeat of the current solution interval.
Expand Down Expand Up @@ -92,7 +94,7 @@ def gaincal_wrapper(selfcal_library, selfcal_plan, target, band, vis, solint, so
include_scans = ""
print('Include targets: ', include_targets)

if solint == "scan_inf":
if selfcal_plan[vis]['solint_settings'][solint]['sub-name'] == "scan_inf":
include_scans = scan_inf_scan_combine(selfcal_library, vis, target, gaincalibrator_dict, guess_scan_combine=guess_scan_combine)
else:
include_scans = [include_scans]
Expand All @@ -107,10 +109,10 @@ def gaincal_wrapper(selfcal_library, selfcal_plan, target, band, vis, solint, so
for incl_scan in include_scans:
scan_targets = []
for fid in [selfcal_library['sub-fields-fid_map'][vis][fid] for fid in \
np.intersect1d(selfcal_library['sub-fields-to-gaincal'],list(selfcal_library['sub-fields-fid_map'][vis].keys()))] if incl_scan == '' else \
np.intersect1d(selfcal_library[vis]['sub-fields-to-gaincal'],list(selfcal_library['sub-fields-fid_map'][vis].keys()))] if incl_scan == '' else \
np.intersect1d(msmd.fieldsforscans(np.array(incl_scan.split(",")).astype(int)), \
[selfcal_library['sub-fields-fid_map'][vis][fid] for fid in \
numpy.intersect1d(selfcal_library['sub-fields-to-gaincal'],list(selfcal_library['sub-fields-fid_map'][vis].keys()))]):
numpy.intersect1d(selfcal_library[vis]['sub-fields-to-gaincal'],list(selfcal_library['sub-fields-fid_map'][vis].keys()))]):
# Note: because of the msmd above getting actual fids from the MS, we just need to append fid below.
scan_targets.append(fid)

Expand Down Expand Up @@ -162,13 +164,14 @@ def gaincal_wrapper(selfcal_library, selfcal_plan, target, band, vis, solint, so
spwselect=','.join(str(spw) for spw in selfcal_library['spws_set'][vis][i].tolist())
else:
spwselect=selfcal_library[vis]['spws']

gaintable_name=sani_target+'_'+vis+'_'+band+'_'+solint+'_'+str(iteration)+'_'+selfcal_plan['solmode'][iteration]+'_'+filename_append+'.g'
print('prior to gaincal',gaintable_name, gc_mode)

if gc_mode != 'per_bb':
gcdict=call_gaincal(vis=vis, caltable=gaintable_name, gaintype=selfcal_plan[vis]['solint_settings'][solint]['gaincal_gaintype'][gc_mode], spw=spwselect,
refant=selfcal_library[vis]['refant'], calmode=selfcal_plan['solmode'][iteration], solnorm=solnorm if not do_fallback_calonly else False,
solint=solint_interval.replace('_EB','').replace('_ap','').replace('scan_','').replace('_fb1','').replace('_fb2','').replace('_fb3',''),\
solint=selfcal_plan[vis]['solint_settings'][solint]['interval'].replace('_EB','').replace('_ap','').replace('scan_','').replace('_fb1','').replace('_fb2','').replace('_fb3',''),\
minsnr=gaincal_minsnr if not do_fallback_calonly else max(gaincal_minsnr,gaincal_unflag_minsnr), minblperant=4,combine=gaincal_combine,\
field=incl_targets,scan=incl_scans,gaintable=gaincal_preapply_gaintable,spwmap=gaincal_spwmap,uvrange=selfcal_library['uvrange'],\
interp=gaincal_interpolate, solmode=gaincal_solmode, refantmode='flex',\
Expand All @@ -179,7 +182,7 @@ def gaincal_wrapper(selfcal_library, selfcal_plan, target, band, vis, solint, so
spwselect_bb=selfcal_library[vis]['baseband'][baseband]['spwstring']
gcdict=call_gaincal(vis=vis, caltable=gaintable_name, gaintype=selfcal_plan[vis]['solint_settings'][solint]['gaincal_gaintype'][gc_mode], spw=spwselect_bb,
refant=selfcal_library[vis]['refant'], calmode=selfcal_plan['solmode'][iteration], solnorm=solnorm if not do_fallback_calonly else False,
solint=solint_interval.replace('_EB','').replace('_ap','').replace('scan_','').replace('_fb1','').replace('_fb2','').replace('_fb3',''),\
solint=selfcal_plan[vis]['solint_settings'][solint]['interval'].replace('_EB','').replace('_ap','').replace('scan_','').replace('_fb1','').replace('_fb2','').replace('_fb3',''),\
minsnr=gaincal_minsnr if not do_fallback_calonly else max(gaincal_minsnr,gaincal_unflag_minsnr), minblperant=4,combine=gaincal_combine,\
field=incl_targets,scan=incl_scans,gaintable=gaincal_preapply_gaintable,spwmap=gaincal_spwmap,uvrange=selfcal_library['uvrange'],\
interp=gaincal_interpolate, solmode=gaincal_solmode, refantmode='flex',\
Expand All @@ -195,7 +198,7 @@ def gaincal_wrapper(selfcal_library, selfcal_plan, target, band, vis, solint, so

gaintable_prefix=sani_target+'_'+vis+'_'+band+'_'
# assume that if there is only one mode to attempt, that it is combinespw and don't bother checking.
if 'delay' not in solint:
if 'd' not in solint:
if len(selfcal_plan[vis]['solint_settings'][solint]['modes_to_attempt']) > 1:
get_gaincalmode_flagging_stats(selfcal_library,selfcal_plan,vis,gaintable_prefix,solint)
preferred_mode,fallback,spwmap,spwmapping_for_applycal = \
Expand Down Expand Up @@ -244,7 +247,7 @@ def gaincal_wrapper(selfcal_library, selfcal_plan, target, band, vis, solint, so
remove_modes(selfcal_plan,vis,current_solint_index)


for fid in np.intersect1d(selfcal_library['sub-fields-to-selfcal'],list(selfcal_library['sub-fields-fid_map'][vis].keys())):
for fid in np.intersect1d(selfcal_library[vis]['sub-fields-to-selfcal'],list(selfcal_library['sub-fields-fid_map'][vis].keys())):
selfcal_library[fid][vis][solint]['final_mode']=preferred_mode+''
selfcal_library[fid][vis][solint]['spwmap']=applycal_spwmap.copy()
selfcal_library[fid][vis][solint]['gaincal_combine']=selfcal_plan[vis]['solint_settings'][solint]['gaincal_combine'][preferred_mode]+''
Expand All @@ -263,14 +266,16 @@ def gaincal_wrapper(selfcal_library, selfcal_plan, target, band, vis, solint, so

else: # this else is for ap selfcal
os.system('rm -rf temp*.g')
for fid in np.intersect1d(selfcal_library['sub-fields-to-selfcal'],list(selfcal_library['sub-fields-fid_map'][vis].keys())):
for fid in np.intersect1d(selfcal_library[vis]['sub-fields-to-selfcal'],list(selfcal_library['sub-fields-fid_map'][vis].keys())):
gaincal_spwmap=[]
gaincal_preapply_gaintable=[]
gaincal_interpolate=[]
applycal_gaintable=[]
applycal_interpolate=[]
applycal_spwmap=[]
for j in range(current_solint_index):
if not selfcal_plan['solints'][j] in selfcal_plan[vis]['solint_settings']:
continue
if selfcal_plan[vis]['solint_settings'][selfcal_plan['solints'][j]]['preapply_this_gaintable']: #allow amplitude and phase to be pre-applied
# and selfcal_plan[vis]['solint_settings'][selfcal_plan['solints'][j]]['solmode']=='p':
gaincal_preapply_gaintable.append(selfcal_plan[vis]['solint_settings'][selfcal_plan['solints'][j]]['accepted_gaintable'])
Expand Down Expand Up @@ -306,11 +311,12 @@ def gaincal_wrapper(selfcal_library, selfcal_plan, target, band, vis, solint, so
spwselect=','.join(str(spw) for spw in selfcal_library['spws_set'][vis][i].tolist())
else:
spwselect=selfcal_library[vis]['spws']

gaintable_name='temp_'+solint+'_'+str(iteration)+'_'+selfcal_plan['solmode'][iteration]+'_'+filename_append+'.g'
if gc_mode != 'per_bb':
gcdict=call_gaincal(vis=vis, caltable=gaintable_name, gaintype=selfcal_plan[vis]['solint_settings'][solint]['gaincal_gaintype'][gc_mode], spw=spwselect,
refant=selfcal_library[vis]['refant'], calmode=selfcal_plan['solmode'][iteration], solnorm=solnorm if not do_fallback_calonly else False,
solint=solint_interval.replace('_EB','').replace('_ap','').replace('scan_',''),\
solint=selfcal_plan[vis]['solint_settings'][solint]['interval'].replace('_EB','').replace('_ap','').replace('scan_',''),\
minsnr=gaincal_minsnr if not do_fallback_calonly else max(gaincal_minsnr,gaincal_unflag_minsnr), minblperant=4,combine=gaincal_combine,\
field=str(selfcal_library['sub-fields-fid_map'][vis][fid]),gaintable=gaincal_preapply_gaintable,spwmap=gaincal_spwmap,uvrange=selfcal_library['uvrange'],\
interp=gaincal_interpolate, solmode=gaincal_solmode, refantmode='flex',\
Expand All @@ -321,7 +327,7 @@ def gaincal_wrapper(selfcal_library, selfcal_plan, target, band, vis, solint, so
spwselect_bb=selfcal_library[vis]['baseband'][baseband]['spwstring']
gcdict=call_gaincal(vis=vis, caltable=gaintable_name, gaintype=selfcal_plan[vis]['solint_settings'][solint]['gaincal_gaintype'][gc_mode], spw=spwselect_bb,
refant=selfcal_library[vis]['refant'], calmode=selfcal_plan['solmode'][iteration], solnorm=solnorm if not do_fallback_calonly else False,
solint=solint_interval.replace('_EB','').replace('_ap','').replace('scan_',''),\
solint=selfcal_plan[vis]['solint_settings'][solint]['interval'].replace('_EB','').replace('_ap','').replace('scan_',''),\
minsnr=gaincal_minsnr if not do_fallback_calonly else max(gaincal_minsnr,gaincal_unflag_minsnr), minblperant=4,combine=gaincal_combine,\
field=str(selfcal_library['sub-fields-fid_map'][vis][fid]),gaintable=gaincal_preapply_gaintable,spwmap=gaincal_spwmap,uvrange=selfcal_library['uvrange'],\
interp=gaincal_interpolate, solmode=gaincal_solmode, refantmode='flex',\
Expand All @@ -337,7 +343,7 @@ def gaincal_wrapper(selfcal_library, selfcal_plan, target, band, vis, solint, so
select_best_gaincal_mode(selfcal_library,selfcal_plan,vis,gaintable_prefix,solint,spectral_solution_fraction,minsnr_to_proceed)
else:
preferred_mode=selfcal_plan[vis]['solint_settings'][solint]['modes_to_attempt'][0]
if 'delay' not in solint:
if 'd' not in solint:
get_gaincalmode_flagging_stats(selfcal_library,selfcal_plan,vis,gaintable_prefix,solint)
fallback=''
spwmapping_for_applycal=[]
Expand Down Expand Up @@ -367,7 +373,7 @@ def gaincal_wrapper(selfcal_library, selfcal_plan, target, band, vis, solint, so
remove_modes(selfcal_plan,vis,current_solint_index)


for fid in np.intersect1d(selfcal_library['sub-fields-to-selfcal'],list(selfcal_library['sub-fields-fid_map'][vis].keys())):
for fid in np.intersect1d(selfcal_library[vis]['sub-fields-to-selfcal'],list(selfcal_library['sub-fields-fid_map'][vis].keys())):
selfcal_library[fid][vis][solint]['final_mode']=preferred_mode+''
selfcal_library[fid][vis][solint]['spwmap']=applycal_spwmap.copy()
selfcal_library[fid][vis][solint]['gaincal_combine']=selfcal_plan[vis]['solint_settings'][solint]['gaincal_combine'][preferred_mode]+''
Expand Down Expand Up @@ -442,7 +448,7 @@ def gaincal_wrapper(selfcal_library, selfcal_plan, target, band, vis, solint, so
refant=selfcal_library[vis]["refant"], refantmode=refantmode if 'inf_EB' not in solint else 'flex')

selfcal_library[vis][solint]['fallback']=fallback+''
for fid in np.intersect1d(selfcal_library['sub-fields-to-selfcal'],list(selfcal_library['sub-fields-fid_map'][vis].keys())):
for fid in np.intersect1d(selfcal_library[vis]['sub-fields-to-selfcal'],list(selfcal_library['sub-fields-fid_map'][vis].keys())):
selfcal_library[fid][vis][solint]['fallback']=fallback+''

# If iteration two, try restricting to just the antennas with enough unflagged data.
Expand Down Expand Up @@ -486,7 +492,7 @@ def gaincal_wrapper(selfcal_library, selfcal_plan, target, band, vis, solint, so
if (solint != "inf_EB" and not allow_gain_interpolation) or (allow_gain_interpolation and "inf" not in solint):
# If a given field has > 25% of its solutions flagged then just flag the whole field because it will have too much
# interpolation.
if solint == "scan_inf":
if selfcal_plan[vis]['solint_settings'][solint]['sub-name'] == "scan_inf":
max_n_solutions = max([(scans == scan).sum() for scan in np.unique(scans)])
for scan in np.unique(scans):
scan_n_solutions = (flags[0,0,scans == scan] == False).sum()
Expand All @@ -509,7 +515,7 @@ def gaincal_wrapper(selfcal_library, selfcal_plan, target, band, vis, solint, so
def generate_settings_for_combinespw_fallback(selfcal_library, selfcal_plan, target, band, vis, solint, iteration):
sani_target=sanitize_string(target)
current_solint_index=selfcal_plan['solints'].index(solint)
if selfcal_library['telescope'] == 'VLBA' or 'delay' in solint: # use per_bb in place of combinespw for VLBA fall back'
if selfcal_library['telescope'] == 'VLBA' or 'd' in solint: # use per_bb in place of combinespw for VLBA fall back'
preferred_mode='per_bb'
else:
preferred_mode='combinespw'
Expand Down Expand Up @@ -544,7 +550,7 @@ def generate_settings_for_combinespw_fallback(selfcal_library, selfcal_plan, tar
selfcal_library[vis][solint]['applycal_interpolate']=applycal_interpolate
selfcal_library[vis][solint]['solmode']=selfcal_plan['solmode'][iteration]+''
selfcal_library[vis][solint]['gaincal_combine']=selfcal_plan[vis]['solint_settings'][solint]['gaincal_combine'][preferred_mode]+''
for fid in np.intersect1d(selfcal_library['sub-fields-to-selfcal'],list(selfcal_library['sub-fields-fid_map'][vis].keys())):
for fid in np.intersect1d(selfcal_library[vis]['sub-fields-to-selfcal'],list(selfcal_library['sub-fields-fid_map'][vis].keys())):
selfcal_library[fid][vis][solint]['final_mode']=preferred_mode+'_fallback'
selfcal_library[fid][vis][solint]['spwmap']=applycal_spwmap
selfcal_library[fid][vis][solint]['gaincal_combine']=selfcal_plan[vis]['solint_settings'][solint]['gaincal_combine'][preferred_mode]+''
Expand Down
7 changes: 6 additions & 1 deletion auto_selfcal/image_analysis_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ def get_image_stats(image, mask, backup_mask, selfcal_library, use_nfmask, solin
else:
SNR_NF, RMS_NF = SNR, RMS

for vis in selfcal_library['vislist']:
if suffix in ['dirty','orig','initial','final']:
vislist = selfcal_library['vislist']
else:
vislist = selfcal_library['vislist-to-gaincal']

for vis in vislist:
if suffix in ['dirty','orig','initial','final']:
if spw == 'all':
update_dict = selfcal_library
Expand Down
Loading
Loading