diff --git a/docs/swapi/alpha-sw.md b/docs/swapi/alpha-sw.md
index eae0733f..ecfee77f 100644
--- a/docs/swapi/alpha-sw.md
+++ b/docs/swapi/alpha-sw.md
@@ -76,21 +76,33 @@ Finally, the `alpha-sw` CDF variables are derived from the fitted parameter vect
| CDF variable | Symbol | Definition |
|---------------------------------------|---------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------|
-| `epoch` | $`t_{\text{center}}`$ | center time of the 5-sweep chunk |
-| `epoch_delta` | | $`30\thinspace \text{s}`$ (half-width of the 5-sweep chunk) |
-| `alpha_sw_density` | $`n^{\alpha}`$ | $`\exp(x^{\alpha}_{0})`$ |
-| `alpha_sw_density_uncert` | $`\sigma_{n^{\alpha}}`$ | $`n^{\alpha}\thinspace \sqrt{\Sigma_{x^{\alpha}}[0, 0]}`$ |
-| `alpha_sw_temperature` | $`T^{\alpha}`$ | $`\exp(x^{\alpha}_{1})`$ |
-| `alpha_sw_temperature_uncert` | $`\sigma_{T^{\alpha}}`$ | $`T^{\alpha}\thinspace \sqrt{\Sigma_{x^{\alpha}}[1, 1]}`$ |
-| `alpha_sw_velocity_rtn` | $`\mathbf{v}^{\alpha,\text{SC}}`$ | $`\mathbf{v}_{b}^{\text{SC}} + x^{\alpha}_{2}\thinspace \hat{\mathbf{B}}`$ [1](#fn-vp) |
-| `alpha_sw_velocity_rtn_covariance` | $`\Sigma_{\mathbf{v}^{\alpha}}`$ | $`\Sigma_{\mathbf{v}^{p}} + \Sigma_{x^{\alpha}}[2,2 ]\thinspace \hat{\mathbf{B}}\hat{\mathbf{B}}^{\top}`$ |
-| `alpha_sw_velocity_rtn_uncert` | $`\sigma_{\mathbf{v}^{\alpha}}`$ | $`\sqrt{\operatorname{diag}(\Sigma_{\mathbf{v}^{\alpha}})}`$ (same for `alpha_sw_velocity_rtn_sun`) |
-| `alpha_sw_speed` | $`\lvert\mathbf{v}^{\alpha,\text{SC}}\rvert`$ | $`\lvert\mathbf{v}^{\alpha,\text{SC}}\rvert`$ |
-| `alpha_sw_speed_uncert` | $`\sigma_{\lvert\mathbf{v}^{\alpha,\text{SC}}\rvert}`$ | propagated through `uncertainties` from $`\mathbf{v}^{\alpha,\text{SC}}`$ |
-| `alpha_sw_velocity_rtn_sun` | $`\mathbf{v}^{\alpha,\text{sun}}`$ | $`\mathbf{v}^{\alpha,\text{SC}} + \mathbf{v}_{\text{sc}}^{\text{sun}}`$ |
-| `alpha_sw_speed_sun` | $`\lvert\mathbf{v}^{\alpha,\text{sun}}\rvert`$ | $`\lvert\mathbf{v}^{\alpha,\text{sun}}\rvert`$ |
+| `epoch` | $`t_{\text{center}}`$ | center time of the 5-sweep chunk |
+| `epoch_delta` | | $`30\thinspace \text{s}`$ (half-width of the 5-sweep chunk) |
+| `alpha_sw_density` | $`n^{\alpha}`$ | $`\exp(x^{\alpha}_{0})`$ |
+| `alpha_sw_density_uncert` | $`\sigma_{n^{\alpha}}`$ | $`n^{\alpha}\thinspace \sqrt{\Sigma_{x^{\alpha}}[0, 0]}`$ |
+| `alpha_sw_temperature` | $`T^{\alpha}`$ | $`\exp(x^{\alpha}_{1})`$ |
+| `alpha_sw_temperature_uncert` | $`\sigma_{T^{\alpha}}`$ | $`T^{\alpha}\thinspace \sqrt{\Sigma_{x^{\alpha}}[1, 1]}`$ |
+| `alpha_sw_velocity_rtn` | $`\mathbf{v}^{\alpha,\text{SC}}`$ | $`\mathbf{v}_{b}^{\text{SC}} + x^{\alpha}_{2}\thinspace \hat{\mathbf{B}}`$ [1](#fn-vp) |
+| `alpha_sw_velocity_rtn_covariance` | $`\Sigma_{\mathbf{v}^{\alpha}}`$ | $`\Sigma_{\mathbf{v}^{p}} + \Sigma_{x^{\alpha}}[2,2 ]\thinspace \hat{\mathbf{B}}\hat{\mathbf{B}}^{\top}`$ |
+| `alpha_sw_velocity_rtn_uncert` | $`\sigma_{\mathbf{v}^{\alpha}}`$ | $`\sqrt{\operatorname{diag}(\Sigma_{\mathbf{v}^{\alpha}})}`$ (same for `alpha_sw_velocity_rtn_sun`) |
+| `alpha_sw_speed` | $`\lvert\mathbf{v}^{\alpha,\text{SC}}\rvert`$ | $`\lvert\mathbf{v}^{\alpha,\text{SC}}\rvert`$ |
+| `alpha_sw_speed_uncert` | $`\sigma_{\lvert\mathbf{v}^{\alpha,\text{SC}}\rvert}`$ | propagated through `uncertainties` from $`\mathbf{v}^{\alpha,\text{SC}}`$ |
+| `alpha_sw_velocity_rtn_sun` | $`\mathbf{v}^{\alpha,\text{sun}}`$ | $`\mathbf{v}^{\alpha,\text{SC}} + \mathbf{v}_{\text{sc}}^{\text{sun}}`$ |
+| `alpha_sw_velocity_gse` | $`\mathbf{v}^{\alpha,\text{SC}}_{\text{GSE}}`$ | RTN spacecraft-frame velocity rotated to GSE coordinates |
+| `alpha_sw_velocity_gse_sun` | $`\mathbf{v}^{\alpha,\text{sun}}_{\text{GSE}}`$ | RTN Sun-frame velocity rotated to GSE coordinates |
+| `alpha_sw_velocity_gse_covariance` | $`\Sigma_{\mathbf{v}^{\alpha},\text{GSE}}`$ | $`R_{\text{GSE}}\Sigma_{\mathbf{v}^{\alpha}}R_{\text{GSE}}^{\top}`$ |
+| `alpha_sw_velocity_gse_uncert` | $`\sigma_{\mathbf{v}^{\alpha},\text{GSE}}`$ | $`\sqrt{\operatorname{diag}(\Sigma_{\mathbf{v}^{\alpha},\text{GSE}})}`$ |
+| `alpha_sw_velocity_gsm` | $`\mathbf{v}^{\alpha,\text{SC}}_{\text{GSM}}`$ | RTN spacecraft-frame velocity rotated to GSM coordinates |
+| `alpha_sw_velocity_gsm_sun` | $`\mathbf{v}^{\alpha,\text{sun}}_{\text{GSM}}`$ | RTN Sun-frame velocity rotated to GSM coordinates |
+| `alpha_sw_velocity_gsm_covariance` | $`\Sigma_{\mathbf{v}^{\alpha},\text{GSM}}`$ | $`R_{\text{GSM}}\Sigma_{\mathbf{v}^{\alpha}}R_{\text{GSM}}^{\top}`$ |
+| `alpha_sw_velocity_gsm_uncert` | $`\sigma_{\mathbf{v}^{\alpha},\text{GSM}}`$ | $`\sqrt{\operatorname{diag}(\Sigma_{\mathbf{v}^{\alpha},\text{GSM}})}`$ |
+| `alpha_sw_velocity_hae` | $`\mathbf{v}^{\alpha,\text{SC}}_{\text{HAE-J2000}}`$ | RTN spacecraft-frame velocity rotated to HAE-J2000 coordinates |
+| `alpha_sw_velocity_hae_sun` | $`\mathbf{v}^{\alpha,\text{sun}}_{\text{HAE-J2000}}`$ | RTN Sun-frame velocity rotated to HAE-J2000 coordinates |
+| `alpha_sw_velocity_hae_covariance` | $`\Sigma_{\mathbf{v}^{\alpha},\text{HAE-J2000}}`$ | $`R_{\text{HAE-J2000}}\Sigma_{\mathbf{v}^{\alpha}}R_{\text{HAE-J2000}}^{\top}`$ |
+| `alpha_sw_velocity_hae_uncert` | $`\sigma_{\mathbf{v}^{\alpha},\text{HAE-J2000}}`$ | $`\sqrt{\operatorname{diag}(\Sigma_{\mathbf{v}^{\alpha},\text{HAE-J2000}})}`$ |
+| `alpha_sw_speed_sun` | $`\lvert\mathbf{v}^{\alpha,\text{sun}}\rvert`$ | $`\lvert\mathbf{v}^{\alpha,\text{sun}}\rvert`$ |
| `alpha_sw_speed_sun_uncert` | $`\sigma_{\lvert\mathbf{v}^{\alpha,\text{sun}}\rvert}`$ | propagated through `uncertainties` from $`\mathbf{v}^{\alpha,\text{sun}}`$ |
-| `swp_flags` | | quality flag bitmask (see `SwapiL3Flags`) |
+| `swp_flags` | | quality flag bitmask (see `SwapiL3Flags`) |
diff --git a/docs/swapi/proton-sw.md b/docs/swapi/proton-sw.md
index 6b486c59..d4350c3d 100644
--- a/docs/swapi/proton-sw.md
+++ b/docs/swapi/proton-sw.md
@@ -198,6 +198,18 @@ The `proton-sw` CDF variables are derived from $`\mathbf{x}`$ and $`\Sigma_\math
| `proton_sw_speed` | $`\lvert\mathbf{v}_{b}^{\text{SC}}\rvert`$ | $`\lvert\mathbf{v}_{b}^{\text{SC}}\rvert`$ |
| `proton_sw_speed_uncert` | $`\sigma_{\lvert\mathbf{v}_{b}^{\text{SC}}\rvert}`$ | propagated through `uncertainties` from $`\mathbf{v}_{b}^{\text{SC}}`$ |
| `proton_sw_velocity_rtn_sun` | $`\mathbf{v}_{b}^{\text{sun}}`$ | $`\mathbf{v}_{b}^{\text{SC}} + \mathbf{v}_{\text{sc}}^{\text{sun}}`$ [2](#fn-vsc) |
+| `proton_sw_velocity_gse` | $`\mathbf{v}_{b,\text{GSE}}^{\text{SC}}`$ | RTN spacecraft-frame velocity rotated to GSE coordinates |
+| `proton_sw_velocity_gse_sun` | $`\mathbf{v}_{b,\text{GSE}}^{\text{sun}}`$ | RTN Sun-frame velocity rotated to GSE coordinates |
+| `proton_sw_velocity_gse_covariance` | $`\Sigma_{\mathbf{v},\text{GSE}}`$ | $`R_{\text{GSE}}\Sigma_{\mathbf{v}}R_{\text{GSE}}^{\top}`$ |
+| `proton_sw_velocity_gse_uncert` | $`\sigma_{\mathbf{v},\text{GSE}}`$ | $`\sqrt{\operatorname{diag}(\Sigma_{\mathbf{v},\text{GSE}})}`$ |
+| `proton_sw_velocity_gsm` | $`\mathbf{v}_{b,\text{GSM}}^{\text{SC}}`$ | RTN spacecraft-frame velocity rotated to GSM coordinates |
+| `proton_sw_velocity_gsm_sun` | $`\mathbf{v}_{b,\text{GSM}}^{\text{sun}}`$ | RTN Sun-frame velocity rotated to GSM coordinates |
+| `proton_sw_velocity_gsm_covariance` | $`\Sigma_{\mathbf{v},\text{GSM}}`$ | $`R_{\text{GSM}}\Sigma_{\mathbf{v}}R_{\text{GSM}}^{\top}`$ |
+| `proton_sw_velocity_gsm_uncert` | $`\sigma_{\mathbf{v},\text{GSM}}`$ | $`\sqrt{\operatorname{diag}(\Sigma_{\mathbf{v},\text{GSM}})}`$ |
+| `proton_sw_velocity_hae` | $`\mathbf{v}_{b,\text{HAE-J2000}}^{\text{SC}}`$ | RTN spacecraft-frame velocity rotated to HAE-J2000 coordinates |
+| `proton_sw_velocity_hae_sun` | $`\mathbf{v}_{b,\text{HAE-J2000}}^{\text{sun}}`$ | RTN Sun-frame velocity rotated to HAE-J2000 coordinates |
+| `proton_sw_velocity_hae_covariance` | $`\Sigma_{\mathbf{v},\text{HAE-J2000}}`$ | $`R_{\text{HAE-J2000}}\Sigma_{\mathbf{v}}R_{\text{HAE-J2000}}^{\top}`$ |
+| `proton_sw_velocity_hae_uncert` | $`\sigma_{\mathbf{v},\text{HAE-J2000}}`$ | $`\sqrt{\operatorname{diag}(\Sigma_{\mathbf{v},\text{HAE-J2000}})}`$ |
| `proton_sw_speed_sun` | $`v_{\text{sun}}`$ | $`\lvert\mathbf{v}_{b}^{\text{sun}}\rvert`$ |
| `proton_sw_speed_sun_uncert` | $`\sigma_{v_{\text{sun}}}`$ | propagated through `uncertainties` from $`\mathbf{v}_{b}^{\text{sun}}`$ |
| `swp_flags` | | quality flag bitmask (see `SwapiL3Flags`) |
@@ -207,4 +219,3 @@ The `proton-sw` CDF variables are derived from $`\mathbf{x}`$ and $`\Sigma_\math
[1]: The square root of the diagonal of $`\Sigma_{\mathbf{v}}`$ yields the standard error of the $`v_{R}, v_{T}, v_{N}`$ components. The covariance is the same for `proton_sw_velocity_rtn_sun`.
[2]: $`\mathbf{v}_{\text{sc}}^{\text{sun}}`$ is the spacecraft velocity in the Sun's inertial frame.
-
diff --git a/imap_l3_processing/cdf/config/imap_swapi_l3a_variable_attrs.yaml b/imap_l3_processing/cdf/config/imap_swapi_l3a_variable_attrs.yaml
index 8a6cb768..1de180fa 100644
--- a/imap_l3_processing/cdf/config/imap_swapi_l3a_variable_attrs.yaml
+++ b/imap_l3_processing/cdf/config/imap_swapi_l3a_variable_attrs.yaml
@@ -386,6 +386,222 @@ proton_sw_velocity_rtn_uncert:
VALIDMAX: 10000
FILLVAL: -1.000000e+31
SCALETYP: linear
+proton_sw_velocity_gse_sun:
+ NAME: proton_sw_velocity_gse_sun
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Proton Solar Wind Velocity (GSE, Sun Frame)
+ CATDESC: Solar wind proton bulk velocity vector in GSE coordinates (Sun frame)
+ DEPEND_0: epoch
+ LABL_PTR_1: proton_sw_velocity_gse_sun_label
+ VAR_TYPE: data
+ RECORD_VARYING: RV
+ DISPLAY_TYPE: time_series
+ VARIABLE_PURPOSE: PRIMARY_VAR,SUMMARY
+ FORMAT: F19.3
+ LABLAXIS: Vp GSE Sun
+ UNITS: km/s
+ VALIDMIN: -10000
+ VALIDMAX: 10000
+ FILLVAL: -1.000000e+31
+ SCALETYP: linear
+ DELTA_PLUS_VAR: proton_sw_velocity_gse_uncert
+ DELTA_MINUS_VAR: proton_sw_velocity_gse_uncert
+proton_sw_velocity_gse:
+ NAME: proton_sw_velocity_gse
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Proton Solar Wind Velocity (GSE)
+ CATDESC: Solar wind proton bulk velocity vector in GSE coordinates (spacecraft frame)
+ DEPEND_0: epoch
+ LABL_PTR_1: proton_sw_velocity_gse_label
+ VAR_TYPE: data
+ RECORD_VARYING: RV
+ DISPLAY_TYPE: time_series
+ VARIABLE_PURPOSE: PRIMARY_VAR,SUMMARY
+ FORMAT: F19.3
+ LABLAXIS: Vp GSE SC
+ UNITS: km/s
+ VALIDMIN: -10000
+ VALIDMAX: 10000
+ FILLVAL: -1.000000e+31
+ SCALETYP: linear
+ DELTA_PLUS_VAR: proton_sw_velocity_gse_uncert
+ DELTA_MINUS_VAR: proton_sw_velocity_gse_uncert
+proton_sw_velocity_gse_covariance:
+ NAME: proton_sw_velocity_gse_covariance
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Proton Solar Wind Velocity Covariance (GSE)
+ CATDESC: Covariance matrix in GSE coordinates, with standard errors given by the square root of the diagonal
+ DEPEND_0: epoch
+ VAR_TYPE: support_data
+ RECORD_VARYING: RV
+ FORMAT: F19.3
+ LABLAXIS: cov Vp
+ UNITS: km^2/s^2
+ VALIDMIN: -1.0e+8
+ VALIDMAX: 1.0e+8
+ FILLVAL: -1.000000e+31
+ LABL_PTR_1: velocity_gse_label
+ LABL_PTR_2: velocity_gse_label
+proton_sw_velocity_gse_uncert:
+ NAME: proton_sw_velocity_gse_uncert
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Proton Solar Wind Velocity Uncertainty (GSE)
+ CATDESC: 1-sigma standard error
+ DEPEND_0: epoch
+ LABL_PTR_1: velocity_gse_label
+ VAR_TYPE: support_data
+ RECORD_VARYING: RV
+ FORMAT: F19.3
+ LABLAXIS: Vp GSE Err
+ UNITS: km/s
+ VALIDMIN: 0
+ VALIDMAX: 10000
+ FILLVAL: -1.000000e+31
+ SCALETYP: linear
+proton_sw_velocity_gsm_sun:
+ NAME: proton_sw_velocity_gsm_sun
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Proton Solar Wind Velocity (GSM, Sun Frame)
+ CATDESC: Solar wind proton bulk velocity vector in GSM coordinates (Sun frame)
+ DEPEND_0: epoch
+ LABL_PTR_1: proton_sw_velocity_gsm_sun_label
+ VAR_TYPE: data
+ RECORD_VARYING: RV
+ DISPLAY_TYPE: time_series
+ VARIABLE_PURPOSE: PRIMARY_VAR,SUMMARY
+ FORMAT: F19.3
+ LABLAXIS: Vp GSM Sun
+ UNITS: km/s
+ VALIDMIN: -10000
+ VALIDMAX: 10000
+ FILLVAL: -1.000000e+31
+ SCALETYP: linear
+ DELTA_PLUS_VAR: proton_sw_velocity_gsm_uncert
+ DELTA_MINUS_VAR: proton_sw_velocity_gsm_uncert
+proton_sw_velocity_gsm:
+ NAME: proton_sw_velocity_gsm
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Proton Solar Wind Velocity (GSM)
+ CATDESC: Solar wind proton bulk velocity vector in GSM coordinates (spacecraft frame)
+ DEPEND_0: epoch
+ LABL_PTR_1: proton_sw_velocity_gsm_label
+ VAR_TYPE: data
+ RECORD_VARYING: RV
+ DISPLAY_TYPE: time_series
+ VARIABLE_PURPOSE: PRIMARY_VAR,SUMMARY
+ FORMAT: F19.3
+ LABLAXIS: Vp GSM SC
+ UNITS: km/s
+ VALIDMIN: -10000
+ VALIDMAX: 10000
+ FILLVAL: -1.000000e+31
+ SCALETYP: linear
+ DELTA_PLUS_VAR: proton_sw_velocity_gsm_uncert
+ DELTA_MINUS_VAR: proton_sw_velocity_gsm_uncert
+proton_sw_velocity_gsm_covariance:
+ NAME: proton_sw_velocity_gsm_covariance
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Proton Solar Wind Velocity Covariance (GSM)
+ CATDESC: Covariance matrix in GSM coordinates, with standard errors given by the square root of the diagonal
+ DEPEND_0: epoch
+ VAR_TYPE: support_data
+ RECORD_VARYING: RV
+ FORMAT: F19.3
+ LABLAXIS: cov Vp
+ UNITS: km^2/s^2
+ VALIDMIN: -1.0e+8
+ VALIDMAX: 1.0e+8
+ FILLVAL: -1.000000e+31
+ LABL_PTR_1: velocity_gsm_label
+ LABL_PTR_2: velocity_gsm_label
+proton_sw_velocity_gsm_uncert:
+ NAME: proton_sw_velocity_gsm_uncert
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Proton Solar Wind Velocity Uncertainty (GSM)
+ CATDESC: 1-sigma standard error
+ DEPEND_0: epoch
+ LABL_PTR_1: velocity_gsm_label
+ VAR_TYPE: support_data
+ RECORD_VARYING: RV
+ FORMAT: F19.3
+ LABLAXIS: Vp GSM Err
+ UNITS: km/s
+ VALIDMIN: 0
+ VALIDMAX: 10000
+ FILLVAL: -1.000000e+31
+ SCALETYP: linear
+proton_sw_velocity_hae_sun:
+ NAME: proton_sw_velocity_hae_sun
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Proton Solar Wind Velocity (HAE, Sun Frame)
+ CATDESC: Solar wind proton bulk velocity vector in HAE coordinates (Sun frame)
+ DEPEND_0: epoch
+ LABL_PTR_1: proton_sw_velocity_hae_sun_label
+ VAR_TYPE: data
+ RECORD_VARYING: RV
+ DISPLAY_TYPE: time_series
+ VARIABLE_PURPOSE: PRIMARY_VAR,SUMMARY
+ FORMAT: F19.3
+ LABLAXIS: Vp HAE Sun
+ UNITS: km/s
+ VALIDMIN: -10000
+ VALIDMAX: 10000
+ FILLVAL: -1.000000e+31
+ SCALETYP: linear
+ DELTA_PLUS_VAR: proton_sw_velocity_hae_uncert
+ DELTA_MINUS_VAR: proton_sw_velocity_hae_uncert
+proton_sw_velocity_hae:
+ NAME: proton_sw_velocity_hae
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Proton Solar Wind Velocity (HAE)
+ CATDESC: Solar wind proton bulk velocity vector in HAE coordinates (spacecraft frame)
+ DEPEND_0: epoch
+ LABL_PTR_1: proton_sw_velocity_hae_label
+ VAR_TYPE: data
+ RECORD_VARYING: RV
+ DISPLAY_TYPE: time_series
+ VARIABLE_PURPOSE: PRIMARY_VAR,SUMMARY
+ FORMAT: F19.3
+ LABLAXIS: Vp HAE SC
+ UNITS: km/s
+ VALIDMIN: -10000
+ VALIDMAX: 10000
+ FILLVAL: -1.000000e+31
+ SCALETYP: linear
+ DELTA_PLUS_VAR: proton_sw_velocity_hae_uncert
+ DELTA_MINUS_VAR: proton_sw_velocity_hae_uncert
+proton_sw_velocity_hae_covariance:
+ NAME: proton_sw_velocity_hae_covariance
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Proton Solar Wind Velocity Covariance (HAE)
+ CATDESC: Covariance matrix in HAE coordinates, with standard errors given by the square root of the diagonal
+ DEPEND_0: epoch
+ VAR_TYPE: support_data
+ RECORD_VARYING: RV
+ FORMAT: F19.3
+ LABLAXIS: cov Vp
+ UNITS: km^2/s^2
+ VALIDMIN: -1.0e+8
+ VALIDMAX: 1.0e+8
+ FILLVAL: -1.000000e+31
+ LABL_PTR_1: velocity_hae_label
+ LABL_PTR_2: velocity_hae_label
+proton_sw_velocity_hae_uncert:
+ NAME: proton_sw_velocity_hae_uncert
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Proton Solar Wind Velocity Uncertainty (HAE)
+ CATDESC: 1-sigma standard error
+ DEPEND_0: epoch
+ LABL_PTR_1: velocity_hae_label
+ VAR_TYPE: support_data
+ RECORD_VARYING: RV
+ FORMAT: F19.3
+ LABLAXIS: Vp HAE Err
+ UNITS: km/s
+ VALIDMIN: 0
+ VALIDMAX: 10000
+ FILLVAL: -1.000000e+31
+ SCALETYP: linear
alpha_sw_speed:
NAME: alpha_sw_speed
DATA_TYPE: CDF_REAL4
@@ -598,6 +814,222 @@ alpha_sw_velocity_rtn_uncert:
VALIDMAX: 10000
FILLVAL: -1.000000e+31
SCALETYP: linear
+alpha_sw_velocity_gse_sun:
+ NAME: alpha_sw_velocity_gse_sun
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Alpha Solar Wind Velocity (GSE, Sun Frame)
+ CATDESC: Solar wind alpha-particle bulk velocity vector in GSE coordinates (Sun frame)
+ DEPEND_0: epoch
+ LABL_PTR_1: alpha_sw_velocity_gse_sun_label
+ VAR_TYPE: data
+ RECORD_VARYING: RV
+ DISPLAY_TYPE: time_series
+ VARIABLE_PURPOSE: PRIMARY_VAR,SUMMARY
+ FORMAT: F19.3
+ LABLAXIS: Va GSE Sun
+ UNITS: km/s
+ VALIDMIN: -10000
+ VALIDMAX: 10000
+ FILLVAL: -1.000000e+31
+ SCALETYP: linear
+ DELTA_PLUS_VAR: alpha_sw_velocity_gse_uncert
+ DELTA_MINUS_VAR: alpha_sw_velocity_gse_uncert
+alpha_sw_velocity_gse:
+ NAME: alpha_sw_velocity_gse
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Alpha Solar Wind Velocity (GSE)
+ CATDESC: Solar wind alpha-particle bulk velocity vector in GSE coordinates (spacecraft frame)
+ DEPEND_0: epoch
+ LABL_PTR_1: alpha_sw_velocity_gse_label
+ VAR_TYPE: data
+ RECORD_VARYING: RV
+ DISPLAY_TYPE: time_series
+ VARIABLE_PURPOSE: PRIMARY_VAR,SUMMARY
+ FORMAT: F19.3
+ LABLAXIS: Va GSE SC
+ UNITS: km/s
+ VALIDMIN: -10000
+ VALIDMAX: 10000
+ FILLVAL: -1.000000e+31
+ SCALETYP: linear
+ DELTA_PLUS_VAR: alpha_sw_velocity_gse_uncert
+ DELTA_MINUS_VAR: alpha_sw_velocity_gse_uncert
+alpha_sw_velocity_gse_covariance:
+ NAME: alpha_sw_velocity_gse_covariance
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Alpha Solar Wind Velocity Covariance (GSE)
+ CATDESC: Covariance matrix in GSE coordinates, with standard errors given by the square root of the diagonal
+ DEPEND_0: epoch
+ VAR_TYPE: support_data
+ RECORD_VARYING: RV
+ FORMAT: F19.3
+ LABLAXIS: cov Va
+ UNITS: km^2/s^2
+ VALIDMIN: -1.0e+8
+ VALIDMAX: 1.0e+8
+ FILLVAL: -1.000000e+31
+ LABL_PTR_1: velocity_gse_label
+ LABL_PTR_2: velocity_gse_label
+alpha_sw_velocity_gse_uncert:
+ NAME: alpha_sw_velocity_gse_uncert
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Alpha Solar Wind Velocity Uncertainty (GSE)
+ CATDESC: 1-sigma standard error
+ DEPEND_0: epoch
+ LABL_PTR_1: velocity_gse_label
+ VAR_TYPE: support_data
+ RECORD_VARYING: RV
+ FORMAT: F19.3
+ LABLAXIS: Va GSE Err
+ UNITS: km/s
+ VALIDMIN: 0
+ VALIDMAX: 10000
+ FILLVAL: -1.000000e+31
+ SCALETYP: linear
+alpha_sw_velocity_gsm_sun:
+ NAME: alpha_sw_velocity_gsm_sun
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Alpha Solar Wind Velocity (GSM, Sun Frame)
+ CATDESC: Solar wind alpha-particle bulk velocity vector in GSM coordinates (Sun frame)
+ DEPEND_0: epoch
+ LABL_PTR_1: alpha_sw_velocity_gsm_sun_label
+ VAR_TYPE: data
+ RECORD_VARYING: RV
+ DISPLAY_TYPE: time_series
+ VARIABLE_PURPOSE: PRIMARY_VAR,SUMMARY
+ FORMAT: F19.3
+ LABLAXIS: Va GSM Sun
+ UNITS: km/s
+ VALIDMIN: -10000
+ VALIDMAX: 10000
+ FILLVAL: -1.000000e+31
+ SCALETYP: linear
+ DELTA_PLUS_VAR: alpha_sw_velocity_gsm_uncert
+ DELTA_MINUS_VAR: alpha_sw_velocity_gsm_uncert
+alpha_sw_velocity_gsm:
+ NAME: alpha_sw_velocity_gsm
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Alpha Solar Wind Velocity (GSM)
+ CATDESC: Solar wind alpha-particle bulk velocity vector in GSM coordinates (spacecraft frame)
+ DEPEND_0: epoch
+ LABL_PTR_1: alpha_sw_velocity_gsm_label
+ VAR_TYPE: data
+ RECORD_VARYING: RV
+ DISPLAY_TYPE: time_series
+ VARIABLE_PURPOSE: PRIMARY_VAR,SUMMARY
+ FORMAT: F19.3
+ LABLAXIS: Va GSM SC
+ UNITS: km/s
+ VALIDMIN: -10000
+ VALIDMAX: 10000
+ FILLVAL: -1.000000e+31
+ SCALETYP: linear
+ DELTA_PLUS_VAR: alpha_sw_velocity_gsm_uncert
+ DELTA_MINUS_VAR: alpha_sw_velocity_gsm_uncert
+alpha_sw_velocity_gsm_covariance:
+ NAME: alpha_sw_velocity_gsm_covariance
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Alpha Solar Wind Velocity Covariance (GSM)
+ CATDESC: Covariance matrix in GSM coordinates, with standard errors given by the square root of the diagonal
+ DEPEND_0: epoch
+ VAR_TYPE: support_data
+ RECORD_VARYING: RV
+ FORMAT: F19.3
+ LABLAXIS: cov Va
+ UNITS: km^2/s^2
+ VALIDMIN: -1.0e+8
+ VALIDMAX: 1.0e+8
+ FILLVAL: -1.000000e+31
+ LABL_PTR_1: velocity_gsm_label
+ LABL_PTR_2: velocity_gsm_label
+alpha_sw_velocity_gsm_uncert:
+ NAME: alpha_sw_velocity_gsm_uncert
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Alpha Solar Wind Velocity Uncertainty (GSM)
+ CATDESC: 1-sigma standard error
+ DEPEND_0: epoch
+ LABL_PTR_1: velocity_gsm_label
+ VAR_TYPE: support_data
+ RECORD_VARYING: RV
+ FORMAT: F19.3
+ LABLAXIS: Va GSM Err
+ UNITS: km/s
+ VALIDMIN: 0
+ VALIDMAX: 10000
+ FILLVAL: -1.000000e+31
+ SCALETYP: linear
+alpha_sw_velocity_hae_sun:
+ NAME: alpha_sw_velocity_hae_sun
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Alpha Solar Wind Velocity (HAE, Sun Frame)
+ CATDESC: Solar wind alpha-particle bulk velocity vector in HAE coordinates (Sun frame)
+ DEPEND_0: epoch
+ LABL_PTR_1: alpha_sw_velocity_hae_sun_label
+ VAR_TYPE: data
+ RECORD_VARYING: RV
+ DISPLAY_TYPE: time_series
+ VARIABLE_PURPOSE: PRIMARY_VAR,SUMMARY
+ FORMAT: F19.3
+ LABLAXIS: Va HAE Sun
+ UNITS: km/s
+ VALIDMIN: -10000
+ VALIDMAX: 10000
+ FILLVAL: -1.000000e+31
+ SCALETYP: linear
+ DELTA_PLUS_VAR: alpha_sw_velocity_hae_uncert
+ DELTA_MINUS_VAR: alpha_sw_velocity_hae_uncert
+alpha_sw_velocity_hae:
+ NAME: alpha_sw_velocity_hae
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Alpha Solar Wind Velocity (HAE)
+ CATDESC: Solar wind alpha-particle bulk velocity vector in HAE coordinates (spacecraft frame)
+ DEPEND_0: epoch
+ LABL_PTR_1: alpha_sw_velocity_hae_label
+ VAR_TYPE: data
+ RECORD_VARYING: RV
+ DISPLAY_TYPE: time_series
+ VARIABLE_PURPOSE: PRIMARY_VAR,SUMMARY
+ FORMAT: F19.3
+ LABLAXIS: Va HAE SC
+ UNITS: km/s
+ VALIDMIN: -10000
+ VALIDMAX: 10000
+ FILLVAL: -1.000000e+31
+ SCALETYP: linear
+ DELTA_PLUS_VAR: alpha_sw_velocity_hae_uncert
+ DELTA_MINUS_VAR: alpha_sw_velocity_hae_uncert
+alpha_sw_velocity_hae_covariance:
+ NAME: alpha_sw_velocity_hae_covariance
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Alpha Solar Wind Velocity Covariance (HAE)
+ CATDESC: Covariance matrix in HAE coordinates, with standard errors given by the square root of the diagonal
+ DEPEND_0: epoch
+ VAR_TYPE: support_data
+ RECORD_VARYING: RV
+ FORMAT: F19.3
+ LABLAXIS: cov Va
+ UNITS: km^2/s^2
+ VALIDMIN: -1.0e+8
+ VALIDMAX: 1.0e+8
+ FILLVAL: -1.000000e+31
+ LABL_PTR_1: velocity_hae_label
+ LABL_PTR_2: velocity_hae_label
+alpha_sw_velocity_hae_uncert:
+ NAME: alpha_sw_velocity_hae_uncert
+ DATA_TYPE: CDF_REAL4
+ FIELDNAM: Alpha Solar Wind Velocity Uncertainty (HAE)
+ CATDESC: 1-sigma standard error
+ DEPEND_0: epoch
+ LABL_PTR_1: velocity_hae_label
+ VAR_TYPE: support_data
+ RECORD_VARYING: RV
+ FORMAT: F19.3
+ LABLAXIS: Va HAE Err
+ UNITS: km/s
+ VALIDMIN: 0
+ VALIDMAX: 10000
+ FILLVAL: -1.000000e+31
+ SCALETYP: linear
swp_flags:
NAME: swp_flags
DATA_TYPE: CDF_UINT2
@@ -630,6 +1062,33 @@ velocity_rtn_label:
RECORD_VARYING: NRV
FORMAT: a20
FILLVAL: ' '
+velocity_gse_label:
+ NAME: velocity_gse_label
+ DATA_TYPE: CDF_CHAR
+ FIELDNAM: Velocity GSE Label
+ CATDESC: Label for Geocentric Solar Ecliptic (GSE) velocity components
+ VAR_TYPE: metadata
+ RECORD_VARYING: NRV
+ FORMAT: a20
+ FILLVAL: ' '
+velocity_gsm_label:
+ NAME: velocity_gsm_label
+ DATA_TYPE: CDF_CHAR
+ FIELDNAM: Velocity GSM Label
+ CATDESC: Label for Geocentric Solar Magnetospheric (GSM) velocity components
+ VAR_TYPE: metadata
+ RECORD_VARYING: NRV
+ FORMAT: a20
+ FILLVAL: ' '
+velocity_hae_label:
+ NAME: velocity_hae_label
+ DATA_TYPE: CDF_CHAR
+ FIELDNAM: Velocity HAE Label
+ CATDESC: Label for Heliocentric Aries Ecliptic (HAE) velocity components
+ VAR_TYPE: metadata
+ RECORD_VARYING: NRV
+ FORMAT: a20
+ FILLVAL: ' '
alpha_sw_velocity_rtn_label:
NAME: alpha_sw_velocity_rtn_label
DATA_TYPE: CDF_CHAR
@@ -666,4 +1125,111 @@ proton_sw_velocity_rtn_sun_label:
RECORD_VARYING: NRV
FORMAT: a20
FILLVAL: ' '
-
+alpha_sw_velocity_gse_label:
+ NAME: alpha_sw_velocity_gse_label
+ DATA_TYPE: CDF_CHAR
+ FIELDNAM: Velocity GSE Label
+ CATDESC: Label for alpha solar wind velocity components in GSE coordinates
+ VAR_TYPE: metadata
+ RECORD_VARYING: NRV
+ FORMAT: a20
+ FILLVAL: ' '
+alpha_sw_velocity_gse_sun_label:
+ NAME: alpha_sw_velocity_gse_sun_label
+ DATA_TYPE: CDF_CHAR
+ FIELDNAM: Velocity GSE Label
+ CATDESC: Label for Sun-frame alpha solar wind velocity components in GSE coordinates
+ VAR_TYPE: metadata
+ RECORD_VARYING: NRV
+ FORMAT: a20
+ FILLVAL: ' '
+alpha_sw_velocity_gsm_label:
+ NAME: alpha_sw_velocity_gsm_label
+ DATA_TYPE: CDF_CHAR
+ FIELDNAM: Velocity GSM Label
+ CATDESC: Label for alpha solar wind velocity components in GSM coordinates
+ VAR_TYPE: metadata
+ RECORD_VARYING: NRV
+ FORMAT: a20
+ FILLVAL: ' '
+alpha_sw_velocity_gsm_sun_label:
+ NAME: alpha_sw_velocity_gsm_sun_label
+ DATA_TYPE: CDF_CHAR
+ FIELDNAM: Velocity GSM Label
+ CATDESC: Label for Sun-frame alpha solar wind velocity components in GSM coordinates
+ VAR_TYPE: metadata
+ RECORD_VARYING: NRV
+ FORMAT: a20
+ FILLVAL: ' '
+alpha_sw_velocity_hae_label:
+ NAME: alpha_sw_velocity_hae_label
+ DATA_TYPE: CDF_CHAR
+ FIELDNAM: Velocity HAE Label
+ CATDESC: Label for alpha solar wind velocity components in HAE coordinates
+ VAR_TYPE: metadata
+ RECORD_VARYING: NRV
+ FORMAT: a20
+ FILLVAL: ' '
+alpha_sw_velocity_hae_sun_label:
+ NAME: alpha_sw_velocity_hae_sun_label
+ DATA_TYPE: CDF_CHAR
+ FIELDNAM: Velocity HAE Label
+ CATDESC: Label for Sun-frame alpha solar wind velocity components in HAE coordinates
+ VAR_TYPE: metadata
+ RECORD_VARYING: NRV
+ FORMAT: a20
+ FILLVAL: ' '
+proton_sw_velocity_gse_label:
+ NAME: proton_sw_velocity_gse_label
+ DATA_TYPE: CDF_CHAR
+ FIELDNAM: Velocity GSE Label
+ CATDESC: Label for proton solar wind velocity components in GSE coordinates
+ VAR_TYPE: metadata
+ RECORD_VARYING: NRV
+ FORMAT: a20
+ FILLVAL: ' '
+proton_sw_velocity_gse_sun_label:
+ NAME: proton_sw_velocity_gse_sun_label
+ DATA_TYPE: CDF_CHAR
+ FIELDNAM: Velocity GSE Label
+ CATDESC: Label for Sun-frame proton solar wind velocity components in GSE coordinates
+ VAR_TYPE: metadata
+ RECORD_VARYING: NRV
+ FORMAT: a20
+ FILLVAL: ' '
+proton_sw_velocity_gsm_label:
+ NAME: proton_sw_velocity_gsm_label
+ DATA_TYPE: CDF_CHAR
+ FIELDNAM: Velocity GSM Label
+ CATDESC: Label for proton solar wind velocity components in GSM coordinates
+ VAR_TYPE: metadata
+ RECORD_VARYING: NRV
+ FORMAT: a20
+ FILLVAL: ' '
+proton_sw_velocity_gsm_sun_label:
+ NAME: proton_sw_velocity_gsm_sun_label
+ DATA_TYPE: CDF_CHAR
+ FIELDNAM: Velocity GSM Label
+ CATDESC: Label for Sun-frame proton solar wind velocity components in GSM coordinates
+ VAR_TYPE: metadata
+ RECORD_VARYING: NRV
+ FORMAT: a20
+ FILLVAL: ' '
+proton_sw_velocity_hae_label:
+ NAME: proton_sw_velocity_hae_label
+ DATA_TYPE: CDF_CHAR
+ FIELDNAM: Velocity HAE Label
+ CATDESC: Label for proton solar wind velocity components in HAE coordinates
+ VAR_TYPE: metadata
+ RECORD_VARYING: NRV
+ FORMAT: a20
+ FILLVAL: ' '
+proton_sw_velocity_hae_sun_label:
+ NAME: proton_sw_velocity_hae_sun_label
+ DATA_TYPE: CDF_CHAR
+ FIELDNAM: Velocity HAE Label
+ CATDESC: Label for Sun-frame proton solar wind velocity components in HAE coordinates
+ VAR_TYPE: metadata
+ RECORD_VARYING: NRV
+ FORMAT: a20
+ FILLVAL: ' '
diff --git a/imap_l3_processing/swapi/l3a/models.py b/imap_l3_processing/swapi/l3a/models.py
index c04d82eb..23e5723e 100644
--- a/imap_l3_processing/swapi/l3a/models.py
+++ b/imap_l3_processing/swapi/l3a/models.py
@@ -34,6 +34,30 @@
PROTON_SOLAR_WIND_VELOCITY_RTN_UNCERTAINTY_CDF_VAR_NAME = (
"proton_sw_velocity_rtn_uncert"
)
+PROTON_SOLAR_WIND_VELOCITY_GSE_SUN_CDF_VAR_NAME = "proton_sw_velocity_gse_sun"
+PROTON_SOLAR_WIND_VELOCITY_GSE_CDF_VAR_NAME = "proton_sw_velocity_gse"
+PROTON_SOLAR_WIND_VELOCITY_GSE_COVARIANCE_CDF_VAR_NAME = (
+ "proton_sw_velocity_gse_covariance"
+)
+PROTON_SOLAR_WIND_VELOCITY_GSE_UNCERTAINTY_CDF_VAR_NAME = (
+ "proton_sw_velocity_gse_uncert"
+)
+PROTON_SOLAR_WIND_VELOCITY_GSM_SUN_CDF_VAR_NAME = "proton_sw_velocity_gsm_sun"
+PROTON_SOLAR_WIND_VELOCITY_GSM_CDF_VAR_NAME = "proton_sw_velocity_gsm"
+PROTON_SOLAR_WIND_VELOCITY_GSM_COVARIANCE_CDF_VAR_NAME = (
+ "proton_sw_velocity_gsm_covariance"
+)
+PROTON_SOLAR_WIND_VELOCITY_GSM_UNCERTAINTY_CDF_VAR_NAME = (
+ "proton_sw_velocity_gsm_uncert"
+)
+PROTON_SOLAR_WIND_VELOCITY_HAE_SUN_CDF_VAR_NAME = "proton_sw_velocity_hae_sun"
+PROTON_SOLAR_WIND_VELOCITY_HAE_CDF_VAR_NAME = "proton_sw_velocity_hae"
+PROTON_SOLAR_WIND_VELOCITY_HAE_COVARIANCE_CDF_VAR_NAME = (
+ "proton_sw_velocity_hae_covariance"
+)
+PROTON_SOLAR_WIND_VELOCITY_HAE_UNCERTAINTY_CDF_VAR_NAME = (
+ "proton_sw_velocity_hae_uncert"
+)
ALPHA_SOLAR_WIND_SPEED_CDF_VAR_NAME = "alpha_sw_speed"
ALPHA_SOLAR_WIND_SPEED_UNCERTAINTY_CDF_VAR_NAME = "alpha_sw_speed_uncert"
@@ -51,6 +75,30 @@
ALPHA_SOLAR_WIND_VELOCITY_RTN_UNCERTAINTY_CDF_VAR_NAME = (
"alpha_sw_velocity_rtn_uncert"
)
+ALPHA_SOLAR_WIND_VELOCITY_GSE_SUN_CDF_VAR_NAME = "alpha_sw_velocity_gse_sun"
+ALPHA_SOLAR_WIND_VELOCITY_GSE_CDF_VAR_NAME = "alpha_sw_velocity_gse"
+ALPHA_SOLAR_WIND_VELOCITY_GSE_COVARIANCE_CDF_VAR_NAME = (
+ "alpha_sw_velocity_gse_covariance"
+)
+ALPHA_SOLAR_WIND_VELOCITY_GSE_UNCERTAINTY_CDF_VAR_NAME = (
+ "alpha_sw_velocity_gse_uncert"
+)
+ALPHA_SOLAR_WIND_VELOCITY_GSM_SUN_CDF_VAR_NAME = "alpha_sw_velocity_gsm_sun"
+ALPHA_SOLAR_WIND_VELOCITY_GSM_CDF_VAR_NAME = "alpha_sw_velocity_gsm"
+ALPHA_SOLAR_WIND_VELOCITY_GSM_COVARIANCE_CDF_VAR_NAME = (
+ "alpha_sw_velocity_gsm_covariance"
+)
+ALPHA_SOLAR_WIND_VELOCITY_GSM_UNCERTAINTY_CDF_VAR_NAME = (
+ "alpha_sw_velocity_gsm_uncert"
+)
+ALPHA_SOLAR_WIND_VELOCITY_HAE_SUN_CDF_VAR_NAME = "alpha_sw_velocity_hae_sun"
+ALPHA_SOLAR_WIND_VELOCITY_HAE_CDF_VAR_NAME = "alpha_sw_velocity_hae"
+ALPHA_SOLAR_WIND_VELOCITY_HAE_COVARIANCE_CDF_VAR_NAME = (
+ "alpha_sw_velocity_hae_covariance"
+)
+ALPHA_SOLAR_WIND_VELOCITY_HAE_UNCERTAINTY_CDF_VAR_NAME = (
+ "alpha_sw_velocity_hae_uncert"
+)
PUI_IONIZATION_RATE_CDF_VAR_NAME = "pui_ionization_rate"
PUI_CUTOFF_SPEED_CDF_VAR_NAME = "pui_cutoff_speed"
@@ -64,11 +112,26 @@
SWAPI_QUALITY_FLAGS_CDF_VAR_NAME = "swp_flags"
VELOCITY_RTN_LABEL_CDF_VAR_NAME = "velocity_rtn_label"
+VELOCITY_GSE_LABEL_CDF_VAR_NAME = "velocity_gse_label"
+VELOCITY_GSM_LABEL_CDF_VAR_NAME = "velocity_gsm_label"
+VELOCITY_HAE_LABEL_CDF_VAR_NAME = "velocity_hae_label"
ALPHA_VELOCITY_RTN_LABEL_CDF_VAR_NAME = "alpha_sw_velocity_rtn_label"
ALPHA_VELOCITY_RTN_SUN_LABEL_CDF_VAR_NAME = "alpha_sw_velocity_rtn_sun_label"
+ALPHA_VELOCITY_GSE_LABEL_CDF_VAR_NAME = "alpha_sw_velocity_gse_label"
+ALPHA_VELOCITY_GSE_SUN_LABEL_CDF_VAR_NAME = "alpha_sw_velocity_gse_sun_label"
+ALPHA_VELOCITY_GSM_LABEL_CDF_VAR_NAME = "alpha_sw_velocity_gsm_label"
+ALPHA_VELOCITY_GSM_SUN_LABEL_CDF_VAR_NAME = "alpha_sw_velocity_gsm_sun_label"
+ALPHA_VELOCITY_HAE_LABEL_CDF_VAR_NAME = "alpha_sw_velocity_hae_label"
+ALPHA_VELOCITY_HAE_SUN_LABEL_CDF_VAR_NAME = "alpha_sw_velocity_hae_sun_label"
PROTON_SOLAR_WIND_VELOCITY_RTN_SUN_LABEL_CDF_VAR_NAME = "proton_sw_velocity_rtn_sun_label"
PROTON_SOLAR_WIND_VELOCITY_RTN_LABEL_CDF_VAR_NAME = "proton_sw_velocity_rtn_label"
+PROTON_SOLAR_WIND_VELOCITY_GSE_SUN_LABEL_CDF_VAR_NAME = "proton_sw_velocity_gse_sun_label"
+PROTON_SOLAR_WIND_VELOCITY_GSE_LABEL_CDF_VAR_NAME = "proton_sw_velocity_gse_label"
+PROTON_SOLAR_WIND_VELOCITY_GSM_SUN_LABEL_CDF_VAR_NAME = "proton_sw_velocity_gsm_sun_label"
+PROTON_SOLAR_WIND_VELOCITY_GSM_LABEL_CDF_VAR_NAME = "proton_sw_velocity_gsm_label"
+PROTON_SOLAR_WIND_VELOCITY_HAE_SUN_LABEL_CDF_VAR_NAME = "proton_sw_velocity_hae_sun_label"
+PROTON_SOLAR_WIND_VELOCITY_HAE_LABEL_CDF_VAR_NAME = "proton_sw_velocity_hae_label"
@dataclass
@@ -85,6 +148,15 @@ class SwapiL3ProtonSolarWindData(DataProduct):
proton_sw_velocity_rtn_sun: np.ndarray # shape (N, 3), km/s, inertial RTN
proton_sw_velocity_rtn: np.ndarray # shape (N, 3), km/s, RTN in SC rest frame
proton_sw_velocity_rtn_covariance: np.ndarray # shape (N, 3, 3), km²/s²
+ proton_sw_velocity_gse_sun: np.ndarray
+ proton_sw_velocity_gse: np.ndarray
+ proton_sw_velocity_gse_covariance: np.ndarray
+ proton_sw_velocity_gsm_sun: np.ndarray
+ proton_sw_velocity_gsm: np.ndarray
+ proton_sw_velocity_gsm_covariance: np.ndarray
+ proton_sw_velocity_hae_sun: np.ndarray
+ proton_sw_velocity_hae: np.ndarray
+ proton_sw_velocity_hae_covariance: np.ndarray
quality_flags: np.ndarray[SwapiL3Flags]
def to_data_product_variables(self) -> list[DataProductVariable]:
@@ -143,10 +215,79 @@ def to_data_product_variables(self) -> list[DataProductVariable]:
)
),
),
+ DataProductVariable(
+ PROTON_SOLAR_WIND_VELOCITY_GSE_SUN_CDF_VAR_NAME,
+ self.proton_sw_velocity_gse_sun,
+ ),
+ DataProductVariable(
+ PROTON_SOLAR_WIND_VELOCITY_GSE_CDF_VAR_NAME,
+ self.proton_sw_velocity_gse,
+ ),
+ DataProductVariable(
+ PROTON_SOLAR_WIND_VELOCITY_GSE_COVARIANCE_CDF_VAR_NAME,
+ self.proton_sw_velocity_gse_covariance,
+ ),
+ DataProductVariable(
+ PROTON_SOLAR_WIND_VELOCITY_GSE_UNCERTAINTY_CDF_VAR_NAME,
+ np.sqrt(
+ np.diagonal(
+ self.proton_sw_velocity_gse_covariance, axis1=1, axis2=2
+ )
+ ),
+ ),
+ DataProductVariable(
+ PROTON_SOLAR_WIND_VELOCITY_GSM_SUN_CDF_VAR_NAME,
+ self.proton_sw_velocity_gsm_sun,
+ ),
+ DataProductVariable(
+ PROTON_SOLAR_WIND_VELOCITY_GSM_CDF_VAR_NAME,
+ self.proton_sw_velocity_gsm,
+ ),
+ DataProductVariable(
+ PROTON_SOLAR_WIND_VELOCITY_GSM_COVARIANCE_CDF_VAR_NAME,
+ self.proton_sw_velocity_gsm_covariance,
+ ),
+ DataProductVariable(
+ PROTON_SOLAR_WIND_VELOCITY_GSM_UNCERTAINTY_CDF_VAR_NAME,
+ np.sqrt(
+ np.diagonal(
+ self.proton_sw_velocity_gsm_covariance, axis1=1, axis2=2
+ )
+ ),
+ ),
+ DataProductVariable(
+ PROTON_SOLAR_WIND_VELOCITY_HAE_SUN_CDF_VAR_NAME,
+ self.proton_sw_velocity_hae_sun,
+ ),
+ DataProductVariable(
+ PROTON_SOLAR_WIND_VELOCITY_HAE_CDF_VAR_NAME,
+ self.proton_sw_velocity_hae,
+ ),
+ DataProductVariable(
+ PROTON_SOLAR_WIND_VELOCITY_HAE_COVARIANCE_CDF_VAR_NAME,
+ self.proton_sw_velocity_hae_covariance,
+ ),
+ DataProductVariable(
+ PROTON_SOLAR_WIND_VELOCITY_HAE_UNCERTAINTY_CDF_VAR_NAME,
+ np.sqrt(
+ np.diagonal(
+ self.proton_sw_velocity_hae_covariance, axis1=1, axis2=2
+ )
+ ),
+ ),
DataProductVariable(SWAPI_QUALITY_FLAGS_CDF_VAR_NAME, self.quality_flags),
DataProductVariable(VELOCITY_RTN_LABEL_CDF_VAR_NAME, value=["R", "T", "N"]),
+ DataProductVariable(VELOCITY_GSE_LABEL_CDF_VAR_NAME, value=["X", "Y", "Z"]),
+ DataProductVariable(VELOCITY_GSM_LABEL_CDF_VAR_NAME, value=["X", "Y", "Z"]),
+ DataProductVariable(VELOCITY_HAE_LABEL_CDF_VAR_NAME, value=["X", "Y", "Z"]),
DataProductVariable(PROTON_SOLAR_WIND_VELOCITY_RTN_LABEL_CDF_VAR_NAME, value=["Vp SC R", "Vp SC T", "Vp SC N"]),
DataProductVariable(PROTON_SOLAR_WIND_VELOCITY_RTN_SUN_LABEL_CDF_VAR_NAME, value=["Vp Sun R", "Vp Sun T", "Vp Sun N"]),
+ DataProductVariable(PROTON_SOLAR_WIND_VELOCITY_GSE_LABEL_CDF_VAR_NAME, value=["Vp SC X", "Vp SC Y", "Vp SC Z"]),
+ DataProductVariable(PROTON_SOLAR_WIND_VELOCITY_GSE_SUN_LABEL_CDF_VAR_NAME, value=["Vp Sun X", "Vp Sun Y", "Vp Sun Z"]),
+ DataProductVariable(PROTON_SOLAR_WIND_VELOCITY_GSM_LABEL_CDF_VAR_NAME, value=["Vp SC X", "Vp SC Y", "Vp SC Z"]),
+ DataProductVariable(PROTON_SOLAR_WIND_VELOCITY_GSM_SUN_LABEL_CDF_VAR_NAME, value=["Vp Sun X", "Vp Sun Y", "Vp Sun Z"]),
+ DataProductVariable(PROTON_SOLAR_WIND_VELOCITY_HAE_LABEL_CDF_VAR_NAME, value=["Vp SC X", "Vp SC Y", "Vp SC Z"]),
+ DataProductVariable(PROTON_SOLAR_WIND_VELOCITY_HAE_SUN_LABEL_CDF_VAR_NAME, value=["Vp Sun X", "Vp Sun Y", "Vp Sun Z"]),
]
@@ -164,6 +305,15 @@ class SwapiL3AlphaSolarWindData(DataProduct):
alpha_sw_velocity_rtn_sun: np.ndarray # shape (N, 3), km/s, inertial RTN
alpha_sw_velocity_rtn: np.ndarray # shape (N, 3), km/s, RTN in SC rest frame
alpha_sw_velocity_rtn_covariance: np.ndarray # shape (N, 3, 3), km²/s²
+ alpha_sw_velocity_gse_sun: np.ndarray
+ alpha_sw_velocity_gse: np.ndarray
+ alpha_sw_velocity_gse_covariance: np.ndarray
+ alpha_sw_velocity_gsm_sun: np.ndarray
+ alpha_sw_velocity_gsm: np.ndarray
+ alpha_sw_velocity_gsm_covariance: np.ndarray
+ alpha_sw_velocity_hae_sun: np.ndarray
+ alpha_sw_velocity_hae: np.ndarray
+ alpha_sw_velocity_hae_covariance: np.ndarray
quality_flags: np.ndarray
def to_data_product_variables(self) -> list[DataProductVariable]:
@@ -222,10 +372,79 @@ def to_data_product_variables(self) -> list[DataProductVariable]:
)
),
),
+ DataProductVariable(
+ ALPHA_SOLAR_WIND_VELOCITY_GSE_SUN_CDF_VAR_NAME,
+ self.alpha_sw_velocity_gse_sun,
+ ),
+ DataProductVariable(
+ ALPHA_SOLAR_WIND_VELOCITY_GSE_CDF_VAR_NAME,
+ self.alpha_sw_velocity_gse,
+ ),
+ DataProductVariable(
+ ALPHA_SOLAR_WIND_VELOCITY_GSE_COVARIANCE_CDF_VAR_NAME,
+ self.alpha_sw_velocity_gse_covariance,
+ ),
+ DataProductVariable(
+ ALPHA_SOLAR_WIND_VELOCITY_GSE_UNCERTAINTY_CDF_VAR_NAME,
+ np.sqrt(
+ np.diagonal(
+ self.alpha_sw_velocity_gse_covariance, axis1=1, axis2=2
+ )
+ ),
+ ),
+ DataProductVariable(
+ ALPHA_SOLAR_WIND_VELOCITY_GSM_SUN_CDF_VAR_NAME,
+ self.alpha_sw_velocity_gsm_sun,
+ ),
+ DataProductVariable(
+ ALPHA_SOLAR_WIND_VELOCITY_GSM_CDF_VAR_NAME,
+ self.alpha_sw_velocity_gsm,
+ ),
+ DataProductVariable(
+ ALPHA_SOLAR_WIND_VELOCITY_GSM_COVARIANCE_CDF_VAR_NAME,
+ self.alpha_sw_velocity_gsm_covariance,
+ ),
+ DataProductVariable(
+ ALPHA_SOLAR_WIND_VELOCITY_GSM_UNCERTAINTY_CDF_VAR_NAME,
+ np.sqrt(
+ np.diagonal(
+ self.alpha_sw_velocity_gsm_covariance, axis1=1, axis2=2
+ )
+ ),
+ ),
+ DataProductVariable(
+ ALPHA_SOLAR_WIND_VELOCITY_HAE_SUN_CDF_VAR_NAME,
+ self.alpha_sw_velocity_hae_sun,
+ ),
+ DataProductVariable(
+ ALPHA_SOLAR_WIND_VELOCITY_HAE_CDF_VAR_NAME,
+ self.alpha_sw_velocity_hae,
+ ),
+ DataProductVariable(
+ ALPHA_SOLAR_WIND_VELOCITY_HAE_COVARIANCE_CDF_VAR_NAME,
+ self.alpha_sw_velocity_hae_covariance,
+ ),
+ DataProductVariable(
+ ALPHA_SOLAR_WIND_VELOCITY_HAE_UNCERTAINTY_CDF_VAR_NAME,
+ np.sqrt(
+ np.diagonal(
+ self.alpha_sw_velocity_hae_covariance, axis1=1, axis2=2
+ )
+ ),
+ ),
DataProductVariable(SWAPI_QUALITY_FLAGS_CDF_VAR_NAME, self.quality_flags),
DataProductVariable(VELOCITY_RTN_LABEL_CDF_VAR_NAME, value=["R", "T", "N"]),
+ DataProductVariable(VELOCITY_GSE_LABEL_CDF_VAR_NAME, value=["X", "Y", "Z"]),
+ DataProductVariable(VELOCITY_GSM_LABEL_CDF_VAR_NAME, value=["X", "Y", "Z"]),
+ DataProductVariable(VELOCITY_HAE_LABEL_CDF_VAR_NAME, value=["X", "Y", "Z"]),
DataProductVariable(ALPHA_VELOCITY_RTN_LABEL_CDF_VAR_NAME, value=["Va SC R", "Va SC T", "Va SC N"]),
DataProductVariable(ALPHA_VELOCITY_RTN_SUN_LABEL_CDF_VAR_NAME, value=["Va Sun R", "Va Sun T", "Va Sun N"]),
+ DataProductVariable(ALPHA_VELOCITY_GSE_LABEL_CDF_VAR_NAME, value=["Va SC X", "Va SC Y", "Va SC Z"]),
+ DataProductVariable(ALPHA_VELOCITY_GSE_SUN_LABEL_CDF_VAR_NAME, value=["Va Sun X", "Va Sun Y", "Va Sun Z"]),
+ DataProductVariable(ALPHA_VELOCITY_GSM_LABEL_CDF_VAR_NAME, value=["Va SC X", "Va SC Y", "Va SC Z"]),
+ DataProductVariable(ALPHA_VELOCITY_GSM_SUN_LABEL_CDF_VAR_NAME, value=["Va Sun X", "Va Sun Y", "Va Sun Z"]),
+ DataProductVariable(ALPHA_VELOCITY_HAE_LABEL_CDF_VAR_NAME, value=["Va SC X", "Va SC Y", "Va SC Z"]),
+ DataProductVariable(ALPHA_VELOCITY_HAE_SUN_LABEL_CDF_VAR_NAME, value=["Va Sun X", "Va Sun Y", "Va Sun Z"]),
]
diff --git a/imap_l3_processing/swapi/l3a/utils.py b/imap_l3_processing/swapi/l3a/utils.py
index 0f44b2f5..74ec89a7 100644
--- a/imap_l3_processing/swapi/l3a/utils.py
+++ b/imap_l3_processing/swapi/l3a/utils.py
@@ -115,6 +115,38 @@ def get_spacecraft_velocity_rtn(epoch_tt2000_ns: float) -> ndarray:
return np.einsum("ij,j->i", rtn_from_eclipj2000, state_eclipj2000[3:])
+def convert_velocity_rtn_to_frame(
+ epoch_tt2000_ns: ndarray,
+ velocity_rtn: ndarray,
+ target_frame: SpiceFrame,
+) -> ndarray:
+ """Express RTN velocity vectors in another coordinate frame."""
+ ephemeris_times = ttj2000ns_to_et(epoch_tt2000_ns)
+ rotation_matrices = get_rotation_matrix(
+ ephemeris_times, SpiceFrame.IMAP_RTN, target_frame
+ )
+ return np.einsum("nij,nj->ni", rotation_matrices, velocity_rtn)
+
+
+def convert_velocity_covariance_rtn_to_frame(
+ epoch_tt2000_ns: ndarray,
+ covariance_rtn: ndarray,
+ target_frame: SpiceFrame,
+) -> ndarray:
+ """Express RTN velocity covariance matrices in another coordinate frame."""
+ ephemeris_times = ttj2000ns_to_et(epoch_tt2000_ns)
+ rotation_matrices = get_rotation_matrix(
+ ephemeris_times, SpiceFrame.IMAP_RTN, target_frame
+ )
+ # This is equivalent to R C R^T
+ return np.einsum(
+ "nij,njk,nlk->nil",
+ rotation_matrices,
+ covariance_rtn,
+ rotation_matrices,
+ )
+
+
@numba.njit
def velocity_components_to_angles_in_instrument_frame(vx: float, vy: float, vz: float):
"""Convert a Cartesian flow-direction velocity to (azimuth_deg, elevation_deg)
diff --git a/imap_l3_processing/swapi/swapi_processor.py b/imap_l3_processing/swapi/swapi_processor.py
index aa4ae7b1..8655ea92 100644
--- a/imap_l3_processing/swapi/swapi_processor.py
+++ b/imap_l3_processing/swapi/swapi_processor.py
@@ -3,6 +3,7 @@
import numpy as np
from imap_data_access.processing_input import ProcessingInputCollection
+from imap_processing.spice.geometry import SpiceFrame
from uncertainties.unumpy import uarray
from imap_l3_processing.constants import FIVE_MINUTES_IN_NANOSECONDS
@@ -26,6 +27,8 @@
from imap_l3_processing.swapi.l3a.swapi_l3a_dependencies import SwapiL3ADependencies
from imap_l3_processing.swapi.l3a.utils import (
chunk_l2_data,
+ convert_velocity_covariance_rtn_to_frame,
+ convert_velocity_rtn_to_frame,
)
from imap_l3_processing.swapi.l3b.models import SwapiL3BCombinedVDF
from imap_l3_processing.swapi.l3b.science.calculate_solar_wind_differential_flux import (
@@ -44,6 +47,70 @@
logger = logging.getLogger(__name__)
+_VELOCITY_TARGET_FRAMES = (
+ ("gse", SpiceFrame.IMAP_GSE),
+ ("gsm", SpiceFrame.IMAP_GSM),
+ ("hae", SpiceFrame.ECLIPJ2000),
+)
+
+
+def _convert_velocity_products_at_epoch(
+ result: dict[str, np.ndarray],
+ prefix: str,
+ index: int,
+ target_frame: SpiceFrame,
+) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
+ """Convert velocity, Sun-relative velocity, and covariance for one epoch."""
+ epoch_slice = result["epoch"][index : index + 1]
+ velocity = convert_velocity_rtn_to_frame(
+ epoch_slice,
+ result[f"{prefix}_rtn"][index : index + 1],
+ target_frame,
+ )[0]
+ velocity_sun = convert_velocity_rtn_to_frame(
+ epoch_slice,
+ result[f"{prefix}_rtn_sun"][index : index + 1],
+ target_frame,
+ )[0]
+ covariance = convert_velocity_covariance_rtn_to_frame(
+ epoch_slice,
+ result[f"{prefix}_rtn_covariance"][index : index + 1],
+ target_frame,
+ )[0]
+ return velocity, velocity_sun, covariance
+
+
+def _add_velocity_products_in_target_frames(
+ result: dict[str, np.ndarray], species: str
+) -> None:
+ """Add velocity vectors and covariance in each requested output frame."""
+ prefix = f"{species}_sw_velocity"
+
+ for frame_name, target_frame in _VELOCITY_TARGET_FRAMES:
+ velocity = np.full(result[f"{prefix}_rtn"].shape, np.nan)
+ velocity_sun = np.full(result[f"{prefix}_rtn_sun"].shape, np.nan)
+ covariance = np.full(result[f"{prefix}_rtn_covariance"].shape, np.nan)
+
+ for index, epoch in enumerate(result["epoch"]):
+ try:
+ converted_products = _convert_velocity_products_at_epoch(
+ result, prefix, index, target_frame
+ )
+ except Exception:
+ logger.warning(
+ f"Error converting {species} velocity products at epoch "
+ f"{epoch} to {target_frame}; using fill values.",
+ exc_info=True,
+ )
+ result["quality_flags"][index] |= int(SwapiL3Flags.FIT_ERROR)
+ continue
+
+ velocity[index], velocity_sun[index], covariance[index] = converted_products
+
+ result[f"{prefix}_{frame_name}"] = velocity
+ result[f"{prefix}_{frame_name}_sun"] = velocity_sun
+ result[f"{prefix}_{frame_name}_covariance"] = covariance
+
class SwapiProcessor(Processor):
def __init__(
@@ -86,9 +153,11 @@ def process_l3a_proton(self, data, dependencies) -> SwapiL3ProtonSolarWindData:
dependencies.swapi_response, dependencies.efficiency_calibration_table
)
+ result = runner.run(chunks, ProtonChunkFitter())
+ _add_velocity_products_in_target_frames(result, "proton")
+
return SwapiL3ProtonSolarWindData(
- replace(self.input_metadata, descriptor="proton-sw"),
- **runner.run(chunks, ProtonChunkFitter()),
+ replace(self.input_metadata, descriptor="proton-sw"), **result
)
def process_l3a_alpha(self, data, dependencies) -> SwapiL3AlphaSolarWindData:
@@ -105,7 +174,9 @@ def process_l3a_alpha(self, data, dependencies) -> SwapiL3AlphaSolarWindData:
fitter = AlphaChunkFitter(dependencies.mag_data)
result = runner.run(chunks, fitter)
-
+
+ _add_velocity_products_in_target_frames(result, "alpha")
+
if dependencies.mag_is_preliminary:
result["quality_flags"] = result["quality_flags"] | int(SwapiL3Flags.PRELIMINARY_MAG)
diff --git a/tests/integration/test_swapi_processor_integration.py b/tests/integration/test_swapi_processor_integration.py
index a88c0caa..7c0a9e04 100644
--- a/tests/integration/test_swapi_processor_integration.py
+++ b/tests/integration/test_swapi_processor_integration.py
@@ -34,6 +34,46 @@
SWAPI_INTEGRATION_DATA_DIR = Path(__file__).parent / "test_data" / "swapi"
+def assert_velocity_frames_are_physically_consistent(test_case, cdf, prefix, index):
+ """Check the transformed vectors against the geometry expected on January 1."""
+ for sun_suffix in ("", "_sun"):
+ rtn = cdf[f"{prefix}_rtn{sun_suffix}"][index]
+ gse = cdf[f"{prefix}_gse{sun_suffix}"][index]
+ gsm = cdf[f"{prefix}_gsm{sun_suffix}"][index]
+ hae = cdf[f"{prefix}_hae{sun_suffix}"][index]
+
+ # A rotation changes coordinates, not the speed.
+ for transformed in (gse, gsm, hae):
+ numpy.testing.assert_allclose(
+ numpy.linalg.norm(transformed),
+ numpy.linalg.norm(rtn),
+ rtol=1e-6,
+ )
+
+ # GSE +X points from Earth toward the Sun, opposite the predominantly
+ # anti-sunward solar-wind flow. GSM is a rotation about that same X axis.
+ test_case.assertLess(gse[0], 0)
+ test_case.assertGreater(abs(gse[0]), numpy.linalg.norm(gse[1:]))
+ numpy.testing.assert_allclose(gsm[0], gse[0], rtol=1e-6)
+
+ # Near January 1, Earth's anti-sunward radial direction in HAE is
+ # predominantly +Y (Earth's heliocentric ecliptic longitude is ~100 deg).
+ test_case.assertGreater(hae[1], 0)
+ test_case.assertGreater(abs(hae[1]), abs(hae[0]))
+ test_case.assertGreater(abs(hae[1]), abs(hae[2]))
+
+ rtn_covariance = cdf[f"{prefix}_rtn_covariance"][index]
+ for frame in ("gse", "gsm", "hae"):
+ covariance = cdf[f"{prefix}_{frame}_covariance"][index]
+ numpy.testing.assert_allclose(covariance, covariance.T, rtol=1e-6, atol=1e-6)
+ numpy.testing.assert_allclose(
+ numpy.linalg.eigvalsh(covariance),
+ numpy.linalg.eigvalsh(rtn_covariance),
+ rtol=1e-5,
+ atol=1e-5,
+ )
+
+
class SwapiProcessorIntegration(unittest.TestCase):
@skipUnless(os.environ.get("IMAP_API_KEY"), "requires production API key")
def test_proton_sw_with_production_data(self):
@@ -55,6 +95,12 @@ def test_proton_sw_with_production_data(self):
'proton_sw_density_uncert': 0.049651436507701874,
'proton_sw_velocity_rtn_sun': [474.1429748535156, 31.2506103515625, 15.421923637390137],
'proton_sw_velocity_rtn': [474.2013854980469, 1.6974985599517822, 18.847949981689453],
+ 'proton_sw_velocity_gse': [-474.21169142, -0.48161806, 18.65798744],
+ 'proton_sw_velocity_gse_sun': [-474.09292141, -30.23247255, 18.65198256],
+ 'proton_sw_velocity_gsm': [-474.21169142, -5.07181642, 17.96187990],
+ 'proton_sw_velocity_gsm_sun': [-474.09292141, -33.90076411, 10.61306001],
+ 'proton_sw_velocity_hae': [-84.52581716, 466.61913283, 18.62932749],
+ 'proton_sw_velocity_hae_sun': [-113.78456481, 461.22903633, 18.62379766],
'proton_sw_velocity_rtn_covariance': [[0.11774054169654846, -0.029444590210914612, 0.13579009473323822],
[-0.029444590210914612, 0.8430156111717224, -0.22263257205486298],
[0.13579009473323822, -0.22263257205486298, 1.3417274951934814]],
@@ -111,6 +157,9 @@ def test_proton_sw_with_production_data(self):
)
except TypeError:
self.assertEqual(expected_values[key], actual_value, msg=key)
+ assert_velocity_frames_are_physically_consistent(
+ self, cdf, "proton_sw_velocity", 0
+ )
@@ -139,6 +188,12 @@ def test_alpha_sw_with_production_data(self):
'alpha_sw_temperature_uncert': 1141809.75,
'alpha_sw_velocity_rtn': [473.010009765625, -9.928609848022461, 16.30108070373535],
'alpha_sw_velocity_rtn_sun': [472.9515686035156, 19.624502182006836, 12.875075340270996],
+ 'alpha_sw_velocity_gse': [-473.04103169, 10.77708246, 14.79218361],
+ 'alpha_sw_velocity_gse_sun': [-472.92223443, -18.97376979, 14.78618060],
+ 'alpha_sw_velocity_gsm': [-473.04103169, 6.79540805, 16.99342908],
+ 'alpha_sw_velocity_gsm_sun': [-472.92223443, -22.03470465, 9.64919000],
+ 'alpha_sw_velocity_hae': [-73.24367583, 467.46141800, 14.76341745],
+ 'alpha_sw_velocity_hae_sun': [-102.50234989, 462.07093380, 14.75788951],
'alpha_sw_velocity_rtn_covariance': [
[0.13386771082878113, 0.23742027580738068, 0.1489003300666809],
[0.23742027580738068, 13.923757553100586, 7.167418003082275],
@@ -196,6 +251,9 @@ def test_alpha_sw_with_production_data(self):
)
except TypeError:
self.assertEqual(expected_values[key], actual_value, msg=key)
+ assert_velocity_frames_are_physically_consistent(
+ self, cdf, "alpha_sw_velocity", sample_index
+ )
@skipUnless(os.environ.get("IMAP_API_KEY"), "requires production API key")
diff --git a/tests/swapi/l3a/test_chunk_fits.py b/tests/swapi/l3a/test_chunk_fits.py
index 6f06e265..d88c45f0 100644
--- a/tests/swapi/l3a/test_chunk_fits.py
+++ b/tests/swapi/l3a/test_chunk_fits.py
@@ -974,11 +974,12 @@ def test_bad_fit_when_alpha_bump_does_not_match_maxwellian(self):
self.assertEqual(int(result["quality_flags"]), int(SwapiL3Flags.BAD_FIT))
_assert_all_nan(self, result, _ALPHA_SCALAR_KEYS, _ALPHA_ARRAY_KEYS)
+ @patch("imap_l3_processing.swapi.swapi_processor._add_velocity_products_in_target_frames")
@patch("imap_l3_processing.swapi.swapi_processor.SwapiL3AlphaSolarWindData")
@patch("imap_l3_processing.swapi.swapi_processor.ParallelChunkRunner")
@patch("imap_l3_processing.swapi.swapi_processor.chunk_l2_data")
def test_preliminary_mag_bit_set_iff_mag_is_preliminary(
- self, mock_chunk_l2_data, mock_runner_class, mock_alpha_data_class
+ self, mock_chunk_l2_data, mock_runner_class, mock_alpha_data_class, _
):
"""The `PRELIMINARY_MAG` bit is OR'd onto every per-chunk quality flag when `mag_is_preliminary=True` (preserving any underlying `BAD_FIT`), and the per-chunk flags pass through untouched when `mag_is_preliminary=False`. Mocked at the processor seam because the bit-OR is processor-level wiring, not chunk-fitter behavior."""
runner_flag = int(SwapiL3Flags.BAD_FIT)
diff --git a/tests/swapi/l3a/test_models.py b/tests/swapi/l3a/test_models.py
index 688414e2..00ef7f94 100644
--- a/tests/swapi/l3a/test_models.py
+++ b/tests/swapi/l3a/test_models.py
@@ -39,6 +39,20 @@
from tests.swapi.cdf_model_test_case import CdfModelTestCase
from tests.test_helpers import with_tempdir
+_FRAME_ROTATIONS = {
+ "gse": np.array([[0, -1, 0], [1, 0, 0], [0, 0, 1]]),
+ "gsm": np.array([[0, 0, 1], [-1, 0, 0], [0, -1, 0]]),
+ "hae": np.array([[-1, 0, 0], [0, 0, 1], [0, 1, 0]]),
+}
+
+
+def _rotate_velocity_frame(velocity_sun, velocity_sc, covariance, rotation):
+ return (
+ velocity_sun @ rotation.T,
+ velocity_sc @ rotation.T,
+ rotation @ covariance @ rotation.T,
+ )
+
class TestModels(CdfModelTestCase):
@@ -58,6 +72,17 @@ def test_getting_proton_sw_data_product_variables(self):
bulk_v_rtn_sun = np.arange(n * 3, dtype=float).reshape(n, 3)
bulk_v_rtn_sc = np.arange(100, 100 + n * 3, dtype=float).reshape(n, 3)
bulk_v_rtn_cov = np.arange(200, 200 + n * 9, dtype=float).reshape(n, 3, 3)
+ velocity_frames = {
+ "gse": _rotate_velocity_frame(
+ bulk_v_rtn_sun, bulk_v_rtn_sc, bulk_v_rtn_cov, _FRAME_ROTATIONS["gse"]
+ ),
+ "gsm": _rotate_velocity_frame(
+ bulk_v_rtn_sun, bulk_v_rtn_sc, bulk_v_rtn_cov, _FRAME_ROTATIONS["gsm"]
+ ),
+ "hae": _rotate_velocity_frame(
+ bulk_v_rtn_sun, bulk_v_rtn_sc, bulk_v_rtn_cov, _FRAME_ROTATIONS["hae"]
+ ),
+ }
quality_flags = np.full(n, SwapiL3Flags.NONE)
quality_flags[3:5] |= SwapiL3Flags.FIT_ERROR
@@ -69,6 +94,9 @@ def test_getting_proton_sw_data_product_variables(self):
temperature, temperature_uncert,
density, density_uncert,
bulk_v_rtn_sun, bulk_v_rtn_sc, bulk_v_rtn_cov,
+ *velocity_frames["gse"],
+ *velocity_frames["gsm"],
+ *velocity_frames["hae"],
quality_flags,
)
@@ -98,10 +126,30 @@ def test_getting_proton_sw_data_product_variables(self):
expected_velocity_uncert = np.sqrt(np.diagonal(bulk_v_rtn_cov, axis1=1, axis2=2))
self.assert_variable_attributes(next(var_iter), expected_velocity_uncert,
PROTON_SOLAR_WIND_VELOCITY_RTN_UNCERTAINTY_CDF_VAR_NAME)
+ for frame, (velocity_sun, velocity_sc, covariance) in velocity_frames.items():
+ self.assert_variable_attributes(next(var_iter), velocity_sun,
+ f"proton_sw_velocity_{frame}_sun")
+ self.assert_variable_attributes(next(var_iter), velocity_sc,
+ f"proton_sw_velocity_{frame}")
+ self.assert_variable_attributes(next(var_iter), covariance,
+ f"proton_sw_velocity_{frame}_covariance")
+ self.assert_variable_attributes(
+ next(var_iter),
+ np.sqrt(np.diagonal(covariance, axis1=1, axis2=2)),
+ f"proton_sw_velocity_{frame}_uncert",
+ )
self.assert_variable_attributes(next(var_iter), quality_flags, SWAPI_QUALITY_FLAGS_CDF_VAR_NAME)
self.assert_variable_attributes(next(var_iter), ["R", "T", "N"], VELOCITY_RTN_LABEL_CDF_VAR_NAME)
+ for frame in velocity_frames:
+ self.assert_variable_attributes(next(var_iter), ["X", "Y", "Z"],
+ f"velocity_{frame}_label")
self.assert_variable_attributes(next(var_iter), ["Vp SC R", "Vp SC T", "Vp SC N"], PROTON_SOLAR_WIND_VELOCITY_RTN_LABEL_CDF_VAR_NAME)
self.assert_variable_attributes(next(var_iter), ["Vp Sun R", "Vp Sun T", "Vp Sun N"], PROTON_SOLAR_WIND_VELOCITY_RTN_SUN_LABEL_CDF_VAR_NAME)
+ for frame in velocity_frames:
+ self.assert_variable_attributes(next(var_iter), ["Vp SC X", "Vp SC Y", "Vp SC Z"],
+ f"proton_sw_velocity_{frame}_label")
+ self.assert_variable_attributes(next(var_iter), ["Vp Sun X", "Vp Sun Y", "Vp Sun Z"],
+ f"proton_sw_velocity_{frame}_sun_label")
self.assertIs(sentinel.done, next(var_iter, sentinel.done))
@@ -121,6 +169,17 @@ def test_getting_alpha_sw_data_product_variables(self):
velocity_rtn_sun = np.arange(n * 3, dtype=float).reshape(n, 3)
velocity_rtn_sc = np.arange(100, 100 + n * 3, dtype=float).reshape(n, 3)
velocity_rtn_cov = np.arange(n * 9, dtype=float).reshape(n, 3, 3)
+ velocity_frames = {
+ "gse": _rotate_velocity_frame(
+ velocity_rtn_sun, velocity_rtn_sc, velocity_rtn_cov, _FRAME_ROTATIONS["gse"]
+ ),
+ "gsm": _rotate_velocity_frame(
+ velocity_rtn_sun, velocity_rtn_sc, velocity_rtn_cov, _FRAME_ROTATIONS["gsm"]
+ ),
+ "hae": _rotate_velocity_frame(
+ velocity_rtn_sun, velocity_rtn_sc, velocity_rtn_cov, _FRAME_ROTATIONS["hae"]
+ ),
+ }
quality_flags = np.full_like(epoch_data, SwapiL3Flags.NONE)
quality_flags[:n // 2] = SwapiL3Flags.BAD_FIT
@@ -132,6 +191,9 @@ def test_getting_alpha_sw_data_product_variables(self):
density, density_uncert,
temperature, temperature_uncert,
velocity_rtn_sun, velocity_rtn_sc, velocity_rtn_cov,
+ *velocity_frames["gse"],
+ *velocity_frames["gsm"],
+ *velocity_frames["hae"],
quality_flags,
)
variables = data.to_data_product_variables()
@@ -160,10 +222,30 @@ def test_getting_alpha_sw_data_product_variables(self):
expected_velocity_uncert = np.sqrt(np.diagonal(velocity_rtn_cov, axis1=1, axis2=2))
self.assert_variable_attributes(next(var_iter), expected_velocity_uncert,
ALPHA_SOLAR_WIND_VELOCITY_RTN_UNCERTAINTY_CDF_VAR_NAME)
+ for frame, (velocity_sun, velocity_sc, covariance) in velocity_frames.items():
+ self.assert_variable_attributes(next(var_iter), velocity_sun,
+ f"alpha_sw_velocity_{frame}_sun")
+ self.assert_variable_attributes(next(var_iter), velocity_sc,
+ f"alpha_sw_velocity_{frame}")
+ self.assert_variable_attributes(next(var_iter), covariance,
+ f"alpha_sw_velocity_{frame}_covariance")
+ self.assert_variable_attributes(
+ next(var_iter),
+ np.sqrt(np.diagonal(covariance, axis1=1, axis2=2)),
+ f"alpha_sw_velocity_{frame}_uncert",
+ )
self.assert_variable_attributes(next(var_iter), quality_flags, SWAPI_QUALITY_FLAGS_CDF_VAR_NAME)
self.assert_variable_attributes(next(var_iter), ["R", "T", "N"], VELOCITY_RTN_LABEL_CDF_VAR_NAME)
+ for frame in velocity_frames:
+ self.assert_variable_attributes(next(var_iter), ["X", "Y", "Z"],
+ f"velocity_{frame}_label")
self.assert_variable_attributes(next(var_iter), ['Va SC R', 'Va SC T', 'Va SC N'], ALPHA_VELOCITY_RTN_LABEL_CDF_VAR_NAME)
self.assert_variable_attributes(next(var_iter), ['Va Sun R', 'Va Sun T', 'Va Sun N'], ALPHA_VELOCITY_RTN_SUN_LABEL_CDF_VAR_NAME)
+ for frame in velocity_frames:
+ self.assert_variable_attributes(next(var_iter), ["Va SC X", "Va SC Y", "Va SC Z"],
+ f"alpha_sw_velocity_{frame}_label")
+ self.assert_variable_attributes(next(var_iter), ["Va Sun X", "Va Sun Y", "Va Sun Z"],
+ f"alpha_sw_velocity_{frame}_sun_label")
self.assertIs(sentinel.done, next(var_iter, sentinel.done))
diff --git a/tests/swapi/l3a/test_utils.py b/tests/swapi/l3a/test_utils.py
index 02ea4897..790e4cae 100644
--- a/tests/swapi/l3a/test_utils.py
+++ b/tests/swapi/l3a/test_utils.py
@@ -2,9 +2,11 @@
from datetime import datetime
from pathlib import Path
from unittest import TestCase
+from unittest.mock import patch
import numpy as np
import spacepy.pycdf
+from imap_processing.spice.geometry import SpiceFrame
from spacepy.pycdf import CDF
from uncertainties import UFloat, ufloat
@@ -25,6 +27,8 @@
)
from imap_l3_processing.swapi.l3a.models import SwapiL2Data
from imap_l3_processing.swapi.l3a.utils import (
+ convert_velocity_covariance_rtn_to_frame,
+ convert_velocity_rtn_to_frame,
velocity_components_to_angles_in_instrument_frame,
calculate_sw_speed,
chunk_l2_data,
@@ -299,6 +303,45 @@ def test_get_spacecraft_velocity_rtn_returns_finite_orbital_velocity(self):
self.assertGreater(speed, 10.0)
self.assertLess(speed, 60.0)
+ @patch("imap_l3_processing.swapi.l3a.utils.get_rotation_matrix")
+ @patch("imap_l3_processing.swapi.l3a.utils.ttj2000ns_to_et")
+ def test_convert_velocity_and_covariance_rtn_to_frame(
+ self, mock_time_conversion, mock_get_rotation_matrix
+ ):
+ epochs = np.array([1, 2])
+ ephemeris_times = np.array([3.0, 4.0])
+ rotations = np.array(
+ [
+ np.eye(3),
+ [[0.0, -1.0, 0.0], [1.0, 0.0, 0.0], [0.0, 0.0, 1.0]],
+ ]
+ )
+ velocities = np.array([[1.0, 2.0, 3.0], [4.0, 5.0, 6.0]])
+ covariances = np.array(
+ [
+ np.diag([1.0, 2.0, 3.0]),
+ [[4.0, 1.0, -2.0], [1.0, 5.0, 3.0], [-2.0, 3.0, 6.0]],
+ ]
+ )
+ mock_time_conversion.return_value = ephemeris_times
+ mock_get_rotation_matrix.return_value = rotations
+
+ actual_velocities = convert_velocity_rtn_to_frame(
+ epochs, velocities, SpiceFrame.IMAP_GSE
+ )
+ actual_covariances = convert_velocity_covariance_rtn_to_frame(
+ epochs, covariances, SpiceFrame.IMAP_GSE
+ )
+
+ expected_velocities = (rotations @ velocities[..., np.newaxis])[..., 0]
+ expected_covariances = rotations @ covariances @ rotations.swapaxes(1, 2)
+ np.testing.assert_allclose(actual_velocities, expected_velocities)
+ np.testing.assert_allclose(actual_covariances, expected_covariances)
+ self.assertEqual(2, mock_get_rotation_matrix.call_count)
+ mock_get_rotation_matrix.assert_called_with(
+ ephemeris_times, SpiceFrame.IMAP_RTN, SpiceFrame.IMAP_GSE
+ )
+
class TestVelocityComponentsToAnglesInInstrumentFrame(TestCase):
"""Tests for `velocity_components_to_angles_in_instrument_frame`. The Cartesian input
diff --git a/tests/swapi/test_swapi_processor.py b/tests/swapi/test_swapi_processor.py
index d06a97d5..f05d95c6 100644
--- a/tests/swapi/test_swapi_processor.py
+++ b/tests/swapi/test_swapi_processor.py
@@ -23,11 +23,75 @@
from imap_l3_processing.swapi.l3b.science.calculate_solar_wind_vdf import DeltaMinusPlus
from imap_l3_processing.swapi.quality_flags import SwapiL3Flags
from imap_l3_processing.swapi.species import Species
-from imap_l3_processing.swapi.swapi_processor import SwapiProcessor
+from imap_l3_processing.swapi.swapi_processor import (
+ SwapiProcessor,
+ _add_velocity_products_in_target_frames,
+)
from tests.test_helpers import create_mock_version_map
class TestSwapiProcessor(TestCase):
+ @patch(
+ "imap_l3_processing.swapi.swapi_processor.convert_velocity_covariance_rtn_to_frame"
+ )
+ @patch("imap_l3_processing.swapi.swapi_processor.convert_velocity_rtn_to_frame")
+ def test_target_frame_conversion_fills_and_flags_only_failed_epoch(
+ self, mock_convert_velocity, mock_convert_covariance
+ ):
+ result = {
+ "epoch": np.array([1, 2, 3]),
+ "proton_sw_velocity_rtn": np.ones((3, 3)),
+ "proton_sw_velocity_rtn_sun": np.full((3, 3), 2.0),
+ "proton_sw_velocity_rtn_covariance": np.repeat(
+ np.eye(3)[np.newaxis, ...], 3, axis=0
+ ),
+ "quality_flags": np.array(
+ [SwapiL3Flags.NONE, SwapiL3Flags.BAD_FIT, SwapiL3Flags.NONE]
+ ),
+ }
+
+ def convert_velocity(epoch, value, _target_frame):
+ if epoch[0] == 2:
+ raise RuntimeError("conversion failed")
+ return value * 10
+
+ mock_convert_velocity.side_effect = convert_velocity
+ mock_convert_covariance.side_effect = lambda epoch, value, frame: value * 10
+
+ with self.assertLogs(
+ "imap_l3_processing.swapi.swapi_processor", level="WARNING"
+ ):
+ _add_velocity_products_in_target_frames(result, "proton")
+
+ for frame in ("gse", "gsm", "hae"):
+ np.testing.assert_array_equal(
+ result[f"proton_sw_velocity_{frame}"][[0, 2]], 10
+ )
+ np.testing.assert_array_equal(
+ result[f"proton_sw_velocity_{frame}_sun"][[0, 2]], 20
+ )
+ np.testing.assert_array_equal(
+ result[f"proton_sw_velocity_{frame}_covariance"][[0, 2]],
+ np.repeat((np.eye(3) * 10)[np.newaxis, ...], 2, axis=0),
+ )
+ self.assertTrue(np.all(np.isnan(result[f"proton_sw_velocity_{frame}"][1])))
+ self.assertTrue(
+ np.all(np.isnan(result[f"proton_sw_velocity_{frame}_sun"][1]))
+ )
+ self.assertTrue(
+ np.all(
+ np.isnan(result[f"proton_sw_velocity_{frame}_covariance"][1])
+ )
+ )
+ np.testing.assert_array_equal(
+ result["quality_flags"],
+ [
+ SwapiL3Flags.NONE,
+ SwapiL3Flags.BAD_FIT | SwapiL3Flags.FIT_ERROR,
+ SwapiL3Flags.NONE,
+ ],
+ )
+
@patch('imap_l3_processing.utils.ImapAttributeManager')
@patch('imap_l3_processing.swapi.swapi_processor.SwapiL3PickupIonData')
@patch('imap_l3_processing.utils.write_cdf')
@@ -192,6 +256,8 @@ def test_process_l3a_pui(self, mock_spicepy,
mock_write_cdf.assert_called_once_with(str(expected_cdf_path), pickup_ion_data, mock_manager)
self.assertEqual([expected_cdf_path], product)
+ @patch('imap_l3_processing.swapi.swapi_processor.convert_velocity_covariance_rtn_to_frame')
+ @patch('imap_l3_processing.swapi.swapi_processor.convert_velocity_rtn_to_frame')
@patch('imap_l3_processing.utils.ImapAttributeManager')
@patch('imap_l3_processing.swapi.swapi_processor.SwapiL3ProtonSolarWindData')
@patch('imap_l3_processing.utils.write_cdf')
@@ -205,7 +271,9 @@ def test_process_l3a_proton(self, mock_spicepy,
mock_parallel_chunk_runner_class,
mock_write_cdf,
mock_proton_solar_wind_data_constructor,
- mock_imap_attribute_manager):
+ mock_imap_attribute_manager,
+ mock_convert_velocity,
+ mock_convert_covariance):
instrument = 'swapi'
incoming_data_level = 'l2'
dependency_start_date = datetime.strftime(datetime(2025, 1, 1), "%Y%m%d")
@@ -257,6 +325,8 @@ def test_process_l3a_proton(self, mock_spicepy,
)
mock_runner = mock_parallel_chunk_runner_class.return_value
mock_runner.run.return_value = runner_result
+ mock_convert_velocity.side_effect = lambda epoch, value, frame: value
+ mock_convert_covariance.side_effect = lambda epoch, value, frame: value
input_file_names = [
f'imap_{instrument}_{incoming_data_level}_{SWAPI_L2_DESCRIPTOR}_{dependency_start_date}_{version}.cdf',
@@ -313,6 +383,12 @@ def test_process_l3a_proton(self, mock_spicepy,
self.assertEqual(expected_proton_metadata, actual_positional[0])
for key, expected_val in runner_result.items():
np.testing.assert_array_equal(expected_val, actual_kwargs[key])
+ for frame in ("gse", "gsm", "hae"):
+ self.assertIn(f"proton_sw_velocity_{frame}", actual_kwargs)
+ self.assertIn(f"proton_sw_velocity_{frame}_sun", actual_kwargs)
+ self.assertIn(f"proton_sw_velocity_{frame}_covariance", actual_kwargs)
+ self.assertEqual(6, mock_convert_velocity.call_count)
+ self.assertEqual(3, mock_convert_covariance.call_count)
mock_manager.add_global_attribute.assert_has_calls([call("Data_version", outgoing_version),
call("Generation_date",
@@ -329,6 +405,8 @@ def test_process_l3a_proton(self, mock_spicepy,
mock_write_cdf.assert_called_once_with(str(expected_cdf_path), proton_solar_wind_data, mock_manager)
self.assertEqual([expected_cdf_path], product)
+ @patch('imap_l3_processing.swapi.swapi_processor.convert_velocity_covariance_rtn_to_frame')
+ @patch('imap_l3_processing.swapi.swapi_processor.convert_velocity_rtn_to_frame')
@patch('imap_l3_processing.utils.ImapAttributeManager')
@patch('imap_l3_processing.swapi.swapi_processor.SwapiL3AlphaSolarWindData')
@patch('imap_l3_processing.utils.write_cdf')
@@ -342,7 +420,9 @@ def test_process_l3a_alpha(self, mock_spicepy,
mock_parallel_chunk_runner_class,
mock_write_cdf,
mock_alpha_solar_wind_data_constructor,
- mock_imap_attribute_manager):
+ mock_imap_attribute_manager,
+ mock_convert_velocity,
+ mock_convert_covariance):
instrument = 'swapi'
incoming_data_level = 'l2'
dependency_start_date = datetime.strftime(datetime(2025, 1, 1), "%Y%m%d")
@@ -384,6 +464,8 @@ def test_process_l3a_alpha(self, mock_spicepy,
)
mock_runner = mock_parallel_chunk_runner_class.return_value
mock_runner.run.return_value = runner_result
+ mock_convert_velocity.side_effect = lambda epoch, value, frame: value
+ mock_convert_covariance.side_effect = lambda epoch, value, frame: value
science_input = ScienceInput(
f'imap_{instrument}_{incoming_data_level}_{SWAPI_L2_DESCRIPTOR}_{dependency_start_date}_{version}.cdf')
@@ -440,6 +522,12 @@ def test_process_l3a_alpha(self, mock_spicepy,
self.assertEqual(expected_alpha_metadata, actual_positional[0])
for key, expected_val in runner_result.items():
np.testing.assert_array_equal(expected_val, actual_kwargs[key])
+ for frame in ("gse", "gsm", "hae"):
+ self.assertIn(f"alpha_sw_velocity_{frame}", actual_kwargs)
+ self.assertIn(f"alpha_sw_velocity_{frame}_sun", actual_kwargs)
+ self.assertIn(f"alpha_sw_velocity_{frame}_covariance", actual_kwargs)
+ self.assertEqual(6, mock_convert_velocity.call_count)
+ self.assertEqual(3, mock_convert_covariance.call_count)
mock_manager.add_global_attribute.assert_has_calls([
call("Data_version", outgoing_version),
diff --git a/tests/test_utils.py b/tests/test_utils.py
index dfbed681..eb251606 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -79,6 +79,15 @@ def test_save_data(self, mock_science_file_path_class, mock_write_cdf, mock_toda
alpha_sw_velocity_rtn_sun=np.zeros((3, 3)),
alpha_sw_velocity_rtn=np.zeros((3, 3)),
alpha_sw_velocity_rtn_covariance=np.zeros((3, 3, 3)),
+ alpha_sw_velocity_gse_sun=np.zeros((3, 3)),
+ alpha_sw_velocity_gse=np.zeros((3, 3)),
+ alpha_sw_velocity_gse_covariance=np.zeros((3, 3, 3)),
+ alpha_sw_velocity_gsm_sun=np.zeros((3, 3)),
+ alpha_sw_velocity_gsm=np.zeros((3, 3)),
+ alpha_sw_velocity_gsm_covariance=np.zeros((3, 3, 3)),
+ alpha_sw_velocity_hae_sun=np.zeros((3, 3)),
+ alpha_sw_velocity_hae=np.zeros((3, 3)),
+ alpha_sw_velocity_hae_covariance=np.zeros((3, 3, 3)),
parent_file_names=sentinel.parent_files,
quality_flags=sentinel.quality_flags,
)
@@ -234,6 +243,15 @@ def test_save_data_does_not_add_parent_attribute_if_empty(self, mock_write_cdf,
alpha_sw_velocity_rtn_sun=np.zeros((3, 3)),
alpha_sw_velocity_rtn=np.zeros((3, 3)),
alpha_sw_velocity_rtn_covariance=np.zeros((3, 3, 3)),
+ alpha_sw_velocity_gse_sun=np.zeros((3, 3)),
+ alpha_sw_velocity_gse=np.zeros((3, 3)),
+ alpha_sw_velocity_gse_covariance=np.zeros((3, 3, 3)),
+ alpha_sw_velocity_gsm_sun=np.zeros((3, 3)),
+ alpha_sw_velocity_gsm=np.zeros((3, 3)),
+ alpha_sw_velocity_gsm_covariance=np.zeros((3, 3, 3)),
+ alpha_sw_velocity_hae_sun=np.zeros((3, 3)),
+ alpha_sw_velocity_hae=np.zeros((3, 3)),
+ alpha_sw_velocity_hae_covariance=np.zeros((3, 3, 3)),
quality_flags=quality_flags,
)
save_data(data_product)
@@ -274,6 +292,15 @@ def test_save_data_custom_path(self, mock_write_cdf, mock_today, _):
alpha_sw_velocity_rtn_sun=np.zeros((3, 3)),
alpha_sw_velocity_rtn=np.zeros((3, 3)),
alpha_sw_velocity_rtn_covariance=np.zeros((3, 3, 3)),
+ alpha_sw_velocity_gse_sun=np.zeros((3, 3)),
+ alpha_sw_velocity_gse=np.zeros((3, 3)),
+ alpha_sw_velocity_gse_covariance=np.zeros((3, 3, 3)),
+ alpha_sw_velocity_gsm_sun=np.zeros((3, 3)),
+ alpha_sw_velocity_gsm=np.zeros((3, 3)),
+ alpha_sw_velocity_gsm_covariance=np.zeros((3, 3, 3)),
+ alpha_sw_velocity_hae_sun=np.zeros((3, 3)),
+ alpha_sw_velocity_hae=np.zeros((3, 3)),
+ alpha_sw_velocity_hae_covariance=np.zeros((3, 3, 3)),
quality_flags=quality_flags,
)