ThreeB 1.1
multispot5.cc
Go to the documentation of this file.
00001 #include <cstdlib>
00002 #include <cerrno>
00003 #include <cstring>
00004 #include <stack>
00005 #include <algorithm>
00006 #include <climits>
00007 #include <iomanip>
00008 #include <map>
00009 #include <tr1/memory>
00010 #include <cvd/image_io.h>
00011 #include <cvd/image_convert.h>
00012 #include <cvd/morphology.h>
00013 #include <cvd/connected_components.h>
00014 #include <cvd/draw.h>
00015 #include <cvd/vector_image_ref.h>
00016 
00017 #include <cvd/random.h>
00018 #include <cvd/timer.h>
00019 #include <gvars3/instances.h>
00020 
00021 #include <TooN/functions/derivatives.h>
00022 #include <TooN/determinant.h>
00023 #include <TooN/SymEigen.h>
00024 #include <TooN/optimization/conjugate_gradient.h>
00025 
00026 #include "conjugate_gradient_only.h"
00027 #include "forward_algorithm.h"
00028 #include "numerical_derivatives.h"
00029 #include "storm.h"
00030 #include "storm_imagery.h"
00031 #include "debug.h"
00032 #include "sampled_multispot.h"
00033 #include "mt19937.h"
00034 #include "utility.h"
00035 #include "multispot5.h"
00036 
00037 
00038 //For benchmarking...
00039 #define TIME(X) 
00040 //#define TIME(X) X
00041 
00042 using namespace std;
00043 using namespace CVD;
00044 using namespace GVars3;
00045 using namespace TooN;
00046 using namespace std::tr1;
00047 
00048 ///Empty destructor
00049 UserInterfaceCallback::~UserInterfaceCallback(){}
00050 
00051 ///User interface callback class which does nothing.
00052 class NullUICallback: public UserInterfaceCallback
00053 {
00054     void per_spot(int, int, int, int){};
00055     void per_modification(int, int, int){};
00056     void per_pass(int, int, const std::vector<TooN::Vector<4> >&){};
00057     void perhaps_stop(){};
00058 };
00059 
00060 ///Factory function to generate an instance of NullGraphics
00061 ///@ingroup gStorm
00062 auto_ptr<UserInterfaceCallback> null_ui()
00063 {
00064     return auto_ptr<UserInterfaceCallback>(new NullUICallback);
00065 }
00066 
00067 
00068 //Declare the graphics classes.
00069 //These provide all the debug drawing operations so that the code can run in GUI and
00070 //headless mode easily and without macros.
00071 FitSpotsGraphics::~FitSpotsGraphics(){}
00072 
00073 ///Graphics class which does absoloutely nothing
00074 ///@ingroup gStorm
00075 class NullGraphics: public  FitSpotsGraphics
00076 {
00077     public:
00078         virtual void init(CVD::ImageRef){}
00079         virtual void draw_krap(const std::vector<TooN::Vector<4> >&, const CVD::Image<CVD::byte>&, const BBox&, int, TooN::Vector<4>){}
00080         virtual void swap(){}
00081         virtual void draw_pixels(const std::vector<CVD::ImageRef>&, float, float, float, float){}
00082         virtual void draw_bbox(const BBox&){}
00083         virtual void glDrawCross(const TooN::Vector<2>&, int){}
00084         virtual ~NullGraphics(){}
00085 };
00086 
00087 ///Factory function to generate an instance of NullGraphics
00088 ///@ingroup gStorm
00089 auto_ptr<FitSpotsGraphics> null_graphics()
00090 {
00091     return auto_ptr<FitSpotsGraphics>(new NullGraphics);
00092 }
00093 
00094 
00095 ///There are two sensible ways of storing the state vector of spot positions.
00096 ///This function converts between them. See also spots_to_vector.
00097 ///@param s list of spots to convert
00098 ///@ingroup gUtility
00099 Vector<> spots_to_Vector(const vector<Vector<4> >& s)
00100 {
00101     Vector<> r(s.size()*4);
00102     for(unsigned int i=0; i < s.size(); i++)
00103     {
00104         r[i*4+0] = s[i][0];
00105         r[i*4+1] = s[i][1];
00106         r[i*4+2] = s[i][2];
00107         r[i*4+3] = s[i][3];
00108     }
00109     return r;
00110 }
00111 
00112 ///There are two sensible ways of storing the state vector of spot positions.
00113 ///This function converts between them. See also spots_to_Vector.
00114 ///@param s list of spots to convert
00115 ///@ingroup gUtility
00116 vector<Vector<4> > spots_to_vector(const Vector<>& s)
00117 {
00118     vector<Vector<4> > r(s.size()/4);
00119     for(unsigned int i=0; i < r.size(); i++)
00120         r[i] = s.slice<Dynamic, 4>(i*4, 4);
00121     return r;
00122 }
00123 
00124 ///Normalize an image for display purposes.
00125 ///@ingroup gUtility
00126 Image<byte> scale_to_bytes(const Image<float>& im, float lo, float hi)
00127 {
00128         Image<byte> out(im.size());
00129         for(int r=0; r < out.size().y-0; r++)
00130                 for(int c=0; c < out.size().x-0; c++)
00131                         out[r][c] = (int)floor((im[r][c]-lo)*255/(hi-lo));
00132         return out;
00133 }
00134 
00135 ///Normalize an image for display purposes.
00136 ///@ingroup gUtility
00137 Image<byte> scale_to_bytes(const Image<float>& im)
00138 {
00139         float lo = *min_element(im.begin(), im.end());
00140         float hi = *max_element(im.begin(), im.end());
00141         Image<byte> out(im.size());
00142         for(int r=0; r < out.size().y-0; r++)
00143                 for(int c=0; c < out.size().x-0; c++)
00144                         out[r][c] = (int)floor((im[r][c]-lo)*255/(hi-lo));
00145 
00146         return out;
00147 }
00148 
00149 ///Average the input image stack for display purposes
00150 ///@ingroup gUtility
00151 Image<float> average_image(const vector<Image<float> >& ims)
00152 {
00153     assert_same_size(ims);
00154     Image<float> r(ims[0].size(), 0);
00155 
00156     for(unsigned int i=0; i < ims.size(); i++)
00157         transform(r.begin(), r.end(), ims[i].begin(), r.begin(), plus<float>());
00158 
00159     transform(r.begin(), r.end(), r.begin(), bind2nd(multiplies<float>(), 1./ims.size()));
00160     return r;
00161 }
00162 
00163 
00164 ////////////////////////////////////////////////////////////////////////////////
00165 ////////////////////////////////////////////////////////////////////////////////
00166 ////////////////////////////////////////////////////////////////////////////////
00167 ////////////////////////////////////////////////////////////////////////////////
00168 ////////////////////////////////////////////////////////////////////////////////
00169 ////////////////////////////////////////////////////////////////////////////////
00170 ////////////////////////////////////////////////////////////////////////////////
00171 ////////////////////////////////////////////////////////////////////////////////
00172 
00173 ///Closure hoding the data required do use GibbsSampler2
00174 ///See FitSpots for naming of variables.
00175 ///@ingroup gStorm
00176 class DataForMCMC
00177 {
00178     protected:
00179     const vector<ImageRef>& pixels;
00180     const vector<vector<double> >& pixel_intensities;//[frame][pixel]
00181     const double mu_brightness, sigma_brightness, mu_blur, sigma_blur;
00182     const double variance;
00183     const int samples, sample_iterations;
00184     const Matrix<3> A;
00185     const Vector<3> pi;
00186     MT19937& rng;
00187     public:
00188 
00189     MT19937& get_rng()const
00190     {
00191         return rng;
00192     }
00193     
00194     public: 
00195     DataForMCMC(const vector<ImageRef>& pixels_, 
00196                 const vector<vector<double> >& pixel_intensities_,
00197                 double mu_brightness_, 
00198                 double sigma_brightness_, 
00199                 double mu_blur_, 
00200                 double sigma_blur_,
00201                 double variance_,
00202                 int samples_,
00203                 int sample_iterations_,
00204                 Matrix<3> A_,
00205                 Vector<3> pi_,
00206                 MT19937& rng_)
00207     :pixels(pixels_),
00208      pixel_intensities(pixel_intensities_),
00209      mu_brightness(mu_brightness_),
00210      sigma_brightness(sigma_brightness_),
00211      mu_blur(mu_blur_),
00212      sigma_blur(sigma_blur_),
00213      variance(variance_),
00214      samples(samples_),
00215      sample_iterations(sample_iterations_),
00216      A(A_),
00217      pi(pi_),
00218      rng(rng_)
00219     {}
00220 };
00221 
00222 ///Class implementing the Kahan summation algorithm
00223 ///to allow accurate summation of very large numbers of
00224 ///doubles.
00225 ///@ingroup gUtility
00226 class Kahan{
00227     private:
00228         double y; ///< Input with the compensation removed. Temporary working space.
00229         double c; ///< Running compenstation for low-order bits.
00230         double t; ///< y + sum, which loses low order bits of y. Temporary working space.
00231     public:
00232         double sum; ///< running sum
00233 
00234         Kahan()
00235         :c(0),sum(0)
00236         {}
00237         
00238         /// Add a number to the running sum
00239         /// @param i Number to add
00240         void add(double i)
00241         {
00242             //y = input -c
00243             y = i;
00244             y-= c;
00245 
00246             //t = sum + y
00247             t = sum;
00248             t += y;
00249             
00250             //c = (t - sum) - y
00251             //c = ((sum + y) - sum) - y)
00252             c = t;
00253             c -= sum;
00254             c -= y;
00255             sum = t;
00256         }
00257 };
00258 
00259 
00260 ///Class for computing the negitve free energy using thermodynamic integration.
00261 class NegativeFreeEnergy: public DataForMCMC
00262 {
00263     public: 
00264 
00265     ///@param d Necessary data
00266     NegativeFreeEnergy(const DataForMCMC& d)
00267     :DataForMCMC(d)
00268     {
00269     }
00270     
00271     ///Give the noise variance given a sample number and growth parameters
00272     ///@param sample Sample number
00273     ///@param samples Total number of samples
00274     ///@param base_sigma Starting value of sigme 
00275     ///@param scale_pow Exponent scaling
00276     double variance_from_sample(double sample, double samples, double base_sigma, double scale_pow) const
00277     {
00278         double scale = pow(1.25, sample * 1. / samples * scale_pow);
00279         double sigma = base_sigma * scale;
00280         double new_variance = sq(sigma);
00281 
00282         return new_variance;
00283     }
00284 
00285     ///Estimate free energy using the Slow Growth Thermodynamic Integration method given in
00286     ///Probalistic Inference Using Markov Chain Monte Carlo Methods, Radford. M. Neal, 1993
00287     ///Except using a 5 point stencil instead of forward differenceing in Eq 6.30
00288     ///@param spots list of spots
00289     ///@param spot_pixels Mask around each spot to use to save on computation
00290     double compute_with_mask(const Vector<>& spots, const vector<vector<int> >& spot_pixels) const
00291     {
00292         //Estimate free energy using the Slow Growth Thermodynamic Integration method given in
00293         //Probalistic Inference Using Markov Chain Monte Carlo Methods, Radford. M. Neal, 1993
00294         //Except using a 5 point stencil instead of forward differenceing in Eq 6.30
00295         double base_sigma = sqrt(variance); // should be 1
00296         double scale_pow = 100.0;
00297 
00298         const unsigned int nspots  = spots.size()/4;
00299         const unsigned int nframes = pixel_intensities.size();
00300         const unsigned int npixels = pixels.size();
00301         assert(spots.size() %4 == 0);
00302         assert(spot_pixels.size() == nspots);
00303 
00304         //Compute the intensities and derivatives for all spot
00305         vector<vector<double> > spot_intensity; //[spot][pixel]
00306         for(unsigned int i=0; i < nspots; i++)
00307             spot_intensity.push_back(compute_spot_intensity(pixels, spots.slice<Dynamic,4>(i*4,4)));
00308         
00309         GibbsSampler2 sampler(pixel_intensities, spot_intensity, spots_to_vector(spots), spot_pixels, A, pi, variance, sample_iterations);
00310 
00311         double sum = 0;
00312         Kahan ksum;
00313         for(int sample=0; sample < samples; sample++)
00314         {
00315             //Compute the positions of the surrounding steps
00316             double var1 = variance_from_sample(sample-2, samples, base_sigma, scale_pow);
00317             double var2 = variance_from_sample(sample-1, samples, base_sigma, scale_pow);
00318             double var3 = variance_from_sample(sample+1, samples, base_sigma, scale_pow);
00319             double var4 = variance_from_sample(sample+2, samples, base_sigma, scale_pow);
00320 
00321             //Take a sample
00322             sampler.set_variance(var2);
00323             sampler.next(DataForMCMC::get_rng());
00324             
00325             //Compute the SSD. This is fixed regardless of sigma.   
00326             double err_sum=0;
00327             for(unsigned int frame=0; frame < nframes; frame++)
00328                 for(unsigned int pixel=0; pixel < npixels; pixel++)
00329                     err_sum -= sq(pixel_intensities[frame][pixel] - sampler.sample_intensities()[frame][pixel]);
00330             
00331             //Compute the derivative using a five point stencil
00332             //This could be done in a better but less clear way
00333             double e1 = err_sum / (2*var1) - npixels*nframes*::log(2*M_PI*var1)/2;
00334             double e2 = err_sum / (2*var2) - npixels*nframes*::log(2*M_PI*var2)/2;
00335             double e3 = err_sum / (2*var3) - npixels*nframes*::log(2*M_PI*var3)/2;
00336             double e4 = err_sum / (2*var4) - npixels*nframes*::log(2*M_PI*var4)/2;
00337             sum += (-e1 + 8*e2 - 8*e3 + e4)/12;
00338 
00339             ksum.add(-e1/12);
00340             ksum.add(8*e2/12);
00341             ksum.add(-8*e3/12);
00342             ksum.add(e4/12);
00343         }
00344 
00345         double log_final = (log(variance_from_sample(samples, samples, base_sigma, scale_pow)*2*M_PI)/2) * npixels * nframes;
00346         
00347         double priors=0;
00348         for(unsigned int i=0; i < nspots; i++)
00349         {
00350             priors += log_log_normal(spots[i*4+0], mu_brightness, sigma_brightness);
00351             priors += log_log_normal(spots[i*4+1], mu_blur, sigma_blur);
00352         }
00353 
00354         /*cout << "Thermo:\n";
00355         cout << "sum: " << sum -log_final << endl;
00356         cout << "kah: " << ksum.sum -log_final << endl;
00357         cout << "priors: " << priors + sum -log_final << endl;
00358         cout << "   kah: " << priors + ksum.sum -log_final << endl;
00359 */
00360         //cout << log_final << endl;
00361         //cout << sum + log_final << endl;
00362         
00363         
00364         sampler.set_variance(variance);
00365         return -(sum+priors - log_final);
00366     }
00367     
00368     ///Estimate free energy using the Slow Growth Thermodynamic Integration method given in
00369     ///Probalistic Inference Using Markov Chain Monte Carlo Methods, Radford. M. Neal, 1993
00370     ///Except using a 5 point stencil instead of forward differenceing in Eq 6.30
00371     ///@param spots list of spots
00372     double operator()(const Vector<>& spots) const
00373     {
00374         double base_sigma = sqrt(variance); // should be 1
00375         double scale_pow = 100.0;
00376 
00377         const unsigned int nspots  = spots.size()/4;
00378         const unsigned int nframes = pixel_intensities.size();
00379         const unsigned int npixels = pixels.size();
00380         assert(spots.size() %4 == 0);
00381 
00382         //Compute the intensities and derivatives for all spot
00383         vector<vector<double> > spot_intensity; //[spot][pixel]
00384         for(unsigned int i=0; i < nspots; i++)
00385             spot_intensity.push_back(compute_spot_intensity(pixels, spots.slice<Dynamic,4>(i*4,4)));
00386         
00387         GibbsSampler sampler(pixel_intensities, spot_intensity, spots_to_vector(spots), A, pi, variance, sample_iterations);
00388 
00389         double sum = 0;
00390         Kahan ksum;
00391         for(int sample=0; sample < samples; sample++)
00392         {
00393             //Compute the positions of the surrounding steps
00394             double var1 = variance_from_sample(sample-2, samples, base_sigma, scale_pow);
00395             double var2 = variance_from_sample(sample-1, samples, base_sigma, scale_pow);
00396             double var3 = variance_from_sample(sample+1, samples, base_sigma, scale_pow);
00397             double var4 = variance_from_sample(sample+2, samples, base_sigma, scale_pow);
00398 
00399             //Take a sample
00400             sampler.set_variance(var2);
00401             sampler.next(DataForMCMC::get_rng());
00402             
00403             //Compute the SSD. This is fixed regardless of sigma.   
00404             double err_sum=0;
00405             for(unsigned int frame=0; frame < nframes; frame++)
00406                 for(unsigned int pixel=0; pixel < npixels; pixel++)
00407                     err_sum -= sq(pixel_intensities[frame][pixel] - sampler.sample_intensities()[frame][pixel]);
00408             
00409             //Compute the derivative using a five point stencil
00410             //This could be done in a better but less clear way
00411             double e1 = err_sum / (2*var1) - npixels*nframes*::log(2*M_PI*var1)/2;
00412             double e2 = err_sum / (2*var2) - npixels*nframes*::log(2*M_PI*var2)/2;
00413             double e3 = err_sum / (2*var3) - npixels*nframes*::log(2*M_PI*var3)/2;
00414             double e4 = err_sum / (2*var4) - npixels*nframes*::log(2*M_PI*var4)/2;
00415             sum += (-e1 + 8*e2 - 8*e3 + e4)/12;
00416 
00417             ksum.add(-e1/12);
00418             ksum.add(8*e2/12);
00419             ksum.add(-8*e3/12);
00420             ksum.add(e4/12);
00421         }
00422 
00423         double log_final = (log(variance_from_sample(samples, samples, base_sigma, scale_pow)*2*M_PI)/2) * npixels * nframes;
00424         
00425         double priors=0;
00426         for(unsigned int i=0; i < nspots; i++)
00427         {
00428             priors += log_log_normal(spots[i*4+0], mu_brightness, sigma_brightness);
00429             priors += log_log_normal(spots[i*4+1], mu_blur, sigma_blur);
00430         }
00431 
00432         /*cout << "Thermo:\n";
00433         cout << "sum: " << sum -log_final << endl;
00434         cout << "kah: " << ksum.sum -log_final << endl;
00435         cout << "priors: " << priors + sum -log_final << endl;
00436         cout << "   kah: " << priors + ksum.sum -log_final << endl;
00437 */
00438         //cout << log_final << endl;
00439         //cout << sum + log_final << endl;
00440         
00441         
00442         sampler.set_variance(variance);
00443         return -(sum+priors - log_final);
00444     }
00445 };
00446 
00447 /// Class for sorting a list of indexes to an array of spots lexicographically
00448 /// according to the 2D positions of the spots.
00449 ///
00450 ///@param Cmp comparator function to specify less or greater
00451 ///@param First most significant position index
00452 ///@ingroup gMultiSpot
00453 template<class Cmp, int First> struct IndexLexicographicPosition{
00454     const vector<Vector<4> >& spots;  ///< Keep around the array of spots for later comprison
00455     
00456     /// @param s Vector to sort indices of
00457     IndexLexicographicPosition(const vector<Vector<4> >& s)
00458     :spots(s)
00459     {}
00460     
00461 
00462     static const int Second = First==2?3:2; ///< Second most siginifcant position index for sorting
00463     
00464     /// Compare two indexes into the array of spots
00465     bool operator()(int a, int b)
00466     {
00467         Cmp cmp;
00468 
00469         if(cmp(spots[a][First], spots[b][First]))
00470             return true;
00471         else if(spots[a][First] == spots[b][First])
00472             return cmp(spots[a][Second], spots[b][Second]);
00473         else
00474             return false;
00475     }
00476 };
00477 
00478 
00479 ///Closure holding image data generated using samples drawn from the model.
00480 ///NB this is used with one spot removed (i.e. set to dark). As a result, the data
00481 ///is treated as the background when considering that spot in isolation.
00482 ///See FitSpots for naming of variables.
00483 ///@ingroup gStorm
00484 struct SampledBackgroundData
00485 {
00486     const vector<vector<vector<double> > >& sample_intensities_without_spot;    //[sample][frame][pixel]
00487     const vector<vector<double> >& pixel_intensities;    //[frame][pixel]
00488     const vector<ImageRef> pixels;
00489 
00490     double mu_brightness, sigma_brightness, mu_blur, sigma_blur;
00491     const Matrix<3> A;
00492     const Vector<3> pi;
00493     double variance;
00494 
00495     const vector<int> O;
00496 
00497     SampledBackgroundData(
00498         const vector<vector<vector<double> > >& sample_intensities_without_spot_,
00499         const vector<vector<double> >& pixel_intensities_,
00500         const vector<ImageRef> pixels_,
00501         double mu_brightness_, 
00502         double sigma_brightness_, 
00503         double mu_blur_, 
00504         double sigma_blur_,
00505         const Matrix<3> A_,
00506         const Vector<3> pi_,
00507         double variance_)
00508     :sample_intensities_without_spot(sample_intensities_without_spot_),
00509         pixel_intensities(pixel_intensities_),
00510         pixels(pixels_),
00511         mu_brightness(mu_brightness_),
00512         sigma_brightness(sigma_brightness_),
00513         mu_blur(mu_blur_),
00514         sigma_blur(sigma_blur_),
00515         A(A_),
00516         pi(pi_),
00517         variance(variance_),
00518         O(sequence(pixel_intensities.size()))
00519     {
00520     }
00521 };
00522 
00523 //!@cond Doxygen_Suppress
00524 //Do not use.
00525 struct SpotProbabilityWithSampledBackgroundFAKE: public SampledBackgroundData
00526 {   
00527     SpotProbabilityWithSampledBackgroundFAKE(const SampledBackgroundData& d)
00528     :SampledBackgroundData(d)
00529     {
00530     }
00531 
00532     //Compute the probability of spot
00533     double operator()(const Vector<4>& spot) const
00534     {
00535         vector<double> spot_intensities = compute_spot_intensity(pixels, spot);
00536 
00537         double sum_log_prob = 0;
00538 
00539         for(unsigned int s=0; s < sample_intensities_without_spot.size(); s++)
00540         {
00541             SpotWithBackground B(sample_intensities_without_spot[s], spot_intensities, pixel_intensities, variance);
00542             double log_prob = forward_algorithm(A, pi, B, O);
00543 
00544             double logprior = log_log_normal(spot[0], mu_brightness, sigma_brightness) + 
00545                           log_log_normal(spot[1], mu_blur, sigma_blur);
00546 
00547             //cout << setprecision(10) <<fixed <<  "Prob : " << log_prob + logprior << endl;
00548 
00549             sum_log_prob += log_prob + logprior;
00550         }
00551 
00552         double average_log_prob = sum_log_prob / sample_intensities_without_spot.size();
00553 
00554     //  cout << "Ave Prob : " << average_log_prob << endl;
00555 
00556         if(spot[0] < 0 || spot[1] < 0)
00557             return 1e100;
00558         
00559         return average_log_prob;
00560     }
00561 };
00562 //@endcond
00563 
00564 ///Compute the derivative of the negative log probability with respect
00565 ///to the parameters of one spot, given some samples of the other spots.
00566 ///@ingroup gStorm
00567 struct SpotNegProbabilityDiffWithSampledBackground: public SampledBackgroundData
00568 {   
00569     ///@param d Necessary data for construction
00570     SpotNegProbabilityDiffWithSampledBackground(const SampledBackgroundData& d)
00571     :SampledBackgroundData(d)
00572     {
00573     }
00574 
00575     ///Compute the probability of spot
00576     ///@param spot Spot position
00577     Vector<4> operator()(const Vector<4>& spot) const
00578     {
00579         if(spot[0] <= 0 || spot[1] <= 0)
00580             return Ones * std::numeric_limits<double>::quiet_NaN();
00581 
00582         vector<pair<double, Vector<4> > > spot_intensities = compute_spot_intensity_derivatives(pixels, spot);
00583 
00584         Vector<4> sum_diff_log = Zeros;
00585 
00586         for(unsigned int s=0; s < sample_intensities_without_spot.size(); s++)
00587         {
00588             SpotWithBackground B(sample_intensities_without_spot[s], spot_intensities, pixel_intensities, variance);
00589 
00590             pair<double, Vector<4> > r = forward_algorithm_deriv(A, pi, B, O);
00591             
00592             sum_diff_log += r.second;
00593         }
00594 
00595         Vector<4> diff_log = sum_diff_log / sample_intensities_without_spot.size();
00596 
00597         //Compute the log probability of the prior
00598         Vector<4> logprior_deriv = makeVector(diff_log_log_normal(spot[0], mu_brightness, sigma_brightness),
00599                                               diff_log_log_normal(spot[1], mu_blur, sigma_blur), 0, 0);
00600         
00601         return -(diff_log + logprior_deriv);
00602     }
00603 };
00604 
00605 
00606 ///Class for computing the Hessian of the negative free energy.
00607 ///@ingroup gStorm
00608 class FreeEnergyHessian: public DataForMCMC
00609 {
00610     public:
00611     
00612     ///Constructor
00613     ///@param d All data required
00614     FreeEnergyHessian(const DataForMCMC& d)
00615     :DataForMCMC(d)
00616     {
00617     }
00618     
00619     ///Compute the Hessian
00620     ///@param spots All spot positions
00621     ///@param spot spot to compute hessian for
00622     Matrix<4> hessian(const vector<Vector<4> >& spots, int spot) const
00623     {
00624         cout << "----Computing pure MCMC hessian\n";
00625         const unsigned int nspots  = spots.size();
00626         const unsigned int nframes = pixel_intensities.size();
00627         const unsigned int npixels = pixels.size();
00628         cout << spot << " " << nspots << " " << nframes << " " << npixels << endl;
00629 
00630         vector<vector<double> > spot_intensity; //[spot][pixel]
00631         for(unsigned int i=0; i < nspots; i++)
00632             spot_intensity.push_back(compute_spot_intensity(pixels, spots[i]));
00633 
00634         vector<tuple<double, Vector<4>, Matrix<4> > > spot_hess_etc = compute_spot_intensity_hessian(pixels, spots[spot]);
00635 
00636         GibbsSampler sampler(pixel_intensities, spot_intensity, spots, A, pi, variance, sample_iterations);
00637         
00638         //Compute derivative of log probability, summed (ie integrated)
00639         Matrix<4> sum_hess1 = Zeros(spots.size());
00640         Matrix<4> sum_hess2 = Zeros(spots.size());
00641         Vector<4> sum_deriv = Zeros(spots.size());
00642 
00643         for(int sample=0; sample < samples; sample++)
00644         {
00645             sampler.next(rng);
00646 
00647             //Compute d log P(data | x, model) / d model, for a given sample
00648             //And the hessian
00649             Matrix<4> hess = Zeros(spots.size());
00650             Vector<4> deriv = Zeros(spots.size());
00651             for(unsigned int frame=0; frame < nframes; frame++)
00652             {
00653                 for(unsigned int pixel=0; pixel < npixels; pixel++)
00654                 {
00655                     double e = pixel_intensities[frame][pixel] - sampler.sample_intensities()[frame][pixel];
00656                     //Build up the derivative
00657                     if(sampler.sample()[spot][frame] == 0)
00658                     {
00659                         hess += e * get<2>(spot_hess_etc[pixel]) - get<1>(spot_hess_etc[pixel]).as_col() * get<1>(spot_hess_etc[pixel]).as_row();
00660                         deriv += e * get<1>(spot_hess_etc[pixel]);
00661 
00662                     }
00663                 }
00664             }
00665 
00666             hess[0][0] += hess_log_log_normal(spots[spot][0], mu_brightness, sigma_brightness);
00667             hess[1][1] += hess_log_log_normal(spots[spot][1], mu_blur, sigma_blur);
00668             sum_hess1 += hess;
00669 
00670             deriv[0] += diff_log_log_normal(spots[spot][0], mu_brightness, sigma_brightness);
00671             deriv[1] += diff_log_log_normal(spots[spot][1], mu_blur, sigma_blur);
00672 
00673             sum_hess2 += deriv.as_col() * deriv.as_row();
00674 
00675             sum_deriv = sum_deriv + deriv;
00676         }
00677 
00678         sum_hess1 /= (samples * variance);
00679         sum_hess2 /= (samples * variance);
00680         sum_deriv /= (samples * variance);
00681 
00682         
00683         cout << sum_hess1 << endl;
00684         cout << sum_hess2 << endl;
00685         cout << sum_deriv.as_col() * sum_deriv.as_row() <<  endl;
00686 
00687         cout << "......." << sum_deriv << endl;
00688         //Put in the prior
00689         //The derivative prior parts cancel out.
00690         //Rather sensibly this means that the second derivatives can be
00691         //computed without reference to the prior, and then the prior can
00692         //be added in later, i.e.: P(data, parameters) = P(data|parameter) P(parameters)
00693 
00694         //The second derivatives have been constructed to be diagonal
00695         DiagonalMatrix<4> hess_prior = Zeros(spots.size());
00696 
00697         cout << "sum of parts = \n" << sum_hess1 + sum_hess2 - sum_deriv.as_col() * sum_deriv.as_row() << endl;
00698         //TooN cannot currently add DiagonalMatrix to Matrix!!
00699         //sum_hess.diagonal_slice() += hess_prior.diagonal_slice();
00700 
00701         cout << "++++Done Computing pure MCMC hessian\n";
00702         return sum_hess1 + sum_hess2 - sum_deriv.as_col() * sum_deriv.as_row();
00703     }
00704 };
00705 
00706 ///Comparator functor for the first element of a std::pair
00707 struct LessSecond
00708 {
00709     ///Comparison function
00710     ///@param a
00711     ///@param b
00712     template<class A, class B> bool operator()(const pair<A,B>& a, const pair<A,B>& b) const
00713     {
00714         return a.second < b.second;
00715     }
00716 };
00717 
00718 //!@cond Doxygen_Suppress
00719 struct NthDeriv{
00720 
00721     const SpotNegProbabilityDiffWithSampledBackground& compute_deriv;
00722     int i;
00723 
00724     NthDeriv(const SpotNegProbabilityDiffWithSampledBackground& c, int ii)
00725     :compute_deriv(c),i(ii)
00726     {}
00727 
00728     double  operator()(const Vector<4>& f) const
00729     {
00730         return compute_deriv(f)[i];
00731     }
00732 };
00733 //!@endcond
00734 
00735 ///Compute the Hessian of the log probability. The background is sampled rather sparsely, and the 
00736 ///spot in question is sampled much more densely using FFBS.
00737 ///@param spot Spot parameters
00738 ///@param d Background brightness (from other spots)
00739 ///@param bs_iterations Exter backward sampling iterations
00740 ///@param rng Random number generator
00741 ///@returns the Hessian of the log probability around the spot
00742 Matrix<4> sampled_background_spot_hessian_ffbs(const Vector<4>& spot, const SampledBackgroundData& d, int bs_iterations, MT19937& rng)
00743 {
00744     vector<tuple<double, Vector<4>, Matrix<4> > > spot_hess_etc = compute_spot_intensity_hessian(d.pixels, spot);
00745     vector<double> spot_intensities = compute_spot_intensity(d.pixels, spot);
00746 
00747     Matrix<4> sum_hess_log = Zeros;
00748     Matrix<4> sum_diff2_log = Zeros;
00749 
00750     vector<State> current_sample;
00751 
00752     const unsigned int nframes = d.pixel_intensities.size();
00753     const unsigned int npixels = d.pixels.size();
00754 
00755     Matrix<4> sum_hess  = Zeros;
00756     Vector<4> sum_deriv = Zeros;
00757     
00758     vector<pair<Matrix<4>, Vector<4> > > hess_and_deriv_part(nframes);
00759     
00760     for(unsigned int s=0; s < d.sample_intensities_without_spot.size(); s++)
00761     {
00762         SpotWithBackground B(d.sample_intensities_without_spot[s], spot_intensities, d.pixel_intensities, d.variance);
00763         
00764         //Compute what the per-frame hess and deriv parts are
00765         //if the spot is on in a frame.
00766         for(unsigned int frame=0; frame < nframes; frame++)
00767         {
00768             Matrix<4> hess = Zeros;
00769             Vector<4> deriv = Zeros;
00770 
00771             for(unsigned int pixel=0; pixel < npixels; pixel++)
00772             {
00773                 double e = d.pixel_intensities[frame][pixel] - (d.sample_intensities_without_spot[s][frame][pixel] + spot_intensities[pixel]);
00774                 //Build up the derivative
00775                 hess += e * get<2>(spot_hess_etc[pixel]) - get<1>(spot_hess_etc[pixel]).as_col() * get<1>(spot_hess_etc[pixel]).as_row();
00776                 deriv += e * get<1>(spot_hess_etc[pixel]);
00777             }
00778             hess_and_deriv_part[frame] = make_pair(hess, deriv);
00779         }
00780         
00781         //Forward filtering
00782         std::vector<array<double, 3> > delta = forward_algorithm_delta(d.A, d.pi, B, d.O);
00783         
00784         for(int i=0; i < bs_iterations; i++)
00785         {
00786             current_sample = backward_sampling<3,State>(d.A, delta, rng);
00787 
00788             Matrix<4> hess = Zeros;
00789             Vector<4> deriv = Zeros;
00790             for(unsigned int frame=0; frame < nframes; frame++)
00791                 if(current_sample[frame] == 0)
00792                 {
00793                         hess += hess_and_deriv_part[frame].first;
00794                         deriv += hess_and_deriv_part[frame].second;
00795                 }
00796 
00797             sum_hess += hess + deriv.as_col() * deriv.as_row();
00798             sum_deriv += deriv;
00799         }
00800     }
00801 
00802     sum_hess  /= (bs_iterations * d.sample_intensities_without_spot.size() * d.variance);
00803     sum_deriv /= (bs_iterations * d.sample_intensities_without_spot.size() * d.variance);
00804 
00805     sum_hess -= sum_deriv.as_col() * sum_deriv.as_row();
00806 
00807     sum_hess[0][0] += hess_log_log_normal(spot[0], d.mu_brightness, d.sigma_brightness);
00808     sum_hess[1][1] += hess_log_log_normal(spot[1], d.mu_blur, d.sigma_blur);
00809     sum_deriv[0] += diff_log_log_normal(spot[0], d.mu_brightness, d.sigma_brightness);
00810     sum_deriv[1] += diff_log_log_normal(spot[1], d.mu_blur, d.sigma_blur);
00811 
00812     //cout << "Turboderiv:" << sum_deriv << endl;
00813     //cout << "Turbohess:\n" << sum_hess << endl;
00814 
00815     return sum_hess;
00816 }
00817 
00818 ///Debugging function. Not mathematically correct. Do not use.
00819 Matrix<4> sampled_background_spot_hessian2(const Vector<4>& spot, const SampledBackgroundData& d)
00820 {
00821     vector<tuple<double, Vector<4>, Matrix<4> > > spot_intensities = compute_spot_intensity_hessian(d.pixels, spot);
00822 
00823     Matrix<4> sum_hess_log = Zeros;
00824     Matrix<4> sum_diff2_log = Zeros;
00825 
00826     for(unsigned int s=0; s < d.sample_intensities_without_spot.size(); s++)
00827     {
00828         SpotWithBackground B(d.sample_intensities_without_spot[s], spot_intensities, d.pixel_intensities, d.variance);
00829 
00830         double prob;
00831         Vector<4> diff;
00832         Matrix<4> hess;
00833 
00834         tie(prob, diff, hess) = forward_algorithm_hessian(d.A, d.pi, B, d.O);
00835         
00836         sum_hess_log += hess;
00837 
00838         diff += makeVector(diff_log_log_normal(spot[0], d.mu_brightness, d.sigma_brightness), diff_log_log_normal(spot[1], d.mu_blur, d.sigma_blur), 0, 0);
00839         sum_diff2_log += diff.as_col() * diff.as_row();
00840     }
00841 
00842     Matrix<4> hess_log = sum_hess_log / d.sample_intensities_without_spot.size();
00843     Matrix<4> diff2_log = sum_diff2_log / d.sample_intensities_without_spot.size();
00844 
00845     //Add in the prior
00846 
00847     hess_log[0][0] += hess_log_log_normal(spot[0], d.mu_brightness, d.sigma_brightness);
00848     hess_log[1][1] += hess_log_log_normal(spot[1], d.mu_blur, d.sigma_blur);
00849 
00850     return hess_log + diff2_log;
00851 }
00852 
00853 ///Debugging function. Not mathematically correct. Do not use.
00854 Matrix<4> sampled_background_spot_hessian_FAKE(const Vector<4>& spot, const SampledBackgroundData& d)
00855 {
00856     vector<tuple<double, Vector<4>, Matrix<4> > > spot_intensities = compute_spot_intensity_hessian(d.pixels, spot);
00857 
00858     Matrix<4> sum_hess_log = Zeros;
00859 
00860     for(unsigned int s=0; s < d.sample_intensities_without_spot.size(); s++)
00861     {
00862         SpotWithBackground B(d.sample_intensities_without_spot[s], spot_intensities, d.pixel_intensities, d.variance);
00863 
00864         double prob;
00865         Vector<4> diff;
00866         Matrix<4> hess;
00867 
00868         tie(prob, diff, hess) = forward_algorithm_hessian(d.A, d.pi, B, d.O);
00869         
00870         sum_hess_log += hess;
00871     }
00872 
00873     Matrix<4> hess_log = sum_hess_log / d.sample_intensities_without_spot.size();
00874 
00875     //Add in the prior
00876 
00877     hess_log[0][0] += hess_log_log_normal(spot[0], d.mu_brightness, d.sigma_brightness);
00878     hess_log[1][1] += hess_log_log_normal(spot[1], d.mu_blur, d.sigma_blur);
00879     
00880     return hess_log;
00881 }
00882 
00883 ///Which pixels belong to a given spot?
00884 ///Find the indices of those pixels
00885 ///@ingroup gStorm
00886 void get_spot_pixels(const vector<ImageRef>& pixels, const Vector<4>& spot, vector<int>& out)
00887 {
00888     //Go out to three sigma
00889 
00890     vector<ImageRef> pix = getDisc(spot[1]*6 + 1);
00891     out.resize(0);
00892     ImageRef offset = ir_rounded(spot.slice<2,2>());
00893     for(unsigned int j=0; j < pix.size(); j++)
00894     {
00895         int pos = lower_bound(pixels.begin(), pixels.end(), pix[j] + offset) - pixels.begin();
00896         if(pos != (int)pixels.size() && pixels[pos] == pix[j] + offset)
00897             out.push_back(pos);
00898     }
00899 
00900     if(out.size() == 0)
00901     {
00902         cout << "********************************\n";
00903         cout << "********************************\n";
00904         cout << "********************************\n";
00905         cout << "********************************\n";
00906         cout << "********************************\n";
00907         cout << "Oe noes!11one\n";
00908         cout << pix.size() << endl;
00909     }
00910 }
00911 
00912 
00913 ///Tokenize a line
00914 ///@ingroup gUtility
00915 vector<string> split(const string& line)
00916 {
00917     vector<string> v;
00918     istringstream i(line);
00919     string s;
00920 
00921     while(!i.eof())
00922     {
00923         i >> s;
00924         if(i.fail())
00925             break;
00926         v.push_back(s);
00927     }
00928     return v;
00929 }
00930 
00931 ///Generic version of itoa.
00932 ///How many times has this been reimplemented??
00933 ///@param x Value to convert to string
00934 ///@ingroup gUtility
00935 template<class C> inline string xtoa(const C& x)
00936 {
00937     ostringstream os;
00938     os << x;
00939     return os.str();
00940 }
00941 
00942 ///Inverse of xtoa()
00943 ///How many times has this been reimplemented??
00944 ///@param s String to convert
00945 ///@param msg Mesage to print on error
00946 ///@ingroup gUtility
00947 template<class C> inline C atox(const string& s, const string& msg)
00948 {
00949     C c;
00950     istringstream i(s);
00951     i >> c;
00952     if(i.fail())
00953         throw LogFileParseError("Error parsing " + msg + ". Text is `" + s + "'.");
00954     return c;
00955 }
00956 
00957 /**Parser for multispot 5 log files. 
00958 
00959 Log files are mostly line oriented and contain various records
00960 
00961 The main records are:
00962 
00963 Iteraton: \#ITNUM
00964 MAIN: <list of spot parameters> 
00965 
00966 Pass: \#PASSNUM
00967 MT19937 <random number generator state>
00968 PASS\#PASSNUM: <list of spot parameters>
00969 ENDCHECKPOINT
00970 
00971 Note that MAIN is redundant since it will be the same as the following PASS 1 (or the first pass
00972 computed if restoring from a checkpoint).
00973 
00974 Data should only be considered valid after ENDCHECKPOINT has been read
00975 
00976 Iteration is written once per iteration, not once per pass. (FIXME)
00977 
00978 Which moron invented this file format???
00979 
00980 Note that the file format hasn't beren fixed, so that the output can easily be compared to the 
00981 output of the historic version which is known to be good.
00982 
00983 @param in Stream to parse file from
00984 @ingroup gStorm
00985 */
00986 StateParameters parse_log_file(istream& in)
00987 {
00988     //A line read from the file
00989     string line;
00990 
00991     //State lines known to be OK
00992     string rngline, passline, iterationline;
00993     bool state_ok=0;
00994     
00995     //State lines read in, with flags of goodness
00996     string new_rngline, new_passline, new_iterationline;
00997     bool new_rngline_ok=0, new_passline_ok=0, new_iterationline_ok=0;
00998 
00999     unsigned int lineno=0;
01000     bool doing_gvars = 0;
01001 
01002     vector<ImageRef> pixels;
01003 
01004     while(!in.eof())
01005     {   
01006         getline(in, line);
01007         if(in.fail())
01008             break;
01009         
01010         lineno++;
01011         
01012         if(line == "ENDGVARLIST")
01013         {
01014             if(!doing_gvars)
01015                 throw LogFileParseError("Spurious end of GVars");
01016             doing_gvars = 0;
01017         }
01018         else if(doing_gvars)
01019         {
01020             GUI.ParseLine(line);
01021         }
01022         else if(line == "BEGINGVARLIST")
01023         {
01024             doing_gvars = 1;
01025         }
01026         if(line.substr(0, 11)  == "Iteration: ")
01027         {
01028             new_iterationline = line;
01029             new_iterationline_ok = true;
01030         }
01031         else if(line.substr(0, 4) == "PASS")
01032         {
01033             new_passline = line;
01034             if(new_passline_ok)
01035                 throw LogFileParseError("Duplicate PASS on line " + xtoa(lineno));
01036             new_passline_ok = true;
01037         }
01038         else if(line.substr(0, 8) == "MT19937 ")
01039         {
01040             new_rngline = line;
01041             if(new_rngline_ok)
01042                 throw LogFileParseError("Duplicate MT19937 on line " + xtoa(lineno));
01043             
01044             new_rngline_ok = true;
01045 
01046         }
01047         else if(line == "ENDCHECKPOINT")
01048         {
01049             if(new_passline_ok && new_rngline_ok && new_iterationline_ok)
01050             {
01051                 iterationline = new_iterationline;
01052                 rngline = new_rngline;
01053                 passline = new_passline;    
01054             }
01055             else
01056                 throw LogFileParseError("Reached checkpoint with missing data: "
01057                          "it=" + xtoa(new_iterationline_ok) + 
01058                         " pa=" + xtoa(new_passline_ok) + 
01059                         " rg=" + xtoa(new_rngline_ok) + " on line " + xtoa(lineno));
01060             
01061             //Don't reset iteration since it only appears once for each entire
01062             //set of passes. 
01063             new_rngline_ok = 0;
01064             new_passline_ok = 0;
01065 
01066             state_ok = true;
01067         }
01068         else if(line.substr(0, 7) == "PIXELS ")
01069         {
01070             vector<string> l = split(line);
01071             if( (l.size() - 1)%2 == 0)
01072             {
01073                 int n = (l.size()-1)/2;
01074                 pixels.resize(n);
01075                 for(int i=0; i < n; i++)
01076                 {
01077                     pixels[i].x = atox<int>(l[i*2+1+0], "pixels");
01078                     pixels[i].y = atox<int>(l[i*2+1+1], "pixels");
01079                 }
01080             }
01081             else
01082                 throw LogFileParseError("Bad PIXELS line");
01083         }
01084     }
01085 
01086     if(!state_ok)
01087         throw LogFileParseError("No state found");
01088     
01089     if(pixels.size() == 0)
01090         throw LogFileParseError("No pixels, or pixels is empty");
01091 
01092     //Now parse the lines
01093     StateParameters p;
01094     vector<string> l;
01095     
01096     //Parse the iterations
01097     l = split(iterationline);
01098     p.iteration = atox<int>(l[1], "iteration");
01099 
01100     //Parse the random number generator
01101     p.rng =shared_ptr<MT19937>(new MT19937);
01102     {
01103         istringstream rng_s(rngline);
01104         try{
01105             p.rng->read(rng_s);
01106         }
01107         catch(MT19937::ParseError p)
01108         {
01109             throw LogFileParseError("Error parsing MT19937");
01110         }
01111     }
01112 
01113     //Parse PASS and the listing of spots
01114     l = split(passline);
01115     if( (l.size() - 1 ) % 4 == 0)
01116     {
01117         p.pass = atox<int>(l[0].substr(4), "pass");
01118 
01119         for(unsigned int i=0; i < (l.size()-1)/4; i++)
01120         {
01121             cout << l[i*4+1+0] << endl;
01122             cout << l[i*4+1+1] << endl;
01123             cout << l[i*4+1+2] << endl;
01124             cout << l[i*4+1+3] << endl;
01125             p.spots.push_back(makeVector(
01126                         atox<double>(l[i*4+1+0], "spot"),
01127                         atox<double>(l[i*4+1+1], "spot"),
01128                         atox<double>(l[i*4+1+2], "spot"),
01129                         atox<double>(l[i*4+1+3], "spot")));
01130         }
01131 
01132     }
01133     else
01134         throw LogFileParseError("Wrong number of elements in PASS line");
01135 
01136     //Set up the pixels (oh god the pixels)
01137     p.pixels = pixels;
01138 
01139     return p;   
01140 }
01141 
01142 
01143 
01144 ///Setup the parameters for a run using the old and deeply peculiar method.
01145 ///This includes the unpleasant and diffucult so use de-checkpointing code.
01146 ///wtf. The use of this function is very strongly deprecated.
01147 ///@param log_ratios Image from which region is selected.
01148 ///@param ims  Input data
01149 ///@param pixels Region for spot fitting to run in
01150 StateParameters generate_state_parameters_ye_olde(const BasicImage<double>& log_ratios, const vector<Image<float> >& ims, vector<ImageRef> pixels){
01151     sort(pixels.begin(), pixels.end());
01152 
01153     const double variance = 1; // it should be
01154 
01155     //To scale the X axis of a log-normal distribution, only
01156     //the mu parameter needs to be changed...
01157     const double intensity_mu = GV3::get<double>("intensity.rel_mu", 0., -1)  + log(sqrt(variance));
01158     const double intensity_sigma = GV3::get<double>("intensity.rel_sigma", 0., -1);
01159     const double blur_mu = GV3::get<double>("blur.mu", 0., -1);
01160     const double blur_sigma = GV3::get<double>("blur.sigma", 0., -1);
01161 
01162     //The region was extracted at a certain threshold.
01163     //These regions may be too small, so some post-region finding dilation 
01164     //may be performed. New spots are only placed at pixels which exceed the threshold.
01165     //post_dilate.threshold is (if set) used as the placing threshold so the placing threshold
01166     //can be different from the region-finding threshold.
01167 
01168     //Note that as a result of dliation, regions of <pixels> may be below the threshold.
01169     //In the historic version, this could affect new spot placement. This feature is not supported
01170     //in this version.
01171     double threshold = GV3::get<double>("threshold", 0, -1);
01172     const double post_threshold = GV3::get<double>("post_dilate.threshold", -1, 1);
01173     if(post_threshold != -1)
01174         threshold = post_threshold;
01175 
01176     
01177     //If dilation after region finding is to be performed, then do it here.
01178     const double post_dilate_radius = GV3::get<double>("post_dilate.radius", 0, -1);
01179     if(post_dilate_radius != 0)
01180     {
01181         Image<byte> pix(ims[0].size());
01182         pix.fill(0);
01183         
01184         for(unsigned int i=0; i < pixels.size(); i++)
01185             pix[pixels[i]] = 255;
01186 
01187         Image<byte> dilated = morphology(pix, getDisc(post_dilate_radius), Morphology::BinaryDilate<byte>());
01188 
01189         pixels.clear();
01190 
01191         ImageRef p(0,0);
01192         do
01193             if(dilated[p])
01194                 pixels.push_back(p);
01195         while(p.next(dilated.size()));
01196     }
01197 
01198 
01199     assert_same_size(ims);
01200     if(log_ratios.size() != ims[0].size())
01201     {
01202         cerr << "Bad log ratios size\n";
01203         exit(1);
01204     }
01205 
01206     vector<Vector<4> > spots;
01207     //Spots can be either put down automatically, or specified 
01208     //The auto-initialization is very strange.
01209     if(GV3::get<bool>("spots.auto_initialise", 1, 1))
01210     {
01211         //You never get two spots in the same disc in the second stage of the algorithm
01212         vector<ImageRef> disc = getDisc(GV3::get<double>("spot_spread", 3.1, 1));
01213         
01214         //Record all the pixels
01215         map<ImageRef, double> valid_pixels;
01216         for(unsigned int i=0; i < pixels.size(); i++)
01217             if(log_ratios[pixels[i]] > threshold)
01218                 valid_pixels.insert(make_pair(pixels[i], log_ratios[pixels[i]]));
01219 
01220 
01221         //Get some initial spots by finding the local maxima
01222         ImageRef neighbours[8] = {
01223             ImageRef(-1, -1),
01224             ImageRef( 0, -1),
01225             ImageRef( 1, -1),
01226 
01227             ImageRef(-1,  0),
01228             ImageRef( 1,  0),
01229 
01230             ImageRef(-1,  1),
01231             ImageRef( 0,  1),
01232             ImageRef( 1,  1),
01233         };
01234         for(unsigned int i=0; i < pixels.size(); i++)
01235         {
01236             if(!(log_ratios[pixels[i]] > threshold))
01237                 goto not_a_maximum;
01238 
01239             for(int j=0; j < 8; j++)
01240                 if(!log_ratios.in_image(pixels[i] + neighbours[j]) || ! (log_ratios[pixels[i]] > log_ratios[pixels[i] + neighbours[j]]))
01241                     goto not_a_maximum;
01242             
01243             spots.push_back(makeVector(log_normal_mode(intensity_mu, intensity_sigma), log_normal_mode(blur_mu, blur_sigma), pixels[i].x, pixels[i].y));
01244 
01245             //Remove the pixels around the initial spots
01246             for(unsigned int j=0; j < disc.size(); j++)
01247                 valid_pixels.erase(pixels[i] + disc[j]);
01248 
01249             not_a_maximum:;
01250         }
01251 
01252         for(unsigned int i=0; i < spots.size(); i++)
01253             cout << spots[i] << endl;
01254         
01255         //Now place down extra spots in the remaining space.
01256         while(!valid_pixels.empty())
01257         {
01258             ImageRef p = max_element(valid_pixels.begin(), valid_pixels.end(), LessSecond())->first;
01259             spots.push_back(makeVector(log_normal_mode(intensity_mu, intensity_sigma), log_normal_mode(blur_mu, blur_sigma), p.x, p.y));
01260 
01261             for(unsigned int j=0; j < disc.size(); j++)
01262                 valid_pixels.erase(p + disc[j]);
01263         }
01264         
01265         //This line allows extra spots to be placed down around each spot already put down.
01266         //This is a shocking hack and jenerally very unpleasant.
01267         double extra_r = GV3::get<double>("extra_spots", 0, 1);
01268         vector<ImageRef> extra = getDisc(extra_r);
01269         vector<Vector<4> > more_spots;
01270         for(unsigned int i=0; i < extra.size(); i++)
01271             if(extra[i] != ImageRef_zero)
01272                 for(unsigned int j=0; j < spots.size(); j++)
01273                     more_spots.push_back(spots[j] + makeVector(0, 0, extra[i].x, extra[i].y) / (2*extra_r+1));
01274 
01275         copy(more_spots.begin(), more_spots.end(), back_inserter(spots));
01276     }
01277     else
01278     {
01279         Vector<>  loaded_spots = GV3::get<Vector<> >("spots.manual_spots", "", -1);
01280 
01281         if(loaded_spots.size()%4 != 0)
01282         {
01283             cerr << "Loaded spot size is not a multiple of 4\n";
01284             exit(1);
01285         }
01286 
01287         else    
01288             spots = spots_to_vector(loaded_spots);
01289     }
01290 
01291     //Initialize the MT19937 RNG from a seed.
01292     shared_ptr<MT19937> rng(new MT19937);
01293     rng->simple_seed(GV3::get<int>("seed", 0, 1));
01294         
01295     //Load in a checkpoint (precise RNG state, iteration and pass).
01296     int start_iteration=0;
01297     int start_pass=0;
01298     if(GV3::get<bool>("checkpoint", 0, 1))
01299     {
01300         string rng_state = GV3::get<string>("checkpoint.rng.state", "", -1);
01301         istringstream rs(rng_state);
01302         rng->read(rs);
01303         start_iteration=GV3::get<int>("checkpoint.iteration", 0, -1);
01304         start_pass=GV3::get<int>("checkpoint.pass", 0, -1);
01305     }
01306     
01307     StateParameters p;
01308     p.spots = spots;
01309     p.rng = rng;
01310     p.pass = start_pass;
01311     p.iteration = start_iteration;
01312     p.pixels = pixels;
01313 
01314     return p;
01315 }
01316 
01317 ///Very simple and inefficient dilation function.
01318 ///@ingroup gUtility
01319 set<ImageRef>  dilate_mask(const vector<ImageRef>& v, double r)
01320 {
01321     vector<ImageRef> m = getDisc(r);
01322 
01323     set<ImageRef> ret;
01324 
01325     for(unsigned int i=0; i < v.size(); i++)
01326         for(unsigned int j=0; j < m.size(); j++)
01327             ret.insert(v[i] + m[j]);
01328 
01329     return ret;
01330 }
01331 
01332 ///How far should steps in brightness be limited to?
01333 ///@ingroup gStorm
01334 double brightness_motion_limit(double mu, double sigma, bool not_one)
01335 {
01336     if(not_one)
01337         return log_normal_std(mu, sigma);
01338     else
01339         return 1;
01340 }
01341 
01342 
01343 
01344 
01345 ///Mega class which actually does the meat of the spot fitting.
01346 ///probably could be refactored a bit.
01347 ///@ingroup gStorm
01348 class FitSpots
01349 {
01350     const vector<Image<float> >& ims; ///< Input data
01351     FitSpotsGraphics& graphics;       ///< Graphics class.
01352     UserInterfaceCallback& ui;        ///< Callbacks to provide user interface
01353     const vector<ImageRef> pixels;    ///< Area in which to perform model fitting
01354 
01355     //Spot positions
01356     vector<Vector<4> > spots;         ///< State in terms of current spot positions
01357     
01358     //Starting point
01359     const int start_iteration;        ///< Starting iteration number (for restarting from checkpoint)
01360     int start_pass;                   ///< Starting pass (for restarting from checkpoint)
01361 
01362     MT19937& rng;                     ///< Random numbewr generator
01363 
01364     const double variance;            ///< Variance of noise in data. Must be 1.
01365     const double intensity_mu;        ///< Prior for spot intensity
01366     const double intensity_sigma;     ///< Prior for spot intensity
01367     const double blur_mu;             ///< Prior for spot shape
01368     const double blur_sigma;          ///< Prior for spt shape
01369 
01370     //pixels is dilated slightly, by a disk of size area_extra_radius.
01371     //The result is stored in allowed_area. This is used to implement a uniform
01372     //prior over position, which is uniform within allowed_area, and zero
01373     //everywhere else.
01374     //
01375     //This is implemented as a set, because the mask may extend beyond the borders of the 
01376     //image slightly
01377     const double area_extra_radius;   ///< Extra size beyone marked region in which spots are allowed to exist
01378     set<ImageRef> allowed_area;       ///< Total allowed region, pixels dilated by area_extra_radius
01379     const int use_position_prior;     ///< Should a proper prior over position be uesd? A clue: yes.
01380     const double position_prior;      ///< Value for the posision prior, i.e. reciprocal of area
01381     
01382     //General optimizing and sampling parameters
01383     const double max_motion;          ///< Maximum motion on any axes for optimization. See ConjugateGradientOnly.
01384     const int sample_iterations;      ///< Number of mixing samples to use in Gibbs sampling
01385     
01386     //Task specific optimizing and sampling parameters:
01387 
01388     //Main optimization loop
01389     const int main_cg_max_iterations;  ///< Maximum iterations allowed for ConjugateGradientOnly in main optimization loop
01390     const int main_samples;            ///< Number of samples to use in main loop
01391     const int main_passes;             ///< Number of passes to perform per iteration in main loop
01392     const int outer_loop_iterations;   ///< Total number of iterations to perform
01393     
01394     //Spot selection loop
01395     const int add_remove_tries;        ///< Number of attemts to add/remove a spot
01396     const int add_remove_opt_samples;  ///< Number of samples to use in model modification phase
01397     const int add_remove_opt_retries;  ///< Number of attempts restarting the optimization to escape saddle points
01398     const int add_remove_opt_hess_inner_samples; ///< Number of extra FFBS samples to use for computing Hessian when testing for convergence to non-saddle point
01399     const int h_outer_samples;         ///< Number of samples used for computing Hessian as part of Laplace's approximation
01400     const int h_inner_samples;         ///< Number of additional FFBS samples to use for computing Hessian as part of Laplace's approximation
01401     const int tsamples;                ///< Number of samples to use in thermodynamic integration
01402 
01403     // Average of all inputs (used for debugging)
01404     const Image<float> ave;            ///< Average of input data: used for 
01405     
01406 
01407     //File to save output to
01408     ofstream& save_spots;               ///< Output stream for log file
01409     
01410     //Time accumulators for benchmarking
01411     double time_gibbs;                  ///< Benchmarking data
01412     double time_cg;                     ///< Benchmarking data
01413     
01414     ///Motion limit for ConjugateGradientOnly
01415     ///The x distance, y distance and spot size are all approximately the same scale
01416     ///which is of order 1. The brigntness is not. By default, the brightness limit is also 1.
01417     ///This flag controls whether is should be set to the standard deviation of the brightness prior
01418     ///distribution. This setting will put the motion limit on the same scale as the other three
01419     ///parameters.
01420     const bool scale_brightness_limit; 
01421     const Vector<4> limit;              ///< Limit vector for ConjugateGradientOnly
01422     
01423     const Matrix<3> A;                  ///< Transition matrix 
01424     const Vector<3> pi;                 ///< Initial probabilities
01425 
01426     
01427     vector<vector<double> > pixel_intensities; ///<Pixel intensities for all images [frame][pixel]
01428 
01429     DataForMCMC data_for_t_mcmc;  ///<Aggergated data for thermodynamic integration
01430     DataForMCMC data_for_h_mcmc;  ///<Aggergated data for finding hessian
01431     
01432     int iteration;                     ///< Iteration number
01433 
01434 
01435     TIME(cvd_timer timer;)
01436     public:
01437 
01438     FitSpots(const vector<Image<float> >& ims_, FitSpotsGraphics& graphics_, UserInterfaceCallback& ui_, StateParameters& params, ofstream& save_spots_)
01439     :ims(ims_), graphics(graphics_),ui(ui_),
01440      
01441      //Set up the main parameters
01442      pixels(params.pixels),
01443      spots(params.spots),
01444      start_iteration(params.iteration),
01445      start_pass(params.pass),
01446      rng(*params.rng),
01447 
01448 
01449      
01450      //Set up all the system parameters
01451      variance(1), // it should be
01452 
01453      //To scale the X axis of a log-normal distribution, only
01454      //the mu parameter needs to be changed...
01455      intensity_mu(GV3::get<double>("intensity.rel_mu", 0., -1)  + log(sqrt(variance))),
01456      intensity_sigma(GV3::get<double>("intensity.rel_sigma", 0., -1)),
01457      blur_mu(GV3::get<double>("blur.mu", 0., -1)),
01458      blur_sigma(GV3::get<double>("blur.sigma", 0., -1)),
01459  
01460      //Spot position prior
01461      area_extra_radius(GV3::get<double>("position.extra_radius", 0., -1)),
01462      allowed_area(dilate_mask(pixels, area_extra_radius)),
01463      use_position_prior(GV3::get<bool>("position.use_prior", true, -1)),
01464      position_prior(1.0 / allowed_area.size()),
01465         
01466      //General optimizing and sampling parameters
01467      max_motion(GV3::get<double>("cg.max_motion", 0., -1)),
01468      sample_iterations(GV3::get<int>("gibbs.mixing_iterations", 0, -1)),
01469      
01470      //Task specific optimizing and sampling parameters:
01471  
01472      //Main optimization loop
01473      main_cg_max_iterations(GV3::get<double>("main.cg.max_iterations", 0., -1)),
01474      main_samples(GV3::get<int>("main.gibbs.samples", 0, -1)),
01475      main_passes(GV3::get<int>("main.passes", 0, -1)),
01476      outer_loop_iterations(GV3::get<int>("main.total_iterations", 100000000, 1)),
01477      
01478      //Spot selection loop
01479      add_remove_tries(GV3::get<int>("add_remove.tries", 0, -1)),
01480      add_remove_opt_samples(GV3::get<int>("add_remove.optimizer.samples", 0, -1)),
01481      add_remove_opt_retries(GV3::get<int>("add_remove.optimizer.attempts", 0, -1)),
01482      add_remove_opt_hess_inner_samples(GV3::get<int>("add_remove.optimizer.hessian_inner_samples", 0, -1)),
01483      h_outer_samples(GV3::get<int>("add_remove.hessian.outer_samples", 0, -1)),
01484      h_inner_samples(GV3::get<int>("add_remove.hessian.inner_samples", 0, -1)),
01485      tsamples(GV3::get<int>("add_remove.thermo.samples", 0, -1)),
01486 
01487      ave(average_image(ims_)),
01488 
01489      save_spots(save_spots_),
01490      
01491      time_gibbs(0),
01492      time_cg(0),
01493     
01494      scale_brightness_limit(GV3::get<bool>("max_motion.use_brightness_std", 0, -1)),
01495      limit(makeVector(brightness_motion_limit(intensity_mu, intensity_sigma, scale_brightness_limit), 1, 1, 1)*max_motion),
01496 
01497      A(GV3::get<Matrix<3> >("A", Zeros, 1)),
01498      pi(GV3::get<Vector<3> >("pi", Zeros, 1)),
01499 
01500 
01501      data_for_t_mcmc(pixels, pixel_intensities, intensity_mu, intensity_sigma, blur_mu, blur_sigma, variance, tsamples, sample_iterations, A, pi, rng),
01502      data_for_h_mcmc(pixels, pixel_intensities, intensity_mu, intensity_sigma, blur_mu, blur_sigma, variance, h_outer_samples, sample_iterations, A, pi, rng)
01503 
01504     {
01505         assert_same_size(ims);
01506 
01507         //Pixel intensities for all images [frame][pixel]
01508         pixel_intensities.resize(ims.size(), vector<double>(pixels.size()));
01509         for(unsigned int frame=0; frame < ims.size(); frame++)
01510             for(unsigned int p=0; p < pixels.size(); p++)
01511                 pixel_intensities[frame][p] = ims[frame][pixels[p]];
01512     
01513     }
01514     
01515     ///Perform a complete iteration of the optimzation stage of the spot firrint algorithm
01516     void optimize_each_spot_in_turn_for_several_passes()
01517     {
01518         //Precompute the intensities for all spot pixels
01519         vector<vector<double> > spot_intensities; //[spot][pixel]
01520         for(unsigned int i=0; i < spots.size(); i++)
01521             spot_intensities.push_back(compute_spot_intensity(pixels, spots[i]));
01522 
01523         //Which pixels does each spot have?
01524         vector<vector<int> > spot_pixels; //[spot][pixel]
01525         spot_pixels.resize(spots.size());
01526         for(unsigned int s=0; s < spots.size(); s++)
01527             get_spot_pixels(pixels, spots[s], spot_pixels[s]);
01528 
01529         
01530         //Optimize the model, N spots at a time.
01531         //
01532         for(int pass=start_pass; pass < main_passes; pass++)
01533         {
01534             save_spots << "Pass: " << pass << endl;
01535             rng.write(save_spots);
01536             save_spots << endl;
01537 
01538             start_pass=0; // This is only nonzero first time, since we might chekpoint midway through an iteration
01539             save_spots << "PASS" << pass << ": " << setprecision(20) << scientific << spots_to_Vector(spots) << endl;
01540             save_spots << "ENDCHECKPOINT" << endl << flush;
01541 
01542             ui.per_pass(iteration, pass, spots);
01543             //Sort spots according to pass%4
01544 
01545             //Sort the spots so that the optimization runs in sweeps
01546             //This heiristic seems to increase the rate of propagation of information
01547             //about spot positions.
01548 
01549             //Create a list of indices
01550             vector<int> index = sequence(spots.size());
01551             
01552             int passs = pass + iteration;
01553             //Sort the indices according to the position of the spot that they index
01554             if(passs%4 == 0)
01555                 sort(index.begin(), index.end(), IndexLexicographicPosition<less<double>, 2>(spots));
01556             else if(passs%4==1)
01557                 sort(index.begin(), index.end(), IndexLexicographicPosition<greater<double>, 2>(spots));
01558             else if(passs%4==1)
01559                 sort(index.begin(), index.end(), IndexLexicographicPosition<less<double>, 3>(spots));
01560             else
01561                 sort(index.begin(), index.end(), IndexLexicographicPosition<greater<double>, 3>(spots));
01562 
01563             //Reorder the spots and their intensities and their pixel lists
01564             {
01565                 vector<Vector<4> > tmp_spot(index.size());
01566                 vector<vector<double> > tmp_spot_intensities(index.size());
01567                 vector<vector<int> > tmp_spot_pixels(index.size());
01568                 for(unsigned int i=0; i < index.size(); i++)
01569                 {
01570                     tmp_spot[i] = spots[index[i]];
01571                     swap(tmp_spot_intensities[i], spot_intensities[index[i]]);
01572                     swap(tmp_spot_pixels[i], spot_pixels[i]);
01573                 }
01574 
01575                 swap(tmp_spot, spots);
01576                 swap(tmp_spot_intensities, spot_intensities);
01577                 swap(tmp_spot_pixels, spot_pixels);
01578             }
01579 
01580             //Sweep through and optimize each spot in turn
01581             for(int s=0; s < (int)spots.size(); s++)
01582             {
01583                 ui.per_spot(iteration, pass, s, spots.size()); 
01584                 ui.perhaps_stop();
01585 
01586                 TIME(timer.reset();)
01587                 //Get some samples with Gibbs sampling
01588                 vector<vector<vector<State> > > sample_list; //[N][spot][frame]: list of samples drawn using Gibbs sampling
01589                 vector<vector<vector<double> > > sample_intensities; //[sample][frame][pixel]
01590 
01591                 GibbsSampler2 sampler(pixel_intensities, spot_intensities, spots, spot_pixels, A, pi, variance, sample_iterations);
01592                 for(int i=0; i < main_samples; i++)
01593                 {
01594                     sampler.next(rng);
01595                     sample_list.push_back(sampler.sample());
01596                     sample_intensities.push_back(sampler.sample_intensities());
01597 
01598                     ui.perhaps_stop();
01599                 }
01600 
01601                 //First, remove the spot from all the samples.
01602                 for(unsigned int i=0; i < sample_list.size(); i++)
01603                     remove_spot(sample_intensities[i], spot_intensities[s], sample_list[i][s]);
01604                 
01605                 //cout << timer.get_time() << endl;
01606                 TIME(time_gibbs += timer.reset();)
01607 
01608                 //Package up all the data
01609                 SampledBackgroundData data(sample_intensities, pixel_intensities, pixels, 
01610                                            intensity_mu, intensity_sigma, blur_mu, blur_sigma, 
01611                                            A, pi, variance);
01612                 
01613                 //Derivative computer:
01614                 SpotNegProbabilityDiffWithSampledBackground compute_deriv(data);
01615                 
01616 
01617                 graphics.draw_pixels(pixels, 0, 0, 1, 1);
01618                 graphics.draw_krap(spots, scale_to_bytes(ave), boundingbox(pixels), s);
01619                 graphics.swap();
01620 
01621                 //Optimize spot "s"
01622                 //Optimize with the derivatives only since the actual probability
01623                 //is much harder to compute
01624                 ConjugateGradientOnly<4> cg(spots[s], compute_deriv, limit);
01625 
01626 
01627                 cg.max_iterations = main_cg_max_iterations;
01628 
01629 
01630                 #if 0
01631                     cout << setprecision(10);
01632                     cout << spots_to_Vector(spots) << endl;
01633                     Matrix<4> hess, hess_errors;
01634                     cout << "Hello, my name is Inigo Montoya\n";
01635                     /*for(int i=0; i < 4; i++)
01636                     {
01637                         Matrix<4, 2> d = numerical_gradient_with_errors(NthDeriv(compute_deriv, i), cg.x);
01638                         hess[i] = d.T()[0];
01639                         hess_errors[i] = d.T()[1];
01640                     }
01641                     */
01642                     //cout << "Errors:\n" << hess_errors << endl;
01643                     //cout << "NHess:\n" << hess<< endl;
01644                     Matrix<4> rhess =  -sampled_background_spot_hessian(cg.x, data);
01645                     cout << "Hess:\n" << rhess << endl;
01646                     //cout << "Err:\n" << hess - rhess << endl;
01647 
01648                     //Vector<4> grad = compute_deriv(cg.x);
01649 
01650                     //Matrix<4> e = hess - rhess;
01651 
01652                     //for(int i=0; i < 4; i++)
01653                     //  for(int j=0; j < 4; j++)
01654                     //      e[i][j] /= hess_errors[i][j];
01655 
01656                     //cout << "Err:\n" << e << endl;
01657                     cout << "Deriv:" <<  compute_deriv(cg.x) << endl;
01658                     //cout << "Full:\n" << sampled_background_spot_hessian2(cg.x, data) - grad.as_col()*grad.as_row() << endl;
01659 
01660                     FreeEnergyHessian hesscomputer(data_for_h_mcmc);
01661 
01662                     Matrix<4> nhess = hesscomputer.hessian(spots, 0);
01663                     cout << "NHess:\n" << nhess << endl;
01664 
01665                     cout << "Turbo-N Hess:\n" << sampled_background_spot_hessian_ffbs(cg.x, data, 10000) << endl;
01666 
01667                     cout << "TI energy: " << NegativeFreeEnergy(data_for_t_mcmc)(spots_to_Vector(spots)) << endl;
01668                     cout << "FA energy: " <<  SpotProbabilityWithSampledBackgroundFAKE(data)(cg.x) << endl;
01669 
01670 
01671 
01672                     //cout << "Numerical hessian from FD:\n" << numerical_hessian(SpotProbabilityWithSampledBackgroundFAKE(data), cg.x) << endl;
01673                     exit(0);
01674                 #endif
01675                 //cout << "Starting opt... " << cg.x << endl;
01676                 while(cg.iterate(compute_deriv))
01677                 {
01678                     graphics.draw_krap(spots, scale_to_bytes(ave), boundingbox(pixels), s, cg.x);
01679                     graphics.draw_pixels(pixels, 0, 0, 1, .2);
01680                     graphics.swap();
01681                     ui.perhaps_stop();
01682                     //cout << cg.x << endl;
01683                 }
01684 
01685                 //Update to use the result of the optimization
01686                 spots[s] = cg.x;
01687                 //cout << "End: " << cg.x << endl;
01688                 
01689                 graphics.draw_krap(spots, scale_to_bytes(ave), boundingbox(pixels), -1);
01690                 graphics.swap();
01691                     
01692                 //Recompute the new spot intensity, since the spot has changed
01693                 spot_intensities[s] = compute_spot_intensity(pixels, spots[s]);
01694 
01695                 //Recompute which are the useful pixels
01696                 get_spot_pixels(pixels, spots[s], spot_pixels[s]);
01697                 
01698                 //Is the spot within the allowed area, i.e. is it's prior 0?
01699                 //The prior is sero only if it we are using it and we're in an invalid area
01700 
01701                 ImageRef quantized_spot_position = ir_rounded(spots[s].slice<2,2>());
01702                 bool zero_prior = use_position_prior && (allowed_area.count(quantized_spot_position)==0);
01703 
01704                 //Check to see if spot has been ejected. If spot_pixels is empty, then it has certainly been ejected.
01705                 if(spot_pixels[s].empty() || zero_prior)
01706                 {
01707                     //Spot has been ejected. Erase it.
01708                     cout  << " Erasing ejected spot: " << spot_pixels[s].empty() << " " << zero_prior << endl;
01709                     cout << spots[s] << endl;
01710                     //GUI_Pause(1);
01711 
01712                     spot_intensities.erase(spot_intensities.begin() + s);
01713                     spot_pixels.erase(spot_pixels.begin() + s);
01714                     spots.erase(spots.begin() + s);
01715                     s--;
01716                     //exit(0);
01717                 }
01718                 
01719                 //cout << timer.get_time() << endl;
01720                 TIME(time_cg += timer.reset();)
01721 
01722                 //cout << "Times: " << time_gibbs << " " << time_cg << endl;
01723                 //save_spots << "INTERMEDIATE: " << setprecision(15) << scientific << spots_to_Vector(spots) << endl;
01724             }
01725         }
01726     }
01727 
01728     ///Perform a complete iteration of the model size modification stage of the spot fitting algorithm
01729     void try_modifying_model()
01730     {
01731 
01732         for(int i=0; i < add_remove_tries; i++)
01733         {
01734             ui.per_modification(iteration, i, add_remove_tries);
01735             ui.perhaps_stop();
01736 
01737             cout << endl << endl << "Modifying the model" << endl << "======================\n";
01738             cout << "Hello\n";
01739             bool add_spot = (rng() > 0.5) || (spots.size() == 1);
01740             cout << "World\n";
01741 
01742             vector<Vector<4> > model_1, model_2;
01743 
01744             
01745             int original; //What is the original model? Model 1 or Model 2?
01746 
01747             if(add_spot)
01748             {
01749                 model_1 = spots;
01750                 model_2 = model_1;
01751                 
01752                 //Pick a pixel within the thresholded ones as a starting point
01753                 int r;
01754                 do
01755                 {
01756                     r = (int)(rng() * pixels.size());
01757                     //cout << r << " " << log_ratios[pixels[r]] << " " << pixels[r] << " " << threshold << endl;
01758                 }
01759                 while(0);
01760 
01761                 //This version does not (yet?) suppotrt thresholding on log_ratios
01762                 //for placing spots, since the purpose of log_ratios has diminished.
01763                 //while(log_ratios[pixels[r]] < threshold);
01764 
01765 
01766                 model_2.push_back(makeVector(log_normal_mode(intensity_mu, intensity_sigma), 
01767                                              log_normal_mode(blur_mu, blur_sigma), 
01768                                              pixels[r].x + rng()-.5, pixels[r].y + rng() - .5));
01769                 cout << "Adding a spot\n";
01770 
01771                 original = 1;
01772             }
01773             else
01774             {   
01775                 //Pick a random point to optimize/remove
01776                 int a_random_spot = static_cast<int>(rng() * spots.size());
01777                 model_1 = spots;
01778                 swap(model_1[model_1.size()-1], model_1[a_random_spot]);
01779 
01780                 model_2 = model_1;
01781 
01782                 model_1.pop_back();
01783                 cout << "Removing a spot\n";
01784                 original = 2;
01785             }
01786             
01787             //The mobile spot is always the last spot of model_2
01788             const int spot = model_2.size() - 1;
01789 
01790             cout << "Original model: " << original << endl;
01791 
01792             //Precompute the intensities for all spot pixels
01793             //Model 2 is always one longer than model 1 and 
01794             //differs only on the extra element
01795             vector<vector<double> > model2_spot_intensities; //[spot][pixel]
01796             for(unsigned int i=0; i < model_2.size(); i++)
01797                 model2_spot_intensities.push_back(compute_spot_intensity(pixels, model_2[i]));
01798 
01799             //Which pixels does each spot have?
01800             vector<vector<int> > model2_spot_pixels(model_2.size()); //[spot][pixel]
01801             for(unsigned int s=0; s < model_2.size(); s++)
01802                 get_spot_pixels(pixels, model_2[s], model2_spot_pixels[s]);
01803 
01804             //Optimize spot:
01805             {
01806                 cout << "Optimizing spot for model selection\n";
01807 
01808 
01809                 //Get some samples with Gibbs sampling
01810                 vector<vector<vector<State> > > sample_list; //[N][spot][frame]: list of samples drawn using Gibbs sampling
01811                 vector<vector<vector<double> > > sample_intensities; //[sample][frame][pixel]
01812 
01813                 GibbsSampler2 sampler(pixel_intensities, model2_spot_intensities, model_2, model2_spot_pixels, A, pi, variance, sample_iterations);
01814                 for(int i=0; i < add_remove_opt_samples; i++)
01815                 {
01816                     sampler.next(rng);
01817                     sample_list.push_back(sampler.sample());
01818                     sample_intensities.push_back(sampler.sample_intensities());
01819                     ui.perhaps_stop();
01820                 }
01821 
01822                 //First, remove the spot from all the samples.
01823                 for(unsigned int i=0; i < sample_list.size(); i++)
01824                     remove_spot(sample_intensities[i], model2_spot_intensities[spot], sample_list[i][spot]);
01825 
01826                 //Package up all the data
01827                 SampledBackgroundData data(sample_intensities, pixel_intensities, pixels, 
01828                                            intensity_mu, intensity_sigma, blur_mu, blur_sigma, 
01829                                            A, pi, variance);
01830                 
01831                 //Derivative computer:
01832                 SpotNegProbabilityDiffWithSampledBackground compute_deriv(data);
01833                 
01834                 graphics.draw_krap(model_2, scale_to_bytes(ave), boundingbox(pixels), spot);
01835                 graphics.swap();
01836 
01837                 //Optimize spot "s"
01838                 //Optimize with the derivatives only since the actual probability
01839                 //is much harder to compute
01840                 ConjugateGradientOnly<4> cg(model_2[spot], compute_deriv, limit);
01841 
01842 
01843                 for(int attempt=0; attempt < add_remove_opt_retries; attempt++)
01844                 {
01845                     cout << "Attempt " << attempt << " of " << add_remove_opt_retries << endl;
01846                     ui.perhaps_stop();
01847 
01848                     //Optimize with conjugate gradient
01849                     while(cg.iterate(compute_deriv))
01850                     {
01851                         ui.perhaps_stop();
01852                         graphics.draw_krap(model_2, scale_to_bytes(ave), boundingbox(pixels), spot, cg.x);
01853                         graphics.swap();
01854                     }
01855                     
01856                     //Check for being at a saddle point (no point checking on the last try)
01857                     //All eigenvectors should be negative at a maximum.
01858                     //WTF: is this a bug? WTF?
01859                     //It was this:
01860                     //if(attempt < add_remove_tries - 1)
01861                     if(attempt < add_remove_opt_retries - 1)
01862                     {
01863                         Matrix<4> hessian = sampled_background_spot_hessian_ffbs(cg.x, data, add_remove_opt_hess_inner_samples, rng);
01864                         SymEigen<4> hess_decomp(hessian);
01865 
01866                         //cout << "What the fuck:" << endl << hessian << endl << hessian3<< endl << hessian2 << endl;
01867                         
01868                         cout << "Eigenvalues are: " << hess_decomp.get_evalues() << endl;
01869 
01870                         if(hess_decomp.is_negdef())
01871                             break;
01872                         else
01873                         {
01874                             //Restart in the direction of the best uphill part
01875                             cg.init(cg.x + 0.1 * hess_decomp.get_evectors()[3], (hess_decomp.get_evectors()[3]));
01876 
01877 
01878                             cout << "Grad = " << compute_deriv(cg.x) << endl;
01879                             for(int i=0; i < 4; i++)
01880                             {
01881                                 cout << "Direction: " << i << endl;
01882                                 cout << unit(compute_deriv(cg.x + 0.1*hess_decomp.get_evectors()[i])) * hess_decomp.get_evectors()[i] << endl;
01883                             }
01884 
01885                             for(int i=0; i < 4; i++)
01886                             {
01887                                 cout << "Direction: " << i << endl;
01888                                 Vector<4> d = Zeros;
01889                                 d[i] = 1;
01890                                 cout << unit(compute_deriv(cg.x + d)) * hess_decomp.get_evectors()[i] << endl;
01891                             }
01892                         }
01893                     }
01894                 }
01895 
01896 
01897                 //Update to use the result of the optimization
01898                 model_2[spot] = cg.x;
01899                 
01900                 graphics.draw_krap(model_2, scale_to_bytes(ave), boundingbox(pixels), -1);
01901                 graphics.swap();
01902     
01903 
01904                 //Update cached data based on the new spot position
01905                 model2_spot_intensities[spot] = compute_spot_intensity(pixels, model_2[spot]);
01906                 get_spot_pixels(pixels, model_2[spot], model2_spot_pixels[spot]);
01907 
01908                 cout << "Done optimizing for model selection\n";
01909             }
01910 
01911 
01912             //Which model to keep?
01913             int keep=original;
01914         
01915             //Compute position prior (and we might be able to reject it really quickly here)
01916             bool zero_prior = use_position_prior && (allowed_area.count(ir_rounded(model_2[spot].slice<2,2>()))==0); 
01917             
01918             if(zero_prior)
01919             {
01920                 //Model 2 went bad, so we clearly keep model 1
01921                 keep = 1;
01922             }
01923             else
01924             {
01925                 
01926                 //The position prior is independent
01927                 //Compute the difference  model2 - model1
01928                 //This is only valid if model2 is in the valid region
01929                 double position_log_prior_model2_minus_model1;
01930                 if(use_position_prior)
01931                     position_log_prior_model2_minus_model1 = (model_2.size() - model_1.size()) * ln(position_prior);
01932                 else
01933                     position_log_prior_model2_minus_model1 = 0;
01934 
01935 
01936                 //Integrate model_2
01937                 //First compute the Hessian since this might go wrong.
01938 
01939                 //FreeEnergyHessian hesscomputer(data_for_h_mcmc);
01940                 Matrix<4> hess;// = hesscomputer.hessian(model_2, spot);
01941 
01942                 //Use turbohess here since it is much faster, as the backwards sampling step is fast
01943                 //We expect this hessian to be really quite different, if the spot has moved from
01944                 //a long way away, since the sampling will have changed dramatically
01945                 {
01946                     //Get some samples with Gibbs sampling
01947                     vector<vector<vector<State> > > sample_list; //[N][spot][frame]: list of samples drawn using Gibbs sampling
01948                     vector<vector<vector<double> > > sample_intensities; //[sample][frame][pixel]
01949 
01950                     GibbsSampler sampler(pixel_intensities, model2_spot_intensities, model_2, A, pi, variance, sample_iterations);
01951                     for(int i=0; i < h_outer_samples; i++)
01952                     {
01953                         ui.perhaps_stop();
01954                         sampler.next(rng);
01955                         sample_list.push_back(sampler.sample());
01956                         sample_intensities.push_back(sampler.sample_intensities());
01957                     }
01958                     
01959                     //First, remove the spot from all the samples.
01960                     for(unsigned int i=0; i < sample_list.size(); i++)
01961                         remove_spot(sample_intensities[i], model2_spot_intensities[spot], sample_list[i][spot]);
01962 
01963                     //Package up all the data
01964                     SampledBackgroundData data(sample_intensities, pixel_intensities, pixels, 
01965                                                intensity_mu, intensity_sigma, blur_mu, blur_sigma, 
01966                                                A, pi, variance);
01967 
01968                     hess = sampled_background_spot_hessian_ffbs(model_2[spot], data, h_inner_samples, rng);
01969                 }
01970 
01971 
01972                 double det = determinant(-hess / (M_PI*2));
01973                 SymEigen<4> hess_decomp(-hess);
01974                 cout << "Hessien Eigenvalues are: " << hess_decomp.get_evalues() << endl;
01975                 const double smallest_evalue = 1e-6;
01976 
01977                 //If the determinant is negative, then we are still at a saddle point
01978                 //despite the attempts above, so abandon the attempt.
01979                 if(hess_decomp.get_evalues()[0] >  smallest_evalue)
01980                 {
01981 
01982                     //Compute the free energy of model 2 at the MLE estimate
01983                     cout << "Model 2:\n";
01984             //      double model_2_energy = -NegativeFreeEnergy(data_for_t_mcmc)(spots_to_Vector(model_2));
01985                     double model_2_energy = -NegativeFreeEnergy(data_for_t_mcmc).compute_with_mask(spots_to_Vector(model_2), model2_spot_pixels);
01986                     cout << "Energy: " << model_2_energy << endl;
01987                 
01988                     //Combine the MLE energy and Hessian using Laplace's approximation
01989                     double model_2_occam =  -0.5 * log(det);
01990                     double model_2_prob = model_2_energy + model_2_occam + position_log_prior_model2_minus_model1;
01991 
01992                     cout << "Occam: " << model_2_occam << endl;
01993                     cout << "Position: " << position_log_prior_model2_minus_model1 << endl;
01994                     cout << "Prob: " << model_2_prob << endl;
01995 
01996                     //Integrate model_1
01997                     //It has no parameters, in this formulation.
01998                     //double model_1_prob = -NegativeFreeEnergy(data_for_t_mcmc)(spots_to_Vector(model_1));
01999                     
02000                     //Note that model_1 always has one fewer spots, and the last spot is always the one
02001                     //missing, so we can make the correct mask very easily:
02002                     model2_spot_pixels.pop_back();
02003                     double model_1_prob = -NegativeFreeEnergy(data_for_t_mcmc).compute_with_mask(spots_to_Vector(model_1), model2_spot_pixels);
02004                     cout << "Prob: " << model_1_prob << endl;
02005                     //model_1_prob = -NegativeFreeEnergy(data_for_t_mcmc)(spots_to_Vector(model_1));
02006 
02007                     if(model_2_prob  >  model_1_prob)
02008                         keep=2;
02009                     else
02010                         keep=1;
02011 
02012                     cout << "Models evaluated\n";
02013                 }
02014                 else
02015                 {
02016                     cout << "Determinant has bad eigenvalues!\n";
02017                     keep = original;
02018                     cout << hess_decomp.get_evalues() << endl;
02019                 }
02020             }
02021 
02022             if(keep == 2)
02023             {
02024                 spots = model_2;
02025                 cout << "Keeping model 2\n";
02026 
02027             }
02028             else
02029             {
02030                 spots = model_1;
02031                 cout << "Keeping model 1\n";
02032             }
02033 
02034             if(original != keep)
02035             {
02036                 cout << "Model changed!\n";
02037                 //break;
02038             }
02039         }
02040     }
02041     
02042     ///Run the complete optimization algorithm.
02043     void run()
02044     {
02045         graphics.init(ims[0].size());
02046         save_spots << "LOGVERSION 2" << endl;
02047         save_spots << "PIXELS";
02048         for(unsigned int i=0; i < pixels.size(); i++)
02049             save_spots << " " << pixels[i].x << " " << pixels[i].y;
02050         save_spots << endl;
02051 
02052         save_spots << "BEGINGVARLIST" << endl;
02053         GV3::print_var_list(save_spots, "", 1);
02054         save_spots << "ENDGVARLIST" << endl;
02055 
02056         //TODO all GVARS are set, so dump out gvars.
02057 
02058         cout << "Limit vector: " << limit << endl;
02059 
02060         for(iteration=start_iteration; iteration < outer_loop_iterations ;iteration++)
02061         {
02062             save_spots << "Iteration: " << iteration << " (" << iteration *  main_passes << ")" << endl;
02063             save_spots << "MAIN: " << setprecision(20) << scientific << spots_to_Vector(spots) << endl;
02064 
02065             cout << endl << endl << "----------------------" << endl << "Optimizing:\n";
02066             cout << spots.size() << endl;
02067             
02068 
02069             optimize_each_spot_in_turn_for_several_passes();
02070 
02071             //spot_intensities is be correct here!
02072             try_modifying_model();
02073         }
02074         save_spots << "FINAL: " << setprecision(15) << scientific << spots_to_Vector(spots) << endl;
02075     }
02076 
02077 };
02078 
02079 ///Wrapper function for using FitSpots
02080 ///@ingroup gStorm
02081 void fit_spots_new(const vector<Image<float> >& ims, StateParameters& p, ofstream& save_spots, FitSpotsGraphics& gr)
02082 {
02083     auto_ptr<UserInterfaceCallback> ui = null_ui();
02084     FitSpots fit(ims, gr, *ui, p, save_spots);
02085     fit.run();
02086 }
02087 
02088 ///Wrapper function for using FitSpots
02089 ///@ingroup gStorm
02090 void fit_spots_new(const vector<Image<float> >& ims, StateParameters& p, ofstream& save_spots, FitSpotsGraphics& gr, UserInterfaceCallback& ui)
02091 {
02092     try{
02093         FitSpots fit(ims, gr, ui, p, save_spots);
02094         fit.run();
02095     }
02096     catch(UserInterfaceCallback::UserIssuedStop)
02097     {
02098     }
02099 }