Looking for feedback: Sensor linearity assessor

Hi all. The need to assess the linearity of some new cameras recently came up and I could not immediately find a good tool to help in doing that. It seems that most folks have done this largely by hand using a spreadsheet. SharpCap’s sensor characterization tool does do a linearity assessment, but its findings do not appear to be saved in its JSON output.

Given all that, I decided to create my own CLI tool in Python using astropy, numpy, and matplotlib. The basic premise is to point it at a directory of flat fielding frames from the camera in question, with constant gain+offset but increasing exposure time across them. It then takes the mean of them all and plots them on a graph with a least-squares fit. Deviation of each image below the specified saturation ADU (default: 65000) is displayed with each point, along with the R². It produces a PNG image of the linearity plot. Various bits of info are extracted from the FITS headers and added to the plot to provide context beyond the X/Y axis values. An example:

There are command-line options that permit the user to filter images based on exposure time. If multiple images of the same exposure duration are present, their means are averaged.

I’m interested in feedback concerning the approach and if anything else might be useful. You can find a README containing use instructions here:

https://github.com/daleghent/image-tools/blob/main/README.linearity.md

And the script itself:

https://raw.githubusercontent.com/daleghent/image-tools/refs/heads/main/linearity.py

TIA
/dale

You’re evaluating dark frames (that saturate)?

Keith

Oh dang! I misspoke. I meant flats! I happened to be busy calibrating some images with darks as I wrote that post, so that activity must have leaked into my writing. I’ll correct that.

Hi Dale,

Welcome to the forum!

In general I agree with your approach. I checked linearity of my camera in a very similar way.

The only thing that may worth discussion is

Mean ADUs are averaged together if multiple images of the same exposure time are provided

I would just add any image as a separate data point. If mean ADU varies to much between images of the same exposure, we probably want to catch that.


Regards,
Dmitry

Thank you for taking a look, Dmitry. I also thought about this, but then considered that the images being fed into the script are, usually, made for this specific purpose in a (more or less) controlled environment. So, I would expect that any image with a wildly different mean compared to others in its same exposure time series to be a true reflection of that camera’s particular performance and thus ought to be reflected in the findings.

Dale - I gave it a quick test, Windows 11, Python 3.13, with images from a CCD, not a CMOS camera, and I ran into a snag.
I’ve got a folder “results” in the current directory, and have tried setting -o results and weirdly it is failing to write the file… the path in the final message isn’t making sense to me:
File “C:\Users\Colin\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.13_qbz5n2kfra8p0\LocalCache\local-packages\Python313\site-packages\PIL\Image.py”, line 2591, in save
fp = builtins.open(filename, “w+b”)
FileNotFoundError: [Errno 2] No such file or directory: ‘./results\DL_Imaging_GN/A_ON/A_Normal_Sensor_Linearity_20250411T122340.png’

A quick look at the source, and I see something going on with “camera_safe” but I don’t know what you’re trying to do there. So I just hacked it out to give me a simpler filename.

After the hack, I got a nice straight line plot, as expected, with small deviations, except for the one image at the shortest exposure time.
Since Bias isn’t taken into account, perhaps this is ok.
If I get some more time, I’ll go play with it further and make some real input data.