Skip to content

Commit 5d513c1

Browse files
committed
Consistent naming of obs / ob. Port memory counter operator and unit tests. Add clear() method to Observation class.
1 parent 0a3d4e2 commit 5d513c1

File tree

11 files changed

+191
-206
lines changed

11 files changed

+191
-206
lines changed

src/toast/future_ops/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
install(FILES
55
__init__.py
66
pipeline.py
7+
memory_counter.py
78
sim_hwp.py
89
sim_tod_noise.py
910
sim_satellite.py

src/toast/future_ops/__init__.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
# import functions into our public API
66

7+
from .memory_counter import MemoryCounter
8+
79
from .pipeline import Pipeline
810

911
from .sim_satellite import SimSatellite

src/toast/future_ops/noise_model.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,15 @@ def _exec(self, data, detectors=None, **kwargs):
4343

4444
comm = data.comm
4545

46-
for obs in data.obs:
46+
for ob in data.obs:
4747
# Get the detectors we are using for this observation
48-
dets = obs.select_local_detectors(detectors)
48+
dets = ob.select_local_detectors(detectors)
4949
if len(dets) == 0:
5050
# Nothing to do for this observation
5151
continue
5252

5353
# The focalplane for this observation
54-
focalplane = obs.telescope.focalplane
54+
focalplane = ob.telescope.focalplane
5555

5656
# Every process has a copy of the focalplane, and every process may want
5757
# the noise model for all detectors (not just our local detectors).
@@ -73,7 +73,7 @@ def _exec(self, data, detectors=None, **kwargs):
7373
rate=rates, fmin=fmin, detectors=dets, fknee=fknee, alpha=alpha, NET=NET
7474
)
7575

76-
obs[self.noise_model] = noise
76+
ob[self.noise_model] = noise
7777

7878
return
7979

src/toast/future_ops/pointing_healpix.py

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -162,61 +162,61 @@ def _exec(self, data, detectors=None, **kwargs):
162162
# overhead from temporary arrays.
163163
tod_buffer_length = env.tod_buffer_length()
164164

165-
for obs in data.obs:
165+
for ob in data.obs:
166166
# Get the detectors we are using for this observation
167-
dets = obs.select_local_detectors(detectors)
167+
dets = ob.select_local_detectors(detectors)
168168
if len(dets) == 0:
169169
# Nothing to do for this observation
170170
continue
171171

172172
# Get the flags if needed
173173
flags = None
174174
if self.flags is not None:
175-
flags = np.array(obs.shared[self.flags])
175+
flags = np.array(ob.shared[self.flags])
176176
flags &= self.flag_mask
177177

178178
# HWP angle if needed
179179
hwp_angle = None
180180
if self.hwp_angle is not None:
181-
hwp_angle = obs.shared[self.hwp_angle]
181+
hwp_angle = ob.shared[self.hwp_angle]
182182

183183
# Boresight pointing quaternions
184-
boresight = obs.shared[self.boresight]
184+
boresight = ob.shared[self.boresight]
185185

186186
# Focalplane for this observation
187-
focalplane = obs.telescope.focalplane
187+
focalplane = ob.telescope.focalplane
188188

189189
# Optional calibration
190190
cal = None
191191
if self.cal is not None:
192-
cal = obs[self.cal]
192+
cal = ob[self.cal]
193193

194194
# Create output data for the pixels, weights and optionally the
195195
# detector quaternions.
196196

