Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding AZSS correction per subscan #1065

Open
wants to merge 36 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 34 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
1a129de
align with master
susannaaz Dec 9, 2024
f211e88
cleanup
susannaaz Dec 10, 2024
166aa3c
Merge remote-tracking branch 'upstream/master' into 20241209_preproc_…
susannaaz Dec 10, 2024
5b5af2d
temporarily taken away azss per subscan, do in another PR
susannaaz Dec 10, 2024
0c59a8d
cleanup functions
susannaaz Dec 11, 2024
25be19f
eliminate duplicate functions in filters
susannaaz Dec 11, 2024
5f2e13e
rewrite docstring
susannaaz Dec 11, 2024
7a73c18
cleaned darkdets function
susannaaz Dec 11, 2024
15053cf
minor cleanup functions and docstrings
susannaaz Dec 11, 2024
d1f3737
correct spacings
susannaaz Dec 11, 2024
138cb05
rm bad subscans flagging
susannaaz Dec 11, 2024
1ee65ec
some minor format fixes
chervias Dec 11, 2024
8dac03d
some more minor format fixes
chervias Dec 11, 2024
bf0abb7
Merge branch 'master' into 20241209_preproc_mapmaking
Dec 13, 2024
e8d4874
fix focalplane nan flagging
susannaaz Dec 13, 2024
907289c
- refactor common mode deprojection to simultaneously treat Q/U\n\- u…
susannaaz Dec 15, 2024
1e07280
Merge remote-tracking branch 'origin' into 20241209_preproc_mapmaking
susannaaz Dec 15, 2024
6d888d9
align init with deprojection functions
susannaaz Dec 15, 2024
539f72d
interfaced noisy subscans process with get stats, call subscan azss e…
susannaaz Dec 16, 2024
b0cae07
azss: try to fix IndexError
earosenberg Dec 16, 2024
9a318b8
function to flag noisy subscans
susannaaz Dec 16, 2024
613323c
Pull out azss_model generation fn.
msilvafe Dec 16, 2024
a85e273
Pull out azss_stats prep and left/right handling.
msilvafe Dec 16, 2024
29582fe
Finish up tod_ops.azss
msilvafe Dec 16, 2024
c46c7e3
Update process method.
msilvafe Dec 17, 2024
b7ef718
Fixed bugs.
msilvafe Dec 17, 2024
7a7d6be
Merge branch 'azss_update' into 20241210_preproc_mapmaking_azsssubscan
msilvafe Dec 17, 2024
a6443e4
Fix broken test.
msilvafe Dec 17, 2024
0e546fc
Address failing test.
msilvafe Dec 17, 2024
a42869a
Fix test_azss.py failures.
msilvafe Dec 17, 2024
75bf0d5
Use subscan_flags and RangesMatrix ops in BadSubscans
earosenberg Dec 17, 2024
9a3b564
optional noise flags for noisy subscans
susannaaz Dec 17, 2024
aa22a21
azss tested with bad subscans flags included
susannaaz Dec 18, 2024
6eb4f2b
fixed azss and valid subscans flags
susannaaz Jan 7, 2025
bcf6b8e
Fix azss left-right masking and remove nans from azss model
earosenberg Jan 21, 2025
8782b1a
azss removal: correct interpolation of nans
earosenberg Jan 15, 2025
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
2 changes: 1 addition & 1 deletion sotodlib/mapmaking/demod_mapmaker.py
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ def make_demod_map(context, obslist, noise_model, info,
overwrite=False)
errors.append(error) ; outputs.append((output_init, output_proc)) ;
if error not in [None,'load_success']:
L.info('tod %s:%s:%s failed in the prepoc database'%(obs_id,detset,band))
L.info('tod %s:%s:%s failed in the preproc database'%(obs_id,detset,band))
continue
obs.wrap("weather", np.full(1, "toco"))
obs.wrap("site", np.full(1, site))
Expand Down
121 changes: 108 additions & 13 deletions sotodlib/preprocess/processes.py
Original file line number Diff line number Diff line change
Expand Up @@ -804,37 +804,76 @@ def process(self, aman, proc_aman):
aman.samps.offset + aman.samps.count - trim))


class EstimateAzSS(_Preprocess):
class AzSS(_Preprocess):
"""Estimates Azimuth Synchronous Signal (AzSS) by binning signal by azimuth of boresight.
All process confgis go to `get_azss`. If `method` is 'interpolate', no fitting applied
and binned signal is directly used as AzSS model. If `method` is 'fit', Legendre polynominal
fitting will be applied and used as AzSS model.

Example configuration block::

- name: "estimate_azss"
- name: "azss"
azss_stats_name: 'azss_statsQ'
proc_aman_turnaround_info: 'turnaround_flags'
calc:
signal: 'demodQ'
azss_stats_name: 'azss_statsQ'
range: [-1.57079, 7.85398]
frange: [-1.57079, 7.85398]
bins: 1080
merge_stats: False
merge_model: False
left_right: True
save: True
process:
subtract: True

.. autofunction:: sotodlib.tod_ops.azss.get_azss
"""
name = "estimate_azss"
name = "azss"
def __init__(self, step_cfgs):
self.azss_stats_name = step_cfgs.get('azss_stats_name', 'azss_stats')
self.proc_aman_turnaround_info = step_cfgs.get('proc_aman_turnaround_info', None)

super().__init__(step_cfgs)

def calc_and_save(self, aman, proc_aman):
calc_aman, _ = tod_ops.azss.get_azss(aman, **self.calc_cfgs)
self.save(proc_aman, calc_aman)
# If process is run then just wrap info from process step
if self.process_cfgs:
self.save(proc_aman, aman[self.azss_stats_name])
else:
if self.proc_aman_turnaround_info:
_f = attrgetter(self.proc_aman_turnaround_info)
turnaround_info = _f(proc_aman)
else:
turnaround_info = None
_azss = tod_ops.azss.get_azss(aman, azss_stats_name=self.azss_stats_name,
turnaround_info=turnaround_info,
merge_stats=False, merge_model=False,
subtract_in_place=self.process_cfgs["subtract"],
**self.calc_cfgs)
azss_stats = _azss[0]
self.save(proc_aman, azss_stats)

def save(self, proc_aman, azss_stats):
if self.save_cfgs is None:
return
if self.save_cfgs:
proc_aman.wrap(self.calc_cfgs["azss_stats_name"], azss_stats)
proc_aman.wrap(self.azss_stats_name, azss_stats)

