Index: /trunk/archive/scripts/src/phase2/Makefile
===================================================================
--- /trunk/archive/scripts/src/phase2/Makefile	(revision 5620)
+++ /trunk/archive/scripts/src/phase2/Makefile	(revision 5621)
@@ -12,5 +12,5 @@
 
 OBJS = papPhase2.o psAdditionals.o pmConfig.o pmFPA.o pmFPAConstruct.o papStuff.o pmFPARead.o                \
-	pmFPAConceptsGet.o pmFPAConceptsSet.o pmFPAWrite.o                                                   \
+	pmFPAConceptsGet.o pmFPAConceptsSet.o pmFPAWrite.o pmChipMosaic.o                                    \
 	pmFlatField.o pmMaskBadPixels.o pmNonLinear.o pmSubtractBias.o
 TARGET = papPhase2
Index: /trunk/archive/scripts/src/phase2/gpc1_raw.config
===================================================================
--- /trunk/archive/scripts/src/phase2/gpc1_raw.config	(revision 5621)
+++ /trunk/archive/scripts/src/phase2/gpc1_raw.config	(revision 5621)
@@ -0,0 +1,172 @@
+# The raw GPC data comes off the telescope with each of the chips stored in separate files
+
+# How to identify this type
+RULE	METADATA
+#	TELESCOP	STR	PS1
+#	DETECTOR	STR	GPC1
+	EXTEND		BOOL	T
+	NEXTEND		S32	64
+	NAMPS		S32	64
+END
+
+# How to read this data
+PHU		STR	CHIP	# The FITS file represents a single chip
+EXTENSIONS	STR	CELL	# The extensions represent cells
+
+# What's in the FITS file?
+CONTENTS	METADATA
+	# Extension name, type
+	xy00	STR	pitch10u
+	xy01	STR	pitch10u
+	xy02	STR	pitch10u
+	xy03	STR	pitch10u
+	xy04	STR	pitch10u
+	xy05	STR	pitch10u
+	xy06	STR	pitch10u
+	xy07	STR	pitch10u
+	xy10	STR	pitch10u
+	xy11	STR	pitch10u
+	xy12	STR	pitch10u
+	xy13	STR	pitch10u
+	xy14	STR	pitch10u
+	xy15	STR	pitch10u
+	xy16	STR	pitch10u
+	xy17	STR	pitch10u
+	xy20	STR	pitch10u
+	xy21	STR	pitch10u
+	xy22	STR	pitch10u
+	xy23	STR	pitch10u
+	xy24	STR	pitch10u
+	xy25	STR	pitch10u
+	xy26	STR	pitch10u
+	xy27	STR	pitch10u
+	xy30	STR	pitch10u
+	xy31	STR	pitch10u
+	xy32	STR	pitch10u
+	xy33	STR	pitch10u
+	xy34	STR	pitch10u
+	xy35	STR	pitch10u
+	xy36	STR	pitch10u
+	xy37	STR	pitch10u
+	xy40	STR	pitch10u
+	xy41	STR	pitch10u
+	xy42	STR	pitch10u
+	xy43	STR	pitch10u
+	xy44	STR	pitch10u
+	xy45	STR	pitch10u
+	xy46	STR	pitch10u
+	xy47	STR	pitch10u
+	xy50	STR	pitch10u
+	xy51	STR	pitch10u
+	xy52	STR	pitch10u
+	xy53	STR	pitch10u
+	xy54	STR	pitch10u
+	xy55	STR	pitch10u
+	xy56	STR	pitch10u
+	xy57	STR	pitch10u
+	xy60	STR	pitch10u
+	xy61	STR	pitch10u
+	xy62	STR	pitch10u
+	xy63	STR	pitch10u
+	xy64	STR	pitch10u
+	xy65	STR	pitch10u
+	xy66	STR	pitch10u
+	xy67	STR	pitch10u
+	xy70	STR	pitch10u
+	xy71	STR	pitch10u
+	xy72	STR	pitch10u
+	xy73	STR	pitch10u
+	xy74	STR	pitch10u
+	xy75	STR	pitch10u
+	xy76	STR	pitch10u
+	xy77	STR	pitch10u
+END
+
+# Specify the cell data
+CELLS	METADATA
+	pitch10u	METADATA
+		CELL.BIASSEC.SOURCE	STR	VALUE
+		CELL.TRIMSEC.SOURCE	STR	VALUE
+		CELL.BIASSEC		STR	[575:606,1:594]
+		CELL.TRIMSEC		STR	[1:574,1:594]
+	#	CELL.BIASSEC		STR	BIASSEC
+	#	CELL.TRIMSEC		STR	DATASEC
+	END
+
+	# This is just in here for fun
+	pitch12u	METADATA
+		CELL.BIASSEC.SOURCE	STR	VALUE
+		CELL.TRIMSEC.SOURCE	STR	VALUE
+		CELL.BIASSEC		STR	[1:10,1:512];[523:574,1:512]
+		CELL.TRIMSEC		STR	[11:522,1:512]
+	#	CELL.BIASSEC		STR	BIASSEC
+	#	CELL.TRIMSEC		STR	TRIMSEC
+	END
+END
+
+
+# How to translate PS concepts into FITS headers
+TRANSLATION	METADATA
+	CELL.XBIN	STR	CCDSUM
+	CELL.YBIN	STR	CCDSUM
+	CELL.X0		STR	IMNPIX1
+	CELL.Y0		STR	IMNPIX2
+	CELL.XPARITY	STR	LTM1_1
+	CELL.YPARITY	STR	LTM2_2
+	CELL.SATURATION	STR	SATURATE
+END
+
+# Default PS concepts that may be specified by value
+DEFAULTS	METADATA
+	FPA.AIRMASS	F32	0.0
+	FPA.FILTER	STR	NONE
+	FPA.POSANGLE	F32	0.0
+	FPA.RA		STR	0:0:0
+	FPA.DEC		STR	0:0:0
+	FPA.RADECSYS	STR	ICRS
+	FPA.NAME	S32	12345
+	CELL.EXPOSURE	F32	0.0
+	CELL.DARKTIME	F32	0.0
+	CELL.GAIN	F32	1.0
+	CELL.READNOISE	F32	0.0
+	CELL.READDIR	S32	2
+	CELL.BAD	S32	0
+	CELL.TIMESYS	STR	UTC
+	CELL.TIME	STR	2005-11-23T12:34:56.78
+END
+
+# How to translation PS concepts into database lookups
+DATABASE	METADATA
+	TYPE		dbEntry		TABLE		COLUMN		GIVENDBCOL	GIVENPS
+#	CELL.GAIN	dbEntry		Camera		gain		chipId,cellId	CHIP,CELL
+#	CELL.READNOISE	dbEntry		Camera		readNoise	chipId,cellId	CHIP,CELL
+
+# A database entry refers to a particular column (COLUMN) in a
+# particular table (TABLE), given certain PS concepts (GIVENPS) that
+# match certain database columns (GIVENDBCOL).
+
+END
+
+
+# Where there might be some ambiguity, specify the format
+FORMATS		METADATA
+	FPA.RA		STR	HOURS
+	FPA.DEC		STR	DEGREES
+	CELL.TIME	STR	ISO
+	CELL.BINNING	STR	TOGETHER
+	CELL.X0		STR	FORTRAN
+	CELl.Y0		STR	FORTRAN
+END
+ 
+# Recipe options
+RECIPES		METADATA
+	PHASE2		STR	phase2.config		# Phase 2 recipe details
+END
+ 
+# How to get the supplementary stuff: mask and weight
+SUPPLEMENTARY	METADATA
+	MASK.SOURCE	STR	FILE		# Source type for mask: EXT | FILE
+	MASK.NAME	STR	%a_mask.fits	# Name for mask extension or filename
+	WEIGHT.SOURCE	STR	FILE		# Source type for weight: EXT | FILE
+	WEIGHT.NAME	STR	%a_weight.fits	# Name for weight extension or filename
+END
Index: /trunk/archive/scripts/src/phase2/ipprc.config
===================================================================
--- /trunk/archive/scripts/src/phase2/ipprc.config	(revision 5620)
+++ /trunk/archive/scripts/src/phase2/ipprc.config	(revision 5621)
@@ -22,8 +22,8 @@
 LOGDEST	STR	STDOUT				# Log destination
 TRACE		METADATA			# Trace levels
-	pmConfigRead		S32	10
 	pap			S32	10
-	pmFPAWriteMask		S32	10
-	pmFPAWriteWeight	S32	10
-	p_pmFPATranslateName	S32	10
+#	pmConfigRead		S32	10
+#	pmFPAWriteMask		S32	10
+#	pmFPAWriteWeight	S32	10
+	pmChipMosaic		S32	10
 END
Index: /trunk/archive/scripts/src/phase2/megacam_raw.config
===================================================================
--- /trunk/archive/scripts/src/phase2/megacam_raw.config	(revision 5620)
+++ /trunk/archive/scripts/src/phase2/megacam_raw.config	(revision 5621)
@@ -98,4 +98,6 @@
 		CELL.TRIMSEC		STR	DATASEC
 		CELL.XPARITY		S32	1 # We could have specified this as a DEFAULT, but this works
+		CELL.X0			S32	1
+		CELL.Y0			S32	1
 	END
 	right	METADATA	# Right amplifier
@@ -105,4 +107,6 @@
 		CELL.TRIMSEC		STR	DATASEC
 		CELL.XPARITY		S32	-1 # This cell is read out in the opposite direction
+		CELL.X0			S32	2048
+		CELL.Y0			S32	1
 	END
 END
@@ -153,4 +157,6 @@
 	CELL.TIME	STR	MJD
 #	CELL.BINNING	STR	SEPARATE
+	CELL.X0		STR	FORTRAN
+	CELL.Y0		STR	FORTRAN
 END
 
Index: /trunk/archive/scripts/src/phase2/nonlin.dat
===================================================================
--- /trunk/archive/scripts/src/phase2/nonlin.dat	(revision 5621)
+++ /trunk/archive/scripts/src/phase2/nonlin.dat	(revision 5621)
@@ -0,0 +1,106 @@
+# Non-linearity correction lookup table
+# Col 1: Input value
+# Col 2: Corrected value
+0	0
+100	1
+200	2
+300	3
+400	4
+500	5
+600	6
+700	7
+800	8
+900	9
+1000	10
+1100	11
+1200	12
+1300	13
+1400	14
+1500	15
+1600	16
+1700	17
+1800	18
+1900	19
+2000	20
+2100	21
+2200	22
+2300	23
+2400	24
+2500	25
+2600	26
+2700	27
+2800	28
+2900	29
+3000	30
+3100	31
+3200	32
+3300	33
+3400	34
+3500	35
+3600	36
+3700	37
+3800	38
+3900	39
+4000	40
+4100	41
+4200	42
+4300	43
+4400	44
+4500	45
+4600	46
+4700	47
+4800	48
+4900	49
+5000	50
+5100	51
+5200	52
+5300	53
+5400	54
+5500	55
+5600	56
+5700	57
+5800	58
+5900	59
+6000	60
+6100	61
+6200	62
+6300	63
+6400	64
+6500	65
+6600	66
+6700	67
+6800	68
+6900	69
+7000	70
+7100	71
+7200	72
+7300	73
+7400	74
+7500	75
+7600	76
+7700	77
+7800	78
+7900	79
+8000	80
+8100	81
+8200	82
+8300	83
+8400	84
+8500	85
+8600	86
+8700	87
+8800	88
+8900	89
+9000	90
+9100	91
+9200	92
+9300	93
+9400	94
+9500	95
+9600	96
+9700	97
+9800	98
+9900	99
+10000	100
+10001	-1
+1e6	-1
Index: /trunk/archive/scripts/src/phase2/papPhase2.c
===================================================================
--- /trunk/archive/scripts/src/phase2/papPhase2.c	(revision 5620)
+++ /trunk/archive/scripts/src/phase2/papPhase2.c	(revision 5621)
@@ -16,4 +16,5 @@
 #include "pmNonLinear.h"
 #include "pmSubtractBias.h"
+#include "pmChipMosaic.h"
 
 // Phase 2 needs to:
