Skip to content
intermediatescience

Galaxy Zoo 2 Galaxy Morphology Decision Tree

Classify ten real Galaxy Zoo 2 galaxy images with an 11-question decision tree chained with display_logic, with a trainer pre-labeling the first question.

Try it live — no install

Boot the real Potato server in your browser (WebAssembly) and annotate with this exact config. Nothing leaves your machine.

Run live in your browser

Get This Design

View on GitHub(opens in a new tab)

Clone or download from the repository

Quick start:

bash
git clone https://github.com/davidjurgens/potato-showcase.git
cd potato-showcase/science/astronomy/galaxy-zoo-2-morphology-tree
potato start config.yaml

About this dataset

Galaxy Zoo 2 is a citizen-science project in which volunteers classified the morphology of galaxies imaged by the Sloan Digital Sky Survey. Willett et al. (2013) released the classifications for 304,122 galaxies, collected from 83,943 volunteers who made 16,340,298 classifications between February 2009 and April 2010. The subject images are published separately on Zenodo under a CC BY 4.0 license.

Volunteers walked a decision tree of 11 tasks with 37 possible responses in total. The first task asks whether the galaxy is smooth, shows features or a disk, or is a star or artifact, and the answer decides which task follows. The design reproduces Table 2 of the paper. Every question and response is quoted from the table, each task is a radio scheme, and a display_logic block repeats the full path to the task so that changing an early answer hides the whole branch below the changed answer. A test script that walked all 1,265 paths through the tree confirmed that each path shows exactly the tasks answered so far plus the next one. The paper's text says tasks 01 and 06 are always answered, while Table 2 routes star or artifact to the end, and the design follows the table.

Galaxy Zoo 2 aggregated many volunteers per galaxy, so the config sets consensus_aggregation and three annotators per item, and the consensus export reports each question's top answer and that answer's share of votes. The export counts plain votes and does not reproduce the paper's volunteer weighting. The model_training block names hf-image-classification, which fine-tunes a vision transformer on the radio answers to task 01 only and writes predictions back as pre-labels. Images are read from disk, so the ten galaxies ship in media/, and at least 20 labeled images are needed in the training split by default, which means adding more images from the Zenodo zip. The ten sample galaxies carry no classifications.

Galaxies classified
304,122
Tasks in the decision tree
11
Possible responses
37
Classifications
16,340,298
Volunteers
83,943
Images in the Zenodo release
243,434
Median classifications per galaxy (main sample)
44

Configuration File

This Potato config reproduces the annotation task. Save it as config.yaml and run potato start config.yaml to try it.

