Index: trunk/ppImage/src/Makefile.am
===================================================================
--- trunk/ppImage/src/Makefile.am	(revision 42293)
+++ trunk/ppImage/src/Makefile.am	(revision 42340)
@@ -23,4 +23,5 @@
 	ppImageDetrendRecord.c \
 	ppImageDetrendNonLinear.c \
+	ppImageDetrendNewNonLinear.c \
 	ppImageDetrendFringe.c \
 	ppImageDetrendFree.c \
Index: trunk/ppImage/src/ppImage.h
===================================================================
--- trunk/ppImage/src/ppImage.h	(revision 42293)
+++ trunk/ppImage/src/ppImage.h	(revision 42340)
@@ -35,4 +35,5 @@
     bool doAuxMask;                     // apply auxillary mask
     bool doNonLin;                      // Non-linearity correction
+    bool doNewNonLin;                   // Non-linearity correction
     bool doOverscan;                    // Overscan subtraction
     bool doNoiseMap;                    // Bias subtraction
@@ -175,4 +176,6 @@
 bool ppImageDetrendBias(pmReadout *inputReadout, pmReadout *bias, pmReadout *dark, ppImageOptions *options);
 
+bool ppImageDetrendNewNonLinear(pmReadout *input, pmFPAview *linearity, pmConfig *config);
+
 bool ppImageDetrendNonLinear(pmReadout *input, pmFPAview *linearity, pmConfig *config);
 bool ppImageDetrendNonLinearLookup(pmReadout *input, psMetadataItem *dataItem);
Index: trunk/ppImage/src/ppImageArguments.c
===================================================================
--- trunk/ppImage/src/ppImageArguments.c	(revision 42293)
+++ trunk/ppImage/src/ppImageArguments.c	(revision 42340)
@@ -25,4 +25,5 @@
     fprintf(stderr, "\t-fringe/-fringelist: Fringe image and data.\n");
     fprintf(stderr, "\t-linearity/-linearlist: linearity correction file.\n");
+    fprintf(stderr, "\t-newnonlin/-newnonlinlist: non-linearity correction file (v 2023.01).\n");
     fprintf(stderr, "\n");
     exit (2);
@@ -116,4 +117,5 @@
     pmConfigFileSetsMD (config->arguments, &argc, argv, "FRINGE", "-fringe", "-fringelist");
     pmConfigFileSetsMD (config->arguments, &argc, argv, "LINEARITY", "-linearity", "-linearlist");
+    pmConfigFileSetsMD (config->arguments, &argc, argv, "NEWNONLIN", "-newnonlin", "-newnonlinlist");
     pmConfigFileSetsMD (config->arguments, &argc, argv, "PATTERN.ROW.AMP", "-pattern-row-amplitude", "-not-defined");
 
Index: trunk/ppImage/src/ppImageDetrendFree.c
===================================================================
--- trunk/ppImage/src/ppImageDetrendFree.c	(revision 42293)
+++ trunk/ppImage/src/ppImageDetrendFree.c	(revision 42340)
@@ -14,4 +14,5 @@
     "PPIMAGE.SHUTTER",
     "PPIMAGE.LINEARITY",
+    "PPIMAGE.NEWNONLIN",
     NULL
 };