@@ -81,5 +82,5 @@
 #endif
 
-    psTraceSetLevel("pmConfigCameraFromHeader", 10);
+    psTimerStart("phase2");
 
     // Parse the configurations
@@ -276,4 +277,6 @@
 	psLogMsg("phase2", PS_LOG_INFO, "Operating only on chip %d\n", chipNum);
     }
+
+    psLogMsg("phase2", PS_LOG_INFO, "Setup completed after %f sec.\n", psTimerMark("phase2"));
 
     // Read in the input pixels
@@ -447,4 +450,6 @@
     }
     
+    psLogMsg("phase2", PS_LOG_INFO, "Input completed after %f sec.\n", psTimerMark("phase2"));
+
     psArray *inputChips = input->chips; // Array of chips in input image
     psArray *biasChips = bias->chips;	// Array of chips in bias image
@@ -766,4 +771,5 @@
 		// XXX: Temporary: until the other functions are altered to do this themselves.
 		// Trim, so that flat, fringe etc computations are faster.
+#if 0
 #ifndef PRODUCTION
 		psRegion *trimRegion = psMetadataLookupPtr(NULL, inputCell->concepts, "CELL.TRIMSEC");
@@ -772,5 +778,5 @@
 		inputReadout->image = trimmed;
 #endif
-
+#endif
 		// Flat-field correction
 		if (doFlat) {
@@ -804,7 +810,20 @@
 		}
 
+
 	    } // Iterating over readouts
 	} // Iterating over cells
+
+	// Testing pmChipMosaic
+	{
+	    psImage *mosaic = pmChipMosaic(inputChip, 1, 1); // Mosaic of chip
+	    psFits *mosaicFile = psFitsAlloc("mosaic.fits"); // FITS file to which to write
+	    psFitsWriteImage(mosaicFile, NULL, mosaic, 0);
+	    psFree(mosaicFile);
+	    psFree(mosaic);		
+	}
+ 
     } // Iterating over chips
+
+    psLogMsg("phase2", PS_LOG_INFO, "Processing completed after %f sec.\n", psTimerMark("phase2"));
 
     // Write the output
@@ -812,4 +831,6 @@
     pmFPAWriteMask(input, outputFile);
     pmFPAWriteWeight(input, outputFile);
+
+    psLogMsg("phase2", PS_LOG_INFO, "Output completed after %f sec.\n", psTimerMark("phase2"));
 
 #ifdef PRODUCTION
@@ -831,4 +852,7 @@
     psFree(overscanFit);
     psFree(overscanStats);
+
+    psLogMsg("phase2", PS_LOG_INFO, "Cleanup completed after %f sec.\n", psTimerMark("phase2"));
+    psTimerStop();
 
 #if 1
Index: /trunk/archive/scripts/src/phase2/phase2.config
===================================================================
--- /trunk/archive/scripts/src/phase2/phase2.config	(revision 5620)
+++ /trunk/archive/scripts/src/phase2/phase2.config	(revision 5621)
@@ -6,5 +6,5 @@
 BIAS		BOOL	FALSE		# Bias subtraction
 DARK		BOOL	FALSE		# Dark subtraction
-OVERSCAN	BOOL	FALSE		# Overscan subtraction
+OVERSCAN	BOOL	TRUE		# Overscan subtraction
 FLAT		BOOL	FALSE		# Flat-field normalisation
 FRINGE		BOOL	FALSE		# Fringe subtraction