yaml
# Galaxy Zoo 2 morphology decision tree (11 tasks, 37 responses)
#
# Dataset: Galaxy Zoo 2 (Willett et al., 2013). Volunteers classified SDSS
# colour-composite galaxy images by walking a decision tree. The question and
# response wording below is quoted from Table 2 of the paper ("The text in
# 'Question' and 'Responses' are displayed to volunteers during
# classification"). The paper also shows an icon beside each response
# (Figure 1), which this design leaves out.
#
# Paper:  Willett et al., Galaxy Zoo 2: detailed morphological classifications
#         for 304 122 galaxies from the Sloan Digital Sky Survey. MNRAS 435(4),
#         2835-2860, 2013.
# DOI:    10.1093/mnras/stt1458
# BibTeX (Crossref):
#   @article{Willett_2013,
#     title   = {Galaxy Zoo 2: detailed morphological classifications for 304 122 galaxies from the Sloan Digital Sky Survey},
#     volume  = {435},
#     ISSN    = {0035-8711},
#     url     = {http://dx.doi.org/10.1093/mnras/stt1458},
#     DOI     = {10.1093/mnras/stt1458},
#     number  = {4},
#     journal = {Monthly Notices of the Royal Astronomical Society},
#     publisher = {Oxford University Press (OUP)},
#     author  = {Willett, Kyle W. and Lintott, Chris J. and Bamford, Steven P. and Masters, Karen L. and Simmons, Brooke D. and Casteels, Kevin R. V. and Edmondson, Edward M. and Fortson, Lucy F. and Kaviraj, Sugata and Keel, William C. and Melvin, Thomas and Nichol, Robert C. and Raddick, M. Jordan and Schawinski, Kevin and Simpson, Robert J. and Skibba, Ramin A. and Smith, Arfon M. and Thomas, Daniel},
#     year    = {2013},
#     month   = Sept,
#     pages   = {2835--2860}
#   }
# Data:   https://data.galaxyzoo.org (tables)
#         https://zenodo.org/records/3565489 (subject images)
#         Dataset DOI 10.5281/zenodo.3565489, "Galaxy Zoo 2: Images from
#         Original Sample", Creative Commons Attribution 4.0 International.
# Images: the ten galaxies in media/ are real GZ2 subject images from the
#         Zenodo record (CC BY 4.0). Source files and attribution are in
#         media/LICENSE-media.txt. Their classifications are NOT included.
#
# The tree (Table 2, "Next" column). A volunteer chooses one response per task
# and is taken straight to the next task. The paper's text says tasks 01 and 06
# are the only questions always answered, while Table 2 sends "star or
# artifact" to the end without task 06. This design follows the Table.
#
#   01 smooth -> 07 | features or disk -> 02 | star or artifact -> end
#   02 yes -> 09 | no -> 03
#   03 yes or no -> 04
#   04 yes -> 10 | no -> 05
#   05 any response -> 06
#   06 yes -> 08 | no -> end
#   07 any response -> 06
#   08 any response -> end
#   09 any response -> 06
#   10 any response -> 11
#   11 any response -> 05
#
# How the tree is expressed. Each task is a radio scheme, and each one after
# task 01 carries a display_logic block that shows it only on the path that
# leads to it. A hidden question keeps its answer, so every condition repeats
# the whole path from task 01, and a question appears once the question before
# it has an answer. Task 05 is reached from task 04 and from task 11, and task
# 06 from tasks 05, 07 and 09, so those use an "any" group. The answer you
# change at the top hides the entire branch below it.
#
# Adaptations (this design differs from the original protocol here):
#   - The ten galaxies are a small sample of the Zenodo images, not the full
#     sample. They are served by Potato's assignment, not at random from the
#     whole survey.
#   - The original site showed one task at a time. Potato shows every
#     question that is currently on the path on one page.
#   - The original interface offered an inverted version of each image. This
#     design shows the colour image only.
#   - The paper's icons (Figure 1) are not reproduced.
#   - Every task is required, as it was for a volunteer on the path.
#   - Response labels are lower case, exactly as in Table 2.
#
# Consensus. GZ2 aggregated the votes of many volunteers per galaxy (the main
# sample finished with a median of 44 classifications). The consensus_aggregation
# block below drives Potato's "consensus" export, which reports for each
# question the share of classifiers who gave the top answer and whether the
# item is retired or needs review. It counts plain votes per question. It does
# not reproduce the paper's volunteer weighting or debiasing, so its numbers
# are not the GZ2 catalogue's vote fractions.
#
#   python -m potato.export -c config.yaml -f consensus -o consensus_out
#
# Model training. The trainer is hf-image-classification (needs
# pip install 'potato-annotation[train-vision]'). It fine-tunes a vision
# transformer on the galaxy images and the radio answers to task 01 ONLY,
# "smooth", "features or disk" or "star or artifact", and writes its
# predictions back as prelabels for galaxies nobody has labelled. It does not
# learn the other ten tasks, does not follow the tree, and does not serve or
# deploy a model. It reads images from disk, which is why the galaxies ship in
# media/ rather than as links. By default it needs at least 20 images in the
# training split, and this sample has ten galaxies, so add more images from
# the Zenodo zip (each file is images/<asset_id>.jpg, matched to a galaxy by
# gz2_filename_mapping.csv in the same record) before training. Open
# /admin/training with the admin key below, pick the trainer and the
# t01_smooth_or_features scheme, and click Train now.
#
# Run from this folder:
#   potato start config.yaml -p 8000

annotation_task_name: "Galaxy Zoo 2 morphology tree"
task_dir: "."
media_directory: media

data_files:
  - "sample-data.json"

item_properties:
  id_key: id
  text_key: image

instance_display:
  fields:
    - key: image
      type: image
      label: "SDSS colour composite"
      display_options:
        alt_text: "SDSS colour-composite image of one galaxy from Galaxy Zoo 2"
        max_width: 424

output_annotation_dir: "annotation_output"
export_annotation_format: jsonl

require_password: false
admin_api_key: "demo-admin-key"

user_config:
  allow_all_users: true

# GZ2 showed each galaxy to many volunteers. Three per galaxy keeps the demo
# small while giving the consensus export something to aggregate.
num_annotators_per_item: 3

consensus_aggregation:
  agreement_threshold: 0.8
  min_classifiers: 3

model_training:
  enabled: true
  writeback:
    schemas: ["t01_smooth_or_features"]
    include_unlabeled: true
    min_confidence: 0.6

annotation_instructions: |
  Look at the galaxy and answer the questions that appear, starting with the
  first. Each answer opens the next question on the tree, and the questions
  that follow depend on what you choose.

