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

SCHED 692: Add night conditions #494

Merged
merged 3 commits into from
Aug 19, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
5 changes: 3 additions & 2 deletions scheduler/core/calculations/selection.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@

from dataclasses import dataclass
from datetime import timedelta
from typing import final, Callable, FrozenSet, Mapping, Optional
from typing import final, Callable, FrozenSet, Mapping, Optional, Dict

from lucupy.helpers import flatten
from lucupy.minimodel import Group, NightIndices, Program, ProgramID, Site, UniqueGroupID
from lucupy.minimodel import Group, NightIndices, Program, ProgramID, Site, UniqueGroupID, VariantSnapshot

from scheduler.core.components.ranker import Ranker
from scheduler.core.types import StartingTimeslots
Expand Down Expand Up @@ -35,6 +35,7 @@ class Selection:
schedulable_groups: Mapping[UniqueGroupID, GroupData]
night_events: Mapping[Site, NightEvents]
night_indices: NightIndices
night_conditions: Dict[Site, VariantSnapshot]
time_slot_length: timedelta
starting_time_slots: StartingTimeslots
ranker: Ranker
Expand Down
2 changes: 1 addition & 1 deletion scheduler/core/components/changemonitor/change_monitor.py
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ def process_event(self,
# Regardless, we want to change the weather values for CC and IQ.
self.selector.update_site_variant(site, variant_change)

# If the site is blocked, we have no reason to recalculate a plan until all blocking evens
# If the site is blocked, we have no reason to recalculate a plan until all blocking events
# are unblocked.
if plans is None:
if self.is_site_blocked(site):
Expand Down
4 changes: 3 additions & 1 deletion scheduler/core/components/optimizer/optimizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,9 @@ def schedule(self, selection: Selection) -> List[Plans]:
self.night_events = selection.night_events

# Create set of plans for the amount of nights
nights = [Plans(self.night_events, night_idx) for night_idx in self.selection.night_indices]
nights = [Plans(self.night_events,
selection.night_conditions,
night_idx) for night_idx in self.selection.night_indices]
self.algorithm.schedule(nights)
return nights

Expand Down
1 change: 1 addition & 0 deletions scheduler/core/components/selector/selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,7 @@ def select(self,
schedulable_groups=schedulable_groups_map,
night_events={site: self.collector.get_night_events(site) for site in sites},
night_indices=night_indices,
night_conditions=self._variant_snapshot_per_site,
starting_time_slots=starting_time_slots,
time_slot_length=self.collector.time_slot_length.to_datetime(),
ranker=ranker,
Expand Down
3 changes: 2 additions & 1 deletion scheduler/core/eventsqueue/nightchanges.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ def get_final_plan(self, night_idx: NightIndex, site: Site) -> Optional[Plan]:
end=relevant_entries[-1].plan_generated.end,
time_slot_length=relevant_entries[0].plan_generated.time_slot_length,
site=site,
_time_slots_left=relevant_entries[-1].plan_generated.time_left())
_time_slots_left=relevant_entries[-1].plan_generated.time_left(),
conditions=relevant_entries[-1].plan_generated.conditions)
p.visits = [v for v in reversed(all_generated)]
return p

Expand Down
6 changes: 4 additions & 2 deletions scheduler/core/plans/plan.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from typing import final, List, Optional, Tuple

from lucupy.observatory.abstract import ObservatoryProperties
from lucupy.minimodel import Observation, ObservationID, Site
from lucupy.minimodel import Observation, ObservationID, Site, VariantSnapshot
from lucupy.timeutils import time2slots

from .nightstats import NightStats
Expand All @@ -31,12 +31,14 @@ class Plan:
time_slot_length: timedelta
site: Site
_time_slots_left: int
conditions: VariantSnapshot

visits: List[Visit] = field(init=False, default_factory=list)
is_full: bool = field(init=False, default=False)
night_stats: Optional[NightStats] = field(init=False, default=None)
alt_degs: List[List[float]] = field(init=False, default_factory=list)


