astro4j icon indicating copy to clipboard operation
astro4j copied to clipboard

Perpendicular Banding - could be mechanical, could be artifact

Open vnp85 opened this issue 8 months ago • 24 comments

Since the latest 3.0.x versions, I noticed that banding, perpendicular to the scanning direction, shows up on the output images.

While I cannot rule out mechanical issues, this is something quite new to me. I will run the same file through an ancient JSolEx installation, to see where it goes.

These two are adjacent pixel shifts as shown by their filenames.

Image

exagerrated in imagemath

Image

vnp85 avatar Apr 16 '25 15:04 vnp85

It may be a

  • bad / vibrating recording, or
  • a camera readout issue

I tested with 2.11.3 dev version, and the same thing shows up

Image

vnp85 avatar Apr 16 '25 16:04 vnp85

mmm, the edges are suffering from extreme jagging, this is quite surprising. Either you have terrible seeing, or it may be vibrations indeed.

melix avatar Apr 16 '25 16:04 melix

seeingwise, this is actually .... good, given my location :D

vnp85 avatar Apr 16 '25 16:04 vnp85

The bands seem to match the most shifted lines, so I wonder if it could be an artifact of banding correction, if the band size is too small?

melix avatar Apr 16 '25 16:04 melix

the pattern is parallel to the scanning slit, that's why I think it could be either a camera readout thing or a mechanical vibration of perhaps one or two pixels

vnp85 avatar Apr 16 '25 16:04 vnp85

I put in some more screws and metal plates to consolidate the structure, hopefully it is a mechanical issue, and a shaking (by two-three microns) of the camera was the culprit.

vnp85 avatar Apr 17 '25 08:04 vnp85

this now is extra good seeing, by the ersatz-obsi's measure, btw -- my obsi's location sux

Image

vnp85 avatar Apr 17 '25 10:04 vnp85

I inspected videos more closely today, visually scrolling through AS4, with an anchor point dropped onto a thin spectral line, looking for vertical wobble. I saw nothing obvious.

vnp85 avatar Apr 17 '25 21:04 vnp85

I noticed that the pixel shift that you are using when these bands are visible is particularly high (-220). I wonder if this could be related to the polynomial interpolation, if the line observed is particularly thin... Not sure, but I'm running out of ideas.

melix avatar Apr 18 '25 06:04 melix

It happens at -72 also. Here I was trying to dig out He I details, 447.15 nm

Image

Let me upload the video and script. Visually, scrolling through the ser video, it kind of looks OK, all the vertical stripes make it hard to notice anything funny, but the X stays on band

Image

Helium447p15M72_offset = -72
Helium447p15M72_context = 0
Helium447p15M72_step = 1


kontinuum_offset = -54
kontinuum_context = 3
kontinuum_step = 1

kontL = kontinuum_offset - kontinuum_context
kontR = kontinuum_offset + kontinuum_context

Helium447p15M72L = Helium447p15M72_offset - Helium447p15M72_context
Helium447p15M72R = Helium447p15M72_offset + Helium447p15M72_context


lineZero = min(autocrop2(range(-1, 1)))
lineZeroB = fix_banding(lineZero, 100, 50)
lineZeroBL = linear_stretch(lineZeroB)
lineZeroL = linear_stretch(lineZero)
lineZeroBLSQ = linear_stretch(pow(lineZeroB, 2))

[outputs]

Helium447p15M72Raw = min(autocrop2(range(Helium447p15M72L,Helium447p15M72R,Helium447p15M72_step)))
Helium447p15M72RawRot = rotate_rad(linear_stretch(Helium447p15M72Raw), angleP)
kontinuum = avg(autocrop2(range(kontL,kontR,kontinuum_step)))
kontinuumLinearRotated = rotate_rad(linear_stretch(kontinuum), angleP)
Helium447p15M72_delta2 = fix_banding(Helium447p15M72Raw - kontinuum, 100, 50)
Helium447p15M72Log = linear_stretch(log(Helium447p15M72Raw, 2))
Helium447p15M72LogRot = rotate_rad(Helium447p15M72Log, angleP)
Helium447p15M72LogHelium447p15M72Raw = linear_stretch(pow(Helium447p15M72Log + Helium447p15M72Raw, 1.2))
Helium447p15M72Mul = linear_stretch(Helium447p15M72LogHelium447p15M72Raw * Helium447p15M72_delta2)
Helium447p15M72Min = min(Helium447p15M72LogHelium447p15M72Raw, Helium447p15M72Mul)
Helium447p15M72Prime = linear_stretch(Helium447p15M72Log + Helium447p15M72Min + linear_stretch(pow(Helium447p15M72Min,4)) + linear_stretch(pow(Helium447p15M72Raw,2)) + Helium447p15M72LogHelium447p15M72Raw)
Helium447p15M72PrimeRot = rotate_rad(Helium447p15M72Prime, angleP)
Helium447p15M72PrimeRotP = linear_stretch(pow(Helium447p15M72PrimeRot, 1.1))
Helium447p15M72PrimeRotFinalPow1 = linear_stretch(avg(Helium447p15M72PrimeRotP, Helium447p15M72PrimeRot)) 
Helium447p15M72PrimeRotFinalPow2 = linear_stretch(pow(avg(Helium447p15M72PrimeRotP, Helium447p15M72PrimeRot), 2))
Helium447p15M72PrimeRotFinalPow3 = linear_stretch(pow(avg(Helium447p15M72PrimeRotP, Helium447p15M72PrimeRot), 3))
Helium447p15M72PrimeRotFinalPow3PlusLog = linear_stretch(Helium447p15M72LogRot + Helium447p15M72PrimeRotFinalPow3) 
Helium447p15M72PrimeRFP3PlusLog = max(Helium447p15M72PrimeRotFinalPow1, Helium447p15M72PrimeRotFinalPow3PlusLog)
Helium447p15M72PrimeRFP3PlusLogSq = linear_stretch(pow(Helium447p15M72PrimeRFP3PlusLog, 1.4))



