I found the following to work well. It works directly on Bayered gray-scale images, rather than the un-Bayered color images.
A hot pixel is any peak that rides more than 10 MAD above the local median level defined by the nearest 4 pixels of the same Bayer cell pattern. Hence, it looks +/- 2 pixels from the pixel under consideration. Change the threshold with symbol f.
This avoids the deBayering process which smears a hot pixel into adjacent pixels and causes it to lose some of its defining character. In some cases, I want to split the Bayer channels, and not ever deBayer the image.
This is just dying to be parallelized into 4 concurrent streams... But it runs, more or less, acceptably fast in PI.
PixelMath expression:
------------------------
w=width($T)-2;
h=height($T)-2;
x1 = x();
y1 = y();
x0 = iif(x1<2,0,x1-2);
y0 = iif(y1<2,0,y1-2);
x2 = iif(x1>w,w+1,x1+2);
y2 = iif(y1>h,h+1,y1+2);
p11 = pixel($T,x1,y1);
p10 = pixel($T,x1,y0);
p12 = pixel($T,x1,y2);
p01 = pixel($T,x0,y1);
p21 = pixel($T,x2,y1);
pmed = med(p10,p12,p01,p21);
pmad = mdev(p10,p12,p01,p21);
f=10;
iif(p11 > pmed + f*pmad,pmed,p11)
--------------------------
PixelMath Symbols: w, h, x1, y1, x0, x2, y0, y2, p11, p01, p21, p10, p12, pmed, pmad, f