Skip to content

Commit

Permalink
MTScheduler: Add BLOCK-T345 json for science program
Browse files Browse the repository at this point in the history
Co-authored-by: Lynne Jones <[email protected]>
  • Loading branch information
gmegh and rhiannonlynne committed Dec 11, 2024
1 parent 99b6bc7 commit af87c1b
Show file tree
Hide file tree
Showing 3 changed files with 320 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
# This file is part of ts_config_ocs.
#
# Developed for the Vera Rubin Observatory Telescope and Site System.
# This product includes software developed by the LSST Project
# (https://www.lsst.org).
# See the COPYRIGHT file at the top-level directory of this distribution
# for details of code ownership.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

import numpy as np
from rubin_scheduler.scheduler import basis_functions, detailers, example, features
from rubin_scheduler.scheduler.schedulers import CoreScheduler
from rubin_scheduler.scheduler.surveys import BlobSurvey
from rubin_scheduler.scheduler.utils import CurrentAreaMap, Footprint
from rubin_scheduler.site_models import Almanac


def get_scheduler():
nside = 32
science_program = "BLOCK-T345"
survey_start = 60653.5
camera_rot_limits = [-80, 80]

map_band_to_filtername = {
"u": "u_02",
"g": "g_01",
"r": "r_03",
"i": "i_06",
"z": "z_03",
"y": "y_04",
}

filtername = map_band_to_filtername["r"]
filtername2 = map_band_to_filtername["g"]

# Masks are fine - no band specific information.
mask_basis_functions = example.standard_masks(
nside=nside,
# Let's avoid the moon by this many degrees
moon_distance=30.0,
# Erik says to make wind speed minor so set limit high
wind_speed_maximum=50.0,
# I think these are the values appropriate for alt limits now?
min_alt=40,
max_alt=70,
min_az=0,
max_az=360,
# Avoid going into avoidance regions 30 minutes into the future
shadow_minutes=30,
)
# Mask basis functions have zero weights.
mask_basis_functions_weights = [0 for mask in mask_basis_functions]

# Set up footprint stuff here instead of in rubin_scheduler.
# Use the Almanac to find the position of the sun at the start of survey.
almanac = Almanac(mjd_start=survey_start)
sun_moon_info = almanac.get_sun_moon_positions(survey_start)
sun_ra_start = sun_moon_info["sun_RA"].copy()
# So this is a dictionary of filternames : int.
filterdict = {}
for i, f in enumerate(map_band_to_filtername.values()):
filterdict[f] = i
footprints = Footprint(
filters=filterdict,
mjd_start=survey_start,
sun_ra_start=sun_ra_start,
nside=nside,
)
# need to remap this to filtername not band
footprint = CurrentAreaMap(nside=nside)
footprint_hp, labels = footprint.return_maps()
new_dtype = np.dtype([(map_band_to_filtername[f], "<f8") for f in "ugrizy"])
footprint_hp_filter = footprint_hp.astype(new_dtype)
for f in footprint_hp_filter.dtype.names:
footprints.set_footprint(f, footprint_hp_filter[f])

# Now set up basis functions
m5_weight = 6.0
footprint_weight = 1.5
slewtime_weight = 3.0
stayfilter_weight = 3.0
repeat_weight = -20
# Add the same basis functions, but M5 and footprint
# basis functions need to be added twice, with half the weight.
rf1 = example.simple_rewards(
footprints=footprints,
filtername=filtername,
nside=nside,
m5_weight=m5_weight / 2.0,
footprint_weight=footprint_weight / 2.0,
slewtime_weight=slewtime_weight,
stayfilter_weight=stayfilter_weight,
repeat_weight=repeat_weight,
)
rf2 = example.simple_rewards(
footprints=footprints,
filtername=filtername2,
nside=nside,
m5_weight=m5_weight / 2.0,
footprint_weight=footprint_weight / 2.0,
slewtime_weight=0,
stayfilter_weight=0,
repeat_weight=0,
)
# Now clean up and combine these - and remove the separate
# BasisFunction for FilterLoadedBasisFunction.
reward_functions = [(i[0], i[1]) for i in rf1 if i[1] > 0] + [
(i[0], i[1]) for i in rf2 if i[1] > 0
]
# Remove the M5Diff basis functions as unusable at present
reward_functions = [
(bf, weight)
for (bf, weight) in reward_functions
if not isinstance(bf, basis_functions.M5DiffBasisFunction)
]

# unpack the basis functions and weights
reward_basis_functions_weights = [val[1] for val in reward_functions]
reward_basis_functions = [val[0] for val in reward_functions]

