def optimize(orbits, required, locations, tokens, camera_name="MEGACAM_40"): """ @param orbits: a dictionary of orbits to optimize the point of. @param required: list of objects that MUST be observed. @param locations: locations of the objects at the start of observing period. @param tokens: List of tokens (object names) that we will try and cover. @return: """ # Get the tokens that will be paged through in random order. token_order = np.random.permutation(required) optimal_pointings = {} covered = [ ] # the objects that have already been covered by a planned pointing. search_order = [ 0, ] # search_order = [22 + 4] # search_order.extend(range(len(Camera.names))) # For each required target find the pointing that will include the largest number of other required targets # and then tweak that specific pointing to include the maximum number of secondary targets. for token in token_order: if token in covered: continue logging.debug( "Optimizing pointing for required target: {}".format(token)) if token not in orbits: logging.error("No orbit available for: {}".format(token)) continue obj = orbits[token] separations = obj.coordinate.separation(locations) possible_tokens = tokens[separations < 1.3 * units.degree] this_required = [] for this_token in required: if this_token in possible_tokens: this_required.append(this_token) # This object is not inside the existing coverage. max_sources_in_pointing = 0 best_coverage = [] p = SkyCoord(obj.coordinate.ra, obj.coordinate.dec) pointing = Camera(p, camera=camera_name) if len(possible_tokens) == 1: optimal_pointings[token] = pointing, possible_tokens logging.info(" {} is all alone!".format(token)) continue logging.debug("examining possible optimizations") if len(this_required) == 1: best_coverage = [token] else: logging.debug("Maximizing inclusion of required targets") for idx in search_order: pointing.offset(index=idx) this_coverage = [] for this_token in this_required: if this_token in covered: continue this_obj = orbits[this_token] if pointing.polygon.isInside( this_obj.coordinate.ra.degree, this_obj.coordinate.dec.degree): this_coverage.append(this_token) if len(this_coverage) > max_sources_in_pointing: max_sources_in_pointing = len(this_coverage) best_coverage = this_coverage # best_pointing now contains the pointing that covers the largest number of required sources. # best_coverage is the list of sources (tokens) that this pointing covered. # now move around the best_pointing, keeping all the objects listed in best_coverage but maximizing the # number of other sources that get coverage (optimal_coverage) logging.info("{} pointing these {} required targets: {}".format( token, len(best_coverage), best_coverage)) max_sources_in_pointing = 0 optimal_coverage = [] optimal_pointing = None for idx in search_order: pointing.offset(index=idx) exclude = False # exclude this offset because it doesn't overlap one or more of the required sources. for this_token in best_coverage: this_obj = orbits[this_token] if not pointing.polygon.isInside( this_obj.coordinate.ra.degree, this_obj.coordinate.dec.degree): exclude = True break if exclude: continue # OK, this offset has all the required sources possible, how many extra sources do we get? this_coverage = [] for this_token in possible_tokens: if this_token in covered: continue this_obj = orbits[this_token] if pointing.polygon.isInside(this_obj.coordinate.ra.degree, this_obj.coordinate.dec.degree): this_coverage.append(this_token) if len(this_coverage) > max_sources_in_pointing: max_sources_in_pointing = len(this_coverage) optimal_coverage = this_coverage optimal_pointing = idx # remove all sources covered by optimal_pointing from further consideration. sys.stdout.write("{} pointing covers: ".format(token)) unique_coverage_list = [] for this_token in optimal_coverage: if this_token not in covered: unique_coverage_list.append(this_token) sys.stdout.write(" {} ".format(this_token)) covered.append(this_token) sys.stdout.write("\n") pointing.offset(index=optimal_pointing) optimal_pointings[token] = pointing, unique_coverage_list n = 0 new_required = [] for this_token in token_order: if this_token not in covered: new_required.append(this_token) n += 1 logging.info( "Remaining required targets: {}, targets covered: {}".format( n, len(covered))) required = new_required return optimal_pointings
def optimize(orbits, required, locations, tokens, camera_name="MEGACAM_40"): """ @param orbits: a dictionary of orbits to optimize the point of. @param required: list of objects that MUST be observed. @param locations: locations of the objects at the start of observing period. @param tokens: List of tokens (object names) that we will try and cover. @return: """ # Get the tokens that will be paged through in random order. token_order = np.random.permutation(required) optimal_pointings = {} covered = [] # the objects that have already been covered by a planned pointing. search_order = [0, ] # search_order = [22 + 4] # search_order.extend(range(len(Camera.names))) # For each required target find the pointing that will include the largest number of other required targets # and then tweak that specific pointing to include the maximum number of secondary targets. for token in token_order: if token in covered: continue logging.debug("Optimizing pointing for required target: {}".format(token)) if token not in orbits: logging.error("No orbit available for: {}".format(token)) continue obj = orbits[token] separations = obj.coordinate.separation(locations) possible_tokens = tokens[separations < 1.3 * units.degree] this_required = [] for this_token in required: if this_token in possible_tokens: this_required.append(this_token) # This object is not inside the existing coverage. max_sources_in_pointing = 0 best_coverage = [] p = SkyCoord(obj.coordinate.ra, obj.coordinate.dec) pointing = Camera(p, camera=camera_name) if len(possible_tokens) == 1: optimal_pointings[token] = pointing, possible_tokens logging.info(" {} is all alone!".format(token)) continue logging.debug("examining possible optimizations") if len(this_required) == 1: best_coverage = [token] else: logging.debug("Maximizing inclusion of required targets") for idx in search_order: pointing.offset(index=idx) this_coverage = [] for this_token in this_required: if this_token in covered: continue this_obj = orbits[this_token] if pointing.polygon.isInside(this_obj.coordinate.ra.degree, this_obj.coordinate.dec.degree): this_coverage.append(this_token) if len(this_coverage) > max_sources_in_pointing: max_sources_in_pointing = len(this_coverage) best_coverage = this_coverage # best_pointing now contains the pointing that covers the largest number of required sources. # best_coverage is the list of sources (tokens) that this pointing covered. # now move around the best_pointing, keeping all the objects listed in best_coverage but maximizing the # number of other sources that get coverage (optimal_coverage) logging.info("{} pointing these {} required targets: {}".format(token, len(best_coverage), best_coverage)) max_sources_in_pointing = 0 optimal_coverage = [] optimal_pointing = None for idx in search_order: pointing.offset(index=idx) exclude = False # exclude this offset because it doesn't overlap one or more of the required sources. for this_token in best_coverage: this_obj = orbits[this_token] if not pointing.polygon.isInside(this_obj.coordinate.ra.degree, this_obj.coordinate.dec.degree): exclude = True break if exclude: continue # OK, this offset has all the required sources possible, how many extra sources do we get? this_coverage = [] for this_token in possible_tokens: if this_token in covered: continue this_obj = orbits[this_token] if pointing.polygon.isInside(this_obj.coordinate.ra.degree, this_obj.coordinate.dec.degree): this_coverage.append(this_token) if len(this_coverage) > max_sources_in_pointing: max_sources_in_pointing = len(this_coverage) optimal_coverage = this_coverage optimal_pointing = idx # remove all sources covered by optimal_pointing from further consideration. sys.stdout.write("{} pointing covers: ".format(token)) unique_coverage_list = [] for this_token in optimal_coverage: if this_token not in covered: unique_coverage_list.append(this_token) sys.stdout.write(" {} ".format(this_token)) covered.append(this_token) sys.stdout.write("\n") pointing.offset(index=optimal_pointing) optimal_pointings[token] = pointing, unique_coverage_list n = 0 new_required = [] for this_token in token_order: if this_token not in covered: new_required.append(this_token) n += 1 logging.info("Remaining required targets: {}, targets covered: {}".format(n, len(covered))) required = new_required return optimal_pointings