본문으로 건너뛰기

FITS 컷아웃의 진짜-가짜 판별과 은하 형태 분류

과학, 참조, 차분 FITS 컷아웃에 적경/적위 표시와 광도 곡선을 붙여 일시적 천체 후보를 판별하거나, 질문 트리로 은하를 분류합니다.

v2.13.0에서 추가

fits_cutout 디스플레이는 브라우저에서 FITS 이미지를 보여 줍니다. 항목당 이미지 하나를 보여 주거나, 일시적 천체 후보의 과학, 참조, 차분 컷아웃을 후보의 광도 곡선 위에 나란히 보여 줍니다. 시간 영역 천문학자는 이 디스플레이를 진짜-가짜 판별에 사용합니다. 진짜-가짜 판별에서 주석자는 ZTF나 Rubin 같은 탐사의 각 후보에 진짜 천체물리학적 일시적 천체인지 가짜 검출인지 레이블을 붙입니다. 이 레이블은 진짜-가짜 분류기의 학습 데이터가 됩니다. 예를 들어 ZTF용 Braai 분류기는 레이블이 붙은 과학, 참조, 차분 세 쌍 3만 개 이상으로 학습되었습니다(Duev et al., MNRAS 489, 3582). 은하 형태 분류는 항목당 이미지 하나와 Galaxy Zoo 방식의 질문 트리를 사용합니다. 디스플레이 자체는 아무것도 저장하지 않습니다. 판별 질문은 보통 Real, Bogus, Unsure를 R, B, U 키에 배정한 일반 radio 스킴입니다.

FITS는 천문 이미지와 표의 표준 파일 형식입니다. FITS 헤더의 세계 좌표계(WCS) 키워드는 이미지의 각 픽셀을 하늘의 위치에 대응시킵니다. 차분 이미지는 보정된 과학 노출에서 같은 시야의 참조(템플릿) 이미지를 뺀 것이며, 진짜 일시적 천체는 차분 이미지에 새로운 점광원으로 나타납니다. ZTF 경보 패킷은 과학, 참조, 차분 컷아웃을 gzip으로 압축한 FITS 이미지로 담고 있고(경보 스키마), Rubin 담당자들은 Rubin 경보도 세 컷아웃을 모두 담을 것이라고 밝혔습니다(Rubin 포럼).

합성 일시 천체 후보의 과학, 참조, 차분 FITS 컷아웃과 RA/Dec 표시, 아래의 두 밴드 광도 곡선차분 컷아웃에서 일시 천체가 두드러집니다

  • 읽기: astropy(BSD-3-Clause)가 Potato 서버에서 FITS 파일을 읽고, 항목의 위치 주변 영역을 잘라 내고, 컷아웃의 값을 스케일링하고, 컷아웃의 WCS 설명과 함께 PNG를 보냅니다. 서버는 첫 FITS 파일을 읽을 때 astropy를 임포트하며, astropy를 불러오지 않고도 시작합니다.
  • 형식: .fits, .fit, .fts, gzip 압축된 .fits.gz. 디스플레이는 hdu로 지정한 HDU를 보여 주며, 없으면 2차원(또는 그 이상) 이미지를 담은 첫 HDU를 보여 줍니다. 큐브이면 큐브의 첫 평면을 보여 줍니다. .fits.gz 이름으로 디스크에 쓴 ZTF 컷아웃은 압축을 풀지 않고 열립니다.
  • 컷아웃: 중심은 FITS 픽셀(x, y) 또는 하늘(ra, dec)의 위치이고, 크기는 픽셀 또는 "40 arcsec" 같은 각도입니다. 압축되지 않은 파일에서는 컷아웃의 행만 읽습니다.
  • 캐싱: 변환된 각 컷아웃은 <task_dir>/.potato_cache/fits/에 PNG와 JSON 파일로 기록됩니다. 캐시 키는 파일의 경로, 크기, 수정 시각, 스케일링 옵션을 포함합니다. 따라서 바뀌지 않은 파일은 한 번만 변환됩니다. 캐시는 가장 최근에 사용한 항목 4,000개를 유지하며, 폴더를 삭제해도 안전합니다.
  • 오프라인: FITS 파일과 광도 곡선은 미디어 디렉터리에서 읽습니다. URL과 미디어 디렉터리 밖의 경로는 거부되며, 광도 곡선 플롯은 Potato와 함께 배포되는 Plotly 사본을 사용합니다.

이 디스플레이에는 astro 엑스트라(astropy>=5.3)가 필요합니다.

bash
pip install 'potato-annotation[astro]'

fits_cutout 필드가 있는데 astropy가 설치되어 있지 않은 설정은 시작할 때 설치 명령이 담긴 메시지와 함께 실패합니다.

설정

아래 설정은 컷아웃 세 쌍에 대한 진짜-가짜 판별을 구성합니다. 모든 후보에 진짜-가짜 레이블이 필수이고, 가짜 검출의 원인에 대한 두 번째 질문은 주석자가 Bogus를 고른 뒤에만 나타납니다.

yaml
annotation_task_name: "Transient candidate vetting"
task_dir: .
media_directory: media
output_annotation_dir: annotation_output
data_files: [data/candidates.json]
item_properties: {id_key: id, text_key: summary}
 
instance_display:
  fields:
    - key: candidate            # item field holding the triplet
      type: fits_cutout
      label: "Cutouts"
      display_options:
        size: 48                # pixels, used when an item gives no size
        interval: zscale
        stretch: linear
        panels:
          - {key: science, label: Science}
          - {key: reference, label: Reference}
          - {key: difference, label: Difference, stretch: asinh}
 
user_config:
  allow_all_users: true
 
annotation_schemes:
  - annotation_type: radio
    name: vetting
    description: "Is this a real astrophysical transient?"
    humanize_labels: false
    labels:
      - {name: "Real", key_value: "r"}
      - {name: "Bogus", key_value: "b"}
      - {name: "Unsure", key_value: "u"}
    label_requirement: {required: true}
 
  - annotation_type: multiselect
    name: bogus_reason
    description: "What makes the candidate bogus?"
    humanize_labels: false
    labels:
      - "Subtraction residual (dipole)"
      - "Cosmic ray or hot pixel"
      - "Satellite or asteroid trail"
      - "Bad column or image edge"
      - "Other"
    display_logic:
      show_when:
        - {schema: vetting, operator: equals, value: "Bogus"}

panels 목록은 컷아웃과 그 순서를 고르며, 각 패널은 자체 스케일링을 설정할 수 있습니다. 여기서 차분 패널은 asinh 스트레치를 사용하고, 과학과 참조 패널은 디스플레이의 zscale 구간과 선형 스트레치를 유지합니다. humanize_labels: false는 각 레이블을 쓴 그대로 보여 줍니다. 그러면 화면의 "Bogus"가 display_logic 조건의 값과 일치합니다. 숨겨진 문항은 페이지와 서버의 필수 답 점검에서 건너뜁니다.

각 항목은 media_directory 기준의 FITS 경로 세 개, 후보의 위치, 선택적인 광도 곡선을 제공합니다.

json
{
  "id": "cand-001",
  "summary": "cand-001: ra 150.11920, dec +2.20583, band r",
  "candidate": {
    "science": "cutouts/cand-001_sci.fits",
    "reference": "cutouts/cand-001_ref.fits",
    "difference": "cutouts/cand-001_diff.fits",
    "ra": 150.11920, "dec": 2.20583,
    "size": 48,
    "light_curve": "lightcurves/cand-001.csv"
  }
}

은하 형태 분류에서는 경로 하나를 담은 항목 필드가 이미지 하나를 보여 줍니다.

json
{"id": "gal-17", "image": "galaxies/gal-17.fits"}

ZTF 광도 곡선

Potato는 흔한 이름으로 광도 곡선 열을 찾으며, ZTF의 측광 열인 magpsf와 sigmapsf는 그 이름에 없습니다. 대응을 지정하지 않으면 jd, fid, magpsf, sigmapsf, diffmaglim 열을 가진 ZTF 광도 곡선은 diffmaglim이 있는 각 행을 상한으로 그립니다. 아래의 부분 블록은 위 설정의 fits_cutout 필드에 옵션 두 개를 추가하고 각 열의 이름을 지정합니다.

