Skip to content

Conversation

@annavik
Copy link
Member

@annavik annavik commented Oct 13, 2025

Summary

In this PR we add support for species charts. To be more specific, we make it possible to see average occurrence per month for a specific species (or taxon).

List of Changes

  • Return summary data from taxon details endpoint
  • Add tab layout to taxon details view
  • Render summary data as plots

Related Issues

Related to #864

Detailed Description

How to Test the Changes

Changes must be tested locally since they include backend updates.

Screenshots

Screenshot 2025-10-13 at 16 25 14

Deployment Notes

Remember to deploy the backend after merge.

@netlify
Copy link

netlify bot commented Oct 13, 2025

Deploy Preview for antenna-preview canceled.

Name Link
🔨 Latest commit 31b1ca1
🔍 Latest deploy log https://app.netlify.com/projects/antenna-preview/deploys/68ef307dcfde3c000897fe8a

@annavik
Copy link
Member Author

annavik commented Oct 13, 2025

Some things to discuss:

  • Are backend updates applied in the way we prefer? I especially got a bit unsure about the part where I make the request params available.
  • What charts do we want? See iNaturalist for inspiration: https://www.inaturalist.org/taxa/127506-Macrothylacia-rubi. The one I included is similar to the "Seasonality".
  • Maybe not for now, but I'm curious about these charts as an alternative to Plotly. I think they seem more appealing for web! :)

Screenshots for inspiration:
Screenshot 2025-10-13 at 16 44 58
Screenshot 2025-10-13 at 16 47 50

@annavik annavik changed the title [Draft] Add support for species charts Add support for species charts Oct 13, 2025
@annavik annavik marked this pull request as ready for review October 13, 2025 18:30
@annavik
Copy link
Member Author

annavik commented Oct 13, 2025

After discussing, we (Anna and Michael) agreed this is a good start and we will try merge it.

Some thoughts for next steps:

  • Extract the summary data to a separate endpoint backend side, to not slow down main endpoints
  • Present more fine grained charts, for example show species occurrences for a single month
  • Make it possible to see this type of charts for a group of species, not just individual species

@annavik annavik requested a review from mihow October 13, 2025 18:38
qs = Occurrence.objects.filter(project=project_pk)

if taxon_pk:
qs = qs.filter(determination_id=taxon_pk)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mihow one thing I forgot to mention is that this means we will present direct occurrences. I guess since the main focus for this task is species, it's perhaps not a big concern, but just FIY.

I think it would be more useful to consider all occurrences, not just direct. But I also know a bit tricker and slower, so maybe not for now? Let me know what you think!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh thanks for calling that out, we have a generic filter for getting the recursive count. The performance should be fine for the detail view.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's add the recursive count in a follow-up! I will merge this as-is now.

@mihow
Copy link
Collaborator

mihow commented Oct 14, 2025

Here's an example for a species & project with more occurrences!
image

However most charts tend to look like this, even when there are a lot of occurrences :)
image

It would be really helpful to show both the occurrences & the number of captures taken. So you can see which months had no monitoring.

iNaturalist also provides an option to normalize the species counts based on the the total count of ALL species observations. We could do something similar by dividing / normalizing the occurrences counts by the total number of captures taken.

return TagSerializer(tag_list, many=True, context=self.context).data

def get_summary_data(self, obj: Taxon):
project = get_active_project(request=self.context["request"], required=False)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@annavik I couldn't help it. I made the get_active_project helper reusable here.

Occurrence.objects.filter(project=project_pk)
.values("event__start__month")
.annotate(
total_occurrences=models.Count("id"),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@annavik here is alternative query to get all of the data you need in a single query. it's less important on detail views than list views, but I try to reduce when I can! it probably is possible to even do the division within the db query, but it's only 12 items (12 months) to divide, so in python is fine.

Copy link
Collaborator

@mihow mihow left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have fight charts! I know they will continue to be revised, but this is a great milestone. Merging!

@mihow mihow merged commit dcb5e8c into main Oct 15, 2025
8 checks passed
@mihow mihow deleted the feat/species-charts branch October 15, 2025 05:57
@annavik
Copy link
Member Author

annavik commented Oct 15, 2025

We have fight charts! I know they will continue to be revised, but this is a great milestone. Merging!

Woho, thank you!!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants