Index: /branches/eam_branches/ipp-20110710/ppSim/src/ppSimMakeGalaxies.c
===================================================================
--- /branches/eam_branches/ipp-20110710/ppSim/src/ppSimMakeGalaxies.c	(revision 32299)
+++ /branches/eam_branches/ipp-20110710/ppSim/src/ppSimMakeGalaxies.c	(revision 32300)
@@ -11,6 +11,6 @@
     if (!galaxyFake) return true;
 
-    float galaxyLum       = psMetadataLookupF32(&mdok, recipe, "GALAXY.LUM"); // Galaxy luminosity func slope
-    float galaxyMag       = psMetadataLookupF32(&mdok, recipe, "GALAXY.MAG"); // Galaxy brightest magnitude
+    float galaxyAlpha     = psMetadataLookupF32(&mdok, recipe, "GALAXY.LUM"); // Galaxy luminosity func slope
+    float brightMag       = psMetadataLookupF32(&mdok, recipe, "GALAXY.MAG"); // Galaxy brightest magnitude
     float galaxyDensity   = psMetadataLookupF32(&mdok, recipe, "GALAXY.DENSITY"); // Density of fakes
 
@@ -39,8 +39,8 @@
     float galaxyIndexMax  = psMetadataLookupF32(&mdok, recipe, "GALAXY.INDEX.MAX"); // Density of fakes
 
-    float darkRate 	  = psMetadataLookupF32(&mdok, recipe, "DARK.RATE"); // Dark rate
+    // float darkRate 	  = psMetadataLookupF32(&mdok, recipe, "DARK.RATE"); // Dark rate
     float expTime  	  = psMetadataLookupF32(&mdok, recipe, "EXPTIME"); // Exposure time
     float zp       	  = psMetadataLookupF32(&mdok, recipe, "ZEROPOINT"); // Photometric zero point
-    float seeing   	  = psMetadataLookupF32(&mdok, recipe, "SEEING"); // Seeing sigma (pix)
+    // float seeing   	  = psMetadataLookupF32(&mdok, recipe, "SEEING"); // Seeing sigma (pix)
     float scale    	  = psMetadataLookupF32(&mdok, recipe, "PIXEL.SCALE") * M_PI / 3600.0 / 180.0; // Plate scale (radians/pixel)
     float skyRate  	  = psMetadataLookupF32(&mdok, recipe, "SKY.RATE"); // Sky rate
@@ -76,33 +76,37 @@
     // Grabbing read noise from the recipe rather than the cell, which is a potential danger, but it
     // shouldn't be too bad.