yaml
instance_display:
  fields:
    - key: candidate
      type: fits_cutout
      display_options:
        light_curve_columns: {time: jd, band: fid, mag: magpsf, err: sigmapsf, limit: diffmaglim}
        time_label: JD

플롯의 "this image" 표시는 과학 이미지의 MJD-OBS에서 오며, Potato는 MJD-OBS가 첫 점보다 앞이거나 마지막 점보다 뒤로 1,000 시간 단위 이내일 때에만 표시를 그립니다. JD 축에서 MJD-OBS는 모든 시간보다 약 2,400,000 작으므로 Potato는 표시를 그리지 않습니다. 각 항목에 JD로 된 epoch를 주면 표시가 놓입니다. ZTF 필터 ID 1, 2, 3은 밴드 이름 "1", "2", "3"이 되며, 밴드 열에 대신 g, r, i를 쓰면 각 밴드가 평소 색을 받습니다.

질문 트리를 쓰는 은하 형태 분류

Galaxy Zoo 방식의 결정 트리는 고정된 순서로 질문을 하며, 각 답이 다음 질문을 정합니다. Galaxy Zoo DECaLS 트리는 "Smooth or Featured?"로 시작합니다(Walmsley et al., MNRAS 509, 3966). Potato에서 트리의 각 질문은 radio 스킴이고, 각 후속 질문의 display_logic은 그 질문으로 이어지는 답 뒤에서만 질문을 보여 줍니다.

display_logic의 규칙 두 가지가 트리를 결정합니다. 첫째, 숨겨진 문항은 숨겨지기 전에 주석자가 준 답을 유지합니다. 둘째, 문항의 가시성은 부모 문항이 화면에 있는지와 관계없이 답만으로 계산됩니다. 따라서 각 조건은 첫 문항부터의 전체 경로를 all로 묶어야 합니다. 부모만 지정하는 조건은 주석자가 앞의 답을 바꾼 뒤에도 뒤의 문항을 화면에 남겨 둡니다.

아래 설정은 은하 이미지 한 장당 네 문항의 트리를 묻습니다.

yaml
annotation_task_name: "Galaxy morphology"
task_dir: .
media_directory: media
output_annotation_dir: annotation_output
data_files: [data/galaxies.json]
item_properties: {id_key: id, text_key: id}
 
instance_display:
  fields:
    - key: image
      type: fits_cutout
      label: "Galaxy"
      display_options:
        interval: percentile
        percentile: 99.5
        stretch: asinh
 
user_config:
  allow_all_users: true
 
annotation_schemes:
  - annotation_type: radio
    name: shape
    description: "Is the galaxy simply smooth and rounded, with no sign of a disk?"
    humanize_labels: false
    labels: ["Smooth", "Features or a disk", "Star or artifact"]
    label_requirement: {required: true}
 
  - annotation_type: radio
    name: edge_on
    description: "Could this be a disk viewed edge-on?"
    labels: ["Yes", "No"]
    label_requirement: {required: true}
    display_logic:
      show_when:
        - {schema: shape, operator: equals, value: "Features or a disk"}
 
  - annotation_type: radio
    name: bulge_edge_on
    description: "Does the edge-on disk have a bulge at its center? If so, what shape?"
    humanize_labels: false
    labels: ["Rounded", "Boxy", "No bulge"]
    label_requirement: {required: true}
    display_logic:
      show_when:
        - all:
            - {schema: shape, operator: equals, value: "Features or a disk"}
            - {schema: edge_on, operator: equals, value: "Yes"}
 
  - annotation_type: radio
    name: spiral
    description: "Is there any sign of a spiral arm pattern?"
    labels: ["Yes", "No"]
    label_requirement: {required: true}
    display_logic:
      show_when:
        - all:
            - {schema: shape, operator: equals, value: "Features or a disk"}
            - {schema: edge_on, operator: equals, value: "No"}