annotation_schemes:
  # Task 01
  - annotation_type: radio
    humanize_labels: false
    name: t01_smooth_or_features
    description: "Is the galaxy simply smooth and rounded, with no sign of a disk?"
    labels:
      - "smooth"
      - "features or disk"
      - "star or artifact"
    label_requirement:
      required: true

  # Task 02
  - annotation_type: radio
    humanize_labels: false
    name: t02_edge_on
    description: "Could this be a disk viewed edge-on?"
    labels:
      - "yes"
      - "no"
    label_requirement:
      required: true
    display_logic:
      show_when:
        - schema: t01_smooth_or_features
          operator: equals
          value: "features or disk"

  # Task 03
  - annotation_type: radio
    humanize_labels: false
    name: t03_bar
    description: "Is there a sign of a bar feature through the centre of the galaxy?"
    labels:
      - "yes"
      - "no"
    label_requirement:
      required: true
    display_logic:
      show_when:
        - schema: t01_smooth_or_features
          operator: equals
          value: "features or disk"
        - schema: t02_edge_on
          operator: equals
          value: "no"

  # Task 04
  - annotation_type: radio
    humanize_labels: false
    name: t04_spiral
    description: "Is there any sign of a spiral arm pattern?"
    labels:
      - "yes"
      - "no"
    label_requirement:
      required: true
    display_logic:
      show_when:
        - schema: t01_smooth_or_features
          operator: equals
          value: "features or disk"
        - schema: t02_edge_on
          operator: equals
          value: "no"
        - schema: t03_bar
          operator: not_empty

  # Task 05
  - annotation_type: radio
    humanize_labels: false
    name: t05_bulge_prominence
    description: "How prominent is the central bulge, compared with the rest of the galaxy?"
    labels:
      - "no bulge"
      - "just noticeable"
      - "obvious"
      - "dominant"
    label_requirement:
      required: true
    display_logic:
      show_when:
        - schema: t01_smooth_or_features
          operator: equals
          value: "features or disk"
        - schema: t02_edge_on
          operator: equals
          value: "no"
        - schema: t03_bar
          operator: not_empty
        - any:
            - schema: t04_spiral
              operator: equals
              value: "no"
            - all:
                - schema: t04_spiral
                  operator: equals
                  value: "yes"
                - schema: t10_spiral_winding
                  operator: not_empty
                - schema: t11_spiral_arms
                  operator: not_empty

  # Task 06
  - annotation_type: radio
    humanize_labels: false
    name: t06_odd
    description: "Is there anything odd?"
    labels:
      - "yes"
      - "no"
    label_requirement:
      required: true
    display_logic:
      show_when:
        - any:
            - all:
                - schema: t01_smooth_or_features
                  operator: equals
                  value: "features or disk"
                - schema: t02_edge_on
                  operator: equals
                  value: "no"
                - schema: t03_bar
                  operator: not_empty
                - any:
                    - schema: t04_spiral
                      operator: equals
                      value: "no"
                    - all:
                        - schema: t04_spiral
                          operator: equals
                          value: "yes"
                        - schema: t10_spiral_winding
                          operator: not_empty
                        - schema: t11_spiral_arms
                          operator: not_empty
                - schema: t05_bulge_prominence
                  operator: not_empty
            - all:
                - schema: t01_smooth_or_features
                  operator: equals
                  value: "smooth"
                - schema: t07_roundness
                  operator: not_empty
            - all:
                - schema: t01_smooth_or_features
                  operator: equals
                  value: "features or disk"
                - schema: t02_edge_on
                  operator: equals
                  value: "yes"
                - schema: t09_bulge_shape
                  operator: not_empty

  # Task 07
  - annotation_type: radio
    humanize_labels: false
    name: t07_roundness
    description: "How rounded is it?"
    labels:
      - "completely round"
      - "in between"
      - "cigar-shaped"
    label_requirement:
      required: true
    display_logic:
      show_when:
        - schema: t01_smooth_or_features
          operator: equals
          value: "smooth"

  # Task 08
  - annotation_type: radio
    humanize_labels: false
    name: t08_odd_feature
    description: "Is the odd feature a ring, or is the galaxy disturbed or irregular?"
    labels:
      - "ring"
      - "lens or arc"
      - "disturbed"
      - "irregular"
      - "other"
      - "merger"
      - "dust lane"
    label_requirement:
      required: true
    display_logic:
      show_when:
        - any:
            - all:
                - schema: t01_smooth_or_features
                  operator: equals
                  value: "features or disk"
                - schema: t02_edge_on
                  operator: equals
                  value: "no"
                - schema: t03_bar
                  operator: not_empty
                - any:
                    - schema: t04_spiral
                      operator: equals
                      value: "no"
                    - all:
                        - schema: t04_spiral
                          operator: equals
                          value: "yes"
                        - schema: t10_spiral_winding
                          operator: not_empty
                        - schema: t11_spiral_arms
                          operator: not_empty
                - schema: t05_bulge_prominence
                  operator: not_empty
            - all:
                - schema: t01_smooth_or_features
                  operator: equals
                  value: "smooth"
                - schema: t07_roundness
                  operator: not_empty
            - all:
                - schema: t01_smooth_or_features
                  operator: equals
                  value: "features or disk"
                - schema: t02_edge_on
                  operator: equals
                  value: "yes"
                - schema: t09_bulge_shape
                  operator: not_empty
        - schema: t06_odd
          operator: equals
          value: "yes"

  # Task 09
  - annotation_type: radio
    humanize_labels: false
    name: t09_bulge_shape
    description: "Does the galaxy have a bulge at its centre? If so, what shape?"
    labels:
      - "rounded"
      - "boxy"
      - "no bulge"
    label_requirement:
      required: true
    display_logic:
      show_when:
        - schema: t01_smooth_or_features
          operator: equals
          value: "features or disk"
        - schema: t02_edge_on
          operator: equals
          value: "yes"

  # Task 10
  - annotation_type: radio
    humanize_labels: false
    name: t10_spiral_winding
    description: "How tightly wound do the spiral arms appear?"
    labels:
      - "tight"
      - "medium"
      - "loose"
    label_requirement:
      required: true
    display_logic:
      show_when:
        - schema: t01_smooth_or_features
          operator: equals
          value: "features or disk"
        - schema: t02_edge_on
          operator: equals
          value: "no"
        - schema: t03_bar
          operator: not_empty
        - schema: t04_spiral
          operator: equals
          value: "yes"

  # Task 11
  - annotation_type: radio
    humanize_labels: false
    name: t11_spiral_arms
    description: "How many spiral arms are there?"
    labels:
      - "1"
      - "2"
      - "3"
      - "4"
      - "more than four"
      - "can’t tell"
    label_requirement:
      required: true
    display_logic:
      show_when:
        - schema: t01_smooth_or_features
          operator: equals
          value: "features or disk"
        - schema: t02_edge_on
          operator: equals
          value: "no"
        - schema: t03_bar
          operator: not_empty
        - schema: t04_spiral
          operator: equals
          value: "yes"
        - schema: t10_spiral_winding
          operator: not_empty

