function corflag,datain,boardnum,pol,val=val,zero=zero,mask=mask,applymask=applymask ;program to interactively flag some bad data and remask with interpolated ;values. Data is returned to outdata, which is identical to the original ;data, in dimensions, parameters etc.... but without bad data! ; ;Data can be replaced with a specific value, which can be passed in with ;'val', or can be set to zero, indicated by the /zero switch. In the absence ;of these, the default is to make a linar interpolation (in the frequency ;direction only) across the band either side of the region to be ;flagged. The interpolation takes the mean of data which is located a ;distance equal to HALF THE SIZE OF THE FLAGGED REGION ON EITHER ;SIDE. i.e. for a flagged region across x1 to x2, data is interpolated from ;the mean of data from x0-(x1-x0)/2 to x1+(x1-x0)/2. There is some error ;checking for the available data for this, but not much, if you try to flag ;data too close to the edge of the band, or the flagged area is too large, ;it might barf. ; ;Some information is displayed on the screen plot, such as the x and y (for ;greyscale), otherwise it is x, y(x) for a plot. The value of the pixel at ;x,y or at y(x) is shown also. ; ;A mask of the flagged area (either a 1d or 2d set) can be returned by ;setting 'MASK'. This is helpful for later re-processing, or for doing ;repetitive masking. if usemask=mask is set, then the mask supplied in ;usemask is applied without going to the interactive stage. N.B. Applying an ;existing mask will only zero the data, or set it to a user-specified value, ;i.e. it does not determine an average in the way that the interactive ;approach does. To make it do this is time consuming and for me, not ;useful. Feel free to make the change if you wish. ; ;Note, this is a crappy script. It uses 'goto'. Sorry, I am too lazy to code ;it properly, I have data to reduce.. but now I can to it without ;interference spikes!!! yeah me. ; ;SYNTAX: OUTDATA=CORLFAG(DATA,BOARDNUM,POL,VAL=VAL,/ZERO,MASK=MASK,/APPLYMASK=APPLYMASK) ; DATA - THE DATASET ; BOARDNUM - SELECT THE BOARD TO FLAG ; POL - CHOOSE THE POL TO FLAG (1,2) ; VAL - THE VALUE WITH WHICH TO REPLACE FLAGGED DATA, THE DEFAULT IS ; THE MEAN OF THE DATASET AROUND THE FLAGGED REGION. ; ZERO - REPLACE FLAGGED DATA WITH ZEROS ; MASK - SET THIS VARIABLE NAME, THE CREATED MASK IS RETURNED HERE. ; APPLYMASK - PASS IN A PREVIOUSLY CREATED MASK HERE, THIS SKIPS THE ; INTERACTIVE PART AND JUST APPLIES THE MASK. ;EXAMPLE: ;TO DO A ONE-OFF, INTERACTIVE DESPIKE: ;despiked=corflag(spike_data,1,1) ; this displays the first board and ;first polarisation of data 'spike' in an interactive plot, or greyscale for ;flagging. the flagged data is by default, set to an average. (use val=10 to replace ;to 10, or /zero to force it to zero). To do all boards and pols, it is ;necessary to do this recursively i.e. ;despiked=corflag(spike_data,1,1) ;despiked=corflag(despike_data,1,2) ;despiked=corflag(despike_data,2,1) ;despiked=corflag(despike_data,1,2) ;despiked=corflag(despike_data,3,1) ;despiked=corflag(despike_data,3,2) ;despiked=corflag(despike_data,4,1) ;despiked=corflag(despike_data,4,2) ; ;The flagging can be saved to a variable set by /mask. This variable is ;passed by reference OUT of the function and can be therefore used by sucessive ;iterations of CORFLAG. ; ;Once a mask has been created, it can be used for any other datasets, ;without the interaction with /applymask: ;despiked=corflag(spike,1,1,applymask=my_mask). ; ;In this case, the setting of board and polarisation number are irrelevant, ;but must be valid numbers anyhow (I couldn't be bothered coding this in a ;more intelligent way just now). data=datain oldmulti=!p.multi !p.multi=0 ans=strarr(1) ; to get later queries from screen !mouse.button=0 boardnum=boardnum-1 ; readjust these numbers for stupid IDL indexing pol=pol-1 if boardnum+1 gt n_tags(data) or boardnum+1 le 0 then begin print,"That board number does not exist in this dataset" return,0 endif datasize=size(data.(boardnum).d) ;Okay, so check for dimensions of data ;If there is three, then there the data probably is a series of spectra ;dumps, of each pol. If there is only two, then there is probably only two ;spectra, one for each pol. if there is one dimension, then it is only one ;spectra, and one pol. case datasize(0) of ; how many dimensions.. and how should it be displayed? 1:begin npols=1 xsize=datasize(1) ysize=1 if pol+1 gt npols or pol+1 le 0 then begin print,"There are not that number of pols for this data" print,strcompress(string(npols)+" pols detected") return,0 endif im=data.(boardnum).d dim=1 end 2:begin npols=2 xsize=datasize(1) ysize=1 if pol+1 gt npols or pol+1 le 0 then begin print,"There are not that number of pols for this data" print,strcompress(string(npols)+" pols detected") return,0 endif im=data.(boardnum).d(*,pol) dim=1 end 3:begin npols=2 xsize=datasize(1) ysize=datasize(3) if pol+1 gt npols or pol+1 le 0 then begin print,"There are not that number of pols for this data" print,strcompress(string(npols)+" pols detected") return,0 endif im=data.(boardnum).d(*,pol,*) dim=2 end else: begin print,"The format for this data is not understood" return,0 end endcase nbrds=n_tags(data) ;Ok, if the mask is supplied, apply it., if keyword_set(applymask) then begin if keyword_set(mask) then begin print,"Cannot create AND apply a mask." print,"Use mask=mask to create a mask first" return,0 endif appmask_size=size(applymask.(boardnum)(*,*,pol)) if appmask_size(0) eq 2 then mask_xsize=appmask_size(1) if total(size(data.(boardnum).d) eq size(applymask.(boardnum))) eq 0 $ or n_tags(applymask) ne nbrds then begin print,"The mask has different dimensions to the dataset" return,0 endif if not keyword_set(val) then val=0. for i=0,nbrds-1 do begin data.(i).d=data.(i).d*(applymask.(i) eq 0) data.(i).d=data.(i).d+val*applymask.(i) print,strcompress(string(fix(total(applymask.(i))))+" pixels blanked.") endfor goto,stopping endif if n_tags(mask) eq 0 then begin print,"Creating new mask" maskarray=0*im case nbrds of 1:mask={b1:fltarr(xsize,npols,ysize)} 2:mask={b1:fltarr(xsize,npols,ysize),b1:fltarr(xsize,npols,ysize)} 3:mask={b1:fltarr(xsize,npols,ysize),b2:fltarr(xsize,npols,ysize),b3:fltarr(xsize,npols,ysize)} 4:mask={b1:fltarr(xsize,npols,ysize),b2:fltarr(xsize,npols,ysize),b3:fltarr(xsize,npols,ysize),b4:fltarr(xsize,npols,ysize)} endcase endif else begin print,"modifying mask" if total(size(data.(boardnum).d) eq size(mask.(boardnum))) eq 0 then begin print,"Supplied mask and dataset dimensions do not match" return,0 endif ;make a copy of the data, fill it with zeros for the mask if keyword_set(mask) then maskarray=0*im endelse print,"Use the left or middle mouse buttons to define a region for changing" print,"Click upper left hand corner first." print,"Click the right hand mouse button to quit at any time." ;-Ok, now if the data has two dimensions, then greyscale it, otherwise, ;plot it. if dim eq 2 then begin remap: !mouse.button=0 x=0 y=0 greyscale,im,max=maxim oldposstr=strcompress("X:"+string(x)+" "+"Y: "+string(y)) oldval=strcompress("Value: "+string(im(x,y))) xyouts,0.7,0.98,oldposstr,/norm xyouts,0.2,0.98,oldval,/norm maxim=max(im) while !mouse.button eq 0 do begin oldposstr=strcompress("X:"+string(x)+" "+"Y: "+string(y)) oldval=strcompress("Value: "+string(im(x,y))) cursor,x,y,2,/data if x lt 0 then x=0 if y lt 0 then y=0 if x ge xsize then x=xsize-1 if y ge ysize then y=ysize-1 newposstr=strcompress("X:"+string(x)+" "+"Y: "+string(y)) newval=strcompress("Value: "+string(im(x,y))) xyouts,0.7,0.98,oldposstr,/norm,color=0 xyouts,0.2,0.98,oldval,/norm,color=0 xyouts,0.7,0.98,newposstr,/norm xyouts,0.2,0.98,newval,/norm endwhile cursor,x0,y0,4,/data if !mouse.button eq 4 then goto,stopping if x0 lt 0 then x0=0 if y0 lt 0 then y0=0 if x0 gt xsize then x0=xsize-1 if y0 gt ysize then y0=ysize-1 polyfill,[x0,xsize-1,xsize-1,x0],[0,0,y0,y0],spacing=0.05,col=200 !mouse.button=0 while !mouse.button eq 0 do begin oldposstr=newposstr oldval=newval cursor,x,y,2,/data if x lt 0 then x=0 if y lt 0 then y=0 if x ge xsize then x=xsize-1 if y ge ysize then y=ysize-1 newposstr=strcompress("X:"+string(x)+" "+"Y: "+string(y)) newval=strcompress("Value: "+string(im(x,y))) xyouts,0.7,0.98,oldposstr,/norm,color=0 xyouts,0.2,0.98,oldval,/norm,color=0 xyouts,0.7,0.98,newposstr,/norm xyouts,0.2,0.98,newval,/norm endwhile if !mouse.button eq 4 then goto,stopping cursor,x1,y1,4,/data if x1 lt 0 then x1=0 if y1 lt 0 then y1=0 if x1 gt xsize then x1=xsize-1 if y1 gt ysize then y1=ysize-1 if x1 lt x0 or y1 gt y0 then begin print,"Must choose second click position inside shaded area" goto,remap endif greyscale,im xyouts,0.7,0.98,newposstr,/norm xyouts,0.2,0.98,newval,/norm polyfill,[x0,x1,x1,x0],[y1,y1,y0,y0],spacing=0.05,col=200 if not(keyword_set(val)) and not(keyword_set(zero))then begin regionx=(x1-x0)/2. if x0-regionx lt 0 or x1+regionx gt xsize then begin print,"Region is too close to edge. Stopping" goto,stopping endif else begin width=(x1-x0)/2. lowside=mean(im(x0-width:x0,y1:y0)) hiside=mean(im(x1:x1+width,y1:y0)) val=(lowside+hiside)/2. endelse endif if keyword_set(zero) then val=0 print,strcompress("Interpolate here? with "+string(val)+" [y/n]: ") read,ans while strlowcase(ans) ne 'y' and strlowcase(ans) ne 'n' do begin print,"Please confirm with 'y' or 'n'" print,"Interpolate here? [y/n]: " read,ans endwhile if strlowcase(ans) eq 'n' then begin goto,remap endif print,strcompress("Replacing "+strcompress(string(x0)+":"+string(x1),/remove_all)+$ " and "+strcompress(string(y0)+":"+string(y1),/remove_all)+" with "+string(val)) im(x0:x1,y1:y0)=val val=0 if keyword_set(mask) then maskarray(x0:x1,y1:y0)=1 goto,remap endif else begin ; Ok, that was for a 2D display for greyscale, now if it is a spectrum.... ;------------------------------------------ redraw: !mouse.button=0 x=0 y=0 plot,im,yrange=[min(im),max(im)*1.1] oldposstr=strcompress("X:"+string(x)+" "+"Y: "+string(im(x))) xyouts,0.7,0.98,oldposstr,/norm highlight=180 while !mouse.button eq 0 do begin oldposstr=strcompress("X:"+string(x)+" "+"Y: "+string(im(x))) cursor,x,y,2,/data if x lt 0 then x=0 if y lt 0 then y=0 if x ge xsize then x=xsize-1 if y ge ysize then y=ysize-1 newposstr=strcompress("X:"+string(x)+" "+"Y: "+string(im(x))) xyouts,0.7,0.98,oldposstr,/norm,color=0 xyouts,0.7,0.98,newposstr,/norm endwhile if !mouse.button eq 4 then goto,stopping cursor,x0,y0,4,/data if x0 lt 0 then x0=0 if x0 gt xsize-1 then x0=xsize-1 polyfill,[x0,x0,xsize-1,xsize-1],[min(im),max(im)*1.1,max(im)*1.1,min(im)],color=200,spacing=0.05 plot,im,yrange=[min(im),max(im)*1.1],/noerase !mouse.button=0 while !mouse.button eq 0 do begin oldposstr=strcompress("X:"+string(x)+" "+"Y: "+string(im(x))) cursor,x,y,2,/data if x lt 0 then x=0 if y lt 0 then y=0 if x ge xsize then x=xsize-1 if y ge ysize then y=ysize-1 newposstr=strcompress("X:"+string(x)+" "+"Y: "+string(im(x))) xyouts,0.7,0.98,oldposstr,/norm,color=0 xyouts,0.7,0.98,newposstr,/norm endwhile if !mouse.button eq 4 then goto,stopping cursor,x1,y1,4,/data if x1 lt 0 then x1=0 if x1 gt xsize-1 then x1=xsize-1 if x1 lt x0 then begin print,"Must choose second click position inside shaded area" goto,redraw endif plot,im,yrange=[min(im),max(im)*1.1] xyouts,0.7,0.98,newposstr,/norm polyfill,[x0,x0,x1,x1],[min(im),max(im)*1.1,max(im)*1.1,min(im)],color=200,spacing=0.05 plot,im,yrange=[min(im),max(im)*1.1],/noerase if not keyword_set(val) and not keyword_set(zero) then begin width=(x1-x0)/2. lowside=mean(im(x0-width:x0)) hiside=mean(im(x1:x1+width)) val=(lowside+hiside)/2. endif if keyword_set(zero) then val=0 print,strcompress("Interpolate here with value "+string(val)+" ?") read,ans while strlowcase(ans) ne 'y' and strlowcase(ans) ne 'n' do begin print,"Please confirm with 'y' or 'n'" print,"Interpolate here? [y/n]: " read,ans endwhile if strlowcase(ans) eq 'n' then goto,redraw im(x0:x1)=val val=0 if keyword_set(mask) then maskarray(x0:x1)=1 goto,redraw goto,stopping endelse stopping: ;finishing it all up. if not keyword_set(applymask) then if npols eq 1 then data.(boardnum).d(*,*)=im else data.(boardnum).d(*,pol,*)=im if keyword_set(mask) then begin print,strcompress("Writing a mask with "+string(nbrds)+" boards") if dim eq 2 then if npols gt 1 then mask.(boardnum)[*,pol,*]=(maskarray) else mask.(boardnum)[*,*]=fix(maskarray) if dim eq 1 then if npols gt 1 then mask.(boardnum)[*,pol]=(maskarray) else mask.(boardnum)[*]=fix(maskarray) endif !p.multi=oldmulti return,data end