steveberardi / starplot

✨ Star charts and maps in Python
https://starplot.dev
MIT License
35 stars 8 forks source link

Showing stars only within a given constellation's border #87

Closed codingfar closed 1 month ago

codingfar commented 2 months ago

Hi, I was wondering whether there is a way to plot a single constellation. Specifically, I would like to plot all the stars that are located within a given constellation's borders, but not outside it. Thanks!

steveberardi commented 2 months ago

Currently, there is no easy way to do this, but I have started working on making things like this easier. Starplot's constellation data actually does have polygons for all the constellation boundaries (see the parser/builder code here), but it's not really accessible right now. I'm still trying to figure out a good way to add this functionality to the Starplot API, making it easier to create maps like this one:

https://en.wikipedia.org/wiki/Sagittarius_(constellation)#/media/File:Sagittarius_IAU.svg

If you have any ideas on how the API could work or even more specific use cases, that'd be helpful! Thanks!

steveberardi commented 2 months ago

I was thinking more about this, and realized there's a somewhat easy way to add this functionality by creating a model for constellations. I was able to whip up some code real quick to create this image:

map-orion

Once this is added to Starplot, you'd be able to create images like this with the code:

p.stars(
  catalog="big-sky",
  bayer_labels=True,
  where=[
    Star.magnitude < 8,
    Star.constellation_id == 'ori'
  ],
)

I'm gonna think about this some more, but will probably have something available like this in the upcoming release (v0.11.0) - stay tuned!

codingfar commented 2 months ago

Thanks so much for the response! Yes, something like that (i.e. along the lines of pairing up where with Star.constellation_id == 'ori') is what I was thinking of (and what I tried to tinker with yesterday, but soon realised it was probably not possible yet, hence my original question). Thanks a lot for taking the time!

Something closely related to this which would be really useful (at least, it's what I was really after) is to be able to plot a single constellation and nothing else at all. That is, imagine simply wanting to plot the constellation of Orion only, with anything else outside Orion's borders being just blank white space. In other words, suppressing all the stuff lying outside Orion's borders (e.g. stars, other constellation lines, DSOs etc). Having the ability to do that would be fantastic.

Once again, thanks for the time you put into this, and for a great tool!

steveberardi commented 2 months ago

Cool, thanks for sharing that second example. I'd love to make it easy for Starplot to do things like that, but that'll require some larger refactoring work, which means it'll probably be in version 0.12.0 or later.

I'm hoping to release v0.11.0 this week sometime, and that'll include the basic "plotting things by constellation" (as illustrated in the image I shared above, i.e. Star.constellation_id == 'ori'). If you're curious, here's the PR that implements this.

Thanks for the feedback and glad you're finding Starplot useful!

codingfar commented 2 months ago

Thanks a lot. Great stuff!

steveberardi commented 2 months ago

Just released v0.11.0, which partially adds this feature 😄

codingfar commented 2 months ago

Thanks! Will try it out! :)

steveberardi commented 1 month ago

I've been making some more progress on this :)

map-orion

Basically, I'm adding two things:

  1. Shapely geometry fields on all models which will allow you to do things like this:
orion = Constellation.get(iau_id="ori")
p.stars(
        where=[
            Star.magnitude < 12,
            Star.geometry.intersects(orion.geometry) 
        ],
    )
  1. Clip path kwarg when creating a plot that lets you specify a custom clip path (which will clip everything):
p = sp.MapPlot(
        projection=Projection.MERCATOR,
        ra_min=3.2,
        ra_max=7.6,
        dec_min=-16,
        dec_max=24,
        style=style,
        resolution=4000,
        clip_path=orion.boundary,
    )

These features will be in the next version (v0.12), hopefully out in the next few weeks.

codingfar commented 1 month ago

That's fantastic! Great job! Looking forward to the next release :)

codingfar commented 1 month ago

Thanks a lot for this version! Would you be so kind as to provide a minimum working example implementing this feature? I've been trying it out, but for the line Star.geometry.intersects(orion.geometry), I keep getting the error: AttributeError: 'Constellation' object has no attribute 'geometry'. I'm sure I'm missing something.

steveberardi commented 1 month ago

ohhh, for constellations, the attribute to get the boundary is boundary. I originally was thinking I'd use geometry but then remembered a constellation's lines might be useful to add later, and I couldn't decide which one should be considered the "geometry" of the constellation: borders or lines.

Anyway, I think to achieve what you're looking for, you want to use the clip_path on the plot, here's an example on the docs.