diff --git a/etc/adjusted/synthetic.json b/etc/adjusted/synthetic.json index f93e5cd4003abd16b9fa37d1c87f2d8cd4df7c8b..c3dd5594f10c4ed6cc19c9a9256c02e72e81634f 100644 --- a/etc/adjusted/synthetic.json +++ b/etc/adjusted/synthetic.json @@ -136,22 +136,22 @@ "results": { "NoConstraints": [ [ - 0.5364919027495764, - -0.20707814501736455, - 0.3372529089344527, - -1.7929218549826358 + 0.5364919027495736, + -0.20707814501736121, + 0.33725290893445425, + -1.7929218549826373 ], [ - 0.532504593054401, - 0.8470924780256476, - -0.3269654921326787, - -4.004987214867758 + 0.5325045930544003, + 0.847092478025647, + -0.32696549213267934, + -4.004987214867749 ], [ - -0.2588476812717039, - 0.4215661361680678, - 0.6706148784369707, - -2.9215661361680687 + -0.25884768127170443, + 0.4215661361680674, + 0.6706148784369698, + -2.921566136168065 ], [ 0, @@ -162,22 +162,22 @@ ], "ZRotationShear": [ [ - 0.623705221351958, - -0.16841150209489725, + 0.5587910280835219, + -0.1593988978820583, 0, - -1.2028974670750636 + -0.9594702768899068 ], [ - 0.4479515917846801, - 0.8096053056474853, + 0.5108856705906101, + 0.8008676180137191, 0, - -4.577013754155448 + -4.813015546664324 ], [ 0, 0, - 0.6098875103018411, - -1.809849332552786 + 0.7036074465845426, + -2.273788534881388 ], [ 0, @@ -188,22 +188,22 @@ ], "ZRotationHscale": [ [ - 0.6561504712144426, - -0.31217620673287216, + 0.6395521012137755, + -0.3193786953272828, 0, - -0.7215676859558748 + -0.6145604575448345 ], [ - 0.31217620673287216, - 0.6561504712144426, + 0.3193786953272828, + 0.6395521012137755, 0, - -3.563702076556801 + -3.550295624100921 ], [ 0, 0, - 0.6098875103018406, - -1.809849332552785 + 0.7036074465845424, + -2.2737885348813887 ], [ 0, @@ -214,14 +214,14 @@ ], "ZRotationHscaleZbaseline": [ [ - 0.016821600812797096, - -0.01778941712811468, + 0.053926953353156136, + 0.03582167951143748, 0, 0 ], [ - 0.01778941712811468, - 0.016821600812797096, + -0.03582167951143748, + 0.053926953353156136, 0, 0 ], @@ -229,7 +229,7 @@ 0, 0, 1, - -2.9674214586052265 + -3.2332029498017487 ], [ 0, @@ -240,22 +240,22 @@ ], "RotationTranslation3D": [ [ - 0.8054252079416996, - -0.31075264909884437, - 0.5047009267775519, - -2.662452958809875 + 0.8100811050998874, + -0.3030939677547838, + 0.5018990435045756, + -2.8734904692082317 ], [ - 0.5054022574334629, - 0.804909769980755, - -0.3109482599576447, - -3.803929616959254 + 0.4979757275740692, + 0.8075341522117618, + -0.3160834822617412, + -3.7722406528522203 ], [ - -0.309610711367079, - 0.5055225546576319, - 0.8053497092190405, - -3.5091860177384517 + -0.3094976218119015, + 0.5059867979723319, + 0.8051015975456041, + -3.511977037527143 ], [ 0, @@ -266,21 +266,21 @@ ], "Rescale3D": [ [ - 0.02758794737157335, + 0.10754195315849033, 0, 0, 0 ], [ 0, - 0.010807638086966475, + 0.012787625579547376, 0, 0 ], [ 0, 0, - 0.03534928189623147, + 0.032798154583522594, 0 ], [ @@ -295,19 +295,19 @@ 1, 0, 0, - -2.9812470914161855 + -3.0518410718922895 ], [ 0, 1, 0, - -4.02728108273549 + -3.8667699341149695 ], [ 0, 0, 1, - -2.9674214586052265 + -3.2332029498017487 ], [ 0, @@ -324,14 +324,14 @@ 0 ], [ - -1.3484311868544543, + -0.6692050417082805, 1, 0, 0 ], [ - 0.5519469765286653, - -0.10894882663577743, + 0.35315324212931615, + -0.06394207042397665, 1, 0 ], @@ -344,22 +344,22 @@ ], "RotationTranslationXY": [ [ - 0.9030081198758902, - -0.4296234810135611, + 0.8946494196067308, + -0.44676886193795917, 0, - -0.9742971123340419 + -0.9794537295011263 ], [ - 0.4296234810135612, - 0.9030081198758901, + 0.4467688619379593, + 0.894649419606731, 0, - -4.897795293523813 + -4.958977628364134 ], [ 0, 0, 1, - -2.9674214586052274 + -3.233202949801749 ], [ 0, @@ -370,22 +370,22 @@ ], "QRFactorization": [ [ - 0.8122230186734241, - -0.22848881373914198, + 0.7380347209075413, + -0.2626732024800775, 0, - -1.51463869998581 + -1.1628964087154696 ], [ - 0.5833470390231107, - 1.0670858952888813, + 0.6747627366229761, + 1.1147956698369132, 0, - -6.006314806000902 + -6.5703958608516055 ], [ 0, 0, 1, - -2.9674214586052274 + -3.233202949801749 ], [ 0, diff --git a/geomagio/adjusted/Transform.py b/geomagio/adjusted/Transform.py index ad79e5d24a575aa9e41e51f63a1330993207dfc2..0e2dcd58f5274d19b3d4824aa4e04a43154a235f 100644 --- a/geomagio/adjusted/Transform.py +++ b/geomagio/adjusted/Transform.py @@ -98,11 +98,8 @@ class LeastSq(Transform): if weights is None: return values weights = np.sqrt(weights) - return ( - values[0] * weights, - values[1] * weights, - values[2] * weights, - ) + weights = np.vstack((weights, weights, weights)).T.ravel() + return values * weights class SVD(Transform): @@ -146,8 +143,6 @@ class NoConstraints(LeastSq): weights: List[float], ) -> np.array: """Calculates affine with no constraints using least squares.""" - ordinates = self.get_weighted_values(ordinates, weights) - absolutes = self.get_weighted_values(absolutes, weights) # LHS, or dependent variables # # [A[0,0], A[1,0], A[2,0], A[0,1], A[1,1], A[2,1], ...] @@ -176,6 +171,9 @@ class NoConstraints(LeastSq): ord_stacked[10, 2::3] = ordinates[2] ord_stacked[11, 2::3] = 1.0 + ord_stacked = self.get_weighted_values(ord_stacked, weights) + abs_stacked = self.get_weighted_values(abs_stacked, weights) + # regression matrix M that minimizes L2 norm M_r, res, rank, sigma = spl.lstsq(ord_stacked.T, abs_stacked.T) @@ -200,8 +198,6 @@ class ZRotationShear(LeastSq): weights: List[float], ) -> np.array: """Calculates affine using least squares, constrained to rotate about the Z axis.""" - ordinates = self.get_weighted_values(ordinates, weights) - absolutes = self.get_weighted_values(absolutes, weights) # LHS, or dependent variables # abs_stacked = self.get_stacked_absolutes(absolutes) @@ -221,6 +217,9 @@ class ZRotationShear(LeastSq): ord_stacked[6, 2::3] = ordinates[2] ord_stacked[7, 2::3] = 1.0 + ord_stacked = self.get_weighted_values(ord_stacked, weights) + abs_stacked = self.get_weighted_values(abs_stacked, weights) + # regression matrix M that minimizes L2 norm M_r, res, rank, sigma = spl.lstsq(ord_stacked.T, abs_stacked.T) @@ -246,8 +245,6 @@ class ZRotationHscale(LeastSq): absolutes: Tuple[List[float], List[float], List[float]], weights: List[float], ) -> np.array: - ordinates = self.get_weighted_values(ordinates, weights) - absolutes = self.get_weighted_values(absolutes, weights) # LHS, or dependent variables # abs_stacked = self.get_stacked_absolutes(absolutes) @@ -267,6 +264,9 @@ class ZRotationHscale(LeastSq): ord_stacked[4, 2::3] = ordinates[2] ord_stacked[5, 2::3] = 1.0 + ord_stacked = self.get_weighted_values(ord_stacked, weights) + abs_stacked = self.get_weighted_values(abs_stacked, weights) + # regression matrix M that minimizes L2 norm M_r, res, rank, sigma = spl.lstsq(ord_stacked.T, abs_stacked.T) @@ -344,15 +344,14 @@ class RotationTranslation3D(SVD): # generate weighted "covariance" matrix H = np.dot( self.get_stacked_values( - values=ordinates, - weighted_values=weighted_ordinates, - ndims=3, + values=ordinates, weighted_values=weighted_ordinates, ndims=3, + ), + np.dot( + np.diag(weights), + self.get_stacked_values( + values=absolutes, weighted_values=weighted_absolutes, ndims=3, + ).T, ), - self.get_stacked_values( - values=absolutes, - weighted_values=weighted_absolutes, - ndims=3, - ).T, ) # Singular value decomposition, then rotation matrix from L&R eigenvectors # (the determinant guarantees a rotation, and not a reflection) @@ -388,8 +387,6 @@ class Rescale3D(LeastSq): absolutes: Tuple[List[float], List[float], List[float]], weights: List[float], ) -> np.array: - absolutes = self.get_weighted_values(values=absolutes, weights=weights) - ordinates = self.get_weighted_values(values=ordinates, weights=weights) abs_stacked = self.get_stacked_absolutes(absolutes=absolutes) # RHS, or independent variables # (reduces degrees of freedom by 13: @@ -404,6 +401,9 @@ class Rescale3D(LeastSq): ord_stacked[1, 1::3] = ordinates[1] ord_stacked[2, 2::3] = ordinates[2] + abs_stacked = self.get_weighted_values(values=abs_stacked, weights=weights) + ord_stacked = self.get_weighted_values(values=ord_stacked, weights=weights) + # regression matrix M that minimizes L2 norm M_r, res, rank, sigma = spl.lstsq(ord_stacked.T, abs_stacked.T) @@ -483,8 +483,6 @@ class ShearYZ(LeastSq): absolutes: Tuple[List[float], List[float], List[float]], weights: List[float], ) -> np.array: - ordinates = self.get_weighted_values(values=ordinates, weights=weights) - # return generate_affine_7(ord_hez, abs_xyz, weights) # RHS, or independent variables # (reduces degrees of freedom by 13: # - 2 for making x independent of y,z; @@ -498,9 +496,10 @@ class ShearYZ(LeastSq): ord_stacked[2, 0::3] = ordinates[0] ord_stacked[2, 1::3] = ordinates[1] ord_stacked[2, 2::3] = 1.0 - - # regression matrix M that minimizes L2 norm abs_stacked = self.get_stacked_absolutes(absolutes=absolutes) + ord_stacked = self.get_weighted_values(values=ord_stacked, weights=weights) + abs_stacked = self.get_weighted_values(values=abs_stacked, weights=weights) + # regression matrix M that minimizes L2 norm M_r, res, rank, sigma = spl.lstsq(ord_stacked.T, abs_stacked.T) if rank < 3: @@ -534,16 +533,12 @@ class RotationTranslationXY(SVD): # generate weighted "covariance" matrix H = np.dot( self.get_stacked_values( - values=ordinates, - weighted_values=weighted_ordinates, - ndims=2, + values=ordinates, weighted_values=weighted_ordinates, ndims=2, ), np.dot( np.diag(weights), self.get_stacked_values( - values=absolutes, - weighted_values=weighted_absolutes, - ndims=2, + values=absolutes, weighted_values=weighted_absolutes, ndims=2, ).T, ), ) @@ -588,12 +583,7 @@ class QRFactorization(SVD): if weights is None: return values weights = np.sqrt(weights) - return np.array( - [ - values[0] * weights, - values[1] * weights, - ] - ) + return np.array([values[0] * weights, values[1] * weights,]) def calculate( self, @@ -611,25 +601,19 @@ class QRFactorization(SVD): # return generate_affine_9(ord_hez, abs_xyz, weights) # LHS, or dependent variables abs_stacked = self.get_stacked_values( - values=absolutes, - weighted_values=weighted_absolutes, - ndims=2, + values=absolutes, weighted_values=weighted_absolutes, ndims=2, ) # RHS, or independent variables ord_stacked = self.get_stacked_values( - values=ordinates, - weighted_values=weighted_ordinates, - ndims=2, + values=ordinates, weighted_values=weighted_ordinates, ndims=2, ) abs_stacked = self.get_weighted_values_lstsq( - values=abs_stacked, - weights=weights, + values=abs_stacked, weights=weights, ) ord_stacked = self.get_weighted_values_lstsq( - values=ord_stacked, - weights=weights, + values=ord_stacked, weights=weights, ) # regression matrix M that minimizes L2 norm diff --git a/test/adjusted_test/adjusted_test.py b/test/adjusted_test/adjusted_test.py index 503806fb468556fa7e3721f813a7dec756f487fa..0e76e972549fdaa3102b99b90c0d6d01bce1bb86 100644 --- a/test/adjusted_test/adjusted_test.py +++ b/test/adjusted_test/adjusted_test.py @@ -54,7 +54,8 @@ def get_sythetic_variables(): variables = data["variables"] ordinates = np.array([variables["h_ord"], variables["e_ord"], variables["z_ord"]]) absolutes = np.array([variables["x_abs"], variables["y_abs"], variables["z_abs"]]) - return ordinates, absolutes + weights = np.arange(0, len(ordinates[0])) + return ordinates, absolutes, weights def get_expected_synthetic_result(key): @@ -64,12 +65,10 @@ def get_expected_synthetic_result(key): def test_NoConstraints_synthetic(): - ordinates, absolutes = get_sythetic_variables() + ordinates, absolutes, weights = get_sythetic_variables() assert_array_almost_equal( NoConstraints().calculate( - ordinates=ordinates, - absolutes=absolutes, - weights=None, + ordinates=ordinates, absolutes=absolutes, weights=weights, ), get_expected_synthetic_result("NoConstraints"), decimal=3, @@ -77,12 +76,10 @@ def test_NoConstraints_synthetic(): def test_ZRotationShear_synthetic(): - ordinates, absolutes = get_sythetic_variables() + ordinates, absolutes, weights = get_sythetic_variables() assert_array_almost_equal( ZRotationShear().calculate( - ordinates=ordinates, - absolutes=absolutes, - weights=None, + ordinates=ordinates, absolutes=absolutes, weights=weights, ), get_expected_synthetic_result("ZRotationShear"), decimal=3, @@ -90,12 +87,10 @@ def test_ZRotationShear_synthetic(): def test_ZRotationHscale_synthetic(): - ordinates, absolutes = get_sythetic_variables() + ordinates, absolutes, weights = get_sythetic_variables() assert_array_almost_equal( ZRotationHscale().calculate( - ordinates=ordinates, - absolutes=absolutes, - weights=None, + ordinates=ordinates, absolutes=absolutes, weights=weights, ), get_expected_synthetic_result("ZRotationHscale"), decimal=3, @@ -103,12 +98,10 @@ def test_ZRotationHscale_synthetic(): def test_ZRotationHscaleZbaseline_synthetic(): - ordinates, absolutes = get_sythetic_variables() + ordinates, absolutes, weights = get_sythetic_variables() assert_array_almost_equal( ZRotationHscaleZbaseline().calculate( - ordinates=ordinates, - absolutes=absolutes, - weights=None, + ordinates=ordinates, absolutes=absolutes, weights=weights, ), get_expected_synthetic_result("ZRotationHscaleZbaseline"), decimal=3, @@ -116,12 +109,10 @@ def test_ZRotationHscaleZbaseline_synthetic(): def test_RotationTranslation3D_synthetic(): - ordinates, absolutes = get_sythetic_variables() + ordinates, absolutes, weights = get_sythetic_variables() assert_array_almost_equal( RotationTranslation3D().calculate( - ordinates=ordinates, - absolutes=absolutes, - weights=None, + ordinates=ordinates, absolutes=absolutes, weights=weights, ), get_expected_synthetic_result("RotationTranslation3D"), decimal=3, @@ -129,12 +120,10 @@ def test_RotationTranslation3D_synthetic(): def test_Rescale3D_synthetic(): - ordinates, absolutes = get_sythetic_variables() + ordinates, absolutes, weights = get_sythetic_variables() assert_array_almost_equal( Rescale3D().calculate( - ordinates=ordinates, - absolutes=absolutes, - weights=None, + ordinates=ordinates, absolutes=absolutes, weights=weights, ), get_expected_synthetic_result("Rescale3D"), decimal=3, @@ -142,12 +131,10 @@ def test_Rescale3D_synthetic(): def test_TranslateOrigins_synthetic(): - ordinates, absolutes = get_sythetic_variables() + ordinates, absolutes, weights = get_sythetic_variables() assert_array_almost_equal( TranslateOrigins().calculate( - ordinates=ordinates, - absolutes=absolutes, - weights=None, + ordinates=ordinates, absolutes=absolutes, weights=weights, ), get_expected_synthetic_result("TranslateOrigins"), decimal=3, @@ -155,25 +142,19 @@ def test_TranslateOrigins_synthetic(): def test_ShearYZ_synthetic(): - ordinates, absolutes = get_sythetic_variables() + ordinates, absolutes, weights = get_sythetic_variables() assert_array_almost_equal( - ShearYZ().calculate( - ordinates=ordinates, - absolutes=absolutes, - weights=None, - ), + ShearYZ().calculate(ordinates=ordinates, absolutes=absolutes, weights=weights,), get_expected_synthetic_result("ShearYZ"), decimal=3, ) def test_RotationTranslationXY_synthetic(): - ordinates, absolutes = get_sythetic_variables() + ordinates, absolutes, weights = get_sythetic_variables() assert_array_almost_equal( RotationTranslationXY().calculate( - ordinates=ordinates, - absolutes=absolutes, - weights=None, + ordinates=ordinates, absolutes=absolutes, weights=weights, ), get_expected_synthetic_result("RotationTranslationXY"), decimal=3, @@ -181,12 +162,10 @@ def test_RotationTranslationXY_synthetic(): def test_QRFactorization_synthetic(): - ordinates, absolutes = get_sythetic_variables() + ordinates, absolutes, weights = get_sythetic_variables() assert_array_almost_equal( QRFactorization().calculate( - ordinates=ordinates, - absolutes=absolutes, - weights=None, + ordinates=ordinates, absolutes=absolutes, weights=weights, ), get_expected_synthetic_result("QRFactorization"), decimal=3, @@ -259,9 +238,7 @@ def test_BOU201911202001_short_acausal(): endtime=endtime, update_interval=update_interval, acausal=True, - ).calculate( - readings=readings, - ) + ).calculate(readings=readings,) matrices = format_result([adjusted_matrix.matrix for adjusted_matrix in result]) expected_matrices = get_excpected_matrices("BOU", "short_acausal") @@ -293,9 +270,7 @@ def test_BOU201911202001_infinite_weekly(): RotationTranslationXY(memory=np.inf), TranslateOrigins(memory=np.inf), ], - ).calculate( - readings=readings, - ) + ).calculate(readings=readings,) matrices = format_result([adjusted_matrix.matrix for adjusted_matrix in result]) expected_matrices = get_excpected_matrices("BOU", "inf_weekly") @@ -321,9 +296,7 @@ def test_BOU201911202001_infinite_one_interval(): TranslateOrigins(memory=np.inf), ], update_interval=None, - ).calculate( - readings=readings, - ) + ).calculate(readings=readings,) matrices = format_result([adjusted_matrix.matrix for adjusted_matrix in result]) expected_matrices = get_excpected_matrices("BOU", "inf_one_interval") @@ -356,9 +329,7 @@ def test_CMO2015_causal(): starttime=starttime, endtime=endtime, update_interval=update_interval, - ).calculate( - readings=readings, - ) + ).calculate(readings=readings,) matrices = format_result([adjusted_matrix.matrix for adjusted_matrix in result]) expected_matrices = get_excpected_matrices("CMO", "short_causal") @@ -392,9 +363,7 @@ def test_CMO2015_acausal(): endtime=endtime, update_interval=update_interval, acausal=True, - ).calculate( - readings=readings, - ) + ).calculate(readings=readings,) matrices = format_result([adjusted_matrix.matrix for adjusted_matrix in result]) expected_matrices = get_excpected_matrices("CMO", "short_acausal") @@ -432,9 +401,7 @@ def test_CMO2015_infinite_weekly(): ], update_interval=update_interval, acausal=True, - ).calculate( - readings=readings, - ) + ).calculate(readings=readings,) matrices = format_result([adjusted_matrix.matrix for adjusted_matrix in result]) expected_matrices = get_excpected_matrices("CMO", "inf_weekly") @@ -468,9 +435,7 @@ def test_CMO2015_infinite_one_interval(): ], acausal=True, update_interval=None, - ).calculate( - readings=readings, - ) + ).calculate(readings=readings,) matrices = format_result([adjusted_matrix.matrix for adjusted_matrix in result]) expected_matrices = get_excpected_matrices("CMO", "inf_one_interval")