; docformat = 'rst' ; ; NAME: ; shapeRmsOcc ; PURPOSE: ; Compute the RMS deviation between a 2-D profile and stellar occultation chords. ;+ ; :Description: ; Compute the RMS deviation between a 2-D profile and stellar occultation chords. ; ; :Categories: ; Shape Models, Occultations ; ; :Returns: The (model-chords) RMS ; ; INPUTS: ; XY: in, required, type=fltarr ; Cartesian coordinates of the profile ; OCC: in, required, type=structure ; The structure of the stellar occultation (single epoch). See ; readOcc for more details on the fields. ; ; :Keywords: ; weights: in, optional, type=fltarr ; An array of weight, one per chord, used to weight the RMS ; individual: in, optional, type=boolean, default=0 ; If set, returns an array of residuals between the model and each chord. ; ; :Examples: ; Read a model profile, and an occultation data, and compute the rms:: ; IDL> occ = readOcc( 'my_occultation_file' ) ; IDL> model = readVer( 'my_model_file' ) ; IDL> spin = readSpin( 'my_spin_file' ) ; IDL> sep = subObserver_coord( occ[0].xyz.pos, *spin[0],'iso_date_of_occultation', PA=PA, /LTC ) ; IDL> profile = shapeProfile( *model[0], sep=sep, ssp=sep, pa=pa ) ; IDL> rms = shapeRmsOcc( profile, occ[0] ) ; ; :Uses: ; interLine ; ; :Author: ; B.Carry (OCA) ; ; :History: ; Change History:: ; Original Version written in December 2013, B. Carry (IMCCE) ; 2014 Dec. - B.Carry (IMCCE) - IdlDoc ; 2016 Aug. - B.Carry (OCA) - Added idl2 compile option ; 2016 Aug. - B.Carry (OCA) - Added individual keyword ; 2016 Aug. - B.Carry (OCA) - Renamed after rmsOcc ;- function shapeRmsOcc, xy, occ, weights=weights, individual=individual COMPILE_OPT hidden, idl2 ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--- TAG --- I -- Initialization And Input Verification -----------------------; ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--I.1-- Check Input Parameters ------------------------------------------------------- if N_PARAMS() LT 2 then begin message, /IOERROR, 'Syntax : rms = shapeRmsOcc( xy, occ [, weights=])' return, -1 endif ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--- TAG --- II -- Analyse Input Occultation and Profile -----------------------; ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--II.1-- Identify Positive Chords ----------------------------------------------------- pos = where( (*occ.in)[*].flag ne -1 and (*occ.ex)[*].flag ne -1, nbPos, comp=neg, ncomp=nbNeg ) chordLen = fltarr(nbPos) ;--II.2-- Residual Arrays -------------------------------------------------------------- omc = fltarr(nbPos,2) rms = fltarr(nbPos) ;--II.3-- Profile Sides ---------------------------------------------------------------- nbSide = n_elements(xy)/2. ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--- TAG --- III -- Compute Occultation-Model Residuals -----------------------; ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; for kPos=0, nbPos-1 do begin ;--III.1-- Length of Current Chord ------------------------------------------------------ chordLen[kPos] = sqrt( ((*occ.in)[pos[kPos]].x-(*occ.ex)[pos[kPos]].x)^2. + $ ((*occ.in)[pos[kPos]].y-(*occ.ex)[pos[kPos]].y)^2. ) ;--III.2-- Search Chord-Side Intersection ----------------------------------------------- kFind=0 for kSide=0, nbSide-1 do begin ;--III.2.1-- Vertex Defining the Side V1 = kSide V2 = (kSide+1) mod nbSide ;--III.2.2-- Search Intersection with Chord intersect = interLine( [(*occ.in)[pos[kPos]].x,(*occ.in)[pos[kPos]].y], $ [(*occ.ex)[pos[kPos]].x,(*occ.ex)[pos[kPos]].y], $ xy[*,V1], xy[*,V2], $ flag=interFlag, dist=sep, /LINE1) ;--III.2.3-- Intersection Found if interFlag eq 1 or interFlag eq 2 then begin ;--III.2.3/A-- Store Residual omc[kPos,kFind] = sep kFind++ ;--III.2.3/B-- Second Intersection of the Chord --> Abort if kFind ge 2 then kSide=nbSide endif endfor ;--III.3-- Compute RMS for Current Chord ------------------------------------------------ ;--III.3.1-- Sort First and Second Intersection ord=sort(omc[kPos,*]) omcA = omc[kPos,ord[0]] omcB = omc[kPos,ord[1]] ;--III.3.2-- Current Squared Residual rms[kPos] = omcA^2. + (chordLen[kPos]-omcB)^2. endfor ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--- TAG --- IV -- Compute RMS and Return -----------------------; ;-----------------------------------------------------------------------------------------------; ;-----------------------------------------------------------------------------------------------; ;--IV.1-- Individual Residuals Output -------------------------------------------------------- if keyword_set( individual ) then begin return, sqrt(rms) ;--IV.2-- Average RMS Output ----------------------------------------------------------------- endif else begin ;--IV.2.1-- Chords have Different Weights if keyword_set(weights) then begin return, sqrt( total(rms*weights)/ total(2*weights) ) ;--IV.2.2-- All Chords are Weighted Equally endif else return, sqrt( total(rms)/(2*nbPos) ) endelse end ;--- CONFIG 0 - Case 1 ; -------------- ; ______ ; / \ ; | | ;--- CONFIG 1 - Case 2A ; ; ______ ; / \ ------- ; | | ;--- CONFIG 2 - Case 2B ; ; ______ ; ------- / \ ; | | ;--- CONFIG 3 - Case 3A ; _____ ; / \ ; | ----+-------- ;--- CONFIG 4 - Case 3B ; _____ ; / \ ; ----+-- | ;--- CONFIG 5 - Case 4 ; _____ ; / \ ; ----+------+-------- ;--- CONFIG 6 - Case 5 ; _____ ; / \ ; | --- | ;--III.4-- Compute RMS for Current Chord ------------------------------------------------ ; if keyword_set(FLAG) then begin ; ; config=0 ; ;-CONFIG 2A 3A 5 ; if v1 lt 0 then begin ; ; ;-CONFIG 2A ; if v2 lt 0 then begin ; config = 1 ; ; endif else begin ; ; ;-CONFIG 3A ; if v2-chordLen[kPos] lt 0 then begin ; config=3 ; ; ;-CONFIG 5 ; endif else begin ; config=6 ; ; endelse ; ; endelse ; ; ; endif else begin ; ; ;-CONFIGS 3B 4 ; if v1-chordLen[kPos] lt 0 then begin ; ; ;-CONFIG 4 ; if v2-chordLen[kPos] lt 0 then begin ; config=5 ; ; ;-CONFIG 3B ; endif else begin ; config=4 ; ; endelse ; ; endif else begin ; ; config=2 ; ; endelse ; ; endelse ; ; endif