diff --git a/astroplan/scheduling.py b/astroplan/scheduling.py index 98ca45b7..32f49273 100644 --- a/astroplan/scheduling.py +++ b/astroplan/scheduling.py @@ -748,7 +748,7 @@ def _make_schedule(self, blocks): score_array = scorer.create_score_array(time_resolution) # Sort the list of blocks by priority - sorted_indices = np.argsort(_block_priorities) + sorted_indices = np.argsort(_block_priorities, kind='mergesort') unscheduled_blocks = [] # Compute the optimal observation time in priority order @@ -786,7 +786,7 @@ def _make_schedule(self, blocks): # does not prevent us from fitting it in. # loop over valid times and see if it fits # TODO: speed up by searching multiples of time resolution? - for idx in np.argsort(sum_scores)[::-1]: + for idx in np.argsort(-sum_scores, kind='mergesort'): if sum_scores[idx] <= 0.0: # we've run through all optimal blocks _is_scheduled = False diff --git a/astroplan/tests/test_scheduling.py b/astroplan/tests/test_scheduling.py index 76a35ba7..49d88627 100644 --- a/astroplan/tests/test_scheduling.py +++ b/astroplan/tests/test_scheduling.py @@ -158,6 +158,30 @@ def test_priority_scheduler(): scheduler(blocks, schedule) scheduler(blocks, schedule) + # Check if the order of equal values is respected: + # 1. For equal priorities in blocks + # 2. For equal scores (boolean_constraint) + constraints = [AirmassConstraint(3, boolean_constraint=True)] + scheduler.constraints = constraints + # Any resolution coarser than this may result in gaps between the blocks + scheduler.time_resolution = 20*u.second + # This only happens with more than 16 items or so + targets_18 = [polaris, polaris, polaris, polaris, polaris, polaris, + polaris, polaris, polaris, polaris, polaris, polaris, + polaris, polaris, polaris, polaris, polaris, polaris] + blocks = [ObservingBlock(t, 4*u.minute, 5, name=i) for i, t in enumerate(targets_18)] + + schedule = Schedule(start_time, end_time) + scheduler(blocks, schedule) + + for i, t in enumerate(targets_18): + # Order of blocks + block = schedule.observing_blocks[i] + assert block.name == i + if i < len(targets_18) - 1: + # Same score for all timeslots, should be filled from the start without gaps + assert block.end_time.isclose(schedule.observing_blocks[i+1].start_time) + def test_sequential_scheduler(): constraints = [AirmassConstraint(2.5, boolean_constraint=False)]