Sample Data

json
[
  {
    "id": "gz2_001",
    "image": "/media/gz2_001.jpg",
    "dr7objid": "587722981741363294",
    "asset_id": 3
  },
  {
    "id": "gz2_002",
    "image": "/media/gz2_002.jpg",
    "dr7objid": "587722981741363323",
    "asset_id": 4
  }
]

// ... and 8 more items

Dataset & paper

Willett et al., MNRAS 2013

Paper DOI
10.1093/mnras/stt1458
Dataset DOI
10.5281/zenodo.3565489

Citation (BibTeX)

bibtex
@article{Willett2013GalaxyZoo2,
  title = {Galaxy Zoo 2: detailed morphological classifications for 304 122 galaxies from the Sloan Digital Sky Survey},
  volume = {435},
  ISSN = {0035-8711},
  url = {http://dx.doi.org/10.1093/mnras/stt1458},
  DOI = {10.1093/mnras/stt1458},
  number = {4},
  journal = {Monthly Notices of the Royal Astronomical Society},
  publisher = {Oxford University Press (OUP)},
  author = {Willett, Kyle W. and Lintott, Chris J. and Bamford, Steven P. and Masters, Karen L. and Simmons, Brooke D. and Casteels, Kevin R. V. and Edmondson, Edward M. and Fortson, Lucy F. and Kaviraj, Sugata and Keel, William C. and Melvin, Thomas and Nichol, Robert C. and Raddick, M. Jordan and Schawinski, Kevin and Simpson, Robert J. and Skibba, Ramin A. and Smith, Arfon M. and Thomas, Daniel},
  year = {2013},
  month = sep,
  pages = {2835--2860}
}

Details

Annotation Types

radio

Domain

astronomycitizen science

Use Cases

galaxy morphology classificationdecision tree annotationcrowd consensus

Tags

galaxy zoo 2galaxy zoosdssgalaxy morphologydecision treecitizen sciencedisplay_logicconsensus

Found an issue or want to improve this design?

Open an Issue(opens in a new tab)