def process(self, aman, proc_aman):
if self.proc_aman_turnaround_info:
_f = attrgetter(self.proc_aman_turnaround_info)
turnaround_info = _f(proc_aman)
else:
turnaround_info = None
if self.azss_stats_name in proc_aman:
if self.process_cfgs["subtract"]:
tod_ops.azss.subtract_azss(aman, proc_aman[self.azss_stats_name],
signal = self.calc_cfgs.get('signal'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very minor formatting on signal = self.calc_cfgs.get('signal') (space not needed).

in_place=True)
else:
tod_ops.azss.get_azss(aman, azss_stats_name=self.azss_stats_name,
turnaround_info=turnaround_info,
merge_stats=True, merge_model=False,
subtract_in_place=self.process_cfgs["subtract"],
**self.calc_cfgs)

class GlitchFill(_Preprocess):
"""Fill glitches. All process configs go to `fill_glitches`.
Expand Down Expand Up @@ -1546,6 +1585,7 @@ def __init__(self, step_cfgs):
super().__init__(step_cfgs)

def calc_and_save(self, aman, proc_aman):
coeff_aman = get_qu_common_mode_coeffs(aman, Q_signal, U_signal, merge)
self.save(proc_aman, aman)

def save(self, proc_aman, aman):
Expand Down Expand Up @@ -1592,7 +1632,7 @@ def save(self, proc_aman, fp_aman):
return
if self.save_cfgs:
proc_aman.wrap("fp_flags", fp_aman)

def select(self, meta, proc_aman=None):
if self.select_cfgs is None:
return meta
Expand Down Expand Up @@ -1621,6 +1661,60 @@ def process(self, aman, proc_aman):
if self.process_cfgs:
pointing_model.apply_pointing_model(aman)

class BadSubscanFlags(_Preprocess):
"""Identifies and flags bad subscans.

Example config block::

- name : "noisy_subscan_flags"
stats_name: tod_stats # optional
calc:
nstd_lim: 5.0
merge: False
save: True
select: True

.. autofunction:: sotodlib.tod_ops.flags.get_badsubscan_flags
"""
name = "noisy_subscan_flags"

def __init__(self, step_cfgs):
self.stats_name = step_cfgs.get('stats_name', 'tod_stats')
super().__init__(step_cfgs)

def calc_and_save(self, aman, proc_aman):
from so3g.proj import RangesMatrix, Ranges
msk_ss = RangesMatrix.zeros((aman.dets.count, aman.samps.count))
msk_det = np.ones(aman.dets.count, dtype=bool)
signal = self.calc_cfgs["subscan_stats"] if isinstance(self.calc_cfgs["subscan_stats"], list) else [self.calc_cfgs["subscan_stats"]]
for sig in signal:
self.calc_cfgs["subscan_stats"] = proc_aman[self.stats_name+"_"+sig[-1]]
_msk_ss, _msk_det = tod_ops.flags.get_noisy_subscan_flags(
aman, **self.calc_cfgs)
msk_ss += _msk_ss
msk_det &= _msk_det
ss_aman = core.AxisManager(aman.dets, aman.samps)
ss_aman.wrap("valid_subscans", msk_ss, [(0, 'dets'), (1, 'samps')])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is True for bad subscans. As such "valid_subscans" is a somewhat confusing name. Perhaps change to "bad_subscans" or something, or at least add a comment.

This is doubly confusing since valid_dets is True for good detectors. Would be good to use the same convention (which I think is to use True for bad ones)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, by default in sotodlib the flags scheme is False for the stuff you want to keep and True for the stuff you want to cut. That is why the parameter in the pointing matrix functions is cuts=, where it expects a flag where the stuff you want to cut is True. This also explains why the union of flags functions is a union (logical OR) and not an intersection (logical AND). So always keep this in mind when creating flags.

det_aman = core.AxisManager(aman.dets)
det_aman.wrap("valid_dets", msk_det)
self.save(proc_aman, ss_aman, "noisy_subscan_flags")
self.save(proc_aman, det_aman, "noisy_dets_flags")

def save(self, proc_aman, calc_aman, name):
if self.save_cfgs is None:
return
if self.save_cfgs:
proc_aman.wrap(name, calc_aman)

def select(self, meta, proc_aman=None):
if self.select_cfgs is None:
return meta
if proc_aman is None:
proc_aman = meta.preprocess
keep = proc_aman.noisy_dets_flags.valid_dets
meta.restrict('dets', proc_aman.dets.vals[keep])
return meta

_Preprocess.register(SplitFlags)
_Preprocess.register(SubtractT2P)
_Preprocess.register(EstimateT2P)
Expand All @@ -1641,7 +1735,7 @@ def process(self, aman, proc_aman):
_Preprocess.register(SubtractHWPSS)
_Preprocess.register(Apodize)
_Preprocess.register(Demodulate)
_Preprocess.register(EstimateAzSS)
_Preprocess.register(AzSS)
_Preprocess.register(GlitchFill)
_Preprocess.register(FlagTurnarounds)
_Preprocess.register(SubPolyf)
Expand All @@ -1655,4 +1749,5 @@ def process(self, aman, proc_aman):
_Preprocess.register(RotateQU)
_Preprocess.register(SubtractQUCommonMode)
_Preprocess.register(FocalplaneNanFlags)
_Preprocess.register(PointingModel)
_Preprocess.register(PointingModel)
_Preprocess.register(BadSubscanFlags)
Loading
Loading