;+ ; PROCEDURE: ; mms_eis_pad ; ; PURPOSE: ; Calculate pitch angle distributions using data from the MMS Energetic Ion Spectrometer (EIS) ; ; ; KEYWORDS: ; trange: time range of interest ; probes: value for MMS SC # ; species: proton (default), alpha, oxygen, electron ; energy: energy range to include in the calculation ; size_pabin: size of the pitch angle bins ; data_units: flux or cps ; datatype: extof, phxtof, electronenergy ; scopes: string array of telescopes to be included in PAD ('0'-'5') ; suffix: suffix used when loading the data ; num_smooth: should contain number of seconds to use when smoothing ; only creates a smoothed product (_pad_smth) if this keyword is specified ; ; EXAMPLES: ; ; ; OUTPUT: ; ; ; NOTES: ; This was written by Brian Walsh; minor modifications by egrimes@igpp and Ian Cohen (APL) ; ;$LastChangedBy: egrimes $ ;$LastChangedDate: 2017-11-21 14:31:32 -0800 (Tue, 21 Nov 2017) $ ;$LastChangedRevision: 24335 $ ;$URL: svn+ssh://thmsvn@ambrosia.ssl.berkeley.edu/repos/spdsoft/tags/spedas_2_1/projects/mms/eis/mms_eis_pad.pro $ ;- ; REVISION HISTORY: ; + 2015-10-26, I. Cohen : added "scopes" keyword to mms_eis_pad call-line to allow omittance of t3 (ions) & t2 (electrons) ; + 2015-11-12, I. Cohen : changed sizing of second dimension of flux_file and pa_file to reflect number of elements in "scopes" ; + 2015-12-14, I. Cohen : introduced data_rate keyword and conditional definition of prefix to handle burst data ; + 2016-1-8, egrimes : moved eis_pabin_info, mms_eis_pad_spinavg into separate routines; changed stops to returns ; + 2016-01-26, I. Cohen : added scope_suffix definition to allow for distinction between single telescope PADs ; : added to call to mms_eis_pad_spinavg.pro ; + 2016-02-26, I. Cohen : changed 'cps' units_label from 'Counts/s' to '1/s' for compliance with mission standards ; + 2016-04-29, egrimes : implemented suffix keyword, now allowing probes to be passed as an integer ; + 2016-09-19, E. Grimes : updated to support v3 L1b files ; + 2017-06-06, I. Cohen : added num_smooth keyword ; + 2017-10-18, I. Cohen : updated to incorporate finite angular width of telescopes (after mms_feeps_pad.pro); changed "size_pabin" ; keyword to "size_pabin" ; + 2017-11-17, I. Cohen : altered program to calculate PAD for each individual EIS channel within defined energy range, as well as ; integral over all defined energies; changed default energy range; added capability to combine PHxTOF and ; ExTOF proton data if user-defined energy range calls for it; changed PAD tplot variable names to use integers ; instead of double-precision numbers; added ability to handle multiple s/c at once and introduced call to ; mms_eis_pad_combine_sc.pro when doing so; replaced species keyword definition with species and removed species ; + 2017-11-20, E. Grimes : a few minor bug fixes caught by the test suite ;- pro mms_eis_pad,probes = probes, trange = trange, species = species, data_rate = data_rate, $ energy = energy, size_pabin = size_pabin, data_units = data_units, $ datatype = datatype, scopes = scopes, level = level, suffix = suffix, num_smooth = num_smooth ; compile_opt idl2 if not KEYWORD_SET(probes) then probes = '1' else probes = strcompress(string(probes), /rem) if not KEYWORD_SET(datatype) then datatype = 'extof' if not KEYWORD_SET(species) then species = 'proton' if (datatype eq 'electronenergy') then begin species = 'electron' flag_combine = 0 endif if not KEYWORD_SET(energy) then energy = [55,800] if not KEYWORD_SET(size_pabin) then size_pabin = 15 if not KEYWORD_SET(data_units) then data_units = 'flux' if not KEYWORD_SET(data_rate) then data_rate = 'srvy' else data_rate = strlowcase(data_rate) if not KEYWORD_SET(scopes) then scopes = ['0','1','2','3','4','5'] if not KEYWORD_SET(level) then level = 'l2' if not KEYWORD_SET(suffix) then suffix = '' if (species eq 'proton') then if (where(energy[1] gt 50) eq -1) or (where(energy[0] lt 50) eq -1) then begin flag_combine = 0 endif else begin flag_combine = 1 datatype = ['phxtof','extof'] endelse ; ; would be good to get this from the metadata eventually units_label = data_units eq 'cps' ? '1/s': '1/(cm!U2!N-sr-s-keV)' ; if (n_elements(scopes) eq 1) then scope_suffix = '_t'+scopes+suffix else if (n_elements(scopes) eq 6) then scope_suffix = '_omni'+suffix ; if energy[0] gt energy[1] then begin print, 'Low energy must be given first, then high energy in "energy" keyword' return endif ; ; set up the number of pa bins to create size_pabin = double(size_pabin) n_pabins = 180./size_pabin pa_bins = 180.*indgen(n_pabins+1)/n_pabins pa_label = 180.*indgen(n_pabins)/n_pabins+size_pabin/2. ; ; Account for angular response (finite field of view) of instruments pa_halfang_width = 10.0 ; [deg] delta_pa = size_pabin/2d ; dprint, dlevel=0, 'Num PA bins: ', string(n_pabins) dprint, dlevel=0, 'PA bins: ', string(pa_bins) ; status = 1 ; for pp=0,n_elements(probes)-1 do begin if (data_rate eq 'brst') then prefix = 'mms'+probes[pp]+'_epd_eis_brst_' else prefix = 'mms'+probes[pp]+'_epd_eis_' ; for dd=0,n_elements(datatype)-1 do begin ; ; check to make sure the data exist get_data, prefix + datatype[dd] + '_pitch_angle_t0'+suffix, data=d, index = index if (index eq 0) then begin print, 'No '+data_rate+' '+datatype[dd]+' data is currently loaded for MMS'+probes[pp]+' for the selected time period' status = 0 return endif ; ; if data exists continue if (status ne 0) then begin for species_idx = 0, n_elements(species)-1 do begin ; ; get pa from each detector get_data, prefix + datatype[dd] + '_pitch_angle_t0'+suffix, data = d pa_file = dblarr(n_elements(d.x),n_elements(scopes)) ; time x telescopes (look directions) pa_file[*,0] = d.y ; ; get_data,prefix+datatype[dd]+'_'+species+'_'+data_units+'_omni'+suffix,data=omni_data these_energies = where((omni_data.v ge energy[0]) and (omni_data.v le energy[1])) if (n_elements(these_energies) eq 0) then begin print, 'Energy range selected is not covered by the detector for ' + [dd] + ' ' + species[species_idx] + ' ' + data_units return endif flux_file = dblarr(n_elements(d.x),n_elements(scopes),n_elements(these_energies)) ; time x telescopes (look directions) x energy pa_flux = dblarr(n_elements(d.x),n_pabins,n_elements(these_energies)) + !Values.d_NAN ; time x bins x energy pa_num_in_bin = dblarr(n_elements(d.x),n_pabins,n_elements(these_energies)) ; time x bins x energy ; for t=0, n_elements(scopes)-1 do begin get_data, prefix + datatype[dd] + '_pitch_angle_t'+scopes[t]+suffix, data = d pa_file[*,t] = reform(d.y) ; ; use wild cards to figure out what this variable name should be for telescope 0 this_variable = tnames(prefix + datatype[dd] + '_' + species[species_idx] + '*_' + data_units + '_t0'+suffix) ; if level eq 'l2' || level eq 'l1b' then begin ; get the P# value from the name of telescope 0: pval_num_in_name = data_rate eq 'brst' ? 6 : 5 pvalue = (strsplit(this_variable, '_', /extract))[pval_num_in_name] if pvalue ne data_units then pvalue = pvalue + '_' else pvalue = '' endif else begin pvalue = '' endelse ; ; get flux from each detector get_data, prefix + datatype[dd] + '_' + species[species_idx] + '_' + pvalue + data_units + '_t'+scopes[t]+suffix, data = d dprint, dlevel=1, prefix + datatype[dd] + '_' + species[species_idx] + '_' + pvalue + data_units + '_t'+scopes[t]+suffix d.y[where(d.y eq 0.0)] = !Values.d_NAN ; ; get energy range of interest e = d.v[these_energies] ; flux_file[*,t,*] = d.y[*,these_energies] endfor ; ; CREATE PAD VARIABLES FOR EACH ENERGY CHANNEL IN USER-DEFINED ENERGY RANGE ; for i=0, n_elements(d.x)-1 do for j=0, n_pabins-1 do for ee=0,n_elements(these_energies)-1 do begin ind = where((pa_file[i,*] + pa_halfang_width ge pa_label[j]-delta_pa) and (pa_file[i,*] - pa_halfang_width lt pa_label[j]+delta_pa)) if (ind[0] ne -1) then pa_flux[i,j,ee] = average(flux_file[i,ind,ee], 2, /NAN) endfor pa_flux[where(pa_flux eq 0.0)] = !Values.d_NAN ; fill any missed bins with NAN ; for ee=0,n_elements(these_energies)-1 do begin energy_string = strcompress(string(fix(d.v[these_energies[ee]])), /rem) + 'keV new_name = prefix + datatype[dd] + '_' + energy_string + '_' + species[species_idx] + '_' + data_units + scope_suffix + '_pad' ; ; the following is because of prefix becoming a single element array in some cases if is_array(new_name) then new_name = new_name[0] ; store_data, new_name, data={x:d.x, y:reform(pa_flux[*,*,ee]), v:pa_label} options, new_name, yrange = [0,180], ystyle=1, spec = 1, no_interp=1, ytitle = 'MMS'+probes[pp]+' EIS ' + species[species_idx], ysubtitle=energy_string+'!CPA [Deg]', ztitle=units_label, minzlog=.01 zlim, new_name, 0, 0, 1 ; options, new_name, 'extend_y_edges', 1 endfor ; store_data, prefix + datatype[dd] + '_' + species[species_idx] + '_' + data_units + scope_suffix + '_pads', data={x:d.x, y:pa_flux, v1:pa_label, v2:omni_data.v[these_energies]} if (flag_combine ne 1) then begin ; ; CREATE PAD VARIABLE INTEGRATED OVER USER-DEFINED ENERGY RANGE ; energy_range_string = strcompress(string(fix(energy[0])), /rem) + '-' + strcompress(string(fix(energy[1])), /rem) + 'keV' new_name = prefix + datatype + '_' + energy_range_string + '_' + species[species_idx] + '_' + data_units + scope_suffix + '_pad' ; ; the following is because of prefix becoming a single element array in some cases if is_array(new_name) then new_name = new_name[0] avg_pa_flux = dblarr(n_elements(d.x),n_pabins) + !Values.d_NAN ; time x bins for tt=0,n_elements(d.x)-1 do for bb=0,n_pabins-1 do avg_pa_flux[tt,bb] = average(pa_flux[tt,bb,*],/NAN) ; store_data, new_name, data={x:d.x, y:avg_pa_flux, v:pa_label} options, new_name, yrange = [0,180], ystyle=1, spec = 1, no_interp=1, ytitle = 'MMS'+probes[pp]+' EIS ' + species[species_idx], ysubtitle=energy_range_string+'!CPA [Deg]', ztitle=units_label, minzlog=.01 zlim, new_name, 5e2, 1e4, 1 ; options, new_name, 'extend_y_edges', 1 ; now do the spin average mms_eis_pad_spinavg, probes=probes[pp], species=species[species_idx], datatype=datatype, energy=energy, data_units=data_units, size_pabin=size_pabin, data_rate = data_rate, scopes=scopes, suffix = suffix ; if ~undefined(num_smooth) then spd_smooth_time, new_name, newname=new_name+'_smth', num_smooth, /nan endif endfor endif endfor ; if (flag_combine eq 1) then begin mms_eis_combine_proton_pad, probes=probes[pp], data_rate = data_rate, data_units = data_units, size_pabin = size_pabin, energy = energy, suffix=suffix ; combined_var_name = tnames(prefix+'combined*proton*pad') ; now do the spin average mms_eis_pad_spinavg, probes=probes[pp], species='proton', datatype='combined', energy=energy, data_units=data_units, size_pabin=size_pabin, data_rate = data_rate, scopes=scopes, suffix = suffix ; if KEYWORD_SET(num_smooth) then spd_smooth_time, combined_var_name[0], newname=combined_var_name[0]+'_smth', num_smooth, /nan endif ; endfor ; if (n_elements(probes) gt 1) then mms_eis_pad_combine_sc, suffix=suffix, probes = probes, trange = trange, species = species, data_rate = data_rate, energy = energy, data_units = data_units ; end