Source code for sunkit_image.stara

import numpy as np
import skimage
from skimage.filters import median
from skimage.morphology import disk, white_tophat
from skimage.util import invert

import astropy.units as u

import sunpy.map

if skimage.__version__ < "0.25.0":
    # Need to account for https://github.com/scikit-image/scikit-image/pull/7566/files
    from skimage.morphology import square
else:
    from skimage.morphology import footprint_rectangle

__all__ = ["stara"]


[docs] @u.quantity_input def stara( smap, circle_radius: u.deg = 100 * u.arcsec, median_box: u.deg = 10 * u.arcsec, threshold=6000, limb_filter: u.percent = None, ): """ A method for automatically detecting sunspots in white-light data using morphological operations. Parameters ---------- smap : `sunpy.map.GenericMap` The map to apply the algorithm to. circle_radius : `astropy.units.Quantity`, optional The angular size of the structuring element used in the `skimage.morphology.white_tophat`. This is the maximum radius of detected features. By default, this is set to 100 arcseconds. median_box : `astropy.units.Quantity`, optional The size of the structuring element for the median filter, features smaller than this will be averaged out. The default value is 10 arcseconds. threshold : `int`, optional The threshold used for detection, this will be subject to detector degradation. The default value of 6000, is a reasonable value for HMI continuum images. limb_filter : `astropy.units.Quantity`, optional If set, ignore features close to the limb within a percentage of the radius of the disk. A value of 10% generally filters out false detections around the limb with HMI continuum images. Returns ------- `numpy.ndarray` A 2D boolean array of the same shape as the input solar map. Each element in the array represents a pixel in the solar map, and its value is `True` if the corresponding pixel is identified as part of a sunspot (based on the specified threshold), and `False` otherwise. References ---------- * Fraser Watson and Fletcher Lyndsay "Automated sunspot detection and the evolution of sunspot magnetic fields during solar cycle 23" Proceedings of the International Astronomical Union, vol. 6, no. S273, pp. 51-55, 2010. (doi:10.1017/S1743921311014992)[https://doi.org/10.1017/S1743921311014992] """ data = invert(smap.data) # Filter things that are close to limb to reduce false detections if limb_filter is not None: hpc_coords = sunpy.map.all_coordinates_from_map(smap) r = np.sqrt(hpc_coords.Tx**2 + hpc_coords.Ty**2) / (smap.rsun_obs - smap.rsun_obs * limb_filter) data[r > 1] = np.nan # Median filter to remove detections based on hot pixels m_pix = int((median_box / smap.scale[0]).to_value(u.pix)) if skimage.__version__ < "0.25.0": function = square(m_pix) else: function = footprint_rectangle((m_pix, m_pix)) med = median(data, function, behavior="ndimage") # Construct the pixel structuring element c_pix = int((circle_radius / smap.scale[0]).to_value(u.pix)) circle = disk(c_pix / 2) finite = white_tophat(med, circle) finite[np.isnan(finite)] = 0 return finite > threshold