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

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

Again, a large number of changes to commit:
Cubes/cubes.cc -- added destructors for DataArray?, Image and Cube.

fixed typo in Image::saveArray.

Cubes/cubes.hh -- destructors changed.
Cubes/drawMomentCutout.cc -- Added call to drawBlankEdges, which required

changing how the image array was set up. Now make
use of an isGood array.

Cubes/Merger?.cc -- made new functions mergeList and finaliseList that do a lot

of the work, acting just on the Detection vector.
Cube::Merger() now is mostly a front-end to these primitive
functions.

Cubes/ReadAndSearch?.cc -- new function that reads in FITS array piecemeal and

searches in each piece. For large files that are too
big to read in all at once.

param.cc -- added an explicit copy constructor to Param class.
Detection/spectrumDetect.cc -- fixed typos (pix. instead of pix->)
Detection/outputDetection.cc -- added test to outputDetectionText for number

of columns in ColSet?

Detection/columns.cc -- added push_back statements that had been left out.
Detection/detection.hh -- added prototypes for new merging functions
param.hh -- prototype for copy constructor of Param.

File size: 7.2 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]=0.;
56
57  bool *isGood = new bool[size*size];
58  for(int z=zmin; z<=zmax; z++){
59    for(int x=xmin; x<=xmax; x++){
60      for(int y=ymin; y<=ymax; y++){
61        isGood[(y-ymin) * size + (x-xmin)] = !this->isBlank(x,y,z);
62      }
63    }
64  }
65
66  int imPos,cubePos;
67  for(int z=zmin; z<=zmax; z++){
68    for(int x=xmin; x<=xmax; x++){
69      for(int y=ymin; y<=ymax; y++){
70
71        imPos = (y-ymin) * size + (x-xmin);
72        cubePos = (z)*this->axisDim[0]*this->axisDim[1]+(y)*this->axisDim[0]+(x);
73
74        if(   (x<0)||(x>=this->axisDim[0])  // if outside the boundaries
75           || (y<0)||(y>=this->axisDim[1])  // if outside the boundaries
76           || !isGood[imPos] )              // if not blank
77          image[imPos] = blankVal;
78        else
79          image[imPos] += this->array[cubePos];
80
81      }
82    }
83  }
84
85  for(int i=0;i<size*size;i++){
86    // if there is some signal on this pixel, normalise by the velocity width
87    if(isGood[i]) image[i] /= float(zmax-zmin+1);
88  }
89
90  // now work out the greyscale display limits,
91  //   excluding blank pixels where necessary.
92  float z1,z2,median,madfm;
93  int ct=0;
94  while(!isGood[ct]) ct++; // move to first non-blank pixel
95  z1 = z2 = image[ct];
96  for(int i=1;i<size*size;i++){
97    if(isGood[i]){
98      if(image[i]<z1) z1=image[i];
99      if(image[i]>z2) z2=image[i];
100    }
101  }
102
103  float tr[6] = {xmin-1,1.,0.,ymin-1,0.,1.};
104
105  cpgswin(xmin-0.5,xmax-0.5,ymin-0.5,ymax-0.5);
106  cpggray(image, size, size, 1, size, 1, size, z1, z2, tr);
107
108  delete [] image;
109
110  int ci;
111  cpgqci(&ci);
112
113  // Draw the border of the BLANK region, if there is one...
114  cpgsci(6);
115  drawBlankEdges(image, size, size, par);
116
117  // Draw the borders around the object
118  cpgsci(4);
119  cpgsfs(2);
120  if(this->par.drawBorders())
121    object.drawBorders(xmin,ymin);
122  else
123    cpgrect(object.getXmin()-xmin+0.5,object.getXmax()-xmin+1.5,
124            object.getYmin()-ymin+0.5,object.getYmax()-ymin+1.5);
125  /*
126    To get the borders localised correctly, we need to subtract (xmin-1) from the
127    X values. We then subtract 0.5 for the left hand border (to place it on the
128    pixel border), and add 0.5 for the right hand border. Similarly for y.
129  */
130  cpgsci(ci);
131
132  if(this->head.isWCS()){
133    // Now draw a tick mark to indicate size -- 15 arcmin in length
134    this->drawScale(xmin+2.,ymin+2.,object.getZcentre(),0.25);
135  }
136
137  cpgsci(1);
138  cpgswin(x1,x2,y1,y2);
139
140  if(!flagBlankPix){
141    this->par.setFlagBlankPix(flagBlankPix);
142    this->par.setBlankKeyword(blankKW);
143    this->par.setBzeroKeyword(bzeroKW);
144    this->par.setBscaleKeyword(bscaleKW);
145  }
146
147}
148
149void Cube::drawScale(float xstart, float ystart, float channel, float scaleLength)
150{
151  /**
152   *  Cube::drawScale(xstart, ystart, channel, scaleLength)
153   *
154   *   A routine to draw a scale bar on a (pre-existing) PGPlot image.
155   *   It uses an iterative technique to move from the given start position
156   *    (xstart,ystart) along the positive x-direction so that the length is
157   *    within 1% of the requested value scaleLength.
158   *   The parameter "channel" is required for the wcslib calculations, as the
159   *    positions could theoretically change with channel.
160   */
161
162  double *pix1   = new double[3];
163  double *pix2   = new double[3];
164  double *world1 = new double[3];
165  double *world2 = new double[3];
166  pix1[0] = pix2[0] = xstart + this->par.getXOffset();
167  pix1[1] = pix2[1] = ystart + this->par.getYOffset();
168  pix1[2] = pix2[2] = channel;
169  this->head.pixToWCS(pix1,world1);
170
171  double angSep=0.;
172  bool keepGoing=false;
173  float step = 1.;
174  do{
175    if(angSep>scaleLength){
176      pix2[0] -= step;
177      step /= 2.;
178    }
179    pix2[0] += step;
180    this->head.pixToWCS(pix2,world2);
181    angSep = angularSeparation(world1[0],world1[1],world2[0],world2[1]);
182  }while((fabs(angSep-scaleLength)/scaleLength)>0.01); // look for 1% change
183
184  float tickpt1 = pix1[0] - this->par.getXOffset();
185  float tickpt2 = pix2[0] - this->par.getXOffset();
186  float tickpt3 = ystart;
187  int colour;
188  cpgqci(&colour);
189  cpgsci(2);
190  int thick;
191  cpgqlw(&thick);
192  cpgslw(3);
193  cpgerrx(1,&tickpt1,&tickpt2,&tickpt3,2.);
194  cpgslw(thick);
195
196  std::stringstream text;
197  text << scaleLength*60 << "'";
198  float size,xch,ych;
199  cpgqch(&size);
200  cpgsch(0.4);
201  cpgqcs(4,&xch,&ych); // get the character size in world coords
202  cpgptxt((tickpt1+tickpt2)/2., ystart+ych, 0, 0.5, text.str().c_str());
203  cpgsch(size);
204  cpgsci(colour);
205
206  delete [] pix1,pix2;
207  delete [] world1,world2;
208
209
210}
211
212
213void Detection::drawBorders(int xoffset, int yoffset)
214{
215
216  float x1,x2,y1,y2;
217  cpgqwin(&x1,&x2,&y1,&y2);
218  int xsize = int(x2 - x1) + 1;
219  int ysize = int(y2 - y1) + 1;
220
221  bool *isObj = new bool[xsize*ysize];
222  for(int i=0;i<xsize*ysize;i++) isObj[i]=false;
223  for(int i=0;i<this->pix.size();i++)
224    isObj[ (this->pix[i].getY()-yoffset)*xsize + (this->pix[i].getX()-xoffset) ] = true;
225 
226
227  cpgswin(0,xsize-1,0,ysize-1);
228  for(int x=this->xmin; x<=this->xmax; x++){
229    // for each column...
230    for(int y=1;y<ysize;y++){
231      int current = y*xsize + (x-xoffset);
232      int previous = (y-1)*xsize + (x-xoffset);
233      if((isObj[current]&&!isObj[previous])||(!isObj[current]&&isObj[previous])){
234        cpgmove(x-xoffset+0, y+0);
235        cpgdraw(x-xoffset+1, y+0);
236      }
237    }
238  }
239  for(int y=this->ymin; y<=this->ymax; y++){
240    // now for each row...
241    for(int x=1;x<xsize;x++){
242      int current = (y-yoffset)*xsize + x;
243      int previous = (y-yoffset)*xsize + x - 1;
244      if((isObj[current]&&!isObj[previous])||(!isObj[current]&&isObj[previous])){
245        cpgmove(x+0, y-yoffset+0);
246        cpgdraw(x+0, y-yoffset+1);
247      }
248    }
249  }
250  cpgswin(x1,x2,y1,y2);
251 
252  delete [] isObj;
253
254}   
Note: See TracBrowser for help on using the repository browser.