항목에 위치가 없으면 디스플레이는 이미지 전체를 보여 줍니다. asinh 스트레치를 쓴 백분위 구간은 은하의 희미한 바깥 원반과 밝은 중심핵을 한 화면에 보여 줍니다. zscale 구간은 희미한 광원에 맞춰져 있어 밝은 중심핵을 포화시킬 수 있습니다. 따옴표 없는 Yes와 No는 YAML이 불리언으로 읽으므로 "Yes"와 "No"에는 따옴표를 붙입니다. 업스트림 예제는 같은 종류의 트리를 판별 문항 뒤에 둡니다. 그 예제의 트리는 진짜 후보 각각의 모은하에 대해 묻습니다.

항목 데이터

항목의 필드는 FITS 경로이거나 아래 키를 가진 매핑입니다.

키의미
science, reference, difference, image, 또는 panels 항목이 지정하는 아무 키미디어 디렉터리의 FITS 경로, 또는 이미지 하나를 다르게 스케일링하는 매핑 {path: ..., stretch: ..., interval: ...}
ra, dec도 단위의 컷아웃 중심, 또는 60진법 텍스트(적경은 시간 단위 "10:00:28.6", 적위는 "+02:12:21"). ICRS로 읽고, 프레임이 다르면 이미지 자체의 프레임(FK5, 은하 좌표)으로 변환합니다
x, yFITS 픽셀 단위의 컷아웃 중심. 첫 픽셀의 중심은 ds9나 CRPIX와 같이 (1, 1)입니다. 항목은 x와 y 또는 ra와 dec를 주며 둘 다 주지는 않습니다
size픽셀 또는 각도("30 arcsec", "0.5 arcmin", "0.01 deg")로 나타낸 컷아웃 크기
stretch, interval, percentile, asinh_a, log_a, invert, hdu이 항목의 모든 이미지에 대한 스케일링
light_curve미디어 디렉터리의 CSV, TSV, JSON 파일, 또는 [{"mjd": 60600.0, "band": "g", "mag": 20.21, "magerr": 0.07}] 같은 점 목록
epoch과학 이미지의 MJD-OBS 대신 광도 곡선에 표시할 시간

스케일링 옵션은 낮은 것부터 네 수준에서 적용됩니다. (1) 디스플레이 옵션, (2) panels 항목, (3) 항목, (4) 이미지 하나에 대한 항목의 매핑. 나중 수준이 앞 수준을 덮어씁니다. 위치는 있고 어디에도 크기가 없는 항목은 64픽셀 컷아웃을 받으며, 컷아웃은 한 변이 최대 4,096픽셀입니다. 위치가 없는 항목은 이미지 전체를 보여 주며, 가로나 세로가 1,024픽셀보다 큰 이미지는 1,024로 블록 평균을 내어 줄입니다. 전체 이미지는 max_image_pixels로 제한됩니다. 위치 없이 크기만 있으면 오류입니다. panels 목록이 없으면 디스플레이는 항목이 가진 science, reference, difference 중 있는 것을, 없으면 image를 보여 줍니다.

광도 곡선 파일

광도 곡선 파일은 점당 한 행을 가집니다.

csv
mjd,band,mag,magerr,limit
60570.0,r,,,21.3
60600.0,g,20.21,0.07,
60603.0,g,19.37,0.05,

등급이 있는 행은 검출이고, 등급이 없고 limit이 있는 행은 상한입니다. 사용할 수 있는 시간이 없는 행은 건너뛰고 그 수를 셉니다. light_curve_columns가 없으면 열 이름을 대소문자를 구분하지 않고 아래 목록과 순서대로 대조합니다.

역할시도하는 이름
timemjd, time, jd, hjd, bjd, t
magmag, magnitude, flux, value, y
errmagerr, mag_err, err, error, sigma, fluxerr, flux_err, dy
bandband, filter, fid, passband
limitlimit, upper_limit, diffmaglim, maglim, lim

JSON 광도 곡선은 점 객체의 목록이거나, points 또는 data 아래에 목록을 둔 객체입니다. TSV 파일은 .tsv 확장자 또는 파일 안의 탭으로 감지하며, #로 시작하는 줄은 건너뜁니다. 2 MB를 넘는 파일은 거부되고 20,000행을 넘는 행은 버려집니다. 밴드는 u, g, r, i, z, y, J, H, K, W1, W2, c, o 순서이며, 그 밖의 밴드 이름은 나열된 밴드 뒤에 옵니다.

디스플레이 옵션

