| Bsoft 2.0.5 Bernard's software package

Bimage_histogram.cpp
Go to the documentation of this file.
1
9 #include "Bimage.h"
10 #include "simplex.h"
11 #include "cluster.h"
12 #include "matrix_linear.h"
13 #include "qsort_functions.h"
14 #include "utilities.h"
15
16 // Declaration of global variables
17 extern int verbose; // Level of output to the screen
18
32 long* Bimage::histogram(long bins, double& scale, double& offset)
33 {
34 scale = 1;
35 offset = 0;
36
37 if ( !data_pointer() ) return NULL;
38
39 long i, j, cc;
40 long* histo = new long[bins*c];
41 for ( i=0; i<bins*c; i++ ) histo[i] = 0;
42
43 if ( datatype < Float ) {
44 scale = 1/(ceil((max - min + 1)/bins));
45 offset = -scale*min;
46 } else {
47 scale = (bins - 1)*1.0/(max - min);
48 offset = 0.5 - scale*min;
49 }
50
51 if ( verbose & VERB_DEBUG )
52 cout << "DEBUG Bimage::histogram: range=" << min << "-"
53 << max << " bins=" << bins << " scale=" << scale
54 << " offset=" << offset << endl;
55
56 for ( i=0; i<n*image_size(); ) {
57 for ( cc=0; cc<c; cc++, i++ ) {
58 j = (long) (scale*(*this)[i] + offset);
59 if ( j >= 0 && j < bins ) histo[cc*bins+j]++;
60 }
61 }
62
63 return histo;
64 }
65
78 Bplot* Bimage::histogram(long bins)
79 {
80 long i, j, k, cc, npage, ncol;
81 double Hi, H;
82 double bin_half = (max - min)/(4*bins);
83 double unit_mass = RHO * sampling().volume();
84 long* hsum = new long[bins*c];
85
86 double scale, offset;
87 long* histo = histogram(bins, scale, offset);
88
89 long hmax(0);
90 for ( i=0; i<bins; i++ ) if ( hmax < histo[i] ) hmax = histo[i];
91
92 for ( i=0; i<bins*c; i++ ) hsum[i] = histo[i];
93 for ( i=bins-1; i>0; i-- )
94 for ( cc=0; cc<c; cc++ )
95 hsum[cc*bins+i-1] += hsum[cc*bins+i];
96
97 if ( c > 1 ) {
98 npage = 1;
99 ncol = c + 1;
100 } else {
101 npage = 2;
102 ncol = 3;
103 }
104
105 if ( verbose & VERB_LABEL ) {
106 cout << "Histogram" << endl;
107 if ( c == 1 )
108 cout << "Bin\tLevel\tNumber\tSum\tVolume\tInformation" << endl;
109 else {
110 cout << "Bin\tLevel";
111 for ( cc=0; cc<c; cc++ ) cout << "\tChannel" << cc+1;
112 cout << endl;
113 }
114 }
115
116 Bstring title("Histogram");
117 Bplot* plot = new Bplot(npage, bins, ncol);
118 plot->title(title);
119
120 plot->page(0).title(title);
121 plot->page(0).columns(c+1);
122 for ( i=0; i<=c; i++ ) plot->page(0).column(i).number(i);
123 plot->page(0).column(0).label("Bin");
124 plot->page(0).column(0).axis(1);
125 for ( i=1; i<=c; i++ ) {
126 plot->page(0).column(i).type(1);
127 plot->page(0).column(i).label("Count");
128 plot->page(0).column(i).axis(3);
129 plot->page(0).column(i).element_size(0.5);
130 }
131 if ( c > 1 ) {
132 plot->page(0).column(1).color(1,0,0);
133 plot->page(0).column(2).color(0,1,0);
134 plot->page(0).column(3).color(0,0,1);
135 }
136 plot->page(0).axis(1).min(min - bin_half);
137 plot->page(0).axis(1).max(max + bin_half);
138 plot->page(0).axis(3).min(0);
139 plot->page(0).axis(3).max(hmax);
140
141 if ( c < 2 ) {
142 title = "Cumulative mass";
143 plot->page(1).title(title);
144 plot->page(1).columns(2);
145 plot->page(1).column(0).number(0);
146 plot->page(1).column(1).number(2);
147 plot->page(1).column(0).label("Bin");
148 plot->page(1).column(0).axis(1);
149 plot->page(1).column(1).type(1);
150 plot->page(1).column(1).label("Mass(MDa)");
151 plot->page(1).column(1).axis(3);
152 plot->page(1).column(1).element_size(0.5);
153 plot->page(1).axis(1).min(min - bin_half);
154 plot->page(1).axis(1).max(max + bin_half);
155 plot->page(1).axis(3).min(0);
156 plot->page(1).axis(3).max(hsum[0] * unit_mass);
157 }
158
159 for ( i=0; i<bins; i++ ) {
160 (*plot)[i] = min + i/scale;
161 for ( cc=0, j=i, k=bins+i; cc<c; cc++, j+=bins, k+=bins ) (*plot)[k] = histo[j];
162 }
163
164 if ( c == 1 ) {
165 H = 0;
166 for ( i=0, k=2*bins; i<bins; i++, k++ ) {
167 (*plot)[k] = hsum[i] * unit_mass;
168 Hi = 0;
169 if ( histo[i] )
170 Hi = (-histo[i]*1.0/hsum[0]) * log(histo[i]*1.0/hsum[0]) / log(2.0);
171 H += Hi;
172 cout << i+1 << tab << setw(12) << (*plot)[i] << tab << histo[i] << tab << hsum[i] << tab <<
173 sampling().volume()*hsum[i] << tab << Hi << endl;
174 }
175
176 if ( verbose & VERB_LABEL ) {
177 cout << "Voxels & number in histogram: " << datasize << " "
178 << hsum[0] << " (" << hsum[0]*100.0/datasize << " %)" << endl;
179 cout << "Voxel volume: " << sampling().volume() << " A/voxel" << endl;
180 cout << "Informational entropy and rate: " << H << " " << log(1.0*bins)/log(2.0) - H << endl << endl;
181 }
182 } else {
183 for ( i=0; i<bins; i++ ) {
184 cout << i+1 << tab << (*plot)[i];
185 for ( cc=0, j=0; cc<c; cc++, j+=bins ) cout << tab << histo[j];
186 cout << endl;
187 }
188 }
189
190
191 delete[] histo;
192 delete[] hsum;
193
194 return plot;
195 }
196
206 Bplot* Bimage::histogram_counts(int flags)
207 {
208 long i, j, k, bins(1000), imax(0), imax2(0);
209 double scale, offset, hmax(0), hmax2(0);
210
211 if ( datatype < Float ) bins = max - min + 1;
212
213 long* h = histogram(bins, scale, offset);
214
215 // Find highest peak
216 for ( i=1, imax=0; i<bins; ++i ) if ( hmax < h[i] ) {
217 hmax = h[i];
218 imax = i;
219 }
220 hmax2 = hmax/2;
221
222 // Track to start of peak
223 for ( i=imax; i && h[i] >= hmax2; --i ) ;
224
225 // Track to end of previous peak
226 for ( ; i && h[i] < hmax2; --i ) ;
227
228 // Find previous peak
229 for ( ; i && h[i] > hmax/2; --i ) if ( hmax2 < h[i] ) {
230 hmax2 = h[i];
231 imax2 = i;
232 }
233
234 imax -= imax2;
235
236 if ( imax < 1 ) {
237 cerr << "scale = " << scale << " offset = " << offset << endl;
238 cerr << "imax = " << imax << " imax2 = " << imax2 << endl;
239 bexit(-1);
240 }
241
242 long np(bins/imax+1), ninc(0), thr(datasize/1e4);
243 double stot(0), inc(0), d;
244 double amp[np], s[np], sv[np], sv2[np];
245
246 for ( j=0; j<np; j++ ) s[j] = sv[j] = sv2[j] = amp[j] = 0;
247
248 for ( i=0, j=0; i<bins && j<np; i++ ) {
249 j = (i+imax/2)/imax;
250 if ( j < np ) {
251 s[j] += h[i];
252 sv[j] += h[i]*i;
253 sv2[j] += h[i]*i*i;
254 if ( amp[j] < h[i] ) amp[j] = h[i];
255 }
256 }
257
258 for ( j=0; j<np; j++ ) stot += s[j];
259
260 if ( verbose )
261 cout << "Peak\t%\tAmp\tAvg\tStDev" << endl;
262 for ( j=k=0; j<np; j++ ) if ( s[j] ) {
263 sv[j] /= s[j];
264 sv2[j] = sv2[j]/s[j] - sv[j]*sv[j];
265 if ( j && amp[j] > thr ) {
266 inc += sv[j]/j;
267 ninc++;
268 }
269 if ( verbose )
270 cout << setprecision(4) << j << tab << 100*s[j]/stot << tab <<
271 amp[j] << tab << sv[j] << tab << sqrt(sv2[j]) << endl;
272 }
273
274 if ( ninc ) {
275 inc /= ninc;
276 cout << "Counts scale: " << inc << " (" << ninc << ")" << endl;
277 if ( flags & 2 ) {
278 if ( datatype < Float ) scale = inc;
279 else scale /= inc;
280 for ( i=0; i<datasize; i++ ) set(i, floor((*this)[i]/scale + 0.5));
281 statistics();
282 }
283 }
284
285 long ncol(1+np);
286 Bstring title("Peaks");
287 Bplot* plot = NULL;
288
289 if ( flags & 1 ) {
290 plot = new Bplot(1, bins, ncol);
291 plot->title(title);
292
293 plot->page(0).title(title);
294 plot->page(0).columns(ncol);
295 for ( i=0; i<ncol; i++ ) plot->page(0).column(i).number(i);
296 plot->page(0).column(0).label("Bin");
297 plot->page(0).column(0).axis(1);
298 plot->page(0).column(1).type(1);
299 plot->page(0).column(1).label("Count");
300 plot->page(0).column(1).axis(3);
301 plot->page(0).column(1).element_size(0.5);
302 plot->page(0).column(1).color(0.5,0.5,0.5);
303 for ( j=1, i=2; j<np; j++, i++ ) {
304 plot->page(0).column(i).type(2);
305 plot->page(0).column(i).label("Count");
306 plot->page(0).column(i).axis(3);
307 plot->page(0).column(i).element_size(0.5);
308 plot->page(0).column(i).color(1,0,0);
309 }
310
311 for ( i=0; i<bins; i++ ) {
312 (*plot)[i] = i;
313 (*plot)[i+bins] = h[i];
314 for ( j=1, k=2*bins; j<np; j++, k+=bins )
315 if ( sv2[j] ) {
316 d = sv[j] - i;
317 (*plot)[i+k] = amp[j] * exp(-0.5*d*d/sv2[j]);
318 } else
319 (*plot)[i+k] = 0;
320 }
321 }
322
323 delete[] h;
324
325 return plot;
326 }
327
337 Bplot* Bimage::percentiles()
338 {
339 long bins(10000), pbins(101);
340 long i, j, hsum;
341 double invsize(100.0/datasize);
342 double scale, offset, fraction, d;
343
344 long* histo = histogram(bins, scale, offset);
345
346 double* perc = new double[pbins];
347
348 perc[0] = min;
349 perc[100] = max;
350
351 long ncol(3);
352 Bstring title("Percentiles");
353 Bplot* plot = new Bplot(1, pbins, ncol);
354 plot->title(title);
355
356 plot->page(0).title(title);
357 plot->page(0).columns(ncol);
358 for ( i=0; i<ncol; i++ ) plot->page(0).column(i).number(i);
359 plot->page(0).column(0).label("%");
360 plot->page(0).column(0).axis(1);
361 plot->page(0).column(1).type(1);
362 plot->page(0).column(1).label("Bin");
363 plot->page(0).column(1).axis(3);
364 plot->page(0).column(1).element_size(0.5);
365 plot->page(0).column(2).type(2);
366 plot->page(0).column(2).label("Value");
367 plot->page(0).column(2).axis(3);
368 plot->page(0).column(2).element_size(0.5);
369 plot->page(0).column(2).color(1,0,0);
370 // plot->page(0).axis(1).min(min - bin_half);
371 // plot->page(0).axis(1).max(max + bin_half);
372 // plot->page(0).axis(3).min(prad->minimum());
373 // plot->page(0).axis(3).max(prad->maximum());
374
375 if ( verbose ) {
376 cout << "%\tBin\tValue" << endl;
377 cout << 0 << tab << 0 << tab << perc[0] << endl;
378 }
379 (*plot)[2*pbins] = perc[0];
380 for ( i=j=1, hsum = histo[0]; i<bins; hsum += histo[i], i++ ) {
381 fraction = hsum*invsize;
382 for ( d = (fraction>j)? 1.0/(fraction - j): 1; fraction > j; j++ ) {
383 perc[j] = min + (i - d*(fraction - j))/scale;
384 if ( verbose )
385 cout << j << tab << i << tab << perc[j] << endl;
386 (*plot)[j] = j;
387 (*plot)[pbins+j] = i;
388 (*plot)[2*pbins+j] = perc[j];
389 }
390 }
391 if ( verbose )
392 cout << 100 << tab << i << tab << perc[100] << endl;
393 (*plot)[100] = 100;
394 (*plot)[pbins+100] = i;
395 (*plot)[2*pbins+100] = perc[100];
396
397 delete[] histo;
398 delete[] perc;
399
400 return plot;
401 }
402
414 int Bimage::histogram_thresholds(double& tmin, double& tmax)
415 {
416 if ( max <= min ) statistics();
417
418 // Calculate the histogram and remove large numbers of white and black pixels
419 long i, j, bins(256);
420 if ( (max - min)/std < 25 ) bins = 10*(max - min)/std;
421 if ( datatype <= SCharacter ) bins = (long) (max - min + 1.1);
422
423 long ihi, imin, nmin, imax(bins/2), nmax(0), isig(0);
424 double g, sigma(8.0/(bins*bins));
425 double scale, offset;
426
427 long* hist = histogram(bins, scale, offset);
428
429 if ( verbose & VERB_PROCESS ) {
430 cout << "Estimating extreme thresholds from the histogram:" << endl;
431 cout << "Bins: " << bins << endl;
432 }
433
434 imax = (avg - min)*scale;
435 nmax = hist[imax];
436
437 for ( i=imax/2, j=(bins-imax)/2; i<j; i++ ) {
438 if ( nmax < hist[i] ) { // Find the maximum in the middle part of the histogram
439 nmax = hist[i];
440 imax = i;
441 }
442 }
443
444 while ( imax+isig < bins - 1 && imax-isig > 0 &&
445 hist[imax] < 2*hist[imax+isig] && hist[imax] < 2*hist[imax-isig] )
446 isig++;
447
448 if ( verbose & VERB_DEBUG ) {
449 cout << "DEBUG Bimage::histogram_thresholds: Gaussian parameters:" << endl;
450 cout << "DEBUG Bimage::histogram_thresholds: max=" << nmax << " imax=" << imax << " sigma=" << isig << endl;
451 }
452
453 if ( isig > 0 ) sigma = -0.5/(isig*isig);
454 ihi = 0;
455 for ( i=0; i<imax/2; i++ ) { // Find the highest peak in the first part
456 g = nmax*exp(sigma*(imax - i)*(imax - i));
457 if ( hist[i] > 20*g ) ihi = i;
458 }
459
460 if ( verbose & VERB_DEBUG )
461 cout << "DEBUG Bimage::histogram_thresholds: highest peak in first quarter = " << ihi << endl;
462
463 imin = ihi;
464 nmin = x*y*z;
465 for ( i=ihi; i<imax/2; i++ ) { // Find the minimum after the highest peak in the first part
466 if ( nmin > hist[i] ) {
467 nmin = hist[i];
468 imin = i;
469 }
470 }
471
472 ihi = bins - 1;
473 for ( i=bins-1, j=(bins-imax)/2; i>j; i-- ) { // Find the highest peak in the last part
474 g = nmax*exp(sigma*(imax - i)*(imax - i));
475 if ( hist[i] > 20*g ) ihi = i;
476 }
477
478 if ( verbose & VERB_DEBUG )
479 cout << "DEBUG Bimage::histogram_thresholds: highest peak in last quarter = " << ihi << endl;
480
481 imax = ihi;
482 nmin = x*y*z;
483 for ( i=(bins-imax)/2; i<ihi; i++ ) { // Find the minumum before the highest peak in the last part
484 if ( nmin >= hist[i] ) {
485 nmin = hist[i];
486 imax = i;
487 }
488 }
489
490 delete[] hist;
491
492 if ( imin >= imax ) {
493 cerr << "Error in Bimage::histogram_thresholds: extremes not found!" << endl;
494 return -1;
495 }
496
497 tmin = imin/scale + min;
498 tmax = imax/scale + min;
499
500 if ( verbose & VERB_DEBUG )
501 cout << "DEBUG Bimage::histogram_thresholds: imin=" << imin << " imax=" << imax << " tmin=" << tmin << " tmax=" << tmax << endl;
502
503 if ( verbose & VERB_PROCESS )
504 cout << "Thresholds: " << tmin << tab << tmax << endl << endl;
505
506 return 0;
507 }
508
516 double Bimage::otsu_threshold(long bins)
517 {
518 double scale, offset;
519 long* h = histogram(bins, scale, offset);
520
521 long i, total(x*y*z);
522 double sum(0), sumB(0), wB(0), wF(0), mB, mF, mx(0), bt(0), t1(0), t2(0);
523
524 for ( i = 1; i < bins; ++i )
525 sum += i * h[i];
526
527 for ( i = 0; i < bins; ++i ) {
528 wB += h[i];
529 if (wB == 0)
530 continue;
531 wF = total - wB;
532 if (wF == 0)
533 break;
534 sumB += i * h[i];
535 mB = sumB / wB;
536 mF = (sum - sumB) / wF;
537 bt = wB * wF * (mB - mF) * (mB - mF);
538 if ( bt >= mx ) {
539 t1 = i;
540 if ( bt > mx ) {
541 t2 = i;
542 }
543 mx = bt;
544 }
545 }
546
547 delete[] h;
548
549 return ( t1 + t2 ) / (2 * scale) + min;
550 }
551
552 double simplex_gauss_R(Bsimplex& simp)
553 {
554 long i, j, k;
555 double v, df, R(0);
556 vector<double>& f = simp.dependent_values();
557 vector<double>& x = simp.independent_values();
558
559 for ( i=0; i<simp.points(); i++ ) {
560 for ( j=k=0, df=0; j<simp.constant(0); j++, k+=3 ) {
561 v = (x[i] - simp.parameter(k+1))/simp.parameter(k+2);
562 df += simp.parameter(k)*exp(-0.5*v*v);
563 }
564 df -= f[i];
565 R += df*df;
566 }
567
568 R = sqrt(R/i);
569
570 return R;
571 }
572
583 vector<double> Bimage::histogram_gauss_fit(long bins, long ngauss)
584 {
585 change_type(Float);
586
587 long i, j, nh(bins);
588 long thresh((100*datasize)/bins);
589 double hmax(0), havg[ngauss], hstd[ngauss], w[ngauss];
590
591 double scale, offset;
592 long* histo = histogram(bins, scale, offset);
593
594 long* sel = k_means(datasize, (float *)data_pointer(), ngauss);
595
596 for ( j=0; j<ngauss; j++ ) havg[j] = hstd[j] = w[j] = 0;
597 for ( i=0; i<datasize; i++ ) {
598 havg[sel[i]] += (*this)[i];
599 hstd[sel[i]] += (*this)[i]*(*this)[i];
600 w[sel[i]] += 1;
601 }
602 for ( j=0; j<ngauss; j++ ) {
603 havg[j] /= w[j];
604 hstd[j] /= w[j];
605 hstd[j] -= havg[j]*havg[j];
606 if ( hstd[j] > 0 ) hstd[j] = sqrt(hstd[j]);
607 else hstd[j] = 0;
608 }
609
610 delete[] sel;
611
612 sel = new long[bins];
613
614 // Selection of bins to fit
615 for ( i=nh=0; i<bins; i++ ) {
616 if ( histo[i] < thresh ) {
617 sel[i] = 1;
618 nh++;
619 } else {
620 sel[i] = 0;
621 }
622 }
623
624 if ( nh < 20 && nh < bins/2 )
625 cerr << "Warning: Too few bins selected for fitting! (" << nh << "/" << bins << ")" << endl;
626
627 // 3 parameters: amplitude, position, sigma
628 vector<double> xx(bins), fx(nh);
629 for ( i=j=0; i<bins; i++ ) if ( sel[i] ) {
630 xx[j] = min + i/scale;
631 fx[j] = histo[i];
632 if ( hmax < histo[i] ) hmax = histo[i];
633 j++;
634 }
635
636 delete[] sel;
637
638 Bsimplex simp(1, 3*ngauss, 1, nh, xx, fx);
639 simp.constant(0, ngauss);
640
641 for ( i=j=0; j<ngauss; j++, i++ ) {
642 simp.parameter(i, hmax); // Amplitude
643 simp.limits(i, datasize/bins, 5*hmax);
644 // cout << tab << simp.parameter(i);
645 i++;
646 simp.parameter(i, havg[j]); // Position
647 if ( hstd[j] ) {
648 simp.limits(i, havg[j] - 5*hstd[j], havg[j] + 5*hstd[j]);
649 if ( simp.limit_low(i) < min ) simp.limit_low(i, min);
650 if ( simp.limit_high(i) > max ) simp.limit_high(i, max);
651 } else {
652 simp.limits(i, min, max);
653 }
654 // cout << tab << simp.parameter(i);
655 i++;
656 if ( hstd[j] ) {
657 simp.parameter(i, hstd[j]); // Sigma
658 simp.limits(i, hstd[j]/5, 5*hstd[j]);
659 } else {
660 simp.parameter(i, std); // Sigma
661 simp.limits(i, 1/scale, 0.5*(max - min)/n);
662 }
663 // cout << tab << simp.parameter(i) << endl;
664 }
665
666 double R = simp.run(1000, 0.001, simplex_gauss_R);
667
668 vector<double> gauss;
669 for ( j=0; j<3*ngauss; j++ ) gauss.push_back(simp.parameter(j));
670
671 if ( verbose & VERB_PROCESS ) {
672 cout << "Gaussian fit over " << nh << " bins:" << endl;
673 cout << "Amp\tOffset\tSigma\tSIP" << endl;
674 for ( j=0; j<ngauss; j++ )
675 cout << gauss[3*j] << tab << gauss[3*j+1] << tab << gauss[3*j+2] << tab << bins*gauss[3*j]/datasize << endl;
676 cout << "Sampling-independent RMSD: " << bins*R/datasize << endl << endl;
677 }
678
679 delete[] histo;
680
681 image->FOM(R);
682
683 return gauss;
684 }
685
695 Bplot* Bimage::histogram_gauss_plot(long bins, long ngauss)
696 {
697 long i, j, k, m, ncol(ngauss+2);
698 double v, bin_half = (max - min)/(4*bins);
699
700 vector<double> gauss = histogram_gauss_fit(bins, ngauss);
701
702 double scale, offset;
703 long* histo = histogram(bins, scale, offset);
704
705 // Set the average and standard deviation to the first gaussian parameters
706 average(gauss[1]);
707 standard_deviation(gauss[2]);
708
709 Bstring title("Gaussian fit"), txt;
710 Bplot* plot = new Bplot(1, bins, ncol);
711 plot->title(title);
712
713 plot->page(0).title(title);
714 plot->page(0).columns(ncol);
715 for ( i=0; i<ncol; i++ ) plot->page(0).column(i).number(i);
716 plot->page(0).column(0).label("Bin");
717 plot->page(0).column(0).axis(1);
718 for ( i=1; i<ncol; i++ ) {
719 plot->page(0).column(i).type(2);
720 plot->page(0).column(i).axis(3);
721 plot->page(0).column(i).element_size(0.5);
722 }
723 plot->page(0).column(1).label("Count");
724 for ( i=2; i<ncol; i++ )
725 plot->page(0).column(i).label("Gaussian");
726 plot->page(0).column(1).type(1);
727 plot->page(0).column(1).color(0.5,0.5,0.5);
728 plot->page(0).column(2).color(1,0,0);
729 if ( n > 1 ) plot->page(0).column(3).color(0,1,0);
730 if ( n > 2 ) plot->page(0).column(4).color(0,0,1);
731 plot->page(0).axis(1).min(min - bin_half);
732 plot->page(0).axis(1).max(max + bin_half);
733
734 for ( j=0; j<ngauss; j++ ){
735 txt = Bstring(j+1, "Gaussian %d:") + Bstring(gauss[3*j], " a=%g") +
736 Bstring(gauss[3*j+1], " u=%g") + Bstring(gauss[3*j+2], " s=%g");
737 plot->page(0).add_text(txt);
738 }
739 txt = Bstring(image->FOM(), "R: %g");
740 plot->page(0).add_text(txt);
741
742 for ( i=0, j=bins; i<bins; i++, j++ ) {
743 (*plot)[i] = min + i/scale;
744 (*plot)[j] = histo[i];
745 for ( k=0, m=i+2*bins; k<3*ngauss; k+=3, m+=bins ) {
746 v = ((*plot)[i] - gauss[k+1])/gauss[k+2];
747 (*plot)[m] = gauss[k]*exp(-0.5*v*v);
748 }
749 }
750
751 delete[] histo;
752
753 return plot;
754 }
755 /*
756 double simplex_poisson_R(Bsimplex& simp)
757 {
758 long i, j, n;
759 double v, R(0);
760 // double* df = new double[simp.points()];
761 vector<double> df(simp.points());
762
763 simp.parameter(1, floor(simp.parameter(1)+0.5)); // Enforce integer
764
765 for ( i=0, n=0; i<simp.points(); i++ ) {
766 if ( simp.fx[i] >= 0 ) {
767 v = simp.x[i] + simp.parameter(1);
768 df[i] = fabs(simp.fx[i] - simp.parameter(0) - v*log(simp.parameter(2)) +
769 simp.parameter(2) + lgamma(v+1.0L));
770 if ( !isfinite(df[i]) ) {
771 error_show("Error in img_fit_poisson_to_his_R", __FILE__, __LINE__);
772 cerr << "i=" << i << "\tfx[i]=" << simp.fx[i] << "\tamp=" <<
773 simp.parameter(0) << "\tpos=" << simp.parameter(1)
774 << "\tlambda=" << simp.parameter(2) << endl;
775 return 1e37;
776 }
777 n++;
778 } else df[i] = -1;
779 }
780
781 // qsort((void *) df, simp.points(), sizeof(double),
782 // (int (*)(const void *, const void *)) QsortSmallToLargeDouble);
783 sort(df.begin(), df.end());
784
785 // if ( simp->npoint < 100 ) j = simp->npoint - 3;
786 // else j = (simp->npoint*97)/100;
787 j = simp.points() - 3;
788
789 for ( i=0, R=0; i<j; i++ ) if ( df[i] > -1 ) {
790 R += df[i]*df[i];
791 n++;
792 }
793
794 if ( n ) R = sqrt(R/n);
795 else R = 1e37;
796
797 // delete[] df;
798
799 return R;
800 }
801 */
802 double simplex_poisson_R(Bsimplex& simp)
803 {
804 long i;
805 double df, R(0);
806 vector<double>& f = simp.dependent_values();
807
808 simp.parameter(1, floor(simp.parameter(1)+0.5)); // Enforce integer
809
810 for ( i=0; i<simp.points(); i++ ) {
811 df = f[i] - simp.parameter(0)*pow(simp.parameter(1),(double)i)*exp(-simp.parameter(1))/factorial(i);
812 R += df*df;
813 }
814
815 if ( i ) R = sqrt(R/i);
816
817 return R;
818 }
819
836 /*Bplot* Bimage::histogram_poisson_fit(long bins, int flag)
837 {
838 long i, j, m, nn, ni;
839 double hmax(0), sum(0);
840 double bin_half = (max - min)/(4*bins);
841
842 double scale, offset;
843 long* histo = histogram(bins, scale, offset);
844
845 // Count the number of positive bins and readjust the histogram to have only positive bins
846 for ( i=0, j=0, nn=0, ni=0; i<bins; i++ ) {
847 if ( histo[i] > 0 ) {
848 ni += j;
849 nn++;
850 j = 0;
851 }
852 j++;
853 }
854 // if ( verbose & VERB_FULL )
855 cout << "Positive bins = " << nn << " Interval size = " << ni*1.0/nn << endl;
856 delete[] histo;
857
858 if ( bins < nn ) bins = nn;
859 else bins = (bins*nn)/ni;
860
861 histo = histogram(bins, scale, offset);
862
863 // if ( verbose & VERB_FULL )
864 cout << "Bins reset to " << bins << ", scale = " << scale << ", offset = " << offset << endl << endl;
865
866 // 3 parameters: amplitude, position, sigma
867 // double* x = new double[bins];
868 // double* fx = new double[bins];
869 vector<double> xx(bins), fx(bins);
870 for ( i=0; i<bins; i++ ) xx[i] = min + i/scale;
871 for ( i=1; i<bins-1; i++ ) {
872 if ( histo[i] < 1 ) fx[i] = log(0.5);
873 else fx[i] = log(1.0*histo[i]);
874 sum += fx[i];
875 if ( hmax < fx[i] ) hmax = fx[i];
876 cout << i << tab << xx[i] << tab << histo[i] << tab << fx[i] << endl;
877 }
878 fx[0] = fx[1];
879 fx[bins-1] = log(0.5);
880
881 Bsimplex simp(1, 3, 0, bins, xx, fx);
882
883 simp.parameter(0, log(datasize*1.0)); // ln(Amplitude)
884 simp.limits(0, log(datasize/2.0), log(datasize+1.0));
885
886 simp.parameter(0, 0); // Position in bins
887 simp.limits(1, 0, 0);
888
889 simp.parameter(2, std*std); // Lambda in bins
890 if ( simp.parameter(2) < 0.001 ) simp.parameter(2, 0.001);
891 simp.limits(2, 0.001, 10*std);
892 if ( simp.hi[2] < 1 ) simp.hi[2] = 10*avg;
893
894 double R = simp.run(1000, 0.001, simplex_poisson_R);
895 R = exp(R);
896
897 // delete[] x;
898 // delete[] fx;
899
900 double* poisson = new double[3];
901 poisson[0] = exp(simp.parameter(0));
902 poisson[1] = simp.parameter(1);
903 poisson[2] = simp.parameter(2);
904
905 if ( verbose & VERB_PROCESS ) {
906 cout << "Poisson function fit over " << bins << " bins:" << endl;
907 cout << "Lambda: " << poisson[2] << endl;
908 // cout << "Offset: " << poisson[1] << endl;
909 cout << "Included voxels: " << poisson[0] << " (" << 100*poisson[0]/datasize << "%)" << endl;
910 cout << "Sampling-independent RMSD: " << bins*R/datasize << endl << endl;
911 }
912
913 // Set the average and standard deviation to the poisson parameters
914 average(poisson[2]);
915 standard_deviation(sqrt(poisson[2]));
916 image->FOM(R);
917
918 long ncol(3);
919 Bstring title("Poisson fit"), txt;
920 Bplot* plot = NULL;
921
922 if ( flag ) {
923 plot = new Bplot(1, bins, ncol);
924 plot->title(title);
925
926 plot->page(0).title(title);
927 plot->page(0).columns(ncol);
928 for ( i=0; i<ncol; i++ ) plot->page(0).column(i).number(i);
929 plot->page(0).column(0).label("Bin");
930 plot->page(0).column(0).axis(1);
931 plot->page(0).column(1).type(1);
932 plot->page(0).column(1).label("Count");
933 plot->page(0).column(1).axis(3);
934 plot->page(0).column(1).element_size(0.5);
935 plot->page(0).column(1).color(0.5,0.5,0.5);
936 plot->page(0).column(2).type(2);
937 plot->page(0).column(2).label("Count");
938 plot->page(0).column(2).axis(3);
939 plot->page(0).column(2).element_size(0.5);
940 plot->page(0).column(2).color(1,0,0);
941 plot->page(0).axis(1).min(min - bin_half);
942 plot->page(0).axis(1).max(max + bin_half);
943 // plot->page(0).axis(3).min(prad->minimum());
944 // plot->page(0).axis(3).max(prad->maximum());
945
946 txt = Bstring(poisson[0], "Poisson: a=%g") + Bstring(poisson[2], " u=%g");
947 plot->page(0).add_text(txt);
948 txt = Bstring(R, "R: %g");
949 plot->page(0).add_text(txt);
950
951 for ( i=0, j=bins, m=2*bins; i<bins; i++, j++, m++ ) {
952 (*plot)[i] = i;
953 (*plot)[j] = histo[i];
954 (*plot)[m] = poisson[0]*pow(poisson[2],(double)i)*exp(-poisson[2])/factorial(i);
955 if ( !isfinite((*plot)[m]) ) (*plot)[m] = 0;
956 }
957 }
958
959 delete[] histo;
960 delete[] poisson;
961
962 return plot;
963 }
964 */
965 Bplot* Bimage::histogram_poisson_fit(long bins, int flag)
966 {
967 if ( std <= 0 ) statistics();
968
969 if ( bins > avg + 5*std ) bins = avg + 5*std;
970 if ( bins > 150 ) bins = 150;
971
972 long i, j, m, imax(0);
973 double hmax(0), scale(bins*1.0/(avg+5*std));
974
975 cout << "scale=" << scale << endl;
976
977 vector<double> b(bins, 0);
978 vector<double> h(bins, 0);
979
980 for ( i=0; i<datasize; ++i ) {
981 j = (long) (scale*(*this)[i] + 0.5);
982 if ( j >= 0 && j < bins ) h[j]+=1;
983 }
984
985 for ( i=0; i<bins; ++i ) {
986 b[i] = i;
987 if ( hmax < h[i] ) {
988 hmax = h[i];
989 imax = i;
990 }
991 // cout << i << tab << b[i] << tab << h[i] << endl;
992 }
993
994 // bexit(0);
995
996 Bsimplex simp(1, 2, 0, bins, b, h);
997
998 simp.parameter(0, hmax); // Amplitude
999 simp.limits(0, 5*hmax, 20*hmax);
1000
1001 simp.parameter(1, imax); // Lambda in bins
1002 simp.limits(1, 0.5*imax, 2*imax);
1003 cout << "starting" << endl;
1004 double R = simp.run(1000, 0.001, simplex_poisson_R);
1005
1006 if ( verbose & VERB_PROCESS ) {
1007 cout << "Poisson function fit over " << bins << " bins:" << endl;
1008 cout << "Amplitude: " << simp.parameter(0) << endl;
1009 cout << "Lambda: " << simp.parameter(1) << endl;
1010 cout << "Sampling-independent RMSD: " << bins*R/datasize << endl << endl;
1011 }
1012
1013 // Set the average and standard deviation to the poisson parameters
1014 average(simp.parameter(1));
1015 standard_deviation(sqrt(simp.parameter(1)));
1016 image->FOM(R);
1017
1018 long ncol(3);
1019 Bstring title("Poisson fit"), txt;
1020 Bplot* plot = NULL;
1021
1022 if ( flag ) {
1023 plot = new Bplot(1, bins, ncol);
1024 plot->title(title);
1025
1026 plot->page(0).title(title);
1027 plot->page(0).columns(ncol);
1028 for ( i=0; i<ncol; i++ ) plot->page(0).column(i).number(i);
1029 plot->page(0).column(0).label("Bin");
1030 plot->page(0).column(0).axis(1);
1031 plot->page(0).column(1).type(1);
1032 plot->page(0).column(1).label("Count");
1033 plot->page(0).column(1).axis(3);
1034 plot->page(0).column(1).element_size(0.5);
1035 plot->page(0).column(1).color(0.5,0.5,0.5);
1036 plot->page(0).column(2).type(2);
1037 plot->page(0).column(2).label("Count");
1038 plot->page(0).column(2).axis(3);
1039 plot->page(0).column(2).element_size(0.5);
1040 plot->page(0).column(2).color(1,0,0);
1041 plot->page(0).axis(1).min(0);
1042 plot->page(0).axis(1).max(bins);
1043 // plot->page(0).axis(3).min(prad->minimum());
1044 // plot->page(0).axis(3).max(prad->maximum());
1045
1046 txt = Bstring(simp.parameter(0), "Poisson: a=%g") + Bstring(simp.parameter(1), " u=%g");
1047 plot->page(0).add_text(txt);
1048 txt = Bstring(R, "R: %g");
1049 plot->page(0).add_text(txt);
1050
1051 for ( i=0, j=bins, m=2*bins; i<bins; i++, j++, m++ ) {
1052 (*plot)[i] = i;
1053 (*plot)[j] = h[i];
1054 (*plot)[m] = simp.parameter(0)*pow(simp.parameter(1),(double)i)*exp(-simp.parameter(1))/factorial(i);
1055 if ( !isfinite((*plot)[m]) ) (*plot)[m] = 0;
1056 }
1057 }
1058
1059 return plot;
1060 }
1061
Bimage::change_type
void change_type(char letter)
Get the data type indicated by a single letter code.
Definition: Bimage.cpp:1743
qsort_functions.h
Header file for utility functions for use in qsort calls.
Bimage::histogram
long * histogram(long bins, double &scale, double &offset)
Calculates the histogram of an image.
Definition: Bimage_histogram.cpp:32
Bimage.h
Header file for image class.
Bimage::sampling
Vector3< double > sampling()
Definition: Bimage.h:505
Baxis::min
double min()
Definition: Bplot.h:30
Bplot::title
Bstring & title()
Definition: Bplot.h:189
Bimage::image_size
long image_size()
Definition: Bimage.h:267
Bcolumn::element_size
double element_size()
Definition: Bplot.h:74
utilities.h
Header file for general utilities.
Bsimplex
Structure used in the downhill simplex method.
Definition: simplex.h:42
VERB_DEBUG
#define VERB_DEBUG
Definition: utilities.h:112
Bcolumn::label
Bstring & label()
Definition: Bplot.h:63
Bsimplex::parameter
void parameter(long i, double p)
Definition: simplex.h:69
Bsimplex::dependent_values
vector< double > & dependent_values()
Definition: simplex.h:83
SCharacter
Definition: utilities.h:150
VERB_PROCESS
#define VERB_PROCESS
Definition: utilities.h:107
Bcolumn::color
double * color()
Definition: Bplot.h:76
Bpage::column
Bcolumn & column(long i)
Definition: Bplot.h:110
Bsimplex::run
double run(long maxcycles, double tolerance, double(funk)(Bsimplex &))
Definition: simplex.cpp:76
Baxis::max
double max()
Definition: Bplot.h:32
Float
Definition: utilities.h:157
Bimage::histogram_gauss_plot
Bplot * histogram_gauss_plot(long bins, long ngauss=1)
Fits a gaussian function to a histogram of an image.
Definition: Bimage_histogram.cpp:695
factorial
double factorial(int n)
Calculates the factorial of n.
Definition: math_util.cpp:66
Bsimplex::independent_values
vector< double > & independent_values()
Definition: simplex.h:82
Bimage::histogram_gauss_fit
vector< double > histogram_gauss_fit(long bins, long ngauss=1)
Fits a gaussian function to a histogram of an image.
Definition: Bimage_histogram.cpp:583
Bsimplex::points
long points()
Definition: simplex.h:64
isfinite
bool isfinite(complex< T > &value)
Bcolumn::number
long number()
Definition: Bplot.h:61
Bimage::statistics
long statistics()
Calculates the statistics for an image.
Definition: Bimage_stats.cpp:22
Bimage::histogram_poisson_fit
Bplot * histogram_poisson_fit(long bins, int flag=0)
Fits a poisson function to a histogram of an image.
Definition: Bimage_histogram.cpp:965
Bsimplex::limit_high
void limit_high(long i, double v)
Definition: simplex.h:73
simplex_gauss_R
double simplex_gauss_R(Bsimplex &simp)
Definition: Bimage_histogram.cpp:552
Bcolumn::type
long type()
Definition: Bplot.h:66
Bsub_image::FOM
double FOM()
Definition: Bimage.h:151
Bpage::axis
Baxis & axis(long id)
Definition: Bplot.h:117
Bpage::title
Bstring & title()
Definition: Bplot.h:100
verbose
int verbose
Bimage::sum
void sum(long m, Bimage **p)
Sums an array of images with their FOM blocks.
Definition: Bimage_combine.cpp:23
Bsimplex::constant
double constant(long i)
Definition: simplex.h:59
Bimage::standard_deviation
double standard_deviation()
Definition: Bimage.h:537
Bimage::average
double average()
Definition: Bimage.h:536
Bimage::set
void set(long j, double v)
Sets a single value at the given index.
Definition: Bimage.cpp:1096
k_means
long * k_means(long n, float *data, long k)
Generate clusters using a K-means algorithm.
Definition: cluster.cpp:28
Bpage::add_text
void add_text(Bstring &s)
Definition: Bplot.h:122
Bimage::data_pointer
unsigned char * data_pointer()
Definition: Bimage.h:261
Bsimplex::limit_low
void limit_low(long i, double v)
Definition: simplex.h:71
simplex.h
Nelder and Mead downhill simplex method for generalized parameter fitting.
Bimage::otsu_threshold
double otsu_threshold(long bins)
Calculates the threshold on a histogram according to Otsu.
Definition: Bimage_histogram.cpp:516
Bstring
Definition: Bstring.h:29
Bplot::page
Bpage & page(long i)
Definition: Bplot.h:211
matrix_linear.h
Header file for matrix functions.
simplex_poisson_R
double simplex_poisson_R(Bsimplex &simp)
Definition: Bimage_histogram.cpp:802
RHO
#define RHO
Definition: utilities.h:91
cluster.h
Header file for clustering functions.
Bpage::columns
void columns(long ncol)
Definition: Bplot.h:105
Bimage::histogram_counts
Bplot * histogram_counts(int flags=0)
Finds the peaks in a quantized image from the histogram.
Definition: Bimage_histogram.cpp:206
Bimage::plot
Bplot * plot()
Converts a one-dimensional image into a plot.
Definition: Bimage.cpp:3836
Vector3::volume
double volume()
Definition: Vector3.h:235
Bimage::percentiles
Bplot * percentiles()
Calculates the percentiles from the histogram of an image.
Definition: Bimage_histogram.cpp:337
VERB_LABEL
#define VERB_LABEL
Definition: utilities.h:106
Bsimplex::limits
void limits(long i, double vlo, double vhi)
Definition: simplex.h:75
Bimage::histogram_thresholds
int histogram_thresholds(double &tmin, double &tmax)
Calculates minimum and maximum thresholds for truncation.
Definition: Bimage_histogram.cpp:414
bexit
int bexit(int value)
Exit function for cleanup and debugging.
Definition: utilities.cpp:273
tab
ostream & tab(ostream &out)
Definition: utilities.cpp:21
Bimage::image
Bsub_image * image
Definition: Bimage.h:188
Bcolumn::axis
long axis()
Definition: Bplot.h:68
Bplot
Definition: Bplot.h:146