program cosmicslitmask c c program to create a 4x/5x magnification of the negative of a slit mask c for use with COSMIC on P200 c the output of this program on a laserprinter will then be photoreduced c by 4x/5x in order to create a film (slits clear; everything else c dark) that is the mask itself c c written by: c Mike Pahre c Caltech c 13 February 1995 c c compile by having the pgplot library in your path; this can be accomplished c at Caltech by including the lines in your .cshrc file : c c set path = ( $path /usr/local/vlb/pgplot /usr/local/bin/X11 ) c setenv LD_LIBRARY_PATH /usr/lang/SC0.0:/usr/openwin/lib:/usr/local/vlb/pgplot c c then the compilation is done by: c f77 -O -o cosmicslitmask cosmicslitmask.o -lpgplot -lX11 c c the program requires an input file with the following specifications: c (for a free-format read) c col(1) integer number of object (not necessarily starting at 1) c col(2) real xposition/arcsec; E is positive c col(3) real yposition/arcsec; N is positive c col(4) real width of slit/arcsec c col(5) real magnitude of object c c the program will output: c (1) the plot of the slitmask; this goes to the terminal if c /xterm is chosen; it goes into pgplot.ps if /vps is chosen c (2) an output table with the chosen slitmask positions c col(1) number of object c col(2) xposition/arcsec; E is positive (rot angle=0) c col(3) yposition/arcsec; N is positive (rot angle=0) c col(4) width of slit/arcsec c col(5) length of slit/arcsec c col(6) percentage of the length of slit to find object c 0% -> top end of slit; 100% -> S end of slit c col(7) xposition/arcsec relative to centroid (using theta) c col(8) yposition/arcsec relative to centroid (using theta) c col(9) length of slit/arcsec west of object c col(10) length of slit/arcsec east of object c c note that the output of this program can also be used as the input of c a successive iteration of the program itself c integer k parameter (k=10000) integer i,inumin,inumnow,inumobj(k),iobjproj(k),iflag(k) real x0,y0,xobj(k),yobj(k),wslit(k),scale,enlarge real xstart(k),xend(k),xproj(k),yproj(k),pi,wproj(k) real ystart(k),yend(k),percent(k),lproj(k),xsize,ysize,yoff real x1,x2,y1,y2,xpts(5),ypts(5),platescale,interchange,xoff real slitposw(k),slitpose(k),slitposwproj(k),slitposeproj(k) real least(k),lwest(k),x0unproj,y0unproj,magin(k),magproj(k) parameter (scale=11.90) parameter (pi=3.1415926535) character*64 infile,outfile character*32 string1,string2 character*40 string3 character*60 string4 character*4 text ioption=0 inumbers=2 xoff=0. yoff=0. c c scale is 11.90 "/mm at prime focus (measured) c enlarge is enlargement factor for laserprinter plot = 4.0 usually c c c query input filename from user c type *, 'Enter input filename:' accept *, infile type *, 'Enter a rotation angle (CCW from input x,y; degrees):' accept *, theta theta=theta/360.*2.*pi type *, 'Enter the name for the plot:' accept *, string1 type *, 'Enter 1 to change expected sense of input coordinates:' accept *, isense if (isense .eq. 1) then type *, 'x axis is normally +ve in the E direction;' type *, ' Enter 1 to change sign of x axis in input file:' accept *, ixsign type *, 'y axis is normally +ve in the N direction;' type *, ' Enter 1 to change sign of y axis in input file:' accept *, iysign endif type *, 'Enter 1 if input file scale is not in arcsec:' accept *, iscale if (iscale .eq. 1) then type *, 'Enter pixel scale (in arcsec/pixel):' accept *, platescale endif type *, 'Enter number of lines to skip at top of the input file:' accept *, iskip c c open the file and read its contents c c the flag is = 0 for data to be used; =1 for data to be excluded c open(unit=11,file=infile,form='formatted',status='old') inumin=0 if (iskip .gt. 0) then do i=1,iskip read(11,*,end=1001,err=1001) enddo endif do i=1,k read(11,*,end=1001,err=1001) inumobj(i),xobj(i), + yobj(i),wslit(i),magin(i) inumin=inumin+1 iflag(i)=0 if (isense .eq. 1) then if (ixsign .eq. 1) then xobj(i)=-1. * xobj(i) endif if (iysign .eq. 1) then yobj(i)=-1. * yobj(i) endif endif if (iscale .eq. 1) then xobj(i)=xobj(i)*platescale yobj(i)=yobj(i)*platescale endif slitpose(i)=0. slitposw(i)=0. enddo 1001 close(unit=11,status='keep') inumnow=inumin c c give opportunity to change the general size of the plot and the c enlargement factor c type *, 'Enter 1 to accept usual parameters for size of plot' type *, ' and enlargement factor (720"x480";mag=4);' type *, ' 2 to change:' 199 accept *, isize if (isize .eq. 2) then 198 type *, 'Enter xsize/"(real), ysize/"(real), magfactor(real):' accept *, xsize, ysize, enlarge if ( xsize/scale*enlarge/25.4 .gt. 10.5) then type *, 'The plot is too large for the page; choose', + ' a new xsize' goto 198 endif if ( xsize/scale*enlarge/25.4 .gt. 8.) then type *, 'The plot is too large for the page; choose', + ' a new ysize' goto 198 endif else if (isize .eq. 1) then xsize=720. ysize=480. enlarge=4. else type *, 'Enter 1 or 2:' goto 199 endif c c this is the general loop for reading unflagged data from the input c list into the working vectors c 2000 icount=0 x0=0. y0=0. do i=1,inumin if (iflag(i) .eq. 0) then icount=icount+1 xproj(icount)=xobj(i)*cos(theta) + yobj(i)*sin(theta) yproj(icount)=yobj(i)*cos(theta) - xobj(i)*sin(theta) wproj(icount)=wslit(i) iobjproj(icount)=inumobj(i) slitposeproj(icount)=slitpose(i) slitposwproj(icount)=slitposw(i) magproj(icount)=magin(i) x0 = x0 + xproj(icount) y0 = y0 + yproj(icount) endif enddo c c put object numbers of zero into the unused ones c do i=icount+1,inumin iobjproj(i)=0 enddo c c centroid of current working object list is (x0,y0) c these centroids are in the current project of the (x,y) coordinates c x0 = x0 / float(icount) y0 = y0 / float(icount) c c the desired (x0,y0) are relative to the input (x=0,y=0) *non-projected* c coordinates c so derotate the coordinates of the centroid c x0unproj=x0*cos(theta) - y0*sin(theta) y0unproj=y0*cos(theta) + x0*sin(theta) c type 110, x0, y0 type 110, x0unproj, y0unproj c c sort the objects into ascending x order, while keeping the other arrays c in the associated positions c piksr7 subroutine is *adapted* from numerical recipes; 4 indicates that c there are six dependent vectors (yproj,wproj,iobjproj,magproj, c slitposeproj,slitposwproj) on the one sorting vector (xproj) c call piksr7(icount,xproj,yproj,wproj,iobjproj,slitposeproj, + slitposwproj,magproj) c c make all (x,y) positions relative to the centroid c do i=1,icount xproj(i) = xproj(i) - x0 + xoff yproj(i) = yproj(i) - y0 + yoff if (xproj(i) .lt. (xsize/(-2.)-15.) + .or. xproj(i) .gt. (xsize/2.+15.) + .or. yproj(i) .lt. (ysize/(-2.)-15.) + .or. yproj(i) .gt. (ysize/2.+15.) ) then type 130, iobjproj(i), xproj(i),yproj(i) endif if (yproj(i) .gt. 60. .or. yproj(i) .lt. -60.) then type 131, iobjproj(i), xproj(i),yproj(i) endif enddo c c set up the slit coordinates c do i=1,icount if (i .eq. 1) then xstart(i) = xproj(i) - 15. else c remove one pixel = 0.4" from length on each end of slit xstart(i)=(xproj(i)+xproj(i-1))/2.+slitposeproj(i)+0.4 endif if (i .eq. icount) then xend(i) = xproj(i) + 15. else xend(i) = (xproj(i)+xproj(i+1))/2.+slitposwproj(i)-0.4 endif if (xproj(i)-xstart(i) .lt. 3.) then type 170, iobjproj(i) endif if (xend(i)-xproj(i) .lt. 3.) then type 171, iobjproj(i) endif c c modification: now gives the percentage of the slit for the object c measured from the E to the W (i.e. left to right on the plot) c c percent(i) = (xproj(i)-xstart(i)) / (xend(i)-xstart(i)) percent(i) = 1. - (xproj(i)-xstart(i)) / (xend(i)-xstart(i)) lproj(i) = xend(i)-xstart(i) lwest(i) = xproj(i)-xstart(i) least(i) = xend(i)-xproj(i) if (lproj(i) .le. 10.) then type 172, iobjproj(i) endif ystart(i) = yproj(i) - wslit(i)/2. yend(i) = yproj(i) + wslit(i)/2. enddo c c plot the current working set of vectors c if (ioption .ne. 0) then call pgend endif if (ioption .eq. 6) then c /ps to create pgplot.ps call pgbegin(0,'/ps',1,1) else c /xterm to terminal type *, 'Enter /xw for xwindow; /xt for xterm:' call pgbegin(0,'?',1,1) endif c c size of plot in inches; x is 720 arcsec, y is 480 arcsec c x1=0.25 x2=xsize/scale*enlarge/25.4+0.25 y1=0.25 y2=ysize/scale*enlarge/25.4+0.25 call pgvsize(x1,x2,y1,y2) c c note: x +ve in the right direction = E (sky parity) c y +ve in the upper direction = N c x1=xsize/(-2.) x2=xsize/(2.) y1=ysize/(-2.) y2=ysize/(2.) c c modification: now N up and E left c c call pgwindow(x1,x2,y1,y2) call pgwindow(x2,x1,y1,y2) call pgslw(1) call pgbox('BC',0.,0.,'BC',0.,0.) c c enter the name in the upper LH corner c call pgsch(0.6) call pgtext(x2-20.,y2-12.,string1) write(string2,150) enlarge call pgtext(x2-20.,y2-24.,string2) theta=theta*360./2./pi c write(string3,151) theta write(string3,155) theta+180. theta=theta/360.*2.*pi call pgtext(x2-20.,y2-36.,string3) write(string4,152) x0unproj,y0unproj call pgtext(x2-20.,y2-48.,string4) call pgsch(1.0) c c plot the rectangular slits c do i=1,icount xpts(1)=xstart(i) ypts(1)=ystart(i) xpts(2)=xend(i) ypts(2)=ystart(i) xpts(3)=xend(i) ypts(3)=yend(i) xpts(4)=xstart(i) ypts(4)=yend(i) xpts(5)=xstart(i) ypts(5)=ystart(i) c call pgslw(3) c number of line strokes call pgslw(1) c c psgsfs(1=solid;2=hollow) c call pgsfs(1) call pgpoly(5,xpts,ypts) call pgslw(1) enddo c c if plotting to the terminal, plot the number of each slit above it c if (ioption .ne. 6 .or. inumbers .eq. 1) then call pgsch(0.8) do i=1,icount text=' ' write(text,140) iobjproj(i) x1=xproj(i) y1=yproj(i)+10. if (iobjproj(i) .ge. 1000) then call pgptext(x1,y1,0.,0.5,text) else if (iobjproj(i) .ge. 100) then call pgptext(x1,y1,0.,0.5,text(2:4)) else if (iobjproj(i) .ge. 10) then call pgptext(x1,y1,0.,0.5,text(3:4)) else call pgptext(x1,y1,0.,0.5,text(4:4)) endif y1=yproj(i) call pgpoint(1,x1,y1,2) enddo call pgsch(1.0) endif inumbers=2 iprevious = ioption c c necessary for the pgplot.ps output to end the plot c if (ioption .eq. 6) then call pgend endif c c query the user if they desire a change in any of the parameters c 4000 type *, 'Enter 1 to change the rotation angle,' type *, ' 2 to exclude an object,' type *, ' 3 to include an object,' type *, ' 4 to plot again on the terminal,' type *, ' 5 to type the object list to the terminal,' type *, ' 6 to write an output file,' type *, ' 7 to edit lengths of slits' type *, ' 8 to include all objects' type *, ' 9 to exclude all objects' type *, ' 10 to add overall offset in x or y to all slits:' type *, ' 11 to exit program, no output:' type *, ' ' accept *, ioption if (ioption .eq. 1) then type *, 'Enter a rotation angle (CCW from input x,y; degrees):' accept *, theta theta=theta/360.*2.*pi type *, 'Note that re-projection onto this theta will not be' type *, ' calculated until you replot the data...' goto 4000 else if (ioption .eq. 2) then type *, 'Enter number of object to exclude:' accept *, iex do i=1,inumin if (inumobj(i) .eq. iex) then iflag(i)=1 goto 4001 endif enddo type *, 'No object found with that number, try again:' 4001 goto 4000 else if (ioption .eq. 3) then type *, 'Enter number of object to include:' accept *, iinc do i=1,inumin if (inumobj(i) .eq. iinc) then iflag(i)=0 goto 4002 endif enddo type *, 'No object found with that number, try again:' 4002 goto 4000 else if (ioption .eq. 4) then goto 2000 else if (ioption .eq. 5) then type 103, inumnow type *, 'Included objects:' type *, 'Object x/" y/" width/" length/" percent', + ' L/"(Wside) L/"(Eside)' type *, ' from top' type *, ' ' do i=1,inumin if (iflag(i) .eq. 0) then do j=1,inumnow if (inumobj(i) .eq. iobjproj(j)) then type 102, iobjproj(j),xproj(j),yproj(j),wproj(j), + lproj(j),percent(j),lwest(j),least(j) endif enddo endif enddo type *, ' ' type *, 'Excluded objects:' type *, 'Object x/" y/" width/"' type *, ' ' do i=1,inumin if (iflag(i) .eq. 1) then type 104, inumobj(i),xobj(i),yobj(i),wslit(i) endif enddo goto 4000 else if (ioption .eq. 6) then type *, 'Enter output filename for textfile output:' accept *, outfile open(unit=12,file=outfile,form='formatted',status='new') theta=theta*360./2./pi c c modification: more notation at top of file c c write(12,180) x0unproj,y0unproj,theta,180.+theta c type 180, x0unproj,y0unproj,theta,180.+theta write(12,181) x0unproj,y0unproj write(12,182) theta,theta+180. write(12,183) type 181,x0unproj,y0unproj type 182,theta,theta+180. theta=theta/360.*2.*pi do i=1,inumin if (iflag(i) .eq. 0) then do j=1,inumnow if (inumobj(i) .eq. iobjproj(j)) then c write(12,101) iobjproj(j),xproj(j)+x0,yproj(j)+y0,wproj(j), c + lproj(j),percent(j),xproj(j),yproj(j),least(j),lwest(j) write(12,101) iobjproj(j),xobj(i),yobj(i), + wproj(j),magproj(j),lproj(j),percent(j), + xproj(j),yproj(j),least(j),lwest(j) endif enddo endif enddo type *, 'Postscript version of plot written to pgplot.ps' type *, 'Print by "lpr -s -Pps pgplot.ps"' type *, ' ' close(unit=12,status='keep') type *, 'Enter 1 to include object numbers in plot' type *, ' (for reference purposes),' type *, ' 2 for no numbers (for the actual mask):' accept *, inumbers goto 2000 else if (ioption .eq. 7) then type *, 'Enter object number on W side of slit interface:' accept *, iobjw type *, 'Enter object number on E side of slit interface:' accept *, iobje type *, 'Enter amount to change interface (E +ve):' accept *, interchange do i=1,inumin if (inumobj(i) .eq. iobjw) then slitposw(i)=interchange endif enddo do i=1,inumin if (inumobj(i) .eq. iobje) then slitpose(i)=interchange endif enddo goto 4000 else if (ioption .eq. 8) then do i=1,inumin c flag=0 include; flag=1 exclude iflag(i)=0 enddo goto 4000 else if (ioption .eq. 9) then do i=1,inumin iflag(i)=1 enddo goto 4000 else if (ioption .eq. 11) then goto 5000 else if (ioption .eq. 10) then type *, 'Enter total offset from centroid in x,y (arcsec)' accept *, xoff,yoff goto 4000 else type *, 'Enter value 1-11 only:' goto 4000 endif 5000 continue call pgend stop 101 format(i4,x,2(f7.2,x),2(f5.2,x),f7.2,x,f5.3,x,4(f7.2,x)) 102 format(i4,x,2(f7.2,x),f5.2,x,f7.2,x,f5.3,x,2(f7.2,x)) 103 format('Number of objects in current plot:',3x,i4) 104 format(i4,x,2(f7.2,x),f5.2) 110 format('Centroid of slits is at x=',f7.2,' arcsec, y=', + f7.2,' arcsec') 120 format('Position angle = ',f7.2,' degrees, centroid x0=',f7.2, + ' arcsec, y0=',f7.2) 130 format('Object number ',i4,' at (',f7.2,x,f7.2, + ') is out of the field of view') 131 format('Object number ',i4,' at (',f7.2,x,f7.2, + ') is out of the recommended range of |y|<60"') 140 format(i4) 150 format('Magnification=',f5.2) 151 format('E=',f7.2,' deg CW from +ve x') 152 format('x0=',f7.2,'" y0=',f7.2,'" relative to input (x=0,y=0)') 155 format('COSMIC position angle = ',f7.2,' degrees') 160 format('Theta=',f5.2,' deg CCW from x +ve=E') 170 format('Object #',i4,' has a slit on W side of object < 3"') 171 format('Object #',i4,' has a slit on E side of object < 3"') 172 format('Object #',i4,' has a slit < 10"') 180 format('Centroid x0=',f8.2,'" and y0=',f8.2,'" relative to the', + ' input (x=0,y=0) coordinates; Rotation angle: E=',f8.2, + ' degree CW from positive x-axis',' Set COSMIC base angle', + ' to ',f8.2) 181 format('Centroid x0=',f8.2,'" and y0=',f8.2,'" relative to the', + ' input (x=0,y=0) coordinates') 182 format('Rotation angle from input coordinates:',f8.2,' COSMIC ', + 'base position angle = ',f8.2) 183 format('Obj# Xobj/" Yobj/" Slitwidth/" Mag ', + ' Slitlength/" %(along slit E->W) Xrel/" Yrel/"', + ' SlitlengthW/" SlitlengthE/"') end subroutine piksr7(n,arr,b1rr,b2rr,b3rr,b4rr,b5rr,b6rr) dimension arr(n),b1rr(n),b2rr(n),b3rr(n),b4rr(n),b5rr(n),b6rr(n) do j=2,n a=arr(j) b1=b1rr(j) b2=b2rr(j) b3=b3rr(j) b4=b4rr(j) b5=b5rr(j) b6=b6rr(j) do i=j-1,1,-1 if (arr(i) .le. a) goto 10 arr(i+1)=arr(i) b1rr(i+1)=b1rr(i) b2rr(i+1)=b2rr(i) b3rr(i+1)=b3rr(i) b4rr(i+1)=b4rr(i) b5rr(i+1)=b5rr(i) b6rr(i+1)=b6rr(i) enddo i=0 10 arr(i+1)=a b1rr(i+1)=b1 b2rr(i+1)=b2 b3rr(i+1)=b3 b4rr(i+1)=b4 b5rr(i+1)=b5 b6rr(i+1)=b6 enddo return end