*! Date : 3 Mar 2006 *! Version : 2.01 *! Author : Adrian Mander *! Email : adrian.mander@mrc-hnr.cam.ac.uk *! Description : Producing a contour plot program define contour version 9.1 preserve syntax [varlist] [,Split(numlist) Values *] local gopt "`options'" /* Stack all the data into one column */ qui stack `varlist', into(d) clear qui su d,de qui gen order=_n qui sort _stack order qui by _stack: gen line=_n local mean = `r(mean)' local lower = `r(p25)' local upper = `r(p75)' qui drop order rename line y rename _stack x if "`split'"=="" local split "`lower' `mean' `upper'" tempfile master temp qui save "`master'" local graphtax "" local graphleg "" local i 1 foreach cutp in `split' { local cutlab : di %6.2f `cutp' di as text "Calculating contours at " as res `cutp' if `i'>1 qui use "`master'",replace _cutcontour, cut(`cutp') qui stack x y d colx coly x y d colxx colyy, into(x y d cont`i'x cont`i'y) clear if `i'==1 qui save "`temp'",replace else { qui append using "`temp'" qui save "`temp'",replace } local graphleg `"`graphleg' label(`i' "`cutlab'")"' local graphtax "`graphtax' (line cont`i'y cont`i'x,cmiss(n))" local `i++' } lab var cont1x "Varlist" lab var cont1y "Observation number" if "`values'"~="" local add "(scatter y x,mlabel(d))" twoway `graphtax' `add', legend(`graphleg') `gopt' restore end pr _cutcontour syntax [varlist] [, CUT(real 0) CONT(integer 1)] /* Find out whether values are bridging the cut point and then create 3 records i.e a line Coly are the horizontal lines colxx are the vertical lines Sort x y generate lines for constant x replace lines for constant x NEED both because order of d is different */ /* Set up the following structure around the value d the point I need to decide things about the line dlt dt drt dl d dr dlb db drb */ sort x y qui by x: gen db = d[_n-1] qui by x: gen dt = d[_n+1] sort y x qui by y: gen dr = d[_n+1] qui by y: gen dl = d[_n-1] sort x y qui by x: gen drt = dr[_n+1] qui by x: gen drb = dr[_n-1] qui by x: gen dlt = dl[_n+1] qui by x: gen dlb = dl[_n-1] /* coly will contain a 4 whenever there is a horizontal line needed 0 otherwise */ sort x y qui gen coly = 4*(d[_n+1]>=`cut' & d[_n]<`cut') * (x[_n+1]==x) qui replace coly = cond(coly==0,4*(d[_n+1]<`cut' & d[_n]>=`cut')* (x[_n+1]==x) ,coly) sort y x qui gen colxx = 4*(d[_n+1]>=`cut' & d[_n]<`cut') * (y[_n+1]==y) qui replace colxx = cond(colxx==0,4*(d[_n+1]<`cut' & d[_n]>=`cut')* (y[_n+1]==y) ,colxx) /* Expand the 4 records and then create the line Now create coordinates always end with a dot to end line */ qui expand coly qui sort x y d qui by x y d : replace coly= . if _n==4 /* End the line with missing */ /* This minimises the number of expansions Make sure for the last value that the second expansion is there */ qui by x y d : replace colxx= . if _N==4 & _n<4 qui replace coly =. if coly==0 /* the 0 values do nothing so get rid of them */ qui replace colxx =. if colxx==0 qui gen colx=coly /* create the x coordinates of the horizontal points */ qui replace coly=y if coly~=. /* the y-coords are just y */ qui replace colx=x if colx~=. /* the x-coords are just x */ sort x y coly /* Keep the order to draw that line */ /* this is the business end of creating the x-coords */ qui by x y: replace colx= cond(colx~=., colx+_n/2-1,.) /* the x-coords are x-.5, x, x+.5 */ /* Decide the direction of the second half of the horizontal line */ qui by x y: replace coly= cond(drt>=`cut' & dr >=`cut' & d<`cut' & dr~=., coly, coly) if _n==3 qui by x y: replace coly= cond(drt>=`cut' & dr >=`cut' & d>=`cut' & dr~=., coly+1, coly) if _n==3 qui by x y: replace coly= cond(drt>=`cut' & dr <`cut' & d<`cut' & dr~=., coly+0.5, coly) if _n==3 /* correct way */ qui by x y: replace coly= cond(drt>=`cut' & dr <`cut' & d>=`cut' & dr~=., coly, coly) if _n==3 /* correct way */ qui by x y: replace coly= cond(drt<`cut' & dr <`cut' & d<`cut' & dr~=., coly+1, coly) if _n==3 /* correct way */ qui by x y: replace coly= cond(drt<`cut' & dr <`cut' & d>=`cut' & dr~=., coly, coly) if _n==3 /* correct way */ qui by x y: replace coly= cond(drt<`cut' & dr >=`cut' & d<`cut' & dr~=., coly, coly) if _n==3 /* correct way */ qui by x y: replace coly= cond(drt<`cut' & dr >=`cut' & d>=`cut' & dr~=., coly+0.5, coly) if _n==3 /* correct way */ qui by x y: replace coly= cond(dr==. & drt==. , coly+0.5, coly) if _n==3 /* the middle of the line*/ qui by x y: replace coly= cond(1,coly+0.5,coly) if _n==2 /* The first half of the line */ qui by x y: replace coly= cond(dl==. & dlt==. , coly+0.5,coly) if _n==1 /* make the edges horizontal not slanting */ qui by x y: replace coly= cond(dl>=`cut' & dlt>=`cut' & d>=`cut' & dl~=., coly+1,coly) if _n==1 qui by x y: replace coly= cond(dl>=`cut' & dlt>=`cut' & d<`cut' & dl~=., coly,coly) if _n==1 qui by x y: replace coly= cond(dl<`cut' & dlt>=`cut' & d>=`cut' & dl~=. ,coly+1,coly) if _n==1 qui by x y: replace coly= cond(dl<`cut' & dlt>=`cut' & d<`cut' & dl~=. ,coly+0.5,coly) if _n==1 qui by x y: replace coly= cond(dl<`cut' & dlt<`cut' & d<`cut' & dl~=.,coly+1,coly) if _n==1 qui by x y: replace coly= cond(dl<`cut' & dlt<`cut' & d>=`cut' & dl~=.,coly,coly) if _n==1 qui by x y: replace coly= cond(dl>=`cut' & dlt<`cut' & d>=`cut' & dl~=.,coly+.5,coly) if _n==1 qui by x y: replace coly= cond(dl>=`cut' & dlt<`cut' & d<`cut' & dl~=.,coly+1,coly) if _n==1 /* Now do it for the vertical lines */ qui expand colxx qui sort x y d coly qui by x y d: replace colxx=. if _n==1 /* make sure we have some missing values to end lines */ qui by x y d: replace colxx=. if _n==4 & _N==7 /* this is for the points with horizontal lines */ qui gen colyy=colxx qui replace colyy=y if colyy~=. /* Make sure we have the coordinates in the variables */ qui replace colxx=x if colxx~=. /* Calculating the vertical line coordinates */ sort y x colyy qui by y x: replace colyy= cond(colyy~=., colyy+_n/2-1,.) /* the y-coords are y-.5, y, y+.5 */ /* Lower half of vertical line */ qui by y x: replace colxx= cond(db==. & drb==., colxx+.5,colxx) if _n==1 qui by y x: replace colxx= cond(db>=`cut' & drb<`cut' & d>=`cut' & db~=., colxx+.5,colxx) if _n==1 qui by y x: replace colxx= cond(db>=`cut' & drb<`cut' & d<`cut' & db~=., colxx+1,colxx) if _n==1 qui by y x: replace colxx= cond(db>=`cut' & drb>=`cut' & d>=`cut' & db~=., colxx+1,colxx) if _n==1 qui by y x: replace colxx= cond(db>=`cut' & drb>=`cut' & d<`cut' & db~=., colxx,colxx) if _n==1 qui by y x: replace colxx= cond(db<`cut' & drb>=`cut' & d>=`cut' & db~=., colxx+1,colxx) if _n==1 qui by y x: replace colxx= cond(db<`cut' & drb>=`cut' & d<`cut' & db~=., colxx+.5,colxx) if _n==1 qui by y x: replace colxx= cond(db<`cut' & drb<`cut' & d>=`cut' & db~=., colxx,colxx) if _n==1 qui by y x: replace colxx= cond(db<`cut' & drb<`cut' & d<`cut' & db~=., colxx+1,colxx) if _n==1 /* The middle point */ qui by y x: replace colxx= cond(1, colxx+.5,colxx) if _n==2 /* upper half of line */ qui by y x: replace colxx= cond(dt==. & drt==., colxx+.5,colxx) if _n==3 qui by y x: replace colxx= cond(dt>=`cut' & drt<`cut' & d>=`cut' & dt~=., colxx+.5,colxx) if _n==3 qui by y x: replace colxx= cond(dt>=`cut' & drt<`cut' & d<`cut' & dt~=., colxx,colxx) if _n==3 qui by y x: replace colxx= cond(dt>=`cut' & drt>=`cut' & d>=`cut' & dt~=., colxx+1,colxx) if _n==3 qui by y x: replace colxx= cond(dt>=`cut' & drt>=`cut' & d<`cut' & dt~=., colxx,colxx) if _n==3 qui by y x: replace colxx= cond(dt<`cut' & drt>=`cut' & d>=`cut' & dt~=., colxx,colxx) if _n==3 qui by y x: replace colxx= cond(dt<`cut' & drt>=`cut' & d<`cut' & dt~=., colxx+.5,colxx) if _n==3 qui by y x: replace colxx= cond(dt<`cut' & drt<`cut' & d>=`cut' & dt~=., colxx,colxx) if _n==3 qui by y x: replace colxx= cond(dt<`cut' & drt<`cut' & d<`cut' & dt~=., colxx+1,colxx) if _n==3 sort x y colx colyy end