;+ ;PROCEDURE: mvn_swe_calib ;PURPOSE: ; Maintains SWEA calibration factors in a common block (mvn_swe_com). ; ;USAGE: ; mvn_swe_calib ; ;INPUTS: ; ;KEYWORDS: ; TABNUM: Table number (1-6) corresponding to predefined settings: ; ; 1 : Xmax = 6., Vrange = [0.75, 750.], V0scale = 1., /old_def ; primary table for ATLO and Inner Cruise (first turnon) ; -64 < Elev < +66 ; 7 < E < 4650 ; Chksum = 'CC'X ; ; 2 : Xmax = 6., Vrange = [0.75, 375.], V0scale = 1., /old_def ; alternate table for ATLO and Inner Cruise (never used) ; -64 < Elev < +66 ; 7 < E < 2340 ; Chksum = '1E'X ; ; 3 : Xmax = 5.5, Vrange = [3./Ka, 750.], V0scale = 0., /old_def ; primary table for Outer Cruise ; -59 < Elev < +61 ; 3 < E < 4630 ; Chksum = 'C0'X ; GSEOS svn rev 8360 ; ; 4 : Xmax = 5.5, Vrange = [2./Ka, 750.], V0scale = 1., /old_def ; alternate table for Outer Cruise ; -59 < Elev < +61 ; 3 < E < 4650 ; Chksum = 'DE'X ; GSEOS svn rev 8361 ; ; 5 : Xmax = 5.5, Vrange = [3./Ka, 750.], V0scale = 0. ; primary table for Transition and Science ; -59 < Elev < +61 ; 3 < E < 4630 ; Chksum = 'CC'X ; GSEOS svn rev 8481 ; ; 6 : Xmax = 5.5, Vrange = [2./Ka, 750.], V0scale = 1. ; alternate table for Transition and Science ; -59 < Elev < +61 ; 3 < E < 4650 ; Chksum = '82'X ; GSEOS svn rev 8482 ; ; Default = 3 (outer cruise, VO disabled). ; Passed to mvn_swe_sweep.pro. ; ; CHKSUM: Specify the sweep table by its checksum. See above. ; This only works for table numbers > 3. ; ; $LastChangedBy: dmitchell $ ; $LastChangedDate: 2014-11-26 17:16:52 -0800 (Wed, 26 Nov 2014) $ ; $LastChangedRevision: 16323 $ ; $URL: svn+ssh://thmsvn@ambrosia.ssl.berkeley.edu/repos/spdsoft/trunk/projects/maven/swea/mvn_swe_calib.pro $ ; ;CREATED BY: David L. Mitchell 03-29-13 ;FILE: mvn_swe_calib.pro ;- pro mvn_swe_calib, tabnum=tabnum, chksum=chksum @mvn_swe_com ; Set the SWEA Ground Software Version mvn_swe_version = 1 ; Find the first valid LUT ; chksum = 0B means SWEA has just powered on ; chksum = 255B means SWEA is loading tables ok = 0 if (not ok) then begin if keyword_set(tabnum) then begin swe_active_chksum = mvn_swe_tabnum(tabnum,/inverse) swe_chksum = replicate(swe_active_chksum,n_elements(swe_hsk)) if (swe_active_chksum ne 0B) then ok = 1 endif endif if (not ok) then begin if keyword_set(chksum) then begin swe_active_chksum = chksum tabnum = mvn_swe_tabnum(swe_active_chksum) swe_chksum = replicate(swe_active_chksum,n_elements(swe_hsk)) if (tabnum ne 0) then ok = 1 endif endif if (not ok) then begin if (size(swe_hsk,/type) eq 8) then begin nhsk = n_elements(swe_hsk) lutnum = swe_hsk.ssctl ; active LUT number swe_chksum = bytarr(nhsk) ; checksum of active LUT for i=0L,(nhsk-1L) do swe_chksum[i] = swe_hsk[i].chksum[lutnum[i] < 3] indx = where(lutnum gt 3, count) if (count gt 0L) then swe_chksum[indx] = 'FF'XB ; table load during turn-on indx = where((swe_chksum gt 0B) and (swe_chksum lt 255B), count) if (count gt 0L) then begin swe_active_chksum = swe_chksum[indx[0]] tabnum = mvn_swe_tabnum(swe_active_chksum) if (tabnum ne 0) then ok = 1 endif endif else print,"No SWEA housekeeping." endif if (not ok) then begin print,"No valid table number or checksum." print,"Cannot determine calibration factors." return endif print, tabnum, swe_active_chksum, format='("LUT: ",i2.2,3x,"Checksum: ",Z2.2)' ; Integration time per energy/angle bin prior to summing bins. ; There are 7 deflection bins for each of 64 energy bins spanning ; 1.95 sec. The first deflection bin is for settling and is ; discarded. swe_duty = (1.95D/2D)*(6D/7D) ; duty cycle (fraction of time counts are accumulated) swe_integ_t = 1.95D/(7D*64D) ; integration time per energy/deflector bin ; Analyzer constant (calibrations show 1.4% variation in azimuth caused ; by slight misalignment of the hemispheres) swe_Ka = 6.17 ; Energy Sweep ; Generate initial sweep table mvn_swe_sweep, tabnum=tabnum, result=swp ; Energy Sweep swe_swp = fltarr(64,3) ; energy for group=0,1,2 swe_swp[*,0] = swp.e for i=0,31 do swe_swp[(2*i):(2*i+1),1] = sqrt(swe_swp[(2*i),0] * swe_swp[(2*i+1),0]) for i=0,15 do swe_swp[(4*i):(4*i+3),2] = sqrt(swe_swp[(4*i),1] * swe_swp[(4*i+3),1]) ; Energy Resolution (dE/E, FWHM), which can be a function of elevation, ; so this array has an additional dimension. Calibrations show that the ; variation with elevation is modest (< 1% from +55 to -30 deg, increasing ; to 4% at -45 deg). swe_de = fltarr(6,64,3) ; energy resolution for group=0,1,2 for i=0,5 do swe_de[i,*,0] = swp.de * swp.e for i=0,31 do begin swe_de[*,(2*i),1] = (swe_swp[(2*i),0] + swe_de[*,(2*i),0]/2.) - $ (swe_swp[(2*i+1),0] - swe_de[*,(2*i+1),0]/2.) swe_de[*,(2*i+1),1] = swe_de[*,(2*i),1] endfor for i=0,15 do begin swe_de[*,(4*i),2] = (swe_swp[(4*i),0] + swe_de[*,(4*i),0]/2.) - $ (swe_swp[(4*i+3),0] - swe_de[*,(4*i+3),0]/2.) for j=1,3 do swe_de[*,(4*i+j),2] = swe_de[*,(4*i),2] endfor ; Deflection Angle swe_el = fltarr(6,64,3) ; 6 el bins per energy step for group=0,1,2 swe_el[*,*,0] = swp.theta for i=0,31 do begin swe_el[*,(2*i),1] = (swe_el[*,(2*i),0] + swe_el[*,(2*i+1),0])/2. swe_el[*,(2*i+1),1] = swe_el[*,(2*i),1] endfor for i=0,15 do begin swe_el[*,(4*i),2] = (swe_el[*,(4*i),1] + swe_el[*,(4*i+3),1])/2. for j=1,3 do swe_el[*,(4*i+j),2] = swe_el[*,(4*i),2] endfor ; Deflection Angle Range swe_del = fltarr(6,64,3) ; 6 del bins per energy step for group=0,1,2 ; SWEA calibrations (energy/angle response) p = { a0 : 7.579357236d+00, $ a1 : -1.735792405d-01, $ a2 : -3.795756270d-04, $ a3 : 4.389078897d-05, $ a4 : 5.688218987d-07, $ a5 : 0.0 } dtheta = abs(swp.th1 - swp.th2) ; elevations spanned over 4 deflector steps fwhm = polycurve(swp.theta, par=p) ; instrumental resolution at center elevation swe_del[*,*,0] = dtheta + fwhm ; elevation resolution of the 4 bins combined for i=0,31 do begin swe_del[*,(2*i),1] = (swe_del[*,(2*i),0] + swe_del[*,(2*i+1),0])/2. swe_del[*,(2*i+1),1] = swe_del[*,(2*i),1] endfor for i=0,15 do begin swe_del[*,(4*i),2] = (swe_del[*,(4*i),1] + swe_del[*,(4*i+3),1])/2. for j=1,3 do swe_del[*,(4*i+j),2] = swe_del[*,(4*i),2] endfor ; Alternate method, just make the bins touch with no gaps ; This seems to be what plot3d is expecting. for j=0,2 do for i=0,63 do swe_del[*,i,j] = median(swe_el[*,i,j] - shift(swe_el[*,i,j],1)) ; Azimuth Angle and Range ; From the rotation scan of 2013-02-27 at 1 keV. These are the centroids of the ; azimuth response function (F) of each anode: <az> = total(az*F(az))/total(F(az)) swe_az = [ 11.2470, 31.6462, 55.4238, 76.0096, 101.7052, 122.2142, $ 146.2746, 166.3412, 192.0000, 212.4004, 235.8170, 255.6995, $ 281.4268, 301.6986, 325.7882, 345.7588 ] swe_daz = (shift(swe_az,-1) - shift(swe_az,1))/2. swe_daz[[0,15]] = swe_daz[[0,15]] + 180. ; For now, override with nominal swe_az = 11.25 + 22.5*findgen(16) ; azimuth bins in SWEA science coord. swe_daz = replicate(22.5,16) ; nominal widths ; Pitch angle mapping lookup table mvn_swe_padlut, lut=lut, dlat=22.5 ; default at launch (maybe I will update) swe_padlut = lut ; Geometric Factor ; Simulations give a geometric factor of 0.032 (ignoring grids, posts, MCP ; efficiency, scattering, and fringing fields). ; ; posts : 0.84 (7 deg per post * 8 posts) ; entrance grid : 0.70 (for both grids combined) ; exit grid : 0.90 ; MCP Efficiency : 0.75 (nominal, energy dependent) ; ------------------------- ; product : 0.40 ; ; Total estimated geometric factor from simulations: 0.032 * 0.4 = 0.013 ; ; The measured geometric factor is 0.009 (IRAP calibration). When using V0, ; deceleration of the incoming electrons effectively reduces the geometric ; factor in an energy dependent manner (see mvn_swe_sweep for details). ; This geometric factor includes the absolute MCP efficiency, since it is ; based on analyzer measurements in a calibrated beam. geom_factor = 0.009/16. ; geometric factor per anode (cm2-ster-eV/eV) geom_factor = geom_factor/2.9 ; scale factor from cross calibration swe_gf = replicate(!values.f_nan,64,3) swe_gf[*,0] = geom_factor*swp.gfw for i=0,31 do swe_gf[(2*i):(2*i+1),1] = (swe_gf[(2*i),0] + swe_gf[(2*i+1),0])/2. for i=0,15 do swe_gf[(4*i):(4*i+3),2] = (swe_gf[(4*i),1] + swe_gf[(4*i+3),1])/2. ; Add a dimension for relative variation among the 16 anodes. This variation is ; dominated by the MCP efficiency, but I include the same dimension here for ease ; of calculation later. swe_gf = replicate(1.,16) # reform(swe_gf,64*3) swe_gf = transpose(reform(swe_gf,16,64,3),[1,0,2]) ; Relative MCP efficiency ; Note that absolute efficiency is incorporated into IRAP geometric factor. ; The efficiency is energy dependent, peaking at around 300 eV, then falling ; gradually with increasing energy. For SWEA, electrons are accelerated from ; the analyzer exit grid (V0) to the top of the MCP stack (+300 V). If one ; uses the electron energy before entering the instrument (E), then the effect ; of V0 cancels, so the energy of an electron when it strikes the top of the ; MCP stack is E + 300. ; ; The following is from Goruganthu & Wilson (Rev. Sci. Instr. 55, 2030, 1984), ; which fits experimental data up to 2 keV to within 2%. (There is a typo in ; Equation 4 of that paper.) I extrapolate from 2 to 4.6 keV. alpha = 1.35 Tmax = 2.283 Emax = 325. k = 2.2 Vbias = 300. ; pre-acceleration for SWEA Erat = (swe_swp + Vbias)/Emax ; effect of V0 cancels when using swe_swp arg = Tmax*(Erat^alpha) < 80. ; avoid underflow delta = (Erat^(1. - alpha))*(1. - exp(-arg))/(1. - exp(-Tmax)) swe_mcp_eff = (1. - exp(-k*delta))/(1. - exp(-k)) ; IRAP geometric factor was calibrated at 1.4 keV, so scale the MCP efficiency ; to unity at that energy. Erat = (1400. + Vbias)/Emax delta = (Erat^(1. - alpha))*(1. - exp(-Tmax*(Erat^alpha)))/(1. - exp(-Tmax)) eff0 = (1. - exp(-k*delta))/(1. - exp(-k)) swe_mcp_eff = swe_mcp_eff/eff0 ; Now include variation of MCP efficiency with anode. This is from a rotation ; scan at 1 keV performed on 2013-02-27. This is expected to change gradually ; in flight, with discrete jumps when the MCP HV is adjusted. swe_rgf = [0.86321, 1.09728, 1.04393, 0.88254, 0.95927, 1.07825, $ 1.07699, 0.93499, 1.04213, 1.12928, 1.11343, 0.94783, $ 0.87957, 0.96588, 1.00358, 0.98184 ] swe_mcp_eff = swe_rgf # reform(swe_mcp_eff,64*3) swe_mcp_eff = transpose(reform(swe_mcp_eff,16,64,3),[1,0,2]) ; Analyzer elevation response (from IRAP calibrations, averaged over the six ; elevation bins). Normalization: mean(swe_dgf) = 1. Note that rotation ; scans at different yaws in the large SSL vacuum chamber confirm behavior of ; this sort. p = { a0 : 5.417775771d-03, $ a1 : 1.911692997d-05, $ a2 : 1.067720924d-06, $ a3 : -2.341636265d-08, $ a4 : -4.758984454d-10, $ a5 : 3.831231544e-12 } theta = findgen(131) - 65. dgf = polycurve(theta,par=p) swe_dgf = fltarr(6,64,3) th_min = swp.th1 < swp.th2 th_max = swp.th1 > swp.th2 for i=0,5 do begin for j=0,63 do begin indx = where((theta ge th_min[i,j]) and (theta le th_max[i,j])) swe_dgf[i,j,0] = mean(dgf[indx]) endfor endfor for i=0,31 do begin swe_dgf[*,(2*i),1] = (swe_dgf[*,(2*i),0] + swe_dgf[*,(2*i+1),0])/2. swe_dgf[*,(2*i+1),1] = swe_dgf[*,(2*i),1] endfor for i=0,15 do begin swe_dgf[*,(4*i),2] = (swe_dgf[*,(4*i),1] + swe_dgf[*,(4*i+3),1])/2. for j=1,3 do swe_dgf[*,(4*i+j),2] = swe_dgf[*,(4*i),2] endfor ; Normalize: mean(swe_dgf[*,i,j]) = 1. for i=0,63 do begin for j=0,2 do begin swe_dgf[*,i,j] = swe_dgf[*,i,j]/mean(swe_dgf[*,i,j]) endfor endfor swe_dgf = transpose(swe_dgf,[1,0,2]) swe_dgf[*] = 1. ; disable for now ; Dead time (from IRAP calibration: MCP-Anode-Preamp chain) ; This is for ONE of the 16 chains. Energy spectra combine all 16 chains, so ; the deadtime correction is different for APID's A4 and A5. swe_dead = 2.8e-6 ; IRAP calibration, one MCP-Anode-Preamp chain swe_min_dtc = 0.25 ; max 4x deadtime correction ; Electron rest mass c = 2.99792458D5 ; velocity of light [km/s] mass_e = (5.10998910D5)/(c*c) ; electron rest mass [eV/(km/s)^2] return end