I have pushed the code. I found two linearizers in linearize.py, LinearizeSquare, and LinearizeLookupTable. Question: do we need to implement both in this code? It seems that LinearizeSquared was written for a specific case (Subaru); I would think that this case and other general cases could be covered by the table.
In any case, LinearizeSquared requires a coefficient c0, which we agreed would be given by c0 = -k2/k1^2 for a fit of the form "mean_signal = k0 + k1*time + k2*time^2" (Question: should k0 be set to zero?). This is implemented at the top of “calculateLinearityResidualAndLinearizers”.
The “c0” coefficient per amplifier is saved for the moment as a dictionary in the output PhotonTransferCurveDataset.
LinearizeLookupTable is a mapping from ADU values to the corrections that should be added to those values. The array should have nrows = number of amplifiers and ncolumns=range of ADU values. An example of converting DECam linearity tables is in https://github.com/lsst/obs_decam/blob/master/decam/makeLinearizer.py, where the range of ADU’s goes up to 2^16. In this case, I have set the maximum size of the ADU range to 2^18. For the moment, in order to populate the array with the corrections, I first fit an n-degree polynomial to the "mean_signal vs time curve" (new parameter: self.config.polynomialFitDegreeNl). I use the linear part of that polynomial to obtain a tMax where the linear signal is ADUMax = 2^18 ADU. Then evaluate the linear part of the polynomial at the range of times [0, tMax] (“signalIdeal”) and the full polynomial (“signalUncorrected”). The difference between the two is the correction for the table. All of this is per amplifier, and it is also in the function “calculateLinearityResidualAndLinearizers”.