Skip to content
Snippets Groups Projects
Commit 980cf5e5 authored by Jorrit Schaap's avatar Jorrit Schaap
Browse files

TMSS-2823: the bug fix, and in general better handling of transit_offset computations

parent cc739d9f
No related branches found
No related tags found
1 merge request!1187TMSS-2823
......@@ -966,7 +966,9 @@ def evaluate_sky_transit_constraint(scheduling_unit: models.SchedulingUnitBluepr
transit_from_limit_with_margin = transit_from_limit - 60*gridder.grid_minutes
transit_to_limit_with_margin = transit_to_limit + 60*gridder.grid_minutes
logger.debug("evaluate_sky_transit_constraint: SUB id=%s proposed_start_time='%s'", scheduling_unit.id, proposed_start_time)
# keep track of all optimal_start_times for all target-observations and all targets
# if this constraint is met for all, then compute an overall average optimal starttime as final result
optimal_start_times = []
# transits are only computed for target observations
target_obs_tasks = [t for t in scheduling_unit.observation_tasks if t.is_target_observation]
......@@ -997,39 +999,60 @@ def evaluate_sky_transit_constraint(scheduling_unit: models.SchedulingUnitBluepr
for station, transit_timestamps in transits.items():
assert len(transit_timestamps) == 1 # only one center time
transit_timestamp = round_to_second_precision(transit_timestamps[0])
if logger.level==logging.DEBUG:
if logger.isEnabledFor(logging.DEBUG):
transit_timestamp_lst = local_sidereal_time_for_utc_and_station(transit_timestamp, station)
logger.debug("SUB id=%s transit='%sUTC' '%sLST' for %s %s task_proposed_center_time='%s'", scheduling_unit.id, transit_timestamp, transit_timestamp_lst, station, pointing.str_astro(), task_proposed_center_time)
logger.debug("SUB id=%s transit='%sUTC' '%sLST' for %s %s near task_proposed_center_time='%s'", scheduling_unit.id, transit_timestamp, transit_timestamp_lst, station, pointing.str_astro(), task_proposed_center_time)
optimal_task_center_time = transit_timestamp - target_obs_task.relative_start_time
# the optimal start_time is half a duration earlier than the center
optimal_task_start_time = optimal_task_center_time - (target_obs_task.specified_duration / 2)
# if transit_from_limit>0 or transit_to_limit<0,
# then the optimal_task_start_time should be 'pushed' asymetrically to that side, in order to keep the center within the limits.
if transit_from_limit > 0:
optimal_task_start_time -= timedelta(seconds=transit_from_limit)
if transit_to_limit < 0:
optimal_task_start_time += timedelta(seconds=transit_to_limit)
# keep track of all optimal_start_time to compute one final overall average optimal_start_time at the end, together with one score.
optimal_start_times.append(optimal_task_start_time)
# now check if the constraint is met
# include the margins for gridding effects when checking offset-within-window,
offset = int((task_proposed_center_time-optimal_task_center_time).total_seconds())
if offset < transit_from_limit_with_margin or offset > transit_to_limit_with_margin:
# constraint not met for this task/target.
result.message = "offset of %s[s] at task_center='%s' from transit at '%s' at %s for %s is not within [%s, %s]" % (offset, task_proposed_center_time, transit_timestamp, station, pointing, transit_from_limit, transit_to_limit)
logger.debug(result)
# transit minus half duration is by definition the optimal start_time
# also take the task relative start time against the su.starttime into account
result.optimal_start_time = transit_timestamp - (target_obs_task.specified_duration / 2) - target_obs_task.relative_start_time
# compute the overall averaged result
if len(optimal_start_times) == 1:
result.optimal_start_time = optimal_start_times[0]
else:
result.optimal_start_time = optimal_start_times[0] + timedelta(seconds=sum([(t-optimal_start_times[0]).total_seconds() for t in optimal_start_times[1:]])/len(optimal_start_times))
# earliest_possible_start_time is the transit plus the lower limit (which is usually negative)
result.earliest_possible_start_time = result.optimal_start_time + timedelta(seconds=transit_from_limit)
result.optimal_start_time = round_to_second_precision(result.optimal_start_time)
# now check if the constraint is met, and compute/set score
# include the margins for gridding effects when checking offset-within-window,
# but not when computing score
offset = int((task_proposed_center_time-transit_timestamp).total_seconds())
if offset > transit_from_limit_with_margin and offset < transit_to_limit_with_margin:
# constraint is met. compute score.
# 1.0 when proposed_center_time==transit_timestamp
# 0.0 at either translit offset limit
if offset <= 0:
score = abs(transit_from_limit_with_margin - offset)/abs(transit_from_limit_with_margin)
else:
score = abs(transit_to_limit_with_margin - offset)/abs(transit_to_limit_with_margin)
# earliest_possible_start_time is the transit plus the lower limit (which is usually negative)
result.earliest_possible_start_time = result.optimal_start_time + timedelta(seconds=transit_from_limit)
if transit_to_limit < 0: # nudge asymmetric
result.earliest_possible_start_time -= timedelta(seconds=transit_to_limit)
result.score = min(1.0, max(0.0, score))
else:
result.score = 0
result.message = "offset of %s[s] at task_center='%s' from transit at '%s' at %s for %s is not within [%s, %s]" % (offset, task_proposed_center_time, transit_timestamp, station, pointing, transit_from_limit, transit_to_limit)
# log and early exit, cause the constraint is not met.
logger.debug(result)
return result
if result.message:
# the message was set for one or more failing task/target/station transit_offset constraints
result.score = 0
else:
# all task/target/station transit_offset constraints were met.
# compute overall score
# 1.0 when proposed_center_time==transit_timestamp
# 0.0 at either translit offset limit
# overall average offset
offset = int((proposed_start_time - result.optimal_start_time).total_seconds())
if offset <= 0:
score = abs(transit_from_limit - offset) / abs(transit_from_limit)
else:
score = abs(transit_to_limit - offset) / abs(transit_to_limit)
result.score = min(1.0, max(0.0, score))
logger.debug(result)
return result
......@@ -1405,7 +1428,7 @@ def get_earliest_possible_start_time_for_sky_transit_offset(scheduling_unit: mod
if result.is_constraint_met:
if result.earliest_possible_start_time > lower_bound:
return result.earliest_possible_start_time
return max(possible_start_time, result.earliest_possible_start_time)
return lower_bound
# constraint is not met, or before lower_bound... or equal to previous evaluation result
......@@ -1415,7 +1438,7 @@ def get_earliest_possible_start_time_for_sky_transit_offset(scheduling_unit: mod
allow_quick_jump = False # prevent more quick jumps which may lead to an endless back-and-forth loop
else:
# advance with a step, and evaluate again
possible_start_time += max(timedelta(hours=1), gridder.as_timedelta())
possible_start_time += max(timedelta(minutes=5), gridder.as_timedelta())
return None
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment