Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Sunspots, groups and the Wolf number

Helia can find the sunspots on a white-light stack, group them, count them and measure their areas (#57). It gives:

  • the number of groups g and of individual spots s;
  • the relative Wolf number R = k (10 g + s), with the observer factor k you set (1 is the raw count);
  • each spot's area in millionths of the solar hemisphere (MSH), as seen and corrected for foreshortening, and its umbra alone;
  • each spot's and group's position on the Sun: latitude, central meridian distance and, when the capture has a time, Carrington longitude;
  • an overlay picture: the flattened disc with the penumbra (yellow) and umbra (red) outlined, the limb (cyan), the group numbers (green) and an arrow to solar north.

It is for white light, with the whole disc in the frame. In H-alpha or calcium the contrast of a spot is different and the filaments and plage give false spots; the thresholds below mean nothing there.

The Stack step after a stack with the sunspot search on

Using it

$ helia sunspots stack.tif --date 2025-09-17T16:14:00 --csv spots.csv --json spots.json --overlay spots.png
file:        stack.tif
image:       1080 x 1920
disc:        centre (554.5, 980.8), radius 401.7 px
time:        2025-09-17T16:14:00.000 UTC
7 groups, 14 spots; Wolf number 84.0 (k = 1)
area 1218 millionths of the hemisphere corrected (795 as seen), umbra 380
P 24.49, B0 7.16, L0 247.82 degrees
group 1: 1 spot, 1 umbra, lat +33, L 174, 326 MSH (98 as seen)
...
spot group    x     y    lat   cmd   lon    mu umbrae  as seen corrected umbra (MSH)
   1     1   229   778 +32.5 -73.8 174.0  0.30      1       98       326         114
  • On a stack as it is made: helia stack capture.ser -o sun.fits --sunspots (white-light captures; the time comes from the capture). The table, JSON and overlay are saved beside the output as sun-sunspots.csv, .json and .png, the summary is printed, and a FITS output carries it in its header.
  • On any stacked image: helia sunspots image.tif. The time comes from --date (UTC, 2025-09-17T16:14:00), from the frame stamps of the capture the image was made from (--capture file.ser), or from the DATE-AVG or DATE-OBS card of a FITS file.
  • In the API: "sunspots": {} in a job's config; see The API.
  • In the app: the Sunspots chips in the Stack step. After the stack the step shows the count, Show overlay puts the overlay in the viewer, and Save table and overlay writes the CSV, JSON and PNG.

How it works

  1. Flatten. The limb darkening is fitted and divided out (Sharpening), so one threshold means the same thing at the centre and near the limb. The disc centre and radius come from the same fit.
  2. Quiet level. The image is smoothed a little (a Gaussian of about a pixel per 400 px of disc radius). The quiet-Sun level at each pixel is the mean of the surrounding disc (a box 40% of the radius across) with the dark and the bright pixels left out, found in four passes that tighten from 60% to 93%. A gradient the flattening cannot remove (a vignette, a thin cloud, a one-sided filter) is then not read as spot. "Dark" below means a share of this local level, above the sky.
  3. Penumbra and umbra. A pixel darker than the penumbra threshold (0.88 by default) is spot; a spot's pixels darker than the umbra threshold (0.55) are its umbra. 0.88 and 0.55 are the middle of a typical penumbra (0.75 of the photosphere) against the photosphere and of an umbra (0.3) against the penumbra, because a blurred edge sits half way. They are the options --sunspot-penumbra and --sunspot-umbra.
  4. Spots. Connected regions (eight-neighbour) of at least 4 pixels and 2 MSH are spots. Each umbra of 2 pixels or more counts as one individual spot for the Wolf number, and a region with no umbra (a pore) counts as one.
  5. Groups. Two spots whose edges are closer than 3 degrees on the Sun (--sunspot-group-gap) are in one group, and the grouping is transitive. The edge of a spot is taken as a circle of the spot's own corrected area about its centroid. This is not the Zurich classification, and the Wolf number depends on how groups are drawn: it is a relative figure.
  6. Foreshortening. A pixel at a distance u from the disc centre, in radii, is 1 / mu of its picture area on the Sun, with mu = sqrt(1 - u^2). Helia sums 1 / mu over every pixel of the spot, so a spot that spans a lot of the disc is treated correctly. The hemisphere is 2 pi R^2 pixels, so one MSH is R^2 pi / 500000 pixels (1.6 pixels at a radius of 500). The corrected area is what the spot really covers; "as seen" is what it covers in the picture.
  7. Position. The pixel position, the disc centre and radius and the orientation give a point on the disc; with B0 (the tilt of the Sun's axis towards us) that is a heliographic latitude and a longitude from the central meridian. With the capture time L0 makes it a Carrington longitude.

Spots nearer the limb than 97% of the radius are not measured: the limb fit and the flattening are least certain there, and a pixel is foreshortened by more than four to one. A dark region larger than 6000 MSH (the largest groups ever recorded are about that size, --sunspot-max-area) is left out with a note: it is a cloud, a vignette or an uneven flat, not a spot.

Time, orientation and the Sun's axis

P (position angle of the Sun's axis), B0 and L0 come from the Sun's position at the capture time, from the low-precision series of Meeus, Astronomical Algorithms, chapters 25 and 29 (good to about 0.01 degree; checked against the book's worked example). The time is the mean of the frame stamps of the frames that were stacked (SER files have them), else the header's start time. Without a time B0 is taken as 0 and longitudes are measured from the central meridian only; the report says so.

Helia does not know how your camera sits on the sky. By default solar north is taken to be up. If it is not:

  • --north-angle DEG turns solar north counter-clockwise from the top of the image (API north_angle_deg);
  • --celestial-north-up is for an equatorial mount without a flip: solar north is then P degrees counter-clockwise from the top (the Sun's axis is P east of celestial north), and P is taken from the capture time;
  • --mirror is for a mirror image (a diagonal without a flip, an odd number of reflections).

A wrong orientation does not change the counts or the areas, only latitude and longitude, and so the foreshortening is unaffected too.

The output

The CSV has one row per spot:

ColumnMeaning
spot, groupNumbers from 1; groups are numbered largest first
x_px, y_pxCentroid, pixels, top row 0
lat_degHeliographic latitude, degrees north
cmd_degCentral meridian distance, degrees, west positive
lon_degCarrington longitude; empty without a capture time
muCosine of the angle from the disc centre at the centroid
umbraeIndividual spots in the region (at least 1)
umbra_px, penumbra_pxPixels of umbra, and of penumbra without it
projected_mshWhole spot as seen, MSH
area_mshWhole spot, corrected for foreshortening, MSH
umbra_mshUmbra, corrected, MSH
darkestDarkest smoothed intensity inside, a share of the quiet disc

The JSON adds the groups, the disc, the time, P, B0, L0, the thresholds and the notes. The FITS header gets SPOTNGRP, SPOTNSPT, SPOTWOLF, SPOTK, SPOTAREA (corrected), SPOTPROJ, SPOTUMBR, SPOTTHRU, SPOTTHRP, SPOTP, and the SOLARNET observer coordinates CRLT_OBS (B0) and CRLN_OBS (L0).

What was measured

Known answers. The unit tests render a limb-darkened disc with spots of known size and heliographic position (including ones near the limb), blurred and noisy, and check what Helia recovers: the counts are exact for isolated spots, a spot's corrected area is within 5% of the truth and its umbra within 15% (the umbra of the smallest, 8 pixels across, is the least sure), the latitude and central meridian distance within 0.5 degree, a near-limb spot is seen at under 0.6 of its corrected area, groups form and split at the separation asked for, two umbrae in one penumbra count as two spots, and a clean disc has none. The ephemeris matches Meeus's worked example for 1992 October 13 (P 26.27, B0 5.99, L0 238.63).

A real white-light disc. A phone video of the Sun on 2025-09-17 (2025-09-17-161400-Solar.mp4, 1080 by 1920, disc radius 402 px) stacked at 6, 12, 25 and 50% of the frames gives 7 groups and 14, 14, 13 and 13 spots: Wolf number 84, 84, 83 and 83. It has a dark region at the bottom of the disc (a gradient across the frame, 37 600 MSH) which is left out by the size limit and which would otherwise have been the biggest "group". The spot areas are 17 to 326 MSH, and a group at central meridian distance +1.7 degrees is seen at the same size as it is corrected. There is no reference count for that day among the captures, so the Wolf number is not compared with the official series, which needs a calibrated k for each observer and instrument.

Limits

  • The count depends on resolution and seeing: small spots and pores are missed, and k for your telescope is something to calibrate against the published series.
  • White light only.
  • The group definition is a distance, not the Zurich classification.
  • The positions assume the image is orientated as you say (see above) and the limb fit is a circle, so a clipped or out-of-round disc gives a worse position.
  • The Sun's ephemeris is a series good to about 0.01 degree, ignoring the minute between UT and terrestrial time.

Reference: every option

SettingCLIAPI (config.sunspots)AppRangeDefault
Find sunspotshelia stack --sunspots; helia sunspots IMAGEsunspots (an object; {} for the defaults)Stack step, Sunspots: Off / Findon or offoff
Umbra threshold--sunspot-umbraumbranot offeredabove 0 and below the penumbra0.55
Penumbra threshold--sunspot-penumbrapenumbranot offeredabove the umbra, below 10.88
Smallest spot (MSH)--sunspot-min-areamin_areanot offered0 to max_area2
Largest spot (MSH)--sunspot-max-areamax_areanot offeredabove min_area6000
Group gap (degrees)--sunspot-group-gapgroup_gap_degnot offered0 to 903
Observer factor k--wolf-kwolf_kObserver factor k (0.1 to 5)above 01
North angle (degrees, counter-clockwise from the top)--north-anglenorth_angle_degnot offeredany0
Celestial north is up--celestial-north-upcelestial_north_upCelestial north is upon or offoff
Mirror image--mirrormirrornot offeredon or offoff
Time of the image (UTC)helia sunspots --date TIME or --capture FILE.ser (a FITS file's DATE-AVG or DATE-OBS otherwise); in stack the capture'sthe capture'sthe capture'sYYYY-MM-DDThh:mm:ssnone
Outputs--csv FILE, --json FILE, --overlay FILE; stack writes NAME-sunspots.csv, .json, .pngsummary.sunspots, GET /jobs/{id}/sunspots.csv, GET /jobs/{id}/sunspots.pngShow overlay, Save table and overlay

Thresholds are shares of the quiet disc's brightness above the sky after the limb darkening is flattened. A value outside its range is 422 invalid_config in the API and an error on the command line.