lineZeroLRot = rotate_rad(lineZeroL, angleP)
lineZeroBLRot = rotate_rad(lineZeroBL, angleP)
lineZeroBLRotSQ = rotate_rad(lineZeroBLSQ, angleP)

Helium447p15M72_delta2Rot = rotate_rad(linear_stretch(Helium447p15M72_delta2), angleP)
Helium447p15M72MulRot = rotate_rad(Helium447p15M72Mul, angleP)
Helium447p15M72MulNRot = linear_stretch(Helium447p15M72RawRot * Helium447p15M72MulRot)
Helium447p15M72PrimeRFP3PlusLogSqPlusHelium447p15M72MulNRot = linear_stretch(Helium447p15M72RawRot * Helium447p15M72MulRot + Helium447p15M72PrimeRFP3PlusLogSq)

the video is (uploading) at http://narnia.go.ro/seagate2tb.php?mask=2025-04-16

vnp85 avatar Apr 18 '25 06:04 vnp85

Present on the tilt image, so at the moment I have three hypotheses

  • some camera readout issue
  • pixel level vibrations shifting the spectrum red-blue
  • some jsolex artefact

INTI usually fails at obscure lines and such, so even though I usually use it to sanity check, sometimes it's just not worth the effort.

Image

vnp85 avatar Apr 18 '25 07:04 vnp85

at 300% there is maybe some wobble in the spectral line's position, in this particular video. If the clouds are nice, I'll see how it fares with the screws, an ND filter to keep the redout at around 1ms and not below, and see what happens. Maybe it is that simple, it happened to vibrate cause I somehow hit the right length for something to resonate, idk

vnp85 avatar Apr 18 '25 07:04 vnp85

That's an option indeed. You're also using a cooled camera right? If so maybe the fan is causing enough vibration to mess things up.

melix avatar Apr 18 '25 07:04 melix

Everything trivial is accounted for:

  • camera and RA-mount-motor fans stop on scan start (and restart on scan finish)
  • there is ramping to minimize vibrations
  • cables are arranged so they don't pull on anything, not even with there own weight (anchor points)
  • declination backlash is sort-of accounted for, as in tension is left in the gears, hoping it wouldn't dance around in the backlash related no man's land, but that is related to the jagged edges, not the spectrum moving around

I mean as shitty as my location and setup are, I tried to bring out the best of this shitty situation called life.

I tried the video debugger in the 3.0.2 version, a per frame calculation, and it indeed shows a one pixel shift (the d in the ax3 + bx2 + cx + d poly if I get it correctly), around 120-122 for the outer half of the disk, and 121 for the disk center -- there is a reason the average is used.

The pattern is too uniform to not have come from a resonance, either mechanical or digital, but perhaps too uniform to be purely mechanical.

vnp85 avatar Apr 18 '25 07:04 vnp85

It's just a shame that the otherwise decent seeing didn't yield the nice pictures I was hoping for.

I have a suitcase full of SSDs, so for now I kind of have the storage space to put the raws aside and tinker with them later.

Image

vnp85 avatar Apr 18 '25 07:04 vnp85

that's a He I 447.15 filament btw

Image

vnp85 avatar Apr 18 '25 08:04 vnp85

I did the following:

  1. spacially trimmed the ser video in PIPP to exclude the dark spectral line at the bottom
  2. I let JSolex video debugger to crunch the video to obtain a forced poly
  3. I set new values for the helium I was looking for -- same continuum region, same helium line, just approached from closer and from the top
  4. I got this image, way less banding
  5. This doesn't rule out the vibrations, maybe half a pixel makes the difference, but point to a software artefact
Helium447p15M73_offset = 33
Helium447p15M73_context = 0
Helium447p15M73_step = 1


kontinuum_offset = 46
kontinuum_context = 5
kontinuum_step = 1

kontL = kontinuum_offset - kontinuum_context
kontR = kontinuum_offset + kontinuum_context

Helium447p15M73L = Helium447p15M73_offset - Helium447p15M73_context
Helium447p15M73R = Helium447p15M73_offset + Helium447p15M73_context


lineZero = min(autocrop2(range(-1, 1)))
lineZeroB = fix_banding(lineZero, 100, 50)
lineZeroBL = linear_stretch(lineZeroB)
lineZeroL = linear_stretch(lineZero)
lineZeroBLSQ = linear_stretch(pow(lineZeroB, 2))

