Skip to content

Correction of readout delay using bgmap#1645

Open
satoru99 wants to merge 5 commits into
masterfrom
bgmap_delay
Open

Correction of readout delay using bgmap#1645
satoru99 wants to merge 5 commits into
masterfrom
bgmap_delay

Conversation

@satoru99
Copy link
Copy Markdown
Member

Implement readout delay correction from bgmap data

sotodlib/site_pipeline/update_bgmap_delay.py

  • Core function is run_bgmap_process
  • Analyze bgmap data to fit readout delay from bias step pulse.
  • Estimate sample delay (channel_delay) by interpolation among reliable channels.
  • Save AxisManager into hdf5 and make ManifestDB of bgmaps
  • Make another ManifestDB to map observation to bgmap
  • It can be tested by adding the followings into the context yaml:
metadata:
  - db: '{manifestdir}/smurf_detsets/v0/smurf_detset_info_local.sqlite'
    label: smurf
    det_info: true
    on_missing: fail
  - db: '/pscratch/sd/t/takakura/sojp/bgmap_delay/satp1/manifests/bgmap_delay/satp1_bgmap_delay_20260525/bgmap_delay.sqlite'
    label: bgmap_delay
    unpack:
    - bgmap_delay

sotodlib/tod_ops/filters.py

  • Modify timeshift filter to be able to get 'dt' by name from AxisManger
  • Made fft_apply_filter version like timeconst_filter
  • It will be used with the following preprocess config
process_pipe:
    ...
    - name: "fourier_filter"
      skip_on_sim: True
      process:
        filt_function: "iir_filter"
        filter_params:
          invert: True

    - name: "fourier_filter"
      skip_on_sim: True
      process:
        filt_function: "timeconst_filter"
        filter_params:
          timeconst: "det_cal.tau_eff"
          invert: True

    # delay correction!
    - name: "fourier_filter"
      process:
        filt_function: "timeshift_filter"
        filter_params:
          dt: "bgmap_delay.channel_delay"
          invert: true
      skip_on_sim: true

@satoru99 satoru99 requested review from mhasself and ykyohei May 25, 2026 13:10
Copy link
Copy Markdown
Contributor

@ykyohei ykyohei left a comment

Choose a reason for hiding this comment

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

Thank you so much for making this PR! This looks great.

If I understand correctly, this pipeline can be run both on-site and off-site (i.e. nersc), so I suggest dropping the 'run_method' and modifying '_main', as well as renaming 'run_update_obs_site' and 'run_update_bgmap_site'.

Just to confirm, is it correct that this can only correct step delay, and that we cannot measure global delay using bgmap?

return

# Transient errors of metadata loading.
# These can happen when hwpss_subtraction is True, but we can retry.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This docstring is wrong

We fit three models: expon, exponbox, exponboxw.
They are different in the width of the box window.
"""
# Normalize not to bee very small value
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

bee -> be

std = chdata.mean_resp[:20].std()
y = chdata.mean_resp / std

# Usual BiasStepAnalysis has 20 samples before t=0.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I suggest to define a constant at the beginning and use it everywhere, for example
PRE_STEP_SAMPLES = 20 # samples before bias step at t=0

res.results = aman
res.success = True
except Exception as e:
res.traceback = traceback.format_exc()
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

traceback and fail_msg looks same, and fail_msg is not defined in RunBgmapResult, I suggest to unify these.

bgmap_ids.append(oid)
res.bgmap_ids = bgmap_ids
res.success = True
except Exception as e:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

traceback and fail_msg looks same, and fail_msg is not defined in RunObsResult, I suggest to unify these.

bgmap_ids: Optional[list[str]] = None


def run_obs_process(cfg: BgmapDelayCfg, obs_id: str) -> RunBgmapResult:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
def run_obs_process(cfg: BgmapDelayCfg, obs_id: str) -> RunBgmapResult:
def run_obs_process(cfg: BgmapDelayCfg, obs_id: str) -> RunObsResult:

import logging
from tqdm.auto import tqdm, trange
from dataclasses import dataclass, astuple, field, fields
from typing import Optional, Union, Any, Literal, Callable, Self
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

There are some unused imports
dataclasses.astuple, dataclasses.fields, typing.Any, concurrent.futures.Future

Comment on lines +393 to +406
if np.isscalar(dt):
if invert:
target *= np.exp(2j * np.pi * freqs * dt)
else:
target *= np.exp(-2j * np.pi * freqs * dt)
return

assert(len(dt) == len(target)) # safe zip.
if invert:
for chdt, dest in zip(dt, target):
dest *= np.exp(2j * np.pi * freqs * chdt)
else:
for chdt, dest in zip(dt, target):
dest *= np.exp(-2j * np.pi * freqs * chdt)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think this can be simplified as follows

Suggested change
if np.isscalar(dt):
if invert:
target *= np.exp(2j * np.pi * freqs * dt)
else:
target *= np.exp(-2j * np.pi * freqs * dt)
return
assert(len(dt) == len(target)) # safe zip.
if invert:
for chdt, dest in zip(dt, target):
dest *= np.exp(2j * np.pi * freqs * chdt)
else:
for chdt, dest in zip(dt, target):
dest *= np.exp(-2j * np.pi * freqs * chdt)
if not np.isscalar(dt):
assert(len(dt) == len(target)) # safe zip.
dt = dt[:, None]
if invert:
target *= np.exp(2j * np.pi * freqs * dt)
else:
target *= np.exp(-2j * np.pi * freqs * dt)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants