pro trace2equator, tarray, in_pos_array, out_foot_array, out_trace_array=out_trace_array, $
in_coord=in_coord, out_coord=out_coord, internal_model=internal_model, external_model=external_model, $
south=south, km=km, par=par, period=period, error=error, r0=r0, rlim=rlim, add_tilt=add_tilt, $
get_tilt=get_tilt, set_tilt=set_tilt, get_nperiod=get_nperiod, get_period_times=get_period_times, $
geopack_2008=geopack_2008, _extra=_extra
error = 0
valid_coords = ['gei', 'gse','geo', 'gsm', 'sm']
valid_internals = ['dip', 'igrf']
valid_externals = ['none', 't89', 't96', 't01', 't04s']
km_in_re = 6374.4D
if not keyword_set(rlim) then $
if keyword_set(km) then $
rlim = 60D*km_in_re $
else $
rlim = 60D
if igp_test(geopack_2008=geopack_2008) eq 0 then return
if not keyword_set(tarray) then begin
message, /continue, 'tarray must be set'
return
endif
if not keyword_set(in_pos_array) then begin
message, /continue, 'in_pos_array must be set'
return
endif
if not arg_present(out_foot_array) then begin
message, /continue, 'out_foot_array must be set'
return
endif
if keyword_set(in_coord) then begin
in_coord2 = strlowcase(in_coord)
if(strfilter(valid_coords, in_coord2) eq '') then begin
message, /continue, 'in_coord not a valid coordinate name'
return
endif
endif else in_coord2 = 'gsm'
if keyword_set(out_coord) then begin
out_coord2 = strlowcase(out_coord)
if(strfilter(valid_coords, out_coord2) eq '') then begin
message, /continue, 'out_coord not a valid coordinate name'
return
endif
endif else out_coord2 = 'gsm'
if keyword_set(internal_model) then begin
internal_model2 = strlowcase(internal_model)
if(strfilter(valid_internals, internal_model2) eq '') then begin
message, /continue, 'internal_model not a valid internal model name'
return
endif
endif else internal_model2 = 'igrf'
if keyword_set(external_model) then begin
external_model2 = strlowcase(external_model)
if(strfilter(valid_externals, external_model2) eq '') then begin
message, /continue, 'external_model not a valid external model name'
return
endif
endif else external_model2 = 'none'
if keyword_set(south) then dir = 1.0D $
else dir = -1.0D
tarray2 = double(tarray)
in_pos_array2 = double(in_pos_array)
if n_elements(r0) gt 0 then r02 = double(r0)
if n_elements(rlim) gt 0 then rlim2 = double(rlim)
if keyword_set(km) then begin
in_pos_array2 = in_pos_array2/km_in_re
if n_elements(r02) gt 0 then r02 = r02/km_in_re
if n_elements(rlim2) gt 0 then rlim2 = rlim2/km_in_re
endif else begin
idx_temp = where(abs(in_pos_array2) gt km_in_re)
if idx_temp[0] ne -1L then begin
message,/continue,'!!!! WARNING !!!! the magnitude of your rgsm values suggests your data may be in km'
message,/continue,'Default is Re, please set keyword "km" or see calling sequence by typing doc_library,"trace2equator".'
endif
endelse
if internal_model2 eq 'igrf' then IGRF = 1 else IGRF = 0
if external_model2 ne 'none' and not keyword_set(par) then begin
message,/continue,'par must be set if external model is set'
return
endif
if external_model2 eq 't89' then begin
T89 = 1
T96 = 0
T01 = 0
TS04 = 0
if size(par,/n_dim) eq 0 then par_array = make_array(n_elements(tarray2),/DOUBLE,value=par)
if size(par,/n_dim) eq 1 then begin
if n_elements(par) ne n_elements(tarray2) then begin
message,/continue,'par must have the same number of elements as tarray '
return
endif else par_array = double(par)
endif
if size(par,/n_dim) gt 1 then begin
message,/continue,'par must have 0 or 1 dimensions when used with model t89'
return
endif
par_idx_low = where(par_array lt 1)
if par_idx_low[0] ne -1L then begin
message, /continue, 'par has value less than 1'
return
endif
par_idx_high = where(par_array gt 7)
if par_idx_high[0] ne -1L then begin
message, /continue, 'par has value greater than 7'
return
endif
endif else if external_model2 ne 'none' then begin
T89 = 0
if external_model2 eq 't96' then T96 = 1 else T96 = 0
if external_model2 eq 't01' then T01 = 1 else T01 = 0
if external_model2 eq 't04s' then TS04 = 1 else TS04 = 0
s = size(par,/dimensions)
if n_elements(s) eq 1 && s[0] eq 10 then par_array = transpose(rebin(par,10,n_elements(tarray2))) else $
if n_elements(s) eq 2 && s[0] eq 1 && s[1] eq 10 then par_array = rebin(par,n_elements(tarray2),10) else $
if n_elements(s) ne 2 || s[1] ne 10 || s[0] ne n_elements(tarray2) then begin
message,/continue,'par must be an N x 10 array if ' + external_model2 + ' is set'
return
endif else par_array = double(par)
endif else begin
T89 = 0
T96 = 0
T01 = 0
TS04 = 0
endelse
t_size = size(tarray2, /dimensions)
r_size = size(in_pos_array2, /dimensions)
if n_elements(t_size) ne 1 then begin
message, /continue, 'tarray has incorrect dimensions'
return
endif
if n_elements(r_size) ne 2 || r_size[1] ne 3 then begin
message, /continue, 'in_pos_array has incorrect dimensions'
return
endif
if t_size[0] ne r_size[0] then begin
message, /continue, 'number of times in tarray does not match number of positions in in_pos_array'
return
endif
ts = time_struct(tarray2)
tstart = tarray2[0]
if ~undefined(geopack_2008) then begin
if in_coord2 eq 'gei' then begin
cotrans,in_pos_array2,in_pos_array2,tarray2,/gei2gse
endif else if in_coord2 eq 'geo' then begin
cotrans,in_pos_array2,in_pos_array2,tarray2,/geo2gei
cotrans,in_pos_array2,in_pos_array2,tarray2,/gei2gse
endif else if in_coord2 eq 'sm' then begin
cotrans,in_pos_array2,in_pos_array2,tarray2,/sm2gse
endif else if in_coord2 eq 'gsm' then begin
cotrans,in_pos_array2,in_pos_array2,tarray2, /gsm2gse
endif
geopack_recalc_08, ts[0].year, ts[0].doy, ts[0].hour, ts[0].min, ts[0].sec, tilt = tilt
geopack_conv_coord_08, in_pos_array2[*,0], in_pos_array2[*,1], in_pos_array2[*,2], x_out_gsw, y_out_gsw, z_out_gsw, /from_gse, /to_gsw
in_pos_array2 = [[x_out_gsw], [y_out_gsw], [z_out_gsw]]
endif else begin
if in_coord2 eq 'gei' then begin
cotrans,in_pos_array2,in_pos_array2,tarray2,/gei2gse
cotrans,in_pos_array2,in_pos_array2,tarray2,/gse2gsm
endif else if in_coord2 eq 'geo' then begin
cotrans,in_pos_array2,in_pos_array2,tarray2,/geo2gei
cotrans,in_pos_array2,in_pos_array2,tarray2,/gei2gse
cotrans,in_pos_array2,in_pos_array2,tarray2,/gse2gsm
endif else if in_coord2 eq 'gse' then $
cotrans,in_pos_array2,in_pos_array2,tarray2,/gse2gsm $
else if in_coord2 eq 'sm' then $
cotrans,in_pos_array2,in_pos_array2,tarray2,/sm2gsm
endelse
if not keyword_set(period) then period2 = 60.0D $
else period2 = double(period)
if period2 le 0. then begin
message, /contiune, 'period must be positive'
return
endif
out_foot_array = make_array(r_size, /DOUBLE, VALUE = !VALUES.D_NAN)
idx = where((tarray2[1:n_elements(tarray2)-1] - tarray2[0:n_elements(tarray2)-2]) lt 0,nonmonotone_times)
if nonmonotone_times gt 0 then begin
dprint,'Warning some times are non monotonic, this may cause unreliable results'
endif
if arg_present(out_trace_array) then begin
ct = t_size[0] - 1L
tr_ptr_arr = ptrarr(t_size[0])
max_trace_size = 0
endif else begin
tstart = tarray2[0]
tend = tarray2[t_size[0] - 1L]
ct = ceil((tend-tstart)/period2)
endelse
nperiod = ct+1
if arg_present(get_nperiod) then begin
get_nperiod = nperiod
endif
if arg_present(get_tilt) then begin
get_tilt = dblarr(nperiod)
endif
if arg_present(get_period_times) then begin
get_period_times = tstart + dindgen(nperiod)*period2+period2/2.
endif
if n_elements(add_tilt) gt 0 then begin
if n_elements(add_tilt) eq 1 then begin
tilt_value = replicate(add_tilt[0],nperiod)
endif else if n_elements(add_tilt) eq nperiod then begin
tilt_value = add_tilt
endif else if n_elements(add_tilt) eq t_size[0] then begin
period_abcissas = tstart + dindgen(nperiod)*period+period/2
tilt_value = interpol(add_tilt,tarray,period_abcissas)
endif else begin
dprint,'Error: add_tilt values do not match data values or period values'
return
endelse
endif
if n_elements(set_tilt) gt 0 then begin
if n_elements(set_tilt) eq 1 then begin
tilt_value = replicate(set_tilt[0],nperiod)
endif else if n_elements(set_tilt) eq nperiod then begin
tilt_value = set_tilt
endif else if n_elements(set_tilt) eq t_size[0] then begin
period_abcissas = tstart + dindgen(nperiod)*period+period/2
tilt_value = interpol(set_tilt,tarray,period_abcissas)
endif else begin
dprint,'Error: set_tilt values do not match data values or period values'
return
endelse
endif
i = 0L
while i le ct do begin
if arg_present(out_trace_array) then begin
if ~undefined(geopack_2008) then begin
geopack_recalc_08, ts[i].year,ts[i].doy, ts[i].hour, ts[i].min, ts[i].sec, tilt = tilt
endif else begin
geopack_recalc, ts[i].year,ts[i].doy, ts[i].hour, ts[i].min, ts[i].sec, tilt = tilt
endelse
if T89 eq 1 then par_iter = par_array[i] $
else if T96 eq 1 || T01 eq 1 || TS04 eq 1 then par_iter = par_array[i,*] $
else par_iter = ''
if n_elements(tilt_value) gt 0 then begin
if n_elements(set_tilt) gt 0 then begin
tilt = tilt_value[i]
endif else if n_elements(add_tilt) gt 0 then begin
tilt = tilt+tilt_value[i]
endif
endif
if n_elements(get_tilt) gt 0 then begin
get_tilt[i] = tilt
endif
if ~undefined(geopack_2008) then begin
geopack_trace_08,in_pos_array2[i, 0], in_pos_array2[i, 1], in_pos_array2[i, 2], dir, par_iter, out_foot_x, out_foot_y, out_foot_z, R0 = R02, RLIM = RLIM2, fline = trgsm_out, tilt = tilt, IGRF = IGRF, T89 = T89, T96 = T96, T01 = T01, TS04 = TS04, /refine, /equator, _extra = _extra
endif else begin
geopack_trace, in_pos_array2[i, 0], in_pos_array2[i, 1], in_pos_array2[i, 2], dir, par_iter, out_foot_x, out_foot_y, out_foot_z, R0 = R02, RLIM = RLIM2, fline = trgsm_out, tilt = tilt, IGRF = IGRF, T89 = T89, T96 = T96, T01 = T01, TS04 = TS04, /refine, /equator, _extra = _extra
endelse
out_foot_array[i, 0] = out_foot_x
out_foot_array[i, 1] = out_foot_y
out_foot_array[i, 2] = out_foot_z
tr_ptr_arr[i] = ptr_new(trgsm_out)
tr_size = size(trgsm_out,/dimensions)
if tr_size[0] gt max_trace_size then max_trace_size = tr_size[0]
endif else begin
idx1 = where(tarray2 ge tstart + i*period2)
idx2 = where(tarray2 le tstart + (i+1)*period2)
idx = ssl_set_intersection(idx1, idx2)
if idx[0] ne -1L then begin
id = idx[0]
if ~undefined(geopack_2008) then begin
geopack_recalc_08, ts[id].year,ts[id].doy, ts[id].hour, ts[id].min, ts[id].sec, tilt = tilt
endif else begin
geopack_recalc, ts[id].year,ts[id].doy, ts[id].hour, ts[id].min, ts[id].sec, tilt = tilt
endelse
if n_elements(tilt_value) gt 0 then begin
if n_elements(set_tilt) gt 0 then begin
tilt = tilt_value[i]
endif else if n_elements(add_tilt) gt 0 then begin
tilt = tilt+tilt_value[i]
endif
endif
if n_elements(get_tilt) gt 0 then begin
get_tilt[i] = tilt
endif
rgsm_x = in_pos_array2[idx, 0]
rgsm_y = in_pos_array2[idx, 1]
rgsm_z = in_pos_array2[idx, 2]
if T89 eq 1 then par_iter = par_array[id] $
else if T96 eq 1 || T01 eq 1 || TS04 eq 1 then par_iter = par_array[id,*] else par_iter = ''
if ~undefined(geopack_2008) then begin
geopack_trace_08,rgsm_x,rgsm_y,rgsm_z,dir,par_iter,foot_x,foot_y,foot_z,R0=R02,RLIM=RLIM2,tilt=tilt,IGRF=IGRF,T89=T89,T96=T96,T01=T01,TS04=TS04,_extra=_extra,/REFINE,/EQUATOR
endif else begin
geopack_trace,rgsm_x,rgsm_y,rgsm_z,dir,par_iter,foot_x,foot_y,foot_z,R0=R02,RLIM=RLIM2,tilt=tilt,IGRF=IGRF,T89=T89,T96=T96,T01=T01,TS04=TS04,_extra=_extra,/REFINE,/EQUATOR
endelse
out_foot_array[idx, 0] = foot_x
out_foot_array[idx, 1] = foot_y
out_foot_array[idx, 2] = foot_z
endif
endelse
i++
endwhile
if arg_present(out_trace_array) then begin
out_trace_array = make_array([t_size[0],max_trace_size,3],/DOUBLE, VALUE = !VALUES.D_NAN)
for i = 0L,t_size[0]-1L do begin
tr_temp = *tr_ptr_arr[i]
ptr_free,tr_ptr_arr[i]
s_temp = size(tr_temp,/dimensions)
t_temp = replicate(tarray2[i],s_temp[0])
if ~undefined(geopack_2008) then begin
geopack_conv_coord_08, tr_temp[*,0], tr_temp[*,1], tr_temp[*,2], x_out_gse, y_out_gse, z_out_gse, /from_gsw, /to_gse
tr_temp = [[x_out_gse], [y_out_gse], [z_out_gse]]
cotrans, tr_temp, tr_temp, t_temp, /gse2gsm
endif
if out_coord2 eq 'gei' then begin
cotrans,tr_temp,tr_temp,t_temp,/gsm2gse
cotrans,tr_temp,tr_temp,t_temp,/gse2gei
endif else if out_coord2 eq 'geo' then begin
cotrans,tr_temp,tr_temp,t_temp,/gsm2gse
cotrans,tr_temp,tr_temp,t_temp,/gse2gei
cotrans,tr_temp,tr_temp,t_temp,/gei2geo
endif else if out_coord2 eq 'gse' then $
cotrans,tr_temp,tr_temp,t_temp,/gsm2gse $
else if out_coord2 eq 'sm' then $
cotrans,tr_temp,tr_temp,t_temp,/gsm2sm
out_trace_array[i,0:(s_temp[0]-1L),*] = tr_temp
endfor
if keyword_set(km) then out_trace_array *= km_in_re
endif
if ~undefined(geopack_2008) then begin
geopack_conv_coord_08, out_foot_array[*,0], out_foot_array[*,1], out_foot_array[*,2], x_footout_gse, y_footout_gse, z_footout_gse, /from_gsw, /to_gse
out_foot_array = [[x_footout_gse], [y_footout_gse], [z_footout_gse]]
cotrans, out_foot_array, out_foot_array, tarray2, /gse2gsm
endif
if out_coord2 eq 'gei' then begin
cotrans,out_foot_array,out_foot_array,tarray2,/gsm2gse
cotrans,out_foot_array,out_foot_array,tarray2,/gse2gei
endif else if out_coord2 eq 'geo' then begin
cotrans,out_foot_array,out_foot_array,tarray2,/gsm2gse
cotrans,out_foot_array,out_foot_array,tarray2,/gse2gei
cotrans,out_foot_array,out_foot_array,tarray2,/gei2geo
endif else if out_coord2 eq 'gse' then $
cotrans,out_foot_array,out_foot_array,tarray2,/gsm2gse $
else if out_coord2 eq 'sm' then $
cotrans,out_foot_array,out_foot_array,tarray2,/gsm2sm
if keyword_set(km) then out_foot_array *= km_in_re
error = 1
end