Index: /trunk/archive/scripts/src/phase2/pmChipMosaic.c
===================================================================
--- /trunk/archive/scripts/src/phase2/pmChipMosaic.c	(revision 5621)
+++ /trunk/archive/scripts/src/phase2/pmChipMosaic.c	(revision 5621)
@@ -0,0 +1,125 @@
+#include <stdio.h>
+
+#include "pslib.h"
+#include "pmFPA.h"
+#include "pmChipMosaic.h"
+
+// Compare a value with a maximum and minimum
+#define COMPARE(value,min,max) \
+    if ((value) < (min)) { \
+        (min) = (value); \
+    } \
+    if ((value) > (max)) { \
+        (max) = (value); \
+    }
+
+psImage *pmChipMosaic(pmChip *chip,	// Chip to mosaic
+		      int xBinChip, int yBinChip // Binning of mosaic image in x and y
+    )
+{
+    psArray *cells = chip->cells;	// The array of cells
+    psVector *x0 = psVectorAlloc(cells->n, PS_TYPE_S32); // Origin x coordinates
+    psVector *y0 = psVectorAlloc(cells->n, PS_TYPE_S32); // Origin y coordinates
+    psVector *xBin = psVectorAlloc(cells->n, PS_TYPE_S32); // Binning in x
+    psVector *yBin = psVectorAlloc(cells->n, PS_TYPE_S32); // Binning in y
+    psVector *xParity = psVectorAlloc(cells->n, PS_TYPE_S32); // Parity in x
+    psVector *yParity = psVectorAlloc(cells->n, PS_TYPE_S32); // Parity in y
+    psArray *trimsec = psArrayAlloc(cells->n); // Trim section
+
+    // Get the maximum extent of the mosaic image
+    int xMin = INT_MAX;
+    int xMax = 0;
+    int yMin = INT_MAX;
+    int yMax = 0;
+    for (int i = 0; i < cells->n; i++) {
+	pmCell *cell = cells->data[i];	// The cell of interest
+	x0->data.S32[i] = psMetadataLookupS32(NULL, cell->concepts, "CELL.X0");
+	y0->data.S32[i] = psMetadataLookupS32(NULL, cell->concepts, "CELL.Y0");
+	xBin->data.S32[i] = psMetadataLookupS32(NULL, cell->concepts, "CELL.XBIN");
+	yBin->data.S32[i] = psMetadataLookupS32(NULL, cell->concepts, "CELL.XBIN");
+	xParity->data.S32[i] = psMetadataLookupS32(NULL, cell->concepts, "CELL.XPARITY");
+	yParity->data.S32[i] = psMetadataLookupS32(NULL, cell->concepts, "CELL.YPARITY");
+	trimsec->data[i] = psMemIncrRefCounter(psMetadataLookupPtr(NULL, cell->concepts, "CELL.TRIMSEC"));
+	psTrace(__func__, 7, "Cell %d trimsec: [%.0f:%.0f,%.0f:%.0f]\n", i, ((psRegion*)trimsec->data[i])->x0,
+		((psRegion*)trimsec->data[i])->x1, ((psRegion*)trimsec->data[i])->y0,
+		((psRegion*)trimsec->data[i])->y1);
+	// Size of cell in x and y
+	int nx = (int)(((psRegion*)trimsec->data[i])->x1 - (int)((psRegion*)trimsec->data[i])->x0);
+	int ny = (int)(((psRegion*)trimsec->data[i])->y1 - (int)((psRegion*)trimsec->data[i])->y0);
+	psTrace(__func__, 5, "Extent of cell %d: %d -> %d , %d -> %d\n", i, x0->data.S32[i],
+		x0->data.S32[i] + xParity->data.S32[i] * xBin->data.S32[i] * nx, y0->data.S32[i],
+		y0->data.S32[i] + yParity->data.S32[i] * yBin->data.S32[i] * ny);
+
+	COMPARE(x0->data.S32[i], xMin, xMax);
+	COMPARE(y0->data.S32[i], yMin, yMax);
+	// Subtract the parity to get the inclusive limit (not exclusive)
+	COMPARE(x0->data.S32[i] + xParity->data.S32[i] * xBin->data.S32[i] * nx - xParity->data.S32[i], xMin, xMax);
+	COMPARE(y0->data.S32[i] + yParity->data.S32[i] * yBin->data.S32[i] * ny - yParity->data.S32[i], yMin, yMax);
+    }
+
+    // Set up the image
+    // Since both upper and lower values are inclusive, we need to add one to the size
+    float xSize = (float)(xMax - xMin + 1) / (float)xBinChip;
+    if (xSize - (int)xSize > 0) {
+	xSize += 1;
+    }
+    float ySize = (float)(yMax - yMin + 1) / (float)yBinChip;
+    if (ySize - (int)ySize > 0) {
+	ySize += 1;
+    }
+
+    psTrace(__func__, 3, "Mosaicked chip will be %dx%d\n", (int)xSize, (int)ySize);
+    psImage *mosaic = psImageAlloc((int)xSize, (int)ySize, PS_TYPE_F32); // The mosaic image
+    psImageInit(mosaic, 0.0);
+
+    // Set the image
+    for (int i = 0; i < cells->n; i++) {
+	pmCell *cell = cells->data[i];	// The cell of interest
+	psArray *readouts = cell->readouts; // The array of readouts
+	if (readouts->n > 1) {
+	    psLogMsg(__func__, PS_LOG_WARN, "Cell %d contains more than one readout --- only the first will "
+		     "be mosaicked.\n", i);
+	}
+	psImage *image = ((pmReadout*)readouts->data[0])->image; // The image to put into the mosaic
+	psImage *trimmed = psImageSubset(image, *(psRegion*)(trimsec->data[i])); // Trimmed image (no overscan)
+
+	if (xBin->data.S32[i] == xBinChip && yBin->data.S32[i] == yBinChip && xParity->data.S32[i] == 1 &&
+	    yParity->data.S32[i] == 1) {
+	    // Let someone else do the hard work; useful to test psImageOverlaySection if no other reason
+	    psImageOverlaySection(mosaic, trimmed, x0->data.S32[i], y0->data.S32[i], "+");
+	} else {
+	    // We have to do the hard work ourself
+	    for (int y = 0; y < trimmed->numRows; y++) {
+		float yTargetBase = (y0->data.S32[i] + yParity->data.S32[i] * yBin->data.S32[i] * y) /
+		    yBinChip;
+		for (int x = 0; x < trimmed->numCols; x++) {
+		    float xTargetBase = (x0->data.S32[i] + xParity->data.S32[i] * xBin->data.S32[i] * x) /
+			xBinChip;
+
+		    // In case the original image is binned but the mosaic is not, we need to fill in the
+		    // values in the mosaic.
+		    for (int j = 0; j < yBin->data.S32[i]; j++) {
+			int yTarget = (int)(yTargetBase + yParity->data.S32[i] * (float)j / (float)yBinChip);
+			for (int i = 0; i < xBin->data.S32[i]; i++) {
+			    int xTarget = (int)(xTargetBase +
+						xParity->data.S32[i] * (float)i / (float)xBinChip);
+
+			    mosaic->data.F32[yTarget][xTarget] += trimmed->data.F32[y][x];
+			}
+		    } // Iterating over mosaic image for binned input image
+		}
+	    } // Iterating over input image
+	}
+	psFree(trimmed);
+    } // Iterating over cells
+
+    psFree(x0);
+    psFree(y0);
+    psFree(xBin);
+    psFree(yBin);
+    psFree(xParity);
+    psFree(yParity);
+    psFree(trimsec);
+
+    return mosaic;
+}
Index: /trunk/archive/scripts/src/phase2/pmChipMosaic.h
===================================================================
--- /trunk/archive/scripts/src/phase2/pmChipMosaic.h	(revision 5621)
+++ /trunk/archive/scripts/src/phase2/pmChipMosaic.h	(revision 5621)
@@ -0,0 +1,12 @@
+#ifndef PM_CHIP_MOSAIC_H
+#define PM_CHIP_MOSAIC_H
+
+#include "pslib.h"
+#include "pmFPA.h"
+
+psImage *pmChipMosaic(pmChip *chip,	// Chip to mosaic
+		      int xBinChip, int yBinChip // Binning of mosaic image in x and y
+    );
+
+
+#endif
Index: /trunk/archive/scripts/src/phase2/pmFPAConceptsGet.c
===================================================================
--- /trunk/archive/scripts/src/phase2/pmFPAConceptsGet.c	(revision 5620)
+++ /trunk/archive/scripts/src/phase2/pmFPAConceptsGet.c	(revision 5621)
@@ -344,4 +344,14 @@
 	  case PS_TYPE_S32:
 	    value = item->data.S32;
