;+ ;PROCEDURE: mvn_swe_topo ; ;PURPOSE: This routine provides topology based on the combination of ; shape parameters, and PAD info. ; 8 topology results are provided: ; 0 Unknown ; 1 Dayside Closed ; 2 Day-Night Closed ; 3 Night Closed -- Trapped/two-sided loss cone ; 4 Night CLosed -- Void ; 5 Day Open ; 6 Night Open ; 7 Draped ; ;USAGE: ; mvn_swe_topo,trange = trange, result=result, storeTplot = storeTplot, $ ; tbl = tbl, orbit = orbit, thrd_shp=thrd_shp,fthrd=fthrd, $ ; lcThreshold = lcThreshold, parng=parng, filter_reg=filter_reg ; ;INPUTS: ; None ; ;KEYWORDS: ; ; trange: Time range. If not given, it will automatically look ; for current tplot time range ; ; result: A structure that contains time and topology results. ; ; storeTplot: If set, it will create two tplot variables for topology, ; 'topo1' and 'topo_alt'. 'topo_alt' shows altitudes ; colored by topology. The default is set to be true. ; ; tbl: A color table for topology. The default is set to be ; [0,1,2,3,4,5,6,7] ; ; orbit: Use orbit number(s) to define the time range ; ; thrd_shp: The threshold for shape parameter to define ; photoelectrons. If shape < thrd_shp, it's identified ; as photoelectrons. The default value is 1. ; ; fthrd: Eflux (@ 40 eV) threshold to define electron voids. ; If Eflux(40 eV) < fthrd, defined as a void. The default ; value is 1.e5. ; ; lcThreshold: Threshold for loss cone. The default is set as 3.0. ; ; parng: Index for which PA range to choose for shape ; parameters. 1: 0-30 deg, 2: 0-45 deg, 3: 0-60 deg. ; The default is 0-30 deg. ; ; filter_reg: Using SWIA data to identify solar wind/sheath regions, ; by restoring save files created with 'mvn_swia_regid'. ; ID=1, solar wind; ID=2, sheath. The topology for these ; two regions will be overwritten with draped. The ; default is set to be true. ; ; quality: A 3-element array with quality flags: ; quality[0] : LPW potentials available (1=yes, 0=no) ; quality[1] : Shape parameter available (1=yes, 0=no) ; quality[2] : Padscore available (1=yes, 0=no) ; ; success: Returns 1 if topology information available (at whatever ; quality), 0 otherwise. ; ; $LastChangedBy: tweber $ ; $LastChangedDate: 2019-01-10 15:47:13 -0800 (Thu, 10 Jan 2019) $ ; $LastChangedRevision: 26451 $ ; $URL: svn+ssh://thmsvn@ambrosia.ssl.berkeley.edu/repos/spdsoft/tags/spedas_3_3/projects/maven/swea/mvn_swe_topo.pro $ ; ;CREATED BY: Shaosui Xu, 11/03/2017 ;FILE: mvn_swe_topo.pro Pro mvn_swe_topo,trange = trange, result=result, storeTplot = storeTplot, $ tbl = tbl, orbit = orbit, thrd_shp=thrd_shp,fthrd=fthrd, $ lcThreshold = lcThreshold, parng=parng, filter_reg=filter_reg, $ thrd_frat1 = thrd_frat, thrd_frat2 = thrd_frat2,quality=quality, success=success success = 0 quality = [0,0,0] padScoreFlag = 1 shapeFlag = 1 ;set the default to be creating tplot variables if (size(storeTplot,/type) eq 0) then storeTplot=1 $ else storeTplot=keyword_set(storeTplot) ;set the default to filter out sheath/solar wind regions with RegID if (size(filter_reg,/type) eq 0) then filter_reg=1 $ else filter_reg=keyword_set(filter_reg) if keyword_set(orbit) then begin imin = min(orbit, max=imax) trange = mvn_orbit_num(orbnum=[imin-0.5,imax+0.5]) endif if ~keyword_set(trange) then begin tplot_options, get_opt=topt tspan_exists = (max(topt.trange) gt time_double('2013-11-18')) if tspan_exists then trange = topt.trange else begin print, 'Must provide either a time range, orbit numbers, ' $ +'or have a current tplot timerange to use' return endelse endif if (size(parng,/type) eq 0) then parng=1 ;PA=30 mvn_swe_shape_restore,trange,results=data,tplot=1,parng=parng if (size(data,/type) eq 8) then begin quality[0:1] = 1 ;now convert to index to be used directly parng = parng - 1 ;create indices for shape parameter if (size(thrd_shp,/type) eq 0) then thrd_shp=1. ;default threshold for shape par if (size(fthrd,/type) eq 0) then fthrd=1.e5 ;default threshold for e- voids if (size(lcThreshold,/type) eq 0) then lcThreshold = 3.0 if (size(tbl,/type) eq 0) then tbl=[0,1,2,3,4,5,6,7] if (size(thrd_frat,/type) eq 0) then thrd_frat = 0.2;0.35;0.75 if (size(thrd_frat2,/type) eq 0) then thrd_frat2 = 5;3.5;2 shp_away=reform(data.shape[0,parng]) ;away shape parameter shp_twd=reform(data.shape[1,parng]) ;twd shape parameter f40 = reform(data.f40) ;eflux at 40 eV, used to determine e- voids npts = n_elements(shp_away) jshp_away=bytarr(npts) inna = where(shp_away ne shp_away,nac,com=ina,ncom=ac) ;if not NAN, below threshold, j=0, else j=1 if ac gt 0 then jshp_away[ina] =[floor(shp_away[ina]/thrd_shp)] < 1 ;if ac gt 0 then jshp_away[ina] = min([floor(shp_away[ina]/thrd_shp),1]) ;set NANs to j=2 if nac gt 0 then jshp_away[inna] = 2 jshp_twd=bytarr(npts) innt = where(shp_twd ne shp_twd,ntc,com=ints,ncom=tc) ;if not NAN, below threshold, j=0, else j=1 if tc gt 0 then jshp_twd[ints] = [floor(shp_twd[ints]/thrd_shp)] < 1 ;if tc gt 0 then jshp_twd[ints] = min([floor(shp_twd[ints]/thrd_shp),1]) ;set NANs to j=2 if ntc gt 0 then jshp_twd[innt] = 2 jf=bytarr(npts) ; innf = where(f40 ne f40 or f40 eq 0.0,nfc,com=inf,ncom=fc) innf = where(f40 ne f40,nfc,com=inf,ncom=fc);some voids have f40=0 as well, need another fix ;if not NAN, below threshold, j=0, else j=1 if fc gt 0 then jf[inf]=[floor(f40[inf]/fthrd)] < 1 ;if fc gt 0 then jf[inf]=min([floor(f40/fthrd),1]) ;set NANs to j=2 if nfc gt 0 then jf[innf]=2 numShp = n_elements(jshp_away) endif else begin print,"Warning: PAD Shape not available!" shapeFlag = 0 return endelse ;-----from PAD-------- ;jupz, assuming 1 being lc, 0 being non lc ;jdnz, assuming 1 being lc, 0 being non lc mvn_swe_pad_lc_restore, trange = trange, result = padLC if (n_elements(padLC) gt 0L) then begin quality[2] = 1 ;coAddNum = 4 jupz = bytarr(numShp) LCUpProcessed = bytarr(n_elements(padLC)) badUp = where(~finite(padLC[*].zScoreUp), numBadUp, $ complement = goodUp, ncomplement = numGoodUp) if numGoodUp gt 0 then LCUpProcessed[goodUp] = $ (padLC[goodUp].zScoreUp lt (-1 * lcThreshold)) if numBadUp gt 0 then LCUpProcessed[badUp] = 2 jdnz = bytarr(numShp) LCDownProcessed = bytarr(n_elements(padLC)) badDown = where(~finite(padLC[*].zScoreDown), numBadDown, $ complement = goodDown, ncomplement = numGoodDown) if numGoodDown gt 0 then LCDownProcessed[goodDown] = $ (padLC[goodDown].zScoreDown lt (-1 * lcThreshold)) if numBadDown gt 0 then LCDownProcessed[badDown] = 2 ;index = nn(padLC.time,data.t) ;jupz = LCUpProcessed[index] ;jdnz = LCDownProcessed[index] ;gap = where(abs(data.t-padLC[index].time) ge 16,count) ;>16s jupz = interp(LCUpProcessed,padLC.time,data.t,/no_extra,interp_thre=16) jdnz = interp(LCDownProcessed,padLC.time,data.t,/no_extra,interp_thre=16) gap = where(jupz ne jupz,count) if count gt 0L then begin jupz[gap] = 2 jdnz[gap] = 2 endif endif else begin print,"Warning: PAD Score not available!" padScoreFlag = 0 jupz = replicate(2B, numShp) ; fill with unknowns jdnz = replicate(2B, numShp) ; fill with unknowns endelse ;------Previous interpolation... Ignore this for now------ ; time_interp = value_locate(padLC[*].time, data[*].t) ; time_interp[where(time_interp eq -1)] = 0 ; ; jupz = time_interp[LCUpProcessed] ; jdnz = time_interp[LCDownProcessed] ;----Interpolate... without using nn.pro ; for i = 0, numshp-1 do begin ; dummy = min(abs(data[i].t - padLC[*].time), index) ; jupz[i] = LCUpProcessed[index] ; jdnz[i] = LCDownProcessed[index] ; endfor ;-----for day/night--- ;this index is place holder, will not change topo results regardless ;if it's on dayside or night. it's set to be 1 here. jdn = bytarr(npts) ;jdn[*] = 1 ;-----enlisting this index for field-aligned flux ratio--- ;this is a proxy to find loss cone to distinguish draped and open to night fratio=reform(data.fratio_a2t[0,parng]) ;0--low energy, 1--high energy inna = where(fratio ne fratio,nac,com=ina,ncom=ac) ;thrd_frat = 0.35 ;could be converted to a nob, find dn lc ;thrd_frat2 = 3 ; to find upward beamed, find x-term on dayside ;if not NAN, below threshold, j=0, else j=1 inlc=jdn inbm=jdn if ac gt 0L then begin inlc[ina] = [floor(fratio[ina]/thrd_frat)] < 1;0--lc, 1--no lc inbm[ina] = [floor(fratio[ina]/thrd_frat2)] < 1 ; 0--ratthrd2 jdn[ina] = inlc[ina] + inbm[ina] ; 0--lc, 1-- isotropic, 2--upward beamed endif if nac gt 0L then jdn[inna] = 3 topo_mtrx = topomtrx();(tbl = tbl) topo=topo_mtrx[jshp_away,jshp_twd,jf,jupz,jdnz,jdn] toponame=['0-?','1-CD','2-CX','3-CT','4-CV','5-OD','6-ON','7-D'] if keyword_set(filter_reg) then begin mvn_swe_regid_restore,trange,res=regid,/tplot if (size(regid,/type) eq 8) then begin inxp=nearest_neighbor(regid.time,data.t,gap=16D,/no_extrap) idtmp=regid.id id=idtmp[inxp] inv=where(inxp ne inxp,count) if (count gt 0L) then id[inv]=0 infilter = where(id eq 1 or id eq 2,count) ; 1--solar wind, 2--sheath if (count gt 0L) then topo[infilter] = 7 ; overwrite these regions to draped endif get_data,'reg_id',data=reg_id,index=i if (i gt 0) then begin indx = where(reg_id.y gt 3, count) if (count gt 0) then reg_id.y[indx] -= 1 store_data,'reg_id',data=reg_id idname = ['?','SW','Sheath','Iono','Lobe'] store_data,'reg_id_lab',data={x:trange, y:replicate(!values.f_nan,2,5), v:indgen(5)} options,'reg_id_lab','labels',idname options,'reg_id_lab','labflag',1 options,'reg_id_lab','colors',replicate(!p.color,5) options,'reg_id','colors',4 store_data,'reg_ids',data=['reg_id_lab','reg_id'] ylim,'reg_ids',-0.5,4.5,0 options,'reg_ids','ytitle','Region' options,'reg_ids','yminor',1 endif endif result = {time:data.t, topo:topo, toponame:toponame} if keyword_set(storeTplot) then begin store_data, 'topo', data = {x:data[*].t, y:topo} options, 'topo', 'psym', 4 options, 'topo', 'symsize', 0.5 ylim, 'topo', 0, 8, 0 alttopo = replicate(!values.f_nan,n_elements(data),8) ;ft=['unknown','cls-day','cls-d2n','cls-trp','void','opn2d','opn2n','drp'] ft=['0-unkn','1-cls-day','2-cls-d2n','3-cls-trp','4-void',$ '5-opn2d','6-opn2n','7-drp'] ; Create a tplot variable for all topology labs=ft clr=[!p.background,tbl[1:7]] psym=[3,1,1,3,3,1,3,3] sysz=[1,0.5,0.5,1,1,0.5,1,1] store_data,'topo_lab',data={x:minmax(data.t),y:replicate(!values.f_nan,2,8)} options,'topo_lab','labels',toponame;labs options,'topo_lab','colors',clr options,'topo_lab','labflag',1 store_data,'topo1',data=['topo','topo_lab'] options,'topo1','ytitle','Topology' ylim, 'topo1', -0.5, 7.5, 0 for i=1,7 do begin inj=where(topo eq i,count) if count gt 0L then begin alttopo[inj,i] = data[inj].alt endif ename='alt_'+ft[i] store_data,ename,data={x:data.t,y:alttopo[*,i]} options,ename,'color',clr[i] options,ename,'psym',psym[i] options,ename,'symsize',sysz[i] endfor store_data,'topo_alt',data=['topo_lab','alt_'+ft[1:7]] if padScoreFlag eq 1 then begin store_data,'PAD_LC',data={x:padLC.time, y:[[padLC.zScoreUp], [padLC.zScoreDown]]} options,'PAD_LC','ytitle',('PAD!cZ-Scores') options,'PAD_LC','labels',['Away','Towards'] options,'PAD_LC','labflag',1 options,'PAD_LC','constant',[0,2] ylim,'PAD_LC',-6, 6, 0 endif get_data,'rat_a2t',data=rat store_data,'frat_a2t',data={x:rat.x,y:reform(rat.y[*,0])} options,'frat_a2t',yrange=[0.1,10],constant=[thrd_frat,1,thrd_frat2],$ ytitle='flux ratio!C35-60 eV!Caway/twd!CPA 0-30',ylog=1 ;ytitle='flux ratio!C100-300 eV!Caway/twd!CPA 0-30',ylog=1 endif success = 1 return end