;+ ; ;PROCEDURE: MVN_STA_3D_SNAP ; ;PURPOSE: Plots 3D (angular) snapshots in a separate window ; for times selected with the cursor in a tplot window. ; Hold down the left mouse button and slide for a movie effect. ; This version uses 'plot3d' (or 'spec3d') on packaged 3D data. ; ;INPUTS: None. ; But the specified time (or [tmin, tmax]) is set, it ; automatically show the snapshot. In this case, the ; cursor does not appear in a tplot window. ; ;KEYWORDS: ; ; EBINS: Energy bins to plot (passed to plot3d). ; Default = ddd.nenergy. ; ; CENTER: Longitude and latitude of the center [lon, lat]. ; ; MAP: Mapping projection. See 'plot3d_options' for details. ; ; SPEC: Plots energy spectra using 'spec3d'. ; (Not working yet.) ; ; UNITS: Units for the 'spec3d'. ; (Not working yet.) ; ; ENERGY: One or more energies to plot. Overrides "EBINS". ; ; DDD: Named variable to hold a 3D structure including mass ; at the last time selected. ; ; SUM: If set, use cursor to specify time ranges for averaging. ; ; SMO: Sets smoothing in energy and angle. Since there are only ; 4 theta bins depending APIDs, smoothing in that dimension is not recommended. ; ; smo = [n_energy, n_phi, n_theta] ; default = [1,1,1] ; ; This routine takes into account the 360-0 degree wrap when ; smoothing (But not working yet). ; ; SUNDIR: Plots the direction of the Sun in STATIC coordinates. ; (Not working yet.) ; ; LABEL: If set, label the 3D angle bins. ; ; KEEPWINS: If set, then don't close the snapshot window(s) on exit. ; ; ARCHIVE: If set, show snapshots of archive data. ; ; BURST: Synonym for "ARCHIVE". ; ; MASK_SC: Masks solid angle bins that are blocked by the spacecraft. ; (Not working yet.) ; ; MASS: Selects ion mass/charge range to show. Default is all. ; ; MMIN: Defines the minimum ion mass/charge to use. ; ; MMAX: Defines the maximum ion mass/charge to use. ; ; M_INT: Assumes ion mass/charge. Default = 1. ; ; ERANGE: If set, plots energy ranges for averaging. ; ; WINDOW: Sets the window number to show. Default = 0. ; ; MSODIR: Plots the direction of the MSO axes in STATIC coordinates. ; ; APPDIR: Plots the direction of the APP boom in STATIC coordinates. ; ; APID: If set, specifies the APID data product to use. ; ; PLOT_SC: Overplots the projection of the spacecraft body. ; ; SWIA: Overplots the SWIA FOV in STATIC coordidates in ; order to make sure the FOV overlap each other. ; ; ZLOG: Sets a logarithmic color bar scaling. ; ; CT: Sets a color table number based on 'loadct2'. ; Default is 34 (Rainbow). ; ;NOTE: This routine is written based on partially 'swe_3d_snap' ; created by Dave Mitchell. ; ;USAGE EXAMPLES: ; 1. ; mvn_sta_3d_snap, erange=[0.1, 1.d4], wi=1, /mso, /app, /label, /plot_sc ; ; 2. ; ctime, t ; Clicks once or twice on the tplot window. ; mvn_sta_3d_snap, t, erange=[0.1, 1.d4], wi=1, /mso, /app, /label, /plot_sc ; ; 3. ; ctime, routine='mvn_sta_3d_snap' ; ;CREATED BY: Takuya Hara on 2015-02-11. ; ; $LastChangedBy: haraday $ ; $LastChangedDate: 2022-11-23 23:34:37 -0800 (Wed, 23 Nov 2022) $ ; $LastChangedRevision: 31295 $ ; $URL: svn+ssh://thmsvn@ambrosia.ssl.berkeley.edu/repos/spdsoft/tags/spedas_6_0/projects/maven/sta/mvn_sta_gen_snapshot/mvn_sta_3d_snap.pro $ ; ;- ;sub program FUNCTION mvn_sta_3d_snap_exponent, axis, index, number times = 'x' ;; A special case. IF number EQ 0 THEN RETURN, '0' ;; Assuming multiples of 10 with format. ex = STRING(number, format='(e8.0)') pt = STRPOS(ex, '.') first = STRMID(ex, 0, pt) sign = STRMID(ex, pt+2, 1) thisExponent = STRMID(ex, pt+3) ;; Shave off leading zero in exponent WHILE STRMID(thisExponent, 0, 1) EQ '0' DO thisExponent = STRMID(thisExponent, 1) ;; Fix for sign and missing zero problem. IF (Long(thisExponent) EQ 0) THEN BEGIN sign = '' thisExponent = '0' ENDIF IF (first EQ ' 1') OR (first EQ ' 1') THEN BEGIN first = '' times = '' ENDIF ;; Make the exponent a superscript. IF sign EQ '-' THEN BEGIN RETURN, first + times + '10!U' + sign + thisExponent + '!N' ENDIF ELSE BEGIN RETURN, first + times + '10!U' + thisExponent + '!N' ENDELSE END ;main program PRO mvn_sta_3d_snap, var1, var2, spec=spec, keepwins=keepwins, archive=archive, ebins=ebins, $ center=center, units=units, ddd=ddd, sum=sum, energy=energy, $ label=label, smo=smo, sundir=sundir, map=map, $ abins=abins, dbins=dbins, obins=obins, mask_sc=mask_sc, burst=burst, $ mass=mass, m_int=mq, erange=erange, window=window, msodir=mso, apid=id, $ appdir=app, mmin=mmin, mmax=mmax, plot_sc=plot_sc, swia=swia, $ _extra=extra, $ ; for 'plot3d_new' options. zlog=zlog, zrange=zrange, unnormalize=unnormalize, ct=ct COMMON mvn_c6 tplot_options, get_option=topt except = !except IF SIZE(var1, /type) NE 0 AND SIZE(var2, /type) EQ 0 THEN var2 = var1 IF SIZE(var2, /type) NE 0 THEN BEGIN trange = time_double(var2) IF SIZE(window, /type) EQ 0 THEN $ IF !d.window EQ topt.window THEN window = !d.window + 1 ELSE window = !d.window IF compare_struct(var1, var2) EQ 0 THEN BEGIN IF SIZE(mso, /type) EQ 0 THEN mso = 1 IF SIZE(app, /type) EQ 0 THEN app = 1 IF SIZE(plot_sc, /type) EQ 0 THEN plot_sc = 1 IF SIZE(label, /type) EQ 0 THEN label = 1 IF SIZE(erange, /type) EQ 0 THEN erange = [0.01, 40.d3] ; whole energy range ENDIF ENDIF IF keyword_set(archive) THEN aflg = 1 ELSE aflg = 0 IF keyword_set(burst) THEN aflg = 1 IF keyword_set(energy) THEN e1flg = 1 ELSE e1flg = 0 IF keyword_set(erange) THEN e2flg = 1 ELSE e2flg = 0 IF keyword_set(zrange) THEN unnormalize = 1 IF keyword_set(unnormalize) THEN BEGIN nocolorbar = 1 IF SIZE(zlog, /type) EQ 0 THEN zlog = 1 ENDIF IF ~keyword_set(ct) THEN ct = 34 IF (SIZE(units, /type) NE 7) THEN units = 'crate' IF (SIZE(map, /type) NE 7) THEN map = 'ait' IF keyword_set(mass) THEN mmin = MIN(mass, max=mmax) IF keyword_set(mmin) AND ~keyword_set(mmax) THEN mtit = STRING(mmin, '(F0.1)') + ' < m/q' IF keyword_set(mmax) AND ~keyword_set(mmin) THEN mtit = 'm/q < ' + STRING(mmax, '(F0.1)') IF keyword_set(mmin) AND keyword_set(mmax) THEN mtit = STRING(mmin, '(F0.1)') + ' < m/q < ' + STRING(mmax, '(F0.1)') IF SIZE(mtit, /type) EQ 0 THEN mtit = 'm/q = all' plot3d_options, map=map case strupcase(units) of 'COUNTS' : yrange = [1.,1.e5] 'RATE' : yrange = [1.,1.e5] 'CRATE' : yrange = [1.,1.e6] 'FLUX' : yrange = [1.,1.e8] 'EFLUX' : yrange = [1.e4,1.e9] 'DF' : yrange = [1.e-19,1.e-8] else : yrange = [0.,0.] endcase case n_elements(center) of 0 : begin lon = 180. lat = 0. end 1 : begin lon = center[0] lat = 0. end else : begin lon = center[0] lat = center[1] end endcase if keyword_set(spec) then sflg = 1 else sflg = 0 if keyword_set(keepwins) then kflg = 0 else kflg = 1 if (n_elements(smo) gt 0) then begin nsmo = [1,1,1] for i=0,(n_elements(smo)-1) do nsmo[i] = round(smo[i]) dosmo = 1 endif else dosmo = 0 if keyword_set(sum) then npts = 2 else npts = 1 ; Put up snapshot window(s) IF keyword_set(window) THEN wnum = window ELSE wnum = !d.window wi, wnum, wsize=[800, 600] ; Select the first time, then get the 3D spectrum closest that time IF SIZE(var1, /type) EQ 0 THEN print,'Use button 1 to select time; button 3 to quit.' wset, wnum IF SIZE(var2, /type) EQ 0 THEN ctime2, trange, npoints=npts, /silent, button=button $ ELSE IF N_ELEMENTS(var2) EQ 2 THEN sum = 1 ; if (size(trange,/type) eq 2) then begin ; Abort before first time select. ; if (sflg) then wdelete, wnum+1 ; wset, wnum ; return ; endif ok = 1 IF ~keyword_set(id) THEN BEGIN mode = mvn_c6_dat.mode mtime = mvn_c6_dat.time ENDIF func = 'mvn_sta_get' IF ~keyword_set(mmin) THEN mmin = 0 IF ~keyword_set(mmax) THEN mmin = 100. loadct2, ct, previous_ct=oldct init_swi = 1 WHILE (ok) DO BEGIN ;; Put up a 3D spectrogram wset, wnum IF ~keyword_set(id) THEN BEGIN idx = nn(mtime, trange) emode = mode[idx] emode = emode[uniq(emode)] IF N_ELEMENTS(emode) EQ 1 THEN BEGIN IF MEAN(trange) LT time_double('2015-07') THEN BEGIN CASE emode OF 1: IF (aflg) THEN apid = 'cd' ELSE apid = 'cc' 2: IF (aflg) THEN apid = 'cf' ELSE apid = 'ce' 3: IF (aflg) THEN apid = 'd1' ELSE apid = 'd0' 5: IF (aflg) THEN apid = 'd1' ELSE apid = 'd0' 6: IF (aflg) THEN apid = 'd1' ELSE apid = 'd0' ELSE: apid = 'ca' ENDCASE ENDIF ELSE IF (aflg) THEN apid = 'd1' ELSE apid = 'd0' ENDIF ELSE BEGIN dprint, 'The selected time interval includes multiple APID modes.' apid = 'ca' ENDELSE undefine, idx, emode ENDIF ELSE apid = id IF keyword_set(sum) THEN ddd = mvn_sta_get(apid, tt=trange) $ ELSE ddd = CALL_FUNCTION(func + '_' + apid, trange) IF ddd.valid EQ 1 THEN BEGIN IF keyword_set(mass) THEN BEGIN idx = where(ddd.mass_arr LT mass[0] OR ddd.mass_arr GT mass[1], nidx) IF nidx GT 0 THEN BEGIN ddd.cnts[idx] = 0. ddd.data[idx] = 0. ENDIF IF keyword_set(mq) THEN ddd.mass *= FLOAT(mq) ENDIF ddd = conv_units(ddd, units) ddd = sum4m(ddd) IF SIZE(var2, /type) NE 0 THEN $ IF SIZE(var1, /type) EQ SIZE(var2, /type) THEN $ IF compare_struct(var1, var2) EQ 1 THEN IF ((e1flg EQ 0) AND (e2flg EQ 0)) THEN energy = average(ddd.energy, 2) IF (SIZE(ddd, /type) EQ 8) THEN BEGIN data = ddd.data IF (e1flg) THEN BEGIN IF (e2flg) THEN BEGIN esweep = average(ddd.energy, 2) idx = WHERE(esweep GE MIN(erange) AND esweep LE MAX(erange), nidx) IF nidx GT 0 THEN BEGIN n_e = nidx ebins = idx ENDIF ELSE RETURN undefine, esweep, idx, nidx ENDIF ELSE BEGIN n_e = n_elements(energy) ebins = intarr(n_e) FOR k=0,(n_e-1) DO BEGIN de = MIN(ABS(ddd.energy[*,0] - energy[k]), j) ebins[k] = j ENDFOR ENDELSE ENDIF IF (e2flg) THEN BEGIN IF e1flg EQ 0 THEN BEGIN idx = where(ddd.energy[*, 0] GE erange[0] AND ddd.energy[*, 0] LE erange[1], nidx) IF nidx GT 0 THEN BEGIN ebins = idx[0] sebins = nidx ENDIF ELSE RETURN ENDIF ELSE sebins = 1 ENDIF ELSE sebins = 1 IF (SIZE(ebins, /type) EQ 0) THEN ebins = REVERSE(INDGEN(ddd.nenergy)) nbins = FLOAT(N_ELEMENTS(ebins)) IF N_ELEMENTS(ebins) GT 1 THEN nocolorbar = 0 plot3d_new, ddd, lat, lon, ebins=ebins, sum_ebins=sebins, $ _extra=extra, log=zlog, zrange=zrange, nocolorbar=nocolorbar lab2 = '' IF keyword_set(mso) THEN BEGIN vec = [ [1., 0., 0.], [0., 1., 0.], [0., 0., 1.] ] IF TOTAL(ddd.quat_mso) EQ 0. THEN $ FOR i=0, 2 DO append_array, vmso, TRANSPOSE(spice_vector_rotate(vec[*, i], MEAN(trange), 'MAVEN_MSO', 'MAVEN_STATIC', verbose=-1)) $ ELSE FOR i=0, 2 DO append_array, vmso, TRANSPOSE(quaternion_rotation(vec[*, i], qinv(ddd.quat_mso), /last_ind)) xyz_to_polar, vmso, theta=tmso, phi=pmso, /ph_0_360 PLOTS, pmso, tmso, psym=1, color=[2, 4, 6], thick=2, symsize=1.5 PLOTS, pmso+180., -tmso, psym=4, color=[2, 4, 6], thick=2, symsize=1.5 undefine, vec, vmso, tmso, pmso lab2 += ' Xmso (b) Ymso (g) Zmso (r) ' ENDIF IF keyword_set(app) THEN BEGIN IF TOTAL(ddd.quat_sc) EQ 0. THEN $ xsc = TRANSPOSE(spice_vector_rotate([1., 0., 0.], MEAN(trange), 'MAVEN_SPACECRAFT', 'MAVEN_STATIC', verbose=-1)) $ ELSE xsc = TRANSPOSE(quaternion_rotation([1., 0., 0.], qinv(ddd.quat_sc), /last_ind)) xyz_to_polar, xsc, theta=tsc, phi=psc, /ph_0_360 PLOTS, psc, tsc, psym=7, color=1, thick=2, symsize=1.5 undefine, xsc, tsc, psc lab2 += 'APP (m) ' ENDIF IF keyword_set(plot_sc) THEN $ mvn_spc_fov_blockage, trange=MEAN(trange), /static, clr=1, /invert_phi, /invert_theta IF keyword_set(label) THEN BEGIN lab = STRCOMPRESS(INDGEN(ddd.nbins), /rem) XYOUTS, REFORM(ddd.phi[ddd.nenergy-1, *]), REFORM(ddd.theta[ddd.nenergy-1, *]), lab, align=0.5 XYOUTS, !x.window[1], !y.window[0]*1.2, lab2, charsize=!p.charsize, /normal, color=255, align=1. XYOUTS, !x.window[1], !y.window[1]-!y.window[0]*0.5, '(+: Plus / -: Diamond) ', charsize=!p.charsize, /normal, color=255, align=1. ENDIF XYOUTS, !x.window[0]*1.2, !y.window[0]*1.2, mtit, charsize=!p.charsize, /normal, color=255 IF keyword_set(swia) THEN BEGIN status = EXECUTE("swicom = SCOPE_VARNAME(common='mvn_swia_data')") IF status EQ 1 THEN BEGIN IF (init_swi) THEN BEGIN status = EXECUTE('COMMON mvn_swia_data') init_swi = 0 ENDIF dcs = mvn_swia_get_3dc(MEAN(trange)) mk = spice_test('*') idx = WHERE(mk NE '', count) IF count EQ 0 THEN mk = mvn_spice_kernels(/load, /all, trange=trange, verbose=-1) undefine, idx, count mvn_pfp_cotrans, dcs, from='MAVEN_SWIA', to='MAVEN_STATIC', theta=tswi, phi=pswi, verbose=-1 ; Assuming that the color table is defined via 'loadct2'. cswi = bytescale(dcs.phi, bottom=7, top=254, range=[0., 360.]) lswi = [0., 90., 180., 270., 360.] clswi = bytescale(lswi, bottom=7, top=254, range=[0., 360.]) idx = WHERE(dcs.theta[dcs.nenergy-1, *] GT 0., nidx, complement=jdx, ncomplement=njdx) PLOTS, REFORM(pswi[dcs.nenergy-1, idx], nidx), REFORM(tswi[dcs.nenergy-1, idx], nidx), $ psym=6, color=REFORM(cswi[dcs.nenergy-1, idx], nidx) PLOTS, REFORM(pswi[dcs.nenergy-1, jdx], njdx), REFORM(tswi[dcs.nenergy-1, jdx], njdx), $ psym=5, color=REFORM(cswi[dcs.nenergy-1, jdx], njdx) undefine, dcs, tswi, pswi, cswi, idx, nidx, jdx, njdx XYOUTS, !x.window[0]*1.2, !y.window[1]-!y.window[0]*0.5, '(SWIA, +: Square / -: Triangle)', charsize=!p.charsize, /normal, color=255 FOR i=0, N_ELEMENTS(lswi)-1 DO $ XYOUTS, !x.window[0]*1.2 + 0.04*i, !y.window[1]-!y.window[0]*1.1, STRING(lswi[i], '(I0)'), charsize=!p.charsize, /normal, color=clswi[i] undefine, i, lswi, clswi ENDIF ELSE dprint, 'No SWIA data loaded.' undefine, status, swicom ENDIF if (sflg) then begin wset, wnum+1 spec3d, ddd, units=units, limits={yrange:yrange, ystyle:1, ylog:1, psym:0} endif endif IF keyword_set(unnormalize) AND N_ELEMENTS(ebins) EQ 1 THEN BEGIN IF keyword_set(zrange) THEN crange = zrange ELSE crange = minmax(TOTAL(data[ebins:ebins+sebins-1, *], 1), /pos) xposmax = 0. yposmax = 0. yposmin = 1. IF xposmax LT !x.window[1] THEN xposmax = !x.window[1] IF yposmax LT !y.window[1] THEN yposmax = !y.window[1] IF yposmin GT !y.window[1] THEN yposmin = !y.window[0] IF !p.charsize EQ 0 THEN chsz = 1 ELSE chsz = !p.charsize space = chsz * FLOAT(!d.x_ch_size)/!d.x_size colbar_pos =[xposmax+space, yposmin, xposmax+3*space, yposmax] !except = 0 draw_color_scale, range=crange, pos=colbar_pos, chars=chsz, log=zlog, ytickformat='mvn_sta_3d_snap_exponent' !except = except XYOUTS, colbar_pos[2], colbar_pos[3] + (colbar_pos[1]/!y.margin[0]), STRUPCASE(units), charsize=chsz, align=0.5, /normal undefine, crange ENDIF ;; Get the next button press ENDIF ELSE dprint, 'Click again.' wset, wnum IF SIZE(var2, /type) EQ 0 THEN BEGIN ctime2,trange,npoints=npts,/silent,button=button if (size(trange,/type) eq 5) then ok = 1 else ok = 0 ENDIF ELSE ok = 0 ENDWHILE loadct2, oldct if (kflg) then begin IF SIZE(var2, /type) EQ 0 THEN BEGIN wdelete, wnum if (sflg) then wdelete, wnum+1 ENDIF endif RETURN END