; docformat = 'rst' ; ; NAME: ; ViSiON ; PURPOSE: ; Generate the figures and PDF of the IMCCE ViSiON service ;+ ; :Description: ; Generate the figures and pdf of the IMCCE ViSiON service. See ; Miriade documentation for more details: ; http://vo.imcce.fr/webservices/miriade/?vision ; ; :Categories: ; Ephemeris, VO, ViSiON ; ; :Params: ; PATH: in, optional, type=string ; The directory containing ViSiON ephemeris file ; ; :Returns: A flag indicative of the completions of tasks:: ; 0: Everything worked ; 1: The ViSiON file ('ephevision.dat') not found ; 2: The path does not exist ; 3: No target visible on any date ; 4: Night delimiter wrongly spelled ; 5: Horizon not found (either not registered or supplied file not found) ; 6: No target ; 11: Missing bash command: latex ; 12: Missing bash command: dvips ; 13: Missing bash command: ps2pdf ; 14: Error during bash execution ; ; :Keywords: ; mime: in, optional, type=string, default=from config.in ; Format of the ephemeris (pdf|votable|html), ; cuts: in, optional, type=structure, default=from config.in ; Contains the cuts defining the visibility window. Fields ; are:: ; .el.min: Minimum elevation (deg) ; .el.max: Maximum elevation (deg) ; .mag.min: Minimum apparent magnitude ; .mag.max: Maximum apparent magnitude ; .phase.min: Minimum solar phase angle (deg) ; .phase.max: Maximum solar phase angle (deg) ; .elong.sun: Minimum solar elongation (deg) ; .elong.moon: Minimum lunar elongation (deg) ; .diam.min: Minimum apparent diameter ; .diam.max: Maximum apparent diameter ; .diam.unit: Unit for apparent diameter ; .duration: Minimum time span during which conditions are met ; .event: Set night limits: sun|civil|nautic|astro ; sort: in, optional, type=string, default=ra ; Define the column used to sort entries (name|type|mv|diam|ra|dec) ; horizon: in, optional, type=string/structure ; Either a) the path to a file with an horizon in ViSiON ; format, b) the name of a telescope which horizons is stored ; in ViSiON sources, or c) a structure containing the horizon ; defined by either alt-Az or H-dec pairs. Fields are:: ; .az: Azimuth (deg) ; .alt: Altitude (deg) ; .h: Hour angle (deg) ; .dec: Declination (deg) ; conf: in, optional, type=structure or string ; Configuration structure (see visionLoadConfig) or path to it. ; debug: out, optional, type=string ; Path to a file in which ViSiON will push its running logs. ; showID: in, optional, type=boolean, default=0 ; Use the identifier from the user if set, the IAU name otherwise ; ; :Examples: ; Run ViSiON on local directory, output as PDF ; IDL> flag=ViSiON('./',mime='pdf') ; Run ViSiON on eproc default directory, output as html ; IDL> flag=ViSiON('~/Eproc/ephem/',mime='html') ; Run ViSiON on local directory, with ; IDL> flag=ViSiON('~/Eproc/ephem/',mime='html') ; ; :Uses: ; visionLoadConfig, visionReadObs, visionReadBase, ; visionReadNight, visionReadTarget, ; visionOpenElevation, visionPlotTwilight, visionPlotElevation, ; visionOpenallsky, visionPlotHorizon, visionPlotAllSky, visionCloseGraphic ; date_conv, readcol, ; ; NB: vision requires latex, dvips (with pst-tools), and ps2pdf ; ; :Author: ; B.Carry (OCA) ; ; :History: ; Change History:: ; Original Version written in March 2012, B. Carry (ESA) & J. Berthier (IMCCE) ; 2014 Oct. - B. Carry (IMCCE) - Links to detailed ephemeris added ; 2014 Oct. - B. Carry (IMCCE) - Bug on Sun/Moon elongation corrected ; 2014 Apr. - B. Carry (IMCCE) - Comet are drawn on sky views ; 2015 Feb. - B. Carry (IMCCE) - Caption added for tables for readability in multi-dates output ; 2015 Mar. - B. Carry (IMCCE) - Horizon Caption & Drawing Added ; 2015 Nov. - B. Carry (OCA) - Compile option idl2 added ; 2018 Feb. - B. Carry (OCA) - Added showID keyword ;- function ViSiON, path, mime=mime, cuts=cuts, sort=sort, showID=showID, $ horizon=horizon, conf=conf, debug=debug COMPILE_OPT hidden, idl2 !Quiet=1 ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--- TAG --- I -- Initialization And Input Verification -----------------------; ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--I.1-- Input Directory --------------------------------------------------------------------- if not keyword_set(path) then path ='./' else path=strtrim(string(path,format='(A)'),2) if not file_test(path) then begin message, 'Target directory does not exist: '+strtrim(path,2) return, 2 endif ;--I.2-- Input Ephemeris --------------------------------------------------------------------- ephemFile = path+'ephevision.dat' if not file_test(ephemFile,/read) then begin message, 'Ephemeris file not found: '+strtrim(ephemFile,2) return, 1 endif ;--I.3-- Default Configuration --------------------------------------------------------------- ;--I.3.1-- ViSiON Sources Directory visionPATH = routine_filepath( 'vision', /Is_Function ) visionPATH = strMid( visionPATH, 0, strlen(visionPATH)-10) ;--I.3.2-- File Extensions sufEPS = '.eps' sufPNG = '.png' ;--I.3.3-- Log location if not keyword_set(debug) then debug='/dev/null' ;--I.4-- Read Configuration File ------------------------------------------------------------- confDefault = visionLoadConfig(visionPATH+'config.ini') ;--I.4.1-- Use Default Configuration if not keyword_set(conf) then conf=confDefault else begin dimC=size(conf) ;--I.4.2-- Use Provided Configuration if dimC[dimC[0]+1] eq 8 then begin conf = updateStructure( confDefault, conf ) ;--I.4.3-- Read & Use Provided Configuration endif else begin conf = visionLoadConfig( conf ) conf = updateStructure( confDefault, conf ) endelse endelse ;--I.5-- Selection Criteria ------------------------------------------------------------------ ;--I.5.1-- Complete Default Criteria if not keyword_set(cuts) then cuts = conf.select $ else cuts = updateStructure( conf.select, cuts ) cuts.duration /= (24.D*60.) ;-Convert into days ;--I.5.2-- Convert Apparent Diameter to Arcseconds diamSymb='\arcsec' case cuts.diam.unit of 'deg': diamSymb='\degr' 'min': diamSymb='\arcmin' 'sec': diamSymb='\arcsec' else: endcase ;--I.6-- Sort and Output Format -------------------------------------------------------------- ;--I.6.1-- Interpret input mime or set to default if keyword_set(mime) then begin mime=strLowCase(strtrim(mime,2)) conf.env.mime=mime endif else mime = strLowCase(conf.env.mime) ;--I.6.2-- Set sort option to default if not specified if keyword_set(sort) then begin sort=strLowCase(strtrim(sort,2)) conf.select.sort=sort endif else sort=strLowCase(conf.select.sort) ;--I.7-- Horizon Input ----------------------------------------------------------------------- if not keyword_set(horizon) then horizon=0 else begin dimH = size(horizon) ;--I.7.1-- Horizon is a Structure with Local Horizon if dimH[dimH[0]+1] eq 8 then begin ;--I.7.2-- Horizon is either a path or a telescope ID endif else begin ;--I.7.2/A-- Search through Register dirHor = visionPATH+'resources/horizons/' readcol, dirHor+'telescopes.dat', telID, file, format='(A,A)',skip=1,/silent match = where( strcmp(strtrim(telID,2),strtrim(horizon,2),/fold) ) ;--I.7.2/B-- Registered Horizon if match[0] ne -1 then horizon = visionReadHorizon(dirHor+file[match[0]]) $ ;--I.7.2/C-- User-Supplied File else begin if file_test(horizon,/read) then horizon = visionReadHorizon(horizon) $ else begin message, 'Horizon ('+strtrim(horizon,2)+') not found.' return, 5 endelse endelse endelse ;--I.7.3-- Interpolate Horizon Profile over 360 points nbPoints=361 theta = findgen(nbPoints) horAlt = interpol( horizon.alt, horizon.az, theta ) horizon = {alt: horAlt, $ az : theta*!DTOR} endelse ;--I.8-- Check Availability of latex/dvips/ps2pdf -------------------------------------------- if strcmp(mime,'pdf') then begin ;--I.8.1-- Define the list of commands cmd=['latex','dvips','ps2pdf'] nbCmd=n_elements(cmd) ;--I.8.2-- Test each command for kCmd=0, nbCmd-1 do begin spawn, 'command -v '+cmd[kCmd], res, err if strcmp(res, '') then begin message, /Information, 'Missing bash command: '+cmd[kCmd] return, 11+kCmd endif endfor endif ;-----------------------Rubish section margin=0.02D ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--- TAG --- II -- Read Miriade/ViSiON Ephemeris -----------------------; ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--II.1-- Read ViSiON Header: Observatory ---------------------------------------- obs = visionReadObs(ephemFile) ;--II.2-- Read ViSiON Header: Base parameters ------------------------------------ base = visionReadBase(ephemFile) if base.target le 0 then return, 6 ;--II.3-- Read ViSiON Body: Sun & Twilight --------------------------------------- night = visionReadNight(ephemFile, base.date) ;--II.4-- Read ViSiON Body: Target Ephemeris ------------------------------------- target = visionReadTarget(ephemFile, base) case cuts.diam.unit of 'deg': target.ephem.diam /= 3600. 'min': target.ephem.diam /= 60. else: endcase ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--- TAG --- III -- Define Visibility Periods -----------------------; ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--III.1-- Select Night Limits ---------------------------------------------------- for kDate=0, base.date-1 do begin ;--III.1-- Limits for Ephemeris Selection case cuts.event of 'sun': begin night[kDate].start.sel.jd = night[kDate].sun.set.jd night[kDate].close.sel.jd = night[kDate].sun.rise.jd end 'civil': begin night[kDate].start.sel.jd = night[kDate].twi.eve.civil.jd night[kDate].close.sel.jd = night[kDate].twi.mor.civil.jd end 'nautic': begin night[kDate].start.sel.jd = night[kDate].twi.eve.nautic.jd night[kDate].close.sel.jd = night[kDate].twi.mor.nautic.jd end 'astro': begin night[kDate].start.sel.jd = night[kDate].twi.eve.astro.jd night[kDate].close.sel.jd = night[kDate].twi.mor.astro.jd end else: return, 4 endcase ;--III.2-- Limits for Graphic Generation obsBeg = date_conv( night[kDate].sun.set.jd-margin, 'FITS') night[kDate].start.graph.iso = strmid( obsBeg,0,13)+':00:00' night[kDate].start.graph.jd = date_conv(night[kDate].start.graph.iso,'JULIAN') night[kDate].close.graph.jd = night[kDate].sun.rise.jd+night[kDate].sun.set.jd-night[kDate].start.graph.jd night[kDate].close.graph.iso = date_conv(night[kDate].close.graph.jd,'FITS') endfor ;--III.2-- Select Observing Epochs ------------------------------------------------ target = visionSelectEphem( target, night, cuts ) ;--III.3-- Links to VO Services --------------------------------------------------- link = visionTargetLink( target, night, obs=obs, conf=conf ) ;--III.4-- Loop over Observing Epochs --------------------------------------------- for kDate=0, base.date-1 do begin sDate=strmid(night[kDate].id.iso,0,10) ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--- TAG --- IV -- ViSiON Elevation Graphic -----------------------; ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--IV.1-- Filename Syntax -------------------------------------------------------- nameFigElev = conf.graph.elev.name + sDate + sufEPS nameVigElev = conf.thumb.elev.name + sDate + sufEPS ;--IV.2-- Main Plot -------------------------------------------------------------- ;--IV.2.1-- Open Graphic Environment visionOpenElevation, night[kDate], obs, conf=conf, dump=path+nameFigElev ;--IV.2.2-- Display Daylight and Twilights visionPlotTwilight, night[kDate], obs, conf=conf ;--IV.2.3-- Plot Target Elevation Curves for kTarget=0, base.target-1 do begin if target[kTarget].avg[kDate].vis ge float(cuts.duration)/base.step.val then $ visionPlotElevation, target[kTarget].info, target[kTarget].ephem[kDate,*], $ night[kDate], conf=conf, showID=keyword_set(showID) endfor ;--IV.2.4-- Close Graphic visionCloseGraphic ;--IV.3-- Thumbnail --------------------------------------------------------------- if conf.thumb.elev.show eq 1 then begin ;--IV.3.1-- Open Graphic Environment visionOpenElevation, night[kDate], obs, conf=conf, dump=path+nameVigElev, /THUMBNAIL ;--IV.3.2-- Display Daylight and Twilights visionPlotTwilight, night[kDate], obs, conf=conf, /THUMBNAIL ;--IV.3.3-- Plot Target Elevation Curves for kTarget=0, base.target-1 do begin if target[kTarget].avg[kDate].vis ge float(cuts.duration)/base.step.val then $ visionPlotElevation, target[kTarget].info, target[kTarget].ephem[kDate,*], night[kDate], conf=conf, /THUMBNAIL endfor ;--IV.3.4-- Close Graphic visionCloseGraphic, /THUMBNAIL endif ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--- TAG --- V -- ViSiON All-Sky Graphic -----------------------; ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--V.1-- Filename Syntax -------------------------------------------------------- nameFigSky = conf.graph.sky.name + sDate + sufEPS nameVigSky = conf.thumb.sky.name + sDate + sufEPS ;--V.2-- Main Plot -------------------------------------------------------------- ;--V.2.1-- Open Graphic Environment visionOpenAllSky, night[kDate], obs, conf=conf, dump=path+nameFigSky ;--V.2.2-- Display Horizon and Airmass Grid visionPlotHorizon, horizon, conf=conf ;--V.2.3-- Plot Target Alt/Az Curves for kTarget=0, base.target-1 do begin if target[kTarget].avg[kDate].vis ge float(cuts.duration)/base.step.val then $ visionPlotAllSky, target[kTarget].info, target[kTarget].ephem[kDate,*], $ night[kDate], conf=conf, showID=keyword_set(showID) endfor ;--V.2.4-- Close Graphic visionCloseGraphic ;--V.3-- Thumbnail --------------------------------------------------------------- if conf.thumb.sky.show eq 1 then begin ;--V.3.1-- Open Graphic Environment visionOpenAllSky, night[kDate], obs, conf=conf, dump=path+nameVigSky, /THUMBNAIL ;--V.3.2-- Display Horizon and Airmass Grid visionPlotHorizon, horizon, conf=conf, /THUMBNAIL ;--V.3.3-- Plot Target Alt/Az Curves for kTarget=0, base.target-1 do begin if target[kTarget].avg[kDate].vis ge float(cuts.duration)/base.step.val then $ visionPlotAllSky, target[kTarget].info, target[kTarget].ephem[kDate,*], night[kDate], conf=conf, /THUMBNAIL endfor ;--V.3.4-- Close Graphic visionCloseGraphic, /THUMBNAIL endif ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--- TAG --- VI -- Summary Tables -----------------------; ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--VI.1-- Night Selection -------------------------------------------------------- sel = where( (target.info.name ne 'Moon' and target.info.name ne 'Lune') and $ target.avg[kDate].vis ge float(cuts.duration)/base.step.val, nbSel ) night[kDate].vis = nbSel if nbSel eq 0 then goto, j2NextDate ;--VI.2-- Sort Entries ----------------------------------------------------------- ;--VI.2.1-- Single Sorting Parameter split=strlowcase(strtrim(strsplit(sort,'>',/extract,count=nbSplit),2)) if nbSplit eq 1 then begin nbType=1 key=split[0] locSel=ptr_new(indgen(nbSel)) ;--VI.2.2-- Two Sorting Parameters endif else begin if strcmp(split[0],'type') then begin uniqIndex= uniq( target[sel].info.type, sort(target[sel].info.type) ) uniqType = target[sel[uniqIndex]].info.type nbType = n_elementS(uniqType) key=split[1] locSel=ptrarr(nbType) for kType=0, nbType-1 do locSel[kType] = ptr_new(where( strcmp(target[sel].info.type,uniqType[kType] ) )) ;--VI.2.3-- Wrong syntax: Back to Single Sorting Parameter endif else begin nbType=1 key=split[0] locSel=ptr_new(indgen(nbSel)) endelse endelse ;--VI.2.4-- Build Sort Array (ord) from Primary Key Loop & Sort command select = 0 for kType=0, nbType-1 do begin loc = sel[*locSel[kType]] case key of ;--VI.2.4/A-- Apparent magnitude and Diameter 'mv': ord = sort( target[loc].avg[kDate].vmag ) 'diam': ord = sort( target[loc].avg[kDate].diam ) ;--VI.2.4/B-- Coordinates: Local, Horizontal, Equatorial, Galactic 'ra': ord = sort( target[loc].avg[kDate].JD ) 'dec': ord = sort( target[loc].avg[kDate].cEq.dec) 'rate': ord = sort( target[loc].avg[kDate].motion ) 'alt': ord = sort( target[loc].avg[kDate].cHor.alt) 'az' : ord = sort( target[loc].avg[kDate].cHor.az ) 'glon': ord = sort( target[loc].avg[kDate].cGal.lon) 'glat': ord = sort( target[loc].avg[kDate].cGal.lat) ;--VI.2.4/C-- Distances to observer & Sun 'dobs': ord = sort( target[loc].avg[kDate].dObs) 'dsun': ord = sort( target[loc].avg[kDate].dSun) ;--VI.2.4/D-- Phase and Elongation angles 'phase': ord = sort( target[loc].avg[kDate].phase) 'sune': ord = sort( target[loc].avg[kDate].elong.sun) 'moone': ord = sort( target[loc].avg[kDate].elong.moon) ;--VI.2.4/E-- Type of objects 'type': ord = sort(target[loc].info.type) else: ord=indgen(nbSel) endcase select = [select,loc[ord]] endfor ;--VI.3-- Export Selection to Tabular Format ------------------------------------- case mime of 'pdf': tabName = 'tab-eph-' + sDate + '.tex' 'votable': tabName = 'votable-' + sDate + '.xml' endcase visionExportEphem, target[select].info, link[select,kDate], target[select].avg[kDate], base, $ fig={sky:nameFigSky, elev:nameFigElev, label:strmid(night[kDate].id.iso,0,10)}, $ mime=mime, dump=path+tabName j2NextDate: endfor ;--III.4-- End of Loop over Observing Epochs ;--III.5-- Night Selection -------------------------------------------------------- sel = where( night.vis ne 0, nbSel ) if sel[0] eq -1 then return, 3 ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--- TAG --- VII -- LaTeX Front Page & Compilation -----------------------; ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; if strcmp(mime,'pdf',/fold) then begin ;--VII.1-- LaTeX Front Page ------------------------------------------------------- visionExportNight, path, night[sel] visionExportCut, path, cuts, conf=conf ;--VII.2-- Compile LaTeX Document ------------------------------------------------- spawn, 'cd '+path+' && '+$ ;-Go to path 'cp '+visionPATH+'resources/*eps . && '+ $ ;-Copy logos 'cp '+visionPATH+'resources/*sty . && '+ $ ;-Copy truncate.sty 'sed ''s/OBSERVATORY/'+obs.name+'/g'' '+$ ;-Copy main.tex visionPATH+'resources/main.tex > ' +$ ; with updated Observatory name './main.tex && '+ $ 'latex main.tex && '+$ ;-Compilation 'latex main.tex && '+$ ;-Compilation for labels 'dvips main.dvi && '+$ ;-DVI -> PS 'ps2pdf main.ps ViSiON.pdf', res, err ;-PS -> PDF ;--VII.3-- Check Everything Ran Ok ------------------------------------------------ nbRes=n_elements(res) if nbRes eq 1 then if res eq '' then return, 14 endif return, 0 end