melix / astro4j

Astronomy libraries for Java
Apache License 2.0
28 stars 5 forks source link

Banding: rounding error, not slit issue? #405

Open vnp85 opened 1 month ago

vnp85 commented 1 month ago

Using my Sodium images, I extracted two adjacent pixel offsets, separated by 0.5 pixels. The result is a reversal of the banding as shown in the pictures. Hence, my working hypothesis regarding both INTI and JSol'Ex is that at least some of the banding is a result not of the slit but of the disk-to-pixel mapping, falling sometimes towards the edge of the spectral line. This issue may then be exacerbated as the mu angle (together with the bending of the line's projection) increases. It could also be a camera readout issue, as the pixel shifts traverse camera scanlines at different x coordinates.


[outputs]
diskM0p5 = rotate_rad(img(-0.5), angleP)
diskM1p0 = rotate_rad(img(-1), angleP)
diskM1p5 = rotate_rad(img(-1.5), angleP)

diskP0p5 = rotate_rad(img(0.5), angleP)
diskP1p0 = rotate_rad(img(1), angleP)
diskP1p5 = rotate_rad(img(1.5), angleP)

diskM0p5LS = linear_stretch(rotate_rad(img(-0.5), angleP))
diskM1p0LS = linear_stretch(rotate_rad(img(-1), angleP))
diskM1p5LS = linear_stretch(rotate_rad(img(-1.5), angleP))

diskP0p5LS = linear_stretch(rotate_rad(img(0.5), angleP))
diskP1p0LS = linear_stretch(rotate_rad(img(1), angleP))
diskP1p5LS = linear_stretch(rotate_rad(img(1.5), angleP))

From M1p0LS and M1p5LS we have the following two frames, which shows the banding "blinking" ie getting reversed:

2024-08-07-0956_5-Sun-NaD2-nantong_20240807_diskM1p5LS_pipp

vnp85 commented 1 month ago

If the clouds don't roll in, I'll try to recreate the effect today.

melix commented 1 month ago

I'm curious to see if you find out something. Both JSol'Ex and INTI (as far as I understood) use linear interpolation for reconstruction, so there shouldn't be rounding errors causing this :thinking:

vnp85 commented 1 month ago

I'm thinking how a really narrow band, bent, gets distributed across the pixel grid, and how its value is recovered from the matrix. And how subpixels are being handled. Something along this classic example (with the spectral line being aliased):

image

melix commented 1 month ago

That's a good hint. A bilinear interpolation might be better to handle this.

vnp85 commented 1 month ago

I think another good hint is that the smallest banding produces the lowest frequency of banding, the arc

Banding frequency is the lowest where the spectral line is the most horizontal

image

melix commented 1 month ago

how comfortable are you with the idea of building JSol'Ex from a branch?

vnp85 commented 1 month ago

how comfortable are you with the idea of building JSol'Ex from a branch?

at the moment, not much, as there are about ~ten~ six years between me and the last time I built something java. I'd probably need a lot of handholding to onboard and get stuff installed till I can hello-world a JSol'Ex compilation.

melix commented 1 month ago

Shouldn't involve much more than:

  1. Install https://www.graalvm.org/release-notes/JDK_21/
  2. clone JSol'Ex, checkout the cc/issue-405 branch
  3. execute ./gradlew :jsolex:run

(if using windows that would be gradlew.bat :jsolex:run)

and give the potential fix a try. If you don't feel comfortable I could merge the PR and rollback if it doesn't help.

vnp85 commented 1 month ago

Thank you, I'll try.

melix commented 1 month ago

(you may have to also set the JAVA_HOME environment variable to the JDK 21 GraalVM install if not done automatically, not sure what it does under Windows)

vnp85 commented 1 month ago

Am I on the right track here? No

Just reading the source code at the moment. This sure looks like something that "bridges" together values that, in a way, I think, would require something more like a point spread function to correct for the spectral line being divided up onto multiple pixels, and the surrounding "lines" bleeding into the pixel shift of interest.

image

vnp85 commented 1 month ago

No, this is not it.

It should be this guy

    private double bilinearInterpolation(double x, double y, boolean mark) {
vnp85 commented 1 month ago

Thinking aloud: I think a point spread function is needed, as the bending smears the spectral line info into multiple pixels, and averaging them is in fact averaging values that are already an average of the spectral line and the surrounding continuum

melix commented 1 month ago

Well this is what the (optional) deconvolution is correcting. Taking a PSF into consideration during reconstruction is IMHO way too complicated.

vnp85 commented 1 month ago

Still thinking aloud. A local slope should give the amount by which to perform a vertical-only deconvolution.

In fact I think this is a good way to show what's happening with the spectral line, when it gets projected onto the sensor: it mixes up with the surrounding continuum. The phenomenon is aggravated by taking, again, into account, the adjacent pixels, while interpolating when locating the pixelshift. The error is masked when the line is wide enough and the curve is small enough -- or considered slit-caused banding when in fact it is not.

https://en.wikipedia.org/wiki/Xiaolin_Wu%27s_line_algorithm

vnp85 commented 4 weeks ago

Still thinking how to address this issue. These Sodium D2 images are too nice to be left out of the repertoire.

image