;+ ;Procedure: ; mms_cotrans ; ; ;Purpose: ; Transform between MMS and geophysical coordinate systems. ; ; ;Calling Sequence: ; mms_cotrans, input_name [,output_name] ; ,out_coord=out_coord [,out_suffix=out_suffix] ; [,in_coord=in_coord] [,in_suffix=in_suffix] ... ; ; ;Example Usage: ; mms_cotrans, 'mms1_fgm_b_gse_srvy_l2_bvec', in_coord='gse', out_coord='gsm', $ ; out_suffix='_gsm', /ignore_dlimits ; ; ;Arguments: ; input_name: String or string array of input tplot variable(s). Standard tplot ; wildcards may be used to specify multiple variables. ; output_name (optional) String or string array of output tplot variable names. ; Number of output names must match number of input names once ; wildcards are considered. ; ;Keywords: ; in_coord: String specifying the coordinate system of the input(s). ; This keyword is optional if the dlimits.data_att.coord_sys attribute ; is present for the tplot variable, and if present, it must match ; the value of that attribute (see cotrans_set_coord, cotrans_get_coord). ; e.g. 'gse', 'gsm', 'sm', 'gei','geo', 'mag' ; out_coord: String specifying the desitnation coordinate system. ; e.g. 'gse', 'gsm', 'sm', 'gei','geo', 'mag' ; in_suffix: Suffix of input variable name. This specifies the portion of ; the input variable's name that will be replace with the output ; suffix. If specified, the name effective input name will be ; input_name + in_suffix ; out_suffix: Suffix appended to the output name. If in_suffix is present or ; the input coordinates are part of the input variable's name then ; they will be replaced with out_suffix. ; support_suffix: Suffix appended to standard support data names when looking ; for support data (i.e. RA & Dec) ; ; out_vars: return a list of the names of any transformed variables ; ; valid_names: return valid coordinate system names in named variables supplied to ; in_coord and/or out_coord keywords. ; ignore_dlimits: set this keyword to true so that an error will not ; be produced if the internal label of the coordinate system clashed ; with the user provided coordinate system. ; no_update_labels: Set this keyword if you want the routine to not update the labels automatically ; ; ;Notes: ; Based on thm_cotrans ; ; ; egrimes disabled DMPA coordinate transformations on 2July18 - please use mms_qcotrans for ; these transformations ; ; ;$LastChangedBy: egrimes $ ;$LastChangedDate: 2020-05-18 12:42:05 -0700 (Mon, 18 May 2020) $ ;$LastChangedRevision: 28709 $ ;$URL: svn+ssh://thmsvn@ambrosia.ssl.berkeley.edu/repos/spdsoft/tags/spedas_5_0/projects/mms/common/cotrans/mms_cotrans.pro $ ;- pro mms_cotrans, $ ; variable names in_name_0, $ out_name_0, $ ; coordinates in_coord=in_coord_0, $ out_coord=out_coord_0, $ ; suffixes in_suffix=in_suffix, $ out_suffix=out_suffix, $ support_suffix=support_suffix, $ ; supplementary info probe=probe_0, $ valid_names=valid_names, $ out_vars=out_vars, $ ; metadata options no_update_labels=no_update_labels, $ ignore_dlimits=ignore_dlimits, $ ; other verbose=verbose, $ allow_dmpa=allow_dmpa compile_opt idl2, hidden mms_init vb = undefined(verbose) ? !mms.verbose : verbose ;get general coordinates coord_obj = obj_new('spd_ui_coordinate_systems') general_coords = coord_obj->makeCoordSysList() obj_destroy, coord_obj ;valid values valid_probes = ['1','2','3','4'] valid_coords = ['dsl','dmpa',general_coords] ;TODO: return MMS coords from common routine/obj? ;print and return valid inputs if requested if keyword_set(valid_names) then begin in_coord_0 = valid_coords out_coord_0 = valid_coords probe_0 = valid_probes if keyword_set(vb) then begin dprint, string(strjoin(valid_coords, ','), format = '( "Valid coords:",X,A,".")') dprint, string(strjoin(valid_probes, ','), format = '( "Valid probes:",X,A,".")') endif return endif ;copy input strings from temp vars to keep them from being altered if ~undefined(in_name_0) then in_name = in_name_0 if ~undefined(out_name_0) then out_name = out_name_0 if ~undefined(in_coord_0) then in_coord = in_coord_0 if ~undefined(out_coord_0) then out_coord = out_coord_0 if ~undefined(probe_0) then probe = probe_0 ; Validate input/output coordinates ;---------------------------------------------------------- if n_elements(out_coord) gt 1 or n_elements(out_suffix) gt 1 then begin dprint, dlevel=0, 'Can only specify one out_coord/out_suffix' return endif ;get output coord from suffix if none is specified ; -distinguish "sm" from "gsm" if undefined(out_coord) and is_string(out_suffix) then begin out_coord = mms_cotrans_parse(out_suffix,valid_coords) endif if undefined(out_coord) then begin dprint, dlevel=0, 'Must specify out_coord or out_suffix' return endif else begin out_coord = ssl_check_valid_name(strlowcase(out_coord), valid_coords) endelse if ~is_string(out_coord) then return if n_elements(in_coord) gt 1 or n_elements(in_suffix) gt 1 then begin dprint, dlevel=0, 'Can only specify one in_coord/in_suffix' return endif ;get input coord from suffix if none is specified ; -distinguish "sm" from "gsm" if undefined(in_coord) && is_string(in_suffix) then begin in_coord = mms_cotrans_parse(in_suffix,valid_coords) endif ;check input coordinates, but allow for it to be unspecified if ~undefined(in_coord) then begin in_coord = ssl_check_valid_name(strlowcase(in_coord), valid_coords) if ~is_string(in_coord) then begin return endif endif ; if undefined(in_suffix) then in_suffix = '' if undefined(out_suffix) then out_suffix = '' if undefined(support_suffix) then support_suffix = '' ; Build list of input/output variables ; -allow wildcards in input names ;---------------------------------------------------------- in_names = tnames(in_name+in_suffix, n) if n eq 0 then begin dprint, dlevel=0, 'No matches found for input: '+in_name+in_suffix return endif ;generate output names if not provided if n_params() eq 1 || n_elements(in_names) ne n_elements(out_name) then begin if n_params() eq 2 then dprint, 'WARNING: Ignoring out_names' if in_suffix ne '' then begin base_len = strpos(in_names,in_suffix,/reverse_search) endif else begin base_len = strlen(in_names) endelse out_names = in_names for j = 0, n-1 do begin out_names[j] = strmid(in_names[j],0,base_len[j])+out_suffix endfor endif else begin out_names = out_name + out_suffix endelse if n_elements(in_names) ne n_elements(out_names) then begin message, 'Number of input variables does not match number of output variables' endif ; Get input coordinates ; -preprocess coordinate systems, so we can determine if probe keyword is required ; -this code also helps resolve discrepancies between in_coord keyword and data_att.coord_sys ;---------------------------------------------------------- if keyword_set(ignore_dlimits) then begin if is_string(in_coord) then begin in_coords = replicate(in_coord,n_elements(in_names)) endif else begin dprint, 'Must specify input coordinates if /ignore_dlimits is set' return endelse endif else begin in_coords = strarr(n_elements(in_names)) for i = 0,n_elements(in_names)-1 do begin ;this only returns 'unknown' if the field is not present, ;blank fields will be returned and lower routines expect ;them to have been filtered as conflicted data_in_coord = cotrans_get_coord(in_names[i]) if ~is_string(in_coord) then begin in_coords[i] = data_in_coord endif else if strmatch(data_in_coord,'unknown') then begin in_coords[i] = in_coord endif else if data_in_coord ne in_coord then begin in_coords[i] = 'conflict' endif else begin in_coords[i] = in_coord endelse endfor endelse ; tell the user to use mms_qcotrans instead of mms_cotrans if they're requesting DMPA transformation if (array_contains([in_coords,out_coord], 'dmpa') or array_contains([in_coords,out_coord], 'dsl')) && ~keyword_set(allow_dmpa) then begin dprint, dlevel=0, 'Please use mms_qcotrans for transforming data to/from the DMPA/DSL coordinate system; note: if you are sure you want to do this transformation with mms_cotrans, you can override this message and do the transformation with the /allow_dmpa keyword' return endif ; Determine if probe is required ;---------------------------------------------------------- req_probe = ['dmpa'] if undefined(probe) then begin ;get probe designation from variable name probes = ( stregex(in_names,'^mms([1-4])',/subexpr,/extract) )[1,*] ;check if probe is required for and transforms if is_string( ssl_set_intersection([in_coords,out_coord],req_probe) ) then begin if total(probes eq '') gt 0 then begin dprint, dlevel=0, 'Some input name(s) do not specify probe according to MMS convention: dprint, dlevel=0, ' '+in_names[where(probes eq'')] dprint, dlevel=0, 'Must specify probe with PROBE keyword' return endif endif endif else begin ;ensure that probe is either singular or matches the number of input names if n_elements(probe) gt 1 then begin if n_elements(probe) ne n_elements(in_names) then begin dprint, dlevel=0, 'PROBE keyword must be singular or match the number on input names' return endif probes = probe endif else begin probes = replicate(probe,n_elements(in_names)) endelse probes = strtrim(probes,2) endelse ; Loop over input names to perform transformations ;---------------------------------------------------------- for i = 0, n_elements(in_names)-1 do begin in_name = in_names[i] out_name = out_names[i] probe = probes[i] ;verify data is valid get_data,in_name,data=in,dl=in_dl if ~is_struct(in) then begin dprint, 'input tplot variable '+in_name+' has no data' continue endif ;verify data is a 3-vector in_size=size(in.y) if in_size[0] ne 2 or in_size[2] ne 3 then begin dprint,'Input tplot variable '+in_name+' is not a 3-vector. Skipping' continue endif in_c = in_coords[i] ;notify if in_coord is inconsistent with metadata and skip variable if in_c eq 'conflict' then begin dprint,'Specified coordinate system does not match metadata for "' + in_name + '". Skipping.' continue endif else if in_c eq 'unknown' then begin dprint,'Tplot variable "' + in_name + '" has unknown input coordinate system. Skipping' continue endif dprint, 'Coordinate system of input '+in_name+': '+in_c ; Note: L_vec is used here because it assumes rigid-body rotation even when the ; wire booms are oscillating, and thus, at any point in time it does not give L, ; but rather the average orientation of the nutating MPA (which is also assumed ; fixed relative to the rigid body) as it wobbles in inertial space with a ; period of ~7 minutes. spinras = 'mms'+probe+'_defatt_spinras'+support_suffix spindec = 'mms'+probe+'_defatt_spindec'+support_suffix ; the following check is only required for DMPA coordinates if strlowcase(in_name) eq 'dmpa' or strlowcase(out_name) eq 'dmpa' then begin ; check if the defatt spinras/spindec variables were loaded ras = tnames(spinras) decl = tnames(spindec) if ras eq '' && decl eq '' then begin dprint, dlevel = 0, 'Error, couldnt find the right ascension/declination variables' endif endif mms_cotrans_transformer, in_name, out_name, in_c, out_coord, $ spinras, spindec, ignore_dlimits=ignore_dlimits ;aggregate transformed variables name_list = array_concat(out_name,name_list) ;update labels in limits and dlimits structures if ~keyword_set(no_update_labels) then begin spd_cotrans_update_dlimits,out_name,in_c,strupcase(out_coord) spd_cotrans_update_limits,out_name,in_c,strupcase(out_coord) endif endfor if arg_present(out_vars) && n_elements(name_list) gt 0 then begin out_vars = name_list endif end