옵션은 display_options 아래 또는 필드에 직접 두며, 서버는 시작할 때 모든 값을 점검합니다.

옵션기본값의미
panels항목의 science, reference, difference, 없으면 image{key, label} 형태의 순서 있는 패널 최대 6개. 패널은 아래의 스케일링 옵션도 설정할 수 있습니다. label이 없는 패널은 키에서 제목을 만듭니다
size없음항목이 크기를 주지 않을 때의 컷아웃 크기(픽셀 또는 각도). 위치가 있고 어디에도 크기가 없으면 64픽셀
intervalzscaleminmax, zscale(ds9와 같은 IRAF의 zscale), percentile
percentile99.5interval: percentile일 때 한계 안에 들어가는 픽셀의 비율이며 0보다 크고 100 이하
stretchlinearlinear, sqrt, log, asinh
asinh_a0.1asinh 스트레치의 a 매개변수. 값이 작을수록 밝은 픽셀을 더 압축합니다
log_a1000log 스트레치의 a 매개변수
invertfalse밝은 배경에 어두운 광원
hdu첫 이미지 HDUHDU 번호(0이 주 HDU) 또는 EXTNAME
max_file_mb100읽는 FITS 파일의 최대 크기(압축 여부와 무관, 메가바이트)
max_image_pixels25000000항목이 위치를 주지 않을 때 전체로 보여 주는 이미지의 최대 크기
light_curvetrue항목에 광도 곡선이 있으면 그립니다
light_curve_columns감지{time, mag, err, band, limit} 형태의 역할별 열 이름
light_curve_unitsmagmag(밝을수록 위) 또는 flux
light_curve_height260픽셀 단위의 플롯 높이
time_labelMJD시간 축 제목
crosshairtrue공유 십자선을 표시합니다
compasstrueWCS의 북쪽과 동쪽 화살표를 표시합니다
panel_size18rem(패널 하나이면 30rem)CSS 길이로 나타낸 패널의 최대 너비. 숫자만 쓰면 픽셀입니다

engine 옵션은 potato 한 가지 값만 받습니다. FITS 파일은 항상 서버에서 읽으므로 디스플레이는 allow_remote를 거부합니다.

뷰어 조작

패널은 확대, 이동, 십자선 하나를 공유하며, 확대 단계는 1×에서 16×까지입니다.

동작효과
컷아웃 위로 포인터 이동모든 패널에서 십자선을 옮기며, 표시창이 적경과 적위(60진법과 도), 원본 이미지의 FITS 픽셀, 패널을 보여 줍니다
클릭 또는 탭십자선을 고정합니다. 다시 클릭하거나 Escape를 누르면 해제됩니다
+, −, Reset 버튼모든 패널을 함께 확대하거나, 1×로 되돌리고 십자선을 지웁니다
Ctrl 또는 Cmd와 휠, 또는 트랙패드 핀치포인터 위치에서 확대합니다
확대한 상태에서 드래그모든 패널을 함께 이동합니다
Tab으로 컷아웃에 이동한 뒤 화살표 키십자선을 한 픽셀씩 옮깁니다. **+**와 **−**는 확대하고 0은 초기화합니다

주석 키(판별 설정의 R, B, U)는 컷아웃에 포커스가 있는 동안에도 계속 작동합니다. 화살표 키는 컷아웃에 포커스가 있을 때에만 십자선을 옮기며, 그 밖에서는 평소처럼 항목 사이를 이동합니다. 비어 있는(NaN 또는 BLANK) 픽셀과 이미지 가장자리를 넘어선 컷아웃 부분은 투명하게 체크무늬로 보이며, 패널 아래의 상태 줄이 어느 경우인지 알려 줍니다.

패널은 크기가 같고, 픽셀 스케일이 1% 이내이며, 하늘에서 중심이 반 픽셀 이내일 때 정렬된 것으로 칩니다. 정렬되지 않은 패널에는 안내가 붙고, Potato는 각 패널의 선형 TAN WCS로 하늘 위치를 기준으로 각 패널에 십자선을 놓습니다. 광도 곡선 플롯은 과학 이미지의 시점을 "this image"로 표시하고, 상한은 아래를 향한 빈 삼각형으로 그리며, 플롯 아래 표에 모든 점을 나열합니다.

