aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas White <taw@physics.org>2014-10-06 16:34:46 +0200
committerThomas White <taw@physics.org>2014-10-06 16:34:46 +0200
commitfa005231eeb48c2ba04a8159de81f786f4dd12c8 (patch)
tree94f4fda96873d17c800bccba4c1844dc22fcdf50
parent111332cfe3289815d7458dc5fa6108e0d703d01e (diff)
WIP on SCGaussian gradients
-rw-r--r--libcrystfel/src/geometry.c14
-rw-r--r--src/post-refinement.c71
2 files changed, 66 insertions, 19 deletions
diff --git a/libcrystfel/src/geometry.c b/libcrystfel/src/geometry.c
index e08d9120..6bd18e0e 100644
--- a/libcrystfel/src/geometry.c
+++ b/libcrystfel/src/geometry.c
@@ -131,7 +131,7 @@ double sphere_fraction(double rlow, double rhigh, double pr)
}
-double gaussian_fraction(double rlow, double rhigh, double pr)
+double gaussian_fraction(double rlow, double rhigh, double R)
{
double plow, phigh;
const double ng = 2.6;
@@ -144,13 +144,13 @@ double gaussian_fraction(double rlow, double rhigh, double pr)
* zero) correspond to the six situations in Table 3 of Rossmann
* et al. (1979).
*/
- if ( rlow < -pr ) rlow = -pr;
- if ( rlow > +pr ) rlow = +pr;
- if ( rhigh < -pr ) rhigh = -pr;
- if ( rhigh > +pr ) rhigh = +pr;
+ if ( rlow < -R ) rlow = -R;
+ if ( rlow > +R ) rlow = +R;
+ if ( rhigh < -R ) rhigh = -R;
+ if ( rhigh > +R ) rhigh = +R;
- plow = 0.5 * gsl_sf_erf(ng * rlow / (sqrt(2.0)*pr));
- phigh = 0.5 * gsl_sf_erf(ng * rhigh / (sqrt(2.0)*pr));
+ plow = 0.5 * (1.0 + gsl_sf_erf(pow(ng*rlow /R, 2.0)/sqrt(2.0)));
+ phigh = 0.5 * (1.0 + gsl_sf_erf(pow(ng*rhigh/R, 2.0)/sqrt(2.0)));
return plow - phigh;
}
diff --git a/src/post-refinement.c b/src/post-refinement.c
index 5b7759a1..8bdc0956 100644
--- a/src/post-refinement.c
+++ b/src/post-refinement.c
@@ -56,18 +56,15 @@
/* Returns dp(gauss)/dr at "r" */
-static double gaussian_fraction_gradient(double r, double pr)
+static double gaussian_fraction_gradient(double r, double R)
{
- double q, dpdq, dqdr;
+ const double ng = 2.6;
/* If the Ewald sphere isn't within the profile, the gradient is zero */
- if ( r < -pr ) return 0.0;
- if ( r > +pr ) return 0.0;
+ if ( r < -R ) return 0.0;
+ if ( r > +R ) return 0.0;
- q = (r + pr)/(2.0*pr);
- dpdq = 6.0*(q - q*q); /* FIXME: Put a real gradient on this line */
- dqdr = 1.0 / (2.0*pr);
- return dpdq * dqdr;
+ return ng/(R*sqrt(2.0*M_PI)) * exp(-pow(r*ng/R, 2.0)/2.0);
}
@@ -124,6 +121,56 @@ static double sphere_fraction_rgradient(double r, double R)
}
+static double gaussian_fraction_rgradient(double r, double R)
+{
+ /* If the Ewald sphere isn't within the profile, the gradient is zero */
+ if ( r < -R ) return 0.0;
+ if ( r > +R ) return 0.0;
+
+ return -(3.0*r/(4.0*R*R)) * (1.0 - r*r/(R*R));
+}
+
+
+static double volume_fraction_rgradient(double r, double pr,
+ PartialityModel pmodel)
+{
+ switch ( pmodel )
+ {
+ case PMODEL_UNITY :
+ return 1.0;
+
+ case PMODEL_SCSPHERE :
+ return sphere_fraction_rgradient(r, pr);
+
+ case PMODEL_SCGAUSSIAN :
+ return gaussian_fraction_rgradient(r, pr);
+ }
+
+ ERROR("No pmodel in volume_fraction_rgradient!\n");
+ return 1.0;
+}
+
+
+static double volume_fraction(double rlow, double rhigh, double pr,
+ PartialityModel pmodel)
+{
+ switch ( pmodel )
+ {
+ case PMODEL_UNITY :
+ return 1.0;
+
+ case PMODEL_SCSPHERE :
+ return sphere_fraction(rlow, rhigh, pr);
+
+ case PMODEL_SCGAUSSIAN :
+ return gaussian_fraction(rlow, rhigh, pr);
+ }
+
+ ERROR("No pmodel in volume_fraction!\n");
+ return 1.0;
+}
+
+
/* Return the gradient of partiality wrt parameter 'k' given the current status
* of 'image'. */
double p_gradient(Crystal *cr, int k, Reflection *refl, PartialityModel pmodel)
@@ -151,10 +198,10 @@ double p_gradient(Crystal *cr, int k, Reflection *refl, PartialityModel pmodel)
double Rglow, Rghigh;
D = rlow - rhigh;
- psph = sphere_fraction(rlow, rhigh, R);
+ psph = volume_fraction(rlow, rhigh, R, pmodel);
- Rglow = sphere_fraction_rgradient(rlow, R);
- Rghigh = sphere_fraction_rgradient(rhigh, R);
+ Rglow = volume_fraction_rgradient(rlow, R, pmodel);
+ Rghigh = volume_fraction_rgradient(rhigh, R, pmodel);
return 4.0*psph/(3.0*D) + (4.0*R/(3.0*D))*(Rglow - Rghigh);
@@ -229,7 +276,7 @@ double p_gradient(Crystal *cr, int k, Reflection *refl, PartialityModel pmodel)
case REF_DIV :
D = rlow - rhigh;
- psph = sphere_fraction(rlow, rhigh, R);
+ psph = volume_fraction(rlow, rhigh, R, pmodel);
return (ds/2.0)*(glow+ghigh) - 4.0*R*psph*ds/(3.0*D*D);
}