source: trunk/src/Cubes/drawMomentCutout.cc @ 135

Last change on this file since 135 was 135, checked in by Matthew Whiting, 18 years ago

Corrected a bug that led to image cutouts not being drawn correctly when the
blank pixel value was not defined (ie. flagBlankPix was false or keywords
weren't in header). Now inserts a temporary blank pixel value so that the
z-scaling is done properly.

File size: 7.0 KB
Line 
1#include <iostream>
2#include <sstream>
3#include <cpgplot.h>
4#include <math.h>
5#include <wcs.h>
6#include <Cubes/cubes.hh>
7#include <Utils/utils.hh>
8
9void Cube::drawMomentCutout(Detection &object)
10{
11  /**
12   *  Cube::drawMomentCutout(object)
13   *
14   *   A routine to draw the 0th moment for the given detection
15   *    using the flux given by the pixel array in the Cube.
16   *   The 0th moment is constructed by adding the flux of each
17   *    pixel within the full extent of the object (this may be more
18   *    pixels than were actually detected in the object)
19   *   A tick mark is also drawn to indicate angular scale (but only
20   *    if the WCS for the Cube is valid).
21   */
22
23  bool flagBlankPix = this->par.getFlagBlankPix();
24  int blankKW;
25  float bscaleKW,bzeroKW,blankVal;
26  if(!flagBlankPix){
27    this->par.setFlagBlankPix(true);
28    blankKW =this->par.getBlankKeyword();
29    bscaleKW=this->par.getBscaleKeyword();
30    bzeroKW =this->par.getBzeroKeyword();
31    this->par.setBlankKeyword(1);
32    this->par.setBzeroKeyword(0.);
33    this->par.setBscaleKeyword(-100.1234); 
34    blankVal = this->par.getBscaleKeyword();
35  }
36  else blankVal = this->par.getBlankPixVal();
37
38  float x1,x2,y1,y2;
39  cpgqwin(&x1,&x2,&y1,&y2);
40
41  long size = (object.getXmax()-object.getXmin()+1);
42  if(size<(object.getYmax()-object.getYmin()+1))
43    size = object.getYmax()-object.getYmin()+1;
44  size += 20;
45
46
47  long xmin = (object.getXmax()+object.getXmin())/2 - size/2 + 1;
48  long xmax = (object.getXmax()+object.getXmin())/2 + size/2;
49  long ymin = (object.getYmax()+object.getYmin())/2 - size/2 + 1;
50  long ymax = (object.getYmax()+object.getYmin())/2 + size/2;
51  long zmin = object.getZmin();
52  long zmax = object.getZmax();
53
54  float *image = new float[size*size];
55  for(int i=0;i<size*size;i++) image[i]=blankVal;
56
57  int imPos,cubePos;
58  float val;
59  for(int z=zmin; z<=zmax; z++){
60    for(int x=xmin; x<=xmax; x++){
61      for(int y=ymin; y<=ymax; y++){
62        imPos = (y-ymin) * size + (x-xmin);
63        cubePos = (z)*this->axisDim[0]*this->axisDim[1]+(y)*this->axisDim[0]+(x);
64        if((x<0)||(x>=this->axisDim[0])||(y<0)||(y>=this->axisDim[1])) // if outside the boundaries
65          image[imPos] = blankVal;
66        else{
67          val = this->array[cubePos];
68          if (!this->par.isBlank(val)) // if pixel's not blank
69            image[imPos] += val;
70        }
71      }
72    }
73  }
74
75  for(int i=0;i<size*size;i++){
76    if(!this->par.isBlank(image[i])){ // if there is some signal on this pixel
77      image[i]-=blankVal;   // remove the starting value so we just have the signal
78      image[i] /= float(zmax-zmin+1); // normalise by the velocity width
79    }
80  }
81
82  // now work out the greyscale display limits, excluding blank pixels where necessary.
83  float z1,z2,median,madfm;
84  int ct=0;
85  while(this->par.isBlank(image[ct])) ct++; // move to first non-blank pixel
86  z1 = z2 = image[ct];
87  for(int i=1;i<size*size;i++){
88    if(!this->par.isBlank(image[i])){
89      if(image[i]<z1) z1=image[i];
90      if(image[i]>z2) z2=image[i];
91    }
92  }
93
94  float tr[6] = {xmin-1,1.,0.,ymin-1,0.,1.};
95
96  cpgswin(xmin-0.5,xmax-0.5,ymin-0.5,ymax-0.5);
97  cpggray(image, size, size, 1, size, 1, size, z1, z2, tr);
98
99  delete [] image;
100
101  // Draw the borders around the object
102  int ci;
103  cpgqci(&ci);
104  cpgsci(4);
105  cpgsfs(2);
106  if(this->par.drawBorders())
107    object.drawBorders(xmin,ymin);
108  else
109    cpgrect(object.getXmin()-xmin+0.5,object.getXmax()-xmin+1.5,
110            object.getYmin()-ymin+0.5,object.getYmax()-ymin+1.5);
111  /*
112    To get the borders localised correctly, we need to subtract (xmin-1) from the
113    X values. We then subtract 0.5 for the left hand border (to place it on the
114    pixel border), and add 0.5 for the right hand border. Similarly for y.
115  */
116  cpgsci(ci);
117
118  if(this->head.isWCS()){
119    // Now draw a tick mark to indicate size -- 15 arcmin in length
120    this->drawScale(xmin+2.,ymin+2.,object.getZcentre(),0.25);
121  }
122
123  cpgsci(1);
124  cpgswin(x1,x2,y1,y2);
125
126  if(!flagBlankPix){
127    this->par.setFlagBlankPix(flagBlankPix);
128    this->par.setBlankKeyword(blankKW);
129    this->par.setBzeroKeyword(bzeroKW);
130    this->par.setBscaleKeyword(bscaleKW);
131  }
132
133}
134
135void Cube::drawScale(float xstart, float ystart, float channel, float scaleLength)
136{
137  /**
138   *  Cube::drawScale(xstart, ystart, channel, scaleLength)
139   *
140   *   A routine to draw a scale bar on a (pre-existing) PGPlot image.
141   *   It uses an iterative technique to move from the given start position
142   *    (xstart,ystart) along the positive x-direction so that the length is
143   *    within 1% of the requested value scaleLength.
144   *   The parameter "channel" is required for the wcslib calculations, as the
145   *    positions could theoretically change with channel.
146   */
147
148  double *pix1   = new double[3];
149  double *pix2   = new double[3];
150  double *world1 = new double[3];
151  double *world2 = new double[3];
152  pix1[0] = pix2[0] = xstart + this->par.getXOffset();
153  pix1[1] = pix2[1] = ystart + this->par.getYOffset();
154  pix1[2] = pix2[2] = channel;
155  this->head.pixToWCS(pix1,world1);
156
157  double angSep=0.;
158  bool keepGoing=false;
159  float step = 1.;
160  do{
161    if(angSep>scaleLength){
162      pix2[0] -= step;
163      step /= 2.;
164    }
165    pix2[0] += step;
166    this->head.pixToWCS(pix2,world2);
167    angSep = angularSeparation(world1[0],world1[1],world2[0],world2[1]);
168  }while((fabs(angSep-scaleLength)/scaleLength)>0.01); // look for 1% change
169
170  float tickpt1 = pix1[0] - this->par.getXOffset();
171  float tickpt2 = pix2[0] - this->par.getXOffset();
172  float tickpt3 = ystart;
173  int colour;
174  cpgqci(&colour);
175  cpgsci(2);
176  int thick;
177  cpgqlw(&thick);
178  cpgslw(3);
179  cpgerrx(1,&tickpt1,&tickpt2,&tickpt3,2.);
180  cpgslw(thick);
181
182  std::stringstream text;
183  text << scaleLength*60 << "'";
184  float size,xch,ych;
185  cpgqch(&size);
186  cpgsch(0.4);
187  cpgqcs(4,&xch,&ych); // get the character size in world coords
188  cpgptxt((tickpt1+tickpt2)/2., ystart+ych, 0, 0.5, text.str().c_str());
189  cpgsch(size);
190  cpgsci(colour);
191
192  delete [] pix1,pix2;
193  delete [] world1,world2;
194
195
196}
197
198
199void Detection::drawBorders(int xoffset, int yoffset)
200{
201
202  float x1,x2,y1,y2;
203  cpgqwin(&x1,&x2,&y1,&y2);
204  int xsize = int(x2 - x1) + 1;
205  int ysize = int(y2 - y1) + 1;
206
207  bool *isObj = new bool[xsize*ysize];
208  for(int i=0;i<xsize*ysize;i++) isObj[i]=false;
209  for(int i=0;i<this->pix.size();i++)
210    isObj[ (this->pix[i].getY()-yoffset)*xsize + (this->pix[i].getX()-xoffset) ] = true;
211 
212
213  cpgswin(0,xsize-1,0,ysize-1);
214  for(int x=this->xmin; x<=this->xmax; x++){
215    // for each column...
216    for(int y=1;y<ysize;y++){
217      int current = y*xsize + (x-xoffset);
218      int previous = (y-1)*xsize + (x-xoffset);
219      if((isObj[current]&&!isObj[previous])||(!isObj[current]&&isObj[previous])){
220        cpgmove(x-xoffset+0, y+0);
221        cpgdraw(x-xoffset+1, y+0);
222      }
223    }
224  }
225  for(int y=this->ymin; y<=this->ymax; y++){
226    // now for each row...
227    for(int x=1;x<xsize;x++){
228      int current = (y-yoffset)*xsize + x;
229      int previous = (y-yoffset)*xsize + x - 1;
230      if((isObj[current]&&!isObj[previous])||(!isObj[current]&&isObj[previous])){
231        cpgmove(x+0, y-yoffset+0);
232        cpgdraw(x+0, y-yoffset+1);
233      }
234    }
235  }
236  cpgswin(x1,x2,y1,y2);
237 
238  delete [] isObj;
239
240}   
Note: See TracBrowser for help on using the repository browser.