; SHOW.PRO ; ; Originally written to show images from Polar Camera initial field test ; at Ryning Farm Observatory ; Modified 1993/1/29 by DPS to handle images from image tree structure ; on /jasper/cnsr3_data1 ; Modified 17 Oct 93 at Eureka for use with IDL for Windows. Path names ; shrunk to 12 chars maximum. ; ; create byte-valued input parameters cam=0B & filt=cam & day=cam & month=cam mask=BYTARR(256,256) ; load various string-valued arrays needed initialize,filters,months,days,modes,mpaths,firstchars s='' !ORDER=1 ; set colour table PRINT,'Do you want a colour display? (Y/[N])' resp='' READ,resp IF STRUPCASE(resp) EQ 'Y' THEN loadct,13,/silent ELSE loadct,0,/silent ; tell user what imaging modes and filters are available IF D.NAME EQ 'WIN' THEN WDELETE,0 ; uncover screen where text is to be printed PRINT,"Modes:" & FOR i=0,5 DO PRINT,i,modes(i),FORMAT='(I1,1X,A)' PRINT," " & PRINT,"Camera 0:" & PRINT,"Filter Emission" FOR i=0,4 DO BEGIN wavelength=STRMID(filters(i),0,STRPOS(filters(i),'nm')+2) PRINT,STRING(i,wavelength,FORMAT='(I1,7X,A)') ENDFOR PRINT," " & PRINT,"Camera 1:" & PRINT,"Filter Emission" FOR i=0,4 DO BEGIN wavelength=STRMID(filters(i+5),0,STRPOS(filters(i),'nm')+2) PRINT,STRING(i,wavelength,FORMAT='(I1,7X,A)') ENDFOR ; prompt user and get input PRINT,'Enter the mode, camera, filter, day, month, and year desired' READ,mode,cam,filt,day,month,year IF mode EQ 0 THEN BEGIN ; auroral mode. variable exposure time ; prompt user for exposure time desired (0 => all exposure times OK) PRINT,'Enter the exposure time (s) for the images you want to view,' PRINT,'(or 0 for all available images)' READ,texp ENDIF ELSE texp=0 ; create 3-character string giving desired exposure time (or all) IF texp EQ 0 THEN exp='???' ELSE exp=STRING(texp,FORMAT='(I3.3)') ; ensure a 4-digit year for display; make reasonable assumptions IF year LT 1900 THEN BEGIN IF year LT 50 THEN year=year+2000 IF year GT 50 THEN year=year+1900 ENDIF ; create title for image plot wtitle=STRING(modes(mode),filters(cam*5+filt),year,months(month-1), $ day,FORMAT='("Polar Camera",2X,A,2X,A,2X,I4,1X,A3,1X,I0.2)') ; define mask for images, with fixed horizon at 150 superpixels prad=150 d256=SHIFT(dist(256),128,128) & base=WHERE(d256 GT 150) wprad=WHERE(d256 LE prad) & mask(wprad)=1 ; define path to desired images IF (mode EQ 1) OR (mode EQ 3) $ THEN dir=STRING(mpaths(mode),cam,FORMAT='(A,"/c",I1,"/")') $ ELSE dir=STRING(mpaths(mode),cam,filt,FORMAT='(A,"/c",I1,"/f",I1,"/")') ; make list of available files of desired type template=firstchars(mode)+STRING(day,cam,filt,FORMAT='(I2.2,I1,I1)') $ +exp+'.*' files=FINDFILE(dir+template,COUNT=nfiles) IF nfiles LE 0 THEN BEGIN PRINT,'No files found; quitting.' GOTO,DONE ENDIF ; sort contents of 'files' in time order timesort,files,day,month,year,nfiles,jsecs ; define path to corresponding dark frames, if required IF (mode NE 1) AND (mode NE 3) THEN BEGIN ; only open-shutter images require dark subtraction ddir=STRING(mpaths(3),cam,FORMAT='(A,"/c",I1,"/")') dtemplate=STRING(day,cam,FORMAT='("d",I2.2,I1,"?")')+exp+'.*' dfiles=FINDFILE(ddir+dtemplate,COUNT=ndfiles) IF ndfiles GT 0 THEN BEGIN timesort,dfiles,day,month,year,ndfiles PRINT,STRING(ndfiles,FORMAT='(I3," dark frame files found")') ENDIF ELSE PRINT,"No dark frame files found" ENDIF ; identify image sequences and prompt user for sequence(s) to display djs=ABS(jsecs-SHIFT(jsecs,1)) ; rectify big negative number in front seqstart=WHERE(djs GT 600) ; semi-arbitrary large number (10 min) ext_list=extensio(files) PRINT,'There are '+STRTRIM(nfiles,2)+' images, with extensions '+ $ ext_list(0)+' to '+ext_list(nfiles-1)+'.' IF seqstart(0) GE 0 THEN BEGIN PRINT,'Sequences begin with the following image file numbers(s):' PRINT,extensio(files(seqstart)) ENDIF PRINT,'Enter the range of image file numbers to display (* for all images)' instring='' & READ,instring f=isnumber(instring,inf) IF f NE 0 THEN BEGIN ; user entered at least one number inf=FIX(inf) IF f GT 0 $ ; user entered only one number THEN inl=nfiles-1 $ ELSE BEGIN f=isnumber(getwrd(instring,1),inl) IF f NE 0 THEN inl=FIX(inl) ELSE inl=nfiles-1 ENDELSE ENDIF ELSE BEGIN inf=0 inl=nfiles-1 ENDELSE ;IF STRPOS(instring,'*') EQ -1 THEN BEGIN ; user entered numbers ; instring=STRTRIM(instring,2) ; remove leading/trailing blanks ; blank=STRPOS(instring,' ') ; space between two numbers ; inf=FIX(STRMID(instring,0,blank)) ; inl=FIX(STRMID(instring,blank,STRLEN(instring)-blank)) ; inf=WHERE(inf EQ FIX(ext_list)) ; inl=WHERE(inl EQ FIX(ext_list)) ;ENDIF ELSE BEGIN ; inf=0 & inl=nfiles-1 ;ENDELSE ; Prompt user for fixed saturation brightness PRINT,'If you want to assign the top of the color bar to a fixed number of counts,' PRINT,'enter that number now, otherwise enter anything else for auto-scaling.' tops='' READ,tops flag=isnumber(tops,topnum) ; topnum=0 if tops doesn't represent a number ; create and label image display window X_charheight=10 ; try to keep scalings that apply in X windows X_charwidth=8 barwidth=16 ninrow=3 nincol=2 ninwin=ninrow*nincol wwidth=ninrow*256+barwidth wheight=nincol*256+4*X_charheight IF !D.NAME EQ 'WIN' THEN $ WINDOW,0,XSIZE=wwidth,YSIZE=wheight $ ELSE DEVICE,/COLOR,BITS_PER_PIXEL=8 ; PostScript csz=((1.*X_charheight)/wheight)/((1.*!D.Y_CH_SIZE)/!D.Y_VSIZE) ; keep 'X' char size XYOUTS,scl(res=120.,(wwidth-barwidth)/2) $ ,scl(res=120.,wheight-3*X_charheight),wtitle $ ,/DEVICE,ALIGNMENT=0.5,CHARSIZE=2.0*csz,WIDTH=twidthn twidthd=CONVERT_COORD([twidthn,0.],/NORMAL,/TO_DEVICE) twidthd=twidthd(0) ; we only need the x-component ; get user's name and display it username='CNSR3' XYOUTS,scl(res=120.,wwidth-X_charwidth),scl(res=120.,wheight-3.9*X_charheight) $ ,'User '+STRUPCASE(username),ALIGNMENT=1.0,/DEVICE,CHARSIZE=csz ; get date/time and display them ;SPAWN,'date -u',datetime ;XYOUTS,scl(res=120.,wwidth-X_charwidth),scl(res=120.,wheight-2.5*X_charheight) $ ;,STRMID(datetime,11,9)+' UT',ALIGNMENT=1.0,/DEVICE,CHARSIZE=csz ;XYOUTS,scl(res=120.,wwidth-X_charwidth),scl(res=120.,wheight-1.1*X_charheight) $ ;,STRMID(datetime,4,7)+STRMID(datetime,24,4),ALIGNMENT=1.0,/DEVICE,CHARSIZE=csz ; create and display color bar bar=REBIN(BINDGEN(256,barwidth),nincol*256,barwidth) bar=ROTATE(bar,3) mtv,bar,ninrow*256,0,res=120. ; read in each image, decode the header, subtract dark frame, rebin to ; 256x256 if necessary, scale to 8 bits and display ip=-1 mid=-1 FOR i=inf(0),inl(0) DO BEGIN rdkimg,files(i),h,im KIh=gethd(h) ; if image isn't 256x256, rebin it im=REBIN(im,256,256) ; ensure counts are actually summed if a 512x512 image is compressed cfac=512/(256*KIh.exp.sbin) rfac=512/(256*KIh.exp.pbin) im=im*cfac*rfac ; extract start time of image from header itime=BYTARR(4) FOR itptr=0,3 DO itime(itptr)=KIh.misc.tm.(itptr) utsecs=TOTAL(itime*[3600,60,1,.01]) IF NOT ((mode EQ 1) OR (mode EQ 3)) THEN BEGIN IF (ndfiles GT 0) AND $ ; dark frames exist, for this exposure time (TOTAL(exposure(dfiles) EQ exposure(files(i))) GT 0) THEN BEGIN ; find closest dark frame ; (NB: this isn't going to work over day boundaries!) id=MAX([mid-1,-1]) mid=-1 mindif=90000. thisdif=86400. REPEAT BEGIN id=id+1 IF (exposure(dfiles(id)) EQ exposure(files(i))) THEN BEGIN rdkihd,dfiles(id),dh ; read id'th file header dKIh=gethd(dh) dtime=BYTARR(4) FOR itptr=0,3 DO dtime(itptr)=dKIh.misc.tm.(itptr) dutsecs=TOTAL(dtime*[3600,60,1,.01]) thisdif=ABS(dutsecs-utsecs) IF thisdif LT mindif THEN BEGIN mindif=thisdif ; update minimum time difference mid=id ; and id no. of closest frame ENDIF ENDIF ENDREP UNTIL (mindif LT thisdif) OR (id EQ ndfiles-1) ; Dark frames not taken at some exposure times; warn user and go on IF mid NE -1 THEN BEGIN rdkimg,dfiles(mid),dh,dkimg ; read dark frame closest in time im=(im-dkimg)>0 ; subtract dark frame ENDIF ELSE BEGIN IF NOT KEYWORD_SET(meandk) THEN BEGIN fexp=FIX(STRMID(files(i),STRLEN(files(i))-7,3)) rdmeandk,cam,fexp,meandk ENDIF im=(im-meandk)>0 ENDELSE ENDIF ELSE BEGIN IF NOT KEYWORD_SET(meandk) THEN BEGIN fexp=FIX(STRMID(files(i),STRLEN(files(i))-7,3)) rdmeandk,cam,fexp,meandk ENDIF im=(im-meandk)>0 ENDELSE ENDIF ; If camera 0, subtract contamination image ; IF cam EQ 0 THEN im=(im-minim)>0 ; If autoscaling is desired, find lmaxi, otherwise use topnum IF topnum EQ 0 THEN BEGIN ; Is there any useful information left in the image? ; identify useful min and max values for byte-scaling ih=HISTOGRAM(im(wprad),MIN=0,BIN=1) ; histogram of exposed image cih=ih ; next line computes cumulative pixel value pdf FOR jj=1,N_ELEMENTS(cih)-1 DO cih(jj)=cih(jj)+cih(jj-1) cih=cih/FLOAT(MAX(cih)) ; normalize to unity lmaxi=MAX(WHERE(cih LE .999)) ; top 0.1% of pixels saturate ENDIF ELSE lmaxi=topnum ; if viewing filter images, take dark 'skirt' as min value IF filt LE 4 THEN BEGIN IF MAX(im(base) GT 0) THEN BEGIN bh=HISTOGRAM(im(base),MIN=0,BIN=1) maxbh=MAX(bh,lmaxbh) ; bottom = most prob. skirt value ENDIF ELSE lmaxbh=0 ENDIF ELSE BEGIN ; otherwise take lowest level in dark frame lmini=MIN(WHERE(cih GE .001)) lmaxbh=lmini ; rename this parameter for compatibility below ENDELSE ip=ip+1 ; index number for screen position of image ; show image orientation, one time only IF ip EQ 0 THEN BEGIN nflag=isnumber(KIh.misc.az,azimuth) IF nflag NE 0 THEN BEGIN ; if the camera azimuth is known, azrad=!DTOR*azimuth ; plot arrows showing the azimuth leftend=scl(res=120.,wwidth/2.)-twidthd/2. maxlen=(leftend-scl(res=120.,1.5*X_charwidth)) $ /scl(res=120.,(COS(azrad)+SIN(azrad))*X_charheight) arlen=MIN([FIX(maxlen),4])*X_charheight tailx=REPLICATE(scl(res=120.,0.5*X_charwidth+SIN(azrad)*arlen),2) taily=REPLICATE(scl(res=120.,nincol*256),2) headx=[tailx(0)-scl(res=120.,arlen*SIN(azrad)), $ tailx(1)+scl(res=120.,arlen*COS(azrad))] heady=[scl(res=120.,nincol*256+arlen*COS(azrad)), $ scl(res=120.,nincol*256+arlen*SIN(azrad))] arrow,tailx,taily,headx,heady,/device,hsize=-0.2 XYOUTS,headx(0)+scl(res=120.,X_charwidth) $ ,MIN([heady(0),scl(res=120.,wheight-X_charheight)]) $ ,'N',ALIGNMENT=0,/DEVICE,CHARSIZE=csz XYOUTS,headx(1)+scl(res=120.,X_charwidth),heady(1),'E' $ ,ALIGNMENT=0.5,/DEVICE,CHARSIZE=csz ENDIF ELSE BEGIN ; otherwise show cardinal directions XYOUTS,scl(3*X_charwidth,res=120.) $ ,scl(nincol*256+3*X_charheight,res=120.) $ ,'N',/DEVICE,ALIGNMENT=0.5,CHARSIZE=csz XYOUTS,scl(res=120.,X_charwidth) $ ,scl(res=120.,nincol*256+1.5*X_charheight),'W' $ ,/DEVICE,ALIGNMENT=0.5,CHARSIZE=csz XYOUTS,scl(res=120.,5*X_charwidth) $ ,scl(res=120.,nincol*256+1.5*X_charheight),'E' $ ,/DEVICE,ALIGNMENT=0.5,CHARSIZE=csz XYOUTS,scl(res=120.,3*X_charwidth) $ ,scl(res=120.,nincol*256),'S',/DEVICE $ ,ALIGNMENT=0.5,CHARSIZE=csz ENDELSE ENDIF ; display the image mtv,ROTATE(im*mask,5),low=lmaxbh,high=lmaxi,res=120. $ ,(ip MOD ninrow)*256,(nincol-1-(ip MOD ninwin)/ninrow)*256 ; mtv,im*mask,low=lmaxbh,high=lmaxi,res=120. $ ; ,(ip MOD ninrow)*256,(nincol-1-(ip MOD ninwin)/ninrow)*256 ; display image sequence number XYOUTS,scl(res=120.,(ip MOD ninrow)*256+1) $ ,scl(res=120.,(nincol-(ip MOD ninwin)/ninrow)*256-1-X_charheight) $ ,ext_list(i),/DEVICE,ALIGNMENT=0.0,CHARSIZE=csz,COLOR=0.8*!D.N_COLORS ; and image time XYOUTS,scl(res=120.,(ip MOD ninrow)*256+1) $ ,scl(res=120.,(nincol-1-(ip MOD ninwin)/ninrow)*256+3+X_charheight) $ ,/DEVICE,ALIGNMENT=0.0,CHARSIZE=csz,COLOR=0.8*!D.N_COLORS $ ,STRING(itime(0:2),FORMAT='(I2.2,":",I2.2,":",I2.2)') ; and exposure time XYOUTS,scl(res=120.,(ip MOD ninrow)*256+1) $ ,scl(res=120.,(nincol-1-(ip MOD ninwin)/ninrow)*256+1) $ ,STRING(KIh.misc.exp_scale*KIh.exp.exposure/1000. $ ,FORMAT='(F5.1,1X,"s")'),/DEVICE,ALIGNMENT=0.0,CHARSIZE=csz $ ,COLOR=0.8*!D.N_COLORS ; and maximum displayed DN XYOUTS,scl(res=120.,((ip MOD ninrow)+1)*256-1) $ ,scl(res=120.,(nincol-(ip MOD ninwin)/ninrow)*256-1-X_charheight) $ ,STRING(FIX(lmaxi),FORMAT='("< ",I0.0," DN")') $ ,/DEVICE,ALIGNMENT=1.0,CHARSIZE=csz,COLOR=0.8*!D.N_COLORS ; and minimum displayed DN XYOUTS,scl(res=120.,((ip MOD ninrow)+1)*256-1) $ ,scl(res=120.,(nincol-1-(ip MOD ninwin)/ninrow)*256+1) $ ,STRING(FIX(lmaxbh),FORMAT='("> ",I0.0," DN")'),/DEVICE $ ,ALIGNMENT=1.0,CHARSIZE=csz,COLOR=0.8*!D.N_COLORS PRINT,'.',FORMAT='(A,$)' IF (ip+1) MOD ninwin EQ 0 THEN PRINT,'|',FORMAT='(A,$)' IF GET_KBRD(1) EQ 'q' THEN GOTO,DONE ENDFOR DONE: PRINT,'' END