def select_stars(magnitude, constellation=None, ra_range=None, dec_range=None): """ Select a set of stars brighter than the given magnitude, based on coordinate range and/or constellation membership. Args: magnitude (float): The maximum magnitude to include constellation (string): The constellation name; if given, only stars from that constellation are returned ra_range (tuple): The range (min_ra, max_ra) of right ascension to include, in degrees dec_range (tuple): The range (min_dec, max_dec) of declination to include, in degrees Returns: list: All Star objects in the database matching the criteria """ # Build the query q = """SELECT * FROM skymap_stars WHERE magnitude<={0}""".format(magnitude) if constellation: q += """ AND constellation='{0}'""".format(constellation) if ra_range: min_ra, max_ra = ra_range min_ra = ensure_angle_range(min_ra) max_ra = ensure_angle_range(max_ra) if min_ra < max_ra: q += """ AND right_ascension>={0} AND right_ascension<={1}""".format( min_ra, max_ra ) elif max_ra < min_ra: q += """ AND (right_ascension>={0} OR right_ascension<={1})""".format( min_ra, max_ra ) else: # min_ra is equal to max_ra: full circle: no ra limits pass if dec_range: min_dec, max_dec = dec_range if ( min_dec < -90 or min_dec > 90 or max_dec < -90 or max_dec > 90 or max_dec <= min_dec ): raise ValueError("Illegal DEC range!") q += """ AND declination>={0} AND declination<={1}""".format(min_dec, max_dec) # Order stars from brightest to weakest so displaying them is easier q += """ ORDER BY magnitude ASC""" # Execute the query db = SkyMapDatabase() rows = db.query(q) result = [Star(row) for row in rows] db.close() return result
def inside_coordinate_range(self, sp): ra = ensure_angle_range( sp.ra.degree, 0.5 * (self.min_longitude + self.max_longitude)) dec = ensure_angle_range(sp.dec.degree, 0.5 * (self.min_latitude + self.max_latitude)) longitude_inside = self.min_longitude <= ra <= self.max_longitude latitude_inside = self.min_latitude <= dec <= self.max_latitude return longitude_inside and latitude_inside
def tickangle2(self): if hasattr(self._curve, "angle"): return ensure_angle_range(self._curve.angle) try: p = self._curve.p2 - self._curve.center except AttributeError: return None if self.config.center_latitude < 0: return ensure_angle_range(p.angle + 90) return ensure_angle_range(p.angle - 90)
def backproject(self, point): rho = self.origin.distance(point) theta = ensure_angle_range(math.degrees(math.atan2(point.y, point.x))) if self.reverse_polar_direction: theta *= -1 longitude = ensure_angle_range(theta + self.center_longitude) latitude = (-rho * self.reference_scale / self.horizontal_stretch + self.center_latitude) return SkyCoordDeg(longitude, latitude)
def inverse_project(self, point): rho = self.origin.distance(point) theta = ensure_angle_range(math.degrees(math.atan2(point.y, point.x))) if self.reverse_polar_direction: longitude = ensure_angle_range(-theta + self.reference_longitude) else: longitude = ensure_angle_range(theta + self.reference_longitude) return SphericalPoint( longitude, -rho * self.reference_scale + self.origin_latitude)
def ecliptic_to_equatorial(p, epoch=REFERENCE_EPOCH): """Returns the equatorial coordinates for the given point in ecliptic coordinates. Equations taken from: Practical Astronomy with your Calculator or Spreadsheet Peter Duffett-Smith and Jonathan Zwart Cambridge University Press, 2011 Paragraph 27 (page 51) Only used to draw the ecliptic. """ eps = math.radians(obliquity_of_the_ecliptic(REFERENCE_EPOCH)) ceps = math.cos(eps) seps = math.sin(eps) l = math.radians(p.ra.degree) b = math.radians(p.dec.degree) longitude = math.degrees( math.atan2(math.sin(l) * ceps - math.tan(b) * seps, math.cos(l))) latitude = math.degrees( math.asin(math.sin(b) * ceps + math.cos(b) * seps * math.sin(l))) # Precess to the current epoch pc = PrecessionCalculator(REFERENCE_EPOCH, epoch) longitude, latitude = pc.precess(longitude, latitude) return SkyCoordDeg(ensure_angle_range(longitude), latitude)
def get_constellation_boundaries_for_area(min_longitude, max_longitude, min_latitude, max_latitude, epoch=REFERENCE_EPOCH): # Convert longitude to 0-360 values # TODO: sometimes boundaries cross the map but have no vertices within the map area + margin and are not plotted min_longitude = ensure_angle_range(min_longitude) max_longitude = ensure_angle_range(max_longitude) if max_longitude == min_longitude: max_longitude += 360 db = SkyMapDatabase() q = "SELECT * FROM skymap_constellation_boundaries WHERE" if min_longitude < max_longitude: q += " ((ra1>={0} AND ra1<={1}".format(min_longitude, max_longitude) else: q += " (((ra1>={0} OR ra1<={1})".format(min_longitude, max_longitude) q += " AND dec1>={0} AND dec1<={1}) OR".format(min_latitude, max_latitude) if min_longitude < max_longitude: q += " (ra2>={0} AND ra2<={1}".format(min_longitude, max_longitude) else: q += " ((ra2>={0} OR ra2<={1})".format(min_longitude, max_longitude) q += " AND dec2>={0} AND dec2<={1}))".format(min_latitude, max_latitude) res = db.query(q) result = [] pc = PrecessionCalculator(CONST_BOUND_EPOCH, epoch) for row in res: p1 = SphericalPoint(row['ra1'], row['dec1']) p2 = SphericalPoint(row['ra2'], row['dec2']) e = BoundaryEdge(p1, p2) e.precess(pc) result.append(e) db.close() return result
def draw_meridians(self, origin_offsets={}, include_endpoint=True): start_longitude = self.gridline_factory.meridian_tick_interval * math.ceil( self.min_longitude / self.gridline_factory.meridian_tick_interval) if include_endpoint: stop_longitude = self.max_longitude + 0.5 * self.gridline_factory.meridian_tick_interval else: stop_longitude = self.max_longitude for longitude in numpy.arange( start_longitude, stop_longitude, self.gridline_factory.meridian_tick_interval): self.draw_meridian(ensure_angle_range(longitude), origin_offsets)
def get_constellation_boundaries_for_area( min_longitude, max_longitude, min_latitude, max_latitude, epoch="J2000.0" ): # Convert longitude to 0-360 values # TODO: sometimes boundaries cross the map but have no vertices within the map area + margin and are not plotted min_longitude = ensure_angle_range(min_longitude) max_longitude = ensure_angle_range(max_longitude) if max_longitude == min_longitude: max_longitude += 360 db = SkyMapDatabase() q = "SELECT * FROM skymap_constellation_boundaries WHERE" if min_longitude < max_longitude: q += " ((ra1>={0} AND ra1<={1}".format(min_longitude, max_longitude) else: q += " (((ra1>={0} OR ra1<={1})".format(min_longitude, max_longitude) q += " AND dec1>={0} AND dec1<={1}) OR".format(min_latitude, max_latitude) if min_longitude < max_longitude: q += " (ra2>={0} AND ra2<={1}".format(min_longitude, max_longitude) else: q += " ((ra2>={0} OR ra2<={1})".format(min_longitude, max_longitude) q += " AND dec2>={0} AND dec2<={1}))".format(min_latitude, max_latitude) res = db.query(q) result = [] for row in res: p1 = SkyCoordDeg(row["ra1"], row["dec1"]) p2 = SkyCoordDeg(row["ra2"], row["dec2"]) e = ConstellationBoundaryEdge(p1, p2) e.precess() result.append(e) db.close() return result
def _latitude(self, longitude): longitude = ensure_angle_range(longitude) if longitude < self.LONGITUDES[self.frame][0]: i = -1 long1 = self.LONGITUDES[self.frame][-1] - 360.0 long2 = self.LONGITUDES[self.frame][0] elif longitude > self.LONGITUDES[self.frame][-1]: i = -1 long1 = self.LONGITUDES[self.frame][-1] long2 = self.LONGITUDES[self.frame][0] + 360 else: i = [x > longitude for x in self.LONGITUDES[self.frame]].index(True) - 1 long1 = self.LONGITUDES[self.frame][i] long2 = self.LONGITUDES[self.frame][i + 1] lat1 = self.LATITUDES[self.frame][i] lat2 = self.LATITUDES[self.frame][i + 1] return lat1 + (lat2 - lat1) * (longitude - long1) / (long2 - long1)
def galactic_to_equatorial(p, epoch=REFERENCE_EPOCH): """Returns the equatorial coordinates for the given point in galactic coordinates. Equations taken from: Practical Astronomy with your Calculator or Spreadsheet Peter Duffett-Smith and Jonathan Zwart Cambridge University Press, 2011 Paragraph 30 (page 58) Only used to draw the galactic equator. """ l = math.radians(p.ra.degree) b = math.radians(p.dec.degree) # Get the longitude and latitude of the north galactic pole ngp = galactic_pole(GALACTIC_NORTH_POLE_EPOCH) pl = math.radians(ngp.ra.degree) pb = math.radians(ngp.dec.degree) # Get the galactic longitude offset l0 = math.radians(GALACTIC_LONGITUDE_NORTH_CELESTIAL_POLE - 90.0) # Determine the equatorial longitude = math.degrees( math.atan2( math.cos(b) * math.cos(l - l0), (math.sin(b) * math.cos(pb) - math.cos(b) * math.sin(pb) * math.sin(l - l0)), ) + pl) latitude = math.degrees( math.asin( math.cos(b) * math.cos(pb) * math.sin(l - l0) + math.sin(b) * math.sin(pb))) # Precess to the current epoch pc = PrecessionCalculator(GALACTIC_NORTH_POLE_EPOCH, epoch) longitude, latitude = pc.precess(longitude, latitude) return SkyCoordDeg(ensure_angle_range(longitude), latitude)
def reduce_longitude(self, longitude): return ensure_angle_range(longitude, self.center_longitude)
poles=True) m.draw_galactic(linewidth=GALACTIC_LINEWIDTH, tickinterval=1, dashed=GALACTIC_DASH_PATTERN, poles=True) # Legend rightlegend(f, chart_number, 0, 360, 84, 90) f.render(os.path.join(OUTPUT_FOLDER, "{:02}B.pdf".format(chart_number)), open=False) # North conic maps for conic in CONICS: n = 360 / abs(conic['longitude_step']) for i in range(n): center_longitude = ensure_angle_range(i * conic['longitude_step']) chart_number += 1 # Left page chart_side = 'left' f, m = conic_map(chart_number, chart_side, center_longitude, center_longitude + conic['longitude_range'], conic['min_latitude'], conic['max_latitude'], conic['meridian_interval'], conic['offset']) m.draw_meridians() m.draw_parallels() with m.clip(m.clipping_path): m.draw_constellations(linewidth=0.3) m.draw_ecliptic(linewidth=ECLIPTIC_LINEWIDTH, tickinterval=1,
def tickangle1(self): return ensure_angle_range(self._curve.angle - 180)
def reduce_longitude(self, longitude): """Return the longitude within +/- 180 degrees from the center longitude.""" return ensure_angle_range(longitude, self.center_longitude)
def tickangle2(self): return ensure_angle_range(self._curve.angle)
def labelangle2(self): if self.config.flip_labels: return ensure_angle_range(self.tickangle2 + 90) return ensure_angle_range(self.tickangle2 - 90)
def labelangle1(self): return ensure_angle_range(self.tickangle1)
def labelangle2(self): return ensure_angle_range(self.tickangle2 + 180)
def parallels(self): config = self.config.parallel_config interval = config.tick_interval current_latitude = math.ceil(self.min_latitude / interval) * interval # Internal ticks and labels internal_longitude = self.config.center_longitude if self.config.internal_label_longitude is not None: internal_longitude = self.config.internal_label_longitude internal_meridian = self.projection.meridian(internal_longitude, self.min_latitude, self.max_latitude) internal_tickangle = internal_meridian.angle - 90 if internal_tickangle < 0: internal_tickangle += 180 while current_latitude <= self.max_latitude: # print(f"Parallel at {current_latitude}") parallel = self.projection.parallel(current_latitude, self.min_longitude, self.max_longitude) internal_point = self.projection.project( SkyCoordDeg(internal_longitude, current_latitude)) if not self.clipper.point_inside(internal_point): internal_point = None if self.clip_at_border: parallel_parts, borders = self.clipper.clip(parallel) for p, b in zip(parallel_parts, borders): yield Parallel( current_latitude, p, b, internal_point, internal_tickangle, config, ) else: if isinstance(parallel, Circle) and ensure_angle_range( self.min_longitude) != ensure_angle_range( self.max_longitude): # Construct the arc from the endpoints p1 = (self.projection.project( SkyCoordDeg(self.min_longitude, current_latitude)) - parallel.center) p2 = (self.projection.project( SkyCoordDeg(self.max_longitude, current_latitude)) - parallel.center) parallel = Arc(parallel.center, parallel.radius, p1.angle, p2.angle) yield Parallel( current_latitude, parallel, ["right", "left"], internal_point, internal_tickangle, config, ) current_latitude += interval
def reduce_longitude(self, longitude): return ensure_angle_range(longitude, self.reference_longitude)