EMAN2
pointarray.cpp
Go to the documentation of this file.
1/*
2 * Author: Wen Jiang, 08/11/2004 (jiang12@purdue.edu)
3 * Copyright (c) 2000-2006 Baylor College of Medicine
4 *
5 * This software is issued under a joint BSD/GNU license. You may use the
6 * source code in this file under either license. However, note that the
7 * complete EMAN2 and SPARX software packages have some GPL dependencies,
8 * so you are responsible for compliance with the licenses of these packages
9 * if you opt to use BSD licensing. The warranty disclaimer below holds
10 * in either instance.
11 *
12 * This complete copyright notice must be included in any revised version of the
13 * source code. Additional authorship citations may be added, but existing
14 * author citations must be preserved.
15 *
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 *
30 * */
31
32
33#include "pointarray.h"
34#include "util.h"
35#include "vec3.h"
36#include <vector>
37#include <cstring>
38#include <boost/random.hpp>
39
40#ifdef __APPLE__
41 typedef unsigned int uint;
42#endif //__APPLE__
43
44#ifdef _WIN32
45 typedef unsigned int uint;
46#endif //_WIN32
47
48using namespace EMAN;
49
50int cmp_axis_x(const void *a, const void *b)
51{
52 double diff = ((double *) a)[0] - ((double *) b)[0];
53 if (diff < 0.0)
54 return -1;
55 else if (diff > 0.0)
56 return 1;
57 else
58 return 0;
59}
60int cmp_axis_y(const void *a, const void *b)
61{
62 double diff = ((double *) a)[1] - ((double *) b)[1];
63 if (diff < 0.0)
64 return -1;
65 else if (diff > 0.0)
66 return 1;
67 else
68 return 0;
69}
70int cmp_axis_z(const void *a, const void *b)
71{
72 double diff = ((double *) a)[2] - ((double *) b)[2];
73 if (diff < 0.0)
74 return -1;
75 else if (diff > 0.0)
76 return 1;
77 else
78 return 0;
79}
80int cmp_val(const void *a, const void *b)
81{
82 double diff = ((double *) a)[3] - ((double *) b)[3];
83 if (diff < 0.0)
84 return -1;
85 else if (diff > 0.0)
86 return 1;
87 else
88 return 0;
89}
90// This will do a sort in descending order
91int cmp_float(const void *a, const void *b)
92{
93 double diff = *((float *) a) - *((float *) b);
94 if (diff < 0.0)
95 return 1;
96 else if (diff > 0.0)
97 return -1;
98 else
99 return 0;
100}
101
102
103PointArray::PointArray()
104{
105 points = 0;
106 bfactor = 0;
107 n = 0;
108
109 adist=0;
110 aang=0;
111 adihed=0;
112
114}
115
117{
118 n = nn;
119 points = (double *) calloc(4 * n, sizeof(double));
120
121 adist=0;
122 aang=0;
123 adihed=0;
125}
126
128{
129 if( points )
130 {
131 free(points);
132 points = 0;
133 }
134
135 if (adist) free(adist);
136 if (aang) free(aang);
137 if (adihed) free(adihed);
138// if (map!=0) delete map;
139 if (gradx!=0) delete gradx;
140 if (grady!=0) delete grady;
141 if (gradz!=0) delete gradz;
142}
143
145{
146 memset((void *) points, 0, 4 * n * sizeof(double));
147}
148
150{
151 PointArray *pa2 = new PointArray();
153 double *pa2data = pa2->get_points_array();
154 memcpy(pa2data, get_points_array(), sizeof(double) * 4 * get_number_points());
155
156 return pa2;
157}
158
160{
161 if (this != &pa) {
163 memcpy(get_points_array(), pa.get_points_array(), sizeof(double) * 4 * get_number_points());
164 }
165 return *this;
166}
167
169{
170 return n;
171}
172
174{
175 if (n != nn) {
176 n = nn;
177 points = (double *) realloc(points, 4 * n * sizeof(double));
178 bfactor = (double *) realloc(bfactor, n * sizeof(double));
179 }
180}
181
183{
184 return points;
185}
186
188{
189 points = p;
190}
191
193if (n==0) return NULL;
194
195unsigned int i,j;
196
197EMData *ret= new EMData(n,n,1);
198ret->to_zero();
199
200for (i=0; i<n; i++) {
201 for (j=i+1; j<n; j++) {
202 float r=(get_vector_at(i)-get_vector_at(j)).length();
203 ret->set_value_at(i,j,0,r);
204 ret->set_value_at(j,i,0,r);
205 }
206}
207
208if (sortrows) {
209 float *data=ret->get_data();
210 for (i=0; i<n; i++) qsort(&data[i*n],n,sizeof(float),cmp_float);
211 ret->update();
212}
213
214return ret;
215}
216
217vector<int> PointArray::match_points(PointArray *to,float max_miss) {
218EMData *mx0=distmx(1);
219EMData *mx1=to->distmx(1);
220unsigned int n2=mx1->get_xsize(); // same as get_number_points on to
221
222if (max_miss<0) max_miss=(float)mx0->get_attr("sigma")/10.0f;
223//printf("max error %f\n",max_miss);
224
225
226
227vector<int> ret(n,-1);
228vector<float> rete(n,0.0);
229unsigned int i,j,k,l;
230
231if (!mx0 || !mx1) {
232 if (mx0) delete mx0;
233 if (mx1) delete mx1;
234 return ret;
235}
236
237// i iterates over elements of 'this', j looks for a match in 'to'
238// k and l iterate over the individual distances
239for (i=0; i<n; i++) {
240 int bestn=-1; // number of best match in mx1
241 double bestd=1.0e38; // residual error distance in best match
242 for (j=0; j<n2; j++) {
243 double d=0;
244 int nd=0;
245 for (k=l=0; k<n-1 && l<n2-1; k++,l++) {
246 float d1=fabs(mx0->get_value_at(k,i)-mx1->get_value_at(l,j));
247 float d2=fabs(mx0->get_value_at(k+1,i)-mx1->get_value_at(l,j));
248 float d3=fabs(mx0->get_value_at(k,i)-mx1->get_value_at(l+1,j));
249 float d4=fabs(mx0->get_value_at(k+1,i)-mx1->get_value_at(l+1,j));
250 if (d2<d1 && d4>d2) { l--; continue; }
251 if (d3<d1 && d4>d3) { k--; continue; }
252 d+=d1;
253 nd++;
254 }
255 d/=(float)nd;
256// printf("%d -> %d\t%f\t%d\n",i,j,d,nd);
257 if (d<bestd) { bestd=d; bestn=j; }
258 }
259 ret[i]=bestn;
260 rete[i]=static_cast<float>(bestd);
261}
262
263// This will remove duplicate assignments, keeping the best one
264// also remove any assignments with large errors
265for (i=0; i<n; i++) {
266 for (j=0; j<n; j++) {
267 if (rete[i]>max_miss) { ret[i]=-1; break; }
268 if (i==j || ret[i]!=ret[j] || ret[i]==-1) continue;
269 if (rete[i]>rete[j]) { ret[i]=-1; break; }
270 }
271}
272
273delete mx0;
274delete mx1;
275
276return ret;
277}
278
279// uses bilinear least-squares to generate a transformation
280// matrix for pairs of points
282vector<int> match=match_points(to,max_dist);
283Transform *ret=new Transform();
284
285// we use bilinear least squares to get 3/6 matrix components
286unsigned int i,j;
287
288vector<float> pts;
289for (i=0; i<match.size(); i++) {
290 if (match[i]==-1) continue;
291
292// printf("%d -> %d\n",i,match[i]);
293 pts.push_back(get_vector_at(i)[0]);
294 pts.push_back(get_vector_at(i)[1]);
295 pts.push_back(to->get_vector_at(match[i])[0]);
296}
297
299
300// then we get the other 3/6
301for (i=j=0; i<match.size(); i++) {
302 if (match[i]==-1) continue;
303 pts[j*3] =get_vector_at(i)[0];
304 pts[j*3+1]=get_vector_at(i)[1];
305 pts[j*3+2]=to->get_vector_at(match[i])[1];
306 j++;
307}
308
310
311//ret->set_rotation(vx[1],vx[2],0.0,vy[1],vy[2],0.0,0.0,0.0,1.0);
312//ret->set_rotation(vx[1],vy[1],0.0,vx[2],vy[2],0.0,0.0,0.0,1.0);
313//ret->set_pretrans(Vec3f(-vx[0],-vy[0],0));
314
315ret->set(0, 0, vx[1]);
316ret->set(0, 1, vy[1]);
317ret->set(0, 2, 0.0f);
318ret->set(1, 0, vx[2]);
319ret->set(1, 1, vy[2]);
320ret->set(1, 2, 0.0f);
321ret->set(2, 0, 0.0f);
322ret->set(2, 1, 0.0f);
323ret->set(2, 2, 1.0f);
324ret->set_pre_trans(Vec3f(-vx[0],-vy[0],0));
325
326return ret;
327}
328
329bool PointArray::read_from_pdb(const char *file, const vector<int> &lines)
330{
331 struct stat filestat;
332 stat(file, &filestat);
333 set_number_points(( int)(filestat.st_size / 80 + 1));
334
335 #ifdef DEBUG
336 printf("PointArray::read_from_pdb(): try %4lu atoms first\n", get_number_points());
337 #endif
338
339 FILE *fp = fopen(file, "r");
340 if(!fp) {
341 fprintf(stderr,"ERROR in PointArray::read_from_pdb(): cannot open file %s\n",file);
342 throw;
343 }
344 char s[200];
345 size_t count = 0;
346
347 int line_num = -1;
348
349 set<int> lines_set(begin(lines), end(lines)); // searching in sets should be faster than vectors
350
351 while ((fgets(s, 200, fp) != NULL)) {
352 line_num++;
353
354 if(find(begin(lines_set), end(lines_set), line_num) == end(lines_set))
355 continue;
356
357 if (strncmp(s, "ENDMDL", 6) == 0)
358 break;
359 if (strncmp(s, "ATOM", 4) != 0)
360 continue;
361
362 if (s[13] == ' ')
363 s[13] = s[14];
364 if (s[13] == ' ')
365 s[13] = s[15];
366
367 float e = 0;
368 char ctt, ctt2 = ' ';
369 if (s[13] == ' ')
370 ctt = s[14];
371 else if (s[12] == ' ') {
372 ctt = s[13];
373 ctt2 = s[14];
374 }
375 else {
376 ctt = s[12];
377 ctt2 = s[13];
378 }
379
380 switch (ctt) {
381 case 'H':
382 e = 1.0;
383 break;
384 case 'C':
385 e = 6.0;
386 break;
387 case 'A':
388 if (ctt2 == 'U') {
389 e = 79.0;
390 break;
391 }
392 // treat 'A'mbiguous atoms as N, not perfect, but good enough
393 case 'N':
394 e = 7.0;
395 break;
396 case 'O':
397 e = 8.0;
398 break;
399 case 'P':
400 e = 15.0;
401 break;
402 case 'S':
403 e = 16.0;
404 break;
405 case 'W':
406 e = 18.0;
407 break; // ficticious water 'atom'
408 case 'K':
409 e = 19.0;
410 break;
411 default:
412 fprintf(stderr, "Unknown atom %c%c\n", ctt, ctt2);
413 e = 0;
414 }
415 if (e == 0)
416 continue;
417
418 float x, y, z, q;
419 sscanf(&s[28], " %f %f %f", &x, &y, &z);
420 sscanf(&s[60], " %f", &q);
421
422 if (count + 1 > get_number_points())
423 set_number_points(2 * (count + 1)); //makes sure point array is big enough
424
425#ifdef DEBUG
426 printf("Atom %4lu: x,y,z = %8g,%8g,%8g\te = %g\n", count, x, y, z, e);
427#endif
428 points[4 * count] = x;
429 points[4 * count + 1] = y;
430 points[4 * count + 2] = z;
431 points[4 * count + 3] = e;
432 bfactor[count] = q;
433 count++;
434 }
435 fclose(fp);
436 set_number_points(count);
437 return true;
438}
439
440
441void PointArray::save_to_pdb(const char *file)
442{
443 FILE *fp = fopen(file, "w");
444 for ( size_t i = 0; i < get_number_points(); i++) {
445 fprintf(fp, "ATOM %5lu CA ALA A%4lu %8.3f%8.3f%8.3f%6.2f%6.2f%8s\n", i, i,
446 points[4 * i], points[4 * i + 1], points[4 * i + 2], points[4 * i + 3], 0.0, " ");
447 }
448 fprintf(fp, "TER %5lu ALA A%4lu\nEND", get_number_points(),get_number_points()-1);
449 fclose(fp);
450}
451
452
454{
455 double xc, yc, zc;
456 xc = yc = zc = 0.0;
457 double norm = 0.0;
458 for ( size_t i = 0; i < 4 * get_number_points(); i += 4) {
459 xc += points[i] * points[i + 3];
460 yc += points[i + 1] * points[i + 3];
461 zc += points[i + 2] * points[i + 3];
462 norm += points[i + 3];
463 }
464 if (norm <= 0) {
465 fprintf(stderr, "Abnormal total value (%g) for PointArray, it should be >0\n", norm);
466 return FloatPoint(0, 0, 0);
467 }
468 else
469 return FloatPoint(xc / norm, yc / norm, zc / norm);
470}
471
473{
474 FloatPoint center = get_center();
475 for ( size_t i = 0; i < 4 * get_number_points(); i += 4) {
476 points[i] -= center[0];
477 points[i + 1] -= center[1];
478 points[i + 2] -= center[2];
479 }
480}
481
483{
484 double xmin, ymin, zmin;
485 double xmax, ymax, zmax;
486 xmin = xmax = points[0];
487 ymin = ymax = points[1];
488 zmin = zmax = points[2];
489 for ( size_t i = 0; i < 4 * get_number_points(); i += 4) {
490 if (points[i] > xmax)
491 xmax = points[i];
492 if (points[i] < xmin)
493 xmin = points[i];
494 if (points[i + 1] > ymax)
495 ymax = points[i + 1];
496 if (points[i + 1] < ymin)
497 ymin = points[i + 1];
498 if (points[i + 2] > zmax)
499 zmax = points[i + 2];
500 if (points[i + 2] < zmin)
501 zmin = points[i + 2];
502 }
503 return Region(xmin, ymin, zmin, xmax - xmin, ymax - ymin, zmax - zmin);
504}
505
506
507void PointArray::mask(double rmax, double rmin)
508{
509 double rmax2 = rmax * rmax, rmin2 = rmin * rmin;
510 PointArray *tmp = this->copy();
511 double *tmp_points = tmp->get_points_array();
512 int count = 0;
513 for ( size_t i = 0; i < 4 * tmp->get_number_points(); i += 4) {
514 double x = tmp_points[i], y = tmp_points[i + 1], z = tmp_points[i + 2], v =
515 tmp_points[i + 3];
516 double r2 = x * x + y * y + z * z;
517 if (r2 >= rmin2 && r2 <= rmax2) {
518 points[count * 4] = x;
519 points[count * 4 + 1] = y;
520 points[count * 4 + 2] = z;
521 points[count * 4 + 3] = v;
522 ++count;
523 }
524 }
525 set_number_points(count);
526 if( tmp )
527 {
528 delete tmp;
529 tmp = 0;
530 }
531}
532
533
534void PointArray::mask_asymmetric_unit(const string & sym)
535{
536 if (sym == "c1" || sym == "C1")
537 return; // do nothing for C1 symmetry
538 double alt0 = 0, alt1 = M_PI, alt2 = M_PI;
539 double az0 = 0, az1 = M_PI;
540 if (sym[0] == 'c' || sym[0] == 'C') {
541 int nsym = atoi(sym.c_str() + 1);
542 az1 = 2.0 * M_PI / nsym / 2.0;
543 }
544 else if (sym[0] == 'd' || sym[0] == 'D') {
545 int nsym = atoi(sym.c_str() + 1);
546 alt1 = M_PI / 2.0;
547 alt2 = alt1;
548 az1 = 2.0 * M_PI / nsym / 2.0;
549 }
550 else if (sym == "icos" || sym == "ICOS") {
551 alt1 = 0.652358139784368185995; // 5fold to 3fold
552 alt2 = 0.55357435889704525151; // half of edge ie. 5fold to 2fold along the edge
553 az1 = 2.0 * M_PI / 5 / 2.0;
554 }
555 else {
556 LOGERR("PointArray::set_to_asymmetric_unit(): sym = %s is not implemented yet",
557 sym.c_str());
558 return;
559 }
560#ifdef DEBUG
561 printf("Sym %s: alt0 = %8g\talt1 = %8g\talt2 = %8g\taz0 = %8g\taz1 = %8g\n", sym.c_str(), alt0*180.0/M_PI, alt1*180.0/M_PI, alt2*180.0/M_PI, az0*180.0/M_PI, az1*180.0/M_PI);
562#endif
563
564 PointArray *tmp = this->copy();
565 double *tmp_points = tmp->get_points_array();
566 int count = 0;
567 for ( size_t i = 0; i < 4 * tmp->get_number_points(); i += 4) {
568 double x = tmp_points[i], y = tmp_points[i + 1], z = tmp_points[i + 2], v = tmp_points[i + 3];
569 double az = atan2(y, x);
570 double az_abs = fabs(az - az0);
571 if (az_abs < (az1 - az0)) {
572 double alt_max = alt1 + (alt2 - alt1) * az_abs / (az1 - az0);
573 double alt = acos(z / sqrt(x * x + y * y + z * z));
574 if (alt < alt_max && alt >= alt0) {
575#ifdef DEBUG
576 printf("Point %3lu: x,y,z = %8g,%8g,%8g\taz = %8g\talt = %8g\n",i/4,x,y,z,az*180.0/M_PI, alt*180.0/M_PI);
577#endif
578 points[count * 4] = x;
579 points[count * 4 + 1] = y;
580 points[count * 4 + 2] = z;
581 points[count * 4 + 3] = v;
582 count++;
583 }
584 }
585 }
586 set_number_points(count);
587 if( tmp )
588 {
589 delete tmp;
590 tmp = 0;
591 }
592}
593
594vector<float> PointArray::get_points() {
595vector<float> ret;
596for (unsigned int i=0; i<n; i++) {
597 ret.push_back((float)points[i*4]);
598 ret.push_back((float)points[i*4+1]);
599 ret.push_back((float)points[i*4+2]);
600}
601
602return ret;
603}
604
606
607 for ( unsigned int i = 0; i < 4 * n; i += 4) {
608 Vec3f v((float)points[i],(float)points[i+1],(float)points[i+2]);
609 v=v*xf;
610 points[i] =v[0];
611 points[i+1]=v[1];
612 points[i+2]=v[2];
613 }
614
615}
616
618 for ( unsigned int i = 0; i < 4 * n; i += 4) {
619 Transform s = transform.transpose();
620 Vec3f v((float)points[i],(float)points[i+1],(float)points[i+2]);
621 v= s*v;
622 points[i] =v[0];
623 points[i+1]=v[1];
624 points[i+2]=v[2];
625 }
626}
627void PointArray::set_from(PointArray * source, const string & sym, Transform *transform)
628{
629 set_from(source->get_points_array(), source->get_number_points(), sym, transform);
630}
631
632void PointArray::set_from(double *src, int num, const string & sym, Transform *xform)
633{
634 int nsym = xform->get_nsym(sym);
635 if (xform==0){
636 Transform tr;
637 xform=&tr;
638 }
639
640 if (get_number_points() != (size_t)nsym * num)
641 set_number_points((size_t)nsym * num);
642
643 double *target = get_points_array();
644
645 for ( int s = 0; s < nsym; s++) {
646 int index = s * 4 * num;
647 for ( int i = 0; i < 4 * num; i += 4, index += 4) {
648 Vec3f v((float)src[i],(float)src[i+1],(float)src[i+2]);
649 v=v*xform->get_sym(sym,s);
650 target[index] =v[0];
651 target[index+1]=v[1];
652 target[index+2]=v[2];
653 target[index+3]=src[i+3];
654 }
655 }
656}
657
658void PointArray::set_from(vector<float> pts) {
659 set_number_points(pts.size()/4);
660 for (unsigned int i=0; i<pts.size(); i++) points[i]=pts[i];
661}
662
663void PointArray::set_from_density_map(EMData * map, int num, float thresh, float apix,
665{
666 if (mode == PEAKS_SUB || mode == PEAKS_DIV) {
667 // find out how many voxels are useful voxels
668 int num_voxels = 0;
669 int nx = map->get_xsize(), ny = map->get_ysize(), nz = map->get_zsize();
670 size_t size = (size_t)nx * ny * nz;
671 EMData *tmp_map = map->copy();
672 float *pd = tmp_map->get_data();
673 for (size_t i = 0; i < size; ++i) {
674 if (pd[i] > thresh)
675 ++num_voxels;
676 }
677
678 double pointvol = double (num_voxels) / double (num);
679 double gauss_real_width = pow(pointvol, 1. / 3.); // in pixels
680#ifdef DEBUG
681 printf("Average point range radius = %g pixels for %d points from %d used voxels\n",
682 gauss_real_width, num, num_voxels);
683#endif
684
685 double min_table_val = 1e-4;
686 double max_table_x = sqrt(-log(min_table_val)); // for exp(-x*x)
687
688 double table_step_size = 1.; // number of steps for each pixel
689 double inv_table_step_size = 1.0 / table_step_size;
690 int table_size = int (max_table_x * gauss_real_width / (table_step_size) * 1.25) + 1;
691 double *table = (double *) malloc(sizeof(double) * table_size);
692 for (int i = 0; i < table_size; i++) {
693 double x = i * table_step_size / gauss_real_width;
694 table[i] = exp(-x * x);
695 }
696
697 int gbox = int (max_table_x * gauss_real_width); // local box half size in pixels to consider for each point
698 if (gbox <= 0)
699 gbox = 1;
700
702 for (int count = 0; count < num; count++) {
703 float cmax = pd[0];
704 int cmaxpos = 0;
705 for (size_t i = 0; i < size; ++i) {
706 if (pd[i] > cmax) {
707 cmax = pd[i];
708 cmaxpos = i;
709 }
710 }
711 int iz = cmaxpos / (nx * ny), iy = (cmaxpos - iz * nx * ny) / nx, ix =
712 cmaxpos - iz * nx * ny - iy * nx;
713
714 // update coordinates in pixels
715 points[4*count ] = ix;
716 points[4*count+1] = iy;
717 points[4*count+2] = iz;
718 points[4*count+3] = cmax;
719#ifdef DEBUG
720 printf("Point %d: val = %g\tat %d, %d, %d\n", count, cmax, ix, iy, iz);
721#endif
722
723 int imin = ix - gbox, imax = ix + gbox;
724 int jmin = iy - gbox, jmax = iy + gbox;
725 int kmin = iz - gbox, kmax = iz + gbox;
726 if (imin < 0)
727 imin = 0;
728 if (jmin < 0)
729 jmin = 0;
730 if (kmin < 0)
731 kmin = 0;
732 if (imax > nx)
733 imax = nx;
734 if (jmax > ny)
735 jmax = ny;
736 if (kmax > nz)
737 kmax = nz;
738
739 for (int k = kmin; k < kmax; ++k) {
740 int table_index_z = int (fabs(double (k - iz)) * inv_table_step_size);
741 double zval = table[table_index_z];
742 size_t pd_index_z = k * nx * ny;
743 //printf("k = %8d\tx = %8g\tval = %8g\n", k, float(k-iz), zval);
744 for (int j = jmin; j < jmax; ++j) {
745 int table_index_y = int (fabs(double (j - iy)) * inv_table_step_size);
746 double yval = table[table_index_y];
747 size_t pd_index = pd_index_z + j * nx + imin;
748 for (int i = imin; i < imax; ++i, ++pd_index) {
749 int table_index_x = int (fabs(double (i - ix)) * inv_table_step_size);
750 double xval = table[table_index_x];
751 if (mode == PEAKS_SUB)
752 pd[pd_index] -= (float)(cmax * zval * yval * xval);
753 else
754 pd[pd_index] *= (float)(1.0 - zval * yval * xval); // mode == PEAKS_DIV
755 }
756 }
757 }
758 }
760 tmp_map->update();
761 if( tmp_map )
762 {
763 delete tmp_map;
764 tmp_map = 0;
765 }
766 }
767 else if (mode == KMEANS) {
769 zero();
770
771 PointArray tmp_pa;
772 tmp_pa.set_number_points(num);
773 tmp_pa.zero();
774
775 int nx = map->get_xsize(), ny = map->get_ysize(), nz = map->get_zsize();
776 float *pd = map->get_data();
777
778 // initialize segments with random centers at pixels with values > thresh
779#ifdef DEBUG
780 printf("Start initial random seeding\n");
781#endif
782 for ( size_t i = 0; i < get_number_points(); i++) {
783 int x, y, z;
784 double v;
785 do {
786 x = ( int) Util::get_frand(0, nx - 1);
787 y = ( int) Util::get_frand(0, ny - 1);
788 z = ( int) Util::get_frand(0, nz - 1);
789 v = pd[z * nx * ny + y * nx + x];
790#ifdef DEBUG
791 printf("Trying Point %lu: val = %g\tat %d, %d, %d\tfrom map (%d,%d,%d)\n", i, v, x,
792 y, z, nx, ny, nz);
793#endif
794 } while (v <= thresh);
795 points[4 * i] = (double) x;
796 points[4 * i + 1] = (double) y;
797 points[4 * i + 2] = (double) z;
798 points[4 * i + 3] = (double) v;
799#ifdef DEBUG
800 printf("Point %lu: val = %g\tat %g, %g, %g\n", i, points[4 * i + 3], points[4 * i],
801 points[4 * i + 1], points[4 * i + 2]);
802#endif
803 }
804
805 double min_dcen = 1e0; // minimal mean segment center shift as convergence criterion
806 double dcen = 0.0;
807 int iter = 0, max_iter = 100;
808 do {
809#ifdef DEBUG
810 printf("Iteration %3d, start\n", iter);
811#endif
812 double *tmp_points = tmp_pa.get_points_array();
813
814 // reassign each pixel to the best segment
815 for ( int k = 0; k < nz; k++) {
816 for ( int j = 0; j < ny; j++) {
817 for ( int i = 0; i < nx; i++) {
818 size_t idx = k * nx * ny + j * nx + i;
819 if (pd[idx] > thresh) {
820 double min_dist = 1e60; // just a large distance
821 int min_s = 0;
822 for ( size_t s = 0; s < get_number_points(); ++s) {
823 double x = points[4 * s];
824 double y = points[4 * s + 1];
825 double z = points[4 * s + 2];
826 double dist =
827 (k - z) * (k - z) + (j - y) * (j - y) + (i - x) * (i - x);
828 if (dist < min_dist) {
829 min_dist = dist;
830 min_s = s;
831 }
832 }
833 tmp_points[4 * min_s] += i;
834 tmp_points[4 * min_s + 1] += j;
835 tmp_points[4 * min_s + 2] += k;
836 tmp_points[4 * min_s + 3] += 1.0;
837 }
838 }
839 }
840 }
841#ifdef DEBUG
842 printf("Iteration %3d, finished reassigning segments\n", iter);
843#endif
844 // update each segment's center
845 dcen = 0.0;
846 for ( size_t s = 0; s < get_number_points(); ++s) {
847 if (tmp_points[4 * s + 3]) {
848 tmp_points[4 * s] /= tmp_points[4 * s + 3];
849 tmp_points[4 * s + 1] /= tmp_points[4 * s + 3];
850 tmp_points[4 * s + 2] /= tmp_points[4 * s + 3];
851#ifdef DEBUG
852 printf("Iteration %3d, Point %3lu at %8g, %8g, %8g -> %8g, %8g, %8g\n", iter, s,
853 points[4 * s], points[4 * s + 1], points[4 * s + 2], tmp_points[4 * s],
854 tmp_points[4 * s + 1], tmp_points[4 * s + 2]);
855#endif
856 }
857 else { // empty segments are reseeded
858 int x, y, z;
859 double v;
860 do {
861 x = ( int) Util::get_frand(0, nx - 1);
862 y = ( int) Util::get_frand(0, ny - 1);
863 z = ( int) Util::get_frand(0, nz - 1);
864 v = pd[z * nx * ny + y * nx + x];
865 } while (v <= thresh);
866 tmp_points[4 * s] = (double) x;
867 tmp_points[4 * s + 1] = (double) y;
868 tmp_points[4 * s + 2] = (double) z;
869 tmp_points[4 * s + 3] = (double) v;
870#ifdef DEBUG
871 printf
872 ("Iteration %3d, Point %3lu reseeded from %8g, %8g, %8g -> %8g, %8g, %8g\n",
873 iter, s, points[4 * s], points[4 * s + 1], points[4 * s + 2],
874 tmp_points[4 * s], tmp_points[4 * s + 1], tmp_points[4 * s + 2]);
875#endif
876 }
877 double dx = tmp_points[4 * s] - points[4 * s];
878 double dy = tmp_points[4 * s + 1] - points[4 * s + 1];
879 double dz = tmp_points[4 * s + 2] - points[4 * s + 2];
880 dcen += dx * dx + dy * dy + dz * dz;
881 }
882 dcen = sqrt(dcen / get_number_points());
883 //swap pointter, faster but risky
884#ifdef DEBUG
885 printf("before swap: points = %ld\ttmp_points = %ld\n", (long)get_points_array(),
886 (long)tmp_pa.get_points_array());
887#endif
888 double *tp = get_points_array();
889 set_points_array(tmp_points);
890 tmp_pa.set_points_array(tp);
891 tmp_pa.zero();
892#ifdef DEBUG
893 printf("after swap: points = %ld\ttmp_points = %ld\n", (long)get_points_array(),
894 (long)tmp_pa.get_points_array());
895 printf("Iteration %3d, finished updating segment centers with dcen = %g pixels\n", iter,
896 dcen);
897#endif
898
899 iter++;
900 } while (dcen > min_dcen && iter <= max_iter);
901 map->update();
902
903 sort_by_axis(2); // x,y,z axes = 0, 1, 2
904 }
905 else {
906 LOGERR("PointArray::set_from_density_map(): mode = %d is not implemented yet", mode);
907 }
908 //update to use apix and origin
909 int nx = map->get_xsize(), ny = map->get_ysize(), nz = map->get_zsize();
910 float origx, origy, origz;
911 try {
912 origx = map->get_attr("origin_x");
913 origy = map->get_attr("origin_y");
914 origz = map->get_attr("origin_z");
915 }
916 catch(...) {
917 origx = -nx / 2 * apix;
918 origy = -ny / 2 * apix;
919 origz = -nz / 2 * apix;
920 }
921
922#ifdef DEBUG
923 printf("Apix = %g\torigin x,y,z = %8g,%8g,%8g\n",apix, origx, origy, origz);
924#endif
925
926 float *pd = map->get_data();
927 for ( size_t i = 0; i < get_number_points(); ++i) {
928#ifdef DEBUG
929 printf("Point %4lu: x,y,z,v = %8g,%8g,%8g,%8g",i, points[4 * i],points[4 * i + 1],points[4 * i + 2],points[4 * i + 3]);
930#endif
931 points[4 * i + 3] =
932 pd[(int) points[4 * i + 2] * nx * ny + (int) points[4 * i + 1] * nx +
933 (int) points[4 * i]];
934 points[4 * i] = points[4 * i] * apix + origx;
935 points[4 * i + 1] = points[4 * i + 1] * apix + origy;
936 points[4 * i + 2] = points[4 * i + 2] * apix + origz;
937#ifdef DEBUG
938 printf("\t->\t%8g,%8g,%8g,%8g\n",points[4 * i],points[4 * i + 1],points[4 * i + 2],points[4 * i + 3]);
939#endif
940 }
941 map->update();
942}
943
946 if (!adist) adist=(double *)malloc(sizeof(double)*n);
947 if (!aang) aang=(double *)malloc(sizeof(double)*n);
948 if (!adihed) adihed=(double *)malloc(sizeof(double)*n);
949
950 for (size_t ii=0; ii<n; ii++) {
951 // how expensive is % ? Worth replacing ?
952 int ib=4*((ii+n-1)%n); // point before i with wraparound
953 int ibb=4*((ii+n-2)%n); // 2 points before i with wraparound
954 int ia=4*((ii+1)%n); // 1 point after
955 int i=4*ii;
956
957 Vec3f a(points[ib]-points[ibb],points[ib+1]-points[ibb+1],points[ib+2]-points[ibb+2]); // -2 -> -1
958 Vec3f b(points[i]-points[ib],points[i+1]-points[ib+1],points[i+2]-points[ib+2]); // -1 -> 0
959 Vec3f c(points[ia]-points[i],points[ia+1]-points[i+1],points[ia+2]-points[i+2]); // 0 -> 1
960 adist[ii]=b.length();
961
962 // angle
963 aang[ii]=b.dot(c);
964 if (aang[ii]!=0) {
965 aang[ii]/=(adist[ii]*c.length());
966 if (aang[ii]>=1.0) aang[ii]=0.0;
967 else if (aang[ii]<=-1.0) aang[ii]=M_PI;
968 else aang[ii]=acos(aang[ii]);
969 }
970
971 // dihedral
972 Vec3f cr1=a.cross(b);
973 Vec3f cr2=b.cross(c);
974 double denom=cr1.length()*cr2.length();
975 if (denom==0) adihed[ii]=0;
976 else {
977 double tmp=cr1.dot(cr2)/(denom);
978 if (tmp>1) tmp=1;
979 if (tmp<-1) tmp=-1;
980 adihed[ii]=acos(tmp);
981 }
982
983// if (std::isnan(ang[ii])) ang[ii]=0;
984
985 }
986}
987
989 double ret=0;
991
992 if (map &&mapc) {
993 for (size_t i=0; i<n; i++) ret+=sim_pointpotential(adist[i],aang[i],adihed[i])-mapc*map->sget_value_at_interp(points[i*4]/apix+centx,points[i*4+1]/apix+centy,points[i*4+2]/apix+centz);
994 }
995 else {
996 for (size_t i=0; i<n; i++) ret+=sim_pointpotential(adist[i],aang[i],adihed[i]);
997 }
998
999 return ret/n;
1000}
1001
1002// potential for a single point. Note that if a point moves, it will impact energies +-2 from its position. This function computes only for the point i
1004 if (!adist) sim_updategeom(); // wasteful, but only once
1005
1006// if (i<0 || i>=n) throw InvalidParameterException("Point number out of range");
1007 size_t i;
1008 if (ind<0)
1009 i=ind-n*(ind/n-1);
1010 else
1011 i=ind;
1012 if (i>=n) i=i%n;
1013
1014 // how expensive is % ? Worth replacing ?
1015 int ib=4*((i+n-1)%n); // point before i with wraparound
1016 int ibb=4*((i+n-2)%n); // 2 points before i with wraparound
1017 int ia=4*((i+1)%n); // 1 point after
1018 int ii=i*4;
1019
1020 Vec3f a(points[ib]-points[ibb],points[ib+1]-points[ibb+1],points[ib+2]-points[ibb+2]); // -2 -> -1
1021 Vec3f b(points[ii]-points[ib],points[ii+1]-points[ib+1],points[ii+2]-points[ib+2]); // -1 -> 0
1022 Vec3f c(points[ia]-points[ii],points[ia+1]-points[ii+1],points[ia+2]-points[ii+2]); // 0 -> 1
1023 double dist=b.length();
1024 adist[i]=dist;
1025 // Angle, tests should avoid isnan being necessary
1026 double ang=b.dot(c);
1027 if (ang!=0.0) { // if b.dot(c) is 0, we set it to the last determined value...
1028 ang/=(dist*c.length());
1029 if (ang>1.0) ang=1.0; // should never happen, but just in case of roundoff error
1030 if (ang<-1.0) ang=-1.0;
1031 ang=acos(ang);
1032 }
1033 else ang=aang[i];
1034 aang[i]=ang;
1035
1036 // Dihedral
1037 Vec3f cr1=a.cross(b);
1038 Vec3f cr2=b.cross(c);
1039 double dihed;
1040 double denom=cr1.length()*cr2.length();
1041 if (denom==0) dihed=adihed[i]; // set the dihedral to the last determined value if indeterminate
1042 else {
1043 dihed=cr1.dot(cr2)/denom;
1044 if (dihed>1.0) dihed=1.0; // should never happen, but just in case of roundoff error
1045 if (dihed<-1.0) dihed=-1.0;
1046 dihed=acos(dihed);
1047 }
1048 adihed[i]=dihed;
1049//* Do not need for small amount of points
1050 // Distance to the closest neighbor
1051 double mindist=10000;
1052 for (size_t j=0;j<n;j++){
1053 if(j==i)
1054 continue;
1055 int ja=4*j;
1056 Vec3f d(points[ii]-points[ja],points[ii+1]-points[ja+1],points[ii+2]-points[ja+2]);
1057 double jdst=d.length();
1058 if(jdst<mindist)
1059 mindist=jdst;
1060 }
1061 double distpen=0;
1062 if (mindist<mindistc)
1063 distpen=distpenc/mindist;
1064//*/
1065
1066
1067// if (std::isnan(dist) || std::isnan(ang) || std::isnan(dihed)) printf("%d\t%g\t%g\t%g\t%g\t%g\t%g\n",i,dist,ang,dihed,b.length(),c.length(),b.dot(c)/(dist*c.length()));
1068// if (std::isnan(dihed)) dihed=dihed0;
1069// if (std::isnan(ang)) ang=0;
1070// if (std::isnan(dist)) dist=3.3;
1071// if (isnan(dihed)) dihed=dihed0;
1072// if (isnan(ang)) ang=0;
1073 if (map && mapc) {
1074 return distpen+sim_pointpotential(dist,ang,dihed)-mapc*map->sget_value_at_interp(points[ii]/apix+centx,points[ii+1]/apix+centy,points[ii+2]/apix+centz);
1075 }
1076 return sim_pointpotential(dist,ang,dihed);
1077}
1078
1079// Computes a potential for a point and +-2 nearest neighbors under perturbation of the central point location
1080double PointArray::sim_potentialdxyz(int i, double dx, double dy, double dz) {
1081 Vec3f old(points[i*4],points[i*4+1],points[i*4+2]);
1082 double potd=0.;
1083
1084 points[i*4]=old[0]+dx;
1085 points[i*4+1]=old[1]+dy;
1086 points[i*4+2]=old[2]+dz;
1087 for (int ii=i-2; ii<=i+2; ii++) potd+=sim_potentiald(ii);
1088// potd=potential();
1089 points[i*4]=old[0];
1090 points[i*4+1]=old[1];
1091 points[i*4+2]=old[2];
1092
1093 return potd;
1094}
1095
1097 double dist=0;
1098 for(size_t i=0; i<n; i++){
1099 int k=(i+1)%n;
1100 double d=(points[i*4]-points[k*4])*(points[i*4]-points[k*4])+(points[i*4+1]-points[k*4+1])*(points[i*4+1]-points[k*4+1])+(points[i*4+2]-points[k*4+2])*(points[i*4+2]-points[k*4+2]);
1101 d=sqrt(d);
1102 dist+=d;
1103 }
1104 return dist;
1105}
1106
1107// Computes a gradient of the potential for a single point, including impact on +-2 nearest neighbors
1109 Vec3f old(points[i*4],points[i*4+1],points[i*4+2]);
1110 double pot=0.,potx=0.,poty=0.,potz=0.;
1111 double stepsz=0.01;
1112
1113 for (int ii=i-2; ii<=i+2; ii++) pot+=sim_potentiald(ii);
1114// pot=potential();
1115
1116 points[i*4]=old[0]+stepsz;
1117 for (int ii=i-2; ii<=i+2; ii++) potx+=sim_potentiald(ii);
1118// potx=potential();
1119 points[i*4]=old[0];
1120
1121 points[i*4+1]=old[1]+stepsz;
1122 for (int ii=i-2; ii<=i+2; ii++) poty+=sim_potentiald(ii);
1123// poty=potential();
1124 points[i*4+1]=old[1];
1125
1126 points[i*4+2]=old[2]+stepsz;
1127 for (int ii=i-2; ii<=i+2; ii++) potz+=sim_potentiald(ii);
1128// potz=potential();
1129 points[i*4+2]=old[2];
1130
1131 // printf("%1.4g\t%1.4g\t%1.4g\t%1.4g\t%1.4g\t%1.4g\t%1.4g\n",pot,potx,poty,potz,(pot-potx),(pot-poty),(pot-potz));
1132
1133// if (pot==potx) potx=pot+1000000.0;
1134// if (pot==potx) potx=pot+1000000.0;
1135// if (pot==potx) potx=pot+1000000.0;
1136 return Vec3f((pot-potx),(pot-poty),(pot-potz));
1137}
1138
1140void PointArray::sim_minstep(double maxshift) {
1141 vector<Vec3f> shifts;
1142
1143 double max=0.0;
1144 double mean=0.0;
1145 for (size_t i=0; i<n; i++) {
1146 if (oldshifts.size()==n) shifts.push_back((sim_descent(i)+oldshifts[i])/2.0);
1147 else shifts.push_back(sim_descent(i));
1148 float len=shifts[i].length();
1149 if (len>max) max=len;
1150 mean+=len;
1151 }
1152 oldshifts=shifts;
1153
1154// printf("max vec %1.2f\tmean %1.3f\n",max,mean/n);
1155
1156 for (size_t i=0; i<n; i++) {
1157// if (std::isnan(shifts[i][0]) ||std::isnan(shifts[i][1]) ||std::isnan(shifts[i][2])) { printf("Nan: %d\n",i); shifts[i]=Vec3f(max,max,max); }
1158 points[i*4]+=shifts[i][0]*maxshift/max;
1159 points[i*4+1]+=shifts[i][1]*maxshift/max;
1160 points[i*4+2]+=shifts[i][2]*maxshift/max;
1161// printf("%d. %1.2f\t%1.2f\t%1.2f\n",i,shifts[i][0]*maxshift/max,shifts[i][1]*maxshift/max,shifts[i][2]*maxshift/max);
1162 }
1163}
1164
1166void PointArray::sim_minstep_seq(double meanshift) {
1167 /*
1168 // Try to minimize potential globally
1169 boost::mt19937 rng;
1170 boost::normal_distribution<> nd(0.0, 20.0);
1171 boost::variate_generator<boost::mt19937&,boost::normal_distribution<> > var_nor(rng, nd);
1172 double *oldpts=new double[4*get_number_points()];
1173 double *bestpts=new double[4*get_number_points()];
1174 double best_pot,new_pot;
1175 memcpy(oldpts, get_points_array(), sizeof(double) * 4 * get_number_points());
1176 memcpy(bestpts, get_points_array(), sizeof(double) * 4 * get_number_points());
1177 best_pot=sim_potential();
1178 double disttmp=0;
1179 for (int k=0; k<n; k++) disttmp+=adist[k];
1180 best_pot+=distc*pow((disttmp-336*3.3),2.0);
1181 for (int i=0; i<1000; i++){
1182 for (int j=0; j<n; j++){
1183 points[4*j]=oldpts[4*j]+var_nor();
1184 points[4*j+1]=oldpts[4*j+1]+var_nor();
1185 points[4*j+2]=oldpts[4*j+2]+var_nor();
1186 }
1187 new_pot=sim_potential();
1188 disttmp=0;
1189 for (int k=0; k<n; k++) disttmp+=adist[k];
1190 new_pot+=distc*pow((disttmp-336*3.3),2.0);
1191 if (new_pot<best_pot){
1192 memcpy(bestpts, get_points_array(), sizeof(double) * 4 * get_number_points());
1193 best_pot=new_pot;
1194 printf("%f\t",best_pot);
1195 }
1196 }
1197 memcpy(get_points_array(),bestpts, sizeof(double) * 4 * get_number_points());
1198
1199 delete []oldpts;
1200 delete []bestpts;
1201 */
1202 // we compute 10 random gradients and use these to adjust stepsize
1203 double mean=0.0;
1204 for (int i=0; i<10; i++) {
1205// Vec3f shift=sim_descent(random()%n);
1206 Vec3f shift=sim_descent(Util::get_irand(0,n-1));
1207 mean+=shift.length();
1208 }
1209 mean/=10.0;
1210 double stepadj=meanshift/mean;
1211// printf("\t%1.4g\n",stepadj);
1212
1213 // Now we go through all points sequentially and move each downhill
1214 // The trick here is the sequential part, as each point is impacted by the point already moved before it.
1215 // This may create a "seam" at the first point which won't be adjusted to compensate for the last point (wraparound)
1216 // until the next cycle
1217 Vec3f oshifts;
1218 for (size_t ii=0; ii<n; ii++) {
1219 size_t i=2*(ii%(n/2))+2*ii/n; // this maps a linear sequence to an all-even -> all odd sequence
1220 Vec3f shift,d;
1221 if (ii==n) {
1222 d=sim_descent(i);
1223 shift=(d+oshifts)/2.0;
1224 oshifts=d;
1225 }
1226 else {
1227 shift=sim_descent(i);
1228 oshifts=shift;
1229 }
1230
1231// double p2=potential();
1232// double pot=sim_potentialdxyz(i,0.0,0.0,0.0);
1233// double pots=sim_potentialdxyz(i,shift[0]*stepadj,shift[1]*stepadj,shift[2]*stepadj);
1234
1235 // only step if it actually improves the potential for this particle (note that it does not need to improve the overall potential)
1236// if (pots<pot) {
1237 points[i*4]+=shift[0]*stepadj;
1238 points[i*4+1]+=shift[1]*stepadj;
1239 if (!map2d)
1240 points[i*4+2]+=shift[2]*stepadj;
1241// printf("%d. %1.4g -> %1.4g %1.3g %1.3g %1.3g %1.3g\n",i,pot,pots,shift[0],shift[1],shift[2],stepadj);
1242// if (potential()>p2) printf("%d. %1.4g %1.4g\t%1.4g %1.4g\n",i,pot,pots,p2,potential());
1243// }
1244
1245 }
1246}
1247
1248
1250 double meandist=0.0;
1251 double max=0.0,min=dist0*1000.0;
1252
1253 for (size_t ii=0; ii<n; ii++) {
1254 int ib=4*((ii+n-1)%n); // point before i with wraparound
1255 int i=4*ii;
1256
1257 Vec3f b(points[i]-points[ib],points[i+1]-points[ib+1],points[i+2]-points[ib+2]); // -1 -> 0
1258 double len=b.length();
1259 meandist+=len;
1260 max=len>max?len:max;
1261 min=len<min?len:min;
1262 }
1263 meandist/=n;
1264 double scale=dist0/meandist;
1265
1266 printf("mean = %1.3f rescaled: %1.3f - %1.3f\n",meandist,min*scale,max*scale);
1267
1268 for (size_t i=0; i<n; i++) {
1269 points[i*4]*=scale;
1270 points[i*4+1]*=scale;
1271 points[i*4+2]*=scale;
1272 }
1273
1274}
1276 sim_updategeom();
1277
1278 double mdist=0.0,mang=0.0,mdihed=0.0;
1279 double midist=1000.0,miang=M_PI*2,midihed=M_PI*2;
1280 double madist=0.0,maang=0.0,madihed=0.0;
1281 double mmap=0.0;
1282 if (map &&mapc) {
1283 for (size_t i=0; i<n; i++) {
1284 double m=map->sget_value_at_interp(points[i*4]/apix+centx,points[i*4+1]/apix+centy,points[i*4+2]/apix+centz);
1285 mmap+=m;
1286// printf("%f,%f,%f\t %f\n",points[i*4]/apix+centx,points[i*4+1]/apix+centy,points[i*4+2]/apix+centz,m);
1287 }
1288 mmap/=n;
1289 }
1290 for (size_t i=0; i<n; i++) {
1291 mdist+=adist[i];
1292 mang+=aang[i];
1293 mdihed+=adihed[i];
1294
1295
1296
1297 midist=adist[i]<midist?adist[i]:midist;
1298 madist=adist[i]>madist?adist[i]:madist;
1299
1300 miang=aang[i]<miang?aang[i]:miang;
1301 maang=aang[i]>maang?aang[i]:maang;
1302
1303 midihed=adihed[i]<midihed?adihed[i]:midihed;
1304 madihed=adihed[i]>madihed?adihed[i]:madihed;
1305 }
1306 double p=sim_potential();
1307 double anorm = 180.0/M_PI;
1308 printf(" potential: %1.1f\t map: %1.2f\tdist: %1.2f || %1.2f / %1.2f / %1.2f\tang: %1.2f / %1.2f / %1.2f\tdihed: %1.2f / %1.2f / %1.2f ln=%1.1f\n",p,mmap,dist0,midist,mdist/n,madist,miang*anorm,mang/n*anorm,maang*anorm,midihed*anorm,mdihed/n*anorm,madihed*anorm,mdihed/(M_PI*2.0)-n/10.0);
1309}
1310
1311void PointArray::sim_set_pot_parms(double pdist0,double pdistc,double pangc, double pdihed0, double pdihedc, double pmapc, EMData *pmap, double pmindistc,double pdistpenc) {
1312 dist0=pdist0;
1313 distc=pdistc;
1314 angc=pangc;
1315 dihed0=pdihed0;
1316 dihedc=pdihedc;
1317 mapc=pmapc;
1318 mindistc=pmindistc;
1319 distpenc=pdistpenc;
1320 if (pmap!=0 && pmap!=map) {
1321// if (map!=0) delete map;
1322 if (gradx!=0) delete gradx;
1323 if (grady!=0) delete grady;
1324 if (gradz!=0) delete gradz;
1325
1326 map=pmap;
1327 apix=map->get_attr("apix_x");
1328 if (map->get_zsize()==1)
1329 map2d=true;
1330 else
1331 map2d=false;
1332// centx=map->get_xsize()/2;
1333// centy=map->get_ysize()/2;
1334// centz=map->get_zsize()/2;
1335 centx=0;
1336 centy=0;
1337 centz=0;
1338// gradx=map->process("math.edge.xgradient"); // we compute the gradient to make the minimization easier
1339// grady=map->process("math.edge.ygradient");
1340// gradz=map->process("math.edge.zgradient");
1341 }
1342}
1343
1344// Double the number of points by adding new points on the center of edges
1346
1347 int nn=n*2;
1348 int tmpn=n;
1350 double* pa2data=(double *) calloc(4 * nn, sizeof(double));
1351 bool *newpt=new bool[nn];
1352 for (int i=0;i<nn;i++){
1353 if (i%2==0)
1354 newpt[i]=1;
1355 else
1356 newpt[i]=0;
1357 }
1358 int i=0;
1359 for (int ii=0;ii<nn;ii++){
1360 if (newpt[ii]) {
1361
1362 pa2data[ii*4]=points[i*4];
1363 pa2data[ii*4+1]=points[i*4+1];
1364 pa2data[ii*4+2]=points[i*4+2];
1365 pa2data[ii*4+3]=1;
1366 i++;
1367 }
1368 else{
1369 int k;
1370 if (i<tmpn)
1371 k=i;
1372 else
1373 k=0;
1374 pa2data[ii*4]=(points[k*4]+points[(i-1)*4])/2;
1375 pa2data[ii*4+1]=(points[k*4+1]+points[(i-1)*4+1])/2;
1376 pa2data[ii*4+2]=(points[k*4+2]+points[(i-1)*4+2])/2;
1377 pa2data[ii*4+3]=1;
1378 }
1379
1380 }
1381
1382 delete []newpt;
1383 free(points);
1384 set_points_array(pa2data);
1385
1386 if (adist) free(adist);
1387 if (aang) free(aang);
1388 if (adihed) free(adihed);
1389 adist=aang=adihed=0;
1391}
1392
1393// Delete one point with lowest density, and add two points on the edges to that one.
1394// Or add one point on the edge with lowest density
1396
1397 double maxpot=-1000000,pot,meanpot=0;
1398 size_t ipt=0;
1399 bool onedge=0;
1400 // Find the highest potential point
1401 for (size_t i=0; i<n; i++) {
1402 meanpot+=sim_pointpotential(adist[i],aang[i],adihed[i]);
1403 pot=/*sim_pointpotential(adist[i],aang[i],adihed[i])*/-mapc*map->sget_value_at_interp(points[i*4]/apix+centx,points[i*4+1]/apix+centy,points[i*4+2]/apix+centz);
1404 if (pot>maxpot){
1405 maxpot=pot;
1406 ipt=i;
1407 }
1408 }
1409 meanpot/=n;
1410
1411 for (size_t i=0; i<n; i++) {
1412 int k=(i+1)%n;
1413 double pt0,pt1,pt2;
1414 pt0=(points[k*4]+points[i*4])/2;
1415 pt1=(points[k*4+1]+points[i*4+1])/2;
1416 pt2=(points[k*4+2]+points[i*4+2])/2;
1417 pot=/*meanpot*/-mapc*map->sget_value_at_interp(pt0/apix+centx,pt1/apix+centy,pt2/apix+centz);
1418 if (pot>maxpot){
1419 maxpot=pot;
1420 ipt=i;
1421 onedge=1;
1422 }
1423 }
1424
1425 // The rest points remain the same
1426 size_t i;
1427 double* pa2data=(double *) calloc(4 * (n+1), sizeof(double));
1428 for (size_t ii=0; ii<n+1; ii++) {
1429 if(ii!=ipt && ii!=ipt+1){
1430 if(ii<ipt)
1431 i=ii;
1432 else // shift the points after the adding position
1433 i=ii-1;
1434
1435 pa2data[ii*4]=points[i*4];
1436 pa2data[ii*4+1]=points[i*4+1];
1437 pa2data[ii*4+2]=points[i*4+2];
1438 pa2data[ii*4+3]=1;
1439 }
1440 }
1441 // Adding points
1442 if( onedge ) {
1443 size_t k1;
1444// k0=((ipt+n-1)%n);
1445 k1=((ipt+1)%n);
1446 pa2data[ipt*4]=points[ipt*4];
1447 pa2data[ipt*4+1]=points[ipt*4+1];
1448 pa2data[ipt*4+2]=points[ipt*4+2];
1449 pa2data[ipt*4+3]=1;
1450
1451 pa2data[(ipt+1)*4]=(points[ipt*4]+points[k1*4])/2;
1452 pa2data[(ipt+1)*4+1]=(points[ipt*4+1]+points[k1*4+1])/2;
1453 pa2data[(ipt+1)*4+2]=(points[ipt*4+2]+points[k1*4+2])/2;
1454 pa2data[(ipt+1)*4+3]=1;
1455
1456 }
1457 else {
1458 size_t k0,k1;
1459 k0=((ipt+n-1)%n);
1460 k1=((ipt+1)%n);
1461 pa2data[ipt*4]=(points[ipt*4]+points[k0*4])/2;
1462 pa2data[ipt*4+1]=(points[ipt*4+1]+points[k0*4+1])/2;
1463 pa2data[ipt*4+2]=(points[ipt*4+2]+points[k0*4+2])/2;
1464 pa2data[ipt*4+3]=1;
1465
1466 pa2data[(ipt+1)*4]=(points[ipt*4]+points[k1*4])/2;
1467 pa2data[(ipt+1)*4+1]=(points[ipt*4+1]+points[k1*4+1])/2;
1468 pa2data[(ipt+1)*4+2]=(points[ipt*4+2]+points[k1*4+2])/2;
1469 pa2data[(ipt+1)*4+3]=1;
1470
1471 }
1472 free(points);
1473 n++;
1474 set_points_array(pa2data);
1475
1476 if (adist) free(adist);
1477 if (aang) free(aang);
1478 if (adihed) free(adihed);
1479 adist=aang=adihed=0;
1481
1482 // search for the best position for the new points
1483 if (onedge){
1484 i=ipt+1;
1485 double bestpot=10000,nowpot;
1486 Vec3f old(points[i*4],points[(i+1)*4],points[(i+2)*4]);
1487 Vec3f newpt(points[i*4],points[(i+1)*4],points[(i+2)*4]);
1488 for (int ii=0;ii<5000;ii++){
1489 // Try to minimize potential globally
1490 boost::mt19937 rng;
1491 boost::normal_distribution<> nd(0.0, 0.0);
1492 boost::variate_generator<boost::mt19937&,boost::normal_distribution<> > var_nor(rng, nd);
1493 points[i*4]=old[0]+var_nor();
1494 points[i*4+1]=old[1]+var_nor();
1495 points[i*4+2]=old[2]+var_nor();
1496 nowpot=sim_potentiald(i);
1497 if (nowpot<bestpot) {
1498 bestpot=nowpot;
1499 newpt[0]=points[i*4];
1500 newpt[1]=points[(i+1)*4];
1501 newpt[2]=points[(i+2)*4];
1502 }
1503 }
1504 points[i*4]=newpt[0];
1505 points[i*4+1]=newpt[1];
1506 points[i*4+2]=newpt[2];
1507 }
1508}
1509
1510vector<float> PointArray::do_pca(int start=0, int end=-1){
1511 if (end==-1) end=n;
1512 float covmat[9],mean[3];
1513 for (int i=0; i<3; i++) mean[i]=0;
1514 for (int i=start; i<end; i++){
1515 for (int j=0; j<3; j++){
1516 mean[j]+=points[i*4+j];
1517 }
1518 }
1519 for (int i=0; i<3; i++) mean[i]/=end-start;
1520
1521 for (int i=0; i<3; i++){
1522 for (int j=0; j<3; j++){
1523 if (j<i){
1524 covmat[i*3+j]=covmat[j*3+i];
1525 }
1526 else{
1527 covmat[i*3+j]=0;
1528 for (int k=start; k<end; k++)
1529 {
1530 covmat[i*3+j]+=(points[k*4+i]-mean[i])*(points[k*4+j]-mean[j]);
1531 }
1532 }
1533
1534// printf("%f\t",covmat[i*3+j]);
1535 }
1536// printf("\n");
1537 }
1538
1539 float eigval[3],eigvec[9];
1540 Util::coveig(3,covmat,eigval,eigvec);
1541 vector<float> eigv(eigvec,eigvec+sizeof(eigvec)/sizeof(float));
1542// printf(" %f,%f,%f\n %f,%f,%f\n %f,%f,%f\n",eigvec[0],eigvec[1],eigvec[2],eigvec[3],eigvec[4],eigvec[5],eigvec[6],eigvec[7],eigvec[8]);
1543 return eigv;
1544}
1545
1546vector<float> PointArray::do_filter(vector<float> pts, float *ft, int num){
1547 // filter a 1D array
1548 vector<float> result(pts);
1549 for (size_t i=0; i<pts.size(); i++)
1550 result[i]=0;
1551 for (size_t i=(num-1)/2; i<pts.size()-(num-1)/2; i++){
1552 for (int j=0; j<num; j++){
1553 int k=i+j-(num-1)/2;
1554 result[i]+=pts[k]*ft[j];
1555 }
1556 }
1557 return result;
1558}
1559
1560vector<double> PointArray::fit_helix(EMData* pmap,int minlength=13,float mindensity=4, vector<int> edge=vector<int>(),int twodir=0,size_t minl=9)
1561{
1562 vector<float> hlxlen(n);
1563 vector<int> helix;
1564 map=pmap;
1565 float ft[7]={0.0044,0.0540,0.2420,0.3989,0.2420,0.0540,0.0044};
1566// float ft[7]={0,0,0,1,0,0,0};
1567
1568 // search for long rods in the point array globally
1569 for (int dir=twodir; dir<2; dir++){
1570 // search in both directions and combine the result
1571 if( twodir==0)
1572 reverse_chain();
1573 for (size_t i=0; i<n; i++){
1574 vector<float> dist(50);
1575 // for each point, search the following 50 points, find the longest rod
1576 for (int len=5; len<50; len++){
1577 size_t pos=i+len;
1578 if (pos>=n) break;
1579 vector<float> eigvec=do_pca(i,pos); // align the points
1580 vector<float> pts((len+1)*3);
1581 float mean[3];
1582 for (int k=0; k<3; k++) mean[k]=0;
1583 for (size_t k=i; k<pos; k++){
1584 for (int l=0; l<3; l++){
1585 pts[(k-i)*3+l]=points[k*4+0]*eigvec[l*3+0]+points[k*4+1]*eigvec[l*3+1]+points[k*4+2]*eigvec[l*3+2];
1586 mean[l]+=pts[(k-i)*3+l];
1587 }
1588 }
1589 for (int k=0; k<3; k++) mean[k]/=len;
1590 float dst=0;
1591 // distance to the center axis
1592 for (int k=0; k<len; k++){
1593 dst+=abs((pts[k*3]-mean[0])*(pts[k*3]-mean[0])+(pts[k*3+1]-mean[1])*(pts[k*3+1]-mean[1]));
1594 }
1595 dist[len]=1-dst/len/len;
1596 }
1597
1598 vector<float> nd=do_filter(dist,ft,7);
1599 nd=do_filter(nd,ft,7);
1600 // length of the first rod
1601 for (int j=7; j<49; j++){
1602 if(nd[j]>nd[j-1] && nd[j]>nd[j+1]){
1603 hlxlen[i]=j-6;
1604 break;
1605 }
1606 }
1607
1608 if(hlxlen[i]>25) hlxlen[i]=0;
1609 }
1610 // filter the array before further process
1611// hlxlen[50]=100;
1612// for (int i=0; i<n; i++) printf("%d\t%f\n",i,hlxlen[i]);
1613// for (int i=0; i<3; i++) hlxlen=do_filter(hlxlen,ft,7);
1614// for (int i=0; i<n; i++) printf("%d\t%f\n",i,hlxlen[i]);
1615 vector<float> ishlx(n);
1616 int hlx=0;
1617 float up=minlength; // rod length threshold
1618 // record position of possible helixes
1619 for (size_t i=0; i<n; i++){
1620 if(hlx<=0){
1621 if(hlxlen[i]>up){
1622 hlx=hlxlen[i];
1623 helix.push_back(i);
1624 helix.push_back(i+hlxlen[i]-5);
1625 }
1626 }
1627 else{
1628 hlx--;
1629 ishlx[i]=hlxlen[i];
1630 }
1631 }
1632 // while counting reversely
1633 if(dir==0){
1634 for (size_t i=0; i<helix.size(); i++) helix[i]=n-1-helix[i];
1635 for (size_t i=0; i<helix.size()/2; i++){
1636 int tmp=helix[i*2+1];
1637 helix[i*2+1]=helix[i*2];
1638 helix[i*2]=tmp;
1639 }
1640 }
1641
1642 }
1643
1644#ifdef DEBUG
1645 printf("potential helix counting from both sides: \n");
1646 for (size_t i=0; i<helix.size()/2; i++){
1647 printf("%d\t%d\n",helix[i*2],helix[i*2+1]);
1648 }
1649 printf("\n\n");
1650#endif
1651/*
1652
1653 // Combine the result from both side
1654 for (size_t i=0; i<helix.size()/2; i++){
1655 int change=1;
1656 while(change==1){
1657 change=0;
1658 for (size_t j=i+1; j<helix.size()/2; j++){
1659 if(helix[j*2]==0) continue;
1660 if(helix[j*2]-2<helix[i*2+1] && helix[j*2+1]+2>helix[i*2]){
1661 helix[i*2]=(helix[i*2]<helix[j*2])?helix[i*2]:helix[j*2];
1662 helix[i*2+1]=(helix[i*2+1]>helix[j*2+1])?helix[i*2+1]:helix[j*2+1];
1663 helix[j*2]=0;
1664 helix[j*2+1]=0;
1665 change=1;
1666 }
1667 }
1668 }
1669 }*/
1670
1671 vector<int> allhlx;
1672 int minid=1;
1673 while (minid>=0){
1674 int mins=10000;
1675 minid=-1;
1676 for (size_t i=0;i<helix.size()/2; i++){
1677 if(helix[i*2]<.1) continue;
1678 if(helix[i*2]<mins){
1679 mins=helix[i*2];
1680 minid=i;
1681 }
1682 }
1683 if(minid>=0){
1684 allhlx.push_back(helix[minid*2]);
1685 allhlx.push_back(helix[minid*2+1]);
1686 helix[minid*2]=-1;
1687 }
1688 }
1689
1690#ifdef DEBUG
1691 printf("combined result: \n");
1692 for (size_t i=0; i<allhlx.size()/2; i++){
1693 printf("%d\t%d\n",allhlx[i*2],allhlx[i*2+1]);
1694 }
1695 printf("\n\n");
1696#endif
1697
1698 // local search to decide the start and end point of each helix
1699// vector<float> allscore(allhlx.size()/2);
1700 for (size_t i=0; i<allhlx.size()/2; i++){
1701 int sz=5;
1702 size_t start=allhlx[i*2]-sz,end=allhlx[i*2+1]+sz;
1703 start=start>0?start:0;
1704 end=end<n?end:n;
1705 float minscr=100000;
1706 int mj=0,mk=0;
1707
1708 for (size_t j=start; j<end; j++){
1709 for (size_t k=j+6; k<end; k++){
1710 vector<float> eigvec=do_pca(j,k);
1711 vector<float> pts((k-j)*3);
1712 float mean[3];
1713 for (int u=0; u<3; u++) mean[u]=0;
1714 for (size_t u=j; u<k; u++){
1715 for (int v=0; v<3; v++){
1716 pts[(u-j)*3+v]=points[u*4+0]*eigvec[v*3+0]+points[u*4+1]*eigvec[v*3+1]+points[u*4+2]*eigvec[v*3+2];
1717 mean[v]+=pts[(u-j)*3+v];
1718 }
1719 }
1720 for (size_t u=0; u<3; u++) mean[u]/=(k-j);
1721 float dst=0;
1722 // distance to the center axis
1723 for (size_t u=0; u<k-j; u++){
1724 dst+=sqrt((pts[u*3]-mean[0])*(pts[u*3]-mean[0])+(pts[u*3+1]-mean[1])*(pts[u*3+1]-mean[1]));
1725 }
1726 float len=k-j;
1727 float scr=dst/len/len;
1728 if (scr<minscr){
1729// printf("%f\t%d\t%d\n",scr,j,k);
1730 minscr=scr;
1731 mj=j;
1732 mk=k;
1733 }
1734 }
1735 }
1736
1737// printf("%d\t%d\n",mj,mk);
1738
1739 allhlx[i*2]=mj;
1740 allhlx[i*2+1]=mk;
1741// allscore[i]=minscr;
1742// if (mk-mj>60)
1743// allscore[i]=100;
1744 }
1745
1746 for (size_t i=0; i<edge.size()/2; i++){
1747 allhlx.push_back(edge[i*2]);
1748 allhlx.push_back(edge[i*2+1]);
1749 }
1750
1751 vector<int> allhlx2;
1752 minid=1;
1753 while (minid>=0){
1754 int mins=10000;
1755 minid=-1;
1756 for (size_t i=0;i<allhlx.size()/2; i++){
1757 if(allhlx[i*2]<.1) continue;
1758 if(allhlx[i*2]<mins){
1759 mins=allhlx[i*2];
1760 minid=i;
1761 }
1762 }
1763 if(minid>=0){
1764 allhlx2.push_back(allhlx[minid*2]<allhlx[minid*2+1]?allhlx[minid*2]:allhlx[minid*2+1]);
1765 allhlx2.push_back(allhlx[minid*2]>allhlx[minid*2+1]?allhlx[minid*2]:allhlx[minid*2+1]);
1766 allhlx[minid*2]=-1;
1767 }
1768 }
1769 allhlx=allhlx2;
1770
1771#ifdef DEBUG
1772 printf("Fitted helixes: \n");
1773 for (size_t i=0; i<allhlx.size()/2; i++){
1774 printf("%d\t%d\n",allhlx[i*2],allhlx[i*2+1]);
1775 }
1776 printf("\n\n");
1777#endif
1778 // create ideal helix
1779 size_t ia=0,ka=0;
1780 int dir;
1781 vector<double> finalhlx;
1782 vector<double> hlxid;
1783 printf("Confirming helix... \n");
1784 while(ia<n){
1785 if (int(ia)==allhlx[ka*2]){
1786// int sz=(allhlx[ka*2+1]-allhlx[ka*2])>10?5:(allhlx[ka*2+1]-allhlx[ka*2])/2;
1787 int sz=3;
1788 float score=0,maxscr=0;
1789 float bestphs=0,phsscore=0,pscore=0;
1790 int mi=0,mj=0;
1791 for (int i=0; i<sz; i++){
1792 for (int j=0; j<sz; j++){
1793 int start=allhlx[ka*2]+i,end=allhlx[ka*2+1]-j;
1794 phsscore=0;bestphs=-1;
1795 for (float phs=-180; phs<180; phs+=10){ //search for phase
1796 construct_helix(start,end,phs,pscore,dir);
1797 if (pscore>phsscore){
1798 phsscore=pscore;
1799 bestphs=phs;
1800 }
1801 }
1802// printf("%f\t",bestphs);
1803 construct_helix(start,end,bestphs,score,dir);
1804 if (score>maxscr){
1805 maxscr=score;
1806 mi=i;
1807 mj=j;
1808 }
1809 }
1810 }
1811 int start=allhlx[ka*2]+mi,end=allhlx[ka*2+1]-mj;
1812 printf("%d\t%d\t%f\tden %d\t",start,end,maxscr,maxscr>mindensity);
1813 if (maxscr>mindensity){
1814 phsscore=0;
1815 for (float phs=-180; phs<180; phs+=10){ //search for phase
1816 construct_helix(start,end,phs,pscore,dir);
1817 if (pscore>phsscore){
1818 phsscore=pscore;
1819 bestphs=phs;
1820 }
1821 }
1822 vector<double> pts=construct_helix(start,end,bestphs,score,dir);
1823 int lendiff=end-start-pts.size()/3-2;
1824 printf("dir %d\t",dir);
1825 printf("len %lu\t diff %d\t",pts.size()/3-2,lendiff);
1826 if (pts.size()/3-2>minl && abs(lendiff)<15){
1827
1828 for (int i=0; i<mi; i++){
1829 finalhlx.push_back(points[(i+ia)*4]);
1830 finalhlx.push_back(points[(i+ia)*4+1]);
1831 finalhlx.push_back(points[(i+ia)*4+2]);
1832 }
1833 hlxid.push_back(finalhlx.size()/3+1);
1834 printf("%lu\t",finalhlx.size()/3+1);
1835 for (size_t j=3; j<pts.size()-3; j++)
1836 finalhlx.push_back(pts[j]);
1837 hlxid.push_back(finalhlx.size()/3-2);
1838 printf("%lu\t",finalhlx.size()/3-2);
1839 for (size_t j=0; j<3; j++)
1840 hlxid.push_back(pts[j]);
1841 for (size_t j=pts.size()-3; j<pts.size(); j++)
1842 hlxid.push_back(pts[j]);
1843 ia=end;
1844 }
1845 else{
1846 printf("\t *");
1847
1848 }
1849
1850 }
1851 printf("\n\n");
1852 ka++;
1853 while(allhlx[ka*2]<int(ia))
1854 ka++;
1855 }
1856 else{
1857// printf("%d\t",ia);
1858 finalhlx.push_back(points[ia*4]);
1859 finalhlx.push_back(points[ia*4+1]);
1860 finalhlx.push_back(points[ia*4+2]);
1861 ia++;
1862 }
1863 }
1864
1865 set_number_points(finalhlx.size()/3);
1866
1867 for (size_t i=0; i<n; i++){
1868 for (size_t j=0; j<3; j++)
1869 points[i*4+j]=finalhlx[i*3+j];
1870 points[i*4+3]=0;
1871 }
1872
1873 printf("\n\n");
1874 return hlxid;
1875}
1876
1877vector<double> PointArray::construct_helix(int start,int end, float phs, float &score, int &rtdir){
1878 // calculate length
1879 int dir=1;
1880 rtdir=0;
1881 Vec3f d(points[end*4]-points[start*4],points[end*4+1]-points[start*4+1],points[end*4+2]-points[start*4+2]);
1882 double len=d.length();
1883 int nh=int(Util::round(len/1.54))+2;
1884 vector<double> helix(nh*3);
1885 vector<float> eigvec=do_pca(start,end);
1886 float eigval[3],vec[9];
1887
1888 Util::coveig(3,&eigvec[0],eigval,vec);
1889 float maxeigv=0;
1890// int maxvi=-1;
1891 for(int i=0; i<3; i++){
1892 if(abs(eigval[i])>maxeigv){
1893 maxeigv=abs(eigval[i]);
1894// maxvi=i;
1895 }
1896 }
1897// dir=eigval[maxvi]>0;
1898 dir=1;
1899 vector<double> pts(nh*3);
1900 for (int dd=0; dd<2; dd++){
1901 // printf("%f\t",eigval[maxvi]);
1902 // vector<float> eigv(eigvec,eigvec+sizeof(eigvec)/sizeof(float));
1903 // create helix
1904 helix[0]=0;helix[1]=0;helix[2]=0;
1905 helix[nh*3-3]=.0;helix[nh*3-2]=0;helix[nh*3-1]=len;
1906
1907 for (int i=0; i<nh-2; i++){
1908 if(dir>0){
1909 helix[(i+1)*3+0]=cos(((phs+(100*i))*M_PI)/180)*2.3;
1910 helix[(i+1)*3+1]=sin(((phs+(100*i))*M_PI)/180)*2.3;
1911 }
1912 else{
1913 helix[(i+1)*3+1]=cos(((phs+(100*i))*M_PI)/180)*2.3;
1914 helix[(i+1)*3+0]=sin(((phs+(100*i))*M_PI)/180)*2.3;
1915 }
1916 helix[(i+1)*3+2]=i*1.54;
1917 }
1918 // transform to correct position
1919 float mean[3];
1920 for (int k=0; k<3; k++) mean[k]=0;
1921 for (int k=0; k<nh; k++){
1922 for (int l=0; l<3; l++){
1923 pts[k*3+l]=helix[k*3+0]*eigvec[0*3+l]+helix[k*3+1]*eigvec[1*3+l]+helix[k*3+2]*eigvec[2*3+l];
1924 mean[l]+=pts[k*3+l];
1925 }
1926 }
1927 for (int k=0; k<3; k++) mean[k]/=nh;
1928 for (int k=0; k<nh; k++){
1929 for (int l=0; l<3; l++){
1930 pts[k*3+l]-=mean[l];
1931 }
1932 }
1933 for (int k=0; k<3; k++) mean[k]=0;
1934 for (int k=start; k<end; k++){
1935 for (int l=0; l<3; l++){
1936 mean[l]+=points[k*4+l];
1937 }
1938 }
1939 for (int k=0; k<3; k++) mean[k]/=(end-start);
1940 for (int k=0; k<nh; k++){
1941 for (int l=0; l<3; l++){
1942 pts[k*3+l]+=mean[l];
1943 }
1944 }
1945
1946
1947 // correct direction
1948 Vec3f d1(pts[0]-points[start*4],pts[1]-points[start*4+1],pts[2]-points[start*4+2]);
1949 Vec3f d2(pts[0]-points[end*4],pts[1]-points[end*4+1],pts[2]-points[end*4+2]);
1950
1951 if (d1.length()>d2.length()) { //do reverse
1952 double tmp;
1953 for (int i=0; i<nh/2; i++){
1954 for(int j=0; j<3; j++){
1955 tmp=pts[i*3+j];
1956 pts[i*3+j]=pts[(nh-i-1)*3+j];
1957 pts[(nh-i-1)*3+j]=tmp;
1958 }
1959 }
1960 }
1961
1962 // correct handness
1963 float hel=calc_helicity(pts);
1964
1965 rtdir=hel;
1966// break;
1967 if(hel>0)
1968 break;
1969 else
1970 dir=0;
1971 }
1972 // calculate score
1973// int sx=map->get_xsize(),sy=map->get_ysize(),sz=map->get_zsize();
1974 int sx=0,sy=0,sz=0;
1975 float ax=map->get_attr("apix_x"),ay=map->get_attr("apix_y"),az=map->get_attr("apix_z");
1976 score=0;
1977 float aind=0;
1978 for (int i=1; i<nh-1; i++){
1979 float ind=1;//(float(abs(i-nh/2))/float(nh))+.5;
1980 score+=ind*map->get_value_at(int(pts[i*3]/ax+sx/2),int(pts[i*3+1]/ay+sy/2),int(pts[i*3+2]/az+sz/2));
1981 aind+=ind;
1982 }
1983 score/=aind;//(nh-2);
1984// float nsc=score;
1985// score=0;
1986// for (int i=1; i<nh-1; i++){
1987// float ind=(float(abs(i-nh/2))/float(nh))+.5;
1988// float mapden=map->get_value_at(int(pts[i*3]/ax+sx/2),int(pts[i*3+1]/ay+sy/2),int(pts[i*3+2]/az+sz/2));
1989// if (mapden>nsc*1.2)
1990// mapden=nsc*1.2;
1991// if (mapden<nsc*.5)
1992// mapden=0;
1993// score+=ind*mapden;
1994// }
1995// score/=aind;//(nh-2);
1996
1997
1998 return pts;
1999}
2000
2001void PointArray::merge_to(PointArray &pa,float thr=3.5)
2002{
2003 printf("merging\n");
2004 vector<double> result;
2005 for (size_t i=0; i<pa.n; i++){
2006 result.push_back(pa.points[i*4]);
2007 result.push_back(pa.points[i*4+1]);
2008 result.push_back(pa.points[i*4+2]);
2009 }
2010 for (size_t i=0; i<n; i++){
2011 float dist=100;
2012 for (size_t j=0; j<pa.n; j++){
2013 Vec3f d(points[i*4]-pa.points[j*4],points[i*4+1]-pa.points[j*4+1],points[i*4+2]-pa.points[j*4+2]);
2014 dist=d.length();
2015 if (dist<thr)
2016 break;
2017 }
2018 printf("%f\n",dist);
2019 if (dist>thr){
2020 result.push_back(points[i*4]);
2021 result.push_back(points[i*4+1]);
2022 result.push_back(points[i*4+2]);
2023 }
2024 }
2025 set_number_points(result.size()/3);
2026 for (size_t i=0; i<n; i++){
2027 for (size_t j=0; j<3; j++)
2028 points[i*4+j]=result[i*3+j];
2029 points[i*4+3]=0;
2030 }
2031 printf("done\n");
2032
2033}
2034
2035float PointArray::calc_helicity(vector<double> pts){
2036 int npt=pts.size();
2037 vector<double> vpoint(npt-3);
2038 for (int i=0; i<npt-3; i++){
2039 vpoint[i]=pts[i+3]-pts[i];
2040 }
2041 Vec3f hlxdir(pts[npt-3]-pts[0],pts[npt-2]-pts[1],pts[npt-1]-pts[2]);
2042 Vec3f vcs(0,0,0);
2043 for (int i=0; i<npt/3-2; i++){
2044 Vec3f v0(vpoint[i*3],vpoint[i*3+1],vpoint[i*3+2]);
2045 Vec3f v1(vpoint[i*3+3],vpoint[i*3+4],vpoint[i*3+5]);
2046 vcs+=v0.cross(v1);
2047 }
2048 vcs/=(npt/3-2);
2049
2050 return hlxdir.dot(vcs);
2051}
2052
2053void PointArray::save_pdb_with_helix(const char *file, vector<float> hlxid)
2054{
2055
2056 FILE *fp = fopen(file, "w");
2057
2058 for (size_t i=0; i<hlxid.size()/8; i++){
2059 fprintf(fp, "HELIX%5lu A ALA A%5d ALA A%5d 1 %5d\n",
2060 i, (int)hlxid[i*8], (int)hlxid[i*8+1], int(hlxid[i*8+1]-hlxid[i*8]+4));
2061 }
2062 for ( size_t i = 0; i < get_number_points(); i++) {
2063 fprintf(fp, "ATOM %5lu CA ALA A%4lu %8.3f%8.3f%8.3f%6.2f%6.2f%8s\n", i, i,
2064 points[4 * i], points[4 * i + 1], points[4 * i + 2], points[4 * i + 3], 0.0, " ");
2065 }
2066 fprintf(fp, "TER %5lu ALA A%4lu\nEND", get_number_points(),get_number_points()-1);
2067
2068 fclose(fp);
2069}
2070
2071void PointArray::remove_helix_from_map(EMData *m, vector<float> hlxid){
2072
2073 int sx=m->get_xsize(),sy=m->get_ysize(),sz=m->get_zsize();
2074 float ax=m->get_attr("apix_x"),ay=m->get_attr("apix_y"),az=m->get_attr("apix_z");
2075 for (int x=0; x<sx; x++){
2076 for (int y=0; y<sy; y++){
2077 for (int z=0; z<sz; z++){
2078 Vec3f p0((x)*ax,(y)*ay,(z)*az);
2079 bool inhlx=false;
2080 for (size_t i=0; i<hlxid.size()/8; i++){
2081 Vec3f p1(hlxid[i*8+2],hlxid[i*8+3],hlxid[i*8+4]),p2(hlxid[i*8+5],hlxid[i*8+6],hlxid[i*8+7]);
2082 Vec3f dp=p2-p1;
2083 float l=dp.length();
2084 float d=((p0-p1).cross(p0-p2)).length()/l;
2085 float t=-(p1-p0).dot(p2-p1)/(l*l);
2086 if (d<5 && t>0 && t<1){
2087 inhlx=true;
2088 break;
2089 }
2090 }
2091 if(inhlx){
2092 m->set_value_at(x,y,z,0);
2093 }
2094
2095 }
2096 }
2097 }
2098}
2099
2100
2102{
2103 Transform t;
2104
2105 // calculate translation
2106 FloatPoint c1=p->get_center(),c2=get_center();
2107 t.set_trans(c1[0]-c2[0],c1[1]-c2[1],c1[2]-c2[2]);
2108
2109 // calculate rotation
2110 // this rotation rotates unit vectors a,b into A,B;
2111 // The program assumes a dot b must equal A dot B
2112
2113 //pick two bonds randomly
2114 int i1=Util::get_irand(0,n-2);
2115 int i2=Util::get_irand(0,n-2);
2116 while(i1==i2)
2117 i2=Util::get_irand(0,n-2);
2118
2119 const Vec3f eahat=get_vector_at(i1+1)-get_vector_at(i1);
2120 const Vec3f ebhat=get_vector_at(i2+1)-get_vector_at(i2);
2121 const Vec3f eAhat=p->get_vector_at(i1+1)-p->get_vector_at(i1);
2122 const Vec3f eBhat=p->get_vector_at(i2+1)-p->get_vector_at(i2);
2123 Vec3f eahatcp(eahat);
2124 Vec3f ebhatcp(ebhat);
2125 Vec3f eAhatcp(eAhat);
2126 Vec3f eBhatcp(eBhat);
2127
2128 eahatcp.normalize();
2129 ebhatcp.normalize();
2130 eAhatcp.normalize();
2131 eBhatcp.normalize();
2132
2133 Vec3f aMinusA(eahatcp);
2134 aMinusA -= eAhatcp;
2135 Vec3f bMinusB(ebhatcp);
2136 bMinusB -= eBhatcp;
2137
2138
2139 Vec3f nhat;
2140 float aAlength = aMinusA.length();
2141 float bBlength = bMinusB.length();
2142 if (aAlength==0){
2143 nhat=eahatcp;
2144 }else if (bBlength==0){
2145 nhat=ebhatcp;
2146 }else{
2147 nhat= aMinusA.cross(bMinusB);
2148 nhat.normalize();
2149 }
2150
2151// printf("nhat=%f,%f,%f \n",nhat[0],nhat[1],nhat[2]);
2152
2153 Vec3f neahat = eahatcp.cross(nhat);
2154 Vec3f nebhat = ebhatcp.cross(nhat);
2155 Vec3f neAhat = eAhatcp.cross(nhat);
2156 Vec3f neBhat = eBhatcp.cross(nhat);
2157
2158 double cosomegaA = (neahat.dot(neAhat)) / (neahat.dot(neahat));
2159// float cosomegaB = (nebhat.dot(neBhat)) / (nebhat.dot(nebhat));
2160 double sinomegaA = (neahat.dot(eAhatcp)) / (neahat.dot(neahat));
2161// printf("cosomegaA=%f \n",cosomegaA); printf("sinomegaA=%f \n",sinomegaA);
2162
2163 double omegaA = atan2(sinomegaA,cosomegaA);
2164// printf("omegaA=%f \n",omegaA*180/M_PI);
2165 Dict rotation;
2166 rotation["type"]="spin";
2167 rotation["n1"]= nhat[0];
2168 rotation["n2"]= nhat[1];
2169 rotation["n3"]= nhat[2];
2170 rotation["omega"] = (float)(omegaA*180.0/M_PI);
2171 t.set_rotation(rotation);
2172 return t;
2173}
2174
2176 // reverse the point array chain, from the last to the first point
2177 double tmp;
2178// for(int i=0; i<n/2; i++){
2179// for (int j=0; j<4; j++){
2180// printf("%f\t",
2181 for(size_t i=0; i<n/2; i++){
2182 for (size_t j=0; j<4; j++){
2183 tmp=points[(n-1-i)*4+j];
2184 points[(n-1-i)*4+j]=points[i*4+j];
2185 points[i*4+j]=tmp;
2186 }
2187 }
2188}
2189
2191 for (size_t i=id*4; i<n*4; i++){
2192 points[i]=points[i+4];
2193 }
2195}
2196
2197bool PointArray::read_ca_from_pdb(const char *file)
2198{
2199 struct stat filestat;
2200 stat(file, &filestat);
2201 set_number_points(( int)(filestat.st_size / 80 + 1));
2202
2203 #ifdef DEBUG
2204 printf("PointArray::read_from_pdb(): try %4lu atoms first\n", get_number_points());
2205 #endif
2206
2207 FILE *fp = fopen(file, "r");
2208 if(!fp) {
2209 fprintf(stderr,"ERROR in PointArray::read_from_pdb(): cannot open file %s\n",file);
2210 throw;
2211 }
2212 char s[200];
2213 size_t count = 0;
2214
2215 while ((fgets(s, 200, fp) != NULL)) {
2216 if (strncmp(s, "ENDMDL", 6) == 0)
2217 break;
2218 if (strncmp(s, "ATOM", 4) != 0)
2219 continue;
2220
2221 if (s[13] == ' ')
2222 s[13] = s[14];
2223 if (s[13] == ' ')
2224 s[13] = s[15];
2225
2226 float e = 6;
2227 char ctt, ctt2 = ' ';
2228 if (s[13] == ' ')
2229 ctt = s[14];
2230 else if (s[12] == ' ') {
2231 ctt = s[13];
2232 ctt2 = s[14];
2233 }
2234 else {
2235 ctt = s[12];
2236 ctt2 = s[13];
2237 }
2238 if (ctt != 'C' || ctt2 != 'A')
2239 continue;
2240
2241 float x, y, z, q;
2242 sscanf(&s[28], " %f %f %f", &x, &y, &z);
2243 sscanf(&s[60], " %f", &q);
2244
2245 if (count + 1 > get_number_points())
2246 set_number_points(2 * (count + 1)); //makes sure point array is big enough
2247
2248#ifdef DEBUG
2249 printf("Atom %4lu: x,y,z = %8g,%8g,%8g\te = %g\n", count, x, y, z, e);
2250#endif
2251 points[4 * count] = x;
2252 points[4 * count + 1] = y;
2253 points[4 * count + 2] = z;
2254 points[4 * count + 3] = e;
2255 bfactor[count] = q;
2256 count++;
2257 }
2258 fclose(fp);
2259 set_number_points(count);
2260 return true;
2261}
2262
2264{
2265 if (axis == 0)
2266 qsort(points, n, sizeof(double) * 4, cmp_axis_x);
2267 else if (axis == 1)
2268 qsort(points, n, sizeof(double) * 4, cmp_axis_y);
2269 else if (axis == 2)
2270 qsort(points, n, sizeof(double) * 4, cmp_axis_z);
2271 else
2272 qsort(points, n, sizeof(double) * 4, cmp_val);
2273}
2274
2275
2276EMData *PointArray::pdb2mrc_by_summation(int map_size, float apix, float res, int addpdbbfactor)
2277{
2278#ifdef DEBUG
2279 printf("PointArray::pdb2mrc_by_summation(): %lu points\tmapsize = %4d\tapix = %g\tres = %g\n",get_number_points(),map_size, apix, res);
2280#endif
2281 //if ( gauss_real_width < apix) LOGERR("PointArray::projection_by_summation(): apix(%g) is too large for resolution (%g Angstrom in Fourier space) with %g pixels of 1/e half width", apix, res, gauss_real_width);
2282
2283 double min_table_val = 1e-7;
2284 double max_table_x = sqrt(-log(min_table_val)); // for exp(-x*x)
2285
2286 double table_step_size = 0.001; // number of steps for each pixel
2287 double inv_table_step_size = 1.0 / table_step_size;
2288
2289// sort_by_axis(2); // sort by Z-axis
2290
2291 EMData *map = new EMData();
2292 map->set_size(map_size, map_size, map_size);
2293 map->to_zero();
2294 float *pd = map->get_data();
2295
2296 vector<double> table;
2297 double gauss_real_width;
2298 int table_size;
2299 int gbox;
2300
2301
2302 for ( size_t s = 0; s < get_number_points(); ++s) {
2303 double xc = points[4 * s] / apix + map_size / 2;
2304 double yc = points[4 * s + 1] / apix + map_size / 2;
2305 double zc = points[4 * s + 2] / apix + map_size / 2;
2306 double fval = points[4 * s + 3];
2307
2308 //printf("\n bfactor=%f",bfactor[s]);
2309
2310 if(addpdbbfactor==-1){
2311 gauss_real_width = res/M_PI; // in Angstrom, res is in Angstrom
2312 }else{
2313 gauss_real_width = (bfactor[s])/(4*sqrt(2.0)*M_PI); // in Angstrom, res is in Angstrom
2314 }
2315
2316 table_size = int (max_table_x * gauss_real_width / (apix * table_step_size) * 1.25);
2317 table.resize(table_size);
2318 for (int i = 0; i < table_size; i++){
2319 table[i] = 0;
2320 }
2321
2322 for (int i = 0; i < table_size; i++) {
2323 double x = -i * table_step_size * apix / gauss_real_width;
2324 if(addpdbbfactor==-1){
2325 table[i] = exp(-x * x);
2326 }
2327 else{
2328 table[i] = exp(-x * x)/sqrt(gauss_real_width * gauss_real_width * 2 * M_PI);
2329 }
2330 }
2331
2332 gbox = int (max_table_x * gauss_real_width / apix); // local box half size in pixels to consider for each point
2333 if (gbox <= 0)
2334 gbox = 1;
2335
2336 int imin = int (xc) - gbox, imax = int (xc) + gbox;
2337 int jmin = int (yc) - gbox, jmax = int (yc) + gbox;
2338 int kmin = int (zc) - gbox, kmax = int (zc) + gbox;
2339 if (imin < 0)
2340 imin = 0;
2341 if (jmin < 0)
2342 jmin = 0;
2343 if (kmin < 0)
2344 kmin = 0;
2345 if (imax > map_size)
2346 imax = map_size;
2347 if (jmax > map_size)
2348 jmax = map_size;
2349 if (kmax > map_size)
2350 kmax = map_size;
2351
2352 for (int k = kmin; k < kmax; k++) {
2353 size_t table_index_z = size_t (fabs(k - zc) * inv_table_step_size);
2354 if ( table_index_z >= table.size() ) continue;
2355 double zval = table[table_index_z];
2356 size_t pd_index_z = k * map_size * map_size;
2357
2358 for (int j = jmin; j < jmax; j++) {
2359 size_t table_index_y = size_t (fabs(j - yc) * inv_table_step_size);
2360 if ( table_index_y >= table.size() ) continue;
2361 double yval = table[table_index_y];
2362 size_t pd_index = pd_index_z + j * map_size + imin;
2363 for (int i = imin; i < imax; i++, pd_index++) {
2364 size_t table_index_x = size_t (fabs(i - xc) * inv_table_step_size);
2365 if ( table_index_x >= table.size() ) continue;
2366 double xval = table[table_index_x];
2367 pd[pd_index] += (float) (fval * zval * yval * xval);
2368 }
2369 }
2370 }
2371 }
2372
2373 map->update();
2374 map->set_attr("apix_x", apix);
2375 map->set_attr("apix_y", apix);
2376 map->set_attr("apix_z", apix);
2377 map->set_attr("origin_x", -map_size/2*apix);
2378 map->set_attr("origin_y", -map_size/2*apix);
2379 map->set_attr("origin_z", -map_size/2*apix);
2380
2381 return map;
2382}
2383
2384
2385EMData *PointArray::projection_by_summation(int image_size, float apix, float res)
2386{
2387 double gauss_real_width = res / (M_PI); // in Angstrom, res is in Angstrom
2388 //if ( gauss_real_width < apix) LOGERR("PointArray::projection_by_summation(): apix(%g) is too large for resolution (%g Angstrom in Fourier space) with %g pixels of 1/e half width", apix, res, gauss_real_width);
2389
2390 double min_table_val = 1e-7;
2391 double max_table_x = sqrt(-log(min_table_val)); // for exp(-x*x)
2392
2393 //double table_step_size = 0.001; // number of steps for x=[0,1] in exp(-x*x)
2394 //int table_size = int(max_table_x / table_step_size *1.25);
2395 //double* table = (double*)malloc(sizeof(double) * table_size);
2396 //for(int i=0; i<table_size; i++) table[i]=exp(-i*i*table_step_size*table_step_size);
2397
2398 double table_step_size = 0.001; // number of steps for each pixel
2399 double inv_table_step_size = 1.0 / table_step_size;
2400 int table_size = int (max_table_x * gauss_real_width / (apix * table_step_size) * 1.25);
2401 double *table = (double *) malloc(sizeof(double) * table_size);
2402 for (int i = 0; i < table_size; i++) {
2403 double x = -i * table_step_size * apix / gauss_real_width;
2404 table[i] = exp(-x * x);
2405 }
2406
2407 int gbox = int (max_table_x * gauss_real_width / apix); // local box half size in pixels to consider for each point
2408 if (gbox <= 0)
2409 gbox = 1;
2410 EMData *proj = new EMData();
2411 proj->set_size(image_size, image_size, 1);
2412 proj->to_zero();
2413 float *pd = proj->get_data();
2414 for ( size_t s = 0; s < get_number_points(); ++s) {
2415 double xc = points[4 * s] / apix + image_size / 2;
2416 double yc = points[4 * s + 1] / apix + image_size / 2;
2417 double fval = points[4 * s + 3];
2418 int imin = int (xc) - gbox, imax = int (xc) + gbox;
2419 int jmin = int (yc) - gbox, jmax = int (yc) + gbox;
2420 if (imin < 0)
2421 imin = 0;
2422 if (jmin < 0)
2423 jmin = 0;
2424 if (imax > image_size)
2425 imax = image_size;
2426 if (jmax > image_size)
2427 jmax = image_size;
2428
2429 for (int j = jmin; j < jmax; j++) {
2430 //int table_index_y = int(fabs(j-yc)*apix/gauss_real_width/table_step_size);
2431 int table_index_y = int (fabs(j - yc) * inv_table_step_size);
2432 double yval = table[table_index_y];
2433#ifdef DEBUG
2434 //double yval2 = exp( - (j-yc)*(j-yc)*apix*apix/(gauss_real_width*gauss_real_width));
2435 //if(fabs(yval2-yval)/yval2>1e-2) printf("s=%d\txc,yc=%g,%g\tyval,yval2=%g,%g\tdiff=%g\n",s,xc,yc,yval,yval2,fabs(yval2-yval)/yval2);
2436#endif
2437 int pd_index = j * image_size + imin;
2438 for (int i = imin; i < imax; i++, pd_index++) {
2439 //int table_index_x = int(fabs(i-xc)*apix/gauss_real_width/table_step_size);
2440 int table_index_x = int (fabs(i - xc) * inv_table_step_size);
2441 double xval = table[table_index_x];
2442#ifdef DEBUG
2443 //double xval2 = exp( - (i-xc)*(i-xc)*apix*apix/(gauss_real_width*gauss_real_width));
2444 //if(fabs(xval2-xval)/xval2>1e-2) printf("\ts=%d\txc,yc=%g,%g\txval,xval2=%g,%g\tdiff=%g\n",s,xc,yc,xval,xval2,fabs(xval2-xval)/xval2);
2445#endif
2446 pd[pd_index] += (float)(fval * yval * xval);
2447 }
2448 }
2449 }
2450 for (int i = 0; i < image_size * image_size; i++)
2451 pd[i] /= sqrt(M_PI);
2452 proj->update();
2453 return proj;
2454}
2455
2456void PointArray::replace_by_summation(EMData *proj, int ind, Vec3f vec, float amp, float apix, float res)
2457{
2458 double gauss_real_width = res / (M_PI); // in Angstrom, res is in Angstrom
2459
2460 double min_table_val = 1e-7;
2461 double max_table_x = sqrt(-log(min_table_val)); // for exp(-x*x)
2462
2463 double table_step_size = 0.001; // number of steps for each pixel
2464 double inv_table_step_size = 1.0 / table_step_size;
2465 int table_size = int (max_table_x * gauss_real_width / (apix * table_step_size) * 1.25);
2466 double *table = (double *) malloc(sizeof(double) * table_size);
2467 for (int i = 0; i < table_size; i++) {
2468 double x = -i * table_step_size * apix / gauss_real_width;
2469 table[i] = exp(-x * x)/pow((float)M_PI,.25f);
2470 }
2471 int image_size=proj->get_xsize();
2472
2473 // subtract the old point
2474 int gbox = int (max_table_x * gauss_real_width / apix); // local box half size in pixels to consider for each point
2475 if (gbox <= 0)
2476 gbox = 1;
2477 float *pd = proj->get_data();
2478 int s = ind;
2479 double xc = points[4 * s] / apix + image_size / 2;
2480 double yc = points[4 * s + 1] / apix + image_size / 2;
2481 double fval = points[4 * s + 3];
2482 int imin = int (xc) - gbox, imax = int (xc) + gbox;
2483 int jmin = int (yc) - gbox, jmax = int (yc) + gbox;
2484
2485 if (imin < 0) imin = 0;
2486 if (jmin < 0) jmin = 0;
2487 if (imax > image_size) imax = image_size;
2488 if (jmax > image_size) jmax = image_size;
2489
2490 for (int j = jmin; j < jmax; j++) {
2491 int table_index_y = int (fabs(j - yc) * inv_table_step_size);
2492 double yval = table[table_index_y];
2493 int pd_index = j * image_size + imin;
2494 for (int i = imin; i < imax; i++, pd_index++) {
2495 int table_index_x = int (fabs(i - xc) * inv_table_step_size);
2496 double xval = table[table_index_x];
2497 pd[pd_index] -= (float)(fval * yval * xval);
2498 }
2499 }
2500
2501 // add the new point
2502 gbox = int (max_table_x * gauss_real_width / apix); // local box half size in pixels to consider for each point
2503 if (gbox <= 0)
2504 gbox = 1;
2505 pd = proj->get_data();
2506 s = ind;
2507 xc = vec[0] / apix + image_size / 2;
2508 yc = vec[1] / apix + image_size / 2;
2509 fval = amp;
2510 imin = int (xc) - gbox, imax = int (xc) + gbox;
2511 jmin = int (yc) - gbox, jmax = int (yc) + gbox;
2512
2513 if (imin < 0) imin = 0;
2514 if (jmin < 0) jmin = 0;
2515 if (imax > image_size) imax = image_size;
2516 if (jmax > image_size) jmax = image_size;
2517
2518 for (int j = jmin; j < jmax; j++) {
2519 int table_index_y = int (fabs(j - yc) * inv_table_step_size);
2520 double yval = table[table_index_y];
2521 int pd_index = j * image_size + imin;
2522 for (int i = imin; i < imax; i++, pd_index++) {
2523 int table_index_x = int (fabs(i - xc) * inv_table_step_size);
2524 double xval = table[table_index_x];
2525 pd[pd_index] -= (float)(fval * yval * xval);
2526 }
2527 }
2528
2529 proj->update();
2530 return;
2531}
2532
2533
2535{
2536#if defined USE_NFFT
2537 nfft_3D_plan my_plan; // plan for the nfft
2538
2540 nfft_3D_init(&my_plan, map_size, get_number_points());
2541
2543 for (int j = 0, i = 0; j < my_plan.M; j++, i += 4) {
2544 // FFTW and nfft use row major array layout, EMAN uses column major
2545 my_plan.v[3 * j + 2] = (fftw_real) (points[i] / (apix * map_size));
2546 my_plan.v[3 * j + 1] = (fftw_real) (points[i + 1] / (apix * map_size));
2547 my_plan.v[3 * j] = (fftw_real) (points[i + 2] / (apix * map_size));
2548 my_plan.f[j].re = (fftw_real) (points[i + 3]);
2549 my_plan.f[j].im = 0.0;
2550 }
2551
2553 if (my_plan.nfft_flags & PRE_PSI) {
2554 nfft_3D_precompute_psi(&my_plan);
2555 }
2556
2557 // compute the uniform Fourier transform
2558 nfft_3D_transpose(&my_plan);
2559
2560 // copy the Fourier transform to EMData data array
2561 EMData *fft = new EMData();
2562 fft->set_size(map_size + 2, map_size, map_size);
2563 fft->set_complex(true);
2564 fft->set_ri(true);
2565 fft->to_zero();
2566 float *data = fft->get_data();
2567 double norm = 1.0 / (map_size * map_size * map_size);
2568 for (int k = 0; k < map_size; k++) {
2569 for (int j = 0; j < map_size; j++) {
2570 for (int i = 0; i < map_size / 2; i++) {
2571 data[k * map_size * (map_size + 2) + j * (map_size + 2) + 2 * i] =
2572 (float) (my_plan.
2573 f_hat[k * map_size * map_size + j * map_size + i +
2574 map_size / 2].re) * norm;
2575 data[k * map_size * (map_size + 2) + j * (map_size + 2) + 2 * i + 1] =
2576 (float) (my_plan.
2577 f_hat[k * map_size * map_size + j * map_size + i +
2578 map_size / 2].im) * norm * (-1.0);
2579 }
2580 }
2581 }
2583 nfft_3D_finalize(&my_plan);
2584
2585 // low pass processor
2586 double sigma2 = (map_size * apix / res) * (map_size * apix / res);
2587 int index = 0;
2588 for (int k = 0; k < map_size; k++) {
2589 double RZ2 = (k - map_size / 2) * (k - map_size / 2);
2590 for (int j = 0; j < map_size; j++) {
2591 double RY2 = (j - map_size / 2) * (j - map_size / 2);
2592 for (int i = 0; i < map_size / 2 + 1; i++, index += 2) {
2593 float val = exp(-(i * i + RY2 + RZ2) / sigma2);
2594 data[index] *= val;
2595 data[index + 1] *= val;
2596 }
2597 }
2598 }
2599 fft->update();
2600 //fft->process_inplace("filter.lowpass.gauss",Dict("cutoff_abs", map_size*apix/res));
2601
2602 fft->process_inplace("xform.phaseorigin.tocorner"); // move phase origin to center of image map_size, instead of at corner
2603 EMData *map = fft->do_ift();
2604 map->set_attr("apix_x", apix);
2605 map->set_attr("apix_y", apix);
2606 map->set_attr("apix_z", apix);
2607 map->set_attr("origin_x", -map_size/2*apix);
2608 map->set_attr("origin_y", -map_size/2*apix);
2609 map->set_attr("origin_z", -map_size/2*apix);
2610 if( fft )
2611 {
2612 delete fft;
2613 fft = 0;
2614 }
2615 return map;
2616#elif defined NFFT2
2617 nfft_plan my_plan; // plan for the nfft
2618
2620 nfft_init_3d(&my_plan, map_size, map_size, map_size, get_number_points());
2621
2623 for (int j = 0, i = 0; j < my_plan.M; j++, i += 4) {
2624 // FFTW and nfft use row major array layout, EMAN uses column major
2625 my_plan.x[3 * j + 2] = (double) (points[i] / (apix * map_size));
2626 my_plan.x[3 * j + 1] = (double) (points[i + 1] / (apix * map_size));
2627 my_plan.x[3 * j] = (double) (points[i + 2] / (apix * map_size));
2628 my_plan.f[j][0] = (double) (points[i + 3]);
2629 my_plan.f[j][1] = 0.0;
2630 }
2631
2633 if (my_plan.nfft_flags & PRE_PSI) {
2634 nfft_precompute_psi(&my_plan);
2635 if (my_plan.nfft_flags & PRE_FULL_PSI)
2636 nfft_full_psi(&my_plan, pow(10, -10));
2637 }
2638
2639 // compute the uniform Fourier transform
2640 nfft_transposed(&my_plan);
2641
2642 // copy the Fourier transform to EMData data array
2643 EMData *fft = new EMData();
2644 fft->set_size(map_size + 2, map_size, map_size);
2645 fft->set_complex(true);
2646 fft->set_ri(true);
2647 fft->to_zero();
2648 float *data = fft->get_data();
2649 double norm = 1.0 / (map_size * map_size * map_size);
2650 for (int k = 0; k < map_size; k++) {
2651 for (int j = 0; j < map_size; j++) {
2652 for (int i = 0; i < map_size / 2; i++) {
2653 data[k * map_size * (map_size + 2) + j * (map_size + 2) + 2 * i] =
2654 (float) (my_plan.
2655 f_hat[k * map_size * map_size + j * map_size + i +
2656 map_size / 2][0]) * norm;
2657 data[k * map_size * (map_size + 2) + j * (map_size + 2) + 2 * i + 1] =
2658 (float) (my_plan.
2659 f_hat[k * map_size * map_size + j * map_size + i +
2660 map_size / 2][1]) * norm;
2661 }
2662 }
2663 }
2665 nfft_finalize(&my_plan);
2666
2667 // low pass processor
2668 double sigma2 = (map_size * apix / res) * (map_size * apix / res);
2669 int index = 0;
2670 for (int k = 0; k < map_size; k++) {
2671 double RZ2 = (k - map_size / 2) * (k - map_size / 2);
2672 for (int j = 0; j < map_size; j++) {
2673 double RY2 = (j - map_size / 2) * (j - map_size / 2);
2674 for (int i = 0; i < map_size / 2 + 1; i++, index += 2) {
2675 float val = exp(-(i * i + RY2 + RZ2) / sigma2);
2676 data[index] *= val;
2677 data[index + 1] *= val;
2678 }
2679 }
2680 }
2681 fft->update();
2682 //fft->process_inplace(".filter.lowpass.gauss",Dict("cutoff_abs", map_size*apix/res));
2683
2684 fft->process_inplace("xform.phaseorigin.tocenter"); // move phase origin to center of image map_size, instead of at corner
2685 EMData *map = fft->do_ift();
2686 map->set_attr("apix_x", apix);
2687 map->set_attr("apix_y", apix);
2688 map->set_attr("apix_z", apix);
2689 map->set_attr("origin_x", -map_size / 2 * apix);
2690 map->set_attr("origin_y", -map_size / 2 * apix);
2691 map->set_attr("origin_z", -map_size / 2 * apix);
2692 if( fft )
2693 {
2694 delete fft;
2695 fft = 0;
2696 }
2697 return map;
2698#else
2699 LOGWARN("nfft support is not enabled. please recompile with nfft support enabled\n");
2700 return 0;
2701#endif
2702}
2703
2705{
2706#if defined USE_NFFT
2707 nfft_2D_plan my_plan; // plan for the nfft
2708 int N[2], n[2];
2709 N[0] = image_size;
2710 n[0] = next_power_of_2(2 * image_size);
2711 N[1] = image_size;
2712 n[1] = next_power_of_2(2 * image_size);
2713
2715 nfft_2D_init(&my_plan, image_size, get_number_points());
2716 //nfft_2D_init_specific(&my_plan, N, get_number_points(), n, 3,
2717 // PRE_PHI_HUT | PRE_PSI,
2718 // FFTW_ESTIMATE | FFTW_OUT_OF_PLACE);
2720 for (int j = 0, i = 0; j < my_plan.M; j++, i += 4) {
2721 // FFTW and nfft use row major array layout, EMAN uses column major
2722 my_plan.v[2 * j + 1] = (fftw_real) (points[i] / (apix * image_size));
2723 my_plan.v[2 * j] = (fftw_real) (points[i + 1] / (apix * image_size));
2724 my_plan.f[j].re = (fftw_real) points[i + 3];
2725 my_plan.f[j].im = 0.0;
2726 }
2727
2729 if (my_plan.nfft_flags & PRE_PSI) {
2730 nfft_2D_precompute_psi(&my_plan);
2731 }
2732
2733 // compute the uniform Fourier transform
2734 nfft_2D_transpose(&my_plan);
2735
2736 // copy the Fourier transform to EMData data array
2737 EMData *fft = new EMData();
2738 fft->set_size(image_size + 2, image_size, 1);
2739 fft->set_complex(true);
2740 fft->set_ri(true);
2741 fft->to_zero();
2742 float *data = fft->get_data();
2743 double norm = 1.0 / (image_size * image_size);
2744 for (int j = 0; j < image_size; j++) {
2745 for (int i = 0; i < image_size / 2; i++) {
2746 data[j * (image_size + 2) + 2 * i] =
2747 (float) (my_plan.f_hat[j * image_size + i + image_size / 2].re) * norm;
2748 data[j * (image_size + 2) + 2 * i + 1] =
2749 (float) (my_plan.f_hat[j * image_size + i + image_size / 2].im) * norm * (-1.0);
2750 }
2751 }
2753 nfft_2D_finalize(&my_plan);
2754
2755 if (res > 0) {
2756 // Gaussian low pass processor
2757 double sigma2 = (image_size * apix / res) * (image_size * apix / res);
2758 int index = 0;
2759 for (int j = 0; j < image_size; j++) {
2760 double RY2 = (j - image_size / 2) * (j - image_size / 2);
2761 for (int i = 0; i < image_size / 2 + 1; i++, index += 2) {
2762 double val = exp(-(i * i + RY2) / sigma2);
2763 data[index] *= val;
2764 data[index + 1] *= val;
2765 }
2766 }
2767 }
2768 fft->update();
2769 //fft->process_inplace("filter.lowpass.gauss",Dict("cutoff_abs", box*apix/res));
2770
2771 fft->process_inplace("xform.phaseorigin.tocenter"); // move phase origin to center of image box, instead of at corner
2772
2773 return fft;
2774#elif defined NFFT2
2775 nfft_plan my_plan; // plan for the nfft
2776 int N[2], n[2];
2777 N[0] = image_size;
2778 n[0] = next_power_of_2(2 * image_size);
2779 N[1] = image_size;
2780 n[1] = next_power_of_2(2 * image_size);
2781
2783 //nfft_init_2d(&my_plan,image_size,image_size,get_number_points());
2784 nfft_init_specific(&my_plan, 2, N, get_number_points(), n, 3,
2785 PRE_PHI_HUT | PRE_PSI |
2786 MALLOC_X | MALLOC_F_HAT | MALLOC_F, FFTW_ESTIMATE | FFTW_DESTROY_INPUT);
2788 for (int j = 0, i = 0; j < my_plan.M; j++, i += 4) {
2789 // FFTW and nfft use row major array layout, EMAN uses column major
2790 my_plan.x[2 * j + 1] = (double) (points[i] / (apix * image_size));
2791 my_plan.x[2 * j] = (double) (points[i + 1] / (apix * image_size));
2792 my_plan.f[j][0] = (double) points[i + 3];
2793 my_plan.f[j][1] = 0.0;
2794 }
2795
2797 if (my_plan.nfft_flags & PRE_PSI) {
2798 nfft_precompute_psi(&my_plan);
2799 if (my_plan.nfft_flags & PRE_FULL_PSI)
2800 nfft_full_psi(&my_plan, pow(10, -6));
2801 }
2802
2803 // compute the uniform Fourier transform
2804 nfft_transposed(&my_plan);
2805
2806 // copy the Fourier transform to EMData data array
2807 EMData *fft = new EMData();
2808 fft->set_size(image_size + 2, image_size, 1);
2809 fft->set_complex(true);
2810 fft->set_ri(true);
2811 fft->to_zero();
2812 float *data = fft->get_data();
2813 double norm = 1.0 / (image_size * image_size);
2814 for (int j = 0; j < image_size; j++) {
2815 for (int i = 0; i < image_size / 2; i++) {
2816 data[j * (image_size + 2) + 2 * i] =
2817 (float) (my_plan.f_hat[j * image_size + i + image_size / 2][0]) * norm;
2818 data[j * (image_size + 2) + 2 * i + 1] =
2819 (float) (my_plan.f_hat[j * image_size + i + image_size / 2][1]) * norm;
2820 }
2821 }
2823 nfft_finalize(&my_plan);
2824
2825 if (res > 0) {
2826 // Gaussian low pass process
2827 double sigma2 = (image_size * apix / res) * (image_size * apix / res);
2828 int index = 0;
2829 for (int j = 0; j < image_size; j++) {
2830 double RY2 = (j - image_size / 2) * (j - image_size / 2);
2831 for (int i = 0; i < image_size / 2 + 1; i++, index += 2) {
2832 double val = exp(-(i * i + RY2) / sigma2);
2833 data[index] *= val;
2834 data[index + 1] *= val;
2835 }
2836 }
2837 }
2838 fft->update();
2839 //fft->process_inplace("filter.lowpass.gauss",Dict("cutoff_abs", box*apix/res));
2840
2841 fft->process_inplace("xform.phaseorigin.tocenter"); // move phase origin to center of image box, instead of at corner
2842
2843 return fft;
2844#else
2845 LOGWARN("nfft support is not enabled. please recompile with nfft support enabled\n");
2846 return 0;
2847#endif
2848}
2849
2850#ifdef USE_OPTPP
2851#include "NLF.h"
2852#include "BoundConstraint.h"
2853#include "OptCG.h"
2854//#include "OptNewton.h"
2855#include "newmatap.h"
2856
2857vector<EMData*> optdata;
2858PointArray *optobj;
2859float optpixres;
2860
2861void init_opt_proj(int ndim, ColumnVector& x)
2862{
2863int i;
2864double *data=optobj->get_points_array();
2865
2866for (i=0; i<ndim; i++) x(i+1)=data[i];
2867}
2868
2869void calc_opt_proj(int n, const ColumnVector& x, double& fx, int& result)
2870{
2871 int i;
2872 PointArray pa;
2873 Transform xform;
2874 int size=optdata[0]->get_xsize();
2875 fx=0;
2876
2877 for (i=0; i<optdata.size(); i++) {
2878 xform=(optdata[i]->get_transform());
2879 pa.set_from((double *)x.nric()+1,n/4,std::string("c1"),&xform);
2880 EMData *p=pa.projection_by_summation(size,1.0,optpixres);
2881 p->process_inplace("normalize.unitlen");
2882 fx-=sqrt(p->cmp("dot",EMObject(optdata[i]),Dict()));
2883 }
2884
2885 result=NLPFunction;
2886
2887 printf("%g\t%1.1f %1.1f %1.1f %g\t%1.1f %1.1f %1.1f %g\t%1.1f %1.1f %1.1f %g\n",fx,x(1),x(2),x(3),x(4),x(5),x(6),x(7),x(8),x(9),x(10),x(11),x(12));
2888}
2889
2890void calc_opt_projd(int mode,int n, const ColumnVector& x, double& fx, ColumnVector& gx, int& result)
2891{
2892
2893if (mode & NLPFunction) {
2894
2895}
2896
2897if (mode & NLPGradient) {
2898
2899}
2900
2901}
2902#endif
2903
2904void PointArray::opt_from_proj(const vector<EMData*> & proj,float pixres) {
2905#ifdef USE_OPTPP
2906 optdata=proj;
2907 optobj=this;
2908 optpixres=pixres;
2909
2910 FDNLF1 nlf(get_number_points()*4,calc_opt_proj,init_opt_proj);
2911// NLF1 nlf(get_number_points()*4,init_opt_proj,calc_opt_projd);
2912 nlf.initFcn();
2913
2914 OptCG opt(&nlf);
2915// OptQNewton opt(&nlf);
2916 opt.setMaxFeval(2000);
2917 opt.optimize();
2918 opt.printStatus("Done");
2919#else
2920 (void)proj; //suppress warning message
2921 (void)pixres; //suppress warning message
2922 LOGWARN("OPT++ support not enabled.\n");
2923 return;
2924#endif
2925}
2926
2928{
2929return Vec3f((float)points[i*4],(float)points[i*4+1],(float)points[i*4+2]);
2930}
2931
2933{
2934return points[i*4+3];
2935}
2936
2937void PointArray::set_vector_at(int i,Vec3f vec,double value)
2938{
2939points[i*4]=vec[0];
2940points[i*4+1]=vec[1];
2941points[i*4+2]=vec[2];
2942points[i*4+3]=value;
2943}
2944
2945void PointArray::set_vector_at(int i,vector<double> v)
2946{
2947points[i*4] =v[0];
2948points[i*4+1]=v[1];
2949points[i*4+2]=v[2];
2950if (v.size()>=4) points[i*4+3]=v[3];
2951}
#define eigval(i)
Definition: analyzer.cpp:594
#define v0(i)
Definition: analyzer.cpp:698
#define covmat(i, j)
Definition: analyzer.cpp:452
#define eigvec(i, j)
Definition: analyzer.cpp:958
Dict is a dictionary to store <string, EMObject> pair.
Definition: emobject.h:385
EMData stores an image's data and defines core image processing routines.
Definition: emdata.h:82
EMObject is a wrapper class for types including int, float, double, etc as defined in ObjectType.
Definition: emobject.h:123
FloatPoint defines a float-coordinate point in a 1D/2D/3D space.
Definition: geometry.h:278
PointArray defines a double array of points with values in a 3D space.
Definition: pointarray.h:52
EMData * gradz
Definition: pointarray.h:247
EMData * projection_by_summation(int image_size, float apix, float res)
Transform * align_2d(PointArray *to, float max_dist)
Aligns one PointArray to another in 2 dimensions.
Definition: pointarray.cpp:281
void save_pdb_with_helix(const char *file, vector< float > hlxid)
Save the point array to pdb file, including helices information.
void save_to_pdb(const char *file)
Definition: pointarray.cpp:441
double * get_points_array()
Definition: pointarray.cpp:182
Transform calc_transform(PointArray *p)
Calculate the transform to another identical pointarray.
void sim_add_point_one()
void sim_add_point_double()
Add more points during the simulation.
EMData * distmx(int sortrows=0)
Calculates a (symmetrized) distance matrix for the current PointArray.
Definition: pointarray.cpp:192
void set_from_density_map(EMData *map, int num, float thresh, float apix, Density2PointsArrayAlgorithm mode=PEAKS_DIV)
Definition: pointarray.cpp:663
vector< double > fit_helix(EMData *pmap, int minlength, float mindensity, vector< int > edge, int twodir, size_t minl)
Fit helix from peptide chains.
double get_value_at(int i)
vector< float > get_points()
Returns all x,y,z triplets packed into a vector<float>
Definition: pointarray.cpp:594
void sim_minstep_seq(double meanshift)
Takes a step to minimize the potential.
PointArray * copy()
Definition: pointarray.cpp:149
void replace_by_summation(EMData *image, int i, Vec3f vec, float amp, float apix, float res)
void sim_updategeom()
Updates the dist, ang, dihed parameters.
Definition: pointarray.cpp:945
bool read_ca_from_pdb(const char *file)
Read only C-alpha atoms from a pdb file.
vector< int > match_points(PointArray *to, float max_miss=-1.0)
Will try to establish a 1-1 correspondence between points in two different PointArray objects (this a...
Definition: pointarray.cpp:217
EMData * projection_by_nfft(int image_size, float apix, float res=0)
void sim_minstep(double maxshift)
Takes a step to minimize the potential.
EMData * pdb2mrc_by_summation(int map_size, float apix, float res, int addpdbbfactor)
double * adist
Definition: pointarray.h:227
EMData * gradx
Definition: pointarray.h:247
double * points
Definition: pointarray.h:221
vector< double > construct_helix(int start, int end, float phs, float &score, int &dir)
Construct an ideal helix between the start and end points given phase.
FloatPoint get_center()
Definition: pointarray.cpp:453
vector< float > do_pca(int start, int end)
Do principal component analysis to (a subset of) the point array, used in helix fitting in pathwalker...
void opt_from_proj(const vector< EMData * > &proj, float pixres)
Optimizes a pointarray based on a set of projection images (EMData objects) This is effectively a 3D ...
PointArray & operator=(PointArray &pa)
Definition: pointarray.cpp:159
void merge_to(PointArray &pa, float thr)
Merge to another point array.
Vec3f get_vector_at(int i)
float calc_helicity(vector< double > pts)
Calculate the helicity of some points.
double * bfactor
Definition: pointarray.h:223
double * adihed
Definition: pointarray.h:229
void right_transform(const Transform &transform)
Does Transform*v as opposed to v*Transform (as in the transform function)
Definition: pointarray.cpp:617
EMData * pdb2mrc_by_nfft(int map_size, float apix, float res)
double sim_potentialdxyz(int i, double dx, double dy, double dz)
Compute a potential value for a perturbed point, including +-2 nearest neighbors which will also be i...
void set_from(vector< float >)
Definition: pointarray.cpp:658
Region get_bounding_box()
Definition: pointarray.cpp:482
void mask(double rmax, double rmin=0.0)
Definition: pointarray.cpp:507
void delete_point(int id)
Delete one point in the array.
double dist0
Used for simplistic loop dynamics simulation Assumes all points are connected sequentially in a close...
Definition: pointarray.h:244
double sim_potentiald(int ind)
Compute a single point potential value.
void sim_printstat()
prints some statistics to the screen
void set_vector_at(int i, Vec3f vec, double value)
void set_number_points(size_t nn)
Definition: pointarray.cpp:173
void reverse_chain()
Reverse the pointarray chain.
double calc_total_length()
Calculate total length.
EMData * grady
Definition: pointarray.h:247
void sort_by_axis(int axis=1)
bool read_from_pdb(const char *file, const vector< int > &lines=vector< int >())
Definition: pointarray.cpp:329
void set_points_array(double *p)
Definition: pointarray.cpp:187
void transform(const Transform &transform)
Definition: pointarray.cpp:605
void sim_set_pot_parms(double pdist0, double pdistc, double pangc, double pdihed0, double pdihedc, double pmapc, EMData *pmap, double pmindistc, double pdistpenc)
Sets the parameters for the energy function.
void remove_helix_from_map(EMData *m, vector< float > hlxid)
Remove the corresponding density of the helix point from a density map.
double sim_potential()
Computes overall potential for the configuration.
Definition: pointarray.cpp:988
void sim_rescale()
rescale the entire set so the mean bond length matches dist0
vector< float > do_filter(vector< float > pts, float *ft, int num)
Filter the point array to smooth the line, used in helix fitting in pathwalker.
double sim_pointpotential(double dist, double ang, double dihed)
Computes a potential value for a single point from a set of angles/distances using current energy set...
Definition: pointarray.h:142
Vec3f sim_descent(int i)
returns a vector pointing downhill for a single point
size_t get_number_points() const
Definition: pointarray.cpp:168
vector< Vec3f > oldshifts
Definition: pointarray.h:248
void mask_asymmetric_unit(const string &sym)
Definition: pointarray.cpp:534
Region defines a 2D or 3D rectangular region specified by its origin coordinates and all edges' sizes...
Definition: geometry.h:497
A Transform object is a somewhat specialized object designed specifically for EMAN2/Sparx storage of ...
Definition: transform.h:75
Transform get_sym(const string &sym, int n) const
Apply the symmetry deduced from the function arguments to this Transform and return the result.
Definition: transform.cpp:1389
void set_rotation(const Dict &rotation)
Set a rotation using a specific Euler type and the dictionary interface Works for all Euler types.
Definition: transform.cpp:519
void set(int r, int c, float value)
Set the value stored in the internal transformation matrix at at coordinate (r,c) to value.
Definition: transform.h:400
void set_pre_trans(const type &v)
Set the translational component of the matrix as though it was MSRT_ not MTSR, where T_ is the pre tr...
Definition: transform.h:556
void set_trans(const float &x, const float &y, const float &z=0)
Set the post translation component.
Definition: transform.cpp:1036
static int get_nsym(const string &sym)
get the number of symmetries associated with the given symmetry name
Definition: transform.cpp:1570
static Vec3f calc_bilinear_least_square(const vector< float > &points)
calculate bilinear least-square fit, z = a + b x + c y Takes a set of x,y,z vectors and produces an a...
Definition: util.cpp:577
static float get_frand(int low, int high)
Get a float random number between low and high, [low, high)
Definition: util.cpp:725
static int round(float x)
Get ceiling round of a float number x.
Definition: util.h:465
static int get_irand(int low, int high)
Get an integer random number between low and high, [low, high].
Definition: util.cpp:719
Vec3< Type > cross(const Vec3< Type2 > &v) const
Calculate the cross product of 'this' vector with a second vector.
Definition: vec3.h:384
Type dot(const Vec3< Type2 > &v) const
Calculate the dot product of 'this' vector with a second vector.
Definition: vec3.h:373
float normalize()
Normalize the vector and return its length before the normalization.
Definition: vec3.h:332
float length() const
Calculate its length.
Definition: vec3.h:352
EMData * log() const
return natural logarithm image for a image
EMData * sqrt() const
return square root of current image
#define LOGWARN
Definition: log.h:53
#define LOGERR
Definition: log.h:51
E2Exception class.
Definition: aligner.h:40
Vector3 cross(const Vector3 &w, const Vector3 &v)
Definition: vecmath.h:309
Vec3< float > Vec3f
Definition: vec3.h:693
double dot(const Vector3 &w, const Vector3 &v)
Definition: vecmath.h:305
double length(const Vector3 &v)
Definition: vecmath.h:313
int cmp_val(const void *a, const void *b)
Definition: pointarray.cpp:80
int cmp_float(const void *a, const void *b)
Definition: pointarray.cpp:91
int cmp_axis_y(const void *a, const void *b)
Definition: pointarray.cpp:60
int cmp_axis_x(const void *a, const void *b)
Definition: pointarray.cpp:50
int cmp_axis_z(const void *a, const void *b)
Definition: pointarray.cpp:70
#define y(i, j)
Definition: projector.cpp:1516
#define x(i)
Definition: projector.cpp:1517