+	    break;
+	  case PS_TYPE_F32:
+	    psLogMsg(__func__, PS_LOG_WARN, "Concept %s (%s) should be S32, but is F32 --- converting.\n",
+		     name, comment);
+	    value = (int)item->data.F32;
+	    break;
+	  case PS_TYPE_F64:
+	    psLogMsg(__func__, PS_LOG_WARN, "Concept %s (%s) should be S32, but is F64 --- converting.\n",
+		     name, comment);
+	    value = (int)item->data.F64;
 	    break;
 	  default:
@@ -977,4 +987,29 @@
     }
 
+    // These are new and experimental concepts: CELL.X0 and CELL.Y0
+
+    // CELL.X0
+    p_pmFPAConceptGetS32(fpa, chip, cell, db, cell->concepts, "CELL.X0", "Position of (0,0) on the chip ");
+    // CELL.Y0
+    p_pmFPAConceptGetS32(fpa, chip, cell, db, cell->concepts, "CELL.Y0", "Position of (0,0) on the chip");
+    // Add corrective
+    {
+	const psMetadata *camera = fpa->camera;
+	bool mdok = false;		// Result of MD lookup
+	psMetadata *formats = psMetadataLookupMD(&mdok, camera, "FORMATS");
+	if (mdok && formats) {
+	    psString format = psMetadataLookupString(&mdok, formats, "CELL.X0");
+	    if (mdok && strlen(format) > 0 && strcasecmp(format, "FORTRAN") == 0) {
+		psMetadataItem *cellx0 = psMetadataLookup(cell->concepts, "CELL.X0");
+		cellx0->data.S32 -= 1;
+	    }
+	    format = psMetadataLookupString(&mdok, formats, "CELL.Y0");
+	    if (mdok && strlen(format) > 0 && strcasecmp(format, "FORTRAN") == 0) {
+		psMetadataItem *celly0 = psMetadataLookup(cell->concepts, "CELL.Y0");
+		celly0->data.S32 -= 1;
+	    }
+	}
+    }
+
     // Pau.
 }
