CC Localization
loc1.cc
Go to the documentation of this file.
1 
4 #include "tiff.hh"
5 #include "nelder_mead.hxx"
6 #include "utils.hh"
7 #include <iostream>
8 #include <cmath>
9 
10 double i2p = 3.6;
11 double plsz = 80;
12 int fwr = 4;
13 
15 typedef std::array<double,5> param_t;
16 
18 double psf_ig2(double x, double y, param_t const & p)
19 {
20  double s2s = sqrt(2)*p[2]*p[2];
21  double ex = (erf((x-p[0]+.5)/s2s)-erf((x-p[0]-.5)/s2s))*.5;
22  double ey = (erf((y-p[1]+.5)/s2s)-erf((y-p[1]-.5)/s2s))*.5;
23  return ex*ey*p[3]*p[3]+p[4]*p[4];
24 }
25 
28 {
29  double const * i;
30  int l;
31  int w;
32 public:
33  int cnt;
34  Likelihood(
36  int l,
37  int w
38  ) : l(l), w(w) {}
40  void set_image(double const * im) {i = im;}
42  double operator()(param_t const & p)
43  {
44  double tl = 0;
45  for (int y = 0; y<l; y++) for (int x = 0; x<l; x++) {
46  auto psf = psf_ig2(x,y,p);
47  tl += i[y*w+x]*log(psf)-psf;
48  }
49  return -tl;
50  }
51 };
52 
54 struct Particle
55 {
56  int x;
57  int y;
59 };
60 
62 std::vector<Particle> process_image(
63  double const * data,
64  int w,
65  int h
66 )
67 {
68  std::vector<Particle> res;
69  // convolution kernels
70  double const wk1[] = {1./16,1./4,3./8,1./4,1./16};
71  double const wk2[] = {1./16,0,1./4,0,3./8,0,1./4,0,1./16};
72  int sz = w*h;
73  int l = 2*fwr+1;
74  // utilities
75  std::vector<double> bf(sz); // workspace
76  NelderMead<5> nm; // Nelder--Mead minimizer
77  Likelihood fn(l,w); // likelihood function
78 
79  // calculate v1,f1
80  std::vector<double> v1(sz);
81  for (int i = 0; i<sz; i++) {
82  int x = i%w;
83  double s = 0;
84  int r1 = x+2<w ? 5 : w+2-x;
85  for (int j = x<2 ? 2-x : 0; j<r1; j++) s += data[i+j-2]*wk1[j];
86  bf[i] = s;
87  }
88  double f1a = 0;
89  double f1a2 = 0;
90  for (int i = 0; i<sz; i++) {
91  int y = i/w;
92  double s = 0;
93  int r1 = y+2<h ? 5 : h+2-y;
94  for (int j = y<2 ? 2-y : 0; j<r1; j++) s += bf[i+j*w-2*w]*wk1[j];
95  v1[i] = s;
96  double f1 = data[i]-s;
97  f1a += f1;
98  f1a2 += f1*f1;
99  }
100  f1a /= sz;
101  f1a2 /= sz;
102  double threshold = 1.5*sqrt(f1a2-f1a*f1a);
103  debug << "threshold = " << threshold << '\n';
104 
105  // calculate f2
106  std::vector<double> f2(sz);
107  for (int i = 0; i<sz; i++) {
108  int x = i%w;
109  double s = 0;
110  int r1 = x+4<w ? 9 : w+4-x;
111  for (int j = x<4 ? 4-x : 0; j<r1; j++) s += v1[i+j-4]*wk2[j];
112  bf[i] = s;
113  }
114  for (int i = 0; i<sz; i++) {
115  int y = i/w;
116  double s = 0;
117  int r1 = y+4<h ? 9 : h+4-y;
118  for (int j = y<4 ? 4-y : 0; j<r1; j++) s += bf[i+j*w-4*w]*wk2[j];
119  f2[i] = v1[i]-s;
120  }
121  // convert intensity to photon count
122  for (int i = 0; i<sz; i++) bf[i] = data[i]*i2p;
123 
124  // find 8-connected local maximum by forward elimination
125  std::vector<int> nd{1,w+1,w,w-1};
126  std::vector<bool> n8(sz,true);
127  param_t stps = {1,1,0.2,1,1}; // step size
128  int ne = sz-w-1;
129  for (int i = 0; i<ne; i++) {
130  for (int d: nd) {
131  if (f2[i]>f2[i+d]) n8[i+d] = false;
132  else n8[i] = false;
133  }
134  int x = i%w;
135  int y = i/w;
136  if (n8[i] && x>=fwr && x<w-fwr && y>=fwr && y<h-fwr && f2[i]>threshold) {
137  // a local maximum, perform fitting to PSF
138  double const * sq = bf.data()+i-(w+1)*fwr; // keeping starting corner of square
139  // initial guess
140  double mx = sq[0];
141  double mn = sq[0];
142  for (int y = 0; y<l; y++) for (int x = 0; x<l; x++) {
143  double vv = sq[y*w+x];
144  if (vv>mx) mx = vv;
145  else if (vv<mn) mn = vv;
146  }
147  param_t p = {double(fwr),double(fwr),sqrt(1.6),sqrt(mx-mn),sqrt(mn)};
148  fn.set_image(sq);
149  fn.cnt = 0;
150  res.push_back({x,y,nm.minimize(std::ref(fn),p,stps)});
151  }
152  }
153  return res;
154 }
155 
157 int main(int argc, char ** argv)
158 {
159  if (argc<2) {
160  msg(0) << "Missing expected filename!\nUsage:\n";
161  msg(0) << '\t' << argv[0] << " <filename of TIFF>\n\n";
162  return EXIT_FAILURE;
163  }
164 
165  Tiff tf(std::make_shared<std::ifstream>(argv[1]));
166  tf.start();
167 
168  uint32_t nxt = 0;
169  unsigned icnt = 0;
170  do {
171  nxt = tf.parse_ifd(nxt);
172  int w = tf.image_width;
173  int h = tf.image_length;
174  int sz = w*h;
175  auto imd = tf.read_image();
176  uint16_t * v = reinterpret_cast<uint16_t *>(imd.data());
177  // convert to double
178  std::vector<double> im(v,v+sz);
179  for (auto r: process_image(im.data(), w, h)) {
180  // throw out outliers
181  if (r.p[0]<fwr-fwr/2||r.p[0]>fwr+fwr/2) continue;
182  if (r.p[1]<fwr-fwr/2||r.p[1]>fwr+fwr/2) continue;
183  if (r.p[2]<0.5||r.p[2]>fwr/2) continue;
184  if (abs(r.p[3])>1000) continue;
185  std::cout << icnt+1 << ",\t"; // layer
186  std::cout << plsz*(r.x+r.p[0]) << ",\t";
187  std::cout << plsz*(r.y+r.p[1]) << ",\t";
188  std::cout << plsz*(r.p[2]*r.p[2]) << ",\t";
189  std::cout << r.p[3]*r.p[3] << ",\t";
190  std::cout << r.p[4]*r.p[4] << '\n';
191  }
192  icnt ++;
193  } while (nxt);
194  return 0;
195 }
Template implementation of Nelder–Mead method for minimization.
double fn(double const *p)
Function to be minimized.
Definition: localization.cc:39
TIFF file processor.
Definition: tiff.hh:13
std::vector< char > read_image()
Definition: tiff.cc:168
vec_t minimize(fun_t fn, vec_t const &x0, vec_t const &step)
<perform minimization
Definition: nelder_mead.hxx:26
std::vector< Particle > process_image(double const *data, int w, int h)
Process a single 2D image.
Definition: loc1.cc:62
Likelihood(int l, int w)
Construct the calculator.
Definition: loc1.cc:35
Optimizer with Nelder–Mead method for functions with N arguments.
Definition: nelder_mead.hxx:11
uint32_t image_width
width of image
Definition: tiff.hh:125
std::ostream & msg(int l)
message output stream
Definition: utils.cc:48
std::array< double, 5 > param_t
Type for fitting parameters.
Definition: loc1.cc:15
uint32_t image_length
length of image
Definition: tiff.hh:126
Detected particle.
Definition: loc1.cc:54
int x
x coordinate of the maximum
Definition: loc1.cc:56
int fwr
fitting window range
Definition: loc1.cc:12
int cnt
Definition: loc1.cc:33
void set_image(double const *im)
Set the image for calculation.
Definition: loc1.cc:40
double psf_ig2(double x, double y, param_t const &p)
Point-spread function with integrated Gaussian.
Definition: loc1.cc:18
param_t p
fitted parameters of the point-spread function
Definition: loc1.cc:58
double plsz
pixel size in nm
Definition: loc1.cc:11
void start()
Definition: tiff.cc:113
int main(int argc, char **argv)
Main function for localization.
Definition: loc1.cc:157
Functor for likelihood calculation.
Definition: loc1.cc:27
double operator()(param_t const &p)
Actual calculation make the functor.
Definition: loc1.cc:42
double i2p
intensity to photon scale
Definition: loc1.cc:10
std::ostream & debug
stream for debug messages
Definition: utils.cc:53
int y
y coordinate of the maximum
Definition: loc1.cc:57
Miscellaneous utilities.
uint32_t parse_ifd(uint32_t i=0)
Parse image file directory (IFD)
Definition: tiff.cc:127
Class for processing TIFF file.