; docformat = 'rst' ; ; NAME: ; PSV ; PURPOSE: ; Planetary Scene Viewer: creates a cube of images (FITS format) of ; the apparent aspect of a Solar System Object for a given observer and time span. ;+ ; :Description: ; Planetary Scene Viewer (PSV) creates a cube of images (FITS format) of ; the apparent aspect of a Solar System Object for a given observer and time span. ; ; :Categories: ; PSV, Visualization ; ; :Params: ; ID: in, required, type=integer/string ; Target identifyer (Name, Provisional designation, Number) ; ; :Returns: An image cube in FITS format ; ; :Keywords: ; config: in, optional, type=string ; Path to a configuration file ; ; type: in, optional, type=string, default='aster' ; Type of target (aster | planet | satel | comet), can be set ; alternatively with the optional keywords ASTEROID, PLANET, ; SATELLITE, COMET ; asteroid: in, optional, type=boolean, default=1 ; Set the target type to asteroid (equiv. to type='aster') ; planet: in, optional, type=boolean, default=0 ; Set the target type to planet (equiv. to type='planet') ; satellite: in, optional, type=boolean, default=0 ; Set the target type to satellite (equiv. to type='satel') ; comet: in, optional, type=boolean, default=0 ; Set the target type to comet (equiv. to type='comet') ; ; SO: in, optional, type=integer, default=1 ; Solution number for Spin and Shape model ; shape3d: in, optional, type=string ; Path to the working directory ; ; NBD: in, optional, type=integer, default=1 ; Number of dates of ephemeris to compute ; step: in, optional, type=string, default='1d' ; Step of increment followed by one of (d)ays or (h)ours or ; (m)inutes or (s)econds, e.g, '1.5h' ; EP: in, optional, type=double/string ; The starting epoch of the ephemeris ; ; observer: in, optional, type=string ; A spacecraft or IAU code of the observer (see Miriade ; webservice for more info about osberver's naming] ; resolution: in, optional, type=intarr(2) ; Dimensions of the output images (X x Y) ; FOV: in, optional, type=structure ; Dimension and orientation of the Field of View. Fields are:: ; .X: Size of the Field of View along x axis ; .Y: Size of the Field of View along y axis ; .UNIT: Unit for the size of the FoV (deg|min|sec) ; .PA: Rotation of the Field of View (from North to Y, direct sense, degrees) ; ; path: in, optional, type=string ; Path to the working directory ; file: in, optional, type=string ; Name of the output file ; ; ephem: in, optional, type=string ; Source of ephemeris (miriade|ephemph) ; maxFrame: in, optional, type=integer ; Maximum number of frames in the output file ; ; showStar: in, optional, type=boolean, default=0 ; Display stars within the FOV ; showSSO: in, optional, type=boolean, default=0 ; Display Solar System Objects within the FOV ; magLim: in, optional, type=float, default=10 ; Maximum magnitude to display (stars & SSOs) ; ; ; ; ; ; ; ERROR HANDLING: ; 0: no error ; 1: unknown solar system object ; 2: unknown configuration file ; 3: Number of frames (nbd=) to generate is too big (max=) ; 4: Cone-search radius for VizieR and SkyBoT () is too big (max=) ; ; 3: no VER file for requested Sso ; 4: the PSF file cannot be read ; 10: Miriade Web service returns an error: ; 11: ephemph program returns an error: ; 50: wget to VizieR service returns an error: ; 51: No star retrieved by VizieR service ; 60: wget to SkyBoT service returns an error: ; 61: No data in SkyBoT response ; 61: No Sso retrieved by SkyBoT service ; 62: SkyBoT returns an error (flag = -1) ; 63: No Sso retrieved by SkyBoT service ; ; :Uses: ; psvLoadConfig, ; ; :Author: ; J. Berthier (IMCCE) & B.Carry (IMCCE) ; ; :History: ; Change History:: ; Original Version written in May 2012, J-B. Valet (IMCCE) ; 2013-01-02: J. Berthier (IMCCE) - I/O cleaned ; 2014-01-10: B. Carry (IMCCE) - Comments in idldoc RST format ; 2014-06-10: B. Carry (IMCCE) - First 3-D view ;- function PSV, ID, config=config, $ ;-Target-related Variables type=type, planet=planet, asteroid=asteroid, satellite=satellite, comet=comet, $ ;-Shape Models-related Variables so=so, $ ;-Time-related Variables nbd=nbd, step=step, ep=ep, $ ;-Observer- and FOV-related Variables observer=observer, resolution=resolution, FOV=FOV, $ ;-Output Directory and File (todo rm?) path=path, file=file, $ ;-Display Options showStar=showStar, showSSO=showSSO, showLabel=showLabel, $ magLim=magLim, $ ;-General Configuration Parameters maxFrame=maxFrame, $ ;-Convolution with PSF Variables psf=psf, $ ; string - load a PSF or not {file | airy | seeing | 0} psffile=psffile, $ ; string - path name to the PSF fits file seeing=seeing, $ ; float - value of atmosphere seeing (arcsec) aperture=aperture, $ ; float - aperture of the optic device (m) wavelength=wavelength, $ ; float - observationnal wavelength (m) map=map, $ ; boolean - load an image map or not mapfile=mapfile, $ ; string - path name to the TIFF image file verbose=verbose ; boolean - to start verbose mode ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--- TAG --- I -- Initialization And Input Verification -----------------------; ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; COMPILE_OPT hidden verbose = 1 ;-debug MJD = 2400000.5D ;--I.1-- Global Initialization -------------------------------------------------- ; COMMON share, objVertex, objPolygons, barr, nbFacet ;BC todo: remove common share ; External programs ; GREP = 'grep' ; WGET = 'wget' errFlag = 0 if keyword_set(verbose) then verbose=1 else verbose=0 if verbose then begin print,'##################################################' print,'# - PSV 2014-06-11' print,'##################################################' endif ;--I.2-- Input Target ------------------------------------------------------------ target={type:'', id:'', num:0L, name:'' } ;BC todo: Allow target to be a fixed RA/DEC? ;--I.2.1-- Check for Presence if not keyword_set(ID) then begin errFlag = 1 message, /IOERROR, 'Error '+strtrim(string(errFlag,format='(I)'),2)+': unknown Solar System Object' return, errFlag endif ;--I.2.2-- Target Type (asteroid | comet | planet | satellite) if keyword_set(TYPE) then begin target.type = strtrim(type,2) endif else begin ;--I.2.2/A-- If Nothing Specified -> Target is an asteroid if not keyword_set(PLANET) AND $ not keyword_set(SATELLITE) AND $ not keyword_set(COMET) AND $ not keyword_set(ASTEROID) then asteroid=1 ;--I.2.2/B-- Choose from User-supplied Keywords if keyword_set(PLANET) then target.type = 'planet' if keyword_set(SATELLITE) then target.type = 'satel' if keyword_set(COMET) then target.type = 'comet' if keyword_set(ASTEROID) then target.type = 'aster' endelse ;--I.2.2/C-- Target type from ID input split=strsplit(ID,':',count=nbField,/EXTRACT) if nbField ne 1 then begin case split(0) of 'p': target.type = 'planet' 's': target.type = 'satel' 'c': target.type = 'comet' 'a': target.type = 'aster' else: endcase tempID=split(1) endif else begin tempID=ID endelse ;--I.2.3-- Target Name & Number planetName = ['Mercury', 'Venus', 'Earth', 'Mars', 'Jupiter', 'Saturn', 'Uranus', 'Neptune'] case target.type of ;--I.2.3/A-- Asteroids 'aster': begin if valid_num(tempID) then begin target.num = tempID target.id = strtrim(string(tempID,format='(I)'),2) target.name = designation(target.num) endif else begin target.name = tempID target.num = designation(target.name) if target.num gt 0 then $ target.id = strtrim(string(tempID,format='(I)'),2) $ else $ target.id = target.name endelse end ;--I.2.3/B-- Planets 'planet': begin if valid_num(tempID) then begin target.num = tempID target.name = planetName(target.num-1) endif else begin target.name = strlowcase(strtrim(tempID,2)) target.num = where( strcmp(target.name,planetName,/FOLD) )+1 endelse target.id = target.num end ;--I.2.3/C-- Comets 'comet': begin print, 'code comets in target interpretation' ;BC todo end ;--I.2.3/D-- Satellites 'satel': begin print, 'code satellite in target interpretation' ;BC todo end else: endcase ;--I.3-- Configuration Files ---------------------------------------------------- ;--I.3.1-- Path to PSV Directory psvPath = routine_filePath('psv', /IS_FUNCTION) psvPath = strmid(psvPath, 0, strlen(psvPATH)-7) ;--I.3.2-- Load PSV Defaults default = psvLoadConfig( psvPath+'conf/default.ini' ) ;--I.3.3-- Read User Supplied Configuration (override defaults) if keyword_set(CONFIG) then begin ;--I.3.3/A-- Find not Found if not file_test(CONFIG,/READ) then begin message, /IOERROR, 'Error 2: Configuration file not found: '+strtrim(config,2) return, 2 ;--I.3.3/B-- Complete Default Configuration with Supplied File endif else begin if verbose then print,'# - Loading configuration file: '+strtrim(CONFIG)+' ...' conf = psvLoadConfig( CONFIG, default ) endelse endif else conf = default ;--I.4-- Command-line Configuration --------------------------------------------- ;--I.4.1-- Observer and Field of View Variables if keyword_set(PATH) then conf.env.usr.cwd = strtrim(path,2) if keyword_set(FILE) then conf.env.usr.file = strtrim(file,2) ; if keyword_set(EPHEM) then conf.env.usr.ephem = strtrim(ephem,2) ;--I.4.2-- Observer and Field of View Variables if keyword_set(OBSERVER) then conf.obs.id = observer if keyword_set(RESOLUTION) then conf.obs.res = {x:resolution(0), y:resolution(1)} if keyword_set(FOV) then conf.obs.fov = updateStructure( conf.obs.fov, fov ) ;--I.4.3-- Timing Variables if keyword_set(NBD) then conf.time.nbd = nbd if keyword_set(STEP) then conf.time.step = step ;-todo code a function to interpret epoch (JD/ISO/now+-x) if keyword_set(EP) then conf.time.ep = epRead(ep) conf.time.iso = date_conv( conf.time.jd, 'FITS' ) ;--I.4.4-- Shape Models Repositery & Defaults if keyword_set(shape3d) then conf.shape.root = strtrim(shape3d,2) if keyword_set(so) then conf.shape.so = so ;--I.4.5-- Astronomical Catalogs and Variables case conf.astro.cone.unit of 'deg': coneSearch_degree = conf.astro.cone.size 'min': coneSearch_degree = conf.astro.cone.size / 60. 'sec': coneSearch_degree = conf.astro.cone.size / 3600. else: print, 'ARF - see code #1 :-)' endcase ;--I.4.6-- Graphical Output Variables if keyword_set(showStar) then conf.display.showStar = 1 if keyword_set(showSSO) then conf.display.showSSO = 1 if keyword_set(magLim) then conf.display.magLim = magLim ;--I.4.7-- PSV Variables if keyword_set(MAXFRAME) then conf.psv.maxFrame= MAXFRAME case conf.psv.cone.unit of 'deg': coneSearchMax = conf.psv.cone.size 'min': coneSearchMax = conf.psv.cone.size / 60. 'sec': coneSearchMax = conf.psv.cone.size / 3600. else: print, 'ARF - see code #2 :-)' endcase ;--I.5-- Dealing with Errors and Exceptions ------------------------------------- ;--I.5.1-- Number of Frames if conf.time.nbd gt conf.psv.maxFrame then begin message, 'Error 3: Number of frames (nbd = '+$ strtrim(string(conf.time.nbd,FORMAT='(I5)'),2)+' deg) is too large (max='+$ strtrim(string(conf.env.usr.maxFrame,FORMAT='(I4)'),2)+')' return, 3 endif ;--I.5.2-- ConeSearch if coneSearch_degree gt coneSearchMax then begin message, 'Error 4: Cone-search radius for VizieR and SkyBoT ('+$ strtrim(string(coneSearch_degree),2)+') is too large (max='+$ strtrim(string(coneSearchMax),2)+')' return, 4 endif ;--flagggg ;---- ;---- ;---- set_plot, 'Z' ;---- device, set_pixel_depth=24, $ ;---- set_resolution=[conf.obs.res.x, conf.obs.res.y], $ ;---- set_font='Times', $ ;---- decomposed=1 ;---- ;---- ;----help, /dev.reset ;---- plot, [0,conf.obs.res.x],[0,conf.obs.res.y], /DEVICE, $ ;---- position=[0,0,conf.obs.res.x,conf.obs.res.y], $ ;---- xst=1, $ ;---- yst=1, $ ;---- thick=4, $ ;---- color=cgColor('Yellow') ;---- ;---- ;---- oplot, [0,conf.obs.res.x],[conf.obs.res.y,0], $ ;---- color=cgColor('Purple'), thick=2 ;---- oplot, [0,conf.obs.res.x],[conf.obs.res.y,0]+100, $ ;---- color=cgColor('Blue'), thick=3 ;---- ;---- ;---- im=tvrd(true=1) ;----help, im ;----; imR=tvrd(channel=1,/WORD) ;----; imV=tvrd(channel=2,/WORD) ;----; imB=tvrd(channel=3,/WORD) ;----;help, imR, imV, imB ;---- ;---- ;----print, min(im),max(im) ;---- write_png, './test-label1.png', im ;---- ;---- device, /close ;---- im=tvrd() ;----help, im ;----print, min(im),max(im) ;---- ;----stop ;---- ;---- ;---- ;--I.6-- Input Summary for User ------------------------------------------------- if verbose then begin print,'# -' print,'# - Target : '+strtrim(target.name) print,'# - Observer : '+strtrim(string(conf.obs.ID),2) print,'# - Starting epoch (JD) : '+string(conf.time.jd,FORMAT='(F16.8)') print,'# - (ISO) : '+strtrim(conf.time.iso,2) print,'# - Ephemeris steps : '+strtrim(conf.time.step,2) print,'# - Nb frames to generate: '+strtrim(string(conf.time.nbd,FORMAT='(I)'),2) ; print,'# - Layers per frame : ',strtrim(string(jobstruct.nframes),2) print,'# - Cone-search radius : '+string(coneSearch_degree,format='(F6.4)')+' deg' endif ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--- TAG --- II -- List all SSOs in the FOV at all Epochs -----------------------; ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--II.1-- Target Ephemeris ------------------------------------------------------- ephemcc = voMiriade_callEphemcc( target.name, type=target.type, conf.time.jd, $ nbd=conf.time.nbd, step=conf.time.step, $ observer=conf.obs.ID ) ;--II.2-- Variable FOV ----------------------------------------------------------- ;todo ;--II.3-- SkyBoT Requests for Each Epoch ----------------------------------------- SSOs=ptrarr(conf.time.nbd,/ALL) ssoID = '' for kEp=0, conf.time.nbd-1 do begin *SSOs(kEp) = voSkybot_coneSearch(ephemcc(kEp).ra.dec, ephemcc(kEp).dec.dec, '32,min', $ ephemcc(kEp).JD, obs=conf.obs.ID ) ssoID = [ssoID,(*SSOs(kEp))(*).name] endfor ;--II.4-- Identify Unique & Resolved SSOs ---------------------------------------- ssoID = ssoID(1:n_elements(ssoID)-1) uniqSSO = ssoID( uniq(ssoID,sort(ssoID)) ) nbUniqSSO = n_elements(uniqSSO) flagSSO = intarr(nbUniqSSO) for kSSO=0, nbUniqSSO-1 do begin ;- 1 - retrieve diameter ;- 2 - compare diameter with minimum distance ;- 3 - decide resolve/unresolve depending on pixel scale ;- 4 - load models and spin endfor help, /stru, *SSOs(0) help, /stru, (*SSOs(0))(0).ra, (*SSOs(0))(0).dec stop ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--- TAG --- III -- Create Views of Stars & SSOs at Each Epoch -----------------------; ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; cube=fltarr(conf.obs.res.x,conf.obs.res.y,conf.time.nbd) for kEp=0, conf.time.nbd-1 do begin ;--III.1-- Astrometry Matrix ------------------------------------------------------ ps = [-conf.obs.fov.x/float(conf.obs.res.x), conf.obs.fov.y/float(conf.obs.res.y)] case conf.obs.fov.unit of 'min': ps /= 60. 'sec': ps /= 3600. else: endcase cdArr = [ [ cos(conf.obs.fov.pa*!DTOR), -sin(conf.obs.fov.pa*!DTOR)], $ [ sin(conf.obs.fov.pa*!DTOR), cos(conf.obs.fov.pa*!DTOR)]] astroMat = {NAXIS: [conf.obs.res.x, conf.obs.res.y], $ CD: cdArr, $ ;-Transformation matrix CDELT: ps, $ ;-Platescale (degree/pixel) CRPIX: [conf.obs.res.x, conf.obs.res.y]/2., $ ;-Reference pixel CRVAL: [ephemcc(kEp).ra.dec, ephemcc(kEp).dec.dec], $ ;-Coordinate at reference pixel CTYPE: ['RA---TAN', 'DEC--TAN'], $ ;-Coordinate system (Axis2) LONGPOLE: 180., $ LATPOLE: 90., $ PV2: [0., 0.], $ PV1: [0., 0., 90., 180., 90.], $ AXES: [1,2], $ REVERSE: byte(0), $ PROJECTION: 'TAN', $ COORDSYS: 'C', $ RADECSYS: 'FK5', $ EPOCH: 2000., $ DATEOBS: ephemcc(kEp).ISO, $ MJDOBS: ephemcc(kEp).JD-MJD, $ X0Y0: [0.d,0.d] } ;--III.2-- Background Stars ------------------------------------------------------- ;--III.1.1-- Request VizieR to Find Stars stars= voVizier_query(ephemcc(kEp).ra.dec, ephemcc(kEp).dec.dec, conf.obs.fov, $ conf.astro.star, vizier=conf.env.sys.vizier, $ mag=conf.display.magLim ) ;--III.1.2-- Number of Stars dimStar=size(stars) if dimStar(dimStar(0)+1) eq 8 then nbStar=0 $ else nbStar=n_elements(stars) ;--III.1.3-- Draw Stars if Requested and Present if conf.display.showStar eq 1 and nbStar ne 0 then begin ; gStar = psvDrawFOV(stars, conf.obs.res, astroMat, limit=conf.display.magLim) ; writefits, '~/data/test/psv/gstars.fits', gStar.im gStar = psvDrawFOV(stars, conf.obs.res, astroMat, limitingMagnitude=conf.display.magLim) writefits, '~/data/test/psv/gstars.fits', gStar endif ;--III.3-- UnResolved SSOs -------------------------------------------------------- ;--III.3.1-- Number of SSOs dimSSO=size(*SSOs(kEp)) if dimSSO(dimSSO(0)+1) eq 8 then nbSSO=0 $ else nbSSO=n_elements(*SSOs(kEP)) ;--III.1.3-- Draw SSOs if Requested and Present if conf.display.showSSO eq 1 and nbSSO ne 0 then begin ; gSSO = psvDrawFOV(SSOs, conf.obs.res, astroMat, limit=conf.display.magLim, type='sso' ) ; writefits, '~/data/test/psv/gssos.fits', gSSO.im gSSO = psvDrawFOV(SSOs, conf.obs.res, astroMat, limitingMagnitude=conf.display.magLim, type='sso' ) writefits, '~/data/test/psv/gssos.fits', gSSO endif ;--III.4-- Resolved SSOs ---------------------------------------------------------- dir3d = conf.shape.root+target.type+'/'+target.name+'/'+strtrim(string(conf.shape.so,format='(I)'),2)+'/' if file_test(dir3d,/DIR) then begin model = readVer( dir3d+'shape.dat',/edges) spin = readSpin( dir3d+'spin.dat') ephemph = voMiriade_callEphemph( target.name, type=target.type, ephemcc(kEp).JD, $ nbd=1, observer=conf.obs.ID, so=1 ) tilt=tilteceq(ephemcc(kEp).ra.dec, ephemcc(kEp).dec.dec) ephemph.pa = (ephemph.pa+tilt +360) mod 360 gRes = shapeShow3D( model, spin, conf.obs.res, fov=conf.obs.fov, ephem=ephemph ) cube(*,*,kEp)=gRes endif endfor writefits, '~/data/test/psv/gres.fits', cube ; ; Add info ; SXADDPAR, header, 'OBJECT' , strtrim(target,2) ," Object's name" ; SXADDPAR, header, 'CRPIX1' , resolution(0)/2. ,' (pix) Image X center' ; SXADDPAR, header, 'CRPIX2' , resolution(1)/2. ,' (pix) Image Y center' ; SXADDPAR, header, 'CTYPE1' , 'RA---TAN' ,' Coordinate system of axis' ; SXADDPAR, header, 'CTYPE2' , 'DEC--TAN' ,' Coordinate system of axis' ; SXADDPAR, header, 'EQUINOX' , 2000. ,' Standard FK5' ; SXADDPAR, header, 'RADECSYS', 'FK5' ,' FK5' ; SXADDPAR, header, 'TYPECOOR', 'UTC' ,' Coordinates type' ; SXADDPAR, header, 'CD1_1' , -viewfield(0) / resolution(0) ,' Translation matrix element' ; SXADDPAR, header, 'CD1_2' , 0 ,' Translation matrix element' ; SXADDPAR, header, 'CD2_1' , 0 ,' Translation matrix element' ; SXADDPAR, header, 'CD2_2' , viewfield(1) / resolution(1) ,' Translation matrix element' ; SXADDPAR, header, 'CRVAL1' , crval1(0) ,' Right ascension of the fiducial point' ; SXADDPAR, header, 'CRVAL2' , crval2(0) ,' Declinaison of the fiducial point' ; SXADDPAR, header, 'DATE-OBS', ISOdate ,' Ephemeris date ('+timescale+')' ; SXADDPAR, header, 'SR#' , sr ,' Pole solution number (APDT)' ; SXADDPAR, header, 'L_SEP' , lsep(kDate) ,' (deg) Sub-Earth Point longitude' ; SXADDPAR, header, 'B_SEP' , bsep(kDate) ,' (deg) Sub-Earth Point latitude' ; SXADDPAR, header, 'L_SSP' , lsun(kDate) ,' (deg) Sub-Solar Point longitude' ; SXADDPAR, header, 'B_SSP' , bsun(kDate) ,' (deg) Sub-Solar Point latitude' ; SXADDPAR, header, 'NP' , NP(kDate) ,' (deg) Target North pole position angle' ; SXADDPAR, header, 'RA' , ra(kDate)/!DTOR ,' (deg) Object Right Ascension' ; SXADDPAR, header, 'DEC' , dec(kDate)/!DTOR ,' (deg) Object Declination' ; SXADDPAR, header, 'DIST_OBS', Dg(kDate) ,' (AU) Object range to observer' ; SXADDPAR, header, 'DSUN_OBS', Dh(kDate) ,' (AU) Object heliocentric distance' ; SXADDPAR, header, 'VMAG' , Vmag(kDate) ,' Object V magnitude' ; SXADDPAR, header, 'PHOTO_X' , photoCenter(0) ,' (pix) Photocentre X position' ; SXADDPAR, header, 'PHOTO_Y' , photoCenter(1) ,' (pix) Photocentre Y position' ; SXADDPAR, header, 'OMEGA' , omega0 ,' (rad/s) Object Spin' ; SXADDPAR, header, 'RMAX' , Rmax ,' (km) Object maximum radius' ; SXADDPAR, header, 'RAPP' , objScale(1)*2.0 ,' (mas) Object apparent radius' ; SXADDPAR, header, 'RADSHIFT', vmoy ,' (km/s) Observed mean radial velocity' ; SXADDPAR, header, 'VROT' , v2moy ,' (km/s) Rotational velocity integral (abs(vrad))' ; SXADDPAR, header, 'MUSOL' , musol(kDate) ,' (km/s) Sun radial velocity' ; SXADDPAR, header, 'MURHO' , murho(kDate) ,' (km/s) Earth radial velocity' ; SXADDPAR, header, 'MURA' , mura(kDate) ,' ("/s) Earth RA velocity' ; SXADDPAR, header, 'MUDEC' , mudec(kDate) ,' ("/s) Earth DEC velocity' ; SXADDPAR, header, 'KMPIX' , Rmax*winScale/240 ,' (km) Plate scale (km per pixel)' ; SXADDPAR, header, 'VERFILE' , locname ," Source file for Object's Shape (.ver)" ; SXADDPAR, header, 'OVERSAMP', oversamp ,' Pixels Oversampling' ; ; No error return, cube END