Closed d-perez-1 closed 2 years ago
The "auto" scaling in PYMEAcquire does min-max scaling, but still on a subsampled image (1000 pixels). The whole subsampling thing actually started with PYMEAcquire as the histogram calculation etc ... was slowing down data acquisition. This is probably around 10 years ago though, so might not be as big an issue. The way it's written it would also be fairly easy to calculate the min and max on the full image and still do the histogram on the subsampled data.
Will do a quick check on how long min and max actually take on a typical 4MP sCMOS frame and see if we still need to worry. If they are fast enough, it should be a simple change. I think the histograming was expensive enough however, that it might make sense to still do that on a subset even if we set the scaling using min/max of the full frame.
As to actually detecting saturation, there have been various thoughts in the past about, e.g., turning the histogram red if saturation is detected, (could also look into using an overflow LUT, although this gets complex when the scaling is not maxed out). There is also some saturation checking code (which now seems to be commented out, although is potentially activated in specific init scripts) which automatically turned EMCCD gain down if saturation was detected, and a corresponding camera property SaturationThreshold
(which is effectively the bit depth of the camera).
Timing results (4MP uint16 camera frame, mac M1):
.min()
: 3.8 ms
.max()
: 3.8 ms
np.histogram(...)
: 183 ms
With a display refresh rate of 10Hz (at higher acquisition rates, intervening frames get streamed without ever being shown), everything involved with displaying a frame / display scaling etc must take less than 100 ms (ideally less than around 50ms to let the rest of the GUI do it's thing). In addition to any autoscaling there is also a significant cost involved in doing the LUT transformation and actually displaying the data. Based on this, the full histogram is definitely out. Min-max scaling on the full frame might just be possible, but would still represent a decent fraction of our 50ms window.
Any thoughts on exposing some configuration options, David? I think an expandable menu to e.g. select which auto mode you are using, whether you're subsampling the hist, your LUT, etc. would be really nice.
At the moment I find myself typing pa.currentFrame.max() in the shell when an overflow LUT with camera-based (ADO to saturation) bounds is exactly what I want on one of my cameras - would be more convenient.
I know some folks are acquiring rather slowly (e.g. slower than the 10 Hz display refresh) - if you are acquiring at 0.5 Hz, maybe you'd rather have the full histogram and additionally don't need a display refresh rate faster than a couple Hz?
Thanks for doing these tests @David-Baddeley , and for raising something that's also been bugging me, @d-perez-1
I'm leaning pretty strongly towards making min-max on the whole frame the default as the benefit from having decent saturation detection is really significant. Would argue for leaving the histogram subsampled though. Will do a quick test on an older computer to see if we need to make the current behaviour available as a PYME.config
option. I'd be reluctant to write too much extra GUI stuff as it's time consuming and adds to the clutter on what is already a pretty cluttered interface. The one possible exception here is allowing the LUT to be set without using the command line.
Unresolved questions:
More timing info (Intel i7-3930K, 4Mp sCMOS frame):
.min()
: 13.5 ms
.max()
: 10 ms
This machine is probably indicative of / at the slower end of the generation still commonly used for data acquisition. At these timings it's getting close to 50% of our window, so probably problematic from a performance perspective. I was really hoping the difference would be less and I could just switch the default behaviour.
Regardless of default behavior, it would be great to have on option to turn these sorts of things on/off. My use is a bit different, typically 10Hz is the fastest I'll image, more often 2 or 3 Hz. I'm also using a 512x512 EMCCD, so I'd have plenty of time for these operations. Maybe keep the default fast but have options for the more complete calculations, and a warning if they're taking a lot of the timing window?
calculating the min and max in the same loop with cython might help
Agreed ...
Mac M1, 4Mp:
c-coded minmax_uint16
: 3.9 ms
(Intel i7-3930K, 4Mp sCMOS frame):
minmax_uint16
: 2.33 ms
Which is actually better than the M1!, and and order of mag better than numpy (which is super wierd - suggests a broken numpy install).
I'm a little reluctant to have lots of different options due to the associated maintenance and documentation cost / overhead. It's better, when possible, to have a good default behaviour. #1271 might be most of what we need to have sensible default behaviour for acquisition:
The one remaining oddity is that clicking the "optimize" button functions identically to the optimize in PYMEImage (uses percentiles rather than min-max, and a different subsampling than the histogram display).
Ran into an issue trying the latest histogram stuff
on Win10
Odd ... can you do a dev install on the main branch? Suggests a broken compiler install of some description, as it seems to be a linker error, rather than anything to do with the code itself ...
David
Actually, on second thoughts the error is fairly clear - do you have any PYME components open? You typically get that error when trying to write to a dll / .pyd that is in use.
Relevant bit of the trace is:
LINK : fatal error LNK1104: cannot open file 'PYME\DSView\LUT\lut.cp37-win_amd64.pyd'
Ahhh, David you caught me right when I realized it - sorry for the miscue, Install works fine. Will test the histogram shortly
@d-perez-1 if this is satisfactory feel free to close the issue - thanks!
Yeah this is perfect, thanks! Sorry new to github not used to all this...
Is your feature request related to a problem? Please describe. I want to be able to quickly tell if I'm saturating the camera on the fly, so I can adjust settings appropriately. Generally more histogram control would also be nice.
Is the histogram calculated the same way as in PYMEImage, i.e. using subset of pixels and not the entire frame? If I have one bright emitter in an otherwise dark field of view, and I check auto on the histogram scaling, then read off the top bound, can I use that to determine if I'm bellow saturation? Or is it possible the brightest pixels aren't included in the the histogram, or auto scaling does not set bounds to max and min?
Describe the solution you'd like An option to use the full frame in the histogram, if this isn't already how its done. Also live scale image to max and min, unless that's what auto already does. Additionally, display some sort of non-obtrusive warning if some pixels are above threshold. Would also be nice to highlight a region and use just that for setting bounds.