def nir_slots(self,
science_obs: List[Observation],
n_slots_filled: int,
Expand Down Expand Up @@ -115,7 +117,7 @@ def get_slice(self, start: Optional[int] = None, stop: Optional[int] = None) ->
else:
visits_by_timeslot = {v.start_time_slot: v for v in self.visits}
visits_timeslots = [v.start_time_slot for v in self.visits]
plan = Plan(self.start, self.end, self.time_slot_length, self.site, self._time_slots_left)
plan = Plan(self.start, self.end, self.time_slot_length, self.site, self._time_slots_left, self.conditions)

start = start or 0
stop = stop or visits_timeslots[-1]
Expand Down
6 changes: 4 additions & 2 deletions scheduler/core/plans/plans.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from dataclasses import dataclass, field, InitVar
from typing import final, Dict, Mapping

from lucupy.minimodel import NightIndex, Site
from lucupy.minimodel import NightIndex, Site, VariantSnapshot

from .plan import Plan
from scheduler.core.calculations.nightevents import NightEvents
Expand All @@ -21,6 +21,7 @@ class Plans:
A collection of Plan for all sites for a specific night.
"""
night_events: InitVar[Mapping[Site, NightEvents]]
night_conditions: Dict[Site, VariantSnapshot]
night_idx: NightIndex
plans: Dict[Site, Plan] = field(init=False, default_factory=dict)

Expand All @@ -32,7 +33,8 @@ def __post_init__(self, night_events: Mapping[Site, NightEvents]):
ne.local_times[self.night_idx][-1],
ne.time_slot_length.to_datetime(),
site,
len(ne.times[self.night_idx]))
len(ne.times[self.night_idx]),
self.night_conditions[site])

def __getitem__(self, site: Site) -> Plan:
return self.plans[site]
Expand Down
5 changes: 4 additions & 1 deletion scheduler/engine/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,10 @@ def setup(self, scp: SCP) -> Dict[Site, Dict[NightIndex, Optional[VariantSnapsho
# morn_twi_slot = time2slots(time_slot_length, morn_twi_time - eve_twi_time)
morn_twi_slot = night_events.num_timeslots_per_night[night_idx]

# Get initial conditions for the nights
initial_variants[site][night_idx] = scp.collector.sources.origin.env.get_initial_conditions(site,
night_date)

# Get the weather events for the site for the given night date.
# Get the VariantSnapshots for the times of the night where the variant changes.
variant_changes_dict = scp.collector.sources.origin.env.get_variant_changes_for_night(site, night_date)
Expand All @@ -296,7 +300,6 @@ def setup(self, scp: SCP) -> Dict[Site, Dict[NightIndex, Optional[VariantSnapsho
# The closer to the first time slot, the more accurate, and the ordering on them will overwrite
# the previous values.
if variant_timeslot <= 0:
initial_variants[site][night_idx] = variant_snapshot
continue

if variant_timeslot >= morn_twi_slot:
Expand Down
15 changes: 13 additions & 2 deletions scheduler/graphql_mid/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,16 @@ def from_computed_night_stats(ns: NightStats) -> 'SNightStats':
program_completion=pc)


@strawberry.type
class SConditions:
iq: str
cc: str

@staticmethod
def from_computed_conditions(variant: VariantSnapshot):
return SConditions(iq=variant.iq.name, cc=variant.cc.name)


@strawberry.type
class SVisit:
"""
Expand Down Expand Up @@ -85,6 +95,7 @@ class SPlan:
end_time: datetime
visits: List[SVisit]
night_stats: SNightStats
night_conditions: SConditions

@staticmethod
def from_computed_plan(plan: Plan) -> 'SPlan':
Expand All @@ -94,7 +105,8 @@ def from_computed_plan(plan: Plan) -> 'SPlan':
start_time=plan.start.astimezone(utc),
end_time=plan.end.astimezone(utc),
visits=[SVisit.from_computed_visit(visit, alt) for visit, alt in zip(plan.visits, plan.alt_degs)],
night_stats=SNightStats.from_computed_night_stats(plan.night_stats)
night_stats=SNightStats.from_computed_night_stats(plan.night_stats),
night_conditions=SConditions.from_computed_conditions(plan.conditions)
)


Expand Down Expand Up @@ -169,7 +181,6 @@ def from_computed_timelines(timeline: NightlyTimeline) -> 'SNightTimelines':
timelines.append(sn)
return SNightTimelines(night_timeline=timelines)


@strawberry.type
class NewNightPlans:
night_plans: SNightTimelines
Expand Down
Binary file modified scheduler/pickles/ocsenv.pickle
Binary file not shown.
7 changes: 5 additions & 2 deletions scheduler/scripts/run_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,9 @@ def main(*,
# morn_twi_slot = time2slots(time_slot_length, morn_twi_time - eve_twi_time)
morn_twi_slot = night_events.num_timeslots_per_night[night_idx]

# Get initial conditions for the nights
initial_variants[site][night_idx] = collector.sources.origin.env.get_initial_conditions(site, night_date)

# Get the weather events for the site for the given night date.
# Get the VariantSnapshots for the times of the night where the variant changes.
variant_changes_dict = collector.sources.origin.env.get_variant_changes_for_night(site, night_date)
Expand All @@ -151,7 +154,6 @@ def main(*,
# The closer to the first time slot, the more accurate, and the ordering on them will overwrite
# the previous values.
if variant_timeslot <= 0:
initial_variants[site][night_idx] = variant_snapshot
continue

if variant_timeslot >= morn_twi_slot:
Expand Down Expand Up @@ -384,7 +386,8 @@ def main(*,
# Piece together the plans for the night to get the overall plans.
# This is rather convoluted because of the confusing relationship between Plan, Plans, and NightlyTimeline.
night_events = {site: collector.get_night_events(site) for site in collector.sites}
final_plans = Plans(night_events, NightIndex(night_idx))
night_conditions = {site: initial_variants[site][night_idx] for site in collector.sites}
final_plans = Plans(night_events, night_conditions, NightIndex(night_idx))
for site in collector.sites:
calculated_plan = nightly_timeline.get_final_plan(NightIndex(night_idx), site)
if calculated_plan is not None:
Expand Down
Loading
Loading