Index: trunk/ppImage/src/ppImageDetrendNewNonLinear.c
===================================================================
--- trunk/ppImage/src/ppImageDetrendNewNonLinear.c	(revision 42340)
+++ trunk/ppImage/src/ppImageDetrendNewNonLinear.c	(revision 42340)
@@ -0,0 +1,42 @@
+#include "ppImage.h"
+
+bool ppImageDetrendNewNonLinear(pmReadout *input, pmFPAview *detview, pmConfig  *config) {
+
+    bool status;
+
+    pmFPAfile *linearity_file = psMetadataLookupPtr(&status, config->files, "PPIMAGE.NEWNONLIN");
+    psFits *linearity_fits = linearity_file->fits;
+
+    char *extname = psMetadataLookupStr(&status, input->parent->concepts, "CELL.NAME");
+    if (!extname) {
+	psError(PS_ERR_IO, false, "missing CELL.NAME in concepts");
+	return(false);
+    }
+
+    // if pmFPAfile has been loaded (by ppImageDefineFile in ppImageParseCamera), then
+    // the file corresponding to the current chip is found and opened
+    // NOTE: if the extname is missing, we skip the correction
+    if (!psFitsMoveExtName(linearity_fits, extname)) {
+        psLogMsg ("ppImageDetrendNewNonLinear", 4, "Unable to move to non-linearity (v2023) table %s, skipping", extname);
+	return(true);
+    }
+  
+    psArray *table = psFitsReadTable(linearity_fits);
+    if (!table) {
+	psError(PS_ERR_IO, false, "Unable to read non-linearity table.\n");
+	return(false);
+    }
+
+    if (!pmNewNonLinearityApply(input,table)) {
+	psError(PS_ERR_UNKNOWN, false, "Unable to apply non-linearity corrections.\n");
+	psFree (table);
+	return(false);
+    }	    
+    psFree (table);
+
+    return true;
+}
+
+// the new non-linearity correction is a set of splines, one per cell, with the
+// xKnots equal to the log10(DN) in the pixel, and the spline value at a point
+// equal to a fractional multiplier (i.e., 1 + dF)
Index: trunk/ppImage/src/ppImageDetrendNonLinear.c
===================================================================
--- trunk/ppImage/src/ppImageDetrendNonLinear.c	(revision 42293)
+++ trunk/ppImage/src/ppImageDetrendNonLinear.c	(revision 42340)
@@ -1,6 +1,2 @@
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
 #include "ppImage.h"
 
Index: trunk/ppImage/src/ppImageDetrendReadout.c
===================================================================
--- trunk/ppImage/src/ppImageDetrendReadout.c	(revision 42293)
+++ trunk/ppImage/src/ppImageDetrendReadout.c	(revision 42340)
@@ -124,4 +124,13 @@
       // psLogMsg ("ppImage", 6, "nonlinear correction: %f sec\n", psTimerMark ("detrend.readout"));
     }
+    // New Non-linearity correction (exclusive of the above)
+    if (options->doNewNonLin) {
+      if (!ppImageDetrendNewNonLinear(input, detview, config)) {
+	psError(PS_ERR_UNKNOWN, false, "Unable to correct Non-Linearity with new version (2023)");
+	psFree(detview);
+	return(false);
+      }
+      // psLogMsg ("ppImage", 6, "nonlinear correction: %f sec\n", psTimerMark ("detrend.readout"));
+    }
 
     // set up the dark and bias
@@ -188,39 +197,4 @@
             psImageUnbin (noiseImage, noiseMap->image, binning);
             psFree (binning);
-	    // Stolen from pmSkySubtract.c
-	    // CZW: Unneeded, as psImageUnbin does the bilinear interpolation?  It still looks blocky. 
-/* 	    psMetadata *recipe = psMetadataLookupMetadata(NULL, config->recipes, RECIPE_NAME); // Recipe */
-/* 	    psAssert(recipe, "Should be there!"); */
-
-/* 	    psS32 xBinFactor = psMetadataLookupS32(NULL,recipe,"NOISE.XBIN"); */
-/* 	    psS32 yBinFactor = psMetadataLookupS32(NULL,recipe,"NOISE.YBIN"); */
-/* 	    psImageInterpolateOptions *interp = psImageInterpolateOptionsAlloc(PS_INTERPOLATE_BILINEAR, */
-/* 									       noiseMap->image, */
-/* 									       NULL, NULL, */
-/* 									       0, 0.0, 0.0, 0, 0, 0.0); */
-/* 	    for (psS32 row = 0; row < input->image->numRows; row++) { */
-/* 	      for (psS32 col = 0; col < input->image->numCols; col++) { */
-/* 		// We calculate the F32 value of the pixel coordinates in the */
-/* 		// binned image and then use a pixel interpolation routine to */
-/* 		// determine the value of the pixel at that location. */
-/* 		psF32 binRowF64 = ((psF32) row) / ((psF32) yBinFactor); */
-/* 		psF32 binColF64 = ((psF32) col) / ((psF32) xBinFactor); */
-/* 		// We add 0.5 to the pixel locations since the pixel */
-/* 		// interpolation routine defines the location of pixel */
-/* 		// (i, j) as (i+0.5, j+0.5). */
-/* 		binRowF64+= 0.5; */
-/* 		binColF64+= 0.5; */
-
-/* 		double binPixel; */
-/* 		if (!psImagePixelInterpolate(&binPixel, NULL, NULL, binColF64, binRowF64, interp)) { */
-/* 		  psError(PS_ERR_UNKNOWN, false, "Unable to interpolate image."); */
-/* 		  psFree(interp); */
-/* 		  psFree(noiseImage); */
-/* 		  return NULL; */
-/* 		} */
-/* 		noiseImage->data.F32[row][col] = binPixel; */
-/* 	      } */
-/* 	    } */
-/* 	    psFree(interp); */
         }
 