[outputs]

Helium447p15M73Raw = min(autocrop2(range(Helium447p15M73L,Helium447p15M73R,Helium447p15M73_step)))
Helium447p15M73RawRot = rotate_rad(linear_stretch(Helium447p15M73Raw), angleP)
kontinuum = avg(autocrop2(range(kontL,kontR,kontinuum_step)))
kontinuumLinearRotated = rotate_rad(linear_stretch(kontinuum), angleP)
Helium447p15M73_delta2 = fix_banding(Helium447p15M73Raw - kontinuum, 100, 50)
Helium447p15M73Log = linear_stretch(log(Helium447p15M73Raw, 2))
Helium447p15M73LogRot = rotate_rad(Helium447p15M73Log, angleP)
Helium447p15M73LogHelium447p15M73Raw = linear_stretch(pow(Helium447p15M73Log + Helium447p15M73Raw, 1.2))
Helium447p15M73Mul = linear_stretch(Helium447p15M73LogHelium447p15M73Raw * Helium447p15M73_delta2)
Helium447p15M73Min = min(Helium447p15M73LogHelium447p15M73Raw, Helium447p15M73Mul)
Helium447p15M73Prime = linear_stretch(Helium447p15M73Log + Helium447p15M73Min + linear_stretch(pow(Helium447p15M73Min,4)) + linear_stretch(pow(Helium447p15M73Raw,2)) + Helium447p15M73LogHelium447p15M73Raw)
Helium447p15M73PrimeRot = rotate_rad(Helium447p15M73Prime, angleP)
Helium447p15M73PrimeRotP = linear_stretch(pow(Helium447p15M73PrimeRot, 1.1))
Helium447p15M73PrimeRotFinalPow1 = linear_stretch(avg(Helium447p15M73PrimeRotP, Helium447p15M73PrimeRot)) 
Helium447p15M73PrimeRotFinalPow2 = linear_stretch(pow(avg(Helium447p15M73PrimeRotP, Helium447p15M73PrimeRot), 2))
Helium447p15M73PrimeRotFinalPow3 = linear_stretch(pow(avg(Helium447p15M73PrimeRotP, Helium447p15M73PrimeRot), 3))
Helium447p15M73PrimeRotFinalPow3PlusLog = linear_stretch(Helium447p15M73LogRot + Helium447p15M73PrimeRotFinalPow3) 
Helium447p15M73PrimeRFP3PlusLog = max(Helium447p15M73PrimeRotFinalPow1, Helium447p15M73PrimeRotFinalPow3PlusLog)
Helium447p15M73PrimeRFP3PlusLogSq = linear_stretch(pow(Helium447p15M73PrimeRFP3PlusLog, 1.4))



lineZeroLRot = rotate_rad(lineZeroL, angleP)
lineZeroBLRot = rotate_rad(lineZeroBL, angleP)
lineZeroBLRotSQ = rotate_rad(lineZeroBLSQ, angleP)

Helium447p15M73_delta2Rot = rotate_rad(linear_stretch(Helium447p15M73_delta2), angleP)
Helium447p15M73MulRot = rotate_rad(Helium447p15M73Mul, angleP)
Helium447p15M73MulNRot = linear_stretch(Helium447p15M73RawRot * Helium447p15M73MulRot)
Helium447p15M73PrimeRFP3PlusLogSqPlusHelium447p15M73MulNRot = linear_stretch(Helium447p15M73RawRot * Helium447p15M73MulRot + Helium447p15M73PrimeRFP3PlusLogSq)

Image

Image

vnp85 avatar Apr 18 '25 08:04 vnp85

Makes sense. I think reusing the same polynomial for a line which is far away isn't a good idea. Line detection is itself extremely tricky (you wouldn't believe how much time I spend on tweaking this). Cropping the SER file on the region of interest is reasonable in this case.

melix avatar Apr 18 '25 08:04 melix

I agree with you about cropping to a ROI.

However, what a far away line should do is deviate and go off band, not oscillate.

vnp85 avatar Apr 18 '25 09:04 vnp85

I don't think it oscillates. I think it's an artifact of interpolation (discrete pixels) and rounding which will not work well if the polynomial is not as close as possible to the "real" line.

melix avatar Apr 18 '25 09:04 melix

I noticed something in the raw camera output, when zoomed in and at high gain with very low expo time

I think it is a bias issue, and the perpendicular lines appear when the spectral line, as it curves, passes through the horizontal scanlines affected by this

vnp85 avatar May 02 '25 17:05 vnp85

Oh, that's an interesting finding. Which camera is this?

melix avatar May 02 '25 17:05 melix

ZWO ASI 678MM, with external peltier cooling, sensor kept at 20C

vnp85 avatar May 02 '25 17:05 vnp85

I managed to mitigate the issue by increasing the exposure time, and that by putting a neutral density filter into the light train. At around 1-1.5 ms expo time, the camera performs decently and the stripes are mostly gone

vnp85 avatar May 03 '25 21:05 vnp85