-    float readnoise = psMetadataLookupF32(&mdok, recipe, "READNOISE"); // Default read noise
-    if (!mdok) {
-	psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Unable to find READNOISE in recipe.");
-	psFree(bounds);
-	return false;
-    }
-
-    // Peak fluxes: faintest and brightest levels for random galaxy
-    float faint = 0.1 * 10.0 * sqrt(2.0*M_PI) * seeing * sqrtf(PS_SQR(readnoise) + (darkRate + skyRate) * expTime);
-    float bright = powf(10.0, -0.4 * (galaxyMag - zp)) / sqrt(2.0*M_PI) / seeing * expTime;
-    if (bright < faint) {
-	psLogMsg("ppSim", PS_LOG_INFO,
-		 "Image noise is above brightest random galaxy --- no random galaxy added.");
+    // float readnoise = psMetadataLookupF32(&mdok, recipe, "READNOISE"); // Default read noise
+    // if (!mdok) {
+    // 	psError(PS_ERR_BAD_PARAMETER_VALUE, false, "Unable to find READNOISE in recipe.");
+    // 	psFree(bounds);
+    // 	return false;
+    // }
+
+    // faintest and brightest magnitudes for random galaxies
+    // float brightFlux = ppSimMagToFlux (brightMag, zp) * expTime;
+    float faintMag = brightMag + 5.0;
+    if (brightMag > faintMag) {
+	psLogMsg("ppSim", PS_LOG_INFO, "Image noise is above brightest random galaxy --- no random galaxy added.");
 	return true;
     }
 
     // Normalisation, set by the specified stellar density at the specified bright magnitude
-    float norm = galaxyDensity * xSize * ySize * PS_SQR(scale * 180.0 / M_PI) /
-	powf(bright, galaxyLum);
+    float refSum = galaxyDensity * xSize * ySize * PS_SQR(scale * 180.0 / M_PI);
+    float normLum =  refSum / (galaxyAlpha * logf(10.0) * powf(10.0, (galaxyAlpha * brightMag)));
+    float normScale = normLum * galaxyAlpha * logf(10.0);
 
     // Total number of galaxy down to the faint flux end
-    long num = expf(logf(norm) + galaxyLum * logf(faint)) + 0.5;
-
-    fprintf (stderr, "galaxy grid inst mag: %f\n", galaxyGridMag - zp - 2.5*log10(expTime));
+    long nTotal = 0;
+    if (galaxyAlpha < 0.1) {
+	nTotal = 100;
+    } else {
+	nTotal = normScale * powf (10.0, (galaxyAlpha * faintMag));
+    }
 
     if (galaxyGrid) {
-	num = (int)(xSize / galaxyGridDX) * (int)(ySize / galaxyGridDY);
+	fprintf (stderr, "galaxy grid inst mag: %f\n", galaxyGridMag - zp - 2.5*log10(expTime));
+	nTotal = (int)(xSize / galaxyGridDX) * (int)(ySize / galaxyGridDY);
     
-	psLogMsg("ppSim", PS_LOG_INFO, "Adding grid of %ld galaxies\n", num);
+	psLogMsg("ppSim", PS_LOG_INFO, "Adding grid of %ld galaxies\n", nTotal);
 
 	float galaxyIndexSlope = (galaxyIndexMax - galaxyIndexMin);
@@ -131,17 +135,17 @@
 		float rndValue;
 
-		rndValue = galaxyGridRandom ? drand48() : i / (float) num;
+		rndValue = galaxyGridRandom ? drand48() : i / (float) nTotal;
 		float index = (galaxyIndexMin  + rndValue * galaxyIndexSlope);
 		galaxy->index = 0.5/index; // factor of 0.5 because the Sersic model creates exp(-z^n), not exp(-r^n)
 
-		rndValue = galaxyGridRandom ? drand48() : i / (float) num;
+		rndValue = galaxyGridRandom ? drand48() : i / (float) nTotal;
 		float scale = (galaxyRmajorMin + rndValue * galaxyRmajorSlope);
 
 		galaxy->Rmaj  = scale;
 
-		rndValue = galaxyGridRandom ? drand48() : i / (float) num;
+		rndValue = galaxyGridRandom ? drand48() : i / (float) nTotal;
 		galaxy->Rmin  = (galaxyARatioMin + rndValue * galaxyARatioSlope) * galaxy->Rmaj;
 
-		rndValue = galaxyGridRandom ? drand48() : i / (float) num;
+		rndValue = galaxyGridRandom ? drand48() : i / (float) nTotal;
 		galaxy->theta = (galaxyThetaMin  + rndValue * galaxyThetaSlope);
 		
@@ -179,4 +183,5 @@
     } else {    
 
+	fprintf (stderr, "galaxy ref inst mag: %f\n", brightMag - zp - 2.5*log10(expTime));
 	float galaxyIndexSlope = (galaxyIndexMax - galaxyIndexMin);
 	float galaxyThetaSlope = (galaxyThetaMax - galaxyThetaMin);
@@ -184,8 +189,7 @@
 	float galaxyRmajorSlope = (galaxyRmajorMax - galaxyRmajorMin);
 
-	psLogMsg("ppSim", PS_LOG_INFO, "Adding %ld galaxies down to %f mag\n", num,
-		 -2.5 * log10(faint * sqrt(2.0*M_PI) * seeing / expTime) + zp);
-
-	for (long i = 0; i < num; i++) {
+	psLogMsg("ppSim", PS_LOG_INFO, "Adding %ld galaxies down to %f mag\n", nTotal, faintMag);
+
+	for (long i = 0; i < nTotal; i++) {
 	    ppSimGalaxy *galaxy = ppSimGalaxyAlloc ();
 
@@ -198,23 +202,34 @@
 
 	    float scale = (psRandomUniform(rng) * galaxyRmajorSlope + galaxyRmajorMin);
-
-	    // for a sersic model, 
-	    float bn = 1.9992*index - 0.3271;
-	    float fR = 1.0 / (sqrt(2.0) * pow (bn, index));
-	    float Io = exp(bn);
-
 	    galaxy->Rmaj  = scale;
-
 	    galaxy->Rmin  = (PS_SQR(psRandomUniform(rng)) * galaxyARatioSlope + galaxyARatioMin) * galaxy->Rmaj;
-
 	    galaxy->theta = (psRandomUniform(rng) * galaxyThetaSlope  + galaxyThetaMin);
 
-	    // the flux is only approximately correct (scaling of the peak is wrong)
-	    // elsewhere (ppSimInsertGalaxies.c) we calculate the true galaxy flux
-	    galaxy->flux = expf((logf(i + 1) - logf(norm)) / galaxyLum); // Peak flux
-	    galaxy->peak = galaxy->flux / (2.0*M_PI*PS_SQR(seeing));
-
-	    if (0) {
-	      fprintf (stderr, "Rmaj: %f, scale: %f, index: %f, bn: %f, Ro: %f, Io: %f\n", galaxy->Rmaj, scale, index, bn, fR, Io);
+	    bool sersicType = false;
+	    sersicType |= (type == pmModelClassGetType ("PS_MODEL_SERSIC"));
+	    sersicType |= (type == pmModelClassGetType ("PS_MODEL_EXP"));
+	    sersicType |= (type == pmModelClassGetType ("PS_MODEL_DEV"));
+	    if (sersicType) {
+		if (type == pmModelClassGetType ("PS_MODEL_DEV")) index = 4.0;
+		if (type == pmModelClassGetType ("PS_MODEL_EXP")) index = 1.0;
+		
+		// for a sersic model, 
+		float bn = 1.9992*index - 0.3271;
+		float Io = exp(bn);
+		
+		// the integral of a Sersic has an analytical form as follows:
+		float logGamma = lgamma(2.0*index);
+		float bnFactor = pow(bn, 2.0*index);
+		float norm = 2.0 * M_PI * PS_SQR(galaxy->Rmaj) * index * Io * exp(logGamma) / bnFactor;
+		    
+		// XXX probably should limit the allowed thinness of a galaxy
+		float galaxyMag =  PS_MIN (faintMag, PS_MAX (brightMag, (log10((i + 1.0) / normScale) / galaxyAlpha)));
+
+		galaxy->flux = ppSimMagToFlux (galaxyMag, zp) * expTime;
+		galaxy->peak = galaxy->flux / norm / (galaxy->Rmin / galaxy->Rmaj);
+	    }
+
+	    if (1) {
+		fprintf (stderr, "Rmaj: %f, Rmin: %f, theta: %f, scale: %f, index: %f, peak: %f, mag: %f\n", galaxy->Rmaj, galaxy->Rmin, galaxy->theta*180.0/M_PI, scale, index, galaxy->peak, -2.5*log10(galaxy->flux));
 	    }
 
