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

Update wrap up move command and change all moves to single command #140

Merged
merged 4 commits into from
Dec 13, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
28 changes: 12 additions & 16 deletions src/schedlib/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def clear_history(self):
def save(self, fname):
out = self.clear_history()
np.save( fname, out.to_dict() )

@classmethod
def load(cls, fname):
return cls.from_dict( np.load(fname, allow_pickle=True).item() )
Expand Down Expand Up @@ -195,7 +195,7 @@ class Operation(ABC):
An operation is a callable object that produces a set of commands to be executed by the observatory.

This block takes an observatory state (dict) as input and returns a tuple containing a new state object
as the effect of the command, and a list of commands for the telescope. Each command in the list is a
as the effect of the command, and a list of commands for the telescope. Each command in the list is a
string-like object.

Parameters
Expand Down Expand Up @@ -386,21 +386,17 @@ def move_to(state, az, el, min_el=48, force=False):
duration = 0
cmd = []

if el == state.el_now:
cmd += [f"run.acu.move_to(az={round(az, 3)}, el={(round(el, 3))})"]
else:
if state.hwp_spinning and el < min_el:
state = state.replace(hwp_spinning=False)
duration += HWP_SPIN_DOWN
cmd += [
"run.hwp.stop(active=True)",
"sup.disable_driver_board()",
]

if state.hwp_spinning and el < min_el:
state = state.replace(hwp_spinning=False)
duration += HWP_SPIN_DOWN
cmd += [
f"run.acu.move_to(az={round(az, 3)}, el={round(state.el_now, 3)})",
f"run.acu.move_to(az={round(az, 3)}, el={round(el, 3)})",
"run.hwp.stop(active=True)",
"sup.disable_driver_board()",
]

cmd += [
f"run.acu.move_to(az={round(az, 3)}, el={round(el, 3)})",
]
state = state.replace(az_now=az, el_now=el)

return state, duration, cmd
Expand All @@ -410,4 +406,4 @@ def set_scan_params(state, az_speed, az_accel):
if az_speed != state.az_speed_now or az_accel != state.az_accel_now:
state = state.replace(az_speed_now=az_speed, az_accel_now=az_accel)
return state, [ f"run.acu.set_scan_params({az_speed}, {az_accel})"]
return state, []
return state, []
6 changes: 2 additions & 4 deletions src/schedlib/policies/sat.py
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ def hwp_spin_up(state, disable_hwp=False, forward=True):
f"run.hwp.set_freq(freq={freq})",
]


@cmd.operation(name='sat.hwp_spin_down', return_duration=True)
def hwp_spin_down(state, disable_hwp=False):
if disable_hwp:
Expand Down Expand Up @@ -365,11 +366,8 @@ def bias_step(state, block, bias_step_cadence=None):
return state, 0, []

@cmd.operation(name='sat.wrap_up', duration=0)
def wrap_up(state, az_stow, el_stow):
state = state.replace(az_now=az_stow, el_now=el_stow)
def wrap_up(state):
return state, [
"# go home",
f"run.acu.move_to(az={az_stow}, el={el_stow})",
"time.sleep(1)"
]