브라우저로 전달되는 WCS

브라우저는 FITS를 읽지 않습니다. 각 컷아웃에 대해 서버는 PNG의 URL과, 컷아웃의 CRPIX, CRVAL, CD 행렬, 픽셀 스케일, 북쪽과 동쪽 방향, 컷아웃 전체에서 출력 픽셀 16개마다 샘플링한 하늘 위치 격자가 담긴 WCS 설명을 보냅니다. 표시창은 격자를 보간하며 astropy가 읽는 모든 투영을 따릅니다(SIP 왜곡 포함). 격자는 각 하늘 위치를 단위 벡터로 저장하며, 단위 벡터를 보간하면 적경 0/360과 극 근처에서도 표시가 연속적으로 유지됩니다. 선형 키워드는 SIP 항을 제외하며, 정렬되지 않은 패널의 십자선 배치는 선형 키워드를 사용합니다. 은하 좌표 이미지는 축 레이블을 l과 b로, 황도 좌표 이미지는 λ와 β로 표시합니다.

저장되는 답과 내보내기

디스플레이는 아무것도 저장하지 않습니다. 페이지의 각 스킴은 일반 radio 또는 multiselect 문항처럼 주석자의 답을 저장하며, 답은 일반 형식으로 내보내집니다.

bash
python -m potato.export -c config.yaml -f csv -o exports/csv

CSV는 주석자와 항목당 한 행을 가지며 vetting.Real, bogus_reason.Cosmic ray or hot pixel처럼 스킴과 레이블마다 열이 있습니다. -f jsonl은 같은 레코드를 JSON 줄로 씁니다. 나중에 숨겨진 트리 문항의 답은 저장된 주석에 남아 있습니다. 분석 전에 앞선 답의 경로를 기준으로 후속 답을 걸러 내세요.

Potato의 합의도 지표는 이 스킴들을 다룹니다. vetting 같은 radio 문항은 일치율, Cohen과 Fleiss의 카파, Krippendorff의 알파를 얻고, bogus_reason 같은 multiselect 문항은 평균 Jaccard와 MASI 거리를 쓰는 Krippendorff의 알파를 얻습니다. 2.13에서 추가된 consensus 내보내기도 radio와 multiselect를 다루며, 내보내기는 각 후보의 득표 비율과 consensus_aggregation 블록의 임계값에 따른 retired 또는 needs_review 상태를 나열합니다. 합의도 지표도 consensus 내보내기도 display_logic을 확인하지 않으며, 숨겨진 문항에 남은 답은 지표와 내보내기에 포함됩니다. num_annotators_per_item은 각 후보를 판별하는 주석자 수로 설정하세요.

예제

bash
python potato/flask_server.py start examples/image/astronomy-real-bogus/config.yaml -p 8000

이 예제에는 합성 후보 네 개가 있습니다. 원반 은하의 초신성, 차분 쌍극자, 우주선, 모은하 없는 점광원입니다. 각 후보는 1″/픽셀의 TAN WCS 하나를 쓰는 96 × 96 FITS 이미지 세 장과 광도 곡선을 가집니다. 네 번째 후보의 이미지는 gzip으로 압축되어 있습니다. 같은 폴더의 generate_data.py가 파일을 다시 씁니다.

코딩 에이전트로 연구 설정하기

potato-skill 1.2.0은 Potato 2.13.1을 대상으로 하며 fits_cutout 디스플레이를 이름으로 압니다. 이 스킬은 연구 설계 측면을 안내합니다. 주석자에게 무엇을 물을지, 후보당 몇 명의 주석자가 판별할지, 훈련과 주의 점검, 내보내기가 여기에 포함됩니다. 이 스킬은 아직 FITS 항목 형식, 디스플레이 옵션, astro 엑스트라를 문서화하지 않습니다. potato-skill을 설치하고 에이전트에게 연구를 설명한 뒤, 형식과 옵션은 이 페이지의 Markdown 사본을 가리켜 알려 주세요. Markdown 사본은 https://www.potatoannotator.com/docs/annotation-types/astronomy.md에 있습니다.

더 읽을거리

구현 세부 사항은 소스 문서를 참고하세요.