Index: /trunk/archive/scripts/src/phase2/pmFPAConceptsSet.c
===================================================================
--- /trunk/archive/scripts/src/phase2/pmFPAConceptsSet.c	(revision 5620)
+++ /trunk/archive/scripts/src/phase2/pmFPAConceptsSet.c	(revision 5621)
@@ -856,4 +856,27 @@
     }
 
+    // Remove corrective
+    {
+	const psMetadata *camera = fpa->camera;
+	bool mdok = false;		// Result of MD lookup
+	psMetadata *formats = psMetadataLookupMD(&mdok, camera, "FORMATS");
+	if (mdok && formats) {
+	    psString format = psMetadataLookupString(&mdok, formats, "CELL.X0");
+	    if (mdok && strlen(format) > 0 && strcasecmp(format, "FORTRAN") == 0) {
+		psMetadataItem *cellx0 = psMetadataLookup(cell->concepts, "CELL.X0");
+		cellx0->data.S32 += 1;
+	    }
+	    format = psMetadataLookupString(&mdok, formats, "CELL.Y0");
+	    if (mdok && strlen(format) > 0 && strcasecmp(format, "FORTRAN") == 0) {
+		psMetadataItem *celly0 = psMetadataLookup(cell->concepts, "CELL.Y0");
+		celly0->data.S32 += 1;
+	    }
+	}
+    }
+    // CELL.X0
+    setConcept(fpa, chip, cell, db, cell->concepts, "CELL.X0");
+    // CELL.Y0
+    setConcept(fpa, chip, cell, db, cell->concepts, "CELL.Y0");
+
     // Pau.
 }
Index: /trunk/archive/scripts/src/phase2/pmFPAMorph.c
===================================================================
--- /trunk/archive/scripts/src/phase2/pmFPAMorph.c	(revision 5620)
+++ /trunk/archive/scripts/src/phase2/pmFPAMorph.c	(revision 5621)
@@ -68,5 +68,5 @@
 }
 
-
+// Splice a list of cells together
 static psArray *spliceCells(psList *outCells, // List of target cells (required for parity info)
 			    psList *inCells, // List of cells to splice together