# Set up blob surveys.
pair_time = 20
if filtername2 is None:
survey_name = "simple pair %i, %s" % (pair_time, filtername)
else:
survey_name = "simple pair %i, %s%s" % (pair_time, filtername, filtername2)

# Set up detailers for each requested observation.
detailer_list = []
# Avoid camera rotator limits.
detailer_list.append(
detailers.CameraRotDetailer(
min_rot=np.min(camera_rot_limits), max_rot=np.max(camera_rot_limits)
)
)
# Reorder visits in a blob so that closest to current altitude is first.
detailer_list.append(detailers.CloseAltDetailer())
# Add a detailer to label visits as either first or second of the pair.
if filtername2 is not None:
detailer_list.append(detailers.TakeAsPairsDetailer(filtername=filtername2))

# Set up the survey.
ignore_obs = ["DD"]

BlobSurvey_params = {
"slew_approx": 7.5,
"filter_change_approx": 140.0,
"read_approx": 2.4,
"flush_time": pair_time * 3,
"smoothing_kernel": None,
"nside": nside,
"seed": 42,
"dither": True,
"twilight_scale": False,
}

pair_survey = BlobSurvey(
reward_basis_functions + mask_basis_functions,
reward_basis_functions_weights + mask_basis_functions_weights,
filtername1=filtername,
filtername2=filtername2,
exptime=150,
ideal_pair_time=pair_time,
survey_name=survey_name,
ignore_obs=ignore_obs,
nexp=1,
detailers=detailer_list,
science_program=science_program,
**BlobSurvey_params,
)

# Tucking this here so we can look at how many observations
# recorded for this survey and what was the last one.
pair_survey.extra_features["ObsRecorded"] = features.NObsCount()
pair_survey.extra_features["LastObs"] = features.LastObservation()

scheduler = CoreScheduler([pair_survey], nside=nside)
return nside, scheduler


if __name__ == "config":
nside, scheduler = get_scheduler()
79 changes: 79 additions & 0 deletions Scheduler/observing_blocks_maintel/AOS/BLOCK-T345.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
{
"name": "AOSSurveyMode",
"program": "BLOCK-T345",
"constraints": [],
"scripts": [
{
"name": "maintel/track_target.py",
"standard": true,
"parameters": {
"target_name": "$name",
"slew_icrs": {
"ra": "$ra",
"dec": "$dec"
},
"rot_value": "$rot",
"rot_type": "PhysicalSky",
"az_wrap_strategy": "NOUNWRAP"
}
},
{
"name": "maintel/close_loop_comcam.py",
"standard": true,
"parameters": {
"exposure_time": 15,
"max_iter": 1,
"gain_sequence": [
0.75
],
"mode": "FAM",
"program": "$program",
"note": "closed_loop_aos_survey_mode",
"reason": "aos_survey_mode",
"filter": "$band_filter",
"used_dofs": [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
17,
18,
19,
20,
21,
22,
23,
28,
29,
30,
31,
32,
33,
34,
37,
38,
39,
40,
41,
42,
45,
46
],
"apply_corrections": true,
"use_ocps": true
}
}
],
"configuration_schema": ""
}
47 changes: 47 additions & 0 deletions Scheduler/v7/maintel_fbs_sit_block_t345.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
maintel:
driver_type: feature_scheduler
mode: ADVANCE
startup_type: COLD
startup_database: /home/saluser/rubin_sim_data/fbs_observation_database_maintel.sql
instrument_name: CCCamera
models:
observatory_model:
camera:
filter_max_changes_burst_num: 1000000
filter_max_changes_avg_num: 30000
optics_loop_corr:
tel_optics_cl_alt_limit:
- 0
- 60
- 90
park:
filter_position: r_03
driver_configuration:
parameters:
night_boundary: -10.0
stop_tracking_observing_script_name: maintel/stop_tracking.py
feature_scheduler_driver_configuration:
observation_database_name: /home/saluser/rubin_sim_data/fbs_observation_database_maintel.sql
scheduler_config: /net/obs-env/auto_base_packages/ts_config_ocs/Scheduler/feature_scheduler/maintel/fbs_config_sit_survey_block_t345.py
telemetry:
streams:
- name: seeing
efd_table: lsst.sal.DIMM.logevent_dimmMeasurement
efd_columns:
- fwhm
efd_delta_time: 300.0
fill_value: 1.0
- name: wind_speed
efd_table: lsst.sal.ESS.airFlow
efd_columns:
- speed
efd_delta_time: 300.0
fill_value: 0.0
csc_index: 301
- name: wind_direction
efd_table: lsst.sal.ESS.airFlow
efd_columns:
- direction
efd_delta_time: 300.0
fill_value: 0.0
csc_index: 301

0 comments on commit af87c1b

Please sign in to comment.