EMAN2
xydata.cpp
Go to the documentation of this file.
1/*
2 * Author: Steven Ludtke, 04/10/2003 (sludtke@bcm.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#ifndef WIN32
33#include <sys/param.h>
34#else
35#include <windows.h>
36#define MAXPATHLEN (MAX_PATH*4)
37#endif
38#include "xydata.h"
39#include <algorithm>
40#include <cfloat>
41#include <cmath>
42#include <cstdio>
43#include "log.h"
44#include "exception.h"
45
46using namespace EMAN;
47
48XYData::XYData()
49 : ymin(FLT_MAX), ymax(-FLT_MAX), mean_x_spacing(1.0)
50{
51}
52
54{
55 if (data.size()==0) return;
56
57 std::sort(data.begin(), data.end());
58
59 ymin = FLT_MAX;
60 ymax = -FLT_MAX;
61
62 typedef vector < Pair >::const_iterator Ptype;
63 for (Ptype p = data.begin(); p != data.end(); p++) {
64 if (p->y > ymax) {
65 ymax = p->y;
66 }
67 if (p->y < ymin) {
68 ymin = p->y;
69 }
70 }
71
72 size_t n = data.size();
73 mean_x_spacing = (data[n - 1].x - data[0].x) / (float) n;
74}
75
76
77int XYData::read_file(const string & filename)
78{
79 FILE *in = fopen(filename.c_str(), "rb");
80 if (!in) {
81 throw FileAccessException(filename.c_str());
82// LOGERR("cannot open xydata file '%s'", filename.c_str());
83// return 1;
84 }
85
86 char buf[MAXPATHLEN];
87 char tmp_str[MAXPATHLEN];
88
89 while (fgets(buf, MAXPATHLEN, in)) {
90 if (buf[0] != '#') {
91 float x = 0;
92 float y = 0;
93
94 if (sscanf(buf, " %f%[^.0-9-]%f", &x, tmp_str, &y) != 3) {
95 break;
96 }
97 data.push_back(Pair(x, y));
98 }
99 }
100
101 fclose(in);
102 in = 0;
103
104 update();
105
106 return 0;
107}
108
109int XYData::write_file(const string & filename) const
110{
111 FILE *out = fopen(filename.c_str(), "wb");
112 if (!out) {
113 LOGERR("cannot open xydata file '%s' to write", filename.c_str());
114 return 1;
115 }
116
117 typedef vector < Pair >::const_iterator Ptype;
118 for (Ptype p = data.begin(); p != data.end(); p++) {
119 fprintf(out, "%1.6g\t%1.6g\n", p->x, p->y);
120 }
121
122 fclose(out);
123 out = 0;
124
125 return 0;
126}
127
128
129float XYData::calc_correlation(XYData * xy, float minx, float maxx) const
130{
131 size_t n = data.size();
132 float x0 = data[0].x;
133 float xn = data[n - 1].x;
134
135 if (maxx <= minx || minx >= xn || maxx <= x0) {
136 LOGERR("incorrect minx, maxx=%f,%f for this XYData range [%f,%f]",
137 minx, maxx, x0, xn);
138 return 0;
139 }
140
141 float scc = 0;
142 float norm1 = 0;
143 float norm2 = 0;
144
145 xy->update();
146 for (size_t i = 0; i < n; i++) {
147 float x = data[i].x;
148 if (x >= minx && x <= maxx && xy->is_validx(x)) {
149 float selfy = data[i].y;
150 float xyy = xy->get_yatx(x);
151
152 scc += selfy * xyy;
153 norm1 += selfy * selfy;
154 norm2 += xyy * xyy;
155 }
156 }
157
158 float result = scc / sqrt(norm1 * norm2);
159 return result;
160}
161
162void XYData::make_gauss(int n,float xmax, float width)
163{
164 set_size(n);
165 for (int i=0; i<n; i++) {
166 float x=i*xmax/n;
167 data[i].x=x;
168 data[i].y=exp(-x*x/(width*width));
169 }
170}
171
172float XYData::get_yatx(float x,bool outzero)
173{
174 if (data.size()==0 || mean_x_spacing==0) return 0.0;
175
176 int nx = (int) data.size();
177 // Do the range checking up front before we get into trouble
178 if (x<data[0].x) return outzero?0.0f:data[0].y;
179 if (x>data[nx-1].x) return outzero?0.0f:data[nx-1].y;
180
181 int s = (int) floor((x - data[0].x) / mean_x_spacing);
182 if (s>nx-1) s=nx-1;
183
184 // These deal with possibly nonuniform x values. A btree would be better, but this is simple
185 while (s>0 && data[s].x > x) s--;
186 while (s<(nx-1) && data[s + 1].x < x ) s++;
187 if (s>nx-2) return outzero?0.0f:data[nx-1].y;
188
189 float f = (x - data[s].x) / (data[s + 1].x - data[s].x);
190 float y = data[s].y * (1 - f) + data[s + 1].y * f;
191 return y;
192}
193
194float XYData::get_yatx_smooth(float x,int smoothing)
195{
196 if (data.size()==0) return 0.0;
197 if (data.size()==1) return data[0].y;
198 if (smoothing!=1) throw InvalidParameterException("Only smoothing==1 (linear) currently supported");
199
200 int nx = (int) data.size();
201
202 int s = nx/2;
203 if (mean_x_spacing>0) s=(int) floor((x - data[0].x) / mean_x_spacing);
204 if (s>nx-2) s=nx-2;
205 else if (s<0) s=0;
206 else {
207 // These deal with possibly nonuniform x values. A btree would be better, but this is simple, and there usually won't be THAT many points
208 while (s>0 && data[s].x > x) s--;
209 while (s<(nx-2) && data[s + 1].x < x ) s++;
210 }
211
212 float f = 0,y=0;
213 if (data[s + 1].x != data[s].x) {
214 f= (x - data[s].x) / (data[s + 1].x - data[s].x);
215 y = data[s].y * (1 - f) + data[s + 1].y * f;
216 }
217 else {
218 int s2=s;
219 while (data[s2].x==data[s].x) {
220 if (s2<nx-1) s2++;
221 if (s>0) s--;
222 if (s==0 &&s2==nx-1) return data[nx/2].y;
223 }
224 f= (x - data[s].x) / (data[s2].x - data[s].x);
225 y = data[s].y * (1 - f) + data[s2].y * f;
226
227 }
228// printf("%d %1.2f x %1.2f %1.2f %1.2f y %1.2f %1.2f\n",s,f,x,data[s].x,data[s+1].x,data[s].y,data[s+1].y);
229 return y;
230}
231
232// FIXME: clearly a slow way to do this
233void XYData::insort(float x, float y) {
234 data.push_back(Pair(x,y));
235 update();
236
237
238 // int nx = (int) data.size();
239// if (nx==0) { data.push_back(Pair(x,y)); return; }
240//
241// int s = (int) floor((x - data[0].x) / mean_x_spacing);
242// if (s>nx) s=nx;
243// else if (s<0) s=0;
244// else {
245// // These deal with possibly nonuniform x values. A btree would be better, but this is simple, and there usually won't be THAT many points
246// while (s>0 && data[s-1].x > x) s--;
247// while (s<nx && data[s].x <= x ) s++;
248// }
249// data.insert(data.begin()+s,Pair(x,y));
250}
251
252// data must be sorted before this will work
254 float acnt=1.0;
255 for (std::vector<Pair>::iterator it = data.begin() ; it+1 < data.end(); ++it) {
256 while (it+1<data.end() && it->x==(it+1)->x) {
257// printf("%d\t%d\t%1.0f\t%f\t%f\n",it-data.begin(),data.end()-it,acnt,it->x,(it+1)->x);
258 it->y+=(it+1)->y;
259 acnt+=1.0;
260 data.erase(it+1);
261 }
262 if (acnt>1.0) {
263 it->y/=acnt;
264 acnt=1.0;
265 }
266 }
267}
268
269void XYData::set_xy_list(const vector<float>& xlist, const vector<float>& ylist)
270{
271 if(xlist.size() != ylist.size()) {
272 throw InvalidParameterException("xlist and ylist size does not match!");
273 }
274
275 for(unsigned int i=0; i<xlist.size(); ++i) {
276 data.push_back(Pair(xlist[i], ylist[i]));
277 }
278}
279
280void XYData::set_size(size_t n)
281{
282 data.resize(n, Pair(0.0f, 0.0f));
283}
284
285vector<float> XYData::get_state() const {
286 vector<float> list;
287 vector<Pair>::const_iterator cit;
288 for(cit=data.begin(); cit!=data.end(); ++cit) {
289 list.push_back( (*cit).x);
290 list.push_back( (*cit).y);
291 }
292
293 return list;
294
295}
296
297void XYData::set_state(vector<float> list) {
298 if(list.size()%2==1) {
299 throw InvalidParameterException("Invalid pickled data");
300 }
301
302 data.clear();
303 for(unsigned int i=0; i<list.size(); i+=2) {
304 data.push_back(Pair(list[i], list[i+1]));
305 }
306
307 update();
308}
309
310vector<float> XYData::get_xlist() const
311{
312 vector<float> xlist;
313 vector<Pair>::const_iterator cit;
314 for(cit=data.begin(); cit!=data.end(); ++cit) {
315 xlist.push_back( (*cit).x);
316 }
317
318 return xlist;
319}
320
321vector<float> XYData::get_ylist() const
322{
323 vector<float> ylist;
324 vector<Pair>::const_iterator cit;
325 for(cit=data.begin(); cit!=data.end(); ++cit) {
326 ylist.push_back( (*cit).y);
327 }
328
329 return ylist;
330}
XYData defines a 1D (x,y) data set.
Definition: xydata.h:47
void make_gauss(int n, float xmax, float width)
Definition: xydata.cpp:162
void update()
Definition: xydata.cpp:53
vector< Pair > data
Definition: xydata.h:156
float calc_correlation(XYData *xy, float minx, float maxx) const
Definition: xydata.cpp:129
float get_yatx(float x, bool outzero=true)
Definition: xydata.cpp:172
float get_yatx_smooth(float x, int smoothing)
Definition: xydata.cpp:194
void insort(float x, float y)
Definition: xydata.cpp:233
int write_file(const string &filename) const
Definition: xydata.cpp:109
void dedupx()
Definition: xydata.cpp:253
float mean_x_spacing
Definition: xydata.h:159
float ymin
Definition: xydata.h:157
void set_xy_list(const vector< float > &xlist, const vector< float > &ylist)
Definition: xydata.cpp:269
float ymax
Definition: xydata.h:158
bool is_validx(float x) const
Definition: xydata.h:146
vector< float > get_xlist() const
Definition: xydata.cpp:310
vector< float > get_state() const
Definition: xydata.cpp:285
void set_size(size_t n)
Definition: xydata.cpp:280
int read_file(const string &filename)
Definition: xydata.cpp:77
vector< float > get_ylist() const
Definition: xydata.cpp:321
void set_state(vector< float >)
Definition: xydata.cpp:297
EMData * sqrt() const
return square root of current image
#define InvalidParameterException(desc)
Definition: exception.h:361
#define FileAccessException(filename)
Definition: exception.h:187
#define LOGERR
Definition: log.h:51
E2Exception class.
Definition: aligner.h:40
#define y(i, j)
Definition: projector.cpp:1516
#define x(i)
Definition: projector.cpp:1517