197197
if self.single_precision:
198-
obs.detdata.create(
198+
ob.detdata.create(
199199
self.pixels, detshape=(), dtype=np.int32, detectors=dets
200200
)
201-
obs.detdata.create(
201+
ob.detdata.create(
202202
self.weights,
203203
detshape=(self._nnz,),
204204
dtype=np.float32,
205205
detectors=dets,
206206
)
207207
else:
208-
obs.detdata.create(
208+
ob.detdata.create(
209209
self.pixels, detshape=(), dtype=np.int64, detectors=dets
210210
)
211-
obs.detdata.create(
211+
ob.detdata.create(
212212
self.weights,
213213
detshape=(self._nnz,),
214214
dtype=np.float64,
215215
detectors=dets,
216216
)
217217

218218
if self.quats is not None:
219-
obs.detdata.create(
219+
ob.detdata.create(
220220
self.quats,
221221
detshape=(4,),
222222
dtype=np.float64,
@@ -237,7 +237,7 @@ def _exec(self, data, detectors=None, **kwargs):
237237
# Timestream of detector quaternions
238238
quats = qa.mult(boresight, detquat)
239239
if self.quats is not None:
240-
obs.detdata[self.quats][det, :] = quats
240+
ob.detdata[self.quats][det, :] = quats
241241

242242
# Cal for this detector
243243
dcal = 1.0
@@ -247,9 +247,9 @@ def _exec(self, data, detectors=None, **kwargs):
247247
# Buffered pointing calculation
248248
buf_off = 0
249249
buf_n = tod_buffer_length
250-
while buf_off < obs.n_local_samples:
251-
if buf_off + buf_n > obs.n_local_samples:
252-
buf_n = obs.n_local_samples - buf_off
250+
while buf_off < ob.n_local_samples:
251+
if buf_off + buf_n > ob.n_local_samples:
252+
buf_n = ob.n_local_samples - buf_off
253253
bslice = slice(buf_off, buf_off + buf_n)
254254

255255
# This buffer of detector quaternions
@@ -266,8 +266,8 @@ def _exec(self, data, detectors=None, **kwargs):
266266
fslice = flags[bslice].reshape(-1)
267267

268268
# Pixel and weight buffers
269-
pxslice = obs.detdata[self.pixels][det, bslice].reshape(-1)
270-
wtslice = obs.detdata[self.weights][det, bslice].reshape(-1)
269+
pxslice = ob.detdata[self.pixels][det, bslice].reshape(-1)
270+
wtslice = ob.detdata[self.weights][det, bslice].reshape(-1)
271271

272272
pbuf = pxslice
273273
wbuf = wtslice
@@ -296,7 +296,7 @@ def _exec(self, data, detectors=None, **kwargs):
296296

297297
if self.create_dist is not None:
298298
self._local_submaps[
299-
obs.detdata["pixels"][det] // self._n_pix_submap
299+
ob.detdata["pixels"][det] // self._n_pix_submap
300300
] = True
301301
return
302302

src/toast/future_ops/sim_hwp.py

Lines changed: 56 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -4,95 +4,115 @@
44

55
import numpy as np
66

7+
from astropy import units as u
8+
79
from ..timing import function_timer, Timer
810

911

1012
@function_timer
11-
def simulate_hwp_angle(
12-
obs, obs_key, hwp_start_s, hwp_rpm, hwp_step_deg, hwp_step_time_m
13+
def simulate_hwp_response(
14+
ob,
15+
ob_angle_key=None,
16+
ob_mueller_key=None,
17+
hwp_start=None,
18+
hwp_rpm=None,
19+
hwp_step=None,
20+
hwp_step_time=None,
1321
):
1422
"""Simulate and store the HWP angle for one observation.
1523
1624
Args:
17-
obs (Observation): The observation to populate.
18-
obs_key (str): The observation key for the HWP angle.
19-
hwp_start_s (float): The mission starting time in seconds of the HWP rotation.
25+
ob (Observation): The observation to populate.
26+
ob_time_key (str): The observation shared key for timestamps.
27+
ob_angle_key (str): (optional) The output observation key for the HWP angle.
28+
ob_mueller_key (str): (optional) The output observation key for the full
29+
Mueller matrix.
30+
hwp_start (Quantity): The mission starting time of the HWP rotation.
2031
hwp_rpm (float): The HWP rotation rate in Revolutions Per Minute.
21-
hwp_step_deg (float): The HWP step size in degrees.
22-
hwp_step_time_m (float): The time in minutes between steps.
32+
hwp_step (Quantity): The HWP step size.
33+
hwp_step_time (Quantity): The time between steps.
2334
2435
Returns:
2536
None
2637
2738
"""
28-
if hwp_rpm is None and hwp_step_deg is None:
39+
if ob_mueller_key is not None:
40+
raise NotImplementedError("Mueller matrix not yet implemented")
41+
42+
if hwp_rpm is None and hwp_step is None:
2943
# Nothing to do!
3044
return
3145

32-
if (hwp_rpm is not None) and (hwp_step_deg is not None):
46+
if (hwp_rpm is not None) and (hwp_step is not None):
3347
raise RuntimeError("choose either continuously rotating or stepped HWP")
3448

35-
if hwp_step_deg is not None and hwp_step_time_m is None:
49+
if hwp_step is not None and hwp_step_time is None:
3650
raise RuntimeError("for a stepped HWP, you must specify the time between steps")
3751

52+
hwp_start_s = hwp_start.to_value(u.second)
53+
3854
# compute effective sample rate
39-
times = obs.times
55+
times = ob.shared[ob_time_key]
4056
dt = np.mean(times[1:-1] - times[0:-2])
4157
rate = 1.0 / dt
4258

4359
hwp_rate = None
44-
hwp_step = None
45-
hwp_step_time = None
60+
hwp_step_rad = None
61+
hwp_step_time_s = None
4662

4763
if hwp_rpm is not None:
4864
# convert to radians / second
4965
hwp_rate = hwp_rpm * 2.0 * np.pi / 60.0
5066

5167
if hwp_step_deg is not None:
5268
# convert to radians and seconds
53-
hwp_step = hwp_step_deg * np.pi / 180.0
54-
hwp_step_time = hwp_step_time_m * 60.0
55-
56-
first_samp, n_samp = obs.local_samples
57-
58-
obs.shared.create(
59-
obs_key, shape=(n_samp,), dtype=np.float64, comm=obs.grid_comm_col
60-
)
69+
hwp_step_rad = hwp_set.to_value(u.radian)
70+
hwp_step_time_s = hwp_step_time.to_value(u.second)
6171

6272
# Only the first process in each grid column simulates the common HWP angle
6373

6474
start_sample = int(hwp_start_s * rate)
75+
first_sample = ob.local_index_offset
76+
n_sample = ob.n_local_samples
77+
6578
hwp_angle = None
79+
hwp_mueller = None
6680

67-
if obs.grid_comm_col is None or obs.grid_comm_col.rank == 0:
81+
if ob.grid_comm_col is None or ob.grid_comm_col.rank == 0:
6882
if hwp_rate is not None:
6983
# continuous HWP
7084
# HWP increment per sample is:
7185
# (hwprate / samplerate)
7286
hwpincr = hwp_rate / rate
73-
startang = np.fmod((start_sample + first_samp) * hwpincr, 2 * np.pi)
74-
hwp_angle = hwpincr * np.arange(n_samp, dtype=np.float64)
87+
startang = np.fmod((start_sample + first_sample) * hwpincr, 2 * np.pi)
88+
hwp_angle = hwpincr * np.arange(n_sample, dtype=np.float64)
7589
hwp_angle += startang
7690
elif hwp_step is not None:
7791
# stepped HWP
78-
hwp_angle = np.ones(n_samp, dtype=np.float64)
79-
stepsamples = int(hwp_step_time * rate)
80-
wholesteps = int((start_sample + first_samp) / stepsamples)
81-
remsamples = (start_sample + first_samp) - wholesteps * stepsamples
82-
curang = np.fmod(wholesteps * hwp_step, 2 * np.pi)
92+
hwp_angle = np.ones(n_sample, dtype=np.float64)
93+
stepsamples = int(hwp_step_time_s * rate)
94+
wholesteps = int((start_sample + first_sample) / stepsamples)
95+
remsamples = (start_sample + first_sample) - wholesteps * stepsamples
96+
curang = np.fmod(wholesteps * hwp_step_rad, 2 * np.pi)
8397
curoff = 0
8498
fill = remsamples
85-
while curoff < n_samp:
86-
if curoff + fill > n_samp:
87-
fill = n_samp - curoff
99+
while curoff < n_sample:
100+
if curoff + fill > n_sample:
101+
fill = n_sample - curoff
88102
hwp_angle[curoff:fill] *= curang
89103
curang += hwp_step
90104
curoff += fill
91105
fill = stepsamples
92-
if hwp_angle is not None:
93-
# Choose the HWP angle between [0, 2*pi)
94-
hwp_angle %= 2 * np.pi
106+
# Choose the HWP angle between [0, 2*pi)
107+
hwp_angle %= 2 * np.pi
108+
109+
# Create a Mueller matrix if we will be writing that...
95110

96-
obs.shared[obs_key].set(hwp_angle, offset=(0,), fromrank=0)
111+
# Store the angle and / or the Mueller matrix
112+
if ob_angle_key is not None:
113+
ob.shared.create(
114+
ob_angle_key, shape=(n_sample,), dtype=np.float64, comm=ob.grid_comm_col
115+
)
116+
ob.shared[ob_angle_key].set(hwp_angle, offset=(0,), fromrank=0)
97117

98118
return

0 commit comments

Comments
 (0)