-
Flipping an image/array
Hi
I am trying to create an X-Window program that plots numerical data files from my fortran simulations.
Am pretty new to c++ so have been working from examples.
I can get X11 to plot my data, but the y-axis (vertical axis) in X11 is reflected. (i.e. it goes down the page/screen not up)
I would like to have my program plot the values properly, but am having trouble.
My idea is rather than messing with XLib commands and all that jazz, is to read in the data from the file in a different way, which flips the y-data. But so far my attempts fail. I have been trying to consider the way the data file is written, but can't see my error.
I would be very grateful if somebody could spot what I am doing wrong.
Code:
int nRead2DDataFromFile(FILE *fpIN, double **data, int nx, int ny)
{
int i, j;
double tp;
/* load data */
printf("\nLoading data....");
for(i=0; i<nx; i++)
for(j=0; j<ny; j++)
{
fscanf(fpIN, "%lf", &tp );
data[i][j] =tp;
}
printf("\nOK\n");
return 1;
}
-
You plot screenHeight-y rather than y to flip it vertically.
-
This is something I would be leery about doing while reading the file. I would gather, since you are talking about scientific data, that the numbers in the file are not screen coordinates, but actual x-y data with whatever units attach. You would want to read the data in as real data, and then deal with this issue when you turn "real data" into "screen coordinates". (For instance, if you modify the data now, you would not be able to do further transformations, like making a log-log plot or rescaling the axis.)
-
The numbers i am plotting are values of energy over an x-y plane.
I don't have x-y coordinates in the file at all since the data is calculated on a discrete grid.
So all I need to construct the data array is the sequence of values and the size of the system.
The former comes from the data file while the latter is given by nx and ny.
So the routine reads the string of numbers separated by spaces and maps it to an the data[i][j] array.
I tried several things:
data[i][ny-j-1] gives me horizontal (x) tears in the image
data[nx-i-1][j] flips the image but also tears it vertically in (y)
data[nx-i-1][ny-j-1] reflects the image in both x and y
The first give nonsense and the last one is not what i want.
But I am convinced it is possible. Maybe I'm wrong.
-
If you do nothing at all, just plot x,y, what do you actually get?
Is it correct except for being upside down?
-
I'm not sure what you mean by "tears in the image". I'm guessing you are generating a grid of (x,y) points and using the value from the file for color/size/similar?
The first one is exactly what you want -- you read across and up. If you're getting some sort of skew, that probably means that the number of numbers in the file doesn't match what your nx and ny are saying.
-
Yup. Leaving the X,Y as they are, gives me an image that is reflected in the horizontal. And it appears upside down.
And yup the tears are a result of some mismatch in numbers, but I can't figure out where.
I have attached the images generated by X11.
The system size is nx=180, ny=660.
-
If it's getting skewed, you should check your input data.
Can we assume that each row of data appears on a single line in the text file you're scanning from?
-
Nope. The data is stored sequentially i believe.
So it is not arranged in rows and columns.
Thus after getting through all of the 660 y values for one x line it will begin reading the next x line.
At least that is the way it should work.
-
I have attached a smaller nx=104 ny=180 file as an example.
-
Is there any way to verify the data by some other means?
Code:
$ wc 039.txt
4169 18720 295854 039.txt
It has 18720 words, which is 104*180.
It might be worth checking this
Code:
if ( fscanf(fpIN, "%lf", &tp ) == 1 ) {
data[i][j] =tp;
} else {
fprintf(stderr,"Failed at %d,%d\n", i, j );
}
How did you allocate the **data parameter before calling nRead2DDataFromFile
Did you get the right type sizes (and counts) in the malloc calls?
-
Okies Here is the memory allocation routine.
Code:
/***********************************************/
/* ALLOCATE MEMORY */
/***********************************************/
double **Malloc2Dd(int nx,int ny)
{
double **p;
int i;
p = (double **)malloc(nx*sizeof(double*));
if(!p) return NULL;
for(i=0; i<nx; i++)
{
p[i] =(double*)malloc(ny*sizeof(double));
if(!(p[i])) return NULL;
}
return p;
}
void free2Dd(double **p, int nx)
{
int i;
for(i=0; i<nx; i++)
{
free( p[i] );
}
free(p);
}
In MAIN the malloc and loading of data is called as:
Code:
/* ALLOCATE MEMORY */
data = Malloc2Dd(nx, ny);
if(!data)
{
fprintf(stderr,"not enough memory!\n");
exit(1);
}
/* LOAD DATA */
fpIN =fpOpenDataFile(argv[1]);
nRead2DDataFromFile(fpIN, data, nx,ny);
nCloseDataFile(fpIN);
-
Mmm, there doesn't seem to be anything wrong with the memory, or the approach to reading the data.
Are there any other uses of malloc in the same program?
You could also try to verify this as well.
Create a really simple program to just read the file and write it out again in a consistent format.
Code:
int main ( int argc, char *argv[] ) {
fpIn = fopen(argv[1],"r");
fpOut=fopen("normalised1.txt","w");
while ( fscanf(fpIN, "%lf", &tp ) == 1 ) fprintf(fpOut,"%f\n", tp);
fclose(fpIn);
fclose(fpOut);
return 0;
}
Similarly, write out the whole array (using two loops) after you have read the file to another (say normalised2.txt) and then compare.
-
I massaged the data to add \n after every 104 numbers (since that's what you said nx was) and fed it to gnuplot. Obviously I didn't do colors or anything like that, but: is this the image you're looking for? How does it compare with what you get out of yours (for this smaller data, I'm assuming the above was for a larger data set)?
(EDIT: I changed my mind about the colors.)
-
Hi. Thanks to all for helping.
I have been away from the real word doing synchrotron experiments. Still there actually. I will try and verify the things you have all suggested.
The file is upside down in gnuplot as well, for some reason.
Here is the plot of the small file.