Index: trunk/ppImage/src/ppImageDetrendRecord.c
===================================================================
--- trunk/ppImage/src/ppImageDetrendRecord.c	(revision 42293)
+++ trunk/ppImage/src/ppImageDetrendRecord.c	(revision 42340)
@@ -75,5 +75,6 @@
     detrendRecord(options->doFringe,   detrend, config, view, "PPIMAGE.FRINGE",   "DETREND.FRINGE",   "Fringe filename");
 
-    detrendRecord(options->doNonLin,   detrend, config, view, "PPIMAGE.LINEARITY","DETREND.NONLIN",   "Non-linearity table filename");
+    detrendRecord(options->doNonLin,    detrend, config, view, "PPIMAGE.LINEARITY","DETREND.NONLIN",   "Non-linearity table filename");
+    detrendRecord(options->doNewNonLin, detrend, config, view, "PPIMAGE.NEWNONLIN","DETREND.NEWNONLIN","Non-linearity table filename (v2023)");
 
     detrendRecord(options->doDark & options->useVideoDark, detrend, config, view, "PPIMAGE.VIDEODARK", "DETREND.VIDEODARK", "VideoDark filename");
Index: trunk/ppImage/src/ppImageOptions.c
===================================================================
--- trunk/ppImage/src/ppImageOptions.c	(revision 42293)
+++ trunk/ppImage/src/ppImageOptions.c	(revision 42340)
@@ -28,4 +28,5 @@
     options->doAuxMask       = false;   // apply auxillary mask
     options->doNonLin        = false;   // Non-linearity correction
+    options->doNewNonLin     = false;   // New Non-linearity correction (v2023)
     options->doOverscan      = false;   // Overscan subtraction
     options->doNoiseMap      = false;   // Apply Read Noise Map
@@ -175,4 +176,12 @@
     // XXX PAP: The overscan stuff needs to be updated following the reworked API
 
+    // New Non-linearity (v 2023) recipe options
+    // non-linearity corrections are loaded from a file defined in the detrend system or on the command-line
+    if (psMetadataLookupBool(NULL, recipe, "NEWNONLIN")) {
+        options->doNewNonLin = true;
+    }
+
+    // XXX PAP: The overscan stuff needs to be updated following the reworked API
+
     // Overscan recipe options
     // XXX EAM : we should abort on invalid options. default options?
Index: trunk/ppImage/src/ppImageParseCamera.c
===================================================================
--- trunk/ppImage/src/ppImageParseCamera.c	(revision 42293)
+++ trunk/ppImage/src/ppImageParseCamera.c	(revision 42340)
@@ -104,10 +104,21 @@
 
     if (options->doNonLin) {
-      if (!ppImageDefineFile(config, input->fpa, "PPIMAGE.LINEARITY", "LINEARITY",
-			     PM_FPA_FILE_LINEARITY, PM_DETREND_TYPE_LINEARITY)) {
-	psError(PS_ERR_IO, false, "Can't find a non-linearity correction source");
-	psFree(options);
-	return NULL;
-      }
+	if (!ppImageDefineFile(config, input->fpa, "PPIMAGE.LINEARITY", "LINEARITY",
+			       PM_FPA_FILE_LINEARITY, PM_DETREND_TYPE_LINEARITY)) {
+	    psError(PS_ERR_IO, false, "Can't find a non-linearity correction source");
+	    psFree(options);
+	    return NULL;
+	}
+    }
+    if (options->doNewNonLin) {
+	// if the file has been specified on the command-line (-newnonlin file), then the file
+	// is identified by the NEWNONLIN entry in config->arguments.  otherwise, load from the
+	// detrend system as type NEWNONLIN
+	if (!ppImageDefineFile(config, input->fpa, "PPIMAGE.NEWNONLIN", "NEWNONLIN",
+			       PM_FPA_FILE_NEWNONLIN, PM_DETREND_TYPE_NEWNONLIN)) {
+	    psError(PS_ERR_IO, false, "Can't find a new non-linearity correction source");
+	    psFree(options);
+	    return NULL;
+	}
     }
 