Expand Down
20 changes: 13 additions & 7 deletions src/schedlib/policies/satp1.py
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ def make_operations(
if home_at_end:
post_session_ops = [
{ 'name': 'sat.hwp_spin_down' , 'sched_mode': SchedMode.PostSession, 'disable_hwp': disable_hwp, },
{ 'name': 'sat.wrap_up' , 'sched_mode': SchedMode.PostSession, 'az_stow': 180, 'el_stow': 48},
{ 'name': 'sat.wrap_up' , 'sched_mode': SchedMode.PostSession},
]
else:
post_session_ops = []
Expand Down Expand Up @@ -235,6 +235,11 @@ def make_config(
'min_el': 48,
}

stow_position = {
'az_stow': 180,
'el_stow': 48,
}

config = {
'blocks': blocks,
'geometries': geometries,
Expand All @@ -248,15 +253,16 @@ def make_config(
'cal_targets': cal_targets,
'scan_tag': None,
'boresight_override': boresight_override,
'az_speed' : az_speed,
'az_accel' : az_accel,
'iv_cadence' : iv_cadence,
'bias_step_cadence' : bias_step_cadence,
'min_hwp_el' : min_hwp_el,
'max_cmb_scan_duration' : max_cmb_scan_duration,
'az_speed': az_speed,
'az_accel': az_accel,
'iv_cadence': iv_cadence,
'bias_step_cadence': bias_step_cadence,
'min_hwp_el': min_hwp_el,
'max_cmb_scan_duration': max_cmb_scan_duration,
'stages': {
'build_op': {
'plan_moves': {
'stow_position': stow_position,
'sun_policy': sun_policy,
'az_step': 0.5,
'az_limits': [-45, 405],
Expand Down
10 changes: 8 additions & 2 deletions src/schedlib/policies/satp2.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ def make_operations(
if home_at_end:
post_session_ops = [
{ 'name': 'sat.hwp_spin_down' , 'sched_mode': SchedMode.PostSession, 'disable_hwp': disable_hwp, },
{ 'name': 'sat.wrap_up' , 'sched_mode': SchedMode.PostSession, 'az_stow': 180, 'el_stow': 40},
{ 'name': 'sat.wrap_up' , 'sched_mode': SchedMode.PostSession},
]
else:
post_session_ops = []
Expand Down Expand Up @@ -236,6 +236,11 @@ def make_config(
'min_el': 40,
}

stow_position = {
'az_stow': 180,
'el_stow': 40,
}

config = {
'blocks': blocks,
'geometries': geometries,
Expand All @@ -258,6 +263,7 @@ def make_config(
'stages': {
'build_op': {
'plan_moves': {
'stow_position': stow_position,
'sun_policy': sun_policy,
'az_step': 0.5,
'az_limits': [-45, 405],
Expand Down Expand Up @@ -287,7 +293,7 @@ def from_defaults(cls, master_file, az_speed=0.8, az_accel=1.5,
state_file=None, **op_cfg
):
x = cls(**make_config(
master_file, az_speed, az_accel,
master_file, az_speed, az_accel,
iv_cadence, bias_step_cadence, min_hwp_el,
max_cmb_scan_duration, cal_targets,
boresight_override, **op_cfg
Expand Down
20 changes: 13 additions & 7 deletions src/schedlib/policies/satp3.py
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ def make_operations(
if home_at_end:
post_session_ops = [
{ 'name': 'sat.hwp_spin_down' , 'sched_mode': SchedMode.PostSession, 'disable_hwp': disable_hwp, },
{ 'name': 'sat.wrap_up' , 'sched_mode': SchedMode.PostSession, 'az_stow': 180, 'el_stow': 40},
{ 'name': 'sat.wrap_up' , 'sched_mode': SchedMode.PostSession},
]
else:
post_session_ops = []
Expand Down Expand Up @@ -256,6 +256,11 @@ def make_config(
'min_el': 40,
}

stow_position = {
'az_stow': 180,
'el_stow': 40,
}

config = {
'blocks': blocks,
'geometries': geometries,
Expand All @@ -268,15 +273,16 @@ def make_config(
'operations': operations,
'cal_targets': cal_targets,
'scan_tag': None,
'az_speed' : az_speed,
'az_accel' : az_accel,
'iv_cadence' : iv_cadence,
'bias_step_cadence' : bias_step_cadence,
'min_hwp_el' : min_hwp_el,
'max_cmb_scan_duration' : max_cmb_scan_duration,
'az_speed': az_speed,
'az_accel': az_accel,
'iv_cadence': iv_cadence,
'bias_step_cadence': bias_step_cadence,
'min_hwp_el': min_hwp_el,
'max_cmb_scan_duration': max_cmb_scan_duration,
'stages': {
'build_op': {
'plan_moves': {
'stow_position': stow_position,
'sun_policy': sun_policy,
'az_step': 0.5,
'az_limits': [-45, 405],
Expand Down
38 changes: 20 additions & 18 deletions src/schedlib/policies/stages/build_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@ def __repr__(self):
return f"{self.name[:15]:<15} ({self.subtype[:8]:<8}) az = {az}: {self.t0.strftime('%y-%m-%d %H:%M:%S')} -> {self.t1.strftime('%y-%m-%d %H:%M:%S')}"

def replace(self, **kwargs):
"""link `replace` in the wrapper block with the block it contains.
Note that when IR is produced, we assume no trimming needs to happen,
so we use `dc_replace` instead of `super().replace` which accounts for
trimming effect on drift scans. It is not necessary here as we are
"""link `replace` in the wrapper block with the block it contains.
Note that when IR is produced, we assume no trimming needs to happen,
so we use `dc_replace` instead of `super().replace` which accounts for
trimming effect on drift scans. It is not necessary here as we are
merely solving for different unwraps for drift scan.

"""
Expand Down Expand Up @@ -387,16 +387,17 @@ def lower(self, seq, t0, t1, state, operations):

ops = [op for op in operations if op['sched_mode'] == SchedMode.PostSession]
state, post_dur, _ = self._apply_ops(state, ops)
ir += [
ir += [
IR(name='post_session', subtype=IRMode.PostSession,
t0=state.curr_time-dt.timedelta(seconds=post_dur),
t0=state.curr_time-dt.timedelta(seconds=post_dur),
t1=state.curr_time, operations=ops,
az=state.az_now, alt=state.el_now)
az=self.plan_moves['stow_position']['az_stow'],
alt=self.plan_moves['stow_position']['el_stow'])
]
logger.debug(f"post-session state: {state}")

return ir

def round_trip(self, seq, t0, t1, state, operations):
ir = self.lower(seq, t0, t1, state, operations)
seq = self.lift(ir)
Expand Down Expand Up @@ -442,7 +443,7 @@ def resolve_block(state, ir):
for ir in irs:
state, op_blocks = resolve_block(state, ir)
ir_lowered += op_blocks
return ir_lowered, state
return ir_lowered, state

def _apply_ops(self, state, op_cfgs, block=None, az=None, alt=None):
"""
Expand Down Expand Up @@ -682,7 +683,7 @@ def _plan_block_operations(self, state, block, constraint, pre_ops, in_ops, post
az=block.az,
alt=block.alt,
block=block,
operations=post_ops)
operations=post_ops)
]

return state, op_seq
Expand All @@ -691,6 +692,7 @@ def _plan_block_operations(self, state, block, constraint, pre_ops, in_ops, post
class PlanMoves:
"""solve moves to make seq possible"""
sun_policy: Dict[str, Any]
stow_position: Dict[str, Any]
az_step: float = 1
az_limits: Tuple[float, float] = (-90, 450)

Expand Down Expand Up @@ -804,13 +806,13 @@ def check_parking(t0_parking, t1_parking, alt_parking):
gaps = get_safe_gaps(seq[i-1], seq[i])
seq_.extend(gaps)
seq_.append(seq[i])

# Replace gaps with Wait, Move, Wait.
seq_, seq = [], seq_
last_az, last_alt = None, None
# Combine, but skipping first and last blocks, which are init/shutdown.
for i, b in enumerate(seq):
if b.name in ['pre_session', 'post_session']:
if b.name in ['pre_session']:
# Pre/post-ambles, leave it alone.
seq_ += [b]
elif b.name == 'gap':
Expand All @@ -830,7 +832,7 @@ def check_parking(t0_parking, t1_parking, alt_parking):
seq_ += [MoveTo(az=b.az, alt=b.alt)]
last_az, last_alt = b.az, b.alt
else:
if (b.block != seq[i-1].block) & (i>0):
if i > 0:
seq_ += [MoveTo(az=b.az, alt=b.alt)]
seq_ += [b]

Expand Down Expand Up @@ -870,18 +872,18 @@ def without(i):
# gap followed by wait until will be replaced by the wait until
return without(bi)
return ir


def find_unwrap(az, az_limits=[-90, 450]) -> List[float]:
az = (az - az_limits[0]) % 360 + az_limits[0] # min az becomes az_limits[0]
az_unwraps = list(np.arange(az, az_limits[1], 360))
return az_unwraps

def az_ranges_intersect(
r1: List[Tuple[float, float]],
r2: List[Tuple[float, float]],
*,
az_limits: Tuple[float, float],
r1: List[Tuple[float, float]],
r2: List[Tuple[float, float]],
*,
az_limits: Tuple[float, float],
az_step: float
) -> List[Tuple[float, float]]:
az_full = np.arange(az_limits[0], az_limits[1]+az_step, az_step)
Expand Down