PRO qImage_cw_ZEllipse, state, box, exclude_box=exclude_box, $ noupdate=noupdate, zval=zval, zpix=zpix, wedge=wedge, $ centroid=centroid, $ image=image, img_center=img_center, img_prorate=img_prorate ;+ ; NAME: ; qImage_cw_ZEllipse ; PURPOSE: ; Calculates the Z-values min, max, average and standard deviations ; for an ellipse in the image plane ; CATEGORY: ; Compound widget qImage_cw ; CALLING SEQUENCE: ; qImage_cw_ZEllipse, state, box, zval=zval ; INPUTS: ; state array[1]; type: structure ; qImage_cw state structure ; OPTIONAL INPUT PARAMETERS: ; box array[2,2]; type:float ; limiting values in phase angle and radius of the wedge ; in the form [[angle1,radius1],[angle2,radius2]]. ; Angle1 and angle2 are in radians between [-!pi,+!pi]. ; The wedge runs counterclockwise from 'angle1' to 'angle2' ; over less than 180 degrees: either angle2 > angle1 with ; angle2-angle1 < !pi or angle2 < angle1 with ; angle+2*!pi-angle1 < !pi. Always radius1 < radius2. ; ; If p_box is not specified then the wedge specified in ; the qImage_cw widget is used. ; ; exclude_box=exclude_box ; array[2,2; type: float ; another wedge specified in the same way as p_box. ; This wedge should lie completely inside the p_box wedge. ; If this box is specified than the return values refer to the ; area in between the two wedges. This box is passed unmodified to ; Inside_Wedge. ; !!!!! If exclude_p_box is set then also /noupdate should be set: ; if /noupdate NOT set then p_box will be slightly modified, and ; exclude_p_box won't. ; ; /noupdate Only used if polar_box is specified. This argument is passed to ; qImage_cw_Wedge where it bypasses a call to qImage_cw_Box ; (which updates the position widgets). ; ; OPTIONAL OUTPUT PARAMETERS: ; zval array[4]; float ; minimum, maximum, average and standard deviation across the wedge ; if the wedge is empty then 4 x !values.f_nan is returned ; zpix scalar; type: float or integer ; # pixels in wedge (non-integer values result from pro-rating) ; if the wedge is empty then zero is returned ; wedge array[2,n]; type: float ; boundary of wedge as a closed array (first=last point) ; in rectangular (pixel) coordinates (output from qImage_cw_Wedge) ; centroid array[2]; type: float ; centroid of the wedge ; if the wedge is empty then 2 x !values.f_nan is returned ; INCLUDE: @compile_opt.pro ; On error, return to caller ; CALLS: ; qImage_cw_Wedge, qImage_cw_BoxImage, qImage_cw_Box, Inside_Wedge ; SuperArray, CenterOfMass, gridgen, IsType ; PROCEDURE: ; > qImage_cw_Wedge is used to limit the part of the image to be included to the smallest ; square box including the whole wedge. ; > Inside_Wedge applied to pixel centers (integer coordinate values) is used to find ; pixels entirely lying inside the wedge. ; > A similar test on pixel corners (half-integer coordinate values) in combination with ; the previous test is used to locate pixels which lie across the wedge boundary. ; > These last group of pixels is subdivided in a 10x10 array of subpixels. A test on the ; centers on these subpixels is used to prorate the pixels with the ratio of subpixels ; inside the wedge and total number of pixels. ; > The prorating can be switched of by setting the user value of state.wid_prorate to 0. ; > Prorating is done only for the average value. Minimum, maximum and standard deviation ; are calculated with all pixels with centers inside the wedge weighted the same. ; STATE INFO USED: ; widget_control, state.wid_prorate, get_uvalue=set ; MODIFICATION HISTORY: ; FEB-2000, Paul Hick (UCSD/CASS; pphick@ucsd.edu) ;- from_widget = IsType(image,/undefined) zpix = 0 zval = replicate(!values.f_nan,4) centroid = replicate(!values.f_nan,2) b_box = qImage_cw_Wedge(state, p_box, wedge=wedge, noupdate=noupdate, img_center=img_center) CASE from_widget OF 0: sub_img = image[b_box[0]:b_box[2],b_box[1]:b_box[3]] 1: BEGIN IF NOT qImage_cw_BoxImage(state, b_box, sub_img=sub_img, sub_box=sub_box) THEN BEGIN message, /info, 'empty wedge' RETURN ENDIF b_box = sub_box qImage_cw_Box, state, img_center, /center widget_control, /hourglass END ENDCASE cntr = img_center-b_box[0:1] nx = b_box[2]-b_box[0]+1 ny = b_box[3]-b_box[1]+1 ; Rectangular pixel coordinates relative to cntr r_img = gridgen([nx,ny],origin=cntr) ; Convert the pixel centers to polar coordinates ; (phi is returned between -!pi and !pi) inside_centers = Inside_Wedge(p_box, cv_coord(from_rect=r_img, /to_polar), exclude_p_box=exclude_p_box) inside_centers = reform([inside_centers], nx, ny, /overwrite) ; Convert the pixel corners to polar coordinates r = gridgen([nx,ny]+1,origin=cntr+0.5) inside = Inside_Wedge(p_box, cv_coord(from_rect=r, /to_polar), exclude_p_box=exclude_p_box) inside = reform([inside],nx+1,ny+1,/overwrite) ; Zero entries in 'clear_inside' identify pixels that bridge the wedge boundary ; These pixels need to be prorated clear_inside = inside_centers EQ inside[0:nx-1,0:ny-1] AND $ inside_centers EQ inside[1:nx ,0:ny-1] AND $ inside_centers EQ inside[0:nx-1,1:ny ] AND $ inside_centers EQ inside[1:nx ,1:ny ] ; Determine all pixels that lie completely inside the wedge clear_across = where(clear_inside EQ 0B, n_across) clear_inside = where(clear_inside EQ 1B AND inside_centers EQ 1B, n_inside) CASE from_widget OF 0: set = img_prorate[2] 1: widget_control, state.wid_prorate[2], get_uvalue=set ENDCASE n_across = set*n_across frac = fltarr(nx, ny) IF n_inside GT 0 THEN frac[clear_inside] = 1. IF n_across GT 0 THEN BEGIN ; The prorating is done by dividing each pixel on the boundary ; in a group of 10x10 subpixels CASE from_widget OF 0: BEGIN mx = img_prorate[0] my = img_prorate[1] END 1: BEGIN widget_control, state.wid_prorate[0], get_value=mx widget_control, state.wid_prorate[1], get_value=my END ENDCASE ; x,y coordinates of subpixels between -0.5,+0.5 r = [mx,my] r_small = gridgen( r, range=(0.5*[-1,1])#((r-1.)/r) ) ; x,y coordinate relative to origin of pixels to be prorated r = r_img[*,clear_across] ; Set up an mx x my x n_across array for all subpixels in all pixels to be prorated r = SuperArray(r, mx*my, after=1)+SuperArray(r_small,n_across,/trail) r = reform(r,2,mx*my*n_across, /overwrite) ; Convert the subpixel centers to polar coordinates ; Determine which subpixels lie inside the wedge r = Inside_Wedge(p_box, cv_coord(from_rect=r, /to_polar), exclude_p_box=exclude_p_box) r = reform(r, mx*my, n_across, /overwrite) r = total(r,1)/(mx*my) ; Fraction of subpixels lying inside the wedge frac[clear_across] = r ENDIF zpix = total(frac) IF zpix GT 0 THEN BEGIN r = where(frac NE 0, nr) zmin = min(sub_img[r], max=zmax, /nan) IF nr GT 1 THEN zstd = stddev(sub_img[r], /nan) ELSE zstd = 0. frac = frac/total(frac) zval = frac*sub_img zavg = total(zval, /nan) centroid = b_box[0:1]+CenterOfMass(zval) zval = [zmin, zmax, zavg, zstd] ENDIF RETURN & END