diff --git a/.gitignore b/.gitignore index 04e8e76d1..b3ea282dd 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /build* +.idea *.pyc *.DS_Store /examples/Data/dubrovnik-3-7-pre-rewritten.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index de9b4152f..3c93264f3 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -66,7 +66,7 @@ option(GTSAM_WITH_EIGEN_MKL_OPENMP "Eigen, when using Intel MKL, will also option(GTSAM_THROW_CHEIRALITY_EXCEPTION "Throw exception when a triangulated point is behind a camera" ON) option(GTSAM_BUILD_PYTHON "Enable/Disable building & installation of Python module" OFF) option(GTSAM_ALLOW_DEPRECATED_SINCE_V4 "Allow use of methods/functions deprecated in GTSAM 4" ON) -option(GTSAM_USE_VECTOR3_POINTS "Simply typdef Point3 to eigen::Vector3d" OFF) +option(GTSAM_TYPEDEF_POINTS_TO_VECTORS "Typdef Point2 and Point3 to Eigen::Vector equivalents" OFF) option(GTSAM_SUPPORT_NESTED_DISSECTION "Support Metis-based nested dissection" ON) option(GTSAM_TANGENT_PREINTEGRATION "Use new ImuFactor with integration on tangent space" ON) @@ -91,8 +91,8 @@ if(GTSAM_BUILD_PYTHON AND GTSAM_ALLOW_DEPRECATED_SINCE_V4) message(FATAL_ERROR "GTSAM_BUILD_PYTHON and GTSAM_ALLOW_DEPRECATED_SINCE_V4 are both enabled. The python module cannot be compiled with deprecated functions turned on. Turn one of the two options off.") endif() -if(GTSAM_INSTALL_MATLAB_TOOLBOX AND GTSAM_USE_VECTOR3_POINTS) - message(FATAL_ERROR "GTSAM_INSTALL_MATLAB_TOOLBOX and GTSAM_USE_VECTOR3_POINTS are both enabled. For now, the MATLAB toolbox cannot deal with this yet. Please turn one of the two options off.") +if(GTSAM_INSTALL_MATLAB_TOOLBOX AND GTSAM_TYPEDEF_POINTS_TO_VECTORS) + message(FATAL_ERROR "GTSAM_INSTALL_MATLAB_TOOLBOX and GTSAM_TYPEDEF_POINTS_TO_VECTORS are both enabled. For now, the MATLAB toolbox cannot deal with this yet. Please turn one of the two options off.") endif() # Flags for choosing default packaging tools @@ -491,7 +491,7 @@ print_config_flag(${GTSAM_ENABLE_CONSISTENCY_CHECKS} "Runtime consistency chec print_config_flag(${GTSAM_ROT3_EXPMAP} "Rot3 retract is full ExpMap ") print_config_flag(${GTSAM_POSE3_EXPMAP} "Pose3 retract is full ExpMap ") print_config_flag(${GTSAM_ALLOW_DEPRECATED_SINCE_V4} "Deprecated in GTSAM 4 allowed ") -print_config_flag(${GTSAM_USE_VECTOR3_POINTS} "Point3 is typedef to Vector3 ") +print_config_flag(${GTSAM_TYPEDEF_POINTS_TO_VECTORS} "Point3 is typedef to Vector3 ") print_config_flag(${GTSAM_SUPPORT_NESTED_DISSECTION} "Metis-based Nested Dissection ") print_config_flag(${GTSAM_TANGENT_PREINTEGRATION} "Use tangent-space preintegration") diff --git a/CppUnitLite/Test.h b/CppUnitLite/Test.h index ff1f1b692..23d1e2573 100644 --- a/CppUnitLite/Test.h +++ b/CppUnitLite/Test.h @@ -68,6 +68,12 @@ protected: testGroup##testName##Instance; \ void testGroup##testName##Test::run (TestResult& result_) +/** + * Declare friend in a class to test its private methods + */ +#define FRIEND_TEST(testGroup, testName) \ + friend class testGroup##testName##Test; + /** * For debugging only: use TEST_UNSAFE to allow debuggers to have access to exceptions, as this * will not wrap execution with a try/catch block diff --git a/CppUnitLite/TestResult.h b/CppUnitLite/TestResult.h index a30275647..b64b40d75 100644 --- a/CppUnitLite/TestResult.h +++ b/CppUnitLite/TestResult.h @@ -18,8 +18,6 @@ // /////////////////////////////////////////////////////////////////////////////// - - #ifndef TESTRESULT_H #define TESTRESULT_H diff --git a/cmake/GtsamBuildTypes.cmake b/cmake/GtsamBuildTypes.cmake index 4647b51a1..e9521c257 100644 --- a/cmake/GtsamBuildTypes.cmake +++ b/cmake/GtsamBuildTypes.cmake @@ -61,18 +61,18 @@ mark_as_advanced(GTSAM_CMAKE_C_FLAGS_TIMING GTSAM_CMAKE_CXX_FLAGS_TIMING GTSAM_C # Apply the gtsam specific build flags as normal variables. This makes it so that they only # apply to the gtsam part of the build if gtsam is built as a subproject -set(CMAKE_C_FLAGS ${GTSAM_CMAKE_C_FLAGS}) -set(CMAKE_CXX_FLAGS ${GTSAM_CMAKE_CXX_FLAGS}) -set(CMAKE_C_FLAGS_DEBUG ${GTSAM_CMAKE_C_FLAGS_DEBUG}) -set(CMAKE_CXX_FLAGS_DEBUG ${GTSAM_CMAKE_CXX_FLAGS_DEBUG}) -set(CMAKE_C_FLAGS_RELWITHDEBINFO ${GTSAM_CMAKE_C_FLAGS_RELWITHDEBINFO}) -set(CMAKE_CXX_FLAGS_RELWITHDEBINFO ${GTSAM_CMAKE_CXX_FLAGS_RELWITHDEBINFO}) -set(CMAKE_C_FLAGS_RELEASE ${GTSAM_CMAKE_C_FLAGS_RELEASE}) -set(CMAKE_CXX_FLAGS_RELEASE ${GTSAM_CMAKE_CXX_FLAGS_RELEASE}) -set(CMAKE_C_FLAGS_PROFILING ${GTSAM_CMAKE_C_FLAGS_PROFILING}) -set(CMAKE_CXX_FLAGS_PROFILING ${GTSAM_CMAKE_CXX_FLAGS_PROFILING}) -set(CMAKE_C_FLAGS_TIMING ${GTSAM_CMAKE_C_FLAGS_TIMING}) -set(CMAKE_CXX_FLAGS_TIMING ${GTSAM_CMAKE_CXX_FLAGS_TIMING}) +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GTSAM_CMAKE_C_FLAGS}") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GTSAM_CMAKE_CXX_FLAGS}") +set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${GTSAM_CMAKE_C_FLAGS_DEBUG}") +set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${GTSAM_CMAKE_CXX_FLAGS_DEBUG}") +set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} ${GTSAM_CMAKE_C_FLAGS_RELWITHDEBINFO}") +set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${GTSAM_CMAKE_CXX_FLAGS_RELWITHDEBINFO}") +set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${GTSAM_CMAKE_C_FLAGS_RELEASE}") +set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${GTSAM_CMAKE_CXX_FLAGS_RELEASE}") +set(CMAKE_C_FLAGS_PROFILING "${CMAKE_C_FLAGS_PROFILING} ${GTSAM_CMAKE_C_FLAGS_PROFILING}") +set(CMAKE_CXX_FLAGS_PROFILING "${CMAKE_CXX_FLAGS_PROFILING} ${GTSAM_CMAKE_CXX_FLAGS_PROFILING}") +set(CMAKE_C_FLAGS_TIMING "${CMAKE_C_FLAGS_TIMING} ${GTSAM_CMAKE_C_FLAGS_TIMING}") +set(CMAKE_CXX_FLAGS_TIMING "${CMAKE_CXX_FLAGS_TIMING} ${GTSAM_CMAKE_CXX_FLAGS_TIMING}") set(CMAKE_SHARED_LINKER_FLAGS_TIMING ${GTSAM_CMAKE_SHARED_LINKER_FLAGS_TIMING}) set(CMAKE_MODULE_LINKER_FLAGS_TIMING ${GTSAM_CMAKE_MODULE_LINKER_FLAGS_TIMING}) diff --git a/examples/CameraResectioning.cpp b/examples/CameraResectioning.cpp index 43814731f..676dd42ec 100644 --- a/examples/CameraResectioning.cpp +++ b/examples/CameraResectioning.cpp @@ -48,8 +48,7 @@ public: virtual Vector evaluateError(const Pose3& pose, boost::optional H = boost::none) const { SimpleCamera camera(pose, *K_); - Point2 reprojectionError(camera.project(P_, H, boost::none, boost::none) - p_); - return reprojectionError.vector(); + return camera.project(P_, H, boost::none, boost::none) - p_; } }; diff --git a/examples/Data/QPExample.QPS b/examples/Data/QPExample.QPS new file mode 100644 index 000000000..d67c59e0a --- /dev/null +++ b/examples/Data/QPExample.QPS @@ -0,0 +1,21 @@ +NAME QP example +ROWS + N obj + G r1 + L r2 +COLUMNS + c1 r1 2.0 r2 -1.0 + c1 obj 1.5 + c2 r1 1.0 r2 2.0 + c2 obj -2.0 +RHS + rhs1 obj -4.0 + rhs1 r1 2.0 r2 6.0 +RANGES +BOUNDS + UP BOUNDS c1 20.0 +QUADOBJ + c1 c1 8.0 + c1 c2 2.0 + c2 c2 10.0 +ENDATA \ No newline at end of file diff --git a/examples/Data/imuAndGPSdata.csv b/examples/Data/imuAndGPSdata.csv new file mode 100644 index 000000000..9631e3374 --- /dev/null +++ b/examples/Data/imuAndGPSdata.csv @@ -0,0 +1,20101 @@ +i,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.000100,0.0,0.0,0.0,0.0,0.0 +1,0.000000,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.000200,0.0,0.0,0.0,0.0,0.0 +0,0.000300,0.0,0.0,0.0,0.0,0.0 +0,0.000400,0.0,0.0,0.0,0.0,0.0 +0,0.000500,0.0,0.0,0.0,0.0,0.0 +0,0.000600,0.0,0.0,0.0,0.0,0.0 +0,0.000700,0.0,0.0,0.0,0.0,0.0 +0,0.000800,0.0,0.0,0.0,0.0,0.0 +0,0.000900,0.0,0.0,0.0,0.0,0.0 +0,0.001000,0.0,0.0,0.0,0.0,0.0 +0,0.001100,0.0,0.0,0.0,0.0,0.0 +0,0.001200,0.0,0.0,0.0,0.0,0.0 +0,0.001300,0.0,0.0,0.0,0.0,0.0 +0,0.001400,0.0,0.0,0.0,0.0,0.0 +0,0.001500,0.0,0.0,0.0,0.0,0.0 +0,0.001600,0.0,0.0,0.0,0.0,0.0 +0,0.001700,0.0,0.0,0.0,0.0,0.0 +0,0.001800,0.0,0.0,0.0,0.0,0.0 +0,0.001900,0.0,0.0,0.0,0.0,0.0 +0,0.002000,0.0,0.0,0.0,0.0,0.0 +0,0.002100,0.0,0.0,0.0,0.0,0.0 +0,0.002200,0.0,0.0,0.0,0.0,0.0 +0,0.002300,0.0,0.0,0.0,0.0,0.0 +0,0.002400,0.0,0.0,0.0,0.0,0.0 +0,0.002500,0.0,0.0,0.0,0.0,0.0 +0,0.002600,0.0,0.0,0.0,0.0,0.0 +0,0.002700,0.0,0.0,0.0,0.0,0.0 +0,0.002800,0.0,0.0,0.0,0.0,0.0 +0,0.002900,0.0,0.0,0.0,0.0,0.0 +0,0.003000,0.0,0.0,0.0,0.0,0.0 +0,0.003100,0.0,0.0,0.0,0.0,0.0 +0,0.003200,0.0,0.0,0.0,0.0,0.0 +0,0.003300,0.0,0.0,0.0,0.0,0.0 +0,0.003400,0.0,0.0,0.0,0.0,0.0 +0,0.003500,0.0,0.0,0.0,0.0,0.0 +0,0.003600,0.0,0.0,0.0,0.0,0.0 +0,0.003700,0.0,0.0,0.0,0.0,0.0 +0,0.003800,0.0,0.0,0.0,0.0,0.0 +0,0.003900,0.0,0.0,0.0,0.0,0.0 +0,0.004000,0.0,0.0,0.0,0.0,0.0 +0,0.004100,0.0,0.0,0.0,0.0,0.0 +0,0.004200,0.0,0.0,0.0,0.0,0.0 +0,0.004300,0.0,0.0,0.0,0.0,0.0 +0,0.004400,0.0,0.0,0.0,0.0,0.0 +0,0.004500,0.0,0.0,0.0,0.0,0.0 +0,0.004600,0.0,0.0,0.0,0.0,0.0 +0,0.004700,0.0,0.0,0.0,0.0,0.0 +0,0.004800,0.0,0.0,0.0,0.0,0.0 +0,0.004900,0.0,0.0,0.0,0.0,0.0 +0,0.005000,0.0,0.0,0.0,0.0,0.0 +0,0.005100,0.0,0.0,0.0,0.0,0.0 +0,0.005200,0.0,0.0,0.0,0.0,0.0 +0,0.005300,0.0,0.0,0.0,0.0,0.0 +0,0.005400,0.0,0.0,0.0,0.0,0.0 +0,0.005500,0.0,0.0,0.0,0.0,0.0 +0,0.005600,0.0,0.0,0.0,0.0,0.0 +0,0.005700,0.0,0.0,0.0,0.0,0.0 +0,0.005800,0.0,0.0,0.0,0.0,0.0 +0,0.005900,0.0,0.0,0.0,0.0,0.0 +0,0.006000,0.0,0.0,0.0,0.0,0.0 +0,0.006100,0.0,0.0,0.0,0.0,0.0 +0,0.006200,0.0,0.0,0.0,0.0,0.0 +0,0.006300,0.0,0.0,0.0,0.0,0.0 +0,0.006400,0.0,0.0,0.0,0.0,0.0 +0,0.006500,0.0,0.0,0.0,0.0,0.0 +0,0.006600,0.0,0.0,0.0,0.0,0.0 +0,0.006700,0.0,0.0,0.0,0.0,0.0 +0,0.006800,0.0,0.0,0.0,0.0,0.0 +0,0.006900,0.0,0.0,0.0,0.0,0.0 +0,0.007000,0.0,0.0,0.0,0.0,0.0 +0,0.007100,0.0,0.0,0.0,0.0,0.0 +0,0.007200,0.0,0.0,0.0,0.0,0.0 +0,0.007300,0.0,0.0,0.0,0.0,0.0 +0,0.007400,0.0,0.0,0.0,0.0,0.0 +0,0.007500,0.0,0.0,0.0,0.0,0.0 +0,0.007600,0.0,0.0,0.0,0.0,0.0 +0,0.007700,0.0,0.0,0.0,0.0,0.0 +0,0.007800,0.0,0.0,0.0,0.0,0.0 +0,0.007900,0.0,0.0,0.0,0.0,0.0 +0,0.008000,0.0,0.0,0.0,0.0,0.0 +0,0.008100,0.0,0.0,0.0,0.0,0.0 +0,0.008200,0.0,0.0,0.0,0.0,0.0 +0,0.008300,0.0,0.0,0.0,0.0,0.0 +0,0.008400,0.0,0.0,0.0,0.0,0.0 +0,0.008500,0.0,0.0,0.0,0.0,0.0 +0,0.008600,0.0,0.0,0.0,0.0,0.0 +0,0.008700,0.0,0.0,0.0,0.0,0.0 +0,0.008800,0.0,0.0,0.0,0.0,0.0 +0,0.008900,0.0,0.0,0.0,0.0,0.0 +0,0.009000,0.0,0.0,0.0,0.0,0.0 +0,0.009100,0.0,0.0,0.0,0.0,0.0 +0,0.009200,0.0,0.0,0.0,0.0,0.0 +0,0.009300,0.0,0.0,0.0,0.0,0.0 +0,0.009400,0.0,0.0,0.0,0.0,0.0 +0,0.009500,0.0,0.0,0.0,0.0,0.0 +0,0.009600,0.0,0.0,0.0,0.0,0.0 +0,0.009700,0.0,0.0,0.0,0.0,0.0 +0,0.009800,0.0,0.0,0.0,0.0,0.0 +0,0.009900,0.0,0.0,0.0,0.0,0.0 +0,0.010000,0.0,0.0,0.0,0.0,0.0 +0,0.010100,0.0,0.0,0.0,0.0,0.0 +0,0.010200,0.0,0.0,0.0,0.0,0.0 +0,0.010300,0.0,0.0,0.0,0.0,0.0 +0,0.010400,0.0,0.0,0.0,0.0,0.0 +0,0.010500,0.0,0.0,0.0,0.0,0.0 +0,0.010600,0.0,0.0,0.0,0.0,0.0 +0,0.010700,0.0,0.0,0.0,0.0,0.0 +0,0.010800,0.0,0.0,0.0,0.0,0.0 +0,0.010900,0.0,0.0,0.0,0.0,0.0 +0,0.011000,0.0,0.0,0.0,0.0,0.0 +0,0.011100,0.0,0.0,0.0,0.0,0.0 +0,0.011200,0.0,0.0,0.0,0.0,0.0 +0,0.011300,0.0,0.0,0.0,0.0,0.0 +0,0.011400,0.0,0.0,0.0,0.0,0.0 +0,0.011500,0.0,0.0,0.0,0.0,0.0 +0,0.011600,0.0,0.0,0.0,0.0,0.0 +0,0.011700,0.0,0.0,0.0,0.0,0.0 +0,0.011800,0.0,0.0,0.0,0.0,0.0 +0,0.011900,0.0,0.0,0.0,0.0,0.0 +0,0.012000,0.0,0.0,0.0,0.0,0.0 +0,0.012100,0.0,0.0,0.0,0.0,0.0 +0,0.012200,0.0,0.0,0.0,0.0,0.0 +0,0.012300,0.0,0.0,0.0,0.0,0.0 +0,0.012400,0.0,0.0,0.0,0.0,0.0 +0,0.012500,0.0,0.0,0.0,0.0,0.0 +0,0.012600,0.0,0.0,0.0,0.0,0.0 +0,0.012700,0.0,0.0,0.0,0.0,0.0 +0,0.012800,0.0,0.0,0.0,0.0,0.0 +0,0.012900,0.0,0.0,0.0,0.0,0.0 +0,0.013000,0.0,0.0,0.0,0.0,0.0 +0,0.013100,0.0,0.0,0.0,0.0,0.0 +0,0.013200,0.0,0.0,0.0,0.0,0.0 +0,0.013300,0.0,0.0,0.0,0.0,0.0 +0,0.013400,0.0,0.0,0.0,0.0,0.0 +0,0.013500,0.0,0.0,0.0,0.0,0.0 +0,0.013600,0.0,0.0,0.0,0.0,0.0 +0,0.013700,0.0,0.0,0.0,0.0,0.0 +0,0.013800,0.0,0.0,0.0,0.0,0.0 +0,0.013900,0.0,0.0,0.0,0.0,0.0 +0,0.014000,0.0,0.0,0.0,0.0,0.0 +0,0.014100,0.0,0.0,0.0,0.0,0.0 +0,0.014200,0.0,0.0,0.0,0.0,0.0 +0,0.014300,0.0,0.0,0.0,0.0,0.0 +0,0.014400,0.0,0.0,0.0,0.0,0.0 +0,0.014500,0.0,0.0,0.0,0.0,0.0 +0,0.014600,0.0,0.0,0.0,0.0,0.0 +0,0.014700,0.0,0.0,0.0,0.0,0.0 +0,0.014800,0.0,0.0,0.0,0.0,0.0 +0,0.014900,0.0,0.0,0.0,0.0,0.0 +0,0.015000,0.0,0.0,0.0,0.0,0.0 +0,0.015100,0.0,0.0,0.0,0.0,0.0 +0,0.015200,0.0,0.0,0.0,0.0,0.0 +0,0.015300,0.0,0.0,0.0,0.0,0.0 +0,0.015400,0.0,0.0,0.0,0.0,0.0 +0,0.015500,0.0,0.0,0.0,0.0,0.0 +0,0.015600,0.0,0.0,0.0,0.0,0.0 +0,0.015700,0.0,0.0,0.0,0.0,0.0 +0,0.015800,0.0,0.0,0.0,0.0,0.0 +0,0.015900,0.0,0.0,0.0,0.0,0.0 +0,0.016000,0.0,0.0,0.0,0.0,0.0 +0,0.016100,0.0,0.0,0.0,0.0,0.0 +0,0.016200,0.0,0.0,0.0,0.0,0.0 +0,0.016300,0.0,0.0,0.0,0.0,0.0 +0,0.016400,0.0,0.0,0.0,0.0,0.0 +0,0.016500,0.0,0.0,0.0,0.0,0.0 +0,0.016600,0.0,0.0,0.0,0.0,0.0 +0,0.016700,0.0,0.0,0.0,0.0,0.0 +0,0.016800,0.0,0.0,0.0,0.0,0.0 +0,0.016900,0.0,0.0,0.0,0.0,0.0 +0,0.017000,0.0,0.0,0.0,0.0,0.0 +0,0.017100,0.0,0.0,0.0,0.0,0.0 +0,0.017200,0.0,0.0,0.0,0.0,0.0 +0,0.017300,0.0,0.0,0.0,0.0,0.0 +0,0.017400,0.0,0.0,0.0,0.0,0.0 +0,0.017500,0.0,0.0,0.0,0.0,0.0 +0,0.017600,0.0,0.0,0.0,0.0,0.0 +0,0.017700,0.0,0.0,0.0,0.0,0.0 +0,0.017800,0.0,0.0,0.0,0.0,0.0 +0,0.017900,0.0,0.0,0.0,0.0,0.0 +0,0.018000,0.0,0.0,0.0,0.0,0.0 +0,0.018100,0.0,0.0,0.0,0.0,0.0 +0,0.018200,0.0,0.0,0.0,0.0,0.0 +0,0.018300,0.0,0.0,0.0,0.0,0.0 +0,0.018400,0.0,0.0,0.0,0.0,0.0 +0,0.018500,0.0,0.0,0.0,0.0,0.0 +0,0.018600,0.0,0.0,0.0,0.0,0.0 +0,0.018700,0.0,0.0,0.0,0.0,0.0 +0,0.018800,0.0,0.0,0.0,0.0,0.0 +0,0.018900,0.0,0.0,0.0,0.0,0.0 +0,0.019000,0.0,0.0,0.0,0.0,0.0 +0,0.019100,0.0,0.0,0.0,0.0,0.0 +0,0.019200,0.0,0.0,0.0,0.0,0.0 +0,0.019300,0.0,0.0,0.0,0.0,0.0 +0,0.019400,0.0,0.0,0.0,0.0,0.0 +0,0.019500,0.0,0.0,0.0,0.0,0.0 +0,0.019600,0.0,0.0,0.0,0.0,0.0 +0,0.019700,0.0,0.0,0.0,0.0,0.0 +0,0.019800,0.0,0.0,0.0,0.0,0.0 +0,0.019900,0.0,0.0,0.0,0.0,0.0 +0,0.020000,0.0,0.0,0.0,0.0,0.0 +0,0.020100,0.0,0.0,0.0,0.0,0.0 +1,0.003409,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.020200,0.0,0.0,0.0,0.0,0.0 +0,0.020300,0.0,0.0,0.0,0.0,0.0 +0,0.020400,0.0,0.0,0.0,0.0,0.0 +0,0.020500,0.0,0.0,0.0,0.0,0.0 +0,0.020600,0.0,0.0,0.0,0.0,0.0 +0,0.020700,0.0,0.0,0.0,0.0,0.0 +0,0.020800,0.0,0.0,0.0,0.0,0.0 +0,0.020900,0.0,0.0,0.0,0.0,0.0 +0,0.021000,0.0,0.0,0.0,0.0,0.0 +0,0.021100,0.0,0.0,0.0,0.0,0.0 +0,0.021200,0.0,0.0,0.0,0.0,0.0 +0,0.021300,0.0,0.0,0.0,0.0,0.0 +0,0.021400,0.0,0.0,0.0,0.0,0.0 +0,0.021500,0.0,0.0,0.0,0.0,0.0 +0,0.021600,0.0,0.0,0.0,0.0,0.0 +0,0.021700,0.0,0.0,0.0,0.0,0.0 +0,0.021800,0.0,0.0,0.0,0.0,0.0 +0,0.021900,0.0,0.0,0.0,0.0,0.0 +0,0.022000,0.0,0.0,0.0,0.0,0.0 +0,0.022100,0.0,0.0,0.0,0.0,0.0 +0,0.022200,0.0,0.0,0.0,0.0,0.0 +0,0.022300,0.0,0.0,0.0,0.0,0.0 +0,0.022400,0.0,0.0,0.0,0.0,0.0 +0,0.022500,0.0,0.0,0.0,0.0,0.0 +0,0.022600,0.0,0.0,0.0,0.0,0.0 +0,0.022700,0.0,0.0,0.0,0.0,0.0 +0,0.022800,0.0,0.0,0.0,0.0,0.0 +0,0.022900,0.0,0.0,0.0,0.0,0.0 +0,0.023000,0.0,0.0,0.0,0.0,0.0 +0,0.023100,0.0,0.0,0.0,0.0,0.0 +0,0.023200,0.0,0.0,0.0,0.0,0.0 +0,0.023300,0.0,0.0,0.0,0.0,0.0 +0,0.023400,0.0,0.0,0.0,0.0,0.0 +0,0.023500,0.0,0.0,0.0,0.0,0.0 +0,0.023600,0.0,0.0,0.0,0.0,0.0 +0,0.023700,0.0,0.0,0.0,0.0,0.0 +0,0.023800,0.0,0.0,0.0,0.0,0.0 +0,0.023900,0.0,0.0,0.0,0.0,0.0 +0,0.024000,0.0,0.0,0.0,0.0,0.0 +0,0.024100,0.0,0.0,0.0,0.0,0.0 +0,0.024200,0.0,0.0,0.0,0.0,0.0 +0,0.024300,0.0,0.0,0.0,0.0,0.0 +0,0.024400,0.0,0.0,0.0,0.0,0.0 +0,0.024500,0.0,0.0,0.0,0.0,0.0 +0,0.024600,0.0,0.0,0.0,0.0,0.0 +0,0.024700,0.0,0.0,0.0,0.0,0.0 +0,0.024800,0.0,0.0,0.0,0.0,0.0 +0,0.024900,0.0,0.0,0.0,0.0,0.0 +0,0.025000,0.0,0.0,0.0,0.0,0.0 +0,0.025100,0.0,0.0,0.0,0.0,0.0 +0,0.025200,0.0,0.0,0.0,0.0,0.0 +0,0.025300,0.0,0.0,0.0,0.0,0.0 +0,0.025400,0.0,0.0,0.0,0.0,0.0 +0,0.025500,0.0,0.0,0.0,0.0,0.0 +0,0.025600,0.0,0.0,0.0,0.0,0.0 +0,0.025700,0.0,0.0,0.0,0.0,0.0 +0,0.025800,0.0,0.0,0.0,0.0,0.0 +0,0.025900,0.0,0.0,0.0,0.0,0.0 +0,0.026000,0.0,0.0,0.0,0.0,0.0 +0,0.026100,0.0,0.0,0.0,0.0,0.0 +0,0.026200,0.0,0.0,0.0,0.0,0.0 +0,0.026300,0.0,0.0,0.0,0.0,0.0 +0,0.026400,0.0,0.0,0.0,0.0,0.0 +0,0.026500,0.0,0.0,0.0,0.0,0.0 +0,0.026600,0.0,0.0,0.0,0.0,0.0 +0,0.026700,0.0,0.0,0.0,0.0,0.0 +0,0.026800,0.0,0.0,0.0,0.0,0.0 +0,0.026900,0.0,0.0,0.0,0.0,0.0 +0,0.027000,0.0,0.0,0.0,0.0,0.0 +0,0.027100,0.0,0.0,0.0,0.0,0.0 +0,0.027200,0.0,0.0,0.0,0.0,0.0 +0,0.027300,0.0,0.0,0.0,0.0,0.0 +0,0.027400,0.0,0.0,0.0,0.0,0.0 +0,0.027500,0.0,0.0,0.0,0.0,0.0 +0,0.027600,0.0,0.0,0.0,0.0,0.0 +0,0.027700,0.0,0.0,0.0,0.0,0.0 +0,0.027800,0.0,0.0,0.0,0.0,0.0 +0,0.027900,0.0,0.0,0.0,0.0,0.0 +0,0.028000,0.0,0.0,0.0,0.0,0.0 +0,0.028100,0.0,0.0,0.0,0.0,0.0 +0,0.028200,0.0,0.0,0.0,0.0,0.0 +0,0.028300,0.0,0.0,0.0,0.0,0.0 +0,0.028400,0.0,0.0,0.0,0.0,0.0 +0,0.028500,0.0,0.0,0.0,0.0,0.0 +0,0.028600,0.0,0.0,0.0,0.0,0.0 +0,0.028700,0.0,0.0,0.0,0.0,0.0 +0,0.028800,0.0,0.0,0.0,0.0,0.0 +0,0.028900,0.0,0.0,0.0,0.0,0.0 +0,0.029000,0.0,0.0,0.0,0.0,0.0 +0,0.029100,0.0,0.0,0.0,0.0,0.0 +0,0.029200,0.0,0.0,0.0,0.0,0.0 +0,0.029300,0.0,0.0,0.0,0.0,0.0 +0,0.029400,0.0,0.0,0.0,0.0,0.0 +0,0.029500,0.0,0.0,0.0,0.0,0.0 +0,0.029600,0.0,0.0,0.0,0.0,0.0 +0,0.029700,0.0,0.0,0.0,0.0,0.0 +0,0.029800,0.0,0.0,0.0,0.0,0.0 +0,0.029900,0.0,0.0,0.0,0.0,0.0 +0,0.030000,0.0,0.0,0.0,0.0,0.0 +0,0.030100,0.0,0.0,0.0,0.0,0.0 +0,0.030200,0.0,0.0,0.0,0.0,0.0 +0,0.030300,0.0,0.0,0.0,0.0,0.0 +0,0.030400,0.0,0.0,0.0,0.0,0.0 +0,0.030500,0.0,0.0,0.0,0.0,0.0 +0,0.030600,0.0,0.0,0.0,0.0,0.0 +0,0.030700,0.0,0.0,0.0,0.0,0.0 +0,0.030800,0.0,0.0,0.0,0.0,0.0 +0,0.030900,0.0,0.0,0.0,0.0,0.0 +0,0.031000,0.0,0.0,0.0,0.0,0.0 +0,0.031100,0.0,0.0,0.0,0.0,0.0 +0,0.031200,0.0,0.0,0.0,0.0,0.0 +0,0.031300,0.0,0.0,0.0,0.0,0.0 +0,0.031400,0.0,0.0,0.0,0.0,0.0 +0,0.031500,0.0,0.0,0.0,0.0,0.0 +0,0.031600,0.0,0.0,0.0,0.0,0.0 +0,0.031700,0.0,0.0,0.0,0.0,0.0 +0,0.031800,0.0,0.0,0.0,0.0,0.0 +0,0.031900,0.0,0.0,0.0,0.0,0.0 +0,0.032000,0.0,0.0,0.0,0.0,0.0 +0,0.032100,0.0,0.0,0.0,0.0,0.0 +0,0.032200,0.0,0.0,0.0,0.0,0.0 +0,0.032300,0.0,0.0,0.0,0.0,0.0 +0,0.032400,0.0,0.0,0.0,0.0,0.0 +0,0.032500,0.0,0.0,0.0,0.0,0.0 +0,0.032600,0.0,0.0,0.0,0.0,0.0 +0,0.032700,0.0,0.0,0.0,0.0,0.0 +0,0.032800,0.0,0.0,0.0,0.0,0.0 +0,0.032900,0.0,0.0,0.0,0.0,0.0 +0,0.033000,0.0,0.0,0.0,0.0,0.0 +0,0.033100,0.0,0.0,0.0,0.0,0.0 +0,0.033200,0.0,0.0,0.0,0.0,0.0 +0,0.033300,0.0,0.0,0.0,0.0,0.0 +0,0.033400,0.0,0.0,0.0,0.0,0.0 +0,0.033500,0.0,0.0,0.0,0.0,0.0 +0,0.033600,0.0,0.0,0.0,0.0,0.0 +0,0.033700,0.0,0.0,0.0,0.0,0.0 +0,0.033800,0.0,0.0,0.0,0.0,0.0 +0,0.033900,0.0,0.0,0.0,0.0,0.0 +0,0.034000,0.0,0.0,0.0,0.0,0.0 +0,0.034100,0.0,0.0,0.0,0.0,0.0 +0,0.034200,0.0,0.0,0.0,0.0,0.0 +0,0.034300,0.0,0.0,0.0,0.0,0.0 +0,0.034400,0.0,0.0,0.0,0.0,0.0 +0,0.034500,0.0,0.0,0.0,0.0,0.0 +0,0.034600,0.0,0.0,0.0,0.0,0.0 +0,0.034700,0.0,0.0,0.0,0.0,0.0 +0,0.034800,0.0,0.0,0.0,0.0,0.0 +0,0.034900,0.0,0.0,0.0,0.0,0.0 +0,0.035000,0.0,0.0,0.0,0.0,0.0 +0,0.035100,0.0,0.0,0.0,0.0,0.0 +0,0.035200,0.0,0.0,0.0,0.0,0.0 +0,0.035300,0.0,0.0,0.0,0.0,0.0 +0,0.035400,0.0,0.0,0.0,0.0,0.0 +0,0.035500,0.0,0.0,0.0,0.0,0.0 +0,0.035600,0.0,0.0,0.0,0.0,0.0 +0,0.035700,0.0,0.0,0.0,0.0,0.0 +0,0.035800,0.0,0.0,0.0,0.0,0.0 +0,0.035900,0.0,0.0,0.0,0.0,0.0 +0,0.036000,0.0,0.0,0.0,0.0,0.0 +0,0.036100,0.0,0.0,0.0,0.0,0.0 +0,0.036200,0.0,0.0,0.0,0.0,0.0 +0,0.036300,0.0,0.0,0.0,0.0,0.0 +0,0.036400,0.0,0.0,0.0,0.0,0.0 +0,0.036500,0.0,0.0,0.0,0.0,0.0 +0,0.036600,0.0,0.0,0.0,0.0,0.0 +0,0.036700,0.0,0.0,0.0,0.0,0.0 +0,0.036800,0.0,0.0,0.0,0.0,0.0 +0,0.036900,0.0,0.0,0.0,0.0,0.0 +0,0.037000,0.0,0.0,0.0,0.0,0.0 +0,0.037100,0.0,0.0,0.0,0.0,0.0 +0,0.037200,0.0,0.0,0.0,0.0,0.0 +0,0.037300,0.0,0.0,0.0,0.0,0.0 +0,0.037400,0.0,0.0,0.0,0.0,0.0 +0,0.037500,0.0,0.0,0.0,0.0,0.0 +0,0.037600,0.0,0.0,0.0,0.0,0.0 +0,0.037700,0.0,0.0,0.0,0.0,0.0 +0,0.037800,0.0,0.0,0.0,0.0,0.0 +0,0.037900,0.0,0.0,0.0,0.0,0.0 +0,0.038000,0.0,0.0,0.0,0.0,0.0 +0,0.038100,0.0,0.0,0.0,0.0,0.0 +0,0.038200,0.0,0.0,0.0,0.0,0.0 +0,0.038300,0.0,0.0,0.0,0.0,0.0 +0,0.038400,0.0,0.0,0.0,0.0,0.0 +0,0.038500,0.0,0.0,0.0,0.0,0.0 +0,0.038600,0.0,0.0,0.0,0.0,0.0 +0,0.038700,0.0,0.0,0.0,0.0,0.0 +0,0.038800,0.0,0.0,0.0,0.0,0.0 +0,0.038900,0.0,0.0,0.0,0.0,0.0 +0,0.039000,0.0,0.0,0.0,0.0,0.0 +0,0.039100,0.0,0.0,0.0,0.0,0.0 +0,0.039200,0.0,0.0,0.0,0.0,0.0 +0,0.039300,0.0,0.0,0.0,0.0,0.0 +0,0.039400,0.0,0.0,0.0,0.0,0.0 +0,0.039500,0.0,0.0,0.0,0.0,0.0 +0,0.039600,0.0,0.0,0.0,0.0,0.0 +0,0.039700,0.0,0.0,0.0,0.0,0.0 +0,0.039800,0.0,0.0,0.0,0.0,0.0 +0,0.039900,0.0,0.0,0.0,0.0,0.0 +0,0.040000,0.0,0.0,0.0,0.0,0.0 +0,0.040100,0.0,0.0,0.0,0.0,0.0 +1,0.026968,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.040200,0.0,0.0,0.0,0.0,0.0 +0,0.040300,0.0,0.0,0.0,0.0,0.0 +0,0.040400,0.0,0.0,0.0,0.0,0.0 +0,0.040500,0.0,0.0,0.0,0.0,0.0 +0,0.040600,0.0,0.0,0.0,0.0,0.0 +0,0.040700,0.0,0.0,0.0,0.0,0.0 +0,0.040800,0.0,0.0,0.0,0.0,0.0 +0,0.040900,0.0,0.0,0.0,0.0,0.0 +0,0.041000,0.0,0.0,0.0,0.0,0.0 +0,0.041100,0.0,0.0,0.0,0.0,0.0 +0,0.041200,0.0,0.0,0.0,0.0,0.0 +0,0.041300,0.0,0.0,0.0,0.0,0.0 +0,0.041400,0.0,0.0,0.0,0.0,0.0 +0,0.041500,0.0,0.0,0.0,0.0,0.0 +0,0.041600,0.0,0.0,0.0,0.0,0.0 +0,0.041700,0.0,0.0,0.0,0.0,0.0 +0,0.041800,0.0,0.0,0.0,0.0,0.0 +0,0.041900,0.0,0.0,0.0,0.0,0.0 +0,0.042000,0.0,0.0,0.0,0.0,0.0 +0,0.042100,0.0,0.0,0.0,0.0,0.0 +0,0.042200,0.0,0.0,0.0,0.0,0.0 +0,0.042300,0.0,0.0,0.0,0.0,0.0 +0,0.042400,0.0,0.0,0.0,0.0,0.0 +0,0.042500,0.0,0.0,0.0,0.0,0.0 +0,0.042600,0.0,0.0,0.0,0.0,0.0 +0,0.042700,0.0,0.0,0.0,0.0,0.0 +0,0.042800,0.0,0.0,0.0,0.0,0.0 +0,0.042900,0.0,0.0,0.0,0.0,0.0 +0,0.043000,0.0,0.0,0.0,0.0,0.0 +0,0.043100,0.0,0.0,0.0,0.0,0.0 +0,0.043200,0.0,0.0,0.0,0.0,0.0 +0,0.043300,0.0,0.0,0.0,0.0,0.0 +0,0.043400,0.0,0.0,0.0,0.0,0.0 +0,0.043500,0.0,0.0,0.0,0.0,0.0 +0,0.043600,0.0,0.0,0.0,0.0,0.0 +0,0.043700,0.0,0.0,0.0,0.0,0.0 +0,0.043800,0.0,0.0,0.0,0.0,0.0 +0,0.043900,0.0,0.0,0.0,0.0,0.0 +0,0.044000,0.0,0.0,0.0,0.0,0.0 +0,0.044100,0.0,0.0,0.0,0.0,0.0 +0,0.044200,0.0,0.0,0.0,0.0,0.0 +0,0.044300,0.0,0.0,0.0,0.0,0.0 +0,0.044400,0.0,0.0,0.0,0.0,0.0 +0,0.044500,0.0,0.0,0.0,0.0,0.0 +0,0.044600,0.0,0.0,0.0,0.0,0.0 +0,0.044700,0.0,0.0,0.0,0.0,0.0 +0,0.044800,0.0,0.0,0.0,0.0,0.0 +0,0.044900,0.0,0.0,0.0,0.0,0.0 +0,0.045000,0.0,0.0,0.0,0.0,0.0 +0,0.045100,0.0,0.0,0.0,0.0,0.0 +0,0.045200,0.0,0.0,0.0,0.0,0.0 +0,0.045300,0.0,0.0,0.0,0.0,0.0 +0,0.045400,0.0,0.0,0.0,0.0,0.0 +0,0.045500,0.0,0.0,0.0,0.0,0.0 +0,0.045600,0.0,0.0,0.0,0.0,0.0 +0,0.045700,0.0,0.0,0.0,0.0,0.0 +0,0.045800,0.0,0.0,0.0,0.0,0.0 +0,0.045900,0.0,0.0,0.0,0.0,0.0 +0,0.046000,0.0,0.0,0.0,0.0,0.0 +0,0.046100,0.0,0.0,0.0,0.0,0.0 +0,0.046200,0.0,0.0,0.0,0.0,0.0 +0,0.046300,0.0,0.0,0.0,0.0,0.0 +0,0.046400,0.0,0.0,0.0,0.0,0.0 +0,0.046500,0.0,0.0,0.0,0.0,0.0 +0,0.046600,0.0,0.0,0.0,0.0,0.0 +0,0.046700,0.0,0.0,0.0,0.0,0.0 +0,0.046800,0.0,0.0,0.0,0.0,0.0 +0,0.046900,0.0,0.0,0.0,0.0,0.0 +0,0.047000,0.0,0.0,0.0,0.0,0.0 +0,0.047100,0.0,0.0,0.0,0.0,0.0 +0,0.047200,0.0,0.0,0.0,0.0,0.0 +0,0.047300,0.0,0.0,0.0,0.0,0.0 +0,0.047400,0.0,0.0,0.0,0.0,0.0 +0,0.047500,0.0,0.0,0.0,0.0,0.0 +0,0.047600,0.0,0.0,0.0,0.0,0.0 +0,0.047700,0.0,0.0,0.0,0.0,0.0 +0,0.047800,0.0,0.0,0.0,0.0,0.0 +0,0.047900,0.0,0.0,0.0,0.0,0.0 +0,0.048000,0.0,0.0,0.0,0.0,0.0 +0,0.048100,0.0,0.0,0.0,0.0,0.0 +0,0.048200,0.0,0.0,0.0,0.0,0.0 +0,0.048300,0.0,0.0,0.0,0.0,0.0 +0,0.048400,0.0,0.0,0.0,0.0,0.0 +0,0.048500,0.0,0.0,0.0,0.0,0.0 +0,0.048600,0.0,0.0,0.0,0.0,0.0 +0,0.048700,0.0,0.0,0.0,0.0,0.0 +0,0.048800,0.0,0.0,0.0,0.0,0.0 +0,0.048900,0.0,0.0,0.0,0.0,0.0 +0,0.049000,0.0,0.0,0.0,0.0,0.0 +0,0.049100,0.0,0.0,0.0,0.0,0.0 +0,0.049200,0.0,0.0,0.0,0.0,0.0 +0,0.049300,0.0,0.0,0.0,0.0,0.0 +0,0.049400,0.0,0.0,0.0,0.0,0.0 +0,0.049500,0.0,0.0,0.0,0.0,0.0 +0,0.049600,0.0,0.0,0.0,0.0,0.0 +0,0.049700,0.0,0.0,0.0,0.0,0.0 +0,0.049800,0.0,0.0,0.0,0.0,0.0 +0,0.049900,0.0,0.0,0.0,0.0,0.0 +0,0.050000,0.0,0.0,0.0,0.0,0.0 +0,0.050100,0.0,0.0,0.0,0.0,0.0 +0,0.050200,0.0,0.0,0.0,0.0,0.0 +0,0.050300,0.0,0.0,0.0,0.0,0.0 +0,0.050400,0.0,0.0,0.0,0.0,0.0 +0,0.050500,0.0,0.0,0.0,0.0,0.0 +0,0.050600,0.0,0.0,0.0,0.0,0.0 +0,0.050700,0.0,0.0,0.0,0.0,0.0 +0,0.050800,0.0,0.0,0.0,0.0,0.0 +0,0.050900,0.0,0.0,0.0,0.0,0.0 +0,0.051000,0.0,0.0,0.0,0.0,0.0 +0,0.051100,0.0,0.0,0.0,0.0,0.0 +0,0.051200,0.0,0.0,0.0,0.0,0.0 +0,0.051300,0.0,0.0,0.0,0.0,0.0 +0,0.051400,0.0,0.0,0.0,0.0,0.0 +0,0.051500,0.0,0.0,0.0,0.0,0.0 +0,0.051600,0.0,0.0,0.0,0.0,0.0 +0,0.051700,0.0,0.0,0.0,0.0,0.0 +0,0.051800,0.0,0.0,0.0,0.0,0.0 +0,0.051900,0.0,0.0,0.0,0.0,0.0 +0,0.052000,0.0,0.0,0.0,0.0,0.0 +0,0.052100,0.0,0.0,0.0,0.0,0.0 +0,0.052200,0.0,0.0,0.0,0.0,0.0 +0,0.052300,0.0,0.0,0.0,0.0,0.0 +0,0.052400,0.0,0.0,0.0,0.0,0.0 +0,0.052500,0.0,0.0,0.0,0.0,0.0 +0,0.052600,0.0,0.0,0.0,0.0,0.0 +0,0.052700,0.0,0.0,0.0,0.0,0.0 +0,0.052800,0.0,0.0,0.0,0.0,0.0 +0,0.052900,0.0,0.0,0.0,0.0,0.0 +0,0.053000,0.0,0.0,0.0,0.0,0.0 +0,0.053100,0.0,0.0,0.0,0.0,0.0 +0,0.053200,0.0,0.0,0.0,0.0,0.0 +0,0.053300,0.0,0.0,0.0,0.0,0.0 +0,0.053400,0.0,0.0,0.0,0.0,0.0 +0,0.053500,0.0,0.0,0.0,0.0,0.0 +0,0.053600,0.0,0.0,0.0,0.0,0.0 +0,0.053700,0.0,0.0,0.0,0.0,0.0 +0,0.053800,0.0,0.0,0.0,0.0,0.0 +0,0.053900,0.0,0.0,0.0,0.0,0.0 +0,0.054000,0.0,0.0,0.0,0.0,0.0 +0,0.054100,0.0,0.0,0.0,0.0,0.0 +0,0.054200,0.0,0.0,0.0,0.0,0.0 +0,0.054300,0.0,0.0,0.0,0.0,0.0 +0,0.054400,0.0,0.0,0.0,0.0,0.0 +0,0.054500,0.0,0.0,0.0,0.0,0.0 +0,0.054600,0.0,0.0,0.0,0.0,0.0 +0,0.054700,0.0,0.0,0.0,0.0,0.0 +0,0.054800,0.0,0.0,0.0,0.0,0.0 +0,0.054900,0.0,0.0,0.0,0.0,0.0 +0,0.055000,0.0,0.0,0.0,0.0,0.0 +0,0.055100,0.0,0.0,0.0,0.0,0.0 +0,0.055200,0.0,0.0,0.0,0.0,0.0 +0,0.055300,0.0,0.0,0.0,0.0,0.0 +0,0.055400,0.0,0.0,0.0,0.0,0.0 +0,0.055500,0.0,0.0,0.0,0.0,0.0 +0,0.055600,0.0,0.0,0.0,0.0,0.0 +0,0.055700,0.0,0.0,0.0,0.0,0.0 +0,0.055800,0.0,0.0,0.0,0.0,0.0 +0,0.055900,0.0,0.0,0.0,0.0,0.0 +0,0.056000,0.0,0.0,0.0,0.0,0.0 +0,0.056100,0.0,0.0,0.0,0.0,0.0 +0,0.056200,0.0,0.0,0.0,0.0,0.0 +0,0.056300,0.0,0.0,0.0,0.0,0.0 +0,0.056400,0.0,0.0,0.0,0.0,0.0 +0,0.056500,0.0,0.0,0.0,0.0,0.0 +0,0.056600,0.0,0.0,0.0,0.0,0.0 +0,0.056700,0.0,0.0,0.0,0.0,0.0 +0,0.056800,0.0,0.0,0.0,0.0,0.0 +0,0.056900,0.0,0.0,0.0,0.0,0.0 +0,0.057000,0.0,0.0,0.0,0.0,0.0 +0,0.057100,0.0,0.0,0.0,0.0,0.0 +0,0.057200,0.0,0.0,0.0,0.0,0.0 +0,0.057300,0.0,0.0,0.0,0.0,0.0 +0,0.057400,0.0,0.0,0.0,0.0,0.0 +0,0.057500,0.0,0.0,0.0,0.0,0.0 +0,0.057600,0.0,0.0,0.0,0.0,0.0 +0,0.057700,0.0,0.0,0.0,0.0,0.0 +0,0.057800,0.0,0.0,0.0,0.0,0.0 +0,0.057900,0.0,0.0,0.0,0.0,0.0 +0,0.058000,0.0,0.0,0.0,0.0,0.0 +0,0.058100,0.0,0.0,0.0,0.0,0.0 +0,0.058200,0.0,0.0,0.0,0.0,0.0 +0,0.058300,0.0,0.0,0.0,0.0,0.0 +0,0.058400,0.0,0.0,0.0,0.0,0.0 +0,0.058500,0.0,0.0,0.0,0.0,0.0 +0,0.058600,0.0,0.0,0.0,0.0,0.0 +0,0.058700,0.0,0.0,0.0,0.0,0.0 +0,0.058800,0.0,0.0,0.0,0.0,0.0 +0,0.058900,0.0,0.0,0.0,0.0,0.0 +0,0.059000,0.0,0.0,0.0,0.0,0.0 +0,0.059100,0.0,0.0,0.0,0.0,0.0 +0,0.059200,0.0,0.0,0.0,0.0,0.0 +0,0.059300,0.0,0.0,0.0,0.0,0.0 +0,0.059400,0.0,0.0,0.0,0.0,0.0 +0,0.059500,0.0,0.0,0.0,0.0,0.0 +0,0.059600,0.0,0.0,0.0,0.0,0.0 +0,0.059700,0.0,0.0,0.0,0.0,0.0 +0,0.059800,0.0,0.0,0.0,0.0,0.0 +0,0.059900,0.0,0.0,0.0,0.0,0.0 +0,0.060000,0.0,0.0,0.0,0.0,0.0 +0,0.060100,0.0,0.0,0.0,0.0,0.0 +1,0.090677,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.060200,0.0,0.0,0.0,0.0,0.0 +0,0.060300,0.0,0.0,0.0,0.0,0.0 +0,0.060400,0.0,0.0,0.0,0.0,0.0 +0,0.060500,0.0,0.0,0.0,0.0,0.0 +0,0.060600,0.0,0.0,0.0,0.0,0.0 +0,0.060700,0.0,0.0,0.0,0.0,0.0 +0,0.060800,0.0,0.0,0.0,0.0,0.0 +0,0.060900,0.0,0.0,0.0,0.0,0.0 +0,0.061000,0.0,0.0,0.0,0.0,0.0 +0,0.061100,0.0,0.0,0.0,0.0,0.0 +0,0.061200,0.0,0.0,0.0,0.0,0.0 +0,0.061300,0.0,0.0,0.0,0.0,0.0 +0,0.061400,0.0,0.0,0.0,0.0,0.0 +0,0.061500,0.0,0.0,0.0,0.0,0.0 +0,0.061600,0.0,0.0,0.0,0.0,0.0 +0,0.061700,0.0,0.0,0.0,0.0,0.0 +0,0.061800,0.0,0.0,0.0,0.0,0.0 +0,0.061900,0.0,0.0,0.0,0.0,0.0 +0,0.062000,0.0,0.0,0.0,0.0,0.0 +0,0.062100,0.0,0.0,0.0,0.0,0.0 +0,0.062200,0.0,0.0,0.0,0.0,0.0 +0,0.062300,0.0,0.0,0.0,0.0,0.0 +0,0.062400,0.0,0.0,0.0,0.0,0.0 +0,0.062500,0.0,0.0,0.0,0.0,0.0 +0,0.062600,0.0,0.0,0.0,0.0,0.0 +0,0.062700,0.0,0.0,0.0,0.0,0.0 +0,0.062800,0.0,0.0,0.0,0.0,0.0 +0,0.062900,0.0,0.0,0.0,0.0,0.0 +0,0.063000,0.0,0.0,0.0,0.0,0.0 +0,0.063100,0.0,0.0,0.0,0.0,0.0 +0,0.063200,0.0,0.0,0.0,0.0,0.0 +0,0.063300,0.0,0.0,0.0,0.0,0.0 +0,0.063400,0.0,0.0,0.0,0.0,0.0 +0,0.063500,0.0,0.0,0.0,0.0,0.0 +0,0.063600,0.0,0.0,0.0,0.0,0.0 +0,0.063700,0.0,0.0,0.0,0.0,0.0 +0,0.063800,0.0,0.0,0.0,0.0,0.0 +0,0.063900,0.0,0.0,0.0,0.0,0.0 +0,0.064000,0.0,0.0,0.0,0.0,0.0 +0,0.064100,0.0,0.0,0.0,0.0,0.0 +0,0.064200,0.0,0.0,0.0,0.0,0.0 +0,0.064300,0.0,0.0,0.0,0.0,0.0 +0,0.064400,0.0,0.0,0.0,0.0,0.0 +0,0.064500,0.0,0.0,0.0,0.0,0.0 +0,0.064600,0.0,0.0,0.0,0.0,0.0 +0,0.064700,0.0,0.0,0.0,0.0,0.0 +0,0.064800,0.0,0.0,0.0,0.0,0.0 +0,0.064900,0.0,0.0,0.0,0.0,0.0 +0,0.065000,0.0,0.0,0.0,0.0,0.0 +0,0.065100,0.0,0.0,0.0,0.0,0.0 +0,0.065200,0.0,0.0,0.0,0.0,0.0 +0,0.065300,0.0,0.0,0.0,0.0,0.0 +0,0.065400,0.0,0.0,0.0,0.0,0.0 +0,0.065500,0.0,0.0,0.0,0.0,0.0 +0,0.065600,0.0,0.0,0.0,0.0,0.0 +0,0.065700,0.0,0.0,0.0,0.0,0.0 +0,0.065800,0.0,0.0,0.0,0.0,0.0 +0,0.065900,0.0,0.0,0.0,0.0,0.0 +0,0.066000,0.0,0.0,0.0,0.0,0.0 +0,0.066100,0.0,0.0,0.0,0.0,0.0 +0,0.066200,0.0,0.0,0.0,0.0,0.0 +0,0.066300,0.0,0.0,0.0,0.0,0.0 +0,0.066400,0.0,0.0,0.0,0.0,0.0 +0,0.066500,0.0,0.0,0.0,0.0,0.0 +0,0.066600,0.0,0.0,0.0,0.0,0.0 +0,0.066700,0.0,0.0,0.0,0.0,0.0 +0,0.066800,0.0,0.0,0.0,0.0,0.0 +0,0.066900,0.0,0.0,0.0,0.0,0.0 +0,0.067000,0.0,0.0,0.0,0.0,0.0 +0,0.067100,0.0,0.0,0.0,0.0,0.0 +0,0.067200,0.0,0.0,0.0,0.0,0.0 +0,0.067300,0.0,0.0,0.0,0.0,0.0 +0,0.067400,0.0,0.0,0.0,0.0,0.0 +0,0.067500,0.0,0.0,0.0,0.0,0.0 +0,0.067600,0.0,0.0,0.0,0.0,0.0 +0,0.067700,0.0,0.0,0.0,0.0,0.0 +0,0.067800,0.0,0.0,0.0,0.0,0.0 +0,0.067900,0.0,0.0,0.0,0.0,0.0 +0,0.068000,0.0,0.0,0.0,0.0,0.0 +0,0.068100,0.0,0.0,0.0,0.0,0.0 +0,0.068200,0.0,0.0,0.0,0.0,0.0 +0,0.068300,0.0,0.0,0.0,0.0,0.0 +0,0.068400,0.0,0.0,0.0,0.0,0.0 +0,0.068500,0.0,0.0,0.0,0.0,0.0 +0,0.068600,0.0,0.0,0.0,0.0,0.0 +0,0.068700,0.0,0.0,0.0,0.0,0.0 +0,0.068800,0.0,0.0,0.0,0.0,0.0 +0,0.068900,0.0,0.0,0.0,0.0,0.0 +0,0.069000,0.0,0.0,0.0,0.0,0.0 +0,0.069100,0.0,0.0,0.0,0.0,0.0 +0,0.069200,0.0,0.0,0.0,0.0,0.0 +0,0.069300,0.0,0.0,0.0,0.0,0.0 +0,0.069400,0.0,0.0,0.0,0.0,0.0 +0,0.069500,0.0,0.0,0.0,0.0,0.0 +0,0.069600,0.0,0.0,0.0,0.0,0.0 +0,0.069700,0.0,0.0,0.0,0.0,0.0 +0,0.069800,0.0,0.0,0.0,0.0,0.0 +0,0.069900,0.0,0.0,0.0,0.0,0.0 +0,0.070000,0.0,0.0,0.0,0.0,0.0 +0,0.070100,0.0,0.0,0.0,0.0,0.0 +0,0.070200,0.0,0.0,0.0,0.0,0.0 +0,0.070300,0.0,0.0,0.0,0.0,0.0 +0,0.070400,0.0,0.0,0.0,0.0,0.0 +0,0.070500,0.0,0.0,0.0,0.0,0.0 +0,0.070600,0.0,0.0,0.0,0.0,0.0 +0,0.070700,0.0,0.0,0.0,0.0,0.0 +0,0.070800,0.0,0.0,0.0,0.0,0.0 +0,0.070900,0.0,0.0,0.0,0.0,0.0 +0,0.071000,0.0,0.0,0.0,0.0,0.0 +0,0.071100,0.0,0.0,0.0,0.0,0.0 +0,0.071200,0.0,0.0,0.0,0.0,0.0 +0,0.071300,0.0,0.0,0.0,0.0,0.0 +0,0.071400,0.0,0.0,0.0,0.0,0.0 +0,0.071500,0.0,0.0,0.0,0.0,0.0 +0,0.071600,0.0,0.0,0.0,0.0,0.0 +0,0.071700,0.0,0.0,0.0,0.0,0.0 +0,0.071800,0.0,0.0,0.0,0.0,0.0 +0,0.071900,0.0,0.0,0.0,0.0,0.0 +0,0.072000,0.0,0.0,0.0,0.0,0.0 +0,0.072100,0.0,0.0,0.0,0.0,0.0 +0,0.072200,0.0,0.0,0.0,0.0,0.0 +0,0.072300,0.0,0.0,0.0,0.0,0.0 +0,0.072400,0.0,0.0,0.0,0.0,0.0 +0,0.072500,0.0,0.0,0.0,0.0,0.0 +0,0.072600,0.0,0.0,0.0,0.0,0.0 +0,0.072700,0.0,0.0,0.0,0.0,0.0 +0,0.072800,0.0,0.0,0.0,0.0,0.0 +0,0.072900,0.0,0.0,0.0,0.0,0.0 +0,0.073000,0.0,0.0,0.0,0.0,0.0 +0,0.073100,0.0,0.0,0.0,0.0,0.0 +0,0.073200,0.0,0.0,0.0,0.0,0.0 +0,0.073300,0.0,0.0,0.0,0.0,0.0 +0,0.073400,0.0,0.0,0.0,0.0,0.0 +0,0.073500,0.0,0.0,0.0,0.0,0.0 +0,0.073600,0.0,0.0,0.0,0.0,0.0 +0,0.073700,0.0,0.0,0.0,0.0,0.0 +0,0.073800,0.0,0.0,0.0,0.0,0.0 +0,0.073900,0.0,0.0,0.0,0.0,0.0 +0,0.074000,0.0,0.0,0.0,0.0,0.0 +0,0.074100,0.0,0.0,0.0,0.0,0.0 +0,0.074200,0.0,0.0,0.0,0.0,0.0 +0,0.074300,0.0,0.0,0.0,0.0,0.0 +0,0.074400,0.0,0.0,0.0,0.0,0.0 +0,0.074500,0.0,0.0,0.0,0.0,0.0 +0,0.074600,0.0,0.0,0.0,0.0,0.0 +0,0.074700,0.0,0.0,0.0,0.0,0.0 +0,0.074800,0.0,0.0,0.0,0.0,0.0 +0,0.074900,0.0,0.0,0.0,0.0,0.0 +0,0.075000,0.0,0.0,0.0,0.0,0.0 +0,0.075100,0.0,0.0,0.0,0.0,0.0 +0,0.075200,0.0,0.0,0.0,0.0,0.0 +0,0.075300,0.0,0.0,0.0,0.0,0.0 +0,0.075400,0.0,0.0,0.0,0.0,0.0 +0,0.075500,0.0,0.0,0.0,0.0,0.0 +0,0.075600,0.0,0.0,0.0,0.0,0.0 +0,0.075700,0.0,0.0,0.0,0.0,0.0 +0,0.075800,0.0,0.0,0.0,0.0,0.0 +0,0.075900,0.0,0.0,0.0,0.0,0.0 +0,0.076000,0.0,0.0,0.0,0.0,0.0 +0,0.076100,0.0,0.0,0.0,0.0,0.0 +0,0.076200,0.0,0.0,0.0,0.0,0.0 +0,0.076300,0.0,0.0,0.0,0.0,0.0 +0,0.076400,0.0,0.0,0.0,0.0,0.0 +0,0.076500,0.0,0.0,0.0,0.0,0.0 +0,0.076600,0.0,0.0,0.0,0.0,0.0 +0,0.076700,0.0,0.0,0.0,0.0,0.0 +0,0.076800,0.0,0.0,0.0,0.0,0.0 +0,0.076900,0.0,0.0,0.0,0.0,0.0 +0,0.077000,0.0,0.0,0.0,0.0,0.0 +0,0.077100,0.0,0.0,0.0,0.0,0.0 +0,0.077200,0.0,0.0,0.0,0.0,0.0 +0,0.077300,0.0,0.0,0.0,0.0,0.0 +0,0.077400,0.0,0.0,0.0,0.0,0.0 +0,0.077500,0.0,0.0,0.0,0.0,0.0 +0,0.077600,0.0,0.0,0.0,0.0,0.0 +0,0.077700,0.0,0.0,0.0,0.0,0.0 +0,0.077800,0.0,0.0,0.0,0.0,0.0 +0,0.077900,0.0,0.0,0.0,0.0,0.0 +0,0.078000,0.0,0.0,0.0,0.0,0.0 +0,0.078100,0.0,0.0,0.0,0.0,0.0 +0,0.078200,0.0,0.0,0.0,0.0,0.0 +0,0.078300,0.0,0.0,0.0,0.0,0.0 +0,0.078400,0.0,0.0,0.0,0.0,0.0 +0,0.078500,0.0,0.0,0.0,0.0,0.0 +0,0.078600,0.0,0.0,0.0,0.0,0.0 +0,0.078700,0.0,0.0,0.0,0.0,0.0 +0,0.078800,0.0,0.0,0.0,0.0,0.0 +0,0.078900,0.0,0.0,0.0,0.0,0.0 +0,0.079000,0.0,0.0,0.0,0.0,0.0 +0,0.079100,0.0,0.0,0.0,0.0,0.0 +0,0.079200,0.0,0.0,0.0,0.0,0.0 +0,0.079300,0.0,0.0,0.0,0.0,0.0 +0,0.079400,0.0,0.0,0.0,0.0,0.0 +0,0.079500,0.0,0.0,0.0,0.0,0.0 +0,0.079600,0.0,0.0,0.0,0.0,0.0 +0,0.079700,0.0,0.0,0.0,0.0,0.0 +0,0.079800,0.0,0.0,0.0,0.0,0.0 +0,0.079900,0.0,0.0,0.0,0.0,0.0 +0,0.080000,0.0,0.0,0.0,0.0,0.0 +0,0.080100,0.0,0.0,0.0,0.0,0.0 +1,0.214536,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.080200,0.0,0.0,0.0,0.0,0.0 +0,0.080300,0.0,0.0,0.0,0.0,0.0 +0,0.080400,0.0,0.0,0.0,0.0,0.0 +0,0.080500,0.0,0.0,0.0,0.0,0.0 +0,0.080600,0.0,0.0,0.0,0.0,0.0 +0,0.080700,0.0,0.0,0.0,0.0,0.0 +0,0.080800,0.0,0.0,0.0,0.0,0.0 +0,0.080900,0.0,0.0,0.0,0.0,0.0 +0,0.081000,0.0,0.0,0.0,0.0,0.0 +0,0.081100,0.0,0.0,0.0,0.0,0.0 +0,0.081200,0.0,0.0,0.0,0.0,0.0 +0,0.081300,0.0,0.0,0.0,0.0,0.0 +0,0.081400,0.0,0.0,0.0,0.0,0.0 +0,0.081500,0.0,0.0,0.0,0.0,0.0 +0,0.081600,0.0,0.0,0.0,0.0,0.0 +0,0.081700,0.0,0.0,0.0,0.0,0.0 +0,0.081800,0.0,0.0,0.0,0.0,0.0 +0,0.081900,0.0,0.0,0.0,0.0,0.0 +0,0.082000,0.0,0.0,0.0,0.0,0.0 +0,0.082100,0.0,0.0,0.0,0.0,0.0 +0,0.082200,0.0,0.0,0.0,0.0,0.0 +0,0.082300,0.0,0.0,0.0,0.0,0.0 +0,0.082400,0.0,0.0,0.0,0.0,0.0 +0,0.082500,0.0,0.0,0.0,0.0,0.0 +0,0.082600,0.0,0.0,0.0,0.0,0.0 +0,0.082700,0.0,0.0,0.0,0.0,0.0 +0,0.082800,0.0,0.0,0.0,0.0,0.0 +0,0.082900,0.0,0.0,0.0,0.0,0.0 +0,0.083000,0.0,0.0,0.0,0.0,0.0 +0,0.083100,0.0,0.0,0.0,0.0,0.0 +0,0.083200,0.0,0.0,0.0,0.0,0.0 +0,0.083300,0.0,0.0,0.0,0.0,0.0 +0,0.083400,0.0,0.0,0.0,0.0,0.0 +0,0.083500,0.0,0.0,0.0,0.0,0.0 +0,0.083600,0.0,0.0,0.0,0.0,0.0 +0,0.083700,0.0,0.0,0.0,0.0,0.0 +0,0.083800,0.0,0.0,0.0,0.0,0.0 +0,0.083900,0.0,0.0,0.0,0.0,0.0 +0,0.084000,0.0,0.0,0.0,0.0,0.0 +0,0.084100,0.0,0.0,0.0,0.0,0.0 +0,0.084200,0.0,0.0,0.0,0.0,0.0 +0,0.084300,0.0,0.0,0.0,0.0,0.0 +0,0.084400,0.0,0.0,0.0,0.0,0.0 +0,0.084500,0.0,0.0,0.0,0.0,0.0 +0,0.084600,0.0,0.0,0.0,0.0,0.0 +0,0.084700,0.0,0.0,0.0,0.0,0.0 +0,0.084800,0.0,0.0,0.0,0.0,0.0 +0,0.084900,0.0,0.0,0.0,0.0,0.0 +0,0.085000,0.0,0.0,0.0,0.0,0.0 +0,0.085100,0.0,0.0,0.0,0.0,0.0 +0,0.085200,0.0,0.0,0.0,0.0,0.0 +0,0.085300,0.0,0.0,0.0,0.0,0.0 +0,0.085400,0.0,0.0,0.0,0.0,0.0 +0,0.085500,0.0,0.0,0.0,0.0,0.0 +0,0.085600,0.0,0.0,0.0,0.0,0.0 +0,0.085700,0.0,0.0,0.0,0.0,0.0 +0,0.085800,0.0,0.0,0.0,0.0,0.0 +0,0.085900,0.0,0.0,0.0,0.0,0.0 +0,0.086000,0.0,0.0,0.0,0.0,0.0 +0,0.086100,0.0,0.0,0.0,0.0,0.0 +0,0.086200,0.0,0.0,0.0,0.0,0.0 +0,0.086300,0.0,0.0,0.0,0.0,0.0 +0,0.086400,0.0,0.0,0.0,0.0,0.0 +0,0.086500,0.0,0.0,0.0,0.0,0.0 +0,0.086600,0.0,0.0,0.0,0.0,0.0 +0,0.086700,0.0,0.0,0.0,0.0,0.0 +0,0.086800,0.0,0.0,0.0,0.0,0.0 +0,0.086900,0.0,0.0,0.0,0.0,0.0 +0,0.087000,0.0,0.0,0.0,0.0,0.0 +0,0.087100,0.0,0.0,0.0,0.0,0.0 +0,0.087200,0.0,0.0,0.0,0.0,0.0 +0,0.087300,0.0,0.0,0.0,0.0,0.0 +0,0.087400,0.0,0.0,0.0,0.0,0.0 +0,0.087500,0.0,0.0,0.0,0.0,0.0 +0,0.087600,0.0,0.0,0.0,0.0,0.0 +0,0.087700,0.0,0.0,0.0,0.0,0.0 +0,0.087800,0.0,0.0,0.0,0.0,0.0 +0,0.087900,0.0,0.0,0.0,0.0,0.0 +0,0.088000,0.0,0.0,0.0,0.0,0.0 +0,0.088100,0.0,0.0,0.0,0.0,0.0 +0,0.088200,0.0,0.0,0.0,0.0,0.0 +0,0.088300,0.0,0.0,0.0,0.0,0.0 +0,0.088400,0.0,0.0,0.0,0.0,0.0 +0,0.088500,0.0,0.0,0.0,0.0,0.0 +0,0.088600,0.0,0.0,0.0,0.0,0.0 +0,0.088700,0.0,0.0,0.0,0.0,0.0 +0,0.088800,0.0,0.0,0.0,0.0,0.0 +0,0.088900,0.0,0.0,0.0,0.0,0.0 +0,0.089000,0.0,0.0,0.0,0.0,0.0 +0,0.089100,0.0,0.0,0.0,0.0,0.0 +0,0.089200,0.0,0.0,0.0,0.0,0.0 +0,0.089300,0.0,0.0,0.0,0.0,0.0 +0,0.089400,0.0,0.0,0.0,0.0,0.0 +0,0.089500,0.0,0.0,0.0,0.0,0.0 +0,0.089600,0.0,0.0,0.0,0.0,0.0 +0,0.089700,0.0,0.0,0.0,0.0,0.0 +0,0.089800,0.0,0.0,0.0,0.0,0.0 +0,0.089900,0.0,0.0,0.0,0.0,0.0 +0,0.090000,0.0,0.0,0.0,0.0,0.0 +0,0.090100,0.0,0.0,0.0,0.0,0.0 +0,0.090200,0.0,0.0,0.0,0.0,0.0 +0,0.090300,0.0,0.0,0.0,0.0,0.0 +0,0.090400,0.0,0.0,0.0,0.0,0.0 +0,0.090500,0.0,0.0,0.0,0.0,0.0 +0,0.090600,0.0,0.0,0.0,0.0,0.0 +0,0.090700,0.0,0.0,0.0,0.0,0.0 +0,0.090800,0.0,0.0,0.0,0.0,0.0 +0,0.090900,0.0,0.0,0.0,0.0,0.0 +0,0.091000,0.0,0.0,0.0,0.0,0.0 +0,0.091100,0.0,0.0,0.0,0.0,0.0 +0,0.091200,0.0,0.0,0.0,0.0,0.0 +0,0.091300,0.0,0.0,0.0,0.0,0.0 +0,0.091400,0.0,0.0,0.0,0.0,0.0 +0,0.091500,0.0,0.0,0.0,0.0,0.0 +0,0.091600,0.0,0.0,0.0,0.0,0.0 +0,0.091700,0.0,0.0,0.0,0.0,0.0 +0,0.091800,0.0,0.0,0.0,0.0,0.0 +0,0.091900,0.0,0.0,0.0,0.0,0.0 +0,0.092000,0.0,0.0,0.0,0.0,0.0 +0,0.092100,0.0,0.0,0.0,0.0,0.0 +0,0.092200,0.0,0.0,0.0,0.0,0.0 +0,0.092300,0.0,0.0,0.0,0.0,0.0 +0,0.092400,0.0,0.0,0.0,0.0,0.0 +0,0.092500,0.0,0.0,0.0,0.0,0.0 +0,0.092600,0.0,0.0,0.0,0.0,0.0 +0,0.092700,0.0,0.0,0.0,0.0,0.0 +0,0.092800,0.0,0.0,0.0,0.0,0.0 +0,0.092900,0.0,0.0,0.0,0.0,0.0 +0,0.093000,0.0,0.0,0.0,0.0,0.0 +0,0.093100,0.0,0.0,0.0,0.0,0.0 +0,0.093200,0.0,0.0,0.0,0.0,0.0 +0,0.093300,0.0,0.0,0.0,0.0,0.0 +0,0.093400,0.0,0.0,0.0,0.0,0.0 +0,0.093500,0.0,0.0,0.0,0.0,0.0 +0,0.093600,0.0,0.0,0.0,0.0,0.0 +0,0.093700,0.0,0.0,0.0,0.0,0.0 +0,0.093800,0.0,0.0,0.0,0.0,0.0 +0,0.093900,0.0,0.0,0.0,0.0,0.0 +0,0.094000,0.0,0.0,0.0,0.0,0.0 +0,0.094100,0.0,0.0,0.0,0.0,0.0 +0,0.094200,0.0,0.0,0.0,0.0,0.0 +0,0.094300,0.0,0.0,0.0,0.0,0.0 +0,0.094400,0.0,0.0,0.0,0.0,0.0 +0,0.094500,0.0,0.0,0.0,0.0,0.0 +0,0.094600,0.0,0.0,0.0,0.0,0.0 +0,0.094700,0.0,0.0,0.0,0.0,0.0 +0,0.094800,0.0,0.0,0.0,0.0,0.0 +0,0.094900,0.0,0.0,0.0,0.0,0.0 +0,0.095000,0.0,0.0,0.0,0.0,0.0 +0,0.095100,0.0,0.0,0.0,0.0,0.0 +0,0.095200,0.0,0.0,0.0,0.0,0.0 +0,0.095300,0.0,0.0,0.0,0.0,0.0 +0,0.095400,0.0,0.0,0.0,0.0,0.0 +0,0.095500,0.0,0.0,0.0,0.0,0.0 +0,0.095600,0.0,0.0,0.0,0.0,0.0 +0,0.095700,0.0,0.0,0.0,0.0,0.0 +0,0.095800,0.0,0.0,0.0,0.0,0.0 +0,0.095900,0.0,0.0,0.0,0.0,0.0 +0,0.096000,0.0,0.0,0.0,0.0,0.0 +0,0.096100,0.0,0.0,0.0,0.0,0.0 +0,0.096200,0.0,0.0,0.0,0.0,0.0 +0,0.096300,0.0,0.0,0.0,0.0,0.0 +0,0.096400,0.0,0.0,0.0,0.0,0.0 +0,0.096500,0.0,0.0,0.0,0.0,0.0 +0,0.096600,0.0,0.0,0.0,0.0,0.0 +0,0.096700,0.0,0.0,0.0,0.0,0.0 +0,0.096800,0.0,0.0,0.0,0.0,0.0 +0,0.096900,0.0,0.0,0.0,0.0,0.0 +0,0.097000,0.0,0.0,0.0,0.0,0.0 +0,0.097100,0.0,0.0,0.0,0.0,0.0 +0,0.097200,0.0,0.0,0.0,0.0,0.0 +0,0.097300,0.0,0.0,0.0,0.0,0.0 +0,0.097400,0.0,0.0,0.0,0.0,0.0 +0,0.097500,0.0,0.0,0.0,0.0,0.0 +0,0.097600,0.0,0.0,0.0,0.0,0.0 +0,0.097700,0.0,0.0,0.0,0.0,0.0 +0,0.097800,0.0,0.0,0.0,0.0,0.0 +0,0.097900,0.0,0.0,0.0,0.0,0.0 +0,0.098000,0.0,0.0,0.0,0.0,0.0 +0,0.098100,0.0,0.0,0.0,0.0,0.0 +0,0.098200,0.0,0.0,0.0,0.0,0.0 +0,0.098300,0.0,0.0,0.0,0.0,0.0 +0,0.098400,0.0,0.0,0.0,0.0,0.0 +0,0.098500,0.0,0.0,0.0,0.0,0.0 +0,0.098600,0.0,0.0,0.0,0.0,0.0 +0,0.098700,0.0,0.0,0.0,0.0,0.0 +0,0.098800,0.0,0.0,0.0,0.0,0.0 +0,0.098900,0.0,0.0,0.0,0.0,0.0 +0,0.099000,0.0,0.0,0.0,0.0,0.0 +0,0.099100,0.0,0.0,0.0,0.0,0.0 +0,0.099200,0.0,0.0,0.0,0.0,0.0 +0,0.099300,0.0,0.0,0.0,0.0,0.0 +0,0.099400,0.0,0.0,0.0,0.0,0.0 +0,0.099500,0.0,0.0,0.0,0.0,0.0 +0,0.099600,0.0,0.0,0.0,0.0,0.0 +0,0.099700,0.0,0.0,0.0,0.0,0.0 +0,0.099800,0.0,0.0,0.0,0.0,0.0 +0,0.099900,0.0,0.0,0.0,0.0,0.0 +0,0.100000,0.0,0.0,0.0,0.0,0.0 +0,0.100100,0.0,0.0,0.0,0.0,0.0 +1,0.418544,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.100200,0.0,0.0,0.0,0.0,0.0 +0,0.100300,0.0,0.0,0.0,0.0,0.0 +0,0.100400,0.0,0.0,0.0,0.0,0.0 +0,0.100500,0.0,0.0,0.0,0.0,0.0 +0,0.100600,0.0,0.0,0.0,0.0,0.0 +0,0.100700,0.0,0.0,0.0,0.0,0.0 +0,0.100800,0.0,0.0,0.0,0.0,0.0 +0,0.100900,0.0,0.0,0.0,0.0,0.0 +0,0.101000,0.0,0.0,0.0,0.0,0.0 +0,0.101100,0.0,0.0,0.0,0.0,0.0 +0,0.101200,0.0,0.0,0.0,0.0,0.0 +0,0.101300,0.0,0.0,0.0,0.0,0.0 +0,0.101400,0.0,0.0,0.0,0.0,0.0 +0,0.101500,0.0,0.0,0.0,0.0,0.0 +0,0.101600,0.0,0.0,0.0,0.0,0.0 +0,0.101700,0.0,0.0,0.0,0.0,0.0 +0,0.101800,0.0,0.0,0.0,0.0,0.0 +0,0.101900,0.0,0.0,0.0,0.0,0.0 +0,0.102000,0.0,0.0,0.0,0.0,0.0 +0,0.102100,0.0,0.0,0.0,0.0,0.0 +0,0.102200,0.0,0.0,0.0,0.0,0.0 +0,0.102300,0.0,0.0,0.0,0.0,0.0 +0,0.102400,0.0,0.0,0.0,0.0,0.0 +0,0.102500,0.0,0.0,0.0,0.0,0.0 +0,0.102600,0.0,0.0,0.0,0.0,0.0 +0,0.102700,0.0,0.0,0.0,0.0,0.0 +0,0.102800,0.0,0.0,0.0,0.0,0.0 +0,0.102900,0.0,0.0,0.0,0.0,0.0 +0,0.103000,0.0,0.0,0.0,0.0,0.0 +0,0.103100,0.0,0.0,0.0,0.0,0.0 +0,0.103200,0.0,0.0,0.0,0.0,0.0 +0,0.103300,0.0,0.0,0.0,0.0,0.0 +0,0.103400,0.0,0.0,0.0,0.0,0.0 +0,0.103500,0.0,0.0,0.0,0.0,0.0 +0,0.103600,0.0,0.0,0.0,0.0,0.0 +0,0.103700,0.0,0.0,0.0,0.0,0.0 +0,0.103800,0.0,0.0,0.0,0.0,0.0 +0,0.103900,0.0,0.0,0.0,0.0,0.0 +0,0.104000,0.0,0.0,0.0,0.0,0.0 +0,0.104100,0.0,0.0,0.0,0.0,0.0 +0,0.104200,0.0,0.0,0.0,0.0,0.0 +0,0.104300,0.0,0.0,0.0,0.0,0.0 +0,0.104400,0.0,0.0,0.0,0.0,0.0 +0,0.104500,0.0,0.0,0.0,0.0,0.0 +0,0.104600,0.0,0.0,0.0,0.0,0.0 +0,0.104700,0.0,0.0,0.0,0.0,0.0 +0,0.104800,0.0,0.0,0.0,0.0,0.0 +0,0.104900,0.0,0.0,0.0,0.0,0.0 +0,0.105000,0.0,0.0,0.0,0.0,0.0 +0,0.105100,0.0,0.0,0.0,0.0,0.0 +0,0.105200,0.0,0.0,0.0,0.0,0.0 +0,0.105300,0.0,0.0,0.0,0.0,0.0 +0,0.105400,0.0,0.0,0.0,0.0,0.0 +0,0.105500,0.0,0.0,0.0,0.0,0.0 +0,0.105600,0.0,0.0,0.0,0.0,0.0 +0,0.105700,0.0,0.0,0.0,0.0,0.0 +0,0.105800,0.0,0.0,0.0,0.0,0.0 +0,0.105900,0.0,0.0,0.0,0.0,0.0 +0,0.106000,0.0,0.0,0.0,0.0,0.0 +0,0.106100,0.0,0.0,0.0,0.0,0.0 +0,0.106200,0.0,0.0,0.0,0.0,0.0 +0,0.106300,0.0,0.0,0.0,0.0,0.0 +0,0.106400,0.0,0.0,0.0,0.0,0.0 +0,0.106500,0.0,0.0,0.0,0.0,0.0 +0,0.106600,0.0,0.0,0.0,0.0,0.0 +0,0.106700,0.0,0.0,0.0,0.0,0.0 +0,0.106800,0.0,0.0,0.0,0.0,0.0 +0,0.106900,0.0,0.0,0.0,0.0,0.0 +0,0.107000,0.0,0.0,0.0,0.0,0.0 +0,0.107100,0.0,0.0,0.0,0.0,0.0 +0,0.107200,0.0,0.0,0.0,0.0,0.0 +0,0.107300,0.0,0.0,0.0,0.0,0.0 +0,0.107400,0.0,0.0,0.0,0.0,0.0 +0,0.107500,0.0,0.0,0.0,0.0,0.0 +0,0.107600,0.0,0.0,0.0,0.0,0.0 +0,0.107700,0.0,0.0,0.0,0.0,0.0 +0,0.107800,0.0,0.0,0.0,0.0,0.0 +0,0.107900,0.0,0.0,0.0,0.0,0.0 +0,0.108000,0.0,0.0,0.0,0.0,0.0 +0,0.108100,0.0,0.0,0.0,0.0,0.0 +0,0.108200,0.0,0.0,0.0,0.0,0.0 +0,0.108300,0.0,0.0,0.0,0.0,0.0 +0,0.108400,0.0,0.0,0.0,0.0,0.0 +0,0.108500,0.0,0.0,0.0,0.0,0.0 +0,0.108600,0.0,0.0,0.0,0.0,0.0 +0,0.108700,0.0,0.0,0.0,0.0,0.0 +0,0.108800,0.0,0.0,0.0,0.0,0.0 +0,0.108900,0.0,0.0,0.0,0.0,0.0 +0,0.109000,0.0,0.0,0.0,0.0,0.0 +0,0.109100,0.0,0.0,0.0,0.0,0.0 +0,0.109200,0.0,0.0,0.0,0.0,0.0 +0,0.109300,0.0,0.0,0.0,0.0,0.0 +0,0.109400,0.0,0.0,0.0,0.0,0.0 +0,0.109500,0.0,0.0,0.0,0.0,0.0 +0,0.109600,0.0,0.0,0.0,0.0,0.0 +0,0.109700,0.0,0.0,0.0,0.0,0.0 +0,0.109800,0.0,0.0,0.0,0.0,0.0 +0,0.109900,0.0,0.0,0.0,0.0,0.0 +0,0.110000,0.0,0.0,0.0,0.0,0.0 +0,0.110100,0.0,0.0,0.0,0.0,0.0 +0,0.110200,0.0,0.0,0.0,0.0,0.0 +0,0.110300,0.0,0.0,0.0,0.0,0.0 +0,0.110400,0.0,0.0,0.0,0.0,0.0 +0,0.110500,0.0,0.0,0.0,0.0,0.0 +0,0.110600,0.0,0.0,0.0,0.0,0.0 +0,0.110700,0.0,0.0,0.0,0.0,0.0 +0,0.110800,0.0,0.0,0.0,0.0,0.0 +0,0.110900,0.0,0.0,0.0,0.0,0.0 +0,0.111000,0.0,0.0,0.0,0.0,0.0 +0,0.111100,0.0,0.0,0.0,0.0,0.0 +0,0.111200,0.0,0.0,0.0,0.0,0.0 +0,0.111300,0.0,0.0,0.0,0.0,0.0 +0,0.111400,0.0,0.0,0.0,0.0,0.0 +0,0.111500,0.0,0.0,0.0,0.0,0.0 +0,0.111600,0.0,0.0,0.0,0.0,0.0 +0,0.111700,0.0,0.0,0.0,0.0,0.0 +0,0.111800,0.0,0.0,0.0,0.0,0.0 +0,0.111900,0.0,0.0,0.0,0.0,0.0 +0,0.112000,0.0,0.0,0.0,0.0,0.0 +0,0.112100,0.0,0.0,0.0,0.0,0.0 +0,0.112200,0.0,0.0,0.0,0.0,0.0 +0,0.112300,0.0,0.0,0.0,0.0,0.0 +0,0.112400,0.0,0.0,0.0,0.0,0.0 +0,0.112500,0.0,0.0,0.0,0.0,0.0 +0,0.112600,0.0,0.0,0.0,0.0,0.0 +0,0.112700,0.0,0.0,0.0,0.0,0.0 +0,0.112800,0.0,0.0,0.0,0.0,0.0 +0,0.112900,0.0,0.0,0.0,0.0,0.0 +0,0.113000,0.0,0.0,0.0,0.0,0.0 +0,0.113100,0.0,0.0,0.0,0.0,0.0 +0,0.113200,0.0,0.0,0.0,0.0,0.0 +0,0.113300,0.0,0.0,0.0,0.0,0.0 +0,0.113400,0.0,0.0,0.0,0.0,0.0 +0,0.113500,0.0,0.0,0.0,0.0,0.0 +0,0.113600,0.0,0.0,0.0,0.0,0.0 +0,0.113700,0.0,0.0,0.0,0.0,0.0 +0,0.113800,0.0,0.0,0.0,0.0,0.0 +0,0.113900,0.0,0.0,0.0,0.0,0.0 +0,0.114000,0.0,0.0,0.0,0.0,0.0 +0,0.114100,0.0,0.0,0.0,0.0,0.0 +0,0.114200,0.0,0.0,0.0,0.0,0.0 +0,0.114300,0.0,0.0,0.0,0.0,0.0 +0,0.114400,0.0,0.0,0.0,0.0,0.0 +0,0.114500,0.0,0.0,0.0,0.0,0.0 +0,0.114600,0.0,0.0,0.0,0.0,0.0 +0,0.114700,0.0,0.0,0.0,0.0,0.0 +0,0.114800,0.0,0.0,0.0,0.0,0.0 +0,0.114900,0.0,0.0,0.0,0.0,0.0 +0,0.115000,0.0,0.0,0.0,0.0,0.0 +0,0.115100,0.0,0.0,0.0,0.0,0.0 +0,0.115200,0.0,0.0,0.0,0.0,0.0 +0,0.115300,0.0,0.0,0.0,0.0,0.0 +0,0.115400,0.0,0.0,0.0,0.0,0.0 +0,0.115500,0.0,0.0,0.0,0.0,0.0 +0,0.115600,0.0,0.0,0.0,0.0,0.0 +0,0.115700,0.0,0.0,0.0,0.0,0.0 +0,0.115800,0.0,0.0,0.0,0.0,0.0 +0,0.115900,0.0,0.0,0.0,0.0,0.0 +0,0.116000,0.0,0.0,0.0,0.0,0.0 +0,0.116100,0.0,0.0,0.0,0.0,0.0 +0,0.116200,0.0,0.0,0.0,0.0,0.0 +0,0.116300,0.0,0.0,0.0,0.0,0.0 +0,0.116400,0.0,0.0,0.0,0.0,0.0 +0,0.116500,0.0,0.0,0.0,0.0,0.0 +0,0.116600,0.0,0.0,0.0,0.0,0.0 +0,0.116700,0.0,0.0,0.0,0.0,0.0 +0,0.116800,0.0,0.0,0.0,0.0,0.0 +0,0.116900,0.0,0.0,0.0,0.0,0.0 +0,0.117000,0.0,0.0,0.0,0.0,0.0 +0,0.117100,0.0,0.0,0.0,0.0,0.0 +0,0.117200,0.0,0.0,0.0,0.0,0.0 +0,0.117300,0.0,0.0,0.0,0.0,0.0 +0,0.117400,0.0,0.0,0.0,0.0,0.0 +0,0.117500,0.0,0.0,0.0,0.0,0.0 +0,0.117600,0.0,0.0,0.0,0.0,0.0 +0,0.117700,0.0,0.0,0.0,0.0,0.0 +0,0.117800,0.0,0.0,0.0,0.0,0.0 +0,0.117900,0.0,0.0,0.0,0.0,0.0 +0,0.118000,0.0,0.0,0.0,0.0,0.0 +0,0.118100,0.0,0.0,0.0,0.0,0.0 +0,0.118200,0.0,0.0,0.0,0.0,0.0 +0,0.118300,0.0,0.0,0.0,0.0,0.0 +0,0.118400,0.0,0.0,0.0,0.0,0.0 +0,0.118500,0.0,0.0,0.0,0.0,0.0 +0,0.118600,0.0,0.0,0.0,0.0,0.0 +0,0.118700,0.0,0.0,0.0,0.0,0.0 +0,0.118800,0.0,0.0,0.0,0.0,0.0 +0,0.118900,0.0,0.0,0.0,0.0,0.0 +0,0.119000,0.0,0.0,0.0,0.0,0.0 +0,0.119100,0.0,0.0,0.0,0.0,0.0 +0,0.119200,0.0,0.0,0.0,0.0,0.0 +0,0.119300,0.0,0.0,0.0,0.0,0.0 +0,0.119400,0.0,0.0,0.0,0.0,0.0 +0,0.119500,0.0,0.0,0.0,0.0,0.0 +0,0.119600,0.0,0.0,0.0,0.0,0.0 +0,0.119700,0.0,0.0,0.0,0.0,0.0 +0,0.119800,0.0,0.0,0.0,0.0,0.0 +0,0.119900,0.0,0.0,0.0,0.0,0.0 +0,0.120000,0.0,0.0,0.0,0.0,0.0 +0,0.120100,0.0,0.0,0.0,0.0,0.0 +1,0.722703,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.120200,0.0,0.0,0.0,0.0,0.0 +0,0.120300,0.0,0.0,0.0,0.0,0.0 +0,0.120400,0.0,0.0,0.0,0.0,0.0 +0,0.120500,0.0,0.0,0.0,0.0,0.0 +0,0.120600,0.0,0.0,0.0,0.0,0.0 +0,0.120700,0.0,0.0,0.0,0.0,0.0 +0,0.120800,0.0,0.0,0.0,0.0,0.0 +0,0.120900,0.0,0.0,0.0,0.0,0.0 +0,0.121000,0.0,0.0,0.0,0.0,0.0 +0,0.121100,0.0,0.0,0.0,0.0,0.0 +0,0.121200,0.0,0.0,0.0,0.0,0.0 +0,0.121300,0.0,0.0,0.0,0.0,0.0 +0,0.121400,0.0,0.0,0.0,0.0,0.0 +0,0.121500,0.0,0.0,0.0,0.0,0.0 +0,0.121600,0.0,0.0,0.0,0.0,0.0 +0,0.121700,0.0,0.0,0.0,0.0,0.0 +0,0.121800,0.0,0.0,0.0,0.0,0.0 +0,0.121900,0.0,0.0,0.0,0.0,0.0 +0,0.122000,0.0,0.0,0.0,0.0,0.0 +0,0.122100,0.0,0.0,0.0,0.0,0.0 +0,0.122200,0.0,0.0,0.0,0.0,0.0 +0,0.122300,0.0,0.0,0.0,0.0,0.0 +0,0.122400,0.0,0.0,0.0,0.0,0.0 +0,0.122500,0.0,0.0,0.0,0.0,0.0 +0,0.122600,0.0,0.0,0.0,0.0,0.0 +0,0.122700,0.0,0.0,0.0,0.0,0.0 +0,0.122800,0.0,0.0,0.0,0.0,0.0 +0,0.122900,0.0,0.0,0.0,0.0,0.0 +0,0.123000,0.0,0.0,0.0,0.0,0.0 +0,0.123100,0.0,0.0,0.0,0.0,0.0 +0,0.123200,0.0,0.0,0.0,0.0,0.0 +0,0.123300,0.0,0.0,0.0,0.0,0.0 +0,0.123400,0.0,0.0,0.0,0.0,0.0 +0,0.123500,0.0,0.0,0.0,0.0,0.0 +0,0.123600,0.0,0.0,0.0,0.0,0.0 +0,0.123700,0.0,0.0,0.0,0.0,0.0 +0,0.123800,0.0,0.0,0.0,0.0,0.0 +0,0.123900,0.0,0.0,0.0,0.0,0.0 +0,0.124000,0.0,0.0,0.0,0.0,0.0 +0,0.124100,0.0,0.0,0.0,0.0,0.0 +0,0.124200,0.0,0.0,0.0,0.0,0.0 +0,0.124300,0.0,0.0,0.0,0.0,0.0 +0,0.124400,0.0,0.0,0.0,0.0,0.0 +0,0.124500,0.0,0.0,0.0,0.0,0.0 +0,0.124600,0.0,0.0,0.0,0.0,0.0 +0,0.124700,0.0,0.0,0.0,0.0,0.0 +0,0.124800,0.0,0.0,0.0,0.0,0.0 +0,0.124900,0.0,0.0,0.0,0.0,0.0 +0,0.125000,0.0,0.0,0.0,0.0,0.0 +0,0.125100,0.0,0.0,0.0,0.0,0.0 +0,0.125200,0.0,0.0,0.0,0.0,0.0 +0,0.125300,0.0,0.0,0.0,0.0,0.0 +0,0.125400,0.0,0.0,0.0,0.0,0.0 +0,0.125500,0.0,0.0,0.0,0.0,0.0 +0,0.125600,0.0,0.0,0.0,0.0,0.0 +0,0.125700,0.0,0.0,0.0,0.0,0.0 +0,0.125800,0.0,0.0,0.0,0.0,0.0 +0,0.125900,0.0,0.0,0.0,0.0,0.0 +0,0.126000,0.0,0.0,0.0,0.0,0.0 +0,0.126100,0.0,0.0,0.0,0.0,0.0 +0,0.126200,0.0,0.0,0.0,0.0,0.0 +0,0.126300,0.0,0.0,0.0,0.0,0.0 +0,0.126400,0.0,0.0,0.0,0.0,0.0 +0,0.126500,0.0,0.0,0.0,0.0,0.0 +0,0.126600,0.0,0.0,0.0,0.0,0.0 +0,0.126700,0.0,0.0,0.0,0.0,0.0 +0,0.126800,0.0,0.0,0.0,0.0,0.0 +0,0.126900,0.0,0.0,0.0,0.0,0.0 +0,0.127000,0.0,0.0,0.0,0.0,0.0 +0,0.127100,0.0,0.0,0.0,0.0,0.0 +0,0.127200,0.0,0.0,0.0,0.0,0.0 +0,0.127300,0.0,0.0,0.0,0.0,0.0 +0,0.127400,0.0,0.0,0.0,0.0,0.0 +0,0.127500,0.0,0.0,0.0,0.0,0.0 +0,0.127600,0.0,0.0,0.0,0.0,0.0 +0,0.127700,0.0,0.0,0.0,0.0,0.0 +0,0.127800,0.0,0.0,0.0,0.0,0.0 +0,0.127900,0.0,0.0,0.0,0.0,0.0 +0,0.128000,0.0,0.0,0.0,0.0,0.0 +0,0.128100,0.0,0.0,0.0,0.0,0.0 +0,0.128200,0.0,0.0,0.0,0.0,0.0 +0,0.128300,0.0,0.0,0.0,0.0,0.0 +0,0.128400,0.0,0.0,0.0,0.0,0.0 +0,0.128500,0.0,0.0,0.0,0.0,0.0 +0,0.128600,0.0,0.0,0.0,0.0,0.0 +0,0.128700,0.0,0.0,0.0,0.0,0.0 +0,0.128800,0.0,0.0,0.0,0.0,0.0 +0,0.128900,0.0,0.0,0.0,0.0,0.0 +0,0.129000,0.0,0.0,0.0,0.0,0.0 +0,0.129100,0.0,0.0,0.0,0.0,0.0 +0,0.129200,0.0,0.0,0.0,0.0,0.0 +0,0.129300,0.0,0.0,0.0,0.0,0.0 +0,0.129400,0.0,0.0,0.0,0.0,0.0 +0,0.129500,0.0,0.0,0.0,0.0,0.0 +0,0.129600,0.0,0.0,0.0,0.0,0.0 +0,0.129700,0.0,0.0,0.0,0.0,0.0 +0,0.129800,0.0,0.0,0.0,0.0,0.0 +0,0.129900,0.0,0.0,0.0,0.0,0.0 +0,0.130000,0.0,0.0,0.0,0.0,0.0 +0,0.130100,0.0,0.0,0.0,0.0,0.0 +0,0.130200,0.0,0.0,0.0,0.0,0.0 +0,0.130300,0.0,0.0,0.0,0.0,0.0 +0,0.130400,0.0,0.0,0.0,0.0,0.0 +0,0.130500,0.0,0.0,0.0,0.0,0.0 +0,0.130600,0.0,0.0,0.0,0.0,0.0 +0,0.130700,0.0,0.0,0.0,0.0,0.0 +0,0.130800,0.0,0.0,0.0,0.0,0.0 +0,0.130900,0.0,0.0,0.0,0.0,0.0 +0,0.131000,0.0,0.0,0.0,0.0,0.0 +0,0.131100,0.0,0.0,0.0,0.0,0.0 +0,0.131200,0.0,0.0,0.0,0.0,0.0 +0,0.131300,0.0,0.0,0.0,0.0,0.0 +0,0.131400,0.0,0.0,0.0,0.0,0.0 +0,0.131500,0.0,0.0,0.0,0.0,0.0 +0,0.131600,0.0,0.0,0.0,0.0,0.0 +0,0.131700,0.0,0.0,0.0,0.0,0.0 +0,0.131800,0.0,0.0,0.0,0.0,0.0 +0,0.131900,0.0,0.0,0.0,0.0,0.0 +0,0.132000,0.0,0.0,0.0,0.0,0.0 +0,0.132100,0.0,0.0,0.0,0.0,0.0 +0,0.132200,0.0,0.0,0.0,0.0,0.0 +0,0.132300,0.0,0.0,0.0,0.0,0.0 +0,0.132400,0.0,0.0,0.0,0.0,0.0 +0,0.132500,0.0,0.0,0.0,0.0,0.0 +0,0.132600,0.0,0.0,0.0,0.0,0.0 +0,0.132700,0.0,0.0,0.0,0.0,0.0 +0,0.132800,0.0,0.0,0.0,0.0,0.0 +0,0.132900,0.0,0.0,0.0,0.0,0.0 +0,0.133000,0.0,0.0,0.0,0.0,0.0 +0,0.133100,0.0,0.0,0.0,0.0,0.0 +0,0.133200,0.0,0.0,0.0,0.0,0.0 +0,0.133300,0.0,0.0,0.0,0.0,0.0 +0,0.133400,0.0,0.0,0.0,0.0,0.0 +0,0.133500,0.0,0.0,0.0,0.0,0.0 +0,0.133600,0.0,0.0,0.0,0.0,0.0 +0,0.133700,0.0,0.0,0.0,0.0,0.0 +0,0.133800,0.0,0.0,0.0,0.0,0.0 +0,0.133900,0.0,0.0,0.0,0.0,0.0 +0,0.134000,0.0,0.0,0.0,0.0,0.0 +0,0.134100,0.0,0.0,0.0,0.0,0.0 +0,0.134200,0.0,0.0,0.0,0.0,0.0 +0,0.134300,0.0,0.0,0.0,0.0,0.0 +0,0.134400,0.0,0.0,0.0,0.0,0.0 +0,0.134500,0.0,0.0,0.0,0.0,0.0 +0,0.134600,0.0,0.0,0.0,0.0,0.0 +0,0.134700,0.0,0.0,0.0,0.0,0.0 +0,0.134800,0.0,0.0,0.0,0.0,0.0 +0,0.134900,0.0,0.0,0.0,0.0,0.0 +0,0.135000,0.0,0.0,0.0,0.0,0.0 +0,0.135100,0.0,0.0,0.0,0.0,0.0 +0,0.135200,0.0,0.0,0.0,0.0,0.0 +0,0.135300,0.0,0.0,0.0,0.0,0.0 +0,0.135400,0.0,0.0,0.0,0.0,0.0 +0,0.135500,0.0,0.0,0.0,0.0,0.0 +0,0.135600,0.0,0.0,0.0,0.0,0.0 +0,0.135700,0.0,0.0,0.0,0.0,0.0 +0,0.135800,0.0,0.0,0.0,0.0,0.0 +0,0.135900,0.0,0.0,0.0,0.0,0.0 +0,0.136000,0.0,0.0,0.0,0.0,0.0 +0,0.136100,0.0,0.0,0.0,0.0,0.0 +0,0.136200,0.0,0.0,0.0,0.0,0.0 +0,0.136300,0.0,0.0,0.0,0.0,0.0 +0,0.136400,0.0,0.0,0.0,0.0,0.0 +0,0.136500,0.0,0.0,0.0,0.0,0.0 +0,0.136600,0.0,0.0,0.0,0.0,0.0 +0,0.136700,0.0,0.0,0.0,0.0,0.0 +0,0.136800,0.0,0.0,0.0,0.0,0.0 +0,0.136900,0.0,0.0,0.0,0.0,0.0 +0,0.137000,0.0,0.0,0.0,0.0,0.0 +0,0.137100,0.0,0.0,0.0,0.0,0.0 +0,0.137200,0.0,0.0,0.0,0.0,0.0 +0,0.137300,0.0,0.0,0.0,0.0,0.0 +0,0.137400,0.0,0.0,0.0,0.0,0.0 +0,0.137500,0.0,0.0,0.0,0.0,0.0 +0,0.137600,0.0,0.0,0.0,0.0,0.0 +0,0.137700,0.0,0.0,0.0,0.0,0.0 +0,0.137800,0.0,0.0,0.0,0.0,0.0 +0,0.137900,0.0,0.0,0.0,0.0,0.0 +0,0.138000,0.0,0.0,0.0,0.0,0.0 +0,0.138100,0.0,0.0,0.0,0.0,0.0 +0,0.138200,0.0,0.0,0.0,0.0,0.0 +0,0.138300,0.0,0.0,0.0,0.0,0.0 +0,0.138400,0.0,0.0,0.0,0.0,0.0 +0,0.138500,0.0,0.0,0.0,0.0,0.0 +0,0.138600,0.0,0.0,0.0,0.0,0.0 +0,0.138700,0.0,0.0,0.0,0.0,0.0 +0,0.138800,0.0,0.0,0.0,0.0,0.0 +0,0.138900,0.0,0.0,0.0,0.0,0.0 +0,0.139000,0.0,0.0,0.0,0.0,0.0 +0,0.139100,0.0,0.0,0.0,0.0,0.0 +0,0.139200,0.0,0.0,0.0,0.0,0.0 +0,0.139300,0.0,0.0,0.0,0.0,0.0 +0,0.139400,0.0,0.0,0.0,0.0,0.0 +0,0.139500,0.0,0.0,0.0,0.0,0.0 +0,0.139600,0.0,0.0,0.0,0.0,0.0 +0,0.139700,0.0,0.0,0.0,0.0,0.0 +0,0.139800,0.0,0.0,0.0,0.0,0.0 +0,0.139900,0.0,0.0,0.0,0.0,0.0 +0,0.140000,0.0,0.0,0.0,0.0,0.0 +0,0.140100,0.0,0.0,0.0,0.0,0.0 +1,1.147012,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.140200,0.0,0.0,0.0,0.0,0.0 +0,0.140300,0.0,0.0,0.0,0.0,0.0 +0,0.140400,0.0,0.0,0.0,0.0,0.0 +0,0.140500,0.0,0.0,0.0,0.0,0.0 +0,0.140600,0.0,0.0,0.0,0.0,0.0 +0,0.140700,0.0,0.0,0.0,0.0,0.0 +0,0.140800,0.0,0.0,0.0,0.0,0.0 +0,0.140900,0.0,0.0,0.0,0.0,0.0 +0,0.141000,0.0,0.0,0.0,0.0,0.0 +0,0.141100,0.0,0.0,0.0,0.0,0.0 +0,0.141200,0.0,0.0,0.0,0.0,0.0 +0,0.141300,0.0,0.0,0.0,0.0,0.0 +0,0.141400,0.0,0.0,0.0,0.0,0.0 +0,0.141500,0.0,0.0,0.0,0.0,0.0 +0,0.141600,0.0,0.0,0.0,0.0,0.0 +0,0.141700,0.0,0.0,0.0,0.0,0.0 +0,0.141800,0.0,0.0,0.0,0.0,0.0 +0,0.141900,0.0,0.0,0.0,0.0,0.0 +0,0.142000,0.0,0.0,0.0,0.0,0.0 +0,0.142100,0.0,0.0,0.0,0.0,0.0 +0,0.142200,0.0,0.0,0.0,0.0,0.0 +0,0.142300,0.0,0.0,0.0,0.0,0.0 +0,0.142400,0.0,0.0,0.0,0.0,0.0 +0,0.142500,0.0,0.0,0.0,0.0,0.0 +0,0.142600,0.0,0.0,0.0,0.0,0.0 +0,0.142700,0.0,0.0,0.0,0.0,0.0 +0,0.142800,0.0,0.0,0.0,0.0,0.0 +0,0.142900,0.0,0.0,0.0,0.0,0.0 +0,0.143000,0.0,0.0,0.0,0.0,0.0 +0,0.143100,0.0,0.0,0.0,0.0,0.0 +0,0.143200,0.0,0.0,0.0,0.0,0.0 +0,0.143300,0.0,0.0,0.0,0.0,0.0 +0,0.143400,0.0,0.0,0.0,0.0,0.0 +0,0.143500,0.0,0.0,0.0,0.0,0.0 +0,0.143600,0.0,0.0,0.0,0.0,0.0 +0,0.143700,0.0,0.0,0.0,0.0,0.0 +0,0.143800,0.0,0.0,0.0,0.0,0.0 +0,0.143900,0.0,0.0,0.0,0.0,0.0 +0,0.144000,0.0,0.0,0.0,0.0,0.0 +0,0.144100,0.0,0.0,0.0,0.0,0.0 +0,0.144200,0.0,0.0,0.0,0.0,0.0 +0,0.144300,0.0,0.0,0.0,0.0,0.0 +0,0.144400,0.0,0.0,0.0,0.0,0.0 +0,0.144500,0.0,0.0,0.0,0.0,0.0 +0,0.144600,0.0,0.0,0.0,0.0,0.0 +0,0.144700,0.0,0.0,0.0,0.0,0.0 +0,0.144800,0.0,0.0,0.0,0.0,0.0 +0,0.144900,0.0,0.0,0.0,0.0,0.0 +0,0.145000,0.0,0.0,0.0,0.0,0.0 +0,0.145100,0.0,0.0,0.0,0.0,0.0 +0,0.145200,0.0,0.0,0.0,0.0,0.0 +0,0.145300,0.0,0.0,0.0,0.0,0.0 +0,0.145400,0.0,0.0,0.0,0.0,0.0 +0,0.145500,0.0,0.0,0.0,0.0,0.0 +0,0.145600,0.0,0.0,0.0,0.0,0.0 +0,0.145700,0.0,0.0,0.0,0.0,0.0 +0,0.145800,0.0,0.0,0.0,0.0,0.0 +0,0.145900,0.0,0.0,0.0,0.0,0.0 +0,0.146000,0.0,0.0,0.0,0.0,0.0 +0,0.146100,0.0,0.0,0.0,0.0,0.0 +0,0.146200,0.0,0.0,0.0,0.0,0.0 +0,0.146300,0.0,0.0,0.0,0.0,0.0 +0,0.146400,0.0,0.0,0.0,0.0,0.0 +0,0.146500,0.0,0.0,0.0,0.0,0.0 +0,0.146600,0.0,0.0,0.0,0.0,0.0 +0,0.146700,0.0,0.0,0.0,0.0,0.0 +0,0.146800,0.0,0.0,0.0,0.0,0.0 +0,0.146900,0.0,0.0,0.0,0.0,0.0 +0,0.147000,0.0,0.0,0.0,0.0,0.0 +0,0.147100,0.0,0.0,0.0,0.0,0.0 +0,0.147200,0.0,0.0,0.0,0.0,0.0 +0,0.147300,0.0,0.0,0.0,0.0,0.0 +0,0.147400,0.0,0.0,0.0,0.0,0.0 +0,0.147500,0.0,0.0,0.0,0.0,0.0 +0,0.147600,0.0,0.0,0.0,0.0,0.0 +0,0.147700,0.0,0.0,0.0,0.0,0.0 +0,0.147800,0.0,0.0,0.0,0.0,0.0 +0,0.147900,0.0,0.0,0.0,0.0,0.0 +0,0.148000,0.0,0.0,0.0,0.0,0.0 +0,0.148100,0.0,0.0,0.0,0.0,0.0 +0,0.148200,0.0,0.0,0.0,0.0,0.0 +0,0.148300,0.0,0.0,0.0,0.0,0.0 +0,0.148400,0.0,0.0,0.0,0.0,0.0 +0,0.148500,0.0,0.0,0.0,0.0,0.0 +0,0.148600,0.0,0.0,0.0,0.0,0.0 +0,0.148700,0.0,0.0,0.0,0.0,0.0 +0,0.148800,0.0,0.0,0.0,0.0,0.0 +0,0.148900,0.0,0.0,0.0,0.0,0.0 +0,0.149000,0.0,0.0,0.0,0.0,0.0 +0,0.149100,0.0,0.0,0.0,0.0,0.0 +0,0.149200,0.0,0.0,0.0,0.0,0.0 +0,0.149300,0.0,0.0,0.0,0.0,0.0 +0,0.149400,0.0,0.0,0.0,0.0,0.0 +0,0.149500,0.0,0.0,0.0,0.0,0.0 +0,0.149600,0.0,0.0,0.0,0.0,0.0 +0,0.149700,0.0,0.0,0.0,0.0,0.0 +0,0.149800,0.0,0.0,0.0,0.0,0.0 +0,0.149900,0.0,0.0,0.0,0.0,0.0 +0,0.150000,0.0,0.0,0.0,0.0,0.0 +0,0.150100,0.0,0.0,0.0,0.0,0.0 +0,0.150200,0.0,0.0,0.0,0.0,0.0 +0,0.150300,0.0,0.0,0.0,0.0,0.0 +0,0.150400,0.0,0.0,0.0,0.0,0.0 +0,0.150500,0.0,0.0,0.0,0.0,0.0 +0,0.150600,0.0,0.0,0.0,0.0,0.0 +0,0.150700,0.0,0.0,0.0,0.0,0.0 +0,0.150800,0.0,0.0,0.0,0.0,0.0 +0,0.150900,0.0,0.0,0.0,0.0,0.0 +0,0.151000,0.0,0.0,0.0,0.0,0.0 +0,0.151100,0.0,0.0,0.0,0.0,0.0 +0,0.151200,0.0,0.0,0.0,0.0,0.0 +0,0.151300,0.0,0.0,0.0,0.0,0.0 +0,0.151400,0.0,0.0,0.0,0.0,0.0 +0,0.151500,0.0,0.0,0.0,0.0,0.0 +0,0.151600,0.0,0.0,0.0,0.0,0.0 +0,0.151700,0.0,0.0,0.0,0.0,0.0 +0,0.151800,0.0,0.0,0.0,0.0,0.0 +0,0.151900,0.0,0.0,0.0,0.0,0.0 +0,0.152000,0.0,0.0,0.0,0.0,0.0 +0,0.152100,0.0,0.0,0.0,0.0,0.0 +0,0.152200,0.0,0.0,0.0,0.0,0.0 +0,0.152300,0.0,0.0,0.0,0.0,0.0 +0,0.152400,0.0,0.0,0.0,0.0,0.0 +0,0.152500,0.0,0.0,0.0,0.0,0.0 +0,0.152600,0.0,0.0,0.0,0.0,0.0 +0,0.152700,0.0,0.0,0.0,0.0,0.0 +0,0.152800,0.0,0.0,0.0,0.0,0.0 +0,0.152900,0.0,0.0,0.0,0.0,0.0 +0,0.153000,0.0,0.0,0.0,0.0,0.0 +0,0.153100,0.0,0.0,0.0,0.0,0.0 +0,0.153200,0.0,0.0,0.0,0.0,0.0 +0,0.153300,0.0,0.0,0.0,0.0,0.0 +0,0.153400,0.0,0.0,0.0,0.0,0.0 +0,0.153500,0.0,0.0,0.0,0.0,0.0 +0,0.153600,0.0,0.0,0.0,0.0,0.0 +0,0.153700,0.0,0.0,0.0,0.0,0.0 +0,0.153800,0.0,0.0,0.0,0.0,0.0 +0,0.153900,0.0,0.0,0.0,0.0,0.0 +0,0.154000,0.0,0.0,0.0,0.0,0.0 +0,0.154100,0.0,0.0,0.0,0.0,0.0 +0,0.154200,0.0,0.0,0.0,0.0,0.0 +0,0.154300,0.0,0.0,0.0,0.0,0.0 +0,0.154400,0.0,0.0,0.0,0.0,0.0 +0,0.154500,0.0,0.0,0.0,0.0,0.0 +0,0.154600,0.0,0.0,0.0,0.0,0.0 +0,0.154700,0.0,0.0,0.0,0.0,0.0 +0,0.154800,0.0,0.0,0.0,0.0,0.0 +0,0.154900,0.0,0.0,0.0,0.0,0.0 +0,0.155000,0.0,0.0,0.0,0.0,0.0 +0,0.155100,0.0,0.0,0.0,0.0,0.0 +0,0.155200,0.0,0.0,0.0,0.0,0.0 +0,0.155300,0.0,0.0,0.0,0.0,0.0 +0,0.155400,0.0,0.0,0.0,0.0,0.0 +0,0.155500,0.0,0.0,0.0,0.0,0.0 +0,0.155600,0.0,0.0,0.0,0.0,0.0 +0,0.155700,0.0,0.0,0.0,0.0,0.0 +0,0.155800,0.0,0.0,0.0,0.0,0.0 +0,0.155900,0.0,0.0,0.0,0.0,0.0 +0,0.156000,0.0,0.0,0.0,0.0,0.0 +0,0.156100,0.0,0.0,0.0,0.0,0.0 +0,0.156200,0.0,0.0,0.0,0.0,0.0 +0,0.156300,0.0,0.0,0.0,0.0,0.0 +0,0.156400,0.0,0.0,0.0,0.0,0.0 +0,0.156500,0.0,0.0,0.0,0.0,0.0 +0,0.156600,0.0,0.0,0.0,0.0,0.0 +0,0.156700,0.0,0.0,0.0,0.0,0.0 +0,0.156800,0.0,0.0,0.0,0.0,0.0 +0,0.156900,0.0,0.0,0.0,0.0,0.0 +0,0.157000,0.0,0.0,0.0,0.0,0.0 +0,0.157100,0.0,0.0,0.0,0.0,0.0 +0,0.157200,0.0,0.0,0.0,0.0,0.0 +0,0.157300,0.0,0.0,0.0,0.0,0.0 +0,0.157400,0.0,0.0,0.0,0.0,0.0 +0,0.157500,0.0,0.0,0.0,0.0,0.0 +0,0.157600,0.0,0.0,0.0,0.0,0.0 +0,0.157700,0.0,0.0,0.0,0.0,0.0 +0,0.157800,0.0,0.0,0.0,0.0,0.0 +0,0.157900,0.0,0.0,0.0,0.0,0.0 +0,0.158000,0.0,0.0,0.0,0.0,0.0 +0,0.158100,0.0,0.0,0.0,0.0,0.0 +0,0.158200,0.0,0.0,0.0,0.0,0.0 +0,0.158300,0.0,0.0,0.0,0.0,0.0 +0,0.158400,0.0,0.0,0.0,0.0,0.0 +0,0.158500,0.0,0.0,0.0,0.0,0.0 +0,0.158600,0.0,0.0,0.0,0.0,0.0 +0,0.158700,0.0,0.0,0.0,0.0,0.0 +0,0.158800,0.0,0.0,0.0,0.0,0.0 +0,0.158900,0.0,0.0,0.0,0.0,0.0 +0,0.159000,0.0,0.0,0.0,0.0,0.0 +0,0.159100,0.0,0.0,0.0,0.0,0.0 +0,0.159200,0.0,0.0,0.0,0.0,0.0 +0,0.159300,0.0,0.0,0.0,0.0,0.0 +0,0.159400,0.0,0.0,0.0,0.0,0.0 +0,0.159500,0.0,0.0,0.0,0.0,0.0 +0,0.159600,0.0,0.0,0.0,0.0,0.0 +0,0.159700,0.0,0.0,0.0,0.0,0.0 +0,0.159800,0.0,0.0,0.0,0.0,0.0 +0,0.159900,0.0,0.0,0.0,0.0,0.0 +0,0.160000,0.0,0.0,0.0,0.0,0.0 +0,0.160100,0.0,0.0,0.0,0.0,0.0 +1,1.711471,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.160200,0.0,0.0,0.0,0.0,0.0 +0,0.160300,0.0,0.0,0.0,0.0,0.0 +0,0.160400,0.0,0.0,0.0,0.0,0.0 +0,0.160500,0.0,0.0,0.0,0.0,0.0 +0,0.160600,0.0,0.0,0.0,0.0,0.0 +0,0.160700,0.0,0.0,0.0,0.0,0.0 +0,0.160800,0.0,0.0,0.0,0.0,0.0 +0,0.160900,0.0,0.0,0.0,0.0,0.0 +0,0.161000,0.0,0.0,0.0,0.0,0.0 +0,0.161100,0.0,0.0,0.0,0.0,0.0 +0,0.161200,0.0,0.0,0.0,0.0,0.0 +0,0.161300,0.0,0.0,0.0,0.0,0.0 +0,0.161400,0.0,0.0,0.0,0.0,0.0 +0,0.161500,0.0,0.0,0.0,0.0,0.0 +0,0.161600,0.0,0.0,0.0,0.0,0.0 +0,0.161700,0.0,0.0,0.0,0.0,0.0 +0,0.161800,0.0,0.0,0.0,0.0,0.0 +0,0.161900,0.0,0.0,0.0,0.0,0.0 +0,0.162000,0.0,0.0,0.0,0.0,0.0 +0,0.162100,0.0,0.0,0.0,0.0,0.0 +0,0.162200,0.0,0.0,0.0,0.0,0.0 +0,0.162300,0.0,0.0,0.0,0.0,0.0 +0,0.162400,0.0,0.0,0.0,0.0,0.0 +0,0.162500,0.0,0.0,0.0,0.0,0.0 +0,0.162600,0.0,0.0,0.0,0.0,0.0 +0,0.162700,0.0,0.0,0.0,0.0,0.0 +0,0.162800,0.0,0.0,0.0,0.0,0.0 +0,0.162900,0.0,0.0,0.0,0.0,0.0 +0,0.163000,0.0,0.0,0.0,0.0,0.0 +0,0.163100,0.0,0.0,0.0,0.0,0.0 +0,0.163200,0.0,0.0,0.0,0.0,0.0 +0,0.163300,0.0,0.0,0.0,0.0,0.0 +0,0.163400,0.0,0.0,0.0,0.0,0.0 +0,0.163500,0.0,0.0,0.0,0.0,0.0 +0,0.163600,0.0,0.0,0.0,0.0,0.0 +0,0.163700,0.0,0.0,0.0,0.0,0.0 +0,0.163800,0.0,0.0,0.0,0.0,0.0 +0,0.163900,0.0,0.0,0.0,0.0,0.0 +0,0.164000,0.0,0.0,0.0,0.0,0.0 +0,0.164100,0.0,0.0,0.0,0.0,0.0 +0,0.164200,0.0,0.0,0.0,0.0,0.0 +0,0.164300,0.0,0.0,0.0,0.0,0.0 +0,0.164400,0.0,0.0,0.0,0.0,0.0 +0,0.164500,0.0,0.0,0.0,0.0,0.0 +0,0.164600,0.0,0.0,0.0,0.0,0.0 +0,0.164700,0.0,0.0,0.0,0.0,0.0 +0,0.164800,0.0,0.0,0.0,0.0,0.0 +0,0.164900,0.0,0.0,0.0,0.0,0.0 +0,0.165000,0.0,0.0,0.0,0.0,0.0 +0,0.165100,0.0,0.0,0.0,0.0,0.0 +0,0.165200,0.0,0.0,0.0,0.0,0.0 +0,0.165300,0.0,0.0,0.0,0.0,0.0 +0,0.165400,0.0,0.0,0.0,0.0,0.0 +0,0.165500,0.0,0.0,0.0,0.0,0.0 +0,0.165600,0.0,0.0,0.0,0.0,0.0 +0,0.165700,0.0,0.0,0.0,0.0,0.0 +0,0.165800,0.0,0.0,0.0,0.0,0.0 +0,0.165900,0.0,0.0,0.0,0.0,0.0 +0,0.166000,0.0,0.0,0.0,0.0,0.0 +0,0.166100,0.0,0.0,0.0,0.0,0.0 +0,0.166200,0.0,0.0,0.0,0.0,0.0 +0,0.166300,0.0,0.0,0.0,0.0,0.0 +0,0.166400,0.0,0.0,0.0,0.0,0.0 +0,0.166500,0.0,0.0,0.0,0.0,0.0 +0,0.166600,0.0,0.0,0.0,0.0,0.0 +0,0.166700,0.0,0.0,0.0,0.0,0.0 +0,0.166800,0.0,0.0,0.0,0.0,0.0 +0,0.166900,0.0,0.0,0.0,0.0,0.0 +0,0.167000,0.0,0.0,0.0,0.0,0.0 +0,0.167100,0.0,0.0,0.0,0.0,0.0 +0,0.167200,0.0,0.0,0.0,0.0,0.0 +0,0.167300,0.0,0.0,0.0,0.0,0.0 +0,0.167400,0.0,0.0,0.0,0.0,0.0 +0,0.167500,0.0,0.0,0.0,0.0,0.0 +0,0.167600,0.0,0.0,0.0,0.0,0.0 +0,0.167700,0.0,0.0,0.0,0.0,0.0 +0,0.167800,0.0,0.0,0.0,0.0,0.0 +0,0.167900,0.0,0.0,0.0,0.0,0.0 +0,0.168000,0.0,0.0,0.0,0.0,0.0 +0,0.168100,0.0,0.0,0.0,0.0,0.0 +0,0.168200,0.0,0.0,0.0,0.0,0.0 +0,0.168300,0.0,0.0,0.0,0.0,0.0 +0,0.168400,0.0,0.0,0.0,0.0,0.0 +0,0.168500,0.0,0.0,0.0,0.0,0.0 +0,0.168600,0.0,0.0,0.0,0.0,0.0 +0,0.168700,0.0,0.0,0.0,0.0,0.0 +0,0.168800,0.0,0.0,0.0,0.0,0.0 +0,0.168900,0.0,0.0,0.0,0.0,0.0 +0,0.169000,0.0,0.0,0.0,0.0,0.0 +0,0.169100,0.0,0.0,0.0,0.0,0.0 +0,0.169200,0.0,0.0,0.0,0.0,0.0 +0,0.169300,0.0,0.0,0.0,0.0,0.0 +0,0.169400,0.0,0.0,0.0,0.0,0.0 +0,0.169500,0.0,0.0,0.0,0.0,0.0 +0,0.169600,0.0,0.0,0.0,0.0,0.0 +0,0.169700,0.0,0.0,0.0,0.0,0.0 +0,0.169800,0.0,0.0,0.0,0.0,0.0 +0,0.169900,0.0,0.0,0.0,0.0,0.0 +0,0.170000,0.0,0.0,0.0,0.0,0.0 +0,0.170100,0.0,0.0,0.0,0.0,0.0 +0,0.170200,0.0,0.0,0.0,0.0,0.0 +0,0.170300,0.0,0.0,0.0,0.0,0.0 +0,0.170400,0.0,0.0,0.0,0.0,0.0 +0,0.170500,0.0,0.0,0.0,0.0,0.0 +0,0.170600,0.0,0.0,0.0,0.0,0.0 +0,0.170700,0.0,0.0,0.0,0.0,0.0 +0,0.170800,0.0,0.0,0.0,0.0,0.0 +0,0.170900,0.0,0.0,0.0,0.0,0.0 +0,0.171000,0.0,0.0,0.0,0.0,0.0 +0,0.171100,0.0,0.0,0.0,0.0,0.0 +0,0.171200,0.0,0.0,0.0,0.0,0.0 +0,0.171300,0.0,0.0,0.0,0.0,0.0 +0,0.171400,0.0,0.0,0.0,0.0,0.0 +0,0.171500,0.0,0.0,0.0,0.0,0.0 +0,0.171600,0.0,0.0,0.0,0.0,0.0 +0,0.171700,0.0,0.0,0.0,0.0,0.0 +0,0.171800,0.0,0.0,0.0,0.0,0.0 +0,0.171900,0.0,0.0,0.0,0.0,0.0 +0,0.172000,0.0,0.0,0.0,0.0,0.0 +0,0.172100,0.0,0.0,0.0,0.0,0.0 +0,0.172200,0.0,0.0,0.0,0.0,0.0 +0,0.172300,0.0,0.0,0.0,0.0,0.0 +0,0.172400,0.0,0.0,0.0,0.0,0.0 +0,0.172500,0.0,0.0,0.0,0.0,0.0 +0,0.172600,0.0,0.0,0.0,0.0,0.0 +0,0.172700,0.0,0.0,0.0,0.0,0.0 +0,0.172800,0.0,0.0,0.0,0.0,0.0 +0,0.172900,0.0,0.0,0.0,0.0,0.0 +0,0.173000,0.0,0.0,0.0,0.0,0.0 +0,0.173100,0.0,0.0,0.0,0.0,0.0 +0,0.173200,0.0,0.0,0.0,0.0,0.0 +0,0.173300,0.0,0.0,0.0,0.0,0.0 +0,0.173400,0.0,0.0,0.0,0.0,0.0 +0,0.173500,0.0,0.0,0.0,0.0,0.0 +0,0.173600,0.0,0.0,0.0,0.0,0.0 +0,0.173700,0.0,0.0,0.0,0.0,0.0 +0,0.173800,0.0,0.0,0.0,0.0,0.0 +0,0.173900,0.0,0.0,0.0,0.0,0.0 +0,0.174000,0.0,0.0,0.0,0.0,0.0 +0,0.174100,0.0,0.0,0.0,0.0,0.0 +0,0.174200,0.0,0.0,0.0,0.0,0.0 +0,0.174300,0.0,0.0,0.0,0.0,0.0 +0,0.174400,0.0,0.0,0.0,0.0,0.0 +0,0.174500,0.0,0.0,0.0,0.0,0.0 +0,0.174600,0.0,0.0,0.0,0.0,0.0 +0,0.174700,0.0,0.0,0.0,0.0,0.0 +0,0.174800,0.0,0.0,0.0,0.0,0.0 +0,0.174900,0.0,0.0,0.0,0.0,0.0 +0,0.175000,0.0,0.0,0.0,0.0,0.0 +0,0.175100,0.0,0.0,0.0,0.0,0.0 +0,0.175200,0.0,0.0,0.0,0.0,0.0 +0,0.175300,0.0,0.0,0.0,0.0,0.0 +0,0.175400,0.0,0.0,0.0,0.0,0.0 +0,0.175500,0.0,0.0,0.0,0.0,0.0 +0,0.175600,0.0,0.0,0.0,0.0,0.0 +0,0.175700,0.0,0.0,0.0,0.0,0.0 +0,0.175800,0.0,0.0,0.0,0.0,0.0 +0,0.175900,0.0,0.0,0.0,0.0,0.0 +0,0.176000,0.0,0.0,0.0,0.0,0.0 +0,0.176100,0.0,0.0,0.0,0.0,0.0 +0,0.176200,0.0,0.0,0.0,0.0,0.0 +0,0.176300,0.0,0.0,0.0,0.0,0.0 +0,0.176400,0.0,0.0,0.0,0.0,0.0 +0,0.176500,0.0,0.0,0.0,0.0,0.0 +0,0.176600,0.0,0.0,0.0,0.0,0.0 +0,0.176700,0.0,0.0,0.0,0.0,0.0 +0,0.176800,0.0,0.0,0.0,0.0,0.0 +0,0.176900,0.0,0.0,0.0,0.0,0.0 +0,0.177000,0.0,0.0,0.0,0.0,0.0 +0,0.177100,0.0,0.0,0.0,0.0,0.0 +0,0.177200,0.0,0.0,0.0,0.0,0.0 +0,0.177300,0.0,0.0,0.0,0.0,0.0 +0,0.177400,0.0,0.0,0.0,0.0,0.0 +0,0.177500,0.0,0.0,0.0,0.0,0.0 +0,0.177600,0.0,0.0,0.0,0.0,0.0 +0,0.177700,0.0,0.0,0.0,0.0,0.0 +0,0.177800,0.0,0.0,0.0,0.0,0.0 +0,0.177900,0.0,0.0,0.0,0.0,0.0 +0,0.178000,0.0,0.0,0.0,0.0,0.0 +0,0.178100,0.0,0.0,0.0,0.0,0.0 +0,0.178200,0.0,0.0,0.0,0.0,0.0 +0,0.178300,0.0,0.0,0.0,0.0,0.0 +0,0.178400,0.0,0.0,0.0,0.0,0.0 +0,0.178500,0.0,0.0,0.0,0.0,0.0 +0,0.178600,0.0,0.0,0.0,0.0,0.0 +0,0.178700,0.0,0.0,0.0,0.0,0.0 +0,0.178800,0.0,0.0,0.0,0.0,0.0 +0,0.178900,0.0,0.0,0.0,0.0,0.0 +0,0.179000,0.0,0.0,0.0,0.0,0.0 +0,0.179100,0.0,0.0,0.0,0.0,0.0 +0,0.179200,0.0,0.0,0.0,0.0,0.0 +0,0.179300,0.0,0.0,0.0,0.0,0.0 +0,0.179400,0.0,0.0,0.0,0.0,0.0 +0,0.179500,0.0,0.0,0.0,0.0,0.0 +0,0.179600,0.0,0.0,0.0,0.0,0.0 +0,0.179700,0.0,0.0,0.0,0.0,0.0 +0,0.179800,0.0,0.0,0.0,0.0,0.0 +0,0.179900,0.0,0.0,0.0,0.0,0.0 +0,0.180000,0.0,0.0,0.0,0.0,0.0 +0,0.180100,0.0,0.0,0.0,0.0,0.0 +1,2.436080,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.180200,0.0,0.0,0.0,0.0,0.0 +0,0.180300,0.0,0.0,0.0,0.0,0.0 +0,0.180400,0.0,0.0,0.0,0.0,0.0 +0,0.180500,0.0,0.0,0.0,0.0,0.0 +0,0.180600,0.0,0.0,0.0,0.0,0.0 +0,0.180700,0.0,0.0,0.0,0.0,0.0 +0,0.180800,0.0,0.0,0.0,0.0,0.0 +0,0.180900,0.0,0.0,0.0,0.0,0.0 +0,0.181000,0.0,0.0,0.0,0.0,0.0 +0,0.181100,0.0,0.0,0.0,0.0,0.0 +0,0.181200,0.0,0.0,0.0,0.0,0.0 +0,0.181300,0.0,0.0,0.0,0.0,0.0 +0,0.181400,0.0,0.0,0.0,0.0,0.0 +0,0.181500,0.0,0.0,0.0,0.0,0.0 +0,0.181600,0.0,0.0,0.0,0.0,0.0 +0,0.181700,0.0,0.0,0.0,0.0,0.0 +0,0.181800,0.0,0.0,0.0,0.0,0.0 +0,0.181900,0.0,0.0,0.0,0.0,0.0 +0,0.182000,0.0,0.0,0.0,0.0,0.0 +0,0.182100,0.0,0.0,0.0,0.0,0.0 +0,0.182200,0.0,0.0,0.0,0.0,0.0 +0,0.182300,0.0,0.0,0.0,0.0,0.0 +0,0.182400,0.0,0.0,0.0,0.0,0.0 +0,0.182500,0.0,0.0,0.0,0.0,0.0 +0,0.182600,0.0,0.0,0.0,0.0,0.0 +0,0.182700,0.0,0.0,0.0,0.0,0.0 +0,0.182800,0.0,0.0,0.0,0.0,0.0 +0,0.182900,0.0,0.0,0.0,0.0,0.0 +0,0.183000,0.0,0.0,0.0,0.0,0.0 +0,0.183100,0.0,0.0,0.0,0.0,0.0 +0,0.183200,0.0,0.0,0.0,0.0,0.0 +0,0.183300,0.0,0.0,0.0,0.0,0.0 +0,0.183400,0.0,0.0,0.0,0.0,0.0 +0,0.183500,0.0,0.0,0.0,0.0,0.0 +0,0.183600,0.0,0.0,0.0,0.0,0.0 +0,0.183700,0.0,0.0,0.0,0.0,0.0 +0,0.183800,0.0,0.0,0.0,0.0,0.0 +0,0.183900,0.0,0.0,0.0,0.0,0.0 +0,0.184000,0.0,0.0,0.0,0.0,0.0 +0,0.184100,0.0,0.0,0.0,0.0,0.0 +0,0.184200,0.0,0.0,0.0,0.0,0.0 +0,0.184300,0.0,0.0,0.0,0.0,0.0 +0,0.184400,0.0,0.0,0.0,0.0,0.0 +0,0.184500,0.0,0.0,0.0,0.0,0.0 +0,0.184600,0.0,0.0,0.0,0.0,0.0 +0,0.184700,0.0,0.0,0.0,0.0,0.0 +0,0.184800,0.0,0.0,0.0,0.0,0.0 +0,0.184900,0.0,0.0,0.0,0.0,0.0 +0,0.185000,0.0,0.0,0.0,0.0,0.0 +0,0.185100,0.0,0.0,0.0,0.0,0.0 +0,0.185200,0.0,0.0,0.0,0.0,0.0 +0,0.185300,0.0,0.0,0.0,0.0,0.0 +0,0.185400,0.0,0.0,0.0,0.0,0.0 +0,0.185500,0.0,0.0,0.0,0.0,0.0 +0,0.185600,0.0,0.0,0.0,0.0,0.0 +0,0.185700,0.0,0.0,0.0,0.0,0.0 +0,0.185800,0.0,0.0,0.0,0.0,0.0 +0,0.185900,0.0,0.0,0.0,0.0,0.0 +0,0.186000,0.0,0.0,0.0,0.0,0.0 +0,0.186100,0.0,0.0,0.0,0.0,0.0 +0,0.186200,0.0,0.0,0.0,0.0,0.0 +0,0.186300,0.0,0.0,0.0,0.0,0.0 +0,0.186400,0.0,0.0,0.0,0.0,0.0 +0,0.186500,0.0,0.0,0.0,0.0,0.0 +0,0.186600,0.0,0.0,0.0,0.0,0.0 +0,0.186700,0.0,0.0,0.0,0.0,0.0 +0,0.186800,0.0,0.0,0.0,0.0,0.0 +0,0.186900,0.0,0.0,0.0,0.0,0.0 +0,0.187000,0.0,0.0,0.0,0.0,0.0 +0,0.187100,0.0,0.0,0.0,0.0,0.0 +0,0.187200,0.0,0.0,0.0,0.0,0.0 +0,0.187300,0.0,0.0,0.0,0.0,0.0 +0,0.187400,0.0,0.0,0.0,0.0,0.0 +0,0.187500,0.0,0.0,0.0,0.0,0.0 +0,0.187600,0.0,0.0,0.0,0.0,0.0 +0,0.187700,0.0,0.0,0.0,0.0,0.0 +0,0.187800,0.0,0.0,0.0,0.0,0.0 +0,0.187900,0.0,0.0,0.0,0.0,0.0 +0,0.188000,0.0,0.0,0.0,0.0,0.0 +0,0.188100,0.0,0.0,0.0,0.0,0.0 +0,0.188200,0.0,0.0,0.0,0.0,0.0 +0,0.188300,0.0,0.0,0.0,0.0,0.0 +0,0.188400,0.0,0.0,0.0,0.0,0.0 +0,0.188500,0.0,0.0,0.0,0.0,0.0 +0,0.188600,0.0,0.0,0.0,0.0,0.0 +0,0.188700,0.0,0.0,0.0,0.0,0.0 +0,0.188800,0.0,0.0,0.0,0.0,0.0 +0,0.188900,0.0,0.0,0.0,0.0,0.0 +0,0.189000,0.0,0.0,0.0,0.0,0.0 +0,0.189100,0.0,0.0,0.0,0.0,0.0 +0,0.189200,0.0,0.0,0.0,0.0,0.0 +0,0.189300,0.0,0.0,0.0,0.0,0.0 +0,0.189400,0.0,0.0,0.0,0.0,0.0 +0,0.189500,0.0,0.0,0.0,0.0,0.0 +0,0.189600,0.0,0.0,0.0,0.0,0.0 +0,0.189700,0.0,0.0,0.0,0.0,0.0 +0,0.189800,0.0,0.0,0.0,0.0,0.0 +0,0.189900,0.0,0.0,0.0,0.0,0.0 +0,0.190000,0.0,0.0,0.0,0.0,0.0 +0,0.190100,0.0,0.0,0.0,0.0,0.0 +0,0.190200,0.0,0.0,0.0,0.0,0.0 +0,0.190300,0.0,0.0,0.0,0.0,0.0 +0,0.190400,0.0,0.0,0.0,0.0,0.0 +0,0.190500,0.0,0.0,0.0,0.0,0.0 +0,0.190600,0.0,0.0,0.0,0.0,0.0 +0,0.190700,0.0,0.0,0.0,0.0,0.0 +0,0.190800,0.0,0.0,0.0,0.0,0.0 +0,0.190900,0.0,0.0,0.0,0.0,0.0 +0,0.191000,0.0,0.0,0.0,0.0,0.0 +0,0.191100,0.0,0.0,0.0,0.0,0.0 +0,0.191200,0.0,0.0,0.0,0.0,0.0 +0,0.191300,0.0,0.0,0.0,0.0,0.0 +0,0.191400,0.0,0.0,0.0,0.0,0.0 +0,0.191500,0.0,0.0,0.0,0.0,0.0 +0,0.191600,0.0,0.0,0.0,0.0,0.0 +0,0.191700,0.0,0.0,0.0,0.0,0.0 +0,0.191800,0.0,0.0,0.0,0.0,0.0 +0,0.191900,0.0,0.0,0.0,0.0,0.0 +0,0.192000,0.0,0.0,0.0,0.0,0.0 +0,0.192100,0.0,0.0,0.0,0.0,0.0 +0,0.192200,0.0,0.0,0.0,0.0,0.0 +0,0.192300,0.0,0.0,0.0,0.0,0.0 +0,0.192400,0.0,0.0,0.0,0.0,0.0 +0,0.192500,0.0,0.0,0.0,0.0,0.0 +0,0.192600,0.0,0.0,0.0,0.0,0.0 +0,0.192700,0.0,0.0,0.0,0.0,0.0 +0,0.192800,0.0,0.0,0.0,0.0,0.0 +0,0.192900,0.0,0.0,0.0,0.0,0.0 +0,0.193000,0.0,0.0,0.0,0.0,0.0 +0,0.193100,0.0,0.0,0.0,0.0,0.0 +0,0.193200,0.0,0.0,0.0,0.0,0.0 +0,0.193300,0.0,0.0,0.0,0.0,0.0 +0,0.193400,0.0,0.0,0.0,0.0,0.0 +0,0.193500,0.0,0.0,0.0,0.0,0.0 +0,0.193600,0.0,0.0,0.0,0.0,0.0 +0,0.193700,0.0,0.0,0.0,0.0,0.0 +0,0.193800,0.0,0.0,0.0,0.0,0.0 +0,0.193900,0.0,0.0,0.0,0.0,0.0 +0,0.194000,0.0,0.0,0.0,0.0,0.0 +0,0.194100,0.0,0.0,0.0,0.0,0.0 +0,0.194200,0.0,0.0,0.0,0.0,0.0 +0,0.194300,0.0,0.0,0.0,0.0,0.0 +0,0.194400,0.0,0.0,0.0,0.0,0.0 +0,0.194500,0.0,0.0,0.0,0.0,0.0 +0,0.194600,0.0,0.0,0.0,0.0,0.0 +0,0.194700,0.0,0.0,0.0,0.0,0.0 +0,0.194800,0.0,0.0,0.0,0.0,0.0 +0,0.194900,0.0,0.0,0.0,0.0,0.0 +0,0.195000,0.0,0.0,0.0,0.0,0.0 +0,0.195100,0.0,0.0,0.0,0.0,0.0 +0,0.195200,0.0,0.0,0.0,0.0,0.0 +0,0.195300,0.0,0.0,0.0,0.0,0.0 +0,0.195400,0.0,0.0,0.0,0.0,0.0 +0,0.195500,0.0,0.0,0.0,0.0,0.0 +0,0.195600,0.0,0.0,0.0,0.0,0.0 +0,0.195700,0.0,0.0,0.0,0.0,0.0 +0,0.195800,0.0,0.0,0.0,0.0,0.0 +0,0.195900,0.0,0.0,0.0,0.0,0.0 +0,0.196000,0.0,0.0,0.0,0.0,0.0 +0,0.196100,0.0,0.0,0.0,0.0,0.0 +0,0.196200,0.0,0.0,0.0,0.0,0.0 +0,0.196300,0.0,0.0,0.0,0.0,0.0 +0,0.196400,0.0,0.0,0.0,0.0,0.0 +0,0.196500,0.0,0.0,0.0,0.0,0.0 +0,0.196600,0.0,0.0,0.0,0.0,0.0 +0,0.196700,0.0,0.0,0.0,0.0,0.0 +0,0.196800,0.0,0.0,0.0,0.0,0.0 +0,0.196900,0.0,0.0,0.0,0.0,0.0 +0,0.197000,0.0,0.0,0.0,0.0,0.0 +0,0.197100,0.0,0.0,0.0,0.0,0.0 +0,0.197200,0.0,0.0,0.0,0.0,0.0 +0,0.197300,0.0,0.0,0.0,0.0,0.0 +0,0.197400,0.0,0.0,0.0,0.0,0.0 +0,0.197500,0.0,0.0,0.0,0.0,0.0 +0,0.197600,0.0,0.0,0.0,0.0,0.0 +0,0.197700,0.0,0.0,0.0,0.0,0.0 +0,0.197800,0.0,0.0,0.0,0.0,0.0 +0,0.197900,0.0,0.0,0.0,0.0,0.0 +0,0.198000,0.0,0.0,0.0,0.0,0.0 +0,0.198100,0.0,0.0,0.0,0.0,0.0 +0,0.198200,0.0,0.0,0.0,0.0,0.0 +0,0.198300,0.0,0.0,0.0,0.0,0.0 +0,0.198400,0.0,0.0,0.0,0.0,0.0 +0,0.198500,0.0,0.0,0.0,0.0,0.0 +0,0.198600,0.0,0.0,0.0,0.0,0.0 +0,0.198700,0.0,0.0,0.0,0.0,0.0 +0,0.198800,0.0,0.0,0.0,0.0,0.0 +0,0.198900,0.0,0.0,0.0,0.0,0.0 +0,0.199000,0.0,0.0,0.0,0.0,0.0 +0,0.199100,0.0,0.0,0.0,0.0,0.0 +0,0.199200,0.0,0.0,0.0,0.0,0.0 +0,0.199300,0.0,0.0,0.0,0.0,0.0 +0,0.199400,0.0,0.0,0.0,0.0,0.0 +0,0.199500,0.0,0.0,0.0,0.0,0.0 +0,0.199600,0.0,0.0,0.0,0.0,0.0 +0,0.199700,0.0,0.0,0.0,0.0,0.0 +0,0.199800,0.0,0.0,0.0,0.0,0.0 +0,0.199900,0.0,0.0,0.0,0.0,0.0 +0,0.200000,0.0,0.0,0.0,0.0,0.0 +0,0.200100,0.0,0.0,0.0,0.0,0.0 +1,3.340839,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.200200,0.0,0.0,0.0,0.0,0.0 +0,0.200300,0.0,0.0,0.0,0.0,0.0 +0,0.200400,0.0,0.0,0.0,0.0,0.0 +0,0.200500,0.0,0.0,0.0,0.0,0.0 +0,0.200600,0.0,0.0,0.0,0.0,0.0 +0,0.200700,0.0,0.0,0.0,0.0,0.0 +0,0.200800,0.0,0.0,0.0,0.0,0.0 +0,0.200900,0.0,0.0,0.0,0.0,0.0 +0,0.201000,0.0,0.0,0.0,0.0,0.0 +0,0.201100,0.0,0.0,0.0,0.0,0.0 +0,0.201200,0.0,0.0,0.0,0.0,0.0 +0,0.201300,0.0,0.0,0.0,0.0,0.0 +0,0.201400,0.0,0.0,0.0,0.0,0.0 +0,0.201500,0.0,0.0,0.0,0.0,0.0 +0,0.201600,0.0,0.0,0.0,0.0,0.0 +0,0.201700,0.0,0.0,0.0,0.0,0.0 +0,0.201800,0.0,0.0,0.0,0.0,0.0 +0,0.201900,0.0,0.0,0.0,0.0,0.0 +0,0.202000,0.0,0.0,0.0,0.0,0.0 +0,0.202100,0.0,0.0,0.0,0.0,0.0 +0,0.202200,0.0,0.0,0.0,0.0,0.0 +0,0.202300,0.0,0.0,0.0,0.0,0.0 +0,0.202400,0.0,0.0,0.0,0.0,0.0 +0,0.202500,0.0,0.0,0.0,0.0,0.0 +0,0.202600,0.0,0.0,0.0,0.0,0.0 +0,0.202700,0.0,0.0,0.0,0.0,0.0 +0,0.202800,0.0,0.0,0.0,0.0,0.0 +0,0.202900,0.0,0.0,0.0,0.0,0.0 +0,0.203000,0.0,0.0,0.0,0.0,0.0 +0,0.203100,0.0,0.0,0.0,0.0,0.0 +0,0.203200,0.0,0.0,0.0,0.0,0.0 +0,0.203300,0.0,0.0,0.0,0.0,0.0 +0,0.203400,0.0,0.0,0.0,0.0,0.0 +0,0.203500,0.0,0.0,0.0,0.0,0.0 +0,0.203600,0.0,0.0,0.0,0.0,0.0 +0,0.203700,0.0,0.0,0.0,0.0,0.0 +0,0.203800,0.0,0.0,0.0,0.0,0.0 +0,0.203900,0.0,0.0,0.0,0.0,0.0 +0,0.204000,0.0,0.0,0.0,0.0,0.0 +0,0.204100,0.0,0.0,0.0,0.0,0.0 +0,0.204200,0.0,0.0,0.0,0.0,0.0 +0,0.204300,0.0,0.0,0.0,0.0,0.0 +0,0.204400,0.0,0.0,0.0,0.0,0.0 +0,0.204500,0.0,0.0,0.0,0.0,0.0 +0,0.204600,0.0,0.0,0.0,0.0,0.0 +0,0.204700,0.0,0.0,0.0,0.0,0.0 +0,0.204800,0.0,0.0,0.0,0.0,0.0 +0,0.204900,0.0,0.0,0.0,0.0,0.0 +0,0.205000,0.0,0.0,0.0,0.0,0.0 +0,0.205100,0.0,0.0,0.0,0.0,0.0 +0,0.205200,0.0,0.0,0.0,0.0,0.0 +0,0.205300,0.0,0.0,0.0,0.0,0.0 +0,0.205400,0.0,0.0,0.0,0.0,0.0 +0,0.205500,0.0,0.0,0.0,0.0,0.0 +0,0.205600,0.0,0.0,0.0,0.0,0.0 +0,0.205700,0.0,0.0,0.0,0.0,0.0 +0,0.205800,0.0,0.0,0.0,0.0,0.0 +0,0.205900,0.0,0.0,0.0,0.0,0.0 +0,0.206000,0.0,0.0,0.0,0.0,0.0 +0,0.206100,0.0,0.0,0.0,0.0,0.0 +0,0.206200,0.0,0.0,0.0,0.0,0.0 +0,0.206300,0.0,0.0,0.0,0.0,0.0 +0,0.206400,0.0,0.0,0.0,0.0,0.0 +0,0.206500,0.0,0.0,0.0,0.0,0.0 +0,0.206600,0.0,0.0,0.0,0.0,0.0 +0,0.206700,0.0,0.0,0.0,0.0,0.0 +0,0.206800,0.0,0.0,0.0,0.0,0.0 +0,0.206900,0.0,0.0,0.0,0.0,0.0 +0,0.207000,0.0,0.0,0.0,0.0,0.0 +0,0.207100,0.0,0.0,0.0,0.0,0.0 +0,0.207200,0.0,0.0,0.0,0.0,0.0 +0,0.207300,0.0,0.0,0.0,0.0,0.0 +0,0.207400,0.0,0.0,0.0,0.0,0.0 +0,0.207500,0.0,0.0,0.0,0.0,0.0 +0,0.207600,0.0,0.0,0.0,0.0,0.0 +0,0.207700,0.0,0.0,0.0,0.0,0.0 +0,0.207800,0.0,0.0,0.0,0.0,0.0 +0,0.207900,0.0,0.0,0.0,0.0,0.0 +0,0.208000,0.0,0.0,0.0,0.0,0.0 +0,0.208100,0.0,0.0,0.0,0.0,0.0 +0,0.208200,0.0,0.0,0.0,0.0,0.0 +0,0.208300,0.0,0.0,0.0,0.0,0.0 +0,0.208400,0.0,0.0,0.0,0.0,0.0 +0,0.208500,0.0,0.0,0.0,0.0,0.0 +0,0.208600,0.0,0.0,0.0,0.0,0.0 +0,0.208700,0.0,0.0,0.0,0.0,0.0 +0,0.208800,0.0,0.0,0.0,0.0,0.0 +0,0.208900,0.0,0.0,0.0,0.0,0.0 +0,0.209000,0.0,0.0,0.0,0.0,0.0 +0,0.209100,0.0,0.0,0.0,0.0,0.0 +0,0.209200,0.0,0.0,0.0,0.0,0.0 +0,0.209300,0.0,0.0,0.0,0.0,0.0 +0,0.209400,0.0,0.0,0.0,0.0,0.0 +0,0.209500,0.0,0.0,0.0,0.0,0.0 +0,0.209600,0.0,0.0,0.0,0.0,0.0 +0,0.209700,0.0,0.0,0.0,0.0,0.0 +0,0.209800,0.0,0.0,0.0,0.0,0.0 +0,0.209900,0.0,0.0,0.0,0.0,0.0 +0,0.210000,0.0,0.0,0.0,0.0,0.0 +0,0.210100,0.0,0.0,0.0,0.0,0.0 +0,0.210200,0.0,0.0,0.0,0.0,0.0 +0,0.210300,0.0,0.0,0.0,0.0,0.0 +0,0.210400,0.0,0.0,0.0,0.0,0.0 +0,0.210500,0.0,0.0,0.0,0.0,0.0 +0,0.210600,0.0,0.0,0.0,0.0,0.0 +0,0.210700,0.0,0.0,0.0,0.0,0.0 +0,0.210800,0.0,0.0,0.0,0.0,0.0 +0,0.210900,0.0,0.0,0.0,0.0,0.0 +0,0.211000,0.0,0.0,0.0,0.0,0.0 +0,0.211100,0.0,0.0,0.0,0.0,0.0 +0,0.211200,0.0,0.0,0.0,0.0,0.0 +0,0.211300,0.0,0.0,0.0,0.0,0.0 +0,0.211400,0.0,0.0,0.0,0.0,0.0 +0,0.211500,0.0,0.0,0.0,0.0,0.0 +0,0.211600,0.0,0.0,0.0,0.0,0.0 +0,0.211700,0.0,0.0,0.0,0.0,0.0 +0,0.211800,0.0,0.0,0.0,0.0,0.0 +0,0.211900,0.0,0.0,0.0,0.0,0.0 +0,0.212000,0.0,0.0,0.0,0.0,0.0 +0,0.212100,0.0,0.0,0.0,0.0,0.0 +0,0.212200,0.0,0.0,0.0,0.0,0.0 +0,0.212300,0.0,0.0,0.0,0.0,0.0 +0,0.212400,0.0,0.0,0.0,0.0,0.0 +0,0.212500,0.0,0.0,0.0,0.0,0.0 +0,0.212600,0.0,0.0,0.0,0.0,0.0 +0,0.212700,0.0,0.0,0.0,0.0,0.0 +0,0.212800,0.0,0.0,0.0,0.0,0.0 +0,0.212900,0.0,0.0,0.0,0.0,0.0 +0,0.213000,0.0,0.0,0.0,0.0,0.0 +0,0.213100,0.0,0.0,0.0,0.0,0.0 +0,0.213200,0.0,0.0,0.0,0.0,0.0 +0,0.213300,0.0,0.0,0.0,0.0,0.0 +0,0.213400,0.0,0.0,0.0,0.0,0.0 +0,0.213500,0.0,0.0,0.0,0.0,0.0 +0,0.213600,0.0,0.0,0.0,0.0,0.0 +0,0.213700,0.0,0.0,0.0,0.0,0.0 +0,0.213800,0.0,0.0,0.0,0.0,0.0 +0,0.213900,0.0,0.0,0.0,0.0,0.0 +0,0.214000,0.0,0.0,0.0,0.0,0.0 +0,0.214100,0.0,0.0,0.0,0.0,0.0 +0,0.214200,0.0,0.0,0.0,0.0,0.0 +0,0.214300,0.0,0.0,0.0,0.0,0.0 +0,0.214400,0.0,0.0,0.0,0.0,0.0 +0,0.214500,0.0,0.0,0.0,0.0,0.0 +0,0.214600,0.0,0.0,0.0,0.0,0.0 +0,0.214700,0.0,0.0,0.0,0.0,0.0 +0,0.214800,0.0,0.0,0.0,0.0,0.0 +0,0.214900,0.0,0.0,0.0,0.0,0.0 +0,0.215000,0.0,0.0,0.0,0.0,0.0 +0,0.215100,0.0,0.0,0.0,0.0,0.0 +0,0.215200,0.0,0.0,0.0,0.0,0.0 +0,0.215300,0.0,0.0,0.0,0.0,0.0 +0,0.215400,0.0,0.0,0.0,0.0,0.0 +0,0.215500,0.0,0.0,0.0,0.0,0.0 +0,0.215600,0.0,0.0,0.0,0.0,0.0 +0,0.215700,0.0,0.0,0.0,0.0,0.0 +0,0.215800,0.0,0.0,0.0,0.0,0.0 +0,0.215900,0.0,0.0,0.0,0.0,0.0 +0,0.216000,0.0,0.0,0.0,0.0,0.0 +0,0.216100,0.0,0.0,0.0,0.0,0.0 +0,0.216200,0.0,0.0,0.0,0.0,0.0 +0,0.216300,0.0,0.0,0.0,0.0,0.0 +0,0.216400,0.0,0.0,0.0,0.0,0.0 +0,0.216500,0.0,0.0,0.0,0.0,0.0 +0,0.216600,0.0,0.0,0.0,0.0,0.0 +0,0.216700,0.0,0.0,0.0,0.0,0.0 +0,0.216800,0.0,0.0,0.0,0.0,0.0 +0,0.216900,0.0,0.0,0.0,0.0,0.0 +0,0.217000,0.0,0.0,0.0,0.0,0.0 +0,0.217100,0.0,0.0,0.0,0.0,0.0 +0,0.217200,0.0,0.0,0.0,0.0,0.0 +0,0.217300,0.0,0.0,0.0,0.0,0.0 +0,0.217400,0.0,0.0,0.0,0.0,0.0 +0,0.217500,0.0,0.0,0.0,0.0,0.0 +0,0.217600,0.0,0.0,0.0,0.0,0.0 +0,0.217700,0.0,0.0,0.0,0.0,0.0 +0,0.217800,0.0,0.0,0.0,0.0,0.0 +0,0.217900,0.0,0.0,0.0,0.0,0.0 +0,0.218000,0.0,0.0,0.0,0.0,0.0 +0,0.218100,0.0,0.0,0.0,0.0,0.0 +0,0.218200,0.0,0.0,0.0,0.0,0.0 +0,0.218300,0.0,0.0,0.0,0.0,0.0 +0,0.218400,0.0,0.0,0.0,0.0,0.0 +0,0.218500,0.0,0.0,0.0,0.0,0.0 +0,0.218600,0.0,0.0,0.0,0.0,0.0 +0,0.218700,0.0,0.0,0.0,0.0,0.0 +0,0.218800,0.0,0.0,0.0,0.0,0.0 +0,0.218900,0.0,0.0,0.0,0.0,0.0 +0,0.219000,0.0,0.0,0.0,0.0,0.0 +0,0.219100,0.0,0.0,0.0,0.0,0.0 +0,0.219200,0.0,0.0,0.0,0.0,0.0 +0,0.219300,0.0,0.0,0.0,0.0,0.0 +0,0.219400,0.0,0.0,0.0,0.0,0.0 +0,0.219500,0.0,0.0,0.0,0.0,0.0 +0,0.219600,0.0,0.0,0.0,0.0,0.0 +0,0.219700,0.0,0.0,0.0,0.0,0.0 +0,0.219800,0.0,0.0,0.0,0.0,0.0 +0,0.219900,0.0,0.0,0.0,0.0,0.0 +0,0.220000,0.0,0.0,0.0,0.0,0.0 +0,0.220100,0.0,0.0,0.0,0.0,0.0 +1,4.445748,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.220200,0.0,0.0,0.0,0.0,0.0 +0,0.220300,0.0,0.0,0.0,0.0,0.0 +0,0.220400,0.0,0.0,0.0,0.0,0.0 +0,0.220500,0.0,0.0,0.0,0.0,0.0 +0,0.220600,0.0,0.0,0.0,0.0,0.0 +0,0.220700,0.0,0.0,0.0,0.0,0.0 +0,0.220800,0.0,0.0,0.0,0.0,0.0 +0,0.220900,0.0,0.0,0.0,0.0,0.0 +0,0.221000,0.0,0.0,0.0,0.0,0.0 +0,0.221100,0.0,0.0,0.0,0.0,0.0 +0,0.221200,0.0,0.0,0.0,0.0,0.0 +0,0.221300,0.0,0.0,0.0,0.0,0.0 +0,0.221400,0.0,0.0,0.0,0.0,0.0 +0,0.221500,0.0,0.0,0.0,0.0,0.0 +0,0.221600,0.0,0.0,0.0,0.0,0.0 +0,0.221700,0.0,0.0,0.0,0.0,0.0 +0,0.221800,0.0,0.0,0.0,0.0,0.0 +0,0.221900,0.0,0.0,0.0,0.0,0.0 +0,0.222000,0.0,0.0,0.0,0.0,0.0 +0,0.222100,0.0,0.0,0.0,0.0,0.0 +0,0.222200,0.0,0.0,0.0,0.0,0.0 +0,0.222300,0.0,0.0,0.0,0.0,0.0 +0,0.222400,0.0,0.0,0.0,0.0,0.0 +0,0.222500,0.0,0.0,0.0,0.0,0.0 +0,0.222600,0.0,0.0,0.0,0.0,0.0 +0,0.222700,0.0,0.0,0.0,0.0,0.0 +0,0.222800,0.0,0.0,0.0,0.0,0.0 +0,0.222900,0.0,0.0,0.0,0.0,0.0 +0,0.223000,0.0,0.0,0.0,0.0,0.0 +0,0.223100,0.0,0.0,0.0,0.0,0.0 +0,0.223200,0.0,0.0,0.0,0.0,0.0 +0,0.223300,0.0,0.0,0.0,0.0,0.0 +0,0.223400,0.0,0.0,0.0,0.0,0.0 +0,0.223500,0.0,0.0,0.0,0.0,0.0 +0,0.223600,0.0,0.0,0.0,0.0,0.0 +0,0.223700,0.0,0.0,0.0,0.0,0.0 +0,0.223800,0.0,0.0,0.0,0.0,0.0 +0,0.223900,0.0,0.0,0.0,0.0,0.0 +0,0.224000,0.0,0.0,0.0,0.0,0.0 +0,0.224100,0.0,0.0,0.0,0.0,0.0 +0,0.224200,0.0,0.0,0.0,0.0,0.0 +0,0.224300,0.0,0.0,0.0,0.0,0.0 +0,0.224400,0.0,0.0,0.0,0.0,0.0 +0,0.224500,0.0,0.0,0.0,0.0,0.0 +0,0.224600,0.0,0.0,0.0,0.0,0.0 +0,0.224700,0.0,0.0,0.0,0.0,0.0 +0,0.224800,0.0,0.0,0.0,0.0,0.0 +0,0.224900,0.0,0.0,0.0,0.0,0.0 +0,0.225000,0.0,0.0,0.0,0.0,0.0 +0,0.225100,0.0,0.0,0.0,0.0,0.0 +0,0.225200,0.0,0.0,0.0,0.0,0.0 +0,0.225300,0.0,0.0,0.0,0.0,0.0 +0,0.225400,0.0,0.0,0.0,0.0,0.0 +0,0.225500,0.0,0.0,0.0,0.0,0.0 +0,0.225600,0.0,0.0,0.0,0.0,0.0 +0,0.225700,0.0,0.0,0.0,0.0,0.0 +0,0.225800,0.0,0.0,0.0,0.0,0.0 +0,0.225900,0.0,0.0,0.0,0.0,0.0 +0,0.226000,0.0,0.0,0.0,0.0,0.0 +0,0.226100,0.0,0.0,0.0,0.0,0.0 +0,0.226200,0.0,0.0,0.0,0.0,0.0 +0,0.226300,0.0,0.0,0.0,0.0,0.0 +0,0.226400,0.0,0.0,0.0,0.0,0.0 +0,0.226500,0.0,0.0,0.0,0.0,0.0 +0,0.226600,0.0,0.0,0.0,0.0,0.0 +0,0.226700,0.0,0.0,0.0,0.0,0.0 +0,0.226800,0.0,0.0,0.0,0.0,0.0 +0,0.226900,0.0,0.0,0.0,0.0,0.0 +0,0.227000,0.0,0.0,0.0,0.0,0.0 +0,0.227100,0.0,0.0,0.0,0.0,0.0 +0,0.227200,0.0,0.0,0.0,0.0,0.0 +0,0.227300,0.0,0.0,0.0,0.0,0.0 +0,0.227400,0.0,0.0,0.0,0.0,0.0 +0,0.227500,0.0,0.0,0.0,0.0,0.0 +0,0.227600,0.0,0.0,0.0,0.0,0.0 +0,0.227700,0.0,0.0,0.0,0.0,0.0 +0,0.227800,0.0,0.0,0.0,0.0,0.0 +0,0.227900,0.0,0.0,0.0,0.0,0.0 +0,0.228000,0.0,0.0,0.0,0.0,0.0 +0,0.228100,0.0,0.0,0.0,0.0,0.0 +0,0.228200,0.0,0.0,0.0,0.0,0.0 +0,0.228300,0.0,0.0,0.0,0.0,0.0 +0,0.228400,0.0,0.0,0.0,0.0,0.0 +0,0.228500,0.0,0.0,0.0,0.0,0.0 +0,0.228600,0.0,0.0,0.0,0.0,0.0 +0,0.228700,0.0,0.0,0.0,0.0,0.0 +0,0.228800,0.0,0.0,0.0,0.0,0.0 +0,0.228900,0.0,0.0,0.0,0.0,0.0 +0,0.229000,0.0,0.0,0.0,0.0,0.0 +0,0.229100,0.0,0.0,0.0,0.0,0.0 +0,0.229200,0.0,0.0,0.0,0.0,0.0 +0,0.229300,0.0,0.0,0.0,0.0,0.0 +0,0.229400,0.0,0.0,0.0,0.0,0.0 +0,0.229500,0.0,0.0,0.0,0.0,0.0 +0,0.229600,0.0,0.0,0.0,0.0,0.0 +0,0.229700,0.0,0.0,0.0,0.0,0.0 +0,0.229800,0.0,0.0,0.0,0.0,0.0 +0,0.229900,0.0,0.0,0.0,0.0,0.0 +0,0.230000,0.0,0.0,0.0,0.0,0.0 +0,0.230100,0.0,0.0,0.0,0.0,0.0 +0,0.230200,0.0,0.0,0.0,0.0,0.0 +0,0.230300,0.0,0.0,0.0,0.0,0.0 +0,0.230400,0.0,0.0,0.0,0.0,0.0 +0,0.230500,0.0,0.0,0.0,0.0,0.0 +0,0.230600,0.0,0.0,0.0,0.0,0.0 +0,0.230700,0.0,0.0,0.0,0.0,0.0 +0,0.230800,0.0,0.0,0.0,0.0,0.0 +0,0.230900,0.0,0.0,0.0,0.0,0.0 +0,0.231000,0.0,0.0,0.0,0.0,0.0 +0,0.231100,0.0,0.0,0.0,0.0,0.0 +0,0.231200,0.0,0.0,0.0,0.0,0.0 +0,0.231300,0.0,0.0,0.0,0.0,0.0 +0,0.231400,0.0,0.0,0.0,0.0,0.0 +0,0.231500,0.0,0.0,0.0,0.0,0.0 +0,0.231600,0.0,0.0,0.0,0.0,0.0 +0,0.231700,0.0,0.0,0.0,0.0,0.0 +0,0.231800,0.0,0.0,0.0,0.0,0.0 +0,0.231900,0.0,0.0,0.0,0.0,0.0 +0,0.232000,0.0,0.0,0.0,0.0,0.0 +0,0.232100,0.0,0.0,0.0,0.0,0.0 +0,0.232200,0.0,0.0,0.0,0.0,0.0 +0,0.232300,0.0,0.0,0.0,0.0,0.0 +0,0.232400,0.0,0.0,0.0,0.0,0.0 +0,0.232500,0.0,0.0,0.0,0.0,0.0 +0,0.232600,0.0,0.0,0.0,0.0,0.0 +0,0.232700,0.0,0.0,0.0,0.0,0.0 +0,0.232800,0.0,0.0,0.0,0.0,0.0 +0,0.232900,0.0,0.0,0.0,0.0,0.0 +0,0.233000,0.0,0.0,0.0,0.0,0.0 +0,0.233100,0.0,0.0,0.0,0.0,0.0 +0,0.233200,0.0,0.0,0.0,0.0,0.0 +0,0.233300,0.0,0.0,0.0,0.0,0.0 +0,0.233400,0.0,0.0,0.0,0.0,0.0 +0,0.233500,0.0,0.0,0.0,0.0,0.0 +0,0.233600,0.0,0.0,0.0,0.0,0.0 +0,0.233700,0.0,0.0,0.0,0.0,0.0 +0,0.233800,0.0,0.0,0.0,0.0,0.0 +0,0.233900,0.0,0.0,0.0,0.0,0.0 +0,0.234000,0.0,0.0,0.0,0.0,0.0 +0,0.234100,0.0,0.0,0.0,0.0,0.0 +0,0.234200,0.0,0.0,0.0,0.0,0.0 +0,0.234300,0.0,0.0,0.0,0.0,0.0 +0,0.234400,0.0,0.0,0.0,0.0,0.0 +0,0.234500,0.0,0.0,0.0,0.0,0.0 +0,0.234600,0.0,0.0,0.0,0.0,0.0 +0,0.234700,0.0,0.0,0.0,0.0,0.0 +0,0.234800,0.0,0.0,0.0,0.0,0.0 +0,0.234900,0.0,0.0,0.0,0.0,0.0 +0,0.235000,0.0,0.0,0.0,0.0,0.0 +0,0.235100,0.0,0.0,0.0,0.0,0.0 +0,0.235200,0.0,0.0,0.0,0.0,0.0 +0,0.235300,0.0,0.0,0.0,0.0,0.0 +0,0.235400,0.0,0.0,0.0,0.0,0.0 +0,0.235500,0.0,0.0,0.0,0.0,0.0 +0,0.235600,0.0,0.0,0.0,0.0,0.0 +0,0.235700,0.0,0.0,0.0,0.0,0.0 +0,0.235800,0.0,0.0,0.0,0.0,0.0 +0,0.235900,0.0,0.0,0.0,0.0,0.0 +0,0.236000,0.0,0.0,0.0,0.0,0.0 +0,0.236100,0.0,0.0,0.0,0.0,0.0 +0,0.236200,0.0,0.0,0.0,0.0,0.0 +0,0.236300,0.0,0.0,0.0,0.0,0.0 +0,0.236400,0.0,0.0,0.0,0.0,0.0 +0,0.236500,0.0,0.0,0.0,0.0,0.0 +0,0.236600,0.0,0.0,0.0,0.0,0.0 +0,0.236700,0.0,0.0,0.0,0.0,0.0 +0,0.236800,0.0,0.0,0.0,0.0,0.0 +0,0.236900,0.0,0.0,0.0,0.0,0.0 +0,0.237000,0.0,0.0,0.0,0.0,0.0 +0,0.237100,0.0,0.0,0.0,0.0,0.0 +0,0.237200,0.0,0.0,0.0,0.0,0.0 +0,0.237300,0.0,0.0,0.0,0.0,0.0 +0,0.237400,0.0,0.0,0.0,0.0,0.0 +0,0.237500,0.0,0.0,0.0,0.0,0.0 +0,0.237600,0.0,0.0,0.0,0.0,0.0 +0,0.237700,0.0,0.0,0.0,0.0,0.0 +0,0.237800,0.0,0.0,0.0,0.0,0.0 +0,0.237900,0.0,0.0,0.0,0.0,0.0 +0,0.238000,0.0,0.0,0.0,0.0,0.0 +0,0.238100,0.0,0.0,0.0,0.0,0.0 +0,0.238200,0.0,0.0,0.0,0.0,0.0 +0,0.238300,0.0,0.0,0.0,0.0,0.0 +0,0.238400,0.0,0.0,0.0,0.0,0.0 +0,0.238500,0.0,0.0,0.0,0.0,0.0 +0,0.238600,0.0,0.0,0.0,0.0,0.0 +0,0.238700,0.0,0.0,0.0,0.0,0.0 +0,0.238800,0.0,0.0,0.0,0.0,0.0 +0,0.238900,0.0,0.0,0.0,0.0,0.0 +0,0.239000,0.0,0.0,0.0,0.0,0.0 +0,0.239100,0.0,0.0,0.0,0.0,0.0 +0,0.239200,0.0,0.0,0.0,0.0,0.0 +0,0.239300,0.0,0.0,0.0,0.0,0.0 +0,0.239400,0.0,0.0,0.0,0.0,0.0 +0,0.239500,0.0,0.0,0.0,0.0,0.0 +0,0.239600,0.0,0.0,0.0,0.0,0.0 +0,0.239700,0.0,0.0,0.0,0.0,0.0 +0,0.239800,0.0,0.0,0.0,0.0,0.0 +0,0.239900,0.0,0.0,0.0,0.0,0.0 +0,0.240000,0.0,0.0,0.0,0.0,0.0 +0,0.240100,0.0,0.0,0.0,0.0,0.0 +1,5.770807,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.240200,0.0,0.0,0.0,0.0,0.0 +0,0.240300,0.0,0.0,0.0,0.0,0.0 +0,0.240400,0.0,0.0,0.0,0.0,0.0 +0,0.240500,0.0,0.0,0.0,0.0,0.0 +0,0.240600,0.0,0.0,0.0,0.0,0.0 +0,0.240700,0.0,0.0,0.0,0.0,0.0 +0,0.240800,0.0,0.0,0.0,0.0,0.0 +0,0.240900,0.0,0.0,0.0,0.0,0.0 +0,0.241000,0.0,0.0,0.0,0.0,0.0 +0,0.241100,0.0,0.0,0.0,0.0,0.0 +0,0.241200,0.0,0.0,0.0,0.0,0.0 +0,0.241300,0.0,0.0,0.0,0.0,0.0 +0,0.241400,0.0,0.0,0.0,0.0,0.0 +0,0.241500,0.0,0.0,0.0,0.0,0.0 +0,0.241600,0.0,0.0,0.0,0.0,0.0 +0,0.241700,0.0,0.0,0.0,0.0,0.0 +0,0.241800,0.0,0.0,0.0,0.0,0.0 +0,0.241900,0.0,0.0,0.0,0.0,0.0 +0,0.242000,0.0,0.0,0.0,0.0,0.0 +0,0.242100,0.0,0.0,0.0,0.0,0.0 +0,0.242200,0.0,0.0,0.0,0.0,0.0 +0,0.242300,0.0,0.0,0.0,0.0,0.0 +0,0.242400,0.0,0.0,0.0,0.0,0.0 +0,0.242500,0.0,0.0,0.0,0.0,0.0 +0,0.242600,0.0,0.0,0.0,0.0,0.0 +0,0.242700,0.0,0.0,0.0,0.0,0.0 +0,0.242800,0.0,0.0,0.0,0.0,0.0 +0,0.242900,0.0,0.0,0.0,0.0,0.0 +0,0.243000,0.0,0.0,0.0,0.0,0.0 +0,0.243100,0.0,0.0,0.0,0.0,0.0 +0,0.243200,0.0,0.0,0.0,0.0,0.0 +0,0.243300,0.0,0.0,0.0,0.0,0.0 +0,0.243400,0.0,0.0,0.0,0.0,0.0 +0,0.243500,0.0,0.0,0.0,0.0,0.0 +0,0.243600,0.0,0.0,0.0,0.0,0.0 +0,0.243700,0.0,0.0,0.0,0.0,0.0 +0,0.243800,0.0,0.0,0.0,0.0,0.0 +0,0.243900,0.0,0.0,0.0,0.0,0.0 +0,0.244000,0.0,0.0,0.0,0.0,0.0 +0,0.244100,0.0,0.0,0.0,0.0,0.0 +0,0.244200,0.0,0.0,0.0,0.0,0.0 +0,0.244300,0.0,0.0,0.0,0.0,0.0 +0,0.244400,0.0,0.0,0.0,0.0,0.0 +0,0.244500,0.0,0.0,0.0,0.0,0.0 +0,0.244600,0.0,0.0,0.0,0.0,0.0 +0,0.244700,0.0,0.0,0.0,0.0,0.0 +0,0.244800,0.0,0.0,0.0,0.0,0.0 +0,0.244900,0.0,0.0,0.0,0.0,0.0 +0,0.245000,0.0,0.0,0.0,0.0,0.0 +0,0.245100,0.0,0.0,0.0,0.0,0.0 +0,0.245200,0.0,0.0,0.0,0.0,0.0 +0,0.245300,0.0,0.0,0.0,0.0,0.0 +0,0.245400,0.0,0.0,0.0,0.0,0.0 +0,0.245500,0.0,0.0,0.0,0.0,0.0 +0,0.245600,0.0,0.0,0.0,0.0,0.0 +0,0.245700,0.0,0.0,0.0,0.0,0.0 +0,0.245800,0.0,0.0,0.0,0.0,0.0 +0,0.245900,0.0,0.0,0.0,0.0,0.0 +0,0.246000,0.0,0.0,0.0,0.0,0.0 +0,0.246100,0.0,0.0,0.0,0.0,0.0 +0,0.246200,0.0,0.0,0.0,0.0,0.0 +0,0.246300,0.0,0.0,0.0,0.0,0.0 +0,0.246400,0.0,0.0,0.0,0.0,0.0 +0,0.246500,0.0,0.0,0.0,0.0,0.0 +0,0.246600,0.0,0.0,0.0,0.0,0.0 +0,0.246700,0.0,0.0,0.0,0.0,0.0 +0,0.246800,0.0,0.0,0.0,0.0,0.0 +0,0.246900,0.0,0.0,0.0,0.0,0.0 +0,0.247000,0.0,0.0,0.0,0.0,0.0 +0,0.247100,0.0,0.0,0.0,0.0,0.0 +0,0.247200,0.0,0.0,0.0,0.0,0.0 +0,0.247300,0.0,0.0,0.0,0.0,0.0 +0,0.247400,0.0,0.0,0.0,0.0,0.0 +0,0.247500,0.0,0.0,0.0,0.0,0.0 +0,0.247600,0.0,0.0,0.0,0.0,0.0 +0,0.247700,0.0,0.0,0.0,0.0,0.0 +0,0.247800,0.0,0.0,0.0,0.0,0.0 +0,0.247900,0.0,0.0,0.0,0.0,0.0 +0,0.248000,0.0,0.0,0.0,0.0,0.0 +0,0.248100,0.0,0.0,0.0,0.0,0.0 +0,0.248200,0.0,0.0,0.0,0.0,0.0 +0,0.248300,0.0,0.0,0.0,0.0,0.0 +0,0.248400,0.0,0.0,0.0,0.0,0.0 +0,0.248500,0.0,0.0,0.0,0.0,0.0 +0,0.248600,0.0,0.0,0.0,0.0,0.0 +0,0.248700,0.0,0.0,0.0,0.0,0.0 +0,0.248800,0.0,0.0,0.0,0.0,0.0 +0,0.248900,0.0,0.0,0.0,0.0,0.0 +0,0.249000,0.0,0.0,0.0,0.0,0.0 +0,0.249100,0.0,0.0,0.0,0.0,0.0 +0,0.249200,0.0,0.0,0.0,0.0,0.0 +0,0.249300,0.0,0.0,0.0,0.0,0.0 +0,0.249400,0.0,0.0,0.0,0.0,0.0 +0,0.249500,0.0,0.0,0.0,0.0,0.0 +0,0.249600,0.0,0.0,0.0,0.0,0.0 +0,0.249700,0.0,0.0,0.0,0.0,0.0 +0,0.249800,0.0,0.0,0.0,0.0,0.0 +0,0.249900,0.0,0.0,0.0,0.0,0.0 +0,0.250000,0.0,0.0,0.0,0.0,0.0 +0,0.250100,0.0,0.0,0.0,0.0,0.0 +0,0.250200,0.0,0.0,0.0,0.0,0.0 +0,0.250300,0.0,0.0,0.0,0.0,0.0 +0,0.250400,0.0,0.0,0.0,0.0,0.0 +0,0.250500,0.0,0.0,0.0,0.0,0.0 +0,0.250600,0.0,0.0,0.0,0.0,0.0 +0,0.250700,0.0,0.0,0.0,0.0,0.0 +0,0.250800,0.0,0.0,0.0,0.0,0.0 +0,0.250900,0.0,0.0,0.0,0.0,0.0 +0,0.251000,0.0,0.0,0.0,0.0,0.0 +0,0.251100,0.0,0.0,0.0,0.0,0.0 +0,0.251200,0.0,0.0,0.0,0.0,0.0 +0,0.251300,0.0,0.0,0.0,0.0,0.0 +0,0.251400,0.0,0.0,0.0,0.0,0.0 +0,0.251500,0.0,0.0,0.0,0.0,0.0 +0,0.251600,0.0,0.0,0.0,0.0,0.0 +0,0.251700,0.0,0.0,0.0,0.0,0.0 +0,0.251800,0.0,0.0,0.0,0.0,0.0 +0,0.251900,0.0,0.0,0.0,0.0,0.0 +0,0.252000,0.0,0.0,0.0,0.0,0.0 +0,0.252100,0.0,0.0,0.0,0.0,0.0 +0,0.252200,0.0,0.0,0.0,0.0,0.0 +0,0.252300,0.0,0.0,0.0,0.0,0.0 +0,0.252400,0.0,0.0,0.0,0.0,0.0 +0,0.252500,0.0,0.0,0.0,0.0,0.0 +0,0.252600,0.0,0.0,0.0,0.0,0.0 +0,0.252700,0.0,0.0,0.0,0.0,0.0 +0,0.252800,0.0,0.0,0.0,0.0,0.0 +0,0.252900,0.0,0.0,0.0,0.0,0.0 +0,0.253000,0.0,0.0,0.0,0.0,0.0 +0,0.253100,0.0,0.0,0.0,0.0,0.0 +0,0.253200,0.0,0.0,0.0,0.0,0.0 +0,0.253300,0.0,0.0,0.0,0.0,0.0 +0,0.253400,0.0,0.0,0.0,0.0,0.0 +0,0.253500,0.0,0.0,0.0,0.0,0.0 +0,0.253600,0.0,0.0,0.0,0.0,0.0 +0,0.253700,0.0,0.0,0.0,0.0,0.0 +0,0.253800,0.0,0.0,0.0,0.0,0.0 +0,0.253900,0.0,0.0,0.0,0.0,0.0 +0,0.254000,0.0,0.0,0.0,0.0,0.0 +0,0.254100,0.0,0.0,0.0,0.0,0.0 +0,0.254200,0.0,0.0,0.0,0.0,0.0 +0,0.254300,0.0,0.0,0.0,0.0,0.0 +0,0.254400,0.0,0.0,0.0,0.0,0.0 +0,0.254500,0.0,0.0,0.0,0.0,0.0 +0,0.254600,0.0,0.0,0.0,0.0,0.0 +0,0.254700,0.0,0.0,0.0,0.0,0.0 +0,0.254800,0.0,0.0,0.0,0.0,0.0 +0,0.254900,0.0,0.0,0.0,0.0,0.0 +0,0.255000,0.0,0.0,0.0,0.0,0.0 +0,0.255100,0.0,0.0,0.0,0.0,0.0 +0,0.255200,0.0,0.0,0.0,0.0,0.0 +0,0.255300,0.0,0.0,0.0,0.0,0.0 +0,0.255400,0.0,0.0,0.0,0.0,0.0 +0,0.255500,0.0,0.0,0.0,0.0,0.0 +0,0.255600,0.0,0.0,0.0,0.0,0.0 +0,0.255700,0.0,0.0,0.0,0.0,0.0 +0,0.255800,0.0,0.0,0.0,0.0,0.0 +0,0.255900,0.0,0.0,0.0,0.0,0.0 +0,0.256000,0.0,0.0,0.0,0.0,0.0 +0,0.256100,0.0,0.0,0.0,0.0,0.0 +0,0.256200,0.0,0.0,0.0,0.0,0.0 +0,0.256300,0.0,0.0,0.0,0.0,0.0 +0,0.256400,0.0,0.0,0.0,0.0,0.0 +0,0.256500,0.0,0.0,0.0,0.0,0.0 +0,0.256600,0.0,0.0,0.0,0.0,0.0 +0,0.256700,0.0,0.0,0.0,0.0,0.0 +0,0.256800,0.0,0.0,0.0,0.0,0.0 +0,0.256900,0.0,0.0,0.0,0.0,0.0 +0,0.257000,0.0,0.0,0.0,0.0,0.0 +0,0.257100,0.0,0.0,0.0,0.0,0.0 +0,0.257200,0.0,0.0,0.0,0.0,0.0 +0,0.257300,0.0,0.0,0.0,0.0,0.0 +0,0.257400,0.0,0.0,0.0,0.0,0.0 +0,0.257500,0.0,0.0,0.0,0.0,0.0 +0,0.257600,0.0,0.0,0.0,0.0,0.0 +0,0.257700,0.0,0.0,0.0,0.0,0.0 +0,0.257800,0.0,0.0,0.0,0.0,0.0 +0,0.257900,0.0,0.0,0.0,0.0,0.0 +0,0.258000,0.0,0.0,0.0,0.0,0.0 +0,0.258100,0.0,0.0,0.0,0.0,0.0 +0,0.258200,0.0,0.0,0.0,0.0,0.0 +0,0.258300,0.0,0.0,0.0,0.0,0.0 +0,0.258400,0.0,0.0,0.0,0.0,0.0 +0,0.258500,0.0,0.0,0.0,0.0,0.0 +0,0.258600,0.0,0.0,0.0,0.0,0.0 +0,0.258700,0.0,0.0,0.0,0.0,0.0 +0,0.258800,0.0,0.0,0.0,0.0,0.0 +0,0.258900,0.0,0.0,0.0,0.0,0.0 +0,0.259000,0.0,0.0,0.0,0.0,0.0 +0,0.259100,0.0,0.0,0.0,0.0,0.0 +0,0.259200,0.0,0.0,0.0,0.0,0.0 +0,0.259300,0.0,0.0,0.0,0.0,0.0 +0,0.259400,0.0,0.0,0.0,0.0,0.0 +0,0.259500,0.0,0.0,0.0,0.0,0.0 +0,0.259600,0.0,0.0,0.0,0.0,0.0 +0,0.259700,0.0,0.0,0.0,0.0,0.0 +0,0.259800,0.0,0.0,0.0,0.0,0.0 +0,0.259900,0.0,0.0,0.0,0.0,0.0 +0,0.260000,0.0,0.0,0.0,0.0,0.0 +0,0.260100,0.0,0.0,0.0,0.0,0.0 +1,7.336015,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.260200,0.0,0.0,0.0,0.0,0.0 +0,0.260300,0.0,0.0,0.0,0.0,0.0 +0,0.260400,0.0,0.0,0.0,0.0,0.0 +0,0.260500,0.0,0.0,0.0,0.0,0.0 +0,0.260600,0.0,0.0,0.0,0.0,0.0 +0,0.260700,0.0,0.0,0.0,0.0,0.0 +0,0.260800,0.0,0.0,0.0,0.0,0.0 +0,0.260900,0.0,0.0,0.0,0.0,0.0 +0,0.261000,0.0,0.0,0.0,0.0,0.0 +0,0.261100,0.0,0.0,0.0,0.0,0.0 +0,0.261200,0.0,0.0,0.0,0.0,0.0 +0,0.261300,0.0,0.0,0.0,0.0,0.0 +0,0.261400,0.0,0.0,0.0,0.0,0.0 +0,0.261500,0.0,0.0,0.0,0.0,0.0 +0,0.261600,0.0,0.0,0.0,0.0,0.0 +0,0.261700,0.0,0.0,0.0,0.0,0.0 +0,0.261800,0.0,0.0,0.0,0.0,0.0 +0,0.261900,0.0,0.0,0.0,0.0,0.0 +0,0.262000,0.0,0.0,0.0,0.0,0.0 +0,0.262100,0.0,0.0,0.0,0.0,0.0 +0,0.262200,0.0,0.0,0.0,0.0,0.0 +0,0.262300,0.0,0.0,0.0,0.0,0.0 +0,0.262400,0.0,0.0,0.0,0.0,0.0 +0,0.262500,0.0,0.0,0.0,0.0,0.0 +0,0.262600,0.0,0.0,0.0,0.0,0.0 +0,0.262700,0.0,0.0,0.0,0.0,0.0 +0,0.262800,0.0,0.0,0.0,0.0,0.0 +0,0.262900,0.0,0.0,0.0,0.0,0.0 +0,0.263000,0.0,0.0,0.0,0.0,0.0 +0,0.263100,0.0,0.0,0.0,0.0,0.0 +0,0.263200,0.0,0.0,0.0,0.0,0.0 +0,0.263300,0.0,0.0,0.0,0.0,0.0 +0,0.263400,0.0,0.0,0.0,0.0,0.0 +0,0.263500,0.0,0.0,0.0,0.0,0.0 +0,0.263600,0.0,0.0,0.0,0.0,0.0 +0,0.263700,0.0,0.0,0.0,0.0,0.0 +0,0.263800,0.0,0.0,0.0,0.0,0.0 +0,0.263900,0.0,0.0,0.0,0.0,0.0 +0,0.264000,0.0,0.0,0.0,0.0,0.0 +0,0.264100,0.0,0.0,0.0,0.0,0.0 +0,0.264200,0.0,0.0,0.0,0.0,0.0 +0,0.264300,0.0,0.0,0.0,0.0,0.0 +0,0.264400,0.0,0.0,0.0,0.0,0.0 +0,0.264500,0.0,0.0,0.0,0.0,0.0 +0,0.264600,0.0,0.0,0.0,0.0,0.0 +0,0.264700,0.0,0.0,0.0,0.0,0.0 +0,0.264800,0.0,0.0,0.0,0.0,0.0 +0,0.264900,0.0,0.0,0.0,0.0,0.0 +0,0.265000,0.0,0.0,0.0,0.0,0.0 +0,0.265100,0.0,0.0,0.0,0.0,0.0 +0,0.265200,0.0,0.0,0.0,0.0,0.0 +0,0.265300,0.0,0.0,0.0,0.0,0.0 +0,0.265400,0.0,0.0,0.0,0.0,0.0 +0,0.265500,0.0,0.0,0.0,0.0,0.0 +0,0.265600,0.0,0.0,0.0,0.0,0.0 +0,0.265700,0.0,0.0,0.0,0.0,0.0 +0,0.265800,0.0,0.0,0.0,0.0,0.0 +0,0.265900,0.0,0.0,0.0,0.0,0.0 +0,0.266000,0.0,0.0,0.0,0.0,0.0 +0,0.266100,0.0,0.0,0.0,0.0,0.0 +0,0.266200,0.0,0.0,0.0,0.0,0.0 +0,0.266300,0.0,0.0,0.0,0.0,0.0 +0,0.266400,0.0,0.0,0.0,0.0,0.0 +0,0.266500,0.0,0.0,0.0,0.0,0.0 +0,0.266600,0.0,0.0,0.0,0.0,0.0 +0,0.266700,0.0,0.0,0.0,0.0,0.0 +0,0.266800,0.0,0.0,0.0,0.0,0.0 +0,0.266900,0.0,0.0,0.0,0.0,0.0 +0,0.267000,0.0,0.0,0.0,0.0,0.0 +0,0.267100,0.0,0.0,0.0,0.0,0.0 +0,0.267200,0.0,0.0,0.0,0.0,0.0 +0,0.267300,0.0,0.0,0.0,0.0,0.0 +0,0.267400,0.0,0.0,0.0,0.0,0.0 +0,0.267500,0.0,0.0,0.0,0.0,0.0 +0,0.267600,0.0,0.0,0.0,0.0,0.0 +0,0.267700,0.0,0.0,0.0,0.0,0.0 +0,0.267800,0.0,0.0,0.0,0.0,0.0 +0,0.267900,0.0,0.0,0.0,0.0,0.0 +0,0.268000,0.0,0.0,0.0,0.0,0.0 +0,0.268100,0.0,0.0,0.0,0.0,0.0 +0,0.268200,0.0,0.0,0.0,0.0,0.0 +0,0.268300,0.0,0.0,0.0,0.0,0.0 +0,0.268400,0.0,0.0,0.0,0.0,0.0 +0,0.268500,0.0,0.0,0.0,0.0,0.0 +0,0.268600,0.0,0.0,0.0,0.0,0.0 +0,0.268700,0.0,0.0,0.0,0.0,0.0 +0,0.268800,0.0,0.0,0.0,0.0,0.0 +0,0.268900,0.0,0.0,0.0,0.0,0.0 +0,0.269000,0.0,0.0,0.0,0.0,0.0 +0,0.269100,0.0,0.0,0.0,0.0,0.0 +0,0.269200,0.0,0.0,0.0,0.0,0.0 +0,0.269300,0.0,0.0,0.0,0.0,0.0 +0,0.269400,0.0,0.0,0.0,0.0,0.0 +0,0.269500,0.0,0.0,0.0,0.0,0.0 +0,0.269600,0.0,0.0,0.0,0.0,0.0 +0,0.269700,0.0,0.0,0.0,0.0,0.0 +0,0.269800,0.0,0.0,0.0,0.0,0.0 +0,0.269900,0.0,0.0,0.0,0.0,0.0 +0,0.270000,0.0,0.0,0.0,0.0,0.0 +0,0.270100,0.0,0.0,0.0,0.0,0.0 +0,0.270200,0.0,0.0,0.0,0.0,0.0 +0,0.270300,0.0,0.0,0.0,0.0,0.0 +0,0.270400,0.0,0.0,0.0,0.0,0.0 +0,0.270500,0.0,0.0,0.0,0.0,0.0 +0,0.270600,0.0,0.0,0.0,0.0,0.0 +0,0.270700,0.0,0.0,0.0,0.0,0.0 +0,0.270800,0.0,0.0,0.0,0.0,0.0 +0,0.270900,0.0,0.0,0.0,0.0,0.0 +0,0.271000,0.0,0.0,0.0,0.0,0.0 +0,0.271100,0.0,0.0,0.0,0.0,0.0 +0,0.271200,0.0,0.0,0.0,0.0,0.0 +0,0.271300,0.0,0.0,0.0,0.0,0.0 +0,0.271400,0.0,0.0,0.0,0.0,0.0 +0,0.271500,0.0,0.0,0.0,0.0,0.0 +0,0.271600,0.0,0.0,0.0,0.0,0.0 +0,0.271700,0.0,0.0,0.0,0.0,0.0 +0,0.271800,0.0,0.0,0.0,0.0,0.0 +0,0.271900,0.0,0.0,0.0,0.0,0.0 +0,0.272000,0.0,0.0,0.0,0.0,0.0 +0,0.272100,0.0,0.0,0.0,0.0,0.0 +0,0.272200,0.0,0.0,0.0,0.0,0.0 +0,0.272300,0.0,0.0,0.0,0.0,0.0 +0,0.272400,0.0,0.0,0.0,0.0,0.0 +0,0.272500,0.0,0.0,0.0,0.0,0.0 +0,0.272600,0.0,0.0,0.0,0.0,0.0 +0,0.272700,0.0,0.0,0.0,0.0,0.0 +0,0.272800,0.0,0.0,0.0,0.0,0.0 +0,0.272900,0.0,0.0,0.0,0.0,0.0 +0,0.273000,0.0,0.0,0.0,0.0,0.0 +0,0.273100,0.0,0.0,0.0,0.0,0.0 +0,0.273200,0.0,0.0,0.0,0.0,0.0 +0,0.273300,0.0,0.0,0.0,0.0,0.0 +0,0.273400,0.0,0.0,0.0,0.0,0.0 +0,0.273500,0.0,0.0,0.0,0.0,0.0 +0,0.273600,0.0,0.0,0.0,0.0,0.0 +0,0.273700,0.0,0.0,0.0,0.0,0.0 +0,0.273800,0.0,0.0,0.0,0.0,0.0 +0,0.273900,0.0,0.0,0.0,0.0,0.0 +0,0.274000,0.0,0.0,0.0,0.0,0.0 +0,0.274100,0.0,0.0,0.0,0.0,0.0 +0,0.274200,0.0,0.0,0.0,0.0,0.0 +0,0.274300,0.0,0.0,0.0,0.0,0.0 +0,0.274400,0.0,0.0,0.0,0.0,0.0 +0,0.274500,0.0,0.0,0.0,0.0,0.0 +0,0.274600,0.0,0.0,0.0,0.0,0.0 +0,0.274700,0.0,0.0,0.0,0.0,0.0 +0,0.274800,0.0,0.0,0.0,0.0,0.0 +0,0.274900,0.0,0.0,0.0,0.0,0.0 +0,0.275000,0.0,0.0,0.0,0.0,0.0 +0,0.275100,0.0,0.0,0.0,0.0,0.0 +0,0.275200,0.0,0.0,0.0,0.0,0.0 +0,0.275300,0.0,0.0,0.0,0.0,0.0 +0,0.275400,0.0,0.0,0.0,0.0,0.0 +0,0.275500,0.0,0.0,0.0,0.0,0.0 +0,0.275600,0.0,0.0,0.0,0.0,0.0 +0,0.275700,0.0,0.0,0.0,0.0,0.0 +0,0.275800,0.0,0.0,0.0,0.0,0.0 +0,0.275900,0.0,0.0,0.0,0.0,0.0 +0,0.276000,0.0,0.0,0.0,0.0,0.0 +0,0.276100,0.0,0.0,0.0,0.0,0.0 +0,0.276200,0.0,0.0,0.0,0.0,0.0 +0,0.276300,0.0,0.0,0.0,0.0,0.0 +0,0.276400,0.0,0.0,0.0,0.0,0.0 +0,0.276500,0.0,0.0,0.0,0.0,0.0 +0,0.276600,0.0,0.0,0.0,0.0,0.0 +0,0.276700,0.0,0.0,0.0,0.0,0.0 +0,0.276800,0.0,0.0,0.0,0.0,0.0 +0,0.276900,0.0,0.0,0.0,0.0,0.0 +0,0.277000,0.0,0.0,0.0,0.0,0.0 +0,0.277100,0.0,0.0,0.0,0.0,0.0 +0,0.277200,0.0,0.0,0.0,0.0,0.0 +0,0.277300,0.0,0.0,0.0,0.0,0.0 +0,0.277400,0.0,0.0,0.0,0.0,0.0 +0,0.277500,0.0,0.0,0.0,0.0,0.0 +0,0.277600,0.0,0.0,0.0,0.0,0.0 +0,0.277700,0.0,0.0,0.0,0.0,0.0 +0,0.277800,0.0,0.0,0.0,0.0,0.0 +0,0.277900,0.0,0.0,0.0,0.0,0.0 +0,0.278000,0.0,0.0,0.0,0.0,0.0 +0,0.278100,0.0,0.0,0.0,0.0,0.0 +0,0.278200,0.0,0.0,0.0,0.0,0.0 +0,0.278300,0.0,0.0,0.0,0.0,0.0 +0,0.278400,0.0,0.0,0.0,0.0,0.0 +0,0.278500,0.0,0.0,0.0,0.0,0.0 +0,0.278600,0.0,0.0,0.0,0.0,0.0 +0,0.278700,0.0,0.0,0.0,0.0,0.0 +0,0.278800,0.0,0.0,0.0,0.0,0.0 +0,0.278900,0.0,0.0,0.0,0.0,0.0 +0,0.279000,0.0,0.0,0.0,0.0,0.0 +0,0.279100,0.0,0.0,0.0,0.0,0.0 +0,0.279200,0.0,0.0,0.0,0.0,0.0 +0,0.279300,0.0,0.0,0.0,0.0,0.0 +0,0.279400,0.0,0.0,0.0,0.0,0.0 +0,0.279500,0.0,0.0,0.0,0.0,0.0 +0,0.279600,0.0,0.0,0.0,0.0,0.0 +0,0.279700,0.0,0.0,0.0,0.0,0.0 +0,0.279800,0.0,0.0,0.0,0.0,0.0 +0,0.279900,0.0,0.0,0.0,0.0,0.0 +0,0.280000,0.0,0.0,0.0,0.0,0.0 +0,0.280100,0.0,0.0,0.0,0.0,0.0 +1,9.161374,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.280200,0.0,0.0,0.0,0.0,0.0 +0,0.280300,0.0,0.0,0.0,0.0,0.0 +0,0.280400,0.0,0.0,0.0,0.0,0.0 +0,0.280500,0.0,0.0,0.0,0.0,0.0 +0,0.280600,0.0,0.0,0.0,0.0,0.0 +0,0.280700,0.0,0.0,0.0,0.0,0.0 +0,0.280800,0.0,0.0,0.0,0.0,0.0 +0,0.280900,0.0,0.0,0.0,0.0,0.0 +0,0.281000,0.0,0.0,0.0,0.0,0.0 +0,0.281100,0.0,0.0,0.0,0.0,0.0 +0,0.281200,0.0,0.0,0.0,0.0,0.0 +0,0.281300,0.0,0.0,0.0,0.0,0.0 +0,0.281400,0.0,0.0,0.0,0.0,0.0 +0,0.281500,0.0,0.0,0.0,0.0,0.0 +0,0.281600,0.0,0.0,0.0,0.0,0.0 +0,0.281700,0.0,0.0,0.0,0.0,0.0 +0,0.281800,0.0,0.0,0.0,0.0,0.0 +0,0.281900,0.0,0.0,0.0,0.0,0.0 +0,0.282000,0.0,0.0,0.0,0.0,0.0 +0,0.282100,0.0,0.0,0.0,0.0,0.0 +0,0.282200,0.0,0.0,0.0,0.0,0.0 +0,0.282300,0.0,0.0,0.0,0.0,0.0 +0,0.282400,0.0,0.0,0.0,0.0,0.0 +0,0.282500,0.0,0.0,0.0,0.0,0.0 +0,0.282600,0.0,0.0,0.0,0.0,0.0 +0,0.282700,0.0,0.0,0.0,0.0,0.0 +0,0.282800,0.0,0.0,0.0,0.0,0.0 +0,0.282900,0.0,0.0,0.0,0.0,0.0 +0,0.283000,0.0,0.0,0.0,0.0,0.0 +0,0.283100,0.0,0.0,0.0,0.0,0.0 +0,0.283200,0.0,0.0,0.0,0.0,0.0 +0,0.283300,0.0,0.0,0.0,0.0,0.0 +0,0.283400,0.0,0.0,0.0,0.0,0.0 +0,0.283500,0.0,0.0,0.0,0.0,0.0 +0,0.283600,0.0,0.0,0.0,0.0,0.0 +0,0.283700,0.0,0.0,0.0,0.0,0.0 +0,0.283800,0.0,0.0,0.0,0.0,0.0 +0,0.283900,0.0,0.0,0.0,0.0,0.0 +0,0.284000,0.0,0.0,0.0,0.0,0.0 +0,0.284100,0.0,0.0,0.0,0.0,0.0 +0,0.284200,0.0,0.0,0.0,0.0,0.0 +0,0.284300,0.0,0.0,0.0,0.0,0.0 +0,0.284400,0.0,0.0,0.0,0.0,0.0 +0,0.284500,0.0,0.0,0.0,0.0,0.0 +0,0.284600,0.0,0.0,0.0,0.0,0.0 +0,0.284700,0.0,0.0,0.0,0.0,0.0 +0,0.284800,0.0,0.0,0.0,0.0,0.0 +0,0.284900,0.0,0.0,0.0,0.0,0.0 +0,0.285000,0.0,0.0,0.0,0.0,0.0 +0,0.285100,0.0,0.0,0.0,0.0,0.0 +0,0.285200,0.0,0.0,0.0,0.0,0.0 +0,0.285300,0.0,0.0,0.0,0.0,0.0 +0,0.285400,0.0,0.0,0.0,0.0,0.0 +0,0.285500,0.0,0.0,0.0,0.0,0.0 +0,0.285600,0.0,0.0,0.0,0.0,0.0 +0,0.285700,0.0,0.0,0.0,0.0,0.0 +0,0.285800,0.0,0.0,0.0,0.0,0.0 +0,0.285900,0.0,0.0,0.0,0.0,0.0 +0,0.286000,0.0,0.0,0.0,0.0,0.0 +0,0.286100,0.0,0.0,0.0,0.0,0.0 +0,0.286200,0.0,0.0,0.0,0.0,0.0 +0,0.286300,0.0,0.0,0.0,0.0,0.0 +0,0.286400,0.0,0.0,0.0,0.0,0.0 +0,0.286500,0.0,0.0,0.0,0.0,0.0 +0,0.286600,0.0,0.0,0.0,0.0,0.0 +0,0.286700,0.0,0.0,0.0,0.0,0.0 +0,0.286800,0.0,0.0,0.0,0.0,0.0 +0,0.286900,0.0,0.0,0.0,0.0,0.0 +0,0.287000,0.0,0.0,0.0,0.0,0.0 +0,0.287100,0.0,0.0,0.0,0.0,0.0 +0,0.287200,0.0,0.0,0.0,0.0,0.0 +0,0.287300,0.0,0.0,0.0,0.0,0.0 +0,0.287400,0.0,0.0,0.0,0.0,0.0 +0,0.287500,0.0,0.0,0.0,0.0,0.0 +0,0.287600,0.0,0.0,0.0,0.0,0.0 +0,0.287700,0.0,0.0,0.0,0.0,0.0 +0,0.287800,0.0,0.0,0.0,0.0,0.0 +0,0.287900,0.0,0.0,0.0,0.0,0.0 +0,0.288000,0.0,0.0,0.0,0.0,0.0 +0,0.288100,0.0,0.0,0.0,0.0,0.0 +0,0.288200,0.0,0.0,0.0,0.0,0.0 +0,0.288300,0.0,0.0,0.0,0.0,0.0 +0,0.288400,0.0,0.0,0.0,0.0,0.0 +0,0.288500,0.0,0.0,0.0,0.0,0.0 +0,0.288600,0.0,0.0,0.0,0.0,0.0 +0,0.288700,0.0,0.0,0.0,0.0,0.0 +0,0.288800,0.0,0.0,0.0,0.0,0.0 +0,0.288900,0.0,0.0,0.0,0.0,0.0 +0,0.289000,0.0,0.0,0.0,0.0,0.0 +0,0.289100,0.0,0.0,0.0,0.0,0.0 +0,0.289200,0.0,0.0,0.0,0.0,0.0 +0,0.289300,0.0,0.0,0.0,0.0,0.0 +0,0.289400,0.0,0.0,0.0,0.0,0.0 +0,0.289500,0.0,0.0,0.0,0.0,0.0 +0,0.289600,0.0,0.0,0.0,0.0,0.0 +0,0.289700,0.0,0.0,0.0,0.0,0.0 +0,0.289800,0.0,0.0,0.0,0.0,0.0 +0,0.289900,0.0,0.0,0.0,0.0,0.0 +0,0.290000,0.0,0.0,0.0,0.0,0.0 +0,0.290100,0.0,0.0,0.0,0.0,0.0 +0,0.290200,0.0,0.0,0.0,0.0,0.0 +0,0.290300,0.0,0.0,0.0,0.0,0.0 +0,0.290400,0.0,0.0,0.0,0.0,0.0 +0,0.290500,0.0,0.0,0.0,0.0,0.0 +0,0.290600,0.0,0.0,0.0,0.0,0.0 +0,0.290700,0.0,0.0,0.0,0.0,0.0 +0,0.290800,0.0,0.0,0.0,0.0,0.0 +0,0.290900,0.0,0.0,0.0,0.0,0.0 +0,0.291000,0.0,0.0,0.0,0.0,0.0 +0,0.291100,0.0,0.0,0.0,0.0,0.0 +0,0.291200,0.0,0.0,0.0,0.0,0.0 +0,0.291300,0.0,0.0,0.0,0.0,0.0 +0,0.291400,0.0,0.0,0.0,0.0,0.0 +0,0.291500,0.0,0.0,0.0,0.0,0.0 +0,0.291600,0.0,0.0,0.0,0.0,0.0 +0,0.291700,0.0,0.0,0.0,0.0,0.0 +0,0.291800,0.0,0.0,0.0,0.0,0.0 +0,0.291900,0.0,0.0,0.0,0.0,0.0 +0,0.292000,0.0,0.0,0.0,0.0,0.0 +0,0.292100,0.0,0.0,0.0,0.0,0.0 +0,0.292200,0.0,0.0,0.0,0.0,0.0 +0,0.292300,0.0,0.0,0.0,0.0,0.0 +0,0.292400,0.0,0.0,0.0,0.0,0.0 +0,0.292500,0.0,0.0,0.0,0.0,0.0 +0,0.292600,0.0,0.0,0.0,0.0,0.0 +0,0.292700,0.0,0.0,0.0,0.0,0.0 +0,0.292800,0.0,0.0,0.0,0.0,0.0 +0,0.292900,0.0,0.0,0.0,0.0,0.0 +0,0.293000,0.0,0.0,0.0,0.0,0.0 +0,0.293100,0.0,0.0,0.0,0.0,0.0 +0,0.293200,0.0,0.0,0.0,0.0,0.0 +0,0.293300,0.0,0.0,0.0,0.0,0.0 +0,0.293400,0.0,0.0,0.0,0.0,0.0 +0,0.293500,0.0,0.0,0.0,0.0,0.0 +0,0.293600,0.0,0.0,0.0,0.0,0.0 +0,0.293700,0.0,0.0,0.0,0.0,0.0 +0,0.293800,0.0,0.0,0.0,0.0,0.0 +0,0.293900,0.0,0.0,0.0,0.0,0.0 +0,0.294000,0.0,0.0,0.0,0.0,0.0 +0,0.294100,0.0,0.0,0.0,0.0,0.0 +0,0.294200,0.0,0.0,0.0,0.0,0.0 +0,0.294300,0.0,0.0,0.0,0.0,0.0 +0,0.294400,0.0,0.0,0.0,0.0,0.0 +0,0.294500,0.0,0.0,0.0,0.0,0.0 +0,0.294600,0.0,0.0,0.0,0.0,0.0 +0,0.294700,0.0,0.0,0.0,0.0,0.0 +0,0.294800,0.0,0.0,0.0,0.0,0.0 +0,0.294900,0.0,0.0,0.0,0.0,0.0 +0,0.295000,0.0,0.0,0.0,0.0,0.0 +0,0.295100,0.0,0.0,0.0,0.0,0.0 +0,0.295200,0.0,0.0,0.0,0.0,0.0 +0,0.295300,0.0,0.0,0.0,0.0,0.0 +0,0.295400,0.0,0.0,0.0,0.0,0.0 +0,0.295500,0.0,0.0,0.0,0.0,0.0 +0,0.295600,0.0,0.0,0.0,0.0,0.0 +0,0.295700,0.0,0.0,0.0,0.0,0.0 +0,0.295800,0.0,0.0,0.0,0.0,0.0 +0,0.295900,0.0,0.0,0.0,0.0,0.0 +0,0.296000,0.0,0.0,0.0,0.0,0.0 +0,0.296100,0.0,0.0,0.0,0.0,0.0 +0,0.296200,0.0,0.0,0.0,0.0,0.0 +0,0.296300,0.0,0.0,0.0,0.0,0.0 +0,0.296400,0.0,0.0,0.0,0.0,0.0 +0,0.296500,0.0,0.0,0.0,0.0,0.0 +0,0.296600,0.0,0.0,0.0,0.0,0.0 +0,0.296700,0.0,0.0,0.0,0.0,0.0 +0,0.296800,0.0,0.0,0.0,0.0,0.0 +0,0.296900,0.0,0.0,0.0,0.0,0.0 +0,0.297000,0.0,0.0,0.0,0.0,0.0 +0,0.297100,0.0,0.0,0.0,0.0,0.0 +0,0.297200,0.0,0.0,0.0,0.0,0.0 +0,0.297300,0.0,0.0,0.0,0.0,0.0 +0,0.297400,0.0,0.0,0.0,0.0,0.0 +0,0.297500,0.0,0.0,0.0,0.0,0.0 +0,0.297600,0.0,0.0,0.0,0.0,0.0 +0,0.297700,0.0,0.0,0.0,0.0,0.0 +0,0.297800,0.0,0.0,0.0,0.0,0.0 +0,0.297900,0.0,0.0,0.0,0.0,0.0 +0,0.298000,0.0,0.0,0.0,0.0,0.0 +0,0.298100,0.0,0.0,0.0,0.0,0.0 +0,0.298200,0.0,0.0,0.0,0.0,0.0 +0,0.298300,0.0,0.0,0.0,0.0,0.0 +0,0.298400,0.0,0.0,0.0,0.0,0.0 +0,0.298500,0.0,0.0,0.0,0.0,0.0 +0,0.298600,0.0,0.0,0.0,0.0,0.0 +0,0.298700,0.0,0.0,0.0,0.0,0.0 +0,0.298800,0.0,0.0,0.0,0.0,0.0 +0,0.298900,0.0,0.0,0.0,0.0,0.0 +0,0.299000,0.0,0.0,0.0,0.0,0.0 +0,0.299100,0.0,0.0,0.0,0.0,0.0 +0,0.299200,0.0,0.0,0.0,0.0,0.0 +0,0.299300,0.0,0.0,0.0,0.0,0.0 +0,0.299400,0.0,0.0,0.0,0.0,0.0 +0,0.299500,0.0,0.0,0.0,0.0,0.0 +0,0.299600,0.0,0.0,0.0,0.0,0.0 +0,0.299700,0.0,0.0,0.0,0.0,0.0 +0,0.299800,0.0,0.0,0.0,0.0,0.0 +0,0.299900,0.0,0.0,0.0,0.0,0.0 +0,0.300000,0.0,0.0,0.0,0.0,0.0 +0,0.300100,0.0,0.0,0.0,0.0,0.0 +1,11.266883,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.300200,0.0,0.0,0.0,0.0,0.0 +0,0.300300,0.0,0.0,0.0,0.0,0.0 +0,0.300400,0.0,0.0,0.0,0.0,0.0 +0,0.300500,0.0,0.0,0.0,0.0,0.0 +0,0.300600,0.0,0.0,0.0,0.0,0.0 +0,0.300700,0.0,0.0,0.0,0.0,0.0 +0,0.300800,0.0,0.0,0.0,0.0,0.0 +0,0.300900,0.0,0.0,0.0,0.0,0.0 +0,0.301000,0.0,0.0,0.0,0.0,0.0 +0,0.301100,0.0,0.0,0.0,0.0,0.0 +0,0.301200,0.0,0.0,0.0,0.0,0.0 +0,0.301300,0.0,0.0,0.0,0.0,0.0 +0,0.301400,0.0,0.0,0.0,0.0,0.0 +0,0.301500,0.0,0.0,0.0,0.0,0.0 +0,0.301600,0.0,0.0,0.0,0.0,0.0 +0,0.301700,0.0,0.0,0.0,0.0,0.0 +0,0.301800,0.0,0.0,0.0,0.0,0.0 +0,0.301900,0.0,0.0,0.0,0.0,0.0 +0,0.302000,0.0,0.0,0.0,0.0,0.0 +0,0.302100,0.0,0.0,0.0,0.0,0.0 +0,0.302200,0.0,0.0,0.0,0.0,0.0 +0,0.302300,0.0,0.0,0.0,0.0,0.0 +0,0.302400,0.0,0.0,0.0,0.0,0.0 +0,0.302500,0.0,0.0,0.0,0.0,0.0 +0,0.302600,0.0,0.0,0.0,0.0,0.0 +0,0.302700,0.0,0.0,0.0,0.0,0.0 +0,0.302800,0.0,0.0,0.0,0.0,0.0 +0,0.302900,0.0,0.0,0.0,0.0,0.0 +0,0.303000,0.0,0.0,0.0,0.0,0.0 +0,0.303100,0.0,0.0,0.0,0.0,0.0 +0,0.303200,0.0,0.0,0.0,0.0,0.0 +0,0.303300,0.0,0.0,0.0,0.0,0.0 +0,0.303400,0.0,0.0,0.0,0.0,0.0 +0,0.303500,0.0,0.0,0.0,0.0,0.0 +0,0.303600,0.0,0.0,0.0,0.0,0.0 +0,0.303700,0.0,0.0,0.0,0.0,0.0 +0,0.303800,0.0,0.0,0.0,0.0,0.0 +0,0.303900,0.0,0.0,0.0,0.0,0.0 +0,0.304000,0.0,0.0,0.0,0.0,0.0 +0,0.304100,0.0,0.0,0.0,0.0,0.0 +0,0.304200,0.0,0.0,0.0,0.0,0.0 +0,0.304300,0.0,0.0,0.0,0.0,0.0 +0,0.304400,0.0,0.0,0.0,0.0,0.0 +0,0.304500,0.0,0.0,0.0,0.0,0.0 +0,0.304600,0.0,0.0,0.0,0.0,0.0 +0,0.304700,0.0,0.0,0.0,0.0,0.0 +0,0.304800,0.0,0.0,0.0,0.0,0.0 +0,0.304900,0.0,0.0,0.0,0.0,0.0 +0,0.305000,0.0,0.0,0.0,0.0,0.0 +0,0.305100,0.0,0.0,0.0,0.0,0.0 +0,0.305200,0.0,0.0,0.0,0.0,0.0 +0,0.305300,0.0,0.0,0.0,0.0,0.0 +0,0.305400,0.0,0.0,0.0,0.0,0.0 +0,0.305500,0.0,0.0,0.0,0.0,0.0 +0,0.305600,0.0,0.0,0.0,0.0,0.0 +0,0.305700,0.0,0.0,0.0,0.0,0.0 +0,0.305800,0.0,0.0,0.0,0.0,0.0 +0,0.305900,0.0,0.0,0.0,0.0,0.0 +0,0.306000,0.0,0.0,0.0,0.0,0.0 +0,0.306100,0.0,0.0,0.0,0.0,0.0 +0,0.306200,0.0,0.0,0.0,0.0,0.0 +0,0.306300,0.0,0.0,0.0,0.0,0.0 +0,0.306400,0.0,0.0,0.0,0.0,0.0 +0,0.306500,0.0,0.0,0.0,0.0,0.0 +0,0.306600,0.0,0.0,0.0,0.0,0.0 +0,0.306700,0.0,0.0,0.0,0.0,0.0 +0,0.306800,0.0,0.0,0.0,0.0,0.0 +0,0.306900,0.0,0.0,0.0,0.0,0.0 +0,0.307000,0.0,0.0,0.0,0.0,0.0 +0,0.307100,0.0,0.0,0.0,0.0,0.0 +0,0.307200,0.0,0.0,0.0,0.0,0.0 +0,0.307300,0.0,0.0,0.0,0.0,0.0 +0,0.307400,0.0,0.0,0.0,0.0,0.0 +0,0.307500,0.0,0.0,0.0,0.0,0.0 +0,0.307600,0.0,0.0,0.0,0.0,0.0 +0,0.307700,0.0,0.0,0.0,0.0,0.0 +0,0.307800,0.0,0.0,0.0,0.0,0.0 +0,0.307900,0.0,0.0,0.0,0.0,0.0 +0,0.308000,0.0,0.0,0.0,0.0,0.0 +0,0.308100,0.0,0.0,0.0,0.0,0.0 +0,0.308200,0.0,0.0,0.0,0.0,0.0 +0,0.308300,0.0,0.0,0.0,0.0,0.0 +0,0.308400,0.0,0.0,0.0,0.0,0.0 +0,0.308500,0.0,0.0,0.0,0.0,0.0 +0,0.308600,0.0,0.0,0.0,0.0,0.0 +0,0.308700,0.0,0.0,0.0,0.0,0.0 +0,0.308800,0.0,0.0,0.0,0.0,0.0 +0,0.308900,0.0,0.0,0.0,0.0,0.0 +0,0.309000,0.0,0.0,0.0,0.0,0.0 +0,0.309100,0.0,0.0,0.0,0.0,0.0 +0,0.309200,0.0,0.0,0.0,0.0,0.0 +0,0.309300,0.0,0.0,0.0,0.0,0.0 +0,0.309400,0.0,0.0,0.0,0.0,0.0 +0,0.309500,0.0,0.0,0.0,0.0,0.0 +0,0.309600,0.0,0.0,0.0,0.0,0.0 +0,0.309700,0.0,0.0,0.0,0.0,0.0 +0,0.309800,0.0,0.0,0.0,0.0,0.0 +0,0.309900,0.0,0.0,0.0,0.0,0.0 +0,0.310000,0.0,0.0,0.0,0.0,0.0 +0,0.310100,0.0,0.0,0.0,0.0,0.0 +0,0.310200,0.0,0.0,0.0,0.0,0.0 +0,0.310300,0.0,0.0,0.0,0.0,0.0 +0,0.310400,0.0,0.0,0.0,0.0,0.0 +0,0.310500,0.0,0.0,0.0,0.0,0.0 +0,0.310600,0.0,0.0,0.0,0.0,0.0 +0,0.310700,0.0,0.0,0.0,0.0,0.0 +0,0.310800,0.0,0.0,0.0,0.0,0.0 +0,0.310900,0.0,0.0,0.0,0.0,0.0 +0,0.311000,0.0,0.0,0.0,0.0,0.0 +0,0.311100,0.0,0.0,0.0,0.0,0.0 +0,0.311200,0.0,0.0,0.0,0.0,0.0 +0,0.311300,0.0,0.0,0.0,0.0,0.0 +0,0.311400,0.0,0.0,0.0,0.0,0.0 +0,0.311500,0.0,0.0,0.0,0.0,0.0 +0,0.311600,0.0,0.0,0.0,0.0,0.0 +0,0.311700,0.0,0.0,0.0,0.0,0.0 +0,0.311800,0.0,0.0,0.0,0.0,0.0 +0,0.311900,0.0,0.0,0.0,0.0,0.0 +0,0.312000,0.0,0.0,0.0,0.0,0.0 +0,0.312100,0.0,0.0,0.0,0.0,0.0 +0,0.312200,0.0,0.0,0.0,0.0,0.0 +0,0.312300,0.0,0.0,0.0,0.0,0.0 +0,0.312400,0.0,0.0,0.0,0.0,0.0 +0,0.312500,0.0,0.0,0.0,0.0,0.0 +0,0.312600,0.0,0.0,0.0,0.0,0.0 +0,0.312700,0.0,0.0,0.0,0.0,0.0 +0,0.312800,0.0,0.0,0.0,0.0,0.0 +0,0.312900,0.0,0.0,0.0,0.0,0.0 +0,0.313000,0.0,0.0,0.0,0.0,0.0 +0,0.313100,0.0,0.0,0.0,0.0,0.0 +0,0.313200,0.0,0.0,0.0,0.0,0.0 +0,0.313300,0.0,0.0,0.0,0.0,0.0 +0,0.313400,0.0,0.0,0.0,0.0,0.0 +0,0.313500,0.0,0.0,0.0,0.0,0.0 +0,0.313600,0.0,0.0,0.0,0.0,0.0 +0,0.313700,0.0,0.0,0.0,0.0,0.0 +0,0.313800,0.0,0.0,0.0,0.0,0.0 +0,0.313900,0.0,0.0,0.0,0.0,0.0 +0,0.314000,0.0,0.0,0.0,0.0,0.0 +0,0.314100,0.0,0.0,0.0,0.0,0.0 +0,0.314200,0.0,0.0,0.0,0.0,0.0 +0,0.314300,0.0,0.0,0.0,0.0,0.0 +0,0.314400,0.0,0.0,0.0,0.0,0.0 +0,0.314500,0.0,0.0,0.0,0.0,0.0 +0,0.314600,0.0,0.0,0.0,0.0,0.0 +0,0.314700,0.0,0.0,0.0,0.0,0.0 +0,0.314800,0.0,0.0,0.0,0.0,0.0 +0,0.314900,0.0,0.0,0.0,0.0,0.0 +0,0.315000,0.0,0.0,0.0,0.0,0.0 +0,0.315100,0.0,0.0,0.0,0.0,0.0 +0,0.315200,0.0,0.0,0.0,0.0,0.0 +0,0.315300,0.0,0.0,0.0,0.0,0.0 +0,0.315400,0.0,0.0,0.0,0.0,0.0 +0,0.315500,0.0,0.0,0.0,0.0,0.0 +0,0.315600,0.0,0.0,0.0,0.0,0.0 +0,0.315700,0.0,0.0,0.0,0.0,0.0 +0,0.315800,0.0,0.0,0.0,0.0,0.0 +0,0.315900,0.0,0.0,0.0,0.0,0.0 +0,0.316000,0.0,0.0,0.0,0.0,0.0 +0,0.316100,0.0,0.0,0.0,0.0,0.0 +0,0.316200,0.0,0.0,0.0,0.0,0.0 +0,0.316300,0.0,0.0,0.0,0.0,0.0 +0,0.316400,0.0,0.0,0.0,0.0,0.0 +0,0.316500,0.0,0.0,0.0,0.0,0.0 +0,0.316600,0.0,0.0,0.0,0.0,0.0 +0,0.316700,0.0,0.0,0.0,0.0,0.0 +0,0.316800,0.0,0.0,0.0,0.0,0.0 +0,0.316900,0.0,0.0,0.0,0.0,0.0 +0,0.317000,0.0,0.0,0.0,0.0,0.0 +0,0.317100,0.0,0.0,0.0,0.0,0.0 +0,0.317200,0.0,0.0,0.0,0.0,0.0 +0,0.317300,0.0,0.0,0.0,0.0,0.0 +0,0.317400,0.0,0.0,0.0,0.0,0.0 +0,0.317500,0.0,0.0,0.0,0.0,0.0 +0,0.317600,0.0,0.0,0.0,0.0,0.0 +0,0.317700,0.0,0.0,0.0,0.0,0.0 +0,0.317800,0.0,0.0,0.0,0.0,0.0 +0,0.317900,0.0,0.0,0.0,0.0,0.0 +0,0.318000,0.0,0.0,0.0,0.0,0.0 +0,0.318100,0.0,0.0,0.0,0.0,0.0 +0,0.318200,0.0,0.0,0.0,0.0,0.0 +0,0.318300,0.0,0.0,0.0,0.0,0.0 +0,0.318400,0.0,0.0,0.0,0.0,0.0 +0,0.318500,0.0,0.0,0.0,0.0,0.0 +0,0.318600,0.0,0.0,0.0,0.0,0.0 +0,0.318700,0.0,0.0,0.0,0.0,0.0 +0,0.318800,0.0,0.0,0.0,0.0,0.0 +0,0.318900,0.0,0.0,0.0,0.0,0.0 +0,0.319000,0.0,0.0,0.0,0.0,0.0 +0,0.319100,0.0,0.0,0.0,0.0,0.0 +0,0.319200,0.0,0.0,0.0,0.0,0.0 +0,0.319300,0.0,0.0,0.0,0.0,0.0 +0,0.319400,0.0,0.0,0.0,0.0,0.0 +0,0.319500,0.0,0.0,0.0,0.0,0.0 +0,0.319600,0.0,0.0,0.0,0.0,0.0 +0,0.319700,0.0,0.0,0.0,0.0,0.0 +0,0.319800,0.0,0.0,0.0,0.0,0.0 +0,0.319900,0.0,0.0,0.0,0.0,0.0 +0,0.320000,0.0,0.0,0.0,0.0,0.0 +0,0.320100,0.0,0.0,0.0,0.0,0.0 +1,13.672542,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.320200,0.0,0.0,0.0,0.0,0.0 +0,0.320300,0.0,0.0,0.0,0.0,0.0 +0,0.320400,0.0,0.0,0.0,0.0,0.0 +0,0.320500,0.0,0.0,0.0,0.0,0.0 +0,0.320600,0.0,0.0,0.0,0.0,0.0 +0,0.320700,0.0,0.0,0.0,0.0,0.0 +0,0.320800,0.0,0.0,0.0,0.0,0.0 +0,0.320900,0.0,0.0,0.0,0.0,0.0 +0,0.321000,0.0,0.0,0.0,0.0,0.0 +0,0.321100,0.0,0.0,0.0,0.0,0.0 +0,0.321200,0.0,0.0,0.0,0.0,0.0 +0,0.321300,0.0,0.0,0.0,0.0,0.0 +0,0.321400,0.0,0.0,0.0,0.0,0.0 +0,0.321500,0.0,0.0,0.0,0.0,0.0 +0,0.321600,0.0,0.0,0.0,0.0,0.0 +0,0.321700,0.0,0.0,0.0,0.0,0.0 +0,0.321800,0.0,0.0,0.0,0.0,0.0 +0,0.321900,0.0,0.0,0.0,0.0,0.0 +0,0.322000,0.0,0.0,0.0,0.0,0.0 +0,0.322100,0.0,0.0,0.0,0.0,0.0 +0,0.322200,0.0,0.0,0.0,0.0,0.0 +0,0.322300,0.0,0.0,0.0,0.0,0.0 +0,0.322400,0.0,0.0,0.0,0.0,0.0 +0,0.322500,0.0,0.0,0.0,0.0,0.0 +0,0.322600,0.0,0.0,0.0,0.0,0.0 +0,0.322700,0.0,0.0,0.0,0.0,0.0 +0,0.322800,0.0,0.0,0.0,0.0,0.0 +0,0.322900,0.0,0.0,0.0,0.0,0.0 +0,0.323000,0.0,0.0,0.0,0.0,0.0 +0,0.323100,0.0,0.0,0.0,0.0,0.0 +0,0.323200,0.0,0.0,0.0,0.0,0.0 +0,0.323300,0.0,0.0,0.0,0.0,0.0 +0,0.323400,0.0,0.0,0.0,0.0,0.0 +0,0.323500,0.0,0.0,0.0,0.0,0.0 +0,0.323600,0.0,0.0,0.0,0.0,0.0 +0,0.323700,0.0,0.0,0.0,0.0,0.0 +0,0.323800,0.0,0.0,0.0,0.0,0.0 +0,0.323900,0.0,0.0,0.0,0.0,0.0 +0,0.324000,0.0,0.0,0.0,0.0,0.0 +0,0.324100,0.0,0.0,0.0,0.0,0.0 +0,0.324200,0.0,0.0,0.0,0.0,0.0 +0,0.324300,0.0,0.0,0.0,0.0,0.0 +0,0.324400,0.0,0.0,0.0,0.0,0.0 +0,0.324500,0.0,0.0,0.0,0.0,0.0 +0,0.324600,0.0,0.0,0.0,0.0,0.0 +0,0.324700,0.0,0.0,0.0,0.0,0.0 +0,0.324800,0.0,0.0,0.0,0.0,0.0 +0,0.324900,0.0,0.0,0.0,0.0,0.0 +0,0.325000,0.0,0.0,0.0,0.0,0.0 +0,0.325100,0.0,0.0,0.0,0.0,0.0 +0,0.325200,0.0,0.0,0.0,0.0,0.0 +0,0.325300,0.0,0.0,0.0,0.0,0.0 +0,0.325400,0.0,0.0,0.0,0.0,0.0 +0,0.325500,0.0,0.0,0.0,0.0,0.0 +0,0.325600,0.0,0.0,0.0,0.0,0.0 +0,0.325700,0.0,0.0,0.0,0.0,0.0 +0,0.325800,0.0,0.0,0.0,0.0,0.0 +0,0.325900,0.0,0.0,0.0,0.0,0.0 +0,0.326000,0.0,0.0,0.0,0.0,0.0 +0,0.326100,0.0,0.0,0.0,0.0,0.0 +0,0.326200,0.0,0.0,0.0,0.0,0.0 +0,0.326300,0.0,0.0,0.0,0.0,0.0 +0,0.326400,0.0,0.0,0.0,0.0,0.0 +0,0.326500,0.0,0.0,0.0,0.0,0.0 +0,0.326600,0.0,0.0,0.0,0.0,0.0 +0,0.326700,0.0,0.0,0.0,0.0,0.0 +0,0.326800,0.0,0.0,0.0,0.0,0.0 +0,0.326900,0.0,0.0,0.0,0.0,0.0 +0,0.327000,0.0,0.0,0.0,0.0,0.0 +0,0.327100,0.0,0.0,0.0,0.0,0.0 +0,0.327200,0.0,0.0,0.0,0.0,0.0 +0,0.327300,0.0,0.0,0.0,0.0,0.0 +0,0.327400,0.0,0.0,0.0,0.0,0.0 +0,0.327500,0.0,0.0,0.0,0.0,0.0 +0,0.327600,0.0,0.0,0.0,0.0,0.0 +0,0.327700,0.0,0.0,0.0,0.0,0.0 +0,0.327800,0.0,0.0,0.0,0.0,0.0 +0,0.327900,0.0,0.0,0.0,0.0,0.0 +0,0.328000,0.0,0.0,0.0,0.0,0.0 +0,0.328100,0.0,0.0,0.0,0.0,0.0 +0,0.328200,0.0,0.0,0.0,0.0,0.0 +0,0.328300,0.0,0.0,0.0,0.0,0.0 +0,0.328400,0.0,0.0,0.0,0.0,0.0 +0,0.328500,0.0,0.0,0.0,0.0,0.0 +0,0.328600,0.0,0.0,0.0,0.0,0.0 +0,0.328700,0.0,0.0,0.0,0.0,0.0 +0,0.328800,0.0,0.0,0.0,0.0,0.0 +0,0.328900,0.0,0.0,0.0,0.0,0.0 +0,0.329000,0.0,0.0,0.0,0.0,0.0 +0,0.329100,0.0,0.0,0.0,0.0,0.0 +0,0.329200,0.0,0.0,0.0,0.0,0.0 +0,0.329300,0.0,0.0,0.0,0.0,0.0 +0,0.329400,0.0,0.0,0.0,0.0,0.0 +0,0.329500,0.0,0.0,0.0,0.0,0.0 +0,0.329600,0.0,0.0,0.0,0.0,0.0 +0,0.329700,0.0,0.0,0.0,0.0,0.0 +0,0.329800,0.0,0.0,0.0,0.0,0.0 +0,0.329900,0.0,0.0,0.0,0.0,0.0 +0,0.330000,0.0,0.0,0.0,0.0,0.0 +0,0.330100,0.0,0.0,0.0,0.0,0.0 +0,0.330200,0.0,0.0,0.0,0.0,0.0 +0,0.330300,0.0,0.0,0.0,0.0,0.0 +0,0.330400,0.0,0.0,0.0,0.0,0.0 +0,0.330500,0.0,0.0,0.0,0.0,0.0 +0,0.330600,0.0,0.0,0.0,0.0,0.0 +0,0.330700,0.0,0.0,0.0,0.0,0.0 +0,0.330800,0.0,0.0,0.0,0.0,0.0 +0,0.330900,0.0,0.0,0.0,0.0,0.0 +0,0.331000,0.0,0.0,0.0,0.0,0.0 +0,0.331100,0.0,0.0,0.0,0.0,0.0 +0,0.331200,0.0,0.0,0.0,0.0,0.0 +0,0.331300,0.0,0.0,0.0,0.0,0.0 +0,0.331400,0.0,0.0,0.0,0.0,0.0 +0,0.331500,0.0,0.0,0.0,0.0,0.0 +0,0.331600,0.0,0.0,0.0,0.0,0.0 +0,0.331700,0.0,0.0,0.0,0.0,0.0 +0,0.331800,0.0,0.0,0.0,0.0,0.0 +0,0.331900,0.0,0.0,0.0,0.0,0.0 +0,0.332000,0.0,0.0,0.0,0.0,0.0 +0,0.332100,0.0,0.0,0.0,0.0,0.0 +0,0.332200,0.0,0.0,0.0,0.0,0.0 +0,0.332300,0.0,0.0,0.0,0.0,0.0 +0,0.332400,0.0,0.0,0.0,0.0,0.0 +0,0.332500,0.0,0.0,0.0,0.0,0.0 +0,0.332600,0.0,0.0,0.0,0.0,0.0 +0,0.332700,0.0,0.0,0.0,0.0,0.0 +0,0.332800,0.0,0.0,0.0,0.0,0.0 +0,0.332900,0.0,0.0,0.0,0.0,0.0 +0,0.333000,0.0,0.0,0.0,0.0,0.0 +0,0.333100,0.0,0.0,0.0,0.0,0.0 +0,0.333200,0.0,0.0,0.0,0.0,0.0 +0,0.333300,0.0,0.0,0.0,0.0,0.0 +0,0.333400,0.0,0.0,0.0,0.0,0.0 +0,0.333500,0.0,0.0,0.0,0.0,0.0 +0,0.333600,0.0,0.0,0.0,0.0,0.0 +0,0.333700,0.0,0.0,0.0,0.0,0.0 +0,0.333800,0.0,0.0,0.0,0.0,0.0 +0,0.333900,0.0,0.0,0.0,0.0,0.0 +0,0.334000,0.0,0.0,0.0,0.0,0.0 +0,0.334100,0.0,0.0,0.0,0.0,0.0 +0,0.334200,0.0,0.0,0.0,0.0,0.0 +0,0.334300,0.0,0.0,0.0,0.0,0.0 +0,0.334400,0.0,0.0,0.0,0.0,0.0 +0,0.334500,0.0,0.0,0.0,0.0,0.0 +0,0.334600,0.0,0.0,0.0,0.0,0.0 +0,0.334700,0.0,0.0,0.0,0.0,0.0 +0,0.334800,0.0,0.0,0.0,0.0,0.0 +0,0.334900,0.0,0.0,0.0,0.0,0.0 +0,0.335000,0.0,0.0,0.0,0.0,0.0 +0,0.335100,0.0,0.0,0.0,0.0,0.0 +0,0.335200,0.0,0.0,0.0,0.0,0.0 +0,0.335300,0.0,0.0,0.0,0.0,0.0 +0,0.335400,0.0,0.0,0.0,0.0,0.0 +0,0.335500,0.0,0.0,0.0,0.0,0.0 +0,0.335600,0.0,0.0,0.0,0.0,0.0 +0,0.335700,0.0,0.0,0.0,0.0,0.0 +0,0.335800,0.0,0.0,0.0,0.0,0.0 +0,0.335900,0.0,0.0,0.0,0.0,0.0 +0,0.336000,0.0,0.0,0.0,0.0,0.0 +0,0.336100,0.0,0.0,0.0,0.0,0.0 +0,0.336200,0.0,0.0,0.0,0.0,0.0 +0,0.336300,0.0,0.0,0.0,0.0,0.0 +0,0.336400,0.0,0.0,0.0,0.0,0.0 +0,0.336500,0.0,0.0,0.0,0.0,0.0 +0,0.336600,0.0,0.0,0.0,0.0,0.0 +0,0.336700,0.0,0.0,0.0,0.0,0.0 +0,0.336800,0.0,0.0,0.0,0.0,0.0 +0,0.336900,0.0,0.0,0.0,0.0,0.0 +0,0.337000,0.0,0.0,0.0,0.0,0.0 +0,0.337100,0.0,0.0,0.0,0.0,0.0 +0,0.337200,0.0,0.0,0.0,0.0,0.0 +0,0.337300,0.0,0.0,0.0,0.0,0.0 +0,0.337400,0.0,0.0,0.0,0.0,0.0 +0,0.337500,0.0,0.0,0.0,0.0,0.0 +0,0.337600,0.0,0.0,0.0,0.0,0.0 +0,0.337700,0.0,0.0,0.0,0.0,0.0 +0,0.337800,0.0,0.0,0.0,0.0,0.0 +0,0.337900,0.0,0.0,0.0,0.0,0.0 +0,0.338000,0.0,0.0,0.0,0.0,0.0 +0,0.338100,0.0,0.0,0.0,0.0,0.0 +0,0.338200,0.0,0.0,0.0,0.0,0.0 +0,0.338300,0.0,0.0,0.0,0.0,0.0 +0,0.338400,0.0,0.0,0.0,0.0,0.0 +0,0.338500,0.0,0.0,0.0,0.0,0.0 +0,0.338600,0.0,0.0,0.0,0.0,0.0 +0,0.338700,0.0,0.0,0.0,0.0,0.0 +0,0.338800,0.0,0.0,0.0,0.0,0.0 +0,0.338900,0.0,0.0,0.0,0.0,0.0 +0,0.339000,0.0,0.0,0.0,0.0,0.0 +0,0.339100,0.0,0.0,0.0,0.0,0.0 +0,0.339200,0.0,0.0,0.0,0.0,0.0 +0,0.339300,0.0,0.0,0.0,0.0,0.0 +0,0.339400,0.0,0.0,0.0,0.0,0.0 +0,0.339500,0.0,0.0,0.0,0.0,0.0 +0,0.339600,0.0,0.0,0.0,0.0,0.0 +0,0.339700,0.0,0.0,0.0,0.0,0.0 +0,0.339800,0.0,0.0,0.0,0.0,0.0 +0,0.339900,0.0,0.0,0.0,0.0,0.0 +0,0.340000,0.0,0.0,0.0,0.0,0.0 +0,0.340100,0.0,0.0,0.0,0.0,0.0 +1,16.398351,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.340200,0.0,0.0,0.0,0.0,0.0 +0,0.340300,0.0,0.0,0.0,0.0,0.0 +0,0.340400,0.0,0.0,0.0,0.0,0.0 +0,0.340500,0.0,0.0,0.0,0.0,0.0 +0,0.340600,0.0,0.0,0.0,0.0,0.0 +0,0.340700,0.0,0.0,0.0,0.0,0.0 +0,0.340800,0.0,0.0,0.0,0.0,0.0 +0,0.340900,0.0,0.0,0.0,0.0,0.0 +0,0.341000,0.0,0.0,0.0,0.0,0.0 +0,0.341100,0.0,0.0,0.0,0.0,0.0 +0,0.341200,0.0,0.0,0.0,0.0,0.0 +0,0.341300,0.0,0.0,0.0,0.0,0.0 +0,0.341400,0.0,0.0,0.0,0.0,0.0 +0,0.341500,0.0,0.0,0.0,0.0,0.0 +0,0.341600,0.0,0.0,0.0,0.0,0.0 +0,0.341700,0.0,0.0,0.0,0.0,0.0 +0,0.341800,0.0,0.0,0.0,0.0,0.0 +0,0.341900,0.0,0.0,0.0,0.0,0.0 +0,0.342000,0.0,0.0,0.0,0.0,0.0 +0,0.342100,0.0,0.0,0.0,0.0,0.0 +0,0.342200,0.0,0.0,0.0,0.0,0.0 +0,0.342300,0.0,0.0,0.0,0.0,0.0 +0,0.342400,0.0,0.0,0.0,0.0,0.0 +0,0.342500,0.0,0.0,0.0,0.0,0.0 +0,0.342600,0.0,0.0,0.0,0.0,0.0 +0,0.342700,0.0,0.0,0.0,0.0,0.0 +0,0.342800,0.0,0.0,0.0,0.0,0.0 +0,0.342900,0.0,0.0,0.0,0.0,0.0 +0,0.343000,0.0,0.0,0.0,0.0,0.0 +0,0.343100,0.0,0.0,0.0,0.0,0.0 +0,0.343200,0.0,0.0,0.0,0.0,0.0 +0,0.343300,0.0,0.0,0.0,0.0,0.0 +0,0.343400,0.0,0.0,0.0,0.0,0.0 +0,0.343500,0.0,0.0,0.0,0.0,0.0 +0,0.343600,0.0,0.0,0.0,0.0,0.0 +0,0.343700,0.0,0.0,0.0,0.0,0.0 +0,0.343800,0.0,0.0,0.0,0.0,0.0 +0,0.343900,0.0,0.0,0.0,0.0,0.0 +0,0.344000,0.0,0.0,0.0,0.0,0.0 +0,0.344100,0.0,0.0,0.0,0.0,0.0 +0,0.344200,0.0,0.0,0.0,0.0,0.0 +0,0.344300,0.0,0.0,0.0,0.0,0.0 +0,0.344400,0.0,0.0,0.0,0.0,0.0 +0,0.344500,0.0,0.0,0.0,0.0,0.0 +0,0.344600,0.0,0.0,0.0,0.0,0.0 +0,0.344700,0.0,0.0,0.0,0.0,0.0 +0,0.344800,0.0,0.0,0.0,0.0,0.0 +0,0.344900,0.0,0.0,0.0,0.0,0.0 +0,0.345000,0.0,0.0,0.0,0.0,0.0 +0,0.345100,0.0,0.0,0.0,0.0,0.0 +0,0.345200,0.0,0.0,0.0,0.0,0.0 +0,0.345300,0.0,0.0,0.0,0.0,0.0 +0,0.345400,0.0,0.0,0.0,0.0,0.0 +0,0.345500,0.0,0.0,0.0,0.0,0.0 +0,0.345600,0.0,0.0,0.0,0.0,0.0 +0,0.345700,0.0,0.0,0.0,0.0,0.0 +0,0.345800,0.0,0.0,0.0,0.0,0.0 +0,0.345900,0.0,0.0,0.0,0.0,0.0 +0,0.346000,0.0,0.0,0.0,0.0,0.0 +0,0.346100,0.0,0.0,0.0,0.0,0.0 +0,0.346200,0.0,0.0,0.0,0.0,0.0 +0,0.346300,0.0,0.0,0.0,0.0,0.0 +0,0.346400,0.0,0.0,0.0,0.0,0.0 +0,0.346500,0.0,0.0,0.0,0.0,0.0 +0,0.346600,0.0,0.0,0.0,0.0,0.0 +0,0.346700,0.0,0.0,0.0,0.0,0.0 +0,0.346800,0.0,0.0,0.0,0.0,0.0 +0,0.346900,0.0,0.0,0.0,0.0,0.0 +0,0.347000,0.0,0.0,0.0,0.0,0.0 +0,0.347100,0.0,0.0,0.0,0.0,0.0 +0,0.347200,0.0,0.0,0.0,0.0,0.0 +0,0.347300,0.0,0.0,0.0,0.0,0.0 +0,0.347400,0.0,0.0,0.0,0.0,0.0 +0,0.347500,0.0,0.0,0.0,0.0,0.0 +0,0.347600,0.0,0.0,0.0,0.0,0.0 +0,0.347700,0.0,0.0,0.0,0.0,0.0 +0,0.347800,0.0,0.0,0.0,0.0,0.0 +0,0.347900,0.0,0.0,0.0,0.0,0.0 +0,0.348000,0.0,0.0,0.0,0.0,0.0 +0,0.348100,0.0,0.0,0.0,0.0,0.0 +0,0.348200,0.0,0.0,0.0,0.0,0.0 +0,0.348300,0.0,0.0,0.0,0.0,0.0 +0,0.348400,0.0,0.0,0.0,0.0,0.0 +0,0.348500,0.0,0.0,0.0,0.0,0.0 +0,0.348600,0.0,0.0,0.0,0.0,0.0 +0,0.348700,0.0,0.0,0.0,0.0,0.0 +0,0.348800,0.0,0.0,0.0,0.0,0.0 +0,0.348900,0.0,0.0,0.0,0.0,0.0 +0,0.349000,0.0,0.0,0.0,0.0,0.0 +0,0.349100,0.0,0.0,0.0,0.0,0.0 +0,0.349200,0.0,0.0,0.0,0.0,0.0 +0,0.349300,0.0,0.0,0.0,0.0,0.0 +0,0.349400,0.0,0.0,0.0,0.0,0.0 +0,0.349500,0.0,0.0,0.0,0.0,0.0 +0,0.349600,0.0,0.0,0.0,0.0,0.0 +0,0.349700,0.0,0.0,0.0,0.0,0.0 +0,0.349800,0.0,0.0,0.0,0.0,0.0 +0,0.349900,0.0,0.0,0.0,0.0,0.0 +0,0.350000,0.0,0.0,0.0,0.0,0.0 +0,0.350100,0.0,0.0,0.0,0.0,0.0 +0,0.350200,0.0,0.0,0.0,0.0,0.0 +0,0.350300,0.0,0.0,0.0,0.0,0.0 +0,0.350400,0.0,0.0,0.0,0.0,0.0 +0,0.350500,0.0,0.0,0.0,0.0,0.0 +0,0.350600,0.0,0.0,0.0,0.0,0.0 +0,0.350700,0.0,0.0,0.0,0.0,0.0 +0,0.350800,0.0,0.0,0.0,0.0,0.0 +0,0.350900,0.0,0.0,0.0,0.0,0.0 +0,0.351000,0.0,0.0,0.0,0.0,0.0 +0,0.351100,0.0,0.0,0.0,0.0,0.0 +0,0.351200,0.0,0.0,0.0,0.0,0.0 +0,0.351300,0.0,0.0,0.0,0.0,0.0 +0,0.351400,0.0,0.0,0.0,0.0,0.0 +0,0.351500,0.0,0.0,0.0,0.0,0.0 +0,0.351600,0.0,0.0,0.0,0.0,0.0 +0,0.351700,0.0,0.0,0.0,0.0,0.0 +0,0.351800,0.0,0.0,0.0,0.0,0.0 +0,0.351900,0.0,0.0,0.0,0.0,0.0 +0,0.352000,0.0,0.0,0.0,0.0,0.0 +0,0.352100,0.0,0.0,0.0,0.0,0.0 +0,0.352200,0.0,0.0,0.0,0.0,0.0 +0,0.352300,0.0,0.0,0.0,0.0,0.0 +0,0.352400,0.0,0.0,0.0,0.0,0.0 +0,0.352500,0.0,0.0,0.0,0.0,0.0 +0,0.352600,0.0,0.0,0.0,0.0,0.0 +0,0.352700,0.0,0.0,0.0,0.0,0.0 +0,0.352800,0.0,0.0,0.0,0.0,0.0 +0,0.352900,0.0,0.0,0.0,0.0,0.0 +0,0.353000,0.0,0.0,0.0,0.0,0.0 +0,0.353100,0.0,0.0,0.0,0.0,0.0 +0,0.353200,0.0,0.0,0.0,0.0,0.0 +0,0.353300,0.0,0.0,0.0,0.0,0.0 +0,0.353400,0.0,0.0,0.0,0.0,0.0 +0,0.353500,0.0,0.0,0.0,0.0,0.0 +0,0.353600,0.0,0.0,0.0,0.0,0.0 +0,0.353700,0.0,0.0,0.0,0.0,0.0 +0,0.353800,0.0,0.0,0.0,0.0,0.0 +0,0.353900,0.0,0.0,0.0,0.0,0.0 +0,0.354000,0.0,0.0,0.0,0.0,0.0 +0,0.354100,0.0,0.0,0.0,0.0,0.0 +0,0.354200,0.0,0.0,0.0,0.0,0.0 +0,0.354300,0.0,0.0,0.0,0.0,0.0 +0,0.354400,0.0,0.0,0.0,0.0,0.0 +0,0.354500,0.0,0.0,0.0,0.0,0.0 +0,0.354600,0.0,0.0,0.0,0.0,0.0 +0,0.354700,0.0,0.0,0.0,0.0,0.0 +0,0.354800,0.0,0.0,0.0,0.0,0.0 +0,0.354900,0.0,0.0,0.0,0.0,0.0 +0,0.355000,0.0,0.0,0.0,0.0,0.0 +0,0.355100,0.0,0.0,0.0,0.0,0.0 +0,0.355200,0.0,0.0,0.0,0.0,0.0 +0,0.355300,0.0,0.0,0.0,0.0,0.0 +0,0.355400,0.0,0.0,0.0,0.0,0.0 +0,0.355500,0.0,0.0,0.0,0.0,0.0 +0,0.355600,0.0,0.0,0.0,0.0,0.0 +0,0.355700,0.0,0.0,0.0,0.0,0.0 +0,0.355800,0.0,0.0,0.0,0.0,0.0 +0,0.355900,0.0,0.0,0.0,0.0,0.0 +0,0.356000,0.0,0.0,0.0,0.0,0.0 +0,0.356100,0.0,0.0,0.0,0.0,0.0 +0,0.356200,0.0,0.0,0.0,0.0,0.0 +0,0.356300,0.0,0.0,0.0,0.0,0.0 +0,0.356400,0.0,0.0,0.0,0.0,0.0 +0,0.356500,0.0,0.0,0.0,0.0,0.0 +0,0.356600,0.0,0.0,0.0,0.0,0.0 +0,0.356700,0.0,0.0,0.0,0.0,0.0 +0,0.356800,0.0,0.0,0.0,0.0,0.0 +0,0.356900,0.0,0.0,0.0,0.0,0.0 +0,0.357000,0.0,0.0,0.0,0.0,0.0 +0,0.357100,0.0,0.0,0.0,0.0,0.0 +0,0.357200,0.0,0.0,0.0,0.0,0.0 +0,0.357300,0.0,0.0,0.0,0.0,0.0 +0,0.357400,0.0,0.0,0.0,0.0,0.0 +0,0.357500,0.0,0.0,0.0,0.0,0.0 +0,0.357600,0.0,0.0,0.0,0.0,0.0 +0,0.357700,0.0,0.0,0.0,0.0,0.0 +0,0.357800,0.0,0.0,0.0,0.0,0.0 +0,0.357900,0.0,0.0,0.0,0.0,0.0 +0,0.358000,0.0,0.0,0.0,0.0,0.0 +0,0.358100,0.0,0.0,0.0,0.0,0.0 +0,0.358200,0.0,0.0,0.0,0.0,0.0 +0,0.358300,0.0,0.0,0.0,0.0,0.0 +0,0.358400,0.0,0.0,0.0,0.0,0.0 +0,0.358500,0.0,0.0,0.0,0.0,0.0 +0,0.358600,0.0,0.0,0.0,0.0,0.0 +0,0.358700,0.0,0.0,0.0,0.0,0.0 +0,0.358800,0.0,0.0,0.0,0.0,0.0 +0,0.358900,0.0,0.0,0.0,0.0,0.0 +0,0.359000,0.0,0.0,0.0,0.0,0.0 +0,0.359100,0.0,0.0,0.0,0.0,0.0 +0,0.359200,0.0,0.0,0.0,0.0,0.0 +0,0.359300,0.0,0.0,0.0,0.0,0.0 +0,0.359400,0.0,0.0,0.0,0.0,0.0 +0,0.359500,0.0,0.0,0.0,0.0,0.0 +0,0.359600,0.0,0.0,0.0,0.0,0.0 +0,0.359700,0.0,0.0,0.0,0.0,0.0 +0,0.359800,0.0,0.0,0.0,0.0,0.0 +0,0.359900,0.0,0.0,0.0,0.0,0.0 +0,0.360000,0.0,0.0,0.0,0.0,0.0 +0,0.360100,0.0,0.0,0.0,0.0,0.0 +1,19.464310,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.360200,0.0,0.0,0.0,0.0,0.0 +0,0.360300,0.0,0.0,0.0,0.0,0.0 +0,0.360400,0.0,0.0,0.0,0.0,0.0 +0,0.360500,0.0,0.0,0.0,0.0,0.0 +0,0.360600,0.0,0.0,0.0,0.0,0.0 +0,0.360700,0.0,0.0,0.0,0.0,0.0 +0,0.360800,0.0,0.0,0.0,0.0,0.0 +0,0.360900,0.0,0.0,0.0,0.0,0.0 +0,0.361000,0.0,0.0,0.0,0.0,0.0 +0,0.361100,0.0,0.0,0.0,0.0,0.0 +0,0.361200,0.0,0.0,0.0,0.0,0.0 +0,0.361300,0.0,0.0,0.0,0.0,0.0 +0,0.361400,0.0,0.0,0.0,0.0,0.0 +0,0.361500,0.0,0.0,0.0,0.0,0.0 +0,0.361600,0.0,0.0,0.0,0.0,0.0 +0,0.361700,0.0,0.0,0.0,0.0,0.0 +0,0.361800,0.0,0.0,0.0,0.0,0.0 +0,0.361900,0.0,0.0,0.0,0.0,0.0 +0,0.362000,0.0,0.0,0.0,0.0,0.0 +0,0.362100,0.0,0.0,0.0,0.0,0.0 +0,0.362200,0.0,0.0,0.0,0.0,0.0 +0,0.362300,0.0,0.0,0.0,0.0,0.0 +0,0.362400,0.0,0.0,0.0,0.0,0.0 +0,0.362500,0.0,0.0,0.0,0.0,0.0 +0,0.362600,0.0,0.0,0.0,0.0,0.0 +0,0.362700,0.0,0.0,0.0,0.0,0.0 +0,0.362800,0.0,0.0,0.0,0.0,0.0 +0,0.362900,0.0,0.0,0.0,0.0,0.0 +0,0.363000,0.0,0.0,0.0,0.0,0.0 +0,0.363100,0.0,0.0,0.0,0.0,0.0 +0,0.363200,0.0,0.0,0.0,0.0,0.0 +0,0.363300,0.0,0.0,0.0,0.0,0.0 +0,0.363400,0.0,0.0,0.0,0.0,0.0 +0,0.363500,0.0,0.0,0.0,0.0,0.0 +0,0.363600,0.0,0.0,0.0,0.0,0.0 +0,0.363700,0.0,0.0,0.0,0.0,0.0 +0,0.363800,0.0,0.0,0.0,0.0,0.0 +0,0.363900,0.0,0.0,0.0,0.0,0.0 +0,0.364000,0.0,0.0,0.0,0.0,0.0 +0,0.364100,0.0,0.0,0.0,0.0,0.0 +0,0.364200,0.0,0.0,0.0,0.0,0.0 +0,0.364300,0.0,0.0,0.0,0.0,0.0 +0,0.364400,0.0,0.0,0.0,0.0,0.0 +0,0.364500,0.0,0.0,0.0,0.0,0.0 +0,0.364600,0.0,0.0,0.0,0.0,0.0 +0,0.364700,0.0,0.0,0.0,0.0,0.0 +0,0.364800,0.0,0.0,0.0,0.0,0.0 +0,0.364900,0.0,0.0,0.0,0.0,0.0 +0,0.365000,0.0,0.0,0.0,0.0,0.0 +0,0.365100,0.0,0.0,0.0,0.0,0.0 +0,0.365200,0.0,0.0,0.0,0.0,0.0 +0,0.365300,0.0,0.0,0.0,0.0,0.0 +0,0.365400,0.0,0.0,0.0,0.0,0.0 +0,0.365500,0.0,0.0,0.0,0.0,0.0 +0,0.365600,0.0,0.0,0.0,0.0,0.0 +0,0.365700,0.0,0.0,0.0,0.0,0.0 +0,0.365800,0.0,0.0,0.0,0.0,0.0 +0,0.365900,0.0,0.0,0.0,0.0,0.0 +0,0.366000,0.0,0.0,0.0,0.0,0.0 +0,0.366100,0.0,0.0,0.0,0.0,0.0 +0,0.366200,0.0,0.0,0.0,0.0,0.0 +0,0.366300,0.0,0.0,0.0,0.0,0.0 +0,0.366400,0.0,0.0,0.0,0.0,0.0 +0,0.366500,0.0,0.0,0.0,0.0,0.0 +0,0.366600,0.0,0.0,0.0,0.0,0.0 +0,0.366700,0.0,0.0,0.0,0.0,0.0 +0,0.366800,0.0,0.0,0.0,0.0,0.0 +0,0.366900,0.0,0.0,0.0,0.0,0.0 +0,0.367000,0.0,0.0,0.0,0.0,0.0 +0,0.367100,0.0,0.0,0.0,0.0,0.0 +0,0.367200,0.0,0.0,0.0,0.0,0.0 +0,0.367300,0.0,0.0,0.0,0.0,0.0 +0,0.367400,0.0,0.0,0.0,0.0,0.0 +0,0.367500,0.0,0.0,0.0,0.0,0.0 +0,0.367600,0.0,0.0,0.0,0.0,0.0 +0,0.367700,0.0,0.0,0.0,0.0,0.0 +0,0.367800,0.0,0.0,0.0,0.0,0.0 +0,0.367900,0.0,0.0,0.0,0.0,0.0 +0,0.368000,0.0,0.0,0.0,0.0,0.0 +0,0.368100,0.0,0.0,0.0,0.0,0.0 +0,0.368200,0.0,0.0,0.0,0.0,0.0 +0,0.368300,0.0,0.0,0.0,0.0,0.0 +0,0.368400,0.0,0.0,0.0,0.0,0.0 +0,0.368500,0.0,0.0,0.0,0.0,0.0 +0,0.368600,0.0,0.0,0.0,0.0,0.0 +0,0.368700,0.0,0.0,0.0,0.0,0.0 +0,0.368800,0.0,0.0,0.0,0.0,0.0 +0,0.368900,0.0,0.0,0.0,0.0,0.0 +0,0.369000,0.0,0.0,0.0,0.0,0.0 +0,0.369100,0.0,0.0,0.0,0.0,0.0 +0,0.369200,0.0,0.0,0.0,0.0,0.0 +0,0.369300,0.0,0.0,0.0,0.0,0.0 +0,0.369400,0.0,0.0,0.0,0.0,0.0 +0,0.369500,0.0,0.0,0.0,0.0,0.0 +0,0.369600,0.0,0.0,0.0,0.0,0.0 +0,0.369700,0.0,0.0,0.0,0.0,0.0 +0,0.369800,0.0,0.0,0.0,0.0,0.0 +0,0.369900,0.0,0.0,0.0,0.0,0.0 +0,0.370000,0.0,0.0,0.0,0.0,0.0 +0,0.370100,0.0,0.0,0.0,0.0,0.0 +0,0.370200,0.0,0.0,0.0,0.0,0.0 +0,0.370300,0.0,0.0,0.0,0.0,0.0 +0,0.370400,0.0,0.0,0.0,0.0,0.0 +0,0.370500,0.0,0.0,0.0,0.0,0.0 +0,0.370600,0.0,0.0,0.0,0.0,0.0 +0,0.370700,0.0,0.0,0.0,0.0,0.0 +0,0.370800,0.0,0.0,0.0,0.0,0.0 +0,0.370900,0.0,0.0,0.0,0.0,0.0 +0,0.371000,0.0,0.0,0.0,0.0,0.0 +0,0.371100,0.0,0.0,0.0,0.0,0.0 +0,0.371200,0.0,0.0,0.0,0.0,0.0 +0,0.371300,0.0,0.0,0.0,0.0,0.0 +0,0.371400,0.0,0.0,0.0,0.0,0.0 +0,0.371500,0.0,0.0,0.0,0.0,0.0 +0,0.371600,0.0,0.0,0.0,0.0,0.0 +0,0.371700,0.0,0.0,0.0,0.0,0.0 +0,0.371800,0.0,0.0,0.0,0.0,0.0 +0,0.371900,0.0,0.0,0.0,0.0,0.0 +0,0.372000,0.0,0.0,0.0,0.0,0.0 +0,0.372100,0.0,0.0,0.0,0.0,0.0 +0,0.372200,0.0,0.0,0.0,0.0,0.0 +0,0.372300,0.0,0.0,0.0,0.0,0.0 +0,0.372400,0.0,0.0,0.0,0.0,0.0 +0,0.372500,0.0,0.0,0.0,0.0,0.0 +0,0.372600,0.0,0.0,0.0,0.0,0.0 +0,0.372700,0.0,0.0,0.0,0.0,0.0 +0,0.372800,0.0,0.0,0.0,0.0,0.0 +0,0.372900,0.0,0.0,0.0,0.0,0.0 +0,0.373000,0.0,0.0,0.0,0.0,0.0 +0,0.373100,0.0,0.0,0.0,0.0,0.0 +0,0.373200,0.0,0.0,0.0,0.0,0.0 +0,0.373300,0.0,0.0,0.0,0.0,0.0 +0,0.373400,0.0,0.0,0.0,0.0,0.0 +0,0.373500,0.0,0.0,0.0,0.0,0.0 +0,0.373600,0.0,0.0,0.0,0.0,0.0 +0,0.373700,0.0,0.0,0.0,0.0,0.0 +0,0.373800,0.0,0.0,0.0,0.0,0.0 +0,0.373900,0.0,0.0,0.0,0.0,0.0 +0,0.374000,0.0,0.0,0.0,0.0,0.0 +0,0.374100,0.0,0.0,0.0,0.0,0.0 +0,0.374200,0.0,0.0,0.0,0.0,0.0 +0,0.374300,0.0,0.0,0.0,0.0,0.0 +0,0.374400,0.0,0.0,0.0,0.0,0.0 +0,0.374500,0.0,0.0,0.0,0.0,0.0 +0,0.374600,0.0,0.0,0.0,0.0,0.0 +0,0.374700,0.0,0.0,0.0,0.0,0.0 +0,0.374800,0.0,0.0,0.0,0.0,0.0 +0,0.374900,0.0,0.0,0.0,0.0,0.0 +0,0.375000,0.0,0.0,0.0,0.0,0.0 +0,0.375100,0.0,0.0,0.0,0.0,0.0 +0,0.375200,0.0,0.0,0.0,0.0,0.0 +0,0.375300,0.0,0.0,0.0,0.0,0.0 +0,0.375400,0.0,0.0,0.0,0.0,0.0 +0,0.375500,0.0,0.0,0.0,0.0,0.0 +0,0.375600,0.0,0.0,0.0,0.0,0.0 +0,0.375700,0.0,0.0,0.0,0.0,0.0 +0,0.375800,0.0,0.0,0.0,0.0,0.0 +0,0.375900,0.0,0.0,0.0,0.0,0.0 +0,0.376000,0.0,0.0,0.0,0.0,0.0 +0,0.376100,0.0,0.0,0.0,0.0,0.0 +0,0.376200,0.0,0.0,0.0,0.0,0.0 +0,0.376300,0.0,0.0,0.0,0.0,0.0 +0,0.376400,0.0,0.0,0.0,0.0,0.0 +0,0.376500,0.0,0.0,0.0,0.0,0.0 +0,0.376600,0.0,0.0,0.0,0.0,0.0 +0,0.376700,0.0,0.0,0.0,0.0,0.0 +0,0.376800,0.0,0.0,0.0,0.0,0.0 +0,0.376900,0.0,0.0,0.0,0.0,0.0 +0,0.377000,0.0,0.0,0.0,0.0,0.0 +0,0.377100,0.0,0.0,0.0,0.0,0.0 +0,0.377200,0.0,0.0,0.0,0.0,0.0 +0,0.377300,0.0,0.0,0.0,0.0,0.0 +0,0.377400,0.0,0.0,0.0,0.0,0.0 +0,0.377500,0.0,0.0,0.0,0.0,0.0 +0,0.377600,0.0,0.0,0.0,0.0,0.0 +0,0.377700,0.0,0.0,0.0,0.0,0.0 +0,0.377800,0.0,0.0,0.0,0.0,0.0 +0,0.377900,0.0,0.0,0.0,0.0,0.0 +0,0.378000,0.0,0.0,0.0,0.0,0.0 +0,0.378100,0.0,0.0,0.0,0.0,0.0 +0,0.378200,0.0,0.0,0.0,0.0,0.0 +0,0.378300,0.0,0.0,0.0,0.0,0.0 +0,0.378400,0.0,0.0,0.0,0.0,0.0 +0,0.378500,0.0,0.0,0.0,0.0,0.0 +0,0.378600,0.0,0.0,0.0,0.0,0.0 +0,0.378700,0.0,0.0,0.0,0.0,0.0 +0,0.378800,0.0,0.0,0.0,0.0,0.0 +0,0.378900,0.0,0.0,0.0,0.0,0.0 +0,0.379000,0.0,0.0,0.0,0.0,0.0 +0,0.379100,0.0,0.0,0.0,0.0,0.0 +0,0.379200,0.0,0.0,0.0,0.0,0.0 +0,0.379300,0.0,0.0,0.0,0.0,0.0 +0,0.379400,0.0,0.0,0.0,0.0,0.0 +0,0.379500,0.0,0.0,0.0,0.0,0.0 +0,0.379600,0.0,0.0,0.0,0.0,0.0 +0,0.379700,0.0,0.0,0.0,0.0,0.0 +0,0.379800,0.0,0.0,0.0,0.0,0.0 +0,0.379900,0.0,0.0,0.0,0.0,0.0 +0,0.380000,0.0,0.0,0.0,0.0,0.0 +0,0.380100,0.0,0.0,0.0,0.0,0.0 +1,22.890419,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.380200,0.0,0.0,0.0,0.0,0.0 +0,0.380300,0.0,0.0,0.0,0.0,0.0 +0,0.380400,0.0,0.0,0.0,0.0,0.0 +0,0.380500,0.0,0.0,0.0,0.0,0.0 +0,0.380600,0.0,0.0,0.0,0.0,0.0 +0,0.380700,0.0,0.0,0.0,0.0,0.0 +0,0.380800,0.0,0.0,0.0,0.0,0.0 +0,0.380900,0.0,0.0,0.0,0.0,0.0 +0,0.381000,0.0,0.0,0.0,0.0,0.0 +0,0.381100,0.0,0.0,0.0,0.0,0.0 +0,0.381200,0.0,0.0,0.0,0.0,0.0 +0,0.381300,0.0,0.0,0.0,0.0,0.0 +0,0.381400,0.0,0.0,0.0,0.0,0.0 +0,0.381500,0.0,0.0,0.0,0.0,0.0 +0,0.381600,0.0,0.0,0.0,0.0,0.0 +0,0.381700,0.0,0.0,0.0,0.0,0.0 +0,0.381800,0.0,0.0,0.0,0.0,0.0 +0,0.381900,0.0,0.0,0.0,0.0,0.0 +0,0.382000,0.0,0.0,0.0,0.0,0.0 +0,0.382100,0.0,0.0,0.0,0.0,0.0 +0,0.382200,0.0,0.0,0.0,0.0,0.0 +0,0.382300,0.0,0.0,0.0,0.0,0.0 +0,0.382400,0.0,0.0,0.0,0.0,0.0 +0,0.382500,0.0,0.0,0.0,0.0,0.0 +0,0.382600,0.0,0.0,0.0,0.0,0.0 +0,0.382700,0.0,0.0,0.0,0.0,0.0 +0,0.382800,0.0,0.0,0.0,0.0,0.0 +0,0.382900,0.0,0.0,0.0,0.0,0.0 +0,0.383000,0.0,0.0,0.0,0.0,0.0 +0,0.383100,0.0,0.0,0.0,0.0,0.0 +0,0.383200,0.0,0.0,0.0,0.0,0.0 +0,0.383300,0.0,0.0,0.0,0.0,0.0 +0,0.383400,0.0,0.0,0.0,0.0,0.0 +0,0.383500,0.0,0.0,0.0,0.0,0.0 +0,0.383600,0.0,0.0,0.0,0.0,0.0 +0,0.383700,0.0,0.0,0.0,0.0,0.0 +0,0.383800,0.0,0.0,0.0,0.0,0.0 +0,0.383900,0.0,0.0,0.0,0.0,0.0 +0,0.384000,0.0,0.0,0.0,0.0,0.0 +0,0.384100,0.0,0.0,0.0,0.0,0.0 +0,0.384200,0.0,0.0,0.0,0.0,0.0 +0,0.384300,0.0,0.0,0.0,0.0,0.0 +0,0.384400,0.0,0.0,0.0,0.0,0.0 +0,0.384500,0.0,0.0,0.0,0.0,0.0 +0,0.384600,0.0,0.0,0.0,0.0,0.0 +0,0.384700,0.0,0.0,0.0,0.0,0.0 +0,0.384800,0.0,0.0,0.0,0.0,0.0 +0,0.384900,0.0,0.0,0.0,0.0,0.0 +0,0.385000,0.0,0.0,0.0,0.0,0.0 +0,0.385100,0.0,0.0,0.0,0.0,0.0 +0,0.385200,0.0,0.0,0.0,0.0,0.0 +0,0.385300,0.0,0.0,0.0,0.0,0.0 +0,0.385400,0.0,0.0,0.0,0.0,0.0 +0,0.385500,0.0,0.0,0.0,0.0,0.0 +0,0.385600,0.0,0.0,0.0,0.0,0.0 +0,0.385700,0.0,0.0,0.0,0.0,0.0 +0,0.385800,0.0,0.0,0.0,0.0,0.0 +0,0.385900,0.0,0.0,0.0,0.0,0.0 +0,0.386000,0.0,0.0,0.0,0.0,0.0 +0,0.386100,0.0,0.0,0.0,0.0,0.0 +0,0.386200,0.0,0.0,0.0,0.0,0.0 +0,0.386300,0.0,0.0,0.0,0.0,0.0 +0,0.386400,0.0,0.0,0.0,0.0,0.0 +0,0.386500,0.0,0.0,0.0,0.0,0.0 +0,0.386600,0.0,0.0,0.0,0.0,0.0 +0,0.386700,0.0,0.0,0.0,0.0,0.0 +0,0.386800,0.0,0.0,0.0,0.0,0.0 +0,0.386900,0.0,0.0,0.0,0.0,0.0 +0,0.387000,0.0,0.0,0.0,0.0,0.0 +0,0.387100,0.0,0.0,0.0,0.0,0.0 +0,0.387200,0.0,0.0,0.0,0.0,0.0 +0,0.387300,0.0,0.0,0.0,0.0,0.0 +0,0.387400,0.0,0.0,0.0,0.0,0.0 +0,0.387500,0.0,0.0,0.0,0.0,0.0 +0,0.387600,0.0,0.0,0.0,0.0,0.0 +0,0.387700,0.0,0.0,0.0,0.0,0.0 +0,0.387800,0.0,0.0,0.0,0.0,0.0 +0,0.387900,0.0,0.0,0.0,0.0,0.0 +0,0.388000,0.0,0.0,0.0,0.0,0.0 +0,0.388100,0.0,0.0,0.0,0.0,0.0 +0,0.388200,0.0,0.0,0.0,0.0,0.0 +0,0.388300,0.0,0.0,0.0,0.0,0.0 +0,0.388400,0.0,0.0,0.0,0.0,0.0 +0,0.388500,0.0,0.0,0.0,0.0,0.0 +0,0.388600,0.0,0.0,0.0,0.0,0.0 +0,0.388700,0.0,0.0,0.0,0.0,0.0 +0,0.388800,0.0,0.0,0.0,0.0,0.0 +0,0.388900,0.0,0.0,0.0,0.0,0.0 +0,0.389000,0.0,0.0,0.0,0.0,0.0 +0,0.389100,0.0,0.0,0.0,0.0,0.0 +0,0.389200,0.0,0.0,0.0,0.0,0.0 +0,0.389300,0.0,0.0,0.0,0.0,0.0 +0,0.389400,0.0,0.0,0.0,0.0,0.0 +0,0.389500,0.0,0.0,0.0,0.0,0.0 +0,0.389600,0.0,0.0,0.0,0.0,0.0 +0,0.389700,0.0,0.0,0.0,0.0,0.0 +0,0.389800,0.0,0.0,0.0,0.0,0.0 +0,0.389900,0.0,0.0,0.0,0.0,0.0 +0,0.390000,0.0,0.0,0.0,0.0,0.0 +0,0.390100,0.0,0.0,0.0,0.0,0.0 +0,0.390200,0.0,0.0,0.0,0.0,0.0 +0,0.390300,0.0,0.0,0.0,0.0,0.0 +0,0.390400,0.0,0.0,0.0,0.0,0.0 +0,0.390500,0.0,0.0,0.0,0.0,0.0 +0,0.390600,0.0,0.0,0.0,0.0,0.0 +0,0.390700,0.0,0.0,0.0,0.0,0.0 +0,0.390800,0.0,0.0,0.0,0.0,0.0 +0,0.390900,0.0,0.0,0.0,0.0,0.0 +0,0.391000,0.0,0.0,0.0,0.0,0.0 +0,0.391100,0.0,0.0,0.0,0.0,0.0 +0,0.391200,0.0,0.0,0.0,0.0,0.0 +0,0.391300,0.0,0.0,0.0,0.0,0.0 +0,0.391400,0.0,0.0,0.0,0.0,0.0 +0,0.391500,0.0,0.0,0.0,0.0,0.0 +0,0.391600,0.0,0.0,0.0,0.0,0.0 +0,0.391700,0.0,0.0,0.0,0.0,0.0 +0,0.391800,0.0,0.0,0.0,0.0,0.0 +0,0.391900,0.0,0.0,0.0,0.0,0.0 +0,0.392000,0.0,0.0,0.0,0.0,0.0 +0,0.392100,0.0,0.0,0.0,0.0,0.0 +0,0.392200,0.0,0.0,0.0,0.0,0.0 +0,0.392300,0.0,0.0,0.0,0.0,0.0 +0,0.392400,0.0,0.0,0.0,0.0,0.0 +0,0.392500,0.0,0.0,0.0,0.0,0.0 +0,0.392600,0.0,0.0,0.0,0.0,0.0 +0,0.392700,0.0,0.0,0.0,0.0,0.0 +0,0.392800,0.0,0.0,0.0,0.0,0.0 +0,0.392900,0.0,0.0,0.0,0.0,0.0 +0,0.393000,0.0,0.0,0.0,0.0,0.0 +0,0.393100,0.0,0.0,0.0,0.0,0.0 +0,0.393200,0.0,0.0,0.0,0.0,0.0 +0,0.393300,0.0,0.0,0.0,0.0,0.0 +0,0.393400,0.0,0.0,0.0,0.0,0.0 +0,0.393500,0.0,0.0,0.0,0.0,0.0 +0,0.393600,0.0,0.0,0.0,0.0,0.0 +0,0.393700,0.0,0.0,0.0,0.0,0.0 +0,0.393800,0.0,0.0,0.0,0.0,0.0 +0,0.393900,0.0,0.0,0.0,0.0,0.0 +0,0.394000,0.0,0.0,0.0,0.0,0.0 +0,0.394100,0.0,0.0,0.0,0.0,0.0 +0,0.394200,0.0,0.0,0.0,0.0,0.0 +0,0.394300,0.0,0.0,0.0,0.0,0.0 +0,0.394400,0.0,0.0,0.0,0.0,0.0 +0,0.394500,0.0,0.0,0.0,0.0,0.0 +0,0.394600,0.0,0.0,0.0,0.0,0.0 +0,0.394700,0.0,0.0,0.0,0.0,0.0 +0,0.394800,0.0,0.0,0.0,0.0,0.0 +0,0.394900,0.0,0.0,0.0,0.0,0.0 +0,0.395000,0.0,0.0,0.0,0.0,0.0 +0,0.395100,0.0,0.0,0.0,0.0,0.0 +0,0.395200,0.0,0.0,0.0,0.0,0.0 +0,0.395300,0.0,0.0,0.0,0.0,0.0 +0,0.395400,0.0,0.0,0.0,0.0,0.0 +0,0.395500,0.0,0.0,0.0,0.0,0.0 +0,0.395600,0.0,0.0,0.0,0.0,0.0 +0,0.395700,0.0,0.0,0.0,0.0,0.0 +0,0.395800,0.0,0.0,0.0,0.0,0.0 +0,0.395900,0.0,0.0,0.0,0.0,0.0 +0,0.396000,0.0,0.0,0.0,0.0,0.0 +0,0.396100,0.0,0.0,0.0,0.0,0.0 +0,0.396200,0.0,0.0,0.0,0.0,0.0 +0,0.396300,0.0,0.0,0.0,0.0,0.0 +0,0.396400,0.0,0.0,0.0,0.0,0.0 +0,0.396500,0.0,0.0,0.0,0.0,0.0 +0,0.396600,0.0,0.0,0.0,0.0,0.0 +0,0.396700,0.0,0.0,0.0,0.0,0.0 +0,0.396800,0.0,0.0,0.0,0.0,0.0 +0,0.396900,0.0,0.0,0.0,0.0,0.0 +0,0.397000,0.0,0.0,0.0,0.0,0.0 +0,0.397100,0.0,0.0,0.0,0.0,0.0 +0,0.397200,0.0,0.0,0.0,0.0,0.0 +0,0.397300,0.0,0.0,0.0,0.0,0.0 +0,0.397400,0.0,0.0,0.0,0.0,0.0 +0,0.397500,0.0,0.0,0.0,0.0,0.0 +0,0.397600,0.0,0.0,0.0,0.0,0.0 +0,0.397700,0.0,0.0,0.0,0.0,0.0 +0,0.397800,0.0,0.0,0.0,0.0,0.0 +0,0.397900,0.0,0.0,0.0,0.0,0.0 +0,0.398000,0.0,0.0,0.0,0.0,0.0 +0,0.398100,0.0,0.0,0.0,0.0,0.0 +0,0.398200,0.0,0.0,0.0,0.0,0.0 +0,0.398300,0.0,0.0,0.0,0.0,0.0 +0,0.398400,0.0,0.0,0.0,0.0,0.0 +0,0.398500,0.0,0.0,0.0,0.0,0.0 +0,0.398600,0.0,0.0,0.0,0.0,0.0 +0,0.398700,0.0,0.0,0.0,0.0,0.0 +0,0.398800,0.0,0.0,0.0,0.0,0.0 +0,0.398900,0.0,0.0,0.0,0.0,0.0 +0,0.399000,0.0,0.0,0.0,0.0,0.0 +0,0.399100,0.0,0.0,0.0,0.0,0.0 +0,0.399200,0.0,0.0,0.0,0.0,0.0 +0,0.399300,0.0,0.0,0.0,0.0,0.0 +0,0.399400,0.0,0.0,0.0,0.0,0.0 +0,0.399500,0.0,0.0,0.0,0.0,0.0 +0,0.399600,0.0,0.0,0.0,0.0,0.0 +0,0.399700,0.0,0.0,0.0,0.0,0.0 +0,0.399800,0.0,0.0,0.0,0.0,0.0 +0,0.399900,0.0,0.0,0.0,0.0,0.0 +0,0.400000,0.0,0.0,0.0,0.0,0.0 +0,0.400100,0.0,0.0,0.0,0.0,0.0 +1,26.696678,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.400200,0.0,0.0,0.0,0.0,0.0 +0,0.400300,0.0,0.0,0.0,0.0,0.0 +0,0.400400,0.0,0.0,0.0,0.0,0.0 +0,0.400500,0.0,0.0,0.0,0.0,0.0 +0,0.400600,0.0,0.0,0.0,0.0,0.0 +0,0.400700,0.0,0.0,0.0,0.0,0.0 +0,0.400800,0.0,0.0,0.0,0.0,0.0 +0,0.400900,0.0,0.0,0.0,0.0,0.0 +0,0.401000,0.0,0.0,0.0,0.0,0.0 +0,0.401100,0.0,0.0,0.0,0.0,0.0 +0,0.401200,0.0,0.0,0.0,0.0,0.0 +0,0.401300,0.0,0.0,0.0,0.0,0.0 +0,0.401400,0.0,0.0,0.0,0.0,0.0 +0,0.401500,0.0,0.0,0.0,0.0,0.0 +0,0.401600,0.0,0.0,0.0,0.0,0.0 +0,0.401700,0.0,0.0,0.0,0.0,0.0 +0,0.401800,0.0,0.0,0.0,0.0,0.0 +0,0.401900,0.0,0.0,0.0,0.0,0.0 +0,0.402000,0.0,0.0,0.0,0.0,0.0 +0,0.402100,0.0,0.0,0.0,0.0,0.0 +0,0.402200,0.0,0.0,0.0,0.0,0.0 +0,0.402300,0.0,0.0,0.0,0.0,0.0 +0,0.402400,0.0,0.0,0.0,0.0,0.0 +0,0.402500,0.0,0.0,0.0,0.0,0.0 +0,0.402600,0.0,0.0,0.0,0.0,0.0 +0,0.402700,0.0,0.0,0.0,0.0,0.0 +0,0.402800,0.0,0.0,0.0,0.0,0.0 +0,0.402900,0.0,0.0,0.0,0.0,0.0 +0,0.403000,0.0,0.0,0.0,0.0,0.0 +0,0.403100,0.0,0.0,0.0,0.0,0.0 +0,0.403200,0.0,0.0,0.0,0.0,0.0 +0,0.403300,0.0,0.0,0.0,0.0,0.0 +0,0.403400,0.0,0.0,0.0,0.0,0.0 +0,0.403500,0.0,0.0,0.0,0.0,0.0 +0,0.403600,0.0,0.0,0.0,0.0,0.0 +0,0.403700,0.0,0.0,0.0,0.0,0.0 +0,0.403800,0.0,0.0,0.0,0.0,0.0 +0,0.403900,0.0,0.0,0.0,0.0,0.0 +0,0.404000,0.0,0.0,0.0,0.0,0.0 +0,0.404100,0.0,0.0,0.0,0.0,0.0 +0,0.404200,0.0,0.0,0.0,0.0,0.0 +0,0.404300,0.0,0.0,0.0,0.0,0.0 +0,0.404400,0.0,0.0,0.0,0.0,0.0 +0,0.404500,0.0,0.0,0.0,0.0,0.0 +0,0.404600,0.0,0.0,0.0,0.0,0.0 +0,0.404700,0.0,0.0,0.0,0.0,0.0 +0,0.404800,0.0,0.0,0.0,0.0,0.0 +0,0.404900,0.0,0.0,0.0,0.0,0.0 +0,0.405000,0.0,0.0,0.0,0.0,0.0 +0,0.405100,0.0,0.0,0.0,0.0,0.0 +0,0.405200,0.0,0.0,0.0,0.0,0.0 +0,0.405300,0.0,0.0,0.0,0.0,0.0 +0,0.405400,0.0,0.0,0.0,0.0,0.0 +0,0.405500,0.0,0.0,0.0,0.0,0.0 +0,0.405600,0.0,0.0,0.0,0.0,0.0 +0,0.405700,0.0,0.0,0.0,0.0,0.0 +0,0.405800,0.0,0.0,0.0,0.0,0.0 +0,0.405900,0.0,0.0,0.0,0.0,0.0 +0,0.406000,0.0,0.0,0.0,0.0,0.0 +0,0.406100,0.0,0.0,0.0,0.0,0.0 +0,0.406200,0.0,0.0,0.0,0.0,0.0 +0,0.406300,0.0,0.0,0.0,0.0,0.0 +0,0.406400,0.0,0.0,0.0,0.0,0.0 +0,0.406500,0.0,0.0,0.0,0.0,0.0 +0,0.406600,0.0,0.0,0.0,0.0,0.0 +0,0.406700,0.0,0.0,0.0,0.0,0.0 +0,0.406800,0.0,0.0,0.0,0.0,0.0 +0,0.406900,0.0,0.0,0.0,0.0,0.0 +0,0.407000,0.0,0.0,0.0,0.0,0.0 +0,0.407100,0.0,0.0,0.0,0.0,0.0 +0,0.407200,0.0,0.0,0.0,0.0,0.0 +0,0.407300,0.0,0.0,0.0,0.0,0.0 +0,0.407400,0.0,0.0,0.0,0.0,0.0 +0,0.407500,0.0,0.0,0.0,0.0,0.0 +0,0.407600,0.0,0.0,0.0,0.0,0.0 +0,0.407700,0.0,0.0,0.0,0.0,0.0 +0,0.407800,0.0,0.0,0.0,0.0,0.0 +0,0.407900,0.0,0.0,0.0,0.0,0.0 +0,0.408000,0.0,0.0,0.0,0.0,0.0 +0,0.408100,0.0,0.0,0.0,0.0,0.0 +0,0.408200,0.0,0.0,0.0,0.0,0.0 +0,0.408300,0.0,0.0,0.0,0.0,0.0 +0,0.408400,0.0,0.0,0.0,0.0,0.0 +0,0.408500,0.0,0.0,0.0,0.0,0.0 +0,0.408600,0.0,0.0,0.0,0.0,0.0 +0,0.408700,0.0,0.0,0.0,0.0,0.0 +0,0.408800,0.0,0.0,0.0,0.0,0.0 +0,0.408900,0.0,0.0,0.0,0.0,0.0 +0,0.409000,0.0,0.0,0.0,0.0,0.0 +0,0.409100,0.0,0.0,0.0,0.0,0.0 +0,0.409200,0.0,0.0,0.0,0.0,0.0 +0,0.409300,0.0,0.0,0.0,0.0,0.0 +0,0.409400,0.0,0.0,0.0,0.0,0.0 +0,0.409500,0.0,0.0,0.0,0.0,0.0 +0,0.409600,0.0,0.0,0.0,0.0,0.0 +0,0.409700,0.0,0.0,0.0,0.0,0.0 +0,0.409800,0.0,0.0,0.0,0.0,0.0 +0,0.409900,0.0,0.0,0.0,0.0,0.0 +0,0.410000,0.0,0.0,0.0,0.0,0.0 +0,0.410100,0.0,0.0,0.0,0.0,0.0 +0,0.410200,0.0,0.0,0.0,0.0,0.0 +0,0.410300,0.0,0.0,0.0,0.0,0.0 +0,0.410400,0.0,0.0,0.0,0.0,0.0 +0,0.410500,0.0,0.0,0.0,0.0,0.0 +0,0.410600,0.0,0.0,0.0,0.0,0.0 +0,0.410700,0.0,0.0,0.0,0.0,0.0 +0,0.410800,0.0,0.0,0.0,0.0,0.0 +0,0.410900,0.0,0.0,0.0,0.0,0.0 +0,0.411000,0.0,0.0,0.0,0.0,0.0 +0,0.411100,0.0,0.0,0.0,0.0,0.0 +0,0.411200,0.0,0.0,0.0,0.0,0.0 +0,0.411300,0.0,0.0,0.0,0.0,0.0 +0,0.411400,0.0,0.0,0.0,0.0,0.0 +0,0.411500,0.0,0.0,0.0,0.0,0.0 +0,0.411600,0.0,0.0,0.0,0.0,0.0 +0,0.411700,0.0,0.0,0.0,0.0,0.0 +0,0.411800,0.0,0.0,0.0,0.0,0.0 +0,0.411900,0.0,0.0,0.0,0.0,0.0 +0,0.412000,0.0,0.0,0.0,0.0,0.0 +0,0.412100,0.0,0.0,0.0,0.0,0.0 +0,0.412200,0.0,0.0,0.0,0.0,0.0 +0,0.412300,0.0,0.0,0.0,0.0,0.0 +0,0.412400,0.0,0.0,0.0,0.0,0.0 +0,0.412500,0.0,0.0,0.0,0.0,0.0 +0,0.412600,0.0,0.0,0.0,0.0,0.0 +0,0.412700,0.0,0.0,0.0,0.0,0.0 +0,0.412800,0.0,0.0,0.0,0.0,0.0 +0,0.412900,0.0,0.0,0.0,0.0,0.0 +0,0.413000,0.0,0.0,0.0,0.0,0.0 +0,0.413100,0.0,0.0,0.0,0.0,0.0 +0,0.413200,0.0,0.0,0.0,0.0,0.0 +0,0.413300,0.0,0.0,0.0,0.0,0.0 +0,0.413400,0.0,0.0,0.0,0.0,0.0 +0,0.413500,0.0,0.0,0.0,0.0,0.0 +0,0.413600,0.0,0.0,0.0,0.0,0.0 +0,0.413700,0.0,0.0,0.0,0.0,0.0 +0,0.413800,0.0,0.0,0.0,0.0,0.0 +0,0.413900,0.0,0.0,0.0,0.0,0.0 +0,0.414000,0.0,0.0,0.0,0.0,0.0 +0,0.414100,0.0,0.0,0.0,0.0,0.0 +0,0.414200,0.0,0.0,0.0,0.0,0.0 +0,0.414300,0.0,0.0,0.0,0.0,0.0 +0,0.414400,0.0,0.0,0.0,0.0,0.0 +0,0.414500,0.0,0.0,0.0,0.0,0.0 +0,0.414600,0.0,0.0,0.0,0.0,0.0 +0,0.414700,0.0,0.0,0.0,0.0,0.0 +0,0.414800,0.0,0.0,0.0,0.0,0.0 +0,0.414900,0.0,0.0,0.0,0.0,0.0 +0,0.415000,0.0,0.0,0.0,0.0,0.0 +0,0.415100,0.0,0.0,0.0,0.0,0.0 +0,0.415200,0.0,0.0,0.0,0.0,0.0 +0,0.415300,0.0,0.0,0.0,0.0,0.0 +0,0.415400,0.0,0.0,0.0,0.0,0.0 +0,0.415500,0.0,0.0,0.0,0.0,0.0 +0,0.415600,0.0,0.0,0.0,0.0,0.0 +0,0.415700,0.0,0.0,0.0,0.0,0.0 +0,0.415800,0.0,0.0,0.0,0.0,0.0 +0,0.415900,0.0,0.0,0.0,0.0,0.0 +0,0.416000,0.0,0.0,0.0,0.0,0.0 +0,0.416100,0.0,0.0,0.0,0.0,0.0 +0,0.416200,0.0,0.0,0.0,0.0,0.0 +0,0.416300,0.0,0.0,0.0,0.0,0.0 +0,0.416400,0.0,0.0,0.0,0.0,0.0 +0,0.416500,0.0,0.0,0.0,0.0,0.0 +0,0.416600,0.0,0.0,0.0,0.0,0.0 +0,0.416700,0.0,0.0,0.0,0.0,0.0 +0,0.416800,0.0,0.0,0.0,0.0,0.0 +0,0.416900,0.0,0.0,0.0,0.0,0.0 +0,0.417000,0.0,0.0,0.0,0.0,0.0 +0,0.417100,0.0,0.0,0.0,0.0,0.0 +0,0.417200,0.0,0.0,0.0,0.0,0.0 +0,0.417300,0.0,0.0,0.0,0.0,0.0 +0,0.417400,0.0,0.0,0.0,0.0,0.0 +0,0.417500,0.0,0.0,0.0,0.0,0.0 +0,0.417600,0.0,0.0,0.0,0.0,0.0 +0,0.417700,0.0,0.0,0.0,0.0,0.0 +0,0.417800,0.0,0.0,0.0,0.0,0.0 +0,0.417900,0.0,0.0,0.0,0.0,0.0 +0,0.418000,0.0,0.0,0.0,0.0,0.0 +0,0.418100,0.0,0.0,0.0,0.0,0.0 +0,0.418200,0.0,0.0,0.0,0.0,0.0 +0,0.418300,0.0,0.0,0.0,0.0,0.0 +0,0.418400,0.0,0.0,0.0,0.0,0.0 +0,0.418500,0.0,0.0,0.0,0.0,0.0 +0,0.418600,0.0,0.0,0.0,0.0,0.0 +0,0.418700,0.0,0.0,0.0,0.0,0.0 +0,0.418800,0.0,0.0,0.0,0.0,0.0 +0,0.418900,0.0,0.0,0.0,0.0,0.0 +0,0.419000,0.0,0.0,0.0,0.0,0.0 +0,0.419100,0.0,0.0,0.0,0.0,0.0 +0,0.419200,0.0,0.0,0.0,0.0,0.0 +0,0.419300,0.0,0.0,0.0,0.0,0.0 +0,0.419400,0.0,0.0,0.0,0.0,0.0 +0,0.419500,0.0,0.0,0.0,0.0,0.0 +0,0.419600,0.0,0.0,0.0,0.0,0.0 +0,0.419700,0.0,0.0,0.0,0.0,0.0 +0,0.419800,0.0,0.0,0.0,0.0,0.0 +0,0.419900,0.0,0.0,0.0,0.0,0.0 +0,0.420000,0.0,0.0,0.0,0.0,0.0 +0,0.420100,0.0,0.0,0.0,0.0,0.0 +1,30.903086,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.420200,0.0,0.0,0.0,0.0,0.0 +0,0.420300,0.0,0.0,0.0,0.0,0.0 +0,0.420400,0.0,0.0,0.0,0.0,0.0 +0,0.420500,0.0,0.0,0.0,0.0,0.0 +0,0.420600,0.0,0.0,0.0,0.0,0.0 +0,0.420700,0.0,0.0,0.0,0.0,0.0 +0,0.420800,0.0,0.0,0.0,0.0,0.0 +0,0.420900,0.0,0.0,0.0,0.0,0.0 +0,0.421000,0.0,0.0,0.0,0.0,0.0 +0,0.421100,0.0,0.0,0.0,0.0,0.0 +0,0.421200,0.0,0.0,0.0,0.0,0.0 +0,0.421300,0.0,0.0,0.0,0.0,0.0 +0,0.421400,0.0,0.0,0.0,0.0,0.0 +0,0.421500,0.0,0.0,0.0,0.0,0.0 +0,0.421600,0.0,0.0,0.0,0.0,0.0 +0,0.421700,0.0,0.0,0.0,0.0,0.0 +0,0.421800,0.0,0.0,0.0,0.0,0.0 +0,0.421900,0.0,0.0,0.0,0.0,0.0 +0,0.422000,0.0,0.0,0.0,0.0,0.0 +0,0.422100,0.0,0.0,0.0,0.0,0.0 +0,0.422200,0.0,0.0,0.0,0.0,0.0 +0,0.422300,0.0,0.0,0.0,0.0,0.0 +0,0.422400,0.0,0.0,0.0,0.0,0.0 +0,0.422500,0.0,0.0,0.0,0.0,0.0 +0,0.422600,0.0,0.0,0.0,0.0,0.0 +0,0.422700,0.0,0.0,0.0,0.0,0.0 +0,0.422800,0.0,0.0,0.0,0.0,0.0 +0,0.422900,0.0,0.0,0.0,0.0,0.0 +0,0.423000,0.0,0.0,0.0,0.0,0.0 +0,0.423100,0.0,0.0,0.0,0.0,0.0 +0,0.423200,0.0,0.0,0.0,0.0,0.0 +0,0.423300,0.0,0.0,0.0,0.0,0.0 +0,0.423400,0.0,0.0,0.0,0.0,0.0 +0,0.423500,0.0,0.0,0.0,0.0,0.0 +0,0.423600,0.0,0.0,0.0,0.0,0.0 +0,0.423700,0.0,0.0,0.0,0.0,0.0 +0,0.423800,0.0,0.0,0.0,0.0,0.0 +0,0.423900,0.0,0.0,0.0,0.0,0.0 +0,0.424000,0.0,0.0,0.0,0.0,0.0 +0,0.424100,0.0,0.0,0.0,0.0,0.0 +0,0.424200,0.0,0.0,0.0,0.0,0.0 +0,0.424300,0.0,0.0,0.0,0.0,0.0 +0,0.424400,0.0,0.0,0.0,0.0,0.0 +0,0.424500,0.0,0.0,0.0,0.0,0.0 +0,0.424600,0.0,0.0,0.0,0.0,0.0 +0,0.424700,0.0,0.0,0.0,0.0,0.0 +0,0.424800,0.0,0.0,0.0,0.0,0.0 +0,0.424900,0.0,0.0,0.0,0.0,0.0 +0,0.425000,0.0,0.0,0.0,0.0,0.0 +0,0.425100,0.0,0.0,0.0,0.0,0.0 +0,0.425200,0.0,0.0,0.0,0.0,0.0 +0,0.425300,0.0,0.0,0.0,0.0,0.0 +0,0.425400,0.0,0.0,0.0,0.0,0.0 +0,0.425500,0.0,0.0,0.0,0.0,0.0 +0,0.425600,0.0,0.0,0.0,0.0,0.0 +0,0.425700,0.0,0.0,0.0,0.0,0.0 +0,0.425800,0.0,0.0,0.0,0.0,0.0 +0,0.425900,0.0,0.0,0.0,0.0,0.0 +0,0.426000,0.0,0.0,0.0,0.0,0.0 +0,0.426100,0.0,0.0,0.0,0.0,0.0 +0,0.426200,0.0,0.0,0.0,0.0,0.0 +0,0.426300,0.0,0.0,0.0,0.0,0.0 +0,0.426400,0.0,0.0,0.0,0.0,0.0 +0,0.426500,0.0,0.0,0.0,0.0,0.0 +0,0.426600,0.0,0.0,0.0,0.0,0.0 +0,0.426700,0.0,0.0,0.0,0.0,0.0 +0,0.426800,0.0,0.0,0.0,0.0,0.0 +0,0.426900,0.0,0.0,0.0,0.0,0.0 +0,0.427000,0.0,0.0,0.0,0.0,0.0 +0,0.427100,0.0,0.0,0.0,0.0,0.0 +0,0.427200,0.0,0.0,0.0,0.0,0.0 +0,0.427300,0.0,0.0,0.0,0.0,0.0 +0,0.427400,0.0,0.0,0.0,0.0,0.0 +0,0.427500,0.0,0.0,0.0,0.0,0.0 +0,0.427600,0.0,0.0,0.0,0.0,0.0 +0,0.427700,0.0,0.0,0.0,0.0,0.0 +0,0.427800,0.0,0.0,0.0,0.0,0.0 +0,0.427900,0.0,0.0,0.0,0.0,0.0 +0,0.428000,0.0,0.0,0.0,0.0,0.0 +0,0.428100,0.0,0.0,0.0,0.0,0.0 +0,0.428200,0.0,0.0,0.0,0.0,0.0 +0,0.428300,0.0,0.0,0.0,0.0,0.0 +0,0.428400,0.0,0.0,0.0,0.0,0.0 +0,0.428500,0.0,0.0,0.0,0.0,0.0 +0,0.428600,0.0,0.0,0.0,0.0,0.0 +0,0.428700,0.0,0.0,0.0,0.0,0.0 +0,0.428800,0.0,0.0,0.0,0.0,0.0 +0,0.428900,0.0,0.0,0.0,0.0,0.0 +0,0.429000,0.0,0.0,0.0,0.0,0.0 +0,0.429100,0.0,0.0,0.0,0.0,0.0 +0,0.429200,0.0,0.0,0.0,0.0,0.0 +0,0.429300,0.0,0.0,0.0,0.0,0.0 +0,0.429400,0.0,0.0,0.0,0.0,0.0 +0,0.429500,0.0,0.0,0.0,0.0,0.0 +0,0.429600,0.0,0.0,0.0,0.0,0.0 +0,0.429700,0.0,0.0,0.0,0.0,0.0 +0,0.429800,0.0,0.0,0.0,0.0,0.0 +0,0.429900,0.0,0.0,0.0,0.0,0.0 +0,0.430000,0.0,0.0,0.0,0.0,0.0 +0,0.430100,0.0,0.0,0.0,0.0,0.0 +0,0.430200,0.0,0.0,0.0,0.0,0.0 +0,0.430300,0.0,0.0,0.0,0.0,0.0 +0,0.430400,0.0,0.0,0.0,0.0,0.0 +0,0.430500,0.0,0.0,0.0,0.0,0.0 +0,0.430600,0.0,0.0,0.0,0.0,0.0 +0,0.430700,0.0,0.0,0.0,0.0,0.0 +0,0.430800,0.0,0.0,0.0,0.0,0.0 +0,0.430900,0.0,0.0,0.0,0.0,0.0 +0,0.431000,0.0,0.0,0.0,0.0,0.0 +0,0.431100,0.0,0.0,0.0,0.0,0.0 +0,0.431200,0.0,0.0,0.0,0.0,0.0 +0,0.431300,0.0,0.0,0.0,0.0,0.0 +0,0.431400,0.0,0.0,0.0,0.0,0.0 +0,0.431500,0.0,0.0,0.0,0.0,0.0 +0,0.431600,0.0,0.0,0.0,0.0,0.0 +0,0.431700,0.0,0.0,0.0,0.0,0.0 +0,0.431800,0.0,0.0,0.0,0.0,0.0 +0,0.431900,0.0,0.0,0.0,0.0,0.0 +0,0.432000,0.0,0.0,0.0,0.0,0.0 +0,0.432100,0.0,0.0,0.0,0.0,0.0 +0,0.432200,0.0,0.0,0.0,0.0,0.0 +0,0.432300,0.0,0.0,0.0,0.0,0.0 +0,0.432400,0.0,0.0,0.0,0.0,0.0 +0,0.432500,0.0,0.0,0.0,0.0,0.0 +0,0.432600,0.0,0.0,0.0,0.0,0.0 +0,0.432700,0.0,0.0,0.0,0.0,0.0 +0,0.432800,0.0,0.0,0.0,0.0,0.0 +0,0.432900,0.0,0.0,0.0,0.0,0.0 +0,0.433000,0.0,0.0,0.0,0.0,0.0 +0,0.433100,0.0,0.0,0.0,0.0,0.0 +0,0.433200,0.0,0.0,0.0,0.0,0.0 +0,0.433300,0.0,0.0,0.0,0.0,0.0 +0,0.433400,0.0,0.0,0.0,0.0,0.0 +0,0.433500,0.0,0.0,0.0,0.0,0.0 +0,0.433600,0.0,0.0,0.0,0.0,0.0 +0,0.433700,0.0,0.0,0.0,0.0,0.0 +0,0.433800,0.0,0.0,0.0,0.0,0.0 +0,0.433900,0.0,0.0,0.0,0.0,0.0 +0,0.434000,0.0,0.0,0.0,0.0,0.0 +0,0.434100,0.0,0.0,0.0,0.0,0.0 +0,0.434200,0.0,0.0,0.0,0.0,0.0 +0,0.434300,0.0,0.0,0.0,0.0,0.0 +0,0.434400,0.0,0.0,0.0,0.0,0.0 +0,0.434500,0.0,0.0,0.0,0.0,0.0 +0,0.434600,0.0,0.0,0.0,0.0,0.0 +0,0.434700,0.0,0.0,0.0,0.0,0.0 +0,0.434800,0.0,0.0,0.0,0.0,0.0 +0,0.434900,0.0,0.0,0.0,0.0,0.0 +0,0.435000,0.0,0.0,0.0,0.0,0.0 +0,0.435100,0.0,0.0,0.0,0.0,0.0 +0,0.435200,0.0,0.0,0.0,0.0,0.0 +0,0.435300,0.0,0.0,0.0,0.0,0.0 +0,0.435400,0.0,0.0,0.0,0.0,0.0 +0,0.435500,0.0,0.0,0.0,0.0,0.0 +0,0.435600,0.0,0.0,0.0,0.0,0.0 +0,0.435700,0.0,0.0,0.0,0.0,0.0 +0,0.435800,0.0,0.0,0.0,0.0,0.0 +0,0.435900,0.0,0.0,0.0,0.0,0.0 +0,0.436000,0.0,0.0,0.0,0.0,0.0 +0,0.436100,0.0,0.0,0.0,0.0,0.0 +0,0.436200,0.0,0.0,0.0,0.0,0.0 +0,0.436300,0.0,0.0,0.0,0.0,0.0 +0,0.436400,0.0,0.0,0.0,0.0,0.0 +0,0.436500,0.0,0.0,0.0,0.0,0.0 +0,0.436600,0.0,0.0,0.0,0.0,0.0 +0,0.436700,0.0,0.0,0.0,0.0,0.0 +0,0.436800,0.0,0.0,0.0,0.0,0.0 +0,0.436900,0.0,0.0,0.0,0.0,0.0 +0,0.437000,0.0,0.0,0.0,0.0,0.0 +0,0.437100,0.0,0.0,0.0,0.0,0.0 +0,0.437200,0.0,0.0,0.0,0.0,0.0 +0,0.437300,0.0,0.0,0.0,0.0,0.0 +0,0.437400,0.0,0.0,0.0,0.0,0.0 +0,0.437500,0.0,0.0,0.0,0.0,0.0 +0,0.437600,0.0,0.0,0.0,0.0,0.0 +0,0.437700,0.0,0.0,0.0,0.0,0.0 +0,0.437800,0.0,0.0,0.0,0.0,0.0 +0,0.437900,0.0,0.0,0.0,0.0,0.0 +0,0.438000,0.0,0.0,0.0,0.0,0.0 +0,0.438100,0.0,0.0,0.0,0.0,0.0 +0,0.438200,0.0,0.0,0.0,0.0,0.0 +0,0.438300,0.0,0.0,0.0,0.0,0.0 +0,0.438400,0.0,0.0,0.0,0.0,0.0 +0,0.438500,0.0,0.0,0.0,0.0,0.0 +0,0.438600,0.0,0.0,0.0,0.0,0.0 +0,0.438700,0.0,0.0,0.0,0.0,0.0 +0,0.438800,0.0,0.0,0.0,0.0,0.0 +0,0.438900,0.0,0.0,0.0,0.0,0.0 +0,0.439000,0.0,0.0,0.0,0.0,0.0 +0,0.439100,0.0,0.0,0.0,0.0,0.0 +0,0.439200,0.0,0.0,0.0,0.0,0.0 +0,0.439300,0.0,0.0,0.0,0.0,0.0 +0,0.439400,0.0,0.0,0.0,0.0,0.0 +0,0.439500,0.0,0.0,0.0,0.0,0.0 +0,0.439600,0.0,0.0,0.0,0.0,0.0 +0,0.439700,0.0,0.0,0.0,0.0,0.0 +0,0.439800,0.0,0.0,0.0,0.0,0.0 +0,0.439900,0.0,0.0,0.0,0.0,0.0 +0,0.440000,0.0,0.0,0.0,0.0,0.0 +0,0.440100,0.0,0.0,0.0,0.0,0.0 +1,35.529645,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.440200,0.0,0.0,0.0,0.0,0.0 +0,0.440300,0.0,0.0,0.0,0.0,0.0 +0,0.440400,0.0,0.0,0.0,0.0,0.0 +0,0.440500,0.0,0.0,0.0,0.0,0.0 +0,0.440600,0.0,0.0,0.0,0.0,0.0 +0,0.440700,0.0,0.0,0.0,0.0,0.0 +0,0.440800,0.0,0.0,0.0,0.0,0.0 +0,0.440900,0.0,0.0,0.0,0.0,0.0 +0,0.441000,0.0,0.0,0.0,0.0,0.0 +0,0.441100,0.0,0.0,0.0,0.0,0.0 +0,0.441200,0.0,0.0,0.0,0.0,0.0 +0,0.441300,0.0,0.0,0.0,0.0,0.0 +0,0.441400,0.0,0.0,0.0,0.0,0.0 +0,0.441500,0.0,0.0,0.0,0.0,0.0 +0,0.441600,0.0,0.0,0.0,0.0,0.0 +0,0.441700,0.0,0.0,0.0,0.0,0.0 +0,0.441800,0.0,0.0,0.0,0.0,0.0 +0,0.441900,0.0,0.0,0.0,0.0,0.0 +0,0.442000,0.0,0.0,0.0,0.0,0.0 +0,0.442100,0.0,0.0,0.0,0.0,0.0 +0,0.442200,0.0,0.0,0.0,0.0,0.0 +0,0.442300,0.0,0.0,0.0,0.0,0.0 +0,0.442400,0.0,0.0,0.0,0.0,0.0 +0,0.442500,0.0,0.0,0.0,0.0,0.0 +0,0.442600,0.0,0.0,0.0,0.0,0.0 +0,0.442700,0.0,0.0,0.0,0.0,0.0 +0,0.442800,0.0,0.0,0.0,0.0,0.0 +0,0.442900,0.0,0.0,0.0,0.0,0.0 +0,0.443000,0.0,0.0,0.0,0.0,0.0 +0,0.443100,0.0,0.0,0.0,0.0,0.0 +0,0.443200,0.0,0.0,0.0,0.0,0.0 +0,0.443300,0.0,0.0,0.0,0.0,0.0 +0,0.443400,0.0,0.0,0.0,0.0,0.0 +0,0.443500,0.0,0.0,0.0,0.0,0.0 +0,0.443600,0.0,0.0,0.0,0.0,0.0 +0,0.443700,0.0,0.0,0.0,0.0,0.0 +0,0.443800,0.0,0.0,0.0,0.0,0.0 +0,0.443900,0.0,0.0,0.0,0.0,0.0 +0,0.444000,0.0,0.0,0.0,0.0,0.0 +0,0.444100,0.0,0.0,0.0,0.0,0.0 +0,0.444200,0.0,0.0,0.0,0.0,0.0 +0,0.444300,0.0,0.0,0.0,0.0,0.0 +0,0.444400,0.0,0.0,0.0,0.0,0.0 +0,0.444500,0.0,0.0,0.0,0.0,0.0 +0,0.444600,0.0,0.0,0.0,0.0,0.0 +0,0.444700,0.0,0.0,0.0,0.0,0.0 +0,0.444800,0.0,0.0,0.0,0.0,0.0 +0,0.444900,0.0,0.0,0.0,0.0,0.0 +0,0.445000,0.0,0.0,0.0,0.0,0.0 +0,0.445100,0.0,0.0,0.0,0.0,0.0 +0,0.445200,0.0,0.0,0.0,0.0,0.0 +0,0.445300,0.0,0.0,0.0,0.0,0.0 +0,0.445400,0.0,0.0,0.0,0.0,0.0 +0,0.445500,0.0,0.0,0.0,0.0,0.0 +0,0.445600,0.0,0.0,0.0,0.0,0.0 +0,0.445700,0.0,0.0,0.0,0.0,0.0 +0,0.445800,0.0,0.0,0.0,0.0,0.0 +0,0.445900,0.0,0.0,0.0,0.0,0.0 +0,0.446000,0.0,0.0,0.0,0.0,0.0 +0,0.446100,0.0,0.0,0.0,0.0,0.0 +0,0.446200,0.0,0.0,0.0,0.0,0.0 +0,0.446300,0.0,0.0,0.0,0.0,0.0 +0,0.446400,0.0,0.0,0.0,0.0,0.0 +0,0.446500,0.0,0.0,0.0,0.0,0.0 +0,0.446600,0.0,0.0,0.0,0.0,0.0 +0,0.446700,0.0,0.0,0.0,0.0,0.0 +0,0.446800,0.0,0.0,0.0,0.0,0.0 +0,0.446900,0.0,0.0,0.0,0.0,0.0 +0,0.447000,0.0,0.0,0.0,0.0,0.0 +0,0.447100,0.0,0.0,0.0,0.0,0.0 +0,0.447200,0.0,0.0,0.0,0.0,0.0 +0,0.447300,0.0,0.0,0.0,0.0,0.0 +0,0.447400,0.0,0.0,0.0,0.0,0.0 +0,0.447500,0.0,0.0,0.0,0.0,0.0 +0,0.447600,0.0,0.0,0.0,0.0,0.0 +0,0.447700,0.0,0.0,0.0,0.0,0.0 +0,0.447800,0.0,0.0,0.0,0.0,0.0 +0,0.447900,0.0,0.0,0.0,0.0,0.0 +0,0.448000,0.0,0.0,0.0,0.0,0.0 +0,0.448100,0.0,0.0,0.0,0.0,0.0 +0,0.448200,0.0,0.0,0.0,0.0,0.0 +0,0.448300,0.0,0.0,0.0,0.0,0.0 +0,0.448400,0.0,0.0,0.0,0.0,0.0 +0,0.448500,0.0,0.0,0.0,0.0,0.0 +0,0.448600,0.0,0.0,0.0,0.0,0.0 +0,0.448700,0.0,0.0,0.0,0.0,0.0 +0,0.448800,0.0,0.0,0.0,0.0,0.0 +0,0.448900,0.0,0.0,0.0,0.0,0.0 +0,0.449000,0.0,0.0,0.0,0.0,0.0 +0,0.449100,0.0,0.0,0.0,0.0,0.0 +0,0.449200,0.0,0.0,0.0,0.0,0.0 +0,0.449300,0.0,0.0,0.0,0.0,0.0 +0,0.449400,0.0,0.0,0.0,0.0,0.0 +0,0.449500,0.0,0.0,0.0,0.0,0.0 +0,0.449600,0.0,0.0,0.0,0.0,0.0 +0,0.449700,0.0,0.0,0.0,0.0,0.0 +0,0.449800,0.0,0.0,0.0,0.0,0.0 +0,0.449900,0.0,0.0,0.0,0.0,0.0 +0,0.450000,0.0,0.0,0.0,0.0,0.0 +0,0.450100,0.0,0.0,0.0,0.0,0.0 +0,0.450200,0.0,0.0,0.0,0.0,0.0 +0,0.450300,0.0,0.0,0.0,0.0,0.0 +0,0.450400,0.0,0.0,0.0,0.0,0.0 +0,0.450500,0.0,0.0,0.0,0.0,0.0 +0,0.450600,0.0,0.0,0.0,0.0,0.0 +0,0.450700,0.0,0.0,0.0,0.0,0.0 +0,0.450800,0.0,0.0,0.0,0.0,0.0 +0,0.450900,0.0,0.0,0.0,0.0,0.0 +0,0.451000,0.0,0.0,0.0,0.0,0.0 +0,0.451100,0.0,0.0,0.0,0.0,0.0 +0,0.451200,0.0,0.0,0.0,0.0,0.0 +0,0.451300,0.0,0.0,0.0,0.0,0.0 +0,0.451400,0.0,0.0,0.0,0.0,0.0 +0,0.451500,0.0,0.0,0.0,0.0,0.0 +0,0.451600,0.0,0.0,0.0,0.0,0.0 +0,0.451700,0.0,0.0,0.0,0.0,0.0 +0,0.451800,0.0,0.0,0.0,0.0,0.0 +0,0.451900,0.0,0.0,0.0,0.0,0.0 +0,0.452000,0.0,0.0,0.0,0.0,0.0 +0,0.452100,0.0,0.0,0.0,0.0,0.0 +0,0.452200,0.0,0.0,0.0,0.0,0.0 +0,0.452300,0.0,0.0,0.0,0.0,0.0 +0,0.452400,0.0,0.0,0.0,0.0,0.0 +0,0.452500,0.0,0.0,0.0,0.0,0.0 +0,0.452600,0.0,0.0,0.0,0.0,0.0 +0,0.452700,0.0,0.0,0.0,0.0,0.0 +0,0.452800,0.0,0.0,0.0,0.0,0.0 +0,0.452900,0.0,0.0,0.0,0.0,0.0 +0,0.453000,0.0,0.0,0.0,0.0,0.0 +0,0.453100,0.0,0.0,0.0,0.0,0.0 +0,0.453200,0.0,0.0,0.0,0.0,0.0 +0,0.453300,0.0,0.0,0.0,0.0,0.0 +0,0.453400,0.0,0.0,0.0,0.0,0.0 +0,0.453500,0.0,0.0,0.0,0.0,0.0 +0,0.453600,0.0,0.0,0.0,0.0,0.0 +0,0.453700,0.0,0.0,0.0,0.0,0.0 +0,0.453800,0.0,0.0,0.0,0.0,0.0 +0,0.453900,0.0,0.0,0.0,0.0,0.0 +0,0.454000,0.0,0.0,0.0,0.0,0.0 +0,0.454100,0.0,0.0,0.0,0.0,0.0 +0,0.454200,0.0,0.0,0.0,0.0,0.0 +0,0.454300,0.0,0.0,0.0,0.0,0.0 +0,0.454400,0.0,0.0,0.0,0.0,0.0 +0,0.454500,0.0,0.0,0.0,0.0,0.0 +0,0.454600,0.0,0.0,0.0,0.0,0.0 +0,0.454700,0.0,0.0,0.0,0.0,0.0 +0,0.454800,0.0,0.0,0.0,0.0,0.0 +0,0.454900,0.0,0.0,0.0,0.0,0.0 +0,0.455000,0.0,0.0,0.0,0.0,0.0 +0,0.455100,0.0,0.0,0.0,0.0,0.0 +0,0.455200,0.0,0.0,0.0,0.0,0.0 +0,0.455300,0.0,0.0,0.0,0.0,0.0 +0,0.455400,0.0,0.0,0.0,0.0,0.0 +0,0.455500,0.0,0.0,0.0,0.0,0.0 +0,0.455600,0.0,0.0,0.0,0.0,0.0 +0,0.455700,0.0,0.0,0.0,0.0,0.0 +0,0.455800,0.0,0.0,0.0,0.0,0.0 +0,0.455900,0.0,0.0,0.0,0.0,0.0 +0,0.456000,0.0,0.0,0.0,0.0,0.0 +0,0.456100,0.0,0.0,0.0,0.0,0.0 +0,0.456200,0.0,0.0,0.0,0.0,0.0 +0,0.456300,0.0,0.0,0.0,0.0,0.0 +0,0.456400,0.0,0.0,0.0,0.0,0.0 +0,0.456500,0.0,0.0,0.0,0.0,0.0 +0,0.456600,0.0,0.0,0.0,0.0,0.0 +0,0.456700,0.0,0.0,0.0,0.0,0.0 +0,0.456800,0.0,0.0,0.0,0.0,0.0 +0,0.456900,0.0,0.0,0.0,0.0,0.0 +0,0.457000,0.0,0.0,0.0,0.0,0.0 +0,0.457100,0.0,0.0,0.0,0.0,0.0 +0,0.457200,0.0,0.0,0.0,0.0,0.0 +0,0.457300,0.0,0.0,0.0,0.0,0.0 +0,0.457400,0.0,0.0,0.0,0.0,0.0 +0,0.457500,0.0,0.0,0.0,0.0,0.0 +0,0.457600,0.0,0.0,0.0,0.0,0.0 +0,0.457700,0.0,0.0,0.0,0.0,0.0 +0,0.457800,0.0,0.0,0.0,0.0,0.0 +0,0.457900,0.0,0.0,0.0,0.0,0.0 +0,0.458000,0.0,0.0,0.0,0.0,0.0 +0,0.458100,0.0,0.0,0.0,0.0,0.0 +0,0.458200,0.0,0.0,0.0,0.0,0.0 +0,0.458300,0.0,0.0,0.0,0.0,0.0 +0,0.458400,0.0,0.0,0.0,0.0,0.0 +0,0.458500,0.0,0.0,0.0,0.0,0.0 +0,0.458600,0.0,0.0,0.0,0.0,0.0 +0,0.458700,0.0,0.0,0.0,0.0,0.0 +0,0.458800,0.0,0.0,0.0,0.0,0.0 +0,0.458900,0.0,0.0,0.0,0.0,0.0 +0,0.459000,0.0,0.0,0.0,0.0,0.0 +0,0.459100,0.0,0.0,0.0,0.0,0.0 +0,0.459200,0.0,0.0,0.0,0.0,0.0 +0,0.459300,0.0,0.0,0.0,0.0,0.0 +0,0.459400,0.0,0.0,0.0,0.0,0.0 +0,0.459500,0.0,0.0,0.0,0.0,0.0 +0,0.459600,0.0,0.0,0.0,0.0,0.0 +0,0.459700,0.0,0.0,0.0,0.0,0.0 +0,0.459800,0.0,0.0,0.0,0.0,0.0 +0,0.459900,0.0,0.0,0.0,0.0,0.0 +0,0.460000,0.0,0.0,0.0,0.0,0.0 +0,0.460100,0.0,0.0,0.0,0.0,0.0 +1,40.596354,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.460200,0.0,0.0,0.0,0.0,0.0 +0,0.460300,0.0,0.0,0.0,0.0,0.0 +0,0.460400,0.0,0.0,0.0,0.0,0.0 +0,0.460500,0.0,0.0,0.0,0.0,0.0 +0,0.460600,0.0,0.0,0.0,0.0,0.0 +0,0.460700,0.0,0.0,0.0,0.0,0.0 +0,0.460800,0.0,0.0,0.0,0.0,0.0 +0,0.460900,0.0,0.0,0.0,0.0,0.0 +0,0.461000,0.0,0.0,0.0,0.0,0.0 +0,0.461100,0.0,0.0,0.0,0.0,0.0 +0,0.461200,0.0,0.0,0.0,0.0,0.0 +0,0.461300,0.0,0.0,0.0,0.0,0.0 +0,0.461400,0.0,0.0,0.0,0.0,0.0 +0,0.461500,0.0,0.0,0.0,0.0,0.0 +0,0.461600,0.0,0.0,0.0,0.0,0.0 +0,0.461700,0.0,0.0,0.0,0.0,0.0 +0,0.461800,0.0,0.0,0.0,0.0,0.0 +0,0.461900,0.0,0.0,0.0,0.0,0.0 +0,0.462000,0.0,0.0,0.0,0.0,0.0 +0,0.462100,0.0,0.0,0.0,0.0,0.0 +0,0.462200,0.0,0.0,0.0,0.0,0.0 +0,0.462300,0.0,0.0,0.0,0.0,0.0 +0,0.462400,0.0,0.0,0.0,0.0,0.0 +0,0.462500,0.0,0.0,0.0,0.0,0.0 +0,0.462600,0.0,0.0,0.0,0.0,0.0 +0,0.462700,0.0,0.0,0.0,0.0,0.0 +0,0.462800,0.0,0.0,0.0,0.0,0.0 +0,0.462900,0.0,0.0,0.0,0.0,0.0 +0,0.463000,0.0,0.0,0.0,0.0,0.0 +0,0.463100,0.0,0.0,0.0,0.0,0.0 +0,0.463200,0.0,0.0,0.0,0.0,0.0 +0,0.463300,0.0,0.0,0.0,0.0,0.0 +0,0.463400,0.0,0.0,0.0,0.0,0.0 +0,0.463500,0.0,0.0,0.0,0.0,0.0 +0,0.463600,0.0,0.0,0.0,0.0,0.0 +0,0.463700,0.0,0.0,0.0,0.0,0.0 +0,0.463800,0.0,0.0,0.0,0.0,0.0 +0,0.463900,0.0,0.0,0.0,0.0,0.0 +0,0.464000,0.0,0.0,0.0,0.0,0.0 +0,0.464100,0.0,0.0,0.0,0.0,0.0 +0,0.464200,0.0,0.0,0.0,0.0,0.0 +0,0.464300,0.0,0.0,0.0,0.0,0.0 +0,0.464400,0.0,0.0,0.0,0.0,0.0 +0,0.464500,0.0,0.0,0.0,0.0,0.0 +0,0.464600,0.0,0.0,0.0,0.0,0.0 +0,0.464700,0.0,0.0,0.0,0.0,0.0 +0,0.464800,0.0,0.0,0.0,0.0,0.0 +0,0.464900,0.0,0.0,0.0,0.0,0.0 +0,0.465000,0.0,0.0,0.0,0.0,0.0 +0,0.465100,0.0,0.0,0.0,0.0,0.0 +0,0.465200,0.0,0.0,0.0,0.0,0.0 +0,0.465300,0.0,0.0,0.0,0.0,0.0 +0,0.465400,0.0,0.0,0.0,0.0,0.0 +0,0.465500,0.0,0.0,0.0,0.0,0.0 +0,0.465600,0.0,0.0,0.0,0.0,0.0 +0,0.465700,0.0,0.0,0.0,0.0,0.0 +0,0.465800,0.0,0.0,0.0,0.0,0.0 +0,0.465900,0.0,0.0,0.0,0.0,0.0 +0,0.466000,0.0,0.0,0.0,0.0,0.0 +0,0.466100,0.0,0.0,0.0,0.0,0.0 +0,0.466200,0.0,0.0,0.0,0.0,0.0 +0,0.466300,0.0,0.0,0.0,0.0,0.0 +0,0.466400,0.0,0.0,0.0,0.0,0.0 +0,0.466500,0.0,0.0,0.0,0.0,0.0 +0,0.466600,0.0,0.0,0.0,0.0,0.0 +0,0.466700,0.0,0.0,0.0,0.0,0.0 +0,0.466800,0.0,0.0,0.0,0.0,0.0 +0,0.466900,0.0,0.0,0.0,0.0,0.0 +0,0.467000,0.0,0.0,0.0,0.0,0.0 +0,0.467100,0.0,0.0,0.0,0.0,0.0 +0,0.467200,0.0,0.0,0.0,0.0,0.0 +0,0.467300,0.0,0.0,0.0,0.0,0.0 +0,0.467400,0.0,0.0,0.0,0.0,0.0 +0,0.467500,0.0,0.0,0.0,0.0,0.0 +0,0.467600,0.0,0.0,0.0,0.0,0.0 +0,0.467700,0.0,0.0,0.0,0.0,0.0 +0,0.467800,0.0,0.0,0.0,0.0,0.0 +0,0.467900,0.0,0.0,0.0,0.0,0.0 +0,0.468000,0.0,0.0,0.0,0.0,0.0 +0,0.468100,0.0,0.0,0.0,0.0,0.0 +0,0.468200,0.0,0.0,0.0,0.0,0.0 +0,0.468300,0.0,0.0,0.0,0.0,0.0 +0,0.468400,0.0,0.0,0.0,0.0,0.0 +0,0.468500,0.0,0.0,0.0,0.0,0.0 +0,0.468600,0.0,0.0,0.0,0.0,0.0 +0,0.468700,0.0,0.0,0.0,0.0,0.0 +0,0.468800,0.0,0.0,0.0,0.0,0.0 +0,0.468900,0.0,0.0,0.0,0.0,0.0 +0,0.469000,0.0,0.0,0.0,0.0,0.0 +0,0.469100,0.0,0.0,0.0,0.0,0.0 +0,0.469200,0.0,0.0,0.0,0.0,0.0 +0,0.469300,0.0,0.0,0.0,0.0,0.0 +0,0.469400,0.0,0.0,0.0,0.0,0.0 +0,0.469500,0.0,0.0,0.0,0.0,0.0 +0,0.469600,0.0,0.0,0.0,0.0,0.0 +0,0.469700,0.0,0.0,0.0,0.0,0.0 +0,0.469800,0.0,0.0,0.0,0.0,0.0 +0,0.469900,0.0,0.0,0.0,0.0,0.0 +0,0.470000,0.0,0.0,0.0,0.0,0.0 +0,0.470100,0.0,0.0,0.0,0.0,0.0 +0,0.470200,0.0,0.0,0.0,0.0,0.0 +0,0.470300,0.0,0.0,0.0,0.0,0.0 +0,0.470400,0.0,0.0,0.0,0.0,0.0 +0,0.470500,0.0,0.0,0.0,0.0,0.0 +0,0.470600,0.0,0.0,0.0,0.0,0.0 +0,0.470700,0.0,0.0,0.0,0.0,0.0 +0,0.470800,0.0,0.0,0.0,0.0,0.0 +0,0.470900,0.0,0.0,0.0,0.0,0.0 +0,0.471000,0.0,0.0,0.0,0.0,0.0 +0,0.471100,0.0,0.0,0.0,0.0,0.0 +0,0.471200,0.0,0.0,0.0,0.0,0.0 +0,0.471300,0.0,0.0,0.0,0.0,0.0 +0,0.471400,0.0,0.0,0.0,0.0,0.0 +0,0.471500,0.0,0.0,0.0,0.0,0.0 +0,0.471600,0.0,0.0,0.0,0.0,0.0 +0,0.471700,0.0,0.0,0.0,0.0,0.0 +0,0.471800,0.0,0.0,0.0,0.0,0.0 +0,0.471900,0.0,0.0,0.0,0.0,0.0 +0,0.472000,0.0,0.0,0.0,0.0,0.0 +0,0.472100,0.0,0.0,0.0,0.0,0.0 +0,0.472200,0.0,0.0,0.0,0.0,0.0 +0,0.472300,0.0,0.0,0.0,0.0,0.0 +0,0.472400,0.0,0.0,0.0,0.0,0.0 +0,0.472500,0.0,0.0,0.0,0.0,0.0 +0,0.472600,0.0,0.0,0.0,0.0,0.0 +0,0.472700,0.0,0.0,0.0,0.0,0.0 +0,0.472800,0.0,0.0,0.0,0.0,0.0 +0,0.472900,0.0,0.0,0.0,0.0,0.0 +0,0.473000,0.0,0.0,0.0,0.0,0.0 +0,0.473100,0.0,0.0,0.0,0.0,0.0 +0,0.473200,0.0,0.0,0.0,0.0,0.0 +0,0.473300,0.0,0.0,0.0,0.0,0.0 +0,0.473400,0.0,0.0,0.0,0.0,0.0 +0,0.473500,0.0,0.0,0.0,0.0,0.0 +0,0.473600,0.0,0.0,0.0,0.0,0.0 +0,0.473700,0.0,0.0,0.0,0.0,0.0 +0,0.473800,0.0,0.0,0.0,0.0,0.0 +0,0.473900,0.0,0.0,0.0,0.0,0.0 +0,0.474000,0.0,0.0,0.0,0.0,0.0 +0,0.474100,0.0,0.0,0.0,0.0,0.0 +0,0.474200,0.0,0.0,0.0,0.0,0.0 +0,0.474300,0.0,0.0,0.0,0.0,0.0 +0,0.474400,0.0,0.0,0.0,0.0,0.0 +0,0.474500,0.0,0.0,0.0,0.0,0.0 +0,0.474600,0.0,0.0,0.0,0.0,0.0 +0,0.474700,0.0,0.0,0.0,0.0,0.0 +0,0.474800,0.0,0.0,0.0,0.0,0.0 +0,0.474900,0.0,0.0,0.0,0.0,0.0 +0,0.475000,0.0,0.0,0.0,0.0,0.0 +0,0.475100,0.0,0.0,0.0,0.0,0.0 +0,0.475200,0.0,0.0,0.0,0.0,0.0 +0,0.475300,0.0,0.0,0.0,0.0,0.0 +0,0.475400,0.0,0.0,0.0,0.0,0.0 +0,0.475500,0.0,0.0,0.0,0.0,0.0 +0,0.475600,0.0,0.0,0.0,0.0,0.0 +0,0.475700,0.0,0.0,0.0,0.0,0.0 +0,0.475800,0.0,0.0,0.0,0.0,0.0 +0,0.475900,0.0,0.0,0.0,0.0,0.0 +0,0.476000,0.0,0.0,0.0,0.0,0.0 +0,0.476100,0.0,0.0,0.0,0.0,0.0 +0,0.476200,0.0,0.0,0.0,0.0,0.0 +0,0.476300,0.0,0.0,0.0,0.0,0.0 +0,0.476400,0.0,0.0,0.0,0.0,0.0 +0,0.476500,0.0,0.0,0.0,0.0,0.0 +0,0.476600,0.0,0.0,0.0,0.0,0.0 +0,0.476700,0.0,0.0,0.0,0.0,0.0 +0,0.476800,0.0,0.0,0.0,0.0,0.0 +0,0.476900,0.0,0.0,0.0,0.0,0.0 +0,0.477000,0.0,0.0,0.0,0.0,0.0 +0,0.477100,0.0,0.0,0.0,0.0,0.0 +0,0.477200,0.0,0.0,0.0,0.0,0.0 +0,0.477300,0.0,0.0,0.0,0.0,0.0 +0,0.477400,0.0,0.0,0.0,0.0,0.0 +0,0.477500,0.0,0.0,0.0,0.0,0.0 +0,0.477600,0.0,0.0,0.0,0.0,0.0 +0,0.477700,0.0,0.0,0.0,0.0,0.0 +0,0.477800,0.0,0.0,0.0,0.0,0.0 +0,0.477900,0.0,0.0,0.0,0.0,0.0 +0,0.478000,0.0,0.0,0.0,0.0,0.0 +0,0.478100,0.0,0.0,0.0,0.0,0.0 +0,0.478200,0.0,0.0,0.0,0.0,0.0 +0,0.478300,0.0,0.0,0.0,0.0,0.0 +0,0.478400,0.0,0.0,0.0,0.0,0.0 +0,0.478500,0.0,0.0,0.0,0.0,0.0 +0,0.478600,0.0,0.0,0.0,0.0,0.0 +0,0.478700,0.0,0.0,0.0,0.0,0.0 +0,0.478800,0.0,0.0,0.0,0.0,0.0 +0,0.478900,0.0,0.0,0.0,0.0,0.0 +0,0.479000,0.0,0.0,0.0,0.0,0.0 +0,0.479100,0.0,0.0,0.0,0.0,0.0 +0,0.479200,0.0,0.0,0.0,0.0,0.0 +0,0.479300,0.0,0.0,0.0,0.0,0.0 +0,0.479400,0.0,0.0,0.0,0.0,0.0 +0,0.479500,0.0,0.0,0.0,0.0,0.0 +0,0.479600,0.0,0.0,0.0,0.0,0.0 +0,0.479700,0.0,0.0,0.0,0.0,0.0 +0,0.479800,0.0,0.0,0.0,0.0,0.0 +0,0.479900,0.0,0.0,0.0,0.0,0.0 +0,0.480000,0.0,0.0,0.0,0.0,0.0 +0,0.480100,0.0,0.0,0.0,0.0,0.0 +1,46.123213,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.480200,0.0,0.0,0.0,0.0,0.0 +0,0.480300,0.0,0.0,0.0,0.0,0.0 +0,0.480400,0.0,0.0,0.0,0.0,0.0 +0,0.480500,0.0,0.0,0.0,0.0,0.0 +0,0.480600,0.0,0.0,0.0,0.0,0.0 +0,0.480700,0.0,0.0,0.0,0.0,0.0 +0,0.480800,0.0,0.0,0.0,0.0,0.0 +0,0.480900,0.0,0.0,0.0,0.0,0.0 +0,0.481000,0.0,0.0,0.0,0.0,0.0 +0,0.481100,0.0,0.0,0.0,0.0,0.0 +0,0.481200,0.0,0.0,0.0,0.0,0.0 +0,0.481300,0.0,0.0,0.0,0.0,0.0 +0,0.481400,0.0,0.0,0.0,0.0,0.0 +0,0.481500,0.0,0.0,0.0,0.0,0.0 +0,0.481600,0.0,0.0,0.0,0.0,0.0 +0,0.481700,0.0,0.0,0.0,0.0,0.0 +0,0.481800,0.0,0.0,0.0,0.0,0.0 +0,0.481900,0.0,0.0,0.0,0.0,0.0 +0,0.482000,0.0,0.0,0.0,0.0,0.0 +0,0.482100,0.0,0.0,0.0,0.0,0.0 +0,0.482200,0.0,0.0,0.0,0.0,0.0 +0,0.482300,0.0,0.0,0.0,0.0,0.0 +0,0.482400,0.0,0.0,0.0,0.0,0.0 +0,0.482500,0.0,0.0,0.0,0.0,0.0 +0,0.482600,0.0,0.0,0.0,0.0,0.0 +0,0.482700,0.0,0.0,0.0,0.0,0.0 +0,0.482800,0.0,0.0,0.0,0.0,0.0 +0,0.482900,0.0,0.0,0.0,0.0,0.0 +0,0.483000,0.0,0.0,0.0,0.0,0.0 +0,0.483100,0.0,0.0,0.0,0.0,0.0 +0,0.483200,0.0,0.0,0.0,0.0,0.0 +0,0.483300,0.0,0.0,0.0,0.0,0.0 +0,0.483400,0.0,0.0,0.0,0.0,0.0 +0,0.483500,0.0,0.0,0.0,0.0,0.0 +0,0.483600,0.0,0.0,0.0,0.0,0.0 +0,0.483700,0.0,0.0,0.0,0.0,0.0 +0,0.483800,0.0,0.0,0.0,0.0,0.0 +0,0.483900,0.0,0.0,0.0,0.0,0.0 +0,0.484000,0.0,0.0,0.0,0.0,0.0 +0,0.484100,0.0,0.0,0.0,0.0,0.0 +0,0.484200,0.0,0.0,0.0,0.0,0.0 +0,0.484300,0.0,0.0,0.0,0.0,0.0 +0,0.484400,0.0,0.0,0.0,0.0,0.0 +0,0.484500,0.0,0.0,0.0,0.0,0.0 +0,0.484600,0.0,0.0,0.0,0.0,0.0 +0,0.484700,0.0,0.0,0.0,0.0,0.0 +0,0.484800,0.0,0.0,0.0,0.0,0.0 +0,0.484900,0.0,0.0,0.0,0.0,0.0 +0,0.485000,0.0,0.0,0.0,0.0,0.0 +0,0.485100,0.0,0.0,0.0,0.0,0.0 +0,0.485200,0.0,0.0,0.0,0.0,0.0 +0,0.485300,0.0,0.0,0.0,0.0,0.0 +0,0.485400,0.0,0.0,0.0,0.0,0.0 +0,0.485500,0.0,0.0,0.0,0.0,0.0 +0,0.485600,0.0,0.0,0.0,0.0,0.0 +0,0.485700,0.0,0.0,0.0,0.0,0.0 +0,0.485800,0.0,0.0,0.0,0.0,0.0 +0,0.485900,0.0,0.0,0.0,0.0,0.0 +0,0.486000,0.0,0.0,0.0,0.0,0.0 +0,0.486100,0.0,0.0,0.0,0.0,0.0 +0,0.486200,0.0,0.0,0.0,0.0,0.0 +0,0.486300,0.0,0.0,0.0,0.0,0.0 +0,0.486400,0.0,0.0,0.0,0.0,0.0 +0,0.486500,0.0,0.0,0.0,0.0,0.0 +0,0.486600,0.0,0.0,0.0,0.0,0.0 +0,0.486700,0.0,0.0,0.0,0.0,0.0 +0,0.486800,0.0,0.0,0.0,0.0,0.0 +0,0.486900,0.0,0.0,0.0,0.0,0.0 +0,0.487000,0.0,0.0,0.0,0.0,0.0 +0,0.487100,0.0,0.0,0.0,0.0,0.0 +0,0.487200,0.0,0.0,0.0,0.0,0.0 +0,0.487300,0.0,0.0,0.0,0.0,0.0 +0,0.487400,0.0,0.0,0.0,0.0,0.0 +0,0.487500,0.0,0.0,0.0,0.0,0.0 +0,0.487600,0.0,0.0,0.0,0.0,0.0 +0,0.487700,0.0,0.0,0.0,0.0,0.0 +0,0.487800,0.0,0.0,0.0,0.0,0.0 +0,0.487900,0.0,0.0,0.0,0.0,0.0 +0,0.488000,0.0,0.0,0.0,0.0,0.0 +0,0.488100,0.0,0.0,0.0,0.0,0.0 +0,0.488200,0.0,0.0,0.0,0.0,0.0 +0,0.488300,0.0,0.0,0.0,0.0,0.0 +0,0.488400,0.0,0.0,0.0,0.0,0.0 +0,0.488500,0.0,0.0,0.0,0.0,0.0 +0,0.488600,0.0,0.0,0.0,0.0,0.0 +0,0.488700,0.0,0.0,0.0,0.0,0.0 +0,0.488800,0.0,0.0,0.0,0.0,0.0 +0,0.488900,0.0,0.0,0.0,0.0,0.0 +0,0.489000,0.0,0.0,0.0,0.0,0.0 +0,0.489100,0.0,0.0,0.0,0.0,0.0 +0,0.489200,0.0,0.0,0.0,0.0,0.0 +0,0.489300,0.0,0.0,0.0,0.0,0.0 +0,0.489400,0.0,0.0,0.0,0.0,0.0 +0,0.489500,0.0,0.0,0.0,0.0,0.0 +0,0.489600,0.0,0.0,0.0,0.0,0.0 +0,0.489700,0.0,0.0,0.0,0.0,0.0 +0,0.489800,0.0,0.0,0.0,0.0,0.0 +0,0.489900,0.0,0.0,0.0,0.0,0.0 +0,0.490000,0.0,0.0,0.0,0.0,0.0 +0,0.490100,0.0,0.0,0.0,0.0,0.0 +0,0.490200,0.0,0.0,0.0,0.0,0.0 +0,0.490300,0.0,0.0,0.0,0.0,0.0 +0,0.490400,0.0,0.0,0.0,0.0,0.0 +0,0.490500,0.0,0.0,0.0,0.0,0.0 +0,0.490600,0.0,0.0,0.0,0.0,0.0 +0,0.490700,0.0,0.0,0.0,0.0,0.0 +0,0.490800,0.0,0.0,0.0,0.0,0.0 +0,0.490900,0.0,0.0,0.0,0.0,0.0 +0,0.491000,0.0,0.0,0.0,0.0,0.0 +0,0.491100,0.0,0.0,0.0,0.0,0.0 +0,0.491200,0.0,0.0,0.0,0.0,0.0 +0,0.491300,0.0,0.0,0.0,0.0,0.0 +0,0.491400,0.0,0.0,0.0,0.0,0.0 +0,0.491500,0.0,0.0,0.0,0.0,0.0 +0,0.491600,0.0,0.0,0.0,0.0,0.0 +0,0.491700,0.0,0.0,0.0,0.0,0.0 +0,0.491800,0.0,0.0,0.0,0.0,0.0 +0,0.491900,0.0,0.0,0.0,0.0,0.0 +0,0.492000,0.0,0.0,0.0,0.0,0.0 +0,0.492100,0.0,0.0,0.0,0.0,0.0 +0,0.492200,0.0,0.0,0.0,0.0,0.0 +0,0.492300,0.0,0.0,0.0,0.0,0.0 +0,0.492400,0.0,0.0,0.0,0.0,0.0 +0,0.492500,0.0,0.0,0.0,0.0,0.0 +0,0.492600,0.0,0.0,0.0,0.0,0.0 +0,0.492700,0.0,0.0,0.0,0.0,0.0 +0,0.492800,0.0,0.0,0.0,0.0,0.0 +0,0.492900,0.0,0.0,0.0,0.0,0.0 +0,0.493000,0.0,0.0,0.0,0.0,0.0 +0,0.493100,0.0,0.0,0.0,0.0,0.0 +0,0.493200,0.0,0.0,0.0,0.0,0.0 +0,0.493300,0.0,0.0,0.0,0.0,0.0 +0,0.493400,0.0,0.0,0.0,0.0,0.0 +0,0.493500,0.0,0.0,0.0,0.0,0.0 +0,0.493600,0.0,0.0,0.0,0.0,0.0 +0,0.493700,0.0,0.0,0.0,0.0,0.0 +0,0.493800,0.0,0.0,0.0,0.0,0.0 +0,0.493900,0.0,0.0,0.0,0.0,0.0 +0,0.494000,0.0,0.0,0.0,0.0,0.0 +0,0.494100,0.0,0.0,0.0,0.0,0.0 +0,0.494200,0.0,0.0,0.0,0.0,0.0 +0,0.494300,0.0,0.0,0.0,0.0,0.0 +0,0.494400,0.0,0.0,0.0,0.0,0.0 +0,0.494500,0.0,0.0,0.0,0.0,0.0 +0,0.494600,0.0,0.0,0.0,0.0,0.0 +0,0.494700,0.0,0.0,0.0,0.0,0.0 +0,0.494800,0.0,0.0,0.0,0.0,0.0 +0,0.494900,0.0,0.0,0.0,0.0,0.0 +0,0.495000,0.0,0.0,0.0,0.0,0.0 +0,0.495100,0.0,0.0,0.0,0.0,0.0 +0,0.495200,0.0,0.0,0.0,0.0,0.0 +0,0.495300,0.0,0.0,0.0,0.0,0.0 +0,0.495400,0.0,0.0,0.0,0.0,0.0 +0,0.495500,0.0,0.0,0.0,0.0,0.0 +0,0.495600,0.0,0.0,0.0,0.0,0.0 +0,0.495700,0.0,0.0,0.0,0.0,0.0 +0,0.495800,0.0,0.0,0.0,0.0,0.0 +0,0.495900,0.0,0.0,0.0,0.0,0.0 +0,0.496000,0.0,0.0,0.0,0.0,0.0 +0,0.496100,0.0,0.0,0.0,0.0,0.0 +0,0.496200,0.0,0.0,0.0,0.0,0.0 +0,0.496300,0.0,0.0,0.0,0.0,0.0 +0,0.496400,0.0,0.0,0.0,0.0,0.0 +0,0.496500,0.0,0.0,0.0,0.0,0.0 +0,0.496600,0.0,0.0,0.0,0.0,0.0 +0,0.496700,0.0,0.0,0.0,0.0,0.0 +0,0.496800,0.0,0.0,0.0,0.0,0.0 +0,0.496900,0.0,0.0,0.0,0.0,0.0 +0,0.497000,0.0,0.0,0.0,0.0,0.0 +0,0.497100,0.0,0.0,0.0,0.0,0.0 +0,0.497200,0.0,0.0,0.0,0.0,0.0 +0,0.497300,0.0,0.0,0.0,0.0,0.0 +0,0.497400,0.0,0.0,0.0,0.0,0.0 +0,0.497500,0.0,0.0,0.0,0.0,0.0 +0,0.497600,0.0,0.0,0.0,0.0,0.0 +0,0.497700,0.0,0.0,0.0,0.0,0.0 +0,0.497800,0.0,0.0,0.0,0.0,0.0 +0,0.497900,0.0,0.0,0.0,0.0,0.0 +0,0.498000,0.0,0.0,0.0,0.0,0.0 +0,0.498100,0.0,0.0,0.0,0.0,0.0 +0,0.498200,0.0,0.0,0.0,0.0,0.0 +0,0.498300,0.0,0.0,0.0,0.0,0.0 +0,0.498400,0.0,0.0,0.0,0.0,0.0 +0,0.498500,0.0,0.0,0.0,0.0,0.0 +0,0.498600,0.0,0.0,0.0,0.0,0.0 +0,0.498700,0.0,0.0,0.0,0.0,0.0 +0,0.498800,0.0,0.0,0.0,0.0,0.0 +0,0.498900,0.0,0.0,0.0,0.0,0.0 +0,0.499000,0.0,0.0,0.0,0.0,0.0 +0,0.499100,0.0,0.0,0.0,0.0,0.0 +0,0.499200,0.0,0.0,0.0,0.0,0.0 +0,0.499300,0.0,0.0,0.0,0.0,0.0 +0,0.499400,0.0,0.0,0.0,0.0,0.0 +0,0.499500,0.0,0.0,0.0,0.0,0.0 +0,0.499600,0.0,0.0,0.0,0.0,0.0 +0,0.499700,0.0,0.0,0.0,0.0,0.0 +0,0.499800,0.0,0.0,0.0,0.0,0.0 +0,0.499900,0.0,0.0,0.0,0.0,0.0 +0,0.500000,0.0,0.0,0.0,0.0,0.0 +0,0.500100,0.0,0.0,0.0,0.0,0.0 +1,52.130222,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.500200,0.0,0.0,0.0,0.0,0.0 +0,0.500300,0.0,0.0,0.0,0.0,0.0 +0,0.500400,0.0,0.0,0.0,0.0,0.0 +0,0.500500,0.0,0.0,0.0,0.0,0.0 +0,0.500600,0.0,0.0,0.0,0.0,0.0 +0,0.500700,0.0,0.0,0.0,0.0,0.0 +0,0.500800,0.0,0.0,0.0,0.0,0.0 +0,0.500900,0.0,0.0,0.0,0.0,0.0 +0,0.501000,0.0,0.0,0.0,0.0,0.0 +0,0.501100,0.0,0.0,0.0,0.0,0.0 +0,0.501200,0.0,0.0,0.0,0.0,0.0 +0,0.501300,0.0,0.0,0.0,0.0,0.0 +0,0.501400,0.0,0.0,0.0,0.0,0.0 +0,0.501500,0.0,0.0,0.0,0.0,0.0 +0,0.501600,0.0,0.0,0.0,0.0,0.0 +0,0.501700,0.0,0.0,0.0,0.0,0.0 +0,0.501800,0.0,0.0,0.0,0.0,0.0 +0,0.501900,0.0,0.0,0.0,0.0,0.0 +0,0.502000,0.0,0.0,0.0,0.0,0.0 +0,0.502100,0.0,0.0,0.0,0.0,0.0 +0,0.502200,0.0,0.0,0.0,0.0,0.0 +0,0.502300,0.0,0.0,0.0,0.0,0.0 +0,0.502400,0.0,0.0,0.0,0.0,0.0 +0,0.502500,0.0,0.0,0.0,0.0,0.0 +0,0.502600,0.0,0.0,0.0,0.0,0.0 +0,0.502700,0.0,0.0,0.0,0.0,0.0 +0,0.502800,0.0,0.0,0.0,0.0,0.0 +0,0.502900,0.0,0.0,0.0,0.0,0.0 +0,0.503000,0.0,0.0,0.0,0.0,0.0 +0,0.503100,0.0,0.0,0.0,0.0,0.0 +0,0.503200,0.0,0.0,0.0,0.0,0.0 +0,0.503300,0.0,0.0,0.0,0.0,0.0 +0,0.503400,0.0,0.0,0.0,0.0,0.0 +0,0.503500,0.0,0.0,0.0,0.0,0.0 +0,0.503600,0.0,0.0,0.0,0.0,0.0 +0,0.503700,0.0,0.0,0.0,0.0,0.0 +0,0.503800,0.0,0.0,0.0,0.0,0.0 +0,0.503900,0.0,0.0,0.0,0.0,0.0 +0,0.504000,0.0,0.0,0.0,0.0,0.0 +0,0.504100,0.0,0.0,0.0,0.0,0.0 +0,0.504200,0.0,0.0,0.0,0.0,0.0 +0,0.504300,0.0,0.0,0.0,0.0,0.0 +0,0.504400,0.0,0.0,0.0,0.0,0.0 +0,0.504500,0.0,0.0,0.0,0.0,0.0 +0,0.504600,0.0,0.0,0.0,0.0,0.0 +0,0.504700,0.0,0.0,0.0,0.0,0.0 +0,0.504800,0.0,0.0,0.0,0.0,0.0 +0,0.504900,0.0,0.0,0.0,0.0,0.0 +0,0.505000,0.0,0.0,0.0,0.0,0.0 +0,0.505100,0.0,0.0,0.0,0.0,0.0 +0,0.505200,0.0,0.0,0.0,0.0,0.0 +0,0.505300,0.0,0.0,0.0,0.0,0.0 +0,0.505400,0.0,0.0,0.0,0.0,0.0 +0,0.505500,0.0,0.0,0.0,0.0,0.0 +0,0.505600,0.0,0.0,0.0,0.0,0.0 +0,0.505700,0.0,0.0,0.0,0.0,0.0 +0,0.505800,0.0,0.0,0.0,0.0,0.0 +0,0.505900,0.0,0.0,0.0,0.0,0.0 +0,0.506000,0.0,0.0,0.0,0.0,0.0 +0,0.506100,0.0,0.0,0.0,0.0,0.0 +0,0.506200,0.0,0.0,0.0,0.0,0.0 +0,0.506300,0.0,0.0,0.0,0.0,0.0 +0,0.506400,0.0,0.0,0.0,0.0,0.0 +0,0.506500,0.0,0.0,0.0,0.0,0.0 +0,0.506600,0.0,0.0,0.0,0.0,0.0 +0,0.506700,0.0,0.0,0.0,0.0,0.0 +0,0.506800,0.0,0.0,0.0,0.0,0.0 +0,0.506900,0.0,0.0,0.0,0.0,0.0 +0,0.507000,0.0,0.0,0.0,0.0,0.0 +0,0.507100,0.0,0.0,0.0,0.0,0.0 +0,0.507200,0.0,0.0,0.0,0.0,0.0 +0,0.507300,0.0,0.0,0.0,0.0,0.0 +0,0.507400,0.0,0.0,0.0,0.0,0.0 +0,0.507500,0.0,0.0,0.0,0.0,0.0 +0,0.507600,0.0,0.0,0.0,0.0,0.0 +0,0.507700,0.0,0.0,0.0,0.0,0.0 +0,0.507800,0.0,0.0,0.0,0.0,0.0 +0,0.507900,0.0,0.0,0.0,0.0,0.0 +0,0.508000,0.0,0.0,0.0,0.0,0.0 +0,0.508100,0.0,0.0,0.0,0.0,0.0 +0,0.508200,0.0,0.0,0.0,0.0,0.0 +0,0.508300,0.0,0.0,0.0,0.0,0.0 +0,0.508400,0.0,0.0,0.0,0.0,0.0 +0,0.508500,0.0,0.0,0.0,0.0,0.0 +0,0.508600,0.0,0.0,0.0,0.0,0.0 +0,0.508700,0.0,0.0,0.0,0.0,0.0 +0,0.508800,0.0,0.0,0.0,0.0,0.0 +0,0.508900,0.0,0.0,0.0,0.0,0.0 +0,0.509000,0.0,0.0,0.0,0.0,0.0 +0,0.509100,0.0,0.0,0.0,0.0,0.0 +0,0.509200,0.0,0.0,0.0,0.0,0.0 +0,0.509300,0.0,0.0,0.0,0.0,0.0 +0,0.509400,0.0,0.0,0.0,0.0,0.0 +0,0.509500,0.0,0.0,0.0,0.0,0.0 +0,0.509600,0.0,0.0,0.0,0.0,0.0 +0,0.509700,0.0,0.0,0.0,0.0,0.0 +0,0.509800,0.0,0.0,0.0,0.0,0.0 +0,0.509900,0.0,0.0,0.0,0.0,0.0 +0,0.510000,0.0,0.0,0.0,0.0,0.0 +0,0.510100,0.0,0.0,0.0,0.0,0.0 +0,0.510200,0.0,0.0,0.0,0.0,0.0 +0,0.510300,0.0,0.0,0.0,0.0,0.0 +0,0.510400,0.0,0.0,0.0,0.0,0.0 +0,0.510500,0.0,0.0,0.0,0.0,0.0 +0,0.510600,0.0,0.0,0.0,0.0,0.0 +0,0.510700,0.0,0.0,0.0,0.0,0.0 +0,0.510800,0.0,0.0,0.0,0.0,0.0 +0,0.510900,0.0,0.0,0.0,0.0,0.0 +0,0.511000,0.0,0.0,0.0,0.0,0.0 +0,0.511100,0.0,0.0,0.0,0.0,0.0 +0,0.511200,0.0,0.0,0.0,0.0,0.0 +0,0.511300,0.0,0.0,0.0,0.0,0.0 +0,0.511400,0.0,0.0,0.0,0.0,0.0 +0,0.511500,0.0,0.0,0.0,0.0,0.0 +0,0.511600,0.0,0.0,0.0,0.0,0.0 +0,0.511700,0.0,0.0,0.0,0.0,0.0 +0,0.511800,0.0,0.0,0.0,0.0,0.0 +0,0.511900,0.0,0.0,0.0,0.0,0.0 +0,0.512000,0.0,0.0,0.0,0.0,0.0 +0,0.512100,0.0,0.0,0.0,0.0,0.0 +0,0.512200,0.0,0.0,0.0,0.0,0.0 +0,0.512300,0.0,0.0,0.0,0.0,0.0 +0,0.512400,0.0,0.0,0.0,0.0,0.0 +0,0.512500,0.0,0.0,0.0,0.0,0.0 +0,0.512600,0.0,0.0,0.0,0.0,0.0 +0,0.512700,0.0,0.0,0.0,0.0,0.0 +0,0.512800,0.0,0.0,0.0,0.0,0.0 +0,0.512900,0.0,0.0,0.0,0.0,0.0 +0,0.513000,0.0,0.0,0.0,0.0,0.0 +0,0.513100,0.0,0.0,0.0,0.0,0.0 +0,0.513200,0.0,0.0,0.0,0.0,0.0 +0,0.513300,0.0,0.0,0.0,0.0,0.0 +0,0.513400,0.0,0.0,0.0,0.0,0.0 +0,0.513500,0.0,0.0,0.0,0.0,0.0 +0,0.513600,0.0,0.0,0.0,0.0,0.0 +0,0.513700,0.0,0.0,0.0,0.0,0.0 +0,0.513800,0.0,0.0,0.0,0.0,0.0 +0,0.513900,0.0,0.0,0.0,0.0,0.0 +0,0.514000,0.0,0.0,0.0,0.0,0.0 +0,0.514100,0.0,0.0,0.0,0.0,0.0 +0,0.514200,0.0,0.0,0.0,0.0,0.0 +0,0.514300,0.0,0.0,0.0,0.0,0.0 +0,0.514400,0.0,0.0,0.0,0.0,0.0 +0,0.514500,0.0,0.0,0.0,0.0,0.0 +0,0.514600,0.0,0.0,0.0,0.0,0.0 +0,0.514700,0.0,0.0,0.0,0.0,0.0 +0,0.514800,0.0,0.0,0.0,0.0,0.0 +0,0.514900,0.0,0.0,0.0,0.0,0.0 +0,0.515000,0.0,0.0,0.0,0.0,0.0 +0,0.515100,0.0,0.0,0.0,0.0,0.0 +0,0.515200,0.0,0.0,0.0,0.0,0.0 +0,0.515300,0.0,0.0,0.0,0.0,0.0 +0,0.515400,0.0,0.0,0.0,0.0,0.0 +0,0.515500,0.0,0.0,0.0,0.0,0.0 +0,0.515600,0.0,0.0,0.0,0.0,0.0 +0,0.515700,0.0,0.0,0.0,0.0,0.0 +0,0.515800,0.0,0.0,0.0,0.0,0.0 +0,0.515900,0.0,0.0,0.0,0.0,0.0 +0,0.516000,0.0,0.0,0.0,0.0,0.0 +0,0.516100,0.0,0.0,0.0,0.0,0.0 +0,0.516200,0.0,0.0,0.0,0.0,0.0 +0,0.516300,0.0,0.0,0.0,0.0,0.0 +0,0.516400,0.0,0.0,0.0,0.0,0.0 +0,0.516500,0.0,0.0,0.0,0.0,0.0 +0,0.516600,0.0,0.0,0.0,0.0,0.0 +0,0.516700,0.0,0.0,0.0,0.0,0.0 +0,0.516800,0.0,0.0,0.0,0.0,0.0 +0,0.516900,0.0,0.0,0.0,0.0,0.0 +0,0.517000,0.0,0.0,0.0,0.0,0.0 +0,0.517100,0.0,0.0,0.0,0.0,0.0 +0,0.517200,0.0,0.0,0.0,0.0,0.0 +0,0.517300,0.0,0.0,0.0,0.0,0.0 +0,0.517400,0.0,0.0,0.0,0.0,0.0 +0,0.517500,0.0,0.0,0.0,0.0,0.0 +0,0.517600,0.0,0.0,0.0,0.0,0.0 +0,0.517700,0.0,0.0,0.0,0.0,0.0 +0,0.517800,0.0,0.0,0.0,0.0,0.0 +0,0.517900,0.0,0.0,0.0,0.0,0.0 +0,0.518000,0.0,0.0,0.0,0.0,0.0 +0,0.518100,0.0,0.0,0.0,0.0,0.0 +0,0.518200,0.0,0.0,0.0,0.0,0.0 +0,0.518300,0.0,0.0,0.0,0.0,0.0 +0,0.518400,0.0,0.0,0.0,0.0,0.0 +0,0.518500,0.0,0.0,0.0,0.0,0.0 +0,0.518600,0.0,0.0,0.0,0.0,0.0 +0,0.518700,0.0,0.0,0.0,0.0,0.0 +0,0.518800,0.0,0.0,0.0,0.0,0.0 +0,0.518900,0.0,0.0,0.0,0.0,0.0 +0,0.519000,0.0,0.0,0.0,0.0,0.0 +0,0.519100,0.0,0.0,0.0,0.0,0.0 +0,0.519200,0.0,0.0,0.0,0.0,0.0 +0,0.519300,0.0,0.0,0.0,0.0,0.0 +0,0.519400,0.0,0.0,0.0,0.0,0.0 +0,0.519500,0.0,0.0,0.0,0.0,0.0 +0,0.519600,0.0,0.0,0.0,0.0,0.0 +0,0.519700,0.0,0.0,0.0,0.0,0.0 +0,0.519800,0.0,0.0,0.0,0.0,0.0 +0,0.519900,0.0,0.0,0.0,0.0,0.0 +0,0.520000,0.0,0.0,0.0,0.0,0.0 +0,0.520100,0.0,0.0,0.0,0.0,0.0 +1,58.637381,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.520200,0.0,0.0,0.0,0.0,0.0 +0,0.520300,0.0,0.0,0.0,0.0,0.0 +0,0.520400,0.0,0.0,0.0,0.0,0.0 +0,0.520500,0.0,0.0,0.0,0.0,0.0 +0,0.520600,0.0,0.0,0.0,0.0,0.0 +0,0.520700,0.0,0.0,0.0,0.0,0.0 +0,0.520800,0.0,0.0,0.0,0.0,0.0 +0,0.520900,0.0,0.0,0.0,0.0,0.0 +0,0.521000,0.0,0.0,0.0,0.0,0.0 +0,0.521100,0.0,0.0,0.0,0.0,0.0 +0,0.521200,0.0,0.0,0.0,0.0,0.0 +0,0.521300,0.0,0.0,0.0,0.0,0.0 +0,0.521400,0.0,0.0,0.0,0.0,0.0 +0,0.521500,0.0,0.0,0.0,0.0,0.0 +0,0.521600,0.0,0.0,0.0,0.0,0.0 +0,0.521700,0.0,0.0,0.0,0.0,0.0 +0,0.521800,0.0,0.0,0.0,0.0,0.0 +0,0.521900,0.0,0.0,0.0,0.0,0.0 +0,0.522000,0.0,0.0,0.0,0.0,0.0 +0,0.522100,0.0,0.0,0.0,0.0,0.0 +0,0.522200,0.0,0.0,0.0,0.0,0.0 +0,0.522300,0.0,0.0,0.0,0.0,0.0 +0,0.522400,0.0,0.0,0.0,0.0,0.0 +0,0.522500,0.0,0.0,0.0,0.0,0.0 +0,0.522600,0.0,0.0,0.0,0.0,0.0 +0,0.522700,0.0,0.0,0.0,0.0,0.0 +0,0.522800,0.0,0.0,0.0,0.0,0.0 +0,0.522900,0.0,0.0,0.0,0.0,0.0 +0,0.523000,0.0,0.0,0.0,0.0,0.0 +0,0.523100,0.0,0.0,0.0,0.0,0.0 +0,0.523200,0.0,0.0,0.0,0.0,0.0 +0,0.523300,0.0,0.0,0.0,0.0,0.0 +0,0.523400,0.0,0.0,0.0,0.0,0.0 +0,0.523500,0.0,0.0,0.0,0.0,0.0 +0,0.523600,0.0,0.0,0.0,0.0,0.0 +0,0.523700,0.0,0.0,0.0,0.0,0.0 +0,0.523800,0.0,0.0,0.0,0.0,0.0 +0,0.523900,0.0,0.0,0.0,0.0,0.0 +0,0.524000,0.0,0.0,0.0,0.0,0.0 +0,0.524100,0.0,0.0,0.0,0.0,0.0 +0,0.524200,0.0,0.0,0.0,0.0,0.0 +0,0.524300,0.0,0.0,0.0,0.0,0.0 +0,0.524400,0.0,0.0,0.0,0.0,0.0 +0,0.524500,0.0,0.0,0.0,0.0,0.0 +0,0.524600,0.0,0.0,0.0,0.0,0.0 +0,0.524700,0.0,0.0,0.0,0.0,0.0 +0,0.524800,0.0,0.0,0.0,0.0,0.0 +0,0.524900,0.0,0.0,0.0,0.0,0.0 +0,0.525000,0.0,0.0,0.0,0.0,0.0 +0,0.525100,0.0,0.0,0.0,0.0,0.0 +0,0.525200,0.0,0.0,0.0,0.0,0.0 +0,0.525300,0.0,0.0,0.0,0.0,0.0 +0,0.525400,0.0,0.0,0.0,0.0,0.0 +0,0.525500,0.0,0.0,0.0,0.0,0.0 +0,0.525600,0.0,0.0,0.0,0.0,0.0 +0,0.525700,0.0,0.0,0.0,0.0,0.0 +0,0.525800,0.0,0.0,0.0,0.0,0.0 +0,0.525900,0.0,0.0,0.0,0.0,0.0 +0,0.526000,0.0,0.0,0.0,0.0,0.0 +0,0.526100,0.0,0.0,0.0,0.0,0.0 +0,0.526200,0.0,0.0,0.0,0.0,0.0 +0,0.526300,0.0,0.0,0.0,0.0,0.0 +0,0.526400,0.0,0.0,0.0,0.0,0.0 +0,0.526500,0.0,0.0,0.0,0.0,0.0 +0,0.526600,0.0,0.0,0.0,0.0,0.0 +0,0.526700,0.0,0.0,0.0,0.0,0.0 +0,0.526800,0.0,0.0,0.0,0.0,0.0 +0,0.526900,0.0,0.0,0.0,0.0,0.0 +0,0.527000,0.0,0.0,0.0,0.0,0.0 +0,0.527100,0.0,0.0,0.0,0.0,0.0 +0,0.527200,0.0,0.0,0.0,0.0,0.0 +0,0.527300,0.0,0.0,0.0,0.0,0.0 +0,0.527400,0.0,0.0,0.0,0.0,0.0 +0,0.527500,0.0,0.0,0.0,0.0,0.0 +0,0.527600,0.0,0.0,0.0,0.0,0.0 +0,0.527700,0.0,0.0,0.0,0.0,0.0 +0,0.527800,0.0,0.0,0.0,0.0,0.0 +0,0.527900,0.0,0.0,0.0,0.0,0.0 +0,0.528000,0.0,0.0,0.0,0.0,0.0 +0,0.528100,0.0,0.0,0.0,0.0,0.0 +0,0.528200,0.0,0.0,0.0,0.0,0.0 +0,0.528300,0.0,0.0,0.0,0.0,0.0 +0,0.528400,0.0,0.0,0.0,0.0,0.0 +0,0.528500,0.0,0.0,0.0,0.0,0.0 +0,0.528600,0.0,0.0,0.0,0.0,0.0 +0,0.528700,0.0,0.0,0.0,0.0,0.0 +0,0.528800,0.0,0.0,0.0,0.0,0.0 +0,0.528900,0.0,0.0,0.0,0.0,0.0 +0,0.529000,0.0,0.0,0.0,0.0,0.0 +0,0.529100,0.0,0.0,0.0,0.0,0.0 +0,0.529200,0.0,0.0,0.0,0.0,0.0 +0,0.529300,0.0,0.0,0.0,0.0,0.0 +0,0.529400,0.0,0.0,0.0,0.0,0.0 +0,0.529500,0.0,0.0,0.0,0.0,0.0 +0,0.529600,0.0,0.0,0.0,0.0,0.0 +0,0.529700,0.0,0.0,0.0,0.0,0.0 +0,0.529800,0.0,0.0,0.0,0.0,0.0 +0,0.529900,0.0,0.0,0.0,0.0,0.0 +0,0.530000,0.0,0.0,0.0,0.0,0.0 +0,0.530100,0.0,0.0,0.0,0.0,0.0 +0,0.530200,0.0,0.0,0.0,0.0,0.0 +0,0.530300,0.0,0.0,0.0,0.0,0.0 +0,0.530400,0.0,0.0,0.0,0.0,0.0 +0,0.530500,0.0,0.0,0.0,0.0,0.0 +0,0.530600,0.0,0.0,0.0,0.0,0.0 +0,0.530700,0.0,0.0,0.0,0.0,0.0 +0,0.530800,0.0,0.0,0.0,0.0,0.0 +0,0.530900,0.0,0.0,0.0,0.0,0.0 +0,0.531000,0.0,0.0,0.0,0.0,0.0 +0,0.531100,0.0,0.0,0.0,0.0,0.0 +0,0.531200,0.0,0.0,0.0,0.0,0.0 +0,0.531300,0.0,0.0,0.0,0.0,0.0 +0,0.531400,0.0,0.0,0.0,0.0,0.0 +0,0.531500,0.0,0.0,0.0,0.0,0.0 +0,0.531600,0.0,0.0,0.0,0.0,0.0 +0,0.531700,0.0,0.0,0.0,0.0,0.0 +0,0.531800,0.0,0.0,0.0,0.0,0.0 +0,0.531900,0.0,0.0,0.0,0.0,0.0 +0,0.532000,0.0,0.0,0.0,0.0,0.0 +0,0.532100,0.0,0.0,0.0,0.0,0.0 +0,0.532200,0.0,0.0,0.0,0.0,0.0 +0,0.532300,0.0,0.0,0.0,0.0,0.0 +0,0.532400,0.0,0.0,0.0,0.0,0.0 +0,0.532500,0.0,0.0,0.0,0.0,0.0 +0,0.532600,0.0,0.0,0.0,0.0,0.0 +0,0.532700,0.0,0.0,0.0,0.0,0.0 +0,0.532800,0.0,0.0,0.0,0.0,0.0 +0,0.532900,0.0,0.0,0.0,0.0,0.0 +0,0.533000,0.0,0.0,0.0,0.0,0.0 +0,0.533100,0.0,0.0,0.0,0.0,0.0 +0,0.533200,0.0,0.0,0.0,0.0,0.0 +0,0.533300,0.0,0.0,0.0,0.0,0.0 +0,0.533400,0.0,0.0,0.0,0.0,0.0 +0,0.533500,0.0,0.0,0.0,0.0,0.0 +0,0.533600,0.0,0.0,0.0,0.0,0.0 +0,0.533700,0.0,0.0,0.0,0.0,0.0 +0,0.533800,0.0,0.0,0.0,0.0,0.0 +0,0.533900,0.0,0.0,0.0,0.0,0.0 +0,0.534000,0.0,0.0,0.0,0.0,0.0 +0,0.534100,0.0,0.0,0.0,0.0,0.0 +0,0.534200,0.0,0.0,0.0,0.0,0.0 +0,0.534300,0.0,0.0,0.0,0.0,0.0 +0,0.534400,0.0,0.0,0.0,0.0,0.0 +0,0.534500,0.0,0.0,0.0,0.0,0.0 +0,0.534600,0.0,0.0,0.0,0.0,0.0 +0,0.534700,0.0,0.0,0.0,0.0,0.0 +0,0.534800,0.0,0.0,0.0,0.0,0.0 +0,0.534900,0.0,0.0,0.0,0.0,0.0 +0,0.535000,0.0,0.0,0.0,0.0,0.0 +0,0.535100,0.0,0.0,0.0,0.0,0.0 +0,0.535200,0.0,0.0,0.0,0.0,0.0 +0,0.535300,0.0,0.0,0.0,0.0,0.0 +0,0.535400,0.0,0.0,0.0,0.0,0.0 +0,0.535500,0.0,0.0,0.0,0.0,0.0 +0,0.535600,0.0,0.0,0.0,0.0,0.0 +0,0.535700,0.0,0.0,0.0,0.0,0.0 +0,0.535800,0.0,0.0,0.0,0.0,0.0 +0,0.535900,0.0,0.0,0.0,0.0,0.0 +0,0.536000,0.0,0.0,0.0,0.0,0.0 +0,0.536100,0.0,0.0,0.0,0.0,0.0 +0,0.536200,0.0,0.0,0.0,0.0,0.0 +0,0.536300,0.0,0.0,0.0,0.0,0.0 +0,0.536400,0.0,0.0,0.0,0.0,0.0 +0,0.536500,0.0,0.0,0.0,0.0,0.0 +0,0.536600,0.0,0.0,0.0,0.0,0.0 +0,0.536700,0.0,0.0,0.0,0.0,0.0 +0,0.536800,0.0,0.0,0.0,0.0,0.0 +0,0.536900,0.0,0.0,0.0,0.0,0.0 +0,0.537000,0.0,0.0,0.0,0.0,0.0 +0,0.537100,0.0,0.0,0.0,0.0,0.0 +0,0.537200,0.0,0.0,0.0,0.0,0.0 +0,0.537300,0.0,0.0,0.0,0.0,0.0 +0,0.537400,0.0,0.0,0.0,0.0,0.0 +0,0.537500,0.0,0.0,0.0,0.0,0.0 +0,0.537600,0.0,0.0,0.0,0.0,0.0 +0,0.537700,0.0,0.0,0.0,0.0,0.0 +0,0.537800,0.0,0.0,0.0,0.0,0.0 +0,0.537900,0.0,0.0,0.0,0.0,0.0 +0,0.538000,0.0,0.0,0.0,0.0,0.0 +0,0.538100,0.0,0.0,0.0,0.0,0.0 +0,0.538200,0.0,0.0,0.0,0.0,0.0 +0,0.538300,0.0,0.0,0.0,0.0,0.0 +0,0.538400,0.0,0.0,0.0,0.0,0.0 +0,0.538500,0.0,0.0,0.0,0.0,0.0 +0,0.538600,0.0,0.0,0.0,0.0,0.0 +0,0.538700,0.0,0.0,0.0,0.0,0.0 +0,0.538800,0.0,0.0,0.0,0.0,0.0 +0,0.538900,0.0,0.0,0.0,0.0,0.0 +0,0.539000,0.0,0.0,0.0,0.0,0.0 +0,0.539100,0.0,0.0,0.0,0.0,0.0 +0,0.539200,0.0,0.0,0.0,0.0,0.0 +0,0.539300,0.0,0.0,0.0,0.0,0.0 +0,0.539400,0.0,0.0,0.0,0.0,0.0 +0,0.539500,0.0,0.0,0.0,0.0,0.0 +0,0.539600,0.0,0.0,0.0,0.0,0.0 +0,0.539700,0.0,0.0,0.0,0.0,0.0 +0,0.539800,0.0,0.0,0.0,0.0,0.0 +0,0.539900,0.0,0.0,0.0,0.0,0.0 +0,0.540000,0.0,0.0,0.0,0.0,0.0 +0,0.540100,0.0,0.0,0.0,0.0,0.0 +1,65.664690,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.540200,0.0,0.0,0.0,0.0,0.0 +0,0.540300,0.0,0.0,0.0,0.0,0.0 +0,0.540400,0.0,0.0,0.0,0.0,0.0 +0,0.540500,0.0,0.0,0.0,0.0,0.0 +0,0.540600,0.0,0.0,0.0,0.0,0.0 +0,0.540700,0.0,0.0,0.0,0.0,0.0 +0,0.540800,0.0,0.0,0.0,0.0,0.0 +0,0.540900,0.0,0.0,0.0,0.0,0.0 +0,0.541000,0.0,0.0,0.0,0.0,0.0 +0,0.541100,0.0,0.0,0.0,0.0,0.0 +0,0.541200,0.0,0.0,0.0,0.0,0.0 +0,0.541300,0.0,0.0,0.0,0.0,0.0 +0,0.541400,0.0,0.0,0.0,0.0,0.0 +0,0.541500,0.0,0.0,0.0,0.0,0.0 +0,0.541600,0.0,0.0,0.0,0.0,0.0 +0,0.541700,0.0,0.0,0.0,0.0,0.0 +0,0.541800,0.0,0.0,0.0,0.0,0.0 +0,0.541900,0.0,0.0,0.0,0.0,0.0 +0,0.542000,0.0,0.0,0.0,0.0,0.0 +0,0.542100,0.0,0.0,0.0,0.0,0.0 +0,0.542200,0.0,0.0,0.0,0.0,0.0 +0,0.542300,0.0,0.0,0.0,0.0,0.0 +0,0.542400,0.0,0.0,0.0,0.0,0.0 +0,0.542500,0.0,0.0,0.0,0.0,0.0 +0,0.542600,0.0,0.0,0.0,0.0,0.0 +0,0.542700,0.0,0.0,0.0,0.0,0.0 +0,0.542800,0.0,0.0,0.0,0.0,0.0 +0,0.542900,0.0,0.0,0.0,0.0,0.0 +0,0.543000,0.0,0.0,0.0,0.0,0.0 +0,0.543100,0.0,0.0,0.0,0.0,0.0 +0,0.543200,0.0,0.0,0.0,0.0,0.0 +0,0.543300,0.0,0.0,0.0,0.0,0.0 +0,0.543400,0.0,0.0,0.0,0.0,0.0 +0,0.543500,0.0,0.0,0.0,0.0,0.0 +0,0.543600,0.0,0.0,0.0,0.0,0.0 +0,0.543700,0.0,0.0,0.0,0.0,0.0 +0,0.543800,0.0,0.0,0.0,0.0,0.0 +0,0.543900,0.0,0.0,0.0,0.0,0.0 +0,0.544000,0.0,0.0,0.0,0.0,0.0 +0,0.544100,0.0,0.0,0.0,0.0,0.0 +0,0.544200,0.0,0.0,0.0,0.0,0.0 +0,0.544300,0.0,0.0,0.0,0.0,0.0 +0,0.544400,0.0,0.0,0.0,0.0,0.0 +0,0.544500,0.0,0.0,0.0,0.0,0.0 +0,0.544600,0.0,0.0,0.0,0.0,0.0 +0,0.544700,0.0,0.0,0.0,0.0,0.0 +0,0.544800,0.0,0.0,0.0,0.0,0.0 +0,0.544900,0.0,0.0,0.0,0.0,0.0 +0,0.545000,0.0,0.0,0.0,0.0,0.0 +0,0.545100,0.0,0.0,0.0,0.0,0.0 +0,0.545200,0.0,0.0,0.0,0.0,0.0 +0,0.545300,0.0,0.0,0.0,0.0,0.0 +0,0.545400,0.0,0.0,0.0,0.0,0.0 +0,0.545500,0.0,0.0,0.0,0.0,0.0 +0,0.545600,0.0,0.0,0.0,0.0,0.0 +0,0.545700,0.0,0.0,0.0,0.0,0.0 +0,0.545800,0.0,0.0,0.0,0.0,0.0 +0,0.545900,0.0,0.0,0.0,0.0,0.0 +0,0.546000,0.0,0.0,0.0,0.0,0.0 +0,0.546100,0.0,0.0,0.0,0.0,0.0 +0,0.546200,0.0,0.0,0.0,0.0,0.0 +0,0.546300,0.0,0.0,0.0,0.0,0.0 +0,0.546400,0.0,0.0,0.0,0.0,0.0 +0,0.546500,0.0,0.0,0.0,0.0,0.0 +0,0.546600,0.0,0.0,0.0,0.0,0.0 +0,0.546700,0.0,0.0,0.0,0.0,0.0 +0,0.546800,0.0,0.0,0.0,0.0,0.0 +0,0.546900,0.0,0.0,0.0,0.0,0.0 +0,0.547000,0.0,0.0,0.0,0.0,0.0 +0,0.547100,0.0,0.0,0.0,0.0,0.0 +0,0.547200,0.0,0.0,0.0,0.0,0.0 +0,0.547300,0.0,0.0,0.0,0.0,0.0 +0,0.547400,0.0,0.0,0.0,0.0,0.0 +0,0.547500,0.0,0.0,0.0,0.0,0.0 +0,0.547600,0.0,0.0,0.0,0.0,0.0 +0,0.547700,0.0,0.0,0.0,0.0,0.0 +0,0.547800,0.0,0.0,0.0,0.0,0.0 +0,0.547900,0.0,0.0,0.0,0.0,0.0 +0,0.548000,0.0,0.0,0.0,0.0,0.0 +0,0.548100,0.0,0.0,0.0,0.0,0.0 +0,0.548200,0.0,0.0,0.0,0.0,0.0 +0,0.548300,0.0,0.0,0.0,0.0,0.0 +0,0.548400,0.0,0.0,0.0,0.0,0.0 +0,0.548500,0.0,0.0,0.0,0.0,0.0 +0,0.548600,0.0,0.0,0.0,0.0,0.0 +0,0.548700,0.0,0.0,0.0,0.0,0.0 +0,0.548800,0.0,0.0,0.0,0.0,0.0 +0,0.548900,0.0,0.0,0.0,0.0,0.0 +0,0.549000,0.0,0.0,0.0,0.0,0.0 +0,0.549100,0.0,0.0,0.0,0.0,0.0 +0,0.549200,0.0,0.0,0.0,0.0,0.0 +0,0.549300,0.0,0.0,0.0,0.0,0.0 +0,0.549400,0.0,0.0,0.0,0.0,0.0 +0,0.549500,0.0,0.0,0.0,0.0,0.0 +0,0.549600,0.0,0.0,0.0,0.0,0.0 +0,0.549700,0.0,0.0,0.0,0.0,0.0 +0,0.549800,0.0,0.0,0.0,0.0,0.0 +0,0.549900,0.0,0.0,0.0,0.0,0.0 +0,0.550000,0.0,0.0,0.0,0.0,0.0 +0,0.550100,0.0,0.0,0.0,0.0,0.0 +0,0.550200,0.0,0.0,0.0,0.0,0.0 +0,0.550300,0.0,0.0,0.0,0.0,0.0 +0,0.550400,0.0,0.0,0.0,0.0,0.0 +0,0.550500,0.0,0.0,0.0,0.0,0.0 +0,0.550600,0.0,0.0,0.0,0.0,0.0 +0,0.550700,0.0,0.0,0.0,0.0,0.0 +0,0.550800,0.0,0.0,0.0,0.0,0.0 +0,0.550900,0.0,0.0,0.0,0.0,0.0 +0,0.551000,0.0,0.0,0.0,0.0,0.0 +0,0.551100,0.0,0.0,0.0,0.0,0.0 +0,0.551200,0.0,0.0,0.0,0.0,0.0 +0,0.551300,0.0,0.0,0.0,0.0,0.0 +0,0.551400,0.0,0.0,0.0,0.0,0.0 +0,0.551500,0.0,0.0,0.0,0.0,0.0 +0,0.551600,0.0,0.0,0.0,0.0,0.0 +0,0.551700,0.0,0.0,0.0,0.0,0.0 +0,0.551800,0.0,0.0,0.0,0.0,0.0 +0,0.551900,0.0,0.0,0.0,0.0,0.0 +0,0.552000,0.0,0.0,0.0,0.0,0.0 +0,0.552100,0.0,0.0,0.0,0.0,0.0 +0,0.552200,0.0,0.0,0.0,0.0,0.0 +0,0.552300,0.0,0.0,0.0,0.0,0.0 +0,0.552400,0.0,0.0,0.0,0.0,0.0 +0,0.552500,0.0,0.0,0.0,0.0,0.0 +0,0.552600,0.0,0.0,0.0,0.0,0.0 +0,0.552700,0.0,0.0,0.0,0.0,0.0 +0,0.552800,0.0,0.0,0.0,0.0,0.0 +0,0.552900,0.0,0.0,0.0,0.0,0.0 +0,0.553000,0.0,0.0,0.0,0.0,0.0 +0,0.553100,0.0,0.0,0.0,0.0,0.0 +0,0.553200,0.0,0.0,0.0,0.0,0.0 +0,0.553300,0.0,0.0,0.0,0.0,0.0 +0,0.553400,0.0,0.0,0.0,0.0,0.0 +0,0.553500,0.0,0.0,0.0,0.0,0.0 +0,0.553600,0.0,0.0,0.0,0.0,0.0 +0,0.553700,0.0,0.0,0.0,0.0,0.0 +0,0.553800,0.0,0.0,0.0,0.0,0.0 +0,0.553900,0.0,0.0,0.0,0.0,0.0 +0,0.554000,0.0,0.0,0.0,0.0,0.0 +0,0.554100,0.0,0.0,0.0,0.0,0.0 +0,0.554200,0.0,0.0,0.0,0.0,0.0 +0,0.554300,0.0,0.0,0.0,0.0,0.0 +0,0.554400,0.0,0.0,0.0,0.0,0.0 +0,0.554500,0.0,0.0,0.0,0.0,0.0 +0,0.554600,0.0,0.0,0.0,0.0,0.0 +0,0.554700,0.0,0.0,0.0,0.0,0.0 +0,0.554800,0.0,0.0,0.0,0.0,0.0 +0,0.554900,0.0,0.0,0.0,0.0,0.0 +0,0.555000,0.0,0.0,0.0,0.0,0.0 +0,0.555100,0.0,0.0,0.0,0.0,0.0 +0,0.555200,0.0,0.0,0.0,0.0,0.0 +0,0.555300,0.0,0.0,0.0,0.0,0.0 +0,0.555400,0.0,0.0,0.0,0.0,0.0 +0,0.555500,0.0,0.0,0.0,0.0,0.0 +0,0.555600,0.0,0.0,0.0,0.0,0.0 +0,0.555700,0.0,0.0,0.0,0.0,0.0 +0,0.555800,0.0,0.0,0.0,0.0,0.0 +0,0.555900,0.0,0.0,0.0,0.0,0.0 +0,0.556000,0.0,0.0,0.0,0.0,0.0 +0,0.556100,0.0,0.0,0.0,0.0,0.0 +0,0.556200,0.0,0.0,0.0,0.0,0.0 +0,0.556300,0.0,0.0,0.0,0.0,0.0 +0,0.556400,0.0,0.0,0.0,0.0,0.0 +0,0.556500,0.0,0.0,0.0,0.0,0.0 +0,0.556600,0.0,0.0,0.0,0.0,0.0 +0,0.556700,0.0,0.0,0.0,0.0,0.0 +0,0.556800,0.0,0.0,0.0,0.0,0.0 +0,0.556900,0.0,0.0,0.0,0.0,0.0 +0,0.557000,0.0,0.0,0.0,0.0,0.0 +0,0.557100,0.0,0.0,0.0,0.0,0.0 +0,0.557200,0.0,0.0,0.0,0.0,0.0 +0,0.557300,0.0,0.0,0.0,0.0,0.0 +0,0.557400,0.0,0.0,0.0,0.0,0.0 +0,0.557500,0.0,0.0,0.0,0.0,0.0 +0,0.557600,0.0,0.0,0.0,0.0,0.0 +0,0.557700,0.0,0.0,0.0,0.0,0.0 +0,0.557800,0.0,0.0,0.0,0.0,0.0 +0,0.557900,0.0,0.0,0.0,0.0,0.0 +0,0.558000,0.0,0.0,0.0,0.0,0.0 +0,0.558100,0.0,0.0,0.0,0.0,0.0 +0,0.558200,0.0,0.0,0.0,0.0,0.0 +0,0.558300,0.0,0.0,0.0,0.0,0.0 +0,0.558400,0.0,0.0,0.0,0.0,0.0 +0,0.558500,0.0,0.0,0.0,0.0,0.0 +0,0.558600,0.0,0.0,0.0,0.0,0.0 +0,0.558700,0.0,0.0,0.0,0.0,0.0 +0,0.558800,0.0,0.0,0.0,0.0,0.0 +0,0.558900,0.0,0.0,0.0,0.0,0.0 +0,0.559000,0.0,0.0,0.0,0.0,0.0 +0,0.559100,0.0,0.0,0.0,0.0,0.0 +0,0.559200,0.0,0.0,0.0,0.0,0.0 +0,0.559300,0.0,0.0,0.0,0.0,0.0 +0,0.559400,0.0,0.0,0.0,0.0,0.0 +0,0.559500,0.0,0.0,0.0,0.0,0.0 +0,0.559600,0.0,0.0,0.0,0.0,0.0 +0,0.559700,0.0,0.0,0.0,0.0,0.0 +0,0.559800,0.0,0.0,0.0,0.0,0.0 +0,0.559900,0.0,0.0,0.0,0.0,0.0 +0,0.560000,0.0,0.0,0.0,0.0,0.0 +0,0.560100,0.0,0.0,0.0,0.0,0.0 +1,73.232149,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.560200,0.0,0.0,0.0,0.0,0.0 +0,0.560300,0.0,0.0,0.0,0.0,0.0 +0,0.560400,0.0,0.0,0.0,0.0,0.0 +0,0.560500,0.0,0.0,0.0,0.0,0.0 +0,0.560600,0.0,0.0,0.0,0.0,0.0 +0,0.560700,0.0,0.0,0.0,0.0,0.0 +0,0.560800,0.0,0.0,0.0,0.0,0.0 +0,0.560900,0.0,0.0,0.0,0.0,0.0 +0,0.561000,0.0,0.0,0.0,0.0,0.0 +0,0.561100,0.0,0.0,0.0,0.0,0.0 +0,0.561200,0.0,0.0,0.0,0.0,0.0 +0,0.561300,0.0,0.0,0.0,0.0,0.0 +0,0.561400,0.0,0.0,0.0,0.0,0.0 +0,0.561500,0.0,0.0,0.0,0.0,0.0 +0,0.561600,0.0,0.0,0.0,0.0,0.0 +0,0.561700,0.0,0.0,0.0,0.0,0.0 +0,0.561800,0.0,0.0,0.0,0.0,0.0 +0,0.561900,0.0,0.0,0.0,0.0,0.0 +0,0.562000,0.0,0.0,0.0,0.0,0.0 +0,0.562100,0.0,0.0,0.0,0.0,0.0 +0,0.562200,0.0,0.0,0.0,0.0,0.0 +0,0.562300,0.0,0.0,0.0,0.0,0.0 +0,0.562400,0.0,0.0,0.0,0.0,0.0 +0,0.562500,0.0,0.0,0.0,0.0,0.0 +0,0.562600,0.0,0.0,0.0,0.0,0.0 +0,0.562700,0.0,0.0,0.0,0.0,0.0 +0,0.562800,0.0,0.0,0.0,0.0,0.0 +0,0.562900,0.0,0.0,0.0,0.0,0.0 +0,0.563000,0.0,0.0,0.0,0.0,0.0 +0,0.563100,0.0,0.0,0.0,0.0,0.0 +0,0.563200,0.0,0.0,0.0,0.0,0.0 +0,0.563300,0.0,0.0,0.0,0.0,0.0 +0,0.563400,0.0,0.0,0.0,0.0,0.0 +0,0.563500,0.0,0.0,0.0,0.0,0.0 +0,0.563600,0.0,0.0,0.0,0.0,0.0 +0,0.563700,0.0,0.0,0.0,0.0,0.0 +0,0.563800,0.0,0.0,0.0,0.0,0.0 +0,0.563900,0.0,0.0,0.0,0.0,0.0 +0,0.564000,0.0,0.0,0.0,0.0,0.0 +0,0.564100,0.0,0.0,0.0,0.0,0.0 +0,0.564200,0.0,0.0,0.0,0.0,0.0 +0,0.564300,0.0,0.0,0.0,0.0,0.0 +0,0.564400,0.0,0.0,0.0,0.0,0.0 +0,0.564500,0.0,0.0,0.0,0.0,0.0 +0,0.564600,0.0,0.0,0.0,0.0,0.0 +0,0.564700,0.0,0.0,0.0,0.0,0.0 +0,0.564800,0.0,0.0,0.0,0.0,0.0 +0,0.564900,0.0,0.0,0.0,0.0,0.0 +0,0.565000,0.0,0.0,0.0,0.0,0.0 +0,0.565100,0.0,0.0,0.0,0.0,0.0 +0,0.565200,0.0,0.0,0.0,0.0,0.0 +0,0.565300,0.0,0.0,0.0,0.0,0.0 +0,0.565400,0.0,0.0,0.0,0.0,0.0 +0,0.565500,0.0,0.0,0.0,0.0,0.0 +0,0.565600,0.0,0.0,0.0,0.0,0.0 +0,0.565700,0.0,0.0,0.0,0.0,0.0 +0,0.565800,0.0,0.0,0.0,0.0,0.0 +0,0.565900,0.0,0.0,0.0,0.0,0.0 +0,0.566000,0.0,0.0,0.0,0.0,0.0 +0,0.566100,0.0,0.0,0.0,0.0,0.0 +0,0.566200,0.0,0.0,0.0,0.0,0.0 +0,0.566300,0.0,0.0,0.0,0.0,0.0 +0,0.566400,0.0,0.0,0.0,0.0,0.0 +0,0.566500,0.0,0.0,0.0,0.0,0.0 +0,0.566600,0.0,0.0,0.0,0.0,0.0 +0,0.566700,0.0,0.0,0.0,0.0,0.0 +0,0.566800,0.0,0.0,0.0,0.0,0.0 +0,0.566900,0.0,0.0,0.0,0.0,0.0 +0,0.567000,0.0,0.0,0.0,0.0,0.0 +0,0.567100,0.0,0.0,0.0,0.0,0.0 +0,0.567200,0.0,0.0,0.0,0.0,0.0 +0,0.567300,0.0,0.0,0.0,0.0,0.0 +0,0.567400,0.0,0.0,0.0,0.0,0.0 +0,0.567500,0.0,0.0,0.0,0.0,0.0 +0,0.567600,0.0,0.0,0.0,0.0,0.0 +0,0.567700,0.0,0.0,0.0,0.0,0.0 +0,0.567800,0.0,0.0,0.0,0.0,0.0 +0,0.567900,0.0,0.0,0.0,0.0,0.0 +0,0.568000,0.0,0.0,0.0,0.0,0.0 +0,0.568100,0.0,0.0,0.0,0.0,0.0 +0,0.568200,0.0,0.0,0.0,0.0,0.0 +0,0.568300,0.0,0.0,0.0,0.0,0.0 +0,0.568400,0.0,0.0,0.0,0.0,0.0 +0,0.568500,0.0,0.0,0.0,0.0,0.0 +0,0.568600,0.0,0.0,0.0,0.0,0.0 +0,0.568700,0.0,0.0,0.0,0.0,0.0 +0,0.568800,0.0,0.0,0.0,0.0,0.0 +0,0.568900,0.0,0.0,0.0,0.0,0.0 +0,0.569000,0.0,0.0,0.0,0.0,0.0 +0,0.569100,0.0,0.0,0.0,0.0,0.0 +0,0.569200,0.0,0.0,0.0,0.0,0.0 +0,0.569300,0.0,0.0,0.0,0.0,0.0 +0,0.569400,0.0,0.0,0.0,0.0,0.0 +0,0.569500,0.0,0.0,0.0,0.0,0.0 +0,0.569600,0.0,0.0,0.0,0.0,0.0 +0,0.569700,0.0,0.0,0.0,0.0,0.0 +0,0.569800,0.0,0.0,0.0,0.0,0.0 +0,0.569900,0.0,0.0,0.0,0.0,0.0 +0,0.570000,0.0,0.0,0.0,0.0,0.0 +0,0.570100,0.0,0.0,0.0,0.0,0.0 +0,0.570200,0.0,0.0,0.0,0.0,0.0 +0,0.570300,0.0,0.0,0.0,0.0,0.0 +0,0.570400,0.0,0.0,0.0,0.0,0.0 +0,0.570500,0.0,0.0,0.0,0.0,0.0 +0,0.570600,0.0,0.0,0.0,0.0,0.0 +0,0.570700,0.0,0.0,0.0,0.0,0.0 +0,0.570800,0.0,0.0,0.0,0.0,0.0 +0,0.570900,0.0,0.0,0.0,0.0,0.0 +0,0.571000,0.0,0.0,0.0,0.0,0.0 +0,0.571100,0.0,0.0,0.0,0.0,0.0 +0,0.571200,0.0,0.0,0.0,0.0,0.0 +0,0.571300,0.0,0.0,0.0,0.0,0.0 +0,0.571400,0.0,0.0,0.0,0.0,0.0 +0,0.571500,0.0,0.0,0.0,0.0,0.0 +0,0.571600,0.0,0.0,0.0,0.0,0.0 +0,0.571700,0.0,0.0,0.0,0.0,0.0 +0,0.571800,0.0,0.0,0.0,0.0,0.0 +0,0.571900,0.0,0.0,0.0,0.0,0.0 +0,0.572000,0.0,0.0,0.0,0.0,0.0 +0,0.572100,0.0,0.0,0.0,0.0,0.0 +0,0.572200,0.0,0.0,0.0,0.0,0.0 +0,0.572300,0.0,0.0,0.0,0.0,0.0 +0,0.572400,0.0,0.0,0.0,0.0,0.0 +0,0.572500,0.0,0.0,0.0,0.0,0.0 +0,0.572600,0.0,0.0,0.0,0.0,0.0 +0,0.572700,0.0,0.0,0.0,0.0,0.0 +0,0.572800,0.0,0.0,0.0,0.0,0.0 +0,0.572900,0.0,0.0,0.0,0.0,0.0 +0,0.573000,0.0,0.0,0.0,0.0,0.0 +0,0.573100,0.0,0.0,0.0,0.0,0.0 +0,0.573200,0.0,0.0,0.0,0.0,0.0 +0,0.573300,0.0,0.0,0.0,0.0,0.0 +0,0.573400,0.0,0.0,0.0,0.0,0.0 +0,0.573500,0.0,0.0,0.0,0.0,0.0 +0,0.573600,0.0,0.0,0.0,0.0,0.0 +0,0.573700,0.0,0.0,0.0,0.0,0.0 +0,0.573800,0.0,0.0,0.0,0.0,0.0 +0,0.573900,0.0,0.0,0.0,0.0,0.0 +0,0.574000,0.0,0.0,0.0,0.0,0.0 +0,0.574100,0.0,0.0,0.0,0.0,0.0 +0,0.574200,0.0,0.0,0.0,0.0,0.0 +0,0.574300,0.0,0.0,0.0,0.0,0.0 +0,0.574400,0.0,0.0,0.0,0.0,0.0 +0,0.574500,0.0,0.0,0.0,0.0,0.0 +0,0.574600,0.0,0.0,0.0,0.0,0.0 +0,0.574700,0.0,0.0,0.0,0.0,0.0 +0,0.574800,0.0,0.0,0.0,0.0,0.0 +0,0.574900,0.0,0.0,0.0,0.0,0.0 +0,0.575000,0.0,0.0,0.0,0.0,0.0 +0,0.575100,0.0,0.0,0.0,0.0,0.0 +0,0.575200,0.0,0.0,0.0,0.0,0.0 +0,0.575300,0.0,0.0,0.0,0.0,0.0 +0,0.575400,0.0,0.0,0.0,0.0,0.0 +0,0.575500,0.0,0.0,0.0,0.0,0.0 +0,0.575600,0.0,0.0,0.0,0.0,0.0 +0,0.575700,0.0,0.0,0.0,0.0,0.0 +0,0.575800,0.0,0.0,0.0,0.0,0.0 +0,0.575900,0.0,0.0,0.0,0.0,0.0 +0,0.576000,0.0,0.0,0.0,0.0,0.0 +0,0.576100,0.0,0.0,0.0,0.0,0.0 +0,0.576200,0.0,0.0,0.0,0.0,0.0 +0,0.576300,0.0,0.0,0.0,0.0,0.0 +0,0.576400,0.0,0.0,0.0,0.0,0.0 +0,0.576500,0.0,0.0,0.0,0.0,0.0 +0,0.576600,0.0,0.0,0.0,0.0,0.0 +0,0.576700,0.0,0.0,0.0,0.0,0.0 +0,0.576800,0.0,0.0,0.0,0.0,0.0 +0,0.576900,0.0,0.0,0.0,0.0,0.0 +0,0.577000,0.0,0.0,0.0,0.0,0.0 +0,0.577100,0.0,0.0,0.0,0.0,0.0 +0,0.577200,0.0,0.0,0.0,0.0,0.0 +0,0.577300,0.0,0.0,0.0,0.0,0.0 +0,0.577400,0.0,0.0,0.0,0.0,0.0 +0,0.577500,0.0,0.0,0.0,0.0,0.0 +0,0.577600,0.0,0.0,0.0,0.0,0.0 +0,0.577700,0.0,0.0,0.0,0.0,0.0 +0,0.577800,0.0,0.0,0.0,0.0,0.0 +0,0.577900,0.0,0.0,0.0,0.0,0.0 +0,0.578000,0.0,0.0,0.0,0.0,0.0 +0,0.578100,0.0,0.0,0.0,0.0,0.0 +0,0.578200,0.0,0.0,0.0,0.0,0.0 +0,0.578300,0.0,0.0,0.0,0.0,0.0 +0,0.578400,0.0,0.0,0.0,0.0,0.0 +0,0.578500,0.0,0.0,0.0,0.0,0.0 +0,0.578600,0.0,0.0,0.0,0.0,0.0 +0,0.578700,0.0,0.0,0.0,0.0,0.0 +0,0.578800,0.0,0.0,0.0,0.0,0.0 +0,0.578900,0.0,0.0,0.0,0.0,0.0 +0,0.579000,0.0,0.0,0.0,0.0,0.0 +0,0.579100,0.0,0.0,0.0,0.0,0.0 +0,0.579200,0.0,0.0,0.0,0.0,0.0 +0,0.579300,0.0,0.0,0.0,0.0,0.0 +0,0.579400,0.0,0.0,0.0,0.0,0.0 +0,0.579500,0.0,0.0,0.0,0.0,0.0 +0,0.579600,0.0,0.0,0.0,0.0,0.0 +0,0.579700,0.0,0.0,0.0,0.0,0.0 +0,0.579800,0.0,0.0,0.0,0.0,0.0 +0,0.579900,0.0,0.0,0.0,0.0,0.0 +0,0.580000,0.0,0.0,0.0,0.0,0.0 +0,0.580100,0.0,0.0,0.0,0.0,0.0 +1,81.359757,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.580200,0.0,0.0,0.0,0.0,0.0 +0,0.580300,0.0,0.0,0.0,0.0,0.0 +0,0.580400,0.0,0.0,0.0,0.0,0.0 +0,0.580500,0.0,0.0,0.0,0.0,0.0 +0,0.580600,0.0,0.0,0.0,0.0,0.0 +0,0.580700,0.0,0.0,0.0,0.0,0.0 +0,0.580800,0.0,0.0,0.0,0.0,0.0 +0,0.580900,0.0,0.0,0.0,0.0,0.0 +0,0.581000,0.0,0.0,0.0,0.0,0.0 +0,0.581100,0.0,0.0,0.0,0.0,0.0 +0,0.581200,0.0,0.0,0.0,0.0,0.0 +0,0.581300,0.0,0.0,0.0,0.0,0.0 +0,0.581400,0.0,0.0,0.0,0.0,0.0 +0,0.581500,0.0,0.0,0.0,0.0,0.0 +0,0.581600,0.0,0.0,0.0,0.0,0.0 +0,0.581700,0.0,0.0,0.0,0.0,0.0 +0,0.581800,0.0,0.0,0.0,0.0,0.0 +0,0.581900,0.0,0.0,0.0,0.0,0.0 +0,0.582000,0.0,0.0,0.0,0.0,0.0 +0,0.582100,0.0,0.0,0.0,0.0,0.0 +0,0.582200,0.0,0.0,0.0,0.0,0.0 +0,0.582300,0.0,0.0,0.0,0.0,0.0 +0,0.582400,0.0,0.0,0.0,0.0,0.0 +0,0.582500,0.0,0.0,0.0,0.0,0.0 +0,0.582600,0.0,0.0,0.0,0.0,0.0 +0,0.582700,0.0,0.0,0.0,0.0,0.0 +0,0.582800,0.0,0.0,0.0,0.0,0.0 +0,0.582900,0.0,0.0,0.0,0.0,0.0 +0,0.583000,0.0,0.0,0.0,0.0,0.0 +0,0.583100,0.0,0.0,0.0,0.0,0.0 +0,0.583200,0.0,0.0,0.0,0.0,0.0 +0,0.583300,0.0,0.0,0.0,0.0,0.0 +0,0.583400,0.0,0.0,0.0,0.0,0.0 +0,0.583500,0.0,0.0,0.0,0.0,0.0 +0,0.583600,0.0,0.0,0.0,0.0,0.0 +0,0.583700,0.0,0.0,0.0,0.0,0.0 +0,0.583800,0.0,0.0,0.0,0.0,0.0 +0,0.583900,0.0,0.0,0.0,0.0,0.0 +0,0.584000,0.0,0.0,0.0,0.0,0.0 +0,0.584100,0.0,0.0,0.0,0.0,0.0 +0,0.584200,0.0,0.0,0.0,0.0,0.0 +0,0.584300,0.0,0.0,0.0,0.0,0.0 +0,0.584400,0.0,0.0,0.0,0.0,0.0 +0,0.584500,0.0,0.0,0.0,0.0,0.0 +0,0.584600,0.0,0.0,0.0,0.0,0.0 +0,0.584700,0.0,0.0,0.0,0.0,0.0 +0,0.584800,0.0,0.0,0.0,0.0,0.0 +0,0.584900,0.0,0.0,0.0,0.0,0.0 +0,0.585000,0.0,0.0,0.0,0.0,0.0 +0,0.585100,0.0,0.0,0.0,0.0,0.0 +0,0.585200,0.0,0.0,0.0,0.0,0.0 +0,0.585300,0.0,0.0,0.0,0.0,0.0 +0,0.585400,0.0,0.0,0.0,0.0,0.0 +0,0.585500,0.0,0.0,0.0,0.0,0.0 +0,0.585600,0.0,0.0,0.0,0.0,0.0 +0,0.585700,0.0,0.0,0.0,0.0,0.0 +0,0.585800,0.0,0.0,0.0,0.0,0.0 +0,0.585900,0.0,0.0,0.0,0.0,0.0 +0,0.586000,0.0,0.0,0.0,0.0,0.0 +0,0.586100,0.0,0.0,0.0,0.0,0.0 +0,0.586200,0.0,0.0,0.0,0.0,0.0 +0,0.586300,0.0,0.0,0.0,0.0,0.0 +0,0.586400,0.0,0.0,0.0,0.0,0.0 +0,0.586500,0.0,0.0,0.0,0.0,0.0 +0,0.586600,0.0,0.0,0.0,0.0,0.0 +0,0.586700,0.0,0.0,0.0,0.0,0.0 +0,0.586800,0.0,0.0,0.0,0.0,0.0 +0,0.586900,0.0,0.0,0.0,0.0,0.0 +0,0.587000,0.0,0.0,0.0,0.0,0.0 +0,0.587100,0.0,0.0,0.0,0.0,0.0 +0,0.587200,0.0,0.0,0.0,0.0,0.0 +0,0.587300,0.0,0.0,0.0,0.0,0.0 +0,0.587400,0.0,0.0,0.0,0.0,0.0 +0,0.587500,0.0,0.0,0.0,0.0,0.0 +0,0.587600,0.0,0.0,0.0,0.0,0.0 +0,0.587700,0.0,0.0,0.0,0.0,0.0 +0,0.587800,0.0,0.0,0.0,0.0,0.0 +0,0.587900,0.0,0.0,0.0,0.0,0.0 +0,0.588000,0.0,0.0,0.0,0.0,0.0 +0,0.588100,0.0,0.0,0.0,0.0,0.0 +0,0.588200,0.0,0.0,0.0,0.0,0.0 +0,0.588300,0.0,0.0,0.0,0.0,0.0 +0,0.588400,0.0,0.0,0.0,0.0,0.0 +0,0.588500,0.0,0.0,0.0,0.0,0.0 +0,0.588600,0.0,0.0,0.0,0.0,0.0 +0,0.588700,0.0,0.0,0.0,0.0,0.0 +0,0.588800,0.0,0.0,0.0,0.0,0.0 +0,0.588900,0.0,0.0,0.0,0.0,0.0 +0,0.589000,0.0,0.0,0.0,0.0,0.0 +0,0.589100,0.0,0.0,0.0,0.0,0.0 +0,0.589200,0.0,0.0,0.0,0.0,0.0 +0,0.589300,0.0,0.0,0.0,0.0,0.0 +0,0.589400,0.0,0.0,0.0,0.0,0.0 +0,0.589500,0.0,0.0,0.0,0.0,0.0 +0,0.589600,0.0,0.0,0.0,0.0,0.0 +0,0.589700,0.0,0.0,0.0,0.0,0.0 +0,0.589800,0.0,0.0,0.0,0.0,0.0 +0,0.589900,0.0,0.0,0.0,0.0,0.0 +0,0.590000,0.0,0.0,0.0,0.0,0.0 +0,0.590100,0.0,0.0,0.0,0.0,0.0 +0,0.590200,0.0,0.0,0.0,0.0,0.0 +0,0.590300,0.0,0.0,0.0,0.0,0.0 +0,0.590400,0.0,0.0,0.0,0.0,0.0 +0,0.590500,0.0,0.0,0.0,0.0,0.0 +0,0.590600,0.0,0.0,0.0,0.0,0.0 +0,0.590700,0.0,0.0,0.0,0.0,0.0 +0,0.590800,0.0,0.0,0.0,0.0,0.0 +0,0.590900,0.0,0.0,0.0,0.0,0.0 +0,0.591000,0.0,0.0,0.0,0.0,0.0 +0,0.591100,0.0,0.0,0.0,0.0,0.0 +0,0.591200,0.0,0.0,0.0,0.0,0.0 +0,0.591300,0.0,0.0,0.0,0.0,0.0 +0,0.591400,0.0,0.0,0.0,0.0,0.0 +0,0.591500,0.0,0.0,0.0,0.0,0.0 +0,0.591600,0.0,0.0,0.0,0.0,0.0 +0,0.591700,0.0,0.0,0.0,0.0,0.0 +0,0.591800,0.0,0.0,0.0,0.0,0.0 +0,0.591900,0.0,0.0,0.0,0.0,0.0 +0,0.592000,0.0,0.0,0.0,0.0,0.0 +0,0.592100,0.0,0.0,0.0,0.0,0.0 +0,0.592200,0.0,0.0,0.0,0.0,0.0 +0,0.592300,0.0,0.0,0.0,0.0,0.0 +0,0.592400,0.0,0.0,0.0,0.0,0.0 +0,0.592500,0.0,0.0,0.0,0.0,0.0 +0,0.592600,0.0,0.0,0.0,0.0,0.0 +0,0.592700,0.0,0.0,0.0,0.0,0.0 +0,0.592800,0.0,0.0,0.0,0.0,0.0 +0,0.592900,0.0,0.0,0.0,0.0,0.0 +0,0.593000,0.0,0.0,0.0,0.0,0.0 +0,0.593100,0.0,0.0,0.0,0.0,0.0 +0,0.593200,0.0,0.0,0.0,0.0,0.0 +0,0.593300,0.0,0.0,0.0,0.0,0.0 +0,0.593400,0.0,0.0,0.0,0.0,0.0 +0,0.593500,0.0,0.0,0.0,0.0,0.0 +0,0.593600,0.0,0.0,0.0,0.0,0.0 +0,0.593700,0.0,0.0,0.0,0.0,0.0 +0,0.593800,0.0,0.0,0.0,0.0,0.0 +0,0.593900,0.0,0.0,0.0,0.0,0.0 +0,0.594000,0.0,0.0,0.0,0.0,0.0 +0,0.594100,0.0,0.0,0.0,0.0,0.0 +0,0.594200,0.0,0.0,0.0,0.0,0.0 +0,0.594300,0.0,0.0,0.0,0.0,0.0 +0,0.594400,0.0,0.0,0.0,0.0,0.0 +0,0.594500,0.0,0.0,0.0,0.0,0.0 +0,0.594600,0.0,0.0,0.0,0.0,0.0 +0,0.594700,0.0,0.0,0.0,0.0,0.0 +0,0.594800,0.0,0.0,0.0,0.0,0.0 +0,0.594900,0.0,0.0,0.0,0.0,0.0 +0,0.595000,0.0,0.0,0.0,0.0,0.0 +0,0.595100,0.0,0.0,0.0,0.0,0.0 +0,0.595200,0.0,0.0,0.0,0.0,0.0 +0,0.595300,0.0,0.0,0.0,0.0,0.0 +0,0.595400,0.0,0.0,0.0,0.0,0.0 +0,0.595500,0.0,0.0,0.0,0.0,0.0 +0,0.595600,0.0,0.0,0.0,0.0,0.0 +0,0.595700,0.0,0.0,0.0,0.0,0.0 +0,0.595800,0.0,0.0,0.0,0.0,0.0 +0,0.595900,0.0,0.0,0.0,0.0,0.0 +0,0.596000,0.0,0.0,0.0,0.0,0.0 +0,0.596100,0.0,0.0,0.0,0.0,0.0 +0,0.596200,0.0,0.0,0.0,0.0,0.0 +0,0.596300,0.0,0.0,0.0,0.0,0.0 +0,0.596400,0.0,0.0,0.0,0.0,0.0 +0,0.596500,0.0,0.0,0.0,0.0,0.0 +0,0.596600,0.0,0.0,0.0,0.0,0.0 +0,0.596700,0.0,0.0,0.0,0.0,0.0 +0,0.596800,0.0,0.0,0.0,0.0,0.0 +0,0.596900,0.0,0.0,0.0,0.0,0.0 +0,0.597000,0.0,0.0,0.0,0.0,0.0 +0,0.597100,0.0,0.0,0.0,0.0,0.0 +0,0.597200,0.0,0.0,0.0,0.0,0.0 +0,0.597300,0.0,0.0,0.0,0.0,0.0 +0,0.597400,0.0,0.0,0.0,0.0,0.0 +0,0.597500,0.0,0.0,0.0,0.0,0.0 +0,0.597600,0.0,0.0,0.0,0.0,0.0 +0,0.597700,0.0,0.0,0.0,0.0,0.0 +0,0.597800,0.0,0.0,0.0,0.0,0.0 +0,0.597900,0.0,0.0,0.0,0.0,0.0 +0,0.598000,0.0,0.0,0.0,0.0,0.0 +0,0.598100,0.0,0.0,0.0,0.0,0.0 +0,0.598200,0.0,0.0,0.0,0.0,0.0 +0,0.598300,0.0,0.0,0.0,0.0,0.0 +0,0.598400,0.0,0.0,0.0,0.0,0.0 +0,0.598500,0.0,0.0,0.0,0.0,0.0 +0,0.598600,0.0,0.0,0.0,0.0,0.0 +0,0.598700,0.0,0.0,0.0,0.0,0.0 +0,0.598800,0.0,0.0,0.0,0.0,0.0 +0,0.598900,0.0,0.0,0.0,0.0,0.0 +0,0.599000,0.0,0.0,0.0,0.0,0.0 +0,0.599100,0.0,0.0,0.0,0.0,0.0 +0,0.599200,0.0,0.0,0.0,0.0,0.0 +0,0.599300,0.0,0.0,0.0,0.0,0.0 +0,0.599400,0.0,0.0,0.0,0.0,0.0 +0,0.599500,0.0,0.0,0.0,0.0,0.0 +0,0.599600,0.0,0.0,0.0,0.0,0.0 +0,0.599700,0.0,0.0,0.0,0.0,0.0 +0,0.599800,0.0,0.0,0.0,0.0,0.0 +0,0.599900,0.0,0.0,0.0,0.0,0.0 +0,0.600000,0.0,0.0,0.0,0.0,0.0 +0,0.600100,0.0,0.0,0.0,0.0,0.0 +1,90.067516,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.600200,0.0,0.0,0.0,0.0,0.0 +0,0.600300,0.0,0.0,0.0,0.0,0.0 +0,0.600400,0.0,0.0,0.0,0.0,0.0 +0,0.600500,0.0,0.0,0.0,0.0,0.0 +0,0.600600,0.0,0.0,0.0,0.0,0.0 +0,0.600700,0.0,0.0,0.0,0.0,0.0 +0,0.600800,0.0,0.0,0.0,0.0,0.0 +0,0.600900,0.0,0.0,0.0,0.0,0.0 +0,0.601000,0.0,0.0,0.0,0.0,0.0 +0,0.601100,0.0,0.0,0.0,0.0,0.0 +0,0.601200,0.0,0.0,0.0,0.0,0.0 +0,0.601300,0.0,0.0,0.0,0.0,0.0 +0,0.601400,0.0,0.0,0.0,0.0,0.0 +0,0.601500,0.0,0.0,0.0,0.0,0.0 +0,0.601600,0.0,0.0,0.0,0.0,0.0 +0,0.601700,0.0,0.0,0.0,0.0,0.0 +0,0.601800,0.0,0.0,0.0,0.0,0.0 +0,0.601900,0.0,0.0,0.0,0.0,0.0 +0,0.602000,0.0,0.0,0.0,0.0,0.0 +0,0.602100,0.0,0.0,0.0,0.0,0.0 +0,0.602200,0.0,0.0,0.0,0.0,0.0 +0,0.602300,0.0,0.0,0.0,0.0,0.0 +0,0.602400,0.0,0.0,0.0,0.0,0.0 +0,0.602500,0.0,0.0,0.0,0.0,0.0 +0,0.602600,0.0,0.0,0.0,0.0,0.0 +0,0.602700,0.0,0.0,0.0,0.0,0.0 +0,0.602800,0.0,0.0,0.0,0.0,0.0 +0,0.602900,0.0,0.0,0.0,0.0,0.0 +0,0.603000,0.0,0.0,0.0,0.0,0.0 +0,0.603100,0.0,0.0,0.0,0.0,0.0 +0,0.603200,0.0,0.0,0.0,0.0,0.0 +0,0.603300,0.0,0.0,0.0,0.0,0.0 +0,0.603400,0.0,0.0,0.0,0.0,0.0 +0,0.603500,0.0,0.0,0.0,0.0,0.0 +0,0.603600,0.0,0.0,0.0,0.0,0.0 +0,0.603700,0.0,0.0,0.0,0.0,0.0 +0,0.603800,0.0,0.0,0.0,0.0,0.0 +0,0.603900,0.0,0.0,0.0,0.0,0.0 +0,0.604000,0.0,0.0,0.0,0.0,0.0 +0,0.604100,0.0,0.0,0.0,0.0,0.0 +0,0.604200,0.0,0.0,0.0,0.0,0.0 +0,0.604300,0.0,0.0,0.0,0.0,0.0 +0,0.604400,0.0,0.0,0.0,0.0,0.0 +0,0.604500,0.0,0.0,0.0,0.0,0.0 +0,0.604600,0.0,0.0,0.0,0.0,0.0 +0,0.604700,0.0,0.0,0.0,0.0,0.0 +0,0.604800,0.0,0.0,0.0,0.0,0.0 +0,0.604900,0.0,0.0,0.0,0.0,0.0 +0,0.605000,0.0,0.0,0.0,0.0,0.0 +0,0.605100,0.0,0.0,0.0,0.0,0.0 +0,0.605200,0.0,0.0,0.0,0.0,0.0 +0,0.605300,0.0,0.0,0.0,0.0,0.0 +0,0.605400,0.0,0.0,0.0,0.0,0.0 +0,0.605500,0.0,0.0,0.0,0.0,0.0 +0,0.605600,0.0,0.0,0.0,0.0,0.0 +0,0.605700,0.0,0.0,0.0,0.0,0.0 +0,0.605800,0.0,0.0,0.0,0.0,0.0 +0,0.605900,0.0,0.0,0.0,0.0,0.0 +0,0.606000,0.0,0.0,0.0,0.0,0.0 +0,0.606100,0.0,0.0,0.0,0.0,0.0 +0,0.606200,0.0,0.0,0.0,0.0,0.0 +0,0.606300,0.0,0.0,0.0,0.0,0.0 +0,0.606400,0.0,0.0,0.0,0.0,0.0 +0,0.606500,0.0,0.0,0.0,0.0,0.0 +0,0.606600,0.0,0.0,0.0,0.0,0.0 +0,0.606700,0.0,0.0,0.0,0.0,0.0 +0,0.606800,0.0,0.0,0.0,0.0,0.0 +0,0.606900,0.0,0.0,0.0,0.0,0.0 +0,0.607000,0.0,0.0,0.0,0.0,0.0 +0,0.607100,0.0,0.0,0.0,0.0,0.0 +0,0.607200,0.0,0.0,0.0,0.0,0.0 +0,0.607300,0.0,0.0,0.0,0.0,0.0 +0,0.607400,0.0,0.0,0.0,0.0,0.0 +0,0.607500,0.0,0.0,0.0,0.0,0.0 +0,0.607600,0.0,0.0,0.0,0.0,0.0 +0,0.607700,0.0,0.0,0.0,0.0,0.0 +0,0.607800,0.0,0.0,0.0,0.0,0.0 +0,0.607900,0.0,0.0,0.0,0.0,0.0 +0,0.608000,0.0,0.0,0.0,0.0,0.0 +0,0.608100,0.0,0.0,0.0,0.0,0.0 +0,0.608200,0.0,0.0,0.0,0.0,0.0 +0,0.608300,0.0,0.0,0.0,0.0,0.0 +0,0.608400,0.0,0.0,0.0,0.0,0.0 +0,0.608500,0.0,0.0,0.0,0.0,0.0 +0,0.608600,0.0,0.0,0.0,0.0,0.0 +0,0.608700,0.0,0.0,0.0,0.0,0.0 +0,0.608800,0.0,0.0,0.0,0.0,0.0 +0,0.608900,0.0,0.0,0.0,0.0,0.0 +0,0.609000,0.0,0.0,0.0,0.0,0.0 +0,0.609100,0.0,0.0,0.0,0.0,0.0 +0,0.609200,0.0,0.0,0.0,0.0,0.0 +0,0.609300,0.0,0.0,0.0,0.0,0.0 +0,0.609400,0.0,0.0,0.0,0.0,0.0 +0,0.609500,0.0,0.0,0.0,0.0,0.0 +0,0.609600,0.0,0.0,0.0,0.0,0.0 +0,0.609700,0.0,0.0,0.0,0.0,0.0 +0,0.609800,0.0,0.0,0.0,0.0,0.0 +0,0.609900,0.0,0.0,0.0,0.0,0.0 +0,0.610000,0.0,0.0,0.0,0.0,0.0 +0,0.610100,0.0,0.0,0.0,0.0,0.0 +0,0.610200,0.0,0.0,0.0,0.0,0.0 +0,0.610300,0.0,0.0,0.0,0.0,0.0 +0,0.610400,0.0,0.0,0.0,0.0,0.0 +0,0.610500,0.0,0.0,0.0,0.0,0.0 +0,0.610600,0.0,0.0,0.0,0.0,0.0 +0,0.610700,0.0,0.0,0.0,0.0,0.0 +0,0.610800,0.0,0.0,0.0,0.0,0.0 +0,0.610900,0.0,0.0,0.0,0.0,0.0 +0,0.611000,0.0,0.0,0.0,0.0,0.0 +0,0.611100,0.0,0.0,0.0,0.0,0.0 +0,0.611200,0.0,0.0,0.0,0.0,0.0 +0,0.611300,0.0,0.0,0.0,0.0,0.0 +0,0.611400,0.0,0.0,0.0,0.0,0.0 +0,0.611500,0.0,0.0,0.0,0.0,0.0 +0,0.611600,0.0,0.0,0.0,0.0,0.0 +0,0.611700,0.0,0.0,0.0,0.0,0.0 +0,0.611800,0.0,0.0,0.0,0.0,0.0 +0,0.611900,0.0,0.0,0.0,0.0,0.0 +0,0.612000,0.0,0.0,0.0,0.0,0.0 +0,0.612100,0.0,0.0,0.0,0.0,0.0 +0,0.612200,0.0,0.0,0.0,0.0,0.0 +0,0.612300,0.0,0.0,0.0,0.0,0.0 +0,0.612400,0.0,0.0,0.0,0.0,0.0 +0,0.612500,0.0,0.0,0.0,0.0,0.0 +0,0.612600,0.0,0.0,0.0,0.0,0.0 +0,0.612700,0.0,0.0,0.0,0.0,0.0 +0,0.612800,0.0,0.0,0.0,0.0,0.0 +0,0.612900,0.0,0.0,0.0,0.0,0.0 +0,0.613000,0.0,0.0,0.0,0.0,0.0 +0,0.613100,0.0,0.0,0.0,0.0,0.0 +0,0.613200,0.0,0.0,0.0,0.0,0.0 +0,0.613300,0.0,0.0,0.0,0.0,0.0 +0,0.613400,0.0,0.0,0.0,0.0,0.0 +0,0.613500,0.0,0.0,0.0,0.0,0.0 +0,0.613600,0.0,0.0,0.0,0.0,0.0 +0,0.613700,0.0,0.0,0.0,0.0,0.0 +0,0.613800,0.0,0.0,0.0,0.0,0.0 +0,0.613900,0.0,0.0,0.0,0.0,0.0 +0,0.614000,0.0,0.0,0.0,0.0,0.0 +0,0.614100,0.0,0.0,0.0,0.0,0.0 +0,0.614200,0.0,0.0,0.0,0.0,0.0 +0,0.614300,0.0,0.0,0.0,0.0,0.0 +0,0.614400,0.0,0.0,0.0,0.0,0.0 +0,0.614500,0.0,0.0,0.0,0.0,0.0 +0,0.614600,0.0,0.0,0.0,0.0,0.0 +0,0.614700,0.0,0.0,0.0,0.0,0.0 +0,0.614800,0.0,0.0,0.0,0.0,0.0 +0,0.614900,0.0,0.0,0.0,0.0,0.0 +0,0.615000,0.0,0.0,0.0,0.0,0.0 +0,0.615100,0.0,0.0,0.0,0.0,0.0 +0,0.615200,0.0,0.0,0.0,0.0,0.0 +0,0.615300,0.0,0.0,0.0,0.0,0.0 +0,0.615400,0.0,0.0,0.0,0.0,0.0 +0,0.615500,0.0,0.0,0.0,0.0,0.0 +0,0.615600,0.0,0.0,0.0,0.0,0.0 +0,0.615700,0.0,0.0,0.0,0.0,0.0 +0,0.615800,0.0,0.0,0.0,0.0,0.0 +0,0.615900,0.0,0.0,0.0,0.0,0.0 +0,0.616000,0.0,0.0,0.0,0.0,0.0 +0,0.616100,0.0,0.0,0.0,0.0,0.0 +0,0.616200,0.0,0.0,0.0,0.0,0.0 +0,0.616300,0.0,0.0,0.0,0.0,0.0 +0,0.616400,0.0,0.0,0.0,0.0,0.0 +0,0.616500,0.0,0.0,0.0,0.0,0.0 +0,0.616600,0.0,0.0,0.0,0.0,0.0 +0,0.616700,0.0,0.0,0.0,0.0,0.0 +0,0.616800,0.0,0.0,0.0,0.0,0.0 +0,0.616900,0.0,0.0,0.0,0.0,0.0 +0,0.617000,0.0,0.0,0.0,0.0,0.0 +0,0.617100,0.0,0.0,0.0,0.0,0.0 +0,0.617200,0.0,0.0,0.0,0.0,0.0 +0,0.617300,0.0,0.0,0.0,0.0,0.0 +0,0.617400,0.0,0.0,0.0,0.0,0.0 +0,0.617500,0.0,0.0,0.0,0.0,0.0 +0,0.617600,0.0,0.0,0.0,0.0,0.0 +0,0.617700,0.0,0.0,0.0,0.0,0.0 +0,0.617800,0.0,0.0,0.0,0.0,0.0 +0,0.617900,0.0,0.0,0.0,0.0,0.0 +0,0.618000,0.0,0.0,0.0,0.0,0.0 +0,0.618100,0.0,0.0,0.0,0.0,0.0 +0,0.618200,0.0,0.0,0.0,0.0,0.0 +0,0.618300,0.0,0.0,0.0,0.0,0.0 +0,0.618400,0.0,0.0,0.0,0.0,0.0 +0,0.618500,0.0,0.0,0.0,0.0,0.0 +0,0.618600,0.0,0.0,0.0,0.0,0.0 +0,0.618700,0.0,0.0,0.0,0.0,0.0 +0,0.618800,0.0,0.0,0.0,0.0,0.0 +0,0.618900,0.0,0.0,0.0,0.0,0.0 +0,0.619000,0.0,0.0,0.0,0.0,0.0 +0,0.619100,0.0,0.0,0.0,0.0,0.0 +0,0.619200,0.0,0.0,0.0,0.0,0.0 +0,0.619300,0.0,0.0,0.0,0.0,0.0 +0,0.619400,0.0,0.0,0.0,0.0,0.0 +0,0.619500,0.0,0.0,0.0,0.0,0.0 +0,0.619600,0.0,0.0,0.0,0.0,0.0 +0,0.619700,0.0,0.0,0.0,0.0,0.0 +0,0.619800,0.0,0.0,0.0,0.0,0.0 +0,0.619900,0.0,0.0,0.0,0.0,0.0 +0,0.620000,0.0,0.0,0.0,0.0,0.0 +0,0.620100,0.0,0.0,0.0,0.0,0.0 +1,99.375425,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.620200,0.0,0.0,0.0,0.0,0.0 +0,0.620300,0.0,0.0,0.0,0.0,0.0 +0,0.620400,0.0,0.0,0.0,0.0,0.0 +0,0.620500,0.0,0.0,0.0,0.0,0.0 +0,0.620600,0.0,0.0,0.0,0.0,0.0 +0,0.620700,0.0,0.0,0.0,0.0,0.0 +0,0.620800,0.0,0.0,0.0,0.0,0.0 +0,0.620900,0.0,0.0,0.0,0.0,0.0 +0,0.621000,0.0,0.0,0.0,0.0,0.0 +0,0.621100,0.0,0.0,0.0,0.0,0.0 +0,0.621200,0.0,0.0,0.0,0.0,0.0 +0,0.621300,0.0,0.0,0.0,0.0,0.0 +0,0.621400,0.0,0.0,0.0,0.0,0.0 +0,0.621500,0.0,0.0,0.0,0.0,0.0 +0,0.621600,0.0,0.0,0.0,0.0,0.0 +0,0.621700,0.0,0.0,0.0,0.0,0.0 +0,0.621800,0.0,0.0,0.0,0.0,0.0 +0,0.621900,0.0,0.0,0.0,0.0,0.0 +0,0.622000,0.0,0.0,0.0,0.0,0.0 +0,0.622100,0.0,0.0,0.0,0.0,0.0 +0,0.622200,0.0,0.0,0.0,0.0,0.0 +0,0.622300,0.0,0.0,0.0,0.0,0.0 +0,0.622400,0.0,0.0,0.0,0.0,0.0 +0,0.622500,0.0,0.0,0.0,0.0,0.0 +0,0.622600,0.0,0.0,0.0,0.0,0.0 +0,0.622700,0.0,0.0,0.0,0.0,0.0 +0,0.622800,0.0,0.0,0.0,0.0,0.0 +0,0.622900,0.0,0.0,0.0,0.0,0.0 +0,0.623000,0.0,0.0,0.0,0.0,0.0 +0,0.623100,0.0,0.0,0.0,0.0,0.0 +0,0.623200,0.0,0.0,0.0,0.0,0.0 +0,0.623300,0.0,0.0,0.0,0.0,0.0 +0,0.623400,0.0,0.0,0.0,0.0,0.0 +0,0.623500,0.0,0.0,0.0,0.0,0.0 +0,0.623600,0.0,0.0,0.0,0.0,0.0 +0,0.623700,0.0,0.0,0.0,0.0,0.0 +0,0.623800,0.0,0.0,0.0,0.0,0.0 +0,0.623900,0.0,0.0,0.0,0.0,0.0 +0,0.624000,0.0,0.0,0.0,0.0,0.0 +0,0.624100,0.0,0.0,0.0,0.0,0.0 +0,0.624200,0.0,0.0,0.0,0.0,0.0 +0,0.624300,0.0,0.0,0.0,0.0,0.0 +0,0.624400,0.0,0.0,0.0,0.0,0.0 +0,0.624500,0.0,0.0,0.0,0.0,0.0 +0,0.624600,0.0,0.0,0.0,0.0,0.0 +0,0.624700,0.0,0.0,0.0,0.0,0.0 +0,0.624800,0.0,0.0,0.0,0.0,0.0 +0,0.624900,0.0,0.0,0.0,0.0,0.0 +0,0.625000,0.0,0.0,0.0,0.0,0.0 +0,0.625100,0.0,0.0,0.0,0.0,0.0 +0,0.625200,0.0,0.0,0.0,0.0,0.0 +0,0.625300,0.0,0.0,0.0,0.0,0.0 +0,0.625400,0.0,0.0,0.0,0.0,0.0 +0,0.625500,0.0,0.0,0.0,0.0,0.0 +0,0.625600,0.0,0.0,0.0,0.0,0.0 +0,0.625700,0.0,0.0,0.0,0.0,0.0 +0,0.625800,0.0,0.0,0.0,0.0,0.0 +0,0.625900,0.0,0.0,0.0,0.0,0.0 +0,0.626000,0.0,0.0,0.0,0.0,0.0 +0,0.626100,0.0,0.0,0.0,0.0,0.0 +0,0.626200,0.0,0.0,0.0,0.0,0.0 +0,0.626300,0.0,0.0,0.0,0.0,0.0 +0,0.626400,0.0,0.0,0.0,0.0,0.0 +0,0.626500,0.0,0.0,0.0,0.0,0.0 +0,0.626600,0.0,0.0,0.0,0.0,0.0 +0,0.626700,0.0,0.0,0.0,0.0,0.0 +0,0.626800,0.0,0.0,0.0,0.0,0.0 +0,0.626900,0.0,0.0,0.0,0.0,0.0 +0,0.627000,0.0,0.0,0.0,0.0,0.0 +0,0.627100,0.0,0.0,0.0,0.0,0.0 +0,0.627200,0.0,0.0,0.0,0.0,0.0 +0,0.627300,0.0,0.0,0.0,0.0,0.0 +0,0.627400,0.0,0.0,0.0,0.0,0.0 +0,0.627500,0.0,0.0,0.0,0.0,0.0 +0,0.627600,0.0,0.0,0.0,0.0,0.0 +0,0.627700,0.0,0.0,0.0,0.0,0.0 +0,0.627800,0.0,0.0,0.0,0.0,0.0 +0,0.627900,0.0,0.0,0.0,0.0,0.0 +0,0.628000,0.0,0.0,0.0,0.0,0.0 +0,0.628100,0.0,0.0,0.0,0.0,0.0 +0,0.628200,0.0,0.0,0.0,0.0,0.0 +0,0.628300,0.0,0.0,0.0,0.0,0.0 +0,0.628400,0.0,0.0,0.0,0.0,0.0 +0,0.628500,0.0,0.0,0.0,0.0,0.0 +0,0.628600,0.0,0.0,0.0,0.0,0.0 +0,0.628700,0.0,0.0,0.0,0.0,0.0 +0,0.628800,0.0,0.0,0.0,0.0,0.0 +0,0.628900,0.0,0.0,0.0,0.0,0.0 +0,0.629000,0.0,0.0,0.0,0.0,0.0 +0,0.629100,0.0,0.0,0.0,0.0,0.0 +0,0.629200,0.0,0.0,0.0,0.0,0.0 +0,0.629300,0.0,0.0,0.0,0.0,0.0 +0,0.629400,0.0,0.0,0.0,0.0,0.0 +0,0.629500,0.0,0.0,0.0,0.0,0.0 +0,0.629600,0.0,0.0,0.0,0.0,0.0 +0,0.629700,0.0,0.0,0.0,0.0,0.0 +0,0.629800,0.0,0.0,0.0,0.0,0.0 +0,0.629900,0.0,0.0,0.0,0.0,0.0 +0,0.630000,0.0,0.0,0.0,0.0,0.0 +0,0.630100,0.0,0.0,0.0,0.0,0.0 +0,0.630200,0.0,0.0,0.0,0.0,0.0 +0,0.630300,0.0,0.0,0.0,0.0,0.0 +0,0.630400,0.0,0.0,0.0,0.0,0.0 +0,0.630500,0.0,0.0,0.0,0.0,0.0 +0,0.630600,0.0,0.0,0.0,0.0,0.0 +0,0.630700,0.0,0.0,0.0,0.0,0.0 +0,0.630800,0.0,0.0,0.0,0.0,0.0 +0,0.630900,0.0,0.0,0.0,0.0,0.0 +0,0.631000,0.0,0.0,0.0,0.0,0.0 +0,0.631100,0.0,0.0,0.0,0.0,0.0 +0,0.631200,0.0,0.0,0.0,0.0,0.0 +0,0.631300,0.0,0.0,0.0,0.0,0.0 +0,0.631400,0.0,0.0,0.0,0.0,0.0 +0,0.631500,0.0,0.0,0.0,0.0,0.0 +0,0.631600,0.0,0.0,0.0,0.0,0.0 +0,0.631700,0.0,0.0,0.0,0.0,0.0 +0,0.631800,0.0,0.0,0.0,0.0,0.0 +0,0.631900,0.0,0.0,0.0,0.0,0.0 +0,0.632000,0.0,0.0,0.0,0.0,0.0 +0,0.632100,0.0,0.0,0.0,0.0,0.0 +0,0.632200,0.0,0.0,0.0,0.0,0.0 +0,0.632300,0.0,0.0,0.0,0.0,0.0 +0,0.632400,0.0,0.0,0.0,0.0,0.0 +0,0.632500,0.0,0.0,0.0,0.0,0.0 +0,0.632600,0.0,0.0,0.0,0.0,0.0 +0,0.632700,0.0,0.0,0.0,0.0,0.0 +0,0.632800,0.0,0.0,0.0,0.0,0.0 +0,0.632900,0.0,0.0,0.0,0.0,0.0 +0,0.633000,0.0,0.0,0.0,0.0,0.0 +0,0.633100,0.0,0.0,0.0,0.0,0.0 +0,0.633200,0.0,0.0,0.0,0.0,0.0 +0,0.633300,0.0,0.0,0.0,0.0,0.0 +0,0.633400,0.0,0.0,0.0,0.0,0.0 +0,0.633500,0.0,0.0,0.0,0.0,0.0 +0,0.633600,0.0,0.0,0.0,0.0,0.0 +0,0.633700,0.0,0.0,0.0,0.0,0.0 +0,0.633800,0.0,0.0,0.0,0.0,0.0 +0,0.633900,0.0,0.0,0.0,0.0,0.0 +0,0.634000,0.0,0.0,0.0,0.0,0.0 +0,0.634100,0.0,0.0,0.0,0.0,0.0 +0,0.634200,0.0,0.0,0.0,0.0,0.0 +0,0.634300,0.0,0.0,0.0,0.0,0.0 +0,0.634400,0.0,0.0,0.0,0.0,0.0 +0,0.634500,0.0,0.0,0.0,0.0,0.0 +0,0.634600,0.0,0.0,0.0,0.0,0.0 +0,0.634700,0.0,0.0,0.0,0.0,0.0 +0,0.634800,0.0,0.0,0.0,0.0,0.0 +0,0.634900,0.0,0.0,0.0,0.0,0.0 +0,0.635000,0.0,0.0,0.0,0.0,0.0 +0,0.635100,0.0,0.0,0.0,0.0,0.0 +0,0.635200,0.0,0.0,0.0,0.0,0.0 +0,0.635300,0.0,0.0,0.0,0.0,0.0 +0,0.635400,0.0,0.0,0.0,0.0,0.0 +0,0.635500,0.0,0.0,0.0,0.0,0.0 +0,0.635600,0.0,0.0,0.0,0.0,0.0 +0,0.635700,0.0,0.0,0.0,0.0,0.0 +0,0.635800,0.0,0.0,0.0,0.0,0.0 +0,0.635900,0.0,0.0,0.0,0.0,0.0 +0,0.636000,0.0,0.0,0.0,0.0,0.0 +0,0.636100,0.0,0.0,0.0,0.0,0.0 +0,0.636200,0.0,0.0,0.0,0.0,0.0 +0,0.636300,0.0,0.0,0.0,0.0,0.0 +0,0.636400,0.0,0.0,0.0,0.0,0.0 +0,0.636500,0.0,0.0,0.0,0.0,0.0 +0,0.636600,0.0,0.0,0.0,0.0,0.0 +0,0.636700,0.0,0.0,0.0,0.0,0.0 +0,0.636800,0.0,0.0,0.0,0.0,0.0 +0,0.636900,0.0,0.0,0.0,0.0,0.0 +0,0.637000,0.0,0.0,0.0,0.0,0.0 +0,0.637100,0.0,0.0,0.0,0.0,0.0 +0,0.637200,0.0,0.0,0.0,0.0,0.0 +0,0.637300,0.0,0.0,0.0,0.0,0.0 +0,0.637400,0.0,0.0,0.0,0.0,0.0 +0,0.637500,0.0,0.0,0.0,0.0,0.0 +0,0.637600,0.0,0.0,0.0,0.0,0.0 +0,0.637700,0.0,0.0,0.0,0.0,0.0 +0,0.637800,0.0,0.0,0.0,0.0,0.0 +0,0.637900,0.0,0.0,0.0,0.0,0.0 +0,0.638000,0.0,0.0,0.0,0.0,0.0 +0,0.638100,0.0,0.0,0.0,0.0,0.0 +0,0.638200,0.0,0.0,0.0,0.0,0.0 +0,0.638300,0.0,0.0,0.0,0.0,0.0 +0,0.638400,0.0,0.0,0.0,0.0,0.0 +0,0.638500,0.0,0.0,0.0,0.0,0.0 +0,0.638600,0.0,0.0,0.0,0.0,0.0 +0,0.638700,0.0,0.0,0.0,0.0,0.0 +0,0.638800,0.0,0.0,0.0,0.0,0.0 +0,0.638900,0.0,0.0,0.0,0.0,0.0 +0,0.639000,0.0,0.0,0.0,0.0,0.0 +0,0.639100,0.0,0.0,0.0,0.0,0.0 +0,0.639200,0.0,0.0,0.0,0.0,0.0 +0,0.639300,0.0,0.0,0.0,0.0,0.0 +0,0.639400,0.0,0.0,0.0,0.0,0.0 +0,0.639500,0.0,0.0,0.0,0.0,0.0 +0,0.639600,0.0,0.0,0.0,0.0,0.0 +0,0.639700,0.0,0.0,0.0,0.0,0.0 +0,0.639800,0.0,0.0,0.0,0.0,0.0 +0,0.639900,0.0,0.0,0.0,0.0,0.0 +0,0.640000,0.0,0.0,0.0,0.0,0.0 +0,0.640100,0.0,0.0,0.0,0.0,0.0 +1,109.303484,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.640200,0.0,0.0,0.0,0.0,0.0 +0,0.640300,0.0,0.0,0.0,0.0,0.0 +0,0.640400,0.0,0.0,0.0,0.0,0.0 +0,0.640500,0.0,0.0,0.0,0.0,0.0 +0,0.640600,0.0,0.0,0.0,0.0,0.0 +0,0.640700,0.0,0.0,0.0,0.0,0.0 +0,0.640800,0.0,0.0,0.0,0.0,0.0 +0,0.640900,0.0,0.0,0.0,0.0,0.0 +0,0.641000,0.0,0.0,0.0,0.0,0.0 +0,0.641100,0.0,0.0,0.0,0.0,0.0 +0,0.641200,0.0,0.0,0.0,0.0,0.0 +0,0.641300,0.0,0.0,0.0,0.0,0.0 +0,0.641400,0.0,0.0,0.0,0.0,0.0 +0,0.641500,0.0,0.0,0.0,0.0,0.0 +0,0.641600,0.0,0.0,0.0,0.0,0.0 +0,0.641700,0.0,0.0,0.0,0.0,0.0 +0,0.641800,0.0,0.0,0.0,0.0,0.0 +0,0.641900,0.0,0.0,0.0,0.0,0.0 +0,0.642000,0.0,0.0,0.0,0.0,0.0 +0,0.642100,0.0,0.0,0.0,0.0,0.0 +0,0.642200,0.0,0.0,0.0,0.0,0.0 +0,0.642300,0.0,0.0,0.0,0.0,0.0 +0,0.642400,0.0,0.0,0.0,0.0,0.0 +0,0.642500,0.0,0.0,0.0,0.0,0.0 +0,0.642600,0.0,0.0,0.0,0.0,0.0 +0,0.642700,0.0,0.0,0.0,0.0,0.0 +0,0.642800,0.0,0.0,0.0,0.0,0.0 +0,0.642900,0.0,0.0,0.0,0.0,0.0 +0,0.643000,0.0,0.0,0.0,0.0,0.0 +0,0.643100,0.0,0.0,0.0,0.0,0.0 +0,0.643200,0.0,0.0,0.0,0.0,0.0 +0,0.643300,0.0,0.0,0.0,0.0,0.0 +0,0.643400,0.0,0.0,0.0,0.0,0.0 +0,0.643500,0.0,0.0,0.0,0.0,0.0 +0,0.643600,0.0,0.0,0.0,0.0,0.0 +0,0.643700,0.0,0.0,0.0,0.0,0.0 +0,0.643800,0.0,0.0,0.0,0.0,0.0 +0,0.643900,0.0,0.0,0.0,0.0,0.0 +0,0.644000,0.0,0.0,0.0,0.0,0.0 +0,0.644100,0.0,0.0,0.0,0.0,0.0 +0,0.644200,0.0,0.0,0.0,0.0,0.0 +0,0.644300,0.0,0.0,0.0,0.0,0.0 +0,0.644400,0.0,0.0,0.0,0.0,0.0 +0,0.644500,0.0,0.0,0.0,0.0,0.0 +0,0.644600,0.0,0.0,0.0,0.0,0.0 +0,0.644700,0.0,0.0,0.0,0.0,0.0 +0,0.644800,0.0,0.0,0.0,0.0,0.0 +0,0.644900,0.0,0.0,0.0,0.0,0.0 +0,0.645000,0.0,0.0,0.0,0.0,0.0 +0,0.645100,0.0,0.0,0.0,0.0,0.0 +0,0.645200,0.0,0.0,0.0,0.0,0.0 +0,0.645300,0.0,0.0,0.0,0.0,0.0 +0,0.645400,0.0,0.0,0.0,0.0,0.0 +0,0.645500,0.0,0.0,0.0,0.0,0.0 +0,0.645600,0.0,0.0,0.0,0.0,0.0 +0,0.645700,0.0,0.0,0.0,0.0,0.0 +0,0.645800,0.0,0.0,0.0,0.0,0.0 +0,0.645900,0.0,0.0,0.0,0.0,0.0 +0,0.646000,0.0,0.0,0.0,0.0,0.0 +0,0.646100,0.0,0.0,0.0,0.0,0.0 +0,0.646200,0.0,0.0,0.0,0.0,0.0 +0,0.646300,0.0,0.0,0.0,0.0,0.0 +0,0.646400,0.0,0.0,0.0,0.0,0.0 +0,0.646500,0.0,0.0,0.0,0.0,0.0 +0,0.646600,0.0,0.0,0.0,0.0,0.0 +0,0.646700,0.0,0.0,0.0,0.0,0.0 +0,0.646800,0.0,0.0,0.0,0.0,0.0 +0,0.646900,0.0,0.0,0.0,0.0,0.0 +0,0.647000,0.0,0.0,0.0,0.0,0.0 +0,0.647100,0.0,0.0,0.0,0.0,0.0 +0,0.647200,0.0,0.0,0.0,0.0,0.0 +0,0.647300,0.0,0.0,0.0,0.0,0.0 +0,0.647400,0.0,0.0,0.0,0.0,0.0 +0,0.647500,0.0,0.0,0.0,0.0,0.0 +0,0.647600,0.0,0.0,0.0,0.0,0.0 +0,0.647700,0.0,0.0,0.0,0.0,0.0 +0,0.647800,0.0,0.0,0.0,0.0,0.0 +0,0.647900,0.0,0.0,0.0,0.0,0.0 +0,0.648000,0.0,0.0,0.0,0.0,0.0 +0,0.648100,0.0,0.0,0.0,0.0,0.0 +0,0.648200,0.0,0.0,0.0,0.0,0.0 +0,0.648300,0.0,0.0,0.0,0.0,0.0 +0,0.648400,0.0,0.0,0.0,0.0,0.0 +0,0.648500,0.0,0.0,0.0,0.0,0.0 +0,0.648600,0.0,0.0,0.0,0.0,0.0 +0,0.648700,0.0,0.0,0.0,0.0,0.0 +0,0.648800,0.0,0.0,0.0,0.0,0.0 +0,0.648900,0.0,0.0,0.0,0.0,0.0 +0,0.649000,0.0,0.0,0.0,0.0,0.0 +0,0.649100,0.0,0.0,0.0,0.0,0.0 +0,0.649200,0.0,0.0,0.0,0.0,0.0 +0,0.649300,0.0,0.0,0.0,0.0,0.0 +0,0.649400,0.0,0.0,0.0,0.0,0.0 +0,0.649500,0.0,0.0,0.0,0.0,0.0 +0,0.649600,0.0,0.0,0.0,0.0,0.0 +0,0.649700,0.0,0.0,0.0,0.0,0.0 +0,0.649800,0.0,0.0,0.0,0.0,0.0 +0,0.649900,0.0,0.0,0.0,0.0,0.0 +0,0.650000,0.0,0.0,0.0,0.0,0.0 +0,0.650100,0.0,0.0,0.0,0.0,0.0 +0,0.650200,0.0,0.0,0.0,0.0,0.0 +0,0.650300,0.0,0.0,0.0,0.0,0.0 +0,0.650400,0.0,0.0,0.0,0.0,0.0 +0,0.650500,0.0,0.0,0.0,0.0,0.0 +0,0.650600,0.0,0.0,0.0,0.0,0.0 +0,0.650700,0.0,0.0,0.0,0.0,0.0 +0,0.650800,0.0,0.0,0.0,0.0,0.0 +0,0.650900,0.0,0.0,0.0,0.0,0.0 +0,0.651000,0.0,0.0,0.0,0.0,0.0 +0,0.651100,0.0,0.0,0.0,0.0,0.0 +0,0.651200,0.0,0.0,0.0,0.0,0.0 +0,0.651300,0.0,0.0,0.0,0.0,0.0 +0,0.651400,0.0,0.0,0.0,0.0,0.0 +0,0.651500,0.0,0.0,0.0,0.0,0.0 +0,0.651600,0.0,0.0,0.0,0.0,0.0 +0,0.651700,0.0,0.0,0.0,0.0,0.0 +0,0.651800,0.0,0.0,0.0,0.0,0.0 +0,0.651900,0.0,0.0,0.0,0.0,0.0 +0,0.652000,0.0,0.0,0.0,0.0,0.0 +0,0.652100,0.0,0.0,0.0,0.0,0.0 +0,0.652200,0.0,0.0,0.0,0.0,0.0 +0,0.652300,0.0,0.0,0.0,0.0,0.0 +0,0.652400,0.0,0.0,0.0,0.0,0.0 +0,0.652500,0.0,0.0,0.0,0.0,0.0 +0,0.652600,0.0,0.0,0.0,0.0,0.0 +0,0.652700,0.0,0.0,0.0,0.0,0.0 +0,0.652800,0.0,0.0,0.0,0.0,0.0 +0,0.652900,0.0,0.0,0.0,0.0,0.0 +0,0.653000,0.0,0.0,0.0,0.0,0.0 +0,0.653100,0.0,0.0,0.0,0.0,0.0 +0,0.653200,0.0,0.0,0.0,0.0,0.0 +0,0.653300,0.0,0.0,0.0,0.0,0.0 +0,0.653400,0.0,0.0,0.0,0.0,0.0 +0,0.653500,0.0,0.0,0.0,0.0,0.0 +0,0.653600,0.0,0.0,0.0,0.0,0.0 +0,0.653700,0.0,0.0,0.0,0.0,0.0 +0,0.653800,0.0,0.0,0.0,0.0,0.0 +0,0.653900,0.0,0.0,0.0,0.0,0.0 +0,0.654000,0.0,0.0,0.0,0.0,0.0 +0,0.654100,0.0,0.0,0.0,0.0,0.0 +0,0.654200,0.0,0.0,0.0,0.0,0.0 +0,0.654300,0.0,0.0,0.0,0.0,0.0 +0,0.654400,0.0,0.0,0.0,0.0,0.0 +0,0.654500,0.0,0.0,0.0,0.0,0.0 +0,0.654600,0.0,0.0,0.0,0.0,0.0 +0,0.654700,0.0,0.0,0.0,0.0,0.0 +0,0.654800,0.0,0.0,0.0,0.0,0.0 +0,0.654900,0.0,0.0,0.0,0.0,0.0 +0,0.655000,0.0,0.0,0.0,0.0,0.0 +0,0.655100,0.0,0.0,0.0,0.0,0.0 +0,0.655200,0.0,0.0,0.0,0.0,0.0 +0,0.655300,0.0,0.0,0.0,0.0,0.0 +0,0.655400,0.0,0.0,0.0,0.0,0.0 +0,0.655500,0.0,0.0,0.0,0.0,0.0 +0,0.655600,0.0,0.0,0.0,0.0,0.0 +0,0.655700,0.0,0.0,0.0,0.0,0.0 +0,0.655800,0.0,0.0,0.0,0.0,0.0 +0,0.655900,0.0,0.0,0.0,0.0,0.0 +0,0.656000,0.0,0.0,0.0,0.0,0.0 +0,0.656100,0.0,0.0,0.0,0.0,0.0 +0,0.656200,0.0,0.0,0.0,0.0,0.0 +0,0.656300,0.0,0.0,0.0,0.0,0.0 +0,0.656400,0.0,0.0,0.0,0.0,0.0 +0,0.656500,0.0,0.0,0.0,0.0,0.0 +0,0.656600,0.0,0.0,0.0,0.0,0.0 +0,0.656700,0.0,0.0,0.0,0.0,0.0 +0,0.656800,0.0,0.0,0.0,0.0,0.0 +0,0.656900,0.0,0.0,0.0,0.0,0.0 +0,0.657000,0.0,0.0,0.0,0.0,0.0 +0,0.657100,0.0,0.0,0.0,0.0,0.0 +0,0.657200,0.0,0.0,0.0,0.0,0.0 +0,0.657300,0.0,0.0,0.0,0.0,0.0 +0,0.657400,0.0,0.0,0.0,0.0,0.0 +0,0.657500,0.0,0.0,0.0,0.0,0.0 +0,0.657600,0.0,0.0,0.0,0.0,0.0 +0,0.657700,0.0,0.0,0.0,0.0,0.0 +0,0.657800,0.0,0.0,0.0,0.0,0.0 +0,0.657900,0.0,0.0,0.0,0.0,0.0 +0,0.658000,0.0,0.0,0.0,0.0,0.0 +0,0.658100,0.0,0.0,0.0,0.0,0.0 +0,0.658200,0.0,0.0,0.0,0.0,0.0 +0,0.658300,0.0,0.0,0.0,0.0,0.0 +0,0.658400,0.0,0.0,0.0,0.0,0.0 +0,0.658500,0.0,0.0,0.0,0.0,0.0 +0,0.658600,0.0,0.0,0.0,0.0,0.0 +0,0.658700,0.0,0.0,0.0,0.0,0.0 +0,0.658800,0.0,0.0,0.0,0.0,0.0 +0,0.658900,0.0,0.0,0.0,0.0,0.0 +0,0.659000,0.0,0.0,0.0,0.0,0.0 +0,0.659100,0.0,0.0,0.0,0.0,0.0 +0,0.659200,0.0,0.0,0.0,0.0,0.0 +0,0.659300,0.0,0.0,0.0,0.0,0.0 +0,0.659400,0.0,0.0,0.0,0.0,0.0 +0,0.659500,0.0,0.0,0.0,0.0,0.0 +0,0.659600,0.0,0.0,0.0,0.0,0.0 +0,0.659700,0.0,0.0,0.0,0.0,0.0 +0,0.659800,0.0,0.0,0.0,0.0,0.0 +0,0.659900,0.0,0.0,0.0,0.0,0.0 +0,0.660000,0.0,0.0,0.0,0.0,0.0 +0,0.660100,0.0,0.0,0.0,0.0,0.0 +1,119.871693,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.660200,0.0,0.0,0.0,0.0,0.0 +0,0.660300,0.0,0.0,0.0,0.0,0.0 +0,0.660400,0.0,0.0,0.0,0.0,0.0 +0,0.660500,0.0,0.0,0.0,0.0,0.0 +0,0.660600,0.0,0.0,0.0,0.0,0.0 +0,0.660700,0.0,0.0,0.0,0.0,0.0 +0,0.660800,0.0,0.0,0.0,0.0,0.0 +0,0.660900,0.0,0.0,0.0,0.0,0.0 +0,0.661000,0.0,0.0,0.0,0.0,0.0 +0,0.661100,0.0,0.0,0.0,0.0,0.0 +0,0.661200,0.0,0.0,0.0,0.0,0.0 +0,0.661300,0.0,0.0,0.0,0.0,0.0 +0,0.661400,0.0,0.0,0.0,0.0,0.0 +0,0.661500,0.0,0.0,0.0,0.0,0.0 +0,0.661600,0.0,0.0,0.0,0.0,0.0 +0,0.661700,0.0,0.0,0.0,0.0,0.0 +0,0.661800,0.0,0.0,0.0,0.0,0.0 +0,0.661900,0.0,0.0,0.0,0.0,0.0 +0,0.662000,0.0,0.0,0.0,0.0,0.0 +0,0.662100,0.0,0.0,0.0,0.0,0.0 +0,0.662200,0.0,0.0,0.0,0.0,0.0 +0,0.662300,0.0,0.0,0.0,0.0,0.0 +0,0.662400,0.0,0.0,0.0,0.0,0.0 +0,0.662500,0.0,0.0,0.0,0.0,0.0 +0,0.662600,0.0,0.0,0.0,0.0,0.0 +0,0.662700,0.0,0.0,0.0,0.0,0.0 +0,0.662800,0.0,0.0,0.0,0.0,0.0 +0,0.662900,0.0,0.0,0.0,0.0,0.0 +0,0.663000,0.0,0.0,0.0,0.0,0.0 +0,0.663100,0.0,0.0,0.0,0.0,0.0 +0,0.663200,0.0,0.0,0.0,0.0,0.0 +0,0.663300,0.0,0.0,0.0,0.0,0.0 +0,0.663400,0.0,0.0,0.0,0.0,0.0 +0,0.663500,0.0,0.0,0.0,0.0,0.0 +0,0.663600,0.0,0.0,0.0,0.0,0.0 +0,0.663700,0.0,0.0,0.0,0.0,0.0 +0,0.663800,0.0,0.0,0.0,0.0,0.0 +0,0.663900,0.0,0.0,0.0,0.0,0.0 +0,0.664000,0.0,0.0,0.0,0.0,0.0 +0,0.664100,0.0,0.0,0.0,0.0,0.0 +0,0.664200,0.0,0.0,0.0,0.0,0.0 +0,0.664300,0.0,0.0,0.0,0.0,0.0 +0,0.664400,0.0,0.0,0.0,0.0,0.0 +0,0.664500,0.0,0.0,0.0,0.0,0.0 +0,0.664600,0.0,0.0,0.0,0.0,0.0 +0,0.664700,0.0,0.0,0.0,0.0,0.0 +0,0.664800,0.0,0.0,0.0,0.0,0.0 +0,0.664900,0.0,0.0,0.0,0.0,0.0 +0,0.665000,0.0,0.0,0.0,0.0,0.0 +0,0.665100,0.0,0.0,0.0,0.0,0.0 +0,0.665200,0.0,0.0,0.0,0.0,0.0 +0,0.665300,0.0,0.0,0.0,0.0,0.0 +0,0.665400,0.0,0.0,0.0,0.0,0.0 +0,0.665500,0.0,0.0,0.0,0.0,0.0 +0,0.665600,0.0,0.0,0.0,0.0,0.0 +0,0.665700,0.0,0.0,0.0,0.0,0.0 +0,0.665800,0.0,0.0,0.0,0.0,0.0 +0,0.665900,0.0,0.0,0.0,0.0,0.0 +0,0.666000,0.0,0.0,0.0,0.0,0.0 +0,0.666100,0.0,0.0,0.0,0.0,0.0 +0,0.666200,0.0,0.0,0.0,0.0,0.0 +0,0.666300,0.0,0.0,0.0,0.0,0.0 +0,0.666400,0.0,0.0,0.0,0.0,0.0 +0,0.666500,0.0,0.0,0.0,0.0,0.0 +0,0.666600,0.0,0.0,0.0,0.0,0.0 +0,0.666700,0.0,0.0,0.0,0.0,0.0 +0,0.666800,0.0,0.0,0.0,0.0,0.0 +0,0.666900,0.0,0.0,0.0,0.0,0.0 +0,0.667000,0.0,0.0,0.0,0.0,0.0 +0,0.667100,0.0,0.0,0.0,0.0,0.0 +0,0.667200,0.0,0.0,0.0,0.0,0.0 +0,0.667300,0.0,0.0,0.0,0.0,0.0 +0,0.667400,0.0,0.0,0.0,0.0,0.0 +0,0.667500,0.0,0.0,0.0,0.0,0.0 +0,0.667600,0.0,0.0,0.0,0.0,0.0 +0,0.667700,0.0,0.0,0.0,0.0,0.0 +0,0.667800,0.0,0.0,0.0,0.0,0.0 +0,0.667900,0.0,0.0,0.0,0.0,0.0 +0,0.668000,0.0,0.0,0.0,0.0,0.0 +0,0.668100,0.0,0.0,0.0,0.0,0.0 +0,0.668200,0.0,0.0,0.0,0.0,0.0 +0,0.668300,0.0,0.0,0.0,0.0,0.0 +0,0.668400,0.0,0.0,0.0,0.0,0.0 +0,0.668500,0.0,0.0,0.0,0.0,0.0 +0,0.668600,0.0,0.0,0.0,0.0,0.0 +0,0.668700,0.0,0.0,0.0,0.0,0.0 +0,0.668800,0.0,0.0,0.0,0.0,0.0 +0,0.668900,0.0,0.0,0.0,0.0,0.0 +0,0.669000,0.0,0.0,0.0,0.0,0.0 +0,0.669100,0.0,0.0,0.0,0.0,0.0 +0,0.669200,0.0,0.0,0.0,0.0,0.0 +0,0.669300,0.0,0.0,0.0,0.0,0.0 +0,0.669400,0.0,0.0,0.0,0.0,0.0 +0,0.669500,0.0,0.0,0.0,0.0,0.0 +0,0.669600,0.0,0.0,0.0,0.0,0.0 +0,0.669700,0.0,0.0,0.0,0.0,0.0 +0,0.669800,0.0,0.0,0.0,0.0,0.0 +0,0.669900,0.0,0.0,0.0,0.0,0.0 +0,0.670000,0.0,0.0,0.0,0.0,0.0 +0,0.670100,0.0,0.0,0.0,0.0,0.0 +0,0.670200,0.0,0.0,0.0,0.0,0.0 +0,0.670300,0.0,0.0,0.0,0.0,0.0 +0,0.670400,0.0,0.0,0.0,0.0,0.0 +0,0.670500,0.0,0.0,0.0,0.0,0.0 +0,0.670600,0.0,0.0,0.0,0.0,0.0 +0,0.670700,0.0,0.0,0.0,0.0,0.0 +0,0.670800,0.0,0.0,0.0,0.0,0.0 +0,0.670900,0.0,0.0,0.0,0.0,0.0 +0,0.671000,0.0,0.0,0.0,0.0,0.0 +0,0.671100,0.0,0.0,0.0,0.0,0.0 +0,0.671200,0.0,0.0,0.0,0.0,0.0 +0,0.671300,0.0,0.0,0.0,0.0,0.0 +0,0.671400,0.0,0.0,0.0,0.0,0.0 +0,0.671500,0.0,0.0,0.0,0.0,0.0 +0,0.671600,0.0,0.0,0.0,0.0,0.0 +0,0.671700,0.0,0.0,0.0,0.0,0.0 +0,0.671800,0.0,0.0,0.0,0.0,0.0 +0,0.671900,0.0,0.0,0.0,0.0,0.0 +0,0.672000,0.0,0.0,0.0,0.0,0.0 +0,0.672100,0.0,0.0,0.0,0.0,0.0 +0,0.672200,0.0,0.0,0.0,0.0,0.0 +0,0.672300,0.0,0.0,0.0,0.0,0.0 +0,0.672400,0.0,0.0,0.0,0.0,0.0 +0,0.672500,0.0,0.0,0.0,0.0,0.0 +0,0.672600,0.0,0.0,0.0,0.0,0.0 +0,0.672700,0.0,0.0,0.0,0.0,0.0 +0,0.672800,0.0,0.0,0.0,0.0,0.0 +0,0.672900,0.0,0.0,0.0,0.0,0.0 +0,0.673000,0.0,0.0,0.0,0.0,0.0 +0,0.673100,0.0,0.0,0.0,0.0,0.0 +0,0.673200,0.0,0.0,0.0,0.0,0.0 +0,0.673300,0.0,0.0,0.0,0.0,0.0 +0,0.673400,0.0,0.0,0.0,0.0,0.0 +0,0.673500,0.0,0.0,0.0,0.0,0.0 +0,0.673600,0.0,0.0,0.0,0.0,0.0 +0,0.673700,0.0,0.0,0.0,0.0,0.0 +0,0.673800,0.0,0.0,0.0,0.0,0.0 +0,0.673900,0.0,0.0,0.0,0.0,0.0 +0,0.674000,0.0,0.0,0.0,0.0,0.0 +0,0.674100,0.0,0.0,0.0,0.0,0.0 +0,0.674200,0.0,0.0,0.0,0.0,0.0 +0,0.674300,0.0,0.0,0.0,0.0,0.0 +0,0.674400,0.0,0.0,0.0,0.0,0.0 +0,0.674500,0.0,0.0,0.0,0.0,0.0 +0,0.674600,0.0,0.0,0.0,0.0,0.0 +0,0.674700,0.0,0.0,0.0,0.0,0.0 +0,0.674800,0.0,0.0,0.0,0.0,0.0 +0,0.674900,0.0,0.0,0.0,0.0,0.0 +0,0.675000,0.0,0.0,0.0,0.0,0.0 +0,0.675100,0.0,0.0,0.0,0.0,0.0 +0,0.675200,0.0,0.0,0.0,0.0,0.0 +0,0.675300,0.0,0.0,0.0,0.0,0.0 +0,0.675400,0.0,0.0,0.0,0.0,0.0 +0,0.675500,0.0,0.0,0.0,0.0,0.0 +0,0.675600,0.0,0.0,0.0,0.0,0.0 +0,0.675700,0.0,0.0,0.0,0.0,0.0 +0,0.675800,0.0,0.0,0.0,0.0,0.0 +0,0.675900,0.0,0.0,0.0,0.0,0.0 +0,0.676000,0.0,0.0,0.0,0.0,0.0 +0,0.676100,0.0,0.0,0.0,0.0,0.0 +0,0.676200,0.0,0.0,0.0,0.0,0.0 +0,0.676300,0.0,0.0,0.0,0.0,0.0 +0,0.676400,0.0,0.0,0.0,0.0,0.0 +0,0.676500,0.0,0.0,0.0,0.0,0.0 +0,0.676600,0.0,0.0,0.0,0.0,0.0 +0,0.676700,0.0,0.0,0.0,0.0,0.0 +0,0.676800,0.0,0.0,0.0,0.0,0.0 +0,0.676900,0.0,0.0,0.0,0.0,0.0 +0,0.677000,0.0,0.0,0.0,0.0,0.0 +0,0.677100,0.0,0.0,0.0,0.0,0.0 +0,0.677200,0.0,0.0,0.0,0.0,0.0 +0,0.677300,0.0,0.0,0.0,0.0,0.0 +0,0.677400,0.0,0.0,0.0,0.0,0.0 +0,0.677500,0.0,0.0,0.0,0.0,0.0 +0,0.677600,0.0,0.0,0.0,0.0,0.0 +0,0.677700,0.0,0.0,0.0,0.0,0.0 +0,0.677800,0.0,0.0,0.0,0.0,0.0 +0,0.677900,0.0,0.0,0.0,0.0,0.0 +0,0.678000,0.0,0.0,0.0,0.0,0.0 +0,0.678100,0.0,0.0,0.0,0.0,0.0 +0,0.678200,0.0,0.0,0.0,0.0,0.0 +0,0.678300,0.0,0.0,0.0,0.0,0.0 +0,0.678400,0.0,0.0,0.0,0.0,0.0 +0,0.678500,0.0,0.0,0.0,0.0,0.0 +0,0.678600,0.0,0.0,0.0,0.0,0.0 +0,0.678700,0.0,0.0,0.0,0.0,0.0 +0,0.678800,0.0,0.0,0.0,0.0,0.0 +0,0.678900,0.0,0.0,0.0,0.0,0.0 +0,0.679000,0.0,0.0,0.0,0.0,0.0 +0,0.679100,0.0,0.0,0.0,0.0,0.0 +0,0.679200,0.0,0.0,0.0,0.0,0.0 +0,0.679300,0.0,0.0,0.0,0.0,0.0 +0,0.679400,0.0,0.0,0.0,0.0,0.0 +0,0.679500,0.0,0.0,0.0,0.0,0.0 +0,0.679600,0.0,0.0,0.0,0.0,0.0 +0,0.679700,0.0,0.0,0.0,0.0,0.0 +0,0.679800,0.0,0.0,0.0,0.0,0.0 +0,0.679900,0.0,0.0,0.0,0.0,0.0 +0,0.680000,0.0,0.0,0.0,0.0,0.0 +0,0.680100,0.0,0.0,0.0,0.0,0.0 +1,131.100052,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.680200,0.0,0.0,0.0,0.0,0.0 +0,0.680300,0.0,0.0,0.0,0.0,0.0 +0,0.680400,0.0,0.0,0.0,0.0,0.0 +0,0.680500,0.0,0.0,0.0,0.0,0.0 +0,0.680600,0.0,0.0,0.0,0.0,0.0 +0,0.680700,0.0,0.0,0.0,0.0,0.0 +0,0.680800,0.0,0.0,0.0,0.0,0.0 +0,0.680900,0.0,0.0,0.0,0.0,0.0 +0,0.681000,0.0,0.0,0.0,0.0,0.0 +0,0.681100,0.0,0.0,0.0,0.0,0.0 +0,0.681200,0.0,0.0,0.0,0.0,0.0 +0,0.681300,0.0,0.0,0.0,0.0,0.0 +0,0.681400,0.0,0.0,0.0,0.0,0.0 +0,0.681500,0.0,0.0,0.0,0.0,0.0 +0,0.681600,0.0,0.0,0.0,0.0,0.0 +0,0.681700,0.0,0.0,0.0,0.0,0.0 +0,0.681800,0.0,0.0,0.0,0.0,0.0 +0,0.681900,0.0,0.0,0.0,0.0,0.0 +0,0.682000,0.0,0.0,0.0,0.0,0.0 +0,0.682100,0.0,0.0,0.0,0.0,0.0 +0,0.682200,0.0,0.0,0.0,0.0,0.0 +0,0.682300,0.0,0.0,0.0,0.0,0.0 +0,0.682400,0.0,0.0,0.0,0.0,0.0 +0,0.682500,0.0,0.0,0.0,0.0,0.0 +0,0.682600,0.0,0.0,0.0,0.0,0.0 +0,0.682700,0.0,0.0,0.0,0.0,0.0 +0,0.682800,0.0,0.0,0.0,0.0,0.0 +0,0.682900,0.0,0.0,0.0,0.0,0.0 +0,0.683000,0.0,0.0,0.0,0.0,0.0 +0,0.683100,0.0,0.0,0.0,0.0,0.0 +0,0.683200,0.0,0.0,0.0,0.0,0.0 +0,0.683300,0.0,0.0,0.0,0.0,0.0 +0,0.683400,0.0,0.0,0.0,0.0,0.0 +0,0.683500,0.0,0.0,0.0,0.0,0.0 +0,0.683600,0.0,0.0,0.0,0.0,0.0 +0,0.683700,0.0,0.0,0.0,0.0,0.0 +0,0.683800,0.0,0.0,0.0,0.0,0.0 +0,0.683900,0.0,0.0,0.0,0.0,0.0 +0,0.684000,0.0,0.0,0.0,0.0,0.0 +0,0.684100,0.0,0.0,0.0,0.0,0.0 +0,0.684200,0.0,0.0,0.0,0.0,0.0 +0,0.684300,0.0,0.0,0.0,0.0,0.0 +0,0.684400,0.0,0.0,0.0,0.0,0.0 +0,0.684500,0.0,0.0,0.0,0.0,0.0 +0,0.684600,0.0,0.0,0.0,0.0,0.0 +0,0.684700,0.0,0.0,0.0,0.0,0.0 +0,0.684800,0.0,0.0,0.0,0.0,0.0 +0,0.684900,0.0,0.0,0.0,0.0,0.0 +0,0.685000,0.0,0.0,0.0,0.0,0.0 +0,0.685100,0.0,0.0,0.0,0.0,0.0 +0,0.685200,0.0,0.0,0.0,0.0,0.0 +0,0.685300,0.0,0.0,0.0,0.0,0.0 +0,0.685400,0.0,0.0,0.0,0.0,0.0 +0,0.685500,0.0,0.0,0.0,0.0,0.0 +0,0.685600,0.0,0.0,0.0,0.0,0.0 +0,0.685700,0.0,0.0,0.0,0.0,0.0 +0,0.685800,0.0,0.0,0.0,0.0,0.0 +0,0.685900,0.0,0.0,0.0,0.0,0.0 +0,0.686000,0.0,0.0,0.0,0.0,0.0 +0,0.686100,0.0,0.0,0.0,0.0,0.0 +0,0.686200,0.0,0.0,0.0,0.0,0.0 +0,0.686300,0.0,0.0,0.0,0.0,0.0 +0,0.686400,0.0,0.0,0.0,0.0,0.0 +0,0.686500,0.0,0.0,0.0,0.0,0.0 +0,0.686600,0.0,0.0,0.0,0.0,0.0 +0,0.686700,0.0,0.0,0.0,0.0,0.0 +0,0.686800,0.0,0.0,0.0,0.0,0.0 +0,0.686900,0.0,0.0,0.0,0.0,0.0 +0,0.687000,0.0,0.0,0.0,0.0,0.0 +0,0.687100,0.0,0.0,0.0,0.0,0.0 +0,0.687200,0.0,0.0,0.0,0.0,0.0 +0,0.687300,0.0,0.0,0.0,0.0,0.0 +0,0.687400,0.0,0.0,0.0,0.0,0.0 +0,0.687500,0.0,0.0,0.0,0.0,0.0 +0,0.687600,0.0,0.0,0.0,0.0,0.0 +0,0.687700,0.0,0.0,0.0,0.0,0.0 +0,0.687800,0.0,0.0,0.0,0.0,0.0 +0,0.687900,0.0,0.0,0.0,0.0,0.0 +0,0.688000,0.0,0.0,0.0,0.0,0.0 +0,0.688100,0.0,0.0,0.0,0.0,0.0 +0,0.688200,0.0,0.0,0.0,0.0,0.0 +0,0.688300,0.0,0.0,0.0,0.0,0.0 +0,0.688400,0.0,0.0,0.0,0.0,0.0 +0,0.688500,0.0,0.0,0.0,0.0,0.0 +0,0.688600,0.0,0.0,0.0,0.0,0.0 +0,0.688700,0.0,0.0,0.0,0.0,0.0 +0,0.688800,0.0,0.0,0.0,0.0,0.0 +0,0.688900,0.0,0.0,0.0,0.0,0.0 +0,0.689000,0.0,0.0,0.0,0.0,0.0 +0,0.689100,0.0,0.0,0.0,0.0,0.0 +0,0.689200,0.0,0.0,0.0,0.0,0.0 +0,0.689300,0.0,0.0,0.0,0.0,0.0 +0,0.689400,0.0,0.0,0.0,0.0,0.0 +0,0.689500,0.0,0.0,0.0,0.0,0.0 +0,0.689600,0.0,0.0,0.0,0.0,0.0 +0,0.689700,0.0,0.0,0.0,0.0,0.0 +0,0.689800,0.0,0.0,0.0,0.0,0.0 +0,0.689900,0.0,0.0,0.0,0.0,0.0 +0,0.690000,0.0,0.0,0.0,0.0,0.0 +0,0.690100,0.0,0.0,0.0,0.0,0.0 +0,0.690200,0.0,0.0,0.0,0.0,0.0 +0,0.690300,0.0,0.0,0.0,0.0,0.0 +0,0.690400,0.0,0.0,0.0,0.0,0.0 +0,0.690500,0.0,0.0,0.0,0.0,0.0 +0,0.690600,0.0,0.0,0.0,0.0,0.0 +0,0.690700,0.0,0.0,0.0,0.0,0.0 +0,0.690800,0.0,0.0,0.0,0.0,0.0 +0,0.690900,0.0,0.0,0.0,0.0,0.0 +0,0.691000,0.0,0.0,0.0,0.0,0.0 +0,0.691100,0.0,0.0,0.0,0.0,0.0 +0,0.691200,0.0,0.0,0.0,0.0,0.0 +0,0.691300,0.0,0.0,0.0,0.0,0.0 +0,0.691400,0.0,0.0,0.0,0.0,0.0 +0,0.691500,0.0,0.0,0.0,0.0,0.0 +0,0.691600,0.0,0.0,0.0,0.0,0.0 +0,0.691700,0.0,0.0,0.0,0.0,0.0 +0,0.691800,0.0,0.0,0.0,0.0,0.0 +0,0.691900,0.0,0.0,0.0,0.0,0.0 +0,0.692000,0.0,0.0,0.0,0.0,0.0 +0,0.692100,0.0,0.0,0.0,0.0,0.0 +0,0.692200,0.0,0.0,0.0,0.0,0.0 +0,0.692300,0.0,0.0,0.0,0.0,0.0 +0,0.692400,0.0,0.0,0.0,0.0,0.0 +0,0.692500,0.0,0.0,0.0,0.0,0.0 +0,0.692600,0.0,0.0,0.0,0.0,0.0 +0,0.692700,0.0,0.0,0.0,0.0,0.0 +0,0.692800,0.0,0.0,0.0,0.0,0.0 +0,0.692900,0.0,0.0,0.0,0.0,0.0 +0,0.693000,0.0,0.0,0.0,0.0,0.0 +0,0.693100,0.0,0.0,0.0,0.0,0.0 +0,0.693200,0.0,0.0,0.0,0.0,0.0 +0,0.693300,0.0,0.0,0.0,0.0,0.0 +0,0.693400,0.0,0.0,0.0,0.0,0.0 +0,0.693500,0.0,0.0,0.0,0.0,0.0 +0,0.693600,0.0,0.0,0.0,0.0,0.0 +0,0.693700,0.0,0.0,0.0,0.0,0.0 +0,0.693800,0.0,0.0,0.0,0.0,0.0 +0,0.693900,0.0,0.0,0.0,0.0,0.0 +0,0.694000,0.0,0.0,0.0,0.0,0.0 +0,0.694100,0.0,0.0,0.0,0.0,0.0 +0,0.694200,0.0,0.0,0.0,0.0,0.0 +0,0.694300,0.0,0.0,0.0,0.0,0.0 +0,0.694400,0.0,0.0,0.0,0.0,0.0 +0,0.694500,0.0,0.0,0.0,0.0,0.0 +0,0.694600,0.0,0.0,0.0,0.0,0.0 +0,0.694700,0.0,0.0,0.0,0.0,0.0 +0,0.694800,0.0,0.0,0.0,0.0,0.0 +0,0.694900,0.0,0.0,0.0,0.0,0.0 +0,0.695000,0.0,0.0,0.0,0.0,0.0 +0,0.695100,0.0,0.0,0.0,0.0,0.0 +0,0.695200,0.0,0.0,0.0,0.0,0.0 +0,0.695300,0.0,0.0,0.0,0.0,0.0 +0,0.695400,0.0,0.0,0.0,0.0,0.0 +0,0.695500,0.0,0.0,0.0,0.0,0.0 +0,0.695600,0.0,0.0,0.0,0.0,0.0 +0,0.695700,0.0,0.0,0.0,0.0,0.0 +0,0.695800,0.0,0.0,0.0,0.0,0.0 +0,0.695900,0.0,0.0,0.0,0.0,0.0 +0,0.696000,0.0,0.0,0.0,0.0,0.0 +0,0.696100,0.0,0.0,0.0,0.0,0.0 +0,0.696200,0.0,0.0,0.0,0.0,0.0 +0,0.696300,0.0,0.0,0.0,0.0,0.0 +0,0.696400,0.0,0.0,0.0,0.0,0.0 +0,0.696500,0.0,0.0,0.0,0.0,0.0 +0,0.696600,0.0,0.0,0.0,0.0,0.0 +0,0.696700,0.0,0.0,0.0,0.0,0.0 +0,0.696800,0.0,0.0,0.0,0.0,0.0 +0,0.696900,0.0,0.0,0.0,0.0,0.0 +0,0.697000,0.0,0.0,0.0,0.0,0.0 +0,0.697100,0.0,0.0,0.0,0.0,0.0 +0,0.697200,0.0,0.0,0.0,0.0,0.0 +0,0.697300,0.0,0.0,0.0,0.0,0.0 +0,0.697400,0.0,0.0,0.0,0.0,0.0 +0,0.697500,0.0,0.0,0.0,0.0,0.0 +0,0.697600,0.0,0.0,0.0,0.0,0.0 +0,0.697700,0.0,0.0,0.0,0.0,0.0 +0,0.697800,0.0,0.0,0.0,0.0,0.0 +0,0.697900,0.0,0.0,0.0,0.0,0.0 +0,0.698000,0.0,0.0,0.0,0.0,0.0 +0,0.698100,0.0,0.0,0.0,0.0,0.0 +0,0.698200,0.0,0.0,0.0,0.0,0.0 +0,0.698300,0.0,0.0,0.0,0.0,0.0 +0,0.698400,0.0,0.0,0.0,0.0,0.0 +0,0.698500,0.0,0.0,0.0,0.0,0.0 +0,0.698600,0.0,0.0,0.0,0.0,0.0 +0,0.698700,0.0,0.0,0.0,0.0,0.0 +0,0.698800,0.0,0.0,0.0,0.0,0.0 +0,0.698900,0.0,0.0,0.0,0.0,0.0 +0,0.699000,0.0,0.0,0.0,0.0,0.0 +0,0.699100,0.0,0.0,0.0,0.0,0.0 +0,0.699200,0.0,0.0,0.0,0.0,0.0 +0,0.699300,0.0,0.0,0.0,0.0,0.0 +0,0.699400,0.0,0.0,0.0,0.0,0.0 +0,0.699500,0.0,0.0,0.0,0.0,0.0 +0,0.699600,0.0,0.0,0.0,0.0,0.0 +0,0.699700,0.0,0.0,0.0,0.0,0.0 +0,0.699800,0.0,0.0,0.0,0.0,0.0 +0,0.699900,0.0,0.0,0.0,0.0,0.0 +0,0.700000,0.0,0.0,0.0,0.0,0.0 +0,0.700100,0.0,0.0,0.0,0.0,0.0 +1,143.008561,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.700200,0.0,0.0,0.0,0.0,0.0 +0,0.700300,0.0,0.0,0.0,0.0,0.0 +0,0.700400,0.0,0.0,0.0,0.0,0.0 +0,0.700500,0.0,0.0,0.0,0.0,0.0 +0,0.700600,0.0,0.0,0.0,0.0,0.0 +0,0.700700,0.0,0.0,0.0,0.0,0.0 +0,0.700800,0.0,0.0,0.0,0.0,0.0 +0,0.700900,0.0,0.0,0.0,0.0,0.0 +0,0.701000,0.0,0.0,0.0,0.0,0.0 +0,0.701100,0.0,0.0,0.0,0.0,0.0 +0,0.701200,0.0,0.0,0.0,0.0,0.0 +0,0.701300,0.0,0.0,0.0,0.0,0.0 +0,0.701400,0.0,0.0,0.0,0.0,0.0 +0,0.701500,0.0,0.0,0.0,0.0,0.0 +0,0.701600,0.0,0.0,0.0,0.0,0.0 +0,0.701700,0.0,0.0,0.0,0.0,0.0 +0,0.701800,0.0,0.0,0.0,0.0,0.0 +0,0.701900,0.0,0.0,0.0,0.0,0.0 +0,0.702000,0.0,0.0,0.0,0.0,0.0 +0,0.702100,0.0,0.0,0.0,0.0,0.0 +0,0.702200,0.0,0.0,0.0,0.0,0.0 +0,0.702300,0.0,0.0,0.0,0.0,0.0 +0,0.702400,0.0,0.0,0.0,0.0,0.0 +0,0.702500,0.0,0.0,0.0,0.0,0.0 +0,0.702600,0.0,0.0,0.0,0.0,0.0 +0,0.702700,0.0,0.0,0.0,0.0,0.0 +0,0.702800,0.0,0.0,0.0,0.0,0.0 +0,0.702900,0.0,0.0,0.0,0.0,0.0 +0,0.703000,0.0,0.0,0.0,0.0,0.0 +0,0.703100,0.0,0.0,0.0,0.0,0.0 +0,0.703200,0.0,0.0,0.0,0.0,0.0 +0,0.703300,0.0,0.0,0.0,0.0,0.0 +0,0.703400,0.0,0.0,0.0,0.0,0.0 +0,0.703500,0.0,0.0,0.0,0.0,0.0 +0,0.703600,0.0,0.0,0.0,0.0,0.0 +0,0.703700,0.0,0.0,0.0,0.0,0.0 +0,0.703800,0.0,0.0,0.0,0.0,0.0 +0,0.703900,0.0,0.0,0.0,0.0,0.0 +0,0.704000,0.0,0.0,0.0,0.0,0.0 +0,0.704100,0.0,0.0,0.0,0.0,0.0 +0,0.704200,0.0,0.0,0.0,0.0,0.0 +0,0.704300,0.0,0.0,0.0,0.0,0.0 +0,0.704400,0.0,0.0,0.0,0.0,0.0 +0,0.704500,0.0,0.0,0.0,0.0,0.0 +0,0.704600,0.0,0.0,0.0,0.0,0.0 +0,0.704700,0.0,0.0,0.0,0.0,0.0 +0,0.704800,0.0,0.0,0.0,0.0,0.0 +0,0.704900,0.0,0.0,0.0,0.0,0.0 +0,0.705000,0.0,0.0,0.0,0.0,0.0 +0,0.705100,0.0,0.0,0.0,0.0,0.0 +0,0.705200,0.0,0.0,0.0,0.0,0.0 +0,0.705300,0.0,0.0,0.0,0.0,0.0 +0,0.705400,0.0,0.0,0.0,0.0,0.0 +0,0.705500,0.0,0.0,0.0,0.0,0.0 +0,0.705600,0.0,0.0,0.0,0.0,0.0 +0,0.705700,0.0,0.0,0.0,0.0,0.0 +0,0.705800,0.0,0.0,0.0,0.0,0.0 +0,0.705900,0.0,0.0,0.0,0.0,0.0 +0,0.706000,0.0,0.0,0.0,0.0,0.0 +0,0.706100,0.0,0.0,0.0,0.0,0.0 +0,0.706200,0.0,0.0,0.0,0.0,0.0 +0,0.706300,0.0,0.0,0.0,0.0,0.0 +0,0.706400,0.0,0.0,0.0,0.0,0.0 +0,0.706500,0.0,0.0,0.0,0.0,0.0 +0,0.706600,0.0,0.0,0.0,0.0,0.0 +0,0.706700,0.0,0.0,0.0,0.0,0.0 +0,0.706800,0.0,0.0,0.0,0.0,0.0 +0,0.706900,0.0,0.0,0.0,0.0,0.0 +0,0.707000,0.0,0.0,0.0,0.0,0.0 +0,0.707100,0.0,0.0,0.0,0.0,0.0 +0,0.707200,0.0,0.0,0.0,0.0,0.0 +0,0.707300,0.0,0.0,0.0,0.0,0.0 +0,0.707400,0.0,0.0,0.0,0.0,0.0 +0,0.707500,0.0,0.0,0.0,0.0,0.0 +0,0.707600,0.0,0.0,0.0,0.0,0.0 +0,0.707700,0.0,0.0,0.0,0.0,0.0 +0,0.707800,0.0,0.0,0.0,0.0,0.0 +0,0.707900,0.0,0.0,0.0,0.0,0.0 +0,0.708000,0.0,0.0,0.0,0.0,0.0 +0,0.708100,0.0,0.0,0.0,0.0,0.0 +0,0.708200,0.0,0.0,0.0,0.0,0.0 +0,0.708300,0.0,0.0,0.0,0.0,0.0 +0,0.708400,0.0,0.0,0.0,0.0,0.0 +0,0.708500,0.0,0.0,0.0,0.0,0.0 +0,0.708600,0.0,0.0,0.0,0.0,0.0 +0,0.708700,0.0,0.0,0.0,0.0,0.0 +0,0.708800,0.0,0.0,0.0,0.0,0.0 +0,0.708900,0.0,0.0,0.0,0.0,0.0 +0,0.709000,0.0,0.0,0.0,0.0,0.0 +0,0.709100,0.0,0.0,0.0,0.0,0.0 +0,0.709200,0.0,0.0,0.0,0.0,0.0 +0,0.709300,0.0,0.0,0.0,0.0,0.0 +0,0.709400,0.0,0.0,0.0,0.0,0.0 +0,0.709500,0.0,0.0,0.0,0.0,0.0 +0,0.709600,0.0,0.0,0.0,0.0,0.0 +0,0.709700,0.0,0.0,0.0,0.0,0.0 +0,0.709800,0.0,0.0,0.0,0.0,0.0 +0,0.709900,0.0,0.0,0.0,0.0,0.0 +0,0.710000,0.0,0.0,0.0,0.0,0.0 +0,0.710100,0.0,0.0,0.0,0.0,0.0 +0,0.710200,0.0,0.0,0.0,0.0,0.0 +0,0.710300,0.0,0.0,0.0,0.0,0.0 +0,0.710400,0.0,0.0,0.0,0.0,0.0 +0,0.710500,0.0,0.0,0.0,0.0,0.0 +0,0.710600,0.0,0.0,0.0,0.0,0.0 +0,0.710700,0.0,0.0,0.0,0.0,0.0 +0,0.710800,0.0,0.0,0.0,0.0,0.0 +0,0.710900,0.0,0.0,0.0,0.0,0.0 +0,0.711000,0.0,0.0,0.0,0.0,0.0 +0,0.711100,0.0,0.0,0.0,0.0,0.0 +0,0.711200,0.0,0.0,0.0,0.0,0.0 +0,0.711300,0.0,0.0,0.0,0.0,0.0 +0,0.711400,0.0,0.0,0.0,0.0,0.0 +0,0.711500,0.0,0.0,0.0,0.0,0.0 +0,0.711600,0.0,0.0,0.0,0.0,0.0 +0,0.711700,0.0,0.0,0.0,0.0,0.0 +0,0.711800,0.0,0.0,0.0,0.0,0.0 +0,0.711900,0.0,0.0,0.0,0.0,0.0 +0,0.712000,0.0,0.0,0.0,0.0,0.0 +0,0.712100,0.0,0.0,0.0,0.0,0.0 +0,0.712200,0.0,0.0,0.0,0.0,0.0 +0,0.712300,0.0,0.0,0.0,0.0,0.0 +0,0.712400,0.0,0.0,0.0,0.0,0.0 +0,0.712500,0.0,0.0,0.0,0.0,0.0 +0,0.712600,0.0,0.0,0.0,0.0,0.0 +0,0.712700,0.0,0.0,0.0,0.0,0.0 +0,0.712800,0.0,0.0,0.0,0.0,0.0 +0,0.712900,0.0,0.0,0.0,0.0,0.0 +0,0.713000,0.0,0.0,0.0,0.0,0.0 +0,0.713100,0.0,0.0,0.0,0.0,0.0 +0,0.713200,0.0,0.0,0.0,0.0,0.0 +0,0.713300,0.0,0.0,0.0,0.0,0.0 +0,0.713400,0.0,0.0,0.0,0.0,0.0 +0,0.713500,0.0,0.0,0.0,0.0,0.0 +0,0.713600,0.0,0.0,0.0,0.0,0.0 +0,0.713700,0.0,0.0,0.0,0.0,0.0 +0,0.713800,0.0,0.0,0.0,0.0,0.0 +0,0.713900,0.0,0.0,0.0,0.0,0.0 +0,0.714000,0.0,0.0,0.0,0.0,0.0 +0,0.714100,0.0,0.0,0.0,0.0,0.0 +0,0.714200,0.0,0.0,0.0,0.0,0.0 +0,0.714300,0.0,0.0,0.0,0.0,0.0 +0,0.714400,0.0,0.0,0.0,0.0,0.0 +0,0.714500,0.0,0.0,0.0,0.0,0.0 +0,0.714600,0.0,0.0,0.0,0.0,0.0 +0,0.714700,0.0,0.0,0.0,0.0,0.0 +0,0.714800,0.0,0.0,0.0,0.0,0.0 +0,0.714900,0.0,0.0,0.0,0.0,0.0 +0,0.715000,0.0,0.0,0.0,0.0,0.0 +0,0.715100,0.0,0.0,0.0,0.0,0.0 +0,0.715200,0.0,0.0,0.0,0.0,0.0 +0,0.715300,0.0,0.0,0.0,0.0,0.0 +0,0.715400,0.0,0.0,0.0,0.0,0.0 +0,0.715500,0.0,0.0,0.0,0.0,0.0 +0,0.715600,0.0,0.0,0.0,0.0,0.0 +0,0.715700,0.0,0.0,0.0,0.0,0.0 +0,0.715800,0.0,0.0,0.0,0.0,0.0 +0,0.715900,0.0,0.0,0.0,0.0,0.0 +0,0.716000,0.0,0.0,0.0,0.0,0.0 +0,0.716100,0.0,0.0,0.0,0.0,0.0 +0,0.716200,0.0,0.0,0.0,0.0,0.0 +0,0.716300,0.0,0.0,0.0,0.0,0.0 +0,0.716400,0.0,0.0,0.0,0.0,0.0 +0,0.716500,0.0,0.0,0.0,0.0,0.0 +0,0.716600,0.0,0.0,0.0,0.0,0.0 +0,0.716700,0.0,0.0,0.0,0.0,0.0 +0,0.716800,0.0,0.0,0.0,0.0,0.0 +0,0.716900,0.0,0.0,0.0,0.0,0.0 +0,0.717000,0.0,0.0,0.0,0.0,0.0 +0,0.717100,0.0,0.0,0.0,0.0,0.0 +0,0.717200,0.0,0.0,0.0,0.0,0.0 +0,0.717300,0.0,0.0,0.0,0.0,0.0 +0,0.717400,0.0,0.0,0.0,0.0,0.0 +0,0.717500,0.0,0.0,0.0,0.0,0.0 +0,0.717600,0.0,0.0,0.0,0.0,0.0 +0,0.717700,0.0,0.0,0.0,0.0,0.0 +0,0.717800,0.0,0.0,0.0,0.0,0.0 +0,0.717900,0.0,0.0,0.0,0.0,0.0 +0,0.718000,0.0,0.0,0.0,0.0,0.0 +0,0.718100,0.0,0.0,0.0,0.0,0.0 +0,0.718200,0.0,0.0,0.0,0.0,0.0 +0,0.718300,0.0,0.0,0.0,0.0,0.0 +0,0.718400,0.0,0.0,0.0,0.0,0.0 +0,0.718500,0.0,0.0,0.0,0.0,0.0 +0,0.718600,0.0,0.0,0.0,0.0,0.0 +0,0.718700,0.0,0.0,0.0,0.0,0.0 +0,0.718800,0.0,0.0,0.0,0.0,0.0 +0,0.718900,0.0,0.0,0.0,0.0,0.0 +0,0.719000,0.0,0.0,0.0,0.0,0.0 +0,0.719100,0.0,0.0,0.0,0.0,0.0 +0,0.719200,0.0,0.0,0.0,0.0,0.0 +0,0.719300,0.0,0.0,0.0,0.0,0.0 +0,0.719400,0.0,0.0,0.0,0.0,0.0 +0,0.719500,0.0,0.0,0.0,0.0,0.0 +0,0.719600,0.0,0.0,0.0,0.0,0.0 +0,0.719700,0.0,0.0,0.0,0.0,0.0 +0,0.719800,0.0,0.0,0.0,0.0,0.0 +0,0.719900,0.0,0.0,0.0,0.0,0.0 +0,0.720000,0.0,0.0,0.0,0.0,0.0 +0,0.720100,0.0,0.0,0.0,0.0,0.0 +1,155.617220,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.720200,0.0,0.0,0.0,0.0,0.0 +0,0.720300,0.0,0.0,0.0,0.0,0.0 +0,0.720400,0.0,0.0,0.0,0.0,0.0 +0,0.720500,0.0,0.0,0.0,0.0,0.0 +0,0.720600,0.0,0.0,0.0,0.0,0.0 +0,0.720700,0.0,0.0,0.0,0.0,0.0 +0,0.720800,0.0,0.0,0.0,0.0,0.0 +0,0.720900,0.0,0.0,0.0,0.0,0.0 +0,0.721000,0.0,0.0,0.0,0.0,0.0 +0,0.721100,0.0,0.0,0.0,0.0,0.0 +0,0.721200,0.0,0.0,0.0,0.0,0.0 +0,0.721300,0.0,0.0,0.0,0.0,0.0 +0,0.721400,0.0,0.0,0.0,0.0,0.0 +0,0.721500,0.0,0.0,0.0,0.0,0.0 +0,0.721600,0.0,0.0,0.0,0.0,0.0 +0,0.721700,0.0,0.0,0.0,0.0,0.0 +0,0.721800,0.0,0.0,0.0,0.0,0.0 +0,0.721900,0.0,0.0,0.0,0.0,0.0 +0,0.722000,0.0,0.0,0.0,0.0,0.0 +0,0.722100,0.0,0.0,0.0,0.0,0.0 +0,0.722200,0.0,0.0,0.0,0.0,0.0 +0,0.722300,0.0,0.0,0.0,0.0,0.0 +0,0.722400,0.0,0.0,0.0,0.0,0.0 +0,0.722500,0.0,0.0,0.0,0.0,0.0 +0,0.722600,0.0,0.0,0.0,0.0,0.0 +0,0.722700,0.0,0.0,0.0,0.0,0.0 +0,0.722800,0.0,0.0,0.0,0.0,0.0 +0,0.722900,0.0,0.0,0.0,0.0,0.0 +0,0.723000,0.0,0.0,0.0,0.0,0.0 +0,0.723100,0.0,0.0,0.0,0.0,0.0 +0,0.723200,0.0,0.0,0.0,0.0,0.0 +0,0.723300,0.0,0.0,0.0,0.0,0.0 +0,0.723400,0.0,0.0,0.0,0.0,0.0 +0,0.723500,0.0,0.0,0.0,0.0,0.0 +0,0.723600,0.0,0.0,0.0,0.0,0.0 +0,0.723700,0.0,0.0,0.0,0.0,0.0 +0,0.723800,0.0,0.0,0.0,0.0,0.0 +0,0.723900,0.0,0.0,0.0,0.0,0.0 +0,0.724000,0.0,0.0,0.0,0.0,0.0 +0,0.724100,0.0,0.0,0.0,0.0,0.0 +0,0.724200,0.0,0.0,0.0,0.0,0.0 +0,0.724300,0.0,0.0,0.0,0.0,0.0 +0,0.724400,0.0,0.0,0.0,0.0,0.0 +0,0.724500,0.0,0.0,0.0,0.0,0.0 +0,0.724600,0.0,0.0,0.0,0.0,0.0 +0,0.724700,0.0,0.0,0.0,0.0,0.0 +0,0.724800,0.0,0.0,0.0,0.0,0.0 +0,0.724900,0.0,0.0,0.0,0.0,0.0 +0,0.725000,0.0,0.0,0.0,0.0,0.0 +0,0.725100,0.0,0.0,0.0,0.0,0.0 +0,0.725200,0.0,0.0,0.0,0.0,0.0 +0,0.725300,0.0,0.0,0.0,0.0,0.0 +0,0.725400,0.0,0.0,0.0,0.0,0.0 +0,0.725500,0.0,0.0,0.0,0.0,0.0 +0,0.725600,0.0,0.0,0.0,0.0,0.0 +0,0.725700,0.0,0.0,0.0,0.0,0.0 +0,0.725800,0.0,0.0,0.0,0.0,0.0 +0,0.725900,0.0,0.0,0.0,0.0,0.0 +0,0.726000,0.0,0.0,0.0,0.0,0.0 +0,0.726100,0.0,0.0,0.0,0.0,0.0 +0,0.726200,0.0,0.0,0.0,0.0,0.0 +0,0.726300,0.0,0.0,0.0,0.0,0.0 +0,0.726400,0.0,0.0,0.0,0.0,0.0 +0,0.726500,0.0,0.0,0.0,0.0,0.0 +0,0.726600,0.0,0.0,0.0,0.0,0.0 +0,0.726700,0.0,0.0,0.0,0.0,0.0 +0,0.726800,0.0,0.0,0.0,0.0,0.0 +0,0.726900,0.0,0.0,0.0,0.0,0.0 +0,0.727000,0.0,0.0,0.0,0.0,0.0 +0,0.727100,0.0,0.0,0.0,0.0,0.0 +0,0.727200,0.0,0.0,0.0,0.0,0.0 +0,0.727300,0.0,0.0,0.0,0.0,0.0 +0,0.727400,0.0,0.0,0.0,0.0,0.0 +0,0.727500,0.0,0.0,0.0,0.0,0.0 +0,0.727600,0.0,0.0,0.0,0.0,0.0 +0,0.727700,0.0,0.0,0.0,0.0,0.0 +0,0.727800,0.0,0.0,0.0,0.0,0.0 +0,0.727900,0.0,0.0,0.0,0.0,0.0 +0,0.728000,0.0,0.0,0.0,0.0,0.0 +0,0.728100,0.0,0.0,0.0,0.0,0.0 +0,0.728200,0.0,0.0,0.0,0.0,0.0 +0,0.728300,0.0,0.0,0.0,0.0,0.0 +0,0.728400,0.0,0.0,0.0,0.0,0.0 +0,0.728500,0.0,0.0,0.0,0.0,0.0 +0,0.728600,0.0,0.0,0.0,0.0,0.0 +0,0.728700,0.0,0.0,0.0,0.0,0.0 +0,0.728800,0.0,0.0,0.0,0.0,0.0 +0,0.728900,0.0,0.0,0.0,0.0,0.0 +0,0.729000,0.0,0.0,0.0,0.0,0.0 +0,0.729100,0.0,0.0,0.0,0.0,0.0 +0,0.729200,0.0,0.0,0.0,0.0,0.0 +0,0.729300,0.0,0.0,0.0,0.0,0.0 +0,0.729400,0.0,0.0,0.0,0.0,0.0 +0,0.729500,0.0,0.0,0.0,0.0,0.0 +0,0.729600,0.0,0.0,0.0,0.0,0.0 +0,0.729700,0.0,0.0,0.0,0.0,0.0 +0,0.729800,0.0,0.0,0.0,0.0,0.0 +0,0.729900,0.0,0.0,0.0,0.0,0.0 +0,0.730000,0.0,0.0,0.0,0.0,0.0 +0,0.730100,0.0,0.0,0.0,0.0,0.0 +0,0.730200,0.0,0.0,0.0,0.0,0.0 +0,0.730300,0.0,0.0,0.0,0.0,0.0 +0,0.730400,0.0,0.0,0.0,0.0,0.0 +0,0.730500,0.0,0.0,0.0,0.0,0.0 +0,0.730600,0.0,0.0,0.0,0.0,0.0 +0,0.730700,0.0,0.0,0.0,0.0,0.0 +0,0.730800,0.0,0.0,0.0,0.0,0.0 +0,0.730900,0.0,0.0,0.0,0.0,0.0 +0,0.731000,0.0,0.0,0.0,0.0,0.0 +0,0.731100,0.0,0.0,0.0,0.0,0.0 +0,0.731200,0.0,0.0,0.0,0.0,0.0 +0,0.731300,0.0,0.0,0.0,0.0,0.0 +0,0.731400,0.0,0.0,0.0,0.0,0.0 +0,0.731500,0.0,0.0,0.0,0.0,0.0 +0,0.731600,0.0,0.0,0.0,0.0,0.0 +0,0.731700,0.0,0.0,0.0,0.0,0.0 +0,0.731800,0.0,0.0,0.0,0.0,0.0 +0,0.731900,0.0,0.0,0.0,0.0,0.0 +0,0.732000,0.0,0.0,0.0,0.0,0.0 +0,0.732100,0.0,0.0,0.0,0.0,0.0 +0,0.732200,0.0,0.0,0.0,0.0,0.0 +0,0.732300,0.0,0.0,0.0,0.0,0.0 +0,0.732400,0.0,0.0,0.0,0.0,0.0 +0,0.732500,0.0,0.0,0.0,0.0,0.0 +0,0.732600,0.0,0.0,0.0,0.0,0.0 +0,0.732700,0.0,0.0,0.0,0.0,0.0 +0,0.732800,0.0,0.0,0.0,0.0,0.0 +0,0.732900,0.0,0.0,0.0,0.0,0.0 +0,0.733000,0.0,0.0,0.0,0.0,0.0 +0,0.733100,0.0,0.0,0.0,0.0,0.0 +0,0.733200,0.0,0.0,0.0,0.0,0.0 +0,0.733300,0.0,0.0,0.0,0.0,0.0 +0,0.733400,0.0,0.0,0.0,0.0,0.0 +0,0.733500,0.0,0.0,0.0,0.0,0.0 +0,0.733600,0.0,0.0,0.0,0.0,0.0 +0,0.733700,0.0,0.0,0.0,0.0,0.0 +0,0.733800,0.0,0.0,0.0,0.0,0.0 +0,0.733900,0.0,0.0,0.0,0.0,0.0 +0,0.734000,0.0,0.0,0.0,0.0,0.0 +0,0.734100,0.0,0.0,0.0,0.0,0.0 +0,0.734200,0.0,0.0,0.0,0.0,0.0 +0,0.734300,0.0,0.0,0.0,0.0,0.0 +0,0.734400,0.0,0.0,0.0,0.0,0.0 +0,0.734500,0.0,0.0,0.0,0.0,0.0 +0,0.734600,0.0,0.0,0.0,0.0,0.0 +0,0.734700,0.0,0.0,0.0,0.0,0.0 +0,0.734800,0.0,0.0,0.0,0.0,0.0 +0,0.734900,0.0,0.0,0.0,0.0,0.0 +0,0.735000,0.0,0.0,0.0,0.0,0.0 +0,0.735100,0.0,0.0,0.0,0.0,0.0 +0,0.735200,0.0,0.0,0.0,0.0,0.0 +0,0.735300,0.0,0.0,0.0,0.0,0.0 +0,0.735400,0.0,0.0,0.0,0.0,0.0 +0,0.735500,0.0,0.0,0.0,0.0,0.0 +0,0.735600,0.0,0.0,0.0,0.0,0.0 +0,0.735700,0.0,0.0,0.0,0.0,0.0 +0,0.735800,0.0,0.0,0.0,0.0,0.0 +0,0.735900,0.0,0.0,0.0,0.0,0.0 +0,0.736000,0.0,0.0,0.0,0.0,0.0 +0,0.736100,0.0,0.0,0.0,0.0,0.0 +0,0.736200,0.0,0.0,0.0,0.0,0.0 +0,0.736300,0.0,0.0,0.0,0.0,0.0 +0,0.736400,0.0,0.0,0.0,0.0,0.0 +0,0.736500,0.0,0.0,0.0,0.0,0.0 +0,0.736600,0.0,0.0,0.0,0.0,0.0 +0,0.736700,0.0,0.0,0.0,0.0,0.0 +0,0.736800,0.0,0.0,0.0,0.0,0.0 +0,0.736900,0.0,0.0,0.0,0.0,0.0 +0,0.737000,0.0,0.0,0.0,0.0,0.0 +0,0.737100,0.0,0.0,0.0,0.0,0.0 +0,0.737200,0.0,0.0,0.0,0.0,0.0 +0,0.737300,0.0,0.0,0.0,0.0,0.0 +0,0.737400,0.0,0.0,0.0,0.0,0.0 +0,0.737500,0.0,0.0,0.0,0.0,0.0 +0,0.737600,0.0,0.0,0.0,0.0,0.0 +0,0.737700,0.0,0.0,0.0,0.0,0.0 +0,0.737800,0.0,0.0,0.0,0.0,0.0 +0,0.737900,0.0,0.0,0.0,0.0,0.0 +0,0.738000,0.0,0.0,0.0,0.0,0.0 +0,0.738100,0.0,0.0,0.0,0.0,0.0 +0,0.738200,0.0,0.0,0.0,0.0,0.0 +0,0.738300,0.0,0.0,0.0,0.0,0.0 +0,0.738400,0.0,0.0,0.0,0.0,0.0 +0,0.738500,0.0,0.0,0.0,0.0,0.0 +0,0.738600,0.0,0.0,0.0,0.0,0.0 +0,0.738700,0.0,0.0,0.0,0.0,0.0 +0,0.738800,0.0,0.0,0.0,0.0,0.0 +0,0.738900,0.0,0.0,0.0,0.0,0.0 +0,0.739000,0.0,0.0,0.0,0.0,0.0 +0,0.739100,0.0,0.0,0.0,0.0,0.0 +0,0.739200,0.0,0.0,0.0,0.0,0.0 +0,0.739300,0.0,0.0,0.0,0.0,0.0 +0,0.739400,0.0,0.0,0.0,0.0,0.0 +0,0.739500,0.0,0.0,0.0,0.0,0.0 +0,0.739600,0.0,0.0,0.0,0.0,0.0 +0,0.739700,0.0,0.0,0.0,0.0,0.0 +0,0.739800,0.0,0.0,0.0,0.0,0.0 +0,0.739900,0.0,0.0,0.0,0.0,0.0 +0,0.740000,0.0,0.0,0.0,0.0,0.0 +0,0.740100,0.0,0.0,0.0,0.0,0.0 +1,168.946028,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.740200,0.0,0.0,0.0,0.0,0.0 +0,0.740300,0.0,0.0,0.0,0.0,0.0 +0,0.740400,0.0,0.0,0.0,0.0,0.0 +0,0.740500,0.0,0.0,0.0,0.0,0.0 +0,0.740600,0.0,0.0,0.0,0.0,0.0 +0,0.740700,0.0,0.0,0.0,0.0,0.0 +0,0.740800,0.0,0.0,0.0,0.0,0.0 +0,0.740900,0.0,0.0,0.0,0.0,0.0 +0,0.741000,0.0,0.0,0.0,0.0,0.0 +0,0.741100,0.0,0.0,0.0,0.0,0.0 +0,0.741200,0.0,0.0,0.0,0.0,0.0 +0,0.741300,0.0,0.0,0.0,0.0,0.0 +0,0.741400,0.0,0.0,0.0,0.0,0.0 +0,0.741500,0.0,0.0,0.0,0.0,0.0 +0,0.741600,0.0,0.0,0.0,0.0,0.0 +0,0.741700,0.0,0.0,0.0,0.0,0.0 +0,0.741800,0.0,0.0,0.0,0.0,0.0 +0,0.741900,0.0,0.0,0.0,0.0,0.0 +0,0.742000,0.0,0.0,0.0,0.0,0.0 +0,0.742100,0.0,0.0,0.0,0.0,0.0 +0,0.742200,0.0,0.0,0.0,0.0,0.0 +0,0.742300,0.0,0.0,0.0,0.0,0.0 +0,0.742400,0.0,0.0,0.0,0.0,0.0 +0,0.742500,0.0,0.0,0.0,0.0,0.0 +0,0.742600,0.0,0.0,0.0,0.0,0.0 +0,0.742700,0.0,0.0,0.0,0.0,0.0 +0,0.742800,0.0,0.0,0.0,0.0,0.0 +0,0.742900,0.0,0.0,0.0,0.0,0.0 +0,0.743000,0.0,0.0,0.0,0.0,0.0 +0,0.743100,0.0,0.0,0.0,0.0,0.0 +0,0.743200,0.0,0.0,0.0,0.0,0.0 +0,0.743300,0.0,0.0,0.0,0.0,0.0 +0,0.743400,0.0,0.0,0.0,0.0,0.0 +0,0.743500,0.0,0.0,0.0,0.0,0.0 +0,0.743600,0.0,0.0,0.0,0.0,0.0 +0,0.743700,0.0,0.0,0.0,0.0,0.0 +0,0.743800,0.0,0.0,0.0,0.0,0.0 +0,0.743900,0.0,0.0,0.0,0.0,0.0 +0,0.744000,0.0,0.0,0.0,0.0,0.0 +0,0.744100,0.0,0.0,0.0,0.0,0.0 +0,0.744200,0.0,0.0,0.0,0.0,0.0 +0,0.744300,0.0,0.0,0.0,0.0,0.0 +0,0.744400,0.0,0.0,0.0,0.0,0.0 +0,0.744500,0.0,0.0,0.0,0.0,0.0 +0,0.744600,0.0,0.0,0.0,0.0,0.0 +0,0.744700,0.0,0.0,0.0,0.0,0.0 +0,0.744800,0.0,0.0,0.0,0.0,0.0 +0,0.744900,0.0,0.0,0.0,0.0,0.0 +0,0.745000,0.0,0.0,0.0,0.0,0.0 +0,0.745100,0.0,0.0,0.0,0.0,0.0 +0,0.745200,0.0,0.0,0.0,0.0,0.0 +0,0.745300,0.0,0.0,0.0,0.0,0.0 +0,0.745400,0.0,0.0,0.0,0.0,0.0 +0,0.745500,0.0,0.0,0.0,0.0,0.0 +0,0.745600,0.0,0.0,0.0,0.0,0.0 +0,0.745700,0.0,0.0,0.0,0.0,0.0 +0,0.745800,0.0,0.0,0.0,0.0,0.0 +0,0.745900,0.0,0.0,0.0,0.0,0.0 +0,0.746000,0.0,0.0,0.0,0.0,0.0 +0,0.746100,0.0,0.0,0.0,0.0,0.0 +0,0.746200,0.0,0.0,0.0,0.0,0.0 +0,0.746300,0.0,0.0,0.0,0.0,0.0 +0,0.746400,0.0,0.0,0.0,0.0,0.0 +0,0.746500,0.0,0.0,0.0,0.0,0.0 +0,0.746600,0.0,0.0,0.0,0.0,0.0 +0,0.746700,0.0,0.0,0.0,0.0,0.0 +0,0.746800,0.0,0.0,0.0,0.0,0.0 +0,0.746900,0.0,0.0,0.0,0.0,0.0 +0,0.747000,0.0,0.0,0.0,0.0,0.0 +0,0.747100,0.0,0.0,0.0,0.0,0.0 +0,0.747200,0.0,0.0,0.0,0.0,0.0 +0,0.747300,0.0,0.0,0.0,0.0,0.0 +0,0.747400,0.0,0.0,0.0,0.0,0.0 +0,0.747500,0.0,0.0,0.0,0.0,0.0 +0,0.747600,0.0,0.0,0.0,0.0,0.0 +0,0.747700,0.0,0.0,0.0,0.0,0.0 +0,0.747800,0.0,0.0,0.0,0.0,0.0 +0,0.747900,0.0,0.0,0.0,0.0,0.0 +0,0.748000,0.0,0.0,0.0,0.0,0.0 +0,0.748100,0.0,0.0,0.0,0.0,0.0 +0,0.748200,0.0,0.0,0.0,0.0,0.0 +0,0.748300,0.0,0.0,0.0,0.0,0.0 +0,0.748400,0.0,0.0,0.0,0.0,0.0 +0,0.748500,0.0,0.0,0.0,0.0,0.0 +0,0.748600,0.0,0.0,0.0,0.0,0.0 +0,0.748700,0.0,0.0,0.0,0.0,0.0 +0,0.748800,0.0,0.0,0.0,0.0,0.0 +0,0.748900,0.0,0.0,0.0,0.0,0.0 +0,0.749000,0.0,0.0,0.0,0.0,0.0 +0,0.749100,0.0,0.0,0.0,0.0,0.0 +0,0.749200,0.0,0.0,0.0,0.0,0.0 +0,0.749300,0.0,0.0,0.0,0.0,0.0 +0,0.749400,0.0,0.0,0.0,0.0,0.0 +0,0.749500,0.0,0.0,0.0,0.0,0.0 +0,0.749600,0.0,0.0,0.0,0.0,0.0 +0,0.749700,0.0,0.0,0.0,0.0,0.0 +0,0.749800,0.0,0.0,0.0,0.0,0.0 +0,0.749900,0.0,0.0,0.0,0.0,0.0 +0,0.750000,0.0,0.0,0.0,0.0,0.0 +0,0.750100,0.0,0.0,0.0,0.0,0.0 +0,0.750200,0.0,0.0,0.0,0.0,0.0 +0,0.750300,0.0,0.0,0.0,0.0,0.0 +0,0.750400,0.0,0.0,0.0,0.0,0.0 +0,0.750500,0.0,0.0,0.0,0.0,0.0 +0,0.750600,0.0,0.0,0.0,0.0,0.0 +0,0.750700,0.0,0.0,0.0,0.0,0.0 +0,0.750800,0.0,0.0,0.0,0.0,0.0 +0,0.750900,0.0,0.0,0.0,0.0,0.0 +0,0.751000,0.0,0.0,0.0,0.0,0.0 +0,0.751100,0.0,0.0,0.0,0.0,0.0 +0,0.751200,0.0,0.0,0.0,0.0,0.0 +0,0.751300,0.0,0.0,0.0,0.0,0.0 +0,0.751400,0.0,0.0,0.0,0.0,0.0 +0,0.751500,0.0,0.0,0.0,0.0,0.0 +0,0.751600,0.0,0.0,0.0,0.0,0.0 +0,0.751700,0.0,0.0,0.0,0.0,0.0 +0,0.751800,0.0,0.0,0.0,0.0,0.0 +0,0.751900,0.0,0.0,0.0,0.0,0.0 +0,0.752000,0.0,0.0,0.0,0.0,0.0 +0,0.752100,0.0,0.0,0.0,0.0,0.0 +0,0.752200,0.0,0.0,0.0,0.0,0.0 +0,0.752300,0.0,0.0,0.0,0.0,0.0 +0,0.752400,0.0,0.0,0.0,0.0,0.0 +0,0.752500,0.0,0.0,0.0,0.0,0.0 +0,0.752600,0.0,0.0,0.0,0.0,0.0 +0,0.752700,0.0,0.0,0.0,0.0,0.0 +0,0.752800,0.0,0.0,0.0,0.0,0.0 +0,0.752900,0.0,0.0,0.0,0.0,0.0 +0,0.753000,0.0,0.0,0.0,0.0,0.0 +0,0.753100,0.0,0.0,0.0,0.0,0.0 +0,0.753200,0.0,0.0,0.0,0.0,0.0 +0,0.753300,0.0,0.0,0.0,0.0,0.0 +0,0.753400,0.0,0.0,0.0,0.0,0.0 +0,0.753500,0.0,0.0,0.0,0.0,0.0 +0,0.753600,0.0,0.0,0.0,0.0,0.0 +0,0.753700,0.0,0.0,0.0,0.0,0.0 +0,0.753800,0.0,0.0,0.0,0.0,0.0 +0,0.753900,0.0,0.0,0.0,0.0,0.0 +0,0.754000,0.0,0.0,0.0,0.0,0.0 +0,0.754100,0.0,0.0,0.0,0.0,0.0 +0,0.754200,0.0,0.0,0.0,0.0,0.0 +0,0.754300,0.0,0.0,0.0,0.0,0.0 +0,0.754400,0.0,0.0,0.0,0.0,0.0 +0,0.754500,0.0,0.0,0.0,0.0,0.0 +0,0.754600,0.0,0.0,0.0,0.0,0.0 +0,0.754700,0.0,0.0,0.0,0.0,0.0 +0,0.754800,0.0,0.0,0.0,0.0,0.0 +0,0.754900,0.0,0.0,0.0,0.0,0.0 +0,0.755000,0.0,0.0,0.0,0.0,0.0 +0,0.755100,0.0,0.0,0.0,0.0,0.0 +0,0.755200,0.0,0.0,0.0,0.0,0.0 +0,0.755300,0.0,0.0,0.0,0.0,0.0 +0,0.755400,0.0,0.0,0.0,0.0,0.0 +0,0.755500,0.0,0.0,0.0,0.0,0.0 +0,0.755600,0.0,0.0,0.0,0.0,0.0 +0,0.755700,0.0,0.0,0.0,0.0,0.0 +0,0.755800,0.0,0.0,0.0,0.0,0.0 +0,0.755900,0.0,0.0,0.0,0.0,0.0 +0,0.756000,0.0,0.0,0.0,0.0,0.0 +0,0.756100,0.0,0.0,0.0,0.0,0.0 +0,0.756200,0.0,0.0,0.0,0.0,0.0 +0,0.756300,0.0,0.0,0.0,0.0,0.0 +0,0.756400,0.0,0.0,0.0,0.0,0.0 +0,0.756500,0.0,0.0,0.0,0.0,0.0 +0,0.756600,0.0,0.0,0.0,0.0,0.0 +0,0.756700,0.0,0.0,0.0,0.0,0.0 +0,0.756800,0.0,0.0,0.0,0.0,0.0 +0,0.756900,0.0,0.0,0.0,0.0,0.0 +0,0.757000,0.0,0.0,0.0,0.0,0.0 +0,0.757100,0.0,0.0,0.0,0.0,0.0 +0,0.757200,0.0,0.0,0.0,0.0,0.0 +0,0.757300,0.0,0.0,0.0,0.0,0.0 +0,0.757400,0.0,0.0,0.0,0.0,0.0 +0,0.757500,0.0,0.0,0.0,0.0,0.0 +0,0.757600,0.0,0.0,0.0,0.0,0.0 +0,0.757700,0.0,0.0,0.0,0.0,0.0 +0,0.757800,0.0,0.0,0.0,0.0,0.0 +0,0.757900,0.0,0.0,0.0,0.0,0.0 +0,0.758000,0.0,0.0,0.0,0.0,0.0 +0,0.758100,0.0,0.0,0.0,0.0,0.0 +0,0.758200,0.0,0.0,0.0,0.0,0.0 +0,0.758300,0.0,0.0,0.0,0.0,0.0 +0,0.758400,0.0,0.0,0.0,0.0,0.0 +0,0.758500,0.0,0.0,0.0,0.0,0.0 +0,0.758600,0.0,0.0,0.0,0.0,0.0 +0,0.758700,0.0,0.0,0.0,0.0,0.0 +0,0.758800,0.0,0.0,0.0,0.0,0.0 +0,0.758900,0.0,0.0,0.0,0.0,0.0 +0,0.759000,0.0,0.0,0.0,0.0,0.0 +0,0.759100,0.0,0.0,0.0,0.0,0.0 +0,0.759200,0.0,0.0,0.0,0.0,0.0 +0,0.759300,0.0,0.0,0.0,0.0,0.0 +0,0.759400,0.0,0.0,0.0,0.0,0.0 +0,0.759500,0.0,0.0,0.0,0.0,0.0 +0,0.759600,0.0,0.0,0.0,0.0,0.0 +0,0.759700,0.0,0.0,0.0,0.0,0.0 +0,0.759800,0.0,0.0,0.0,0.0,0.0 +0,0.759900,0.0,0.0,0.0,0.0,0.0 +0,0.760000,0.0,0.0,0.0,0.0,0.0 +0,0.760100,0.0,0.0,0.0,0.0,0.0 +1,183.014987,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.760200,0.0,0.0,0.0,0.0,0.0 +0,0.760300,0.0,0.0,0.0,0.0,0.0 +0,0.760400,0.0,0.0,0.0,0.0,0.0 +0,0.760500,0.0,0.0,0.0,0.0,0.0 +0,0.760600,0.0,0.0,0.0,0.0,0.0 +0,0.760700,0.0,0.0,0.0,0.0,0.0 +0,0.760800,0.0,0.0,0.0,0.0,0.0 +0,0.760900,0.0,0.0,0.0,0.0,0.0 +0,0.761000,0.0,0.0,0.0,0.0,0.0 +0,0.761100,0.0,0.0,0.0,0.0,0.0 +0,0.761200,0.0,0.0,0.0,0.0,0.0 +0,0.761300,0.0,0.0,0.0,0.0,0.0 +0,0.761400,0.0,0.0,0.0,0.0,0.0 +0,0.761500,0.0,0.0,0.0,0.0,0.0 +0,0.761600,0.0,0.0,0.0,0.0,0.0 +0,0.761700,0.0,0.0,0.0,0.0,0.0 +0,0.761800,0.0,0.0,0.0,0.0,0.0 +0,0.761900,0.0,0.0,0.0,0.0,0.0 +0,0.762000,0.0,0.0,0.0,0.0,0.0 +0,0.762100,0.0,0.0,0.0,0.0,0.0 +0,0.762200,0.0,0.0,0.0,0.0,0.0 +0,0.762300,0.0,0.0,0.0,0.0,0.0 +0,0.762400,0.0,0.0,0.0,0.0,0.0 +0,0.762500,0.0,0.0,0.0,0.0,0.0 +0,0.762600,0.0,0.0,0.0,0.0,0.0 +0,0.762700,0.0,0.0,0.0,0.0,0.0 +0,0.762800,0.0,0.0,0.0,0.0,0.0 +0,0.762900,0.0,0.0,0.0,0.0,0.0 +0,0.763000,0.0,0.0,0.0,0.0,0.0 +0,0.763100,0.0,0.0,0.0,0.0,0.0 +0,0.763200,0.0,0.0,0.0,0.0,0.0 +0,0.763300,0.0,0.0,0.0,0.0,0.0 +0,0.763400,0.0,0.0,0.0,0.0,0.0 +0,0.763500,0.0,0.0,0.0,0.0,0.0 +0,0.763600,0.0,0.0,0.0,0.0,0.0 +0,0.763700,0.0,0.0,0.0,0.0,0.0 +0,0.763800,0.0,0.0,0.0,0.0,0.0 +0,0.763900,0.0,0.0,0.0,0.0,0.0 +0,0.764000,0.0,0.0,0.0,0.0,0.0 +0,0.764100,0.0,0.0,0.0,0.0,0.0 +0,0.764200,0.0,0.0,0.0,0.0,0.0 +0,0.764300,0.0,0.0,0.0,0.0,0.0 +0,0.764400,0.0,0.0,0.0,0.0,0.0 +0,0.764500,0.0,0.0,0.0,0.0,0.0 +0,0.764600,0.0,0.0,0.0,0.0,0.0 +0,0.764700,0.0,0.0,0.0,0.0,0.0 +0,0.764800,0.0,0.0,0.0,0.0,0.0 +0,0.764900,0.0,0.0,0.0,0.0,0.0 +0,0.765000,0.0,0.0,0.0,0.0,0.0 +0,0.765100,0.0,0.0,0.0,0.0,0.0 +0,0.765200,0.0,0.0,0.0,0.0,0.0 +0,0.765300,0.0,0.0,0.0,0.0,0.0 +0,0.765400,0.0,0.0,0.0,0.0,0.0 +0,0.765500,0.0,0.0,0.0,0.0,0.0 +0,0.765600,0.0,0.0,0.0,0.0,0.0 +0,0.765700,0.0,0.0,0.0,0.0,0.0 +0,0.765800,0.0,0.0,0.0,0.0,0.0 +0,0.765900,0.0,0.0,0.0,0.0,0.0 +0,0.766000,0.0,0.0,0.0,0.0,0.0 +0,0.766100,0.0,0.0,0.0,0.0,0.0 +0,0.766200,0.0,0.0,0.0,0.0,0.0 +0,0.766300,0.0,0.0,0.0,0.0,0.0 +0,0.766400,0.0,0.0,0.0,0.0,0.0 +0,0.766500,0.0,0.0,0.0,0.0,0.0 +0,0.766600,0.0,0.0,0.0,0.0,0.0 +0,0.766700,0.0,0.0,0.0,0.0,0.0 +0,0.766800,0.0,0.0,0.0,0.0,0.0 +0,0.766900,0.0,0.0,0.0,0.0,0.0 +0,0.767000,0.0,0.0,0.0,0.0,0.0 +0,0.767100,0.0,0.0,0.0,0.0,0.0 +0,0.767200,0.0,0.0,0.0,0.0,0.0 +0,0.767300,0.0,0.0,0.0,0.0,0.0 +0,0.767400,0.0,0.0,0.0,0.0,0.0 +0,0.767500,0.0,0.0,0.0,0.0,0.0 +0,0.767600,0.0,0.0,0.0,0.0,0.0 +0,0.767700,0.0,0.0,0.0,0.0,0.0 +0,0.767800,0.0,0.0,0.0,0.0,0.0 +0,0.767900,0.0,0.0,0.0,0.0,0.0 +0,0.768000,0.0,0.0,0.0,0.0,0.0 +0,0.768100,0.0,0.0,0.0,0.0,0.0 +0,0.768200,0.0,0.0,0.0,0.0,0.0 +0,0.768300,0.0,0.0,0.0,0.0,0.0 +0,0.768400,0.0,0.0,0.0,0.0,0.0 +0,0.768500,0.0,0.0,0.0,0.0,0.0 +0,0.768600,0.0,0.0,0.0,0.0,0.0 +0,0.768700,0.0,0.0,0.0,0.0,0.0 +0,0.768800,0.0,0.0,0.0,0.0,0.0 +0,0.768900,0.0,0.0,0.0,0.0,0.0 +0,0.769000,0.0,0.0,0.0,0.0,0.0 +0,0.769100,0.0,0.0,0.0,0.0,0.0 +0,0.769200,0.0,0.0,0.0,0.0,0.0 +0,0.769300,0.0,0.0,0.0,0.0,0.0 +0,0.769400,0.0,0.0,0.0,0.0,0.0 +0,0.769500,0.0,0.0,0.0,0.0,0.0 +0,0.769600,0.0,0.0,0.0,0.0,0.0 +0,0.769700,0.0,0.0,0.0,0.0,0.0 +0,0.769800,0.0,0.0,0.0,0.0,0.0 +0,0.769900,0.0,0.0,0.0,0.0,0.0 +0,0.770000,0.0,0.0,0.0,0.0,0.0 +0,0.770100,0.0,0.0,0.0,0.0,0.0 +0,0.770200,0.0,0.0,0.0,0.0,0.0 +0,0.770300,0.0,0.0,0.0,0.0,0.0 +0,0.770400,0.0,0.0,0.0,0.0,0.0 +0,0.770500,0.0,0.0,0.0,0.0,0.0 +0,0.770600,0.0,0.0,0.0,0.0,0.0 +0,0.770700,0.0,0.0,0.0,0.0,0.0 +0,0.770800,0.0,0.0,0.0,0.0,0.0 +0,0.770900,0.0,0.0,0.0,0.0,0.0 +0,0.771000,0.0,0.0,0.0,0.0,0.0 +0,0.771100,0.0,0.0,0.0,0.0,0.0 +0,0.771200,0.0,0.0,0.0,0.0,0.0 +0,0.771300,0.0,0.0,0.0,0.0,0.0 +0,0.771400,0.0,0.0,0.0,0.0,0.0 +0,0.771500,0.0,0.0,0.0,0.0,0.0 +0,0.771600,0.0,0.0,0.0,0.0,0.0 +0,0.771700,0.0,0.0,0.0,0.0,0.0 +0,0.771800,0.0,0.0,0.0,0.0,0.0 +0,0.771900,0.0,0.0,0.0,0.0,0.0 +0,0.772000,0.0,0.0,0.0,0.0,0.0 +0,0.772100,0.0,0.0,0.0,0.0,0.0 +0,0.772200,0.0,0.0,0.0,0.0,0.0 +0,0.772300,0.0,0.0,0.0,0.0,0.0 +0,0.772400,0.0,0.0,0.0,0.0,0.0 +0,0.772500,0.0,0.0,0.0,0.0,0.0 +0,0.772600,0.0,0.0,0.0,0.0,0.0 +0,0.772700,0.0,0.0,0.0,0.0,0.0 +0,0.772800,0.0,0.0,0.0,0.0,0.0 +0,0.772900,0.0,0.0,0.0,0.0,0.0 +0,0.773000,0.0,0.0,0.0,0.0,0.0 +0,0.773100,0.0,0.0,0.0,0.0,0.0 +0,0.773200,0.0,0.0,0.0,0.0,0.0 +0,0.773300,0.0,0.0,0.0,0.0,0.0 +0,0.773400,0.0,0.0,0.0,0.0,0.0 +0,0.773500,0.0,0.0,0.0,0.0,0.0 +0,0.773600,0.0,0.0,0.0,0.0,0.0 +0,0.773700,0.0,0.0,0.0,0.0,0.0 +0,0.773800,0.0,0.0,0.0,0.0,0.0 +0,0.773900,0.0,0.0,0.0,0.0,0.0 +0,0.774000,0.0,0.0,0.0,0.0,0.0 +0,0.774100,0.0,0.0,0.0,0.0,0.0 +0,0.774200,0.0,0.0,0.0,0.0,0.0 +0,0.774300,0.0,0.0,0.0,0.0,0.0 +0,0.774400,0.0,0.0,0.0,0.0,0.0 +0,0.774500,0.0,0.0,0.0,0.0,0.0 +0,0.774600,0.0,0.0,0.0,0.0,0.0 +0,0.774700,0.0,0.0,0.0,0.0,0.0 +0,0.774800,0.0,0.0,0.0,0.0,0.0 +0,0.774900,0.0,0.0,0.0,0.0,0.0 +0,0.775000,0.0,0.0,0.0,0.0,0.0 +0,0.775100,0.0,0.0,0.0,0.0,0.0 +0,0.775200,0.0,0.0,0.0,0.0,0.0 +0,0.775300,0.0,0.0,0.0,0.0,0.0 +0,0.775400,0.0,0.0,0.0,0.0,0.0 +0,0.775500,0.0,0.0,0.0,0.0,0.0 +0,0.775600,0.0,0.0,0.0,0.0,0.0 +0,0.775700,0.0,0.0,0.0,0.0,0.0 +0,0.775800,0.0,0.0,0.0,0.0,0.0 +0,0.775900,0.0,0.0,0.0,0.0,0.0 +0,0.776000,0.0,0.0,0.0,0.0,0.0 +0,0.776100,0.0,0.0,0.0,0.0,0.0 +0,0.776200,0.0,0.0,0.0,0.0,0.0 +0,0.776300,0.0,0.0,0.0,0.0,0.0 +0,0.776400,0.0,0.0,0.0,0.0,0.0 +0,0.776500,0.0,0.0,0.0,0.0,0.0 +0,0.776600,0.0,0.0,0.0,0.0,0.0 +0,0.776700,0.0,0.0,0.0,0.0,0.0 +0,0.776800,0.0,0.0,0.0,0.0,0.0 +0,0.776900,0.0,0.0,0.0,0.0,0.0 +0,0.777000,0.0,0.0,0.0,0.0,0.0 +0,0.777100,0.0,0.0,0.0,0.0,0.0 +0,0.777200,0.0,0.0,0.0,0.0,0.0 +0,0.777300,0.0,0.0,0.0,0.0,0.0 +0,0.777400,0.0,0.0,0.0,0.0,0.0 +0,0.777500,0.0,0.0,0.0,0.0,0.0 +0,0.777600,0.0,0.0,0.0,0.0,0.0 +0,0.777700,0.0,0.0,0.0,0.0,0.0 +0,0.777800,0.0,0.0,0.0,0.0,0.0 +0,0.777900,0.0,0.0,0.0,0.0,0.0 +0,0.778000,0.0,0.0,0.0,0.0,0.0 +0,0.778100,0.0,0.0,0.0,0.0,0.0 +0,0.778200,0.0,0.0,0.0,0.0,0.0 +0,0.778300,0.0,0.0,0.0,0.0,0.0 +0,0.778400,0.0,0.0,0.0,0.0,0.0 +0,0.778500,0.0,0.0,0.0,0.0,0.0 +0,0.778600,0.0,0.0,0.0,0.0,0.0 +0,0.778700,0.0,0.0,0.0,0.0,0.0 +0,0.778800,0.0,0.0,0.0,0.0,0.0 +0,0.778900,0.0,0.0,0.0,0.0,0.0 +0,0.779000,0.0,0.0,0.0,0.0,0.0 +0,0.779100,0.0,0.0,0.0,0.0,0.0 +0,0.779200,0.0,0.0,0.0,0.0,0.0 +0,0.779300,0.0,0.0,0.0,0.0,0.0 +0,0.779400,0.0,0.0,0.0,0.0,0.0 +0,0.779500,0.0,0.0,0.0,0.0,0.0 +0,0.779600,0.0,0.0,0.0,0.0,0.0 +0,0.779700,0.0,0.0,0.0,0.0,0.0 +0,0.779800,0.0,0.0,0.0,0.0,0.0 +0,0.779900,0.0,0.0,0.0,0.0,0.0 +0,0.780000,0.0,0.0,0.0,0.0,0.0 +0,0.780100,0.0,0.0,0.0,0.0,0.0 +1,197.844096,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.780200,0.0,0.0,0.0,0.0,0.0 +0,0.780300,0.0,0.0,0.0,0.0,0.0 +0,0.780400,0.0,0.0,0.0,0.0,0.0 +0,0.780500,0.0,0.0,0.0,0.0,0.0 +0,0.780600,0.0,0.0,0.0,0.0,0.0 +0,0.780700,0.0,0.0,0.0,0.0,0.0 +0,0.780800,0.0,0.0,0.0,0.0,0.0 +0,0.780900,0.0,0.0,0.0,0.0,0.0 +0,0.781000,0.0,0.0,0.0,0.0,0.0 +0,0.781100,0.0,0.0,0.0,0.0,0.0 +0,0.781200,0.0,0.0,0.0,0.0,0.0 +0,0.781300,0.0,0.0,0.0,0.0,0.0 +0,0.781400,0.0,0.0,0.0,0.0,0.0 +0,0.781500,0.0,0.0,0.0,0.0,0.0 +0,0.781600,0.0,0.0,0.0,0.0,0.0 +0,0.781700,0.0,0.0,0.0,0.0,0.0 +0,0.781800,0.0,0.0,0.0,0.0,0.0 +0,0.781900,0.0,0.0,0.0,0.0,0.0 +0,0.782000,0.0,0.0,0.0,0.0,0.0 +0,0.782100,0.0,0.0,0.0,0.0,0.0 +0,0.782200,0.0,0.0,0.0,0.0,0.0 +0,0.782300,0.0,0.0,0.0,0.0,0.0 +0,0.782400,0.0,0.0,0.0,0.0,0.0 +0,0.782500,0.0,0.0,0.0,0.0,0.0 +0,0.782600,0.0,0.0,0.0,0.0,0.0 +0,0.782700,0.0,0.0,0.0,0.0,0.0 +0,0.782800,0.0,0.0,0.0,0.0,0.0 +0,0.782900,0.0,0.0,0.0,0.0,0.0 +0,0.783000,0.0,0.0,0.0,0.0,0.0 +0,0.783100,0.0,0.0,0.0,0.0,0.0 +0,0.783200,0.0,0.0,0.0,0.0,0.0 +0,0.783300,0.0,0.0,0.0,0.0,0.0 +0,0.783400,0.0,0.0,0.0,0.0,0.0 +0,0.783500,0.0,0.0,0.0,0.0,0.0 +0,0.783600,0.0,0.0,0.0,0.0,0.0 +0,0.783700,0.0,0.0,0.0,0.0,0.0 +0,0.783800,0.0,0.0,0.0,0.0,0.0 +0,0.783900,0.0,0.0,0.0,0.0,0.0 +0,0.784000,0.0,0.0,0.0,0.0,0.0 +0,0.784100,0.0,0.0,0.0,0.0,0.0 +0,0.784200,0.0,0.0,0.0,0.0,0.0 +0,0.784300,0.0,0.0,0.0,0.0,0.0 +0,0.784400,0.0,0.0,0.0,0.0,0.0 +0,0.784500,0.0,0.0,0.0,0.0,0.0 +0,0.784600,0.0,0.0,0.0,0.0,0.0 +0,0.784700,0.0,0.0,0.0,0.0,0.0 +0,0.784800,0.0,0.0,0.0,0.0,0.0 +0,0.784900,0.0,0.0,0.0,0.0,0.0 +0,0.785000,0.0,0.0,0.0,0.0,0.0 +0,0.785100,0.0,0.0,0.0,0.0,0.0 +0,0.785200,0.0,0.0,0.0,0.0,0.0 +0,0.785300,0.0,0.0,0.0,0.0,0.0 +0,0.785400,0.0,0.0,0.0,0.0,0.0 +0,0.785500,0.0,0.0,0.0,0.0,0.0 +0,0.785600,0.0,0.0,0.0,0.0,0.0 +0,0.785700,0.0,0.0,0.0,0.0,0.0 +0,0.785800,0.0,0.0,0.0,0.0,0.0 +0,0.785900,0.0,0.0,0.0,0.0,0.0 +0,0.786000,0.0,0.0,0.0,0.0,0.0 +0,0.786100,0.0,0.0,0.0,0.0,0.0 +0,0.786200,0.0,0.0,0.0,0.0,0.0 +0,0.786300,0.0,0.0,0.0,0.0,0.0 +0,0.786400,0.0,0.0,0.0,0.0,0.0 +0,0.786500,0.0,0.0,0.0,0.0,0.0 +0,0.786600,0.0,0.0,0.0,0.0,0.0 +0,0.786700,0.0,0.0,0.0,0.0,0.0 +0,0.786800,0.0,0.0,0.0,0.0,0.0 +0,0.786900,0.0,0.0,0.0,0.0,0.0 +0,0.787000,0.0,0.0,0.0,0.0,0.0 +0,0.787100,0.0,0.0,0.0,0.0,0.0 +0,0.787200,0.0,0.0,0.0,0.0,0.0 +0,0.787300,0.0,0.0,0.0,0.0,0.0 +0,0.787400,0.0,0.0,0.0,0.0,0.0 +0,0.787500,0.0,0.0,0.0,0.0,0.0 +0,0.787600,0.0,0.0,0.0,0.0,0.0 +0,0.787700,0.0,0.0,0.0,0.0,0.0 +0,0.787800,0.0,0.0,0.0,0.0,0.0 +0,0.787900,0.0,0.0,0.0,0.0,0.0 +0,0.788000,0.0,0.0,0.0,0.0,0.0 +0,0.788100,0.0,0.0,0.0,0.0,0.0 +0,0.788200,0.0,0.0,0.0,0.0,0.0 +0,0.788300,0.0,0.0,0.0,0.0,0.0 +0,0.788400,0.0,0.0,0.0,0.0,0.0 +0,0.788500,0.0,0.0,0.0,0.0,0.0 +0,0.788600,0.0,0.0,0.0,0.0,0.0 +0,0.788700,0.0,0.0,0.0,0.0,0.0 +0,0.788800,0.0,0.0,0.0,0.0,0.0 +0,0.788900,0.0,0.0,0.0,0.0,0.0 +0,0.789000,0.0,0.0,0.0,0.0,0.0 +0,0.789100,0.0,0.0,0.0,0.0,0.0 +0,0.789200,0.0,0.0,0.0,0.0,0.0 +0,0.789300,0.0,0.0,0.0,0.0,0.0 +0,0.789400,0.0,0.0,0.0,0.0,0.0 +0,0.789500,0.0,0.0,0.0,0.0,0.0 +0,0.789600,0.0,0.0,0.0,0.0,0.0 +0,0.789700,0.0,0.0,0.0,0.0,0.0 +0,0.789800,0.0,0.0,0.0,0.0,0.0 +0,0.789900,0.0,0.0,0.0,0.0,0.0 +0,0.790000,0.0,0.0,0.0,0.0,0.0 +0,0.790100,0.0,0.0,0.0,0.0,0.0 +0,0.790200,0.0,0.0,0.0,0.0,0.0 +0,0.790300,0.0,0.0,0.0,0.0,0.0 +0,0.790400,0.0,0.0,0.0,0.0,0.0 +0,0.790500,0.0,0.0,0.0,0.0,0.0 +0,0.790600,0.0,0.0,0.0,0.0,0.0 +0,0.790700,0.0,0.0,0.0,0.0,0.0 +0,0.790800,0.0,0.0,0.0,0.0,0.0 +0,0.790900,0.0,0.0,0.0,0.0,0.0 +0,0.791000,0.0,0.0,0.0,0.0,0.0 +0,0.791100,0.0,0.0,0.0,0.0,0.0 +0,0.791200,0.0,0.0,0.0,0.0,0.0 +0,0.791300,0.0,0.0,0.0,0.0,0.0 +0,0.791400,0.0,0.0,0.0,0.0,0.0 +0,0.791500,0.0,0.0,0.0,0.0,0.0 +0,0.791600,0.0,0.0,0.0,0.0,0.0 +0,0.791700,0.0,0.0,0.0,0.0,0.0 +0,0.791800,0.0,0.0,0.0,0.0,0.0 +0,0.791900,0.0,0.0,0.0,0.0,0.0 +0,0.792000,0.0,0.0,0.0,0.0,0.0 +0,0.792100,0.0,0.0,0.0,0.0,0.0 +0,0.792200,0.0,0.0,0.0,0.0,0.0 +0,0.792300,0.0,0.0,0.0,0.0,0.0 +0,0.792400,0.0,0.0,0.0,0.0,0.0 +0,0.792500,0.0,0.0,0.0,0.0,0.0 +0,0.792600,0.0,0.0,0.0,0.0,0.0 +0,0.792700,0.0,0.0,0.0,0.0,0.0 +0,0.792800,0.0,0.0,0.0,0.0,0.0 +0,0.792900,0.0,0.0,0.0,0.0,0.0 +0,0.793000,0.0,0.0,0.0,0.0,0.0 +0,0.793100,0.0,0.0,0.0,0.0,0.0 +0,0.793200,0.0,0.0,0.0,0.0,0.0 +0,0.793300,0.0,0.0,0.0,0.0,0.0 +0,0.793400,0.0,0.0,0.0,0.0,0.0 +0,0.793500,0.0,0.0,0.0,0.0,0.0 +0,0.793600,0.0,0.0,0.0,0.0,0.0 +0,0.793700,0.0,0.0,0.0,0.0,0.0 +0,0.793800,0.0,0.0,0.0,0.0,0.0 +0,0.793900,0.0,0.0,0.0,0.0,0.0 +0,0.794000,0.0,0.0,0.0,0.0,0.0 +0,0.794100,0.0,0.0,0.0,0.0,0.0 +0,0.794200,0.0,0.0,0.0,0.0,0.0 +0,0.794300,0.0,0.0,0.0,0.0,0.0 +0,0.794400,0.0,0.0,0.0,0.0,0.0 +0,0.794500,0.0,0.0,0.0,0.0,0.0 +0,0.794600,0.0,0.0,0.0,0.0,0.0 +0,0.794700,0.0,0.0,0.0,0.0,0.0 +0,0.794800,0.0,0.0,0.0,0.0,0.0 +0,0.794900,0.0,0.0,0.0,0.0,0.0 +0,0.795000,0.0,0.0,0.0,0.0,0.0 +0,0.795100,0.0,0.0,0.0,0.0,0.0 +0,0.795200,0.0,0.0,0.0,0.0,0.0 +0,0.795300,0.0,0.0,0.0,0.0,0.0 +0,0.795400,0.0,0.0,0.0,0.0,0.0 +0,0.795500,0.0,0.0,0.0,0.0,0.0 +0,0.795600,0.0,0.0,0.0,0.0,0.0 +0,0.795700,0.0,0.0,0.0,0.0,0.0 +0,0.795800,0.0,0.0,0.0,0.0,0.0 +0,0.795900,0.0,0.0,0.0,0.0,0.0 +0,0.796000,0.0,0.0,0.0,0.0,0.0 +0,0.796100,0.0,0.0,0.0,0.0,0.0 +0,0.796200,0.0,0.0,0.0,0.0,0.0 +0,0.796300,0.0,0.0,0.0,0.0,0.0 +0,0.796400,0.0,0.0,0.0,0.0,0.0 +0,0.796500,0.0,0.0,0.0,0.0,0.0 +0,0.796600,0.0,0.0,0.0,0.0,0.0 +0,0.796700,0.0,0.0,0.0,0.0,0.0 +0,0.796800,0.0,0.0,0.0,0.0,0.0 +0,0.796900,0.0,0.0,0.0,0.0,0.0 +0,0.797000,0.0,0.0,0.0,0.0,0.0 +0,0.797100,0.0,0.0,0.0,0.0,0.0 +0,0.797200,0.0,0.0,0.0,0.0,0.0 +0,0.797300,0.0,0.0,0.0,0.0,0.0 +0,0.797400,0.0,0.0,0.0,0.0,0.0 +0,0.797500,0.0,0.0,0.0,0.0,0.0 +0,0.797600,0.0,0.0,0.0,0.0,0.0 +0,0.797700,0.0,0.0,0.0,0.0,0.0 +0,0.797800,0.0,0.0,0.0,0.0,0.0 +0,0.797900,0.0,0.0,0.0,0.0,0.0 +0,0.798000,0.0,0.0,0.0,0.0,0.0 +0,0.798100,0.0,0.0,0.0,0.0,0.0 +0,0.798200,0.0,0.0,0.0,0.0,0.0 +0,0.798300,0.0,0.0,0.0,0.0,0.0 +0,0.798400,0.0,0.0,0.0,0.0,0.0 +0,0.798500,0.0,0.0,0.0,0.0,0.0 +0,0.798600,0.0,0.0,0.0,0.0,0.0 +0,0.798700,0.0,0.0,0.0,0.0,0.0 +0,0.798800,0.0,0.0,0.0,0.0,0.0 +0,0.798900,0.0,0.0,0.0,0.0,0.0 +0,0.799000,0.0,0.0,0.0,0.0,0.0 +0,0.799100,0.0,0.0,0.0,0.0,0.0 +0,0.799200,0.0,0.0,0.0,0.0,0.0 +0,0.799300,0.0,0.0,0.0,0.0,0.0 +0,0.799400,0.0,0.0,0.0,0.0,0.0 +0,0.799500,0.0,0.0,0.0,0.0,0.0 +0,0.799600,0.0,0.0,0.0,0.0,0.0 +0,0.799700,0.0,0.0,0.0,0.0,0.0 +0,0.799800,0.0,0.0,0.0,0.0,0.0 +0,0.799900,0.0,0.0,0.0,0.0,0.0 +0,0.800000,0.0,0.0,0.0,0.0,0.0 +0,0.800100,0.0,0.0,0.0,0.0,0.0 +1,213.453355,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.800200,0.0,0.0,0.0,0.0,0.0 +0,0.800300,0.0,0.0,0.0,0.0,0.0 +0,0.800400,0.0,0.0,0.0,0.0,0.0 +0,0.800500,0.0,0.0,0.0,0.0,0.0 +0,0.800600,0.0,0.0,0.0,0.0,0.0 +0,0.800700,0.0,0.0,0.0,0.0,0.0 +0,0.800800,0.0,0.0,0.0,0.0,0.0 +0,0.800900,0.0,0.0,0.0,0.0,0.0 +0,0.801000,0.0,0.0,0.0,0.0,0.0 +0,0.801100,0.0,0.0,0.0,0.0,0.0 +0,0.801200,0.0,0.0,0.0,0.0,0.0 +0,0.801300,0.0,0.0,0.0,0.0,0.0 +0,0.801400,0.0,0.0,0.0,0.0,0.0 +0,0.801500,0.0,0.0,0.0,0.0,0.0 +0,0.801600,0.0,0.0,0.0,0.0,0.0 +0,0.801700,0.0,0.0,0.0,0.0,0.0 +0,0.801800,0.0,0.0,0.0,0.0,0.0 +0,0.801900,0.0,0.0,0.0,0.0,0.0 +0,0.802000,0.0,0.0,0.0,0.0,0.0 +0,0.802100,0.0,0.0,0.0,0.0,0.0 +0,0.802200,0.0,0.0,0.0,0.0,0.0 +0,0.802300,0.0,0.0,0.0,0.0,0.0 +0,0.802400,0.0,0.0,0.0,0.0,0.0 +0,0.802500,0.0,0.0,0.0,0.0,0.0 +0,0.802600,0.0,0.0,0.0,0.0,0.0 +0,0.802700,0.0,0.0,0.0,0.0,0.0 +0,0.802800,0.0,0.0,0.0,0.0,0.0 +0,0.802900,0.0,0.0,0.0,0.0,0.0 +0,0.803000,0.0,0.0,0.0,0.0,0.0 +0,0.803100,0.0,0.0,0.0,0.0,0.0 +0,0.803200,0.0,0.0,0.0,0.0,0.0 +0,0.803300,0.0,0.0,0.0,0.0,0.0 +0,0.803400,0.0,0.0,0.0,0.0,0.0 +0,0.803500,0.0,0.0,0.0,0.0,0.0 +0,0.803600,0.0,0.0,0.0,0.0,0.0 +0,0.803700,0.0,0.0,0.0,0.0,0.0 +0,0.803800,0.0,0.0,0.0,0.0,0.0 +0,0.803900,0.0,0.0,0.0,0.0,0.0 +0,0.804000,0.0,0.0,0.0,0.0,0.0 +0,0.804100,0.0,0.0,0.0,0.0,0.0 +0,0.804200,0.0,0.0,0.0,0.0,0.0 +0,0.804300,0.0,0.0,0.0,0.0,0.0 +0,0.804400,0.0,0.0,0.0,0.0,0.0 +0,0.804500,0.0,0.0,0.0,0.0,0.0 +0,0.804600,0.0,0.0,0.0,0.0,0.0 +0,0.804700,0.0,0.0,0.0,0.0,0.0 +0,0.804800,0.0,0.0,0.0,0.0,0.0 +0,0.804900,0.0,0.0,0.0,0.0,0.0 +0,0.805000,0.0,0.0,0.0,0.0,0.0 +0,0.805100,0.0,0.0,0.0,0.0,0.0 +0,0.805200,0.0,0.0,0.0,0.0,0.0 +0,0.805300,0.0,0.0,0.0,0.0,0.0 +0,0.805400,0.0,0.0,0.0,0.0,0.0 +0,0.805500,0.0,0.0,0.0,0.0,0.0 +0,0.805600,0.0,0.0,0.0,0.0,0.0 +0,0.805700,0.0,0.0,0.0,0.0,0.0 +0,0.805800,0.0,0.0,0.0,0.0,0.0 +0,0.805900,0.0,0.0,0.0,0.0,0.0 +0,0.806000,0.0,0.0,0.0,0.0,0.0 +0,0.806100,0.0,0.0,0.0,0.0,0.0 +0,0.806200,0.0,0.0,0.0,0.0,0.0 +0,0.806300,0.0,0.0,0.0,0.0,0.0 +0,0.806400,0.0,0.0,0.0,0.0,0.0 +0,0.806500,0.0,0.0,0.0,0.0,0.0 +0,0.806600,0.0,0.0,0.0,0.0,0.0 +0,0.806700,0.0,0.0,0.0,0.0,0.0 +0,0.806800,0.0,0.0,0.0,0.0,0.0 +0,0.806900,0.0,0.0,0.0,0.0,0.0 +0,0.807000,0.0,0.0,0.0,0.0,0.0 +0,0.807100,0.0,0.0,0.0,0.0,0.0 +0,0.807200,0.0,0.0,0.0,0.0,0.0 +0,0.807300,0.0,0.0,0.0,0.0,0.0 +0,0.807400,0.0,0.0,0.0,0.0,0.0 +0,0.807500,0.0,0.0,0.0,0.0,0.0 +0,0.807600,0.0,0.0,0.0,0.0,0.0 +0,0.807700,0.0,0.0,0.0,0.0,0.0 +0,0.807800,0.0,0.0,0.0,0.0,0.0 +0,0.807900,0.0,0.0,0.0,0.0,0.0 +0,0.808000,0.0,0.0,0.0,0.0,0.0 +0,0.808100,0.0,0.0,0.0,0.0,0.0 +0,0.808200,0.0,0.0,0.0,0.0,0.0 +0,0.808300,0.0,0.0,0.0,0.0,0.0 +0,0.808400,0.0,0.0,0.0,0.0,0.0 +0,0.808500,0.0,0.0,0.0,0.0,0.0 +0,0.808600,0.0,0.0,0.0,0.0,0.0 +0,0.808700,0.0,0.0,0.0,0.0,0.0 +0,0.808800,0.0,0.0,0.0,0.0,0.0 +0,0.808900,0.0,0.0,0.0,0.0,0.0 +0,0.809000,0.0,0.0,0.0,0.0,0.0 +0,0.809100,0.0,0.0,0.0,0.0,0.0 +0,0.809200,0.0,0.0,0.0,0.0,0.0 +0,0.809300,0.0,0.0,0.0,0.0,0.0 +0,0.809400,0.0,0.0,0.0,0.0,0.0 +0,0.809500,0.0,0.0,0.0,0.0,0.0 +0,0.809600,0.0,0.0,0.0,0.0,0.0 +0,0.809700,0.0,0.0,0.0,0.0,0.0 +0,0.809800,0.0,0.0,0.0,0.0,0.0 +0,0.809900,0.0,0.0,0.0,0.0,0.0 +0,0.810000,0.0,0.0,0.0,0.0,0.0 +0,0.810100,0.0,0.0,0.0,0.0,0.0 +0,0.810200,0.0,0.0,0.0,0.0,0.0 +0,0.810300,0.0,0.0,0.0,0.0,0.0 +0,0.810400,0.0,0.0,0.0,0.0,0.0 +0,0.810500,0.0,0.0,0.0,0.0,0.0 +0,0.810600,0.0,0.0,0.0,0.0,0.0 +0,0.810700,0.0,0.0,0.0,0.0,0.0 +0,0.810800,0.0,0.0,0.0,0.0,0.0 +0,0.810900,0.0,0.0,0.0,0.0,0.0 +0,0.811000,0.0,0.0,0.0,0.0,0.0 +0,0.811100,0.0,0.0,0.0,0.0,0.0 +0,0.811200,0.0,0.0,0.0,0.0,0.0 +0,0.811300,0.0,0.0,0.0,0.0,0.0 +0,0.811400,0.0,0.0,0.0,0.0,0.0 +0,0.811500,0.0,0.0,0.0,0.0,0.0 +0,0.811600,0.0,0.0,0.0,0.0,0.0 +0,0.811700,0.0,0.0,0.0,0.0,0.0 +0,0.811800,0.0,0.0,0.0,0.0,0.0 +0,0.811900,0.0,0.0,0.0,0.0,0.0 +0,0.812000,0.0,0.0,0.0,0.0,0.0 +0,0.812100,0.0,0.0,0.0,0.0,0.0 +0,0.812200,0.0,0.0,0.0,0.0,0.0 +0,0.812300,0.0,0.0,0.0,0.0,0.0 +0,0.812400,0.0,0.0,0.0,0.0,0.0 +0,0.812500,0.0,0.0,0.0,0.0,0.0 +0,0.812600,0.0,0.0,0.0,0.0,0.0 +0,0.812700,0.0,0.0,0.0,0.0,0.0 +0,0.812800,0.0,0.0,0.0,0.0,0.0 +0,0.812900,0.0,0.0,0.0,0.0,0.0 +0,0.813000,0.0,0.0,0.0,0.0,0.0 +0,0.813100,0.0,0.0,0.0,0.0,0.0 +0,0.813200,0.0,0.0,0.0,0.0,0.0 +0,0.813300,0.0,0.0,0.0,0.0,0.0 +0,0.813400,0.0,0.0,0.0,0.0,0.0 +0,0.813500,0.0,0.0,0.0,0.0,0.0 +0,0.813600,0.0,0.0,0.0,0.0,0.0 +0,0.813700,0.0,0.0,0.0,0.0,0.0 +0,0.813800,0.0,0.0,0.0,0.0,0.0 +0,0.813900,0.0,0.0,0.0,0.0,0.0 +0,0.814000,0.0,0.0,0.0,0.0,0.0 +0,0.814100,0.0,0.0,0.0,0.0,0.0 +0,0.814200,0.0,0.0,0.0,0.0,0.0 +0,0.814300,0.0,0.0,0.0,0.0,0.0 +0,0.814400,0.0,0.0,0.0,0.0,0.0 +0,0.814500,0.0,0.0,0.0,0.0,0.0 +0,0.814600,0.0,0.0,0.0,0.0,0.0 +0,0.814700,0.0,0.0,0.0,0.0,0.0 +0,0.814800,0.0,0.0,0.0,0.0,0.0 +0,0.814900,0.0,0.0,0.0,0.0,0.0 +0,0.815000,0.0,0.0,0.0,0.0,0.0 +0,0.815100,0.0,0.0,0.0,0.0,0.0 +0,0.815200,0.0,0.0,0.0,0.0,0.0 +0,0.815300,0.0,0.0,0.0,0.0,0.0 +0,0.815400,0.0,0.0,0.0,0.0,0.0 +0,0.815500,0.0,0.0,0.0,0.0,0.0 +0,0.815600,0.0,0.0,0.0,0.0,0.0 +0,0.815700,0.0,0.0,0.0,0.0,0.0 +0,0.815800,0.0,0.0,0.0,0.0,0.0 +0,0.815900,0.0,0.0,0.0,0.0,0.0 +0,0.816000,0.0,0.0,0.0,0.0,0.0 +0,0.816100,0.0,0.0,0.0,0.0,0.0 +0,0.816200,0.0,0.0,0.0,0.0,0.0 +0,0.816300,0.0,0.0,0.0,0.0,0.0 +0,0.816400,0.0,0.0,0.0,0.0,0.0 +0,0.816500,0.0,0.0,0.0,0.0,0.0 +0,0.816600,0.0,0.0,0.0,0.0,0.0 +0,0.816700,0.0,0.0,0.0,0.0,0.0 +0,0.816800,0.0,0.0,0.0,0.0,0.0 +0,0.816900,0.0,0.0,0.0,0.0,0.0 +0,0.817000,0.0,0.0,0.0,0.0,0.0 +0,0.817100,0.0,0.0,0.0,0.0,0.0 +0,0.817200,0.0,0.0,0.0,0.0,0.0 +0,0.817300,0.0,0.0,0.0,0.0,0.0 +0,0.817400,0.0,0.0,0.0,0.0,0.0 +0,0.817500,0.0,0.0,0.0,0.0,0.0 +0,0.817600,0.0,0.0,0.0,0.0,0.0 +0,0.817700,0.0,0.0,0.0,0.0,0.0 +0,0.817800,0.0,0.0,0.0,0.0,0.0 +0,0.817900,0.0,0.0,0.0,0.0,0.0 +0,0.818000,0.0,0.0,0.0,0.0,0.0 +0,0.818100,0.0,0.0,0.0,0.0,0.0 +0,0.818200,0.0,0.0,0.0,0.0,0.0 +0,0.818300,0.0,0.0,0.0,0.0,0.0 +0,0.818400,0.0,0.0,0.0,0.0,0.0 +0,0.818500,0.0,0.0,0.0,0.0,0.0 +0,0.818600,0.0,0.0,0.0,0.0,0.0 +0,0.818700,0.0,0.0,0.0,0.0,0.0 +0,0.818800,0.0,0.0,0.0,0.0,0.0 +0,0.818900,0.0,0.0,0.0,0.0,0.0 +0,0.819000,0.0,0.0,0.0,0.0,0.0 +0,0.819100,0.0,0.0,0.0,0.0,0.0 +0,0.819200,0.0,0.0,0.0,0.0,0.0 +0,0.819300,0.0,0.0,0.0,0.0,0.0 +0,0.819400,0.0,0.0,0.0,0.0,0.0 +0,0.819500,0.0,0.0,0.0,0.0,0.0 +0,0.819600,0.0,0.0,0.0,0.0,0.0 +0,0.819700,0.0,0.0,0.0,0.0,0.0 +0,0.819800,0.0,0.0,0.0,0.0,0.0 +0,0.819900,0.0,0.0,0.0,0.0,0.0 +0,0.820000,0.0,0.0,0.0,0.0,0.0 +0,0.820100,0.0,0.0,0.0,0.0,0.0 +1,229.862764,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.820200,0.0,0.0,0.0,0.0,0.0 +0,0.820300,0.0,0.0,0.0,0.0,0.0 +0,0.820400,0.0,0.0,0.0,0.0,0.0 +0,0.820500,0.0,0.0,0.0,0.0,0.0 +0,0.820600,0.0,0.0,0.0,0.0,0.0 +0,0.820700,0.0,0.0,0.0,0.0,0.0 +0,0.820800,0.0,0.0,0.0,0.0,0.0 +0,0.820900,0.0,0.0,0.0,0.0,0.0 +0,0.821000,0.0,0.0,0.0,0.0,0.0 +0,0.821100,0.0,0.0,0.0,0.0,0.0 +0,0.821200,0.0,0.0,0.0,0.0,0.0 +0,0.821300,0.0,0.0,0.0,0.0,0.0 +0,0.821400,0.0,0.0,0.0,0.0,0.0 +0,0.821500,0.0,0.0,0.0,0.0,0.0 +0,0.821600,0.0,0.0,0.0,0.0,0.0 +0,0.821700,0.0,0.0,0.0,0.0,0.0 +0,0.821800,0.0,0.0,0.0,0.0,0.0 +0,0.821900,0.0,0.0,0.0,0.0,0.0 +0,0.822000,0.0,0.0,0.0,0.0,0.0 +0,0.822100,0.0,0.0,0.0,0.0,0.0 +0,0.822200,0.0,0.0,0.0,0.0,0.0 +0,0.822300,0.0,0.0,0.0,0.0,0.0 +0,0.822400,0.0,0.0,0.0,0.0,0.0 +0,0.822500,0.0,0.0,0.0,0.0,0.0 +0,0.822600,0.0,0.0,0.0,0.0,0.0 +0,0.822700,0.0,0.0,0.0,0.0,0.0 +0,0.822800,0.0,0.0,0.0,0.0,0.0 +0,0.822900,0.0,0.0,0.0,0.0,0.0 +0,0.823000,0.0,0.0,0.0,0.0,0.0 +0,0.823100,0.0,0.0,0.0,0.0,0.0 +0,0.823200,0.0,0.0,0.0,0.0,0.0 +0,0.823300,0.0,0.0,0.0,0.0,0.0 +0,0.823400,0.0,0.0,0.0,0.0,0.0 +0,0.823500,0.0,0.0,0.0,0.0,0.0 +0,0.823600,0.0,0.0,0.0,0.0,0.0 +0,0.823700,0.0,0.0,0.0,0.0,0.0 +0,0.823800,0.0,0.0,0.0,0.0,0.0 +0,0.823900,0.0,0.0,0.0,0.0,0.0 +0,0.824000,0.0,0.0,0.0,0.0,0.0 +0,0.824100,0.0,0.0,0.0,0.0,0.0 +0,0.824200,0.0,0.0,0.0,0.0,0.0 +0,0.824300,0.0,0.0,0.0,0.0,0.0 +0,0.824400,0.0,0.0,0.0,0.0,0.0 +0,0.824500,0.0,0.0,0.0,0.0,0.0 +0,0.824600,0.0,0.0,0.0,0.0,0.0 +0,0.824700,0.0,0.0,0.0,0.0,0.0 +0,0.824800,0.0,0.0,0.0,0.0,0.0 +0,0.824900,0.0,0.0,0.0,0.0,0.0 +0,0.825000,0.0,0.0,0.0,0.0,0.0 +0,0.825100,0.0,0.0,0.0,0.0,0.0 +0,0.825200,0.0,0.0,0.0,0.0,0.0 +0,0.825300,0.0,0.0,0.0,0.0,0.0 +0,0.825400,0.0,0.0,0.0,0.0,0.0 +0,0.825500,0.0,0.0,0.0,0.0,0.0 +0,0.825600,0.0,0.0,0.0,0.0,0.0 +0,0.825700,0.0,0.0,0.0,0.0,0.0 +0,0.825800,0.0,0.0,0.0,0.0,0.0 +0,0.825900,0.0,0.0,0.0,0.0,0.0 +0,0.826000,0.0,0.0,0.0,0.0,0.0 +0,0.826100,0.0,0.0,0.0,0.0,0.0 +0,0.826200,0.0,0.0,0.0,0.0,0.0 +0,0.826300,0.0,0.0,0.0,0.0,0.0 +0,0.826400,0.0,0.0,0.0,0.0,0.0 +0,0.826500,0.0,0.0,0.0,0.0,0.0 +0,0.826600,0.0,0.0,0.0,0.0,0.0 +0,0.826700,0.0,0.0,0.0,0.0,0.0 +0,0.826800,0.0,0.0,0.0,0.0,0.0 +0,0.826900,0.0,0.0,0.0,0.0,0.0 +0,0.827000,0.0,0.0,0.0,0.0,0.0 +0,0.827100,0.0,0.0,0.0,0.0,0.0 +0,0.827200,0.0,0.0,0.0,0.0,0.0 +0,0.827300,0.0,0.0,0.0,0.0,0.0 +0,0.827400,0.0,0.0,0.0,0.0,0.0 +0,0.827500,0.0,0.0,0.0,0.0,0.0 +0,0.827600,0.0,0.0,0.0,0.0,0.0 +0,0.827700,0.0,0.0,0.0,0.0,0.0 +0,0.827800,0.0,0.0,0.0,0.0,0.0 +0,0.827900,0.0,0.0,0.0,0.0,0.0 +0,0.828000,0.0,0.0,0.0,0.0,0.0 +0,0.828100,0.0,0.0,0.0,0.0,0.0 +0,0.828200,0.0,0.0,0.0,0.0,0.0 +0,0.828300,0.0,0.0,0.0,0.0,0.0 +0,0.828400,0.0,0.0,0.0,0.0,0.0 +0,0.828500,0.0,0.0,0.0,0.0,0.0 +0,0.828600,0.0,0.0,0.0,0.0,0.0 +0,0.828700,0.0,0.0,0.0,0.0,0.0 +0,0.828800,0.0,0.0,0.0,0.0,0.0 +0,0.828900,0.0,0.0,0.0,0.0,0.0 +0,0.829000,0.0,0.0,0.0,0.0,0.0 +0,0.829100,0.0,0.0,0.0,0.0,0.0 +0,0.829200,0.0,0.0,0.0,0.0,0.0 +0,0.829300,0.0,0.0,0.0,0.0,0.0 +0,0.829400,0.0,0.0,0.0,0.0,0.0 +0,0.829500,0.0,0.0,0.0,0.0,0.0 +0,0.829600,0.0,0.0,0.0,0.0,0.0 +0,0.829700,0.0,0.0,0.0,0.0,0.0 +0,0.829800,0.0,0.0,0.0,0.0,0.0 +0,0.829900,0.0,0.0,0.0,0.0,0.0 +0,0.830000,0.0,0.0,0.0,0.0,0.0 +0,0.830100,0.0,0.0,0.0,0.0,0.0 +0,0.830200,0.0,0.0,0.0,0.0,0.0 +0,0.830300,0.0,0.0,0.0,0.0,0.0 +0,0.830400,0.0,0.0,0.0,0.0,0.0 +0,0.830500,0.0,0.0,0.0,0.0,0.0 +0,0.830600,0.0,0.0,0.0,0.0,0.0 +0,0.830700,0.0,0.0,0.0,0.0,0.0 +0,0.830800,0.0,0.0,0.0,0.0,0.0 +0,0.830900,0.0,0.0,0.0,0.0,0.0 +0,0.831000,0.0,0.0,0.0,0.0,0.0 +0,0.831100,0.0,0.0,0.0,0.0,0.0 +0,0.831200,0.0,0.0,0.0,0.0,0.0 +0,0.831300,0.0,0.0,0.0,0.0,0.0 +0,0.831400,0.0,0.0,0.0,0.0,0.0 +0,0.831500,0.0,0.0,0.0,0.0,0.0 +0,0.831600,0.0,0.0,0.0,0.0,0.0 +0,0.831700,0.0,0.0,0.0,0.0,0.0 +0,0.831800,0.0,0.0,0.0,0.0,0.0 +0,0.831900,0.0,0.0,0.0,0.0,0.0 +0,0.832000,0.0,0.0,0.0,0.0,0.0 +0,0.832100,0.0,0.0,0.0,0.0,0.0 +0,0.832200,0.0,0.0,0.0,0.0,0.0 +0,0.832300,0.0,0.0,0.0,0.0,0.0 +0,0.832400,0.0,0.0,0.0,0.0,0.0 +0,0.832500,0.0,0.0,0.0,0.0,0.0 +0,0.832600,0.0,0.0,0.0,0.0,0.0 +0,0.832700,0.0,0.0,0.0,0.0,0.0 +0,0.832800,0.0,0.0,0.0,0.0,0.0 +0,0.832900,0.0,0.0,0.0,0.0,0.0 +0,0.833000,0.0,0.0,0.0,0.0,0.0 +0,0.833100,0.0,0.0,0.0,0.0,0.0 +0,0.833200,0.0,0.0,0.0,0.0,0.0 +0,0.833300,0.0,0.0,0.0,0.0,0.0 +0,0.833400,0.0,0.0,0.0,0.0,0.0 +0,0.833500,0.0,0.0,0.0,0.0,0.0 +0,0.833600,0.0,0.0,0.0,0.0,0.0 +0,0.833700,0.0,0.0,0.0,0.0,0.0 +0,0.833800,0.0,0.0,0.0,0.0,0.0 +0,0.833900,0.0,0.0,0.0,0.0,0.0 +0,0.834000,0.0,0.0,0.0,0.0,0.0 +0,0.834100,0.0,0.0,0.0,0.0,0.0 +0,0.834200,0.0,0.0,0.0,0.0,0.0 +0,0.834300,0.0,0.0,0.0,0.0,0.0 +0,0.834400,0.0,0.0,0.0,0.0,0.0 +0,0.834500,0.0,0.0,0.0,0.0,0.0 +0,0.834600,0.0,0.0,0.0,0.0,0.0 +0,0.834700,0.0,0.0,0.0,0.0,0.0 +0,0.834800,0.0,0.0,0.0,0.0,0.0 +0,0.834900,0.0,0.0,0.0,0.0,0.0 +0,0.835000,0.0,0.0,0.0,0.0,0.0 +0,0.835100,0.0,0.0,0.0,0.0,0.0 +0,0.835200,0.0,0.0,0.0,0.0,0.0 +0,0.835300,0.0,0.0,0.0,0.0,0.0 +0,0.835400,0.0,0.0,0.0,0.0,0.0 +0,0.835500,0.0,0.0,0.0,0.0,0.0 +0,0.835600,0.0,0.0,0.0,0.0,0.0 +0,0.835700,0.0,0.0,0.0,0.0,0.0 +0,0.835800,0.0,0.0,0.0,0.0,0.0 +0,0.835900,0.0,0.0,0.0,0.0,0.0 +0,0.836000,0.0,0.0,0.0,0.0,0.0 +0,0.836100,0.0,0.0,0.0,0.0,0.0 +0,0.836200,0.0,0.0,0.0,0.0,0.0 +0,0.836300,0.0,0.0,0.0,0.0,0.0 +0,0.836400,0.0,0.0,0.0,0.0,0.0 +0,0.836500,0.0,0.0,0.0,0.0,0.0 +0,0.836600,0.0,0.0,0.0,0.0,0.0 +0,0.836700,0.0,0.0,0.0,0.0,0.0 +0,0.836800,0.0,0.0,0.0,0.0,0.0 +0,0.836900,0.0,0.0,0.0,0.0,0.0 +0,0.837000,0.0,0.0,0.0,0.0,0.0 +0,0.837100,0.0,0.0,0.0,0.0,0.0 +0,0.837200,0.0,0.0,0.0,0.0,0.0 +0,0.837300,0.0,0.0,0.0,0.0,0.0 +0,0.837400,0.0,0.0,0.0,0.0,0.0 +0,0.837500,0.0,0.0,0.0,0.0,0.0 +0,0.837600,0.0,0.0,0.0,0.0,0.0 +0,0.837700,0.0,0.0,0.0,0.0,0.0 +0,0.837800,0.0,0.0,0.0,0.0,0.0 +0,0.837900,0.0,0.0,0.0,0.0,0.0 +0,0.838000,0.0,0.0,0.0,0.0,0.0 +0,0.838100,0.0,0.0,0.0,0.0,0.0 +0,0.838200,0.0,0.0,0.0,0.0,0.0 +0,0.838300,0.0,0.0,0.0,0.0,0.0 +0,0.838400,0.0,0.0,0.0,0.0,0.0 +0,0.838500,0.0,0.0,0.0,0.0,0.0 +0,0.838600,0.0,0.0,0.0,0.0,0.0 +0,0.838700,0.0,0.0,0.0,0.0,0.0 +0,0.838800,0.0,0.0,0.0,0.0,0.0 +0,0.838900,0.0,0.0,0.0,0.0,0.0 +0,0.839000,0.0,0.0,0.0,0.0,0.0 +0,0.839100,0.0,0.0,0.0,0.0,0.0 +0,0.839200,0.0,0.0,0.0,0.0,0.0 +0,0.839300,0.0,0.0,0.0,0.0,0.0 +0,0.839400,0.0,0.0,0.0,0.0,0.0 +0,0.839500,0.0,0.0,0.0,0.0,0.0 +0,0.839600,0.0,0.0,0.0,0.0,0.0 +0,0.839700,0.0,0.0,0.0,0.0,0.0 +0,0.839800,0.0,0.0,0.0,0.0,0.0 +0,0.839900,0.0,0.0,0.0,0.0,0.0 +0,0.840000,0.0,0.0,0.0,0.0,0.0 +0,0.840100,0.0,0.0,0.0,0.0,0.0 +1,247.092323,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.840200,0.0,0.0,0.0,0.0,0.0 +0,0.840300,0.0,0.0,0.0,0.0,0.0 +0,0.840400,0.0,0.0,0.0,0.0,0.0 +0,0.840500,0.0,0.0,0.0,0.0,0.0 +0,0.840600,0.0,0.0,0.0,0.0,0.0 +0,0.840700,0.0,0.0,0.0,0.0,0.0 +0,0.840800,0.0,0.0,0.0,0.0,0.0 +0,0.840900,0.0,0.0,0.0,0.0,0.0 +0,0.841000,0.0,0.0,0.0,0.0,0.0 +0,0.841100,0.0,0.0,0.0,0.0,0.0 +0,0.841200,0.0,0.0,0.0,0.0,0.0 +0,0.841300,0.0,0.0,0.0,0.0,0.0 +0,0.841400,0.0,0.0,0.0,0.0,0.0 +0,0.841500,0.0,0.0,0.0,0.0,0.0 +0,0.841600,0.0,0.0,0.0,0.0,0.0 +0,0.841700,0.0,0.0,0.0,0.0,0.0 +0,0.841800,0.0,0.0,0.0,0.0,0.0 +0,0.841900,0.0,0.0,0.0,0.0,0.0 +0,0.842000,0.0,0.0,0.0,0.0,0.0 +0,0.842100,0.0,0.0,0.0,0.0,0.0 +0,0.842200,0.0,0.0,0.0,0.0,0.0 +0,0.842300,0.0,0.0,0.0,0.0,0.0 +0,0.842400,0.0,0.0,0.0,0.0,0.0 +0,0.842500,0.0,0.0,0.0,0.0,0.0 +0,0.842600,0.0,0.0,0.0,0.0,0.0 +0,0.842700,0.0,0.0,0.0,0.0,0.0 +0,0.842800,0.0,0.0,0.0,0.0,0.0 +0,0.842900,0.0,0.0,0.0,0.0,0.0 +0,0.843000,0.0,0.0,0.0,0.0,0.0 +0,0.843100,0.0,0.0,0.0,0.0,0.0 +0,0.843200,0.0,0.0,0.0,0.0,0.0 +0,0.843300,0.0,0.0,0.0,0.0,0.0 +0,0.843400,0.0,0.0,0.0,0.0,0.0 +0,0.843500,0.0,0.0,0.0,0.0,0.0 +0,0.843600,0.0,0.0,0.0,0.0,0.0 +0,0.843700,0.0,0.0,0.0,0.0,0.0 +0,0.843800,0.0,0.0,0.0,0.0,0.0 +0,0.843900,0.0,0.0,0.0,0.0,0.0 +0,0.844000,0.0,0.0,0.0,0.0,0.0 +0,0.844100,0.0,0.0,0.0,0.0,0.0 +0,0.844200,0.0,0.0,0.0,0.0,0.0 +0,0.844300,0.0,0.0,0.0,0.0,0.0 +0,0.844400,0.0,0.0,0.0,0.0,0.0 +0,0.844500,0.0,0.0,0.0,0.0,0.0 +0,0.844600,0.0,0.0,0.0,0.0,0.0 +0,0.844700,0.0,0.0,0.0,0.0,0.0 +0,0.844800,0.0,0.0,0.0,0.0,0.0 +0,0.844900,0.0,0.0,0.0,0.0,0.0 +0,0.845000,0.0,0.0,0.0,0.0,0.0 +0,0.845100,0.0,0.0,0.0,0.0,0.0 +0,0.845200,0.0,0.0,0.0,0.0,0.0 +0,0.845300,0.0,0.0,0.0,0.0,0.0 +0,0.845400,0.0,0.0,0.0,0.0,0.0 +0,0.845500,0.0,0.0,0.0,0.0,0.0 +0,0.845600,0.0,0.0,0.0,0.0,0.0 +0,0.845700,0.0,0.0,0.0,0.0,0.0 +0,0.845800,0.0,0.0,0.0,0.0,0.0 +0,0.845900,0.0,0.0,0.0,0.0,0.0 +0,0.846000,0.0,0.0,0.0,0.0,0.0 +0,0.846100,0.0,0.0,0.0,0.0,0.0 +0,0.846200,0.0,0.0,0.0,0.0,0.0 +0,0.846300,0.0,0.0,0.0,0.0,0.0 +0,0.846400,0.0,0.0,0.0,0.0,0.0 +0,0.846500,0.0,0.0,0.0,0.0,0.0 +0,0.846600,0.0,0.0,0.0,0.0,0.0 +0,0.846700,0.0,0.0,0.0,0.0,0.0 +0,0.846800,0.0,0.0,0.0,0.0,0.0 +0,0.846900,0.0,0.0,0.0,0.0,0.0 +0,0.847000,0.0,0.0,0.0,0.0,0.0 +0,0.847100,0.0,0.0,0.0,0.0,0.0 +0,0.847200,0.0,0.0,0.0,0.0,0.0 +0,0.847300,0.0,0.0,0.0,0.0,0.0 +0,0.847400,0.0,0.0,0.0,0.0,0.0 +0,0.847500,0.0,0.0,0.0,0.0,0.0 +0,0.847600,0.0,0.0,0.0,0.0,0.0 +0,0.847700,0.0,0.0,0.0,0.0,0.0 +0,0.847800,0.0,0.0,0.0,0.0,0.0 +0,0.847900,0.0,0.0,0.0,0.0,0.0 +0,0.848000,0.0,0.0,0.0,0.0,0.0 +0,0.848100,0.0,0.0,0.0,0.0,0.0 +0,0.848200,0.0,0.0,0.0,0.0,0.0 +0,0.848300,0.0,0.0,0.0,0.0,0.0 +0,0.848400,0.0,0.0,0.0,0.0,0.0 +0,0.848500,0.0,0.0,0.0,0.0,0.0 +0,0.848600,0.0,0.0,0.0,0.0,0.0 +0,0.848700,0.0,0.0,0.0,0.0,0.0 +0,0.848800,0.0,0.0,0.0,0.0,0.0 +0,0.848900,0.0,0.0,0.0,0.0,0.0 +0,0.849000,0.0,0.0,0.0,0.0,0.0 +0,0.849100,0.0,0.0,0.0,0.0,0.0 +0,0.849200,0.0,0.0,0.0,0.0,0.0 +0,0.849300,0.0,0.0,0.0,0.0,0.0 +0,0.849400,0.0,0.0,0.0,0.0,0.0 +0,0.849500,0.0,0.0,0.0,0.0,0.0 +0,0.849600,0.0,0.0,0.0,0.0,0.0 +0,0.849700,0.0,0.0,0.0,0.0,0.0 +0,0.849800,0.0,0.0,0.0,0.0,0.0 +0,0.849900,0.0,0.0,0.0,0.0,0.0 +0,0.850000,0.0,0.0,0.0,0.0,0.0 +0,0.850100,0.0,0.0,0.0,0.0,0.0 +0,0.850200,0.0,0.0,0.0,0.0,0.0 +0,0.850300,0.0,0.0,0.0,0.0,0.0 +0,0.850400,0.0,0.0,0.0,0.0,0.0 +0,0.850500,0.0,0.0,0.0,0.0,0.0 +0,0.850600,0.0,0.0,0.0,0.0,0.0 +0,0.850700,0.0,0.0,0.0,0.0,0.0 +0,0.850800,0.0,0.0,0.0,0.0,0.0 +0,0.850900,0.0,0.0,0.0,0.0,0.0 +0,0.851000,0.0,0.0,0.0,0.0,0.0 +0,0.851100,0.0,0.0,0.0,0.0,0.0 +0,0.851200,0.0,0.0,0.0,0.0,0.0 +0,0.851300,0.0,0.0,0.0,0.0,0.0 +0,0.851400,0.0,0.0,0.0,0.0,0.0 +0,0.851500,0.0,0.0,0.0,0.0,0.0 +0,0.851600,0.0,0.0,0.0,0.0,0.0 +0,0.851700,0.0,0.0,0.0,0.0,0.0 +0,0.851800,0.0,0.0,0.0,0.0,0.0 +0,0.851900,0.0,0.0,0.0,0.0,0.0 +0,0.852000,0.0,0.0,0.0,0.0,0.0 +0,0.852100,0.0,0.0,0.0,0.0,0.0 +0,0.852200,0.0,0.0,0.0,0.0,0.0 +0,0.852300,0.0,0.0,0.0,0.0,0.0 +0,0.852400,0.0,0.0,0.0,0.0,0.0 +0,0.852500,0.0,0.0,0.0,0.0,0.0 +0,0.852600,0.0,0.0,0.0,0.0,0.0 +0,0.852700,0.0,0.0,0.0,0.0,0.0 +0,0.852800,0.0,0.0,0.0,0.0,0.0 +0,0.852900,0.0,0.0,0.0,0.0,0.0 +0,0.853000,0.0,0.0,0.0,0.0,0.0 +0,0.853100,0.0,0.0,0.0,0.0,0.0 +0,0.853200,0.0,0.0,0.0,0.0,0.0 +0,0.853300,0.0,0.0,0.0,0.0,0.0 +0,0.853400,0.0,0.0,0.0,0.0,0.0 +0,0.853500,0.0,0.0,0.0,0.0,0.0 +0,0.853600,0.0,0.0,0.0,0.0,0.0 +0,0.853700,0.0,0.0,0.0,0.0,0.0 +0,0.853800,0.0,0.0,0.0,0.0,0.0 +0,0.853900,0.0,0.0,0.0,0.0,0.0 +0,0.854000,0.0,0.0,0.0,0.0,0.0 +0,0.854100,0.0,0.0,0.0,0.0,0.0 +0,0.854200,0.0,0.0,0.0,0.0,0.0 +0,0.854300,0.0,0.0,0.0,0.0,0.0 +0,0.854400,0.0,0.0,0.0,0.0,0.0 +0,0.854500,0.0,0.0,0.0,0.0,0.0 +0,0.854600,0.0,0.0,0.0,0.0,0.0 +0,0.854700,0.0,0.0,0.0,0.0,0.0 +0,0.854800,0.0,0.0,0.0,0.0,0.0 +0,0.854900,0.0,0.0,0.0,0.0,0.0 +0,0.855000,0.0,0.0,0.0,0.0,0.0 +0,0.855100,0.0,0.0,0.0,0.0,0.0 +0,0.855200,0.0,0.0,0.0,0.0,0.0 +0,0.855300,0.0,0.0,0.0,0.0,0.0 +0,0.855400,0.0,0.0,0.0,0.0,0.0 +0,0.855500,0.0,0.0,0.0,0.0,0.0 +0,0.855600,0.0,0.0,0.0,0.0,0.0 +0,0.855700,0.0,0.0,0.0,0.0,0.0 +0,0.855800,0.0,0.0,0.0,0.0,0.0 +0,0.855900,0.0,0.0,0.0,0.0,0.0 +0,0.856000,0.0,0.0,0.0,0.0,0.0 +0,0.856100,0.0,0.0,0.0,0.0,0.0 +0,0.856200,0.0,0.0,0.0,0.0,0.0 +0,0.856300,0.0,0.0,0.0,0.0,0.0 +0,0.856400,0.0,0.0,0.0,0.0,0.0 +0,0.856500,0.0,0.0,0.0,0.0,0.0 +0,0.856600,0.0,0.0,0.0,0.0,0.0 +0,0.856700,0.0,0.0,0.0,0.0,0.0 +0,0.856800,0.0,0.0,0.0,0.0,0.0 +0,0.856900,0.0,0.0,0.0,0.0,0.0 +0,0.857000,0.0,0.0,0.0,0.0,0.0 +0,0.857100,0.0,0.0,0.0,0.0,0.0 +0,0.857200,0.0,0.0,0.0,0.0,0.0 +0,0.857300,0.0,0.0,0.0,0.0,0.0 +0,0.857400,0.0,0.0,0.0,0.0,0.0 +0,0.857500,0.0,0.0,0.0,0.0,0.0 +0,0.857600,0.0,0.0,0.0,0.0,0.0 +0,0.857700,0.0,0.0,0.0,0.0,0.0 +0,0.857800,0.0,0.0,0.0,0.0,0.0 +0,0.857900,0.0,0.0,0.0,0.0,0.0 +0,0.858000,0.0,0.0,0.0,0.0,0.0 +0,0.858100,0.0,0.0,0.0,0.0,0.0 +0,0.858200,0.0,0.0,0.0,0.0,0.0 +0,0.858300,0.0,0.0,0.0,0.0,0.0 +0,0.858400,0.0,0.0,0.0,0.0,0.0 +0,0.858500,0.0,0.0,0.0,0.0,0.0 +0,0.858600,0.0,0.0,0.0,0.0,0.0 +0,0.858700,0.0,0.0,0.0,0.0,0.0 +0,0.858800,0.0,0.0,0.0,0.0,0.0 +0,0.858900,0.0,0.0,0.0,0.0,0.0 +0,0.859000,0.0,0.0,0.0,0.0,0.0 +0,0.859100,0.0,0.0,0.0,0.0,0.0 +0,0.859200,0.0,0.0,0.0,0.0,0.0 +0,0.859300,0.0,0.0,0.0,0.0,0.0 +0,0.859400,0.0,0.0,0.0,0.0,0.0 +0,0.859500,0.0,0.0,0.0,0.0,0.0 +0,0.859600,0.0,0.0,0.0,0.0,0.0 +0,0.859700,0.0,0.0,0.0,0.0,0.0 +0,0.859800,0.0,0.0,0.0,0.0,0.0 +0,0.859900,0.0,0.0,0.0,0.0,0.0 +0,0.860000,0.0,0.0,0.0,0.0,0.0 +0,0.860100,0.0,0.0,0.0,0.0,0.0 +1,265.162032,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.860200,0.0,0.0,0.0,0.0,0.0 +0,0.860300,0.0,0.0,0.0,0.0,0.0 +0,0.860400,0.0,0.0,0.0,0.0,0.0 +0,0.860500,0.0,0.0,0.0,0.0,0.0 +0,0.860600,0.0,0.0,0.0,0.0,0.0 +0,0.860700,0.0,0.0,0.0,0.0,0.0 +0,0.860800,0.0,0.0,0.0,0.0,0.0 +0,0.860900,0.0,0.0,0.0,0.0,0.0 +0,0.861000,0.0,0.0,0.0,0.0,0.0 +0,0.861100,0.0,0.0,0.0,0.0,0.0 +0,0.861200,0.0,0.0,0.0,0.0,0.0 +0,0.861300,0.0,0.0,0.0,0.0,0.0 +0,0.861400,0.0,0.0,0.0,0.0,0.0 +0,0.861500,0.0,0.0,0.0,0.0,0.0 +0,0.861600,0.0,0.0,0.0,0.0,0.0 +0,0.861700,0.0,0.0,0.0,0.0,0.0 +0,0.861800,0.0,0.0,0.0,0.0,0.0 +0,0.861900,0.0,0.0,0.0,0.0,0.0 +0,0.862000,0.0,0.0,0.0,0.0,0.0 +0,0.862100,0.0,0.0,0.0,0.0,0.0 +0,0.862200,0.0,0.0,0.0,0.0,0.0 +0,0.862300,0.0,0.0,0.0,0.0,0.0 +0,0.862400,0.0,0.0,0.0,0.0,0.0 +0,0.862500,0.0,0.0,0.0,0.0,0.0 +0,0.862600,0.0,0.0,0.0,0.0,0.0 +0,0.862700,0.0,0.0,0.0,0.0,0.0 +0,0.862800,0.0,0.0,0.0,0.0,0.0 +0,0.862900,0.0,0.0,0.0,0.0,0.0 +0,0.863000,0.0,0.0,0.0,0.0,0.0 +0,0.863100,0.0,0.0,0.0,0.0,0.0 +0,0.863200,0.0,0.0,0.0,0.0,0.0 +0,0.863300,0.0,0.0,0.0,0.0,0.0 +0,0.863400,0.0,0.0,0.0,0.0,0.0 +0,0.863500,0.0,0.0,0.0,0.0,0.0 +0,0.863600,0.0,0.0,0.0,0.0,0.0 +0,0.863700,0.0,0.0,0.0,0.0,0.0 +0,0.863800,0.0,0.0,0.0,0.0,0.0 +0,0.863900,0.0,0.0,0.0,0.0,0.0 +0,0.864000,0.0,0.0,0.0,0.0,0.0 +0,0.864100,0.0,0.0,0.0,0.0,0.0 +0,0.864200,0.0,0.0,0.0,0.0,0.0 +0,0.864300,0.0,0.0,0.0,0.0,0.0 +0,0.864400,0.0,0.0,0.0,0.0,0.0 +0,0.864500,0.0,0.0,0.0,0.0,0.0 +0,0.864600,0.0,0.0,0.0,0.0,0.0 +0,0.864700,0.0,0.0,0.0,0.0,0.0 +0,0.864800,0.0,0.0,0.0,0.0,0.0 +0,0.864900,0.0,0.0,0.0,0.0,0.0 +0,0.865000,0.0,0.0,0.0,0.0,0.0 +0,0.865100,0.0,0.0,0.0,0.0,0.0 +0,0.865200,0.0,0.0,0.0,0.0,0.0 +0,0.865300,0.0,0.0,0.0,0.0,0.0 +0,0.865400,0.0,0.0,0.0,0.0,0.0 +0,0.865500,0.0,0.0,0.0,0.0,0.0 +0,0.865600,0.0,0.0,0.0,0.0,0.0 +0,0.865700,0.0,0.0,0.0,0.0,0.0 +0,0.865800,0.0,0.0,0.0,0.0,0.0 +0,0.865900,0.0,0.0,0.0,0.0,0.0 +0,0.866000,0.0,0.0,0.0,0.0,0.0 +0,0.866100,0.0,0.0,0.0,0.0,0.0 +0,0.866200,0.0,0.0,0.0,0.0,0.0 +0,0.866300,0.0,0.0,0.0,0.0,0.0 +0,0.866400,0.0,0.0,0.0,0.0,0.0 +0,0.866500,0.0,0.0,0.0,0.0,0.0 +0,0.866600,0.0,0.0,0.0,0.0,0.0 +0,0.866700,0.0,0.0,0.0,0.0,0.0 +0,0.866800,0.0,0.0,0.0,0.0,0.0 +0,0.866900,0.0,0.0,0.0,0.0,0.0 +0,0.867000,0.0,0.0,0.0,0.0,0.0 +0,0.867100,0.0,0.0,0.0,0.0,0.0 +0,0.867200,0.0,0.0,0.0,0.0,0.0 +0,0.867300,0.0,0.0,0.0,0.0,0.0 +0,0.867400,0.0,0.0,0.0,0.0,0.0 +0,0.867500,0.0,0.0,0.0,0.0,0.0 +0,0.867600,0.0,0.0,0.0,0.0,0.0 +0,0.867700,0.0,0.0,0.0,0.0,0.0 +0,0.867800,0.0,0.0,0.0,0.0,0.0 +0,0.867900,0.0,0.0,0.0,0.0,0.0 +0,0.868000,0.0,0.0,0.0,0.0,0.0 +0,0.868100,0.0,0.0,0.0,0.0,0.0 +0,0.868200,0.0,0.0,0.0,0.0,0.0 +0,0.868300,0.0,0.0,0.0,0.0,0.0 +0,0.868400,0.0,0.0,0.0,0.0,0.0 +0,0.868500,0.0,0.0,0.0,0.0,0.0 +0,0.868600,0.0,0.0,0.0,0.0,0.0 +0,0.868700,0.0,0.0,0.0,0.0,0.0 +0,0.868800,0.0,0.0,0.0,0.0,0.0 +0,0.868900,0.0,0.0,0.0,0.0,0.0 +0,0.869000,0.0,0.0,0.0,0.0,0.0 +0,0.869100,0.0,0.0,0.0,0.0,0.0 +0,0.869200,0.0,0.0,0.0,0.0,0.0 +0,0.869300,0.0,0.0,0.0,0.0,0.0 +0,0.869400,0.0,0.0,0.0,0.0,0.0 +0,0.869500,0.0,0.0,0.0,0.0,0.0 +0,0.869600,0.0,0.0,0.0,0.0,0.0 +0,0.869700,0.0,0.0,0.0,0.0,0.0 +0,0.869800,0.0,0.0,0.0,0.0,0.0 +0,0.869900,0.0,0.0,0.0,0.0,0.0 +0,0.870000,0.0,0.0,0.0,0.0,0.0 +0,0.870100,0.0,0.0,0.0,0.0,0.0 +0,0.870200,0.0,0.0,0.0,0.0,0.0 +0,0.870300,0.0,0.0,0.0,0.0,0.0 +0,0.870400,0.0,0.0,0.0,0.0,0.0 +0,0.870500,0.0,0.0,0.0,0.0,0.0 +0,0.870600,0.0,0.0,0.0,0.0,0.0 +0,0.870700,0.0,0.0,0.0,0.0,0.0 +0,0.870800,0.0,0.0,0.0,0.0,0.0 +0,0.870900,0.0,0.0,0.0,0.0,0.0 +0,0.871000,0.0,0.0,0.0,0.0,0.0 +0,0.871100,0.0,0.0,0.0,0.0,0.0 +0,0.871200,0.0,0.0,0.0,0.0,0.0 +0,0.871300,0.0,0.0,0.0,0.0,0.0 +0,0.871400,0.0,0.0,0.0,0.0,0.0 +0,0.871500,0.0,0.0,0.0,0.0,0.0 +0,0.871600,0.0,0.0,0.0,0.0,0.0 +0,0.871700,0.0,0.0,0.0,0.0,0.0 +0,0.871800,0.0,0.0,0.0,0.0,0.0 +0,0.871900,0.0,0.0,0.0,0.0,0.0 +0,0.872000,0.0,0.0,0.0,0.0,0.0 +0,0.872100,0.0,0.0,0.0,0.0,0.0 +0,0.872200,0.0,0.0,0.0,0.0,0.0 +0,0.872300,0.0,0.0,0.0,0.0,0.0 +0,0.872400,0.0,0.0,0.0,0.0,0.0 +0,0.872500,0.0,0.0,0.0,0.0,0.0 +0,0.872600,0.0,0.0,0.0,0.0,0.0 +0,0.872700,0.0,0.0,0.0,0.0,0.0 +0,0.872800,0.0,0.0,0.0,0.0,0.0 +0,0.872900,0.0,0.0,0.0,0.0,0.0 +0,0.873000,0.0,0.0,0.0,0.0,0.0 +0,0.873100,0.0,0.0,0.0,0.0,0.0 +0,0.873200,0.0,0.0,0.0,0.0,0.0 +0,0.873300,0.0,0.0,0.0,0.0,0.0 +0,0.873400,0.0,0.0,0.0,0.0,0.0 +0,0.873500,0.0,0.0,0.0,0.0,0.0 +0,0.873600,0.0,0.0,0.0,0.0,0.0 +0,0.873700,0.0,0.0,0.0,0.0,0.0 +0,0.873800,0.0,0.0,0.0,0.0,0.0 +0,0.873900,0.0,0.0,0.0,0.0,0.0 +0,0.874000,0.0,0.0,0.0,0.0,0.0 +0,0.874100,0.0,0.0,0.0,0.0,0.0 +0,0.874200,0.0,0.0,0.0,0.0,0.0 +0,0.874300,0.0,0.0,0.0,0.0,0.0 +0,0.874400,0.0,0.0,0.0,0.0,0.0 +0,0.874500,0.0,0.0,0.0,0.0,0.0 +0,0.874600,0.0,0.0,0.0,0.0,0.0 +0,0.874700,0.0,0.0,0.0,0.0,0.0 +0,0.874800,0.0,0.0,0.0,0.0,0.0 +0,0.874900,0.0,0.0,0.0,0.0,0.0 +0,0.875000,0.0,0.0,0.0,0.0,0.0 +0,0.875100,0.0,0.0,0.0,0.0,0.0 +0,0.875200,0.0,0.0,0.0,0.0,0.0 +0,0.875300,0.0,0.0,0.0,0.0,0.0 +0,0.875400,0.0,0.0,0.0,0.0,0.0 +0,0.875500,0.0,0.0,0.0,0.0,0.0 +0,0.875600,0.0,0.0,0.0,0.0,0.0 +0,0.875700,0.0,0.0,0.0,0.0,0.0 +0,0.875800,0.0,0.0,0.0,0.0,0.0 +0,0.875900,0.0,0.0,0.0,0.0,0.0 +0,0.876000,0.0,0.0,0.0,0.0,0.0 +0,0.876100,0.0,0.0,0.0,0.0,0.0 +0,0.876200,0.0,0.0,0.0,0.0,0.0 +0,0.876300,0.0,0.0,0.0,0.0,0.0 +0,0.876400,0.0,0.0,0.0,0.0,0.0 +0,0.876500,0.0,0.0,0.0,0.0,0.0 +0,0.876600,0.0,0.0,0.0,0.0,0.0 +0,0.876700,0.0,0.0,0.0,0.0,0.0 +0,0.876800,0.0,0.0,0.0,0.0,0.0 +0,0.876900,0.0,0.0,0.0,0.0,0.0 +0,0.877000,0.0,0.0,0.0,0.0,0.0 +0,0.877100,0.0,0.0,0.0,0.0,0.0 +0,0.877200,0.0,0.0,0.0,0.0,0.0 +0,0.877300,0.0,0.0,0.0,0.0,0.0 +0,0.877400,0.0,0.0,0.0,0.0,0.0 +0,0.877500,0.0,0.0,0.0,0.0,0.0 +0,0.877600,0.0,0.0,0.0,0.0,0.0 +0,0.877700,0.0,0.0,0.0,0.0,0.0 +0,0.877800,0.0,0.0,0.0,0.0,0.0 +0,0.877900,0.0,0.0,0.0,0.0,0.0 +0,0.878000,0.0,0.0,0.0,0.0,0.0 +0,0.878100,0.0,0.0,0.0,0.0,0.0 +0,0.878200,0.0,0.0,0.0,0.0,0.0 +0,0.878300,0.0,0.0,0.0,0.0,0.0 +0,0.878400,0.0,0.0,0.0,0.0,0.0 +0,0.878500,0.0,0.0,0.0,0.0,0.0 +0,0.878600,0.0,0.0,0.0,0.0,0.0 +0,0.878700,0.0,0.0,0.0,0.0,0.0 +0,0.878800,0.0,0.0,0.0,0.0,0.0 +0,0.878900,0.0,0.0,0.0,0.0,0.0 +0,0.879000,0.0,0.0,0.0,0.0,0.0 +0,0.879100,0.0,0.0,0.0,0.0,0.0 +0,0.879200,0.0,0.0,0.0,0.0,0.0 +0,0.879300,0.0,0.0,0.0,0.0,0.0 +0,0.879400,0.0,0.0,0.0,0.0,0.0 +0,0.879500,0.0,0.0,0.0,0.0,0.0 +0,0.879600,0.0,0.0,0.0,0.0,0.0 +0,0.879700,0.0,0.0,0.0,0.0,0.0 +0,0.879800,0.0,0.0,0.0,0.0,0.0 +0,0.879900,0.0,0.0,0.0,0.0,0.0 +0,0.880000,0.0,0.0,0.0,0.0,0.0 +0,0.880100,0.0,0.0,0.0,0.0,0.0 +1,284.091891,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.880200,0.0,0.0,0.0,0.0,0.0 +0,0.880300,0.0,0.0,0.0,0.0,0.0 +0,0.880400,0.0,0.0,0.0,0.0,0.0 +0,0.880500,0.0,0.0,0.0,0.0,0.0 +0,0.880600,0.0,0.0,0.0,0.0,0.0 +0,0.880700,0.0,0.0,0.0,0.0,0.0 +0,0.880800,0.0,0.0,0.0,0.0,0.0 +0,0.880900,0.0,0.0,0.0,0.0,0.0 +0,0.881000,0.0,0.0,0.0,0.0,0.0 +0,0.881100,0.0,0.0,0.0,0.0,0.0 +0,0.881200,0.0,0.0,0.0,0.0,0.0 +0,0.881300,0.0,0.0,0.0,0.0,0.0 +0,0.881400,0.0,0.0,0.0,0.0,0.0 +0,0.881500,0.0,0.0,0.0,0.0,0.0 +0,0.881600,0.0,0.0,0.0,0.0,0.0 +0,0.881700,0.0,0.0,0.0,0.0,0.0 +0,0.881800,0.0,0.0,0.0,0.0,0.0 +0,0.881900,0.0,0.0,0.0,0.0,0.0 +0,0.882000,0.0,0.0,0.0,0.0,0.0 +0,0.882100,0.0,0.0,0.0,0.0,0.0 +0,0.882200,0.0,0.0,0.0,0.0,0.0 +0,0.882300,0.0,0.0,0.0,0.0,0.0 +0,0.882400,0.0,0.0,0.0,0.0,0.0 +0,0.882500,0.0,0.0,0.0,0.0,0.0 +0,0.882600,0.0,0.0,0.0,0.0,0.0 +0,0.882700,0.0,0.0,0.0,0.0,0.0 +0,0.882800,0.0,0.0,0.0,0.0,0.0 +0,0.882900,0.0,0.0,0.0,0.0,0.0 +0,0.883000,0.0,0.0,0.0,0.0,0.0 +0,0.883100,0.0,0.0,0.0,0.0,0.0 +0,0.883200,0.0,0.0,0.0,0.0,0.0 +0,0.883300,0.0,0.0,0.0,0.0,0.0 +0,0.883400,0.0,0.0,0.0,0.0,0.0 +0,0.883500,0.0,0.0,0.0,0.0,0.0 +0,0.883600,0.0,0.0,0.0,0.0,0.0 +0,0.883700,0.0,0.0,0.0,0.0,0.0 +0,0.883800,0.0,0.0,0.0,0.0,0.0 +0,0.883900,0.0,0.0,0.0,0.0,0.0 +0,0.884000,0.0,0.0,0.0,0.0,0.0 +0,0.884100,0.0,0.0,0.0,0.0,0.0 +0,0.884200,0.0,0.0,0.0,0.0,0.0 +0,0.884300,0.0,0.0,0.0,0.0,0.0 +0,0.884400,0.0,0.0,0.0,0.0,0.0 +0,0.884500,0.0,0.0,0.0,0.0,0.0 +0,0.884600,0.0,0.0,0.0,0.0,0.0 +0,0.884700,0.0,0.0,0.0,0.0,0.0 +0,0.884800,0.0,0.0,0.0,0.0,0.0 +0,0.884900,0.0,0.0,0.0,0.0,0.0 +0,0.885000,0.0,0.0,0.0,0.0,0.0 +0,0.885100,0.0,0.0,0.0,0.0,0.0 +0,0.885200,0.0,0.0,0.0,0.0,0.0 +0,0.885300,0.0,0.0,0.0,0.0,0.0 +0,0.885400,0.0,0.0,0.0,0.0,0.0 +0,0.885500,0.0,0.0,0.0,0.0,0.0 +0,0.885600,0.0,0.0,0.0,0.0,0.0 +0,0.885700,0.0,0.0,0.0,0.0,0.0 +0,0.885800,0.0,0.0,0.0,0.0,0.0 +0,0.885900,0.0,0.0,0.0,0.0,0.0 +0,0.886000,0.0,0.0,0.0,0.0,0.0 +0,0.886100,0.0,0.0,0.0,0.0,0.0 +0,0.886200,0.0,0.0,0.0,0.0,0.0 +0,0.886300,0.0,0.0,0.0,0.0,0.0 +0,0.886400,0.0,0.0,0.0,0.0,0.0 +0,0.886500,0.0,0.0,0.0,0.0,0.0 +0,0.886600,0.0,0.0,0.0,0.0,0.0 +0,0.886700,0.0,0.0,0.0,0.0,0.0 +0,0.886800,0.0,0.0,0.0,0.0,0.0 +0,0.886900,0.0,0.0,0.0,0.0,0.0 +0,0.887000,0.0,0.0,0.0,0.0,0.0 +0,0.887100,0.0,0.0,0.0,0.0,0.0 +0,0.887200,0.0,0.0,0.0,0.0,0.0 +0,0.887300,0.0,0.0,0.0,0.0,0.0 +0,0.887400,0.0,0.0,0.0,0.0,0.0 +0,0.887500,0.0,0.0,0.0,0.0,0.0 +0,0.887600,0.0,0.0,0.0,0.0,0.0 +0,0.887700,0.0,0.0,0.0,0.0,0.0 +0,0.887800,0.0,0.0,0.0,0.0,0.0 +0,0.887900,0.0,0.0,0.0,0.0,0.0 +0,0.888000,0.0,0.0,0.0,0.0,0.0 +0,0.888100,0.0,0.0,0.0,0.0,0.0 +0,0.888200,0.0,0.0,0.0,0.0,0.0 +0,0.888300,0.0,0.0,0.0,0.0,0.0 +0,0.888400,0.0,0.0,0.0,0.0,0.0 +0,0.888500,0.0,0.0,0.0,0.0,0.0 +0,0.888600,0.0,0.0,0.0,0.0,0.0 +0,0.888700,0.0,0.0,0.0,0.0,0.0 +0,0.888800,0.0,0.0,0.0,0.0,0.0 +0,0.888900,0.0,0.0,0.0,0.0,0.0 +0,0.889000,0.0,0.0,0.0,0.0,0.0 +0,0.889100,0.0,0.0,0.0,0.0,0.0 +0,0.889200,0.0,0.0,0.0,0.0,0.0 +0,0.889300,0.0,0.0,0.0,0.0,0.0 +0,0.889400,0.0,0.0,0.0,0.0,0.0 +0,0.889500,0.0,0.0,0.0,0.0,0.0 +0,0.889600,0.0,0.0,0.0,0.0,0.0 +0,0.889700,0.0,0.0,0.0,0.0,0.0 +0,0.889800,0.0,0.0,0.0,0.0,0.0 +0,0.889900,0.0,0.0,0.0,0.0,0.0 +0,0.890000,0.0,0.0,0.0,0.0,0.0 +0,0.890100,0.0,0.0,0.0,0.0,0.0 +0,0.890200,0.0,0.0,0.0,0.0,0.0 +0,0.890300,0.0,0.0,0.0,0.0,0.0 +0,0.890400,0.0,0.0,0.0,0.0,0.0 +0,0.890500,0.0,0.0,0.0,0.0,0.0 +0,0.890600,0.0,0.0,0.0,0.0,0.0 +0,0.890700,0.0,0.0,0.0,0.0,0.0 +0,0.890800,0.0,0.0,0.0,0.0,0.0 +0,0.890900,0.0,0.0,0.0,0.0,0.0 +0,0.891000,0.0,0.0,0.0,0.0,0.0 +0,0.891100,0.0,0.0,0.0,0.0,0.0 +0,0.891200,0.0,0.0,0.0,0.0,0.0 +0,0.891300,0.0,0.0,0.0,0.0,0.0 +0,0.891400,0.0,0.0,0.0,0.0,0.0 +0,0.891500,0.0,0.0,0.0,0.0,0.0 +0,0.891600,0.0,0.0,0.0,0.0,0.0 +0,0.891700,0.0,0.0,0.0,0.0,0.0 +0,0.891800,0.0,0.0,0.0,0.0,0.0 +0,0.891900,0.0,0.0,0.0,0.0,0.0 +0,0.892000,0.0,0.0,0.0,0.0,0.0 +0,0.892100,0.0,0.0,0.0,0.0,0.0 +0,0.892200,0.0,0.0,0.0,0.0,0.0 +0,0.892300,0.0,0.0,0.0,0.0,0.0 +0,0.892400,0.0,0.0,0.0,0.0,0.0 +0,0.892500,0.0,0.0,0.0,0.0,0.0 +0,0.892600,0.0,0.0,0.0,0.0,0.0 +0,0.892700,0.0,0.0,0.0,0.0,0.0 +0,0.892800,0.0,0.0,0.0,0.0,0.0 +0,0.892900,0.0,0.0,0.0,0.0,0.0 +0,0.893000,0.0,0.0,0.0,0.0,0.0 +0,0.893100,0.0,0.0,0.0,0.0,0.0 +0,0.893200,0.0,0.0,0.0,0.0,0.0 +0,0.893300,0.0,0.0,0.0,0.0,0.0 +0,0.893400,0.0,0.0,0.0,0.0,0.0 +0,0.893500,0.0,0.0,0.0,0.0,0.0 +0,0.893600,0.0,0.0,0.0,0.0,0.0 +0,0.893700,0.0,0.0,0.0,0.0,0.0 +0,0.893800,0.0,0.0,0.0,0.0,0.0 +0,0.893900,0.0,0.0,0.0,0.0,0.0 +0,0.894000,0.0,0.0,0.0,0.0,0.0 +0,0.894100,0.0,0.0,0.0,0.0,0.0 +0,0.894200,0.0,0.0,0.0,0.0,0.0 +0,0.894300,0.0,0.0,0.0,0.0,0.0 +0,0.894400,0.0,0.0,0.0,0.0,0.0 +0,0.894500,0.0,0.0,0.0,0.0,0.0 +0,0.894600,0.0,0.0,0.0,0.0,0.0 +0,0.894700,0.0,0.0,0.0,0.0,0.0 +0,0.894800,0.0,0.0,0.0,0.0,0.0 +0,0.894900,0.0,0.0,0.0,0.0,0.0 +0,0.895000,0.0,0.0,0.0,0.0,0.0 +0,0.895100,0.0,0.0,0.0,0.0,0.0 +0,0.895200,0.0,0.0,0.0,0.0,0.0 +0,0.895300,0.0,0.0,0.0,0.0,0.0 +0,0.895400,0.0,0.0,0.0,0.0,0.0 +0,0.895500,0.0,0.0,0.0,0.0,0.0 +0,0.895600,0.0,0.0,0.0,0.0,0.0 +0,0.895700,0.0,0.0,0.0,0.0,0.0 +0,0.895800,0.0,0.0,0.0,0.0,0.0 +0,0.895900,0.0,0.0,0.0,0.0,0.0 +0,0.896000,0.0,0.0,0.0,0.0,0.0 +0,0.896100,0.0,0.0,0.0,0.0,0.0 +0,0.896200,0.0,0.0,0.0,0.0,0.0 +0,0.896300,0.0,0.0,0.0,0.0,0.0 +0,0.896400,0.0,0.0,0.0,0.0,0.0 +0,0.896500,0.0,0.0,0.0,0.0,0.0 +0,0.896600,0.0,0.0,0.0,0.0,0.0 +0,0.896700,0.0,0.0,0.0,0.0,0.0 +0,0.896800,0.0,0.0,0.0,0.0,0.0 +0,0.896900,0.0,0.0,0.0,0.0,0.0 +0,0.897000,0.0,0.0,0.0,0.0,0.0 +0,0.897100,0.0,0.0,0.0,0.0,0.0 +0,0.897200,0.0,0.0,0.0,0.0,0.0 +0,0.897300,0.0,0.0,0.0,0.0,0.0 +0,0.897400,0.0,0.0,0.0,0.0,0.0 +0,0.897500,0.0,0.0,0.0,0.0,0.0 +0,0.897600,0.0,0.0,0.0,0.0,0.0 +0,0.897700,0.0,0.0,0.0,0.0,0.0 +0,0.897800,0.0,0.0,0.0,0.0,0.0 +0,0.897900,0.0,0.0,0.0,0.0,0.0 +0,0.898000,0.0,0.0,0.0,0.0,0.0 +0,0.898100,0.0,0.0,0.0,0.0,0.0 +0,0.898200,0.0,0.0,0.0,0.0,0.0 +0,0.898300,0.0,0.0,0.0,0.0,0.0 +0,0.898400,0.0,0.0,0.0,0.0,0.0 +0,0.898500,0.0,0.0,0.0,0.0,0.0 +0,0.898600,0.0,0.0,0.0,0.0,0.0 +0,0.898700,0.0,0.0,0.0,0.0,0.0 +0,0.898800,0.0,0.0,0.0,0.0,0.0 +0,0.898900,0.0,0.0,0.0,0.0,0.0 +0,0.899000,0.0,0.0,0.0,0.0,0.0 +0,0.899100,0.0,0.0,0.0,0.0,0.0 +0,0.899200,0.0,0.0,0.0,0.0,0.0 +0,0.899300,0.0,0.0,0.0,0.0,0.0 +0,0.899400,0.0,0.0,0.0,0.0,0.0 +0,0.899500,0.0,0.0,0.0,0.0,0.0 +0,0.899600,0.0,0.0,0.0,0.0,0.0 +0,0.899700,0.0,0.0,0.0,0.0,0.0 +0,0.899800,0.0,0.0,0.0,0.0,0.0 +0,0.899900,0.0,0.0,0.0,0.0,0.0 +0,0.900000,0.0,0.0,0.0,0.0,0.0 +0,0.900100,0.0,0.0,0.0,0.0,0.0 +1,303.901899,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.900200,0.0,0.0,0.0,0.0,0.0 +0,0.900300,0.0,0.0,0.0,0.0,0.0 +0,0.900400,0.0,0.0,0.0,0.0,0.0 +0,0.900500,0.0,0.0,0.0,0.0,0.0 +0,0.900600,0.0,0.0,0.0,0.0,0.0 +0,0.900700,0.0,0.0,0.0,0.0,0.0 +0,0.900800,0.0,0.0,0.0,0.0,0.0 +0,0.900900,0.0,0.0,0.0,0.0,0.0 +0,0.901000,0.0,0.0,0.0,0.0,0.0 +0,0.901100,0.0,0.0,0.0,0.0,0.0 +0,0.901200,0.0,0.0,0.0,0.0,0.0 +0,0.901300,0.0,0.0,0.0,0.0,0.0 +0,0.901400,0.0,0.0,0.0,0.0,0.0 +0,0.901500,0.0,0.0,0.0,0.0,0.0 +0,0.901600,0.0,0.0,0.0,0.0,0.0 +0,0.901700,0.0,0.0,0.0,0.0,0.0 +0,0.901800,0.0,0.0,0.0,0.0,0.0 +0,0.901900,0.0,0.0,0.0,0.0,0.0 +0,0.902000,0.0,0.0,0.0,0.0,0.0 +0,0.902100,0.0,0.0,0.0,0.0,0.0 +0,0.902200,0.0,0.0,0.0,0.0,0.0 +0,0.902300,0.0,0.0,0.0,0.0,0.0 +0,0.902400,0.0,0.0,0.0,0.0,0.0 +0,0.902500,0.0,0.0,0.0,0.0,0.0 +0,0.902600,0.0,0.0,0.0,0.0,0.0 +0,0.902700,0.0,0.0,0.0,0.0,0.0 +0,0.902800,0.0,0.0,0.0,0.0,0.0 +0,0.902900,0.0,0.0,0.0,0.0,0.0 +0,0.903000,0.0,0.0,0.0,0.0,0.0 +0,0.903100,0.0,0.0,0.0,0.0,0.0 +0,0.903200,0.0,0.0,0.0,0.0,0.0 +0,0.903300,0.0,0.0,0.0,0.0,0.0 +0,0.903400,0.0,0.0,0.0,0.0,0.0 +0,0.903500,0.0,0.0,0.0,0.0,0.0 +0,0.903600,0.0,0.0,0.0,0.0,0.0 +0,0.903700,0.0,0.0,0.0,0.0,0.0 +0,0.903800,0.0,0.0,0.0,0.0,0.0 +0,0.903900,0.0,0.0,0.0,0.0,0.0 +0,0.904000,0.0,0.0,0.0,0.0,0.0 +0,0.904100,0.0,0.0,0.0,0.0,0.0 +0,0.904200,0.0,0.0,0.0,0.0,0.0 +0,0.904300,0.0,0.0,0.0,0.0,0.0 +0,0.904400,0.0,0.0,0.0,0.0,0.0 +0,0.904500,0.0,0.0,0.0,0.0,0.0 +0,0.904600,0.0,0.0,0.0,0.0,0.0 +0,0.904700,0.0,0.0,0.0,0.0,0.0 +0,0.904800,0.0,0.0,0.0,0.0,0.0 +0,0.904900,0.0,0.0,0.0,0.0,0.0 +0,0.905000,0.0,0.0,0.0,0.0,0.0 +0,0.905100,0.0,0.0,0.0,0.0,0.0 +0,0.905200,0.0,0.0,0.0,0.0,0.0 +0,0.905300,0.0,0.0,0.0,0.0,0.0 +0,0.905400,0.0,0.0,0.0,0.0,0.0 +0,0.905500,0.0,0.0,0.0,0.0,0.0 +0,0.905600,0.0,0.0,0.0,0.0,0.0 +0,0.905700,0.0,0.0,0.0,0.0,0.0 +0,0.905800,0.0,0.0,0.0,0.0,0.0 +0,0.905900,0.0,0.0,0.0,0.0,0.0 +0,0.906000,0.0,0.0,0.0,0.0,0.0 +0,0.906100,0.0,0.0,0.0,0.0,0.0 +0,0.906200,0.0,0.0,0.0,0.0,0.0 +0,0.906300,0.0,0.0,0.0,0.0,0.0 +0,0.906400,0.0,0.0,0.0,0.0,0.0 +0,0.906500,0.0,0.0,0.0,0.0,0.0 +0,0.906600,0.0,0.0,0.0,0.0,0.0 +0,0.906700,0.0,0.0,0.0,0.0,0.0 +0,0.906800,0.0,0.0,0.0,0.0,0.0 +0,0.906900,0.0,0.0,0.0,0.0,0.0 +0,0.907000,0.0,0.0,0.0,0.0,0.0 +0,0.907100,0.0,0.0,0.0,0.0,0.0 +0,0.907200,0.0,0.0,0.0,0.0,0.0 +0,0.907300,0.0,0.0,0.0,0.0,0.0 +0,0.907400,0.0,0.0,0.0,0.0,0.0 +0,0.907500,0.0,0.0,0.0,0.0,0.0 +0,0.907600,0.0,0.0,0.0,0.0,0.0 +0,0.907700,0.0,0.0,0.0,0.0,0.0 +0,0.907800,0.0,0.0,0.0,0.0,0.0 +0,0.907900,0.0,0.0,0.0,0.0,0.0 +0,0.908000,0.0,0.0,0.0,0.0,0.0 +0,0.908100,0.0,0.0,0.0,0.0,0.0 +0,0.908200,0.0,0.0,0.0,0.0,0.0 +0,0.908300,0.0,0.0,0.0,0.0,0.0 +0,0.908400,0.0,0.0,0.0,0.0,0.0 +0,0.908500,0.0,0.0,0.0,0.0,0.0 +0,0.908600,0.0,0.0,0.0,0.0,0.0 +0,0.908700,0.0,0.0,0.0,0.0,0.0 +0,0.908800,0.0,0.0,0.0,0.0,0.0 +0,0.908900,0.0,0.0,0.0,0.0,0.0 +0,0.909000,0.0,0.0,0.0,0.0,0.0 +0,0.909100,0.0,0.0,0.0,0.0,0.0 +0,0.909200,0.0,0.0,0.0,0.0,0.0 +0,0.909300,0.0,0.0,0.0,0.0,0.0 +0,0.909400,0.0,0.0,0.0,0.0,0.0 +0,0.909500,0.0,0.0,0.0,0.0,0.0 +0,0.909600,0.0,0.0,0.0,0.0,0.0 +0,0.909700,0.0,0.0,0.0,0.0,0.0 +0,0.909800,0.0,0.0,0.0,0.0,0.0 +0,0.909900,0.0,0.0,0.0,0.0,0.0 +0,0.910000,0.0,0.0,0.0,0.0,0.0 +0,0.910100,0.0,0.0,0.0,0.0,0.0 +0,0.910200,0.0,0.0,0.0,0.0,0.0 +0,0.910300,0.0,0.0,0.0,0.0,0.0 +0,0.910400,0.0,0.0,0.0,0.0,0.0 +0,0.910500,0.0,0.0,0.0,0.0,0.0 +0,0.910600,0.0,0.0,0.0,0.0,0.0 +0,0.910700,0.0,0.0,0.0,0.0,0.0 +0,0.910800,0.0,0.0,0.0,0.0,0.0 +0,0.910900,0.0,0.0,0.0,0.0,0.0 +0,0.911000,0.0,0.0,0.0,0.0,0.0 +0,0.911100,0.0,0.0,0.0,0.0,0.0 +0,0.911200,0.0,0.0,0.0,0.0,0.0 +0,0.911300,0.0,0.0,0.0,0.0,0.0 +0,0.911400,0.0,0.0,0.0,0.0,0.0 +0,0.911500,0.0,0.0,0.0,0.0,0.0 +0,0.911600,0.0,0.0,0.0,0.0,0.0 +0,0.911700,0.0,0.0,0.0,0.0,0.0 +0,0.911800,0.0,0.0,0.0,0.0,0.0 +0,0.911900,0.0,0.0,0.0,0.0,0.0 +0,0.912000,0.0,0.0,0.0,0.0,0.0 +0,0.912100,0.0,0.0,0.0,0.0,0.0 +0,0.912200,0.0,0.0,0.0,0.0,0.0 +0,0.912300,0.0,0.0,0.0,0.0,0.0 +0,0.912400,0.0,0.0,0.0,0.0,0.0 +0,0.912500,0.0,0.0,0.0,0.0,0.0 +0,0.912600,0.0,0.0,0.0,0.0,0.0 +0,0.912700,0.0,0.0,0.0,0.0,0.0 +0,0.912800,0.0,0.0,0.0,0.0,0.0 +0,0.912900,0.0,0.0,0.0,0.0,0.0 +0,0.913000,0.0,0.0,0.0,0.0,0.0 +0,0.913100,0.0,0.0,0.0,0.0,0.0 +0,0.913200,0.0,0.0,0.0,0.0,0.0 +0,0.913300,0.0,0.0,0.0,0.0,0.0 +0,0.913400,0.0,0.0,0.0,0.0,0.0 +0,0.913500,0.0,0.0,0.0,0.0,0.0 +0,0.913600,0.0,0.0,0.0,0.0,0.0 +0,0.913700,0.0,0.0,0.0,0.0,0.0 +0,0.913800,0.0,0.0,0.0,0.0,0.0 +0,0.913900,0.0,0.0,0.0,0.0,0.0 +0,0.914000,0.0,0.0,0.0,0.0,0.0 +0,0.914100,0.0,0.0,0.0,0.0,0.0 +0,0.914200,0.0,0.0,0.0,0.0,0.0 +0,0.914300,0.0,0.0,0.0,0.0,0.0 +0,0.914400,0.0,0.0,0.0,0.0,0.0 +0,0.914500,0.0,0.0,0.0,0.0,0.0 +0,0.914600,0.0,0.0,0.0,0.0,0.0 +0,0.914700,0.0,0.0,0.0,0.0,0.0 +0,0.914800,0.0,0.0,0.0,0.0,0.0 +0,0.914900,0.0,0.0,0.0,0.0,0.0 +0,0.915000,0.0,0.0,0.0,0.0,0.0 +0,0.915100,0.0,0.0,0.0,0.0,0.0 +0,0.915200,0.0,0.0,0.0,0.0,0.0 +0,0.915300,0.0,0.0,0.0,0.0,0.0 +0,0.915400,0.0,0.0,0.0,0.0,0.0 +0,0.915500,0.0,0.0,0.0,0.0,0.0 +0,0.915600,0.0,0.0,0.0,0.0,0.0 +0,0.915700,0.0,0.0,0.0,0.0,0.0 +0,0.915800,0.0,0.0,0.0,0.0,0.0 +0,0.915900,0.0,0.0,0.0,0.0,0.0 +0,0.916000,0.0,0.0,0.0,0.0,0.0 +0,0.916100,0.0,0.0,0.0,0.0,0.0 +0,0.916200,0.0,0.0,0.0,0.0,0.0 +0,0.916300,0.0,0.0,0.0,0.0,0.0 +0,0.916400,0.0,0.0,0.0,0.0,0.0 +0,0.916500,0.0,0.0,0.0,0.0,0.0 +0,0.916600,0.0,0.0,0.0,0.0,0.0 +0,0.916700,0.0,0.0,0.0,0.0,0.0 +0,0.916800,0.0,0.0,0.0,0.0,0.0 +0,0.916900,0.0,0.0,0.0,0.0,0.0 +0,0.917000,0.0,0.0,0.0,0.0,0.0 +0,0.917100,0.0,0.0,0.0,0.0,0.0 +0,0.917200,0.0,0.0,0.0,0.0,0.0 +0,0.917300,0.0,0.0,0.0,0.0,0.0 +0,0.917400,0.0,0.0,0.0,0.0,0.0 +0,0.917500,0.0,0.0,0.0,0.0,0.0 +0,0.917600,0.0,0.0,0.0,0.0,0.0 +0,0.917700,0.0,0.0,0.0,0.0,0.0 +0,0.917800,0.0,0.0,0.0,0.0,0.0 +0,0.917900,0.0,0.0,0.0,0.0,0.0 +0,0.918000,0.0,0.0,0.0,0.0,0.0 +0,0.918100,0.0,0.0,0.0,0.0,0.0 +0,0.918200,0.0,0.0,0.0,0.0,0.0 +0,0.918300,0.0,0.0,0.0,0.0,0.0 +0,0.918400,0.0,0.0,0.0,0.0,0.0 +0,0.918500,0.0,0.0,0.0,0.0,0.0 +0,0.918600,0.0,0.0,0.0,0.0,0.0 +0,0.918700,0.0,0.0,0.0,0.0,0.0 +0,0.918800,0.0,0.0,0.0,0.0,0.0 +0,0.918900,0.0,0.0,0.0,0.0,0.0 +0,0.919000,0.0,0.0,0.0,0.0,0.0 +0,0.919100,0.0,0.0,0.0,0.0,0.0 +0,0.919200,0.0,0.0,0.0,0.0,0.0 +0,0.919300,0.0,0.0,0.0,0.0,0.0 +0,0.919400,0.0,0.0,0.0,0.0,0.0 +0,0.919500,0.0,0.0,0.0,0.0,0.0 +0,0.919600,0.0,0.0,0.0,0.0,0.0 +0,0.919700,0.0,0.0,0.0,0.0,0.0 +0,0.919800,0.0,0.0,0.0,0.0,0.0 +0,0.919900,0.0,0.0,0.0,0.0,0.0 +0,0.920000,0.0,0.0,0.0,0.0,0.0 +0,0.920100,0.0,0.0,0.0,0.0,0.0 +1,324.612058,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.920200,0.0,0.0,0.0,0.0,0.0 +0,0.920300,0.0,0.0,0.0,0.0,0.0 +0,0.920400,0.0,0.0,0.0,0.0,0.0 +0,0.920500,0.0,0.0,0.0,0.0,0.0 +0,0.920600,0.0,0.0,0.0,0.0,0.0 +0,0.920700,0.0,0.0,0.0,0.0,0.0 +0,0.920800,0.0,0.0,0.0,0.0,0.0 +0,0.920900,0.0,0.0,0.0,0.0,0.0 +0,0.921000,0.0,0.0,0.0,0.0,0.0 +0,0.921100,0.0,0.0,0.0,0.0,0.0 +0,0.921200,0.0,0.0,0.0,0.0,0.0 +0,0.921300,0.0,0.0,0.0,0.0,0.0 +0,0.921400,0.0,0.0,0.0,0.0,0.0 +0,0.921500,0.0,0.0,0.0,0.0,0.0 +0,0.921600,0.0,0.0,0.0,0.0,0.0 +0,0.921700,0.0,0.0,0.0,0.0,0.0 +0,0.921800,0.0,0.0,0.0,0.0,0.0 +0,0.921900,0.0,0.0,0.0,0.0,0.0 +0,0.922000,0.0,0.0,0.0,0.0,0.0 +0,0.922100,0.0,0.0,0.0,0.0,0.0 +0,0.922200,0.0,0.0,0.0,0.0,0.0 +0,0.922300,0.0,0.0,0.0,0.0,0.0 +0,0.922400,0.0,0.0,0.0,0.0,0.0 +0,0.922500,0.0,0.0,0.0,0.0,0.0 +0,0.922600,0.0,0.0,0.0,0.0,0.0 +0,0.922700,0.0,0.0,0.0,0.0,0.0 +0,0.922800,0.0,0.0,0.0,0.0,0.0 +0,0.922900,0.0,0.0,0.0,0.0,0.0 +0,0.923000,0.0,0.0,0.0,0.0,0.0 +0,0.923100,0.0,0.0,0.0,0.0,0.0 +0,0.923200,0.0,0.0,0.0,0.0,0.0 +0,0.923300,0.0,0.0,0.0,0.0,0.0 +0,0.923400,0.0,0.0,0.0,0.0,0.0 +0,0.923500,0.0,0.0,0.0,0.0,0.0 +0,0.923600,0.0,0.0,0.0,0.0,0.0 +0,0.923700,0.0,0.0,0.0,0.0,0.0 +0,0.923800,0.0,0.0,0.0,0.0,0.0 +0,0.923900,0.0,0.0,0.0,0.0,0.0 +0,0.924000,0.0,0.0,0.0,0.0,0.0 +0,0.924100,0.0,0.0,0.0,0.0,0.0 +0,0.924200,0.0,0.0,0.0,0.0,0.0 +0,0.924300,0.0,0.0,0.0,0.0,0.0 +0,0.924400,0.0,0.0,0.0,0.0,0.0 +0,0.924500,0.0,0.0,0.0,0.0,0.0 +0,0.924600,0.0,0.0,0.0,0.0,0.0 +0,0.924700,0.0,0.0,0.0,0.0,0.0 +0,0.924800,0.0,0.0,0.0,0.0,0.0 +0,0.924900,0.0,0.0,0.0,0.0,0.0 +0,0.925000,0.0,0.0,0.0,0.0,0.0 +0,0.925100,0.0,0.0,0.0,0.0,0.0 +0,0.925200,0.0,0.0,0.0,0.0,0.0 +0,0.925300,0.0,0.0,0.0,0.0,0.0 +0,0.925400,0.0,0.0,0.0,0.0,0.0 +0,0.925500,0.0,0.0,0.0,0.0,0.0 +0,0.925600,0.0,0.0,0.0,0.0,0.0 +0,0.925700,0.0,0.0,0.0,0.0,0.0 +0,0.925800,0.0,0.0,0.0,0.0,0.0 +0,0.925900,0.0,0.0,0.0,0.0,0.0 +0,0.926000,0.0,0.0,0.0,0.0,0.0 +0,0.926100,0.0,0.0,0.0,0.0,0.0 +0,0.926200,0.0,0.0,0.0,0.0,0.0 +0,0.926300,0.0,0.0,0.0,0.0,0.0 +0,0.926400,0.0,0.0,0.0,0.0,0.0 +0,0.926500,0.0,0.0,0.0,0.0,0.0 +0,0.926600,0.0,0.0,0.0,0.0,0.0 +0,0.926700,0.0,0.0,0.0,0.0,0.0 +0,0.926800,0.0,0.0,0.0,0.0,0.0 +0,0.926900,0.0,0.0,0.0,0.0,0.0 +0,0.927000,0.0,0.0,0.0,0.0,0.0 +0,0.927100,0.0,0.0,0.0,0.0,0.0 +0,0.927200,0.0,0.0,0.0,0.0,0.0 +0,0.927300,0.0,0.0,0.0,0.0,0.0 +0,0.927400,0.0,0.0,0.0,0.0,0.0 +0,0.927500,0.0,0.0,0.0,0.0,0.0 +0,0.927600,0.0,0.0,0.0,0.0,0.0 +0,0.927700,0.0,0.0,0.0,0.0,0.0 +0,0.927800,0.0,0.0,0.0,0.0,0.0 +0,0.927900,0.0,0.0,0.0,0.0,0.0 +0,0.928000,0.0,0.0,0.0,0.0,0.0 +0,0.928100,0.0,0.0,0.0,0.0,0.0 +0,0.928200,0.0,0.0,0.0,0.0,0.0 +0,0.928300,0.0,0.0,0.0,0.0,0.0 +0,0.928400,0.0,0.0,0.0,0.0,0.0 +0,0.928500,0.0,0.0,0.0,0.0,0.0 +0,0.928600,0.0,0.0,0.0,0.0,0.0 +0,0.928700,0.0,0.0,0.0,0.0,0.0 +0,0.928800,0.0,0.0,0.0,0.0,0.0 +0,0.928900,0.0,0.0,0.0,0.0,0.0 +0,0.929000,0.0,0.0,0.0,0.0,0.0 +0,0.929100,0.0,0.0,0.0,0.0,0.0 +0,0.929200,0.0,0.0,0.0,0.0,0.0 +0,0.929300,0.0,0.0,0.0,0.0,0.0 +0,0.929400,0.0,0.0,0.0,0.0,0.0 +0,0.929500,0.0,0.0,0.0,0.0,0.0 +0,0.929600,0.0,0.0,0.0,0.0,0.0 +0,0.929700,0.0,0.0,0.0,0.0,0.0 +0,0.929800,0.0,0.0,0.0,0.0,0.0 +0,0.929900,0.0,0.0,0.0,0.0,0.0 +0,0.930000,0.0,0.0,0.0,0.0,0.0 +0,0.930100,0.0,0.0,0.0,0.0,0.0 +0,0.930200,0.0,0.0,0.0,0.0,0.0 +0,0.930300,0.0,0.0,0.0,0.0,0.0 +0,0.930400,0.0,0.0,0.0,0.0,0.0 +0,0.930500,0.0,0.0,0.0,0.0,0.0 +0,0.930600,0.0,0.0,0.0,0.0,0.0 +0,0.930700,0.0,0.0,0.0,0.0,0.0 +0,0.930800,0.0,0.0,0.0,0.0,0.0 +0,0.930900,0.0,0.0,0.0,0.0,0.0 +0,0.931000,0.0,0.0,0.0,0.0,0.0 +0,0.931100,0.0,0.0,0.0,0.0,0.0 +0,0.931200,0.0,0.0,0.0,0.0,0.0 +0,0.931300,0.0,0.0,0.0,0.0,0.0 +0,0.931400,0.0,0.0,0.0,0.0,0.0 +0,0.931500,0.0,0.0,0.0,0.0,0.0 +0,0.931600,0.0,0.0,0.0,0.0,0.0 +0,0.931700,0.0,0.0,0.0,0.0,0.0 +0,0.931800,0.0,0.0,0.0,0.0,0.0 +0,0.931900,0.0,0.0,0.0,0.0,0.0 +0,0.932000,0.0,0.0,0.0,0.0,0.0 +0,0.932100,0.0,0.0,0.0,0.0,0.0 +0,0.932200,0.0,0.0,0.0,0.0,0.0 +0,0.932300,0.0,0.0,0.0,0.0,0.0 +0,0.932400,0.0,0.0,0.0,0.0,0.0 +0,0.932500,0.0,0.0,0.0,0.0,0.0 +0,0.932600,0.0,0.0,0.0,0.0,0.0 +0,0.932700,0.0,0.0,0.0,0.0,0.0 +0,0.932800,0.0,0.0,0.0,0.0,0.0 +0,0.932900,0.0,0.0,0.0,0.0,0.0 +0,0.933000,0.0,0.0,0.0,0.0,0.0 +0,0.933100,0.0,0.0,0.0,0.0,0.0 +0,0.933200,0.0,0.0,0.0,0.0,0.0 +0,0.933300,0.0,0.0,0.0,0.0,0.0 +0,0.933400,0.0,0.0,0.0,0.0,0.0 +0,0.933500,0.0,0.0,0.0,0.0,0.0 +0,0.933600,0.0,0.0,0.0,0.0,0.0 +0,0.933700,0.0,0.0,0.0,0.0,0.0 +0,0.933800,0.0,0.0,0.0,0.0,0.0 +0,0.933900,0.0,0.0,0.0,0.0,0.0 +0,0.934000,0.0,0.0,0.0,0.0,0.0 +0,0.934100,0.0,0.0,0.0,0.0,0.0 +0,0.934200,0.0,0.0,0.0,0.0,0.0 +0,0.934300,0.0,0.0,0.0,0.0,0.0 +0,0.934400,0.0,0.0,0.0,0.0,0.0 +0,0.934500,0.0,0.0,0.0,0.0,0.0 +0,0.934600,0.0,0.0,0.0,0.0,0.0 +0,0.934700,0.0,0.0,0.0,0.0,0.0 +0,0.934800,0.0,0.0,0.0,0.0,0.0 +0,0.934900,0.0,0.0,0.0,0.0,0.0 +0,0.935000,0.0,0.0,0.0,0.0,0.0 +0,0.935100,0.0,0.0,0.0,0.0,0.0 +0,0.935200,0.0,0.0,0.0,0.0,0.0 +0,0.935300,0.0,0.0,0.0,0.0,0.0 +0,0.935400,0.0,0.0,0.0,0.0,0.0 +0,0.935500,0.0,0.0,0.0,0.0,0.0 +0,0.935600,0.0,0.0,0.0,0.0,0.0 +0,0.935700,0.0,0.0,0.0,0.0,0.0 +0,0.935800,0.0,0.0,0.0,0.0,0.0 +0,0.935900,0.0,0.0,0.0,0.0,0.0 +0,0.936000,0.0,0.0,0.0,0.0,0.0 +0,0.936100,0.0,0.0,0.0,0.0,0.0 +0,0.936200,0.0,0.0,0.0,0.0,0.0 +0,0.936300,0.0,0.0,0.0,0.0,0.0 +0,0.936400,0.0,0.0,0.0,0.0,0.0 +0,0.936500,0.0,0.0,0.0,0.0,0.0 +0,0.936600,0.0,0.0,0.0,0.0,0.0 +0,0.936700,0.0,0.0,0.0,0.0,0.0 +0,0.936800,0.0,0.0,0.0,0.0,0.0 +0,0.936900,0.0,0.0,0.0,0.0,0.0 +0,0.937000,0.0,0.0,0.0,0.0,0.0 +0,0.937100,0.0,0.0,0.0,0.0,0.0 +0,0.937200,0.0,0.0,0.0,0.0,0.0 +0,0.937300,0.0,0.0,0.0,0.0,0.0 +0,0.937400,0.0,0.0,0.0,0.0,0.0 +0,0.937500,0.0,0.0,0.0,0.0,0.0 +0,0.937600,0.0,0.0,0.0,0.0,0.0 +0,0.937700,0.0,0.0,0.0,0.0,0.0 +0,0.937800,0.0,0.0,0.0,0.0,0.0 +0,0.937900,0.0,0.0,0.0,0.0,0.0 +0,0.938000,0.0,0.0,0.0,0.0,0.0 +0,0.938100,0.0,0.0,0.0,0.0,0.0 +0,0.938200,0.0,0.0,0.0,0.0,0.0 +0,0.938300,0.0,0.0,0.0,0.0,0.0 +0,0.938400,0.0,0.0,0.0,0.0,0.0 +0,0.938500,0.0,0.0,0.0,0.0,0.0 +0,0.938600,0.0,0.0,0.0,0.0,0.0 +0,0.938700,0.0,0.0,0.0,0.0,0.0 +0,0.938800,0.0,0.0,0.0,0.0,0.0 +0,0.938900,0.0,0.0,0.0,0.0,0.0 +0,0.939000,0.0,0.0,0.0,0.0,0.0 +0,0.939100,0.0,0.0,0.0,0.0,0.0 +0,0.939200,0.0,0.0,0.0,0.0,0.0 +0,0.939300,0.0,0.0,0.0,0.0,0.0 +0,0.939400,0.0,0.0,0.0,0.0,0.0 +0,0.939500,0.0,0.0,0.0,0.0,0.0 +0,0.939600,0.0,0.0,0.0,0.0,0.0 +0,0.939700,0.0,0.0,0.0,0.0,0.0 +0,0.939800,0.0,0.0,0.0,0.0,0.0 +0,0.939900,0.0,0.0,0.0,0.0,0.0 +0,0.940000,0.0,0.0,0.0,0.0,0.0 +0,0.940100,0.0,0.0,0.0,0.0,0.0 +1,346.242367,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.940200,0.0,0.0,0.0,0.0,0.0 +0,0.940300,0.0,0.0,0.0,0.0,0.0 +0,0.940400,0.0,0.0,0.0,0.0,0.0 +0,0.940500,0.0,0.0,0.0,0.0,0.0 +0,0.940600,0.0,0.0,0.0,0.0,0.0 +0,0.940700,0.0,0.0,0.0,0.0,0.0 +0,0.940800,0.0,0.0,0.0,0.0,0.0 +0,0.940900,0.0,0.0,0.0,0.0,0.0 +0,0.941000,0.0,0.0,0.0,0.0,0.0 +0,0.941100,0.0,0.0,0.0,0.0,0.0 +0,0.941200,0.0,0.0,0.0,0.0,0.0 +0,0.941300,0.0,0.0,0.0,0.0,0.0 +0,0.941400,0.0,0.0,0.0,0.0,0.0 +0,0.941500,0.0,0.0,0.0,0.0,0.0 +0,0.941600,0.0,0.0,0.0,0.0,0.0 +0,0.941700,0.0,0.0,0.0,0.0,0.0 +0,0.941800,0.0,0.0,0.0,0.0,0.0 +0,0.941900,0.0,0.0,0.0,0.0,0.0 +0,0.942000,0.0,0.0,0.0,0.0,0.0 +0,0.942100,0.0,0.0,0.0,0.0,0.0 +0,0.942200,0.0,0.0,0.0,0.0,0.0 +0,0.942300,0.0,0.0,0.0,0.0,0.0 +0,0.942400,0.0,0.0,0.0,0.0,0.0 +0,0.942500,0.0,0.0,0.0,0.0,0.0 +0,0.942600,0.0,0.0,0.0,0.0,0.0 +0,0.942700,0.0,0.0,0.0,0.0,0.0 +0,0.942800,0.0,0.0,0.0,0.0,0.0 +0,0.942900,0.0,0.0,0.0,0.0,0.0 +0,0.943000,0.0,0.0,0.0,0.0,0.0 +0,0.943100,0.0,0.0,0.0,0.0,0.0 +0,0.943200,0.0,0.0,0.0,0.0,0.0 +0,0.943300,0.0,0.0,0.0,0.0,0.0 +0,0.943400,0.0,0.0,0.0,0.0,0.0 +0,0.943500,0.0,0.0,0.0,0.0,0.0 +0,0.943600,0.0,0.0,0.0,0.0,0.0 +0,0.943700,0.0,0.0,0.0,0.0,0.0 +0,0.943800,0.0,0.0,0.0,0.0,0.0 +0,0.943900,0.0,0.0,0.0,0.0,0.0 +0,0.944000,0.0,0.0,0.0,0.0,0.0 +0,0.944100,0.0,0.0,0.0,0.0,0.0 +0,0.944200,0.0,0.0,0.0,0.0,0.0 +0,0.944300,0.0,0.0,0.0,0.0,0.0 +0,0.944400,0.0,0.0,0.0,0.0,0.0 +0,0.944500,0.0,0.0,0.0,0.0,0.0 +0,0.944600,0.0,0.0,0.0,0.0,0.0 +0,0.944700,0.0,0.0,0.0,0.0,0.0 +0,0.944800,0.0,0.0,0.0,0.0,0.0 +0,0.944900,0.0,0.0,0.0,0.0,0.0 +0,0.945000,0.0,0.0,0.0,0.0,0.0 +0,0.945100,0.0,0.0,0.0,0.0,0.0 +0,0.945200,0.0,0.0,0.0,0.0,0.0 +0,0.945300,0.0,0.0,0.0,0.0,0.0 +0,0.945400,0.0,0.0,0.0,0.0,0.0 +0,0.945500,0.0,0.0,0.0,0.0,0.0 +0,0.945600,0.0,0.0,0.0,0.0,0.0 +0,0.945700,0.0,0.0,0.0,0.0,0.0 +0,0.945800,0.0,0.0,0.0,0.0,0.0 +0,0.945900,0.0,0.0,0.0,0.0,0.0 +0,0.946000,0.0,0.0,0.0,0.0,0.0 +0,0.946100,0.0,0.0,0.0,0.0,0.0 +0,0.946200,0.0,0.0,0.0,0.0,0.0 +0,0.946300,0.0,0.0,0.0,0.0,0.0 +0,0.946400,0.0,0.0,0.0,0.0,0.0 +0,0.946500,0.0,0.0,0.0,0.0,0.0 +0,0.946600,0.0,0.0,0.0,0.0,0.0 +0,0.946700,0.0,0.0,0.0,0.0,0.0 +0,0.946800,0.0,0.0,0.0,0.0,0.0 +0,0.946900,0.0,0.0,0.0,0.0,0.0 +0,0.947000,0.0,0.0,0.0,0.0,0.0 +0,0.947100,0.0,0.0,0.0,0.0,0.0 +0,0.947200,0.0,0.0,0.0,0.0,0.0 +0,0.947300,0.0,0.0,0.0,0.0,0.0 +0,0.947400,0.0,0.0,0.0,0.0,0.0 +0,0.947500,0.0,0.0,0.0,0.0,0.0 +0,0.947600,0.0,0.0,0.0,0.0,0.0 +0,0.947700,0.0,0.0,0.0,0.0,0.0 +0,0.947800,0.0,0.0,0.0,0.0,0.0 +0,0.947900,0.0,0.0,0.0,0.0,0.0 +0,0.948000,0.0,0.0,0.0,0.0,0.0 +0,0.948100,0.0,0.0,0.0,0.0,0.0 +0,0.948200,0.0,0.0,0.0,0.0,0.0 +0,0.948300,0.0,0.0,0.0,0.0,0.0 +0,0.948400,0.0,0.0,0.0,0.0,0.0 +0,0.948500,0.0,0.0,0.0,0.0,0.0 +0,0.948600,0.0,0.0,0.0,0.0,0.0 +0,0.948700,0.0,0.0,0.0,0.0,0.0 +0,0.948800,0.0,0.0,0.0,0.0,0.0 +0,0.948900,0.0,0.0,0.0,0.0,0.0 +0,0.949000,0.0,0.0,0.0,0.0,0.0 +0,0.949100,0.0,0.0,0.0,0.0,0.0 +0,0.949200,0.0,0.0,0.0,0.0,0.0 +0,0.949300,0.0,0.0,0.0,0.0,0.0 +0,0.949400,0.0,0.0,0.0,0.0,0.0 +0,0.949500,0.0,0.0,0.0,0.0,0.0 +0,0.949600,0.0,0.0,0.0,0.0,0.0 +0,0.949700,0.0,0.0,0.0,0.0,0.0 +0,0.949800,0.0,0.0,0.0,0.0,0.0 +0,0.949900,0.0,0.0,0.0,0.0,0.0 +0,0.950000,0.0,0.0,0.0,0.0,0.0 +0,0.950100,0.0,0.0,0.0,0.0,0.0 +0,0.950200,0.0,0.0,0.0,0.0,0.0 +0,0.950300,0.0,0.0,0.0,0.0,0.0 +0,0.950400,0.0,0.0,0.0,0.0,0.0 +0,0.950500,0.0,0.0,0.0,0.0,0.0 +0,0.950600,0.0,0.0,0.0,0.0,0.0 +0,0.950700,0.0,0.0,0.0,0.0,0.0 +0,0.950800,0.0,0.0,0.0,0.0,0.0 +0,0.950900,0.0,0.0,0.0,0.0,0.0 +0,0.951000,0.0,0.0,0.0,0.0,0.0 +0,0.951100,0.0,0.0,0.0,0.0,0.0 +0,0.951200,0.0,0.0,0.0,0.0,0.0 +0,0.951300,0.0,0.0,0.0,0.0,0.0 +0,0.951400,0.0,0.0,0.0,0.0,0.0 +0,0.951500,0.0,0.0,0.0,0.0,0.0 +0,0.951600,0.0,0.0,0.0,0.0,0.0 +0,0.951700,0.0,0.0,0.0,0.0,0.0 +0,0.951800,0.0,0.0,0.0,0.0,0.0 +0,0.951900,0.0,0.0,0.0,0.0,0.0 +0,0.952000,0.0,0.0,0.0,0.0,0.0 +0,0.952100,0.0,0.0,0.0,0.0,0.0 +0,0.952200,0.0,0.0,0.0,0.0,0.0 +0,0.952300,0.0,0.0,0.0,0.0,0.0 +0,0.952400,0.0,0.0,0.0,0.0,0.0 +0,0.952500,0.0,0.0,0.0,0.0,0.0 +0,0.952600,0.0,0.0,0.0,0.0,0.0 +0,0.952700,0.0,0.0,0.0,0.0,0.0 +0,0.952800,0.0,0.0,0.0,0.0,0.0 +0,0.952900,0.0,0.0,0.0,0.0,0.0 +0,0.953000,0.0,0.0,0.0,0.0,0.0 +0,0.953100,0.0,0.0,0.0,0.0,0.0 +0,0.953200,0.0,0.0,0.0,0.0,0.0 +0,0.953300,0.0,0.0,0.0,0.0,0.0 +0,0.953400,0.0,0.0,0.0,0.0,0.0 +0,0.953500,0.0,0.0,0.0,0.0,0.0 +0,0.953600,0.0,0.0,0.0,0.0,0.0 +0,0.953700,0.0,0.0,0.0,0.0,0.0 +0,0.953800,0.0,0.0,0.0,0.0,0.0 +0,0.953900,0.0,0.0,0.0,0.0,0.0 +0,0.954000,0.0,0.0,0.0,0.0,0.0 +0,0.954100,0.0,0.0,0.0,0.0,0.0 +0,0.954200,0.0,0.0,0.0,0.0,0.0 +0,0.954300,0.0,0.0,0.0,0.0,0.0 +0,0.954400,0.0,0.0,0.0,0.0,0.0 +0,0.954500,0.0,0.0,0.0,0.0,0.0 +0,0.954600,0.0,0.0,0.0,0.0,0.0 +0,0.954700,0.0,0.0,0.0,0.0,0.0 +0,0.954800,0.0,0.0,0.0,0.0,0.0 +0,0.954900,0.0,0.0,0.0,0.0,0.0 +0,0.955000,0.0,0.0,0.0,0.0,0.0 +0,0.955100,0.0,0.0,0.0,0.0,0.0 +0,0.955200,0.0,0.0,0.0,0.0,0.0 +0,0.955300,0.0,0.0,0.0,0.0,0.0 +0,0.955400,0.0,0.0,0.0,0.0,0.0 +0,0.955500,0.0,0.0,0.0,0.0,0.0 +0,0.955600,0.0,0.0,0.0,0.0,0.0 +0,0.955700,0.0,0.0,0.0,0.0,0.0 +0,0.955800,0.0,0.0,0.0,0.0,0.0 +0,0.955900,0.0,0.0,0.0,0.0,0.0 +0,0.956000,0.0,0.0,0.0,0.0,0.0 +0,0.956100,0.0,0.0,0.0,0.0,0.0 +0,0.956200,0.0,0.0,0.0,0.0,0.0 +0,0.956300,0.0,0.0,0.0,0.0,0.0 +0,0.956400,0.0,0.0,0.0,0.0,0.0 +0,0.956500,0.0,0.0,0.0,0.0,0.0 +0,0.956600,0.0,0.0,0.0,0.0,0.0 +0,0.956700,0.0,0.0,0.0,0.0,0.0 +0,0.956800,0.0,0.0,0.0,0.0,0.0 +0,0.956900,0.0,0.0,0.0,0.0,0.0 +0,0.957000,0.0,0.0,0.0,0.0,0.0 +0,0.957100,0.0,0.0,0.0,0.0,0.0 +0,0.957200,0.0,0.0,0.0,0.0,0.0 +0,0.957300,0.0,0.0,0.0,0.0,0.0 +0,0.957400,0.0,0.0,0.0,0.0,0.0 +0,0.957500,0.0,0.0,0.0,0.0,0.0 +0,0.957600,0.0,0.0,0.0,0.0,0.0 +0,0.957700,0.0,0.0,0.0,0.0,0.0 +0,0.957800,0.0,0.0,0.0,0.0,0.0 +0,0.957900,0.0,0.0,0.0,0.0,0.0 +0,0.958000,0.0,0.0,0.0,0.0,0.0 +0,0.958100,0.0,0.0,0.0,0.0,0.0 +0,0.958200,0.0,0.0,0.0,0.0,0.0 +0,0.958300,0.0,0.0,0.0,0.0,0.0 +0,0.958400,0.0,0.0,0.0,0.0,0.0 +0,0.958500,0.0,0.0,0.0,0.0,0.0 +0,0.958600,0.0,0.0,0.0,0.0,0.0 +0,0.958700,0.0,0.0,0.0,0.0,0.0 +0,0.958800,0.0,0.0,0.0,0.0,0.0 +0,0.958900,0.0,0.0,0.0,0.0,0.0 +0,0.959000,0.0,0.0,0.0,0.0,0.0 +0,0.959100,0.0,0.0,0.0,0.0,0.0 +0,0.959200,0.0,0.0,0.0,0.0,0.0 +0,0.959300,0.0,0.0,0.0,0.0,0.0 +0,0.959400,0.0,0.0,0.0,0.0,0.0 +0,0.959500,0.0,0.0,0.0,0.0,0.0 +0,0.959600,0.0,0.0,0.0,0.0,0.0 +0,0.959700,0.0,0.0,0.0,0.0,0.0 +0,0.959800,0.0,0.0,0.0,0.0,0.0 +0,0.959900,0.0,0.0,0.0,0.0,0.0 +0,0.960000,0.0,0.0,0.0,0.0,0.0 +0,0.960100,0.0,0.0,0.0,0.0,0.0 +1,368.812826,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.960200,0.0,0.0,0.0,0.0,0.0 +0,0.960300,0.0,0.0,0.0,0.0,0.0 +0,0.960400,0.0,0.0,0.0,0.0,0.0 +0,0.960500,0.0,0.0,0.0,0.0,0.0 +0,0.960600,0.0,0.0,0.0,0.0,0.0 +0,0.960700,0.0,0.0,0.0,0.0,0.0 +0,0.960800,0.0,0.0,0.0,0.0,0.0 +0,0.960900,0.0,0.0,0.0,0.0,0.0 +0,0.961000,0.0,0.0,0.0,0.0,0.0 +0,0.961100,0.0,0.0,0.0,0.0,0.0 +0,0.961200,0.0,0.0,0.0,0.0,0.0 +0,0.961300,0.0,0.0,0.0,0.0,0.0 +0,0.961400,0.0,0.0,0.0,0.0,0.0 +0,0.961500,0.0,0.0,0.0,0.0,0.0 +0,0.961600,0.0,0.0,0.0,0.0,0.0 +0,0.961700,0.0,0.0,0.0,0.0,0.0 +0,0.961800,0.0,0.0,0.0,0.0,0.0 +0,0.961900,0.0,0.0,0.0,0.0,0.0 +0,0.962000,0.0,0.0,0.0,0.0,0.0 +0,0.962100,0.0,0.0,0.0,0.0,0.0 +0,0.962200,0.0,0.0,0.0,0.0,0.0 +0,0.962300,0.0,0.0,0.0,0.0,0.0 +0,0.962400,0.0,0.0,0.0,0.0,0.0 +0,0.962500,0.0,0.0,0.0,0.0,0.0 +0,0.962600,0.0,0.0,0.0,0.0,0.0 +0,0.962700,0.0,0.0,0.0,0.0,0.0 +0,0.962800,0.0,0.0,0.0,0.0,0.0 +0,0.962900,0.0,0.0,0.0,0.0,0.0 +0,0.963000,0.0,0.0,0.0,0.0,0.0 +0,0.963100,0.0,0.0,0.0,0.0,0.0 +0,0.963200,0.0,0.0,0.0,0.0,0.0 +0,0.963300,0.0,0.0,0.0,0.0,0.0 +0,0.963400,0.0,0.0,0.0,0.0,0.0 +0,0.963500,0.0,0.0,0.0,0.0,0.0 +0,0.963600,0.0,0.0,0.0,0.0,0.0 +0,0.963700,0.0,0.0,0.0,0.0,0.0 +0,0.963800,0.0,0.0,0.0,0.0,0.0 +0,0.963900,0.0,0.0,0.0,0.0,0.0 +0,0.964000,0.0,0.0,0.0,0.0,0.0 +0,0.964100,0.0,0.0,0.0,0.0,0.0 +0,0.964200,0.0,0.0,0.0,0.0,0.0 +0,0.964300,0.0,0.0,0.0,0.0,0.0 +0,0.964400,0.0,0.0,0.0,0.0,0.0 +0,0.964500,0.0,0.0,0.0,0.0,0.0 +0,0.964600,0.0,0.0,0.0,0.0,0.0 +0,0.964700,0.0,0.0,0.0,0.0,0.0 +0,0.964800,0.0,0.0,0.0,0.0,0.0 +0,0.964900,0.0,0.0,0.0,0.0,0.0 +0,0.965000,0.0,0.0,0.0,0.0,0.0 +0,0.965100,0.0,0.0,0.0,0.0,0.0 +0,0.965200,0.0,0.0,0.0,0.0,0.0 +0,0.965300,0.0,0.0,0.0,0.0,0.0 +0,0.965400,0.0,0.0,0.0,0.0,0.0 +0,0.965500,0.0,0.0,0.0,0.0,0.0 +0,0.965600,0.0,0.0,0.0,0.0,0.0 +0,0.965700,0.0,0.0,0.0,0.0,0.0 +0,0.965800,0.0,0.0,0.0,0.0,0.0 +0,0.965900,0.0,0.0,0.0,0.0,0.0 +0,0.966000,0.0,0.0,0.0,0.0,0.0 +0,0.966100,0.0,0.0,0.0,0.0,0.0 +0,0.966200,0.0,0.0,0.0,0.0,0.0 +0,0.966300,0.0,0.0,0.0,0.0,0.0 +0,0.966400,0.0,0.0,0.0,0.0,0.0 +0,0.966500,0.0,0.0,0.0,0.0,0.0 +0,0.966600,0.0,0.0,0.0,0.0,0.0 +0,0.966700,0.0,0.0,0.0,0.0,0.0 +0,0.966800,0.0,0.0,0.0,0.0,0.0 +0,0.966900,0.0,0.0,0.0,0.0,0.0 +0,0.967000,0.0,0.0,0.0,0.0,0.0 +0,0.967100,0.0,0.0,0.0,0.0,0.0 +0,0.967200,0.0,0.0,0.0,0.0,0.0 +0,0.967300,0.0,0.0,0.0,0.0,0.0 +0,0.967400,0.0,0.0,0.0,0.0,0.0 +0,0.967500,0.0,0.0,0.0,0.0,0.0 +0,0.967600,0.0,0.0,0.0,0.0,0.0 +0,0.967700,0.0,0.0,0.0,0.0,0.0 +0,0.967800,0.0,0.0,0.0,0.0,0.0 +0,0.967900,0.0,0.0,0.0,0.0,0.0 +0,0.968000,0.0,0.0,0.0,0.0,0.0 +0,0.968100,0.0,0.0,0.0,0.0,0.0 +0,0.968200,0.0,0.0,0.0,0.0,0.0 +0,0.968300,0.0,0.0,0.0,0.0,0.0 +0,0.968400,0.0,0.0,0.0,0.0,0.0 +0,0.968500,0.0,0.0,0.0,0.0,0.0 +0,0.968600,0.0,0.0,0.0,0.0,0.0 +0,0.968700,0.0,0.0,0.0,0.0,0.0 +0,0.968800,0.0,0.0,0.0,0.0,0.0 +0,0.968900,0.0,0.0,0.0,0.0,0.0 +0,0.969000,0.0,0.0,0.0,0.0,0.0 +0,0.969100,0.0,0.0,0.0,0.0,0.0 +0,0.969200,0.0,0.0,0.0,0.0,0.0 +0,0.969300,0.0,0.0,0.0,0.0,0.0 +0,0.969400,0.0,0.0,0.0,0.0,0.0 +0,0.969500,0.0,0.0,0.0,0.0,0.0 +0,0.969600,0.0,0.0,0.0,0.0,0.0 +0,0.969700,0.0,0.0,0.0,0.0,0.0 +0,0.969800,0.0,0.0,0.0,0.0,0.0 +0,0.969900,0.0,0.0,0.0,0.0,0.0 +0,0.970000,0.0,0.0,0.0,0.0,0.0 +0,0.970100,0.0,0.0,0.0,0.0,0.0 +0,0.970200,0.0,0.0,0.0,0.0,0.0 +0,0.970300,0.0,0.0,0.0,0.0,0.0 +0,0.970400,0.0,0.0,0.0,0.0,0.0 +0,0.970500,0.0,0.0,0.0,0.0,0.0 +0,0.970600,0.0,0.0,0.0,0.0,0.0 +0,0.970700,0.0,0.0,0.0,0.0,0.0 +0,0.970800,0.0,0.0,0.0,0.0,0.0 +0,0.970900,0.0,0.0,0.0,0.0,0.0 +0,0.971000,0.0,0.0,0.0,0.0,0.0 +0,0.971100,0.0,0.0,0.0,0.0,0.0 +0,0.971200,0.0,0.0,0.0,0.0,0.0 +0,0.971300,0.0,0.0,0.0,0.0,0.0 +0,0.971400,0.0,0.0,0.0,0.0,0.0 +0,0.971500,0.0,0.0,0.0,0.0,0.0 +0,0.971600,0.0,0.0,0.0,0.0,0.0 +0,0.971700,0.0,0.0,0.0,0.0,0.0 +0,0.971800,0.0,0.0,0.0,0.0,0.0 +0,0.971900,0.0,0.0,0.0,0.0,0.0 +0,0.972000,0.0,0.0,0.0,0.0,0.0 +0,0.972100,0.0,0.0,0.0,0.0,0.0 +0,0.972200,0.0,0.0,0.0,0.0,0.0 +0,0.972300,0.0,0.0,0.0,0.0,0.0 +0,0.972400,0.0,0.0,0.0,0.0,0.0 +0,0.972500,0.0,0.0,0.0,0.0,0.0 +0,0.972600,0.0,0.0,0.0,0.0,0.0 +0,0.972700,0.0,0.0,0.0,0.0,0.0 +0,0.972800,0.0,0.0,0.0,0.0,0.0 +0,0.972900,0.0,0.0,0.0,0.0,0.0 +0,0.973000,0.0,0.0,0.0,0.0,0.0 +0,0.973100,0.0,0.0,0.0,0.0,0.0 +0,0.973200,0.0,0.0,0.0,0.0,0.0 +0,0.973300,0.0,0.0,0.0,0.0,0.0 +0,0.973400,0.0,0.0,0.0,0.0,0.0 +0,0.973500,0.0,0.0,0.0,0.0,0.0 +0,0.973600,0.0,0.0,0.0,0.0,0.0 +0,0.973700,0.0,0.0,0.0,0.0,0.0 +0,0.973800,0.0,0.0,0.0,0.0,0.0 +0,0.973900,0.0,0.0,0.0,0.0,0.0 +0,0.974000,0.0,0.0,0.0,0.0,0.0 +0,0.974100,0.0,0.0,0.0,0.0,0.0 +0,0.974200,0.0,0.0,0.0,0.0,0.0 +0,0.974300,0.0,0.0,0.0,0.0,0.0 +0,0.974400,0.0,0.0,0.0,0.0,0.0 +0,0.974500,0.0,0.0,0.0,0.0,0.0 +0,0.974600,0.0,0.0,0.0,0.0,0.0 +0,0.974700,0.0,0.0,0.0,0.0,0.0 +0,0.974800,0.0,0.0,0.0,0.0,0.0 +0,0.974900,0.0,0.0,0.0,0.0,0.0 +0,0.975000,0.0,0.0,0.0,0.0,0.0 +0,0.975100,0.0,0.0,0.0,0.0,0.0 +0,0.975200,0.0,0.0,0.0,0.0,0.0 +0,0.975300,0.0,0.0,0.0,0.0,0.0 +0,0.975400,0.0,0.0,0.0,0.0,0.0 +0,0.975500,0.0,0.0,0.0,0.0,0.0 +0,0.975600,0.0,0.0,0.0,0.0,0.0 +0,0.975700,0.0,0.0,0.0,0.0,0.0 +0,0.975800,0.0,0.0,0.0,0.0,0.0 +0,0.975900,0.0,0.0,0.0,0.0,0.0 +0,0.976000,0.0,0.0,0.0,0.0,0.0 +0,0.976100,0.0,0.0,0.0,0.0,0.0 +0,0.976200,0.0,0.0,0.0,0.0,0.0 +0,0.976300,0.0,0.0,0.0,0.0,0.0 +0,0.976400,0.0,0.0,0.0,0.0,0.0 +0,0.976500,0.0,0.0,0.0,0.0,0.0 +0,0.976600,0.0,0.0,0.0,0.0,0.0 +0,0.976700,0.0,0.0,0.0,0.0,0.0 +0,0.976800,0.0,0.0,0.0,0.0,0.0 +0,0.976900,0.0,0.0,0.0,0.0,0.0 +0,0.977000,0.0,0.0,0.0,0.0,0.0 +0,0.977100,0.0,0.0,0.0,0.0,0.0 +0,0.977200,0.0,0.0,0.0,0.0,0.0 +0,0.977300,0.0,0.0,0.0,0.0,0.0 +0,0.977400,0.0,0.0,0.0,0.0,0.0 +0,0.977500,0.0,0.0,0.0,0.0,0.0 +0,0.977600,0.0,0.0,0.0,0.0,0.0 +0,0.977700,0.0,0.0,0.0,0.0,0.0 +0,0.977800,0.0,0.0,0.0,0.0,0.0 +0,0.977900,0.0,0.0,0.0,0.0,0.0 +0,0.978000,0.0,0.0,0.0,0.0,0.0 +0,0.978100,0.0,0.0,0.0,0.0,0.0 +0,0.978200,0.0,0.0,0.0,0.0,0.0 +0,0.978300,0.0,0.0,0.0,0.0,0.0 +0,0.978400,0.0,0.0,0.0,0.0,0.0 +0,0.978500,0.0,0.0,0.0,0.0,0.0 +0,0.978600,0.0,0.0,0.0,0.0,0.0 +0,0.978700,0.0,0.0,0.0,0.0,0.0 +0,0.978800,0.0,0.0,0.0,0.0,0.0 +0,0.978900,0.0,0.0,0.0,0.0,0.0 +0,0.979000,0.0,0.0,0.0,0.0,0.0 +0,0.979100,0.0,0.0,0.0,0.0,0.0 +0,0.979200,0.0,0.0,0.0,0.0,0.0 +0,0.979300,0.0,0.0,0.0,0.0,0.0 +0,0.979400,0.0,0.0,0.0,0.0,0.0 +0,0.979500,0.0,0.0,0.0,0.0,0.0 +0,0.979600,0.0,0.0,0.0,0.0,0.0 +0,0.979700,0.0,0.0,0.0,0.0,0.0 +0,0.979800,0.0,0.0,0.0,0.0,0.0 +0,0.979900,0.0,0.0,0.0,0.0,0.0 +0,0.980000,0.0,0.0,0.0,0.0,0.0 +0,0.980100,0.0,0.0,0.0,0.0,0.0 +1,392.343435,0.0,0.0,0.0,0.0,0.0,1.0 +0,0.980200,0.0,0.0,0.0,0.0,0.0 +0,0.980300,0.0,0.0,0.0,0.0,0.0 +0,0.980400,0.0,0.0,0.0,0.0,0.0 +0,0.980500,0.0,0.0,0.0,0.0,0.0 +0,0.980600,0.0,0.0,0.0,0.0,0.0 +0,0.980700,0.0,0.0,0.0,0.0,0.0 +0,0.980800,0.0,0.0,0.0,0.0,0.0 +0,0.980900,0.0,0.0,0.0,0.0,0.0 +0,0.981000,0.0,0.0,0.0,0.0,0.0 +0,0.981100,0.0,0.0,0.0,0.0,0.0 +0,0.981200,0.0,0.0,0.0,0.0,0.0 +0,0.981300,0.0,0.0,0.0,0.0,0.0 +0,0.981400,0.0,0.0,0.0,0.0,0.0 +0,0.981500,0.0,0.0,0.0,0.0,0.0 +0,0.981600,0.0,0.0,0.0,0.0,0.0 +0,0.981700,0.0,0.0,0.0,0.0,0.0 +0,0.981800,0.0,0.0,0.0,0.0,0.0 +0,0.981900,0.0,0.0,0.0,0.0,0.0 +0,0.982000,0.0,0.0,0.0,0.0,0.0 +0,0.982100,0.0,0.0,0.0,0.0,0.0 +0,0.982200,0.0,0.0,0.0,0.0,0.0 +0,0.982300,0.0,0.0,0.0,0.0,0.0 +0,0.982400,0.0,0.0,0.0,0.0,0.0 +0,0.982500,0.0,0.0,0.0,0.0,0.0 +0,0.982600,0.0,0.0,0.0,0.0,0.0 +0,0.982700,0.0,0.0,0.0,0.0,0.0 +0,0.982800,0.0,0.0,0.0,0.0,0.0 +0,0.982900,0.0,0.0,0.0,0.0,0.0 +0,0.983000,0.0,0.0,0.0,0.0,0.0 +0,0.983100,0.0,0.0,0.0,0.0,0.0 +0,0.983200,0.0,0.0,0.0,0.0,0.0 +0,0.983300,0.0,0.0,0.0,0.0,0.0 +0,0.983400,0.0,0.0,0.0,0.0,0.0 +0,0.983500,0.0,0.0,0.0,0.0,0.0 +0,0.983600,0.0,0.0,0.0,0.0,0.0 +0,0.983700,0.0,0.0,0.0,0.0,0.0 +0,0.983800,0.0,0.0,0.0,0.0,0.0 +0,0.983900,0.0,0.0,0.0,0.0,0.0 +0,0.984000,0.0,0.0,0.0,0.0,0.0 +0,0.984100,0.0,0.0,0.0,0.0,0.0 +0,0.984200,0.0,0.0,0.0,0.0,0.0 +0,0.984300,0.0,0.0,0.0,0.0,0.0 +0,0.984400,0.0,0.0,0.0,0.0,0.0 +0,0.984500,0.0,0.0,0.0,0.0,0.0 +0,0.984600,0.0,0.0,0.0,0.0,0.0 +0,0.984700,0.0,0.0,0.0,0.0,0.0 +0,0.984800,0.0,0.0,0.0,0.0,0.0 +0,0.984900,0.0,0.0,0.0,0.0,0.0 +0,0.985000,0.0,0.0,0.0,0.0,0.0 +0,0.985100,0.0,0.0,0.0,0.0,0.0 +0,0.985200,0.0,0.0,0.0,0.0,0.0 +0,0.985300,0.0,0.0,0.0,0.0,0.0 +0,0.985400,0.0,0.0,0.0,0.0,0.0 +0,0.985500,0.0,0.0,0.0,0.0,0.0 +0,0.985600,0.0,0.0,0.0,0.0,0.0 +0,0.985700,0.0,0.0,0.0,0.0,0.0 +0,0.985800,0.0,0.0,0.0,0.0,0.0 +0,0.985900,0.0,0.0,0.0,0.0,0.0 +0,0.986000,0.0,0.0,0.0,0.0,0.0 +0,0.986100,0.0,0.0,0.0,0.0,0.0 +0,0.986200,0.0,0.0,0.0,0.0,0.0 +0,0.986300,0.0,0.0,0.0,0.0,0.0 +0,0.986400,0.0,0.0,0.0,0.0,0.0 +0,0.986500,0.0,0.0,0.0,0.0,0.0 +0,0.986600,0.0,0.0,0.0,0.0,0.0 +0,0.986700,0.0,0.0,0.0,0.0,0.0 +0,0.986800,0.0,0.0,0.0,0.0,0.0 +0,0.986900,0.0,0.0,0.0,0.0,0.0 +0,0.987000,0.0,0.0,0.0,0.0,0.0 +0,0.987100,0.0,0.0,0.0,0.0,0.0 +0,0.987200,0.0,0.0,0.0,0.0,0.0 +0,0.987300,0.0,0.0,0.0,0.0,0.0 +0,0.987400,0.0,0.0,0.0,0.0,0.0 +0,0.987500,0.0,0.0,0.0,0.0,0.0 +0,0.987600,0.0,0.0,0.0,0.0,0.0 +0,0.987700,0.0,0.0,0.0,0.0,0.0 +0,0.987800,0.0,0.0,0.0,0.0,0.0 +0,0.987900,0.0,0.0,0.0,0.0,0.0 +0,0.988000,0.0,0.0,0.0,0.0,0.0 +0,0.988100,0.0,0.0,0.0,0.0,0.0 +0,0.988200,0.0,0.0,0.0,0.0,0.0 +0,0.988300,0.0,0.0,0.0,0.0,0.0 +0,0.988400,0.0,0.0,0.0,0.0,0.0 +0,0.988500,0.0,0.0,0.0,0.0,0.0 +0,0.988600,0.0,0.0,0.0,0.0,0.0 +0,0.988700,0.0,0.0,0.0,0.0,0.0 +0,0.988800,0.0,0.0,0.0,0.0,0.0 +0,0.988900,0.0,0.0,0.0,0.0,0.0 +0,0.989000,0.0,0.0,0.0,0.0,0.0 +0,0.989100,0.0,0.0,0.0,0.0,0.0 +0,0.989200,0.0,0.0,0.0,0.0,0.0 +0,0.989300,0.0,0.0,0.0,0.0,0.0 +0,0.989400,0.0,0.0,0.0,0.0,0.0 +0,0.989500,0.0,0.0,0.0,0.0,0.0 +0,0.989600,0.0,0.0,0.0,0.0,0.0 +0,0.989700,0.0,0.0,0.0,0.0,0.0 +0,0.989800,0.0,0.0,0.0,0.0,0.0 +0,0.989900,0.0,0.0,0.0,0.0,0.0 +0,0.990000,0.0,0.0,0.0,0.0,0.0 +0,0.990100,0.0,0.0,0.0,0.0,0.0 +0,0.990200,0.0,0.0,0.0,0.0,0.0 +0,0.990300,0.0,0.0,0.0,0.0,0.0 +0,0.990400,0.0,0.0,0.0,0.0,0.0 +0,0.990500,0.0,0.0,0.0,0.0,0.0 +0,0.990600,0.0,0.0,0.0,0.0,0.0 +0,0.990700,0.0,0.0,0.0,0.0,0.0 +0,0.990800,0.0,0.0,0.0,0.0,0.0 +0,0.990900,0.0,0.0,0.0,0.0,0.0 +0,0.991000,0.0,0.0,0.0,0.0,0.0 +0,0.991100,0.0,0.0,0.0,0.0,0.0 +0,0.991200,0.0,0.0,0.0,0.0,0.0 +0,0.991300,0.0,0.0,0.0,0.0,0.0 +0,0.991400,0.0,0.0,0.0,0.0,0.0 +0,0.991500,0.0,0.0,0.0,0.0,0.0 +0,0.991600,0.0,0.0,0.0,0.0,0.0 +0,0.991700,0.0,0.0,0.0,0.0,0.0 +0,0.991800,0.0,0.0,0.0,0.0,0.0 +0,0.991900,0.0,0.0,0.0,0.0,0.0 +0,0.992000,0.0,0.0,0.0,0.0,0.0 +0,0.992100,0.0,0.0,0.0,0.0,0.0 +0,0.992200,0.0,0.0,0.0,0.0,0.0 +0,0.992300,0.0,0.0,0.0,0.0,0.0 +0,0.992400,0.0,0.0,0.0,0.0,0.0 +0,0.992500,0.0,0.0,0.0,0.0,0.0 +0,0.992600,0.0,0.0,0.0,0.0,0.0 +0,0.992700,0.0,0.0,0.0,0.0,0.0 +0,0.992800,0.0,0.0,0.0,0.0,0.0 +0,0.992900,0.0,0.0,0.0,0.0,0.0 +0,0.993000,0.0,0.0,0.0,0.0,0.0 +0,0.993100,0.0,0.0,0.0,0.0,0.0 +0,0.993200,0.0,0.0,0.0,0.0,0.0 +0,0.993300,0.0,0.0,0.0,0.0,0.0 +0,0.993400,0.0,0.0,0.0,0.0,0.0 +0,0.993500,0.0,0.0,0.0,0.0,0.0 +0,0.993600,0.0,0.0,0.0,0.0,0.0 +0,0.993700,0.0,0.0,0.0,0.0,0.0 +0,0.993800,0.0,0.0,0.0,0.0,0.0 +0,0.993900,0.0,0.0,0.0,0.0,0.0 +0,0.994000,0.0,0.0,0.0,0.0,0.0 +0,0.994100,0.0,0.0,0.0,0.0,0.0 +0,0.994200,0.0,0.0,0.0,0.0,0.0 +0,0.994300,0.0,0.0,0.0,0.0,0.0 +0,0.994400,0.0,0.0,0.0,0.0,0.0 +0,0.994500,0.0,0.0,0.0,0.0,0.0 +0,0.994600,0.0,0.0,0.0,0.0,0.0 +0,0.994700,0.0,0.0,0.0,0.0,0.0 +0,0.994800,0.0,0.0,0.0,0.0,0.0 +0,0.994900,0.0,0.0,0.0,0.0,0.0 +0,0.995000,0.0,0.0,0.0,0.0,0.0 +0,0.995100,0.0,0.0,0.0,0.0,0.0 +0,0.995200,0.0,0.0,0.0,0.0,0.0 +0,0.995300,0.0,0.0,0.0,0.0,0.0 +0,0.995400,0.0,0.0,0.0,0.0,0.0 +0,0.995500,0.0,0.0,0.0,0.0,0.0 +0,0.995600,0.0,0.0,0.0,0.0,0.0 +0,0.995700,0.0,0.0,0.0,0.0,0.0 +0,0.995800,0.0,0.0,0.0,0.0,0.0 +0,0.995900,0.0,0.0,0.0,0.0,0.0 +0,0.996000,0.0,0.0,0.0,0.0,0.0 +0,0.996100,0.0,0.0,0.0,0.0,0.0 +0,0.996200,0.0,0.0,0.0,0.0,0.0 +0,0.996300,0.0,0.0,0.0,0.0,0.0 +0,0.996400,0.0,0.0,0.0,0.0,0.0 +0,0.996500,0.0,0.0,0.0,0.0,0.0 +0,0.996600,0.0,0.0,0.0,0.0,0.0 +0,0.996700,0.0,0.0,0.0,0.0,0.0 +0,0.996800,0.0,0.0,0.0,0.0,0.0 +0,0.996900,0.0,0.0,0.0,0.0,0.0 +0,0.997000,0.0,0.0,0.0,0.0,0.0 +0,0.997100,0.0,0.0,0.0,0.0,0.0 +0,0.997200,0.0,0.0,0.0,0.0,0.0 +0,0.997300,0.0,0.0,0.0,0.0,0.0 +0,0.997400,0.0,0.0,0.0,0.0,0.0 +0,0.997500,0.0,0.0,0.0,0.0,0.0 +0,0.997600,0.0,0.0,0.0,0.0,0.0 +0,0.997700,0.0,0.0,0.0,0.0,0.0 +0,0.997800,0.0,0.0,0.0,0.0,0.0 +0,0.997900,0.0,0.0,0.0,0.0,0.0 +0,0.998000,0.0,0.0,0.0,0.0,0.0 +0,0.998100,0.0,0.0,0.0,0.0,0.0 +0,0.998200,0.0,0.0,0.0,0.0,0.0 +0,0.998300,0.0,0.0,0.0,0.0,0.0 +0,0.998400,0.0,0.0,0.0,0.0,0.0 +0,0.998500,0.0,0.0,0.0,0.0,0.0 +0,0.998600,0.0,0.0,0.0,0.0,0.0 +0,0.998700,0.0,0.0,0.0,0.0,0.0 +0,0.998800,0.0,0.0,0.0,0.0,0.0 +0,0.998900,0.0,0.0,0.0,0.0,0.0 +0,0.999000,0.0,0.0,0.0,0.0,0.0 +0,0.999100,0.0,0.0,0.0,0.0,0.0 +0,0.999200,0.0,0.0,0.0,0.0,0.0 +0,0.999300,0.0,0.0,0.0,0.0,0.0 +0,0.999400,0.0,0.0,0.0,0.0,0.0 +0,0.999500,0.0,0.0,0.0,0.0,0.0 +0,0.999600,0.0,0.0,0.0,0.0,0.0 +0,0.999700,0.0,0.0,0.0,0.0,0.0 +0,0.999800,0.0,0.0,0.0,0.0,0.0 +0,0.999900,0.0,0.0,0.0,0.0,0.0 +0,1.000000,0.0,0.0,0.0,0.0,0.0 +0,1.000100,0.0,0.0,0.0,0.0,0.0 +1,416.854194,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.000200,0.0,0.0,0.0,0.0,0.0 +0,1.000300,0.0,0.0,0.0,0.0,0.0 +0,1.000400,0.0,0.0,0.0,0.0,0.0 +0,1.000500,0.0,0.0,0.0,0.0,0.0 +0,1.000600,0.0,0.0,0.0,0.0,0.0 +0,1.000700,0.0,0.0,0.0,0.0,0.0 +0,1.000800,0.0,0.0,0.0,0.0,0.0 +0,1.000900,0.0,0.0,0.0,0.0,0.0 +0,1.001000,0.0,0.0,0.0,0.0,0.0 +0,1.001100,0.0,0.0,0.0,0.0,0.0 +0,1.001200,0.0,0.0,0.0,0.0,0.0 +0,1.001300,0.0,0.0,0.0,0.0,0.0 +0,1.001400,0.0,0.0,0.0,0.0,0.0 +0,1.001500,0.0,0.0,0.0,0.0,0.0 +0,1.001600,0.0,0.0,0.0,0.0,0.0 +0,1.001700,0.0,0.0,0.0,0.0,0.0 +0,1.001800,0.0,0.0,0.0,0.0,0.0 +0,1.001900,0.0,0.0,0.0,0.0,0.0 +0,1.002000,0.0,0.0,0.0,0.0,0.0 +0,1.002100,0.0,0.0,0.0,0.0,0.0 +0,1.002200,0.0,0.0,0.0,0.0,0.0 +0,1.002300,0.0,0.0,0.0,0.0,0.0 +0,1.002400,0.0,0.0,0.0,0.0,0.0 +0,1.002500,0.0,0.0,0.0,0.0,0.0 +0,1.002600,0.0,0.0,0.0,0.0,0.0 +0,1.002700,0.0,0.0,0.0,0.0,0.0 +0,1.002800,0.0,0.0,0.0,0.0,0.0 +0,1.002900,0.0,0.0,0.0,0.0,0.0 +0,1.003000,0.0,0.0,0.0,0.0,0.0 +0,1.003100,0.0,0.0,0.0,0.0,0.0 +0,1.003200,0.0,0.0,0.0,0.0,0.0 +0,1.003300,0.0,0.0,0.0,0.0,0.0 +0,1.003400,0.0,0.0,0.0,0.0,0.0 +0,1.003500,0.0,0.0,0.0,0.0,0.0 +0,1.003600,0.0,0.0,0.0,0.0,0.0 +0,1.003700,0.0,0.0,0.0,0.0,0.0 +0,1.003800,0.0,0.0,0.0,0.0,0.0 +0,1.003900,0.0,0.0,0.0,0.0,0.0 +0,1.004000,0.0,0.0,0.0,0.0,0.0 +0,1.004100,0.0,0.0,0.0,0.0,0.0 +0,1.004200,0.0,0.0,0.0,0.0,0.0 +0,1.004300,0.0,0.0,0.0,0.0,0.0 +0,1.004400,0.0,0.0,0.0,0.0,0.0 +0,1.004500,0.0,0.0,0.0,0.0,0.0 +0,1.004600,0.0,0.0,0.0,0.0,0.0 +0,1.004700,0.0,0.0,0.0,0.0,0.0 +0,1.004800,0.0,0.0,0.0,0.0,0.0 +0,1.004900,0.0,0.0,0.0,0.0,0.0 +0,1.005000,0.0,0.0,0.0,0.0,0.0 +0,1.005100,0.0,0.0,0.0,0.0,0.0 +0,1.005200,0.0,0.0,0.0,0.0,0.0 +0,1.005300,0.0,0.0,0.0,0.0,0.0 +0,1.005400,0.0,0.0,0.0,0.0,0.0 +0,1.005500,0.0,0.0,0.0,0.0,0.0 +0,1.005600,0.0,0.0,0.0,0.0,0.0 +0,1.005700,0.0,0.0,0.0,0.0,0.0 +0,1.005800,0.0,0.0,0.0,0.0,0.0 +0,1.005900,0.0,0.0,0.0,0.0,0.0 +0,1.006000,0.0,0.0,0.0,0.0,0.0 +0,1.006100,0.0,0.0,0.0,0.0,0.0 +0,1.006200,0.0,0.0,0.0,0.0,0.0 +0,1.006300,0.0,0.0,0.0,0.0,0.0 +0,1.006400,0.0,0.0,0.0,0.0,0.0 +0,1.006500,0.0,0.0,0.0,0.0,0.0 +0,1.006600,0.0,0.0,0.0,0.0,0.0 +0,1.006700,0.0,0.0,0.0,0.0,0.0 +0,1.006800,0.0,0.0,0.0,0.0,0.0 +0,1.006900,0.0,0.0,0.0,0.0,0.0 +0,1.007000,0.0,0.0,0.0,0.0,0.0 +0,1.007100,0.0,0.0,0.0,0.0,0.0 +0,1.007200,0.0,0.0,0.0,0.0,0.0 +0,1.007300,0.0,0.0,0.0,0.0,0.0 +0,1.007400,0.0,0.0,0.0,0.0,0.0 +0,1.007500,0.0,0.0,0.0,0.0,0.0 +0,1.007600,0.0,0.0,0.0,0.0,0.0 +0,1.007700,0.0,0.0,0.0,0.0,0.0 +0,1.007800,0.0,0.0,0.0,0.0,0.0 +0,1.007900,0.0,0.0,0.0,0.0,0.0 +0,1.008000,0.0,0.0,0.0,0.0,0.0 +0,1.008100,0.0,0.0,0.0,0.0,0.0 +0,1.008200,0.0,0.0,0.0,0.0,0.0 +0,1.008300,0.0,0.0,0.0,0.0,0.0 +0,1.008400,0.0,0.0,0.0,0.0,0.0 +0,1.008500,0.0,0.0,0.0,0.0,0.0 +0,1.008600,0.0,0.0,0.0,0.0,0.0 +0,1.008700,0.0,0.0,0.0,0.0,0.0 +0,1.008800,0.0,0.0,0.0,0.0,0.0 +0,1.008900,0.0,0.0,0.0,0.0,0.0 +0,1.009000,0.0,0.0,0.0,0.0,0.0 +0,1.009100,0.0,0.0,0.0,0.0,0.0 +0,1.009200,0.0,0.0,0.0,0.0,0.0 +0,1.009300,0.0,0.0,0.0,0.0,0.0 +0,1.009400,0.0,0.0,0.0,0.0,0.0 +0,1.009500,0.0,0.0,0.0,0.0,0.0 +0,1.009600,0.0,0.0,0.0,0.0,0.0 +0,1.009700,0.0,0.0,0.0,0.0,0.0 +0,1.009800,0.0,0.0,0.0,0.0,0.0 +0,1.009900,0.0,0.0,0.0,0.0,0.0 +0,1.010000,0.0,0.0,0.0,0.0,0.0 +0,1.010100,0.0,0.0,0.0,0.0,0.0 +0,1.010200,0.0,0.0,0.0,0.0,0.0 +0,1.010300,0.0,0.0,0.0,0.0,0.0 +0,1.010400,0.0,0.0,0.0,0.0,0.0 +0,1.010500,0.0,0.0,0.0,0.0,0.0 +0,1.010600,0.0,0.0,0.0,0.0,0.0 +0,1.010700,0.0,0.0,0.0,0.0,0.0 +0,1.010800,0.0,0.0,0.0,0.0,0.0 +0,1.010900,0.0,0.0,0.0,0.0,0.0 +0,1.011000,0.0,0.0,0.0,0.0,0.0 +0,1.011100,0.0,0.0,0.0,0.0,0.0 +0,1.011200,0.0,0.0,0.0,0.0,0.0 +0,1.011300,0.0,0.0,0.0,0.0,0.0 +0,1.011400,0.0,0.0,0.0,0.0,0.0 +0,1.011500,0.0,0.0,0.0,0.0,0.0 +0,1.011600,0.0,0.0,0.0,0.0,0.0 +0,1.011700,0.0,0.0,0.0,0.0,0.0 +0,1.011800,0.0,0.0,0.0,0.0,0.0 +0,1.011900,0.0,0.0,0.0,0.0,0.0 +0,1.012000,0.0,0.0,0.0,0.0,0.0 +0,1.012100,0.0,0.0,0.0,0.0,0.0 +0,1.012200,0.0,0.0,0.0,0.0,0.0 +0,1.012300,0.0,0.0,0.0,0.0,0.0 +0,1.012400,0.0,0.0,0.0,0.0,0.0 +0,1.012500,0.0,0.0,0.0,0.0,0.0 +0,1.012600,0.0,0.0,0.0,0.0,0.0 +0,1.012700,0.0,0.0,0.0,0.0,0.0 +0,1.012800,0.0,0.0,0.0,0.0,0.0 +0,1.012900,0.0,0.0,0.0,0.0,0.0 +0,1.013000,0.0,0.0,0.0,0.0,0.0 +0,1.013100,0.0,0.0,0.0,0.0,0.0 +0,1.013200,0.0,0.0,0.0,0.0,0.0 +0,1.013300,0.0,0.0,0.0,0.0,0.0 +0,1.013400,0.0,0.0,0.0,0.0,0.0 +0,1.013500,0.0,0.0,0.0,0.0,0.0 +0,1.013600,0.0,0.0,0.0,0.0,0.0 +0,1.013700,0.0,0.0,0.0,0.0,0.0 +0,1.013800,0.0,0.0,0.0,0.0,0.0 +0,1.013900,0.0,0.0,0.0,0.0,0.0 +0,1.014000,0.0,0.0,0.0,0.0,0.0 +0,1.014100,0.0,0.0,0.0,0.0,0.0 +0,1.014200,0.0,0.0,0.0,0.0,0.0 +0,1.014300,0.0,0.0,0.0,0.0,0.0 +0,1.014400,0.0,0.0,0.0,0.0,0.0 +0,1.014500,0.0,0.0,0.0,0.0,0.0 +0,1.014600,0.0,0.0,0.0,0.0,0.0 +0,1.014700,0.0,0.0,0.0,0.0,0.0 +0,1.014800,0.0,0.0,0.0,0.0,0.0 +0,1.014900,0.0,0.0,0.0,0.0,0.0 +0,1.015000,0.0,0.0,0.0,0.0,0.0 +0,1.015100,0.0,0.0,0.0,0.0,0.0 +0,1.015200,0.0,0.0,0.0,0.0,0.0 +0,1.015300,0.0,0.0,0.0,0.0,0.0 +0,1.015400,0.0,0.0,0.0,0.0,0.0 +0,1.015500,0.0,0.0,0.0,0.0,0.0 +0,1.015600,0.0,0.0,0.0,0.0,0.0 +0,1.015700,0.0,0.0,0.0,0.0,0.0 +0,1.015800,0.0,0.0,0.0,0.0,0.0 +0,1.015900,0.0,0.0,0.0,0.0,0.0 +0,1.016000,0.0,0.0,0.0,0.0,0.0 +0,1.016100,0.0,0.0,0.0,0.0,0.0 +0,1.016200,0.0,0.0,0.0,0.0,0.0 +0,1.016300,0.0,0.0,0.0,0.0,0.0 +0,1.016400,0.0,0.0,0.0,0.0,0.0 +0,1.016500,0.0,0.0,0.0,0.0,0.0 +0,1.016600,0.0,0.0,0.0,0.0,0.0 +0,1.016700,0.0,0.0,0.0,0.0,0.0 +0,1.016800,0.0,0.0,0.0,0.0,0.0 +0,1.016900,0.0,0.0,0.0,0.0,0.0 +0,1.017000,0.0,0.0,0.0,0.0,0.0 +0,1.017100,0.0,0.0,0.0,0.0,0.0 +0,1.017200,0.0,0.0,0.0,0.0,0.0 +0,1.017300,0.0,0.0,0.0,0.0,0.0 +0,1.017400,0.0,0.0,0.0,0.0,0.0 +0,1.017500,0.0,0.0,0.0,0.0,0.0 +0,1.017600,0.0,0.0,0.0,0.0,0.0 +0,1.017700,0.0,0.0,0.0,0.0,0.0 +0,1.017800,0.0,0.0,0.0,0.0,0.0 +0,1.017900,0.0,0.0,0.0,0.0,0.0 +0,1.018000,0.0,0.0,0.0,0.0,0.0 +0,1.018100,0.0,0.0,0.0,0.0,0.0 +0,1.018200,0.0,0.0,0.0,0.0,0.0 +0,1.018300,0.0,0.0,0.0,0.0,0.0 +0,1.018400,0.0,0.0,0.0,0.0,0.0 +0,1.018500,0.0,0.0,0.0,0.0,0.0 +0,1.018600,0.0,0.0,0.0,0.0,0.0 +0,1.018700,0.0,0.0,0.0,0.0,0.0 +0,1.018800,0.0,0.0,0.0,0.0,0.0 +0,1.018900,0.0,0.0,0.0,0.0,0.0 +0,1.019000,0.0,0.0,0.0,0.0,0.0 +0,1.019100,0.0,0.0,0.0,0.0,0.0 +0,1.019200,0.0,0.0,0.0,0.0,0.0 +0,1.019300,0.0,0.0,0.0,0.0,0.0 +0,1.019400,0.0,0.0,0.0,0.0,0.0 +0,1.019500,0.0,0.0,0.0,0.0,0.0 +0,1.019600,0.0,0.0,0.0,0.0,0.0 +0,1.019700,0.0,0.0,0.0,0.0,0.0 +0,1.019800,0.0,0.0,0.0,0.0,0.0 +0,1.019900,0.0,0.0,0.0,0.0,0.0 +0,1.020000,0.0,0.0,0.0,0.0,0.0 +0,1.020100,0.0,0.0,0.0,0.0,0.0 +1,442.365103,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.020200,0.0,0.0,0.0,0.0,0.0 +0,1.020300,0.0,0.0,0.0,0.0,0.0 +0,1.020400,0.0,0.0,0.0,0.0,0.0 +0,1.020500,0.0,0.0,0.0,0.0,0.0 +0,1.020600,0.0,0.0,0.0,0.0,0.0 +0,1.020700,0.0,0.0,0.0,0.0,0.0 +0,1.020800,0.0,0.0,0.0,0.0,0.0 +0,1.020900,0.0,0.0,0.0,0.0,0.0 +0,1.021000,0.0,0.0,0.0,0.0,0.0 +0,1.021100,0.0,0.0,0.0,0.0,0.0 +0,1.021200,0.0,0.0,0.0,0.0,0.0 +0,1.021300,0.0,0.0,0.0,0.0,0.0 +0,1.021400,0.0,0.0,0.0,0.0,0.0 +0,1.021500,0.0,0.0,0.0,0.0,0.0 +0,1.021600,0.0,0.0,0.0,0.0,0.0 +0,1.021700,0.0,0.0,0.0,0.0,0.0 +0,1.021800,0.0,0.0,0.0,0.0,0.0 +0,1.021900,0.0,0.0,0.0,0.0,0.0 +0,1.022000,0.0,0.0,0.0,0.0,0.0 +0,1.022100,0.0,0.0,0.0,0.0,0.0 +0,1.022200,0.0,0.0,0.0,0.0,0.0 +0,1.022300,0.0,0.0,0.0,0.0,0.0 +0,1.022400,0.0,0.0,0.0,0.0,0.0 +0,1.022500,0.0,0.0,0.0,0.0,0.0 +0,1.022600,0.0,0.0,0.0,0.0,0.0 +0,1.022700,0.0,0.0,0.0,0.0,0.0 +0,1.022800,0.0,0.0,0.0,0.0,0.0 +0,1.022900,0.0,0.0,0.0,0.0,0.0 +0,1.023000,0.0,0.0,0.0,0.0,0.0 +0,1.023100,0.0,0.0,0.0,0.0,0.0 +0,1.023200,0.0,0.0,0.0,0.0,0.0 +0,1.023300,0.0,0.0,0.0,0.0,0.0 +0,1.023400,0.0,0.0,0.0,0.0,0.0 +0,1.023500,0.0,0.0,0.0,0.0,0.0 +0,1.023600,0.0,0.0,0.0,0.0,0.0 +0,1.023700,0.0,0.0,0.0,0.0,0.0 +0,1.023800,0.0,0.0,0.0,0.0,0.0 +0,1.023900,0.0,0.0,0.0,0.0,0.0 +0,1.024000,0.0,0.0,0.0,0.0,0.0 +0,1.024100,0.0,0.0,0.0,0.0,0.0 +0,1.024200,0.0,0.0,0.0,0.0,0.0 +0,1.024300,0.0,0.0,0.0,0.0,0.0 +0,1.024400,0.0,0.0,0.0,0.0,0.0 +0,1.024500,0.0,0.0,0.0,0.0,0.0 +0,1.024600,0.0,0.0,0.0,0.0,0.0 +0,1.024700,0.0,0.0,0.0,0.0,0.0 +0,1.024800,0.0,0.0,0.0,0.0,0.0 +0,1.024900,0.0,0.0,0.0,0.0,0.0 +0,1.025000,0.0,0.0,0.0,0.0,0.0 +0,1.025100,0.0,0.0,0.0,0.0,0.0 +0,1.025200,0.0,0.0,0.0,0.0,0.0 +0,1.025300,0.0,0.0,0.0,0.0,0.0 +0,1.025400,0.0,0.0,0.0,0.0,0.0 +0,1.025500,0.0,0.0,0.0,0.0,0.0 +0,1.025600,0.0,0.0,0.0,0.0,0.0 +0,1.025700,0.0,0.0,0.0,0.0,0.0 +0,1.025800,0.0,0.0,0.0,0.0,0.0 +0,1.025900,0.0,0.0,0.0,0.0,0.0 +0,1.026000,0.0,0.0,0.0,0.0,0.0 +0,1.026100,0.0,0.0,0.0,0.0,0.0 +0,1.026200,0.0,0.0,0.0,0.0,0.0 +0,1.026300,0.0,0.0,0.0,0.0,0.0 +0,1.026400,0.0,0.0,0.0,0.0,0.0 +0,1.026500,0.0,0.0,0.0,0.0,0.0 +0,1.026600,0.0,0.0,0.0,0.0,0.0 +0,1.026700,0.0,0.0,0.0,0.0,0.0 +0,1.026800,0.0,0.0,0.0,0.0,0.0 +0,1.026900,0.0,0.0,0.0,0.0,0.0 +0,1.027000,0.0,0.0,0.0,0.0,0.0 +0,1.027100,0.0,0.0,0.0,0.0,0.0 +0,1.027200,0.0,0.0,0.0,0.0,0.0 +0,1.027300,0.0,0.0,0.0,0.0,0.0 +0,1.027400,0.0,0.0,0.0,0.0,0.0 +0,1.027500,0.0,0.0,0.0,0.0,0.0 +0,1.027600,0.0,0.0,0.0,0.0,0.0 +0,1.027700,0.0,0.0,0.0,0.0,0.0 +0,1.027800,0.0,0.0,0.0,0.0,0.0 +0,1.027900,0.0,0.0,0.0,0.0,0.0 +0,1.028000,0.0,0.0,0.0,0.0,0.0 +0,1.028100,0.0,0.0,0.0,0.0,0.0 +0,1.028200,0.0,0.0,0.0,0.0,0.0 +0,1.028300,0.0,0.0,0.0,0.0,0.0 +0,1.028400,0.0,0.0,0.0,0.0,0.0 +0,1.028500,0.0,0.0,0.0,0.0,0.0 +0,1.028600,0.0,0.0,0.0,0.0,0.0 +0,1.028700,0.0,0.0,0.0,0.0,0.0 +0,1.028800,0.0,0.0,0.0,0.0,0.0 +0,1.028900,0.0,0.0,0.0,0.0,0.0 +0,1.029000,0.0,0.0,0.0,0.0,0.0 +0,1.029100,0.0,0.0,0.0,0.0,0.0 +0,1.029200,0.0,0.0,0.0,0.0,0.0 +0,1.029300,0.0,0.0,0.0,0.0,0.0 +0,1.029400,0.0,0.0,0.0,0.0,0.0 +0,1.029500,0.0,0.0,0.0,0.0,0.0 +0,1.029600,0.0,0.0,0.0,0.0,0.0 +0,1.029700,0.0,0.0,0.0,0.0,0.0 +0,1.029800,0.0,0.0,0.0,0.0,0.0 +0,1.029900,0.0,0.0,0.0,0.0,0.0 +0,1.030000,0.0,0.0,0.0,0.0,0.0 +0,1.030100,0.0,0.0,0.0,0.0,0.0 +0,1.030200,0.0,0.0,0.0,0.0,0.0 +0,1.030300,0.0,0.0,0.0,0.0,0.0 +0,1.030400,0.0,0.0,0.0,0.0,0.0 +0,1.030500,0.0,0.0,0.0,0.0,0.0 +0,1.030600,0.0,0.0,0.0,0.0,0.0 +0,1.030700,0.0,0.0,0.0,0.0,0.0 +0,1.030800,0.0,0.0,0.0,0.0,0.0 +0,1.030900,0.0,0.0,0.0,0.0,0.0 +0,1.031000,0.0,0.0,0.0,0.0,0.0 +0,1.031100,0.0,0.0,0.0,0.0,0.0 +0,1.031200,0.0,0.0,0.0,0.0,0.0 +0,1.031300,0.0,0.0,0.0,0.0,0.0 +0,1.031400,0.0,0.0,0.0,0.0,0.0 +0,1.031500,0.0,0.0,0.0,0.0,0.0 +0,1.031600,0.0,0.0,0.0,0.0,0.0 +0,1.031700,0.0,0.0,0.0,0.0,0.0 +0,1.031800,0.0,0.0,0.0,0.0,0.0 +0,1.031900,0.0,0.0,0.0,0.0,0.0 +0,1.032000,0.0,0.0,0.0,0.0,0.0 +0,1.032100,0.0,0.0,0.0,0.0,0.0 +0,1.032200,0.0,0.0,0.0,0.0,0.0 +0,1.032300,0.0,0.0,0.0,0.0,0.0 +0,1.032400,0.0,0.0,0.0,0.0,0.0 +0,1.032500,0.0,0.0,0.0,0.0,0.0 +0,1.032600,0.0,0.0,0.0,0.0,0.0 +0,1.032700,0.0,0.0,0.0,0.0,0.0 +0,1.032800,0.0,0.0,0.0,0.0,0.0 +0,1.032900,0.0,0.0,0.0,0.0,0.0 +0,1.033000,0.0,0.0,0.0,0.0,0.0 +0,1.033100,0.0,0.0,0.0,0.0,0.0 +0,1.033200,0.0,0.0,0.0,0.0,0.0 +0,1.033300,0.0,0.0,0.0,0.0,0.0 +0,1.033400,0.0,0.0,0.0,0.0,0.0 +0,1.033500,0.0,0.0,0.0,0.0,0.0 +0,1.033600,0.0,0.0,0.0,0.0,0.0 +0,1.033700,0.0,0.0,0.0,0.0,0.0 +0,1.033800,0.0,0.0,0.0,0.0,0.0 +0,1.033900,0.0,0.0,0.0,0.0,0.0 +0,1.034000,0.0,0.0,0.0,0.0,0.0 +0,1.034100,0.0,0.0,0.0,0.0,0.0 +0,1.034200,0.0,0.0,0.0,0.0,0.0 +0,1.034300,0.0,0.0,0.0,0.0,0.0 +0,1.034400,0.0,0.0,0.0,0.0,0.0 +0,1.034500,0.0,0.0,0.0,0.0,0.0 +0,1.034600,0.0,0.0,0.0,0.0,0.0 +0,1.034700,0.0,0.0,0.0,0.0,0.0 +0,1.034800,0.0,0.0,0.0,0.0,0.0 +0,1.034900,0.0,0.0,0.0,0.0,0.0 +0,1.035000,0.0,0.0,0.0,0.0,0.0 +0,1.035100,0.0,0.0,0.0,0.0,0.0 +0,1.035200,0.0,0.0,0.0,0.0,0.0 +0,1.035300,0.0,0.0,0.0,0.0,0.0 +0,1.035400,0.0,0.0,0.0,0.0,0.0 +0,1.035500,0.0,0.0,0.0,0.0,0.0 +0,1.035600,0.0,0.0,0.0,0.0,0.0 +0,1.035700,0.0,0.0,0.0,0.0,0.0 +0,1.035800,0.0,0.0,0.0,0.0,0.0 +0,1.035900,0.0,0.0,0.0,0.0,0.0 +0,1.036000,0.0,0.0,0.0,0.0,0.0 +0,1.036100,0.0,0.0,0.0,0.0,0.0 +0,1.036200,0.0,0.0,0.0,0.0,0.0 +0,1.036300,0.0,0.0,0.0,0.0,0.0 +0,1.036400,0.0,0.0,0.0,0.0,0.0 +0,1.036500,0.0,0.0,0.0,0.0,0.0 +0,1.036600,0.0,0.0,0.0,0.0,0.0 +0,1.036700,0.0,0.0,0.0,0.0,0.0 +0,1.036800,0.0,0.0,0.0,0.0,0.0 +0,1.036900,0.0,0.0,0.0,0.0,0.0 +0,1.037000,0.0,0.0,0.0,0.0,0.0 +0,1.037100,0.0,0.0,0.0,0.0,0.0 +0,1.037200,0.0,0.0,0.0,0.0,0.0 +0,1.037300,0.0,0.0,0.0,0.0,0.0 +0,1.037400,0.0,0.0,0.0,0.0,0.0 +0,1.037500,0.0,0.0,0.0,0.0,0.0 +0,1.037600,0.0,0.0,0.0,0.0,0.0 +0,1.037700,0.0,0.0,0.0,0.0,0.0 +0,1.037800,0.0,0.0,0.0,0.0,0.0 +0,1.037900,0.0,0.0,0.0,0.0,0.0 +0,1.038000,0.0,0.0,0.0,0.0,0.0 +0,1.038100,0.0,0.0,0.0,0.0,0.0 +0,1.038200,0.0,0.0,0.0,0.0,0.0 +0,1.038300,0.0,0.0,0.0,0.0,0.0 +0,1.038400,0.0,0.0,0.0,0.0,0.0 +0,1.038500,0.0,0.0,0.0,0.0,0.0 +0,1.038600,0.0,0.0,0.0,0.0,0.0 +0,1.038700,0.0,0.0,0.0,0.0,0.0 +0,1.038800,0.0,0.0,0.0,0.0,0.0 +0,1.038900,0.0,0.0,0.0,0.0,0.0 +0,1.039000,0.0,0.0,0.0,0.0,0.0 +0,1.039100,0.0,0.0,0.0,0.0,0.0 +0,1.039200,0.0,0.0,0.0,0.0,0.0 +0,1.039300,0.0,0.0,0.0,0.0,0.0 +0,1.039400,0.0,0.0,0.0,0.0,0.0 +0,1.039500,0.0,0.0,0.0,0.0,0.0 +0,1.039600,0.0,0.0,0.0,0.0,0.0 +0,1.039700,0.0,0.0,0.0,0.0,0.0 +0,1.039800,0.0,0.0,0.0,0.0,0.0 +0,1.039900,0.0,0.0,0.0,0.0,0.0 +0,1.040000,0.0,0.0,0.0,0.0,0.0 +0,1.040100,0.0,0.0,0.0,0.0,0.0 +1,468.896162,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.040200,0.0,0.0,0.0,0.0,0.0 +0,1.040300,0.0,0.0,0.0,0.0,0.0 +0,1.040400,0.0,0.0,0.0,0.0,0.0 +0,1.040500,0.0,0.0,0.0,0.0,0.0 +0,1.040600,0.0,0.0,0.0,0.0,0.0 +0,1.040700,0.0,0.0,0.0,0.0,0.0 +0,1.040800,0.0,0.0,0.0,0.0,0.0 +0,1.040900,0.0,0.0,0.0,0.0,0.0 +0,1.041000,0.0,0.0,0.0,0.0,0.0 +0,1.041100,0.0,0.0,0.0,0.0,0.0 +0,1.041200,0.0,0.0,0.0,0.0,0.0 +0,1.041300,0.0,0.0,0.0,0.0,0.0 +0,1.041400,0.0,0.0,0.0,0.0,0.0 +0,1.041500,0.0,0.0,0.0,0.0,0.0 +0,1.041600,0.0,0.0,0.0,0.0,0.0 +0,1.041700,0.0,0.0,0.0,0.0,0.0 +0,1.041800,0.0,0.0,0.0,0.0,0.0 +0,1.041900,0.0,0.0,0.0,0.0,0.0 +0,1.042000,0.0,0.0,0.0,0.0,0.0 +0,1.042100,0.0,0.0,0.0,0.0,0.0 +0,1.042200,0.0,0.0,0.0,0.0,0.0 +0,1.042300,0.0,0.0,0.0,0.0,0.0 +0,1.042400,0.0,0.0,0.0,0.0,0.0 +0,1.042500,0.0,0.0,0.0,0.0,0.0 +0,1.042600,0.0,0.0,0.0,0.0,0.0 +0,1.042700,0.0,0.0,0.0,0.0,0.0 +0,1.042800,0.0,0.0,0.0,0.0,0.0 +0,1.042900,0.0,0.0,0.0,0.0,0.0 +0,1.043000,0.0,0.0,0.0,0.0,0.0 +0,1.043100,0.0,0.0,0.0,0.0,0.0 +0,1.043200,0.0,0.0,0.0,0.0,0.0 +0,1.043300,0.0,0.0,0.0,0.0,0.0 +0,1.043400,0.0,0.0,0.0,0.0,0.0 +0,1.043500,0.0,0.0,0.0,0.0,0.0 +0,1.043600,0.0,0.0,0.0,0.0,0.0 +0,1.043700,0.0,0.0,0.0,0.0,0.0 +0,1.043800,0.0,0.0,0.0,0.0,0.0 +0,1.043900,0.0,0.0,0.0,0.0,0.0 +0,1.044000,0.0,0.0,0.0,0.0,0.0 +0,1.044100,0.0,0.0,0.0,0.0,0.0 +0,1.044200,0.0,0.0,0.0,0.0,0.0 +0,1.044300,0.0,0.0,0.0,0.0,0.0 +0,1.044400,0.0,0.0,0.0,0.0,0.0 +0,1.044500,0.0,0.0,0.0,0.0,0.0 +0,1.044600,0.0,0.0,0.0,0.0,0.0 +0,1.044700,0.0,0.0,0.0,0.0,0.0 +0,1.044800,0.0,0.0,0.0,0.0,0.0 +0,1.044900,0.0,0.0,0.0,0.0,0.0 +0,1.045000,0.0,0.0,0.0,0.0,0.0 +0,1.045100,0.0,0.0,0.0,0.0,0.0 +0,1.045200,0.0,0.0,0.0,0.0,0.0 +0,1.045300,0.0,0.0,0.0,0.0,0.0 +0,1.045400,0.0,0.0,0.0,0.0,0.0 +0,1.045500,0.0,0.0,0.0,0.0,0.0 +0,1.045600,0.0,0.0,0.0,0.0,0.0 +0,1.045700,0.0,0.0,0.0,0.0,0.0 +0,1.045800,0.0,0.0,0.0,0.0,0.0 +0,1.045900,0.0,0.0,0.0,0.0,0.0 +0,1.046000,0.0,0.0,0.0,0.0,0.0 +0,1.046100,0.0,0.0,0.0,0.0,0.0 +0,1.046200,0.0,0.0,0.0,0.0,0.0 +0,1.046300,0.0,0.0,0.0,0.0,0.0 +0,1.046400,0.0,0.0,0.0,0.0,0.0 +0,1.046500,0.0,0.0,0.0,0.0,0.0 +0,1.046600,0.0,0.0,0.0,0.0,0.0 +0,1.046700,0.0,0.0,0.0,0.0,0.0 +0,1.046800,0.0,0.0,0.0,0.0,0.0 +0,1.046900,0.0,0.0,0.0,0.0,0.0 +0,1.047000,0.0,0.0,0.0,0.0,0.0 +0,1.047100,0.0,0.0,0.0,0.0,0.0 +0,1.047200,0.0,0.0,0.0,0.0,0.0 +0,1.047300,0.0,0.0,0.0,0.0,0.0 +0,1.047400,0.0,0.0,0.0,0.0,0.0 +0,1.047500,0.0,0.0,0.0,0.0,0.0 +0,1.047600,0.0,0.0,0.0,0.0,0.0 +0,1.047700,0.0,0.0,0.0,0.0,0.0 +0,1.047800,0.0,0.0,0.0,0.0,0.0 +0,1.047900,0.0,0.0,0.0,0.0,0.0 +0,1.048000,0.0,0.0,0.0,0.0,0.0 +0,1.048100,0.0,0.0,0.0,0.0,0.0 +0,1.048200,0.0,0.0,0.0,0.0,0.0 +0,1.048300,0.0,0.0,0.0,0.0,0.0 +0,1.048400,0.0,0.0,0.0,0.0,0.0 +0,1.048500,0.0,0.0,0.0,0.0,0.0 +0,1.048600,0.0,0.0,0.0,0.0,0.0 +0,1.048700,0.0,0.0,0.0,0.0,0.0 +0,1.048800,0.0,0.0,0.0,0.0,0.0 +0,1.048900,0.0,0.0,0.0,0.0,0.0 +0,1.049000,0.0,0.0,0.0,0.0,0.0 +0,1.049100,0.0,0.0,0.0,0.0,0.0 +0,1.049200,0.0,0.0,0.0,0.0,0.0 +0,1.049300,0.0,0.0,0.0,0.0,0.0 +0,1.049400,0.0,0.0,0.0,0.0,0.0 +0,1.049500,0.0,0.0,0.0,0.0,0.0 +0,1.049600,0.0,0.0,0.0,0.0,0.0 +0,1.049700,0.0,0.0,0.0,0.0,0.0 +0,1.049800,0.0,0.0,0.0,0.0,0.0 +0,1.049900,0.0,0.0,0.0,0.0,0.0 +0,1.050000,0.0,0.0,0.0,0.0,0.0 +0,1.050100,0.0,0.0,0.0,0.0,0.0 +0,1.050200,0.0,0.0,0.0,0.0,0.0 +0,1.050300,0.0,0.0,0.0,0.0,0.0 +0,1.050400,0.0,0.0,0.0,0.0,0.0 +0,1.050500,0.0,0.0,0.0,0.0,0.0 +0,1.050600,0.0,0.0,0.0,0.0,0.0 +0,1.050700,0.0,0.0,0.0,0.0,0.0 +0,1.050800,0.0,0.0,0.0,0.0,0.0 +0,1.050900,0.0,0.0,0.0,0.0,0.0 +0,1.051000,0.0,0.0,0.0,0.0,0.0 +0,1.051100,0.0,0.0,0.0,0.0,0.0 +0,1.051200,0.0,0.0,0.0,0.0,0.0 +0,1.051300,0.0,0.0,0.0,0.0,0.0 +0,1.051400,0.0,0.0,0.0,0.0,0.0 +0,1.051500,0.0,0.0,0.0,0.0,0.0 +0,1.051600,0.0,0.0,0.0,0.0,0.0 +0,1.051700,0.0,0.0,0.0,0.0,0.0 +0,1.051800,0.0,0.0,0.0,0.0,0.0 +0,1.051900,0.0,0.0,0.0,0.0,0.0 +0,1.052000,0.0,0.0,0.0,0.0,0.0 +0,1.052100,0.0,0.0,0.0,0.0,0.0 +0,1.052200,0.0,0.0,0.0,0.0,0.0 +0,1.052300,0.0,0.0,0.0,0.0,0.0 +0,1.052400,0.0,0.0,0.0,0.0,0.0 +0,1.052500,0.0,0.0,0.0,0.0,0.0 +0,1.052600,0.0,0.0,0.0,0.0,0.0 +0,1.052700,0.0,0.0,0.0,0.0,0.0 +0,1.052800,0.0,0.0,0.0,0.0,0.0 +0,1.052900,0.0,0.0,0.0,0.0,0.0 +0,1.053000,0.0,0.0,0.0,0.0,0.0 +0,1.053100,0.0,0.0,0.0,0.0,0.0 +0,1.053200,0.0,0.0,0.0,0.0,0.0 +0,1.053300,0.0,0.0,0.0,0.0,0.0 +0,1.053400,0.0,0.0,0.0,0.0,0.0 +0,1.053500,0.0,0.0,0.0,0.0,0.0 +0,1.053600,0.0,0.0,0.0,0.0,0.0 +0,1.053700,0.0,0.0,0.0,0.0,0.0 +0,1.053800,0.0,0.0,0.0,0.0,0.0 +0,1.053900,0.0,0.0,0.0,0.0,0.0 +0,1.054000,0.0,0.0,0.0,0.0,0.0 +0,1.054100,0.0,0.0,0.0,0.0,0.0 +0,1.054200,0.0,0.0,0.0,0.0,0.0 +0,1.054300,0.0,0.0,0.0,0.0,0.0 +0,1.054400,0.0,0.0,0.0,0.0,0.0 +0,1.054500,0.0,0.0,0.0,0.0,0.0 +0,1.054600,0.0,0.0,0.0,0.0,0.0 +0,1.054700,0.0,0.0,0.0,0.0,0.0 +0,1.054800,0.0,0.0,0.0,0.0,0.0 +0,1.054900,0.0,0.0,0.0,0.0,0.0 +0,1.055000,0.0,0.0,0.0,0.0,0.0 +0,1.055100,0.0,0.0,0.0,0.0,0.0 +0,1.055200,0.0,0.0,0.0,0.0,0.0 +0,1.055300,0.0,0.0,0.0,0.0,0.0 +0,1.055400,0.0,0.0,0.0,0.0,0.0 +0,1.055500,0.0,0.0,0.0,0.0,0.0 +0,1.055600,0.0,0.0,0.0,0.0,0.0 +0,1.055700,0.0,0.0,0.0,0.0,0.0 +0,1.055800,0.0,0.0,0.0,0.0,0.0 +0,1.055900,0.0,0.0,0.0,0.0,0.0 +0,1.056000,0.0,0.0,0.0,0.0,0.0 +0,1.056100,0.0,0.0,0.0,0.0,0.0 +0,1.056200,0.0,0.0,0.0,0.0,0.0 +0,1.056300,0.0,0.0,0.0,0.0,0.0 +0,1.056400,0.0,0.0,0.0,0.0,0.0 +0,1.056500,0.0,0.0,0.0,0.0,0.0 +0,1.056600,0.0,0.0,0.0,0.0,0.0 +0,1.056700,0.0,0.0,0.0,0.0,0.0 +0,1.056800,0.0,0.0,0.0,0.0,0.0 +0,1.056900,0.0,0.0,0.0,0.0,0.0 +0,1.057000,0.0,0.0,0.0,0.0,0.0 +0,1.057100,0.0,0.0,0.0,0.0,0.0 +0,1.057200,0.0,0.0,0.0,0.0,0.0 +0,1.057300,0.0,0.0,0.0,0.0,0.0 +0,1.057400,0.0,0.0,0.0,0.0,0.0 +0,1.057500,0.0,0.0,0.0,0.0,0.0 +0,1.057600,0.0,0.0,0.0,0.0,0.0 +0,1.057700,0.0,0.0,0.0,0.0,0.0 +0,1.057800,0.0,0.0,0.0,0.0,0.0 +0,1.057900,0.0,0.0,0.0,0.0,0.0 +0,1.058000,0.0,0.0,0.0,0.0,0.0 +0,1.058100,0.0,0.0,0.0,0.0,0.0 +0,1.058200,0.0,0.0,0.0,0.0,0.0 +0,1.058300,0.0,0.0,0.0,0.0,0.0 +0,1.058400,0.0,0.0,0.0,0.0,0.0 +0,1.058500,0.0,0.0,0.0,0.0,0.0 +0,1.058600,0.0,0.0,0.0,0.0,0.0 +0,1.058700,0.0,0.0,0.0,0.0,0.0 +0,1.058800,0.0,0.0,0.0,0.0,0.0 +0,1.058900,0.0,0.0,0.0,0.0,0.0 +0,1.059000,0.0,0.0,0.0,0.0,0.0 +0,1.059100,0.0,0.0,0.0,0.0,0.0 +0,1.059200,0.0,0.0,0.0,0.0,0.0 +0,1.059300,0.0,0.0,0.0,0.0,0.0 +0,1.059400,0.0,0.0,0.0,0.0,0.0 +0,1.059500,0.0,0.0,0.0,0.0,0.0 +0,1.059600,0.0,0.0,0.0,0.0,0.0 +0,1.059700,0.0,0.0,0.0,0.0,0.0 +0,1.059800,0.0,0.0,0.0,0.0,0.0 +0,1.059900,0.0,0.0,0.0,0.0,0.0 +0,1.060000,0.0,0.0,0.0,0.0,0.0 +0,1.060100,0.0,0.0,0.0,0.0,0.0 +1,496.467370,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.060200,0.0,0.0,0.0,0.0,0.0 +0,1.060300,0.0,0.0,0.0,0.0,0.0 +0,1.060400,0.0,0.0,0.0,0.0,0.0 +0,1.060500,0.0,0.0,0.0,0.0,0.0 +0,1.060600,0.0,0.0,0.0,0.0,0.0 +0,1.060700,0.0,0.0,0.0,0.0,0.0 +0,1.060800,0.0,0.0,0.0,0.0,0.0 +0,1.060900,0.0,0.0,0.0,0.0,0.0 +0,1.061000,0.0,0.0,0.0,0.0,0.0 +0,1.061100,0.0,0.0,0.0,0.0,0.0 +0,1.061200,0.0,0.0,0.0,0.0,0.0 +0,1.061300,0.0,0.0,0.0,0.0,0.0 +0,1.061400,0.0,0.0,0.0,0.0,0.0 +0,1.061500,0.0,0.0,0.0,0.0,0.0 +0,1.061600,0.0,0.0,0.0,0.0,0.0 +0,1.061700,0.0,0.0,0.0,0.0,0.0 +0,1.061800,0.0,0.0,0.0,0.0,0.0 +0,1.061900,0.0,0.0,0.0,0.0,0.0 +0,1.062000,0.0,0.0,0.0,0.0,0.0 +0,1.062100,0.0,0.0,0.0,0.0,0.0 +0,1.062200,0.0,0.0,0.0,0.0,0.0 +0,1.062300,0.0,0.0,0.0,0.0,0.0 +0,1.062400,0.0,0.0,0.0,0.0,0.0 +0,1.062500,0.0,0.0,0.0,0.0,0.0 +0,1.062600,0.0,0.0,0.0,0.0,0.0 +0,1.062700,0.0,0.0,0.0,0.0,0.0 +0,1.062800,0.0,0.0,0.0,0.0,0.0 +0,1.062900,0.0,0.0,0.0,0.0,0.0 +0,1.063000,0.0,0.0,0.0,0.0,0.0 +0,1.063100,0.0,0.0,0.0,0.0,0.0 +0,1.063200,0.0,0.0,0.0,0.0,0.0 +0,1.063300,0.0,0.0,0.0,0.0,0.0 +0,1.063400,0.0,0.0,0.0,0.0,0.0 +0,1.063500,0.0,0.0,0.0,0.0,0.0 +0,1.063600,0.0,0.0,0.0,0.0,0.0 +0,1.063700,0.0,0.0,0.0,0.0,0.0 +0,1.063800,0.0,0.0,0.0,0.0,0.0 +0,1.063900,0.0,0.0,0.0,0.0,0.0 +0,1.064000,0.0,0.0,0.0,0.0,0.0 +0,1.064100,0.0,0.0,0.0,0.0,0.0 +0,1.064200,0.0,0.0,0.0,0.0,0.0 +0,1.064300,0.0,0.0,0.0,0.0,0.0 +0,1.064400,0.0,0.0,0.0,0.0,0.0 +0,1.064500,0.0,0.0,0.0,0.0,0.0 +0,1.064600,0.0,0.0,0.0,0.0,0.0 +0,1.064700,0.0,0.0,0.0,0.0,0.0 +0,1.064800,0.0,0.0,0.0,0.0,0.0 +0,1.064900,0.0,0.0,0.0,0.0,0.0 +0,1.065000,0.0,0.0,0.0,0.0,0.0 +0,1.065100,0.0,0.0,0.0,0.0,0.0 +0,1.065200,0.0,0.0,0.0,0.0,0.0 +0,1.065300,0.0,0.0,0.0,0.0,0.0 +0,1.065400,0.0,0.0,0.0,0.0,0.0 +0,1.065500,0.0,0.0,0.0,0.0,0.0 +0,1.065600,0.0,0.0,0.0,0.0,0.0 +0,1.065700,0.0,0.0,0.0,0.0,0.0 +0,1.065800,0.0,0.0,0.0,0.0,0.0 +0,1.065900,0.0,0.0,0.0,0.0,0.0 +0,1.066000,0.0,0.0,0.0,0.0,0.0 +0,1.066100,0.0,0.0,0.0,0.0,0.0 +0,1.066200,0.0,0.0,0.0,0.0,0.0 +0,1.066300,0.0,0.0,0.0,0.0,0.0 +0,1.066400,0.0,0.0,0.0,0.0,0.0 +0,1.066500,0.0,0.0,0.0,0.0,0.0 +0,1.066600,0.0,0.0,0.0,0.0,0.0 +0,1.066700,0.0,0.0,0.0,0.0,0.0 +0,1.066800,0.0,0.0,0.0,0.0,0.0 +0,1.066900,0.0,0.0,0.0,0.0,0.0 +0,1.067000,0.0,0.0,0.0,0.0,0.0 +0,1.067100,0.0,0.0,0.0,0.0,0.0 +0,1.067200,0.0,0.0,0.0,0.0,0.0 +0,1.067300,0.0,0.0,0.0,0.0,0.0 +0,1.067400,0.0,0.0,0.0,0.0,0.0 +0,1.067500,0.0,0.0,0.0,0.0,0.0 +0,1.067600,0.0,0.0,0.0,0.0,0.0 +0,1.067700,0.0,0.0,0.0,0.0,0.0 +0,1.067800,0.0,0.0,0.0,0.0,0.0 +0,1.067900,0.0,0.0,0.0,0.0,0.0 +0,1.068000,0.0,0.0,0.0,0.0,0.0 +0,1.068100,0.0,0.0,0.0,0.0,0.0 +0,1.068200,0.0,0.0,0.0,0.0,0.0 +0,1.068300,0.0,0.0,0.0,0.0,0.0 +0,1.068400,0.0,0.0,0.0,0.0,0.0 +0,1.068500,0.0,0.0,0.0,0.0,0.0 +0,1.068600,0.0,0.0,0.0,0.0,0.0 +0,1.068700,0.0,0.0,0.0,0.0,0.0 +0,1.068800,0.0,0.0,0.0,0.0,0.0 +0,1.068900,0.0,0.0,0.0,0.0,0.0 +0,1.069000,0.0,0.0,0.0,0.0,0.0 +0,1.069100,0.0,0.0,0.0,0.0,0.0 +0,1.069200,0.0,0.0,0.0,0.0,0.0 +0,1.069300,0.0,0.0,0.0,0.0,0.0 +0,1.069400,0.0,0.0,0.0,0.0,0.0 +0,1.069500,0.0,0.0,0.0,0.0,0.0 +0,1.069600,0.0,0.0,0.0,0.0,0.0 +0,1.069700,0.0,0.0,0.0,0.0,0.0 +0,1.069800,0.0,0.0,0.0,0.0,0.0 +0,1.069900,0.0,0.0,0.0,0.0,0.0 +0,1.070000,0.0,0.0,0.0,0.0,0.0 +0,1.070100,0.0,0.0,0.0,0.0,0.0 +0,1.070200,0.0,0.0,0.0,0.0,0.0 +0,1.070300,0.0,0.0,0.0,0.0,0.0 +0,1.070400,0.0,0.0,0.0,0.0,0.0 +0,1.070500,0.0,0.0,0.0,0.0,0.0 +0,1.070600,0.0,0.0,0.0,0.0,0.0 +0,1.070700,0.0,0.0,0.0,0.0,0.0 +0,1.070800,0.0,0.0,0.0,0.0,0.0 +0,1.070900,0.0,0.0,0.0,0.0,0.0 +0,1.071000,0.0,0.0,0.0,0.0,0.0 +0,1.071100,0.0,0.0,0.0,0.0,0.0 +0,1.071200,0.0,0.0,0.0,0.0,0.0 +0,1.071300,0.0,0.0,0.0,0.0,0.0 +0,1.071400,0.0,0.0,0.0,0.0,0.0 +0,1.071500,0.0,0.0,0.0,0.0,0.0 +0,1.071600,0.0,0.0,0.0,0.0,0.0 +0,1.071700,0.0,0.0,0.0,0.0,0.0 +0,1.071800,0.0,0.0,0.0,0.0,0.0 +0,1.071900,0.0,0.0,0.0,0.0,0.0 +0,1.072000,0.0,0.0,0.0,0.0,0.0 +0,1.072100,0.0,0.0,0.0,0.0,0.0 +0,1.072200,0.0,0.0,0.0,0.0,0.0 +0,1.072300,0.0,0.0,0.0,0.0,0.0 +0,1.072400,0.0,0.0,0.0,0.0,0.0 +0,1.072500,0.0,0.0,0.0,0.0,0.0 +0,1.072600,0.0,0.0,0.0,0.0,0.0 +0,1.072700,0.0,0.0,0.0,0.0,0.0 +0,1.072800,0.0,0.0,0.0,0.0,0.0 +0,1.072900,0.0,0.0,0.0,0.0,0.0 +0,1.073000,0.0,0.0,0.0,0.0,0.0 +0,1.073100,0.0,0.0,0.0,0.0,0.0 +0,1.073200,0.0,0.0,0.0,0.0,0.0 +0,1.073300,0.0,0.0,0.0,0.0,0.0 +0,1.073400,0.0,0.0,0.0,0.0,0.0 +0,1.073500,0.0,0.0,0.0,0.0,0.0 +0,1.073600,0.0,0.0,0.0,0.0,0.0 +0,1.073700,0.0,0.0,0.0,0.0,0.0 +0,1.073800,0.0,0.0,0.0,0.0,0.0 +0,1.073900,0.0,0.0,0.0,0.0,0.0 +0,1.074000,0.0,0.0,0.0,0.0,0.0 +0,1.074100,0.0,0.0,0.0,0.0,0.0 +0,1.074200,0.0,0.0,0.0,0.0,0.0 +0,1.074300,0.0,0.0,0.0,0.0,0.0 +0,1.074400,0.0,0.0,0.0,0.0,0.0 +0,1.074500,0.0,0.0,0.0,0.0,0.0 +0,1.074600,0.0,0.0,0.0,0.0,0.0 +0,1.074700,0.0,0.0,0.0,0.0,0.0 +0,1.074800,0.0,0.0,0.0,0.0,0.0 +0,1.074900,0.0,0.0,0.0,0.0,0.0 +0,1.075000,0.0,0.0,0.0,0.0,0.0 +0,1.075100,0.0,0.0,0.0,0.0,0.0 +0,1.075200,0.0,0.0,0.0,0.0,0.0 +0,1.075300,0.0,0.0,0.0,0.0,0.0 +0,1.075400,0.0,0.0,0.0,0.0,0.0 +0,1.075500,0.0,0.0,0.0,0.0,0.0 +0,1.075600,0.0,0.0,0.0,0.0,0.0 +0,1.075700,0.0,0.0,0.0,0.0,0.0 +0,1.075800,0.0,0.0,0.0,0.0,0.0 +0,1.075900,0.0,0.0,0.0,0.0,0.0 +0,1.076000,0.0,0.0,0.0,0.0,0.0 +0,1.076100,0.0,0.0,0.0,0.0,0.0 +0,1.076200,0.0,0.0,0.0,0.0,0.0 +0,1.076300,0.0,0.0,0.0,0.0,0.0 +0,1.076400,0.0,0.0,0.0,0.0,0.0 +0,1.076500,0.0,0.0,0.0,0.0,0.0 +0,1.076600,0.0,0.0,0.0,0.0,0.0 +0,1.076700,0.0,0.0,0.0,0.0,0.0 +0,1.076800,0.0,0.0,0.0,0.0,0.0 +0,1.076900,0.0,0.0,0.0,0.0,0.0 +0,1.077000,0.0,0.0,0.0,0.0,0.0 +0,1.077100,0.0,0.0,0.0,0.0,0.0 +0,1.077200,0.0,0.0,0.0,0.0,0.0 +0,1.077300,0.0,0.0,0.0,0.0,0.0 +0,1.077400,0.0,0.0,0.0,0.0,0.0 +0,1.077500,0.0,0.0,0.0,0.0,0.0 +0,1.077600,0.0,0.0,0.0,0.0,0.0 +0,1.077700,0.0,0.0,0.0,0.0,0.0 +0,1.077800,0.0,0.0,0.0,0.0,0.0 +0,1.077900,0.0,0.0,0.0,0.0,0.0 +0,1.078000,0.0,0.0,0.0,0.0,0.0 +0,1.078100,0.0,0.0,0.0,0.0,0.0 +0,1.078200,0.0,0.0,0.0,0.0,0.0 +0,1.078300,0.0,0.0,0.0,0.0,0.0 +0,1.078400,0.0,0.0,0.0,0.0,0.0 +0,1.078500,0.0,0.0,0.0,0.0,0.0 +0,1.078600,0.0,0.0,0.0,0.0,0.0 +0,1.078700,0.0,0.0,0.0,0.0,0.0 +0,1.078800,0.0,0.0,0.0,0.0,0.0 +0,1.078900,0.0,0.0,0.0,0.0,0.0 +0,1.079000,0.0,0.0,0.0,0.0,0.0 +0,1.079100,0.0,0.0,0.0,0.0,0.0 +0,1.079200,0.0,0.0,0.0,0.0,0.0 +0,1.079300,0.0,0.0,0.0,0.0,0.0 +0,1.079400,0.0,0.0,0.0,0.0,0.0 +0,1.079500,0.0,0.0,0.0,0.0,0.0 +0,1.079600,0.0,0.0,0.0,0.0,0.0 +0,1.079700,0.0,0.0,0.0,0.0,0.0 +0,1.079800,0.0,0.0,0.0,0.0,0.0 +0,1.079900,0.0,0.0,0.0,0.0,0.0 +0,1.080000,0.0,0.0,0.0,0.0,0.0 +0,1.080100,0.0,0.0,0.0,0.0,0.0 +1,525.098729,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.080200,0.0,0.0,0.0,0.0,0.0 +0,1.080300,0.0,0.0,0.0,0.0,0.0 +0,1.080400,0.0,0.0,0.0,0.0,0.0 +0,1.080500,0.0,0.0,0.0,0.0,0.0 +0,1.080600,0.0,0.0,0.0,0.0,0.0 +0,1.080700,0.0,0.0,0.0,0.0,0.0 +0,1.080800,0.0,0.0,0.0,0.0,0.0 +0,1.080900,0.0,0.0,0.0,0.0,0.0 +0,1.081000,0.0,0.0,0.0,0.0,0.0 +0,1.081100,0.0,0.0,0.0,0.0,0.0 +0,1.081200,0.0,0.0,0.0,0.0,0.0 +0,1.081300,0.0,0.0,0.0,0.0,0.0 +0,1.081400,0.0,0.0,0.0,0.0,0.0 +0,1.081500,0.0,0.0,0.0,0.0,0.0 +0,1.081600,0.0,0.0,0.0,0.0,0.0 +0,1.081700,0.0,0.0,0.0,0.0,0.0 +0,1.081800,0.0,0.0,0.0,0.0,0.0 +0,1.081900,0.0,0.0,0.0,0.0,0.0 +0,1.082000,0.0,0.0,0.0,0.0,0.0 +0,1.082100,0.0,0.0,0.0,0.0,0.0 +0,1.082200,0.0,0.0,0.0,0.0,0.0 +0,1.082300,0.0,0.0,0.0,0.0,0.0 +0,1.082400,0.0,0.0,0.0,0.0,0.0 +0,1.082500,0.0,0.0,0.0,0.0,0.0 +0,1.082600,0.0,0.0,0.0,0.0,0.0 +0,1.082700,0.0,0.0,0.0,0.0,0.0 +0,1.082800,0.0,0.0,0.0,0.0,0.0 +0,1.082900,0.0,0.0,0.0,0.0,0.0 +0,1.083000,0.0,0.0,0.0,0.0,0.0 +0,1.083100,0.0,0.0,0.0,0.0,0.0 +0,1.083200,0.0,0.0,0.0,0.0,0.0 +0,1.083300,0.0,0.0,0.0,0.0,0.0 +0,1.083400,0.0,0.0,0.0,0.0,0.0 +0,1.083500,0.0,0.0,0.0,0.0,0.0 +0,1.083600,0.0,0.0,0.0,0.0,0.0 +0,1.083700,0.0,0.0,0.0,0.0,0.0 +0,1.083800,0.0,0.0,0.0,0.0,0.0 +0,1.083900,0.0,0.0,0.0,0.0,0.0 +0,1.084000,0.0,0.0,0.0,0.0,0.0 +0,1.084100,0.0,0.0,0.0,0.0,0.0 +0,1.084200,0.0,0.0,0.0,0.0,0.0 +0,1.084300,0.0,0.0,0.0,0.0,0.0 +0,1.084400,0.0,0.0,0.0,0.0,0.0 +0,1.084500,0.0,0.0,0.0,0.0,0.0 +0,1.084600,0.0,0.0,0.0,0.0,0.0 +0,1.084700,0.0,0.0,0.0,0.0,0.0 +0,1.084800,0.0,0.0,0.0,0.0,0.0 +0,1.084900,0.0,0.0,0.0,0.0,0.0 +0,1.085000,0.0,0.0,0.0,0.0,0.0 +0,1.085100,0.0,0.0,0.0,0.0,0.0 +0,1.085200,0.0,0.0,0.0,0.0,0.0 +0,1.085300,0.0,0.0,0.0,0.0,0.0 +0,1.085400,0.0,0.0,0.0,0.0,0.0 +0,1.085500,0.0,0.0,0.0,0.0,0.0 +0,1.085600,0.0,0.0,0.0,0.0,0.0 +0,1.085700,0.0,0.0,0.0,0.0,0.0 +0,1.085800,0.0,0.0,0.0,0.0,0.0 +0,1.085900,0.0,0.0,0.0,0.0,0.0 +0,1.086000,0.0,0.0,0.0,0.0,0.0 +0,1.086100,0.0,0.0,0.0,0.0,0.0 +0,1.086200,0.0,0.0,0.0,0.0,0.0 +0,1.086300,0.0,0.0,0.0,0.0,0.0 +0,1.086400,0.0,0.0,0.0,0.0,0.0 +0,1.086500,0.0,0.0,0.0,0.0,0.0 +0,1.086600,0.0,0.0,0.0,0.0,0.0 +0,1.086700,0.0,0.0,0.0,0.0,0.0 +0,1.086800,0.0,0.0,0.0,0.0,0.0 +0,1.086900,0.0,0.0,0.0,0.0,0.0 +0,1.087000,0.0,0.0,0.0,0.0,0.0 +0,1.087100,0.0,0.0,0.0,0.0,0.0 +0,1.087200,0.0,0.0,0.0,0.0,0.0 +0,1.087300,0.0,0.0,0.0,0.0,0.0 +0,1.087400,0.0,0.0,0.0,0.0,0.0 +0,1.087500,0.0,0.0,0.0,0.0,0.0 +0,1.087600,0.0,0.0,0.0,0.0,0.0 +0,1.087700,0.0,0.0,0.0,0.0,0.0 +0,1.087800,0.0,0.0,0.0,0.0,0.0 +0,1.087900,0.0,0.0,0.0,0.0,0.0 +0,1.088000,0.0,0.0,0.0,0.0,0.0 +0,1.088100,0.0,0.0,0.0,0.0,0.0 +0,1.088200,0.0,0.0,0.0,0.0,0.0 +0,1.088300,0.0,0.0,0.0,0.0,0.0 +0,1.088400,0.0,0.0,0.0,0.0,0.0 +0,1.088500,0.0,0.0,0.0,0.0,0.0 +0,1.088600,0.0,0.0,0.0,0.0,0.0 +0,1.088700,0.0,0.0,0.0,0.0,0.0 +0,1.088800,0.0,0.0,0.0,0.0,0.0 +0,1.088900,0.0,0.0,0.0,0.0,0.0 +0,1.089000,0.0,0.0,0.0,0.0,0.0 +0,1.089100,0.0,0.0,0.0,0.0,0.0 +0,1.089200,0.0,0.0,0.0,0.0,0.0 +0,1.089300,0.0,0.0,0.0,0.0,0.0 +0,1.089400,0.0,0.0,0.0,0.0,0.0 +0,1.089500,0.0,0.0,0.0,0.0,0.0 +0,1.089600,0.0,0.0,0.0,0.0,0.0 +0,1.089700,0.0,0.0,0.0,0.0,0.0 +0,1.089800,0.0,0.0,0.0,0.0,0.0 +0,1.089900,0.0,0.0,0.0,0.0,0.0 +0,1.090000,0.0,0.0,0.0,0.0,0.0 +0,1.090100,0.0,0.0,0.0,0.0,0.0 +0,1.090200,0.0,0.0,0.0,0.0,0.0 +0,1.090300,0.0,0.0,0.0,0.0,0.0 +0,1.090400,0.0,0.0,0.0,0.0,0.0 +0,1.090500,0.0,0.0,0.0,0.0,0.0 +0,1.090600,0.0,0.0,0.0,0.0,0.0 +0,1.090700,0.0,0.0,0.0,0.0,0.0 +0,1.090800,0.0,0.0,0.0,0.0,0.0 +0,1.090900,0.0,0.0,0.0,0.0,0.0 +0,1.091000,0.0,0.0,0.0,0.0,0.0 +0,1.091100,0.0,0.0,0.0,0.0,0.0 +0,1.091200,0.0,0.0,0.0,0.0,0.0 +0,1.091300,0.0,0.0,0.0,0.0,0.0 +0,1.091400,0.0,0.0,0.0,0.0,0.0 +0,1.091500,0.0,0.0,0.0,0.0,0.0 +0,1.091600,0.0,0.0,0.0,0.0,0.0 +0,1.091700,0.0,0.0,0.0,0.0,0.0 +0,1.091800,0.0,0.0,0.0,0.0,0.0 +0,1.091900,0.0,0.0,0.0,0.0,0.0 +0,1.092000,0.0,0.0,0.0,0.0,0.0 +0,1.092100,0.0,0.0,0.0,0.0,0.0 +0,1.092200,0.0,0.0,0.0,0.0,0.0 +0,1.092300,0.0,0.0,0.0,0.0,0.0 +0,1.092400,0.0,0.0,0.0,0.0,0.0 +0,1.092500,0.0,0.0,0.0,0.0,0.0 +0,1.092600,0.0,0.0,0.0,0.0,0.0 +0,1.092700,0.0,0.0,0.0,0.0,0.0 +0,1.092800,0.0,0.0,0.0,0.0,0.0 +0,1.092900,0.0,0.0,0.0,0.0,0.0 +0,1.093000,0.0,0.0,0.0,0.0,0.0 +0,1.093100,0.0,0.0,0.0,0.0,0.0 +0,1.093200,0.0,0.0,0.0,0.0,0.0 +0,1.093300,0.0,0.0,0.0,0.0,0.0 +0,1.093400,0.0,0.0,0.0,0.0,0.0 +0,1.093500,0.0,0.0,0.0,0.0,0.0 +0,1.093600,0.0,0.0,0.0,0.0,0.0 +0,1.093700,0.0,0.0,0.0,0.0,0.0 +0,1.093800,0.0,0.0,0.0,0.0,0.0 +0,1.093900,0.0,0.0,0.0,0.0,0.0 +0,1.094000,0.0,0.0,0.0,0.0,0.0 +0,1.094100,0.0,0.0,0.0,0.0,0.0 +0,1.094200,0.0,0.0,0.0,0.0,0.0 +0,1.094300,0.0,0.0,0.0,0.0,0.0 +0,1.094400,0.0,0.0,0.0,0.0,0.0 +0,1.094500,0.0,0.0,0.0,0.0,0.0 +0,1.094600,0.0,0.0,0.0,0.0,0.0 +0,1.094700,0.0,0.0,0.0,0.0,0.0 +0,1.094800,0.0,0.0,0.0,0.0,0.0 +0,1.094900,0.0,0.0,0.0,0.0,0.0 +0,1.095000,0.0,0.0,0.0,0.0,0.0 +0,1.095100,0.0,0.0,0.0,0.0,0.0 +0,1.095200,0.0,0.0,0.0,0.0,0.0 +0,1.095300,0.0,0.0,0.0,0.0,0.0 +0,1.095400,0.0,0.0,0.0,0.0,0.0 +0,1.095500,0.0,0.0,0.0,0.0,0.0 +0,1.095600,0.0,0.0,0.0,0.0,0.0 +0,1.095700,0.0,0.0,0.0,0.0,0.0 +0,1.095800,0.0,0.0,0.0,0.0,0.0 +0,1.095900,0.0,0.0,0.0,0.0,0.0 +0,1.096000,0.0,0.0,0.0,0.0,0.0 +0,1.096100,0.0,0.0,0.0,0.0,0.0 +0,1.096200,0.0,0.0,0.0,0.0,0.0 +0,1.096300,0.0,0.0,0.0,0.0,0.0 +0,1.096400,0.0,0.0,0.0,0.0,0.0 +0,1.096500,0.0,0.0,0.0,0.0,0.0 +0,1.096600,0.0,0.0,0.0,0.0,0.0 +0,1.096700,0.0,0.0,0.0,0.0,0.0 +0,1.096800,0.0,0.0,0.0,0.0,0.0 +0,1.096900,0.0,0.0,0.0,0.0,0.0 +0,1.097000,0.0,0.0,0.0,0.0,0.0 +0,1.097100,0.0,0.0,0.0,0.0,0.0 +0,1.097200,0.0,0.0,0.0,0.0,0.0 +0,1.097300,0.0,0.0,0.0,0.0,0.0 +0,1.097400,0.0,0.0,0.0,0.0,0.0 +0,1.097500,0.0,0.0,0.0,0.0,0.0 +0,1.097600,0.0,0.0,0.0,0.0,0.0 +0,1.097700,0.0,0.0,0.0,0.0,0.0 +0,1.097800,0.0,0.0,0.0,0.0,0.0 +0,1.097900,0.0,0.0,0.0,0.0,0.0 +0,1.098000,0.0,0.0,0.0,0.0,0.0 +0,1.098100,0.0,0.0,0.0,0.0,0.0 +0,1.098200,0.0,0.0,0.0,0.0,0.0 +0,1.098300,0.0,0.0,0.0,0.0,0.0 +0,1.098400,0.0,0.0,0.0,0.0,0.0 +0,1.098500,0.0,0.0,0.0,0.0,0.0 +0,1.098600,0.0,0.0,0.0,0.0,0.0 +0,1.098700,0.0,0.0,0.0,0.0,0.0 +0,1.098800,0.0,0.0,0.0,0.0,0.0 +0,1.098900,0.0,0.0,0.0,0.0,0.0 +0,1.099000,0.0,0.0,0.0,0.0,0.0 +0,1.099100,0.0,0.0,0.0,0.0,0.0 +0,1.099200,0.0,0.0,0.0,0.0,0.0 +0,1.099300,0.0,0.0,0.0,0.0,0.0 +0,1.099400,0.0,0.0,0.0,0.0,0.0 +0,1.099500,0.0,0.0,0.0,0.0,0.0 +0,1.099600,0.0,0.0,0.0,0.0,0.0 +0,1.099700,0.0,0.0,0.0,0.0,0.0 +0,1.099800,0.0,0.0,0.0,0.0,0.0 +0,1.099900,0.0,0.0,0.0,0.0,0.0 +0,1.100000,0.0,0.0,0.0,0.0,0.0 +0,1.100100,0.0,0.0,0.0,0.0,0.0 +1,554.810238,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.100200,0.0,0.0,0.0,0.0,0.0 +0,1.100300,0.0,0.0,0.0,0.0,0.0 +0,1.100400,0.0,0.0,0.0,0.0,0.0 +0,1.100500,0.0,0.0,0.0,0.0,0.0 +0,1.100600,0.0,0.0,0.0,0.0,0.0 +0,1.100700,0.0,0.0,0.0,0.0,0.0 +0,1.100800,0.0,0.0,0.0,0.0,0.0 +0,1.100900,0.0,0.0,0.0,0.0,0.0 +0,1.101000,0.0,0.0,0.0,0.0,0.0 +0,1.101100,0.0,0.0,0.0,0.0,0.0 +0,1.101200,0.0,0.0,0.0,0.0,0.0 +0,1.101300,0.0,0.0,0.0,0.0,0.0 +0,1.101400,0.0,0.0,0.0,0.0,0.0 +0,1.101500,0.0,0.0,0.0,0.0,0.0 +0,1.101600,0.0,0.0,0.0,0.0,0.0 +0,1.101700,0.0,0.0,0.0,0.0,0.0 +0,1.101800,0.0,0.0,0.0,0.0,0.0 +0,1.101900,0.0,0.0,0.0,0.0,0.0 +0,1.102000,0.0,0.0,0.0,0.0,0.0 +0,1.102100,0.0,0.0,0.0,0.0,0.0 +0,1.102200,0.0,0.0,0.0,0.0,0.0 +0,1.102300,0.0,0.0,0.0,0.0,0.0 +0,1.102400,0.0,0.0,0.0,0.0,0.0 +0,1.102500,0.0,0.0,0.0,0.0,0.0 +0,1.102600,0.0,0.0,0.0,0.0,0.0 +0,1.102700,0.0,0.0,0.0,0.0,0.0 +0,1.102800,0.0,0.0,0.0,0.0,0.0 +0,1.102900,0.0,0.0,0.0,0.0,0.0 +0,1.103000,0.0,0.0,0.0,0.0,0.0 +0,1.103100,0.0,0.0,0.0,0.0,0.0 +0,1.103200,0.0,0.0,0.0,0.0,0.0 +0,1.103300,0.0,0.0,0.0,0.0,0.0 +0,1.103400,0.0,0.0,0.0,0.0,0.0 +0,1.103500,0.0,0.0,0.0,0.0,0.0 +0,1.103600,0.0,0.0,0.0,0.0,0.0 +0,1.103700,0.0,0.0,0.0,0.0,0.0 +0,1.103800,0.0,0.0,0.0,0.0,0.0 +0,1.103900,0.0,0.0,0.0,0.0,0.0 +0,1.104000,0.0,0.0,0.0,0.0,0.0 +0,1.104100,0.0,0.0,0.0,0.0,0.0 +0,1.104200,0.0,0.0,0.0,0.0,0.0 +0,1.104300,0.0,0.0,0.0,0.0,0.0 +0,1.104400,0.0,0.0,0.0,0.0,0.0 +0,1.104500,0.0,0.0,0.0,0.0,0.0 +0,1.104600,0.0,0.0,0.0,0.0,0.0 +0,1.104700,0.0,0.0,0.0,0.0,0.0 +0,1.104800,0.0,0.0,0.0,0.0,0.0 +0,1.104900,0.0,0.0,0.0,0.0,0.0 +0,1.105000,0.0,0.0,0.0,0.0,0.0 +0,1.105100,0.0,0.0,0.0,0.0,0.0 +0,1.105200,0.0,0.0,0.0,0.0,0.0 +0,1.105300,0.0,0.0,0.0,0.0,0.0 +0,1.105400,0.0,0.0,0.0,0.0,0.0 +0,1.105500,0.0,0.0,0.0,0.0,0.0 +0,1.105600,0.0,0.0,0.0,0.0,0.0 +0,1.105700,0.0,0.0,0.0,0.0,0.0 +0,1.105800,0.0,0.0,0.0,0.0,0.0 +0,1.105900,0.0,0.0,0.0,0.0,0.0 +0,1.106000,0.0,0.0,0.0,0.0,0.0 +0,1.106100,0.0,0.0,0.0,0.0,0.0 +0,1.106200,0.0,0.0,0.0,0.0,0.0 +0,1.106300,0.0,0.0,0.0,0.0,0.0 +0,1.106400,0.0,0.0,0.0,0.0,0.0 +0,1.106500,0.0,0.0,0.0,0.0,0.0 +0,1.106600,0.0,0.0,0.0,0.0,0.0 +0,1.106700,0.0,0.0,0.0,0.0,0.0 +0,1.106800,0.0,0.0,0.0,0.0,0.0 +0,1.106900,0.0,0.0,0.0,0.0,0.0 +0,1.107000,0.0,0.0,0.0,0.0,0.0 +0,1.107100,0.0,0.0,0.0,0.0,0.0 +0,1.107200,0.0,0.0,0.0,0.0,0.0 +0,1.107300,0.0,0.0,0.0,0.0,0.0 +0,1.107400,0.0,0.0,0.0,0.0,0.0 +0,1.107500,0.0,0.0,0.0,0.0,0.0 +0,1.107600,0.0,0.0,0.0,0.0,0.0 +0,1.107700,0.0,0.0,0.0,0.0,0.0 +0,1.107800,0.0,0.0,0.0,0.0,0.0 +0,1.107900,0.0,0.0,0.0,0.0,0.0 +0,1.108000,0.0,0.0,0.0,0.0,0.0 +0,1.108100,0.0,0.0,0.0,0.0,0.0 +0,1.108200,0.0,0.0,0.0,0.0,0.0 +0,1.108300,0.0,0.0,0.0,0.0,0.0 +0,1.108400,0.0,0.0,0.0,0.0,0.0 +0,1.108500,0.0,0.0,0.0,0.0,0.0 +0,1.108600,0.0,0.0,0.0,0.0,0.0 +0,1.108700,0.0,0.0,0.0,0.0,0.0 +0,1.108800,0.0,0.0,0.0,0.0,0.0 +0,1.108900,0.0,0.0,0.0,0.0,0.0 +0,1.109000,0.0,0.0,0.0,0.0,0.0 +0,1.109100,0.0,0.0,0.0,0.0,0.0 +0,1.109200,0.0,0.0,0.0,0.0,0.0 +0,1.109300,0.0,0.0,0.0,0.0,0.0 +0,1.109400,0.0,0.0,0.0,0.0,0.0 +0,1.109500,0.0,0.0,0.0,0.0,0.0 +0,1.109600,0.0,0.0,0.0,0.0,0.0 +0,1.109700,0.0,0.0,0.0,0.0,0.0 +0,1.109800,0.0,0.0,0.0,0.0,0.0 +0,1.109900,0.0,0.0,0.0,0.0,0.0 +0,1.110000,0.0,0.0,0.0,0.0,0.0 +0,1.110100,0.0,0.0,0.0,0.0,0.0 +0,1.110200,0.0,0.0,0.0,0.0,0.0 +0,1.110300,0.0,0.0,0.0,0.0,0.0 +0,1.110400,0.0,0.0,0.0,0.0,0.0 +0,1.110500,0.0,0.0,0.0,0.0,0.0 +0,1.110600,0.0,0.0,0.0,0.0,0.0 +0,1.110700,0.0,0.0,0.0,0.0,0.0 +0,1.110800,0.0,0.0,0.0,0.0,0.0 +0,1.110900,0.0,0.0,0.0,0.0,0.0 +0,1.111000,0.0,0.0,0.0,0.0,0.0 +0,1.111100,0.0,0.0,0.0,0.0,0.0 +0,1.111200,0.0,0.0,0.0,0.0,0.0 +0,1.111300,0.0,0.0,0.0,0.0,0.0 +0,1.111400,0.0,0.0,0.0,0.0,0.0 +0,1.111500,0.0,0.0,0.0,0.0,0.0 +0,1.111600,0.0,0.0,0.0,0.0,0.0 +0,1.111700,0.0,0.0,0.0,0.0,0.0 +0,1.111800,0.0,0.0,0.0,0.0,0.0 +0,1.111900,0.0,0.0,0.0,0.0,0.0 +0,1.112000,0.0,0.0,0.0,0.0,0.0 +0,1.112100,0.0,0.0,0.0,0.0,0.0 +0,1.112200,0.0,0.0,0.0,0.0,0.0 +0,1.112300,0.0,0.0,0.0,0.0,0.0 +0,1.112400,0.0,0.0,0.0,0.0,0.0 +0,1.112500,0.0,0.0,0.0,0.0,0.0 +0,1.112600,0.0,0.0,0.0,0.0,0.0 +0,1.112700,0.0,0.0,0.0,0.0,0.0 +0,1.112800,0.0,0.0,0.0,0.0,0.0 +0,1.112900,0.0,0.0,0.0,0.0,0.0 +0,1.113000,0.0,0.0,0.0,0.0,0.0 +0,1.113100,0.0,0.0,0.0,0.0,0.0 +0,1.113200,0.0,0.0,0.0,0.0,0.0 +0,1.113300,0.0,0.0,0.0,0.0,0.0 +0,1.113400,0.0,0.0,0.0,0.0,0.0 +0,1.113500,0.0,0.0,0.0,0.0,0.0 +0,1.113600,0.0,0.0,0.0,0.0,0.0 +0,1.113700,0.0,0.0,0.0,0.0,0.0 +0,1.113800,0.0,0.0,0.0,0.0,0.0 +0,1.113900,0.0,0.0,0.0,0.0,0.0 +0,1.114000,0.0,0.0,0.0,0.0,0.0 +0,1.114100,0.0,0.0,0.0,0.0,0.0 +0,1.114200,0.0,0.0,0.0,0.0,0.0 +0,1.114300,0.0,0.0,0.0,0.0,0.0 +0,1.114400,0.0,0.0,0.0,0.0,0.0 +0,1.114500,0.0,0.0,0.0,0.0,0.0 +0,1.114600,0.0,0.0,0.0,0.0,0.0 +0,1.114700,0.0,0.0,0.0,0.0,0.0 +0,1.114800,0.0,0.0,0.0,0.0,0.0 +0,1.114900,0.0,0.0,0.0,0.0,0.0 +0,1.115000,0.0,0.0,0.0,0.0,0.0 +0,1.115100,0.0,0.0,0.0,0.0,0.0 +0,1.115200,0.0,0.0,0.0,0.0,0.0 +0,1.115300,0.0,0.0,0.0,0.0,0.0 +0,1.115400,0.0,0.0,0.0,0.0,0.0 +0,1.115500,0.0,0.0,0.0,0.0,0.0 +0,1.115600,0.0,0.0,0.0,0.0,0.0 +0,1.115700,0.0,0.0,0.0,0.0,0.0 +0,1.115800,0.0,0.0,0.0,0.0,0.0 +0,1.115900,0.0,0.0,0.0,0.0,0.0 +0,1.116000,0.0,0.0,0.0,0.0,0.0 +0,1.116100,0.0,0.0,0.0,0.0,0.0 +0,1.116200,0.0,0.0,0.0,0.0,0.0 +0,1.116300,0.0,0.0,0.0,0.0,0.0 +0,1.116400,0.0,0.0,0.0,0.0,0.0 +0,1.116500,0.0,0.0,0.0,0.0,0.0 +0,1.116600,0.0,0.0,0.0,0.0,0.0 +0,1.116700,0.0,0.0,0.0,0.0,0.0 +0,1.116800,0.0,0.0,0.0,0.0,0.0 +0,1.116900,0.0,0.0,0.0,0.0,0.0 +0,1.117000,0.0,0.0,0.0,0.0,0.0 +0,1.117100,0.0,0.0,0.0,0.0,0.0 +0,1.117200,0.0,0.0,0.0,0.0,0.0 +0,1.117300,0.0,0.0,0.0,0.0,0.0 +0,1.117400,0.0,0.0,0.0,0.0,0.0 +0,1.117500,0.0,0.0,0.0,0.0,0.0 +0,1.117600,0.0,0.0,0.0,0.0,0.0 +0,1.117700,0.0,0.0,0.0,0.0,0.0 +0,1.117800,0.0,0.0,0.0,0.0,0.0 +0,1.117900,0.0,0.0,0.0,0.0,0.0 +0,1.118000,0.0,0.0,0.0,0.0,0.0 +0,1.118100,0.0,0.0,0.0,0.0,0.0 +0,1.118200,0.0,0.0,0.0,0.0,0.0 +0,1.118300,0.0,0.0,0.0,0.0,0.0 +0,1.118400,0.0,0.0,0.0,0.0,0.0 +0,1.118500,0.0,0.0,0.0,0.0,0.0 +0,1.118600,0.0,0.0,0.0,0.0,0.0 +0,1.118700,0.0,0.0,0.0,0.0,0.0 +0,1.118800,0.0,0.0,0.0,0.0,0.0 +0,1.118900,0.0,0.0,0.0,0.0,0.0 +0,1.119000,0.0,0.0,0.0,0.0,0.0 +0,1.119100,0.0,0.0,0.0,0.0,0.0 +0,1.119200,0.0,0.0,0.0,0.0,0.0 +0,1.119300,0.0,0.0,0.0,0.0,0.0 +0,1.119400,0.0,0.0,0.0,0.0,0.0 +0,1.119500,0.0,0.0,0.0,0.0,0.0 +0,1.119600,0.0,0.0,0.0,0.0,0.0 +0,1.119700,0.0,0.0,0.0,0.0,0.0 +0,1.119800,0.0,0.0,0.0,0.0,0.0 +0,1.119900,0.0,0.0,0.0,0.0,0.0 +0,1.120000,0.0,0.0,0.0,0.0,0.0 +0,1.120100,0.0,0.0,0.0,0.0,0.0 +1,585.621897,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.120200,0.0,0.0,0.0,0.0,0.0 +0,1.120300,0.0,0.0,0.0,0.0,0.0 +0,1.120400,0.0,0.0,0.0,0.0,0.0 +0,1.120500,0.0,0.0,0.0,0.0,0.0 +0,1.120600,0.0,0.0,0.0,0.0,0.0 +0,1.120700,0.0,0.0,0.0,0.0,0.0 +0,1.120800,0.0,0.0,0.0,0.0,0.0 +0,1.120900,0.0,0.0,0.0,0.0,0.0 +0,1.121000,0.0,0.0,0.0,0.0,0.0 +0,1.121100,0.0,0.0,0.0,0.0,0.0 +0,1.121200,0.0,0.0,0.0,0.0,0.0 +0,1.121300,0.0,0.0,0.0,0.0,0.0 +0,1.121400,0.0,0.0,0.0,0.0,0.0 +0,1.121500,0.0,0.0,0.0,0.0,0.0 +0,1.121600,0.0,0.0,0.0,0.0,0.0 +0,1.121700,0.0,0.0,0.0,0.0,0.0 +0,1.121800,0.0,0.0,0.0,0.0,0.0 +0,1.121900,0.0,0.0,0.0,0.0,0.0 +0,1.122000,0.0,0.0,0.0,0.0,0.0 +0,1.122100,0.0,0.0,0.0,0.0,0.0 +0,1.122200,0.0,0.0,0.0,0.0,0.0 +0,1.122300,0.0,0.0,0.0,0.0,0.0 +0,1.122400,0.0,0.0,0.0,0.0,0.0 +0,1.122500,0.0,0.0,0.0,0.0,0.0 +0,1.122600,0.0,0.0,0.0,0.0,0.0 +0,1.122700,0.0,0.0,0.0,0.0,0.0 +0,1.122800,0.0,0.0,0.0,0.0,0.0 +0,1.122900,0.0,0.0,0.0,0.0,0.0 +0,1.123000,0.0,0.0,0.0,0.0,0.0 +0,1.123100,0.0,0.0,0.0,0.0,0.0 +0,1.123200,0.0,0.0,0.0,0.0,0.0 +0,1.123300,0.0,0.0,0.0,0.0,0.0 +0,1.123400,0.0,0.0,0.0,0.0,0.0 +0,1.123500,0.0,0.0,0.0,0.0,0.0 +0,1.123600,0.0,0.0,0.0,0.0,0.0 +0,1.123700,0.0,0.0,0.0,0.0,0.0 +0,1.123800,0.0,0.0,0.0,0.0,0.0 +0,1.123900,0.0,0.0,0.0,0.0,0.0 +0,1.124000,0.0,0.0,0.0,0.0,0.0 +0,1.124100,0.0,0.0,0.0,0.0,0.0 +0,1.124200,0.0,0.0,0.0,0.0,0.0 +0,1.124300,0.0,0.0,0.0,0.0,0.0 +0,1.124400,0.0,0.0,0.0,0.0,0.0 +0,1.124500,0.0,0.0,0.0,0.0,0.0 +0,1.124600,0.0,0.0,0.0,0.0,0.0 +0,1.124700,0.0,0.0,0.0,0.0,0.0 +0,1.124800,0.0,0.0,0.0,0.0,0.0 +0,1.124900,0.0,0.0,0.0,0.0,0.0 +0,1.125000,0.0,0.0,0.0,0.0,0.0 +0,1.125100,0.0,0.0,0.0,0.0,0.0 +0,1.125200,0.0,0.0,0.0,0.0,0.0 +0,1.125300,0.0,0.0,0.0,0.0,0.0 +0,1.125400,0.0,0.0,0.0,0.0,0.0 +0,1.125500,0.0,0.0,0.0,0.0,0.0 +0,1.125600,0.0,0.0,0.0,0.0,0.0 +0,1.125700,0.0,0.0,0.0,0.0,0.0 +0,1.125800,0.0,0.0,0.0,0.0,0.0 +0,1.125900,0.0,0.0,0.0,0.0,0.0 +0,1.126000,0.0,0.0,0.0,0.0,0.0 +0,1.126100,0.0,0.0,0.0,0.0,0.0 +0,1.126200,0.0,0.0,0.0,0.0,0.0 +0,1.126300,0.0,0.0,0.0,0.0,0.0 +0,1.126400,0.0,0.0,0.0,0.0,0.0 +0,1.126500,0.0,0.0,0.0,0.0,0.0 +0,1.126600,0.0,0.0,0.0,0.0,0.0 +0,1.126700,0.0,0.0,0.0,0.0,0.0 +0,1.126800,0.0,0.0,0.0,0.0,0.0 +0,1.126900,0.0,0.0,0.0,0.0,0.0 +0,1.127000,0.0,0.0,0.0,0.0,0.0 +0,1.127100,0.0,0.0,0.0,0.0,0.0 +0,1.127200,0.0,0.0,0.0,0.0,0.0 +0,1.127300,0.0,0.0,0.0,0.0,0.0 +0,1.127400,0.0,0.0,0.0,0.0,0.0 +0,1.127500,0.0,0.0,0.0,0.0,0.0 +0,1.127600,0.0,0.0,0.0,0.0,0.0 +0,1.127700,0.0,0.0,0.0,0.0,0.0 +0,1.127800,0.0,0.0,0.0,0.0,0.0 +0,1.127900,0.0,0.0,0.0,0.0,0.0 +0,1.128000,0.0,0.0,0.0,0.0,0.0 +0,1.128100,0.0,0.0,0.0,0.0,0.0 +0,1.128200,0.0,0.0,0.0,0.0,0.0 +0,1.128300,0.0,0.0,0.0,0.0,0.0 +0,1.128400,0.0,0.0,0.0,0.0,0.0 +0,1.128500,0.0,0.0,0.0,0.0,0.0 +0,1.128600,0.0,0.0,0.0,0.0,0.0 +0,1.128700,0.0,0.0,0.0,0.0,0.0 +0,1.128800,0.0,0.0,0.0,0.0,0.0 +0,1.128900,0.0,0.0,0.0,0.0,0.0 +0,1.129000,0.0,0.0,0.0,0.0,0.0 +0,1.129100,0.0,0.0,0.0,0.0,0.0 +0,1.129200,0.0,0.0,0.0,0.0,0.0 +0,1.129300,0.0,0.0,0.0,0.0,0.0 +0,1.129400,0.0,0.0,0.0,0.0,0.0 +0,1.129500,0.0,0.0,0.0,0.0,0.0 +0,1.129600,0.0,0.0,0.0,0.0,0.0 +0,1.129700,0.0,0.0,0.0,0.0,0.0 +0,1.129800,0.0,0.0,0.0,0.0,0.0 +0,1.129900,0.0,0.0,0.0,0.0,0.0 +0,1.130000,0.0,0.0,0.0,0.0,0.0 +0,1.130100,0.0,0.0,0.0,0.0,0.0 +0,1.130200,0.0,0.0,0.0,0.0,0.0 +0,1.130300,0.0,0.0,0.0,0.0,0.0 +0,1.130400,0.0,0.0,0.0,0.0,0.0 +0,1.130500,0.0,0.0,0.0,0.0,0.0 +0,1.130600,0.0,0.0,0.0,0.0,0.0 +0,1.130700,0.0,0.0,0.0,0.0,0.0 +0,1.130800,0.0,0.0,0.0,0.0,0.0 +0,1.130900,0.0,0.0,0.0,0.0,0.0 +0,1.131000,0.0,0.0,0.0,0.0,0.0 +0,1.131100,0.0,0.0,0.0,0.0,0.0 +0,1.131200,0.0,0.0,0.0,0.0,0.0 +0,1.131300,0.0,0.0,0.0,0.0,0.0 +0,1.131400,0.0,0.0,0.0,0.0,0.0 +0,1.131500,0.0,0.0,0.0,0.0,0.0 +0,1.131600,0.0,0.0,0.0,0.0,0.0 +0,1.131700,0.0,0.0,0.0,0.0,0.0 +0,1.131800,0.0,0.0,0.0,0.0,0.0 +0,1.131900,0.0,0.0,0.0,0.0,0.0 +0,1.132000,0.0,0.0,0.0,0.0,0.0 +0,1.132100,0.0,0.0,0.0,0.0,0.0 +0,1.132200,0.0,0.0,0.0,0.0,0.0 +0,1.132300,0.0,0.0,0.0,0.0,0.0 +0,1.132400,0.0,0.0,0.0,0.0,0.0 +0,1.132500,0.0,0.0,0.0,0.0,0.0 +0,1.132600,0.0,0.0,0.0,0.0,0.0 +0,1.132700,0.0,0.0,0.0,0.0,0.0 +0,1.132800,0.0,0.0,0.0,0.0,0.0 +0,1.132900,0.0,0.0,0.0,0.0,0.0 +0,1.133000,0.0,0.0,0.0,0.0,0.0 +0,1.133100,0.0,0.0,0.0,0.0,0.0 +0,1.133200,0.0,0.0,0.0,0.0,0.0 +0,1.133300,0.0,0.0,0.0,0.0,0.0 +0,1.133400,0.0,0.0,0.0,0.0,0.0 +0,1.133500,0.0,0.0,0.0,0.0,0.0 +0,1.133600,0.0,0.0,0.0,0.0,0.0 +0,1.133700,0.0,0.0,0.0,0.0,0.0 +0,1.133800,0.0,0.0,0.0,0.0,0.0 +0,1.133900,0.0,0.0,0.0,0.0,0.0 +0,1.134000,0.0,0.0,0.0,0.0,0.0 +0,1.134100,0.0,0.0,0.0,0.0,0.0 +0,1.134200,0.0,0.0,0.0,0.0,0.0 +0,1.134300,0.0,0.0,0.0,0.0,0.0 +0,1.134400,0.0,0.0,0.0,0.0,0.0 +0,1.134500,0.0,0.0,0.0,0.0,0.0 +0,1.134600,0.0,0.0,0.0,0.0,0.0 +0,1.134700,0.0,0.0,0.0,0.0,0.0 +0,1.134800,0.0,0.0,0.0,0.0,0.0 +0,1.134900,0.0,0.0,0.0,0.0,0.0 +0,1.135000,0.0,0.0,0.0,0.0,0.0 +0,1.135100,0.0,0.0,0.0,0.0,0.0 +0,1.135200,0.0,0.0,0.0,0.0,0.0 +0,1.135300,0.0,0.0,0.0,0.0,0.0 +0,1.135400,0.0,0.0,0.0,0.0,0.0 +0,1.135500,0.0,0.0,0.0,0.0,0.0 +0,1.135600,0.0,0.0,0.0,0.0,0.0 +0,1.135700,0.0,0.0,0.0,0.0,0.0 +0,1.135800,0.0,0.0,0.0,0.0,0.0 +0,1.135900,0.0,0.0,0.0,0.0,0.0 +0,1.136000,0.0,0.0,0.0,0.0,0.0 +0,1.136100,0.0,0.0,0.0,0.0,0.0 +0,1.136200,0.0,0.0,0.0,0.0,0.0 +0,1.136300,0.0,0.0,0.0,0.0,0.0 +0,1.136400,0.0,0.0,0.0,0.0,0.0 +0,1.136500,0.0,0.0,0.0,0.0,0.0 +0,1.136600,0.0,0.0,0.0,0.0,0.0 +0,1.136700,0.0,0.0,0.0,0.0,0.0 +0,1.136800,0.0,0.0,0.0,0.0,0.0 +0,1.136900,0.0,0.0,0.0,0.0,0.0 +0,1.137000,0.0,0.0,0.0,0.0,0.0 +0,1.137100,0.0,0.0,0.0,0.0,0.0 +0,1.137200,0.0,0.0,0.0,0.0,0.0 +0,1.137300,0.0,0.0,0.0,0.0,0.0 +0,1.137400,0.0,0.0,0.0,0.0,0.0 +0,1.137500,0.0,0.0,0.0,0.0,0.0 +0,1.137600,0.0,0.0,0.0,0.0,0.0 +0,1.137700,0.0,0.0,0.0,0.0,0.0 +0,1.137800,0.0,0.0,0.0,0.0,0.0 +0,1.137900,0.0,0.0,0.0,0.0,0.0 +0,1.138000,0.0,0.0,0.0,0.0,0.0 +0,1.138100,0.0,0.0,0.0,0.0,0.0 +0,1.138200,0.0,0.0,0.0,0.0,0.0 +0,1.138300,0.0,0.0,0.0,0.0,0.0 +0,1.138400,0.0,0.0,0.0,0.0,0.0 +0,1.138500,0.0,0.0,0.0,0.0,0.0 +0,1.138600,0.0,0.0,0.0,0.0,0.0 +0,1.138700,0.0,0.0,0.0,0.0,0.0 +0,1.138800,0.0,0.0,0.0,0.0,0.0 +0,1.138900,0.0,0.0,0.0,0.0,0.0 +0,1.139000,0.0,0.0,0.0,0.0,0.0 +0,1.139100,0.0,0.0,0.0,0.0,0.0 +0,1.139200,0.0,0.0,0.0,0.0,0.0 +0,1.139300,0.0,0.0,0.0,0.0,0.0 +0,1.139400,0.0,0.0,0.0,0.0,0.0 +0,1.139500,0.0,0.0,0.0,0.0,0.0 +0,1.139600,0.0,0.0,0.0,0.0,0.0 +0,1.139700,0.0,0.0,0.0,0.0,0.0 +0,1.139800,0.0,0.0,0.0,0.0,0.0 +0,1.139900,0.0,0.0,0.0,0.0,0.0 +0,1.140000,0.0,0.0,0.0,0.0,0.0 +0,1.140100,0.0,0.0,0.0,0.0,0.0 +1,617.553706,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.140200,0.0,0.0,0.0,0.0,0.0 +0,1.140300,0.0,0.0,0.0,0.0,0.0 +0,1.140400,0.0,0.0,0.0,0.0,0.0 +0,1.140500,0.0,0.0,0.0,0.0,0.0 +0,1.140600,0.0,0.0,0.0,0.0,0.0 +0,1.140700,0.0,0.0,0.0,0.0,0.0 +0,1.140800,0.0,0.0,0.0,0.0,0.0 +0,1.140900,0.0,0.0,0.0,0.0,0.0 +0,1.141000,0.0,0.0,0.0,0.0,0.0 +0,1.141100,0.0,0.0,0.0,0.0,0.0 +0,1.141200,0.0,0.0,0.0,0.0,0.0 +0,1.141300,0.0,0.0,0.0,0.0,0.0 +0,1.141400,0.0,0.0,0.0,0.0,0.0 +0,1.141500,0.0,0.0,0.0,0.0,0.0 +0,1.141600,0.0,0.0,0.0,0.0,0.0 +0,1.141700,0.0,0.0,0.0,0.0,0.0 +0,1.141800,0.0,0.0,0.0,0.0,0.0 +0,1.141900,0.0,0.0,0.0,0.0,0.0 +0,1.142000,0.0,0.0,0.0,0.0,0.0 +0,1.142100,0.0,0.0,0.0,0.0,0.0 +0,1.142200,0.0,0.0,0.0,0.0,0.0 +0,1.142300,0.0,0.0,0.0,0.0,0.0 +0,1.142400,0.0,0.0,0.0,0.0,0.0 +0,1.142500,0.0,0.0,0.0,0.0,0.0 +0,1.142600,0.0,0.0,0.0,0.0,0.0 +0,1.142700,0.0,0.0,0.0,0.0,0.0 +0,1.142800,0.0,0.0,0.0,0.0,0.0 +0,1.142900,0.0,0.0,0.0,0.0,0.0 +0,1.143000,0.0,0.0,0.0,0.0,0.0 +0,1.143100,0.0,0.0,0.0,0.0,0.0 +0,1.143200,0.0,0.0,0.0,0.0,0.0 +0,1.143300,0.0,0.0,0.0,0.0,0.0 +0,1.143400,0.0,0.0,0.0,0.0,0.0 +0,1.143500,0.0,0.0,0.0,0.0,0.0 +0,1.143600,0.0,0.0,0.0,0.0,0.0 +0,1.143700,0.0,0.0,0.0,0.0,0.0 +0,1.143800,0.0,0.0,0.0,0.0,0.0 +0,1.143900,0.0,0.0,0.0,0.0,0.0 +0,1.144000,0.0,0.0,0.0,0.0,0.0 +0,1.144100,0.0,0.0,0.0,0.0,0.0 +0,1.144200,0.0,0.0,0.0,0.0,0.0 +0,1.144300,0.0,0.0,0.0,0.0,0.0 +0,1.144400,0.0,0.0,0.0,0.0,0.0 +0,1.144500,0.0,0.0,0.0,0.0,0.0 +0,1.144600,0.0,0.0,0.0,0.0,0.0 +0,1.144700,0.0,0.0,0.0,0.0,0.0 +0,1.144800,0.0,0.0,0.0,0.0,0.0 +0,1.144900,0.0,0.0,0.0,0.0,0.0 +0,1.145000,0.0,0.0,0.0,0.0,0.0 +0,1.145100,0.0,0.0,0.0,0.0,0.0 +0,1.145200,0.0,0.0,0.0,0.0,0.0 +0,1.145300,0.0,0.0,0.0,0.0,0.0 +0,1.145400,0.0,0.0,0.0,0.0,0.0 +0,1.145500,0.0,0.0,0.0,0.0,0.0 +0,1.145600,0.0,0.0,0.0,0.0,0.0 +0,1.145700,0.0,0.0,0.0,0.0,0.0 +0,1.145800,0.0,0.0,0.0,0.0,0.0 +0,1.145900,0.0,0.0,0.0,0.0,0.0 +0,1.146000,0.0,0.0,0.0,0.0,0.0 +0,1.146100,0.0,0.0,0.0,0.0,0.0 +0,1.146200,0.0,0.0,0.0,0.0,0.0 +0,1.146300,0.0,0.0,0.0,0.0,0.0 +0,1.146400,0.0,0.0,0.0,0.0,0.0 +0,1.146500,0.0,0.0,0.0,0.0,0.0 +0,1.146600,0.0,0.0,0.0,0.0,0.0 +0,1.146700,0.0,0.0,0.0,0.0,0.0 +0,1.146800,0.0,0.0,0.0,0.0,0.0 +0,1.146900,0.0,0.0,0.0,0.0,0.0 +0,1.147000,0.0,0.0,0.0,0.0,0.0 +0,1.147100,0.0,0.0,0.0,0.0,0.0 +0,1.147200,0.0,0.0,0.0,0.0,0.0 +0,1.147300,0.0,0.0,0.0,0.0,0.0 +0,1.147400,0.0,0.0,0.0,0.0,0.0 +0,1.147500,0.0,0.0,0.0,0.0,0.0 +0,1.147600,0.0,0.0,0.0,0.0,0.0 +0,1.147700,0.0,0.0,0.0,0.0,0.0 +0,1.147800,0.0,0.0,0.0,0.0,0.0 +0,1.147900,0.0,0.0,0.0,0.0,0.0 +0,1.148000,0.0,0.0,0.0,0.0,0.0 +0,1.148100,0.0,0.0,0.0,0.0,0.0 +0,1.148200,0.0,0.0,0.0,0.0,0.0 +0,1.148300,0.0,0.0,0.0,0.0,0.0 +0,1.148400,0.0,0.0,0.0,0.0,0.0 +0,1.148500,0.0,0.0,0.0,0.0,0.0 +0,1.148600,0.0,0.0,0.0,0.0,0.0 +0,1.148700,0.0,0.0,0.0,0.0,0.0 +0,1.148800,0.0,0.0,0.0,0.0,0.0 +0,1.148900,0.0,0.0,0.0,0.0,0.0 +0,1.149000,0.0,0.0,0.0,0.0,0.0 +0,1.149100,0.0,0.0,0.0,0.0,0.0 +0,1.149200,0.0,0.0,0.0,0.0,0.0 +0,1.149300,0.0,0.0,0.0,0.0,0.0 +0,1.149400,0.0,0.0,0.0,0.0,0.0 +0,1.149500,0.0,0.0,0.0,0.0,0.0 +0,1.149600,0.0,0.0,0.0,0.0,0.0 +0,1.149700,0.0,0.0,0.0,0.0,0.0 +0,1.149800,0.0,0.0,0.0,0.0,0.0 +0,1.149900,0.0,0.0,0.0,0.0,0.0 +0,1.150000,0.0,0.0,0.0,0.0,0.0 +0,1.150100,0.0,0.0,0.0,0.0,0.0 +0,1.150200,0.0,0.0,0.0,0.0,0.0 +0,1.150300,0.0,0.0,0.0,0.0,0.0 +0,1.150400,0.0,0.0,0.0,0.0,0.0 +0,1.150500,0.0,0.0,0.0,0.0,0.0 +0,1.150600,0.0,0.0,0.0,0.0,0.0 +0,1.150700,0.0,0.0,0.0,0.0,0.0 +0,1.150800,0.0,0.0,0.0,0.0,0.0 +0,1.150900,0.0,0.0,0.0,0.0,0.0 +0,1.151000,0.0,0.0,0.0,0.0,0.0 +0,1.151100,0.0,0.0,0.0,0.0,0.0 +0,1.151200,0.0,0.0,0.0,0.0,0.0 +0,1.151300,0.0,0.0,0.0,0.0,0.0 +0,1.151400,0.0,0.0,0.0,0.0,0.0 +0,1.151500,0.0,0.0,0.0,0.0,0.0 +0,1.151600,0.0,0.0,0.0,0.0,0.0 +0,1.151700,0.0,0.0,0.0,0.0,0.0 +0,1.151800,0.0,0.0,0.0,0.0,0.0 +0,1.151900,0.0,0.0,0.0,0.0,0.0 +0,1.152000,0.0,0.0,0.0,0.0,0.0 +0,1.152100,0.0,0.0,0.0,0.0,0.0 +0,1.152200,0.0,0.0,0.0,0.0,0.0 +0,1.152300,0.0,0.0,0.0,0.0,0.0 +0,1.152400,0.0,0.0,0.0,0.0,0.0 +0,1.152500,0.0,0.0,0.0,0.0,0.0 +0,1.152600,0.0,0.0,0.0,0.0,0.0 +0,1.152700,0.0,0.0,0.0,0.0,0.0 +0,1.152800,0.0,0.0,0.0,0.0,0.0 +0,1.152900,0.0,0.0,0.0,0.0,0.0 +0,1.153000,0.0,0.0,0.0,0.0,0.0 +0,1.153100,0.0,0.0,0.0,0.0,0.0 +0,1.153200,0.0,0.0,0.0,0.0,0.0 +0,1.153300,0.0,0.0,0.0,0.0,0.0 +0,1.153400,0.0,0.0,0.0,0.0,0.0 +0,1.153500,0.0,0.0,0.0,0.0,0.0 +0,1.153600,0.0,0.0,0.0,0.0,0.0 +0,1.153700,0.0,0.0,0.0,0.0,0.0 +0,1.153800,0.0,0.0,0.0,0.0,0.0 +0,1.153900,0.0,0.0,0.0,0.0,0.0 +0,1.154000,0.0,0.0,0.0,0.0,0.0 +0,1.154100,0.0,0.0,0.0,0.0,0.0 +0,1.154200,0.0,0.0,0.0,0.0,0.0 +0,1.154300,0.0,0.0,0.0,0.0,0.0 +0,1.154400,0.0,0.0,0.0,0.0,0.0 +0,1.154500,0.0,0.0,0.0,0.0,0.0 +0,1.154600,0.0,0.0,0.0,0.0,0.0 +0,1.154700,0.0,0.0,0.0,0.0,0.0 +0,1.154800,0.0,0.0,0.0,0.0,0.0 +0,1.154900,0.0,0.0,0.0,0.0,0.0 +0,1.155000,0.0,0.0,0.0,0.0,0.0 +0,1.155100,0.0,0.0,0.0,0.0,0.0 +0,1.155200,0.0,0.0,0.0,0.0,0.0 +0,1.155300,0.0,0.0,0.0,0.0,0.0 +0,1.155400,0.0,0.0,0.0,0.0,0.0 +0,1.155500,0.0,0.0,0.0,0.0,0.0 +0,1.155600,0.0,0.0,0.0,0.0,0.0 +0,1.155700,0.0,0.0,0.0,0.0,0.0 +0,1.155800,0.0,0.0,0.0,0.0,0.0 +0,1.155900,0.0,0.0,0.0,0.0,0.0 +0,1.156000,0.0,0.0,0.0,0.0,0.0 +0,1.156100,0.0,0.0,0.0,0.0,0.0 +0,1.156200,0.0,0.0,0.0,0.0,0.0 +0,1.156300,0.0,0.0,0.0,0.0,0.0 +0,1.156400,0.0,0.0,0.0,0.0,0.0 +0,1.156500,0.0,0.0,0.0,0.0,0.0 +0,1.156600,0.0,0.0,0.0,0.0,0.0 +0,1.156700,0.0,0.0,0.0,0.0,0.0 +0,1.156800,0.0,0.0,0.0,0.0,0.0 +0,1.156900,0.0,0.0,0.0,0.0,0.0 +0,1.157000,0.0,0.0,0.0,0.0,0.0 +0,1.157100,0.0,0.0,0.0,0.0,0.0 +0,1.157200,0.0,0.0,0.0,0.0,0.0 +0,1.157300,0.0,0.0,0.0,0.0,0.0 +0,1.157400,0.0,0.0,0.0,0.0,0.0 +0,1.157500,0.0,0.0,0.0,0.0,0.0 +0,1.157600,0.0,0.0,0.0,0.0,0.0 +0,1.157700,0.0,0.0,0.0,0.0,0.0 +0,1.157800,0.0,0.0,0.0,0.0,0.0 +0,1.157900,0.0,0.0,0.0,0.0,0.0 +0,1.158000,0.0,0.0,0.0,0.0,0.0 +0,1.158100,0.0,0.0,0.0,0.0,0.0 +0,1.158200,0.0,0.0,0.0,0.0,0.0 +0,1.158300,0.0,0.0,0.0,0.0,0.0 +0,1.158400,0.0,0.0,0.0,0.0,0.0 +0,1.158500,0.0,0.0,0.0,0.0,0.0 +0,1.158600,0.0,0.0,0.0,0.0,0.0 +0,1.158700,0.0,0.0,0.0,0.0,0.0 +0,1.158800,0.0,0.0,0.0,0.0,0.0 +0,1.158900,0.0,0.0,0.0,0.0,0.0 +0,1.159000,0.0,0.0,0.0,0.0,0.0 +0,1.159100,0.0,0.0,0.0,0.0,0.0 +0,1.159200,0.0,0.0,0.0,0.0,0.0 +0,1.159300,0.0,0.0,0.0,0.0,0.0 +0,1.159400,0.0,0.0,0.0,0.0,0.0 +0,1.159500,0.0,0.0,0.0,0.0,0.0 +0,1.159600,0.0,0.0,0.0,0.0,0.0 +0,1.159700,0.0,0.0,0.0,0.0,0.0 +0,1.159800,0.0,0.0,0.0,0.0,0.0 +0,1.159900,0.0,0.0,0.0,0.0,0.0 +0,1.160000,0.0,0.0,0.0,0.0,0.0 +0,1.160100,0.0,0.0,0.0,0.0,0.0 +1,650.625665,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.160200,0.0,0.0,0.0,0.0,0.0 +0,1.160300,0.0,0.0,0.0,0.0,0.0 +0,1.160400,0.0,0.0,0.0,0.0,0.0 +0,1.160500,0.0,0.0,0.0,0.0,0.0 +0,1.160600,0.0,0.0,0.0,0.0,0.0 +0,1.160700,0.0,0.0,0.0,0.0,0.0 +0,1.160800,0.0,0.0,0.0,0.0,0.0 +0,1.160900,0.0,0.0,0.0,0.0,0.0 +0,1.161000,0.0,0.0,0.0,0.0,0.0 +0,1.161100,0.0,0.0,0.0,0.0,0.0 +0,1.161200,0.0,0.0,0.0,0.0,0.0 +0,1.161300,0.0,0.0,0.0,0.0,0.0 +0,1.161400,0.0,0.0,0.0,0.0,0.0 +0,1.161500,0.0,0.0,0.0,0.0,0.0 +0,1.161600,0.0,0.0,0.0,0.0,0.0 +0,1.161700,0.0,0.0,0.0,0.0,0.0 +0,1.161800,0.0,0.0,0.0,0.0,0.0 +0,1.161900,0.0,0.0,0.0,0.0,0.0 +0,1.162000,0.0,0.0,0.0,0.0,0.0 +0,1.162100,0.0,0.0,0.0,0.0,0.0 +0,1.162200,0.0,0.0,0.0,0.0,0.0 +0,1.162300,0.0,0.0,0.0,0.0,0.0 +0,1.162400,0.0,0.0,0.0,0.0,0.0 +0,1.162500,0.0,0.0,0.0,0.0,0.0 +0,1.162600,0.0,0.0,0.0,0.0,0.0 +0,1.162700,0.0,0.0,0.0,0.0,0.0 +0,1.162800,0.0,0.0,0.0,0.0,0.0 +0,1.162900,0.0,0.0,0.0,0.0,0.0 +0,1.163000,0.0,0.0,0.0,0.0,0.0 +0,1.163100,0.0,0.0,0.0,0.0,0.0 +0,1.163200,0.0,0.0,0.0,0.0,0.0 +0,1.163300,0.0,0.0,0.0,0.0,0.0 +0,1.163400,0.0,0.0,0.0,0.0,0.0 +0,1.163500,0.0,0.0,0.0,0.0,0.0 +0,1.163600,0.0,0.0,0.0,0.0,0.0 +0,1.163700,0.0,0.0,0.0,0.0,0.0 +0,1.163800,0.0,0.0,0.0,0.0,0.0 +0,1.163900,0.0,0.0,0.0,0.0,0.0 +0,1.164000,0.0,0.0,0.0,0.0,0.0 +0,1.164100,0.0,0.0,0.0,0.0,0.0 +0,1.164200,0.0,0.0,0.0,0.0,0.0 +0,1.164300,0.0,0.0,0.0,0.0,0.0 +0,1.164400,0.0,0.0,0.0,0.0,0.0 +0,1.164500,0.0,0.0,0.0,0.0,0.0 +0,1.164600,0.0,0.0,0.0,0.0,0.0 +0,1.164700,0.0,0.0,0.0,0.0,0.0 +0,1.164800,0.0,0.0,0.0,0.0,0.0 +0,1.164900,0.0,0.0,0.0,0.0,0.0 +0,1.165000,0.0,0.0,0.0,0.0,0.0 +0,1.165100,0.0,0.0,0.0,0.0,0.0 +0,1.165200,0.0,0.0,0.0,0.0,0.0 +0,1.165300,0.0,0.0,0.0,0.0,0.0 +0,1.165400,0.0,0.0,0.0,0.0,0.0 +0,1.165500,0.0,0.0,0.0,0.0,0.0 +0,1.165600,0.0,0.0,0.0,0.0,0.0 +0,1.165700,0.0,0.0,0.0,0.0,0.0 +0,1.165800,0.0,0.0,0.0,0.0,0.0 +0,1.165900,0.0,0.0,0.0,0.0,0.0 +0,1.166000,0.0,0.0,0.0,0.0,0.0 +0,1.166100,0.0,0.0,0.0,0.0,0.0 +0,1.166200,0.0,0.0,0.0,0.0,0.0 +0,1.166300,0.0,0.0,0.0,0.0,0.0 +0,1.166400,0.0,0.0,0.0,0.0,0.0 +0,1.166500,0.0,0.0,0.0,0.0,0.0 +0,1.166600,0.0,0.0,0.0,0.0,0.0 +0,1.166700,0.0,0.0,0.0,0.0,0.0 +0,1.166800,0.0,0.0,0.0,0.0,0.0 +0,1.166900,0.0,0.0,0.0,0.0,0.0 +0,1.167000,0.0,0.0,0.0,0.0,0.0 +0,1.167100,0.0,0.0,0.0,0.0,0.0 +0,1.167200,0.0,0.0,0.0,0.0,0.0 +0,1.167300,0.0,0.0,0.0,0.0,0.0 +0,1.167400,0.0,0.0,0.0,0.0,0.0 +0,1.167500,0.0,0.0,0.0,0.0,0.0 +0,1.167600,0.0,0.0,0.0,0.0,0.0 +0,1.167700,0.0,0.0,0.0,0.0,0.0 +0,1.167800,0.0,0.0,0.0,0.0,0.0 +0,1.167900,0.0,0.0,0.0,0.0,0.0 +0,1.168000,0.0,0.0,0.0,0.0,0.0 +0,1.168100,0.0,0.0,0.0,0.0,0.0 +0,1.168200,0.0,0.0,0.0,0.0,0.0 +0,1.168300,0.0,0.0,0.0,0.0,0.0 +0,1.168400,0.0,0.0,0.0,0.0,0.0 +0,1.168500,0.0,0.0,0.0,0.0,0.0 +0,1.168600,0.0,0.0,0.0,0.0,0.0 +0,1.168700,0.0,0.0,0.0,0.0,0.0 +0,1.168800,0.0,0.0,0.0,0.0,0.0 +0,1.168900,0.0,0.0,0.0,0.0,0.0 +0,1.169000,0.0,0.0,0.0,0.0,0.0 +0,1.169100,0.0,0.0,0.0,0.0,0.0 +0,1.169200,0.0,0.0,0.0,0.0,0.0 +0,1.169300,0.0,0.0,0.0,0.0,0.0 +0,1.169400,0.0,0.0,0.0,0.0,0.0 +0,1.169500,0.0,0.0,0.0,0.0,0.0 +0,1.169600,0.0,0.0,0.0,0.0,0.0 +0,1.169700,0.0,0.0,0.0,0.0,0.0 +0,1.169800,0.0,0.0,0.0,0.0,0.0 +0,1.169900,0.0,0.0,0.0,0.0,0.0 +0,1.170000,0.0,0.0,0.0,0.0,0.0 +0,1.170100,0.0,0.0,0.0,0.0,0.0 +0,1.170200,0.0,0.0,0.0,0.0,0.0 +0,1.170300,0.0,0.0,0.0,0.0,0.0 +0,1.170400,0.0,0.0,0.0,0.0,0.0 +0,1.170500,0.0,0.0,0.0,0.0,0.0 +0,1.170600,0.0,0.0,0.0,0.0,0.0 +0,1.170700,0.0,0.0,0.0,0.0,0.0 +0,1.170800,0.0,0.0,0.0,0.0,0.0 +0,1.170900,0.0,0.0,0.0,0.0,0.0 +0,1.171000,0.0,0.0,0.0,0.0,0.0 +0,1.171100,0.0,0.0,0.0,0.0,0.0 +0,1.171200,0.0,0.0,0.0,0.0,0.0 +0,1.171300,0.0,0.0,0.0,0.0,0.0 +0,1.171400,0.0,0.0,0.0,0.0,0.0 +0,1.171500,0.0,0.0,0.0,0.0,0.0 +0,1.171600,0.0,0.0,0.0,0.0,0.0 +0,1.171700,0.0,0.0,0.0,0.0,0.0 +0,1.171800,0.0,0.0,0.0,0.0,0.0 +0,1.171900,0.0,0.0,0.0,0.0,0.0 +0,1.172000,0.0,0.0,0.0,0.0,0.0 +0,1.172100,0.0,0.0,0.0,0.0,0.0 +0,1.172200,0.0,0.0,0.0,0.0,0.0 +0,1.172300,0.0,0.0,0.0,0.0,0.0 +0,1.172400,0.0,0.0,0.0,0.0,0.0 +0,1.172500,0.0,0.0,0.0,0.0,0.0 +0,1.172600,0.0,0.0,0.0,0.0,0.0 +0,1.172700,0.0,0.0,0.0,0.0,0.0 +0,1.172800,0.0,0.0,0.0,0.0,0.0 +0,1.172900,0.0,0.0,0.0,0.0,0.0 +0,1.173000,0.0,0.0,0.0,0.0,0.0 +0,1.173100,0.0,0.0,0.0,0.0,0.0 +0,1.173200,0.0,0.0,0.0,0.0,0.0 +0,1.173300,0.0,0.0,0.0,0.0,0.0 +0,1.173400,0.0,0.0,0.0,0.0,0.0 +0,1.173500,0.0,0.0,0.0,0.0,0.0 +0,1.173600,0.0,0.0,0.0,0.0,0.0 +0,1.173700,0.0,0.0,0.0,0.0,0.0 +0,1.173800,0.0,0.0,0.0,0.0,0.0 +0,1.173900,0.0,0.0,0.0,0.0,0.0 +0,1.174000,0.0,0.0,0.0,0.0,0.0 +0,1.174100,0.0,0.0,0.0,0.0,0.0 +0,1.174200,0.0,0.0,0.0,0.0,0.0 +0,1.174300,0.0,0.0,0.0,0.0,0.0 +0,1.174400,0.0,0.0,0.0,0.0,0.0 +0,1.174500,0.0,0.0,0.0,0.0,0.0 +0,1.174600,0.0,0.0,0.0,0.0,0.0 +0,1.174700,0.0,0.0,0.0,0.0,0.0 +0,1.174800,0.0,0.0,0.0,0.0,0.0 +0,1.174900,0.0,0.0,0.0,0.0,0.0 +0,1.175000,0.0,0.0,0.0,0.0,0.0 +0,1.175100,0.0,0.0,0.0,0.0,0.0 +0,1.175200,0.0,0.0,0.0,0.0,0.0 +0,1.175300,0.0,0.0,0.0,0.0,0.0 +0,1.175400,0.0,0.0,0.0,0.0,0.0 +0,1.175500,0.0,0.0,0.0,0.0,0.0 +0,1.175600,0.0,0.0,0.0,0.0,0.0 +0,1.175700,0.0,0.0,0.0,0.0,0.0 +0,1.175800,0.0,0.0,0.0,0.0,0.0 +0,1.175900,0.0,0.0,0.0,0.0,0.0 +0,1.176000,0.0,0.0,0.0,0.0,0.0 +0,1.176100,0.0,0.0,0.0,0.0,0.0 +0,1.176200,0.0,0.0,0.0,0.0,0.0 +0,1.176300,0.0,0.0,0.0,0.0,0.0 +0,1.176400,0.0,0.0,0.0,0.0,0.0 +0,1.176500,0.0,0.0,0.0,0.0,0.0 +0,1.176600,0.0,0.0,0.0,0.0,0.0 +0,1.176700,0.0,0.0,0.0,0.0,0.0 +0,1.176800,0.0,0.0,0.0,0.0,0.0 +0,1.176900,0.0,0.0,0.0,0.0,0.0 +0,1.177000,0.0,0.0,0.0,0.0,0.0 +0,1.177100,0.0,0.0,0.0,0.0,0.0 +0,1.177200,0.0,0.0,0.0,0.0,0.0 +0,1.177300,0.0,0.0,0.0,0.0,0.0 +0,1.177400,0.0,0.0,0.0,0.0,0.0 +0,1.177500,0.0,0.0,0.0,0.0,0.0 +0,1.177600,0.0,0.0,0.0,0.0,0.0 +0,1.177700,0.0,0.0,0.0,0.0,0.0 +0,1.177800,0.0,0.0,0.0,0.0,0.0 +0,1.177900,0.0,0.0,0.0,0.0,0.0 +0,1.178000,0.0,0.0,0.0,0.0,0.0 +0,1.178100,0.0,0.0,0.0,0.0,0.0 +0,1.178200,0.0,0.0,0.0,0.0,0.0 +0,1.178300,0.0,0.0,0.0,0.0,0.0 +0,1.178400,0.0,0.0,0.0,0.0,0.0 +0,1.178500,0.0,0.0,0.0,0.0,0.0 +0,1.178600,0.0,0.0,0.0,0.0,0.0 +0,1.178700,0.0,0.0,0.0,0.0,0.0 +0,1.178800,0.0,0.0,0.0,0.0,0.0 +0,1.178900,0.0,0.0,0.0,0.0,0.0 +0,1.179000,0.0,0.0,0.0,0.0,0.0 +0,1.179100,0.0,0.0,0.0,0.0,0.0 +0,1.179200,0.0,0.0,0.0,0.0,0.0 +0,1.179300,0.0,0.0,0.0,0.0,0.0 +0,1.179400,0.0,0.0,0.0,0.0,0.0 +0,1.179500,0.0,0.0,0.0,0.0,0.0 +0,1.179600,0.0,0.0,0.0,0.0,0.0 +0,1.179700,0.0,0.0,0.0,0.0,0.0 +0,1.179800,0.0,0.0,0.0,0.0,0.0 +0,1.179900,0.0,0.0,0.0,0.0,0.0 +0,1.180000,0.0,0.0,0.0,0.0,0.0 +0,1.180100,0.0,0.0,0.0,0.0,0.0 +1,684.857774,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.180200,0.0,0.0,0.0,0.0,0.0 +0,1.180300,0.0,0.0,0.0,0.0,0.0 +0,1.180400,0.0,0.0,0.0,0.0,0.0 +0,1.180500,0.0,0.0,0.0,0.0,0.0 +0,1.180600,0.0,0.0,0.0,0.0,0.0 +0,1.180700,0.0,0.0,0.0,0.0,0.0 +0,1.180800,0.0,0.0,0.0,0.0,0.0 +0,1.180900,0.0,0.0,0.0,0.0,0.0 +0,1.181000,0.0,0.0,0.0,0.0,0.0 +0,1.181100,0.0,0.0,0.0,0.0,0.0 +0,1.181200,0.0,0.0,0.0,0.0,0.0 +0,1.181300,0.0,0.0,0.0,0.0,0.0 +0,1.181400,0.0,0.0,0.0,0.0,0.0 +0,1.181500,0.0,0.0,0.0,0.0,0.0 +0,1.181600,0.0,0.0,0.0,0.0,0.0 +0,1.181700,0.0,0.0,0.0,0.0,0.0 +0,1.181800,0.0,0.0,0.0,0.0,0.0 +0,1.181900,0.0,0.0,0.0,0.0,0.0 +0,1.182000,0.0,0.0,0.0,0.0,0.0 +0,1.182100,0.0,0.0,0.0,0.0,0.0 +0,1.182200,0.0,0.0,0.0,0.0,0.0 +0,1.182300,0.0,0.0,0.0,0.0,0.0 +0,1.182400,0.0,0.0,0.0,0.0,0.0 +0,1.182500,0.0,0.0,0.0,0.0,0.0 +0,1.182600,0.0,0.0,0.0,0.0,0.0 +0,1.182700,0.0,0.0,0.0,0.0,0.0 +0,1.182800,0.0,0.0,0.0,0.0,0.0 +0,1.182900,0.0,0.0,0.0,0.0,0.0 +0,1.183000,0.0,0.0,0.0,0.0,0.0 +0,1.183100,0.0,0.0,0.0,0.0,0.0 +0,1.183200,0.0,0.0,0.0,0.0,0.0 +0,1.183300,0.0,0.0,0.0,0.0,0.0 +0,1.183400,0.0,0.0,0.0,0.0,0.0 +0,1.183500,0.0,0.0,0.0,0.0,0.0 +0,1.183600,0.0,0.0,0.0,0.0,0.0 +0,1.183700,0.0,0.0,0.0,0.0,0.0 +0,1.183800,0.0,0.0,0.0,0.0,0.0 +0,1.183900,0.0,0.0,0.0,0.0,0.0 +0,1.184000,0.0,0.0,0.0,0.0,0.0 +0,1.184100,0.0,0.0,0.0,0.0,0.0 +0,1.184200,0.0,0.0,0.0,0.0,0.0 +0,1.184300,0.0,0.0,0.0,0.0,0.0 +0,1.184400,0.0,0.0,0.0,0.0,0.0 +0,1.184500,0.0,0.0,0.0,0.0,0.0 +0,1.184600,0.0,0.0,0.0,0.0,0.0 +0,1.184700,0.0,0.0,0.0,0.0,0.0 +0,1.184800,0.0,0.0,0.0,0.0,0.0 +0,1.184900,0.0,0.0,0.0,0.0,0.0 +0,1.185000,0.0,0.0,0.0,0.0,0.0 +0,1.185100,0.0,0.0,0.0,0.0,0.0 +0,1.185200,0.0,0.0,0.0,0.0,0.0 +0,1.185300,0.0,0.0,0.0,0.0,0.0 +0,1.185400,0.0,0.0,0.0,0.0,0.0 +0,1.185500,0.0,0.0,0.0,0.0,0.0 +0,1.185600,0.0,0.0,0.0,0.0,0.0 +0,1.185700,0.0,0.0,0.0,0.0,0.0 +0,1.185800,0.0,0.0,0.0,0.0,0.0 +0,1.185900,0.0,0.0,0.0,0.0,0.0 +0,1.186000,0.0,0.0,0.0,0.0,0.0 +0,1.186100,0.0,0.0,0.0,0.0,0.0 +0,1.186200,0.0,0.0,0.0,0.0,0.0 +0,1.186300,0.0,0.0,0.0,0.0,0.0 +0,1.186400,0.0,0.0,0.0,0.0,0.0 +0,1.186500,0.0,0.0,0.0,0.0,0.0 +0,1.186600,0.0,0.0,0.0,0.0,0.0 +0,1.186700,0.0,0.0,0.0,0.0,0.0 +0,1.186800,0.0,0.0,0.0,0.0,0.0 +0,1.186900,0.0,0.0,0.0,0.0,0.0 +0,1.187000,0.0,0.0,0.0,0.0,0.0 +0,1.187100,0.0,0.0,0.0,0.0,0.0 +0,1.187200,0.0,0.0,0.0,0.0,0.0 +0,1.187300,0.0,0.0,0.0,0.0,0.0 +0,1.187400,0.0,0.0,0.0,0.0,0.0 +0,1.187500,0.0,0.0,0.0,0.0,0.0 +0,1.187600,0.0,0.0,0.0,0.0,0.0 +0,1.187700,0.0,0.0,0.0,0.0,0.0 +0,1.187800,0.0,0.0,0.0,0.0,0.0 +0,1.187900,0.0,0.0,0.0,0.0,0.0 +0,1.188000,0.0,0.0,0.0,0.0,0.0 +0,1.188100,0.0,0.0,0.0,0.0,0.0 +0,1.188200,0.0,0.0,0.0,0.0,0.0 +0,1.188300,0.0,0.0,0.0,0.0,0.0 +0,1.188400,0.0,0.0,0.0,0.0,0.0 +0,1.188500,0.0,0.0,0.0,0.0,0.0 +0,1.188600,0.0,0.0,0.0,0.0,0.0 +0,1.188700,0.0,0.0,0.0,0.0,0.0 +0,1.188800,0.0,0.0,0.0,0.0,0.0 +0,1.188900,0.0,0.0,0.0,0.0,0.0 +0,1.189000,0.0,0.0,0.0,0.0,0.0 +0,1.189100,0.0,0.0,0.0,0.0,0.0 +0,1.189200,0.0,0.0,0.0,0.0,0.0 +0,1.189300,0.0,0.0,0.0,0.0,0.0 +0,1.189400,0.0,0.0,0.0,0.0,0.0 +0,1.189500,0.0,0.0,0.0,0.0,0.0 +0,1.189600,0.0,0.0,0.0,0.0,0.0 +0,1.189700,0.0,0.0,0.0,0.0,0.0 +0,1.189800,0.0,0.0,0.0,0.0,0.0 +0,1.189900,0.0,0.0,0.0,0.0,0.0 +0,1.190000,0.0,0.0,0.0,0.0,0.0 +0,1.190100,0.0,0.0,0.0,0.0,0.0 +0,1.190200,0.0,0.0,0.0,0.0,0.0 +0,1.190300,0.0,0.0,0.0,0.0,0.0 +0,1.190400,0.0,0.0,0.0,0.0,0.0 +0,1.190500,0.0,0.0,0.0,0.0,0.0 +0,1.190600,0.0,0.0,0.0,0.0,0.0 +0,1.190700,0.0,0.0,0.0,0.0,0.0 +0,1.190800,0.0,0.0,0.0,0.0,0.0 +0,1.190900,0.0,0.0,0.0,0.0,0.0 +0,1.191000,0.0,0.0,0.0,0.0,0.0 +0,1.191100,0.0,0.0,0.0,0.0,0.0 +0,1.191200,0.0,0.0,0.0,0.0,0.0 +0,1.191300,0.0,0.0,0.0,0.0,0.0 +0,1.191400,0.0,0.0,0.0,0.0,0.0 +0,1.191500,0.0,0.0,0.0,0.0,0.0 +0,1.191600,0.0,0.0,0.0,0.0,0.0 +0,1.191700,0.0,0.0,0.0,0.0,0.0 +0,1.191800,0.0,0.0,0.0,0.0,0.0 +0,1.191900,0.0,0.0,0.0,0.0,0.0 +0,1.192000,0.0,0.0,0.0,0.0,0.0 +0,1.192100,0.0,0.0,0.0,0.0,0.0 +0,1.192200,0.0,0.0,0.0,0.0,0.0 +0,1.192300,0.0,0.0,0.0,0.0,0.0 +0,1.192400,0.0,0.0,0.0,0.0,0.0 +0,1.192500,0.0,0.0,0.0,0.0,0.0 +0,1.192600,0.0,0.0,0.0,0.0,0.0 +0,1.192700,0.0,0.0,0.0,0.0,0.0 +0,1.192800,0.0,0.0,0.0,0.0,0.0 +0,1.192900,0.0,0.0,0.0,0.0,0.0 +0,1.193000,0.0,0.0,0.0,0.0,0.0 +0,1.193100,0.0,0.0,0.0,0.0,0.0 +0,1.193200,0.0,0.0,0.0,0.0,0.0 +0,1.193300,0.0,0.0,0.0,0.0,0.0 +0,1.193400,0.0,0.0,0.0,0.0,0.0 +0,1.193500,0.0,0.0,0.0,0.0,0.0 +0,1.193600,0.0,0.0,0.0,0.0,0.0 +0,1.193700,0.0,0.0,0.0,0.0,0.0 +0,1.193800,0.0,0.0,0.0,0.0,0.0 +0,1.193900,0.0,0.0,0.0,0.0,0.0 +0,1.194000,0.0,0.0,0.0,0.0,0.0 +0,1.194100,0.0,0.0,0.0,0.0,0.0 +0,1.194200,0.0,0.0,0.0,0.0,0.0 +0,1.194300,0.0,0.0,0.0,0.0,0.0 +0,1.194400,0.0,0.0,0.0,0.0,0.0 +0,1.194500,0.0,0.0,0.0,0.0,0.0 +0,1.194600,0.0,0.0,0.0,0.0,0.0 +0,1.194700,0.0,0.0,0.0,0.0,0.0 +0,1.194800,0.0,0.0,0.0,0.0,0.0 +0,1.194900,0.0,0.0,0.0,0.0,0.0 +0,1.195000,0.0,0.0,0.0,0.0,0.0 +0,1.195100,0.0,0.0,0.0,0.0,0.0 +0,1.195200,0.0,0.0,0.0,0.0,0.0 +0,1.195300,0.0,0.0,0.0,0.0,0.0 +0,1.195400,0.0,0.0,0.0,0.0,0.0 +0,1.195500,0.0,0.0,0.0,0.0,0.0 +0,1.195600,0.0,0.0,0.0,0.0,0.0 +0,1.195700,0.0,0.0,0.0,0.0,0.0 +0,1.195800,0.0,0.0,0.0,0.0,0.0 +0,1.195900,0.0,0.0,0.0,0.0,0.0 +0,1.196000,0.0,0.0,0.0,0.0,0.0 +0,1.196100,0.0,0.0,0.0,0.0,0.0 +0,1.196200,0.0,0.0,0.0,0.0,0.0 +0,1.196300,0.0,0.0,0.0,0.0,0.0 +0,1.196400,0.0,0.0,0.0,0.0,0.0 +0,1.196500,0.0,0.0,0.0,0.0,0.0 +0,1.196600,0.0,0.0,0.0,0.0,0.0 +0,1.196700,0.0,0.0,0.0,0.0,0.0 +0,1.196800,0.0,0.0,0.0,0.0,0.0 +0,1.196900,0.0,0.0,0.0,0.0,0.0 +0,1.197000,0.0,0.0,0.0,0.0,0.0 +0,1.197100,0.0,0.0,0.0,0.0,0.0 +0,1.197200,0.0,0.0,0.0,0.0,0.0 +0,1.197300,0.0,0.0,0.0,0.0,0.0 +0,1.197400,0.0,0.0,0.0,0.0,0.0 +0,1.197500,0.0,0.0,0.0,0.0,0.0 +0,1.197600,0.0,0.0,0.0,0.0,0.0 +0,1.197700,0.0,0.0,0.0,0.0,0.0 +0,1.197800,0.0,0.0,0.0,0.0,0.0 +0,1.197900,0.0,0.0,0.0,0.0,0.0 +0,1.198000,0.0,0.0,0.0,0.0,0.0 +0,1.198100,0.0,0.0,0.0,0.0,0.0 +0,1.198200,0.0,0.0,0.0,0.0,0.0 +0,1.198300,0.0,0.0,0.0,0.0,0.0 +0,1.198400,0.0,0.0,0.0,0.0,0.0 +0,1.198500,0.0,0.0,0.0,0.0,0.0 +0,1.198600,0.0,0.0,0.0,0.0,0.0 +0,1.198700,0.0,0.0,0.0,0.0,0.0 +0,1.198800,0.0,0.0,0.0,0.0,0.0 +0,1.198900,0.0,0.0,0.0,0.0,0.0 +0,1.199000,0.0,0.0,0.0,0.0,0.0 +0,1.199100,0.0,0.0,0.0,0.0,0.0 +0,1.199200,0.0,0.0,0.0,0.0,0.0 +0,1.199300,0.0,0.0,0.0,0.0,0.0 +0,1.199400,0.0,0.0,0.0,0.0,0.0 +0,1.199500,0.0,0.0,0.0,0.0,0.0 +0,1.199600,0.0,0.0,0.0,0.0,0.0 +0,1.199700,0.0,0.0,0.0,0.0,0.0 +0,1.199800,0.0,0.0,0.0,0.0,0.0 +0,1.199900,0.0,0.0,0.0,0.0,0.0 +0,1.200000,0.0,0.0,0.0,0.0,0.0 +0,1.200100,0.0,0.0,0.0,0.0,0.0 +1,720.270033,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.200200,0.0,0.0,0.0,0.0,0.0 +0,1.200300,0.0,0.0,0.0,0.0,0.0 +0,1.200400,0.0,0.0,0.0,0.0,0.0 +0,1.200500,0.0,0.0,0.0,0.0,0.0 +0,1.200600,0.0,0.0,0.0,0.0,0.0 +0,1.200700,0.0,0.0,0.0,0.0,0.0 +0,1.200800,0.0,0.0,0.0,0.0,0.0 +0,1.200900,0.0,0.0,0.0,0.0,0.0 +0,1.201000,0.0,0.0,0.0,0.0,0.0 +0,1.201100,0.0,0.0,0.0,0.0,0.0 +0,1.201200,0.0,0.0,0.0,0.0,0.0 +0,1.201300,0.0,0.0,0.0,0.0,0.0 +0,1.201400,0.0,0.0,0.0,0.0,0.0 +0,1.201500,0.0,0.0,0.0,0.0,0.0 +0,1.201600,0.0,0.0,0.0,0.0,0.0 +0,1.201700,0.0,0.0,0.0,0.0,0.0 +0,1.201800,0.0,0.0,0.0,0.0,0.0 +0,1.201900,0.0,0.0,0.0,0.0,0.0 +0,1.202000,0.0,0.0,0.0,0.0,0.0 +0,1.202100,0.0,0.0,0.0,0.0,0.0 +0,1.202200,0.0,0.0,0.0,0.0,0.0 +0,1.202300,0.0,0.0,0.0,0.0,0.0 +0,1.202400,0.0,0.0,0.0,0.0,0.0 +0,1.202500,0.0,0.0,0.0,0.0,0.0 +0,1.202600,0.0,0.0,0.0,0.0,0.0 +0,1.202700,0.0,0.0,0.0,0.0,0.0 +0,1.202800,0.0,0.0,0.0,0.0,0.0 +0,1.202900,0.0,0.0,0.0,0.0,0.0 +0,1.203000,0.0,0.0,0.0,0.0,0.0 +0,1.203100,0.0,0.0,0.0,0.0,0.0 +0,1.203200,0.0,0.0,0.0,0.0,0.0 +0,1.203300,0.0,0.0,0.0,0.0,0.0 +0,1.203400,0.0,0.0,0.0,0.0,0.0 +0,1.203500,0.0,0.0,0.0,0.0,0.0 +0,1.203600,0.0,0.0,0.0,0.0,0.0 +0,1.203700,0.0,0.0,0.0,0.0,0.0 +0,1.203800,0.0,0.0,0.0,0.0,0.0 +0,1.203900,0.0,0.0,0.0,0.0,0.0 +0,1.204000,0.0,0.0,0.0,0.0,0.0 +0,1.204100,0.0,0.0,0.0,0.0,0.0 +0,1.204200,0.0,0.0,0.0,0.0,0.0 +0,1.204300,0.0,0.0,0.0,0.0,0.0 +0,1.204400,0.0,0.0,0.0,0.0,0.0 +0,1.204500,0.0,0.0,0.0,0.0,0.0 +0,1.204600,0.0,0.0,0.0,0.0,0.0 +0,1.204700,0.0,0.0,0.0,0.0,0.0 +0,1.204800,0.0,0.0,0.0,0.0,0.0 +0,1.204900,0.0,0.0,0.0,0.0,0.0 +0,1.205000,0.0,0.0,0.0,0.0,0.0 +0,1.205100,0.0,0.0,0.0,0.0,0.0 +0,1.205200,0.0,0.0,0.0,0.0,0.0 +0,1.205300,0.0,0.0,0.0,0.0,0.0 +0,1.205400,0.0,0.0,0.0,0.0,0.0 +0,1.205500,0.0,0.0,0.0,0.0,0.0 +0,1.205600,0.0,0.0,0.0,0.0,0.0 +0,1.205700,0.0,0.0,0.0,0.0,0.0 +0,1.205800,0.0,0.0,0.0,0.0,0.0 +0,1.205900,0.0,0.0,0.0,0.0,0.0 +0,1.206000,0.0,0.0,0.0,0.0,0.0 +0,1.206100,0.0,0.0,0.0,0.0,0.0 +0,1.206200,0.0,0.0,0.0,0.0,0.0 +0,1.206300,0.0,0.0,0.0,0.0,0.0 +0,1.206400,0.0,0.0,0.0,0.0,0.0 +0,1.206500,0.0,0.0,0.0,0.0,0.0 +0,1.206600,0.0,0.0,0.0,0.0,0.0 +0,1.206700,0.0,0.0,0.0,0.0,0.0 +0,1.206800,0.0,0.0,0.0,0.0,0.0 +0,1.206900,0.0,0.0,0.0,0.0,0.0 +0,1.207000,0.0,0.0,0.0,0.0,0.0 +0,1.207100,0.0,0.0,0.0,0.0,0.0 +0,1.207200,0.0,0.0,0.0,0.0,0.0 +0,1.207300,0.0,0.0,0.0,0.0,0.0 +0,1.207400,0.0,0.0,0.0,0.0,0.0 +0,1.207500,0.0,0.0,0.0,0.0,0.0 +0,1.207600,0.0,0.0,0.0,0.0,0.0 +0,1.207700,0.0,0.0,0.0,0.0,0.0 +0,1.207800,0.0,0.0,0.0,0.0,0.0 +0,1.207900,0.0,0.0,0.0,0.0,0.0 +0,1.208000,0.0,0.0,0.0,0.0,0.0 +0,1.208100,0.0,0.0,0.0,0.0,0.0 +0,1.208200,0.0,0.0,0.0,0.0,0.0 +0,1.208300,0.0,0.0,0.0,0.0,0.0 +0,1.208400,0.0,0.0,0.0,0.0,0.0 +0,1.208500,0.0,0.0,0.0,0.0,0.0 +0,1.208600,0.0,0.0,0.0,0.0,0.0 +0,1.208700,0.0,0.0,0.0,0.0,0.0 +0,1.208800,0.0,0.0,0.0,0.0,0.0 +0,1.208900,0.0,0.0,0.0,0.0,0.0 +0,1.209000,0.0,0.0,0.0,0.0,0.0 +0,1.209100,0.0,0.0,0.0,0.0,0.0 +0,1.209200,0.0,0.0,0.0,0.0,0.0 +0,1.209300,0.0,0.0,0.0,0.0,0.0 +0,1.209400,0.0,0.0,0.0,0.0,0.0 +0,1.209500,0.0,0.0,0.0,0.0,0.0 +0,1.209600,0.0,0.0,0.0,0.0,0.0 +0,1.209700,0.0,0.0,0.0,0.0,0.0 +0,1.209800,0.0,0.0,0.0,0.0,0.0 +0,1.209900,0.0,0.0,0.0,0.0,0.0 +0,1.210000,0.0,0.0,0.0,0.0,0.0 +0,1.210100,0.0,0.0,0.0,0.0,0.0 +0,1.210200,0.0,0.0,0.0,0.0,0.0 +0,1.210300,0.0,0.0,0.0,0.0,0.0 +0,1.210400,0.0,0.0,0.0,0.0,0.0 +0,1.210500,0.0,0.0,0.0,0.0,0.0 +0,1.210600,0.0,0.0,0.0,0.0,0.0 +0,1.210700,0.0,0.0,0.0,0.0,0.0 +0,1.210800,0.0,0.0,0.0,0.0,0.0 +0,1.210900,0.0,0.0,0.0,0.0,0.0 +0,1.211000,0.0,0.0,0.0,0.0,0.0 +0,1.211100,0.0,0.0,0.0,0.0,0.0 +0,1.211200,0.0,0.0,0.0,0.0,0.0 +0,1.211300,0.0,0.0,0.0,0.0,0.0 +0,1.211400,0.0,0.0,0.0,0.0,0.0 +0,1.211500,0.0,0.0,0.0,0.0,0.0 +0,1.211600,0.0,0.0,0.0,0.0,0.0 +0,1.211700,0.0,0.0,0.0,0.0,0.0 +0,1.211800,0.0,0.0,0.0,0.0,0.0 +0,1.211900,0.0,0.0,0.0,0.0,0.0 +0,1.212000,0.0,0.0,0.0,0.0,0.0 +0,1.212100,0.0,0.0,0.0,0.0,0.0 +0,1.212200,0.0,0.0,0.0,0.0,0.0 +0,1.212300,0.0,0.0,0.0,0.0,0.0 +0,1.212400,0.0,0.0,0.0,0.0,0.0 +0,1.212500,0.0,0.0,0.0,0.0,0.0 +0,1.212600,0.0,0.0,0.0,0.0,0.0 +0,1.212700,0.0,0.0,0.0,0.0,0.0 +0,1.212800,0.0,0.0,0.0,0.0,0.0 +0,1.212900,0.0,0.0,0.0,0.0,0.0 +0,1.213000,0.0,0.0,0.0,0.0,0.0 +0,1.213100,0.0,0.0,0.0,0.0,0.0 +0,1.213200,0.0,0.0,0.0,0.0,0.0 +0,1.213300,0.0,0.0,0.0,0.0,0.0 +0,1.213400,0.0,0.0,0.0,0.0,0.0 +0,1.213500,0.0,0.0,0.0,0.0,0.0 +0,1.213600,0.0,0.0,0.0,0.0,0.0 +0,1.213700,0.0,0.0,0.0,0.0,0.0 +0,1.213800,0.0,0.0,0.0,0.0,0.0 +0,1.213900,0.0,0.0,0.0,0.0,0.0 +0,1.214000,0.0,0.0,0.0,0.0,0.0 +0,1.214100,0.0,0.0,0.0,0.0,0.0 +0,1.214200,0.0,0.0,0.0,0.0,0.0 +0,1.214300,0.0,0.0,0.0,0.0,0.0 +0,1.214400,0.0,0.0,0.0,0.0,0.0 +0,1.214500,0.0,0.0,0.0,0.0,0.0 +0,1.214600,0.0,0.0,0.0,0.0,0.0 +0,1.214700,0.0,0.0,0.0,0.0,0.0 +0,1.214800,0.0,0.0,0.0,0.0,0.0 +0,1.214900,0.0,0.0,0.0,0.0,0.0 +0,1.215000,0.0,0.0,0.0,0.0,0.0 +0,1.215100,0.0,0.0,0.0,0.0,0.0 +0,1.215200,0.0,0.0,0.0,0.0,0.0 +0,1.215300,0.0,0.0,0.0,0.0,0.0 +0,1.215400,0.0,0.0,0.0,0.0,0.0 +0,1.215500,0.0,0.0,0.0,0.0,0.0 +0,1.215600,0.0,0.0,0.0,0.0,0.0 +0,1.215700,0.0,0.0,0.0,0.0,0.0 +0,1.215800,0.0,0.0,0.0,0.0,0.0 +0,1.215900,0.0,0.0,0.0,0.0,0.0 +0,1.216000,0.0,0.0,0.0,0.0,0.0 +0,1.216100,0.0,0.0,0.0,0.0,0.0 +0,1.216200,0.0,0.0,0.0,0.0,0.0 +0,1.216300,0.0,0.0,0.0,0.0,0.0 +0,1.216400,0.0,0.0,0.0,0.0,0.0 +0,1.216500,0.0,0.0,0.0,0.0,0.0 +0,1.216600,0.0,0.0,0.0,0.0,0.0 +0,1.216700,0.0,0.0,0.0,0.0,0.0 +0,1.216800,0.0,0.0,0.0,0.0,0.0 +0,1.216900,0.0,0.0,0.0,0.0,0.0 +0,1.217000,0.0,0.0,0.0,0.0,0.0 +0,1.217100,0.0,0.0,0.0,0.0,0.0 +0,1.217200,0.0,0.0,0.0,0.0,0.0 +0,1.217300,0.0,0.0,0.0,0.0,0.0 +0,1.217400,0.0,0.0,0.0,0.0,0.0 +0,1.217500,0.0,0.0,0.0,0.0,0.0 +0,1.217600,0.0,0.0,0.0,0.0,0.0 +0,1.217700,0.0,0.0,0.0,0.0,0.0 +0,1.217800,0.0,0.0,0.0,0.0,0.0 +0,1.217900,0.0,0.0,0.0,0.0,0.0 +0,1.218000,0.0,0.0,0.0,0.0,0.0 +0,1.218100,0.0,0.0,0.0,0.0,0.0 +0,1.218200,0.0,0.0,0.0,0.0,0.0 +0,1.218300,0.0,0.0,0.0,0.0,0.0 +0,1.218400,0.0,0.0,0.0,0.0,0.0 +0,1.218500,0.0,0.0,0.0,0.0,0.0 +0,1.218600,0.0,0.0,0.0,0.0,0.0 +0,1.218700,0.0,0.0,0.0,0.0,0.0 +0,1.218800,0.0,0.0,0.0,0.0,0.0 +0,1.218900,0.0,0.0,0.0,0.0,0.0 +0,1.219000,0.0,0.0,0.0,0.0,0.0 +0,1.219100,0.0,0.0,0.0,0.0,0.0 +0,1.219200,0.0,0.0,0.0,0.0,0.0 +0,1.219300,0.0,0.0,0.0,0.0,0.0 +0,1.219400,0.0,0.0,0.0,0.0,0.0 +0,1.219500,0.0,0.0,0.0,0.0,0.0 +0,1.219600,0.0,0.0,0.0,0.0,0.0 +0,1.219700,0.0,0.0,0.0,0.0,0.0 +0,1.219800,0.0,0.0,0.0,0.0,0.0 +0,1.219900,0.0,0.0,0.0,0.0,0.0 +0,1.220000,0.0,0.0,0.0,0.0,0.0 +0,1.220100,0.0,0.0,0.0,0.0,0.0 +1,756.882441,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.220200,0.0,0.0,0.0,0.0,0.0 +0,1.220300,0.0,0.0,0.0,0.0,0.0 +0,1.220400,0.0,0.0,0.0,0.0,0.0 +0,1.220500,0.0,0.0,0.0,0.0,0.0 +0,1.220600,0.0,0.0,0.0,0.0,0.0 +0,1.220700,0.0,0.0,0.0,0.0,0.0 +0,1.220800,0.0,0.0,0.0,0.0,0.0 +0,1.220900,0.0,0.0,0.0,0.0,0.0 +0,1.221000,0.0,0.0,0.0,0.0,0.0 +0,1.221100,0.0,0.0,0.0,0.0,0.0 +0,1.221200,0.0,0.0,0.0,0.0,0.0 +0,1.221300,0.0,0.0,0.0,0.0,0.0 +0,1.221400,0.0,0.0,0.0,0.0,0.0 +0,1.221500,0.0,0.0,0.0,0.0,0.0 +0,1.221600,0.0,0.0,0.0,0.0,0.0 +0,1.221700,0.0,0.0,0.0,0.0,0.0 +0,1.221800,0.0,0.0,0.0,0.0,0.0 +0,1.221900,0.0,0.0,0.0,0.0,0.0 +0,1.222000,0.0,0.0,0.0,0.0,0.0 +0,1.222100,0.0,0.0,0.0,0.0,0.0 +0,1.222200,0.0,0.0,0.0,0.0,0.0 +0,1.222300,0.0,0.0,0.0,0.0,0.0 +0,1.222400,0.0,0.0,0.0,0.0,0.0 +0,1.222500,0.0,0.0,0.0,0.0,0.0 +0,1.222600,0.0,0.0,0.0,0.0,0.0 +0,1.222700,0.0,0.0,0.0,0.0,0.0 +0,1.222800,0.0,0.0,0.0,0.0,0.0 +0,1.222900,0.0,0.0,0.0,0.0,0.0 +0,1.223000,0.0,0.0,0.0,0.0,0.0 +0,1.223100,0.0,0.0,0.0,0.0,0.0 +0,1.223200,0.0,0.0,0.0,0.0,0.0 +0,1.223300,0.0,0.0,0.0,0.0,0.0 +0,1.223400,0.0,0.0,0.0,0.0,0.0 +0,1.223500,0.0,0.0,0.0,0.0,0.0 +0,1.223600,0.0,0.0,0.0,0.0,0.0 +0,1.223700,0.0,0.0,0.0,0.0,0.0 +0,1.223800,0.0,0.0,0.0,0.0,0.0 +0,1.223900,0.0,0.0,0.0,0.0,0.0 +0,1.224000,0.0,0.0,0.0,0.0,0.0 +0,1.224100,0.0,0.0,0.0,0.0,0.0 +0,1.224200,0.0,0.0,0.0,0.0,0.0 +0,1.224300,0.0,0.0,0.0,0.0,0.0 +0,1.224400,0.0,0.0,0.0,0.0,0.0 +0,1.224500,0.0,0.0,0.0,0.0,0.0 +0,1.224600,0.0,0.0,0.0,0.0,0.0 +0,1.224700,0.0,0.0,0.0,0.0,0.0 +0,1.224800,0.0,0.0,0.0,0.0,0.0 +0,1.224900,0.0,0.0,0.0,0.0,0.0 +0,1.225000,0.0,0.0,0.0,0.0,0.0 +0,1.225100,0.0,0.0,0.0,0.0,0.0 +0,1.225200,0.0,0.0,0.0,0.0,0.0 +0,1.225300,0.0,0.0,0.0,0.0,0.0 +0,1.225400,0.0,0.0,0.0,0.0,0.0 +0,1.225500,0.0,0.0,0.0,0.0,0.0 +0,1.225600,0.0,0.0,0.0,0.0,0.0 +0,1.225700,0.0,0.0,0.0,0.0,0.0 +0,1.225800,0.0,0.0,0.0,0.0,0.0 +0,1.225900,0.0,0.0,0.0,0.0,0.0 +0,1.226000,0.0,0.0,0.0,0.0,0.0 +0,1.226100,0.0,0.0,0.0,0.0,0.0 +0,1.226200,0.0,0.0,0.0,0.0,0.0 +0,1.226300,0.0,0.0,0.0,0.0,0.0 +0,1.226400,0.0,0.0,0.0,0.0,0.0 +0,1.226500,0.0,0.0,0.0,0.0,0.0 +0,1.226600,0.0,0.0,0.0,0.0,0.0 +0,1.226700,0.0,0.0,0.0,0.0,0.0 +0,1.226800,0.0,0.0,0.0,0.0,0.0 +0,1.226900,0.0,0.0,0.0,0.0,0.0 +0,1.227000,0.0,0.0,0.0,0.0,0.0 +0,1.227100,0.0,0.0,0.0,0.0,0.0 +0,1.227200,0.0,0.0,0.0,0.0,0.0 +0,1.227300,0.0,0.0,0.0,0.0,0.0 +0,1.227400,0.0,0.0,0.0,0.0,0.0 +0,1.227500,0.0,0.0,0.0,0.0,0.0 +0,1.227600,0.0,0.0,0.0,0.0,0.0 +0,1.227700,0.0,0.0,0.0,0.0,0.0 +0,1.227800,0.0,0.0,0.0,0.0,0.0 +0,1.227900,0.0,0.0,0.0,0.0,0.0 +0,1.228000,0.0,0.0,0.0,0.0,0.0 +0,1.228100,0.0,0.0,0.0,0.0,0.0 +0,1.228200,0.0,0.0,0.0,0.0,0.0 +0,1.228300,0.0,0.0,0.0,0.0,0.0 +0,1.228400,0.0,0.0,0.0,0.0,0.0 +0,1.228500,0.0,0.0,0.0,0.0,0.0 +0,1.228600,0.0,0.0,0.0,0.0,0.0 +0,1.228700,0.0,0.0,0.0,0.0,0.0 +0,1.228800,0.0,0.0,0.0,0.0,0.0 +0,1.228900,0.0,0.0,0.0,0.0,0.0 +0,1.229000,0.0,0.0,0.0,0.0,0.0 +0,1.229100,0.0,0.0,0.0,0.0,0.0 +0,1.229200,0.0,0.0,0.0,0.0,0.0 +0,1.229300,0.0,0.0,0.0,0.0,0.0 +0,1.229400,0.0,0.0,0.0,0.0,0.0 +0,1.229500,0.0,0.0,0.0,0.0,0.0 +0,1.229600,0.0,0.0,0.0,0.0,0.0 +0,1.229700,0.0,0.0,0.0,0.0,0.0 +0,1.229800,0.0,0.0,0.0,0.0,0.0 +0,1.229900,0.0,0.0,0.0,0.0,0.0 +0,1.230000,0.0,0.0,0.0,0.0,0.0 +0,1.230100,0.0,0.0,0.0,0.0,0.0 +0,1.230200,0.0,0.0,0.0,0.0,0.0 +0,1.230300,0.0,0.0,0.0,0.0,0.0 +0,1.230400,0.0,0.0,0.0,0.0,0.0 +0,1.230500,0.0,0.0,0.0,0.0,0.0 +0,1.230600,0.0,0.0,0.0,0.0,0.0 +0,1.230700,0.0,0.0,0.0,0.0,0.0 +0,1.230800,0.0,0.0,0.0,0.0,0.0 +0,1.230900,0.0,0.0,0.0,0.0,0.0 +0,1.231000,0.0,0.0,0.0,0.0,0.0 +0,1.231100,0.0,0.0,0.0,0.0,0.0 +0,1.231200,0.0,0.0,0.0,0.0,0.0 +0,1.231300,0.0,0.0,0.0,0.0,0.0 +0,1.231400,0.0,0.0,0.0,0.0,0.0 +0,1.231500,0.0,0.0,0.0,0.0,0.0 +0,1.231600,0.0,0.0,0.0,0.0,0.0 +0,1.231700,0.0,0.0,0.0,0.0,0.0 +0,1.231800,0.0,0.0,0.0,0.0,0.0 +0,1.231900,0.0,0.0,0.0,0.0,0.0 +0,1.232000,0.0,0.0,0.0,0.0,0.0 +0,1.232100,0.0,0.0,0.0,0.0,0.0 +0,1.232200,0.0,0.0,0.0,0.0,0.0 +0,1.232300,0.0,0.0,0.0,0.0,0.0 +0,1.232400,0.0,0.0,0.0,0.0,0.0 +0,1.232500,0.0,0.0,0.0,0.0,0.0 +0,1.232600,0.0,0.0,0.0,0.0,0.0 +0,1.232700,0.0,0.0,0.0,0.0,0.0 +0,1.232800,0.0,0.0,0.0,0.0,0.0 +0,1.232900,0.0,0.0,0.0,0.0,0.0 +0,1.233000,0.0,0.0,0.0,0.0,0.0 +0,1.233100,0.0,0.0,0.0,0.0,0.0 +0,1.233200,0.0,0.0,0.0,0.0,0.0 +0,1.233300,0.0,0.0,0.0,0.0,0.0 +0,1.233400,0.0,0.0,0.0,0.0,0.0 +0,1.233500,0.0,0.0,0.0,0.0,0.0 +0,1.233600,0.0,0.0,0.0,0.0,0.0 +0,1.233700,0.0,0.0,0.0,0.0,0.0 +0,1.233800,0.0,0.0,0.0,0.0,0.0 +0,1.233900,0.0,0.0,0.0,0.0,0.0 +0,1.234000,0.0,0.0,0.0,0.0,0.0 +0,1.234100,0.0,0.0,0.0,0.0,0.0 +0,1.234200,0.0,0.0,0.0,0.0,0.0 +0,1.234300,0.0,0.0,0.0,0.0,0.0 +0,1.234400,0.0,0.0,0.0,0.0,0.0 +0,1.234500,0.0,0.0,0.0,0.0,0.0 +0,1.234600,0.0,0.0,0.0,0.0,0.0 +0,1.234700,0.0,0.0,0.0,0.0,0.0 +0,1.234800,0.0,0.0,0.0,0.0,0.0 +0,1.234900,0.0,0.0,0.0,0.0,0.0 +0,1.235000,0.0,0.0,0.0,0.0,0.0 +0,1.235100,0.0,0.0,0.0,0.0,0.0 +0,1.235200,0.0,0.0,0.0,0.0,0.0 +0,1.235300,0.0,0.0,0.0,0.0,0.0 +0,1.235400,0.0,0.0,0.0,0.0,0.0 +0,1.235500,0.0,0.0,0.0,0.0,0.0 +0,1.235600,0.0,0.0,0.0,0.0,0.0 +0,1.235700,0.0,0.0,0.0,0.0,0.0 +0,1.235800,0.0,0.0,0.0,0.0,0.0 +0,1.235900,0.0,0.0,0.0,0.0,0.0 +0,1.236000,0.0,0.0,0.0,0.0,0.0 +0,1.236100,0.0,0.0,0.0,0.0,0.0 +0,1.236200,0.0,0.0,0.0,0.0,0.0 +0,1.236300,0.0,0.0,0.0,0.0,0.0 +0,1.236400,0.0,0.0,0.0,0.0,0.0 +0,1.236500,0.0,0.0,0.0,0.0,0.0 +0,1.236600,0.0,0.0,0.0,0.0,0.0 +0,1.236700,0.0,0.0,0.0,0.0,0.0 +0,1.236800,0.0,0.0,0.0,0.0,0.0 +0,1.236900,0.0,0.0,0.0,0.0,0.0 +0,1.237000,0.0,0.0,0.0,0.0,0.0 +0,1.237100,0.0,0.0,0.0,0.0,0.0 +0,1.237200,0.0,0.0,0.0,0.0,0.0 +0,1.237300,0.0,0.0,0.0,0.0,0.0 +0,1.237400,0.0,0.0,0.0,0.0,0.0 +0,1.237500,0.0,0.0,0.0,0.0,0.0 +0,1.237600,0.0,0.0,0.0,0.0,0.0 +0,1.237700,0.0,0.0,0.0,0.0,0.0 +0,1.237800,0.0,0.0,0.0,0.0,0.0 +0,1.237900,0.0,0.0,0.0,0.0,0.0 +0,1.238000,0.0,0.0,0.0,0.0,0.0 +0,1.238100,0.0,0.0,0.0,0.0,0.0 +0,1.238200,0.0,0.0,0.0,0.0,0.0 +0,1.238300,0.0,0.0,0.0,0.0,0.0 +0,1.238400,0.0,0.0,0.0,0.0,0.0 +0,1.238500,0.0,0.0,0.0,0.0,0.0 +0,1.238600,0.0,0.0,0.0,0.0,0.0 +0,1.238700,0.0,0.0,0.0,0.0,0.0 +0,1.238800,0.0,0.0,0.0,0.0,0.0 +0,1.238900,0.0,0.0,0.0,0.0,0.0 +0,1.239000,0.0,0.0,0.0,0.0,0.0 +0,1.239100,0.0,0.0,0.0,0.0,0.0 +0,1.239200,0.0,0.0,0.0,0.0,0.0 +0,1.239300,0.0,0.0,0.0,0.0,0.0 +0,1.239400,0.0,0.0,0.0,0.0,0.0 +0,1.239500,0.0,0.0,0.0,0.0,0.0 +0,1.239600,0.0,0.0,0.0,0.0,0.0 +0,1.239700,0.0,0.0,0.0,0.0,0.0 +0,1.239800,0.0,0.0,0.0,0.0,0.0 +0,1.239900,0.0,0.0,0.0,0.0,0.0 +0,1.240000,0.0,0.0,0.0,0.0,0.0 +0,1.240100,0.0,0.0,0.0,0.0,0.0 +1,794.715000,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.240200,0.0,0.0,0.0,0.0,0.0 +0,1.240300,0.0,0.0,0.0,0.0,0.0 +0,1.240400,0.0,0.0,0.0,0.0,0.0 +0,1.240500,0.0,0.0,0.0,0.0,0.0 +0,1.240600,0.0,0.0,0.0,0.0,0.0 +0,1.240700,0.0,0.0,0.0,0.0,0.0 +0,1.240800,0.0,0.0,0.0,0.0,0.0 +0,1.240900,0.0,0.0,0.0,0.0,0.0 +0,1.241000,0.0,0.0,0.0,0.0,0.0 +0,1.241100,0.0,0.0,0.0,0.0,0.0 +0,1.241200,0.0,0.0,0.0,0.0,0.0 +0,1.241300,0.0,0.0,0.0,0.0,0.0 +0,1.241400,0.0,0.0,0.0,0.0,0.0 +0,1.241500,0.0,0.0,0.0,0.0,0.0 +0,1.241600,0.0,0.0,0.0,0.0,0.0 +0,1.241700,0.0,0.0,0.0,0.0,0.0 +0,1.241800,0.0,0.0,0.0,0.0,0.0 +0,1.241900,0.0,0.0,0.0,0.0,0.0 +0,1.242000,0.0,0.0,0.0,0.0,0.0 +0,1.242100,0.0,0.0,0.0,0.0,0.0 +0,1.242200,0.0,0.0,0.0,0.0,0.0 +0,1.242300,0.0,0.0,0.0,0.0,0.0 +0,1.242400,0.0,0.0,0.0,0.0,0.0 +0,1.242500,0.0,0.0,0.0,0.0,0.0 +0,1.242600,0.0,0.0,0.0,0.0,0.0 +0,1.242700,0.0,0.0,0.0,0.0,0.0 +0,1.242800,0.0,0.0,0.0,0.0,0.0 +0,1.242900,0.0,0.0,0.0,0.0,0.0 +0,1.243000,0.0,0.0,0.0,0.0,0.0 +0,1.243100,0.0,0.0,0.0,0.0,0.0 +0,1.243200,0.0,0.0,0.0,0.0,0.0 +0,1.243300,0.0,0.0,0.0,0.0,0.0 +0,1.243400,0.0,0.0,0.0,0.0,0.0 +0,1.243500,0.0,0.0,0.0,0.0,0.0 +0,1.243600,0.0,0.0,0.0,0.0,0.0 +0,1.243700,0.0,0.0,0.0,0.0,0.0 +0,1.243800,0.0,0.0,0.0,0.0,0.0 +0,1.243900,0.0,0.0,0.0,0.0,0.0 +0,1.244000,0.0,0.0,0.0,0.0,0.0 +0,1.244100,0.0,0.0,0.0,0.0,0.0 +0,1.244200,0.0,0.0,0.0,0.0,0.0 +0,1.244300,0.0,0.0,0.0,0.0,0.0 +0,1.244400,0.0,0.0,0.0,0.0,0.0 +0,1.244500,0.0,0.0,0.0,0.0,0.0 +0,1.244600,0.0,0.0,0.0,0.0,0.0 +0,1.244700,0.0,0.0,0.0,0.0,0.0 +0,1.244800,0.0,0.0,0.0,0.0,0.0 +0,1.244900,0.0,0.0,0.0,0.0,0.0 +0,1.245000,0.0,0.0,0.0,0.0,0.0 +0,1.245100,0.0,0.0,0.0,0.0,0.0 +0,1.245200,0.0,0.0,0.0,0.0,0.0 +0,1.245300,0.0,0.0,0.0,0.0,0.0 +0,1.245400,0.0,0.0,0.0,0.0,0.0 +0,1.245500,0.0,0.0,0.0,0.0,0.0 +0,1.245600,0.0,0.0,0.0,0.0,0.0 +0,1.245700,0.0,0.0,0.0,0.0,0.0 +0,1.245800,0.0,0.0,0.0,0.0,0.0 +0,1.245900,0.0,0.0,0.0,0.0,0.0 +0,1.246000,0.0,0.0,0.0,0.0,0.0 +0,1.246100,0.0,0.0,0.0,0.0,0.0 +0,1.246200,0.0,0.0,0.0,0.0,0.0 +0,1.246300,0.0,0.0,0.0,0.0,0.0 +0,1.246400,0.0,0.0,0.0,0.0,0.0 +0,1.246500,0.0,0.0,0.0,0.0,0.0 +0,1.246600,0.0,0.0,0.0,0.0,0.0 +0,1.246700,0.0,0.0,0.0,0.0,0.0 +0,1.246800,0.0,0.0,0.0,0.0,0.0 +0,1.246900,0.0,0.0,0.0,0.0,0.0 +0,1.247000,0.0,0.0,0.0,0.0,0.0 +0,1.247100,0.0,0.0,0.0,0.0,0.0 +0,1.247200,0.0,0.0,0.0,0.0,0.0 +0,1.247300,0.0,0.0,0.0,0.0,0.0 +0,1.247400,0.0,0.0,0.0,0.0,0.0 +0,1.247500,0.0,0.0,0.0,0.0,0.0 +0,1.247600,0.0,0.0,0.0,0.0,0.0 +0,1.247700,0.0,0.0,0.0,0.0,0.0 +0,1.247800,0.0,0.0,0.0,0.0,0.0 +0,1.247900,0.0,0.0,0.0,0.0,0.0 +0,1.248000,0.0,0.0,0.0,0.0,0.0 +0,1.248100,0.0,0.0,0.0,0.0,0.0 +0,1.248200,0.0,0.0,0.0,0.0,0.0 +0,1.248300,0.0,0.0,0.0,0.0,0.0 +0,1.248400,0.0,0.0,0.0,0.0,0.0 +0,1.248500,0.0,0.0,0.0,0.0,0.0 +0,1.248600,0.0,0.0,0.0,0.0,0.0 +0,1.248700,0.0,0.0,0.0,0.0,0.0 +0,1.248800,0.0,0.0,0.0,0.0,0.0 +0,1.248900,0.0,0.0,0.0,0.0,0.0 +0,1.249000,0.0,0.0,0.0,0.0,0.0 +0,1.249100,0.0,0.0,0.0,0.0,0.0 +0,1.249200,0.0,0.0,0.0,0.0,0.0 +0,1.249300,0.0,0.0,0.0,0.0,0.0 +0,1.249400,0.0,0.0,0.0,0.0,0.0 +0,1.249500,0.0,0.0,0.0,0.0,0.0 +0,1.249600,0.0,0.0,0.0,0.0,0.0 +0,1.249700,0.0,0.0,0.0,0.0,0.0 +0,1.249800,0.0,0.0,0.0,0.0,0.0 +0,1.249900,0.0,0.0,0.0,0.0,0.0 +0,1.250000,0.0,0.0,0.0,0.0,0.0 +0,1.250100,0.0,0.0,0.0,0.0,0.0 +0,1.250200,0.0,0.0,0.0,0.0,0.0 +0,1.250300,0.0,0.0,0.0,0.0,0.0 +0,1.250400,0.0,0.0,0.0,0.0,0.0 +0,1.250500,0.0,0.0,0.0,0.0,0.0 +0,1.250600,0.0,0.0,0.0,0.0,0.0 +0,1.250700,0.0,0.0,0.0,0.0,0.0 +0,1.250800,0.0,0.0,0.0,0.0,0.0 +0,1.250900,0.0,0.0,0.0,0.0,0.0 +0,1.251000,0.0,0.0,0.0,0.0,0.0 +0,1.251100,0.0,0.0,0.0,0.0,0.0 +0,1.251200,0.0,0.0,0.0,0.0,0.0 +0,1.251300,0.0,0.0,0.0,0.0,0.0 +0,1.251400,0.0,0.0,0.0,0.0,0.0 +0,1.251500,0.0,0.0,0.0,0.0,0.0 +0,1.251600,0.0,0.0,0.0,0.0,0.0 +0,1.251700,0.0,0.0,0.0,0.0,0.0 +0,1.251800,0.0,0.0,0.0,0.0,0.0 +0,1.251900,0.0,0.0,0.0,0.0,0.0 +0,1.252000,0.0,0.0,0.0,0.0,0.0 +0,1.252100,0.0,0.0,0.0,0.0,0.0 +0,1.252200,0.0,0.0,0.0,0.0,0.0 +0,1.252300,0.0,0.0,0.0,0.0,0.0 +0,1.252400,0.0,0.0,0.0,0.0,0.0 +0,1.252500,0.0,0.0,0.0,0.0,0.0 +0,1.252600,0.0,0.0,0.0,0.0,0.0 +0,1.252700,0.0,0.0,0.0,0.0,0.0 +0,1.252800,0.0,0.0,0.0,0.0,0.0 +0,1.252900,0.0,0.0,0.0,0.0,0.0 +0,1.253000,0.0,0.0,0.0,0.0,0.0 +0,1.253100,0.0,0.0,0.0,0.0,0.0 +0,1.253200,0.0,0.0,0.0,0.0,0.0 +0,1.253300,0.0,0.0,0.0,0.0,0.0 +0,1.253400,0.0,0.0,0.0,0.0,0.0 +0,1.253500,0.0,0.0,0.0,0.0,0.0 +0,1.253600,0.0,0.0,0.0,0.0,0.0 +0,1.253700,0.0,0.0,0.0,0.0,0.0 +0,1.253800,0.0,0.0,0.0,0.0,0.0 +0,1.253900,0.0,0.0,0.0,0.0,0.0 +0,1.254000,0.0,0.0,0.0,0.0,0.0 +0,1.254100,0.0,0.0,0.0,0.0,0.0 +0,1.254200,0.0,0.0,0.0,0.0,0.0 +0,1.254300,0.0,0.0,0.0,0.0,0.0 +0,1.254400,0.0,0.0,0.0,0.0,0.0 +0,1.254500,0.0,0.0,0.0,0.0,0.0 +0,1.254600,0.0,0.0,0.0,0.0,0.0 +0,1.254700,0.0,0.0,0.0,0.0,0.0 +0,1.254800,0.0,0.0,0.0,0.0,0.0 +0,1.254900,0.0,0.0,0.0,0.0,0.0 +0,1.255000,0.0,0.0,0.0,0.0,0.0 +0,1.255100,0.0,0.0,0.0,0.0,0.0 +0,1.255200,0.0,0.0,0.0,0.0,0.0 +0,1.255300,0.0,0.0,0.0,0.0,0.0 +0,1.255400,0.0,0.0,0.0,0.0,0.0 +0,1.255500,0.0,0.0,0.0,0.0,0.0 +0,1.255600,0.0,0.0,0.0,0.0,0.0 +0,1.255700,0.0,0.0,0.0,0.0,0.0 +0,1.255800,0.0,0.0,0.0,0.0,0.0 +0,1.255900,0.0,0.0,0.0,0.0,0.0 +0,1.256000,0.0,0.0,0.0,0.0,0.0 +0,1.256100,0.0,0.0,0.0,0.0,0.0 +0,1.256200,0.0,0.0,0.0,0.0,0.0 +0,1.256300,0.0,0.0,0.0,0.0,0.0 +0,1.256400,0.0,0.0,0.0,0.0,0.0 +0,1.256500,0.0,0.0,0.0,0.0,0.0 +0,1.256600,0.0,0.0,0.0,0.0,0.0 +0,1.256700,0.0,0.0,0.0,0.0,0.0 +0,1.256800,0.0,0.0,0.0,0.0,0.0 +0,1.256900,0.0,0.0,0.0,0.0,0.0 +0,1.257000,0.0,0.0,0.0,0.0,0.0 +0,1.257100,0.0,0.0,0.0,0.0,0.0 +0,1.257200,0.0,0.0,0.0,0.0,0.0 +0,1.257300,0.0,0.0,0.0,0.0,0.0 +0,1.257400,0.0,0.0,0.0,0.0,0.0 +0,1.257500,0.0,0.0,0.0,0.0,0.0 +0,1.257600,0.0,0.0,0.0,0.0,0.0 +0,1.257700,0.0,0.0,0.0,0.0,0.0 +0,1.257800,0.0,0.0,0.0,0.0,0.0 +0,1.257900,0.0,0.0,0.0,0.0,0.0 +0,1.258000,0.0,0.0,0.0,0.0,0.0 +0,1.258100,0.0,0.0,0.0,0.0,0.0 +0,1.258200,0.0,0.0,0.0,0.0,0.0 +0,1.258300,0.0,0.0,0.0,0.0,0.0 +0,1.258400,0.0,0.0,0.0,0.0,0.0 +0,1.258500,0.0,0.0,0.0,0.0,0.0 +0,1.258600,0.0,0.0,0.0,0.0,0.0 +0,1.258700,0.0,0.0,0.0,0.0,0.0 +0,1.258800,0.0,0.0,0.0,0.0,0.0 +0,1.258900,0.0,0.0,0.0,0.0,0.0 +0,1.259000,0.0,0.0,0.0,0.0,0.0 +0,1.259100,0.0,0.0,0.0,0.0,0.0 +0,1.259200,0.0,0.0,0.0,0.0,0.0 +0,1.259300,0.0,0.0,0.0,0.0,0.0 +0,1.259400,0.0,0.0,0.0,0.0,0.0 +0,1.259500,0.0,0.0,0.0,0.0,0.0 +0,1.259600,0.0,0.0,0.0,0.0,0.0 +0,1.259700,0.0,0.0,0.0,0.0,0.0 +0,1.259800,0.0,0.0,0.0,0.0,0.0 +0,1.259900,0.0,0.0,0.0,0.0,0.0 +0,1.260000,0.0,0.0,0.0,0.0,0.0 +0,1.260100,0.0,0.0,0.0,0.0,0.0 +1,833.787709,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.260200,0.0,0.0,0.0,0.0,0.0 +0,1.260300,0.0,0.0,0.0,0.0,0.0 +0,1.260400,0.0,0.0,0.0,0.0,0.0 +0,1.260500,0.0,0.0,0.0,0.0,0.0 +0,1.260600,0.0,0.0,0.0,0.0,0.0 +0,1.260700,0.0,0.0,0.0,0.0,0.0 +0,1.260800,0.0,0.0,0.0,0.0,0.0 +0,1.260900,0.0,0.0,0.0,0.0,0.0 +0,1.261000,0.0,0.0,0.0,0.0,0.0 +0,1.261100,0.0,0.0,0.0,0.0,0.0 +0,1.261200,0.0,0.0,0.0,0.0,0.0 +0,1.261300,0.0,0.0,0.0,0.0,0.0 +0,1.261400,0.0,0.0,0.0,0.0,0.0 +0,1.261500,0.0,0.0,0.0,0.0,0.0 +0,1.261600,0.0,0.0,0.0,0.0,0.0 +0,1.261700,0.0,0.0,0.0,0.0,0.0 +0,1.261800,0.0,0.0,0.0,0.0,0.0 +0,1.261900,0.0,0.0,0.0,0.0,0.0 +0,1.262000,0.0,0.0,0.0,0.0,0.0 +0,1.262100,0.0,0.0,0.0,0.0,0.0 +0,1.262200,0.0,0.0,0.0,0.0,0.0 +0,1.262300,0.0,0.0,0.0,0.0,0.0 +0,1.262400,0.0,0.0,0.0,0.0,0.0 +0,1.262500,0.0,0.0,0.0,0.0,0.0 +0,1.262600,0.0,0.0,0.0,0.0,0.0 +0,1.262700,0.0,0.0,0.0,0.0,0.0 +0,1.262800,0.0,0.0,0.0,0.0,0.0 +0,1.262900,0.0,0.0,0.0,0.0,0.0 +0,1.263000,0.0,0.0,0.0,0.0,0.0 +0,1.263100,0.0,0.0,0.0,0.0,0.0 +0,1.263200,0.0,0.0,0.0,0.0,0.0 +0,1.263300,0.0,0.0,0.0,0.0,0.0 +0,1.263400,0.0,0.0,0.0,0.0,0.0 +0,1.263500,0.0,0.0,0.0,0.0,0.0 +0,1.263600,0.0,0.0,0.0,0.0,0.0 +0,1.263700,0.0,0.0,0.0,0.0,0.0 +0,1.263800,0.0,0.0,0.0,0.0,0.0 +0,1.263900,0.0,0.0,0.0,0.0,0.0 +0,1.264000,0.0,0.0,0.0,0.0,0.0 +0,1.264100,0.0,0.0,0.0,0.0,0.0 +0,1.264200,0.0,0.0,0.0,0.0,0.0 +0,1.264300,0.0,0.0,0.0,0.0,0.0 +0,1.264400,0.0,0.0,0.0,0.0,0.0 +0,1.264500,0.0,0.0,0.0,0.0,0.0 +0,1.264600,0.0,0.0,0.0,0.0,0.0 +0,1.264700,0.0,0.0,0.0,0.0,0.0 +0,1.264800,0.0,0.0,0.0,0.0,0.0 +0,1.264900,0.0,0.0,0.0,0.0,0.0 +0,1.265000,0.0,0.0,0.0,0.0,0.0 +0,1.265100,0.0,0.0,0.0,0.0,0.0 +0,1.265200,0.0,0.0,0.0,0.0,0.0 +0,1.265300,0.0,0.0,0.0,0.0,0.0 +0,1.265400,0.0,0.0,0.0,0.0,0.0 +0,1.265500,0.0,0.0,0.0,0.0,0.0 +0,1.265600,0.0,0.0,0.0,0.0,0.0 +0,1.265700,0.0,0.0,0.0,0.0,0.0 +0,1.265800,0.0,0.0,0.0,0.0,0.0 +0,1.265900,0.0,0.0,0.0,0.0,0.0 +0,1.266000,0.0,0.0,0.0,0.0,0.0 +0,1.266100,0.0,0.0,0.0,0.0,0.0 +0,1.266200,0.0,0.0,0.0,0.0,0.0 +0,1.266300,0.0,0.0,0.0,0.0,0.0 +0,1.266400,0.0,0.0,0.0,0.0,0.0 +0,1.266500,0.0,0.0,0.0,0.0,0.0 +0,1.266600,0.0,0.0,0.0,0.0,0.0 +0,1.266700,0.0,0.0,0.0,0.0,0.0 +0,1.266800,0.0,0.0,0.0,0.0,0.0 +0,1.266900,0.0,0.0,0.0,0.0,0.0 +0,1.267000,0.0,0.0,0.0,0.0,0.0 +0,1.267100,0.0,0.0,0.0,0.0,0.0 +0,1.267200,0.0,0.0,0.0,0.0,0.0 +0,1.267300,0.0,0.0,0.0,0.0,0.0 +0,1.267400,0.0,0.0,0.0,0.0,0.0 +0,1.267500,0.0,0.0,0.0,0.0,0.0 +0,1.267600,0.0,0.0,0.0,0.0,0.0 +0,1.267700,0.0,0.0,0.0,0.0,0.0 +0,1.267800,0.0,0.0,0.0,0.0,0.0 +0,1.267900,0.0,0.0,0.0,0.0,0.0 +0,1.268000,0.0,0.0,0.0,0.0,0.0 +0,1.268100,0.0,0.0,0.0,0.0,0.0 +0,1.268200,0.0,0.0,0.0,0.0,0.0 +0,1.268300,0.0,0.0,0.0,0.0,0.0 +0,1.268400,0.0,0.0,0.0,0.0,0.0 +0,1.268500,0.0,0.0,0.0,0.0,0.0 +0,1.268600,0.0,0.0,0.0,0.0,0.0 +0,1.268700,0.0,0.0,0.0,0.0,0.0 +0,1.268800,0.0,0.0,0.0,0.0,0.0 +0,1.268900,0.0,0.0,0.0,0.0,0.0 +0,1.269000,0.0,0.0,0.0,0.0,0.0 +0,1.269100,0.0,0.0,0.0,0.0,0.0 +0,1.269200,0.0,0.0,0.0,0.0,0.0 +0,1.269300,0.0,0.0,0.0,0.0,0.0 +0,1.269400,0.0,0.0,0.0,0.0,0.0 +0,1.269500,0.0,0.0,0.0,0.0,0.0 +0,1.269600,0.0,0.0,0.0,0.0,0.0 +0,1.269700,0.0,0.0,0.0,0.0,0.0 +0,1.269800,0.0,0.0,0.0,0.0,0.0 +0,1.269900,0.0,0.0,0.0,0.0,0.0 +0,1.270000,0.0,0.0,0.0,0.0,0.0 +0,1.270100,0.0,0.0,0.0,0.0,0.0 +0,1.270200,0.0,0.0,0.0,0.0,0.0 +0,1.270300,0.0,0.0,0.0,0.0,0.0 +0,1.270400,0.0,0.0,0.0,0.0,0.0 +0,1.270500,0.0,0.0,0.0,0.0,0.0 +0,1.270600,0.0,0.0,0.0,0.0,0.0 +0,1.270700,0.0,0.0,0.0,0.0,0.0 +0,1.270800,0.0,0.0,0.0,0.0,0.0 +0,1.270900,0.0,0.0,0.0,0.0,0.0 +0,1.271000,0.0,0.0,0.0,0.0,0.0 +0,1.271100,0.0,0.0,0.0,0.0,0.0 +0,1.271200,0.0,0.0,0.0,0.0,0.0 +0,1.271300,0.0,0.0,0.0,0.0,0.0 +0,1.271400,0.0,0.0,0.0,0.0,0.0 +0,1.271500,0.0,0.0,0.0,0.0,0.0 +0,1.271600,0.0,0.0,0.0,0.0,0.0 +0,1.271700,0.0,0.0,0.0,0.0,0.0 +0,1.271800,0.0,0.0,0.0,0.0,0.0 +0,1.271900,0.0,0.0,0.0,0.0,0.0 +0,1.272000,0.0,0.0,0.0,0.0,0.0 +0,1.272100,0.0,0.0,0.0,0.0,0.0 +0,1.272200,0.0,0.0,0.0,0.0,0.0 +0,1.272300,0.0,0.0,0.0,0.0,0.0 +0,1.272400,0.0,0.0,0.0,0.0,0.0 +0,1.272500,0.0,0.0,0.0,0.0,0.0 +0,1.272600,0.0,0.0,0.0,0.0,0.0 +0,1.272700,0.0,0.0,0.0,0.0,0.0 +0,1.272800,0.0,0.0,0.0,0.0,0.0 +0,1.272900,0.0,0.0,0.0,0.0,0.0 +0,1.273000,0.0,0.0,0.0,0.0,0.0 +0,1.273100,0.0,0.0,0.0,0.0,0.0 +0,1.273200,0.0,0.0,0.0,0.0,0.0 +0,1.273300,0.0,0.0,0.0,0.0,0.0 +0,1.273400,0.0,0.0,0.0,0.0,0.0 +0,1.273500,0.0,0.0,0.0,0.0,0.0 +0,1.273600,0.0,0.0,0.0,0.0,0.0 +0,1.273700,0.0,0.0,0.0,0.0,0.0 +0,1.273800,0.0,0.0,0.0,0.0,0.0 +0,1.273900,0.0,0.0,0.0,0.0,0.0 +0,1.274000,0.0,0.0,0.0,0.0,0.0 +0,1.274100,0.0,0.0,0.0,0.0,0.0 +0,1.274200,0.0,0.0,0.0,0.0,0.0 +0,1.274300,0.0,0.0,0.0,0.0,0.0 +0,1.274400,0.0,0.0,0.0,0.0,0.0 +0,1.274500,0.0,0.0,0.0,0.0,0.0 +0,1.274600,0.0,0.0,0.0,0.0,0.0 +0,1.274700,0.0,0.0,0.0,0.0,0.0 +0,1.274800,0.0,0.0,0.0,0.0,0.0 +0,1.274900,0.0,0.0,0.0,0.0,0.0 +0,1.275000,0.0,0.0,0.0,0.0,0.0 +0,1.275100,0.0,0.0,0.0,0.0,0.0 +0,1.275200,0.0,0.0,0.0,0.0,0.0 +0,1.275300,0.0,0.0,0.0,0.0,0.0 +0,1.275400,0.0,0.0,0.0,0.0,0.0 +0,1.275500,0.0,0.0,0.0,0.0,0.0 +0,1.275600,0.0,0.0,0.0,0.0,0.0 +0,1.275700,0.0,0.0,0.0,0.0,0.0 +0,1.275800,0.0,0.0,0.0,0.0,0.0 +0,1.275900,0.0,0.0,0.0,0.0,0.0 +0,1.276000,0.0,0.0,0.0,0.0,0.0 +0,1.276100,0.0,0.0,0.0,0.0,0.0 +0,1.276200,0.0,0.0,0.0,0.0,0.0 +0,1.276300,0.0,0.0,0.0,0.0,0.0 +0,1.276400,0.0,0.0,0.0,0.0,0.0 +0,1.276500,0.0,0.0,0.0,0.0,0.0 +0,1.276600,0.0,0.0,0.0,0.0,0.0 +0,1.276700,0.0,0.0,0.0,0.0,0.0 +0,1.276800,0.0,0.0,0.0,0.0,0.0 +0,1.276900,0.0,0.0,0.0,0.0,0.0 +0,1.277000,0.0,0.0,0.0,0.0,0.0 +0,1.277100,0.0,0.0,0.0,0.0,0.0 +0,1.277200,0.0,0.0,0.0,0.0,0.0 +0,1.277300,0.0,0.0,0.0,0.0,0.0 +0,1.277400,0.0,0.0,0.0,0.0,0.0 +0,1.277500,0.0,0.0,0.0,0.0,0.0 +0,1.277600,0.0,0.0,0.0,0.0,0.0 +0,1.277700,0.0,0.0,0.0,0.0,0.0 +0,1.277800,0.0,0.0,0.0,0.0,0.0 +0,1.277900,0.0,0.0,0.0,0.0,0.0 +0,1.278000,0.0,0.0,0.0,0.0,0.0 +0,1.278100,0.0,0.0,0.0,0.0,0.0 +0,1.278200,0.0,0.0,0.0,0.0,0.0 +0,1.278300,0.0,0.0,0.0,0.0,0.0 +0,1.278400,0.0,0.0,0.0,0.0,0.0 +0,1.278500,0.0,0.0,0.0,0.0,0.0 +0,1.278600,0.0,0.0,0.0,0.0,0.0 +0,1.278700,0.0,0.0,0.0,0.0,0.0 +0,1.278800,0.0,0.0,0.0,0.0,0.0 +0,1.278900,0.0,0.0,0.0,0.0,0.0 +0,1.279000,0.0,0.0,0.0,0.0,0.0 +0,1.279100,0.0,0.0,0.0,0.0,0.0 +0,1.279200,0.0,0.0,0.0,0.0,0.0 +0,1.279300,0.0,0.0,0.0,0.0,0.0 +0,1.279400,0.0,0.0,0.0,0.0,0.0 +0,1.279500,0.0,0.0,0.0,0.0,0.0 +0,1.279600,0.0,0.0,0.0,0.0,0.0 +0,1.279700,0.0,0.0,0.0,0.0,0.0 +0,1.279800,0.0,0.0,0.0,0.0,0.0 +0,1.279900,0.0,0.0,0.0,0.0,0.0 +0,1.280000,0.0,0.0,0.0,0.0,0.0 +0,1.280100,0.0,0.0,0.0,0.0,0.0 +1,874.120568,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.280200,0.0,0.0,0.0,0.0,0.0 +0,1.280300,0.0,0.0,0.0,0.0,0.0 +0,1.280400,0.0,0.0,0.0,0.0,0.0 +0,1.280500,0.0,0.0,0.0,0.0,0.0 +0,1.280600,0.0,0.0,0.0,0.0,0.0 +0,1.280700,0.0,0.0,0.0,0.0,0.0 +0,1.280800,0.0,0.0,0.0,0.0,0.0 +0,1.280900,0.0,0.0,0.0,0.0,0.0 +0,1.281000,0.0,0.0,0.0,0.0,0.0 +0,1.281100,0.0,0.0,0.0,0.0,0.0 +0,1.281200,0.0,0.0,0.0,0.0,0.0 +0,1.281300,0.0,0.0,0.0,0.0,0.0 +0,1.281400,0.0,0.0,0.0,0.0,0.0 +0,1.281500,0.0,0.0,0.0,0.0,0.0 +0,1.281600,0.0,0.0,0.0,0.0,0.0 +0,1.281700,0.0,0.0,0.0,0.0,0.0 +0,1.281800,0.0,0.0,0.0,0.0,0.0 +0,1.281900,0.0,0.0,0.0,0.0,0.0 +0,1.282000,0.0,0.0,0.0,0.0,0.0 +0,1.282100,0.0,0.0,0.0,0.0,0.0 +0,1.282200,0.0,0.0,0.0,0.0,0.0 +0,1.282300,0.0,0.0,0.0,0.0,0.0 +0,1.282400,0.0,0.0,0.0,0.0,0.0 +0,1.282500,0.0,0.0,0.0,0.0,0.0 +0,1.282600,0.0,0.0,0.0,0.0,0.0 +0,1.282700,0.0,0.0,0.0,0.0,0.0 +0,1.282800,0.0,0.0,0.0,0.0,0.0 +0,1.282900,0.0,0.0,0.0,0.0,0.0 +0,1.283000,0.0,0.0,0.0,0.0,0.0 +0,1.283100,0.0,0.0,0.0,0.0,0.0 +0,1.283200,0.0,0.0,0.0,0.0,0.0 +0,1.283300,0.0,0.0,0.0,0.0,0.0 +0,1.283400,0.0,0.0,0.0,0.0,0.0 +0,1.283500,0.0,0.0,0.0,0.0,0.0 +0,1.283600,0.0,0.0,0.0,0.0,0.0 +0,1.283700,0.0,0.0,0.0,0.0,0.0 +0,1.283800,0.0,0.0,0.0,0.0,0.0 +0,1.283900,0.0,0.0,0.0,0.0,0.0 +0,1.284000,0.0,0.0,0.0,0.0,0.0 +0,1.284100,0.0,0.0,0.0,0.0,0.0 +0,1.284200,0.0,0.0,0.0,0.0,0.0 +0,1.284300,0.0,0.0,0.0,0.0,0.0 +0,1.284400,0.0,0.0,0.0,0.0,0.0 +0,1.284500,0.0,0.0,0.0,0.0,0.0 +0,1.284600,0.0,0.0,0.0,0.0,0.0 +0,1.284700,0.0,0.0,0.0,0.0,0.0 +0,1.284800,0.0,0.0,0.0,0.0,0.0 +0,1.284900,0.0,0.0,0.0,0.0,0.0 +0,1.285000,0.0,0.0,0.0,0.0,0.0 +0,1.285100,0.0,0.0,0.0,0.0,0.0 +0,1.285200,0.0,0.0,0.0,0.0,0.0 +0,1.285300,0.0,0.0,0.0,0.0,0.0 +0,1.285400,0.0,0.0,0.0,0.0,0.0 +0,1.285500,0.0,0.0,0.0,0.0,0.0 +0,1.285600,0.0,0.0,0.0,0.0,0.0 +0,1.285700,0.0,0.0,0.0,0.0,0.0 +0,1.285800,0.0,0.0,0.0,0.0,0.0 +0,1.285900,0.0,0.0,0.0,0.0,0.0 +0,1.286000,0.0,0.0,0.0,0.0,0.0 +0,1.286100,0.0,0.0,0.0,0.0,0.0 +0,1.286200,0.0,0.0,0.0,0.0,0.0 +0,1.286300,0.0,0.0,0.0,0.0,0.0 +0,1.286400,0.0,0.0,0.0,0.0,0.0 +0,1.286500,0.0,0.0,0.0,0.0,0.0 +0,1.286600,0.0,0.0,0.0,0.0,0.0 +0,1.286700,0.0,0.0,0.0,0.0,0.0 +0,1.286800,0.0,0.0,0.0,0.0,0.0 +0,1.286900,0.0,0.0,0.0,0.0,0.0 +0,1.287000,0.0,0.0,0.0,0.0,0.0 +0,1.287100,0.0,0.0,0.0,0.0,0.0 +0,1.287200,0.0,0.0,0.0,0.0,0.0 +0,1.287300,0.0,0.0,0.0,0.0,0.0 +0,1.287400,0.0,0.0,0.0,0.0,0.0 +0,1.287500,0.0,0.0,0.0,0.0,0.0 +0,1.287600,0.0,0.0,0.0,0.0,0.0 +0,1.287700,0.0,0.0,0.0,0.0,0.0 +0,1.287800,0.0,0.0,0.0,0.0,0.0 +0,1.287900,0.0,0.0,0.0,0.0,0.0 +0,1.288000,0.0,0.0,0.0,0.0,0.0 +0,1.288100,0.0,0.0,0.0,0.0,0.0 +0,1.288200,0.0,0.0,0.0,0.0,0.0 +0,1.288300,0.0,0.0,0.0,0.0,0.0 +0,1.288400,0.0,0.0,0.0,0.0,0.0 +0,1.288500,0.0,0.0,0.0,0.0,0.0 +0,1.288600,0.0,0.0,0.0,0.0,0.0 +0,1.288700,0.0,0.0,0.0,0.0,0.0 +0,1.288800,0.0,0.0,0.0,0.0,0.0 +0,1.288900,0.0,0.0,0.0,0.0,0.0 +0,1.289000,0.0,0.0,0.0,0.0,0.0 +0,1.289100,0.0,0.0,0.0,0.0,0.0 +0,1.289200,0.0,0.0,0.0,0.0,0.0 +0,1.289300,0.0,0.0,0.0,0.0,0.0 +0,1.289400,0.0,0.0,0.0,0.0,0.0 +0,1.289500,0.0,0.0,0.0,0.0,0.0 +0,1.289600,0.0,0.0,0.0,0.0,0.0 +0,1.289700,0.0,0.0,0.0,0.0,0.0 +0,1.289800,0.0,0.0,0.0,0.0,0.0 +0,1.289900,0.0,0.0,0.0,0.0,0.0 +0,1.290000,0.0,0.0,0.0,0.0,0.0 +0,1.290100,0.0,0.0,0.0,0.0,0.0 +0,1.290200,0.0,0.0,0.0,0.0,0.0 +0,1.290300,0.0,0.0,0.0,0.0,0.0 +0,1.290400,0.0,0.0,0.0,0.0,0.0 +0,1.290500,0.0,0.0,0.0,0.0,0.0 +0,1.290600,0.0,0.0,0.0,0.0,0.0 +0,1.290700,0.0,0.0,0.0,0.0,0.0 +0,1.290800,0.0,0.0,0.0,0.0,0.0 +0,1.290900,0.0,0.0,0.0,0.0,0.0 +0,1.291000,0.0,0.0,0.0,0.0,0.0 +0,1.291100,0.0,0.0,0.0,0.0,0.0 +0,1.291200,0.0,0.0,0.0,0.0,0.0 +0,1.291300,0.0,0.0,0.0,0.0,0.0 +0,1.291400,0.0,0.0,0.0,0.0,0.0 +0,1.291500,0.0,0.0,0.0,0.0,0.0 +0,1.291600,0.0,0.0,0.0,0.0,0.0 +0,1.291700,0.0,0.0,0.0,0.0,0.0 +0,1.291800,0.0,0.0,0.0,0.0,0.0 +0,1.291900,0.0,0.0,0.0,0.0,0.0 +0,1.292000,0.0,0.0,0.0,0.0,0.0 +0,1.292100,0.0,0.0,0.0,0.0,0.0 +0,1.292200,0.0,0.0,0.0,0.0,0.0 +0,1.292300,0.0,0.0,0.0,0.0,0.0 +0,1.292400,0.0,0.0,0.0,0.0,0.0 +0,1.292500,0.0,0.0,0.0,0.0,0.0 +0,1.292600,0.0,0.0,0.0,0.0,0.0 +0,1.292700,0.0,0.0,0.0,0.0,0.0 +0,1.292800,0.0,0.0,0.0,0.0,0.0 +0,1.292900,0.0,0.0,0.0,0.0,0.0 +0,1.293000,0.0,0.0,0.0,0.0,0.0 +0,1.293100,0.0,0.0,0.0,0.0,0.0 +0,1.293200,0.0,0.0,0.0,0.0,0.0 +0,1.293300,0.0,0.0,0.0,0.0,0.0 +0,1.293400,0.0,0.0,0.0,0.0,0.0 +0,1.293500,0.0,0.0,0.0,0.0,0.0 +0,1.293600,0.0,0.0,0.0,0.0,0.0 +0,1.293700,0.0,0.0,0.0,0.0,0.0 +0,1.293800,0.0,0.0,0.0,0.0,0.0 +0,1.293900,0.0,0.0,0.0,0.0,0.0 +0,1.294000,0.0,0.0,0.0,0.0,0.0 +0,1.294100,0.0,0.0,0.0,0.0,0.0 +0,1.294200,0.0,0.0,0.0,0.0,0.0 +0,1.294300,0.0,0.0,0.0,0.0,0.0 +0,1.294400,0.0,0.0,0.0,0.0,0.0 +0,1.294500,0.0,0.0,0.0,0.0,0.0 +0,1.294600,0.0,0.0,0.0,0.0,0.0 +0,1.294700,0.0,0.0,0.0,0.0,0.0 +0,1.294800,0.0,0.0,0.0,0.0,0.0 +0,1.294900,0.0,0.0,0.0,0.0,0.0 +0,1.295000,0.0,0.0,0.0,0.0,0.0 +0,1.295100,0.0,0.0,0.0,0.0,0.0 +0,1.295200,0.0,0.0,0.0,0.0,0.0 +0,1.295300,0.0,0.0,0.0,0.0,0.0 +0,1.295400,0.0,0.0,0.0,0.0,0.0 +0,1.295500,0.0,0.0,0.0,0.0,0.0 +0,1.295600,0.0,0.0,0.0,0.0,0.0 +0,1.295700,0.0,0.0,0.0,0.0,0.0 +0,1.295800,0.0,0.0,0.0,0.0,0.0 +0,1.295900,0.0,0.0,0.0,0.0,0.0 +0,1.296000,0.0,0.0,0.0,0.0,0.0 +0,1.296100,0.0,0.0,0.0,0.0,0.0 +0,1.296200,0.0,0.0,0.0,0.0,0.0 +0,1.296300,0.0,0.0,0.0,0.0,0.0 +0,1.296400,0.0,0.0,0.0,0.0,0.0 +0,1.296500,0.0,0.0,0.0,0.0,0.0 +0,1.296600,0.0,0.0,0.0,0.0,0.0 +0,1.296700,0.0,0.0,0.0,0.0,0.0 +0,1.296800,0.0,0.0,0.0,0.0,0.0 +0,1.296900,0.0,0.0,0.0,0.0,0.0 +0,1.297000,0.0,0.0,0.0,0.0,0.0 +0,1.297100,0.0,0.0,0.0,0.0,0.0 +0,1.297200,0.0,0.0,0.0,0.0,0.0 +0,1.297300,0.0,0.0,0.0,0.0,0.0 +0,1.297400,0.0,0.0,0.0,0.0,0.0 +0,1.297500,0.0,0.0,0.0,0.0,0.0 +0,1.297600,0.0,0.0,0.0,0.0,0.0 +0,1.297700,0.0,0.0,0.0,0.0,0.0 +0,1.297800,0.0,0.0,0.0,0.0,0.0 +0,1.297900,0.0,0.0,0.0,0.0,0.0 +0,1.298000,0.0,0.0,0.0,0.0,0.0 +0,1.298100,0.0,0.0,0.0,0.0,0.0 +0,1.298200,0.0,0.0,0.0,0.0,0.0 +0,1.298300,0.0,0.0,0.0,0.0,0.0 +0,1.298400,0.0,0.0,0.0,0.0,0.0 +0,1.298500,0.0,0.0,0.0,0.0,0.0 +0,1.298600,0.0,0.0,0.0,0.0,0.0 +0,1.298700,0.0,0.0,0.0,0.0,0.0 +0,1.298800,0.0,0.0,0.0,0.0,0.0 +0,1.298900,0.0,0.0,0.0,0.0,0.0 +0,1.299000,0.0,0.0,0.0,0.0,0.0 +0,1.299100,0.0,0.0,0.0,0.0,0.0 +0,1.299200,0.0,0.0,0.0,0.0,0.0 +0,1.299300,0.0,0.0,0.0,0.0,0.0 +0,1.299400,0.0,0.0,0.0,0.0,0.0 +0,1.299500,0.0,0.0,0.0,0.0,0.0 +0,1.299600,0.0,0.0,0.0,0.0,0.0 +0,1.299700,0.0,0.0,0.0,0.0,0.0 +0,1.299800,0.0,0.0,0.0,0.0,0.0 +0,1.299900,0.0,0.0,0.0,0.0,0.0 +0,1.300000,0.0,0.0,0.0,0.0,0.0 +0,1.300100,0.0,0.0,0.0,0.0,0.0 +1,915.733577,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.300200,0.0,0.0,0.0,0.0,0.0 +0,1.300300,0.0,0.0,0.0,0.0,0.0 +0,1.300400,0.0,0.0,0.0,0.0,0.0 +0,1.300500,0.0,0.0,0.0,0.0,0.0 +0,1.300600,0.0,0.0,0.0,0.0,0.0 +0,1.300700,0.0,0.0,0.0,0.0,0.0 +0,1.300800,0.0,0.0,0.0,0.0,0.0 +0,1.300900,0.0,0.0,0.0,0.0,0.0 +0,1.301000,0.0,0.0,0.0,0.0,0.0 +0,1.301100,0.0,0.0,0.0,0.0,0.0 +0,1.301200,0.0,0.0,0.0,0.0,0.0 +0,1.301300,0.0,0.0,0.0,0.0,0.0 +0,1.301400,0.0,0.0,0.0,0.0,0.0 +0,1.301500,0.0,0.0,0.0,0.0,0.0 +0,1.301600,0.0,0.0,0.0,0.0,0.0 +0,1.301700,0.0,0.0,0.0,0.0,0.0 +0,1.301800,0.0,0.0,0.0,0.0,0.0 +0,1.301900,0.0,0.0,0.0,0.0,0.0 +0,1.302000,0.0,0.0,0.0,0.0,0.0 +0,1.302100,0.0,0.0,0.0,0.0,0.0 +0,1.302200,0.0,0.0,0.0,0.0,0.0 +0,1.302300,0.0,0.0,0.0,0.0,0.0 +0,1.302400,0.0,0.0,0.0,0.0,0.0 +0,1.302500,0.0,0.0,0.0,0.0,0.0 +0,1.302600,0.0,0.0,0.0,0.0,0.0 +0,1.302700,0.0,0.0,0.0,0.0,0.0 +0,1.302800,0.0,0.0,0.0,0.0,0.0 +0,1.302900,0.0,0.0,0.0,0.0,0.0 +0,1.303000,0.0,0.0,0.0,0.0,0.0 +0,1.303100,0.0,0.0,0.0,0.0,0.0 +0,1.303200,0.0,0.0,0.0,0.0,0.0 +0,1.303300,0.0,0.0,0.0,0.0,0.0 +0,1.303400,0.0,0.0,0.0,0.0,0.0 +0,1.303500,0.0,0.0,0.0,0.0,0.0 +0,1.303600,0.0,0.0,0.0,0.0,0.0 +0,1.303700,0.0,0.0,0.0,0.0,0.0 +0,1.303800,0.0,0.0,0.0,0.0,0.0 +0,1.303900,0.0,0.0,0.0,0.0,0.0 +0,1.304000,0.0,0.0,0.0,0.0,0.0 +0,1.304100,0.0,0.0,0.0,0.0,0.0 +0,1.304200,0.0,0.0,0.0,0.0,0.0 +0,1.304300,0.0,0.0,0.0,0.0,0.0 +0,1.304400,0.0,0.0,0.0,0.0,0.0 +0,1.304500,0.0,0.0,0.0,0.0,0.0 +0,1.304600,0.0,0.0,0.0,0.0,0.0 +0,1.304700,0.0,0.0,0.0,0.0,0.0 +0,1.304800,0.0,0.0,0.0,0.0,0.0 +0,1.304900,0.0,0.0,0.0,0.0,0.0 +0,1.305000,0.0,0.0,0.0,0.0,0.0 +0,1.305100,0.0,0.0,0.0,0.0,0.0 +0,1.305200,0.0,0.0,0.0,0.0,0.0 +0,1.305300,0.0,0.0,0.0,0.0,0.0 +0,1.305400,0.0,0.0,0.0,0.0,0.0 +0,1.305500,0.0,0.0,0.0,0.0,0.0 +0,1.305600,0.0,0.0,0.0,0.0,0.0 +0,1.305700,0.0,0.0,0.0,0.0,0.0 +0,1.305800,0.0,0.0,0.0,0.0,0.0 +0,1.305900,0.0,0.0,0.0,0.0,0.0 +0,1.306000,0.0,0.0,0.0,0.0,0.0 +0,1.306100,0.0,0.0,0.0,0.0,0.0 +0,1.306200,0.0,0.0,0.0,0.0,0.0 +0,1.306300,0.0,0.0,0.0,0.0,0.0 +0,1.306400,0.0,0.0,0.0,0.0,0.0 +0,1.306500,0.0,0.0,0.0,0.0,0.0 +0,1.306600,0.0,0.0,0.0,0.0,0.0 +0,1.306700,0.0,0.0,0.0,0.0,0.0 +0,1.306800,0.0,0.0,0.0,0.0,0.0 +0,1.306900,0.0,0.0,0.0,0.0,0.0 +0,1.307000,0.0,0.0,0.0,0.0,0.0 +0,1.307100,0.0,0.0,0.0,0.0,0.0 +0,1.307200,0.0,0.0,0.0,0.0,0.0 +0,1.307300,0.0,0.0,0.0,0.0,0.0 +0,1.307400,0.0,0.0,0.0,0.0,0.0 +0,1.307500,0.0,0.0,0.0,0.0,0.0 +0,1.307600,0.0,0.0,0.0,0.0,0.0 +0,1.307700,0.0,0.0,0.0,0.0,0.0 +0,1.307800,0.0,0.0,0.0,0.0,0.0 +0,1.307900,0.0,0.0,0.0,0.0,0.0 +0,1.308000,0.0,0.0,0.0,0.0,0.0 +0,1.308100,0.0,0.0,0.0,0.0,0.0 +0,1.308200,0.0,0.0,0.0,0.0,0.0 +0,1.308300,0.0,0.0,0.0,0.0,0.0 +0,1.308400,0.0,0.0,0.0,0.0,0.0 +0,1.308500,0.0,0.0,0.0,0.0,0.0 +0,1.308600,0.0,0.0,0.0,0.0,0.0 +0,1.308700,0.0,0.0,0.0,0.0,0.0 +0,1.308800,0.0,0.0,0.0,0.0,0.0 +0,1.308900,0.0,0.0,0.0,0.0,0.0 +0,1.309000,0.0,0.0,0.0,0.0,0.0 +0,1.309100,0.0,0.0,0.0,0.0,0.0 +0,1.309200,0.0,0.0,0.0,0.0,0.0 +0,1.309300,0.0,0.0,0.0,0.0,0.0 +0,1.309400,0.0,0.0,0.0,0.0,0.0 +0,1.309500,0.0,0.0,0.0,0.0,0.0 +0,1.309600,0.0,0.0,0.0,0.0,0.0 +0,1.309700,0.0,0.0,0.0,0.0,0.0 +0,1.309800,0.0,0.0,0.0,0.0,0.0 +0,1.309900,0.0,0.0,0.0,0.0,0.0 +0,1.310000,0.0,0.0,0.0,0.0,0.0 +0,1.310100,0.0,0.0,0.0,0.0,0.0 +0,1.310200,0.0,0.0,0.0,0.0,0.0 +0,1.310300,0.0,0.0,0.0,0.0,0.0 +0,1.310400,0.0,0.0,0.0,0.0,0.0 +0,1.310500,0.0,0.0,0.0,0.0,0.0 +0,1.310600,0.0,0.0,0.0,0.0,0.0 +0,1.310700,0.0,0.0,0.0,0.0,0.0 +0,1.310800,0.0,0.0,0.0,0.0,0.0 +0,1.310900,0.0,0.0,0.0,0.0,0.0 +0,1.311000,0.0,0.0,0.0,0.0,0.0 +0,1.311100,0.0,0.0,0.0,0.0,0.0 +0,1.311200,0.0,0.0,0.0,0.0,0.0 +0,1.311300,0.0,0.0,0.0,0.0,0.0 +0,1.311400,0.0,0.0,0.0,0.0,0.0 +0,1.311500,0.0,0.0,0.0,0.0,0.0 +0,1.311600,0.0,0.0,0.0,0.0,0.0 +0,1.311700,0.0,0.0,0.0,0.0,0.0 +0,1.311800,0.0,0.0,0.0,0.0,0.0 +0,1.311900,0.0,0.0,0.0,0.0,0.0 +0,1.312000,0.0,0.0,0.0,0.0,0.0 +0,1.312100,0.0,0.0,0.0,0.0,0.0 +0,1.312200,0.0,0.0,0.0,0.0,0.0 +0,1.312300,0.0,0.0,0.0,0.0,0.0 +0,1.312400,0.0,0.0,0.0,0.0,0.0 +0,1.312500,0.0,0.0,0.0,0.0,0.0 +0,1.312600,0.0,0.0,0.0,0.0,0.0 +0,1.312700,0.0,0.0,0.0,0.0,0.0 +0,1.312800,0.0,0.0,0.0,0.0,0.0 +0,1.312900,0.0,0.0,0.0,0.0,0.0 +0,1.313000,0.0,0.0,0.0,0.0,0.0 +0,1.313100,0.0,0.0,0.0,0.0,0.0 +0,1.313200,0.0,0.0,0.0,0.0,0.0 +0,1.313300,0.0,0.0,0.0,0.0,0.0 +0,1.313400,0.0,0.0,0.0,0.0,0.0 +0,1.313500,0.0,0.0,0.0,0.0,0.0 +0,1.313600,0.0,0.0,0.0,0.0,0.0 +0,1.313700,0.0,0.0,0.0,0.0,0.0 +0,1.313800,0.0,0.0,0.0,0.0,0.0 +0,1.313900,0.0,0.0,0.0,0.0,0.0 +0,1.314000,0.0,0.0,0.0,0.0,0.0 +0,1.314100,0.0,0.0,0.0,0.0,0.0 +0,1.314200,0.0,0.0,0.0,0.0,0.0 +0,1.314300,0.0,0.0,0.0,0.0,0.0 +0,1.314400,0.0,0.0,0.0,0.0,0.0 +0,1.314500,0.0,0.0,0.0,0.0,0.0 +0,1.314600,0.0,0.0,0.0,0.0,0.0 +0,1.314700,0.0,0.0,0.0,0.0,0.0 +0,1.314800,0.0,0.0,0.0,0.0,0.0 +0,1.314900,0.0,0.0,0.0,0.0,0.0 +0,1.315000,0.0,0.0,0.0,0.0,0.0 +0,1.315100,0.0,0.0,0.0,0.0,0.0 +0,1.315200,0.0,0.0,0.0,0.0,0.0 +0,1.315300,0.0,0.0,0.0,0.0,0.0 +0,1.315400,0.0,0.0,0.0,0.0,0.0 +0,1.315500,0.0,0.0,0.0,0.0,0.0 +0,1.315600,0.0,0.0,0.0,0.0,0.0 +0,1.315700,0.0,0.0,0.0,0.0,0.0 +0,1.315800,0.0,0.0,0.0,0.0,0.0 +0,1.315900,0.0,0.0,0.0,0.0,0.0 +0,1.316000,0.0,0.0,0.0,0.0,0.0 +0,1.316100,0.0,0.0,0.0,0.0,0.0 +0,1.316200,0.0,0.0,0.0,0.0,0.0 +0,1.316300,0.0,0.0,0.0,0.0,0.0 +0,1.316400,0.0,0.0,0.0,0.0,0.0 +0,1.316500,0.0,0.0,0.0,0.0,0.0 +0,1.316600,0.0,0.0,0.0,0.0,0.0 +0,1.316700,0.0,0.0,0.0,0.0,0.0 +0,1.316800,0.0,0.0,0.0,0.0,0.0 +0,1.316900,0.0,0.0,0.0,0.0,0.0 +0,1.317000,0.0,0.0,0.0,0.0,0.0 +0,1.317100,0.0,0.0,0.0,0.0,0.0 +0,1.317200,0.0,0.0,0.0,0.0,0.0 +0,1.317300,0.0,0.0,0.0,0.0,0.0 +0,1.317400,0.0,0.0,0.0,0.0,0.0 +0,1.317500,0.0,0.0,0.0,0.0,0.0 +0,1.317600,0.0,0.0,0.0,0.0,0.0 +0,1.317700,0.0,0.0,0.0,0.0,0.0 +0,1.317800,0.0,0.0,0.0,0.0,0.0 +0,1.317900,0.0,0.0,0.0,0.0,0.0 +0,1.318000,0.0,0.0,0.0,0.0,0.0 +0,1.318100,0.0,0.0,0.0,0.0,0.0 +0,1.318200,0.0,0.0,0.0,0.0,0.0 +0,1.318300,0.0,0.0,0.0,0.0,0.0 +0,1.318400,0.0,0.0,0.0,0.0,0.0 +0,1.318500,0.0,0.0,0.0,0.0,0.0 +0,1.318600,0.0,0.0,0.0,0.0,0.0 +0,1.318700,0.0,0.0,0.0,0.0,0.0 +0,1.318800,0.0,0.0,0.0,0.0,0.0 +0,1.318900,0.0,0.0,0.0,0.0,0.0 +0,1.319000,0.0,0.0,0.0,0.0,0.0 +0,1.319100,0.0,0.0,0.0,0.0,0.0 +0,1.319200,0.0,0.0,0.0,0.0,0.0 +0,1.319300,0.0,0.0,0.0,0.0,0.0 +0,1.319400,0.0,0.0,0.0,0.0,0.0 +0,1.319500,0.0,0.0,0.0,0.0,0.0 +0,1.319600,0.0,0.0,0.0,0.0,0.0 +0,1.319700,0.0,0.0,0.0,0.0,0.0 +0,1.319800,0.0,0.0,0.0,0.0,0.0 +0,1.319900,0.0,0.0,0.0,0.0,0.0 +0,1.320000,0.0,0.0,0.0,0.0,0.0 +0,1.320100,0.0,0.0,0.0,0.0,0.0 +1,958.646736,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.320200,0.0,0.0,0.0,0.0,0.0 +0,1.320300,0.0,0.0,0.0,0.0,0.0 +0,1.320400,0.0,0.0,0.0,0.0,0.0 +0,1.320500,0.0,0.0,0.0,0.0,0.0 +0,1.320600,0.0,0.0,0.0,0.0,0.0 +0,1.320700,0.0,0.0,0.0,0.0,0.0 +0,1.320800,0.0,0.0,0.0,0.0,0.0 +0,1.320900,0.0,0.0,0.0,0.0,0.0 +0,1.321000,0.0,0.0,0.0,0.0,0.0 +0,1.321100,0.0,0.0,0.0,0.0,0.0 +0,1.321200,0.0,0.0,0.0,0.0,0.0 +0,1.321300,0.0,0.0,0.0,0.0,0.0 +0,1.321400,0.0,0.0,0.0,0.0,0.0 +0,1.321500,0.0,0.0,0.0,0.0,0.0 +0,1.321600,0.0,0.0,0.0,0.0,0.0 +0,1.321700,0.0,0.0,0.0,0.0,0.0 +0,1.321800,0.0,0.0,0.0,0.0,0.0 +0,1.321900,0.0,0.0,0.0,0.0,0.0 +0,1.322000,0.0,0.0,0.0,0.0,0.0 +0,1.322100,0.0,0.0,0.0,0.0,0.0 +0,1.322200,0.0,0.0,0.0,0.0,0.0 +0,1.322300,0.0,0.0,0.0,0.0,0.0 +0,1.322400,0.0,0.0,0.0,0.0,0.0 +0,1.322500,0.0,0.0,0.0,0.0,0.0 +0,1.322600,0.0,0.0,0.0,0.0,0.0 +0,1.322700,0.0,0.0,0.0,0.0,0.0 +0,1.322800,0.0,0.0,0.0,0.0,0.0 +0,1.322900,0.0,0.0,0.0,0.0,0.0 +0,1.323000,0.0,0.0,0.0,0.0,0.0 +0,1.323100,0.0,0.0,0.0,0.0,0.0 +0,1.323200,0.0,0.0,0.0,0.0,0.0 +0,1.323300,0.0,0.0,0.0,0.0,0.0 +0,1.323400,0.0,0.0,0.0,0.0,0.0 +0,1.323500,0.0,0.0,0.0,0.0,0.0 +0,1.323600,0.0,0.0,0.0,0.0,0.0 +0,1.323700,0.0,0.0,0.0,0.0,0.0 +0,1.323800,0.0,0.0,0.0,0.0,0.0 +0,1.323900,0.0,0.0,0.0,0.0,0.0 +0,1.324000,0.0,0.0,0.0,0.0,0.0 +0,1.324100,0.0,0.0,0.0,0.0,0.0 +0,1.324200,0.0,0.0,0.0,0.0,0.0 +0,1.324300,0.0,0.0,0.0,0.0,0.0 +0,1.324400,0.0,0.0,0.0,0.0,0.0 +0,1.324500,0.0,0.0,0.0,0.0,0.0 +0,1.324600,0.0,0.0,0.0,0.0,0.0 +0,1.324700,0.0,0.0,0.0,0.0,0.0 +0,1.324800,0.0,0.0,0.0,0.0,0.0 +0,1.324900,0.0,0.0,0.0,0.0,0.0 +0,1.325000,0.0,0.0,0.0,0.0,0.0 +0,1.325100,0.0,0.0,0.0,0.0,0.0 +0,1.325200,0.0,0.0,0.0,0.0,0.0 +0,1.325300,0.0,0.0,0.0,0.0,0.0 +0,1.325400,0.0,0.0,0.0,0.0,0.0 +0,1.325500,0.0,0.0,0.0,0.0,0.0 +0,1.325600,0.0,0.0,0.0,0.0,0.0 +0,1.325700,0.0,0.0,0.0,0.0,0.0 +0,1.325800,0.0,0.0,0.0,0.0,0.0 +0,1.325900,0.0,0.0,0.0,0.0,0.0 +0,1.326000,0.0,0.0,0.0,0.0,0.0 +0,1.326100,0.0,0.0,0.0,0.0,0.0 +0,1.326200,0.0,0.0,0.0,0.0,0.0 +0,1.326300,0.0,0.0,0.0,0.0,0.0 +0,1.326400,0.0,0.0,0.0,0.0,0.0 +0,1.326500,0.0,0.0,0.0,0.0,0.0 +0,1.326600,0.0,0.0,0.0,0.0,0.0 +0,1.326700,0.0,0.0,0.0,0.0,0.0 +0,1.326800,0.0,0.0,0.0,0.0,0.0 +0,1.326900,0.0,0.0,0.0,0.0,0.0 +0,1.327000,0.0,0.0,0.0,0.0,0.0 +0,1.327100,0.0,0.0,0.0,0.0,0.0 +0,1.327200,0.0,0.0,0.0,0.0,0.0 +0,1.327300,0.0,0.0,0.0,0.0,0.0 +0,1.327400,0.0,0.0,0.0,0.0,0.0 +0,1.327500,0.0,0.0,0.0,0.0,0.0 +0,1.327600,0.0,0.0,0.0,0.0,0.0 +0,1.327700,0.0,0.0,0.0,0.0,0.0 +0,1.327800,0.0,0.0,0.0,0.0,0.0 +0,1.327900,0.0,0.0,0.0,0.0,0.0 +0,1.328000,0.0,0.0,0.0,0.0,0.0 +0,1.328100,0.0,0.0,0.0,0.0,0.0 +0,1.328200,0.0,0.0,0.0,0.0,0.0 +0,1.328300,0.0,0.0,0.0,0.0,0.0 +0,1.328400,0.0,0.0,0.0,0.0,0.0 +0,1.328500,0.0,0.0,0.0,0.0,0.0 +0,1.328600,0.0,0.0,0.0,0.0,0.0 +0,1.328700,0.0,0.0,0.0,0.0,0.0 +0,1.328800,0.0,0.0,0.0,0.0,0.0 +0,1.328900,0.0,0.0,0.0,0.0,0.0 +0,1.329000,0.0,0.0,0.0,0.0,0.0 +0,1.329100,0.0,0.0,0.0,0.0,0.0 +0,1.329200,0.0,0.0,0.0,0.0,0.0 +0,1.329300,0.0,0.0,0.0,0.0,0.0 +0,1.329400,0.0,0.0,0.0,0.0,0.0 +0,1.329500,0.0,0.0,0.0,0.0,0.0 +0,1.329600,0.0,0.0,0.0,0.0,0.0 +0,1.329700,0.0,0.0,0.0,0.0,0.0 +0,1.329800,0.0,0.0,0.0,0.0,0.0 +0,1.329900,0.0,0.0,0.0,0.0,0.0 +0,1.330000,0.0,0.0,0.0,0.0,0.0 +0,1.330100,0.0,0.0,0.0,0.0,0.0 +0,1.330200,0.0,0.0,0.0,0.0,0.0 +0,1.330300,0.0,0.0,0.0,0.0,0.0 +0,1.330400,0.0,0.0,0.0,0.0,0.0 +0,1.330500,0.0,0.0,0.0,0.0,0.0 +0,1.330600,0.0,0.0,0.0,0.0,0.0 +0,1.330700,0.0,0.0,0.0,0.0,0.0 +0,1.330800,0.0,0.0,0.0,0.0,0.0 +0,1.330900,0.0,0.0,0.0,0.0,0.0 +0,1.331000,0.0,0.0,0.0,0.0,0.0 +0,1.331100,0.0,0.0,0.0,0.0,0.0 +0,1.331200,0.0,0.0,0.0,0.0,0.0 +0,1.331300,0.0,0.0,0.0,0.0,0.0 +0,1.331400,0.0,0.0,0.0,0.0,0.0 +0,1.331500,0.0,0.0,0.0,0.0,0.0 +0,1.331600,0.0,0.0,0.0,0.0,0.0 +0,1.331700,0.0,0.0,0.0,0.0,0.0 +0,1.331800,0.0,0.0,0.0,0.0,0.0 +0,1.331900,0.0,0.0,0.0,0.0,0.0 +0,1.332000,0.0,0.0,0.0,0.0,0.0 +0,1.332100,0.0,0.0,0.0,0.0,0.0 +0,1.332200,0.0,0.0,0.0,0.0,0.0 +0,1.332300,0.0,0.0,0.0,0.0,0.0 +0,1.332400,0.0,0.0,0.0,0.0,0.0 +0,1.332500,0.0,0.0,0.0,0.0,0.0 +0,1.332600,0.0,0.0,0.0,0.0,0.0 +0,1.332700,0.0,0.0,0.0,0.0,0.0 +0,1.332800,0.0,0.0,0.0,0.0,0.0 +0,1.332900,0.0,0.0,0.0,0.0,0.0 +0,1.333000,0.0,0.0,0.0,0.0,0.0 +0,1.333100,0.0,0.0,0.0,0.0,0.0 +0,1.333200,0.0,0.0,0.0,0.0,0.0 +0,1.333300,0.0,0.0,0.0,0.0,0.0 +0,1.333400,0.0,0.0,0.0,0.0,0.0 +0,1.333500,0.0,0.0,0.0,0.0,0.0 +0,1.333600,0.0,0.0,0.0,0.0,0.0 +0,1.333700,0.0,0.0,0.0,0.0,0.0 +0,1.333800,0.0,0.0,0.0,0.0,0.0 +0,1.333900,0.0,0.0,0.0,0.0,0.0 +0,1.334000,0.0,0.0,0.0,0.0,0.0 +0,1.334100,0.0,0.0,0.0,0.0,0.0 +0,1.334200,0.0,0.0,0.0,0.0,0.0 +0,1.334300,0.0,0.0,0.0,0.0,0.0 +0,1.334400,0.0,0.0,0.0,0.0,0.0 +0,1.334500,0.0,0.0,0.0,0.0,0.0 +0,1.334600,0.0,0.0,0.0,0.0,0.0 +0,1.334700,0.0,0.0,0.0,0.0,0.0 +0,1.334800,0.0,0.0,0.0,0.0,0.0 +0,1.334900,0.0,0.0,0.0,0.0,0.0 +0,1.335000,0.0,0.0,0.0,0.0,0.0 +0,1.335100,0.0,0.0,0.0,0.0,0.0 +0,1.335200,0.0,0.0,0.0,0.0,0.0 +0,1.335300,0.0,0.0,0.0,0.0,0.0 +0,1.335400,0.0,0.0,0.0,0.0,0.0 +0,1.335500,0.0,0.0,0.0,0.0,0.0 +0,1.335600,0.0,0.0,0.0,0.0,0.0 +0,1.335700,0.0,0.0,0.0,0.0,0.0 +0,1.335800,0.0,0.0,0.0,0.0,0.0 +0,1.335900,0.0,0.0,0.0,0.0,0.0 +0,1.336000,0.0,0.0,0.0,0.0,0.0 +0,1.336100,0.0,0.0,0.0,0.0,0.0 +0,1.336200,0.0,0.0,0.0,0.0,0.0 +0,1.336300,0.0,0.0,0.0,0.0,0.0 +0,1.336400,0.0,0.0,0.0,0.0,0.0 +0,1.336500,0.0,0.0,0.0,0.0,0.0 +0,1.336600,0.0,0.0,0.0,0.0,0.0 +0,1.336700,0.0,0.0,0.0,0.0,0.0 +0,1.336800,0.0,0.0,0.0,0.0,0.0 +0,1.336900,0.0,0.0,0.0,0.0,0.0 +0,1.337000,0.0,0.0,0.0,0.0,0.0 +0,1.337100,0.0,0.0,0.0,0.0,0.0 +0,1.337200,0.0,0.0,0.0,0.0,0.0 +0,1.337300,0.0,0.0,0.0,0.0,0.0 +0,1.337400,0.0,0.0,0.0,0.0,0.0 +0,1.337500,0.0,0.0,0.0,0.0,0.0 +0,1.337600,0.0,0.0,0.0,0.0,0.0 +0,1.337700,0.0,0.0,0.0,0.0,0.0 +0,1.337800,0.0,0.0,0.0,0.0,0.0 +0,1.337900,0.0,0.0,0.0,0.0,0.0 +0,1.338000,0.0,0.0,0.0,0.0,0.0 +0,1.338100,0.0,0.0,0.0,0.0,0.0 +0,1.338200,0.0,0.0,0.0,0.0,0.0 +0,1.338300,0.0,0.0,0.0,0.0,0.0 +0,1.338400,0.0,0.0,0.0,0.0,0.0 +0,1.338500,0.0,0.0,0.0,0.0,0.0 +0,1.338600,0.0,0.0,0.0,0.0,0.0 +0,1.338700,0.0,0.0,0.0,0.0,0.0 +0,1.338800,0.0,0.0,0.0,0.0,0.0 +0,1.338900,0.0,0.0,0.0,0.0,0.0 +0,1.339000,0.0,0.0,0.0,0.0,0.0 +0,1.339100,0.0,0.0,0.0,0.0,0.0 +0,1.339200,0.0,0.0,0.0,0.0,0.0 +0,1.339300,0.0,0.0,0.0,0.0,0.0 +0,1.339400,0.0,0.0,0.0,0.0,0.0 +0,1.339500,0.0,0.0,0.0,0.0,0.0 +0,1.339600,0.0,0.0,0.0,0.0,0.0 +0,1.339700,0.0,0.0,0.0,0.0,0.0 +0,1.339800,0.0,0.0,0.0,0.0,0.0 +0,1.339900,0.0,0.0,0.0,0.0,0.0 +0,1.340000,0.0,0.0,0.0,0.0,0.0 +0,1.340100,0.0,0.0,0.0,0.0,0.0 +1,1002.880045,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.340200,0.0,0.0,0.0,0.0,0.0 +0,1.340300,0.0,0.0,0.0,0.0,0.0 +0,1.340400,0.0,0.0,0.0,0.0,0.0 +0,1.340500,0.0,0.0,0.0,0.0,0.0 +0,1.340600,0.0,0.0,0.0,0.0,0.0 +0,1.340700,0.0,0.0,0.0,0.0,0.0 +0,1.340800,0.0,0.0,0.0,0.0,0.0 +0,1.340900,0.0,0.0,0.0,0.0,0.0 +0,1.341000,0.0,0.0,0.0,0.0,0.0 +0,1.341100,0.0,0.0,0.0,0.0,0.0 +0,1.341200,0.0,0.0,0.0,0.0,0.0 +0,1.341300,0.0,0.0,0.0,0.0,0.0 +0,1.341400,0.0,0.0,0.0,0.0,0.0 +0,1.341500,0.0,0.0,0.0,0.0,0.0 +0,1.341600,0.0,0.0,0.0,0.0,0.0 +0,1.341700,0.0,0.0,0.0,0.0,0.0 +0,1.341800,0.0,0.0,0.0,0.0,0.0 +0,1.341900,0.0,0.0,0.0,0.0,0.0 +0,1.342000,0.0,0.0,0.0,0.0,0.0 +0,1.342100,0.0,0.0,0.0,0.0,0.0 +0,1.342200,0.0,0.0,0.0,0.0,0.0 +0,1.342300,0.0,0.0,0.0,0.0,0.0 +0,1.342400,0.0,0.0,0.0,0.0,0.0 +0,1.342500,0.0,0.0,0.0,0.0,0.0 +0,1.342600,0.0,0.0,0.0,0.0,0.0 +0,1.342700,0.0,0.0,0.0,0.0,0.0 +0,1.342800,0.0,0.0,0.0,0.0,0.0 +0,1.342900,0.0,0.0,0.0,0.0,0.0 +0,1.343000,0.0,0.0,0.0,0.0,0.0 +0,1.343100,0.0,0.0,0.0,0.0,0.0 +0,1.343200,0.0,0.0,0.0,0.0,0.0 +0,1.343300,0.0,0.0,0.0,0.0,0.0 +0,1.343400,0.0,0.0,0.0,0.0,0.0 +0,1.343500,0.0,0.0,0.0,0.0,0.0 +0,1.343600,0.0,0.0,0.0,0.0,0.0 +0,1.343700,0.0,0.0,0.0,0.0,0.0 +0,1.343800,0.0,0.0,0.0,0.0,0.0 +0,1.343900,0.0,0.0,0.0,0.0,0.0 +0,1.344000,0.0,0.0,0.0,0.0,0.0 +0,1.344100,0.0,0.0,0.0,0.0,0.0 +0,1.344200,0.0,0.0,0.0,0.0,0.0 +0,1.344300,0.0,0.0,0.0,0.0,0.0 +0,1.344400,0.0,0.0,0.0,0.0,0.0 +0,1.344500,0.0,0.0,0.0,0.0,0.0 +0,1.344600,0.0,0.0,0.0,0.0,0.0 +0,1.344700,0.0,0.0,0.0,0.0,0.0 +0,1.344800,0.0,0.0,0.0,0.0,0.0 +0,1.344900,0.0,0.0,0.0,0.0,0.0 +0,1.345000,0.0,0.0,0.0,0.0,0.0 +0,1.345100,0.0,0.0,0.0,0.0,0.0 +0,1.345200,0.0,0.0,0.0,0.0,0.0 +0,1.345300,0.0,0.0,0.0,0.0,0.0 +0,1.345400,0.0,0.0,0.0,0.0,0.0 +0,1.345500,0.0,0.0,0.0,0.0,0.0 +0,1.345600,0.0,0.0,0.0,0.0,0.0 +0,1.345700,0.0,0.0,0.0,0.0,0.0 +0,1.345800,0.0,0.0,0.0,0.0,0.0 +0,1.345900,0.0,0.0,0.0,0.0,0.0 +0,1.346000,0.0,0.0,0.0,0.0,0.0 +0,1.346100,0.0,0.0,0.0,0.0,0.0 +0,1.346200,0.0,0.0,0.0,0.0,0.0 +0,1.346300,0.0,0.0,0.0,0.0,0.0 +0,1.346400,0.0,0.0,0.0,0.0,0.0 +0,1.346500,0.0,0.0,0.0,0.0,0.0 +0,1.346600,0.0,0.0,0.0,0.0,0.0 +0,1.346700,0.0,0.0,0.0,0.0,0.0 +0,1.346800,0.0,0.0,0.0,0.0,0.0 +0,1.346900,0.0,0.0,0.0,0.0,0.0 +0,1.347000,0.0,0.0,0.0,0.0,0.0 +0,1.347100,0.0,0.0,0.0,0.0,0.0 +0,1.347200,0.0,0.0,0.0,0.0,0.0 +0,1.347300,0.0,0.0,0.0,0.0,0.0 +0,1.347400,0.0,0.0,0.0,0.0,0.0 +0,1.347500,0.0,0.0,0.0,0.0,0.0 +0,1.347600,0.0,0.0,0.0,0.0,0.0 +0,1.347700,0.0,0.0,0.0,0.0,0.0 +0,1.347800,0.0,0.0,0.0,0.0,0.0 +0,1.347900,0.0,0.0,0.0,0.0,0.0 +0,1.348000,0.0,0.0,0.0,0.0,0.0 +0,1.348100,0.0,0.0,0.0,0.0,0.0 +0,1.348200,0.0,0.0,0.0,0.0,0.0 +0,1.348300,0.0,0.0,0.0,0.0,0.0 +0,1.348400,0.0,0.0,0.0,0.0,0.0 +0,1.348500,0.0,0.0,0.0,0.0,0.0 +0,1.348600,0.0,0.0,0.0,0.0,0.0 +0,1.348700,0.0,0.0,0.0,0.0,0.0 +0,1.348800,0.0,0.0,0.0,0.0,0.0 +0,1.348900,0.0,0.0,0.0,0.0,0.0 +0,1.349000,0.0,0.0,0.0,0.0,0.0 +0,1.349100,0.0,0.0,0.0,0.0,0.0 +0,1.349200,0.0,0.0,0.0,0.0,0.0 +0,1.349300,0.0,0.0,0.0,0.0,0.0 +0,1.349400,0.0,0.0,0.0,0.0,0.0 +0,1.349500,0.0,0.0,0.0,0.0,0.0 +0,1.349600,0.0,0.0,0.0,0.0,0.0 +0,1.349700,0.0,0.0,0.0,0.0,0.0 +0,1.349800,0.0,0.0,0.0,0.0,0.0 +0,1.349900,0.0,0.0,0.0,0.0,0.0 +0,1.350000,0.0,0.0,0.0,0.0,0.0 +0,1.350100,0.0,0.0,0.0,0.0,0.0 +0,1.350200,0.0,0.0,0.0,0.0,0.0 +0,1.350300,0.0,0.0,0.0,0.0,0.0 +0,1.350400,0.0,0.0,0.0,0.0,0.0 +0,1.350500,0.0,0.0,0.0,0.0,0.0 +0,1.350600,0.0,0.0,0.0,0.0,0.0 +0,1.350700,0.0,0.0,0.0,0.0,0.0 +0,1.350800,0.0,0.0,0.0,0.0,0.0 +0,1.350900,0.0,0.0,0.0,0.0,0.0 +0,1.351000,0.0,0.0,0.0,0.0,0.0 +0,1.351100,0.0,0.0,0.0,0.0,0.0 +0,1.351200,0.0,0.0,0.0,0.0,0.0 +0,1.351300,0.0,0.0,0.0,0.0,0.0 +0,1.351400,0.0,0.0,0.0,0.0,0.0 +0,1.351500,0.0,0.0,0.0,0.0,0.0 +0,1.351600,0.0,0.0,0.0,0.0,0.0 +0,1.351700,0.0,0.0,0.0,0.0,0.0 +0,1.351800,0.0,0.0,0.0,0.0,0.0 +0,1.351900,0.0,0.0,0.0,0.0,0.0 +0,1.352000,0.0,0.0,0.0,0.0,0.0 +0,1.352100,0.0,0.0,0.0,0.0,0.0 +0,1.352200,0.0,0.0,0.0,0.0,0.0 +0,1.352300,0.0,0.0,0.0,0.0,0.0 +0,1.352400,0.0,0.0,0.0,0.0,0.0 +0,1.352500,0.0,0.0,0.0,0.0,0.0 +0,1.352600,0.0,0.0,0.0,0.0,0.0 +0,1.352700,0.0,0.0,0.0,0.0,0.0 +0,1.352800,0.0,0.0,0.0,0.0,0.0 +0,1.352900,0.0,0.0,0.0,0.0,0.0 +0,1.353000,0.0,0.0,0.0,0.0,0.0 +0,1.353100,0.0,0.0,0.0,0.0,0.0 +0,1.353200,0.0,0.0,0.0,0.0,0.0 +0,1.353300,0.0,0.0,0.0,0.0,0.0 +0,1.353400,0.0,0.0,0.0,0.0,0.0 +0,1.353500,0.0,0.0,0.0,0.0,0.0 +0,1.353600,0.0,0.0,0.0,0.0,0.0 +0,1.353700,0.0,0.0,0.0,0.0,0.0 +0,1.353800,0.0,0.0,0.0,0.0,0.0 +0,1.353900,0.0,0.0,0.0,0.0,0.0 +0,1.354000,0.0,0.0,0.0,0.0,0.0 +0,1.354100,0.0,0.0,0.0,0.0,0.0 +0,1.354200,0.0,0.0,0.0,0.0,0.0 +0,1.354300,0.0,0.0,0.0,0.0,0.0 +0,1.354400,0.0,0.0,0.0,0.0,0.0 +0,1.354500,0.0,0.0,0.0,0.0,0.0 +0,1.354600,0.0,0.0,0.0,0.0,0.0 +0,1.354700,0.0,0.0,0.0,0.0,0.0 +0,1.354800,0.0,0.0,0.0,0.0,0.0 +0,1.354900,0.0,0.0,0.0,0.0,0.0 +0,1.355000,0.0,0.0,0.0,0.0,0.0 +0,1.355100,0.0,0.0,0.0,0.0,0.0 +0,1.355200,0.0,0.0,0.0,0.0,0.0 +0,1.355300,0.0,0.0,0.0,0.0,0.0 +0,1.355400,0.0,0.0,0.0,0.0,0.0 +0,1.355500,0.0,0.0,0.0,0.0,0.0 +0,1.355600,0.0,0.0,0.0,0.0,0.0 +0,1.355700,0.0,0.0,0.0,0.0,0.0 +0,1.355800,0.0,0.0,0.0,0.0,0.0 +0,1.355900,0.0,0.0,0.0,0.0,0.0 +0,1.356000,0.0,0.0,0.0,0.0,0.0 +0,1.356100,0.0,0.0,0.0,0.0,0.0 +0,1.356200,0.0,0.0,0.0,0.0,0.0 +0,1.356300,0.0,0.0,0.0,0.0,0.0 +0,1.356400,0.0,0.0,0.0,0.0,0.0 +0,1.356500,0.0,0.0,0.0,0.0,0.0 +0,1.356600,0.0,0.0,0.0,0.0,0.0 +0,1.356700,0.0,0.0,0.0,0.0,0.0 +0,1.356800,0.0,0.0,0.0,0.0,0.0 +0,1.356900,0.0,0.0,0.0,0.0,0.0 +0,1.357000,0.0,0.0,0.0,0.0,0.0 +0,1.357100,0.0,0.0,0.0,0.0,0.0 +0,1.357200,0.0,0.0,0.0,0.0,0.0 +0,1.357300,0.0,0.0,0.0,0.0,0.0 +0,1.357400,0.0,0.0,0.0,0.0,0.0 +0,1.357500,0.0,0.0,0.0,0.0,0.0 +0,1.357600,0.0,0.0,0.0,0.0,0.0 +0,1.357700,0.0,0.0,0.0,0.0,0.0 +0,1.357800,0.0,0.0,0.0,0.0,0.0 +0,1.357900,0.0,0.0,0.0,0.0,0.0 +0,1.358000,0.0,0.0,0.0,0.0,0.0 +0,1.358100,0.0,0.0,0.0,0.0,0.0 +0,1.358200,0.0,0.0,0.0,0.0,0.0 +0,1.358300,0.0,0.0,0.0,0.0,0.0 +0,1.358400,0.0,0.0,0.0,0.0,0.0 +0,1.358500,0.0,0.0,0.0,0.0,0.0 +0,1.358600,0.0,0.0,0.0,0.0,0.0 +0,1.358700,0.0,0.0,0.0,0.0,0.0 +0,1.358800,0.0,0.0,0.0,0.0,0.0 +0,1.358900,0.0,0.0,0.0,0.0,0.0 +0,1.359000,0.0,0.0,0.0,0.0,0.0 +0,1.359100,0.0,0.0,0.0,0.0,0.0 +0,1.359200,0.0,0.0,0.0,0.0,0.0 +0,1.359300,0.0,0.0,0.0,0.0,0.0 +0,1.359400,0.0,0.0,0.0,0.0,0.0 +0,1.359500,0.0,0.0,0.0,0.0,0.0 +0,1.359600,0.0,0.0,0.0,0.0,0.0 +0,1.359700,0.0,0.0,0.0,0.0,0.0 +0,1.359800,0.0,0.0,0.0,0.0,0.0 +0,1.359900,0.0,0.0,0.0,0.0,0.0 +0,1.360000,0.0,0.0,0.0,0.0,0.0 +0,1.360100,0.0,0.0,0.0,0.0,0.0 +1,1048.453504,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.360200,0.0,0.0,0.0,0.0,0.0 +0,1.360300,0.0,0.0,0.0,0.0,0.0 +0,1.360400,0.0,0.0,0.0,0.0,0.0 +0,1.360500,0.0,0.0,0.0,0.0,0.0 +0,1.360600,0.0,0.0,0.0,0.0,0.0 +0,1.360700,0.0,0.0,0.0,0.0,0.0 +0,1.360800,0.0,0.0,0.0,0.0,0.0 +0,1.360900,0.0,0.0,0.0,0.0,0.0 +0,1.361000,0.0,0.0,0.0,0.0,0.0 +0,1.361100,0.0,0.0,0.0,0.0,0.0 +0,1.361200,0.0,0.0,0.0,0.0,0.0 +0,1.361300,0.0,0.0,0.0,0.0,0.0 +0,1.361400,0.0,0.0,0.0,0.0,0.0 +0,1.361500,0.0,0.0,0.0,0.0,0.0 +0,1.361600,0.0,0.0,0.0,0.0,0.0 +0,1.361700,0.0,0.0,0.0,0.0,0.0 +0,1.361800,0.0,0.0,0.0,0.0,0.0 +0,1.361900,0.0,0.0,0.0,0.0,0.0 +0,1.362000,0.0,0.0,0.0,0.0,0.0 +0,1.362100,0.0,0.0,0.0,0.0,0.0 +0,1.362200,0.0,0.0,0.0,0.0,0.0 +0,1.362300,0.0,0.0,0.0,0.0,0.0 +0,1.362400,0.0,0.0,0.0,0.0,0.0 +0,1.362500,0.0,0.0,0.0,0.0,0.0 +0,1.362600,0.0,0.0,0.0,0.0,0.0 +0,1.362700,0.0,0.0,0.0,0.0,0.0 +0,1.362800,0.0,0.0,0.0,0.0,0.0 +0,1.362900,0.0,0.0,0.0,0.0,0.0 +0,1.363000,0.0,0.0,0.0,0.0,0.0 +0,1.363100,0.0,0.0,0.0,0.0,0.0 +0,1.363200,0.0,0.0,0.0,0.0,0.0 +0,1.363300,0.0,0.0,0.0,0.0,0.0 +0,1.363400,0.0,0.0,0.0,0.0,0.0 +0,1.363500,0.0,0.0,0.0,0.0,0.0 +0,1.363600,0.0,0.0,0.0,0.0,0.0 +0,1.363700,0.0,0.0,0.0,0.0,0.0 +0,1.363800,0.0,0.0,0.0,0.0,0.0 +0,1.363900,0.0,0.0,0.0,0.0,0.0 +0,1.364000,0.0,0.0,0.0,0.0,0.0 +0,1.364100,0.0,0.0,0.0,0.0,0.0 +0,1.364200,0.0,0.0,0.0,0.0,0.0 +0,1.364300,0.0,0.0,0.0,0.0,0.0 +0,1.364400,0.0,0.0,0.0,0.0,0.0 +0,1.364500,0.0,0.0,0.0,0.0,0.0 +0,1.364600,0.0,0.0,0.0,0.0,0.0 +0,1.364700,0.0,0.0,0.0,0.0,0.0 +0,1.364800,0.0,0.0,0.0,0.0,0.0 +0,1.364900,0.0,0.0,0.0,0.0,0.0 +0,1.365000,0.0,0.0,0.0,0.0,0.0 +0,1.365100,0.0,0.0,0.0,0.0,0.0 +0,1.365200,0.0,0.0,0.0,0.0,0.0 +0,1.365300,0.0,0.0,0.0,0.0,0.0 +0,1.365400,0.0,0.0,0.0,0.0,0.0 +0,1.365500,0.0,0.0,0.0,0.0,0.0 +0,1.365600,0.0,0.0,0.0,0.0,0.0 +0,1.365700,0.0,0.0,0.0,0.0,0.0 +0,1.365800,0.0,0.0,0.0,0.0,0.0 +0,1.365900,0.0,0.0,0.0,0.0,0.0 +0,1.366000,0.0,0.0,0.0,0.0,0.0 +0,1.366100,0.0,0.0,0.0,0.0,0.0 +0,1.366200,0.0,0.0,0.0,0.0,0.0 +0,1.366300,0.0,0.0,0.0,0.0,0.0 +0,1.366400,0.0,0.0,0.0,0.0,0.0 +0,1.366500,0.0,0.0,0.0,0.0,0.0 +0,1.366600,0.0,0.0,0.0,0.0,0.0 +0,1.366700,0.0,0.0,0.0,0.0,0.0 +0,1.366800,0.0,0.0,0.0,0.0,0.0 +0,1.366900,0.0,0.0,0.0,0.0,0.0 +0,1.367000,0.0,0.0,0.0,0.0,0.0 +0,1.367100,0.0,0.0,0.0,0.0,0.0 +0,1.367200,0.0,0.0,0.0,0.0,0.0 +0,1.367300,0.0,0.0,0.0,0.0,0.0 +0,1.367400,0.0,0.0,0.0,0.0,0.0 +0,1.367500,0.0,0.0,0.0,0.0,0.0 +0,1.367600,0.0,0.0,0.0,0.0,0.0 +0,1.367700,0.0,0.0,0.0,0.0,0.0 +0,1.367800,0.0,0.0,0.0,0.0,0.0 +0,1.367900,0.0,0.0,0.0,0.0,0.0 +0,1.368000,0.0,0.0,0.0,0.0,0.0 +0,1.368100,0.0,0.0,0.0,0.0,0.0 +0,1.368200,0.0,0.0,0.0,0.0,0.0 +0,1.368300,0.0,0.0,0.0,0.0,0.0 +0,1.368400,0.0,0.0,0.0,0.0,0.0 +0,1.368500,0.0,0.0,0.0,0.0,0.0 +0,1.368600,0.0,0.0,0.0,0.0,0.0 +0,1.368700,0.0,0.0,0.0,0.0,0.0 +0,1.368800,0.0,0.0,0.0,0.0,0.0 +0,1.368900,0.0,0.0,0.0,0.0,0.0 +0,1.369000,0.0,0.0,0.0,0.0,0.0 +0,1.369100,0.0,0.0,0.0,0.0,0.0 +0,1.369200,0.0,0.0,0.0,0.0,0.0 +0,1.369300,0.0,0.0,0.0,0.0,0.0 +0,1.369400,0.0,0.0,0.0,0.0,0.0 +0,1.369500,0.0,0.0,0.0,0.0,0.0 +0,1.369600,0.0,0.0,0.0,0.0,0.0 +0,1.369700,0.0,0.0,0.0,0.0,0.0 +0,1.369800,0.0,0.0,0.0,0.0,0.0 +0,1.369900,0.0,0.0,0.0,0.0,0.0 +0,1.370000,0.0,0.0,0.0,0.0,0.0 +0,1.370100,0.0,0.0,0.0,0.0,0.0 +0,1.370200,0.0,0.0,0.0,0.0,0.0 +0,1.370300,0.0,0.0,0.0,0.0,0.0 +0,1.370400,0.0,0.0,0.0,0.0,0.0 +0,1.370500,0.0,0.0,0.0,0.0,0.0 +0,1.370600,0.0,0.0,0.0,0.0,0.0 +0,1.370700,0.0,0.0,0.0,0.0,0.0 +0,1.370800,0.0,0.0,0.0,0.0,0.0 +0,1.370900,0.0,0.0,0.0,0.0,0.0 +0,1.371000,0.0,0.0,0.0,0.0,0.0 +0,1.371100,0.0,0.0,0.0,0.0,0.0 +0,1.371200,0.0,0.0,0.0,0.0,0.0 +0,1.371300,0.0,0.0,0.0,0.0,0.0 +0,1.371400,0.0,0.0,0.0,0.0,0.0 +0,1.371500,0.0,0.0,0.0,0.0,0.0 +0,1.371600,0.0,0.0,0.0,0.0,0.0 +0,1.371700,0.0,0.0,0.0,0.0,0.0 +0,1.371800,0.0,0.0,0.0,0.0,0.0 +0,1.371900,0.0,0.0,0.0,0.0,0.0 +0,1.372000,0.0,0.0,0.0,0.0,0.0 +0,1.372100,0.0,0.0,0.0,0.0,0.0 +0,1.372200,0.0,0.0,0.0,0.0,0.0 +0,1.372300,0.0,0.0,0.0,0.0,0.0 +0,1.372400,0.0,0.0,0.0,0.0,0.0 +0,1.372500,0.0,0.0,0.0,0.0,0.0 +0,1.372600,0.0,0.0,0.0,0.0,0.0 +0,1.372700,0.0,0.0,0.0,0.0,0.0 +0,1.372800,0.0,0.0,0.0,0.0,0.0 +0,1.372900,0.0,0.0,0.0,0.0,0.0 +0,1.373000,0.0,0.0,0.0,0.0,0.0 +0,1.373100,0.0,0.0,0.0,0.0,0.0 +0,1.373200,0.0,0.0,0.0,0.0,0.0 +0,1.373300,0.0,0.0,0.0,0.0,0.0 +0,1.373400,0.0,0.0,0.0,0.0,0.0 +0,1.373500,0.0,0.0,0.0,0.0,0.0 +0,1.373600,0.0,0.0,0.0,0.0,0.0 +0,1.373700,0.0,0.0,0.0,0.0,0.0 +0,1.373800,0.0,0.0,0.0,0.0,0.0 +0,1.373900,0.0,0.0,0.0,0.0,0.0 +0,1.374000,0.0,0.0,0.0,0.0,0.0 +0,1.374100,0.0,0.0,0.0,0.0,0.0 +0,1.374200,0.0,0.0,0.0,0.0,0.0 +0,1.374300,0.0,0.0,0.0,0.0,0.0 +0,1.374400,0.0,0.0,0.0,0.0,0.0 +0,1.374500,0.0,0.0,0.0,0.0,0.0 +0,1.374600,0.0,0.0,0.0,0.0,0.0 +0,1.374700,0.0,0.0,0.0,0.0,0.0 +0,1.374800,0.0,0.0,0.0,0.0,0.0 +0,1.374900,0.0,0.0,0.0,0.0,0.0 +0,1.375000,0.0,0.0,0.0,0.0,0.0 +0,1.375100,0.0,0.0,0.0,0.0,0.0 +0,1.375200,0.0,0.0,0.0,0.0,0.0 +0,1.375300,0.0,0.0,0.0,0.0,0.0 +0,1.375400,0.0,0.0,0.0,0.0,0.0 +0,1.375500,0.0,0.0,0.0,0.0,0.0 +0,1.375600,0.0,0.0,0.0,0.0,0.0 +0,1.375700,0.0,0.0,0.0,0.0,0.0 +0,1.375800,0.0,0.0,0.0,0.0,0.0 +0,1.375900,0.0,0.0,0.0,0.0,0.0 +0,1.376000,0.0,0.0,0.0,0.0,0.0 +0,1.376100,0.0,0.0,0.0,0.0,0.0 +0,1.376200,0.0,0.0,0.0,0.0,0.0 +0,1.376300,0.0,0.0,0.0,0.0,0.0 +0,1.376400,0.0,0.0,0.0,0.0,0.0 +0,1.376500,0.0,0.0,0.0,0.0,0.0 +0,1.376600,0.0,0.0,0.0,0.0,0.0 +0,1.376700,0.0,0.0,0.0,0.0,0.0 +0,1.376800,0.0,0.0,0.0,0.0,0.0 +0,1.376900,0.0,0.0,0.0,0.0,0.0 +0,1.377000,0.0,0.0,0.0,0.0,0.0 +0,1.377100,0.0,0.0,0.0,0.0,0.0 +0,1.377200,0.0,0.0,0.0,0.0,0.0 +0,1.377300,0.0,0.0,0.0,0.0,0.0 +0,1.377400,0.0,0.0,0.0,0.0,0.0 +0,1.377500,0.0,0.0,0.0,0.0,0.0 +0,1.377600,0.0,0.0,0.0,0.0,0.0 +0,1.377700,0.0,0.0,0.0,0.0,0.0 +0,1.377800,0.0,0.0,0.0,0.0,0.0 +0,1.377900,0.0,0.0,0.0,0.0,0.0 +0,1.378000,0.0,0.0,0.0,0.0,0.0 +0,1.378100,0.0,0.0,0.0,0.0,0.0 +0,1.378200,0.0,0.0,0.0,0.0,0.0 +0,1.378300,0.0,0.0,0.0,0.0,0.0 +0,1.378400,0.0,0.0,0.0,0.0,0.0 +0,1.378500,0.0,0.0,0.0,0.0,0.0 +0,1.378600,0.0,0.0,0.0,0.0,0.0 +0,1.378700,0.0,0.0,0.0,0.0,0.0 +0,1.378800,0.0,0.0,0.0,0.0,0.0 +0,1.378900,0.0,0.0,0.0,0.0,0.0 +0,1.379000,0.0,0.0,0.0,0.0,0.0 +0,1.379100,0.0,0.0,0.0,0.0,0.0 +0,1.379200,0.0,0.0,0.0,0.0,0.0 +0,1.379300,0.0,0.0,0.0,0.0,0.0 +0,1.379400,0.0,0.0,0.0,0.0,0.0 +0,1.379500,0.0,0.0,0.0,0.0,0.0 +0,1.379600,0.0,0.0,0.0,0.0,0.0 +0,1.379700,0.0,0.0,0.0,0.0,0.0 +0,1.379800,0.0,0.0,0.0,0.0,0.0 +0,1.379900,0.0,0.0,0.0,0.0,0.0 +0,1.380000,0.0,0.0,0.0,0.0,0.0 +0,1.380100,0.0,0.0,0.0,0.0,0.0 +1,1095.387112,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.380200,0.0,0.0,0.0,0.0,0.0 +0,1.380300,0.0,0.0,0.0,0.0,0.0 +0,1.380400,0.0,0.0,0.0,0.0,0.0 +0,1.380500,0.0,0.0,0.0,0.0,0.0 +0,1.380600,0.0,0.0,0.0,0.0,0.0 +0,1.380700,0.0,0.0,0.0,0.0,0.0 +0,1.380800,0.0,0.0,0.0,0.0,0.0 +0,1.380900,0.0,0.0,0.0,0.0,0.0 +0,1.381000,0.0,0.0,0.0,0.0,0.0 +0,1.381100,0.0,0.0,0.0,0.0,0.0 +0,1.381200,0.0,0.0,0.0,0.0,0.0 +0,1.381300,0.0,0.0,0.0,0.0,0.0 +0,1.381400,0.0,0.0,0.0,0.0,0.0 +0,1.381500,0.0,0.0,0.0,0.0,0.0 +0,1.381600,0.0,0.0,0.0,0.0,0.0 +0,1.381700,0.0,0.0,0.0,0.0,0.0 +0,1.381800,0.0,0.0,0.0,0.0,0.0 +0,1.381900,0.0,0.0,0.0,0.0,0.0 +0,1.382000,0.0,0.0,0.0,0.0,0.0 +0,1.382100,0.0,0.0,0.0,0.0,0.0 +0,1.382200,0.0,0.0,0.0,0.0,0.0 +0,1.382300,0.0,0.0,0.0,0.0,0.0 +0,1.382400,0.0,0.0,0.0,0.0,0.0 +0,1.382500,0.0,0.0,0.0,0.0,0.0 +0,1.382600,0.0,0.0,0.0,0.0,0.0 +0,1.382700,0.0,0.0,0.0,0.0,0.0 +0,1.382800,0.0,0.0,0.0,0.0,0.0 +0,1.382900,0.0,0.0,0.0,0.0,0.0 +0,1.383000,0.0,0.0,0.0,0.0,0.0 +0,1.383100,0.0,0.0,0.0,0.0,0.0 +0,1.383200,0.0,0.0,0.0,0.0,0.0 +0,1.383300,0.0,0.0,0.0,0.0,0.0 +0,1.383400,0.0,0.0,0.0,0.0,0.0 +0,1.383500,0.0,0.0,0.0,0.0,0.0 +0,1.383600,0.0,0.0,0.0,0.0,0.0 +0,1.383700,0.0,0.0,0.0,0.0,0.0 +0,1.383800,0.0,0.0,0.0,0.0,0.0 +0,1.383900,0.0,0.0,0.0,0.0,0.0 +0,1.384000,0.0,0.0,0.0,0.0,0.0 +0,1.384100,0.0,0.0,0.0,0.0,0.0 +0,1.384200,0.0,0.0,0.0,0.0,0.0 +0,1.384300,0.0,0.0,0.0,0.0,0.0 +0,1.384400,0.0,0.0,0.0,0.0,0.0 +0,1.384500,0.0,0.0,0.0,0.0,0.0 +0,1.384600,0.0,0.0,0.0,0.0,0.0 +0,1.384700,0.0,0.0,0.0,0.0,0.0 +0,1.384800,0.0,0.0,0.0,0.0,0.0 +0,1.384900,0.0,0.0,0.0,0.0,0.0 +0,1.385000,0.0,0.0,0.0,0.0,0.0 +0,1.385100,0.0,0.0,0.0,0.0,0.0 +0,1.385200,0.0,0.0,0.0,0.0,0.0 +0,1.385300,0.0,0.0,0.0,0.0,0.0 +0,1.385400,0.0,0.0,0.0,0.0,0.0 +0,1.385500,0.0,0.0,0.0,0.0,0.0 +0,1.385600,0.0,0.0,0.0,0.0,0.0 +0,1.385700,0.0,0.0,0.0,0.0,0.0 +0,1.385800,0.0,0.0,0.0,0.0,0.0 +0,1.385900,0.0,0.0,0.0,0.0,0.0 +0,1.386000,0.0,0.0,0.0,0.0,0.0 +0,1.386100,0.0,0.0,0.0,0.0,0.0 +0,1.386200,0.0,0.0,0.0,0.0,0.0 +0,1.386300,0.0,0.0,0.0,0.0,0.0 +0,1.386400,0.0,0.0,0.0,0.0,0.0 +0,1.386500,0.0,0.0,0.0,0.0,0.0 +0,1.386600,0.0,0.0,0.0,0.0,0.0 +0,1.386700,0.0,0.0,0.0,0.0,0.0 +0,1.386800,0.0,0.0,0.0,0.0,0.0 +0,1.386900,0.0,0.0,0.0,0.0,0.0 +0,1.387000,0.0,0.0,0.0,0.0,0.0 +0,1.387100,0.0,0.0,0.0,0.0,0.0 +0,1.387200,0.0,0.0,0.0,0.0,0.0 +0,1.387300,0.0,0.0,0.0,0.0,0.0 +0,1.387400,0.0,0.0,0.0,0.0,0.0 +0,1.387500,0.0,0.0,0.0,0.0,0.0 +0,1.387600,0.0,0.0,0.0,0.0,0.0 +0,1.387700,0.0,0.0,0.0,0.0,0.0 +0,1.387800,0.0,0.0,0.0,0.0,0.0 +0,1.387900,0.0,0.0,0.0,0.0,0.0 +0,1.388000,0.0,0.0,0.0,0.0,0.0 +0,1.388100,0.0,0.0,0.0,0.0,0.0 +0,1.388200,0.0,0.0,0.0,0.0,0.0 +0,1.388300,0.0,0.0,0.0,0.0,0.0 +0,1.388400,0.0,0.0,0.0,0.0,0.0 +0,1.388500,0.0,0.0,0.0,0.0,0.0 +0,1.388600,0.0,0.0,0.0,0.0,0.0 +0,1.388700,0.0,0.0,0.0,0.0,0.0 +0,1.388800,0.0,0.0,0.0,0.0,0.0 +0,1.388900,0.0,0.0,0.0,0.0,0.0 +0,1.389000,0.0,0.0,0.0,0.0,0.0 +0,1.389100,0.0,0.0,0.0,0.0,0.0 +0,1.389200,0.0,0.0,0.0,0.0,0.0 +0,1.389300,0.0,0.0,0.0,0.0,0.0 +0,1.389400,0.0,0.0,0.0,0.0,0.0 +0,1.389500,0.0,0.0,0.0,0.0,0.0 +0,1.389600,0.0,0.0,0.0,0.0,0.0 +0,1.389700,0.0,0.0,0.0,0.0,0.0 +0,1.389800,0.0,0.0,0.0,0.0,0.0 +0,1.389900,0.0,0.0,0.0,0.0,0.0 +0,1.390000,0.0,0.0,0.0,0.0,0.0 +0,1.390100,0.0,0.0,0.0,0.0,0.0 +0,1.390200,0.0,0.0,0.0,0.0,0.0 +0,1.390300,0.0,0.0,0.0,0.0,0.0 +0,1.390400,0.0,0.0,0.0,0.0,0.0 +0,1.390500,0.0,0.0,0.0,0.0,0.0 +0,1.390600,0.0,0.0,0.0,0.0,0.0 +0,1.390700,0.0,0.0,0.0,0.0,0.0 +0,1.390800,0.0,0.0,0.0,0.0,0.0 +0,1.390900,0.0,0.0,0.0,0.0,0.0 +0,1.391000,0.0,0.0,0.0,0.0,0.0 +0,1.391100,0.0,0.0,0.0,0.0,0.0 +0,1.391200,0.0,0.0,0.0,0.0,0.0 +0,1.391300,0.0,0.0,0.0,0.0,0.0 +0,1.391400,0.0,0.0,0.0,0.0,0.0 +0,1.391500,0.0,0.0,0.0,0.0,0.0 +0,1.391600,0.0,0.0,0.0,0.0,0.0 +0,1.391700,0.0,0.0,0.0,0.0,0.0 +0,1.391800,0.0,0.0,0.0,0.0,0.0 +0,1.391900,0.0,0.0,0.0,0.0,0.0 +0,1.392000,0.0,0.0,0.0,0.0,0.0 +0,1.392100,0.0,0.0,0.0,0.0,0.0 +0,1.392200,0.0,0.0,0.0,0.0,0.0 +0,1.392300,0.0,0.0,0.0,0.0,0.0 +0,1.392400,0.0,0.0,0.0,0.0,0.0 +0,1.392500,0.0,0.0,0.0,0.0,0.0 +0,1.392600,0.0,0.0,0.0,0.0,0.0 +0,1.392700,0.0,0.0,0.0,0.0,0.0 +0,1.392800,0.0,0.0,0.0,0.0,0.0 +0,1.392900,0.0,0.0,0.0,0.0,0.0 +0,1.393000,0.0,0.0,0.0,0.0,0.0 +0,1.393100,0.0,0.0,0.0,0.0,0.0 +0,1.393200,0.0,0.0,0.0,0.0,0.0 +0,1.393300,0.0,0.0,0.0,0.0,0.0 +0,1.393400,0.0,0.0,0.0,0.0,0.0 +0,1.393500,0.0,0.0,0.0,0.0,0.0 +0,1.393600,0.0,0.0,0.0,0.0,0.0 +0,1.393700,0.0,0.0,0.0,0.0,0.0 +0,1.393800,0.0,0.0,0.0,0.0,0.0 +0,1.393900,0.0,0.0,0.0,0.0,0.0 +0,1.394000,0.0,0.0,0.0,0.0,0.0 +0,1.394100,0.0,0.0,0.0,0.0,0.0 +0,1.394200,0.0,0.0,0.0,0.0,0.0 +0,1.394300,0.0,0.0,0.0,0.0,0.0 +0,1.394400,0.0,0.0,0.0,0.0,0.0 +0,1.394500,0.0,0.0,0.0,0.0,0.0 +0,1.394600,0.0,0.0,0.0,0.0,0.0 +0,1.394700,0.0,0.0,0.0,0.0,0.0 +0,1.394800,0.0,0.0,0.0,0.0,0.0 +0,1.394900,0.0,0.0,0.0,0.0,0.0 +0,1.395000,0.0,0.0,0.0,0.0,0.0 +0,1.395100,0.0,0.0,0.0,0.0,0.0 +0,1.395200,0.0,0.0,0.0,0.0,0.0 +0,1.395300,0.0,0.0,0.0,0.0,0.0 +0,1.395400,0.0,0.0,0.0,0.0,0.0 +0,1.395500,0.0,0.0,0.0,0.0,0.0 +0,1.395600,0.0,0.0,0.0,0.0,0.0 +0,1.395700,0.0,0.0,0.0,0.0,0.0 +0,1.395800,0.0,0.0,0.0,0.0,0.0 +0,1.395900,0.0,0.0,0.0,0.0,0.0 +0,1.396000,0.0,0.0,0.0,0.0,0.0 +0,1.396100,0.0,0.0,0.0,0.0,0.0 +0,1.396200,0.0,0.0,0.0,0.0,0.0 +0,1.396300,0.0,0.0,0.0,0.0,0.0 +0,1.396400,0.0,0.0,0.0,0.0,0.0 +0,1.396500,0.0,0.0,0.0,0.0,0.0 +0,1.396600,0.0,0.0,0.0,0.0,0.0 +0,1.396700,0.0,0.0,0.0,0.0,0.0 +0,1.396800,0.0,0.0,0.0,0.0,0.0 +0,1.396900,0.0,0.0,0.0,0.0,0.0 +0,1.397000,0.0,0.0,0.0,0.0,0.0 +0,1.397100,0.0,0.0,0.0,0.0,0.0 +0,1.397200,0.0,0.0,0.0,0.0,0.0 +0,1.397300,0.0,0.0,0.0,0.0,0.0 +0,1.397400,0.0,0.0,0.0,0.0,0.0 +0,1.397500,0.0,0.0,0.0,0.0,0.0 +0,1.397600,0.0,0.0,0.0,0.0,0.0 +0,1.397700,0.0,0.0,0.0,0.0,0.0 +0,1.397800,0.0,0.0,0.0,0.0,0.0 +0,1.397900,0.0,0.0,0.0,0.0,0.0 +0,1.398000,0.0,0.0,0.0,0.0,0.0 +0,1.398100,0.0,0.0,0.0,0.0,0.0 +0,1.398200,0.0,0.0,0.0,0.0,0.0 +0,1.398300,0.0,0.0,0.0,0.0,0.0 +0,1.398400,0.0,0.0,0.0,0.0,0.0 +0,1.398500,0.0,0.0,0.0,0.0,0.0 +0,1.398600,0.0,0.0,0.0,0.0,0.0 +0,1.398700,0.0,0.0,0.0,0.0,0.0 +0,1.398800,0.0,0.0,0.0,0.0,0.0 +0,1.398900,0.0,0.0,0.0,0.0,0.0 +0,1.399000,0.0,0.0,0.0,0.0,0.0 +0,1.399100,0.0,0.0,0.0,0.0,0.0 +0,1.399200,0.0,0.0,0.0,0.0,0.0 +0,1.399300,0.0,0.0,0.0,0.0,0.0 +0,1.399400,0.0,0.0,0.0,0.0,0.0 +0,1.399500,0.0,0.0,0.0,0.0,0.0 +0,1.399600,0.0,0.0,0.0,0.0,0.0 +0,1.399700,0.0,0.0,0.0,0.0,0.0 +0,1.399800,0.0,0.0,0.0,0.0,0.0 +0,1.399900,0.0,0.0,0.0,0.0,0.0 +0,1.400000,0.0,0.0,0.0,0.0,0.0 +0,1.400100,0.0,0.0,0.0,0.0,0.0 +1,1143.700871,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.400200,0.0,0.0,0.0,0.0,0.0 +0,1.400300,0.0,0.0,0.0,0.0,0.0 +0,1.400400,0.0,0.0,0.0,0.0,0.0 +0,1.400500,0.0,0.0,0.0,0.0,0.0 +0,1.400600,0.0,0.0,0.0,0.0,0.0 +0,1.400700,0.0,0.0,0.0,0.0,0.0 +0,1.400800,0.0,0.0,0.0,0.0,0.0 +0,1.400900,0.0,0.0,0.0,0.0,0.0 +0,1.401000,0.0,0.0,0.0,0.0,0.0 +0,1.401100,0.0,0.0,0.0,0.0,0.0 +0,1.401200,0.0,0.0,0.0,0.0,0.0 +0,1.401300,0.0,0.0,0.0,0.0,0.0 +0,1.401400,0.0,0.0,0.0,0.0,0.0 +0,1.401500,0.0,0.0,0.0,0.0,0.0 +0,1.401600,0.0,0.0,0.0,0.0,0.0 +0,1.401700,0.0,0.0,0.0,0.0,0.0 +0,1.401800,0.0,0.0,0.0,0.0,0.0 +0,1.401900,0.0,0.0,0.0,0.0,0.0 +0,1.402000,0.0,0.0,0.0,0.0,0.0 +0,1.402100,0.0,0.0,0.0,0.0,0.0 +0,1.402200,0.0,0.0,0.0,0.0,0.0 +0,1.402300,0.0,0.0,0.0,0.0,0.0 +0,1.402400,0.0,0.0,0.0,0.0,0.0 +0,1.402500,0.0,0.0,0.0,0.0,0.0 +0,1.402600,0.0,0.0,0.0,0.0,0.0 +0,1.402700,0.0,0.0,0.0,0.0,0.0 +0,1.402800,0.0,0.0,0.0,0.0,0.0 +0,1.402900,0.0,0.0,0.0,0.0,0.0 +0,1.403000,0.0,0.0,0.0,0.0,0.0 +0,1.403100,0.0,0.0,0.0,0.0,0.0 +0,1.403200,0.0,0.0,0.0,0.0,0.0 +0,1.403300,0.0,0.0,0.0,0.0,0.0 +0,1.403400,0.0,0.0,0.0,0.0,0.0 +0,1.403500,0.0,0.0,0.0,0.0,0.0 +0,1.403600,0.0,0.0,0.0,0.0,0.0 +0,1.403700,0.0,0.0,0.0,0.0,0.0 +0,1.403800,0.0,0.0,0.0,0.0,0.0 +0,1.403900,0.0,0.0,0.0,0.0,0.0 +0,1.404000,0.0,0.0,0.0,0.0,0.0 +0,1.404100,0.0,0.0,0.0,0.0,0.0 +0,1.404200,0.0,0.0,0.0,0.0,0.0 +0,1.404300,0.0,0.0,0.0,0.0,0.0 +0,1.404400,0.0,0.0,0.0,0.0,0.0 +0,1.404500,0.0,0.0,0.0,0.0,0.0 +0,1.404600,0.0,0.0,0.0,0.0,0.0 +0,1.404700,0.0,0.0,0.0,0.0,0.0 +0,1.404800,0.0,0.0,0.0,0.0,0.0 +0,1.404900,0.0,0.0,0.0,0.0,0.0 +0,1.405000,0.0,0.0,0.0,0.0,0.0 +0,1.405100,0.0,0.0,0.0,0.0,0.0 +0,1.405200,0.0,0.0,0.0,0.0,0.0 +0,1.405300,0.0,0.0,0.0,0.0,0.0 +0,1.405400,0.0,0.0,0.0,0.0,0.0 +0,1.405500,0.0,0.0,0.0,0.0,0.0 +0,1.405600,0.0,0.0,0.0,0.0,0.0 +0,1.405700,0.0,0.0,0.0,0.0,0.0 +0,1.405800,0.0,0.0,0.0,0.0,0.0 +0,1.405900,0.0,0.0,0.0,0.0,0.0 +0,1.406000,0.0,0.0,0.0,0.0,0.0 +0,1.406100,0.0,0.0,0.0,0.0,0.0 +0,1.406200,0.0,0.0,0.0,0.0,0.0 +0,1.406300,0.0,0.0,0.0,0.0,0.0 +0,1.406400,0.0,0.0,0.0,0.0,0.0 +0,1.406500,0.0,0.0,0.0,0.0,0.0 +0,1.406600,0.0,0.0,0.0,0.0,0.0 +0,1.406700,0.0,0.0,0.0,0.0,0.0 +0,1.406800,0.0,0.0,0.0,0.0,0.0 +0,1.406900,0.0,0.0,0.0,0.0,0.0 +0,1.407000,0.0,0.0,0.0,0.0,0.0 +0,1.407100,0.0,0.0,0.0,0.0,0.0 +0,1.407200,0.0,0.0,0.0,0.0,0.0 +0,1.407300,0.0,0.0,0.0,0.0,0.0 +0,1.407400,0.0,0.0,0.0,0.0,0.0 +0,1.407500,0.0,0.0,0.0,0.0,0.0 +0,1.407600,0.0,0.0,0.0,0.0,0.0 +0,1.407700,0.0,0.0,0.0,0.0,0.0 +0,1.407800,0.0,0.0,0.0,0.0,0.0 +0,1.407900,0.0,0.0,0.0,0.0,0.0 +0,1.408000,0.0,0.0,0.0,0.0,0.0 +0,1.408100,0.0,0.0,0.0,0.0,0.0 +0,1.408200,0.0,0.0,0.0,0.0,0.0 +0,1.408300,0.0,0.0,0.0,0.0,0.0 +0,1.408400,0.0,0.0,0.0,0.0,0.0 +0,1.408500,0.0,0.0,0.0,0.0,0.0 +0,1.408600,0.0,0.0,0.0,0.0,0.0 +0,1.408700,0.0,0.0,0.0,0.0,0.0 +0,1.408800,0.0,0.0,0.0,0.0,0.0 +0,1.408900,0.0,0.0,0.0,0.0,0.0 +0,1.409000,0.0,0.0,0.0,0.0,0.0 +0,1.409100,0.0,0.0,0.0,0.0,0.0 +0,1.409200,0.0,0.0,0.0,0.0,0.0 +0,1.409300,0.0,0.0,0.0,0.0,0.0 +0,1.409400,0.0,0.0,0.0,0.0,0.0 +0,1.409500,0.0,0.0,0.0,0.0,0.0 +0,1.409600,0.0,0.0,0.0,0.0,0.0 +0,1.409700,0.0,0.0,0.0,0.0,0.0 +0,1.409800,0.0,0.0,0.0,0.0,0.0 +0,1.409900,0.0,0.0,0.0,0.0,0.0 +0,1.410000,0.0,0.0,0.0,0.0,0.0 +0,1.410100,0.0,0.0,0.0,0.0,0.0 +0,1.410200,0.0,0.0,0.0,0.0,0.0 +0,1.410300,0.0,0.0,0.0,0.0,0.0 +0,1.410400,0.0,0.0,0.0,0.0,0.0 +0,1.410500,0.0,0.0,0.0,0.0,0.0 +0,1.410600,0.0,0.0,0.0,0.0,0.0 +0,1.410700,0.0,0.0,0.0,0.0,0.0 +0,1.410800,0.0,0.0,0.0,0.0,0.0 +0,1.410900,0.0,0.0,0.0,0.0,0.0 +0,1.411000,0.0,0.0,0.0,0.0,0.0 +0,1.411100,0.0,0.0,0.0,0.0,0.0 +0,1.411200,0.0,0.0,0.0,0.0,0.0 +0,1.411300,0.0,0.0,0.0,0.0,0.0 +0,1.411400,0.0,0.0,0.0,0.0,0.0 +0,1.411500,0.0,0.0,0.0,0.0,0.0 +0,1.411600,0.0,0.0,0.0,0.0,0.0 +0,1.411700,0.0,0.0,0.0,0.0,0.0 +0,1.411800,0.0,0.0,0.0,0.0,0.0 +0,1.411900,0.0,0.0,0.0,0.0,0.0 +0,1.412000,0.0,0.0,0.0,0.0,0.0 +0,1.412100,0.0,0.0,0.0,0.0,0.0 +0,1.412200,0.0,0.0,0.0,0.0,0.0 +0,1.412300,0.0,0.0,0.0,0.0,0.0 +0,1.412400,0.0,0.0,0.0,0.0,0.0 +0,1.412500,0.0,0.0,0.0,0.0,0.0 +0,1.412600,0.0,0.0,0.0,0.0,0.0 +0,1.412700,0.0,0.0,0.0,0.0,0.0 +0,1.412800,0.0,0.0,0.0,0.0,0.0 +0,1.412900,0.0,0.0,0.0,0.0,0.0 +0,1.413000,0.0,0.0,0.0,0.0,0.0 +0,1.413100,0.0,0.0,0.0,0.0,0.0 +0,1.413200,0.0,0.0,0.0,0.0,0.0 +0,1.413300,0.0,0.0,0.0,0.0,0.0 +0,1.413400,0.0,0.0,0.0,0.0,0.0 +0,1.413500,0.0,0.0,0.0,0.0,0.0 +0,1.413600,0.0,0.0,0.0,0.0,0.0 +0,1.413700,0.0,0.0,0.0,0.0,0.0 +0,1.413800,0.0,0.0,0.0,0.0,0.0 +0,1.413900,0.0,0.0,0.0,0.0,0.0 +0,1.414000,0.0,0.0,0.0,0.0,0.0 +0,1.414100,0.0,0.0,0.0,0.0,0.0 +0,1.414200,0.0,0.0,0.0,0.0,0.0 +0,1.414300,0.0,0.0,0.0,0.0,0.0 +0,1.414400,0.0,0.0,0.0,0.0,0.0 +0,1.414500,0.0,0.0,0.0,0.0,0.0 +0,1.414600,0.0,0.0,0.0,0.0,0.0 +0,1.414700,0.0,0.0,0.0,0.0,0.0 +0,1.414800,0.0,0.0,0.0,0.0,0.0 +0,1.414900,0.0,0.0,0.0,0.0,0.0 +0,1.415000,0.0,0.0,0.0,0.0,0.0 +0,1.415100,0.0,0.0,0.0,0.0,0.0 +0,1.415200,0.0,0.0,0.0,0.0,0.0 +0,1.415300,0.0,0.0,0.0,0.0,0.0 +0,1.415400,0.0,0.0,0.0,0.0,0.0 +0,1.415500,0.0,0.0,0.0,0.0,0.0 +0,1.415600,0.0,0.0,0.0,0.0,0.0 +0,1.415700,0.0,0.0,0.0,0.0,0.0 +0,1.415800,0.0,0.0,0.0,0.0,0.0 +0,1.415900,0.0,0.0,0.0,0.0,0.0 +0,1.416000,0.0,0.0,0.0,0.0,0.0 +0,1.416100,0.0,0.0,0.0,0.0,0.0 +0,1.416200,0.0,0.0,0.0,0.0,0.0 +0,1.416300,0.0,0.0,0.0,0.0,0.0 +0,1.416400,0.0,0.0,0.0,0.0,0.0 +0,1.416500,0.0,0.0,0.0,0.0,0.0 +0,1.416600,0.0,0.0,0.0,0.0,0.0 +0,1.416700,0.0,0.0,0.0,0.0,0.0 +0,1.416800,0.0,0.0,0.0,0.0,0.0 +0,1.416900,0.0,0.0,0.0,0.0,0.0 +0,1.417000,0.0,0.0,0.0,0.0,0.0 +0,1.417100,0.0,0.0,0.0,0.0,0.0 +0,1.417200,0.0,0.0,0.0,0.0,0.0 +0,1.417300,0.0,0.0,0.0,0.0,0.0 +0,1.417400,0.0,0.0,0.0,0.0,0.0 +0,1.417500,0.0,0.0,0.0,0.0,0.0 +0,1.417600,0.0,0.0,0.0,0.0,0.0 +0,1.417700,0.0,0.0,0.0,0.0,0.0 +0,1.417800,0.0,0.0,0.0,0.0,0.0 +0,1.417900,0.0,0.0,0.0,0.0,0.0 +0,1.418000,0.0,0.0,0.0,0.0,0.0 +0,1.418100,0.0,0.0,0.0,0.0,0.0 +0,1.418200,0.0,0.0,0.0,0.0,0.0 +0,1.418300,0.0,0.0,0.0,0.0,0.0 +0,1.418400,0.0,0.0,0.0,0.0,0.0 +0,1.418500,0.0,0.0,0.0,0.0,0.0 +0,1.418600,0.0,0.0,0.0,0.0,0.0 +0,1.418700,0.0,0.0,0.0,0.0,0.0 +0,1.418800,0.0,0.0,0.0,0.0,0.0 +0,1.418900,0.0,0.0,0.0,0.0,0.0 +0,1.419000,0.0,0.0,0.0,0.0,0.0 +0,1.419100,0.0,0.0,0.0,0.0,0.0 +0,1.419200,0.0,0.0,0.0,0.0,0.0 +0,1.419300,0.0,0.0,0.0,0.0,0.0 +0,1.419400,0.0,0.0,0.0,0.0,0.0 +0,1.419500,0.0,0.0,0.0,0.0,0.0 +0,1.419600,0.0,0.0,0.0,0.0,0.0 +0,1.419700,0.0,0.0,0.0,0.0,0.0 +0,1.419800,0.0,0.0,0.0,0.0,0.0 +0,1.419900,0.0,0.0,0.0,0.0,0.0 +0,1.420000,0.0,0.0,0.0,0.0,0.0 +0,1.420100,0.0,0.0,0.0,0.0,0.0 +1,1193.414780,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.420200,0.0,0.0,0.0,0.0,0.0 +0,1.420300,0.0,0.0,0.0,0.0,0.0 +0,1.420400,0.0,0.0,0.0,0.0,0.0 +0,1.420500,0.0,0.0,0.0,0.0,0.0 +0,1.420600,0.0,0.0,0.0,0.0,0.0 +0,1.420700,0.0,0.0,0.0,0.0,0.0 +0,1.420800,0.0,0.0,0.0,0.0,0.0 +0,1.420900,0.0,0.0,0.0,0.0,0.0 +0,1.421000,0.0,0.0,0.0,0.0,0.0 +0,1.421100,0.0,0.0,0.0,0.0,0.0 +0,1.421200,0.0,0.0,0.0,0.0,0.0 +0,1.421300,0.0,0.0,0.0,0.0,0.0 +0,1.421400,0.0,0.0,0.0,0.0,0.0 +0,1.421500,0.0,0.0,0.0,0.0,0.0 +0,1.421600,0.0,0.0,0.0,0.0,0.0 +0,1.421700,0.0,0.0,0.0,0.0,0.0 +0,1.421800,0.0,0.0,0.0,0.0,0.0 +0,1.421900,0.0,0.0,0.0,0.0,0.0 +0,1.422000,0.0,0.0,0.0,0.0,0.0 +0,1.422100,0.0,0.0,0.0,0.0,0.0 +0,1.422200,0.0,0.0,0.0,0.0,0.0 +0,1.422300,0.0,0.0,0.0,0.0,0.0 +0,1.422400,0.0,0.0,0.0,0.0,0.0 +0,1.422500,0.0,0.0,0.0,0.0,0.0 +0,1.422600,0.0,0.0,0.0,0.0,0.0 +0,1.422700,0.0,0.0,0.0,0.0,0.0 +0,1.422800,0.0,0.0,0.0,0.0,0.0 +0,1.422900,0.0,0.0,0.0,0.0,0.0 +0,1.423000,0.0,0.0,0.0,0.0,0.0 +0,1.423100,0.0,0.0,0.0,0.0,0.0 +0,1.423200,0.0,0.0,0.0,0.0,0.0 +0,1.423300,0.0,0.0,0.0,0.0,0.0 +0,1.423400,0.0,0.0,0.0,0.0,0.0 +0,1.423500,0.0,0.0,0.0,0.0,0.0 +0,1.423600,0.0,0.0,0.0,0.0,0.0 +0,1.423700,0.0,0.0,0.0,0.0,0.0 +0,1.423800,0.0,0.0,0.0,0.0,0.0 +0,1.423900,0.0,0.0,0.0,0.0,0.0 +0,1.424000,0.0,0.0,0.0,0.0,0.0 +0,1.424100,0.0,0.0,0.0,0.0,0.0 +0,1.424200,0.0,0.0,0.0,0.0,0.0 +0,1.424300,0.0,0.0,0.0,0.0,0.0 +0,1.424400,0.0,0.0,0.0,0.0,0.0 +0,1.424500,0.0,0.0,0.0,0.0,0.0 +0,1.424600,0.0,0.0,0.0,0.0,0.0 +0,1.424700,0.0,0.0,0.0,0.0,0.0 +0,1.424800,0.0,0.0,0.0,0.0,0.0 +0,1.424900,0.0,0.0,0.0,0.0,0.0 +0,1.425000,0.0,0.0,0.0,0.0,0.0 +0,1.425100,0.0,0.0,0.0,0.0,0.0 +0,1.425200,0.0,0.0,0.0,0.0,0.0 +0,1.425300,0.0,0.0,0.0,0.0,0.0 +0,1.425400,0.0,0.0,0.0,0.0,0.0 +0,1.425500,0.0,0.0,0.0,0.0,0.0 +0,1.425600,0.0,0.0,0.0,0.0,0.0 +0,1.425700,0.0,0.0,0.0,0.0,0.0 +0,1.425800,0.0,0.0,0.0,0.0,0.0 +0,1.425900,0.0,0.0,0.0,0.0,0.0 +0,1.426000,0.0,0.0,0.0,0.0,0.0 +0,1.426100,0.0,0.0,0.0,0.0,0.0 +0,1.426200,0.0,0.0,0.0,0.0,0.0 +0,1.426300,0.0,0.0,0.0,0.0,0.0 +0,1.426400,0.0,0.0,0.0,0.0,0.0 +0,1.426500,0.0,0.0,0.0,0.0,0.0 +0,1.426600,0.0,0.0,0.0,0.0,0.0 +0,1.426700,0.0,0.0,0.0,0.0,0.0 +0,1.426800,0.0,0.0,0.0,0.0,0.0 +0,1.426900,0.0,0.0,0.0,0.0,0.0 +0,1.427000,0.0,0.0,0.0,0.0,0.0 +0,1.427100,0.0,0.0,0.0,0.0,0.0 +0,1.427200,0.0,0.0,0.0,0.0,0.0 +0,1.427300,0.0,0.0,0.0,0.0,0.0 +0,1.427400,0.0,0.0,0.0,0.0,0.0 +0,1.427500,0.0,0.0,0.0,0.0,0.0 +0,1.427600,0.0,0.0,0.0,0.0,0.0 +0,1.427700,0.0,0.0,0.0,0.0,0.0 +0,1.427800,0.0,0.0,0.0,0.0,0.0 +0,1.427900,0.0,0.0,0.0,0.0,0.0 +0,1.428000,0.0,0.0,0.0,0.0,0.0 +0,1.428100,0.0,0.0,0.0,0.0,0.0 +0,1.428200,0.0,0.0,0.0,0.0,0.0 +0,1.428300,0.0,0.0,0.0,0.0,0.0 +0,1.428400,0.0,0.0,0.0,0.0,0.0 +0,1.428500,0.0,0.0,0.0,0.0,0.0 +0,1.428600,0.0,0.0,0.0,0.0,0.0 +0,1.428700,0.0,0.0,0.0,0.0,0.0 +0,1.428800,0.0,0.0,0.0,0.0,0.0 +0,1.428900,0.0,0.0,0.0,0.0,0.0 +0,1.429000,0.0,0.0,0.0,0.0,0.0 +0,1.429100,0.0,0.0,0.0,0.0,0.0 +0,1.429200,0.0,0.0,0.0,0.0,0.0 +0,1.429300,0.0,0.0,0.0,0.0,0.0 +0,1.429400,0.0,0.0,0.0,0.0,0.0 +0,1.429500,0.0,0.0,0.0,0.0,0.0 +0,1.429600,0.0,0.0,0.0,0.0,0.0 +0,1.429700,0.0,0.0,0.0,0.0,0.0 +0,1.429800,0.0,0.0,0.0,0.0,0.0 +0,1.429900,0.0,0.0,0.0,0.0,0.0 +0,1.430000,0.0,0.0,0.0,0.0,0.0 +0,1.430100,0.0,0.0,0.0,0.0,0.0 +0,1.430200,0.0,0.0,0.0,0.0,0.0 +0,1.430300,0.0,0.0,0.0,0.0,0.0 +0,1.430400,0.0,0.0,0.0,0.0,0.0 +0,1.430500,0.0,0.0,0.0,0.0,0.0 +0,1.430600,0.0,0.0,0.0,0.0,0.0 +0,1.430700,0.0,0.0,0.0,0.0,0.0 +0,1.430800,0.0,0.0,0.0,0.0,0.0 +0,1.430900,0.0,0.0,0.0,0.0,0.0 +0,1.431000,0.0,0.0,0.0,0.0,0.0 +0,1.431100,0.0,0.0,0.0,0.0,0.0 +0,1.431200,0.0,0.0,0.0,0.0,0.0 +0,1.431300,0.0,0.0,0.0,0.0,0.0 +0,1.431400,0.0,0.0,0.0,0.0,0.0 +0,1.431500,0.0,0.0,0.0,0.0,0.0 +0,1.431600,0.0,0.0,0.0,0.0,0.0 +0,1.431700,0.0,0.0,0.0,0.0,0.0 +0,1.431800,0.0,0.0,0.0,0.0,0.0 +0,1.431900,0.0,0.0,0.0,0.0,0.0 +0,1.432000,0.0,0.0,0.0,0.0,0.0 +0,1.432100,0.0,0.0,0.0,0.0,0.0 +0,1.432200,0.0,0.0,0.0,0.0,0.0 +0,1.432300,0.0,0.0,0.0,0.0,0.0 +0,1.432400,0.0,0.0,0.0,0.0,0.0 +0,1.432500,0.0,0.0,0.0,0.0,0.0 +0,1.432600,0.0,0.0,0.0,0.0,0.0 +0,1.432700,0.0,0.0,0.0,0.0,0.0 +0,1.432800,0.0,0.0,0.0,0.0,0.0 +0,1.432900,0.0,0.0,0.0,0.0,0.0 +0,1.433000,0.0,0.0,0.0,0.0,0.0 +0,1.433100,0.0,0.0,0.0,0.0,0.0 +0,1.433200,0.0,0.0,0.0,0.0,0.0 +0,1.433300,0.0,0.0,0.0,0.0,0.0 +0,1.433400,0.0,0.0,0.0,0.0,0.0 +0,1.433500,0.0,0.0,0.0,0.0,0.0 +0,1.433600,0.0,0.0,0.0,0.0,0.0 +0,1.433700,0.0,0.0,0.0,0.0,0.0 +0,1.433800,0.0,0.0,0.0,0.0,0.0 +0,1.433900,0.0,0.0,0.0,0.0,0.0 +0,1.434000,0.0,0.0,0.0,0.0,0.0 +0,1.434100,0.0,0.0,0.0,0.0,0.0 +0,1.434200,0.0,0.0,0.0,0.0,0.0 +0,1.434300,0.0,0.0,0.0,0.0,0.0 +0,1.434400,0.0,0.0,0.0,0.0,0.0 +0,1.434500,0.0,0.0,0.0,0.0,0.0 +0,1.434600,0.0,0.0,0.0,0.0,0.0 +0,1.434700,0.0,0.0,0.0,0.0,0.0 +0,1.434800,0.0,0.0,0.0,0.0,0.0 +0,1.434900,0.0,0.0,0.0,0.0,0.0 +0,1.435000,0.0,0.0,0.0,0.0,0.0 +0,1.435100,0.0,0.0,0.0,0.0,0.0 +0,1.435200,0.0,0.0,0.0,0.0,0.0 +0,1.435300,0.0,0.0,0.0,0.0,0.0 +0,1.435400,0.0,0.0,0.0,0.0,0.0 +0,1.435500,0.0,0.0,0.0,0.0,0.0 +0,1.435600,0.0,0.0,0.0,0.0,0.0 +0,1.435700,0.0,0.0,0.0,0.0,0.0 +0,1.435800,0.0,0.0,0.0,0.0,0.0 +0,1.435900,0.0,0.0,0.0,0.0,0.0 +0,1.436000,0.0,0.0,0.0,0.0,0.0 +0,1.436100,0.0,0.0,0.0,0.0,0.0 +0,1.436200,0.0,0.0,0.0,0.0,0.0 +0,1.436300,0.0,0.0,0.0,0.0,0.0 +0,1.436400,0.0,0.0,0.0,0.0,0.0 +0,1.436500,0.0,0.0,0.0,0.0,0.0 +0,1.436600,0.0,0.0,0.0,0.0,0.0 +0,1.436700,0.0,0.0,0.0,0.0,0.0 +0,1.436800,0.0,0.0,0.0,0.0,0.0 +0,1.436900,0.0,0.0,0.0,0.0,0.0 +0,1.437000,0.0,0.0,0.0,0.0,0.0 +0,1.437100,0.0,0.0,0.0,0.0,0.0 +0,1.437200,0.0,0.0,0.0,0.0,0.0 +0,1.437300,0.0,0.0,0.0,0.0,0.0 +0,1.437400,0.0,0.0,0.0,0.0,0.0 +0,1.437500,0.0,0.0,0.0,0.0,0.0 +0,1.437600,0.0,0.0,0.0,0.0,0.0 +0,1.437700,0.0,0.0,0.0,0.0,0.0 +0,1.437800,0.0,0.0,0.0,0.0,0.0 +0,1.437900,0.0,0.0,0.0,0.0,0.0 +0,1.438000,0.0,0.0,0.0,0.0,0.0 +0,1.438100,0.0,0.0,0.0,0.0,0.0 +0,1.438200,0.0,0.0,0.0,0.0,0.0 +0,1.438300,0.0,0.0,0.0,0.0,0.0 +0,1.438400,0.0,0.0,0.0,0.0,0.0 +0,1.438500,0.0,0.0,0.0,0.0,0.0 +0,1.438600,0.0,0.0,0.0,0.0,0.0 +0,1.438700,0.0,0.0,0.0,0.0,0.0 +0,1.438800,0.0,0.0,0.0,0.0,0.0 +0,1.438900,0.0,0.0,0.0,0.0,0.0 +0,1.439000,0.0,0.0,0.0,0.0,0.0 +0,1.439100,0.0,0.0,0.0,0.0,0.0 +0,1.439200,0.0,0.0,0.0,0.0,0.0 +0,1.439300,0.0,0.0,0.0,0.0,0.0 +0,1.439400,0.0,0.0,0.0,0.0,0.0 +0,1.439500,0.0,0.0,0.0,0.0,0.0 +0,1.439600,0.0,0.0,0.0,0.0,0.0 +0,1.439700,0.0,0.0,0.0,0.0,0.0 +0,1.439800,0.0,0.0,0.0,0.0,0.0 +0,1.439900,0.0,0.0,0.0,0.0,0.0 +0,1.440000,0.0,0.0,0.0,0.0,0.0 +0,1.440100,0.0,0.0,0.0,0.0,0.0 +1,1244.548839,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.440200,0.0,0.0,0.0,0.0,0.0 +0,1.440300,0.0,0.0,0.0,0.0,0.0 +0,1.440400,0.0,0.0,0.0,0.0,0.0 +0,1.440500,0.0,0.0,0.0,0.0,0.0 +0,1.440600,0.0,0.0,0.0,0.0,0.0 +0,1.440700,0.0,0.0,0.0,0.0,0.0 +0,1.440800,0.0,0.0,0.0,0.0,0.0 +0,1.440900,0.0,0.0,0.0,0.0,0.0 +0,1.441000,0.0,0.0,0.0,0.0,0.0 +0,1.441100,0.0,0.0,0.0,0.0,0.0 +0,1.441200,0.0,0.0,0.0,0.0,0.0 +0,1.441300,0.0,0.0,0.0,0.0,0.0 +0,1.441400,0.0,0.0,0.0,0.0,0.0 +0,1.441500,0.0,0.0,0.0,0.0,0.0 +0,1.441600,0.0,0.0,0.0,0.0,0.0 +0,1.441700,0.0,0.0,0.0,0.0,0.0 +0,1.441800,0.0,0.0,0.0,0.0,0.0 +0,1.441900,0.0,0.0,0.0,0.0,0.0 +0,1.442000,0.0,0.0,0.0,0.0,0.0 +0,1.442100,0.0,0.0,0.0,0.0,0.0 +0,1.442200,0.0,0.0,0.0,0.0,0.0 +0,1.442300,0.0,0.0,0.0,0.0,0.0 +0,1.442400,0.0,0.0,0.0,0.0,0.0 +0,1.442500,0.0,0.0,0.0,0.0,0.0 +0,1.442600,0.0,0.0,0.0,0.0,0.0 +0,1.442700,0.0,0.0,0.0,0.0,0.0 +0,1.442800,0.0,0.0,0.0,0.0,0.0 +0,1.442900,0.0,0.0,0.0,0.0,0.0 +0,1.443000,0.0,0.0,0.0,0.0,0.0 +0,1.443100,0.0,0.0,0.0,0.0,0.0 +0,1.443200,0.0,0.0,0.0,0.0,0.0 +0,1.443300,0.0,0.0,0.0,0.0,0.0 +0,1.443400,0.0,0.0,0.0,0.0,0.0 +0,1.443500,0.0,0.0,0.0,0.0,0.0 +0,1.443600,0.0,0.0,0.0,0.0,0.0 +0,1.443700,0.0,0.0,0.0,0.0,0.0 +0,1.443800,0.0,0.0,0.0,0.0,0.0 +0,1.443900,0.0,0.0,0.0,0.0,0.0 +0,1.444000,0.0,0.0,0.0,0.0,0.0 +0,1.444100,0.0,0.0,0.0,0.0,0.0 +0,1.444200,0.0,0.0,0.0,0.0,0.0 +0,1.444300,0.0,0.0,0.0,0.0,0.0 +0,1.444400,0.0,0.0,0.0,0.0,0.0 +0,1.444500,0.0,0.0,0.0,0.0,0.0 +0,1.444600,0.0,0.0,0.0,0.0,0.0 +0,1.444700,0.0,0.0,0.0,0.0,0.0 +0,1.444800,0.0,0.0,0.0,0.0,0.0 +0,1.444900,0.0,0.0,0.0,0.0,0.0 +0,1.445000,0.0,0.0,0.0,0.0,0.0 +0,1.445100,0.0,0.0,0.0,0.0,0.0 +0,1.445200,0.0,0.0,0.0,0.0,0.0 +0,1.445300,0.0,0.0,0.0,0.0,0.0 +0,1.445400,0.0,0.0,0.0,0.0,0.0 +0,1.445500,0.0,0.0,0.0,0.0,0.0 +0,1.445600,0.0,0.0,0.0,0.0,0.0 +0,1.445700,0.0,0.0,0.0,0.0,0.0 +0,1.445800,0.0,0.0,0.0,0.0,0.0 +0,1.445900,0.0,0.0,0.0,0.0,0.0 +0,1.446000,0.0,0.0,0.0,0.0,0.0 +0,1.446100,0.0,0.0,0.0,0.0,0.0 +0,1.446200,0.0,0.0,0.0,0.0,0.0 +0,1.446300,0.0,0.0,0.0,0.0,0.0 +0,1.446400,0.0,0.0,0.0,0.0,0.0 +0,1.446500,0.0,0.0,0.0,0.0,0.0 +0,1.446600,0.0,0.0,0.0,0.0,0.0 +0,1.446700,0.0,0.0,0.0,0.0,0.0 +0,1.446800,0.0,0.0,0.0,0.0,0.0 +0,1.446900,0.0,0.0,0.0,0.0,0.0 +0,1.447000,0.0,0.0,0.0,0.0,0.0 +0,1.447100,0.0,0.0,0.0,0.0,0.0 +0,1.447200,0.0,0.0,0.0,0.0,0.0 +0,1.447300,0.0,0.0,0.0,0.0,0.0 +0,1.447400,0.0,0.0,0.0,0.0,0.0 +0,1.447500,0.0,0.0,0.0,0.0,0.0 +0,1.447600,0.0,0.0,0.0,0.0,0.0 +0,1.447700,0.0,0.0,0.0,0.0,0.0 +0,1.447800,0.0,0.0,0.0,0.0,0.0 +0,1.447900,0.0,0.0,0.0,0.0,0.0 +0,1.448000,0.0,0.0,0.0,0.0,0.0 +0,1.448100,0.0,0.0,0.0,0.0,0.0 +0,1.448200,0.0,0.0,0.0,0.0,0.0 +0,1.448300,0.0,0.0,0.0,0.0,0.0 +0,1.448400,0.0,0.0,0.0,0.0,0.0 +0,1.448500,0.0,0.0,0.0,0.0,0.0 +0,1.448600,0.0,0.0,0.0,0.0,0.0 +0,1.448700,0.0,0.0,0.0,0.0,0.0 +0,1.448800,0.0,0.0,0.0,0.0,0.0 +0,1.448900,0.0,0.0,0.0,0.0,0.0 +0,1.449000,0.0,0.0,0.0,0.0,0.0 +0,1.449100,0.0,0.0,0.0,0.0,0.0 +0,1.449200,0.0,0.0,0.0,0.0,0.0 +0,1.449300,0.0,0.0,0.0,0.0,0.0 +0,1.449400,0.0,0.0,0.0,0.0,0.0 +0,1.449500,0.0,0.0,0.0,0.0,0.0 +0,1.449600,0.0,0.0,0.0,0.0,0.0 +0,1.449700,0.0,0.0,0.0,0.0,0.0 +0,1.449800,0.0,0.0,0.0,0.0,0.0 +0,1.449900,0.0,0.0,0.0,0.0,0.0 +0,1.450000,0.0,0.0,0.0,0.0,0.0 +0,1.450100,0.0,0.0,0.0,0.0,0.0 +0,1.450200,0.0,0.0,0.0,0.0,0.0 +0,1.450300,0.0,0.0,0.0,0.0,0.0 +0,1.450400,0.0,0.0,0.0,0.0,0.0 +0,1.450500,0.0,0.0,0.0,0.0,0.0 +0,1.450600,0.0,0.0,0.0,0.0,0.0 +0,1.450700,0.0,0.0,0.0,0.0,0.0 +0,1.450800,0.0,0.0,0.0,0.0,0.0 +0,1.450900,0.0,0.0,0.0,0.0,0.0 +0,1.451000,0.0,0.0,0.0,0.0,0.0 +0,1.451100,0.0,0.0,0.0,0.0,0.0 +0,1.451200,0.0,0.0,0.0,0.0,0.0 +0,1.451300,0.0,0.0,0.0,0.0,0.0 +0,1.451400,0.0,0.0,0.0,0.0,0.0 +0,1.451500,0.0,0.0,0.0,0.0,0.0 +0,1.451600,0.0,0.0,0.0,0.0,0.0 +0,1.451700,0.0,0.0,0.0,0.0,0.0 +0,1.451800,0.0,0.0,0.0,0.0,0.0 +0,1.451900,0.0,0.0,0.0,0.0,0.0 +0,1.452000,0.0,0.0,0.0,0.0,0.0 +0,1.452100,0.0,0.0,0.0,0.0,0.0 +0,1.452200,0.0,0.0,0.0,0.0,0.0 +0,1.452300,0.0,0.0,0.0,0.0,0.0 +0,1.452400,0.0,0.0,0.0,0.0,0.0 +0,1.452500,0.0,0.0,0.0,0.0,0.0 +0,1.452600,0.0,0.0,0.0,0.0,0.0 +0,1.452700,0.0,0.0,0.0,0.0,0.0 +0,1.452800,0.0,0.0,0.0,0.0,0.0 +0,1.452900,0.0,0.0,0.0,0.0,0.0 +0,1.453000,0.0,0.0,0.0,0.0,0.0 +0,1.453100,0.0,0.0,0.0,0.0,0.0 +0,1.453200,0.0,0.0,0.0,0.0,0.0 +0,1.453300,0.0,0.0,0.0,0.0,0.0 +0,1.453400,0.0,0.0,0.0,0.0,0.0 +0,1.453500,0.0,0.0,0.0,0.0,0.0 +0,1.453600,0.0,0.0,0.0,0.0,0.0 +0,1.453700,0.0,0.0,0.0,0.0,0.0 +0,1.453800,0.0,0.0,0.0,0.0,0.0 +0,1.453900,0.0,0.0,0.0,0.0,0.0 +0,1.454000,0.0,0.0,0.0,0.0,0.0 +0,1.454100,0.0,0.0,0.0,0.0,0.0 +0,1.454200,0.0,0.0,0.0,0.0,0.0 +0,1.454300,0.0,0.0,0.0,0.0,0.0 +0,1.454400,0.0,0.0,0.0,0.0,0.0 +0,1.454500,0.0,0.0,0.0,0.0,0.0 +0,1.454600,0.0,0.0,0.0,0.0,0.0 +0,1.454700,0.0,0.0,0.0,0.0,0.0 +0,1.454800,0.0,0.0,0.0,0.0,0.0 +0,1.454900,0.0,0.0,0.0,0.0,0.0 +0,1.455000,0.0,0.0,0.0,0.0,0.0 +0,1.455100,0.0,0.0,0.0,0.0,0.0 +0,1.455200,0.0,0.0,0.0,0.0,0.0 +0,1.455300,0.0,0.0,0.0,0.0,0.0 +0,1.455400,0.0,0.0,0.0,0.0,0.0 +0,1.455500,0.0,0.0,0.0,0.0,0.0 +0,1.455600,0.0,0.0,0.0,0.0,0.0 +0,1.455700,0.0,0.0,0.0,0.0,0.0 +0,1.455800,0.0,0.0,0.0,0.0,0.0 +0,1.455900,0.0,0.0,0.0,0.0,0.0 +0,1.456000,0.0,0.0,0.0,0.0,0.0 +0,1.456100,0.0,0.0,0.0,0.0,0.0 +0,1.456200,0.0,0.0,0.0,0.0,0.0 +0,1.456300,0.0,0.0,0.0,0.0,0.0 +0,1.456400,0.0,0.0,0.0,0.0,0.0 +0,1.456500,0.0,0.0,0.0,0.0,0.0 +0,1.456600,0.0,0.0,0.0,0.0,0.0 +0,1.456700,0.0,0.0,0.0,0.0,0.0 +0,1.456800,0.0,0.0,0.0,0.0,0.0 +0,1.456900,0.0,0.0,0.0,0.0,0.0 +0,1.457000,0.0,0.0,0.0,0.0,0.0 +0,1.457100,0.0,0.0,0.0,0.0,0.0 +0,1.457200,0.0,0.0,0.0,0.0,0.0 +0,1.457300,0.0,0.0,0.0,0.0,0.0 +0,1.457400,0.0,0.0,0.0,0.0,0.0 +0,1.457500,0.0,0.0,0.0,0.0,0.0 +0,1.457600,0.0,0.0,0.0,0.0,0.0 +0,1.457700,0.0,0.0,0.0,0.0,0.0 +0,1.457800,0.0,0.0,0.0,0.0,0.0 +0,1.457900,0.0,0.0,0.0,0.0,0.0 +0,1.458000,0.0,0.0,0.0,0.0,0.0 +0,1.458100,0.0,0.0,0.0,0.0,0.0 +0,1.458200,0.0,0.0,0.0,0.0,0.0 +0,1.458300,0.0,0.0,0.0,0.0,0.0 +0,1.458400,0.0,0.0,0.0,0.0,0.0 +0,1.458500,0.0,0.0,0.0,0.0,0.0 +0,1.458600,0.0,0.0,0.0,0.0,0.0 +0,1.458700,0.0,0.0,0.0,0.0,0.0 +0,1.458800,0.0,0.0,0.0,0.0,0.0 +0,1.458900,0.0,0.0,0.0,0.0,0.0 +0,1.459000,0.0,0.0,0.0,0.0,0.0 +0,1.459100,0.0,0.0,0.0,0.0,0.0 +0,1.459200,0.0,0.0,0.0,0.0,0.0 +0,1.459300,0.0,0.0,0.0,0.0,0.0 +0,1.459400,0.0,0.0,0.0,0.0,0.0 +0,1.459500,0.0,0.0,0.0,0.0,0.0 +0,1.459600,0.0,0.0,0.0,0.0,0.0 +0,1.459700,0.0,0.0,0.0,0.0,0.0 +0,1.459800,0.0,0.0,0.0,0.0,0.0 +0,1.459900,0.0,0.0,0.0,0.0,0.0 +0,1.460000,0.0,0.0,0.0,0.0,0.0 +0,1.460100,0.0,0.0,0.0,0.0,0.0 +1,1297.123048,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.460200,0.0,0.0,0.0,0.0,0.0 +0,1.460300,0.0,0.0,0.0,0.0,0.0 +0,1.460400,0.0,0.0,0.0,0.0,0.0 +0,1.460500,0.0,0.0,0.0,0.0,0.0 +0,1.460600,0.0,0.0,0.0,0.0,0.0 +0,1.460700,0.0,0.0,0.0,0.0,0.0 +0,1.460800,0.0,0.0,0.0,0.0,0.0 +0,1.460900,0.0,0.0,0.0,0.0,0.0 +0,1.461000,0.0,0.0,0.0,0.0,0.0 +0,1.461100,0.0,0.0,0.0,0.0,0.0 +0,1.461200,0.0,0.0,0.0,0.0,0.0 +0,1.461300,0.0,0.0,0.0,0.0,0.0 +0,1.461400,0.0,0.0,0.0,0.0,0.0 +0,1.461500,0.0,0.0,0.0,0.0,0.0 +0,1.461600,0.0,0.0,0.0,0.0,0.0 +0,1.461700,0.0,0.0,0.0,0.0,0.0 +0,1.461800,0.0,0.0,0.0,0.0,0.0 +0,1.461900,0.0,0.0,0.0,0.0,0.0 +0,1.462000,0.0,0.0,0.0,0.0,0.0 +0,1.462100,0.0,0.0,0.0,0.0,0.0 +0,1.462200,0.0,0.0,0.0,0.0,0.0 +0,1.462300,0.0,0.0,0.0,0.0,0.0 +0,1.462400,0.0,0.0,0.0,0.0,0.0 +0,1.462500,0.0,0.0,0.0,0.0,0.0 +0,1.462600,0.0,0.0,0.0,0.0,0.0 +0,1.462700,0.0,0.0,0.0,0.0,0.0 +0,1.462800,0.0,0.0,0.0,0.0,0.0 +0,1.462900,0.0,0.0,0.0,0.0,0.0 +0,1.463000,0.0,0.0,0.0,0.0,0.0 +0,1.463100,0.0,0.0,0.0,0.0,0.0 +0,1.463200,0.0,0.0,0.0,0.0,0.0 +0,1.463300,0.0,0.0,0.0,0.0,0.0 +0,1.463400,0.0,0.0,0.0,0.0,0.0 +0,1.463500,0.0,0.0,0.0,0.0,0.0 +0,1.463600,0.0,0.0,0.0,0.0,0.0 +0,1.463700,0.0,0.0,0.0,0.0,0.0 +0,1.463800,0.0,0.0,0.0,0.0,0.0 +0,1.463900,0.0,0.0,0.0,0.0,0.0 +0,1.464000,0.0,0.0,0.0,0.0,0.0 +0,1.464100,0.0,0.0,0.0,0.0,0.0 +0,1.464200,0.0,0.0,0.0,0.0,0.0 +0,1.464300,0.0,0.0,0.0,0.0,0.0 +0,1.464400,0.0,0.0,0.0,0.0,0.0 +0,1.464500,0.0,0.0,0.0,0.0,0.0 +0,1.464600,0.0,0.0,0.0,0.0,0.0 +0,1.464700,0.0,0.0,0.0,0.0,0.0 +0,1.464800,0.0,0.0,0.0,0.0,0.0 +0,1.464900,0.0,0.0,0.0,0.0,0.0 +0,1.465000,0.0,0.0,0.0,0.0,0.0 +0,1.465100,0.0,0.0,0.0,0.0,0.0 +0,1.465200,0.0,0.0,0.0,0.0,0.0 +0,1.465300,0.0,0.0,0.0,0.0,0.0 +0,1.465400,0.0,0.0,0.0,0.0,0.0 +0,1.465500,0.0,0.0,0.0,0.0,0.0 +0,1.465600,0.0,0.0,0.0,0.0,0.0 +0,1.465700,0.0,0.0,0.0,0.0,0.0 +0,1.465800,0.0,0.0,0.0,0.0,0.0 +0,1.465900,0.0,0.0,0.0,0.0,0.0 +0,1.466000,0.0,0.0,0.0,0.0,0.0 +0,1.466100,0.0,0.0,0.0,0.0,0.0 +0,1.466200,0.0,0.0,0.0,0.0,0.0 +0,1.466300,0.0,0.0,0.0,0.0,0.0 +0,1.466400,0.0,0.0,0.0,0.0,0.0 +0,1.466500,0.0,0.0,0.0,0.0,0.0 +0,1.466600,0.0,0.0,0.0,0.0,0.0 +0,1.466700,0.0,0.0,0.0,0.0,0.0 +0,1.466800,0.0,0.0,0.0,0.0,0.0 +0,1.466900,0.0,0.0,0.0,0.0,0.0 +0,1.467000,0.0,0.0,0.0,0.0,0.0 +0,1.467100,0.0,0.0,0.0,0.0,0.0 +0,1.467200,0.0,0.0,0.0,0.0,0.0 +0,1.467300,0.0,0.0,0.0,0.0,0.0 +0,1.467400,0.0,0.0,0.0,0.0,0.0 +0,1.467500,0.0,0.0,0.0,0.0,0.0 +0,1.467600,0.0,0.0,0.0,0.0,0.0 +0,1.467700,0.0,0.0,0.0,0.0,0.0 +0,1.467800,0.0,0.0,0.0,0.0,0.0 +0,1.467900,0.0,0.0,0.0,0.0,0.0 +0,1.468000,0.0,0.0,0.0,0.0,0.0 +0,1.468100,0.0,0.0,0.0,0.0,0.0 +0,1.468200,0.0,0.0,0.0,0.0,0.0 +0,1.468300,0.0,0.0,0.0,0.0,0.0 +0,1.468400,0.0,0.0,0.0,0.0,0.0 +0,1.468500,0.0,0.0,0.0,0.0,0.0 +0,1.468600,0.0,0.0,0.0,0.0,0.0 +0,1.468700,0.0,0.0,0.0,0.0,0.0 +0,1.468800,0.0,0.0,0.0,0.0,0.0 +0,1.468900,0.0,0.0,0.0,0.0,0.0 +0,1.469000,0.0,0.0,0.0,0.0,0.0 +0,1.469100,0.0,0.0,0.0,0.0,0.0 +0,1.469200,0.0,0.0,0.0,0.0,0.0 +0,1.469300,0.0,0.0,0.0,0.0,0.0 +0,1.469400,0.0,0.0,0.0,0.0,0.0 +0,1.469500,0.0,0.0,0.0,0.0,0.0 +0,1.469600,0.0,0.0,0.0,0.0,0.0 +0,1.469700,0.0,0.0,0.0,0.0,0.0 +0,1.469800,0.0,0.0,0.0,0.0,0.0 +0,1.469900,0.0,0.0,0.0,0.0,0.0 +0,1.470000,0.0,0.0,0.0,0.0,0.0 +0,1.470100,0.0,0.0,0.0,0.0,0.0 +0,1.470200,0.0,0.0,0.0,0.0,0.0 +0,1.470300,0.0,0.0,0.0,0.0,0.0 +0,1.470400,0.0,0.0,0.0,0.0,0.0 +0,1.470500,0.0,0.0,0.0,0.0,0.0 +0,1.470600,0.0,0.0,0.0,0.0,0.0 +0,1.470700,0.0,0.0,0.0,0.0,0.0 +0,1.470800,0.0,0.0,0.0,0.0,0.0 +0,1.470900,0.0,0.0,0.0,0.0,0.0 +0,1.471000,0.0,0.0,0.0,0.0,0.0 +0,1.471100,0.0,0.0,0.0,0.0,0.0 +0,1.471200,0.0,0.0,0.0,0.0,0.0 +0,1.471300,0.0,0.0,0.0,0.0,0.0 +0,1.471400,0.0,0.0,0.0,0.0,0.0 +0,1.471500,0.0,0.0,0.0,0.0,0.0 +0,1.471600,0.0,0.0,0.0,0.0,0.0 +0,1.471700,0.0,0.0,0.0,0.0,0.0 +0,1.471800,0.0,0.0,0.0,0.0,0.0 +0,1.471900,0.0,0.0,0.0,0.0,0.0 +0,1.472000,0.0,0.0,0.0,0.0,0.0 +0,1.472100,0.0,0.0,0.0,0.0,0.0 +0,1.472200,0.0,0.0,0.0,0.0,0.0 +0,1.472300,0.0,0.0,0.0,0.0,0.0 +0,1.472400,0.0,0.0,0.0,0.0,0.0 +0,1.472500,0.0,0.0,0.0,0.0,0.0 +0,1.472600,0.0,0.0,0.0,0.0,0.0 +0,1.472700,0.0,0.0,0.0,0.0,0.0 +0,1.472800,0.0,0.0,0.0,0.0,0.0 +0,1.472900,0.0,0.0,0.0,0.0,0.0 +0,1.473000,0.0,0.0,0.0,0.0,0.0 +0,1.473100,0.0,0.0,0.0,0.0,0.0 +0,1.473200,0.0,0.0,0.0,0.0,0.0 +0,1.473300,0.0,0.0,0.0,0.0,0.0 +0,1.473400,0.0,0.0,0.0,0.0,0.0 +0,1.473500,0.0,0.0,0.0,0.0,0.0 +0,1.473600,0.0,0.0,0.0,0.0,0.0 +0,1.473700,0.0,0.0,0.0,0.0,0.0 +0,1.473800,0.0,0.0,0.0,0.0,0.0 +0,1.473900,0.0,0.0,0.0,0.0,0.0 +0,1.474000,0.0,0.0,0.0,0.0,0.0 +0,1.474100,0.0,0.0,0.0,0.0,0.0 +0,1.474200,0.0,0.0,0.0,0.0,0.0 +0,1.474300,0.0,0.0,0.0,0.0,0.0 +0,1.474400,0.0,0.0,0.0,0.0,0.0 +0,1.474500,0.0,0.0,0.0,0.0,0.0 +0,1.474600,0.0,0.0,0.0,0.0,0.0 +0,1.474700,0.0,0.0,0.0,0.0,0.0 +0,1.474800,0.0,0.0,0.0,0.0,0.0 +0,1.474900,0.0,0.0,0.0,0.0,0.0 +0,1.475000,0.0,0.0,0.0,0.0,0.0 +0,1.475100,0.0,0.0,0.0,0.0,0.0 +0,1.475200,0.0,0.0,0.0,0.0,0.0 +0,1.475300,0.0,0.0,0.0,0.0,0.0 +0,1.475400,0.0,0.0,0.0,0.0,0.0 +0,1.475500,0.0,0.0,0.0,0.0,0.0 +0,1.475600,0.0,0.0,0.0,0.0,0.0 +0,1.475700,0.0,0.0,0.0,0.0,0.0 +0,1.475800,0.0,0.0,0.0,0.0,0.0 +0,1.475900,0.0,0.0,0.0,0.0,0.0 +0,1.476000,0.0,0.0,0.0,0.0,0.0 +0,1.476100,0.0,0.0,0.0,0.0,0.0 +0,1.476200,0.0,0.0,0.0,0.0,0.0 +0,1.476300,0.0,0.0,0.0,0.0,0.0 +0,1.476400,0.0,0.0,0.0,0.0,0.0 +0,1.476500,0.0,0.0,0.0,0.0,0.0 +0,1.476600,0.0,0.0,0.0,0.0,0.0 +0,1.476700,0.0,0.0,0.0,0.0,0.0 +0,1.476800,0.0,0.0,0.0,0.0,0.0 +0,1.476900,0.0,0.0,0.0,0.0,0.0 +0,1.477000,0.0,0.0,0.0,0.0,0.0 +0,1.477100,0.0,0.0,0.0,0.0,0.0 +0,1.477200,0.0,0.0,0.0,0.0,0.0 +0,1.477300,0.0,0.0,0.0,0.0,0.0 +0,1.477400,0.0,0.0,0.0,0.0,0.0 +0,1.477500,0.0,0.0,0.0,0.0,0.0 +0,1.477600,0.0,0.0,0.0,0.0,0.0 +0,1.477700,0.0,0.0,0.0,0.0,0.0 +0,1.477800,0.0,0.0,0.0,0.0,0.0 +0,1.477900,0.0,0.0,0.0,0.0,0.0 +0,1.478000,0.0,0.0,0.0,0.0,0.0 +0,1.478100,0.0,0.0,0.0,0.0,0.0 +0,1.478200,0.0,0.0,0.0,0.0,0.0 +0,1.478300,0.0,0.0,0.0,0.0,0.0 +0,1.478400,0.0,0.0,0.0,0.0,0.0 +0,1.478500,0.0,0.0,0.0,0.0,0.0 +0,1.478600,0.0,0.0,0.0,0.0,0.0 +0,1.478700,0.0,0.0,0.0,0.0,0.0 +0,1.478800,0.0,0.0,0.0,0.0,0.0 +0,1.478900,0.0,0.0,0.0,0.0,0.0 +0,1.479000,0.0,0.0,0.0,0.0,0.0 +0,1.479100,0.0,0.0,0.0,0.0,0.0 +0,1.479200,0.0,0.0,0.0,0.0,0.0 +0,1.479300,0.0,0.0,0.0,0.0,0.0 +0,1.479400,0.0,0.0,0.0,0.0,0.0 +0,1.479500,0.0,0.0,0.0,0.0,0.0 +0,1.479600,0.0,0.0,0.0,0.0,0.0 +0,1.479700,0.0,0.0,0.0,0.0,0.0 +0,1.479800,0.0,0.0,0.0,0.0,0.0 +0,1.479900,0.0,0.0,0.0,0.0,0.0 +0,1.480000,0.0,0.0,0.0,0.0,0.0 +0,1.480100,0.0,0.0,0.0,0.0,0.0 +1,1351.157407,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.480200,0.0,0.0,0.0,0.0,0.0 +0,1.480300,0.0,0.0,0.0,0.0,0.0 +0,1.480400,0.0,0.0,0.0,0.0,0.0 +0,1.480500,0.0,0.0,0.0,0.0,0.0 +0,1.480600,0.0,0.0,0.0,0.0,0.0 +0,1.480700,0.0,0.0,0.0,0.0,0.0 +0,1.480800,0.0,0.0,0.0,0.0,0.0 +0,1.480900,0.0,0.0,0.0,0.0,0.0 +0,1.481000,0.0,0.0,0.0,0.0,0.0 +0,1.481100,0.0,0.0,0.0,0.0,0.0 +0,1.481200,0.0,0.0,0.0,0.0,0.0 +0,1.481300,0.0,0.0,0.0,0.0,0.0 +0,1.481400,0.0,0.0,0.0,0.0,0.0 +0,1.481500,0.0,0.0,0.0,0.0,0.0 +0,1.481600,0.0,0.0,0.0,0.0,0.0 +0,1.481700,0.0,0.0,0.0,0.0,0.0 +0,1.481800,0.0,0.0,0.0,0.0,0.0 +0,1.481900,0.0,0.0,0.0,0.0,0.0 +0,1.482000,0.0,0.0,0.0,0.0,0.0 +0,1.482100,0.0,0.0,0.0,0.0,0.0 +0,1.482200,0.0,0.0,0.0,0.0,0.0 +0,1.482300,0.0,0.0,0.0,0.0,0.0 +0,1.482400,0.0,0.0,0.0,0.0,0.0 +0,1.482500,0.0,0.0,0.0,0.0,0.0 +0,1.482600,0.0,0.0,0.0,0.0,0.0 +0,1.482700,0.0,0.0,0.0,0.0,0.0 +0,1.482800,0.0,0.0,0.0,0.0,0.0 +0,1.482900,0.0,0.0,0.0,0.0,0.0 +0,1.483000,0.0,0.0,0.0,0.0,0.0 +0,1.483100,0.0,0.0,0.0,0.0,0.0 +0,1.483200,0.0,0.0,0.0,0.0,0.0 +0,1.483300,0.0,0.0,0.0,0.0,0.0 +0,1.483400,0.0,0.0,0.0,0.0,0.0 +0,1.483500,0.0,0.0,0.0,0.0,0.0 +0,1.483600,0.0,0.0,0.0,0.0,0.0 +0,1.483700,0.0,0.0,0.0,0.0,0.0 +0,1.483800,0.0,0.0,0.0,0.0,0.0 +0,1.483900,0.0,0.0,0.0,0.0,0.0 +0,1.484000,0.0,0.0,0.0,0.0,0.0 +0,1.484100,0.0,0.0,0.0,0.0,0.0 +0,1.484200,0.0,0.0,0.0,0.0,0.0 +0,1.484300,0.0,0.0,0.0,0.0,0.0 +0,1.484400,0.0,0.0,0.0,0.0,0.0 +0,1.484500,0.0,0.0,0.0,0.0,0.0 +0,1.484600,0.0,0.0,0.0,0.0,0.0 +0,1.484700,0.0,0.0,0.0,0.0,0.0 +0,1.484800,0.0,0.0,0.0,0.0,0.0 +0,1.484900,0.0,0.0,0.0,0.0,0.0 +0,1.485000,0.0,0.0,0.0,0.0,0.0 +0,1.485100,0.0,0.0,0.0,0.0,0.0 +0,1.485200,0.0,0.0,0.0,0.0,0.0 +0,1.485300,0.0,0.0,0.0,0.0,0.0 +0,1.485400,0.0,0.0,0.0,0.0,0.0 +0,1.485500,0.0,0.0,0.0,0.0,0.0 +0,1.485600,0.0,0.0,0.0,0.0,0.0 +0,1.485700,0.0,0.0,0.0,0.0,0.0 +0,1.485800,0.0,0.0,0.0,0.0,0.0 +0,1.485900,0.0,0.0,0.0,0.0,0.0 +0,1.486000,0.0,0.0,0.0,0.0,0.0 +0,1.486100,0.0,0.0,0.0,0.0,0.0 +0,1.486200,0.0,0.0,0.0,0.0,0.0 +0,1.486300,0.0,0.0,0.0,0.0,0.0 +0,1.486400,0.0,0.0,0.0,0.0,0.0 +0,1.486500,0.0,0.0,0.0,0.0,0.0 +0,1.486600,0.0,0.0,0.0,0.0,0.0 +0,1.486700,0.0,0.0,0.0,0.0,0.0 +0,1.486800,0.0,0.0,0.0,0.0,0.0 +0,1.486900,0.0,0.0,0.0,0.0,0.0 +0,1.487000,0.0,0.0,0.0,0.0,0.0 +0,1.487100,0.0,0.0,0.0,0.0,0.0 +0,1.487200,0.0,0.0,0.0,0.0,0.0 +0,1.487300,0.0,0.0,0.0,0.0,0.0 +0,1.487400,0.0,0.0,0.0,0.0,0.0 +0,1.487500,0.0,0.0,0.0,0.0,0.0 +0,1.487600,0.0,0.0,0.0,0.0,0.0 +0,1.487700,0.0,0.0,0.0,0.0,0.0 +0,1.487800,0.0,0.0,0.0,0.0,0.0 +0,1.487900,0.0,0.0,0.0,0.0,0.0 +0,1.488000,0.0,0.0,0.0,0.0,0.0 +0,1.488100,0.0,0.0,0.0,0.0,0.0 +0,1.488200,0.0,0.0,0.0,0.0,0.0 +0,1.488300,0.0,0.0,0.0,0.0,0.0 +0,1.488400,0.0,0.0,0.0,0.0,0.0 +0,1.488500,0.0,0.0,0.0,0.0,0.0 +0,1.488600,0.0,0.0,0.0,0.0,0.0 +0,1.488700,0.0,0.0,0.0,0.0,0.0 +0,1.488800,0.0,0.0,0.0,0.0,0.0 +0,1.488900,0.0,0.0,0.0,0.0,0.0 +0,1.489000,0.0,0.0,0.0,0.0,0.0 +0,1.489100,0.0,0.0,0.0,0.0,0.0 +0,1.489200,0.0,0.0,0.0,0.0,0.0 +0,1.489300,0.0,0.0,0.0,0.0,0.0 +0,1.489400,0.0,0.0,0.0,0.0,0.0 +0,1.489500,0.0,0.0,0.0,0.0,0.0 +0,1.489600,0.0,0.0,0.0,0.0,0.0 +0,1.489700,0.0,0.0,0.0,0.0,0.0 +0,1.489800,0.0,0.0,0.0,0.0,0.0 +0,1.489900,0.0,0.0,0.0,0.0,0.0 +0,1.490000,0.0,0.0,0.0,0.0,0.0 +0,1.490100,0.0,0.0,0.0,0.0,0.0 +0,1.490200,0.0,0.0,0.0,0.0,0.0 +0,1.490300,0.0,0.0,0.0,0.0,0.0 +0,1.490400,0.0,0.0,0.0,0.0,0.0 +0,1.490500,0.0,0.0,0.0,0.0,0.0 +0,1.490600,0.0,0.0,0.0,0.0,0.0 +0,1.490700,0.0,0.0,0.0,0.0,0.0 +0,1.490800,0.0,0.0,0.0,0.0,0.0 +0,1.490900,0.0,0.0,0.0,0.0,0.0 +0,1.491000,0.0,0.0,0.0,0.0,0.0 +0,1.491100,0.0,0.0,0.0,0.0,0.0 +0,1.491200,0.0,0.0,0.0,0.0,0.0 +0,1.491300,0.0,0.0,0.0,0.0,0.0 +0,1.491400,0.0,0.0,0.0,0.0,0.0 +0,1.491500,0.0,0.0,0.0,0.0,0.0 +0,1.491600,0.0,0.0,0.0,0.0,0.0 +0,1.491700,0.0,0.0,0.0,0.0,0.0 +0,1.491800,0.0,0.0,0.0,0.0,0.0 +0,1.491900,0.0,0.0,0.0,0.0,0.0 +0,1.492000,0.0,0.0,0.0,0.0,0.0 +0,1.492100,0.0,0.0,0.0,0.0,0.0 +0,1.492200,0.0,0.0,0.0,0.0,0.0 +0,1.492300,0.0,0.0,0.0,0.0,0.0 +0,1.492400,0.0,0.0,0.0,0.0,0.0 +0,1.492500,0.0,0.0,0.0,0.0,0.0 +0,1.492600,0.0,0.0,0.0,0.0,0.0 +0,1.492700,0.0,0.0,0.0,0.0,0.0 +0,1.492800,0.0,0.0,0.0,0.0,0.0 +0,1.492900,0.0,0.0,0.0,0.0,0.0 +0,1.493000,0.0,0.0,0.0,0.0,0.0 +0,1.493100,0.0,0.0,0.0,0.0,0.0 +0,1.493200,0.0,0.0,0.0,0.0,0.0 +0,1.493300,0.0,0.0,0.0,0.0,0.0 +0,1.493400,0.0,0.0,0.0,0.0,0.0 +0,1.493500,0.0,0.0,0.0,0.0,0.0 +0,1.493600,0.0,0.0,0.0,0.0,0.0 +0,1.493700,0.0,0.0,0.0,0.0,0.0 +0,1.493800,0.0,0.0,0.0,0.0,0.0 +0,1.493900,0.0,0.0,0.0,0.0,0.0 +0,1.494000,0.0,0.0,0.0,0.0,0.0 +0,1.494100,0.0,0.0,0.0,0.0,0.0 +0,1.494200,0.0,0.0,0.0,0.0,0.0 +0,1.494300,0.0,0.0,0.0,0.0,0.0 +0,1.494400,0.0,0.0,0.0,0.0,0.0 +0,1.494500,0.0,0.0,0.0,0.0,0.0 +0,1.494600,0.0,0.0,0.0,0.0,0.0 +0,1.494700,0.0,0.0,0.0,0.0,0.0 +0,1.494800,0.0,0.0,0.0,0.0,0.0 +0,1.494900,0.0,0.0,0.0,0.0,0.0 +0,1.495000,0.0,0.0,0.0,0.0,0.0 +0,1.495100,0.0,0.0,0.0,0.0,0.0 +0,1.495200,0.0,0.0,0.0,0.0,0.0 +0,1.495300,0.0,0.0,0.0,0.0,0.0 +0,1.495400,0.0,0.0,0.0,0.0,0.0 +0,1.495500,0.0,0.0,0.0,0.0,0.0 +0,1.495600,0.0,0.0,0.0,0.0,0.0 +0,1.495700,0.0,0.0,0.0,0.0,0.0 +0,1.495800,0.0,0.0,0.0,0.0,0.0 +0,1.495900,0.0,0.0,0.0,0.0,0.0 +0,1.496000,0.0,0.0,0.0,0.0,0.0 +0,1.496100,0.0,0.0,0.0,0.0,0.0 +0,1.496200,0.0,0.0,0.0,0.0,0.0 +0,1.496300,0.0,0.0,0.0,0.0,0.0 +0,1.496400,0.0,0.0,0.0,0.0,0.0 +0,1.496500,0.0,0.0,0.0,0.0,0.0 +0,1.496600,0.0,0.0,0.0,0.0,0.0 +0,1.496700,0.0,0.0,0.0,0.0,0.0 +0,1.496800,0.0,0.0,0.0,0.0,0.0 +0,1.496900,0.0,0.0,0.0,0.0,0.0 +0,1.497000,0.0,0.0,0.0,0.0,0.0 +0,1.497100,0.0,0.0,0.0,0.0,0.0 +0,1.497200,0.0,0.0,0.0,0.0,0.0 +0,1.497300,0.0,0.0,0.0,0.0,0.0 +0,1.497400,0.0,0.0,0.0,0.0,0.0 +0,1.497500,0.0,0.0,0.0,0.0,0.0 +0,1.497600,0.0,0.0,0.0,0.0,0.0 +0,1.497700,0.0,0.0,0.0,0.0,0.0 +0,1.497800,0.0,0.0,0.0,0.0,0.0 +0,1.497900,0.0,0.0,0.0,0.0,0.0 +0,1.498000,0.0,0.0,0.0,0.0,0.0 +0,1.498100,0.0,0.0,0.0,0.0,0.0 +0,1.498200,0.0,0.0,0.0,0.0,0.0 +0,1.498300,0.0,0.0,0.0,0.0,0.0 +0,1.498400,0.0,0.0,0.0,0.0,0.0 +0,1.498500,0.0,0.0,0.0,0.0,0.0 +0,1.498600,0.0,0.0,0.0,0.0,0.0 +0,1.498700,0.0,0.0,0.0,0.0,0.0 +0,1.498800,0.0,0.0,0.0,0.0,0.0 +0,1.498900,0.0,0.0,0.0,0.0,0.0 +0,1.499000,0.0,0.0,0.0,0.0,0.0 +0,1.499100,0.0,0.0,0.0,0.0,0.0 +0,1.499200,0.0,0.0,0.0,0.0,0.0 +0,1.499300,0.0,0.0,0.0,0.0,0.0 +0,1.499400,0.0,0.0,0.0,0.0,0.0 +0,1.499500,0.0,0.0,0.0,0.0,0.0 +0,1.499600,0.0,0.0,0.0,0.0,0.0 +0,1.499700,0.0,0.0,0.0,0.0,0.0 +0,1.499800,0.0,0.0,0.0,0.0,0.0 +0,1.499900,0.0,0.0,0.0,0.0,0.0 +0,1.500000,0.0,0.0,0.0,0.0,0.0 +0,1.500100,0.0,0.0,0.0,0.0,0.0 +1,1406.671916,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.500200,0.0,0.0,0.0,0.0,0.0 +0,1.500300,0.0,0.0,0.0,0.0,0.0 +0,1.500400,0.0,0.0,0.0,0.0,0.0 +0,1.500500,0.0,0.0,0.0,0.0,0.0 +0,1.500600,0.0,0.0,0.0,0.0,0.0 +0,1.500700,0.0,0.0,0.0,0.0,0.0 +0,1.500800,0.0,0.0,0.0,0.0,0.0 +0,1.500900,0.0,0.0,0.0,0.0,0.0 +0,1.501000,0.0,0.0,0.0,0.0,0.0 +0,1.501100,0.0,0.0,0.0,0.0,0.0 +0,1.501200,0.0,0.0,0.0,0.0,0.0 +0,1.501300,0.0,0.0,0.0,0.0,0.0 +0,1.501400,0.0,0.0,0.0,0.0,0.0 +0,1.501500,0.0,0.0,0.0,0.0,0.0 +0,1.501600,0.0,0.0,0.0,0.0,0.0 +0,1.501700,0.0,0.0,0.0,0.0,0.0 +0,1.501800,0.0,0.0,0.0,0.0,0.0 +0,1.501900,0.0,0.0,0.0,0.0,0.0 +0,1.502000,0.0,0.0,0.0,0.0,0.0 +0,1.502100,0.0,0.0,0.0,0.0,0.0 +0,1.502200,0.0,0.0,0.0,0.0,0.0 +0,1.502300,0.0,0.0,0.0,0.0,0.0 +0,1.502400,0.0,0.0,0.0,0.0,0.0 +0,1.502500,0.0,0.0,0.0,0.0,0.0 +0,1.502600,0.0,0.0,0.0,0.0,0.0 +0,1.502700,0.0,0.0,0.0,0.0,0.0 +0,1.502800,0.0,0.0,0.0,0.0,0.0 +0,1.502900,0.0,0.0,0.0,0.0,0.0 +0,1.503000,0.0,0.0,0.0,0.0,0.0 +0,1.503100,0.0,0.0,0.0,0.0,0.0 +0,1.503200,0.0,0.0,0.0,0.0,0.0 +0,1.503300,0.0,0.0,0.0,0.0,0.0 +0,1.503400,0.0,0.0,0.0,0.0,0.0 +0,1.503500,0.0,0.0,0.0,0.0,0.0 +0,1.503600,0.0,0.0,0.0,0.0,0.0 +0,1.503700,0.0,0.0,0.0,0.0,0.0 +0,1.503800,0.0,0.0,0.0,0.0,0.0 +0,1.503900,0.0,0.0,0.0,0.0,0.0 +0,1.504000,0.0,0.0,0.0,0.0,0.0 +0,1.504100,0.0,0.0,0.0,0.0,0.0 +0,1.504200,0.0,0.0,0.0,0.0,0.0 +0,1.504300,0.0,0.0,0.0,0.0,0.0 +0,1.504400,0.0,0.0,0.0,0.0,0.0 +0,1.504500,0.0,0.0,0.0,0.0,0.0 +0,1.504600,0.0,0.0,0.0,0.0,0.0 +0,1.504700,0.0,0.0,0.0,0.0,0.0 +0,1.504800,0.0,0.0,0.0,0.0,0.0 +0,1.504900,0.0,0.0,0.0,0.0,0.0 +0,1.505000,0.0,0.0,0.0,0.0,0.0 +0,1.505100,0.0,0.0,0.0,0.0,0.0 +0,1.505200,0.0,0.0,0.0,0.0,0.0 +0,1.505300,0.0,0.0,0.0,0.0,0.0 +0,1.505400,0.0,0.0,0.0,0.0,0.0 +0,1.505500,0.0,0.0,0.0,0.0,0.0 +0,1.505600,0.0,0.0,0.0,0.0,0.0 +0,1.505700,0.0,0.0,0.0,0.0,0.0 +0,1.505800,0.0,0.0,0.0,0.0,0.0 +0,1.505900,0.0,0.0,0.0,0.0,0.0 +0,1.506000,0.0,0.0,0.0,0.0,0.0 +0,1.506100,0.0,0.0,0.0,0.0,0.0 +0,1.506200,0.0,0.0,0.0,0.0,0.0 +0,1.506300,0.0,0.0,0.0,0.0,0.0 +0,1.506400,0.0,0.0,0.0,0.0,0.0 +0,1.506500,0.0,0.0,0.0,0.0,0.0 +0,1.506600,0.0,0.0,0.0,0.0,0.0 +0,1.506700,0.0,0.0,0.0,0.0,0.0 +0,1.506800,0.0,0.0,0.0,0.0,0.0 +0,1.506900,0.0,0.0,0.0,0.0,0.0 +0,1.507000,0.0,0.0,0.0,0.0,0.0 +0,1.507100,0.0,0.0,0.0,0.0,0.0 +0,1.507200,0.0,0.0,0.0,0.0,0.0 +0,1.507300,0.0,0.0,0.0,0.0,0.0 +0,1.507400,0.0,0.0,0.0,0.0,0.0 +0,1.507500,0.0,0.0,0.0,0.0,0.0 +0,1.507600,0.0,0.0,0.0,0.0,0.0 +0,1.507700,0.0,0.0,0.0,0.0,0.0 +0,1.507800,0.0,0.0,0.0,0.0,0.0 +0,1.507900,0.0,0.0,0.0,0.0,0.0 +0,1.508000,0.0,0.0,0.0,0.0,0.0 +0,1.508100,0.0,0.0,0.0,0.0,0.0 +0,1.508200,0.0,0.0,0.0,0.0,0.0 +0,1.508300,0.0,0.0,0.0,0.0,0.0 +0,1.508400,0.0,0.0,0.0,0.0,0.0 +0,1.508500,0.0,0.0,0.0,0.0,0.0 +0,1.508600,0.0,0.0,0.0,0.0,0.0 +0,1.508700,0.0,0.0,0.0,0.0,0.0 +0,1.508800,0.0,0.0,0.0,0.0,0.0 +0,1.508900,0.0,0.0,0.0,0.0,0.0 +0,1.509000,0.0,0.0,0.0,0.0,0.0 +0,1.509100,0.0,0.0,0.0,0.0,0.0 +0,1.509200,0.0,0.0,0.0,0.0,0.0 +0,1.509300,0.0,0.0,0.0,0.0,0.0 +0,1.509400,0.0,0.0,0.0,0.0,0.0 +0,1.509500,0.0,0.0,0.0,0.0,0.0 +0,1.509600,0.0,0.0,0.0,0.0,0.0 +0,1.509700,0.0,0.0,0.0,0.0,0.0 +0,1.509800,0.0,0.0,0.0,0.0,0.0 +0,1.509900,0.0,0.0,0.0,0.0,0.0 +0,1.510000,0.0,0.0,0.0,0.0,0.0 +0,1.510100,0.0,0.0,0.0,0.0,0.0 +0,1.510200,0.0,0.0,0.0,0.0,0.0 +0,1.510300,0.0,0.0,0.0,0.0,0.0 +0,1.510400,0.0,0.0,0.0,0.0,0.0 +0,1.510500,0.0,0.0,0.0,0.0,0.0 +0,1.510600,0.0,0.0,0.0,0.0,0.0 +0,1.510700,0.0,0.0,0.0,0.0,0.0 +0,1.510800,0.0,0.0,0.0,0.0,0.0 +0,1.510900,0.0,0.0,0.0,0.0,0.0 +0,1.511000,0.0,0.0,0.0,0.0,0.0 +0,1.511100,0.0,0.0,0.0,0.0,0.0 +0,1.511200,0.0,0.0,0.0,0.0,0.0 +0,1.511300,0.0,0.0,0.0,0.0,0.0 +0,1.511400,0.0,0.0,0.0,0.0,0.0 +0,1.511500,0.0,0.0,0.0,0.0,0.0 +0,1.511600,0.0,0.0,0.0,0.0,0.0 +0,1.511700,0.0,0.0,0.0,0.0,0.0 +0,1.511800,0.0,0.0,0.0,0.0,0.0 +0,1.511900,0.0,0.0,0.0,0.0,0.0 +0,1.512000,0.0,0.0,0.0,0.0,0.0 +0,1.512100,0.0,0.0,0.0,0.0,0.0 +0,1.512200,0.0,0.0,0.0,0.0,0.0 +0,1.512300,0.0,0.0,0.0,0.0,0.0 +0,1.512400,0.0,0.0,0.0,0.0,0.0 +0,1.512500,0.0,0.0,0.0,0.0,0.0 +0,1.512600,0.0,0.0,0.0,0.0,0.0 +0,1.512700,0.0,0.0,0.0,0.0,0.0 +0,1.512800,0.0,0.0,0.0,0.0,0.0 +0,1.512900,0.0,0.0,0.0,0.0,0.0 +0,1.513000,0.0,0.0,0.0,0.0,0.0 +0,1.513100,0.0,0.0,0.0,0.0,0.0 +0,1.513200,0.0,0.0,0.0,0.0,0.0 +0,1.513300,0.0,0.0,0.0,0.0,0.0 +0,1.513400,0.0,0.0,0.0,0.0,0.0 +0,1.513500,0.0,0.0,0.0,0.0,0.0 +0,1.513600,0.0,0.0,0.0,0.0,0.0 +0,1.513700,0.0,0.0,0.0,0.0,0.0 +0,1.513800,0.0,0.0,0.0,0.0,0.0 +0,1.513900,0.0,0.0,0.0,0.0,0.0 +0,1.514000,0.0,0.0,0.0,0.0,0.0 +0,1.514100,0.0,0.0,0.0,0.0,0.0 +0,1.514200,0.0,0.0,0.0,0.0,0.0 +0,1.514300,0.0,0.0,0.0,0.0,0.0 +0,1.514400,0.0,0.0,0.0,0.0,0.0 +0,1.514500,0.0,0.0,0.0,0.0,0.0 +0,1.514600,0.0,0.0,0.0,0.0,0.0 +0,1.514700,0.0,0.0,0.0,0.0,0.0 +0,1.514800,0.0,0.0,0.0,0.0,0.0 +0,1.514900,0.0,0.0,0.0,0.0,0.0 +0,1.515000,0.0,0.0,0.0,0.0,0.0 +0,1.515100,0.0,0.0,0.0,0.0,0.0 +0,1.515200,0.0,0.0,0.0,0.0,0.0 +0,1.515300,0.0,0.0,0.0,0.0,0.0 +0,1.515400,0.0,0.0,0.0,0.0,0.0 +0,1.515500,0.0,0.0,0.0,0.0,0.0 +0,1.515600,0.0,0.0,0.0,0.0,0.0 +0,1.515700,0.0,0.0,0.0,0.0,0.0 +0,1.515800,0.0,0.0,0.0,0.0,0.0 +0,1.515900,0.0,0.0,0.0,0.0,0.0 +0,1.516000,0.0,0.0,0.0,0.0,0.0 +0,1.516100,0.0,0.0,0.0,0.0,0.0 +0,1.516200,0.0,0.0,0.0,0.0,0.0 +0,1.516300,0.0,0.0,0.0,0.0,0.0 +0,1.516400,0.0,0.0,0.0,0.0,0.0 +0,1.516500,0.0,0.0,0.0,0.0,0.0 +0,1.516600,0.0,0.0,0.0,0.0,0.0 +0,1.516700,0.0,0.0,0.0,0.0,0.0 +0,1.516800,0.0,0.0,0.0,0.0,0.0 +0,1.516900,0.0,0.0,0.0,0.0,0.0 +0,1.517000,0.0,0.0,0.0,0.0,0.0 +0,1.517100,0.0,0.0,0.0,0.0,0.0 +0,1.517200,0.0,0.0,0.0,0.0,0.0 +0,1.517300,0.0,0.0,0.0,0.0,0.0 +0,1.517400,0.0,0.0,0.0,0.0,0.0 +0,1.517500,0.0,0.0,0.0,0.0,0.0 +0,1.517600,0.0,0.0,0.0,0.0,0.0 +0,1.517700,0.0,0.0,0.0,0.0,0.0 +0,1.517800,0.0,0.0,0.0,0.0,0.0 +0,1.517900,0.0,0.0,0.0,0.0,0.0 +0,1.518000,0.0,0.0,0.0,0.0,0.0 +0,1.518100,0.0,0.0,0.0,0.0,0.0 +0,1.518200,0.0,0.0,0.0,0.0,0.0 +0,1.518300,0.0,0.0,0.0,0.0,0.0 +0,1.518400,0.0,0.0,0.0,0.0,0.0 +0,1.518500,0.0,0.0,0.0,0.0,0.0 +0,1.518600,0.0,0.0,0.0,0.0,0.0 +0,1.518700,0.0,0.0,0.0,0.0,0.0 +0,1.518800,0.0,0.0,0.0,0.0,0.0 +0,1.518900,0.0,0.0,0.0,0.0,0.0 +0,1.519000,0.0,0.0,0.0,0.0,0.0 +0,1.519100,0.0,0.0,0.0,0.0,0.0 +0,1.519200,0.0,0.0,0.0,0.0,0.0 +0,1.519300,0.0,0.0,0.0,0.0,0.0 +0,1.519400,0.0,0.0,0.0,0.0,0.0 +0,1.519500,0.0,0.0,0.0,0.0,0.0 +0,1.519600,0.0,0.0,0.0,0.0,0.0 +0,1.519700,0.0,0.0,0.0,0.0,0.0 +0,1.519800,0.0,0.0,0.0,0.0,0.0 +0,1.519900,0.0,0.0,0.0,0.0,0.0 +0,1.520000,0.0,0.0,0.0,0.0,0.0 +0,1.520100,0.0,0.0,0.0,0.0,0.0 +1,1463.686575,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.520200,0.0,0.0,0.0,0.0,0.0 +0,1.520300,0.0,0.0,0.0,0.0,0.0 +0,1.520400,0.0,0.0,0.0,0.0,0.0 +0,1.520500,0.0,0.0,0.0,0.0,0.0 +0,1.520600,0.0,0.0,0.0,0.0,0.0 +0,1.520700,0.0,0.0,0.0,0.0,0.0 +0,1.520800,0.0,0.0,0.0,0.0,0.0 +0,1.520900,0.0,0.0,0.0,0.0,0.0 +0,1.521000,0.0,0.0,0.0,0.0,0.0 +0,1.521100,0.0,0.0,0.0,0.0,0.0 +0,1.521200,0.0,0.0,0.0,0.0,0.0 +0,1.521300,0.0,0.0,0.0,0.0,0.0 +0,1.521400,0.0,0.0,0.0,0.0,0.0 +0,1.521500,0.0,0.0,0.0,0.0,0.0 +0,1.521600,0.0,0.0,0.0,0.0,0.0 +0,1.521700,0.0,0.0,0.0,0.0,0.0 +0,1.521800,0.0,0.0,0.0,0.0,0.0 +0,1.521900,0.0,0.0,0.0,0.0,0.0 +0,1.522000,0.0,0.0,0.0,0.0,0.0 +0,1.522100,0.0,0.0,0.0,0.0,0.0 +0,1.522200,0.0,0.0,0.0,0.0,0.0 +0,1.522300,0.0,0.0,0.0,0.0,0.0 +0,1.522400,0.0,0.0,0.0,0.0,0.0 +0,1.522500,0.0,0.0,0.0,0.0,0.0 +0,1.522600,0.0,0.0,0.0,0.0,0.0 +0,1.522700,0.0,0.0,0.0,0.0,0.0 +0,1.522800,0.0,0.0,0.0,0.0,0.0 +0,1.522900,0.0,0.0,0.0,0.0,0.0 +0,1.523000,0.0,0.0,0.0,0.0,0.0 +0,1.523100,0.0,0.0,0.0,0.0,0.0 +0,1.523200,0.0,0.0,0.0,0.0,0.0 +0,1.523300,0.0,0.0,0.0,0.0,0.0 +0,1.523400,0.0,0.0,0.0,0.0,0.0 +0,1.523500,0.0,0.0,0.0,0.0,0.0 +0,1.523600,0.0,0.0,0.0,0.0,0.0 +0,1.523700,0.0,0.0,0.0,0.0,0.0 +0,1.523800,0.0,0.0,0.0,0.0,0.0 +0,1.523900,0.0,0.0,0.0,0.0,0.0 +0,1.524000,0.0,0.0,0.0,0.0,0.0 +0,1.524100,0.0,0.0,0.0,0.0,0.0 +0,1.524200,0.0,0.0,0.0,0.0,0.0 +0,1.524300,0.0,0.0,0.0,0.0,0.0 +0,1.524400,0.0,0.0,0.0,0.0,0.0 +0,1.524500,0.0,0.0,0.0,0.0,0.0 +0,1.524600,0.0,0.0,0.0,0.0,0.0 +0,1.524700,0.0,0.0,0.0,0.0,0.0 +0,1.524800,0.0,0.0,0.0,0.0,0.0 +0,1.524900,0.0,0.0,0.0,0.0,0.0 +0,1.525000,0.0,0.0,0.0,0.0,0.0 +0,1.525100,0.0,0.0,0.0,0.0,0.0 +0,1.525200,0.0,0.0,0.0,0.0,0.0 +0,1.525300,0.0,0.0,0.0,0.0,0.0 +0,1.525400,0.0,0.0,0.0,0.0,0.0 +0,1.525500,0.0,0.0,0.0,0.0,0.0 +0,1.525600,0.0,0.0,0.0,0.0,0.0 +0,1.525700,0.0,0.0,0.0,0.0,0.0 +0,1.525800,0.0,0.0,0.0,0.0,0.0 +0,1.525900,0.0,0.0,0.0,0.0,0.0 +0,1.526000,0.0,0.0,0.0,0.0,0.0 +0,1.526100,0.0,0.0,0.0,0.0,0.0 +0,1.526200,0.0,0.0,0.0,0.0,0.0 +0,1.526300,0.0,0.0,0.0,0.0,0.0 +0,1.526400,0.0,0.0,0.0,0.0,0.0 +0,1.526500,0.0,0.0,0.0,0.0,0.0 +0,1.526600,0.0,0.0,0.0,0.0,0.0 +0,1.526700,0.0,0.0,0.0,0.0,0.0 +0,1.526800,0.0,0.0,0.0,0.0,0.0 +0,1.526900,0.0,0.0,0.0,0.0,0.0 +0,1.527000,0.0,0.0,0.0,0.0,0.0 +0,1.527100,0.0,0.0,0.0,0.0,0.0 +0,1.527200,0.0,0.0,0.0,0.0,0.0 +0,1.527300,0.0,0.0,0.0,0.0,0.0 +0,1.527400,0.0,0.0,0.0,0.0,0.0 +0,1.527500,0.0,0.0,0.0,0.0,0.0 +0,1.527600,0.0,0.0,0.0,0.0,0.0 +0,1.527700,0.0,0.0,0.0,0.0,0.0 +0,1.527800,0.0,0.0,0.0,0.0,0.0 +0,1.527900,0.0,0.0,0.0,0.0,0.0 +0,1.528000,0.0,0.0,0.0,0.0,0.0 +0,1.528100,0.0,0.0,0.0,0.0,0.0 +0,1.528200,0.0,0.0,0.0,0.0,0.0 +0,1.528300,0.0,0.0,0.0,0.0,0.0 +0,1.528400,0.0,0.0,0.0,0.0,0.0 +0,1.528500,0.0,0.0,0.0,0.0,0.0 +0,1.528600,0.0,0.0,0.0,0.0,0.0 +0,1.528700,0.0,0.0,0.0,0.0,0.0 +0,1.528800,0.0,0.0,0.0,0.0,0.0 +0,1.528900,0.0,0.0,0.0,0.0,0.0 +0,1.529000,0.0,0.0,0.0,0.0,0.0 +0,1.529100,0.0,0.0,0.0,0.0,0.0 +0,1.529200,0.0,0.0,0.0,0.0,0.0 +0,1.529300,0.0,0.0,0.0,0.0,0.0 +0,1.529400,0.0,0.0,0.0,0.0,0.0 +0,1.529500,0.0,0.0,0.0,0.0,0.0 +0,1.529600,0.0,0.0,0.0,0.0,0.0 +0,1.529700,0.0,0.0,0.0,0.0,0.0 +0,1.529800,0.0,0.0,0.0,0.0,0.0 +0,1.529900,0.0,0.0,0.0,0.0,0.0 +0,1.530000,0.0,0.0,0.0,0.0,0.0 +0,1.530100,0.0,0.0,0.0,0.0,0.0 +0,1.530200,0.0,0.0,0.0,0.0,0.0 +0,1.530300,0.0,0.0,0.0,0.0,0.0 +0,1.530400,0.0,0.0,0.0,0.0,0.0 +0,1.530500,0.0,0.0,0.0,0.0,0.0 +0,1.530600,0.0,0.0,0.0,0.0,0.0 +0,1.530700,0.0,0.0,0.0,0.0,0.0 +0,1.530800,0.0,0.0,0.0,0.0,0.0 +0,1.530900,0.0,0.0,0.0,0.0,0.0 +0,1.531000,0.0,0.0,0.0,0.0,0.0 +0,1.531100,0.0,0.0,0.0,0.0,0.0 +0,1.531200,0.0,0.0,0.0,0.0,0.0 +0,1.531300,0.0,0.0,0.0,0.0,0.0 +0,1.531400,0.0,0.0,0.0,0.0,0.0 +0,1.531500,0.0,0.0,0.0,0.0,0.0 +0,1.531600,0.0,0.0,0.0,0.0,0.0 +0,1.531700,0.0,0.0,0.0,0.0,0.0 +0,1.531800,0.0,0.0,0.0,0.0,0.0 +0,1.531900,0.0,0.0,0.0,0.0,0.0 +0,1.532000,0.0,0.0,0.0,0.0,0.0 +0,1.532100,0.0,0.0,0.0,0.0,0.0 +0,1.532200,0.0,0.0,0.0,0.0,0.0 +0,1.532300,0.0,0.0,0.0,0.0,0.0 +0,1.532400,0.0,0.0,0.0,0.0,0.0 +0,1.532500,0.0,0.0,0.0,0.0,0.0 +0,1.532600,0.0,0.0,0.0,0.0,0.0 +0,1.532700,0.0,0.0,0.0,0.0,0.0 +0,1.532800,0.0,0.0,0.0,0.0,0.0 +0,1.532900,0.0,0.0,0.0,0.0,0.0 +0,1.533000,0.0,0.0,0.0,0.0,0.0 +0,1.533100,0.0,0.0,0.0,0.0,0.0 +0,1.533200,0.0,0.0,0.0,0.0,0.0 +0,1.533300,0.0,0.0,0.0,0.0,0.0 +0,1.533400,0.0,0.0,0.0,0.0,0.0 +0,1.533500,0.0,0.0,0.0,0.0,0.0 +0,1.533600,0.0,0.0,0.0,0.0,0.0 +0,1.533700,0.0,0.0,0.0,0.0,0.0 +0,1.533800,0.0,0.0,0.0,0.0,0.0 +0,1.533900,0.0,0.0,0.0,0.0,0.0 +0,1.534000,0.0,0.0,0.0,0.0,0.0 +0,1.534100,0.0,0.0,0.0,0.0,0.0 +0,1.534200,0.0,0.0,0.0,0.0,0.0 +0,1.534300,0.0,0.0,0.0,0.0,0.0 +0,1.534400,0.0,0.0,0.0,0.0,0.0 +0,1.534500,0.0,0.0,0.0,0.0,0.0 +0,1.534600,0.0,0.0,0.0,0.0,0.0 +0,1.534700,0.0,0.0,0.0,0.0,0.0 +0,1.534800,0.0,0.0,0.0,0.0,0.0 +0,1.534900,0.0,0.0,0.0,0.0,0.0 +0,1.535000,0.0,0.0,0.0,0.0,0.0 +0,1.535100,0.0,0.0,0.0,0.0,0.0 +0,1.535200,0.0,0.0,0.0,0.0,0.0 +0,1.535300,0.0,0.0,0.0,0.0,0.0 +0,1.535400,0.0,0.0,0.0,0.0,0.0 +0,1.535500,0.0,0.0,0.0,0.0,0.0 +0,1.535600,0.0,0.0,0.0,0.0,0.0 +0,1.535700,0.0,0.0,0.0,0.0,0.0 +0,1.535800,0.0,0.0,0.0,0.0,0.0 +0,1.535900,0.0,0.0,0.0,0.0,0.0 +0,1.536000,0.0,0.0,0.0,0.0,0.0 +0,1.536100,0.0,0.0,0.0,0.0,0.0 +0,1.536200,0.0,0.0,0.0,0.0,0.0 +0,1.536300,0.0,0.0,0.0,0.0,0.0 +0,1.536400,0.0,0.0,0.0,0.0,0.0 +0,1.536500,0.0,0.0,0.0,0.0,0.0 +0,1.536600,0.0,0.0,0.0,0.0,0.0 +0,1.536700,0.0,0.0,0.0,0.0,0.0 +0,1.536800,0.0,0.0,0.0,0.0,0.0 +0,1.536900,0.0,0.0,0.0,0.0,0.0 +0,1.537000,0.0,0.0,0.0,0.0,0.0 +0,1.537100,0.0,0.0,0.0,0.0,0.0 +0,1.537200,0.0,0.0,0.0,0.0,0.0 +0,1.537300,0.0,0.0,0.0,0.0,0.0 +0,1.537400,0.0,0.0,0.0,0.0,0.0 +0,1.537500,0.0,0.0,0.0,0.0,0.0 +0,1.537600,0.0,0.0,0.0,0.0,0.0 +0,1.537700,0.0,0.0,0.0,0.0,0.0 +0,1.537800,0.0,0.0,0.0,0.0,0.0 +0,1.537900,0.0,0.0,0.0,0.0,0.0 +0,1.538000,0.0,0.0,0.0,0.0,0.0 +0,1.538100,0.0,0.0,0.0,0.0,0.0 +0,1.538200,0.0,0.0,0.0,0.0,0.0 +0,1.538300,0.0,0.0,0.0,0.0,0.0 +0,1.538400,0.0,0.0,0.0,0.0,0.0 +0,1.538500,0.0,0.0,0.0,0.0,0.0 +0,1.538600,0.0,0.0,0.0,0.0,0.0 +0,1.538700,0.0,0.0,0.0,0.0,0.0 +0,1.538800,0.0,0.0,0.0,0.0,0.0 +0,1.538900,0.0,0.0,0.0,0.0,0.0 +0,1.539000,0.0,0.0,0.0,0.0,0.0 +0,1.539100,0.0,0.0,0.0,0.0,0.0 +0,1.539200,0.0,0.0,0.0,0.0,0.0 +0,1.539300,0.0,0.0,0.0,0.0,0.0 +0,1.539400,0.0,0.0,0.0,0.0,0.0 +0,1.539500,0.0,0.0,0.0,0.0,0.0 +0,1.539600,0.0,0.0,0.0,0.0,0.0 +0,1.539700,0.0,0.0,0.0,0.0,0.0 +0,1.539800,0.0,0.0,0.0,0.0,0.0 +0,1.539900,0.0,0.0,0.0,0.0,0.0 +0,1.540000,0.0,0.0,0.0,0.0,0.0 +0,1.540100,0.0,0.0,0.0,0.0,0.0 +1,1522.221383,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.540200,0.0,0.0,0.0,0.0,0.0 +0,1.540300,0.0,0.0,0.0,0.0,0.0 +0,1.540400,0.0,0.0,0.0,0.0,0.0 +0,1.540500,0.0,0.0,0.0,0.0,0.0 +0,1.540600,0.0,0.0,0.0,0.0,0.0 +0,1.540700,0.0,0.0,0.0,0.0,0.0 +0,1.540800,0.0,0.0,0.0,0.0,0.0 +0,1.540900,0.0,0.0,0.0,0.0,0.0 +0,1.541000,0.0,0.0,0.0,0.0,0.0 +0,1.541100,0.0,0.0,0.0,0.0,0.0 +0,1.541200,0.0,0.0,0.0,0.0,0.0 +0,1.541300,0.0,0.0,0.0,0.0,0.0 +0,1.541400,0.0,0.0,0.0,0.0,0.0 +0,1.541500,0.0,0.0,0.0,0.0,0.0 +0,1.541600,0.0,0.0,0.0,0.0,0.0 +0,1.541700,0.0,0.0,0.0,0.0,0.0 +0,1.541800,0.0,0.0,0.0,0.0,0.0 +0,1.541900,0.0,0.0,0.0,0.0,0.0 +0,1.542000,0.0,0.0,0.0,0.0,0.0 +0,1.542100,0.0,0.0,0.0,0.0,0.0 +0,1.542200,0.0,0.0,0.0,0.0,0.0 +0,1.542300,0.0,0.0,0.0,0.0,0.0 +0,1.542400,0.0,0.0,0.0,0.0,0.0 +0,1.542500,0.0,0.0,0.0,0.0,0.0 +0,1.542600,0.0,0.0,0.0,0.0,0.0 +0,1.542700,0.0,0.0,0.0,0.0,0.0 +0,1.542800,0.0,0.0,0.0,0.0,0.0 +0,1.542900,0.0,0.0,0.0,0.0,0.0 +0,1.543000,0.0,0.0,0.0,0.0,0.0 +0,1.543100,0.0,0.0,0.0,0.0,0.0 +0,1.543200,0.0,0.0,0.0,0.0,0.0 +0,1.543300,0.0,0.0,0.0,0.0,0.0 +0,1.543400,0.0,0.0,0.0,0.0,0.0 +0,1.543500,0.0,0.0,0.0,0.0,0.0 +0,1.543600,0.0,0.0,0.0,0.0,0.0 +0,1.543700,0.0,0.0,0.0,0.0,0.0 +0,1.543800,0.0,0.0,0.0,0.0,0.0 +0,1.543900,0.0,0.0,0.0,0.0,0.0 +0,1.544000,0.0,0.0,0.0,0.0,0.0 +0,1.544100,0.0,0.0,0.0,0.0,0.0 +0,1.544200,0.0,0.0,0.0,0.0,0.0 +0,1.544300,0.0,0.0,0.0,0.0,0.0 +0,1.544400,0.0,0.0,0.0,0.0,0.0 +0,1.544500,0.0,0.0,0.0,0.0,0.0 +0,1.544600,0.0,0.0,0.0,0.0,0.0 +0,1.544700,0.0,0.0,0.0,0.0,0.0 +0,1.544800,0.0,0.0,0.0,0.0,0.0 +0,1.544900,0.0,0.0,0.0,0.0,0.0 +0,1.545000,0.0,0.0,0.0,0.0,0.0 +0,1.545100,0.0,0.0,0.0,0.0,0.0 +0,1.545200,0.0,0.0,0.0,0.0,0.0 +0,1.545300,0.0,0.0,0.0,0.0,0.0 +0,1.545400,0.0,0.0,0.0,0.0,0.0 +0,1.545500,0.0,0.0,0.0,0.0,0.0 +0,1.545600,0.0,0.0,0.0,0.0,0.0 +0,1.545700,0.0,0.0,0.0,0.0,0.0 +0,1.545800,0.0,0.0,0.0,0.0,0.0 +0,1.545900,0.0,0.0,0.0,0.0,0.0 +0,1.546000,0.0,0.0,0.0,0.0,0.0 +0,1.546100,0.0,0.0,0.0,0.0,0.0 +0,1.546200,0.0,0.0,0.0,0.0,0.0 +0,1.546300,0.0,0.0,0.0,0.0,0.0 +0,1.546400,0.0,0.0,0.0,0.0,0.0 +0,1.546500,0.0,0.0,0.0,0.0,0.0 +0,1.546600,0.0,0.0,0.0,0.0,0.0 +0,1.546700,0.0,0.0,0.0,0.0,0.0 +0,1.546800,0.0,0.0,0.0,0.0,0.0 +0,1.546900,0.0,0.0,0.0,0.0,0.0 +0,1.547000,0.0,0.0,0.0,0.0,0.0 +0,1.547100,0.0,0.0,0.0,0.0,0.0 +0,1.547200,0.0,0.0,0.0,0.0,0.0 +0,1.547300,0.0,0.0,0.0,0.0,0.0 +0,1.547400,0.0,0.0,0.0,0.0,0.0 +0,1.547500,0.0,0.0,0.0,0.0,0.0 +0,1.547600,0.0,0.0,0.0,0.0,0.0 +0,1.547700,0.0,0.0,0.0,0.0,0.0 +0,1.547800,0.0,0.0,0.0,0.0,0.0 +0,1.547900,0.0,0.0,0.0,0.0,0.0 +0,1.548000,0.0,0.0,0.0,0.0,0.0 +0,1.548100,0.0,0.0,0.0,0.0,0.0 +0,1.548200,0.0,0.0,0.0,0.0,0.0 +0,1.548300,0.0,0.0,0.0,0.0,0.0 +0,1.548400,0.0,0.0,0.0,0.0,0.0 +0,1.548500,0.0,0.0,0.0,0.0,0.0 +0,1.548600,0.0,0.0,0.0,0.0,0.0 +0,1.548700,0.0,0.0,0.0,0.0,0.0 +0,1.548800,0.0,0.0,0.0,0.0,0.0 +0,1.548900,0.0,0.0,0.0,0.0,0.0 +0,1.549000,0.0,0.0,0.0,0.0,0.0 +0,1.549100,0.0,0.0,0.0,0.0,0.0 +0,1.549200,0.0,0.0,0.0,0.0,0.0 +0,1.549300,0.0,0.0,0.0,0.0,0.0 +0,1.549400,0.0,0.0,0.0,0.0,0.0 +0,1.549500,0.0,0.0,0.0,0.0,0.0 +0,1.549600,0.0,0.0,0.0,0.0,0.0 +0,1.549700,0.0,0.0,0.0,0.0,0.0 +0,1.549800,0.0,0.0,0.0,0.0,0.0 +0,1.549900,0.0,0.0,0.0,0.0,0.0 +0,1.550000,0.0,0.0,0.0,0.0,0.0 +0,1.550100,0.0,0.0,0.0,0.0,0.0 +0,1.550200,0.0,0.0,0.0,0.0,0.0 +0,1.550300,0.0,0.0,0.0,0.0,0.0 +0,1.550400,0.0,0.0,0.0,0.0,0.0 +0,1.550500,0.0,0.0,0.0,0.0,0.0 +0,1.550600,0.0,0.0,0.0,0.0,0.0 +0,1.550700,0.0,0.0,0.0,0.0,0.0 +0,1.550800,0.0,0.0,0.0,0.0,0.0 +0,1.550900,0.0,0.0,0.0,0.0,0.0 +0,1.551000,0.0,0.0,0.0,0.0,0.0 +0,1.551100,0.0,0.0,0.0,0.0,0.0 +0,1.551200,0.0,0.0,0.0,0.0,0.0 +0,1.551300,0.0,0.0,0.0,0.0,0.0 +0,1.551400,0.0,0.0,0.0,0.0,0.0 +0,1.551500,0.0,0.0,0.0,0.0,0.0 +0,1.551600,0.0,0.0,0.0,0.0,0.0 +0,1.551700,0.0,0.0,0.0,0.0,0.0 +0,1.551800,0.0,0.0,0.0,0.0,0.0 +0,1.551900,0.0,0.0,0.0,0.0,0.0 +0,1.552000,0.0,0.0,0.0,0.0,0.0 +0,1.552100,0.0,0.0,0.0,0.0,0.0 +0,1.552200,0.0,0.0,0.0,0.0,0.0 +0,1.552300,0.0,0.0,0.0,0.0,0.0 +0,1.552400,0.0,0.0,0.0,0.0,0.0 +0,1.552500,0.0,0.0,0.0,0.0,0.0 +0,1.552600,0.0,0.0,0.0,0.0,0.0 +0,1.552700,0.0,0.0,0.0,0.0,0.0 +0,1.552800,0.0,0.0,0.0,0.0,0.0 +0,1.552900,0.0,0.0,0.0,0.0,0.0 +0,1.553000,0.0,0.0,0.0,0.0,0.0 +0,1.553100,0.0,0.0,0.0,0.0,0.0 +0,1.553200,0.0,0.0,0.0,0.0,0.0 +0,1.553300,0.0,0.0,0.0,0.0,0.0 +0,1.553400,0.0,0.0,0.0,0.0,0.0 +0,1.553500,0.0,0.0,0.0,0.0,0.0 +0,1.553600,0.0,0.0,0.0,0.0,0.0 +0,1.553700,0.0,0.0,0.0,0.0,0.0 +0,1.553800,0.0,0.0,0.0,0.0,0.0 +0,1.553900,0.0,0.0,0.0,0.0,0.0 +0,1.554000,0.0,0.0,0.0,0.0,0.0 +0,1.554100,0.0,0.0,0.0,0.0,0.0 +0,1.554200,0.0,0.0,0.0,0.0,0.0 +0,1.554300,0.0,0.0,0.0,0.0,0.0 +0,1.554400,0.0,0.0,0.0,0.0,0.0 +0,1.554500,0.0,0.0,0.0,0.0,0.0 +0,1.554600,0.0,0.0,0.0,0.0,0.0 +0,1.554700,0.0,0.0,0.0,0.0,0.0 +0,1.554800,0.0,0.0,0.0,0.0,0.0 +0,1.554900,0.0,0.0,0.0,0.0,0.0 +0,1.555000,0.0,0.0,0.0,0.0,0.0 +0,1.555100,0.0,0.0,0.0,0.0,0.0 +0,1.555200,0.0,0.0,0.0,0.0,0.0 +0,1.555300,0.0,0.0,0.0,0.0,0.0 +0,1.555400,0.0,0.0,0.0,0.0,0.0 +0,1.555500,0.0,0.0,0.0,0.0,0.0 +0,1.555600,0.0,0.0,0.0,0.0,0.0 +0,1.555700,0.0,0.0,0.0,0.0,0.0 +0,1.555800,0.0,0.0,0.0,0.0,0.0 +0,1.555900,0.0,0.0,0.0,0.0,0.0 +0,1.556000,0.0,0.0,0.0,0.0,0.0 +0,1.556100,0.0,0.0,0.0,0.0,0.0 +0,1.556200,0.0,0.0,0.0,0.0,0.0 +0,1.556300,0.0,0.0,0.0,0.0,0.0 +0,1.556400,0.0,0.0,0.0,0.0,0.0 +0,1.556500,0.0,0.0,0.0,0.0,0.0 +0,1.556600,0.0,0.0,0.0,0.0,0.0 +0,1.556700,0.0,0.0,0.0,0.0,0.0 +0,1.556800,0.0,0.0,0.0,0.0,0.0 +0,1.556900,0.0,0.0,0.0,0.0,0.0 +0,1.557000,0.0,0.0,0.0,0.0,0.0 +0,1.557100,0.0,0.0,0.0,0.0,0.0 +0,1.557200,0.0,0.0,0.0,0.0,0.0 +0,1.557300,0.0,0.0,0.0,0.0,0.0 +0,1.557400,0.0,0.0,0.0,0.0,0.0 +0,1.557500,0.0,0.0,0.0,0.0,0.0 +0,1.557600,0.0,0.0,0.0,0.0,0.0 +0,1.557700,0.0,0.0,0.0,0.0,0.0 +0,1.557800,0.0,0.0,0.0,0.0,0.0 +0,1.557900,0.0,0.0,0.0,0.0,0.0 +0,1.558000,0.0,0.0,0.0,0.0,0.0 +0,1.558100,0.0,0.0,0.0,0.0,0.0 +0,1.558200,0.0,0.0,0.0,0.0,0.0 +0,1.558300,0.0,0.0,0.0,0.0,0.0 +0,1.558400,0.0,0.0,0.0,0.0,0.0 +0,1.558500,0.0,0.0,0.0,0.0,0.0 +0,1.558600,0.0,0.0,0.0,0.0,0.0 +0,1.558700,0.0,0.0,0.0,0.0,0.0 +0,1.558800,0.0,0.0,0.0,0.0,0.0 +0,1.558900,0.0,0.0,0.0,0.0,0.0 +0,1.559000,0.0,0.0,0.0,0.0,0.0 +0,1.559100,0.0,0.0,0.0,0.0,0.0 +0,1.559200,0.0,0.0,0.0,0.0,0.0 +0,1.559300,0.0,0.0,0.0,0.0,0.0 +0,1.559400,0.0,0.0,0.0,0.0,0.0 +0,1.559500,0.0,0.0,0.0,0.0,0.0 +0,1.559600,0.0,0.0,0.0,0.0,0.0 +0,1.559700,0.0,0.0,0.0,0.0,0.0 +0,1.559800,0.0,0.0,0.0,0.0,0.0 +0,1.559900,0.0,0.0,0.0,0.0,0.0 +0,1.560000,0.0,0.0,0.0,0.0,0.0 +0,1.560100,0.0,0.0,0.0,0.0,0.0 +1,1582.296342,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.560200,0.0,0.0,0.0,0.0,0.0 +0,1.560300,0.0,0.0,0.0,0.0,0.0 +0,1.560400,0.0,0.0,0.0,0.0,0.0 +0,1.560500,0.0,0.0,0.0,0.0,0.0 +0,1.560600,0.0,0.0,0.0,0.0,0.0 +0,1.560700,0.0,0.0,0.0,0.0,0.0 +0,1.560800,0.0,0.0,0.0,0.0,0.0 +0,1.560900,0.0,0.0,0.0,0.0,0.0 +0,1.561000,0.0,0.0,0.0,0.0,0.0 +0,1.561100,0.0,0.0,0.0,0.0,0.0 +0,1.561200,0.0,0.0,0.0,0.0,0.0 +0,1.561300,0.0,0.0,0.0,0.0,0.0 +0,1.561400,0.0,0.0,0.0,0.0,0.0 +0,1.561500,0.0,0.0,0.0,0.0,0.0 +0,1.561600,0.0,0.0,0.0,0.0,0.0 +0,1.561700,0.0,0.0,0.0,0.0,0.0 +0,1.561800,0.0,0.0,0.0,0.0,0.0 +0,1.561900,0.0,0.0,0.0,0.0,0.0 +0,1.562000,0.0,0.0,0.0,0.0,0.0 +0,1.562100,0.0,0.0,0.0,0.0,0.0 +0,1.562200,0.0,0.0,0.0,0.0,0.0 +0,1.562300,0.0,0.0,0.0,0.0,0.0 +0,1.562400,0.0,0.0,0.0,0.0,0.0 +0,1.562500,0.0,0.0,0.0,0.0,0.0 +0,1.562600,0.0,0.0,0.0,0.0,0.0 +0,1.562700,0.0,0.0,0.0,0.0,0.0 +0,1.562800,0.0,0.0,0.0,0.0,0.0 +0,1.562900,0.0,0.0,0.0,0.0,0.0 +0,1.563000,0.0,0.0,0.0,0.0,0.0 +0,1.563100,0.0,0.0,0.0,0.0,0.0 +0,1.563200,0.0,0.0,0.0,0.0,0.0 +0,1.563300,0.0,0.0,0.0,0.0,0.0 +0,1.563400,0.0,0.0,0.0,0.0,0.0 +0,1.563500,0.0,0.0,0.0,0.0,0.0 +0,1.563600,0.0,0.0,0.0,0.0,0.0 +0,1.563700,0.0,0.0,0.0,0.0,0.0 +0,1.563800,0.0,0.0,0.0,0.0,0.0 +0,1.563900,0.0,0.0,0.0,0.0,0.0 +0,1.564000,0.0,0.0,0.0,0.0,0.0 +0,1.564100,0.0,0.0,0.0,0.0,0.0 +0,1.564200,0.0,0.0,0.0,0.0,0.0 +0,1.564300,0.0,0.0,0.0,0.0,0.0 +0,1.564400,0.0,0.0,0.0,0.0,0.0 +0,1.564500,0.0,0.0,0.0,0.0,0.0 +0,1.564600,0.0,0.0,0.0,0.0,0.0 +0,1.564700,0.0,0.0,0.0,0.0,0.0 +0,1.564800,0.0,0.0,0.0,0.0,0.0 +0,1.564900,0.0,0.0,0.0,0.0,0.0 +0,1.565000,0.0,0.0,0.0,0.0,0.0 +0,1.565100,0.0,0.0,0.0,0.0,0.0 +0,1.565200,0.0,0.0,0.0,0.0,0.0 +0,1.565300,0.0,0.0,0.0,0.0,0.0 +0,1.565400,0.0,0.0,0.0,0.0,0.0 +0,1.565500,0.0,0.0,0.0,0.0,0.0 +0,1.565600,0.0,0.0,0.0,0.0,0.0 +0,1.565700,0.0,0.0,0.0,0.0,0.0 +0,1.565800,0.0,0.0,0.0,0.0,0.0 +0,1.565900,0.0,0.0,0.0,0.0,0.0 +0,1.566000,0.0,0.0,0.0,0.0,0.0 +0,1.566100,0.0,0.0,0.0,0.0,0.0 +0,1.566200,0.0,0.0,0.0,0.0,0.0 +0,1.566300,0.0,0.0,0.0,0.0,0.0 +0,1.566400,0.0,0.0,0.0,0.0,0.0 +0,1.566500,0.0,0.0,0.0,0.0,0.0 +0,1.566600,0.0,0.0,0.0,0.0,0.0 +0,1.566700,0.0,0.0,0.0,0.0,0.0 +0,1.566800,0.0,0.0,0.0,0.0,0.0 +0,1.566900,0.0,0.0,0.0,0.0,0.0 +0,1.567000,0.0,0.0,0.0,0.0,0.0 +0,1.567100,0.0,0.0,0.0,0.0,0.0 +0,1.567200,0.0,0.0,0.0,0.0,0.0 +0,1.567300,0.0,0.0,0.0,0.0,0.0 +0,1.567400,0.0,0.0,0.0,0.0,0.0 +0,1.567500,0.0,0.0,0.0,0.0,0.0 +0,1.567600,0.0,0.0,0.0,0.0,0.0 +0,1.567700,0.0,0.0,0.0,0.0,0.0 +0,1.567800,0.0,0.0,0.0,0.0,0.0 +0,1.567900,0.0,0.0,0.0,0.0,0.0 +0,1.568000,0.0,0.0,0.0,0.0,0.0 +0,1.568100,0.0,0.0,0.0,0.0,0.0 +0,1.568200,0.0,0.0,0.0,0.0,0.0 +0,1.568300,0.0,0.0,0.0,0.0,0.0 +0,1.568400,0.0,0.0,0.0,0.0,0.0 +0,1.568500,0.0,0.0,0.0,0.0,0.0 +0,1.568600,0.0,0.0,0.0,0.0,0.0 +0,1.568700,0.0,0.0,0.0,0.0,0.0 +0,1.568800,0.0,0.0,0.0,0.0,0.0 +0,1.568900,0.0,0.0,0.0,0.0,0.0 +0,1.569000,0.0,0.0,0.0,0.0,0.0 +0,1.569100,0.0,0.0,0.0,0.0,0.0 +0,1.569200,0.0,0.0,0.0,0.0,0.0 +0,1.569300,0.0,0.0,0.0,0.0,0.0 +0,1.569400,0.0,0.0,0.0,0.0,0.0 +0,1.569500,0.0,0.0,0.0,0.0,0.0 +0,1.569600,0.0,0.0,0.0,0.0,0.0 +0,1.569700,0.0,0.0,0.0,0.0,0.0 +0,1.569800,0.0,0.0,0.0,0.0,0.0 +0,1.569900,0.0,0.0,0.0,0.0,0.0 +0,1.570000,0.0,0.0,0.0,0.0,0.0 +0,1.570100,0.0,0.0,0.0,0.0,0.0 +0,1.570200,0.0,0.0,0.0,0.0,0.0 +0,1.570300,0.0,0.0,0.0,0.0,0.0 +0,1.570400,0.0,0.0,0.0,0.0,0.0 +0,1.570500,0.0,0.0,0.0,0.0,0.0 +0,1.570600,0.0,0.0,0.0,0.0,0.0 +0,1.570700,0.0,0.0,0.0,0.0,0.0 +0,1.570800,0.0,0.0,0.0,0.0,0.0 +0,1.570900,0.0,0.0,0.0,0.0,0.0 +0,1.571000,0.0,0.0,0.0,0.0,0.0 +0,1.571100,0.0,0.0,0.0,0.0,0.0 +0,1.571200,0.0,0.0,0.0,0.0,0.0 +0,1.571300,0.0,0.0,0.0,0.0,0.0 +0,1.571400,0.0,0.0,0.0,0.0,0.0 +0,1.571500,0.0,0.0,0.0,0.0,0.0 +0,1.571600,0.0,0.0,0.0,0.0,0.0 +0,1.571700,0.0,0.0,0.0,0.0,0.0 +0,1.571800,0.0,0.0,0.0,0.0,0.0 +0,1.571900,0.0,0.0,0.0,0.0,0.0 +0,1.572000,0.0,0.0,0.0,0.0,0.0 +0,1.572100,0.0,0.0,0.0,0.0,0.0 +0,1.572200,0.0,0.0,0.0,0.0,0.0 +0,1.572300,0.0,0.0,0.0,0.0,0.0 +0,1.572400,0.0,0.0,0.0,0.0,0.0 +0,1.572500,0.0,0.0,0.0,0.0,0.0 +0,1.572600,0.0,0.0,0.0,0.0,0.0 +0,1.572700,0.0,0.0,0.0,0.0,0.0 +0,1.572800,0.0,0.0,0.0,0.0,0.0 +0,1.572900,0.0,0.0,0.0,0.0,0.0 +0,1.573000,0.0,0.0,0.0,0.0,0.0 +0,1.573100,0.0,0.0,0.0,0.0,0.0 +0,1.573200,0.0,0.0,0.0,0.0,0.0 +0,1.573300,0.0,0.0,0.0,0.0,0.0 +0,1.573400,0.0,0.0,0.0,0.0,0.0 +0,1.573500,0.0,0.0,0.0,0.0,0.0 +0,1.573600,0.0,0.0,0.0,0.0,0.0 +0,1.573700,0.0,0.0,0.0,0.0,0.0 +0,1.573800,0.0,0.0,0.0,0.0,0.0 +0,1.573900,0.0,0.0,0.0,0.0,0.0 +0,1.574000,0.0,0.0,0.0,0.0,0.0 +0,1.574100,0.0,0.0,0.0,0.0,0.0 +0,1.574200,0.0,0.0,0.0,0.0,0.0 +0,1.574300,0.0,0.0,0.0,0.0,0.0 +0,1.574400,0.0,0.0,0.0,0.0,0.0 +0,1.574500,0.0,0.0,0.0,0.0,0.0 +0,1.574600,0.0,0.0,0.0,0.0,0.0 +0,1.574700,0.0,0.0,0.0,0.0,0.0 +0,1.574800,0.0,0.0,0.0,0.0,0.0 +0,1.574900,0.0,0.0,0.0,0.0,0.0 +0,1.575000,0.0,0.0,0.0,0.0,0.0 +0,1.575100,0.0,0.0,0.0,0.0,0.0 +0,1.575200,0.0,0.0,0.0,0.0,0.0 +0,1.575300,0.0,0.0,0.0,0.0,0.0 +0,1.575400,0.0,0.0,0.0,0.0,0.0 +0,1.575500,0.0,0.0,0.0,0.0,0.0 +0,1.575600,0.0,0.0,0.0,0.0,0.0 +0,1.575700,0.0,0.0,0.0,0.0,0.0 +0,1.575800,0.0,0.0,0.0,0.0,0.0 +0,1.575900,0.0,0.0,0.0,0.0,0.0 +0,1.576000,0.0,0.0,0.0,0.0,0.0 +0,1.576100,0.0,0.0,0.0,0.0,0.0 +0,1.576200,0.0,0.0,0.0,0.0,0.0 +0,1.576300,0.0,0.0,0.0,0.0,0.0 +0,1.576400,0.0,0.0,0.0,0.0,0.0 +0,1.576500,0.0,0.0,0.0,0.0,0.0 +0,1.576600,0.0,0.0,0.0,0.0,0.0 +0,1.576700,0.0,0.0,0.0,0.0,0.0 +0,1.576800,0.0,0.0,0.0,0.0,0.0 +0,1.576900,0.0,0.0,0.0,0.0,0.0 +0,1.577000,0.0,0.0,0.0,0.0,0.0 +0,1.577100,0.0,0.0,0.0,0.0,0.0 +0,1.577200,0.0,0.0,0.0,0.0,0.0 +0,1.577300,0.0,0.0,0.0,0.0,0.0 +0,1.577400,0.0,0.0,0.0,0.0,0.0 +0,1.577500,0.0,0.0,0.0,0.0,0.0 +0,1.577600,0.0,0.0,0.0,0.0,0.0 +0,1.577700,0.0,0.0,0.0,0.0,0.0 +0,1.577800,0.0,0.0,0.0,0.0,0.0 +0,1.577900,0.0,0.0,0.0,0.0,0.0 +0,1.578000,0.0,0.0,0.0,0.0,0.0 +0,1.578100,0.0,0.0,0.0,0.0,0.0 +0,1.578200,0.0,0.0,0.0,0.0,0.0 +0,1.578300,0.0,0.0,0.0,0.0,0.0 +0,1.578400,0.0,0.0,0.0,0.0,0.0 +0,1.578500,0.0,0.0,0.0,0.0,0.0 +0,1.578600,0.0,0.0,0.0,0.0,0.0 +0,1.578700,0.0,0.0,0.0,0.0,0.0 +0,1.578800,0.0,0.0,0.0,0.0,0.0 +0,1.578900,0.0,0.0,0.0,0.0,0.0 +0,1.579000,0.0,0.0,0.0,0.0,0.0 +0,1.579100,0.0,0.0,0.0,0.0,0.0 +0,1.579200,0.0,0.0,0.0,0.0,0.0 +0,1.579300,0.0,0.0,0.0,0.0,0.0 +0,1.579400,0.0,0.0,0.0,0.0,0.0 +0,1.579500,0.0,0.0,0.0,0.0,0.0 +0,1.579600,0.0,0.0,0.0,0.0,0.0 +0,1.579700,0.0,0.0,0.0,0.0,0.0 +0,1.579800,0.0,0.0,0.0,0.0,0.0 +0,1.579900,0.0,0.0,0.0,0.0,0.0 +0,1.580000,0.0,0.0,0.0,0.0,0.0 +0,1.580100,0.0,0.0,0.0,0.0,0.0 +1,1643.931451,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.580200,0.0,0.0,0.0,0.0,0.0 +0,1.580300,0.0,0.0,0.0,0.0,0.0 +0,1.580400,0.0,0.0,0.0,0.0,0.0 +0,1.580500,0.0,0.0,0.0,0.0,0.0 +0,1.580600,0.0,0.0,0.0,0.0,0.0 +0,1.580700,0.0,0.0,0.0,0.0,0.0 +0,1.580800,0.0,0.0,0.0,0.0,0.0 +0,1.580900,0.0,0.0,0.0,0.0,0.0 +0,1.581000,0.0,0.0,0.0,0.0,0.0 +0,1.581100,0.0,0.0,0.0,0.0,0.0 +0,1.581200,0.0,0.0,0.0,0.0,0.0 +0,1.581300,0.0,0.0,0.0,0.0,0.0 +0,1.581400,0.0,0.0,0.0,0.0,0.0 +0,1.581500,0.0,0.0,0.0,0.0,0.0 +0,1.581600,0.0,0.0,0.0,0.0,0.0 +0,1.581700,0.0,0.0,0.0,0.0,0.0 +0,1.581800,0.0,0.0,0.0,0.0,0.0 +0,1.581900,0.0,0.0,0.0,0.0,0.0 +0,1.582000,0.0,0.0,0.0,0.0,0.0 +0,1.582100,0.0,0.0,0.0,0.0,0.0 +0,1.582200,0.0,0.0,0.0,0.0,0.0 +0,1.582300,0.0,0.0,0.0,0.0,0.0 +0,1.582400,0.0,0.0,0.0,0.0,0.0 +0,1.582500,0.0,0.0,0.0,0.0,0.0 +0,1.582600,0.0,0.0,0.0,0.0,0.0 +0,1.582700,0.0,0.0,0.0,0.0,0.0 +0,1.582800,0.0,0.0,0.0,0.0,0.0 +0,1.582900,0.0,0.0,0.0,0.0,0.0 +0,1.583000,0.0,0.0,0.0,0.0,0.0 +0,1.583100,0.0,0.0,0.0,0.0,0.0 +0,1.583200,0.0,0.0,0.0,0.0,0.0 +0,1.583300,0.0,0.0,0.0,0.0,0.0 +0,1.583400,0.0,0.0,0.0,0.0,0.0 +0,1.583500,0.0,0.0,0.0,0.0,0.0 +0,1.583600,0.0,0.0,0.0,0.0,0.0 +0,1.583700,0.0,0.0,0.0,0.0,0.0 +0,1.583800,0.0,0.0,0.0,0.0,0.0 +0,1.583900,0.0,0.0,0.0,0.0,0.0 +0,1.584000,0.0,0.0,0.0,0.0,0.0 +0,1.584100,0.0,0.0,0.0,0.0,0.0 +0,1.584200,0.0,0.0,0.0,0.0,0.0 +0,1.584300,0.0,0.0,0.0,0.0,0.0 +0,1.584400,0.0,0.0,0.0,0.0,0.0 +0,1.584500,0.0,0.0,0.0,0.0,0.0 +0,1.584600,0.0,0.0,0.0,0.0,0.0 +0,1.584700,0.0,0.0,0.0,0.0,0.0 +0,1.584800,0.0,0.0,0.0,0.0,0.0 +0,1.584900,0.0,0.0,0.0,0.0,0.0 +0,1.585000,0.0,0.0,0.0,0.0,0.0 +0,1.585100,0.0,0.0,0.0,0.0,0.0 +0,1.585200,0.0,0.0,0.0,0.0,0.0 +0,1.585300,0.0,0.0,0.0,0.0,0.0 +0,1.585400,0.0,0.0,0.0,0.0,0.0 +0,1.585500,0.0,0.0,0.0,0.0,0.0 +0,1.585600,0.0,0.0,0.0,0.0,0.0 +0,1.585700,0.0,0.0,0.0,0.0,0.0 +0,1.585800,0.0,0.0,0.0,0.0,0.0 +0,1.585900,0.0,0.0,0.0,0.0,0.0 +0,1.586000,0.0,0.0,0.0,0.0,0.0 +0,1.586100,0.0,0.0,0.0,0.0,0.0 +0,1.586200,0.0,0.0,0.0,0.0,0.0 +0,1.586300,0.0,0.0,0.0,0.0,0.0 +0,1.586400,0.0,0.0,0.0,0.0,0.0 +0,1.586500,0.0,0.0,0.0,0.0,0.0 +0,1.586600,0.0,0.0,0.0,0.0,0.0 +0,1.586700,0.0,0.0,0.0,0.0,0.0 +0,1.586800,0.0,0.0,0.0,0.0,0.0 +0,1.586900,0.0,0.0,0.0,0.0,0.0 +0,1.587000,0.0,0.0,0.0,0.0,0.0 +0,1.587100,0.0,0.0,0.0,0.0,0.0 +0,1.587200,0.0,0.0,0.0,0.0,0.0 +0,1.587300,0.0,0.0,0.0,0.0,0.0 +0,1.587400,0.0,0.0,0.0,0.0,0.0 +0,1.587500,0.0,0.0,0.0,0.0,0.0 +0,1.587600,0.0,0.0,0.0,0.0,0.0 +0,1.587700,0.0,0.0,0.0,0.0,0.0 +0,1.587800,0.0,0.0,0.0,0.0,0.0 +0,1.587900,0.0,0.0,0.0,0.0,0.0 +0,1.588000,0.0,0.0,0.0,0.0,0.0 +0,1.588100,0.0,0.0,0.0,0.0,0.0 +0,1.588200,0.0,0.0,0.0,0.0,0.0 +0,1.588300,0.0,0.0,0.0,0.0,0.0 +0,1.588400,0.0,0.0,0.0,0.0,0.0 +0,1.588500,0.0,0.0,0.0,0.0,0.0 +0,1.588600,0.0,0.0,0.0,0.0,0.0 +0,1.588700,0.0,0.0,0.0,0.0,0.0 +0,1.588800,0.0,0.0,0.0,0.0,0.0 +0,1.588900,0.0,0.0,0.0,0.0,0.0 +0,1.589000,0.0,0.0,0.0,0.0,0.0 +0,1.589100,0.0,0.0,0.0,0.0,0.0 +0,1.589200,0.0,0.0,0.0,0.0,0.0 +0,1.589300,0.0,0.0,0.0,0.0,0.0 +0,1.589400,0.0,0.0,0.0,0.0,0.0 +0,1.589500,0.0,0.0,0.0,0.0,0.0 +0,1.589600,0.0,0.0,0.0,0.0,0.0 +0,1.589700,0.0,0.0,0.0,0.0,0.0 +0,1.589800,0.0,0.0,0.0,0.0,0.0 +0,1.589900,0.0,0.0,0.0,0.0,0.0 +0,1.590000,0.0,0.0,0.0,0.0,0.0 +0,1.590100,0.0,0.0,0.0,0.0,0.0 +0,1.590200,0.0,0.0,0.0,0.0,0.0 +0,1.590300,0.0,0.0,0.0,0.0,0.0 +0,1.590400,0.0,0.0,0.0,0.0,0.0 +0,1.590500,0.0,0.0,0.0,0.0,0.0 +0,1.590600,0.0,0.0,0.0,0.0,0.0 +0,1.590700,0.0,0.0,0.0,0.0,0.0 +0,1.590800,0.0,0.0,0.0,0.0,0.0 +0,1.590900,0.0,0.0,0.0,0.0,0.0 +0,1.591000,0.0,0.0,0.0,0.0,0.0 +0,1.591100,0.0,0.0,0.0,0.0,0.0 +0,1.591200,0.0,0.0,0.0,0.0,0.0 +0,1.591300,0.0,0.0,0.0,0.0,0.0 +0,1.591400,0.0,0.0,0.0,0.0,0.0 +0,1.591500,0.0,0.0,0.0,0.0,0.0 +0,1.591600,0.0,0.0,0.0,0.0,0.0 +0,1.591700,0.0,0.0,0.0,0.0,0.0 +0,1.591800,0.0,0.0,0.0,0.0,0.0 +0,1.591900,0.0,0.0,0.0,0.0,0.0 +0,1.592000,0.0,0.0,0.0,0.0,0.0 +0,1.592100,0.0,0.0,0.0,0.0,0.0 +0,1.592200,0.0,0.0,0.0,0.0,0.0 +0,1.592300,0.0,0.0,0.0,0.0,0.0 +0,1.592400,0.0,0.0,0.0,0.0,0.0 +0,1.592500,0.0,0.0,0.0,0.0,0.0 +0,1.592600,0.0,0.0,0.0,0.0,0.0 +0,1.592700,0.0,0.0,0.0,0.0,0.0 +0,1.592800,0.0,0.0,0.0,0.0,0.0 +0,1.592900,0.0,0.0,0.0,0.0,0.0 +0,1.593000,0.0,0.0,0.0,0.0,0.0 +0,1.593100,0.0,0.0,0.0,0.0,0.0 +0,1.593200,0.0,0.0,0.0,0.0,0.0 +0,1.593300,0.0,0.0,0.0,0.0,0.0 +0,1.593400,0.0,0.0,0.0,0.0,0.0 +0,1.593500,0.0,0.0,0.0,0.0,0.0 +0,1.593600,0.0,0.0,0.0,0.0,0.0 +0,1.593700,0.0,0.0,0.0,0.0,0.0 +0,1.593800,0.0,0.0,0.0,0.0,0.0 +0,1.593900,0.0,0.0,0.0,0.0,0.0 +0,1.594000,0.0,0.0,0.0,0.0,0.0 +0,1.594100,0.0,0.0,0.0,0.0,0.0 +0,1.594200,0.0,0.0,0.0,0.0,0.0 +0,1.594300,0.0,0.0,0.0,0.0,0.0 +0,1.594400,0.0,0.0,0.0,0.0,0.0 +0,1.594500,0.0,0.0,0.0,0.0,0.0 +0,1.594600,0.0,0.0,0.0,0.0,0.0 +0,1.594700,0.0,0.0,0.0,0.0,0.0 +0,1.594800,0.0,0.0,0.0,0.0,0.0 +0,1.594900,0.0,0.0,0.0,0.0,0.0 +0,1.595000,0.0,0.0,0.0,0.0,0.0 +0,1.595100,0.0,0.0,0.0,0.0,0.0 +0,1.595200,0.0,0.0,0.0,0.0,0.0 +0,1.595300,0.0,0.0,0.0,0.0,0.0 +0,1.595400,0.0,0.0,0.0,0.0,0.0 +0,1.595500,0.0,0.0,0.0,0.0,0.0 +0,1.595600,0.0,0.0,0.0,0.0,0.0 +0,1.595700,0.0,0.0,0.0,0.0,0.0 +0,1.595800,0.0,0.0,0.0,0.0,0.0 +0,1.595900,0.0,0.0,0.0,0.0,0.0 +0,1.596000,0.0,0.0,0.0,0.0,0.0 +0,1.596100,0.0,0.0,0.0,0.0,0.0 +0,1.596200,0.0,0.0,0.0,0.0,0.0 +0,1.596300,0.0,0.0,0.0,0.0,0.0 +0,1.596400,0.0,0.0,0.0,0.0,0.0 +0,1.596500,0.0,0.0,0.0,0.0,0.0 +0,1.596600,0.0,0.0,0.0,0.0,0.0 +0,1.596700,0.0,0.0,0.0,0.0,0.0 +0,1.596800,0.0,0.0,0.0,0.0,0.0 +0,1.596900,0.0,0.0,0.0,0.0,0.0 +0,1.597000,0.0,0.0,0.0,0.0,0.0 +0,1.597100,0.0,0.0,0.0,0.0,0.0 +0,1.597200,0.0,0.0,0.0,0.0,0.0 +0,1.597300,0.0,0.0,0.0,0.0,0.0 +0,1.597400,0.0,0.0,0.0,0.0,0.0 +0,1.597500,0.0,0.0,0.0,0.0,0.0 +0,1.597600,0.0,0.0,0.0,0.0,0.0 +0,1.597700,0.0,0.0,0.0,0.0,0.0 +0,1.597800,0.0,0.0,0.0,0.0,0.0 +0,1.597900,0.0,0.0,0.0,0.0,0.0 +0,1.598000,0.0,0.0,0.0,0.0,0.0 +0,1.598100,0.0,0.0,0.0,0.0,0.0 +0,1.598200,0.0,0.0,0.0,0.0,0.0 +0,1.598300,0.0,0.0,0.0,0.0,0.0 +0,1.598400,0.0,0.0,0.0,0.0,0.0 +0,1.598500,0.0,0.0,0.0,0.0,0.0 +0,1.598600,0.0,0.0,0.0,0.0,0.0 +0,1.598700,0.0,0.0,0.0,0.0,0.0 +0,1.598800,0.0,0.0,0.0,0.0,0.0 +0,1.598900,0.0,0.0,0.0,0.0,0.0 +0,1.599000,0.0,0.0,0.0,0.0,0.0 +0,1.599100,0.0,0.0,0.0,0.0,0.0 +0,1.599200,0.0,0.0,0.0,0.0,0.0 +0,1.599300,0.0,0.0,0.0,0.0,0.0 +0,1.599400,0.0,0.0,0.0,0.0,0.0 +0,1.599500,0.0,0.0,0.0,0.0,0.0 +0,1.599600,0.0,0.0,0.0,0.0,0.0 +0,1.599700,0.0,0.0,0.0,0.0,0.0 +0,1.599800,0.0,0.0,0.0,0.0,0.0 +0,1.599900,0.0,0.0,0.0,0.0,0.0 +0,1.600000,0.0,0.0,0.0,0.0,0.0 +0,1.600100,0.0,0.0,0.0,0.0,0.0 +1,1707.146710,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.600200,0.0,0.0,0.0,0.0,0.0 +0,1.600300,0.0,0.0,0.0,0.0,0.0 +0,1.600400,0.0,0.0,0.0,0.0,0.0 +0,1.600500,0.0,0.0,0.0,0.0,0.0 +0,1.600600,0.0,0.0,0.0,0.0,0.0 +0,1.600700,0.0,0.0,0.0,0.0,0.0 +0,1.600800,0.0,0.0,0.0,0.0,0.0 +0,1.600900,0.0,0.0,0.0,0.0,0.0 +0,1.601000,0.0,0.0,0.0,0.0,0.0 +0,1.601100,0.0,0.0,0.0,0.0,0.0 +0,1.601200,0.0,0.0,0.0,0.0,0.0 +0,1.601300,0.0,0.0,0.0,0.0,0.0 +0,1.601400,0.0,0.0,0.0,0.0,0.0 +0,1.601500,0.0,0.0,0.0,0.0,0.0 +0,1.601600,0.0,0.0,0.0,0.0,0.0 +0,1.601700,0.0,0.0,0.0,0.0,0.0 +0,1.601800,0.0,0.0,0.0,0.0,0.0 +0,1.601900,0.0,0.0,0.0,0.0,0.0 +0,1.602000,0.0,0.0,0.0,0.0,0.0 +0,1.602100,0.0,0.0,0.0,0.0,0.0 +0,1.602200,0.0,0.0,0.0,0.0,0.0 +0,1.602300,0.0,0.0,0.0,0.0,0.0 +0,1.602400,0.0,0.0,0.0,0.0,0.0 +0,1.602500,0.0,0.0,0.0,0.0,0.0 +0,1.602600,0.0,0.0,0.0,0.0,0.0 +0,1.602700,0.0,0.0,0.0,0.0,0.0 +0,1.602800,0.0,0.0,0.0,0.0,0.0 +0,1.602900,0.0,0.0,0.0,0.0,0.0 +0,1.603000,0.0,0.0,0.0,0.0,0.0 +0,1.603100,0.0,0.0,0.0,0.0,0.0 +0,1.603200,0.0,0.0,0.0,0.0,0.0 +0,1.603300,0.0,0.0,0.0,0.0,0.0 +0,1.603400,0.0,0.0,0.0,0.0,0.0 +0,1.603500,0.0,0.0,0.0,0.0,0.0 +0,1.603600,0.0,0.0,0.0,0.0,0.0 +0,1.603700,0.0,0.0,0.0,0.0,0.0 +0,1.603800,0.0,0.0,0.0,0.0,0.0 +0,1.603900,0.0,0.0,0.0,0.0,0.0 +0,1.604000,0.0,0.0,0.0,0.0,0.0 +0,1.604100,0.0,0.0,0.0,0.0,0.0 +0,1.604200,0.0,0.0,0.0,0.0,0.0 +0,1.604300,0.0,0.0,0.0,0.0,0.0 +0,1.604400,0.0,0.0,0.0,0.0,0.0 +0,1.604500,0.0,0.0,0.0,0.0,0.0 +0,1.604600,0.0,0.0,0.0,0.0,0.0 +0,1.604700,0.0,0.0,0.0,0.0,0.0 +0,1.604800,0.0,0.0,0.0,0.0,0.0 +0,1.604900,0.0,0.0,0.0,0.0,0.0 +0,1.605000,0.0,0.0,0.0,0.0,0.0 +0,1.605100,0.0,0.0,0.0,0.0,0.0 +0,1.605200,0.0,0.0,0.0,0.0,0.0 +0,1.605300,0.0,0.0,0.0,0.0,0.0 +0,1.605400,0.0,0.0,0.0,0.0,0.0 +0,1.605500,0.0,0.0,0.0,0.0,0.0 +0,1.605600,0.0,0.0,0.0,0.0,0.0 +0,1.605700,0.0,0.0,0.0,0.0,0.0 +0,1.605800,0.0,0.0,0.0,0.0,0.0 +0,1.605900,0.0,0.0,0.0,0.0,0.0 +0,1.606000,0.0,0.0,0.0,0.0,0.0 +0,1.606100,0.0,0.0,0.0,0.0,0.0 +0,1.606200,0.0,0.0,0.0,0.0,0.0 +0,1.606300,0.0,0.0,0.0,0.0,0.0 +0,1.606400,0.0,0.0,0.0,0.0,0.0 +0,1.606500,0.0,0.0,0.0,0.0,0.0 +0,1.606600,0.0,0.0,0.0,0.0,0.0 +0,1.606700,0.0,0.0,0.0,0.0,0.0 +0,1.606800,0.0,0.0,0.0,0.0,0.0 +0,1.606900,0.0,0.0,0.0,0.0,0.0 +0,1.607000,0.0,0.0,0.0,0.0,0.0 +0,1.607100,0.0,0.0,0.0,0.0,0.0 +0,1.607200,0.0,0.0,0.0,0.0,0.0 +0,1.607300,0.0,0.0,0.0,0.0,0.0 +0,1.607400,0.0,0.0,0.0,0.0,0.0 +0,1.607500,0.0,0.0,0.0,0.0,0.0 +0,1.607600,0.0,0.0,0.0,0.0,0.0 +0,1.607700,0.0,0.0,0.0,0.0,0.0 +0,1.607800,0.0,0.0,0.0,0.0,0.0 +0,1.607900,0.0,0.0,0.0,0.0,0.0 +0,1.608000,0.0,0.0,0.0,0.0,0.0 +0,1.608100,0.0,0.0,0.0,0.0,0.0 +0,1.608200,0.0,0.0,0.0,0.0,0.0 +0,1.608300,0.0,0.0,0.0,0.0,0.0 +0,1.608400,0.0,0.0,0.0,0.0,0.0 +0,1.608500,0.0,0.0,0.0,0.0,0.0 +0,1.608600,0.0,0.0,0.0,0.0,0.0 +0,1.608700,0.0,0.0,0.0,0.0,0.0 +0,1.608800,0.0,0.0,0.0,0.0,0.0 +0,1.608900,0.0,0.0,0.0,0.0,0.0 +0,1.609000,0.0,0.0,0.0,0.0,0.0 +0,1.609100,0.0,0.0,0.0,0.0,0.0 +0,1.609200,0.0,0.0,0.0,0.0,0.0 +0,1.609300,0.0,0.0,0.0,0.0,0.0 +0,1.609400,0.0,0.0,0.0,0.0,0.0 +0,1.609500,0.0,0.0,0.0,0.0,0.0 +0,1.609600,0.0,0.0,0.0,0.0,0.0 +0,1.609700,0.0,0.0,0.0,0.0,0.0 +0,1.609800,0.0,0.0,0.0,0.0,0.0 +0,1.609900,0.0,0.0,0.0,0.0,0.0 +0,1.610000,0.0,0.0,0.0,0.0,0.0 +0,1.610100,0.0,0.0,0.0,0.0,0.0 +0,1.610200,0.0,0.0,0.0,0.0,0.0 +0,1.610300,0.0,0.0,0.0,0.0,0.0 +0,1.610400,0.0,0.0,0.0,0.0,0.0 +0,1.610500,0.0,0.0,0.0,0.0,0.0 +0,1.610600,0.0,0.0,0.0,0.0,0.0 +0,1.610700,0.0,0.0,0.0,0.0,0.0 +0,1.610800,0.0,0.0,0.0,0.0,0.0 +0,1.610900,0.0,0.0,0.0,0.0,0.0 +0,1.611000,0.0,0.0,0.0,0.0,0.0 +0,1.611100,0.0,0.0,0.0,0.0,0.0 +0,1.611200,0.0,0.0,0.0,0.0,0.0 +0,1.611300,0.0,0.0,0.0,0.0,0.0 +0,1.611400,0.0,0.0,0.0,0.0,0.0 +0,1.611500,0.0,0.0,0.0,0.0,0.0 +0,1.611600,0.0,0.0,0.0,0.0,0.0 +0,1.611700,0.0,0.0,0.0,0.0,0.0 +0,1.611800,0.0,0.0,0.0,0.0,0.0 +0,1.611900,0.0,0.0,0.0,0.0,0.0 +0,1.612000,0.0,0.0,0.0,0.0,0.0 +0,1.612100,0.0,0.0,0.0,0.0,0.0 +0,1.612200,0.0,0.0,0.0,0.0,0.0 +0,1.612300,0.0,0.0,0.0,0.0,0.0 +0,1.612400,0.0,0.0,0.0,0.0,0.0 +0,1.612500,0.0,0.0,0.0,0.0,0.0 +0,1.612600,0.0,0.0,0.0,0.0,0.0 +0,1.612700,0.0,0.0,0.0,0.0,0.0 +0,1.612800,0.0,0.0,0.0,0.0,0.0 +0,1.612900,0.0,0.0,0.0,0.0,0.0 +0,1.613000,0.0,0.0,0.0,0.0,0.0 +0,1.613100,0.0,0.0,0.0,0.0,0.0 +0,1.613200,0.0,0.0,0.0,0.0,0.0 +0,1.613300,0.0,0.0,0.0,0.0,0.0 +0,1.613400,0.0,0.0,0.0,0.0,0.0 +0,1.613500,0.0,0.0,0.0,0.0,0.0 +0,1.613600,0.0,0.0,0.0,0.0,0.0 +0,1.613700,0.0,0.0,0.0,0.0,0.0 +0,1.613800,0.0,0.0,0.0,0.0,0.0 +0,1.613900,0.0,0.0,0.0,0.0,0.0 +0,1.614000,0.0,0.0,0.0,0.0,0.0 +0,1.614100,0.0,0.0,0.0,0.0,0.0 +0,1.614200,0.0,0.0,0.0,0.0,0.0 +0,1.614300,0.0,0.0,0.0,0.0,0.0 +0,1.614400,0.0,0.0,0.0,0.0,0.0 +0,1.614500,0.0,0.0,0.0,0.0,0.0 +0,1.614600,0.0,0.0,0.0,0.0,0.0 +0,1.614700,0.0,0.0,0.0,0.0,0.0 +0,1.614800,0.0,0.0,0.0,0.0,0.0 +0,1.614900,0.0,0.0,0.0,0.0,0.0 +0,1.615000,0.0,0.0,0.0,0.0,0.0 +0,1.615100,0.0,0.0,0.0,0.0,0.0 +0,1.615200,0.0,0.0,0.0,0.0,0.0 +0,1.615300,0.0,0.0,0.0,0.0,0.0 +0,1.615400,0.0,0.0,0.0,0.0,0.0 +0,1.615500,0.0,0.0,0.0,0.0,0.0 +0,1.615600,0.0,0.0,0.0,0.0,0.0 +0,1.615700,0.0,0.0,0.0,0.0,0.0 +0,1.615800,0.0,0.0,0.0,0.0,0.0 +0,1.615900,0.0,0.0,0.0,0.0,0.0 +0,1.616000,0.0,0.0,0.0,0.0,0.0 +0,1.616100,0.0,0.0,0.0,0.0,0.0 +0,1.616200,0.0,0.0,0.0,0.0,0.0 +0,1.616300,0.0,0.0,0.0,0.0,0.0 +0,1.616400,0.0,0.0,0.0,0.0,0.0 +0,1.616500,0.0,0.0,0.0,0.0,0.0 +0,1.616600,0.0,0.0,0.0,0.0,0.0 +0,1.616700,0.0,0.0,0.0,0.0,0.0 +0,1.616800,0.0,0.0,0.0,0.0,0.0 +0,1.616900,0.0,0.0,0.0,0.0,0.0 +0,1.617000,0.0,0.0,0.0,0.0,0.0 +0,1.617100,0.0,0.0,0.0,0.0,0.0 +0,1.617200,0.0,0.0,0.0,0.0,0.0 +0,1.617300,0.0,0.0,0.0,0.0,0.0 +0,1.617400,0.0,0.0,0.0,0.0,0.0 +0,1.617500,0.0,0.0,0.0,0.0,0.0 +0,1.617600,0.0,0.0,0.0,0.0,0.0 +0,1.617700,0.0,0.0,0.0,0.0,0.0 +0,1.617800,0.0,0.0,0.0,0.0,0.0 +0,1.617900,0.0,0.0,0.0,0.0,0.0 +0,1.618000,0.0,0.0,0.0,0.0,0.0 +0,1.618100,0.0,0.0,0.0,0.0,0.0 +0,1.618200,0.0,0.0,0.0,0.0,0.0 +0,1.618300,0.0,0.0,0.0,0.0,0.0 +0,1.618400,0.0,0.0,0.0,0.0,0.0 +0,1.618500,0.0,0.0,0.0,0.0,0.0 +0,1.618600,0.0,0.0,0.0,0.0,0.0 +0,1.618700,0.0,0.0,0.0,0.0,0.0 +0,1.618800,0.0,0.0,0.0,0.0,0.0 +0,1.618900,0.0,0.0,0.0,0.0,0.0 +0,1.619000,0.0,0.0,0.0,0.0,0.0 +0,1.619100,0.0,0.0,0.0,0.0,0.0 +0,1.619200,0.0,0.0,0.0,0.0,0.0 +0,1.619300,0.0,0.0,0.0,0.0,0.0 +0,1.619400,0.0,0.0,0.0,0.0,0.0 +0,1.619500,0.0,0.0,0.0,0.0,0.0 +0,1.619600,0.0,0.0,0.0,0.0,0.0 +0,1.619700,0.0,0.0,0.0,0.0,0.0 +0,1.619800,0.0,0.0,0.0,0.0,0.0 +0,1.619900,0.0,0.0,0.0,0.0,0.0 +0,1.620000,0.0,0.0,0.0,0.0,0.0 +0,1.620100,0.0,0.0,0.0,0.0,0.0 +1,1771.962119,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.620200,0.0,0.0,0.0,0.0,0.0 +0,1.620300,0.0,0.0,0.0,0.0,0.0 +0,1.620400,0.0,0.0,0.0,0.0,0.0 +0,1.620500,0.0,0.0,0.0,0.0,0.0 +0,1.620600,0.0,0.0,0.0,0.0,0.0 +0,1.620700,0.0,0.0,0.0,0.0,0.0 +0,1.620800,0.0,0.0,0.0,0.0,0.0 +0,1.620900,0.0,0.0,0.0,0.0,0.0 +0,1.621000,0.0,0.0,0.0,0.0,0.0 +0,1.621100,0.0,0.0,0.0,0.0,0.0 +0,1.621200,0.0,0.0,0.0,0.0,0.0 +0,1.621300,0.0,0.0,0.0,0.0,0.0 +0,1.621400,0.0,0.0,0.0,0.0,0.0 +0,1.621500,0.0,0.0,0.0,0.0,0.0 +0,1.621600,0.0,0.0,0.0,0.0,0.0 +0,1.621700,0.0,0.0,0.0,0.0,0.0 +0,1.621800,0.0,0.0,0.0,0.0,0.0 +0,1.621900,0.0,0.0,0.0,0.0,0.0 +0,1.622000,0.0,0.0,0.0,0.0,0.0 +0,1.622100,0.0,0.0,0.0,0.0,0.0 +0,1.622200,0.0,0.0,0.0,0.0,0.0 +0,1.622300,0.0,0.0,0.0,0.0,0.0 +0,1.622400,0.0,0.0,0.0,0.0,0.0 +0,1.622500,0.0,0.0,0.0,0.0,0.0 +0,1.622600,0.0,0.0,0.0,0.0,0.0 +0,1.622700,0.0,0.0,0.0,0.0,0.0 +0,1.622800,0.0,0.0,0.0,0.0,0.0 +0,1.622900,0.0,0.0,0.0,0.0,0.0 +0,1.623000,0.0,0.0,0.0,0.0,0.0 +0,1.623100,0.0,0.0,0.0,0.0,0.0 +0,1.623200,0.0,0.0,0.0,0.0,0.0 +0,1.623300,0.0,0.0,0.0,0.0,0.0 +0,1.623400,0.0,0.0,0.0,0.0,0.0 +0,1.623500,0.0,0.0,0.0,0.0,0.0 +0,1.623600,0.0,0.0,0.0,0.0,0.0 +0,1.623700,0.0,0.0,0.0,0.0,0.0 +0,1.623800,0.0,0.0,0.0,0.0,0.0 +0,1.623900,0.0,0.0,0.0,0.0,0.0 +0,1.624000,0.0,0.0,0.0,0.0,0.0 +0,1.624100,0.0,0.0,0.0,0.0,0.0 +0,1.624200,0.0,0.0,0.0,0.0,0.0 +0,1.624300,0.0,0.0,0.0,0.0,0.0 +0,1.624400,0.0,0.0,0.0,0.0,0.0 +0,1.624500,0.0,0.0,0.0,0.0,0.0 +0,1.624600,0.0,0.0,0.0,0.0,0.0 +0,1.624700,0.0,0.0,0.0,0.0,0.0 +0,1.624800,0.0,0.0,0.0,0.0,0.0 +0,1.624900,0.0,0.0,0.0,0.0,0.0 +0,1.625000,0.0,0.0,0.0,0.0,0.0 +0,1.625100,0.0,0.0,0.0,0.0,0.0 +0,1.625200,0.0,0.0,0.0,0.0,0.0 +0,1.625300,0.0,0.0,0.0,0.0,0.0 +0,1.625400,0.0,0.0,0.0,0.0,0.0 +0,1.625500,0.0,0.0,0.0,0.0,0.0 +0,1.625600,0.0,0.0,0.0,0.0,0.0 +0,1.625700,0.0,0.0,0.0,0.0,0.0 +0,1.625800,0.0,0.0,0.0,0.0,0.0 +0,1.625900,0.0,0.0,0.0,0.0,0.0 +0,1.626000,0.0,0.0,0.0,0.0,0.0 +0,1.626100,0.0,0.0,0.0,0.0,0.0 +0,1.626200,0.0,0.0,0.0,0.0,0.0 +0,1.626300,0.0,0.0,0.0,0.0,0.0 +0,1.626400,0.0,0.0,0.0,0.0,0.0 +0,1.626500,0.0,0.0,0.0,0.0,0.0 +0,1.626600,0.0,0.0,0.0,0.0,0.0 +0,1.626700,0.0,0.0,0.0,0.0,0.0 +0,1.626800,0.0,0.0,0.0,0.0,0.0 +0,1.626900,0.0,0.0,0.0,0.0,0.0 +0,1.627000,0.0,0.0,0.0,0.0,0.0 +0,1.627100,0.0,0.0,0.0,0.0,0.0 +0,1.627200,0.0,0.0,0.0,0.0,0.0 +0,1.627300,0.0,0.0,0.0,0.0,0.0 +0,1.627400,0.0,0.0,0.0,0.0,0.0 +0,1.627500,0.0,0.0,0.0,0.0,0.0 +0,1.627600,0.0,0.0,0.0,0.0,0.0 +0,1.627700,0.0,0.0,0.0,0.0,0.0 +0,1.627800,0.0,0.0,0.0,0.0,0.0 +0,1.627900,0.0,0.0,0.0,0.0,0.0 +0,1.628000,0.0,0.0,0.0,0.0,0.0 +0,1.628100,0.0,0.0,0.0,0.0,0.0 +0,1.628200,0.0,0.0,0.0,0.0,0.0 +0,1.628300,0.0,0.0,0.0,0.0,0.0 +0,1.628400,0.0,0.0,0.0,0.0,0.0 +0,1.628500,0.0,0.0,0.0,0.0,0.0 +0,1.628600,0.0,0.0,0.0,0.0,0.0 +0,1.628700,0.0,0.0,0.0,0.0,0.0 +0,1.628800,0.0,0.0,0.0,0.0,0.0 +0,1.628900,0.0,0.0,0.0,0.0,0.0 +0,1.629000,0.0,0.0,0.0,0.0,0.0 +0,1.629100,0.0,0.0,0.0,0.0,0.0 +0,1.629200,0.0,0.0,0.0,0.0,0.0 +0,1.629300,0.0,0.0,0.0,0.0,0.0 +0,1.629400,0.0,0.0,0.0,0.0,0.0 +0,1.629500,0.0,0.0,0.0,0.0,0.0 +0,1.629600,0.0,0.0,0.0,0.0,0.0 +0,1.629700,0.0,0.0,0.0,0.0,0.0 +0,1.629800,0.0,0.0,0.0,0.0,0.0 +0,1.629900,0.0,0.0,0.0,0.0,0.0 +0,1.630000,0.0,0.0,0.0,0.0,0.0 +0,1.630100,0.0,0.0,0.0,0.0,0.0 +0,1.630200,0.0,0.0,0.0,0.0,0.0 +0,1.630300,0.0,0.0,0.0,0.0,0.0 +0,1.630400,0.0,0.0,0.0,0.0,0.0 +0,1.630500,0.0,0.0,0.0,0.0,0.0 +0,1.630600,0.0,0.0,0.0,0.0,0.0 +0,1.630700,0.0,0.0,0.0,0.0,0.0 +0,1.630800,0.0,0.0,0.0,0.0,0.0 +0,1.630900,0.0,0.0,0.0,0.0,0.0 +0,1.631000,0.0,0.0,0.0,0.0,0.0 +0,1.631100,0.0,0.0,0.0,0.0,0.0 +0,1.631200,0.0,0.0,0.0,0.0,0.0 +0,1.631300,0.0,0.0,0.0,0.0,0.0 +0,1.631400,0.0,0.0,0.0,0.0,0.0 +0,1.631500,0.0,0.0,0.0,0.0,0.0 +0,1.631600,0.0,0.0,0.0,0.0,0.0 +0,1.631700,0.0,0.0,0.0,0.0,0.0 +0,1.631800,0.0,0.0,0.0,0.0,0.0 +0,1.631900,0.0,0.0,0.0,0.0,0.0 +0,1.632000,0.0,0.0,0.0,0.0,0.0 +0,1.632100,0.0,0.0,0.0,0.0,0.0 +0,1.632200,0.0,0.0,0.0,0.0,0.0 +0,1.632300,0.0,0.0,0.0,0.0,0.0 +0,1.632400,0.0,0.0,0.0,0.0,0.0 +0,1.632500,0.0,0.0,0.0,0.0,0.0 +0,1.632600,0.0,0.0,0.0,0.0,0.0 +0,1.632700,0.0,0.0,0.0,0.0,0.0 +0,1.632800,0.0,0.0,0.0,0.0,0.0 +0,1.632900,0.0,0.0,0.0,0.0,0.0 +0,1.633000,0.0,0.0,0.0,0.0,0.0 +0,1.633100,0.0,0.0,0.0,0.0,0.0 +0,1.633200,0.0,0.0,0.0,0.0,0.0 +0,1.633300,0.0,0.0,0.0,0.0,0.0 +0,1.633400,0.0,0.0,0.0,0.0,0.0 +0,1.633500,0.0,0.0,0.0,0.0,0.0 +0,1.633600,0.0,0.0,0.0,0.0,0.0 +0,1.633700,0.0,0.0,0.0,0.0,0.0 +0,1.633800,0.0,0.0,0.0,0.0,0.0 +0,1.633900,0.0,0.0,0.0,0.0,0.0 +0,1.634000,0.0,0.0,0.0,0.0,0.0 +0,1.634100,0.0,0.0,0.0,0.0,0.0 +0,1.634200,0.0,0.0,0.0,0.0,0.0 +0,1.634300,0.0,0.0,0.0,0.0,0.0 +0,1.634400,0.0,0.0,0.0,0.0,0.0 +0,1.634500,0.0,0.0,0.0,0.0,0.0 +0,1.634600,0.0,0.0,0.0,0.0,0.0 +0,1.634700,0.0,0.0,0.0,0.0,0.0 +0,1.634800,0.0,0.0,0.0,0.0,0.0 +0,1.634900,0.0,0.0,0.0,0.0,0.0 +0,1.635000,0.0,0.0,0.0,0.0,0.0 +0,1.635100,0.0,0.0,0.0,0.0,0.0 +0,1.635200,0.0,0.0,0.0,0.0,0.0 +0,1.635300,0.0,0.0,0.0,0.0,0.0 +0,1.635400,0.0,0.0,0.0,0.0,0.0 +0,1.635500,0.0,0.0,0.0,0.0,0.0 +0,1.635600,0.0,0.0,0.0,0.0,0.0 +0,1.635700,0.0,0.0,0.0,0.0,0.0 +0,1.635800,0.0,0.0,0.0,0.0,0.0 +0,1.635900,0.0,0.0,0.0,0.0,0.0 +0,1.636000,0.0,0.0,0.0,0.0,0.0 +0,1.636100,0.0,0.0,0.0,0.0,0.0 +0,1.636200,0.0,0.0,0.0,0.0,0.0 +0,1.636300,0.0,0.0,0.0,0.0,0.0 +0,1.636400,0.0,0.0,0.0,0.0,0.0 +0,1.636500,0.0,0.0,0.0,0.0,0.0 +0,1.636600,0.0,0.0,0.0,0.0,0.0 +0,1.636700,0.0,0.0,0.0,0.0,0.0 +0,1.636800,0.0,0.0,0.0,0.0,0.0 +0,1.636900,0.0,0.0,0.0,0.0,0.0 +0,1.637000,0.0,0.0,0.0,0.0,0.0 +0,1.637100,0.0,0.0,0.0,0.0,0.0 +0,1.637200,0.0,0.0,0.0,0.0,0.0 +0,1.637300,0.0,0.0,0.0,0.0,0.0 +0,1.637400,0.0,0.0,0.0,0.0,0.0 +0,1.637500,0.0,0.0,0.0,0.0,0.0 +0,1.637600,0.0,0.0,0.0,0.0,0.0 +0,1.637700,0.0,0.0,0.0,0.0,0.0 +0,1.637800,0.0,0.0,0.0,0.0,0.0 +0,1.637900,0.0,0.0,0.0,0.0,0.0 +0,1.638000,0.0,0.0,0.0,0.0,0.0 +0,1.638100,0.0,0.0,0.0,0.0,0.0 +0,1.638200,0.0,0.0,0.0,0.0,0.0 +0,1.638300,0.0,0.0,0.0,0.0,0.0 +0,1.638400,0.0,0.0,0.0,0.0,0.0 +0,1.638500,0.0,0.0,0.0,0.0,0.0 +0,1.638600,0.0,0.0,0.0,0.0,0.0 +0,1.638700,0.0,0.0,0.0,0.0,0.0 +0,1.638800,0.0,0.0,0.0,0.0,0.0 +0,1.638900,0.0,0.0,0.0,0.0,0.0 +0,1.639000,0.0,0.0,0.0,0.0,0.0 +0,1.639100,0.0,0.0,0.0,0.0,0.0 +0,1.639200,0.0,0.0,0.0,0.0,0.0 +0,1.639300,0.0,0.0,0.0,0.0,0.0 +0,1.639400,0.0,0.0,0.0,0.0,0.0 +0,1.639500,0.0,0.0,0.0,0.0,0.0 +0,1.639600,0.0,0.0,0.0,0.0,0.0 +0,1.639700,0.0,0.0,0.0,0.0,0.0 +0,1.639800,0.0,0.0,0.0,0.0,0.0 +0,1.639900,0.0,0.0,0.0,0.0,0.0 +0,1.640000,0.0,0.0,0.0,0.0,0.0 +0,1.640100,0.0,0.0,0.0,0.0,0.0 +1,1838.397678,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.640200,0.0,0.0,0.0,0.0,0.0 +0,1.640300,0.0,0.0,0.0,0.0,0.0 +0,1.640400,0.0,0.0,0.0,0.0,0.0 +0,1.640500,0.0,0.0,0.0,0.0,0.0 +0,1.640600,0.0,0.0,0.0,0.0,0.0 +0,1.640700,0.0,0.0,0.0,0.0,0.0 +0,1.640800,0.0,0.0,0.0,0.0,0.0 +0,1.640900,0.0,0.0,0.0,0.0,0.0 +0,1.641000,0.0,0.0,0.0,0.0,0.0 +0,1.641100,0.0,0.0,0.0,0.0,0.0 +0,1.641200,0.0,0.0,0.0,0.0,0.0 +0,1.641300,0.0,0.0,0.0,0.0,0.0 +0,1.641400,0.0,0.0,0.0,0.0,0.0 +0,1.641500,0.0,0.0,0.0,0.0,0.0 +0,1.641600,0.0,0.0,0.0,0.0,0.0 +0,1.641700,0.0,0.0,0.0,0.0,0.0 +0,1.641800,0.0,0.0,0.0,0.0,0.0 +0,1.641900,0.0,0.0,0.0,0.0,0.0 +0,1.642000,0.0,0.0,0.0,0.0,0.0 +0,1.642100,0.0,0.0,0.0,0.0,0.0 +0,1.642200,0.0,0.0,0.0,0.0,0.0 +0,1.642300,0.0,0.0,0.0,0.0,0.0 +0,1.642400,0.0,0.0,0.0,0.0,0.0 +0,1.642500,0.0,0.0,0.0,0.0,0.0 +0,1.642600,0.0,0.0,0.0,0.0,0.0 +0,1.642700,0.0,0.0,0.0,0.0,0.0 +0,1.642800,0.0,0.0,0.0,0.0,0.0 +0,1.642900,0.0,0.0,0.0,0.0,0.0 +0,1.643000,0.0,0.0,0.0,0.0,0.0 +0,1.643100,0.0,0.0,0.0,0.0,0.0 +0,1.643200,0.0,0.0,0.0,0.0,0.0 +0,1.643300,0.0,0.0,0.0,0.0,0.0 +0,1.643400,0.0,0.0,0.0,0.0,0.0 +0,1.643500,0.0,0.0,0.0,0.0,0.0 +0,1.643600,0.0,0.0,0.0,0.0,0.0 +0,1.643700,0.0,0.0,0.0,0.0,0.0 +0,1.643800,0.0,0.0,0.0,0.0,0.0 +0,1.643900,0.0,0.0,0.0,0.0,0.0 +0,1.644000,0.0,0.0,0.0,0.0,0.0 +0,1.644100,0.0,0.0,0.0,0.0,0.0 +0,1.644200,0.0,0.0,0.0,0.0,0.0 +0,1.644300,0.0,0.0,0.0,0.0,0.0 +0,1.644400,0.0,0.0,0.0,0.0,0.0 +0,1.644500,0.0,0.0,0.0,0.0,0.0 +0,1.644600,0.0,0.0,0.0,0.0,0.0 +0,1.644700,0.0,0.0,0.0,0.0,0.0 +0,1.644800,0.0,0.0,0.0,0.0,0.0 +0,1.644900,0.0,0.0,0.0,0.0,0.0 +0,1.645000,0.0,0.0,0.0,0.0,0.0 +0,1.645100,0.0,0.0,0.0,0.0,0.0 +0,1.645200,0.0,0.0,0.0,0.0,0.0 +0,1.645300,0.0,0.0,0.0,0.0,0.0 +0,1.645400,0.0,0.0,0.0,0.0,0.0 +0,1.645500,0.0,0.0,0.0,0.0,0.0 +0,1.645600,0.0,0.0,0.0,0.0,0.0 +0,1.645700,0.0,0.0,0.0,0.0,0.0 +0,1.645800,0.0,0.0,0.0,0.0,0.0 +0,1.645900,0.0,0.0,0.0,0.0,0.0 +0,1.646000,0.0,0.0,0.0,0.0,0.0 +0,1.646100,0.0,0.0,0.0,0.0,0.0 +0,1.646200,0.0,0.0,0.0,0.0,0.0 +0,1.646300,0.0,0.0,0.0,0.0,0.0 +0,1.646400,0.0,0.0,0.0,0.0,0.0 +0,1.646500,0.0,0.0,0.0,0.0,0.0 +0,1.646600,0.0,0.0,0.0,0.0,0.0 +0,1.646700,0.0,0.0,0.0,0.0,0.0 +0,1.646800,0.0,0.0,0.0,0.0,0.0 +0,1.646900,0.0,0.0,0.0,0.0,0.0 +0,1.647000,0.0,0.0,0.0,0.0,0.0 +0,1.647100,0.0,0.0,0.0,0.0,0.0 +0,1.647200,0.0,0.0,0.0,0.0,0.0 +0,1.647300,0.0,0.0,0.0,0.0,0.0 +0,1.647400,0.0,0.0,0.0,0.0,0.0 +0,1.647500,0.0,0.0,0.0,0.0,0.0 +0,1.647600,0.0,0.0,0.0,0.0,0.0 +0,1.647700,0.0,0.0,0.0,0.0,0.0 +0,1.647800,0.0,0.0,0.0,0.0,0.0 +0,1.647900,0.0,0.0,0.0,0.0,0.0 +0,1.648000,0.0,0.0,0.0,0.0,0.0 +0,1.648100,0.0,0.0,0.0,0.0,0.0 +0,1.648200,0.0,0.0,0.0,0.0,0.0 +0,1.648300,0.0,0.0,0.0,0.0,0.0 +0,1.648400,0.0,0.0,0.0,0.0,0.0 +0,1.648500,0.0,0.0,0.0,0.0,0.0 +0,1.648600,0.0,0.0,0.0,0.0,0.0 +0,1.648700,0.0,0.0,0.0,0.0,0.0 +0,1.648800,0.0,0.0,0.0,0.0,0.0 +0,1.648900,0.0,0.0,0.0,0.0,0.0 +0,1.649000,0.0,0.0,0.0,0.0,0.0 +0,1.649100,0.0,0.0,0.0,0.0,0.0 +0,1.649200,0.0,0.0,0.0,0.0,0.0 +0,1.649300,0.0,0.0,0.0,0.0,0.0 +0,1.649400,0.0,0.0,0.0,0.0,0.0 +0,1.649500,0.0,0.0,0.0,0.0,0.0 +0,1.649600,0.0,0.0,0.0,0.0,0.0 +0,1.649700,0.0,0.0,0.0,0.0,0.0 +0,1.649800,0.0,0.0,0.0,0.0,0.0 +0,1.649900,0.0,0.0,0.0,0.0,0.0 +0,1.650000,0.0,0.0,0.0,0.0,0.0 +0,1.650100,0.0,0.0,0.0,0.0,0.0 +0,1.650200,0.0,0.0,0.0,0.0,0.0 +0,1.650300,0.0,0.0,0.0,0.0,0.0 +0,1.650400,0.0,0.0,0.0,0.0,0.0 +0,1.650500,0.0,0.0,0.0,0.0,0.0 +0,1.650600,0.0,0.0,0.0,0.0,0.0 +0,1.650700,0.0,0.0,0.0,0.0,0.0 +0,1.650800,0.0,0.0,0.0,0.0,0.0 +0,1.650900,0.0,0.0,0.0,0.0,0.0 +0,1.651000,0.0,0.0,0.0,0.0,0.0 +0,1.651100,0.0,0.0,0.0,0.0,0.0 +0,1.651200,0.0,0.0,0.0,0.0,0.0 +0,1.651300,0.0,0.0,0.0,0.0,0.0 +0,1.651400,0.0,0.0,0.0,0.0,0.0 +0,1.651500,0.0,0.0,0.0,0.0,0.0 +0,1.651600,0.0,0.0,0.0,0.0,0.0 +0,1.651700,0.0,0.0,0.0,0.0,0.0 +0,1.651800,0.0,0.0,0.0,0.0,0.0 +0,1.651900,0.0,0.0,0.0,0.0,0.0 +0,1.652000,0.0,0.0,0.0,0.0,0.0 +0,1.652100,0.0,0.0,0.0,0.0,0.0 +0,1.652200,0.0,0.0,0.0,0.0,0.0 +0,1.652300,0.0,0.0,0.0,0.0,0.0 +0,1.652400,0.0,0.0,0.0,0.0,0.0 +0,1.652500,0.0,0.0,0.0,0.0,0.0 +0,1.652600,0.0,0.0,0.0,0.0,0.0 +0,1.652700,0.0,0.0,0.0,0.0,0.0 +0,1.652800,0.0,0.0,0.0,0.0,0.0 +0,1.652900,0.0,0.0,0.0,0.0,0.0 +0,1.653000,0.0,0.0,0.0,0.0,0.0 +0,1.653100,0.0,0.0,0.0,0.0,0.0 +0,1.653200,0.0,0.0,0.0,0.0,0.0 +0,1.653300,0.0,0.0,0.0,0.0,0.0 +0,1.653400,0.0,0.0,0.0,0.0,0.0 +0,1.653500,0.0,0.0,0.0,0.0,0.0 +0,1.653600,0.0,0.0,0.0,0.0,0.0 +0,1.653700,0.0,0.0,0.0,0.0,0.0 +0,1.653800,0.0,0.0,0.0,0.0,0.0 +0,1.653900,0.0,0.0,0.0,0.0,0.0 +0,1.654000,0.0,0.0,0.0,0.0,0.0 +0,1.654100,0.0,0.0,0.0,0.0,0.0 +0,1.654200,0.0,0.0,0.0,0.0,0.0 +0,1.654300,0.0,0.0,0.0,0.0,0.0 +0,1.654400,0.0,0.0,0.0,0.0,0.0 +0,1.654500,0.0,0.0,0.0,0.0,0.0 +0,1.654600,0.0,0.0,0.0,0.0,0.0 +0,1.654700,0.0,0.0,0.0,0.0,0.0 +0,1.654800,0.0,0.0,0.0,0.0,0.0 +0,1.654900,0.0,0.0,0.0,0.0,0.0 +0,1.655000,0.0,0.0,0.0,0.0,0.0 +0,1.655100,0.0,0.0,0.0,0.0,0.0 +0,1.655200,0.0,0.0,0.0,0.0,0.0 +0,1.655300,0.0,0.0,0.0,0.0,0.0 +0,1.655400,0.0,0.0,0.0,0.0,0.0 +0,1.655500,0.0,0.0,0.0,0.0,0.0 +0,1.655600,0.0,0.0,0.0,0.0,0.0 +0,1.655700,0.0,0.0,0.0,0.0,0.0 +0,1.655800,0.0,0.0,0.0,0.0,0.0 +0,1.655900,0.0,0.0,0.0,0.0,0.0 +0,1.656000,0.0,0.0,0.0,0.0,0.0 +0,1.656100,0.0,0.0,0.0,0.0,0.0 +0,1.656200,0.0,0.0,0.0,0.0,0.0 +0,1.656300,0.0,0.0,0.0,0.0,0.0 +0,1.656400,0.0,0.0,0.0,0.0,0.0 +0,1.656500,0.0,0.0,0.0,0.0,0.0 +0,1.656600,0.0,0.0,0.0,0.0,0.0 +0,1.656700,0.0,0.0,0.0,0.0,0.0 +0,1.656800,0.0,0.0,0.0,0.0,0.0 +0,1.656900,0.0,0.0,0.0,0.0,0.0 +0,1.657000,0.0,0.0,0.0,0.0,0.0 +0,1.657100,0.0,0.0,0.0,0.0,0.0 +0,1.657200,0.0,0.0,0.0,0.0,0.0 +0,1.657300,0.0,0.0,0.0,0.0,0.0 +0,1.657400,0.0,0.0,0.0,0.0,0.0 +0,1.657500,0.0,0.0,0.0,0.0,0.0 +0,1.657600,0.0,0.0,0.0,0.0,0.0 +0,1.657700,0.0,0.0,0.0,0.0,0.0 +0,1.657800,0.0,0.0,0.0,0.0,0.0 +0,1.657900,0.0,0.0,0.0,0.0,0.0 +0,1.658000,0.0,0.0,0.0,0.0,0.0 +0,1.658100,0.0,0.0,0.0,0.0,0.0 +0,1.658200,0.0,0.0,0.0,0.0,0.0 +0,1.658300,0.0,0.0,0.0,0.0,0.0 +0,1.658400,0.0,0.0,0.0,0.0,0.0 +0,1.658500,0.0,0.0,0.0,0.0,0.0 +0,1.658600,0.0,0.0,0.0,0.0,0.0 +0,1.658700,0.0,0.0,0.0,0.0,0.0 +0,1.658800,0.0,0.0,0.0,0.0,0.0 +0,1.658900,0.0,0.0,0.0,0.0,0.0 +0,1.659000,0.0,0.0,0.0,0.0,0.0 +0,1.659100,0.0,0.0,0.0,0.0,0.0 +0,1.659200,0.0,0.0,0.0,0.0,0.0 +0,1.659300,0.0,0.0,0.0,0.0,0.0 +0,1.659400,0.0,0.0,0.0,0.0,0.0 +0,1.659500,0.0,0.0,0.0,0.0,0.0 +0,1.659600,0.0,0.0,0.0,0.0,0.0 +0,1.659700,0.0,0.0,0.0,0.0,0.0 +0,1.659800,0.0,0.0,0.0,0.0,0.0 +0,1.659900,0.0,0.0,0.0,0.0,0.0 +0,1.660000,0.0,0.0,0.0,0.0,0.0 +0,1.660100,0.0,0.0,0.0,0.0,0.0 +1,1906.473387,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.660200,0.0,0.0,0.0,0.0,0.0 +0,1.660300,0.0,0.0,0.0,0.0,0.0 +0,1.660400,0.0,0.0,0.0,0.0,0.0 +0,1.660500,0.0,0.0,0.0,0.0,0.0 +0,1.660600,0.0,0.0,0.0,0.0,0.0 +0,1.660700,0.0,0.0,0.0,0.0,0.0 +0,1.660800,0.0,0.0,0.0,0.0,0.0 +0,1.660900,0.0,0.0,0.0,0.0,0.0 +0,1.661000,0.0,0.0,0.0,0.0,0.0 +0,1.661100,0.0,0.0,0.0,0.0,0.0 +0,1.661200,0.0,0.0,0.0,0.0,0.0 +0,1.661300,0.0,0.0,0.0,0.0,0.0 +0,1.661400,0.0,0.0,0.0,0.0,0.0 +0,1.661500,0.0,0.0,0.0,0.0,0.0 +0,1.661600,0.0,0.0,0.0,0.0,0.0 +0,1.661700,0.0,0.0,0.0,0.0,0.0 +0,1.661800,0.0,0.0,0.0,0.0,0.0 +0,1.661900,0.0,0.0,0.0,0.0,0.0 +0,1.662000,0.0,0.0,0.0,0.0,0.0 +0,1.662100,0.0,0.0,0.0,0.0,0.0 +0,1.662200,0.0,0.0,0.0,0.0,0.0 +0,1.662300,0.0,0.0,0.0,0.0,0.0 +0,1.662400,0.0,0.0,0.0,0.0,0.0 +0,1.662500,0.0,0.0,0.0,0.0,0.0 +0,1.662600,0.0,0.0,0.0,0.0,0.0 +0,1.662700,0.0,0.0,0.0,0.0,0.0 +0,1.662800,0.0,0.0,0.0,0.0,0.0 +0,1.662900,0.0,0.0,0.0,0.0,0.0 +0,1.663000,0.0,0.0,0.0,0.0,0.0 +0,1.663100,0.0,0.0,0.0,0.0,0.0 +0,1.663200,0.0,0.0,0.0,0.0,0.0 +0,1.663300,0.0,0.0,0.0,0.0,0.0 +0,1.663400,0.0,0.0,0.0,0.0,0.0 +0,1.663500,0.0,0.0,0.0,0.0,0.0 +0,1.663600,0.0,0.0,0.0,0.0,0.0 +0,1.663700,0.0,0.0,0.0,0.0,0.0 +0,1.663800,0.0,0.0,0.0,0.0,0.0 +0,1.663900,0.0,0.0,0.0,0.0,0.0 +0,1.664000,0.0,0.0,0.0,0.0,0.0 +0,1.664100,0.0,0.0,0.0,0.0,0.0 +0,1.664200,0.0,0.0,0.0,0.0,0.0 +0,1.664300,0.0,0.0,0.0,0.0,0.0 +0,1.664400,0.0,0.0,0.0,0.0,0.0 +0,1.664500,0.0,0.0,0.0,0.0,0.0 +0,1.664600,0.0,0.0,0.0,0.0,0.0 +0,1.664700,0.0,0.0,0.0,0.0,0.0 +0,1.664800,0.0,0.0,0.0,0.0,0.0 +0,1.664900,0.0,0.0,0.0,0.0,0.0 +0,1.665000,0.0,0.0,0.0,0.0,0.0 +0,1.665100,0.0,0.0,0.0,0.0,0.0 +0,1.665200,0.0,0.0,0.0,0.0,0.0 +0,1.665300,0.0,0.0,0.0,0.0,0.0 +0,1.665400,0.0,0.0,0.0,0.0,0.0 +0,1.665500,0.0,0.0,0.0,0.0,0.0 +0,1.665600,0.0,0.0,0.0,0.0,0.0 +0,1.665700,0.0,0.0,0.0,0.0,0.0 +0,1.665800,0.0,0.0,0.0,0.0,0.0 +0,1.665900,0.0,0.0,0.0,0.0,0.0 +0,1.666000,0.0,0.0,0.0,0.0,0.0 +0,1.666100,0.0,0.0,0.0,0.0,0.0 +0,1.666200,0.0,0.0,0.0,0.0,0.0 +0,1.666300,0.0,0.0,0.0,0.0,0.0 +0,1.666400,0.0,0.0,0.0,0.0,0.0 +0,1.666500,0.0,0.0,0.0,0.0,0.0 +0,1.666600,0.0,0.0,0.0,0.0,0.0 +0,1.666700,0.0,0.0,0.0,0.0,0.0 +0,1.666800,0.0,0.0,0.0,0.0,0.0 +0,1.666900,0.0,0.0,0.0,0.0,0.0 +0,1.667000,0.0,0.0,0.0,0.0,0.0 +0,1.667100,0.0,0.0,0.0,0.0,0.0 +0,1.667200,0.0,0.0,0.0,0.0,0.0 +0,1.667300,0.0,0.0,0.0,0.0,0.0 +0,1.667400,0.0,0.0,0.0,0.0,0.0 +0,1.667500,0.0,0.0,0.0,0.0,0.0 +0,1.667600,0.0,0.0,0.0,0.0,0.0 +0,1.667700,0.0,0.0,0.0,0.0,0.0 +0,1.667800,0.0,0.0,0.0,0.0,0.0 +0,1.667900,0.0,0.0,0.0,0.0,0.0 +0,1.668000,0.0,0.0,0.0,0.0,0.0 +0,1.668100,0.0,0.0,0.0,0.0,0.0 +0,1.668200,0.0,0.0,0.0,0.0,0.0 +0,1.668300,0.0,0.0,0.0,0.0,0.0 +0,1.668400,0.0,0.0,0.0,0.0,0.0 +0,1.668500,0.0,0.0,0.0,0.0,0.0 +0,1.668600,0.0,0.0,0.0,0.0,0.0 +0,1.668700,0.0,0.0,0.0,0.0,0.0 +0,1.668800,0.0,0.0,0.0,0.0,0.0 +0,1.668900,0.0,0.0,0.0,0.0,0.0 +0,1.669000,0.0,0.0,0.0,0.0,0.0 +0,1.669100,0.0,0.0,0.0,0.0,0.0 +0,1.669200,0.0,0.0,0.0,0.0,0.0 +0,1.669300,0.0,0.0,0.0,0.0,0.0 +0,1.669400,0.0,0.0,0.0,0.0,0.0 +0,1.669500,0.0,0.0,0.0,0.0,0.0 +0,1.669600,0.0,0.0,0.0,0.0,0.0 +0,1.669700,0.0,0.0,0.0,0.0,0.0 +0,1.669800,0.0,0.0,0.0,0.0,0.0 +0,1.669900,0.0,0.0,0.0,0.0,0.0 +0,1.670000,0.0,0.0,0.0,0.0,0.0 +0,1.670100,0.0,0.0,0.0,0.0,0.0 +0,1.670200,0.0,0.0,0.0,0.0,0.0 +0,1.670300,0.0,0.0,0.0,0.0,0.0 +0,1.670400,0.0,0.0,0.0,0.0,0.0 +0,1.670500,0.0,0.0,0.0,0.0,0.0 +0,1.670600,0.0,0.0,0.0,0.0,0.0 +0,1.670700,0.0,0.0,0.0,0.0,0.0 +0,1.670800,0.0,0.0,0.0,0.0,0.0 +0,1.670900,0.0,0.0,0.0,0.0,0.0 +0,1.671000,0.0,0.0,0.0,0.0,0.0 +0,1.671100,0.0,0.0,0.0,0.0,0.0 +0,1.671200,0.0,0.0,0.0,0.0,0.0 +0,1.671300,0.0,0.0,0.0,0.0,0.0 +0,1.671400,0.0,0.0,0.0,0.0,0.0 +0,1.671500,0.0,0.0,0.0,0.0,0.0 +0,1.671600,0.0,0.0,0.0,0.0,0.0 +0,1.671700,0.0,0.0,0.0,0.0,0.0 +0,1.671800,0.0,0.0,0.0,0.0,0.0 +0,1.671900,0.0,0.0,0.0,0.0,0.0 +0,1.672000,0.0,0.0,0.0,0.0,0.0 +0,1.672100,0.0,0.0,0.0,0.0,0.0 +0,1.672200,0.0,0.0,0.0,0.0,0.0 +0,1.672300,0.0,0.0,0.0,0.0,0.0 +0,1.672400,0.0,0.0,0.0,0.0,0.0 +0,1.672500,0.0,0.0,0.0,0.0,0.0 +0,1.672600,0.0,0.0,0.0,0.0,0.0 +0,1.672700,0.0,0.0,0.0,0.0,0.0 +0,1.672800,0.0,0.0,0.0,0.0,0.0 +0,1.672900,0.0,0.0,0.0,0.0,0.0 +0,1.673000,0.0,0.0,0.0,0.0,0.0 +0,1.673100,0.0,0.0,0.0,0.0,0.0 +0,1.673200,0.0,0.0,0.0,0.0,0.0 +0,1.673300,0.0,0.0,0.0,0.0,0.0 +0,1.673400,0.0,0.0,0.0,0.0,0.0 +0,1.673500,0.0,0.0,0.0,0.0,0.0 +0,1.673600,0.0,0.0,0.0,0.0,0.0 +0,1.673700,0.0,0.0,0.0,0.0,0.0 +0,1.673800,0.0,0.0,0.0,0.0,0.0 +0,1.673900,0.0,0.0,0.0,0.0,0.0 +0,1.674000,0.0,0.0,0.0,0.0,0.0 +0,1.674100,0.0,0.0,0.0,0.0,0.0 +0,1.674200,0.0,0.0,0.0,0.0,0.0 +0,1.674300,0.0,0.0,0.0,0.0,0.0 +0,1.674400,0.0,0.0,0.0,0.0,0.0 +0,1.674500,0.0,0.0,0.0,0.0,0.0 +0,1.674600,0.0,0.0,0.0,0.0,0.0 +0,1.674700,0.0,0.0,0.0,0.0,0.0 +0,1.674800,0.0,0.0,0.0,0.0,0.0 +0,1.674900,0.0,0.0,0.0,0.0,0.0 +0,1.675000,0.0,0.0,0.0,0.0,0.0 +0,1.675100,0.0,0.0,0.0,0.0,0.0 +0,1.675200,0.0,0.0,0.0,0.0,0.0 +0,1.675300,0.0,0.0,0.0,0.0,0.0 +0,1.675400,0.0,0.0,0.0,0.0,0.0 +0,1.675500,0.0,0.0,0.0,0.0,0.0 +0,1.675600,0.0,0.0,0.0,0.0,0.0 +0,1.675700,0.0,0.0,0.0,0.0,0.0 +0,1.675800,0.0,0.0,0.0,0.0,0.0 +0,1.675900,0.0,0.0,0.0,0.0,0.0 +0,1.676000,0.0,0.0,0.0,0.0,0.0 +0,1.676100,0.0,0.0,0.0,0.0,0.0 +0,1.676200,0.0,0.0,0.0,0.0,0.0 +0,1.676300,0.0,0.0,0.0,0.0,0.0 +0,1.676400,0.0,0.0,0.0,0.0,0.0 +0,1.676500,0.0,0.0,0.0,0.0,0.0 +0,1.676600,0.0,0.0,0.0,0.0,0.0 +0,1.676700,0.0,0.0,0.0,0.0,0.0 +0,1.676800,0.0,0.0,0.0,0.0,0.0 +0,1.676900,0.0,0.0,0.0,0.0,0.0 +0,1.677000,0.0,0.0,0.0,0.0,0.0 +0,1.677100,0.0,0.0,0.0,0.0,0.0 +0,1.677200,0.0,0.0,0.0,0.0,0.0 +0,1.677300,0.0,0.0,0.0,0.0,0.0 +0,1.677400,0.0,0.0,0.0,0.0,0.0 +0,1.677500,0.0,0.0,0.0,0.0,0.0 +0,1.677600,0.0,0.0,0.0,0.0,0.0 +0,1.677700,0.0,0.0,0.0,0.0,0.0 +0,1.677800,0.0,0.0,0.0,0.0,0.0 +0,1.677900,0.0,0.0,0.0,0.0,0.0 +0,1.678000,0.0,0.0,0.0,0.0,0.0 +0,1.678100,0.0,0.0,0.0,0.0,0.0 +0,1.678200,0.0,0.0,0.0,0.0,0.0 +0,1.678300,0.0,0.0,0.0,0.0,0.0 +0,1.678400,0.0,0.0,0.0,0.0,0.0 +0,1.678500,0.0,0.0,0.0,0.0,0.0 +0,1.678600,0.0,0.0,0.0,0.0,0.0 +0,1.678700,0.0,0.0,0.0,0.0,0.0 +0,1.678800,0.0,0.0,0.0,0.0,0.0 +0,1.678900,0.0,0.0,0.0,0.0,0.0 +0,1.679000,0.0,0.0,0.0,0.0,0.0 +0,1.679100,0.0,0.0,0.0,0.0,0.0 +0,1.679200,0.0,0.0,0.0,0.0,0.0 +0,1.679300,0.0,0.0,0.0,0.0,0.0 +0,1.679400,0.0,0.0,0.0,0.0,0.0 +0,1.679500,0.0,0.0,0.0,0.0,0.0 +0,1.679600,0.0,0.0,0.0,0.0,0.0 +0,1.679700,0.0,0.0,0.0,0.0,0.0 +0,1.679800,0.0,0.0,0.0,0.0,0.0 +0,1.679900,0.0,0.0,0.0,0.0,0.0 +0,1.680000,0.0,0.0,0.0,0.0,0.0 +0,1.680100,0.0,0.0,0.0,0.0,0.0 +1,1976.209246,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.680200,0.0,0.0,0.0,0.0,0.0 +0,1.680300,0.0,0.0,0.0,0.0,0.0 +0,1.680400,0.0,0.0,0.0,0.0,0.0 +0,1.680500,0.0,0.0,0.0,0.0,0.0 +0,1.680600,0.0,0.0,0.0,0.0,0.0 +0,1.680700,0.0,0.0,0.0,0.0,0.0 +0,1.680800,0.0,0.0,0.0,0.0,0.0 +0,1.680900,0.0,0.0,0.0,0.0,0.0 +0,1.681000,0.0,0.0,0.0,0.0,0.0 +0,1.681100,0.0,0.0,0.0,0.0,0.0 +0,1.681200,0.0,0.0,0.0,0.0,0.0 +0,1.681300,0.0,0.0,0.0,0.0,0.0 +0,1.681400,0.0,0.0,0.0,0.0,0.0 +0,1.681500,0.0,0.0,0.0,0.0,0.0 +0,1.681600,0.0,0.0,0.0,0.0,0.0 +0,1.681700,0.0,0.0,0.0,0.0,0.0 +0,1.681800,0.0,0.0,0.0,0.0,0.0 +0,1.681900,0.0,0.0,0.0,0.0,0.0 +0,1.682000,0.0,0.0,0.0,0.0,0.0 +0,1.682100,0.0,0.0,0.0,0.0,0.0 +0,1.682200,0.0,0.0,0.0,0.0,0.0 +0,1.682300,0.0,0.0,0.0,0.0,0.0 +0,1.682400,0.0,0.0,0.0,0.0,0.0 +0,1.682500,0.0,0.0,0.0,0.0,0.0 +0,1.682600,0.0,0.0,0.0,0.0,0.0 +0,1.682700,0.0,0.0,0.0,0.0,0.0 +0,1.682800,0.0,0.0,0.0,0.0,0.0 +0,1.682900,0.0,0.0,0.0,0.0,0.0 +0,1.683000,0.0,0.0,0.0,0.0,0.0 +0,1.683100,0.0,0.0,0.0,0.0,0.0 +0,1.683200,0.0,0.0,0.0,0.0,0.0 +0,1.683300,0.0,0.0,0.0,0.0,0.0 +0,1.683400,0.0,0.0,0.0,0.0,0.0 +0,1.683500,0.0,0.0,0.0,0.0,0.0 +0,1.683600,0.0,0.0,0.0,0.0,0.0 +0,1.683700,0.0,0.0,0.0,0.0,0.0 +0,1.683800,0.0,0.0,0.0,0.0,0.0 +0,1.683900,0.0,0.0,0.0,0.0,0.0 +0,1.684000,0.0,0.0,0.0,0.0,0.0 +0,1.684100,0.0,0.0,0.0,0.0,0.0 +0,1.684200,0.0,0.0,0.0,0.0,0.0 +0,1.684300,0.0,0.0,0.0,0.0,0.0 +0,1.684400,0.0,0.0,0.0,0.0,0.0 +0,1.684500,0.0,0.0,0.0,0.0,0.0 +0,1.684600,0.0,0.0,0.0,0.0,0.0 +0,1.684700,0.0,0.0,0.0,0.0,0.0 +0,1.684800,0.0,0.0,0.0,0.0,0.0 +0,1.684900,0.0,0.0,0.0,0.0,0.0 +0,1.685000,0.0,0.0,0.0,0.0,0.0 +0,1.685100,0.0,0.0,0.0,0.0,0.0 +0,1.685200,0.0,0.0,0.0,0.0,0.0 +0,1.685300,0.0,0.0,0.0,0.0,0.0 +0,1.685400,0.0,0.0,0.0,0.0,0.0 +0,1.685500,0.0,0.0,0.0,0.0,0.0 +0,1.685600,0.0,0.0,0.0,0.0,0.0 +0,1.685700,0.0,0.0,0.0,0.0,0.0 +0,1.685800,0.0,0.0,0.0,0.0,0.0 +0,1.685900,0.0,0.0,0.0,0.0,0.0 +0,1.686000,0.0,0.0,0.0,0.0,0.0 +0,1.686100,0.0,0.0,0.0,0.0,0.0 +0,1.686200,0.0,0.0,0.0,0.0,0.0 +0,1.686300,0.0,0.0,0.0,0.0,0.0 +0,1.686400,0.0,0.0,0.0,0.0,0.0 +0,1.686500,0.0,0.0,0.0,0.0,0.0 +0,1.686600,0.0,0.0,0.0,0.0,0.0 +0,1.686700,0.0,0.0,0.0,0.0,0.0 +0,1.686800,0.0,0.0,0.0,0.0,0.0 +0,1.686900,0.0,0.0,0.0,0.0,0.0 +0,1.687000,0.0,0.0,0.0,0.0,0.0 +0,1.687100,0.0,0.0,0.0,0.0,0.0 +0,1.687200,0.0,0.0,0.0,0.0,0.0 +0,1.687300,0.0,0.0,0.0,0.0,0.0 +0,1.687400,0.0,0.0,0.0,0.0,0.0 +0,1.687500,0.0,0.0,0.0,0.0,0.0 +0,1.687600,0.0,0.0,0.0,0.0,0.0 +0,1.687700,0.0,0.0,0.0,0.0,0.0 +0,1.687800,0.0,0.0,0.0,0.0,0.0 +0,1.687900,0.0,0.0,0.0,0.0,0.0 +0,1.688000,0.0,0.0,0.0,0.0,0.0 +0,1.688100,0.0,0.0,0.0,0.0,0.0 +0,1.688200,0.0,0.0,0.0,0.0,0.0 +0,1.688300,0.0,0.0,0.0,0.0,0.0 +0,1.688400,0.0,0.0,0.0,0.0,0.0 +0,1.688500,0.0,0.0,0.0,0.0,0.0 +0,1.688600,0.0,0.0,0.0,0.0,0.0 +0,1.688700,0.0,0.0,0.0,0.0,0.0 +0,1.688800,0.0,0.0,0.0,0.0,0.0 +0,1.688900,0.0,0.0,0.0,0.0,0.0 +0,1.689000,0.0,0.0,0.0,0.0,0.0 +0,1.689100,0.0,0.0,0.0,0.0,0.0 +0,1.689200,0.0,0.0,0.0,0.0,0.0 +0,1.689300,0.0,0.0,0.0,0.0,0.0 +0,1.689400,0.0,0.0,0.0,0.0,0.0 +0,1.689500,0.0,0.0,0.0,0.0,0.0 +0,1.689600,0.0,0.0,0.0,0.0,0.0 +0,1.689700,0.0,0.0,0.0,0.0,0.0 +0,1.689800,0.0,0.0,0.0,0.0,0.0 +0,1.689900,0.0,0.0,0.0,0.0,0.0 +0,1.690000,0.0,0.0,0.0,0.0,0.0 +0,1.690100,0.0,0.0,0.0,0.0,0.0 +0,1.690200,0.0,0.0,0.0,0.0,0.0 +0,1.690300,0.0,0.0,0.0,0.0,0.0 +0,1.690400,0.0,0.0,0.0,0.0,0.0 +0,1.690500,0.0,0.0,0.0,0.0,0.0 +0,1.690600,0.0,0.0,0.0,0.0,0.0 +0,1.690700,0.0,0.0,0.0,0.0,0.0 +0,1.690800,0.0,0.0,0.0,0.0,0.0 +0,1.690900,0.0,0.0,0.0,0.0,0.0 +0,1.691000,0.0,0.0,0.0,0.0,0.0 +0,1.691100,0.0,0.0,0.0,0.0,0.0 +0,1.691200,0.0,0.0,0.0,0.0,0.0 +0,1.691300,0.0,0.0,0.0,0.0,0.0 +0,1.691400,0.0,0.0,0.0,0.0,0.0 +0,1.691500,0.0,0.0,0.0,0.0,0.0 +0,1.691600,0.0,0.0,0.0,0.0,0.0 +0,1.691700,0.0,0.0,0.0,0.0,0.0 +0,1.691800,0.0,0.0,0.0,0.0,0.0 +0,1.691900,0.0,0.0,0.0,0.0,0.0 +0,1.692000,0.0,0.0,0.0,0.0,0.0 +0,1.692100,0.0,0.0,0.0,0.0,0.0 +0,1.692200,0.0,0.0,0.0,0.0,0.0 +0,1.692300,0.0,0.0,0.0,0.0,0.0 +0,1.692400,0.0,0.0,0.0,0.0,0.0 +0,1.692500,0.0,0.0,0.0,0.0,0.0 +0,1.692600,0.0,0.0,0.0,0.0,0.0 +0,1.692700,0.0,0.0,0.0,0.0,0.0 +0,1.692800,0.0,0.0,0.0,0.0,0.0 +0,1.692900,0.0,0.0,0.0,0.0,0.0 +0,1.693000,0.0,0.0,0.0,0.0,0.0 +0,1.693100,0.0,0.0,0.0,0.0,0.0 +0,1.693200,0.0,0.0,0.0,0.0,0.0 +0,1.693300,0.0,0.0,0.0,0.0,0.0 +0,1.693400,0.0,0.0,0.0,0.0,0.0 +0,1.693500,0.0,0.0,0.0,0.0,0.0 +0,1.693600,0.0,0.0,0.0,0.0,0.0 +0,1.693700,0.0,0.0,0.0,0.0,0.0 +0,1.693800,0.0,0.0,0.0,0.0,0.0 +0,1.693900,0.0,0.0,0.0,0.0,0.0 +0,1.694000,0.0,0.0,0.0,0.0,0.0 +0,1.694100,0.0,0.0,0.0,0.0,0.0 +0,1.694200,0.0,0.0,0.0,0.0,0.0 +0,1.694300,0.0,0.0,0.0,0.0,0.0 +0,1.694400,0.0,0.0,0.0,0.0,0.0 +0,1.694500,0.0,0.0,0.0,0.0,0.0 +0,1.694600,0.0,0.0,0.0,0.0,0.0 +0,1.694700,0.0,0.0,0.0,0.0,0.0 +0,1.694800,0.0,0.0,0.0,0.0,0.0 +0,1.694900,0.0,0.0,0.0,0.0,0.0 +0,1.695000,0.0,0.0,0.0,0.0,0.0 +0,1.695100,0.0,0.0,0.0,0.0,0.0 +0,1.695200,0.0,0.0,0.0,0.0,0.0 +0,1.695300,0.0,0.0,0.0,0.0,0.0 +0,1.695400,0.0,0.0,0.0,0.0,0.0 +0,1.695500,0.0,0.0,0.0,0.0,0.0 +0,1.695600,0.0,0.0,0.0,0.0,0.0 +0,1.695700,0.0,0.0,0.0,0.0,0.0 +0,1.695800,0.0,0.0,0.0,0.0,0.0 +0,1.695900,0.0,0.0,0.0,0.0,0.0 +0,1.696000,0.0,0.0,0.0,0.0,0.0 +0,1.696100,0.0,0.0,0.0,0.0,0.0 +0,1.696200,0.0,0.0,0.0,0.0,0.0 +0,1.696300,0.0,0.0,0.0,0.0,0.0 +0,1.696400,0.0,0.0,0.0,0.0,0.0 +0,1.696500,0.0,0.0,0.0,0.0,0.0 +0,1.696600,0.0,0.0,0.0,0.0,0.0 +0,1.696700,0.0,0.0,0.0,0.0,0.0 +0,1.696800,0.0,0.0,0.0,0.0,0.0 +0,1.696900,0.0,0.0,0.0,0.0,0.0 +0,1.697000,0.0,0.0,0.0,0.0,0.0 +0,1.697100,0.0,0.0,0.0,0.0,0.0 +0,1.697200,0.0,0.0,0.0,0.0,0.0 +0,1.697300,0.0,0.0,0.0,0.0,0.0 +0,1.697400,0.0,0.0,0.0,0.0,0.0 +0,1.697500,0.0,0.0,0.0,0.0,0.0 +0,1.697600,0.0,0.0,0.0,0.0,0.0 +0,1.697700,0.0,0.0,0.0,0.0,0.0 +0,1.697800,0.0,0.0,0.0,0.0,0.0 +0,1.697900,0.0,0.0,0.0,0.0,0.0 +0,1.698000,0.0,0.0,0.0,0.0,0.0 +0,1.698100,0.0,0.0,0.0,0.0,0.0 +0,1.698200,0.0,0.0,0.0,0.0,0.0 +0,1.698300,0.0,0.0,0.0,0.0,0.0 +0,1.698400,0.0,0.0,0.0,0.0,0.0 +0,1.698500,0.0,0.0,0.0,0.0,0.0 +0,1.698600,0.0,0.0,0.0,0.0,0.0 +0,1.698700,0.0,0.0,0.0,0.0,0.0 +0,1.698800,0.0,0.0,0.0,0.0,0.0 +0,1.698900,0.0,0.0,0.0,0.0,0.0 +0,1.699000,0.0,0.0,0.0,0.0,0.0 +0,1.699100,0.0,0.0,0.0,0.0,0.0 +0,1.699200,0.0,0.0,0.0,0.0,0.0 +0,1.699300,0.0,0.0,0.0,0.0,0.0 +0,1.699400,0.0,0.0,0.0,0.0,0.0 +0,1.699500,0.0,0.0,0.0,0.0,0.0 +0,1.699600,0.0,0.0,0.0,0.0,0.0 +0,1.699700,0.0,0.0,0.0,0.0,0.0 +0,1.699800,0.0,0.0,0.0,0.0,0.0 +0,1.699900,0.0,0.0,0.0,0.0,0.0 +0,1.700000,0.0,0.0,0.0,0.0,0.0 +0,1.700100,0.0,0.0,0.0,0.0,0.0 +1,2047.625254,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.700200,0.0,0.0,0.0,0.0,0.0 +0,1.700300,0.0,0.0,0.0,0.0,0.0 +0,1.700400,0.0,0.0,0.0,0.0,0.0 +0,1.700500,0.0,0.0,0.0,0.0,0.0 +0,1.700600,0.0,0.0,0.0,0.0,0.0 +0,1.700700,0.0,0.0,0.0,0.0,0.0 +0,1.700800,0.0,0.0,0.0,0.0,0.0 +0,1.700900,0.0,0.0,0.0,0.0,0.0 +0,1.701000,0.0,0.0,0.0,0.0,0.0 +0,1.701100,0.0,0.0,0.0,0.0,0.0 +0,1.701200,0.0,0.0,0.0,0.0,0.0 +0,1.701300,0.0,0.0,0.0,0.0,0.0 +0,1.701400,0.0,0.0,0.0,0.0,0.0 +0,1.701500,0.0,0.0,0.0,0.0,0.0 +0,1.701600,0.0,0.0,0.0,0.0,0.0 +0,1.701700,0.0,0.0,0.0,0.0,0.0 +0,1.701800,0.0,0.0,0.0,0.0,0.0 +0,1.701900,0.0,0.0,0.0,0.0,0.0 +0,1.702000,0.0,0.0,0.0,0.0,0.0 +0,1.702100,0.0,0.0,0.0,0.0,0.0 +0,1.702200,0.0,0.0,0.0,0.0,0.0 +0,1.702300,0.0,0.0,0.0,0.0,0.0 +0,1.702400,0.0,0.0,0.0,0.0,0.0 +0,1.702500,0.0,0.0,0.0,0.0,0.0 +0,1.702600,0.0,0.0,0.0,0.0,0.0 +0,1.702700,0.0,0.0,0.0,0.0,0.0 +0,1.702800,0.0,0.0,0.0,0.0,0.0 +0,1.702900,0.0,0.0,0.0,0.0,0.0 +0,1.703000,0.0,0.0,0.0,0.0,0.0 +0,1.703100,0.0,0.0,0.0,0.0,0.0 +0,1.703200,0.0,0.0,0.0,0.0,0.0 +0,1.703300,0.0,0.0,0.0,0.0,0.0 +0,1.703400,0.0,0.0,0.0,0.0,0.0 +0,1.703500,0.0,0.0,0.0,0.0,0.0 +0,1.703600,0.0,0.0,0.0,0.0,0.0 +0,1.703700,0.0,0.0,0.0,0.0,0.0 +0,1.703800,0.0,0.0,0.0,0.0,0.0 +0,1.703900,0.0,0.0,0.0,0.0,0.0 +0,1.704000,0.0,0.0,0.0,0.0,0.0 +0,1.704100,0.0,0.0,0.0,0.0,0.0 +0,1.704200,0.0,0.0,0.0,0.0,0.0 +0,1.704300,0.0,0.0,0.0,0.0,0.0 +0,1.704400,0.0,0.0,0.0,0.0,0.0 +0,1.704500,0.0,0.0,0.0,0.0,0.0 +0,1.704600,0.0,0.0,0.0,0.0,0.0 +0,1.704700,0.0,0.0,0.0,0.0,0.0 +0,1.704800,0.0,0.0,0.0,0.0,0.0 +0,1.704900,0.0,0.0,0.0,0.0,0.0 +0,1.705000,0.0,0.0,0.0,0.0,0.0 +0,1.705100,0.0,0.0,0.0,0.0,0.0 +0,1.705200,0.0,0.0,0.0,0.0,0.0 +0,1.705300,0.0,0.0,0.0,0.0,0.0 +0,1.705400,0.0,0.0,0.0,0.0,0.0 +0,1.705500,0.0,0.0,0.0,0.0,0.0 +0,1.705600,0.0,0.0,0.0,0.0,0.0 +0,1.705700,0.0,0.0,0.0,0.0,0.0 +0,1.705800,0.0,0.0,0.0,0.0,0.0 +0,1.705900,0.0,0.0,0.0,0.0,0.0 +0,1.706000,0.0,0.0,0.0,0.0,0.0 +0,1.706100,0.0,0.0,0.0,0.0,0.0 +0,1.706200,0.0,0.0,0.0,0.0,0.0 +0,1.706300,0.0,0.0,0.0,0.0,0.0 +0,1.706400,0.0,0.0,0.0,0.0,0.0 +0,1.706500,0.0,0.0,0.0,0.0,0.0 +0,1.706600,0.0,0.0,0.0,0.0,0.0 +0,1.706700,0.0,0.0,0.0,0.0,0.0 +0,1.706800,0.0,0.0,0.0,0.0,0.0 +0,1.706900,0.0,0.0,0.0,0.0,0.0 +0,1.707000,0.0,0.0,0.0,0.0,0.0 +0,1.707100,0.0,0.0,0.0,0.0,0.0 +0,1.707200,0.0,0.0,0.0,0.0,0.0 +0,1.707300,0.0,0.0,0.0,0.0,0.0 +0,1.707400,0.0,0.0,0.0,0.0,0.0 +0,1.707500,0.0,0.0,0.0,0.0,0.0 +0,1.707600,0.0,0.0,0.0,0.0,0.0 +0,1.707700,0.0,0.0,0.0,0.0,0.0 +0,1.707800,0.0,0.0,0.0,0.0,0.0 +0,1.707900,0.0,0.0,0.0,0.0,0.0 +0,1.708000,0.0,0.0,0.0,0.0,0.0 +0,1.708100,0.0,0.0,0.0,0.0,0.0 +0,1.708200,0.0,0.0,0.0,0.0,0.0 +0,1.708300,0.0,0.0,0.0,0.0,0.0 +0,1.708400,0.0,0.0,0.0,0.0,0.0 +0,1.708500,0.0,0.0,0.0,0.0,0.0 +0,1.708600,0.0,0.0,0.0,0.0,0.0 +0,1.708700,0.0,0.0,0.0,0.0,0.0 +0,1.708800,0.0,0.0,0.0,0.0,0.0 +0,1.708900,0.0,0.0,0.0,0.0,0.0 +0,1.709000,0.0,0.0,0.0,0.0,0.0 +0,1.709100,0.0,0.0,0.0,0.0,0.0 +0,1.709200,0.0,0.0,0.0,0.0,0.0 +0,1.709300,0.0,0.0,0.0,0.0,0.0 +0,1.709400,0.0,0.0,0.0,0.0,0.0 +0,1.709500,0.0,0.0,0.0,0.0,0.0 +0,1.709600,0.0,0.0,0.0,0.0,0.0 +0,1.709700,0.0,0.0,0.0,0.0,0.0 +0,1.709800,0.0,0.0,0.0,0.0,0.0 +0,1.709900,0.0,0.0,0.0,0.0,0.0 +0,1.710000,0.0,0.0,0.0,0.0,0.0 +0,1.710100,0.0,0.0,0.0,0.0,0.0 +0,1.710200,0.0,0.0,0.0,0.0,0.0 +0,1.710300,0.0,0.0,0.0,0.0,0.0 +0,1.710400,0.0,0.0,0.0,0.0,0.0 +0,1.710500,0.0,0.0,0.0,0.0,0.0 +0,1.710600,0.0,0.0,0.0,0.0,0.0 +0,1.710700,0.0,0.0,0.0,0.0,0.0 +0,1.710800,0.0,0.0,0.0,0.0,0.0 +0,1.710900,0.0,0.0,0.0,0.0,0.0 +0,1.711000,0.0,0.0,0.0,0.0,0.0 +0,1.711100,0.0,0.0,0.0,0.0,0.0 +0,1.711200,0.0,0.0,0.0,0.0,0.0 +0,1.711300,0.0,0.0,0.0,0.0,0.0 +0,1.711400,0.0,0.0,0.0,0.0,0.0 +0,1.711500,0.0,0.0,0.0,0.0,0.0 +0,1.711600,0.0,0.0,0.0,0.0,0.0 +0,1.711700,0.0,0.0,0.0,0.0,0.0 +0,1.711800,0.0,0.0,0.0,0.0,0.0 +0,1.711900,0.0,0.0,0.0,0.0,0.0 +0,1.712000,0.0,0.0,0.0,0.0,0.0 +0,1.712100,0.0,0.0,0.0,0.0,0.0 +0,1.712200,0.0,0.0,0.0,0.0,0.0 +0,1.712300,0.0,0.0,0.0,0.0,0.0 +0,1.712400,0.0,0.0,0.0,0.0,0.0 +0,1.712500,0.0,0.0,0.0,0.0,0.0 +0,1.712600,0.0,0.0,0.0,0.0,0.0 +0,1.712700,0.0,0.0,0.0,0.0,0.0 +0,1.712800,0.0,0.0,0.0,0.0,0.0 +0,1.712900,0.0,0.0,0.0,0.0,0.0 +0,1.713000,0.0,0.0,0.0,0.0,0.0 +0,1.713100,0.0,0.0,0.0,0.0,0.0 +0,1.713200,0.0,0.0,0.0,0.0,0.0 +0,1.713300,0.0,0.0,0.0,0.0,0.0 +0,1.713400,0.0,0.0,0.0,0.0,0.0 +0,1.713500,0.0,0.0,0.0,0.0,0.0 +0,1.713600,0.0,0.0,0.0,0.0,0.0 +0,1.713700,0.0,0.0,0.0,0.0,0.0 +0,1.713800,0.0,0.0,0.0,0.0,0.0 +0,1.713900,0.0,0.0,0.0,0.0,0.0 +0,1.714000,0.0,0.0,0.0,0.0,0.0 +0,1.714100,0.0,0.0,0.0,0.0,0.0 +0,1.714200,0.0,0.0,0.0,0.0,0.0 +0,1.714300,0.0,0.0,0.0,0.0,0.0 +0,1.714400,0.0,0.0,0.0,0.0,0.0 +0,1.714500,0.0,0.0,0.0,0.0,0.0 +0,1.714600,0.0,0.0,0.0,0.0,0.0 +0,1.714700,0.0,0.0,0.0,0.0,0.0 +0,1.714800,0.0,0.0,0.0,0.0,0.0 +0,1.714900,0.0,0.0,0.0,0.0,0.0 +0,1.715000,0.0,0.0,0.0,0.0,0.0 +0,1.715100,0.0,0.0,0.0,0.0,0.0 +0,1.715200,0.0,0.0,0.0,0.0,0.0 +0,1.715300,0.0,0.0,0.0,0.0,0.0 +0,1.715400,0.0,0.0,0.0,0.0,0.0 +0,1.715500,0.0,0.0,0.0,0.0,0.0 +0,1.715600,0.0,0.0,0.0,0.0,0.0 +0,1.715700,0.0,0.0,0.0,0.0,0.0 +0,1.715800,0.0,0.0,0.0,0.0,0.0 +0,1.715900,0.0,0.0,0.0,0.0,0.0 +0,1.716000,0.0,0.0,0.0,0.0,0.0 +0,1.716100,0.0,0.0,0.0,0.0,0.0 +0,1.716200,0.0,0.0,0.0,0.0,0.0 +0,1.716300,0.0,0.0,0.0,0.0,0.0 +0,1.716400,0.0,0.0,0.0,0.0,0.0 +0,1.716500,0.0,0.0,0.0,0.0,0.0 +0,1.716600,0.0,0.0,0.0,0.0,0.0 +0,1.716700,0.0,0.0,0.0,0.0,0.0 +0,1.716800,0.0,0.0,0.0,0.0,0.0 +0,1.716900,0.0,0.0,0.0,0.0,0.0 +0,1.717000,0.0,0.0,0.0,0.0,0.0 +0,1.717100,0.0,0.0,0.0,0.0,0.0 +0,1.717200,0.0,0.0,0.0,0.0,0.0 +0,1.717300,0.0,0.0,0.0,0.0,0.0 +0,1.717400,0.0,0.0,0.0,0.0,0.0 +0,1.717500,0.0,0.0,0.0,0.0,0.0 +0,1.717600,0.0,0.0,0.0,0.0,0.0 +0,1.717700,0.0,0.0,0.0,0.0,0.0 +0,1.717800,0.0,0.0,0.0,0.0,0.0 +0,1.717900,0.0,0.0,0.0,0.0,0.0 +0,1.718000,0.0,0.0,0.0,0.0,0.0 +0,1.718100,0.0,0.0,0.0,0.0,0.0 +0,1.718200,0.0,0.0,0.0,0.0,0.0 +0,1.718300,0.0,0.0,0.0,0.0,0.0 +0,1.718400,0.0,0.0,0.0,0.0,0.0 +0,1.718500,0.0,0.0,0.0,0.0,0.0 +0,1.718600,0.0,0.0,0.0,0.0,0.0 +0,1.718700,0.0,0.0,0.0,0.0,0.0 +0,1.718800,0.0,0.0,0.0,0.0,0.0 +0,1.718900,0.0,0.0,0.0,0.0,0.0 +0,1.719000,0.0,0.0,0.0,0.0,0.0 +0,1.719100,0.0,0.0,0.0,0.0,0.0 +0,1.719200,0.0,0.0,0.0,0.0,0.0 +0,1.719300,0.0,0.0,0.0,0.0,0.0 +0,1.719400,0.0,0.0,0.0,0.0,0.0 +0,1.719500,0.0,0.0,0.0,0.0,0.0 +0,1.719600,0.0,0.0,0.0,0.0,0.0 +0,1.719700,0.0,0.0,0.0,0.0,0.0 +0,1.719800,0.0,0.0,0.0,0.0,0.0 +0,1.719900,0.0,0.0,0.0,0.0,0.0 +0,1.720000,0.0,0.0,0.0,0.0,0.0 +0,1.720100,0.0,0.0,0.0,0.0,0.0 +1,2120.741413,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.720200,0.0,0.0,0.0,0.0,0.0 +0,1.720300,0.0,0.0,0.0,0.0,0.0 +0,1.720400,0.0,0.0,0.0,0.0,0.0 +0,1.720500,0.0,0.0,0.0,0.0,0.0 +0,1.720600,0.0,0.0,0.0,0.0,0.0 +0,1.720700,0.0,0.0,0.0,0.0,0.0 +0,1.720800,0.0,0.0,0.0,0.0,0.0 +0,1.720900,0.0,0.0,0.0,0.0,0.0 +0,1.721000,0.0,0.0,0.0,0.0,0.0 +0,1.721100,0.0,0.0,0.0,0.0,0.0 +0,1.721200,0.0,0.0,0.0,0.0,0.0 +0,1.721300,0.0,0.0,0.0,0.0,0.0 +0,1.721400,0.0,0.0,0.0,0.0,0.0 +0,1.721500,0.0,0.0,0.0,0.0,0.0 +0,1.721600,0.0,0.0,0.0,0.0,0.0 +0,1.721700,0.0,0.0,0.0,0.0,0.0 +0,1.721800,0.0,0.0,0.0,0.0,0.0 +0,1.721900,0.0,0.0,0.0,0.0,0.0 +0,1.722000,0.0,0.0,0.0,0.0,0.0 +0,1.722100,0.0,0.0,0.0,0.0,0.0 +0,1.722200,0.0,0.0,0.0,0.0,0.0 +0,1.722300,0.0,0.0,0.0,0.0,0.0 +0,1.722400,0.0,0.0,0.0,0.0,0.0 +0,1.722500,0.0,0.0,0.0,0.0,0.0 +0,1.722600,0.0,0.0,0.0,0.0,0.0 +0,1.722700,0.0,0.0,0.0,0.0,0.0 +0,1.722800,0.0,0.0,0.0,0.0,0.0 +0,1.722900,0.0,0.0,0.0,0.0,0.0 +0,1.723000,0.0,0.0,0.0,0.0,0.0 +0,1.723100,0.0,0.0,0.0,0.0,0.0 +0,1.723200,0.0,0.0,0.0,0.0,0.0 +0,1.723300,0.0,0.0,0.0,0.0,0.0 +0,1.723400,0.0,0.0,0.0,0.0,0.0 +0,1.723500,0.0,0.0,0.0,0.0,0.0 +0,1.723600,0.0,0.0,0.0,0.0,0.0 +0,1.723700,0.0,0.0,0.0,0.0,0.0 +0,1.723800,0.0,0.0,0.0,0.0,0.0 +0,1.723900,0.0,0.0,0.0,0.0,0.0 +0,1.724000,0.0,0.0,0.0,0.0,0.0 +0,1.724100,0.0,0.0,0.0,0.0,0.0 +0,1.724200,0.0,0.0,0.0,0.0,0.0 +0,1.724300,0.0,0.0,0.0,0.0,0.0 +0,1.724400,0.0,0.0,0.0,0.0,0.0 +0,1.724500,0.0,0.0,0.0,0.0,0.0 +0,1.724600,0.0,0.0,0.0,0.0,0.0 +0,1.724700,0.0,0.0,0.0,0.0,0.0 +0,1.724800,0.0,0.0,0.0,0.0,0.0 +0,1.724900,0.0,0.0,0.0,0.0,0.0 +0,1.725000,0.0,0.0,0.0,0.0,0.0 +0,1.725100,0.0,0.0,0.0,0.0,0.0 +0,1.725200,0.0,0.0,0.0,0.0,0.0 +0,1.725300,0.0,0.0,0.0,0.0,0.0 +0,1.725400,0.0,0.0,0.0,0.0,0.0 +0,1.725500,0.0,0.0,0.0,0.0,0.0 +0,1.725600,0.0,0.0,0.0,0.0,0.0 +0,1.725700,0.0,0.0,0.0,0.0,0.0 +0,1.725800,0.0,0.0,0.0,0.0,0.0 +0,1.725900,0.0,0.0,0.0,0.0,0.0 +0,1.726000,0.0,0.0,0.0,0.0,0.0 +0,1.726100,0.0,0.0,0.0,0.0,0.0 +0,1.726200,0.0,0.0,0.0,0.0,0.0 +0,1.726300,0.0,0.0,0.0,0.0,0.0 +0,1.726400,0.0,0.0,0.0,0.0,0.0 +0,1.726500,0.0,0.0,0.0,0.0,0.0 +0,1.726600,0.0,0.0,0.0,0.0,0.0 +0,1.726700,0.0,0.0,0.0,0.0,0.0 +0,1.726800,0.0,0.0,0.0,0.0,0.0 +0,1.726900,0.0,0.0,0.0,0.0,0.0 +0,1.727000,0.0,0.0,0.0,0.0,0.0 +0,1.727100,0.0,0.0,0.0,0.0,0.0 +0,1.727200,0.0,0.0,0.0,0.0,0.0 +0,1.727300,0.0,0.0,0.0,0.0,0.0 +0,1.727400,0.0,0.0,0.0,0.0,0.0 +0,1.727500,0.0,0.0,0.0,0.0,0.0 +0,1.727600,0.0,0.0,0.0,0.0,0.0 +0,1.727700,0.0,0.0,0.0,0.0,0.0 +0,1.727800,0.0,0.0,0.0,0.0,0.0 +0,1.727900,0.0,0.0,0.0,0.0,0.0 +0,1.728000,0.0,0.0,0.0,0.0,0.0 +0,1.728100,0.0,0.0,0.0,0.0,0.0 +0,1.728200,0.0,0.0,0.0,0.0,0.0 +0,1.728300,0.0,0.0,0.0,0.0,0.0 +0,1.728400,0.0,0.0,0.0,0.0,0.0 +0,1.728500,0.0,0.0,0.0,0.0,0.0 +0,1.728600,0.0,0.0,0.0,0.0,0.0 +0,1.728700,0.0,0.0,0.0,0.0,0.0 +0,1.728800,0.0,0.0,0.0,0.0,0.0 +0,1.728900,0.0,0.0,0.0,0.0,0.0 +0,1.729000,0.0,0.0,0.0,0.0,0.0 +0,1.729100,0.0,0.0,0.0,0.0,0.0 +0,1.729200,0.0,0.0,0.0,0.0,0.0 +0,1.729300,0.0,0.0,0.0,0.0,0.0 +0,1.729400,0.0,0.0,0.0,0.0,0.0 +0,1.729500,0.0,0.0,0.0,0.0,0.0 +0,1.729600,0.0,0.0,0.0,0.0,0.0 +0,1.729700,0.0,0.0,0.0,0.0,0.0 +0,1.729800,0.0,0.0,0.0,0.0,0.0 +0,1.729900,0.0,0.0,0.0,0.0,0.0 +0,1.730000,0.0,0.0,0.0,0.0,0.0 +0,1.730100,0.0,0.0,0.0,0.0,0.0 +0,1.730200,0.0,0.0,0.0,0.0,0.0 +0,1.730300,0.0,0.0,0.0,0.0,0.0 +0,1.730400,0.0,0.0,0.0,0.0,0.0 +0,1.730500,0.0,0.0,0.0,0.0,0.0 +0,1.730600,0.0,0.0,0.0,0.0,0.0 +0,1.730700,0.0,0.0,0.0,0.0,0.0 +0,1.730800,0.0,0.0,0.0,0.0,0.0 +0,1.730900,0.0,0.0,0.0,0.0,0.0 +0,1.731000,0.0,0.0,0.0,0.0,0.0 +0,1.731100,0.0,0.0,0.0,0.0,0.0 +0,1.731200,0.0,0.0,0.0,0.0,0.0 +0,1.731300,0.0,0.0,0.0,0.0,0.0 +0,1.731400,0.0,0.0,0.0,0.0,0.0 +0,1.731500,0.0,0.0,0.0,0.0,0.0 +0,1.731600,0.0,0.0,0.0,0.0,0.0 +0,1.731700,0.0,0.0,0.0,0.0,0.0 +0,1.731800,0.0,0.0,0.0,0.0,0.0 +0,1.731900,0.0,0.0,0.0,0.0,0.0 +0,1.732000,0.0,0.0,0.0,0.0,0.0 +0,1.732100,0.0,0.0,0.0,0.0,0.0 +0,1.732200,0.0,0.0,0.0,0.0,0.0 +0,1.732300,0.0,0.0,0.0,0.0,0.0 +0,1.732400,0.0,0.0,0.0,0.0,0.0 +0,1.732500,0.0,0.0,0.0,0.0,0.0 +0,1.732600,0.0,0.0,0.0,0.0,0.0 +0,1.732700,0.0,0.0,0.0,0.0,0.0 +0,1.732800,0.0,0.0,0.0,0.0,0.0 +0,1.732900,0.0,0.0,0.0,0.0,0.0 +0,1.733000,0.0,0.0,0.0,0.0,0.0 +0,1.733100,0.0,0.0,0.0,0.0,0.0 +0,1.733200,0.0,0.0,0.0,0.0,0.0 +0,1.733300,0.0,0.0,0.0,0.0,0.0 +0,1.733400,0.0,0.0,0.0,0.0,0.0 +0,1.733500,0.0,0.0,0.0,0.0,0.0 +0,1.733600,0.0,0.0,0.0,0.0,0.0 +0,1.733700,0.0,0.0,0.0,0.0,0.0 +0,1.733800,0.0,0.0,0.0,0.0,0.0 +0,1.733900,0.0,0.0,0.0,0.0,0.0 +0,1.734000,0.0,0.0,0.0,0.0,0.0 +0,1.734100,0.0,0.0,0.0,0.0,0.0 +0,1.734200,0.0,0.0,0.0,0.0,0.0 +0,1.734300,0.0,0.0,0.0,0.0,0.0 +0,1.734400,0.0,0.0,0.0,0.0,0.0 +0,1.734500,0.0,0.0,0.0,0.0,0.0 +0,1.734600,0.0,0.0,0.0,0.0,0.0 +0,1.734700,0.0,0.0,0.0,0.0,0.0 +0,1.734800,0.0,0.0,0.0,0.0,0.0 +0,1.734900,0.0,0.0,0.0,0.0,0.0 +0,1.735000,0.0,0.0,0.0,0.0,0.0 +0,1.735100,0.0,0.0,0.0,0.0,0.0 +0,1.735200,0.0,0.0,0.0,0.0,0.0 +0,1.735300,0.0,0.0,0.0,0.0,0.0 +0,1.735400,0.0,0.0,0.0,0.0,0.0 +0,1.735500,0.0,0.0,0.0,0.0,0.0 +0,1.735600,0.0,0.0,0.0,0.0,0.0 +0,1.735700,0.0,0.0,0.0,0.0,0.0 +0,1.735800,0.0,0.0,0.0,0.0,0.0 +0,1.735900,0.0,0.0,0.0,0.0,0.0 +0,1.736000,0.0,0.0,0.0,0.0,0.0 +0,1.736100,0.0,0.0,0.0,0.0,0.0 +0,1.736200,0.0,0.0,0.0,0.0,0.0 +0,1.736300,0.0,0.0,0.0,0.0,0.0 +0,1.736400,0.0,0.0,0.0,0.0,0.0 +0,1.736500,0.0,0.0,0.0,0.0,0.0 +0,1.736600,0.0,0.0,0.0,0.0,0.0 +0,1.736700,0.0,0.0,0.0,0.0,0.0 +0,1.736800,0.0,0.0,0.0,0.0,0.0 +0,1.736900,0.0,0.0,0.0,0.0,0.0 +0,1.737000,0.0,0.0,0.0,0.0,0.0 +0,1.737100,0.0,0.0,0.0,0.0,0.0 +0,1.737200,0.0,0.0,0.0,0.0,0.0 +0,1.737300,0.0,0.0,0.0,0.0,0.0 +0,1.737400,0.0,0.0,0.0,0.0,0.0 +0,1.737500,0.0,0.0,0.0,0.0,0.0 +0,1.737600,0.0,0.0,0.0,0.0,0.0 +0,1.737700,0.0,0.0,0.0,0.0,0.0 +0,1.737800,0.0,0.0,0.0,0.0,0.0 +0,1.737900,0.0,0.0,0.0,0.0,0.0 +0,1.738000,0.0,0.0,0.0,0.0,0.0 +0,1.738100,0.0,0.0,0.0,0.0,0.0 +0,1.738200,0.0,0.0,0.0,0.0,0.0 +0,1.738300,0.0,0.0,0.0,0.0,0.0 +0,1.738400,0.0,0.0,0.0,0.0,0.0 +0,1.738500,0.0,0.0,0.0,0.0,0.0 +0,1.738600,0.0,0.0,0.0,0.0,0.0 +0,1.738700,0.0,0.0,0.0,0.0,0.0 +0,1.738800,0.0,0.0,0.0,0.0,0.0 +0,1.738900,0.0,0.0,0.0,0.0,0.0 +0,1.739000,0.0,0.0,0.0,0.0,0.0 +0,1.739100,0.0,0.0,0.0,0.0,0.0 +0,1.739200,0.0,0.0,0.0,0.0,0.0 +0,1.739300,0.0,0.0,0.0,0.0,0.0 +0,1.739400,0.0,0.0,0.0,0.0,0.0 +0,1.739500,0.0,0.0,0.0,0.0,0.0 +0,1.739600,0.0,0.0,0.0,0.0,0.0 +0,1.739700,0.0,0.0,0.0,0.0,0.0 +0,1.739800,0.0,0.0,0.0,0.0,0.0 +0,1.739900,0.0,0.0,0.0,0.0,0.0 +0,1.740000,0.0,0.0,0.0,0.0,0.0 +0,1.740100,0.0,0.0,0.0,0.0,0.0 +1,2195.577722,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.740200,0.0,0.0,0.0,0.0,0.0 +0,1.740300,0.0,0.0,0.0,0.0,0.0 +0,1.740400,0.0,0.0,0.0,0.0,0.0 +0,1.740500,0.0,0.0,0.0,0.0,0.0 +0,1.740600,0.0,0.0,0.0,0.0,0.0 +0,1.740700,0.0,0.0,0.0,0.0,0.0 +0,1.740800,0.0,0.0,0.0,0.0,0.0 +0,1.740900,0.0,0.0,0.0,0.0,0.0 +0,1.741000,0.0,0.0,0.0,0.0,0.0 +0,1.741100,0.0,0.0,0.0,0.0,0.0 +0,1.741200,0.0,0.0,0.0,0.0,0.0 +0,1.741300,0.0,0.0,0.0,0.0,0.0 +0,1.741400,0.0,0.0,0.0,0.0,0.0 +0,1.741500,0.0,0.0,0.0,0.0,0.0 +0,1.741600,0.0,0.0,0.0,0.0,0.0 +0,1.741700,0.0,0.0,0.0,0.0,0.0 +0,1.741800,0.0,0.0,0.0,0.0,0.0 +0,1.741900,0.0,0.0,0.0,0.0,0.0 +0,1.742000,0.0,0.0,0.0,0.0,0.0 +0,1.742100,0.0,0.0,0.0,0.0,0.0 +0,1.742200,0.0,0.0,0.0,0.0,0.0 +0,1.742300,0.0,0.0,0.0,0.0,0.0 +0,1.742400,0.0,0.0,0.0,0.0,0.0 +0,1.742500,0.0,0.0,0.0,0.0,0.0 +0,1.742600,0.0,0.0,0.0,0.0,0.0 +0,1.742700,0.0,0.0,0.0,0.0,0.0 +0,1.742800,0.0,0.0,0.0,0.0,0.0 +0,1.742900,0.0,0.0,0.0,0.0,0.0 +0,1.743000,0.0,0.0,0.0,0.0,0.0 +0,1.743100,0.0,0.0,0.0,0.0,0.0 +0,1.743200,0.0,0.0,0.0,0.0,0.0 +0,1.743300,0.0,0.0,0.0,0.0,0.0 +0,1.743400,0.0,0.0,0.0,0.0,0.0 +0,1.743500,0.0,0.0,0.0,0.0,0.0 +0,1.743600,0.0,0.0,0.0,0.0,0.0 +0,1.743700,0.0,0.0,0.0,0.0,0.0 +0,1.743800,0.0,0.0,0.0,0.0,0.0 +0,1.743900,0.0,0.0,0.0,0.0,0.0 +0,1.744000,0.0,0.0,0.0,0.0,0.0 +0,1.744100,0.0,0.0,0.0,0.0,0.0 +0,1.744200,0.0,0.0,0.0,0.0,0.0 +0,1.744300,0.0,0.0,0.0,0.0,0.0 +0,1.744400,0.0,0.0,0.0,0.0,0.0 +0,1.744500,0.0,0.0,0.0,0.0,0.0 +0,1.744600,0.0,0.0,0.0,0.0,0.0 +0,1.744700,0.0,0.0,0.0,0.0,0.0 +0,1.744800,0.0,0.0,0.0,0.0,0.0 +0,1.744900,0.0,0.0,0.0,0.0,0.0 +0,1.745000,0.0,0.0,0.0,0.0,0.0 +0,1.745100,0.0,0.0,0.0,0.0,0.0 +0,1.745200,0.0,0.0,0.0,0.0,0.0 +0,1.745300,0.0,0.0,0.0,0.0,0.0 +0,1.745400,0.0,0.0,0.0,0.0,0.0 +0,1.745500,0.0,0.0,0.0,0.0,0.0 +0,1.745600,0.0,0.0,0.0,0.0,0.0 +0,1.745700,0.0,0.0,0.0,0.0,0.0 +0,1.745800,0.0,0.0,0.0,0.0,0.0 +0,1.745900,0.0,0.0,0.0,0.0,0.0 +0,1.746000,0.0,0.0,0.0,0.0,0.0 +0,1.746100,0.0,0.0,0.0,0.0,0.0 +0,1.746200,0.0,0.0,0.0,0.0,0.0 +0,1.746300,0.0,0.0,0.0,0.0,0.0 +0,1.746400,0.0,0.0,0.0,0.0,0.0 +0,1.746500,0.0,0.0,0.0,0.0,0.0 +0,1.746600,0.0,0.0,0.0,0.0,0.0 +0,1.746700,0.0,0.0,0.0,0.0,0.0 +0,1.746800,0.0,0.0,0.0,0.0,0.0 +0,1.746900,0.0,0.0,0.0,0.0,0.0 +0,1.747000,0.0,0.0,0.0,0.0,0.0 +0,1.747100,0.0,0.0,0.0,0.0,0.0 +0,1.747200,0.0,0.0,0.0,0.0,0.0 +0,1.747300,0.0,0.0,0.0,0.0,0.0 +0,1.747400,0.0,0.0,0.0,0.0,0.0 +0,1.747500,0.0,0.0,0.0,0.0,0.0 +0,1.747600,0.0,0.0,0.0,0.0,0.0 +0,1.747700,0.0,0.0,0.0,0.0,0.0 +0,1.747800,0.0,0.0,0.0,0.0,0.0 +0,1.747900,0.0,0.0,0.0,0.0,0.0 +0,1.748000,0.0,0.0,0.0,0.0,0.0 +0,1.748100,0.0,0.0,0.0,0.0,0.0 +0,1.748200,0.0,0.0,0.0,0.0,0.0 +0,1.748300,0.0,0.0,0.0,0.0,0.0 +0,1.748400,0.0,0.0,0.0,0.0,0.0 +0,1.748500,0.0,0.0,0.0,0.0,0.0 +0,1.748600,0.0,0.0,0.0,0.0,0.0 +0,1.748700,0.0,0.0,0.0,0.0,0.0 +0,1.748800,0.0,0.0,0.0,0.0,0.0 +0,1.748900,0.0,0.0,0.0,0.0,0.0 +0,1.749000,0.0,0.0,0.0,0.0,0.0 +0,1.749100,0.0,0.0,0.0,0.0,0.0 +0,1.749200,0.0,0.0,0.0,0.0,0.0 +0,1.749300,0.0,0.0,0.0,0.0,0.0 +0,1.749400,0.0,0.0,0.0,0.0,0.0 +0,1.749500,0.0,0.0,0.0,0.0,0.0 +0,1.749600,0.0,0.0,0.0,0.0,0.0 +0,1.749700,0.0,0.0,0.0,0.0,0.0 +0,1.749800,0.0,0.0,0.0,0.0,0.0 +0,1.749900,0.0,0.0,0.0,0.0,0.0 +0,1.750000,0.0,0.0,0.0,0.0,0.0 +0,1.750100,0.0,0.0,0.0,0.0,0.0 +0,1.750200,0.0,0.0,0.0,0.0,0.0 +0,1.750300,0.0,0.0,0.0,0.0,0.0 +0,1.750400,0.0,0.0,0.0,0.0,0.0 +0,1.750500,0.0,0.0,0.0,0.0,0.0 +0,1.750600,0.0,0.0,0.0,0.0,0.0 +0,1.750700,0.0,0.0,0.0,0.0,0.0 +0,1.750800,0.0,0.0,0.0,0.0,0.0 +0,1.750900,0.0,0.0,0.0,0.0,0.0 +0,1.751000,0.0,0.0,0.0,0.0,0.0 +0,1.751100,0.0,0.0,0.0,0.0,0.0 +0,1.751200,0.0,0.0,0.0,0.0,0.0 +0,1.751300,0.0,0.0,0.0,0.0,0.0 +0,1.751400,0.0,0.0,0.0,0.0,0.0 +0,1.751500,0.0,0.0,0.0,0.0,0.0 +0,1.751600,0.0,0.0,0.0,0.0,0.0 +0,1.751700,0.0,0.0,0.0,0.0,0.0 +0,1.751800,0.0,0.0,0.0,0.0,0.0 +0,1.751900,0.0,0.0,0.0,0.0,0.0 +0,1.752000,0.0,0.0,0.0,0.0,0.0 +0,1.752100,0.0,0.0,0.0,0.0,0.0 +0,1.752200,0.0,0.0,0.0,0.0,0.0 +0,1.752300,0.0,0.0,0.0,0.0,0.0 +0,1.752400,0.0,0.0,0.0,0.0,0.0 +0,1.752500,0.0,0.0,0.0,0.0,0.0 +0,1.752600,0.0,0.0,0.0,0.0,0.0 +0,1.752700,0.0,0.0,0.0,0.0,0.0 +0,1.752800,0.0,0.0,0.0,0.0,0.0 +0,1.752900,0.0,0.0,0.0,0.0,0.0 +0,1.753000,0.0,0.0,0.0,0.0,0.0 +0,1.753100,0.0,0.0,0.0,0.0,0.0 +0,1.753200,0.0,0.0,0.0,0.0,0.0 +0,1.753300,0.0,0.0,0.0,0.0,0.0 +0,1.753400,0.0,0.0,0.0,0.0,0.0 +0,1.753500,0.0,0.0,0.0,0.0,0.0 +0,1.753600,0.0,0.0,0.0,0.0,0.0 +0,1.753700,0.0,0.0,0.0,0.0,0.0 +0,1.753800,0.0,0.0,0.0,0.0,0.0 +0,1.753900,0.0,0.0,0.0,0.0,0.0 +0,1.754000,0.0,0.0,0.0,0.0,0.0 +0,1.754100,0.0,0.0,0.0,0.0,0.0 +0,1.754200,0.0,0.0,0.0,0.0,0.0 +0,1.754300,0.0,0.0,0.0,0.0,0.0 +0,1.754400,0.0,0.0,0.0,0.0,0.0 +0,1.754500,0.0,0.0,0.0,0.0,0.0 +0,1.754600,0.0,0.0,0.0,0.0,0.0 +0,1.754700,0.0,0.0,0.0,0.0,0.0 +0,1.754800,0.0,0.0,0.0,0.0,0.0 +0,1.754900,0.0,0.0,0.0,0.0,0.0 +0,1.755000,0.0,0.0,0.0,0.0,0.0 +0,1.755100,0.0,0.0,0.0,0.0,0.0 +0,1.755200,0.0,0.0,0.0,0.0,0.0 +0,1.755300,0.0,0.0,0.0,0.0,0.0 +0,1.755400,0.0,0.0,0.0,0.0,0.0 +0,1.755500,0.0,0.0,0.0,0.0,0.0 +0,1.755600,0.0,0.0,0.0,0.0,0.0 +0,1.755700,0.0,0.0,0.0,0.0,0.0 +0,1.755800,0.0,0.0,0.0,0.0,0.0 +0,1.755900,0.0,0.0,0.0,0.0,0.0 +0,1.756000,0.0,0.0,0.0,0.0,0.0 +0,1.756100,0.0,0.0,0.0,0.0,0.0 +0,1.756200,0.0,0.0,0.0,0.0,0.0 +0,1.756300,0.0,0.0,0.0,0.0,0.0 +0,1.756400,0.0,0.0,0.0,0.0,0.0 +0,1.756500,0.0,0.0,0.0,0.0,0.0 +0,1.756600,0.0,0.0,0.0,0.0,0.0 +0,1.756700,0.0,0.0,0.0,0.0,0.0 +0,1.756800,0.0,0.0,0.0,0.0,0.0 +0,1.756900,0.0,0.0,0.0,0.0,0.0 +0,1.757000,0.0,0.0,0.0,0.0,0.0 +0,1.757100,0.0,0.0,0.0,0.0,0.0 +0,1.757200,0.0,0.0,0.0,0.0,0.0 +0,1.757300,0.0,0.0,0.0,0.0,0.0 +0,1.757400,0.0,0.0,0.0,0.0,0.0 +0,1.757500,0.0,0.0,0.0,0.0,0.0 +0,1.757600,0.0,0.0,0.0,0.0,0.0 +0,1.757700,0.0,0.0,0.0,0.0,0.0 +0,1.757800,0.0,0.0,0.0,0.0,0.0 +0,1.757900,0.0,0.0,0.0,0.0,0.0 +0,1.758000,0.0,0.0,0.0,0.0,0.0 +0,1.758100,0.0,0.0,0.0,0.0,0.0 +0,1.758200,0.0,0.0,0.0,0.0,0.0 +0,1.758300,0.0,0.0,0.0,0.0,0.0 +0,1.758400,0.0,0.0,0.0,0.0,0.0 +0,1.758500,0.0,0.0,0.0,0.0,0.0 +0,1.758600,0.0,0.0,0.0,0.0,0.0 +0,1.758700,0.0,0.0,0.0,0.0,0.0 +0,1.758800,0.0,0.0,0.0,0.0,0.0 +0,1.758900,0.0,0.0,0.0,0.0,0.0 +0,1.759000,0.0,0.0,0.0,0.0,0.0 +0,1.759100,0.0,0.0,0.0,0.0,0.0 +0,1.759200,0.0,0.0,0.0,0.0,0.0 +0,1.759300,0.0,0.0,0.0,0.0,0.0 +0,1.759400,0.0,0.0,0.0,0.0,0.0 +0,1.759500,0.0,0.0,0.0,0.0,0.0 +0,1.759600,0.0,0.0,0.0,0.0,0.0 +0,1.759700,0.0,0.0,0.0,0.0,0.0 +0,1.759800,0.0,0.0,0.0,0.0,0.0 +0,1.759900,0.0,0.0,0.0,0.0,0.0 +0,1.760000,0.0,0.0,0.0,0.0,0.0 +0,1.760100,0.0,0.0,0.0,0.0,0.0 +1,2272.154181,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.760200,0.0,0.0,0.0,0.0,0.0 +0,1.760300,0.0,0.0,0.0,0.0,0.0 +0,1.760400,0.0,0.0,0.0,0.0,0.0 +0,1.760500,0.0,0.0,0.0,0.0,0.0 +0,1.760600,0.0,0.0,0.0,0.0,0.0 +0,1.760700,0.0,0.0,0.0,0.0,0.0 +0,1.760800,0.0,0.0,0.0,0.0,0.0 +0,1.760900,0.0,0.0,0.0,0.0,0.0 +0,1.761000,0.0,0.0,0.0,0.0,0.0 +0,1.761100,0.0,0.0,0.0,0.0,0.0 +0,1.761200,0.0,0.0,0.0,0.0,0.0 +0,1.761300,0.0,0.0,0.0,0.0,0.0 +0,1.761400,0.0,0.0,0.0,0.0,0.0 +0,1.761500,0.0,0.0,0.0,0.0,0.0 +0,1.761600,0.0,0.0,0.0,0.0,0.0 +0,1.761700,0.0,0.0,0.0,0.0,0.0 +0,1.761800,0.0,0.0,0.0,0.0,0.0 +0,1.761900,0.0,0.0,0.0,0.0,0.0 +0,1.762000,0.0,0.0,0.0,0.0,0.0 +0,1.762100,0.0,0.0,0.0,0.0,0.0 +0,1.762200,0.0,0.0,0.0,0.0,0.0 +0,1.762300,0.0,0.0,0.0,0.0,0.0 +0,1.762400,0.0,0.0,0.0,0.0,0.0 +0,1.762500,0.0,0.0,0.0,0.0,0.0 +0,1.762600,0.0,0.0,0.0,0.0,0.0 +0,1.762700,0.0,0.0,0.0,0.0,0.0 +0,1.762800,0.0,0.0,0.0,0.0,0.0 +0,1.762900,0.0,0.0,0.0,0.0,0.0 +0,1.763000,0.0,0.0,0.0,0.0,0.0 +0,1.763100,0.0,0.0,0.0,0.0,0.0 +0,1.763200,0.0,0.0,0.0,0.0,0.0 +0,1.763300,0.0,0.0,0.0,0.0,0.0 +0,1.763400,0.0,0.0,0.0,0.0,0.0 +0,1.763500,0.0,0.0,0.0,0.0,0.0 +0,1.763600,0.0,0.0,0.0,0.0,0.0 +0,1.763700,0.0,0.0,0.0,0.0,0.0 +0,1.763800,0.0,0.0,0.0,0.0,0.0 +0,1.763900,0.0,0.0,0.0,0.0,0.0 +0,1.764000,0.0,0.0,0.0,0.0,0.0 +0,1.764100,0.0,0.0,0.0,0.0,0.0 +0,1.764200,0.0,0.0,0.0,0.0,0.0 +0,1.764300,0.0,0.0,0.0,0.0,0.0 +0,1.764400,0.0,0.0,0.0,0.0,0.0 +0,1.764500,0.0,0.0,0.0,0.0,0.0 +0,1.764600,0.0,0.0,0.0,0.0,0.0 +0,1.764700,0.0,0.0,0.0,0.0,0.0 +0,1.764800,0.0,0.0,0.0,0.0,0.0 +0,1.764900,0.0,0.0,0.0,0.0,0.0 +0,1.765000,0.0,0.0,0.0,0.0,0.0 +0,1.765100,0.0,0.0,0.0,0.0,0.0 +0,1.765200,0.0,0.0,0.0,0.0,0.0 +0,1.765300,0.0,0.0,0.0,0.0,0.0 +0,1.765400,0.0,0.0,0.0,0.0,0.0 +0,1.765500,0.0,0.0,0.0,0.0,0.0 +0,1.765600,0.0,0.0,0.0,0.0,0.0 +0,1.765700,0.0,0.0,0.0,0.0,0.0 +0,1.765800,0.0,0.0,0.0,0.0,0.0 +0,1.765900,0.0,0.0,0.0,0.0,0.0 +0,1.766000,0.0,0.0,0.0,0.0,0.0 +0,1.766100,0.0,0.0,0.0,0.0,0.0 +0,1.766200,0.0,0.0,0.0,0.0,0.0 +0,1.766300,0.0,0.0,0.0,0.0,0.0 +0,1.766400,0.0,0.0,0.0,0.0,0.0 +0,1.766500,0.0,0.0,0.0,0.0,0.0 +0,1.766600,0.0,0.0,0.0,0.0,0.0 +0,1.766700,0.0,0.0,0.0,0.0,0.0 +0,1.766800,0.0,0.0,0.0,0.0,0.0 +0,1.766900,0.0,0.0,0.0,0.0,0.0 +0,1.767000,0.0,0.0,0.0,0.0,0.0 +0,1.767100,0.0,0.0,0.0,0.0,0.0 +0,1.767200,0.0,0.0,0.0,0.0,0.0 +0,1.767300,0.0,0.0,0.0,0.0,0.0 +0,1.767400,0.0,0.0,0.0,0.0,0.0 +0,1.767500,0.0,0.0,0.0,0.0,0.0 +0,1.767600,0.0,0.0,0.0,0.0,0.0 +0,1.767700,0.0,0.0,0.0,0.0,0.0 +0,1.767800,0.0,0.0,0.0,0.0,0.0 +0,1.767900,0.0,0.0,0.0,0.0,0.0 +0,1.768000,0.0,0.0,0.0,0.0,0.0 +0,1.768100,0.0,0.0,0.0,0.0,0.0 +0,1.768200,0.0,0.0,0.0,0.0,0.0 +0,1.768300,0.0,0.0,0.0,0.0,0.0 +0,1.768400,0.0,0.0,0.0,0.0,0.0 +0,1.768500,0.0,0.0,0.0,0.0,0.0 +0,1.768600,0.0,0.0,0.0,0.0,0.0 +0,1.768700,0.0,0.0,0.0,0.0,0.0 +0,1.768800,0.0,0.0,0.0,0.0,0.0 +0,1.768900,0.0,0.0,0.0,0.0,0.0 +0,1.769000,0.0,0.0,0.0,0.0,0.0 +0,1.769100,0.0,0.0,0.0,0.0,0.0 +0,1.769200,0.0,0.0,0.0,0.0,0.0 +0,1.769300,0.0,0.0,0.0,0.0,0.0 +0,1.769400,0.0,0.0,0.0,0.0,0.0 +0,1.769500,0.0,0.0,0.0,0.0,0.0 +0,1.769600,0.0,0.0,0.0,0.0,0.0 +0,1.769700,0.0,0.0,0.0,0.0,0.0 +0,1.769800,0.0,0.0,0.0,0.0,0.0 +0,1.769900,0.0,0.0,0.0,0.0,0.0 +0,1.770000,0.0,0.0,0.0,0.0,0.0 +0,1.770100,0.0,0.0,0.0,0.0,0.0 +0,1.770200,0.0,0.0,0.0,0.0,0.0 +0,1.770300,0.0,0.0,0.0,0.0,0.0 +0,1.770400,0.0,0.0,0.0,0.0,0.0 +0,1.770500,0.0,0.0,0.0,0.0,0.0 +0,1.770600,0.0,0.0,0.0,0.0,0.0 +0,1.770700,0.0,0.0,0.0,0.0,0.0 +0,1.770800,0.0,0.0,0.0,0.0,0.0 +0,1.770900,0.0,0.0,0.0,0.0,0.0 +0,1.771000,0.0,0.0,0.0,0.0,0.0 +0,1.771100,0.0,0.0,0.0,0.0,0.0 +0,1.771200,0.0,0.0,0.0,0.0,0.0 +0,1.771300,0.0,0.0,0.0,0.0,0.0 +0,1.771400,0.0,0.0,0.0,0.0,0.0 +0,1.771500,0.0,0.0,0.0,0.0,0.0 +0,1.771600,0.0,0.0,0.0,0.0,0.0 +0,1.771700,0.0,0.0,0.0,0.0,0.0 +0,1.771800,0.0,0.0,0.0,0.0,0.0 +0,1.771900,0.0,0.0,0.0,0.0,0.0 +0,1.772000,0.0,0.0,0.0,0.0,0.0 +0,1.772100,0.0,0.0,0.0,0.0,0.0 +0,1.772200,0.0,0.0,0.0,0.0,0.0 +0,1.772300,0.0,0.0,0.0,0.0,0.0 +0,1.772400,0.0,0.0,0.0,0.0,0.0 +0,1.772500,0.0,0.0,0.0,0.0,0.0 +0,1.772600,0.0,0.0,0.0,0.0,0.0 +0,1.772700,0.0,0.0,0.0,0.0,0.0 +0,1.772800,0.0,0.0,0.0,0.0,0.0 +0,1.772900,0.0,0.0,0.0,0.0,0.0 +0,1.773000,0.0,0.0,0.0,0.0,0.0 +0,1.773100,0.0,0.0,0.0,0.0,0.0 +0,1.773200,0.0,0.0,0.0,0.0,0.0 +0,1.773300,0.0,0.0,0.0,0.0,0.0 +0,1.773400,0.0,0.0,0.0,0.0,0.0 +0,1.773500,0.0,0.0,0.0,0.0,0.0 +0,1.773600,0.0,0.0,0.0,0.0,0.0 +0,1.773700,0.0,0.0,0.0,0.0,0.0 +0,1.773800,0.0,0.0,0.0,0.0,0.0 +0,1.773900,0.0,0.0,0.0,0.0,0.0 +0,1.774000,0.0,0.0,0.0,0.0,0.0 +0,1.774100,0.0,0.0,0.0,0.0,0.0 +0,1.774200,0.0,0.0,0.0,0.0,0.0 +0,1.774300,0.0,0.0,0.0,0.0,0.0 +0,1.774400,0.0,0.0,0.0,0.0,0.0 +0,1.774500,0.0,0.0,0.0,0.0,0.0 +0,1.774600,0.0,0.0,0.0,0.0,0.0 +0,1.774700,0.0,0.0,0.0,0.0,0.0 +0,1.774800,0.0,0.0,0.0,0.0,0.0 +0,1.774900,0.0,0.0,0.0,0.0,0.0 +0,1.775000,0.0,0.0,0.0,0.0,0.0 +0,1.775100,0.0,0.0,0.0,0.0,0.0 +0,1.775200,0.0,0.0,0.0,0.0,0.0 +0,1.775300,0.0,0.0,0.0,0.0,0.0 +0,1.775400,0.0,0.0,0.0,0.0,0.0 +0,1.775500,0.0,0.0,0.0,0.0,0.0 +0,1.775600,0.0,0.0,0.0,0.0,0.0 +0,1.775700,0.0,0.0,0.0,0.0,0.0 +0,1.775800,0.0,0.0,0.0,0.0,0.0 +0,1.775900,0.0,0.0,0.0,0.0,0.0 +0,1.776000,0.0,0.0,0.0,0.0,0.0 +0,1.776100,0.0,0.0,0.0,0.0,0.0 +0,1.776200,0.0,0.0,0.0,0.0,0.0 +0,1.776300,0.0,0.0,0.0,0.0,0.0 +0,1.776400,0.0,0.0,0.0,0.0,0.0 +0,1.776500,0.0,0.0,0.0,0.0,0.0 +0,1.776600,0.0,0.0,0.0,0.0,0.0 +0,1.776700,0.0,0.0,0.0,0.0,0.0 +0,1.776800,0.0,0.0,0.0,0.0,0.0 +0,1.776900,0.0,0.0,0.0,0.0,0.0 +0,1.777000,0.0,0.0,0.0,0.0,0.0 +0,1.777100,0.0,0.0,0.0,0.0,0.0 +0,1.777200,0.0,0.0,0.0,0.0,0.0 +0,1.777300,0.0,0.0,0.0,0.0,0.0 +0,1.777400,0.0,0.0,0.0,0.0,0.0 +0,1.777500,0.0,0.0,0.0,0.0,0.0 +0,1.777600,0.0,0.0,0.0,0.0,0.0 +0,1.777700,0.0,0.0,0.0,0.0,0.0 +0,1.777800,0.0,0.0,0.0,0.0,0.0 +0,1.777900,0.0,0.0,0.0,0.0,0.0 +0,1.778000,0.0,0.0,0.0,0.0,0.0 +0,1.778100,0.0,0.0,0.0,0.0,0.0 +0,1.778200,0.0,0.0,0.0,0.0,0.0 +0,1.778300,0.0,0.0,0.0,0.0,0.0 +0,1.778400,0.0,0.0,0.0,0.0,0.0 +0,1.778500,0.0,0.0,0.0,0.0,0.0 +0,1.778600,0.0,0.0,0.0,0.0,0.0 +0,1.778700,0.0,0.0,0.0,0.0,0.0 +0,1.778800,0.0,0.0,0.0,0.0,0.0 +0,1.778900,0.0,0.0,0.0,0.0,0.0 +0,1.779000,0.0,0.0,0.0,0.0,0.0 +0,1.779100,0.0,0.0,0.0,0.0,0.0 +0,1.779200,0.0,0.0,0.0,0.0,0.0 +0,1.779300,0.0,0.0,0.0,0.0,0.0 +0,1.779400,0.0,0.0,0.0,0.0,0.0 +0,1.779500,0.0,0.0,0.0,0.0,0.0 +0,1.779600,0.0,0.0,0.0,0.0,0.0 +0,1.779700,0.0,0.0,0.0,0.0,0.0 +0,1.779800,0.0,0.0,0.0,0.0,0.0 +0,1.779900,0.0,0.0,0.0,0.0,0.0 +0,1.780000,0.0,0.0,0.0,0.0,0.0 +0,1.780100,0.0,0.0,0.0,0.0,0.0 +1,2350.490790,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.780200,0.0,0.0,0.0,0.0,0.0 +0,1.780300,0.0,0.0,0.0,0.0,0.0 +0,1.780400,0.0,0.0,0.0,0.0,0.0 +0,1.780500,0.0,0.0,0.0,0.0,0.0 +0,1.780600,0.0,0.0,0.0,0.0,0.0 +0,1.780700,0.0,0.0,0.0,0.0,0.0 +0,1.780800,0.0,0.0,0.0,0.0,0.0 +0,1.780900,0.0,0.0,0.0,0.0,0.0 +0,1.781000,0.0,0.0,0.0,0.0,0.0 +0,1.781100,0.0,0.0,0.0,0.0,0.0 +0,1.781200,0.0,0.0,0.0,0.0,0.0 +0,1.781300,0.0,0.0,0.0,0.0,0.0 +0,1.781400,0.0,0.0,0.0,0.0,0.0 +0,1.781500,0.0,0.0,0.0,0.0,0.0 +0,1.781600,0.0,0.0,0.0,0.0,0.0 +0,1.781700,0.0,0.0,0.0,0.0,0.0 +0,1.781800,0.0,0.0,0.0,0.0,0.0 +0,1.781900,0.0,0.0,0.0,0.0,0.0 +0,1.782000,0.0,0.0,0.0,0.0,0.0 +0,1.782100,0.0,0.0,0.0,0.0,0.0 +0,1.782200,0.0,0.0,0.0,0.0,0.0 +0,1.782300,0.0,0.0,0.0,0.0,0.0 +0,1.782400,0.0,0.0,0.0,0.0,0.0 +0,1.782500,0.0,0.0,0.0,0.0,0.0 +0,1.782600,0.0,0.0,0.0,0.0,0.0 +0,1.782700,0.0,0.0,0.0,0.0,0.0 +0,1.782800,0.0,0.0,0.0,0.0,0.0 +0,1.782900,0.0,0.0,0.0,0.0,0.0 +0,1.783000,0.0,0.0,0.0,0.0,0.0 +0,1.783100,0.0,0.0,0.0,0.0,0.0 +0,1.783200,0.0,0.0,0.0,0.0,0.0 +0,1.783300,0.0,0.0,0.0,0.0,0.0 +0,1.783400,0.0,0.0,0.0,0.0,0.0 +0,1.783500,0.0,0.0,0.0,0.0,0.0 +0,1.783600,0.0,0.0,0.0,0.0,0.0 +0,1.783700,0.0,0.0,0.0,0.0,0.0 +0,1.783800,0.0,0.0,0.0,0.0,0.0 +0,1.783900,0.0,0.0,0.0,0.0,0.0 +0,1.784000,0.0,0.0,0.0,0.0,0.0 +0,1.784100,0.0,0.0,0.0,0.0,0.0 +0,1.784200,0.0,0.0,0.0,0.0,0.0 +0,1.784300,0.0,0.0,0.0,0.0,0.0 +0,1.784400,0.0,0.0,0.0,0.0,0.0 +0,1.784500,0.0,0.0,0.0,0.0,0.0 +0,1.784600,0.0,0.0,0.0,0.0,0.0 +0,1.784700,0.0,0.0,0.0,0.0,0.0 +0,1.784800,0.0,0.0,0.0,0.0,0.0 +0,1.784900,0.0,0.0,0.0,0.0,0.0 +0,1.785000,0.0,0.0,0.0,0.0,0.0 +0,1.785100,0.0,0.0,0.0,0.0,0.0 +0,1.785200,0.0,0.0,0.0,0.0,0.0 +0,1.785300,0.0,0.0,0.0,0.0,0.0 +0,1.785400,0.0,0.0,0.0,0.0,0.0 +0,1.785500,0.0,0.0,0.0,0.0,0.0 +0,1.785600,0.0,0.0,0.0,0.0,0.0 +0,1.785700,0.0,0.0,0.0,0.0,0.0 +0,1.785800,0.0,0.0,0.0,0.0,0.0 +0,1.785900,0.0,0.0,0.0,0.0,0.0 +0,1.786000,0.0,0.0,0.0,0.0,0.0 +0,1.786100,0.0,0.0,0.0,0.0,0.0 +0,1.786200,0.0,0.0,0.0,0.0,0.0 +0,1.786300,0.0,0.0,0.0,0.0,0.0 +0,1.786400,0.0,0.0,0.0,0.0,0.0 +0,1.786500,0.0,0.0,0.0,0.0,0.0 +0,1.786600,0.0,0.0,0.0,0.0,0.0 +0,1.786700,0.0,0.0,0.0,0.0,0.0 +0,1.786800,0.0,0.0,0.0,0.0,0.0 +0,1.786900,0.0,0.0,0.0,0.0,0.0 +0,1.787000,0.0,0.0,0.0,0.0,0.0 +0,1.787100,0.0,0.0,0.0,0.0,0.0 +0,1.787200,0.0,0.0,0.0,0.0,0.0 +0,1.787300,0.0,0.0,0.0,0.0,0.0 +0,1.787400,0.0,0.0,0.0,0.0,0.0 +0,1.787500,0.0,0.0,0.0,0.0,0.0 +0,1.787600,0.0,0.0,0.0,0.0,0.0 +0,1.787700,0.0,0.0,0.0,0.0,0.0 +0,1.787800,0.0,0.0,0.0,0.0,0.0 +0,1.787900,0.0,0.0,0.0,0.0,0.0 +0,1.788000,0.0,0.0,0.0,0.0,0.0 +0,1.788100,0.0,0.0,0.0,0.0,0.0 +0,1.788200,0.0,0.0,0.0,0.0,0.0 +0,1.788300,0.0,0.0,0.0,0.0,0.0 +0,1.788400,0.0,0.0,0.0,0.0,0.0 +0,1.788500,0.0,0.0,0.0,0.0,0.0 +0,1.788600,0.0,0.0,0.0,0.0,0.0 +0,1.788700,0.0,0.0,0.0,0.0,0.0 +0,1.788800,0.0,0.0,0.0,0.0,0.0 +0,1.788900,0.0,0.0,0.0,0.0,0.0 +0,1.789000,0.0,0.0,0.0,0.0,0.0 +0,1.789100,0.0,0.0,0.0,0.0,0.0 +0,1.789200,0.0,0.0,0.0,0.0,0.0 +0,1.789300,0.0,0.0,0.0,0.0,0.0 +0,1.789400,0.0,0.0,0.0,0.0,0.0 +0,1.789500,0.0,0.0,0.0,0.0,0.0 +0,1.789600,0.0,0.0,0.0,0.0,0.0 +0,1.789700,0.0,0.0,0.0,0.0,0.0 +0,1.789800,0.0,0.0,0.0,0.0,0.0 +0,1.789900,0.0,0.0,0.0,0.0,0.0 +0,1.790000,0.0,0.0,0.0,0.0,0.0 +0,1.790100,0.0,0.0,0.0,0.0,0.0 +0,1.790200,0.0,0.0,0.0,0.0,0.0 +0,1.790300,0.0,0.0,0.0,0.0,0.0 +0,1.790400,0.0,0.0,0.0,0.0,0.0 +0,1.790500,0.0,0.0,0.0,0.0,0.0 +0,1.790600,0.0,0.0,0.0,0.0,0.0 +0,1.790700,0.0,0.0,0.0,0.0,0.0 +0,1.790800,0.0,0.0,0.0,0.0,0.0 +0,1.790900,0.0,0.0,0.0,0.0,0.0 +0,1.791000,0.0,0.0,0.0,0.0,0.0 +0,1.791100,0.0,0.0,0.0,0.0,0.0 +0,1.791200,0.0,0.0,0.0,0.0,0.0 +0,1.791300,0.0,0.0,0.0,0.0,0.0 +0,1.791400,0.0,0.0,0.0,0.0,0.0 +0,1.791500,0.0,0.0,0.0,0.0,0.0 +0,1.791600,0.0,0.0,0.0,0.0,0.0 +0,1.791700,0.0,0.0,0.0,0.0,0.0 +0,1.791800,0.0,0.0,0.0,0.0,0.0 +0,1.791900,0.0,0.0,0.0,0.0,0.0 +0,1.792000,0.0,0.0,0.0,0.0,0.0 +0,1.792100,0.0,0.0,0.0,0.0,0.0 +0,1.792200,0.0,0.0,0.0,0.0,0.0 +0,1.792300,0.0,0.0,0.0,0.0,0.0 +0,1.792400,0.0,0.0,0.0,0.0,0.0 +0,1.792500,0.0,0.0,0.0,0.0,0.0 +0,1.792600,0.0,0.0,0.0,0.0,0.0 +0,1.792700,0.0,0.0,0.0,0.0,0.0 +0,1.792800,0.0,0.0,0.0,0.0,0.0 +0,1.792900,0.0,0.0,0.0,0.0,0.0 +0,1.793000,0.0,0.0,0.0,0.0,0.0 +0,1.793100,0.0,0.0,0.0,0.0,0.0 +0,1.793200,0.0,0.0,0.0,0.0,0.0 +0,1.793300,0.0,0.0,0.0,0.0,0.0 +0,1.793400,0.0,0.0,0.0,0.0,0.0 +0,1.793500,0.0,0.0,0.0,0.0,0.0 +0,1.793600,0.0,0.0,0.0,0.0,0.0 +0,1.793700,0.0,0.0,0.0,0.0,0.0 +0,1.793800,0.0,0.0,0.0,0.0,0.0 +0,1.793900,0.0,0.0,0.0,0.0,0.0 +0,1.794000,0.0,0.0,0.0,0.0,0.0 +0,1.794100,0.0,0.0,0.0,0.0,0.0 +0,1.794200,0.0,0.0,0.0,0.0,0.0 +0,1.794300,0.0,0.0,0.0,0.0,0.0 +0,1.794400,0.0,0.0,0.0,0.0,0.0 +0,1.794500,0.0,0.0,0.0,0.0,0.0 +0,1.794600,0.0,0.0,0.0,0.0,0.0 +0,1.794700,0.0,0.0,0.0,0.0,0.0 +0,1.794800,0.0,0.0,0.0,0.0,0.0 +0,1.794900,0.0,0.0,0.0,0.0,0.0 +0,1.795000,0.0,0.0,0.0,0.0,0.0 +0,1.795100,0.0,0.0,0.0,0.0,0.0 +0,1.795200,0.0,0.0,0.0,0.0,0.0 +0,1.795300,0.0,0.0,0.0,0.0,0.0 +0,1.795400,0.0,0.0,0.0,0.0,0.0 +0,1.795500,0.0,0.0,0.0,0.0,0.0 +0,1.795600,0.0,0.0,0.0,0.0,0.0 +0,1.795700,0.0,0.0,0.0,0.0,0.0 +0,1.795800,0.0,0.0,0.0,0.0,0.0 +0,1.795900,0.0,0.0,0.0,0.0,0.0 +0,1.796000,0.0,0.0,0.0,0.0,0.0 +0,1.796100,0.0,0.0,0.0,0.0,0.0 +0,1.796200,0.0,0.0,0.0,0.0,0.0 +0,1.796300,0.0,0.0,0.0,0.0,0.0 +0,1.796400,0.0,0.0,0.0,0.0,0.0 +0,1.796500,0.0,0.0,0.0,0.0,0.0 +0,1.796600,0.0,0.0,0.0,0.0,0.0 +0,1.796700,0.0,0.0,0.0,0.0,0.0 +0,1.796800,0.0,0.0,0.0,0.0,0.0 +0,1.796900,0.0,0.0,0.0,0.0,0.0 +0,1.797000,0.0,0.0,0.0,0.0,0.0 +0,1.797100,0.0,0.0,0.0,0.0,0.0 +0,1.797200,0.0,0.0,0.0,0.0,0.0 +0,1.797300,0.0,0.0,0.0,0.0,0.0 +0,1.797400,0.0,0.0,0.0,0.0,0.0 +0,1.797500,0.0,0.0,0.0,0.0,0.0 +0,1.797600,0.0,0.0,0.0,0.0,0.0 +0,1.797700,0.0,0.0,0.0,0.0,0.0 +0,1.797800,0.0,0.0,0.0,0.0,0.0 +0,1.797900,0.0,0.0,0.0,0.0,0.0 +0,1.798000,0.0,0.0,0.0,0.0,0.0 +0,1.798100,0.0,0.0,0.0,0.0,0.0 +0,1.798200,0.0,0.0,0.0,0.0,0.0 +0,1.798300,0.0,0.0,0.0,0.0,0.0 +0,1.798400,0.0,0.0,0.0,0.0,0.0 +0,1.798500,0.0,0.0,0.0,0.0,0.0 +0,1.798600,0.0,0.0,0.0,0.0,0.0 +0,1.798700,0.0,0.0,0.0,0.0,0.0 +0,1.798800,0.0,0.0,0.0,0.0,0.0 +0,1.798900,0.0,0.0,0.0,0.0,0.0 +0,1.799000,0.0,0.0,0.0,0.0,0.0 +0,1.799100,0.0,0.0,0.0,0.0,0.0 +0,1.799200,0.0,0.0,0.0,0.0,0.0 +0,1.799300,0.0,0.0,0.0,0.0,0.0 +0,1.799400,0.0,0.0,0.0,0.0,0.0 +0,1.799500,0.0,0.0,0.0,0.0,0.0 +0,1.799600,0.0,0.0,0.0,0.0,0.0 +0,1.799700,0.0,0.0,0.0,0.0,0.0 +0,1.799800,0.0,0.0,0.0,0.0,0.0 +0,1.799900,0.0,0.0,0.0,0.0,0.0 +0,1.800000,0.0,0.0,0.0,0.0,0.0 +0,1.800100,0.0,0.0,0.0,0.0,0.0 +1,2430.607549,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.800200,0.0,0.0,0.0,0.0,0.0 +0,1.800300,0.0,0.0,0.0,0.0,0.0 +0,1.800400,0.0,0.0,0.0,0.0,0.0 +0,1.800500,0.0,0.0,0.0,0.0,0.0 +0,1.800600,0.0,0.0,0.0,0.0,0.0 +0,1.800700,0.0,0.0,0.0,0.0,0.0 +0,1.800800,0.0,0.0,0.0,0.0,0.0 +0,1.800900,0.0,0.0,0.0,0.0,0.0 +0,1.801000,0.0,0.0,0.0,0.0,0.0 +0,1.801100,0.0,0.0,0.0,0.0,0.0 +0,1.801200,0.0,0.0,0.0,0.0,0.0 +0,1.801300,0.0,0.0,0.0,0.0,0.0 +0,1.801400,0.0,0.0,0.0,0.0,0.0 +0,1.801500,0.0,0.0,0.0,0.0,0.0 +0,1.801600,0.0,0.0,0.0,0.0,0.0 +0,1.801700,0.0,0.0,0.0,0.0,0.0 +0,1.801800,0.0,0.0,0.0,0.0,0.0 +0,1.801900,0.0,0.0,0.0,0.0,0.0 +0,1.802000,0.0,0.0,0.0,0.0,0.0 +0,1.802100,0.0,0.0,0.0,0.0,0.0 +0,1.802200,0.0,0.0,0.0,0.0,0.0 +0,1.802300,0.0,0.0,0.0,0.0,0.0 +0,1.802400,0.0,0.0,0.0,0.0,0.0 +0,1.802500,0.0,0.0,0.0,0.0,0.0 +0,1.802600,0.0,0.0,0.0,0.0,0.0 +0,1.802700,0.0,0.0,0.0,0.0,0.0 +0,1.802800,0.0,0.0,0.0,0.0,0.0 +0,1.802900,0.0,0.0,0.0,0.0,0.0 +0,1.803000,0.0,0.0,0.0,0.0,0.0 +0,1.803100,0.0,0.0,0.0,0.0,0.0 +0,1.803200,0.0,0.0,0.0,0.0,0.0 +0,1.803300,0.0,0.0,0.0,0.0,0.0 +0,1.803400,0.0,0.0,0.0,0.0,0.0 +0,1.803500,0.0,0.0,0.0,0.0,0.0 +0,1.803600,0.0,0.0,0.0,0.0,0.0 +0,1.803700,0.0,0.0,0.0,0.0,0.0 +0,1.803800,0.0,0.0,0.0,0.0,0.0 +0,1.803900,0.0,0.0,0.0,0.0,0.0 +0,1.804000,0.0,0.0,0.0,0.0,0.0 +0,1.804100,0.0,0.0,0.0,0.0,0.0 +0,1.804200,0.0,0.0,0.0,0.0,0.0 +0,1.804300,0.0,0.0,0.0,0.0,0.0 +0,1.804400,0.0,0.0,0.0,0.0,0.0 +0,1.804500,0.0,0.0,0.0,0.0,0.0 +0,1.804600,0.0,0.0,0.0,0.0,0.0 +0,1.804700,0.0,0.0,0.0,0.0,0.0 +0,1.804800,0.0,0.0,0.0,0.0,0.0 +0,1.804900,0.0,0.0,0.0,0.0,0.0 +0,1.805000,0.0,0.0,0.0,0.0,0.0 +0,1.805100,0.0,0.0,0.0,0.0,0.0 +0,1.805200,0.0,0.0,0.0,0.0,0.0 +0,1.805300,0.0,0.0,0.0,0.0,0.0 +0,1.805400,0.0,0.0,0.0,0.0,0.0 +0,1.805500,0.0,0.0,0.0,0.0,0.0 +0,1.805600,0.0,0.0,0.0,0.0,0.0 +0,1.805700,0.0,0.0,0.0,0.0,0.0 +0,1.805800,0.0,0.0,0.0,0.0,0.0 +0,1.805900,0.0,0.0,0.0,0.0,0.0 +0,1.806000,0.0,0.0,0.0,0.0,0.0 +0,1.806100,0.0,0.0,0.0,0.0,0.0 +0,1.806200,0.0,0.0,0.0,0.0,0.0 +0,1.806300,0.0,0.0,0.0,0.0,0.0 +0,1.806400,0.0,0.0,0.0,0.0,0.0 +0,1.806500,0.0,0.0,0.0,0.0,0.0 +0,1.806600,0.0,0.0,0.0,0.0,0.0 +0,1.806700,0.0,0.0,0.0,0.0,0.0 +0,1.806800,0.0,0.0,0.0,0.0,0.0 +0,1.806900,0.0,0.0,0.0,0.0,0.0 +0,1.807000,0.0,0.0,0.0,0.0,0.0 +0,1.807100,0.0,0.0,0.0,0.0,0.0 +0,1.807200,0.0,0.0,0.0,0.0,0.0 +0,1.807300,0.0,0.0,0.0,0.0,0.0 +0,1.807400,0.0,0.0,0.0,0.0,0.0 +0,1.807500,0.0,0.0,0.0,0.0,0.0 +0,1.807600,0.0,0.0,0.0,0.0,0.0 +0,1.807700,0.0,0.0,0.0,0.0,0.0 +0,1.807800,0.0,0.0,0.0,0.0,0.0 +0,1.807900,0.0,0.0,0.0,0.0,0.0 +0,1.808000,0.0,0.0,0.0,0.0,0.0 +0,1.808100,0.0,0.0,0.0,0.0,0.0 +0,1.808200,0.0,0.0,0.0,0.0,0.0 +0,1.808300,0.0,0.0,0.0,0.0,0.0 +0,1.808400,0.0,0.0,0.0,0.0,0.0 +0,1.808500,0.0,0.0,0.0,0.0,0.0 +0,1.808600,0.0,0.0,0.0,0.0,0.0 +0,1.808700,0.0,0.0,0.0,0.0,0.0 +0,1.808800,0.0,0.0,0.0,0.0,0.0 +0,1.808900,0.0,0.0,0.0,0.0,0.0 +0,1.809000,0.0,0.0,0.0,0.0,0.0 +0,1.809100,0.0,0.0,0.0,0.0,0.0 +0,1.809200,0.0,0.0,0.0,0.0,0.0 +0,1.809300,0.0,0.0,0.0,0.0,0.0 +0,1.809400,0.0,0.0,0.0,0.0,0.0 +0,1.809500,0.0,0.0,0.0,0.0,0.0 +0,1.809600,0.0,0.0,0.0,0.0,0.0 +0,1.809700,0.0,0.0,0.0,0.0,0.0 +0,1.809800,0.0,0.0,0.0,0.0,0.0 +0,1.809900,0.0,0.0,0.0,0.0,0.0 +0,1.810000,0.0,0.0,0.0,0.0,0.0 +0,1.810100,0.0,0.0,0.0,0.0,0.0 +0,1.810200,0.0,0.0,0.0,0.0,0.0 +0,1.810300,0.0,0.0,0.0,0.0,0.0 +0,1.810400,0.0,0.0,0.0,0.0,0.0 +0,1.810500,0.0,0.0,0.0,0.0,0.0 +0,1.810600,0.0,0.0,0.0,0.0,0.0 +0,1.810700,0.0,0.0,0.0,0.0,0.0 +0,1.810800,0.0,0.0,0.0,0.0,0.0 +0,1.810900,0.0,0.0,0.0,0.0,0.0 +0,1.811000,0.0,0.0,0.0,0.0,0.0 +0,1.811100,0.0,0.0,0.0,0.0,0.0 +0,1.811200,0.0,0.0,0.0,0.0,0.0 +0,1.811300,0.0,0.0,0.0,0.0,0.0 +0,1.811400,0.0,0.0,0.0,0.0,0.0 +0,1.811500,0.0,0.0,0.0,0.0,0.0 +0,1.811600,0.0,0.0,0.0,0.0,0.0 +0,1.811700,0.0,0.0,0.0,0.0,0.0 +0,1.811800,0.0,0.0,0.0,0.0,0.0 +0,1.811900,0.0,0.0,0.0,0.0,0.0 +0,1.812000,0.0,0.0,0.0,0.0,0.0 +0,1.812100,0.0,0.0,0.0,0.0,0.0 +0,1.812200,0.0,0.0,0.0,0.0,0.0 +0,1.812300,0.0,0.0,0.0,0.0,0.0 +0,1.812400,0.0,0.0,0.0,0.0,0.0 +0,1.812500,0.0,0.0,0.0,0.0,0.0 +0,1.812600,0.0,0.0,0.0,0.0,0.0 +0,1.812700,0.0,0.0,0.0,0.0,0.0 +0,1.812800,0.0,0.0,0.0,0.0,0.0 +0,1.812900,0.0,0.0,0.0,0.0,0.0 +0,1.813000,0.0,0.0,0.0,0.0,0.0 +0,1.813100,0.0,0.0,0.0,0.0,0.0 +0,1.813200,0.0,0.0,0.0,0.0,0.0 +0,1.813300,0.0,0.0,0.0,0.0,0.0 +0,1.813400,0.0,0.0,0.0,0.0,0.0 +0,1.813500,0.0,0.0,0.0,0.0,0.0 +0,1.813600,0.0,0.0,0.0,0.0,0.0 +0,1.813700,0.0,0.0,0.0,0.0,0.0 +0,1.813800,0.0,0.0,0.0,0.0,0.0 +0,1.813900,0.0,0.0,0.0,0.0,0.0 +0,1.814000,0.0,0.0,0.0,0.0,0.0 +0,1.814100,0.0,0.0,0.0,0.0,0.0 +0,1.814200,0.0,0.0,0.0,0.0,0.0 +0,1.814300,0.0,0.0,0.0,0.0,0.0 +0,1.814400,0.0,0.0,0.0,0.0,0.0 +0,1.814500,0.0,0.0,0.0,0.0,0.0 +0,1.814600,0.0,0.0,0.0,0.0,0.0 +0,1.814700,0.0,0.0,0.0,0.0,0.0 +0,1.814800,0.0,0.0,0.0,0.0,0.0 +0,1.814900,0.0,0.0,0.0,0.0,0.0 +0,1.815000,0.0,0.0,0.0,0.0,0.0 +0,1.815100,0.0,0.0,0.0,0.0,0.0 +0,1.815200,0.0,0.0,0.0,0.0,0.0 +0,1.815300,0.0,0.0,0.0,0.0,0.0 +0,1.815400,0.0,0.0,0.0,0.0,0.0 +0,1.815500,0.0,0.0,0.0,0.0,0.0 +0,1.815600,0.0,0.0,0.0,0.0,0.0 +0,1.815700,0.0,0.0,0.0,0.0,0.0 +0,1.815800,0.0,0.0,0.0,0.0,0.0 +0,1.815900,0.0,0.0,0.0,0.0,0.0 +0,1.816000,0.0,0.0,0.0,0.0,0.0 +0,1.816100,0.0,0.0,0.0,0.0,0.0 +0,1.816200,0.0,0.0,0.0,0.0,0.0 +0,1.816300,0.0,0.0,0.0,0.0,0.0 +0,1.816400,0.0,0.0,0.0,0.0,0.0 +0,1.816500,0.0,0.0,0.0,0.0,0.0 +0,1.816600,0.0,0.0,0.0,0.0,0.0 +0,1.816700,0.0,0.0,0.0,0.0,0.0 +0,1.816800,0.0,0.0,0.0,0.0,0.0 +0,1.816900,0.0,0.0,0.0,0.0,0.0 +0,1.817000,0.0,0.0,0.0,0.0,0.0 +0,1.817100,0.0,0.0,0.0,0.0,0.0 +0,1.817200,0.0,0.0,0.0,0.0,0.0 +0,1.817300,0.0,0.0,0.0,0.0,0.0 +0,1.817400,0.0,0.0,0.0,0.0,0.0 +0,1.817500,0.0,0.0,0.0,0.0,0.0 +0,1.817600,0.0,0.0,0.0,0.0,0.0 +0,1.817700,0.0,0.0,0.0,0.0,0.0 +0,1.817800,0.0,0.0,0.0,0.0,0.0 +0,1.817900,0.0,0.0,0.0,0.0,0.0 +0,1.818000,0.0,0.0,0.0,0.0,0.0 +0,1.818100,0.0,0.0,0.0,0.0,0.0 +0,1.818200,0.0,0.0,0.0,0.0,0.0 +0,1.818300,0.0,0.0,0.0,0.0,0.0 +0,1.818400,0.0,0.0,0.0,0.0,0.0 +0,1.818500,0.0,0.0,0.0,0.0,0.0 +0,1.818600,0.0,0.0,0.0,0.0,0.0 +0,1.818700,0.0,0.0,0.0,0.0,0.0 +0,1.818800,0.0,0.0,0.0,0.0,0.0 +0,1.818900,0.0,0.0,0.0,0.0,0.0 +0,1.819000,0.0,0.0,0.0,0.0,0.0 +0,1.819100,0.0,0.0,0.0,0.0,0.0 +0,1.819200,0.0,0.0,0.0,0.0,0.0 +0,1.819300,0.0,0.0,0.0,0.0,0.0 +0,1.819400,0.0,0.0,0.0,0.0,0.0 +0,1.819500,0.0,0.0,0.0,0.0,0.0 +0,1.819600,0.0,0.0,0.0,0.0,0.0 +0,1.819700,0.0,0.0,0.0,0.0,0.0 +0,1.819800,0.0,0.0,0.0,0.0,0.0 +0,1.819900,0.0,0.0,0.0,0.0,0.0 +0,1.820000,0.0,0.0,0.0,0.0,0.0 +0,1.820100,0.0,0.0,0.0,0.0,0.0 +1,2512.524458,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.820200,0.0,0.0,0.0,0.0,0.0 +0,1.820300,0.0,0.0,0.0,0.0,0.0 +0,1.820400,0.0,0.0,0.0,0.0,0.0 +0,1.820500,0.0,0.0,0.0,0.0,0.0 +0,1.820600,0.0,0.0,0.0,0.0,0.0 +0,1.820700,0.0,0.0,0.0,0.0,0.0 +0,1.820800,0.0,0.0,0.0,0.0,0.0 +0,1.820900,0.0,0.0,0.0,0.0,0.0 +0,1.821000,0.0,0.0,0.0,0.0,0.0 +0,1.821100,0.0,0.0,0.0,0.0,0.0 +0,1.821200,0.0,0.0,0.0,0.0,0.0 +0,1.821300,0.0,0.0,0.0,0.0,0.0 +0,1.821400,0.0,0.0,0.0,0.0,0.0 +0,1.821500,0.0,0.0,0.0,0.0,0.0 +0,1.821600,0.0,0.0,0.0,0.0,0.0 +0,1.821700,0.0,0.0,0.0,0.0,0.0 +0,1.821800,0.0,0.0,0.0,0.0,0.0 +0,1.821900,0.0,0.0,0.0,0.0,0.0 +0,1.822000,0.0,0.0,0.0,0.0,0.0 +0,1.822100,0.0,0.0,0.0,0.0,0.0 +0,1.822200,0.0,0.0,0.0,0.0,0.0 +0,1.822300,0.0,0.0,0.0,0.0,0.0 +0,1.822400,0.0,0.0,0.0,0.0,0.0 +0,1.822500,0.0,0.0,0.0,0.0,0.0 +0,1.822600,0.0,0.0,0.0,0.0,0.0 +0,1.822700,0.0,0.0,0.0,0.0,0.0 +0,1.822800,0.0,0.0,0.0,0.0,0.0 +0,1.822900,0.0,0.0,0.0,0.0,0.0 +0,1.823000,0.0,0.0,0.0,0.0,0.0 +0,1.823100,0.0,0.0,0.0,0.0,0.0 +0,1.823200,0.0,0.0,0.0,0.0,0.0 +0,1.823300,0.0,0.0,0.0,0.0,0.0 +0,1.823400,0.0,0.0,0.0,0.0,0.0 +0,1.823500,0.0,0.0,0.0,0.0,0.0 +0,1.823600,0.0,0.0,0.0,0.0,0.0 +0,1.823700,0.0,0.0,0.0,0.0,0.0 +0,1.823800,0.0,0.0,0.0,0.0,0.0 +0,1.823900,0.0,0.0,0.0,0.0,0.0 +0,1.824000,0.0,0.0,0.0,0.0,0.0 +0,1.824100,0.0,0.0,0.0,0.0,0.0 +0,1.824200,0.0,0.0,0.0,0.0,0.0 +0,1.824300,0.0,0.0,0.0,0.0,0.0 +0,1.824400,0.0,0.0,0.0,0.0,0.0 +0,1.824500,0.0,0.0,0.0,0.0,0.0 +0,1.824600,0.0,0.0,0.0,0.0,0.0 +0,1.824700,0.0,0.0,0.0,0.0,0.0 +0,1.824800,0.0,0.0,0.0,0.0,0.0 +0,1.824900,0.0,0.0,0.0,0.0,0.0 +0,1.825000,0.0,0.0,0.0,0.0,0.0 +0,1.825100,0.0,0.0,0.0,0.0,0.0 +0,1.825200,0.0,0.0,0.0,0.0,0.0 +0,1.825300,0.0,0.0,0.0,0.0,0.0 +0,1.825400,0.0,0.0,0.0,0.0,0.0 +0,1.825500,0.0,0.0,0.0,0.0,0.0 +0,1.825600,0.0,0.0,0.0,0.0,0.0 +0,1.825700,0.0,0.0,0.0,0.0,0.0 +0,1.825800,0.0,0.0,0.0,0.0,0.0 +0,1.825900,0.0,0.0,0.0,0.0,0.0 +0,1.826000,0.0,0.0,0.0,0.0,0.0 +0,1.826100,0.0,0.0,0.0,0.0,0.0 +0,1.826200,0.0,0.0,0.0,0.0,0.0 +0,1.826300,0.0,0.0,0.0,0.0,0.0 +0,1.826400,0.0,0.0,0.0,0.0,0.0 +0,1.826500,0.0,0.0,0.0,0.0,0.0 +0,1.826600,0.0,0.0,0.0,0.0,0.0 +0,1.826700,0.0,0.0,0.0,0.0,0.0 +0,1.826800,0.0,0.0,0.0,0.0,0.0 +0,1.826900,0.0,0.0,0.0,0.0,0.0 +0,1.827000,0.0,0.0,0.0,0.0,0.0 +0,1.827100,0.0,0.0,0.0,0.0,0.0 +0,1.827200,0.0,0.0,0.0,0.0,0.0 +0,1.827300,0.0,0.0,0.0,0.0,0.0 +0,1.827400,0.0,0.0,0.0,0.0,0.0 +0,1.827500,0.0,0.0,0.0,0.0,0.0 +0,1.827600,0.0,0.0,0.0,0.0,0.0 +0,1.827700,0.0,0.0,0.0,0.0,0.0 +0,1.827800,0.0,0.0,0.0,0.0,0.0 +0,1.827900,0.0,0.0,0.0,0.0,0.0 +0,1.828000,0.0,0.0,0.0,0.0,0.0 +0,1.828100,0.0,0.0,0.0,0.0,0.0 +0,1.828200,0.0,0.0,0.0,0.0,0.0 +0,1.828300,0.0,0.0,0.0,0.0,0.0 +0,1.828400,0.0,0.0,0.0,0.0,0.0 +0,1.828500,0.0,0.0,0.0,0.0,0.0 +0,1.828600,0.0,0.0,0.0,0.0,0.0 +0,1.828700,0.0,0.0,0.0,0.0,0.0 +0,1.828800,0.0,0.0,0.0,0.0,0.0 +0,1.828900,0.0,0.0,0.0,0.0,0.0 +0,1.829000,0.0,0.0,0.0,0.0,0.0 +0,1.829100,0.0,0.0,0.0,0.0,0.0 +0,1.829200,0.0,0.0,0.0,0.0,0.0 +0,1.829300,0.0,0.0,0.0,0.0,0.0 +0,1.829400,0.0,0.0,0.0,0.0,0.0 +0,1.829500,0.0,0.0,0.0,0.0,0.0 +0,1.829600,0.0,0.0,0.0,0.0,0.0 +0,1.829700,0.0,0.0,0.0,0.0,0.0 +0,1.829800,0.0,0.0,0.0,0.0,0.0 +0,1.829900,0.0,0.0,0.0,0.0,0.0 +0,1.830000,0.0,0.0,0.0,0.0,0.0 +0,1.830100,0.0,0.0,0.0,0.0,0.0 +0,1.830200,0.0,0.0,0.0,0.0,0.0 +0,1.830300,0.0,0.0,0.0,0.0,0.0 +0,1.830400,0.0,0.0,0.0,0.0,0.0 +0,1.830500,0.0,0.0,0.0,0.0,0.0 +0,1.830600,0.0,0.0,0.0,0.0,0.0 +0,1.830700,0.0,0.0,0.0,0.0,0.0 +0,1.830800,0.0,0.0,0.0,0.0,0.0 +0,1.830900,0.0,0.0,0.0,0.0,0.0 +0,1.831000,0.0,0.0,0.0,0.0,0.0 +0,1.831100,0.0,0.0,0.0,0.0,0.0 +0,1.831200,0.0,0.0,0.0,0.0,0.0 +0,1.831300,0.0,0.0,0.0,0.0,0.0 +0,1.831400,0.0,0.0,0.0,0.0,0.0 +0,1.831500,0.0,0.0,0.0,0.0,0.0 +0,1.831600,0.0,0.0,0.0,0.0,0.0 +0,1.831700,0.0,0.0,0.0,0.0,0.0 +0,1.831800,0.0,0.0,0.0,0.0,0.0 +0,1.831900,0.0,0.0,0.0,0.0,0.0 +0,1.832000,0.0,0.0,0.0,0.0,0.0 +0,1.832100,0.0,0.0,0.0,0.0,0.0 +0,1.832200,0.0,0.0,0.0,0.0,0.0 +0,1.832300,0.0,0.0,0.0,0.0,0.0 +0,1.832400,0.0,0.0,0.0,0.0,0.0 +0,1.832500,0.0,0.0,0.0,0.0,0.0 +0,1.832600,0.0,0.0,0.0,0.0,0.0 +0,1.832700,0.0,0.0,0.0,0.0,0.0 +0,1.832800,0.0,0.0,0.0,0.0,0.0 +0,1.832900,0.0,0.0,0.0,0.0,0.0 +0,1.833000,0.0,0.0,0.0,0.0,0.0 +0,1.833100,0.0,0.0,0.0,0.0,0.0 +0,1.833200,0.0,0.0,0.0,0.0,0.0 +0,1.833300,0.0,0.0,0.0,0.0,0.0 +0,1.833400,0.0,0.0,0.0,0.0,0.0 +0,1.833500,0.0,0.0,0.0,0.0,0.0 +0,1.833600,0.0,0.0,0.0,0.0,0.0 +0,1.833700,0.0,0.0,0.0,0.0,0.0 +0,1.833800,0.0,0.0,0.0,0.0,0.0 +0,1.833900,0.0,0.0,0.0,0.0,0.0 +0,1.834000,0.0,0.0,0.0,0.0,0.0 +0,1.834100,0.0,0.0,0.0,0.0,0.0 +0,1.834200,0.0,0.0,0.0,0.0,0.0 +0,1.834300,0.0,0.0,0.0,0.0,0.0 +0,1.834400,0.0,0.0,0.0,0.0,0.0 +0,1.834500,0.0,0.0,0.0,0.0,0.0 +0,1.834600,0.0,0.0,0.0,0.0,0.0 +0,1.834700,0.0,0.0,0.0,0.0,0.0 +0,1.834800,0.0,0.0,0.0,0.0,0.0 +0,1.834900,0.0,0.0,0.0,0.0,0.0 +0,1.835000,0.0,0.0,0.0,0.0,0.0 +0,1.835100,0.0,0.0,0.0,0.0,0.0 +0,1.835200,0.0,0.0,0.0,0.0,0.0 +0,1.835300,0.0,0.0,0.0,0.0,0.0 +0,1.835400,0.0,0.0,0.0,0.0,0.0 +0,1.835500,0.0,0.0,0.0,0.0,0.0 +0,1.835600,0.0,0.0,0.0,0.0,0.0 +0,1.835700,0.0,0.0,0.0,0.0,0.0 +0,1.835800,0.0,0.0,0.0,0.0,0.0 +0,1.835900,0.0,0.0,0.0,0.0,0.0 +0,1.836000,0.0,0.0,0.0,0.0,0.0 +0,1.836100,0.0,0.0,0.0,0.0,0.0 +0,1.836200,0.0,0.0,0.0,0.0,0.0 +0,1.836300,0.0,0.0,0.0,0.0,0.0 +0,1.836400,0.0,0.0,0.0,0.0,0.0 +0,1.836500,0.0,0.0,0.0,0.0,0.0 +0,1.836600,0.0,0.0,0.0,0.0,0.0 +0,1.836700,0.0,0.0,0.0,0.0,0.0 +0,1.836800,0.0,0.0,0.0,0.0,0.0 +0,1.836900,0.0,0.0,0.0,0.0,0.0 +0,1.837000,0.0,0.0,0.0,0.0,0.0 +0,1.837100,0.0,0.0,0.0,0.0,0.0 +0,1.837200,0.0,0.0,0.0,0.0,0.0 +0,1.837300,0.0,0.0,0.0,0.0,0.0 +0,1.837400,0.0,0.0,0.0,0.0,0.0 +0,1.837500,0.0,0.0,0.0,0.0,0.0 +0,1.837600,0.0,0.0,0.0,0.0,0.0 +0,1.837700,0.0,0.0,0.0,0.0,0.0 +0,1.837800,0.0,0.0,0.0,0.0,0.0 +0,1.837900,0.0,0.0,0.0,0.0,0.0 +0,1.838000,0.0,0.0,0.0,0.0,0.0 +0,1.838100,0.0,0.0,0.0,0.0,0.0 +0,1.838200,0.0,0.0,0.0,0.0,0.0 +0,1.838300,0.0,0.0,0.0,0.0,0.0 +0,1.838400,0.0,0.0,0.0,0.0,0.0 +0,1.838500,0.0,0.0,0.0,0.0,0.0 +0,1.838600,0.0,0.0,0.0,0.0,0.0 +0,1.838700,0.0,0.0,0.0,0.0,0.0 +0,1.838800,0.0,0.0,0.0,0.0,0.0 +0,1.838900,0.0,0.0,0.0,0.0,0.0 +0,1.839000,0.0,0.0,0.0,0.0,0.0 +0,1.839100,0.0,0.0,0.0,0.0,0.0 +0,1.839200,0.0,0.0,0.0,0.0,0.0 +0,1.839300,0.0,0.0,0.0,0.0,0.0 +0,1.839400,0.0,0.0,0.0,0.0,0.0 +0,1.839500,0.0,0.0,0.0,0.0,0.0 +0,1.839600,0.0,0.0,0.0,0.0,0.0 +0,1.839700,0.0,0.0,0.0,0.0,0.0 +0,1.839800,0.0,0.0,0.0,0.0,0.0 +0,1.839900,0.0,0.0,0.0,0.0,0.0 +0,1.840000,0.0,0.0,0.0,0.0,0.0 +0,1.840100,0.0,0.0,0.0,0.0,0.0 +1,2596.261517,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.840200,0.0,0.0,0.0,0.0,0.0 +0,1.840300,0.0,0.0,0.0,0.0,0.0 +0,1.840400,0.0,0.0,0.0,0.0,0.0 +0,1.840500,0.0,0.0,0.0,0.0,0.0 +0,1.840600,0.0,0.0,0.0,0.0,0.0 +0,1.840700,0.0,0.0,0.0,0.0,0.0 +0,1.840800,0.0,0.0,0.0,0.0,0.0 +0,1.840900,0.0,0.0,0.0,0.0,0.0 +0,1.841000,0.0,0.0,0.0,0.0,0.0 +0,1.841100,0.0,0.0,0.0,0.0,0.0 +0,1.841200,0.0,0.0,0.0,0.0,0.0 +0,1.841300,0.0,0.0,0.0,0.0,0.0 +0,1.841400,0.0,0.0,0.0,0.0,0.0 +0,1.841500,0.0,0.0,0.0,0.0,0.0 +0,1.841600,0.0,0.0,0.0,0.0,0.0 +0,1.841700,0.0,0.0,0.0,0.0,0.0 +0,1.841800,0.0,0.0,0.0,0.0,0.0 +0,1.841900,0.0,0.0,0.0,0.0,0.0 +0,1.842000,0.0,0.0,0.0,0.0,0.0 +0,1.842100,0.0,0.0,0.0,0.0,0.0 +0,1.842200,0.0,0.0,0.0,0.0,0.0 +0,1.842300,0.0,0.0,0.0,0.0,0.0 +0,1.842400,0.0,0.0,0.0,0.0,0.0 +0,1.842500,0.0,0.0,0.0,0.0,0.0 +0,1.842600,0.0,0.0,0.0,0.0,0.0 +0,1.842700,0.0,0.0,0.0,0.0,0.0 +0,1.842800,0.0,0.0,0.0,0.0,0.0 +0,1.842900,0.0,0.0,0.0,0.0,0.0 +0,1.843000,0.0,0.0,0.0,0.0,0.0 +0,1.843100,0.0,0.0,0.0,0.0,0.0 +0,1.843200,0.0,0.0,0.0,0.0,0.0 +0,1.843300,0.0,0.0,0.0,0.0,0.0 +0,1.843400,0.0,0.0,0.0,0.0,0.0 +0,1.843500,0.0,0.0,0.0,0.0,0.0 +0,1.843600,0.0,0.0,0.0,0.0,0.0 +0,1.843700,0.0,0.0,0.0,0.0,0.0 +0,1.843800,0.0,0.0,0.0,0.0,0.0 +0,1.843900,0.0,0.0,0.0,0.0,0.0 +0,1.844000,0.0,0.0,0.0,0.0,0.0 +0,1.844100,0.0,0.0,0.0,0.0,0.0 +0,1.844200,0.0,0.0,0.0,0.0,0.0 +0,1.844300,0.0,0.0,0.0,0.0,0.0 +0,1.844400,0.0,0.0,0.0,0.0,0.0 +0,1.844500,0.0,0.0,0.0,0.0,0.0 +0,1.844600,0.0,0.0,0.0,0.0,0.0 +0,1.844700,0.0,0.0,0.0,0.0,0.0 +0,1.844800,0.0,0.0,0.0,0.0,0.0 +0,1.844900,0.0,0.0,0.0,0.0,0.0 +0,1.845000,0.0,0.0,0.0,0.0,0.0 +0,1.845100,0.0,0.0,0.0,0.0,0.0 +0,1.845200,0.0,0.0,0.0,0.0,0.0 +0,1.845300,0.0,0.0,0.0,0.0,0.0 +0,1.845400,0.0,0.0,0.0,0.0,0.0 +0,1.845500,0.0,0.0,0.0,0.0,0.0 +0,1.845600,0.0,0.0,0.0,0.0,0.0 +0,1.845700,0.0,0.0,0.0,0.0,0.0 +0,1.845800,0.0,0.0,0.0,0.0,0.0 +0,1.845900,0.0,0.0,0.0,0.0,0.0 +0,1.846000,0.0,0.0,0.0,0.0,0.0 +0,1.846100,0.0,0.0,0.0,0.0,0.0 +0,1.846200,0.0,0.0,0.0,0.0,0.0 +0,1.846300,0.0,0.0,0.0,0.0,0.0 +0,1.846400,0.0,0.0,0.0,0.0,0.0 +0,1.846500,0.0,0.0,0.0,0.0,0.0 +0,1.846600,0.0,0.0,0.0,0.0,0.0 +0,1.846700,0.0,0.0,0.0,0.0,0.0 +0,1.846800,0.0,0.0,0.0,0.0,0.0 +0,1.846900,0.0,0.0,0.0,0.0,0.0 +0,1.847000,0.0,0.0,0.0,0.0,0.0 +0,1.847100,0.0,0.0,0.0,0.0,0.0 +0,1.847200,0.0,0.0,0.0,0.0,0.0 +0,1.847300,0.0,0.0,0.0,0.0,0.0 +0,1.847400,0.0,0.0,0.0,0.0,0.0 +0,1.847500,0.0,0.0,0.0,0.0,0.0 +0,1.847600,0.0,0.0,0.0,0.0,0.0 +0,1.847700,0.0,0.0,0.0,0.0,0.0 +0,1.847800,0.0,0.0,0.0,0.0,0.0 +0,1.847900,0.0,0.0,0.0,0.0,0.0 +0,1.848000,0.0,0.0,0.0,0.0,0.0 +0,1.848100,0.0,0.0,0.0,0.0,0.0 +0,1.848200,0.0,0.0,0.0,0.0,0.0 +0,1.848300,0.0,0.0,0.0,0.0,0.0 +0,1.848400,0.0,0.0,0.0,0.0,0.0 +0,1.848500,0.0,0.0,0.0,0.0,0.0 +0,1.848600,0.0,0.0,0.0,0.0,0.0 +0,1.848700,0.0,0.0,0.0,0.0,0.0 +0,1.848800,0.0,0.0,0.0,0.0,0.0 +0,1.848900,0.0,0.0,0.0,0.0,0.0 +0,1.849000,0.0,0.0,0.0,0.0,0.0 +0,1.849100,0.0,0.0,0.0,0.0,0.0 +0,1.849200,0.0,0.0,0.0,0.0,0.0 +0,1.849300,0.0,0.0,0.0,0.0,0.0 +0,1.849400,0.0,0.0,0.0,0.0,0.0 +0,1.849500,0.0,0.0,0.0,0.0,0.0 +0,1.849600,0.0,0.0,0.0,0.0,0.0 +0,1.849700,0.0,0.0,0.0,0.0,0.0 +0,1.849800,0.0,0.0,0.0,0.0,0.0 +0,1.849900,0.0,0.0,0.0,0.0,0.0 +0,1.850000,0.0,0.0,0.0,0.0,0.0 +0,1.850100,0.0,0.0,0.0,0.0,0.0 +0,1.850200,0.0,0.0,0.0,0.0,0.0 +0,1.850300,0.0,0.0,0.0,0.0,0.0 +0,1.850400,0.0,0.0,0.0,0.0,0.0 +0,1.850500,0.0,0.0,0.0,0.0,0.0 +0,1.850600,0.0,0.0,0.0,0.0,0.0 +0,1.850700,0.0,0.0,0.0,0.0,0.0 +0,1.850800,0.0,0.0,0.0,0.0,0.0 +0,1.850900,0.0,0.0,0.0,0.0,0.0 +0,1.851000,0.0,0.0,0.0,0.0,0.0 +0,1.851100,0.0,0.0,0.0,0.0,0.0 +0,1.851200,0.0,0.0,0.0,0.0,0.0 +0,1.851300,0.0,0.0,0.0,0.0,0.0 +0,1.851400,0.0,0.0,0.0,0.0,0.0 +0,1.851500,0.0,0.0,0.0,0.0,0.0 +0,1.851600,0.0,0.0,0.0,0.0,0.0 +0,1.851700,0.0,0.0,0.0,0.0,0.0 +0,1.851800,0.0,0.0,0.0,0.0,0.0 +0,1.851900,0.0,0.0,0.0,0.0,0.0 +0,1.852000,0.0,0.0,0.0,0.0,0.0 +0,1.852100,0.0,0.0,0.0,0.0,0.0 +0,1.852200,0.0,0.0,0.0,0.0,0.0 +0,1.852300,0.0,0.0,0.0,0.0,0.0 +0,1.852400,0.0,0.0,0.0,0.0,0.0 +0,1.852500,0.0,0.0,0.0,0.0,0.0 +0,1.852600,0.0,0.0,0.0,0.0,0.0 +0,1.852700,0.0,0.0,0.0,0.0,0.0 +0,1.852800,0.0,0.0,0.0,0.0,0.0 +0,1.852900,0.0,0.0,0.0,0.0,0.0 +0,1.853000,0.0,0.0,0.0,0.0,0.0 +0,1.853100,0.0,0.0,0.0,0.0,0.0 +0,1.853200,0.0,0.0,0.0,0.0,0.0 +0,1.853300,0.0,0.0,0.0,0.0,0.0 +0,1.853400,0.0,0.0,0.0,0.0,0.0 +0,1.853500,0.0,0.0,0.0,0.0,0.0 +0,1.853600,0.0,0.0,0.0,0.0,0.0 +0,1.853700,0.0,0.0,0.0,0.0,0.0 +0,1.853800,0.0,0.0,0.0,0.0,0.0 +0,1.853900,0.0,0.0,0.0,0.0,0.0 +0,1.854000,0.0,0.0,0.0,0.0,0.0 +0,1.854100,0.0,0.0,0.0,0.0,0.0 +0,1.854200,0.0,0.0,0.0,0.0,0.0 +0,1.854300,0.0,0.0,0.0,0.0,0.0 +0,1.854400,0.0,0.0,0.0,0.0,0.0 +0,1.854500,0.0,0.0,0.0,0.0,0.0 +0,1.854600,0.0,0.0,0.0,0.0,0.0 +0,1.854700,0.0,0.0,0.0,0.0,0.0 +0,1.854800,0.0,0.0,0.0,0.0,0.0 +0,1.854900,0.0,0.0,0.0,0.0,0.0 +0,1.855000,0.0,0.0,0.0,0.0,0.0 +0,1.855100,0.0,0.0,0.0,0.0,0.0 +0,1.855200,0.0,0.0,0.0,0.0,0.0 +0,1.855300,0.0,0.0,0.0,0.0,0.0 +0,1.855400,0.0,0.0,0.0,0.0,0.0 +0,1.855500,0.0,0.0,0.0,0.0,0.0 +0,1.855600,0.0,0.0,0.0,0.0,0.0 +0,1.855700,0.0,0.0,0.0,0.0,0.0 +0,1.855800,0.0,0.0,0.0,0.0,0.0 +0,1.855900,0.0,0.0,0.0,0.0,0.0 +0,1.856000,0.0,0.0,0.0,0.0,0.0 +0,1.856100,0.0,0.0,0.0,0.0,0.0 +0,1.856200,0.0,0.0,0.0,0.0,0.0 +0,1.856300,0.0,0.0,0.0,0.0,0.0 +0,1.856400,0.0,0.0,0.0,0.0,0.0 +0,1.856500,0.0,0.0,0.0,0.0,0.0 +0,1.856600,0.0,0.0,0.0,0.0,0.0 +0,1.856700,0.0,0.0,0.0,0.0,0.0 +0,1.856800,0.0,0.0,0.0,0.0,0.0 +0,1.856900,0.0,0.0,0.0,0.0,0.0 +0,1.857000,0.0,0.0,0.0,0.0,0.0 +0,1.857100,0.0,0.0,0.0,0.0,0.0 +0,1.857200,0.0,0.0,0.0,0.0,0.0 +0,1.857300,0.0,0.0,0.0,0.0,0.0 +0,1.857400,0.0,0.0,0.0,0.0,0.0 +0,1.857500,0.0,0.0,0.0,0.0,0.0 +0,1.857600,0.0,0.0,0.0,0.0,0.0 +0,1.857700,0.0,0.0,0.0,0.0,0.0 +0,1.857800,0.0,0.0,0.0,0.0,0.0 +0,1.857900,0.0,0.0,0.0,0.0,0.0 +0,1.858000,0.0,0.0,0.0,0.0,0.0 +0,1.858100,0.0,0.0,0.0,0.0,0.0 +0,1.858200,0.0,0.0,0.0,0.0,0.0 +0,1.858300,0.0,0.0,0.0,0.0,0.0 +0,1.858400,0.0,0.0,0.0,0.0,0.0 +0,1.858500,0.0,0.0,0.0,0.0,0.0 +0,1.858600,0.0,0.0,0.0,0.0,0.0 +0,1.858700,0.0,0.0,0.0,0.0,0.0 +0,1.858800,0.0,0.0,0.0,0.0,0.0 +0,1.858900,0.0,0.0,0.0,0.0,0.0 +0,1.859000,0.0,0.0,0.0,0.0,0.0 +0,1.859100,0.0,0.0,0.0,0.0,0.0 +0,1.859200,0.0,0.0,0.0,0.0,0.0 +0,1.859300,0.0,0.0,0.0,0.0,0.0 +0,1.859400,0.0,0.0,0.0,0.0,0.0 +0,1.859500,0.0,0.0,0.0,0.0,0.0 +0,1.859600,0.0,0.0,0.0,0.0,0.0 +0,1.859700,0.0,0.0,0.0,0.0,0.0 +0,1.859800,0.0,0.0,0.0,0.0,0.0 +0,1.859900,0.0,0.0,0.0,0.0,0.0 +0,1.860000,0.0,0.0,0.0,0.0,0.0 +0,1.860100,0.0,0.0,0.0,0.0,0.0 +1,2681.838725,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.860200,0.0,0.0,0.0,0.0,0.0 +0,1.860300,0.0,0.0,0.0,0.0,0.0 +0,1.860400,0.0,0.0,0.0,0.0,0.0 +0,1.860500,0.0,0.0,0.0,0.0,0.0 +0,1.860600,0.0,0.0,0.0,0.0,0.0 +0,1.860700,0.0,0.0,0.0,0.0,0.0 +0,1.860800,0.0,0.0,0.0,0.0,0.0 +0,1.860900,0.0,0.0,0.0,0.0,0.0 +0,1.861000,0.0,0.0,0.0,0.0,0.0 +0,1.861100,0.0,0.0,0.0,0.0,0.0 +0,1.861200,0.0,0.0,0.0,0.0,0.0 +0,1.861300,0.0,0.0,0.0,0.0,0.0 +0,1.861400,0.0,0.0,0.0,0.0,0.0 +0,1.861500,0.0,0.0,0.0,0.0,0.0 +0,1.861600,0.0,0.0,0.0,0.0,0.0 +0,1.861700,0.0,0.0,0.0,0.0,0.0 +0,1.861800,0.0,0.0,0.0,0.0,0.0 +0,1.861900,0.0,0.0,0.0,0.0,0.0 +0,1.862000,0.0,0.0,0.0,0.0,0.0 +0,1.862100,0.0,0.0,0.0,0.0,0.0 +0,1.862200,0.0,0.0,0.0,0.0,0.0 +0,1.862300,0.0,0.0,0.0,0.0,0.0 +0,1.862400,0.0,0.0,0.0,0.0,0.0 +0,1.862500,0.0,0.0,0.0,0.0,0.0 +0,1.862600,0.0,0.0,0.0,0.0,0.0 +0,1.862700,0.0,0.0,0.0,0.0,0.0 +0,1.862800,0.0,0.0,0.0,0.0,0.0 +0,1.862900,0.0,0.0,0.0,0.0,0.0 +0,1.863000,0.0,0.0,0.0,0.0,0.0 +0,1.863100,0.0,0.0,0.0,0.0,0.0 +0,1.863200,0.0,0.0,0.0,0.0,0.0 +0,1.863300,0.0,0.0,0.0,0.0,0.0 +0,1.863400,0.0,0.0,0.0,0.0,0.0 +0,1.863500,0.0,0.0,0.0,0.0,0.0 +0,1.863600,0.0,0.0,0.0,0.0,0.0 +0,1.863700,0.0,0.0,0.0,0.0,0.0 +0,1.863800,0.0,0.0,0.0,0.0,0.0 +0,1.863900,0.0,0.0,0.0,0.0,0.0 +0,1.864000,0.0,0.0,0.0,0.0,0.0 +0,1.864100,0.0,0.0,0.0,0.0,0.0 +0,1.864200,0.0,0.0,0.0,0.0,0.0 +0,1.864300,0.0,0.0,0.0,0.0,0.0 +0,1.864400,0.0,0.0,0.0,0.0,0.0 +0,1.864500,0.0,0.0,0.0,0.0,0.0 +0,1.864600,0.0,0.0,0.0,0.0,0.0 +0,1.864700,0.0,0.0,0.0,0.0,0.0 +0,1.864800,0.0,0.0,0.0,0.0,0.0 +0,1.864900,0.0,0.0,0.0,0.0,0.0 +0,1.865000,0.0,0.0,0.0,0.0,0.0 +0,1.865100,0.0,0.0,0.0,0.0,0.0 +0,1.865200,0.0,0.0,0.0,0.0,0.0 +0,1.865300,0.0,0.0,0.0,0.0,0.0 +0,1.865400,0.0,0.0,0.0,0.0,0.0 +0,1.865500,0.0,0.0,0.0,0.0,0.0 +0,1.865600,0.0,0.0,0.0,0.0,0.0 +0,1.865700,0.0,0.0,0.0,0.0,0.0 +0,1.865800,0.0,0.0,0.0,0.0,0.0 +0,1.865900,0.0,0.0,0.0,0.0,0.0 +0,1.866000,0.0,0.0,0.0,0.0,0.0 +0,1.866100,0.0,0.0,0.0,0.0,0.0 +0,1.866200,0.0,0.0,0.0,0.0,0.0 +0,1.866300,0.0,0.0,0.0,0.0,0.0 +0,1.866400,0.0,0.0,0.0,0.0,0.0 +0,1.866500,0.0,0.0,0.0,0.0,0.0 +0,1.866600,0.0,0.0,0.0,0.0,0.0 +0,1.866700,0.0,0.0,0.0,0.0,0.0 +0,1.866800,0.0,0.0,0.0,0.0,0.0 +0,1.866900,0.0,0.0,0.0,0.0,0.0 +0,1.867000,0.0,0.0,0.0,0.0,0.0 +0,1.867100,0.0,0.0,0.0,0.0,0.0 +0,1.867200,0.0,0.0,0.0,0.0,0.0 +0,1.867300,0.0,0.0,0.0,0.0,0.0 +0,1.867400,0.0,0.0,0.0,0.0,0.0 +0,1.867500,0.0,0.0,0.0,0.0,0.0 +0,1.867600,0.0,0.0,0.0,0.0,0.0 +0,1.867700,0.0,0.0,0.0,0.0,0.0 +0,1.867800,0.0,0.0,0.0,0.0,0.0 +0,1.867900,0.0,0.0,0.0,0.0,0.0 +0,1.868000,0.0,0.0,0.0,0.0,0.0 +0,1.868100,0.0,0.0,0.0,0.0,0.0 +0,1.868200,0.0,0.0,0.0,0.0,0.0 +0,1.868300,0.0,0.0,0.0,0.0,0.0 +0,1.868400,0.0,0.0,0.0,0.0,0.0 +0,1.868500,0.0,0.0,0.0,0.0,0.0 +0,1.868600,0.0,0.0,0.0,0.0,0.0 +0,1.868700,0.0,0.0,0.0,0.0,0.0 +0,1.868800,0.0,0.0,0.0,0.0,0.0 +0,1.868900,0.0,0.0,0.0,0.0,0.0 +0,1.869000,0.0,0.0,0.0,0.0,0.0 +0,1.869100,0.0,0.0,0.0,0.0,0.0 +0,1.869200,0.0,0.0,0.0,0.0,0.0 +0,1.869300,0.0,0.0,0.0,0.0,0.0 +0,1.869400,0.0,0.0,0.0,0.0,0.0 +0,1.869500,0.0,0.0,0.0,0.0,0.0 +0,1.869600,0.0,0.0,0.0,0.0,0.0 +0,1.869700,0.0,0.0,0.0,0.0,0.0 +0,1.869800,0.0,0.0,0.0,0.0,0.0 +0,1.869900,0.0,0.0,0.0,0.0,0.0 +0,1.870000,0.0,0.0,0.0,0.0,0.0 +0,1.870100,0.0,0.0,0.0,0.0,0.0 +0,1.870200,0.0,0.0,0.0,0.0,0.0 +0,1.870300,0.0,0.0,0.0,0.0,0.0 +0,1.870400,0.0,0.0,0.0,0.0,0.0 +0,1.870500,0.0,0.0,0.0,0.0,0.0 +0,1.870600,0.0,0.0,0.0,0.0,0.0 +0,1.870700,0.0,0.0,0.0,0.0,0.0 +0,1.870800,0.0,0.0,0.0,0.0,0.0 +0,1.870900,0.0,0.0,0.0,0.0,0.0 +0,1.871000,0.0,0.0,0.0,0.0,0.0 +0,1.871100,0.0,0.0,0.0,0.0,0.0 +0,1.871200,0.0,0.0,0.0,0.0,0.0 +0,1.871300,0.0,0.0,0.0,0.0,0.0 +0,1.871400,0.0,0.0,0.0,0.0,0.0 +0,1.871500,0.0,0.0,0.0,0.0,0.0 +0,1.871600,0.0,0.0,0.0,0.0,0.0 +0,1.871700,0.0,0.0,0.0,0.0,0.0 +0,1.871800,0.0,0.0,0.0,0.0,0.0 +0,1.871900,0.0,0.0,0.0,0.0,0.0 +0,1.872000,0.0,0.0,0.0,0.0,0.0 +0,1.872100,0.0,0.0,0.0,0.0,0.0 +0,1.872200,0.0,0.0,0.0,0.0,0.0 +0,1.872300,0.0,0.0,0.0,0.0,0.0 +0,1.872400,0.0,0.0,0.0,0.0,0.0 +0,1.872500,0.0,0.0,0.0,0.0,0.0 +0,1.872600,0.0,0.0,0.0,0.0,0.0 +0,1.872700,0.0,0.0,0.0,0.0,0.0 +0,1.872800,0.0,0.0,0.0,0.0,0.0 +0,1.872900,0.0,0.0,0.0,0.0,0.0 +0,1.873000,0.0,0.0,0.0,0.0,0.0 +0,1.873100,0.0,0.0,0.0,0.0,0.0 +0,1.873200,0.0,0.0,0.0,0.0,0.0 +0,1.873300,0.0,0.0,0.0,0.0,0.0 +0,1.873400,0.0,0.0,0.0,0.0,0.0 +0,1.873500,0.0,0.0,0.0,0.0,0.0 +0,1.873600,0.0,0.0,0.0,0.0,0.0 +0,1.873700,0.0,0.0,0.0,0.0,0.0 +0,1.873800,0.0,0.0,0.0,0.0,0.0 +0,1.873900,0.0,0.0,0.0,0.0,0.0 +0,1.874000,0.0,0.0,0.0,0.0,0.0 +0,1.874100,0.0,0.0,0.0,0.0,0.0 +0,1.874200,0.0,0.0,0.0,0.0,0.0 +0,1.874300,0.0,0.0,0.0,0.0,0.0 +0,1.874400,0.0,0.0,0.0,0.0,0.0 +0,1.874500,0.0,0.0,0.0,0.0,0.0 +0,1.874600,0.0,0.0,0.0,0.0,0.0 +0,1.874700,0.0,0.0,0.0,0.0,0.0 +0,1.874800,0.0,0.0,0.0,0.0,0.0 +0,1.874900,0.0,0.0,0.0,0.0,0.0 +0,1.875000,0.0,0.0,0.0,0.0,0.0 +0,1.875100,0.0,0.0,0.0,0.0,0.0 +0,1.875200,0.0,0.0,0.0,0.0,0.0 +0,1.875300,0.0,0.0,0.0,0.0,0.0 +0,1.875400,0.0,0.0,0.0,0.0,0.0 +0,1.875500,0.0,0.0,0.0,0.0,0.0 +0,1.875600,0.0,0.0,0.0,0.0,0.0 +0,1.875700,0.0,0.0,0.0,0.0,0.0 +0,1.875800,0.0,0.0,0.0,0.0,0.0 +0,1.875900,0.0,0.0,0.0,0.0,0.0 +0,1.876000,0.0,0.0,0.0,0.0,0.0 +0,1.876100,0.0,0.0,0.0,0.0,0.0 +0,1.876200,0.0,0.0,0.0,0.0,0.0 +0,1.876300,0.0,0.0,0.0,0.0,0.0 +0,1.876400,0.0,0.0,0.0,0.0,0.0 +0,1.876500,0.0,0.0,0.0,0.0,0.0 +0,1.876600,0.0,0.0,0.0,0.0,0.0 +0,1.876700,0.0,0.0,0.0,0.0,0.0 +0,1.876800,0.0,0.0,0.0,0.0,0.0 +0,1.876900,0.0,0.0,0.0,0.0,0.0 +0,1.877000,0.0,0.0,0.0,0.0,0.0 +0,1.877100,0.0,0.0,0.0,0.0,0.0 +0,1.877200,0.0,0.0,0.0,0.0,0.0 +0,1.877300,0.0,0.0,0.0,0.0,0.0 +0,1.877400,0.0,0.0,0.0,0.0,0.0 +0,1.877500,0.0,0.0,0.0,0.0,0.0 +0,1.877600,0.0,0.0,0.0,0.0,0.0 +0,1.877700,0.0,0.0,0.0,0.0,0.0 +0,1.877800,0.0,0.0,0.0,0.0,0.0 +0,1.877900,0.0,0.0,0.0,0.0,0.0 +0,1.878000,0.0,0.0,0.0,0.0,0.0 +0,1.878100,0.0,0.0,0.0,0.0,0.0 +0,1.878200,0.0,0.0,0.0,0.0,0.0 +0,1.878300,0.0,0.0,0.0,0.0,0.0 +0,1.878400,0.0,0.0,0.0,0.0,0.0 +0,1.878500,0.0,0.0,0.0,0.0,0.0 +0,1.878600,0.0,0.0,0.0,0.0,0.0 +0,1.878700,0.0,0.0,0.0,0.0,0.0 +0,1.878800,0.0,0.0,0.0,0.0,0.0 +0,1.878900,0.0,0.0,0.0,0.0,0.0 +0,1.879000,0.0,0.0,0.0,0.0,0.0 +0,1.879100,0.0,0.0,0.0,0.0,0.0 +0,1.879200,0.0,0.0,0.0,0.0,0.0 +0,1.879300,0.0,0.0,0.0,0.0,0.0 +0,1.879400,0.0,0.0,0.0,0.0,0.0 +0,1.879500,0.0,0.0,0.0,0.0,0.0 +0,1.879600,0.0,0.0,0.0,0.0,0.0 +0,1.879700,0.0,0.0,0.0,0.0,0.0 +0,1.879800,0.0,0.0,0.0,0.0,0.0 +0,1.879900,0.0,0.0,0.0,0.0,0.0 +0,1.880000,0.0,0.0,0.0,0.0,0.0 +0,1.880100,0.0,0.0,0.0,0.0,0.0 +1,2769.276084,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.880200,0.0,0.0,0.0,0.0,0.0 +0,1.880300,0.0,0.0,0.0,0.0,0.0 +0,1.880400,0.0,0.0,0.0,0.0,0.0 +0,1.880500,0.0,0.0,0.0,0.0,0.0 +0,1.880600,0.0,0.0,0.0,0.0,0.0 +0,1.880700,0.0,0.0,0.0,0.0,0.0 +0,1.880800,0.0,0.0,0.0,0.0,0.0 +0,1.880900,0.0,0.0,0.0,0.0,0.0 +0,1.881000,0.0,0.0,0.0,0.0,0.0 +0,1.881100,0.0,0.0,0.0,0.0,0.0 +0,1.881200,0.0,0.0,0.0,0.0,0.0 +0,1.881300,0.0,0.0,0.0,0.0,0.0 +0,1.881400,0.0,0.0,0.0,0.0,0.0 +0,1.881500,0.0,0.0,0.0,0.0,0.0 +0,1.881600,0.0,0.0,0.0,0.0,0.0 +0,1.881700,0.0,0.0,0.0,0.0,0.0 +0,1.881800,0.0,0.0,0.0,0.0,0.0 +0,1.881900,0.0,0.0,0.0,0.0,0.0 +0,1.882000,0.0,0.0,0.0,0.0,0.0 +0,1.882100,0.0,0.0,0.0,0.0,0.0 +0,1.882200,0.0,0.0,0.0,0.0,0.0 +0,1.882300,0.0,0.0,0.0,0.0,0.0 +0,1.882400,0.0,0.0,0.0,0.0,0.0 +0,1.882500,0.0,0.0,0.0,0.0,0.0 +0,1.882600,0.0,0.0,0.0,0.0,0.0 +0,1.882700,0.0,0.0,0.0,0.0,0.0 +0,1.882800,0.0,0.0,0.0,0.0,0.0 +0,1.882900,0.0,0.0,0.0,0.0,0.0 +0,1.883000,0.0,0.0,0.0,0.0,0.0 +0,1.883100,0.0,0.0,0.0,0.0,0.0 +0,1.883200,0.0,0.0,0.0,0.0,0.0 +0,1.883300,0.0,0.0,0.0,0.0,0.0 +0,1.883400,0.0,0.0,0.0,0.0,0.0 +0,1.883500,0.0,0.0,0.0,0.0,0.0 +0,1.883600,0.0,0.0,0.0,0.0,0.0 +0,1.883700,0.0,0.0,0.0,0.0,0.0 +0,1.883800,0.0,0.0,0.0,0.0,0.0 +0,1.883900,0.0,0.0,0.0,0.0,0.0 +0,1.884000,0.0,0.0,0.0,0.0,0.0 +0,1.884100,0.0,0.0,0.0,0.0,0.0 +0,1.884200,0.0,0.0,0.0,0.0,0.0 +0,1.884300,0.0,0.0,0.0,0.0,0.0 +0,1.884400,0.0,0.0,0.0,0.0,0.0 +0,1.884500,0.0,0.0,0.0,0.0,0.0 +0,1.884600,0.0,0.0,0.0,0.0,0.0 +0,1.884700,0.0,0.0,0.0,0.0,0.0 +0,1.884800,0.0,0.0,0.0,0.0,0.0 +0,1.884900,0.0,0.0,0.0,0.0,0.0 +0,1.885000,0.0,0.0,0.0,0.0,0.0 +0,1.885100,0.0,0.0,0.0,0.0,0.0 +0,1.885200,0.0,0.0,0.0,0.0,0.0 +0,1.885300,0.0,0.0,0.0,0.0,0.0 +0,1.885400,0.0,0.0,0.0,0.0,0.0 +0,1.885500,0.0,0.0,0.0,0.0,0.0 +0,1.885600,0.0,0.0,0.0,0.0,0.0 +0,1.885700,0.0,0.0,0.0,0.0,0.0 +0,1.885800,0.0,0.0,0.0,0.0,0.0 +0,1.885900,0.0,0.0,0.0,0.0,0.0 +0,1.886000,0.0,0.0,0.0,0.0,0.0 +0,1.886100,0.0,0.0,0.0,0.0,0.0 +0,1.886200,0.0,0.0,0.0,0.0,0.0 +0,1.886300,0.0,0.0,0.0,0.0,0.0 +0,1.886400,0.0,0.0,0.0,0.0,0.0 +0,1.886500,0.0,0.0,0.0,0.0,0.0 +0,1.886600,0.0,0.0,0.0,0.0,0.0 +0,1.886700,0.0,0.0,0.0,0.0,0.0 +0,1.886800,0.0,0.0,0.0,0.0,0.0 +0,1.886900,0.0,0.0,0.0,0.0,0.0 +0,1.887000,0.0,0.0,0.0,0.0,0.0 +0,1.887100,0.0,0.0,0.0,0.0,0.0 +0,1.887200,0.0,0.0,0.0,0.0,0.0 +0,1.887300,0.0,0.0,0.0,0.0,0.0 +0,1.887400,0.0,0.0,0.0,0.0,0.0 +0,1.887500,0.0,0.0,0.0,0.0,0.0 +0,1.887600,0.0,0.0,0.0,0.0,0.0 +0,1.887700,0.0,0.0,0.0,0.0,0.0 +0,1.887800,0.0,0.0,0.0,0.0,0.0 +0,1.887900,0.0,0.0,0.0,0.0,0.0 +0,1.888000,0.0,0.0,0.0,0.0,0.0 +0,1.888100,0.0,0.0,0.0,0.0,0.0 +0,1.888200,0.0,0.0,0.0,0.0,0.0 +0,1.888300,0.0,0.0,0.0,0.0,0.0 +0,1.888400,0.0,0.0,0.0,0.0,0.0 +0,1.888500,0.0,0.0,0.0,0.0,0.0 +0,1.888600,0.0,0.0,0.0,0.0,0.0 +0,1.888700,0.0,0.0,0.0,0.0,0.0 +0,1.888800,0.0,0.0,0.0,0.0,0.0 +0,1.888900,0.0,0.0,0.0,0.0,0.0 +0,1.889000,0.0,0.0,0.0,0.0,0.0 +0,1.889100,0.0,0.0,0.0,0.0,0.0 +0,1.889200,0.0,0.0,0.0,0.0,0.0 +0,1.889300,0.0,0.0,0.0,0.0,0.0 +0,1.889400,0.0,0.0,0.0,0.0,0.0 +0,1.889500,0.0,0.0,0.0,0.0,0.0 +0,1.889600,0.0,0.0,0.0,0.0,0.0 +0,1.889700,0.0,0.0,0.0,0.0,0.0 +0,1.889800,0.0,0.0,0.0,0.0,0.0 +0,1.889900,0.0,0.0,0.0,0.0,0.0 +0,1.890000,0.0,0.0,0.0,0.0,0.0 +0,1.890100,0.0,0.0,0.0,0.0,0.0 +0,1.890200,0.0,0.0,0.0,0.0,0.0 +0,1.890300,0.0,0.0,0.0,0.0,0.0 +0,1.890400,0.0,0.0,0.0,0.0,0.0 +0,1.890500,0.0,0.0,0.0,0.0,0.0 +0,1.890600,0.0,0.0,0.0,0.0,0.0 +0,1.890700,0.0,0.0,0.0,0.0,0.0 +0,1.890800,0.0,0.0,0.0,0.0,0.0 +0,1.890900,0.0,0.0,0.0,0.0,0.0 +0,1.891000,0.0,0.0,0.0,0.0,0.0 +0,1.891100,0.0,0.0,0.0,0.0,0.0 +0,1.891200,0.0,0.0,0.0,0.0,0.0 +0,1.891300,0.0,0.0,0.0,0.0,0.0 +0,1.891400,0.0,0.0,0.0,0.0,0.0 +0,1.891500,0.0,0.0,0.0,0.0,0.0 +0,1.891600,0.0,0.0,0.0,0.0,0.0 +0,1.891700,0.0,0.0,0.0,0.0,0.0 +0,1.891800,0.0,0.0,0.0,0.0,0.0 +0,1.891900,0.0,0.0,0.0,0.0,0.0 +0,1.892000,0.0,0.0,0.0,0.0,0.0 +0,1.892100,0.0,0.0,0.0,0.0,0.0 +0,1.892200,0.0,0.0,0.0,0.0,0.0 +0,1.892300,0.0,0.0,0.0,0.0,0.0 +0,1.892400,0.0,0.0,0.0,0.0,0.0 +0,1.892500,0.0,0.0,0.0,0.0,0.0 +0,1.892600,0.0,0.0,0.0,0.0,0.0 +0,1.892700,0.0,0.0,0.0,0.0,0.0 +0,1.892800,0.0,0.0,0.0,0.0,0.0 +0,1.892900,0.0,0.0,0.0,0.0,0.0 +0,1.893000,0.0,0.0,0.0,0.0,0.0 +0,1.893100,0.0,0.0,0.0,0.0,0.0 +0,1.893200,0.0,0.0,0.0,0.0,0.0 +0,1.893300,0.0,0.0,0.0,0.0,0.0 +0,1.893400,0.0,0.0,0.0,0.0,0.0 +0,1.893500,0.0,0.0,0.0,0.0,0.0 +0,1.893600,0.0,0.0,0.0,0.0,0.0 +0,1.893700,0.0,0.0,0.0,0.0,0.0 +0,1.893800,0.0,0.0,0.0,0.0,0.0 +0,1.893900,0.0,0.0,0.0,0.0,0.0 +0,1.894000,0.0,0.0,0.0,0.0,0.0 +0,1.894100,0.0,0.0,0.0,0.0,0.0 +0,1.894200,0.0,0.0,0.0,0.0,0.0 +0,1.894300,0.0,0.0,0.0,0.0,0.0 +0,1.894400,0.0,0.0,0.0,0.0,0.0 +0,1.894500,0.0,0.0,0.0,0.0,0.0 +0,1.894600,0.0,0.0,0.0,0.0,0.0 +0,1.894700,0.0,0.0,0.0,0.0,0.0 +0,1.894800,0.0,0.0,0.0,0.0,0.0 +0,1.894900,0.0,0.0,0.0,0.0,0.0 +0,1.895000,0.0,0.0,0.0,0.0,0.0 +0,1.895100,0.0,0.0,0.0,0.0,0.0 +0,1.895200,0.0,0.0,0.0,0.0,0.0 +0,1.895300,0.0,0.0,0.0,0.0,0.0 +0,1.895400,0.0,0.0,0.0,0.0,0.0 +0,1.895500,0.0,0.0,0.0,0.0,0.0 +0,1.895600,0.0,0.0,0.0,0.0,0.0 +0,1.895700,0.0,0.0,0.0,0.0,0.0 +0,1.895800,0.0,0.0,0.0,0.0,0.0 +0,1.895900,0.0,0.0,0.0,0.0,0.0 +0,1.896000,0.0,0.0,0.0,0.0,0.0 +0,1.896100,0.0,0.0,0.0,0.0,0.0 +0,1.896200,0.0,0.0,0.0,0.0,0.0 +0,1.896300,0.0,0.0,0.0,0.0,0.0 +0,1.896400,0.0,0.0,0.0,0.0,0.0 +0,1.896500,0.0,0.0,0.0,0.0,0.0 +0,1.896600,0.0,0.0,0.0,0.0,0.0 +0,1.896700,0.0,0.0,0.0,0.0,0.0 +0,1.896800,0.0,0.0,0.0,0.0,0.0 +0,1.896900,0.0,0.0,0.0,0.0,0.0 +0,1.897000,0.0,0.0,0.0,0.0,0.0 +0,1.897100,0.0,0.0,0.0,0.0,0.0 +0,1.897200,0.0,0.0,0.0,0.0,0.0 +0,1.897300,0.0,0.0,0.0,0.0,0.0 +0,1.897400,0.0,0.0,0.0,0.0,0.0 +0,1.897500,0.0,0.0,0.0,0.0,0.0 +0,1.897600,0.0,0.0,0.0,0.0,0.0 +0,1.897700,0.0,0.0,0.0,0.0,0.0 +0,1.897800,0.0,0.0,0.0,0.0,0.0 +0,1.897900,0.0,0.0,0.0,0.0,0.0 +0,1.898000,0.0,0.0,0.0,0.0,0.0 +0,1.898100,0.0,0.0,0.0,0.0,0.0 +0,1.898200,0.0,0.0,0.0,0.0,0.0 +0,1.898300,0.0,0.0,0.0,0.0,0.0 +0,1.898400,0.0,0.0,0.0,0.0,0.0 +0,1.898500,0.0,0.0,0.0,0.0,0.0 +0,1.898600,0.0,0.0,0.0,0.0,0.0 +0,1.898700,0.0,0.0,0.0,0.0,0.0 +0,1.898800,0.0,0.0,0.0,0.0,0.0 +0,1.898900,0.0,0.0,0.0,0.0,0.0 +0,1.899000,0.0,0.0,0.0,0.0,0.0 +0,1.899100,0.0,0.0,0.0,0.0,0.0 +0,1.899200,0.0,0.0,0.0,0.0,0.0 +0,1.899300,0.0,0.0,0.0,0.0,0.0 +0,1.899400,0.0,0.0,0.0,0.0,0.0 +0,1.899500,0.0,0.0,0.0,0.0,0.0 +0,1.899600,0.0,0.0,0.0,0.0,0.0 +0,1.899700,0.0,0.0,0.0,0.0,0.0 +0,1.899800,0.0,0.0,0.0,0.0,0.0 +0,1.899900,0.0,0.0,0.0,0.0,0.0 +0,1.900000,0.0,0.0,0.0,0.0,0.0 +0,1.900100,0.0,0.0,0.0,0.0,0.0 +1,2858.593593,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.900200,0.0,0.0,0.0,0.0,0.0 +0,1.900300,0.0,0.0,0.0,0.0,0.0 +0,1.900400,0.0,0.0,0.0,0.0,0.0 +0,1.900500,0.0,0.0,0.0,0.0,0.0 +0,1.900600,0.0,0.0,0.0,0.0,0.0 +0,1.900700,0.0,0.0,0.0,0.0,0.0 +0,1.900800,0.0,0.0,0.0,0.0,0.0 +0,1.900900,0.0,0.0,0.0,0.0,0.0 +0,1.901000,0.0,0.0,0.0,0.0,0.0 +0,1.901100,0.0,0.0,0.0,0.0,0.0 +0,1.901200,0.0,0.0,0.0,0.0,0.0 +0,1.901300,0.0,0.0,0.0,0.0,0.0 +0,1.901400,0.0,0.0,0.0,0.0,0.0 +0,1.901500,0.0,0.0,0.0,0.0,0.0 +0,1.901600,0.0,0.0,0.0,0.0,0.0 +0,1.901700,0.0,0.0,0.0,0.0,0.0 +0,1.901800,0.0,0.0,0.0,0.0,0.0 +0,1.901900,0.0,0.0,0.0,0.0,0.0 +0,1.902000,0.0,0.0,0.0,0.0,0.0 +0,1.902100,0.0,0.0,0.0,0.0,0.0 +0,1.902200,0.0,0.0,0.0,0.0,0.0 +0,1.902300,0.0,0.0,0.0,0.0,0.0 +0,1.902400,0.0,0.0,0.0,0.0,0.0 +0,1.902500,0.0,0.0,0.0,0.0,0.0 +0,1.902600,0.0,0.0,0.0,0.0,0.0 +0,1.902700,0.0,0.0,0.0,0.0,0.0 +0,1.902800,0.0,0.0,0.0,0.0,0.0 +0,1.902900,0.0,0.0,0.0,0.0,0.0 +0,1.903000,0.0,0.0,0.0,0.0,0.0 +0,1.903100,0.0,0.0,0.0,0.0,0.0 +0,1.903200,0.0,0.0,0.0,0.0,0.0 +0,1.903300,0.0,0.0,0.0,0.0,0.0 +0,1.903400,0.0,0.0,0.0,0.0,0.0 +0,1.903500,0.0,0.0,0.0,0.0,0.0 +0,1.903600,0.0,0.0,0.0,0.0,0.0 +0,1.903700,0.0,0.0,0.0,0.0,0.0 +0,1.903800,0.0,0.0,0.0,0.0,0.0 +0,1.903900,0.0,0.0,0.0,0.0,0.0 +0,1.904000,0.0,0.0,0.0,0.0,0.0 +0,1.904100,0.0,0.0,0.0,0.0,0.0 +0,1.904200,0.0,0.0,0.0,0.0,0.0 +0,1.904300,0.0,0.0,0.0,0.0,0.0 +0,1.904400,0.0,0.0,0.0,0.0,0.0 +0,1.904500,0.0,0.0,0.0,0.0,0.0 +0,1.904600,0.0,0.0,0.0,0.0,0.0 +0,1.904700,0.0,0.0,0.0,0.0,0.0 +0,1.904800,0.0,0.0,0.0,0.0,0.0 +0,1.904900,0.0,0.0,0.0,0.0,0.0 +0,1.905000,0.0,0.0,0.0,0.0,0.0 +0,1.905100,0.0,0.0,0.0,0.0,0.0 +0,1.905200,0.0,0.0,0.0,0.0,0.0 +0,1.905300,0.0,0.0,0.0,0.0,0.0 +0,1.905400,0.0,0.0,0.0,0.0,0.0 +0,1.905500,0.0,0.0,0.0,0.0,0.0 +0,1.905600,0.0,0.0,0.0,0.0,0.0 +0,1.905700,0.0,0.0,0.0,0.0,0.0 +0,1.905800,0.0,0.0,0.0,0.0,0.0 +0,1.905900,0.0,0.0,0.0,0.0,0.0 +0,1.906000,0.0,0.0,0.0,0.0,0.0 +0,1.906100,0.0,0.0,0.0,0.0,0.0 +0,1.906200,0.0,0.0,0.0,0.0,0.0 +0,1.906300,0.0,0.0,0.0,0.0,0.0 +0,1.906400,0.0,0.0,0.0,0.0,0.0 +0,1.906500,0.0,0.0,0.0,0.0,0.0 +0,1.906600,0.0,0.0,0.0,0.0,0.0 +0,1.906700,0.0,0.0,0.0,0.0,0.0 +0,1.906800,0.0,0.0,0.0,0.0,0.0 +0,1.906900,0.0,0.0,0.0,0.0,0.0 +0,1.907000,0.0,0.0,0.0,0.0,0.0 +0,1.907100,0.0,0.0,0.0,0.0,0.0 +0,1.907200,0.0,0.0,0.0,0.0,0.0 +0,1.907300,0.0,0.0,0.0,0.0,0.0 +0,1.907400,0.0,0.0,0.0,0.0,0.0 +0,1.907500,0.0,0.0,0.0,0.0,0.0 +0,1.907600,0.0,0.0,0.0,0.0,0.0 +0,1.907700,0.0,0.0,0.0,0.0,0.0 +0,1.907800,0.0,0.0,0.0,0.0,0.0 +0,1.907900,0.0,0.0,0.0,0.0,0.0 +0,1.908000,0.0,0.0,0.0,0.0,0.0 +0,1.908100,0.0,0.0,0.0,0.0,0.0 +0,1.908200,0.0,0.0,0.0,0.0,0.0 +0,1.908300,0.0,0.0,0.0,0.0,0.0 +0,1.908400,0.0,0.0,0.0,0.0,0.0 +0,1.908500,0.0,0.0,0.0,0.0,0.0 +0,1.908600,0.0,0.0,0.0,0.0,0.0 +0,1.908700,0.0,0.0,0.0,0.0,0.0 +0,1.908800,0.0,0.0,0.0,0.0,0.0 +0,1.908900,0.0,0.0,0.0,0.0,0.0 +0,1.909000,0.0,0.0,0.0,0.0,0.0 +0,1.909100,0.0,0.0,0.0,0.0,0.0 +0,1.909200,0.0,0.0,0.0,0.0,0.0 +0,1.909300,0.0,0.0,0.0,0.0,0.0 +0,1.909400,0.0,0.0,0.0,0.0,0.0 +0,1.909500,0.0,0.0,0.0,0.0,0.0 +0,1.909600,0.0,0.0,0.0,0.0,0.0 +0,1.909700,0.0,0.0,0.0,0.0,0.0 +0,1.909800,0.0,0.0,0.0,0.0,0.0 +0,1.909900,0.0,0.0,0.0,0.0,0.0 +0,1.910000,0.0,0.0,0.0,0.0,0.0 +0,1.910100,0.0,0.0,0.0,0.0,0.0 +0,1.910200,0.0,0.0,0.0,0.0,0.0 +0,1.910300,0.0,0.0,0.0,0.0,0.0 +0,1.910400,0.0,0.0,0.0,0.0,0.0 +0,1.910500,0.0,0.0,0.0,0.0,0.0 +0,1.910600,0.0,0.0,0.0,0.0,0.0 +0,1.910700,0.0,0.0,0.0,0.0,0.0 +0,1.910800,0.0,0.0,0.0,0.0,0.0 +0,1.910900,0.0,0.0,0.0,0.0,0.0 +0,1.911000,0.0,0.0,0.0,0.0,0.0 +0,1.911100,0.0,0.0,0.0,0.0,0.0 +0,1.911200,0.0,0.0,0.0,0.0,0.0 +0,1.911300,0.0,0.0,0.0,0.0,0.0 +0,1.911400,0.0,0.0,0.0,0.0,0.0 +0,1.911500,0.0,0.0,0.0,0.0,0.0 +0,1.911600,0.0,0.0,0.0,0.0,0.0 +0,1.911700,0.0,0.0,0.0,0.0,0.0 +0,1.911800,0.0,0.0,0.0,0.0,0.0 +0,1.911900,0.0,0.0,0.0,0.0,0.0 +0,1.912000,0.0,0.0,0.0,0.0,0.0 +0,1.912100,0.0,0.0,0.0,0.0,0.0 +0,1.912200,0.0,0.0,0.0,0.0,0.0 +0,1.912300,0.0,0.0,0.0,0.0,0.0 +0,1.912400,0.0,0.0,0.0,0.0,0.0 +0,1.912500,0.0,0.0,0.0,0.0,0.0 +0,1.912600,0.0,0.0,0.0,0.0,0.0 +0,1.912700,0.0,0.0,0.0,0.0,0.0 +0,1.912800,0.0,0.0,0.0,0.0,0.0 +0,1.912900,0.0,0.0,0.0,0.0,0.0 +0,1.913000,0.0,0.0,0.0,0.0,0.0 +0,1.913100,0.0,0.0,0.0,0.0,0.0 +0,1.913200,0.0,0.0,0.0,0.0,0.0 +0,1.913300,0.0,0.0,0.0,0.0,0.0 +0,1.913400,0.0,0.0,0.0,0.0,0.0 +0,1.913500,0.0,0.0,0.0,0.0,0.0 +0,1.913600,0.0,0.0,0.0,0.0,0.0 +0,1.913700,0.0,0.0,0.0,0.0,0.0 +0,1.913800,0.0,0.0,0.0,0.0,0.0 +0,1.913900,0.0,0.0,0.0,0.0,0.0 +0,1.914000,0.0,0.0,0.0,0.0,0.0 +0,1.914100,0.0,0.0,0.0,0.0,0.0 +0,1.914200,0.0,0.0,0.0,0.0,0.0 +0,1.914300,0.0,0.0,0.0,0.0,0.0 +0,1.914400,0.0,0.0,0.0,0.0,0.0 +0,1.914500,0.0,0.0,0.0,0.0,0.0 +0,1.914600,0.0,0.0,0.0,0.0,0.0 +0,1.914700,0.0,0.0,0.0,0.0,0.0 +0,1.914800,0.0,0.0,0.0,0.0,0.0 +0,1.914900,0.0,0.0,0.0,0.0,0.0 +0,1.915000,0.0,0.0,0.0,0.0,0.0 +0,1.915100,0.0,0.0,0.0,0.0,0.0 +0,1.915200,0.0,0.0,0.0,0.0,0.0 +0,1.915300,0.0,0.0,0.0,0.0,0.0 +0,1.915400,0.0,0.0,0.0,0.0,0.0 +0,1.915500,0.0,0.0,0.0,0.0,0.0 +0,1.915600,0.0,0.0,0.0,0.0,0.0 +0,1.915700,0.0,0.0,0.0,0.0,0.0 +0,1.915800,0.0,0.0,0.0,0.0,0.0 +0,1.915900,0.0,0.0,0.0,0.0,0.0 +0,1.916000,0.0,0.0,0.0,0.0,0.0 +0,1.916100,0.0,0.0,0.0,0.0,0.0 +0,1.916200,0.0,0.0,0.0,0.0,0.0 +0,1.916300,0.0,0.0,0.0,0.0,0.0 +0,1.916400,0.0,0.0,0.0,0.0,0.0 +0,1.916500,0.0,0.0,0.0,0.0,0.0 +0,1.916600,0.0,0.0,0.0,0.0,0.0 +0,1.916700,0.0,0.0,0.0,0.0,0.0 +0,1.916800,0.0,0.0,0.0,0.0,0.0 +0,1.916900,0.0,0.0,0.0,0.0,0.0 +0,1.917000,0.0,0.0,0.0,0.0,0.0 +0,1.917100,0.0,0.0,0.0,0.0,0.0 +0,1.917200,0.0,0.0,0.0,0.0,0.0 +0,1.917300,0.0,0.0,0.0,0.0,0.0 +0,1.917400,0.0,0.0,0.0,0.0,0.0 +0,1.917500,0.0,0.0,0.0,0.0,0.0 +0,1.917600,0.0,0.0,0.0,0.0,0.0 +0,1.917700,0.0,0.0,0.0,0.0,0.0 +0,1.917800,0.0,0.0,0.0,0.0,0.0 +0,1.917900,0.0,0.0,0.0,0.0,0.0 +0,1.918000,0.0,0.0,0.0,0.0,0.0 +0,1.918100,0.0,0.0,0.0,0.0,0.0 +0,1.918200,0.0,0.0,0.0,0.0,0.0 +0,1.918300,0.0,0.0,0.0,0.0,0.0 +0,1.918400,0.0,0.0,0.0,0.0,0.0 +0,1.918500,0.0,0.0,0.0,0.0,0.0 +0,1.918600,0.0,0.0,0.0,0.0,0.0 +0,1.918700,0.0,0.0,0.0,0.0,0.0 +0,1.918800,0.0,0.0,0.0,0.0,0.0 +0,1.918900,0.0,0.0,0.0,0.0,0.0 +0,1.919000,0.0,0.0,0.0,0.0,0.0 +0,1.919100,0.0,0.0,0.0,0.0,0.0 +0,1.919200,0.0,0.0,0.0,0.0,0.0 +0,1.919300,0.0,0.0,0.0,0.0,0.0 +0,1.919400,0.0,0.0,0.0,0.0,0.0 +0,1.919500,0.0,0.0,0.0,0.0,0.0 +0,1.919600,0.0,0.0,0.0,0.0,0.0 +0,1.919700,0.0,0.0,0.0,0.0,0.0 +0,1.919800,0.0,0.0,0.0,0.0,0.0 +0,1.919900,0.0,0.0,0.0,0.0,0.0 +0,1.920000,0.0,0.0,0.0,0.0,0.0 +0,1.920100,0.0,0.0,0.0,0.0,0.0 +1,2949.811252,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.920200,0.0,0.0,0.0,0.0,0.0 +0,1.920300,0.0,0.0,0.0,0.0,0.0 +0,1.920400,0.0,0.0,0.0,0.0,0.0 +0,1.920500,0.0,0.0,0.0,0.0,0.0 +0,1.920600,0.0,0.0,0.0,0.0,0.0 +0,1.920700,0.0,0.0,0.0,0.0,0.0 +0,1.920800,0.0,0.0,0.0,0.0,0.0 +0,1.920900,0.0,0.0,0.0,0.0,0.0 +0,1.921000,0.0,0.0,0.0,0.0,0.0 +0,1.921100,0.0,0.0,0.0,0.0,0.0 +0,1.921200,0.0,0.0,0.0,0.0,0.0 +0,1.921300,0.0,0.0,0.0,0.0,0.0 +0,1.921400,0.0,0.0,0.0,0.0,0.0 +0,1.921500,0.0,0.0,0.0,0.0,0.0 +0,1.921600,0.0,0.0,0.0,0.0,0.0 +0,1.921700,0.0,0.0,0.0,0.0,0.0 +0,1.921800,0.0,0.0,0.0,0.0,0.0 +0,1.921900,0.0,0.0,0.0,0.0,0.0 +0,1.922000,0.0,0.0,0.0,0.0,0.0 +0,1.922100,0.0,0.0,0.0,0.0,0.0 +0,1.922200,0.0,0.0,0.0,0.0,0.0 +0,1.922300,0.0,0.0,0.0,0.0,0.0 +0,1.922400,0.0,0.0,0.0,0.0,0.0 +0,1.922500,0.0,0.0,0.0,0.0,0.0 +0,1.922600,0.0,0.0,0.0,0.0,0.0 +0,1.922700,0.0,0.0,0.0,0.0,0.0 +0,1.922800,0.0,0.0,0.0,0.0,0.0 +0,1.922900,0.0,0.0,0.0,0.0,0.0 +0,1.923000,0.0,0.0,0.0,0.0,0.0 +0,1.923100,0.0,0.0,0.0,0.0,0.0 +0,1.923200,0.0,0.0,0.0,0.0,0.0 +0,1.923300,0.0,0.0,0.0,0.0,0.0 +0,1.923400,0.0,0.0,0.0,0.0,0.0 +0,1.923500,0.0,0.0,0.0,0.0,0.0 +0,1.923600,0.0,0.0,0.0,0.0,0.0 +0,1.923700,0.0,0.0,0.0,0.0,0.0 +0,1.923800,0.0,0.0,0.0,0.0,0.0 +0,1.923900,0.0,0.0,0.0,0.0,0.0 +0,1.924000,0.0,0.0,0.0,0.0,0.0 +0,1.924100,0.0,0.0,0.0,0.0,0.0 +0,1.924200,0.0,0.0,0.0,0.0,0.0 +0,1.924300,0.0,0.0,0.0,0.0,0.0 +0,1.924400,0.0,0.0,0.0,0.0,0.0 +0,1.924500,0.0,0.0,0.0,0.0,0.0 +0,1.924600,0.0,0.0,0.0,0.0,0.0 +0,1.924700,0.0,0.0,0.0,0.0,0.0 +0,1.924800,0.0,0.0,0.0,0.0,0.0 +0,1.924900,0.0,0.0,0.0,0.0,0.0 +0,1.925000,0.0,0.0,0.0,0.0,0.0 +0,1.925100,0.0,0.0,0.0,0.0,0.0 +0,1.925200,0.0,0.0,0.0,0.0,0.0 +0,1.925300,0.0,0.0,0.0,0.0,0.0 +0,1.925400,0.0,0.0,0.0,0.0,0.0 +0,1.925500,0.0,0.0,0.0,0.0,0.0 +0,1.925600,0.0,0.0,0.0,0.0,0.0 +0,1.925700,0.0,0.0,0.0,0.0,0.0 +0,1.925800,0.0,0.0,0.0,0.0,0.0 +0,1.925900,0.0,0.0,0.0,0.0,0.0 +0,1.926000,0.0,0.0,0.0,0.0,0.0 +0,1.926100,0.0,0.0,0.0,0.0,0.0 +0,1.926200,0.0,0.0,0.0,0.0,0.0 +0,1.926300,0.0,0.0,0.0,0.0,0.0 +0,1.926400,0.0,0.0,0.0,0.0,0.0 +0,1.926500,0.0,0.0,0.0,0.0,0.0 +0,1.926600,0.0,0.0,0.0,0.0,0.0 +0,1.926700,0.0,0.0,0.0,0.0,0.0 +0,1.926800,0.0,0.0,0.0,0.0,0.0 +0,1.926900,0.0,0.0,0.0,0.0,0.0 +0,1.927000,0.0,0.0,0.0,0.0,0.0 +0,1.927100,0.0,0.0,0.0,0.0,0.0 +0,1.927200,0.0,0.0,0.0,0.0,0.0 +0,1.927300,0.0,0.0,0.0,0.0,0.0 +0,1.927400,0.0,0.0,0.0,0.0,0.0 +0,1.927500,0.0,0.0,0.0,0.0,0.0 +0,1.927600,0.0,0.0,0.0,0.0,0.0 +0,1.927700,0.0,0.0,0.0,0.0,0.0 +0,1.927800,0.0,0.0,0.0,0.0,0.0 +0,1.927900,0.0,0.0,0.0,0.0,0.0 +0,1.928000,0.0,0.0,0.0,0.0,0.0 +0,1.928100,0.0,0.0,0.0,0.0,0.0 +0,1.928200,0.0,0.0,0.0,0.0,0.0 +0,1.928300,0.0,0.0,0.0,0.0,0.0 +0,1.928400,0.0,0.0,0.0,0.0,0.0 +0,1.928500,0.0,0.0,0.0,0.0,0.0 +0,1.928600,0.0,0.0,0.0,0.0,0.0 +0,1.928700,0.0,0.0,0.0,0.0,0.0 +0,1.928800,0.0,0.0,0.0,0.0,0.0 +0,1.928900,0.0,0.0,0.0,0.0,0.0 +0,1.929000,0.0,0.0,0.0,0.0,0.0 +0,1.929100,0.0,0.0,0.0,0.0,0.0 +0,1.929200,0.0,0.0,0.0,0.0,0.0 +0,1.929300,0.0,0.0,0.0,0.0,0.0 +0,1.929400,0.0,0.0,0.0,0.0,0.0 +0,1.929500,0.0,0.0,0.0,0.0,0.0 +0,1.929600,0.0,0.0,0.0,0.0,0.0 +0,1.929700,0.0,0.0,0.0,0.0,0.0 +0,1.929800,0.0,0.0,0.0,0.0,0.0 +0,1.929900,0.0,0.0,0.0,0.0,0.0 +0,1.930000,0.0,0.0,0.0,0.0,0.0 +0,1.930100,0.0,0.0,0.0,0.0,0.0 +0,1.930200,0.0,0.0,0.0,0.0,0.0 +0,1.930300,0.0,0.0,0.0,0.0,0.0 +0,1.930400,0.0,0.0,0.0,0.0,0.0 +0,1.930500,0.0,0.0,0.0,0.0,0.0 +0,1.930600,0.0,0.0,0.0,0.0,0.0 +0,1.930700,0.0,0.0,0.0,0.0,0.0 +0,1.930800,0.0,0.0,0.0,0.0,0.0 +0,1.930900,0.0,0.0,0.0,0.0,0.0 +0,1.931000,0.0,0.0,0.0,0.0,0.0 +0,1.931100,0.0,0.0,0.0,0.0,0.0 +0,1.931200,0.0,0.0,0.0,0.0,0.0 +0,1.931300,0.0,0.0,0.0,0.0,0.0 +0,1.931400,0.0,0.0,0.0,0.0,0.0 +0,1.931500,0.0,0.0,0.0,0.0,0.0 +0,1.931600,0.0,0.0,0.0,0.0,0.0 +0,1.931700,0.0,0.0,0.0,0.0,0.0 +0,1.931800,0.0,0.0,0.0,0.0,0.0 +0,1.931900,0.0,0.0,0.0,0.0,0.0 +0,1.932000,0.0,0.0,0.0,0.0,0.0 +0,1.932100,0.0,0.0,0.0,0.0,0.0 +0,1.932200,0.0,0.0,0.0,0.0,0.0 +0,1.932300,0.0,0.0,0.0,0.0,0.0 +0,1.932400,0.0,0.0,0.0,0.0,0.0 +0,1.932500,0.0,0.0,0.0,0.0,0.0 +0,1.932600,0.0,0.0,0.0,0.0,0.0 +0,1.932700,0.0,0.0,0.0,0.0,0.0 +0,1.932800,0.0,0.0,0.0,0.0,0.0 +0,1.932900,0.0,0.0,0.0,0.0,0.0 +0,1.933000,0.0,0.0,0.0,0.0,0.0 +0,1.933100,0.0,0.0,0.0,0.0,0.0 +0,1.933200,0.0,0.0,0.0,0.0,0.0 +0,1.933300,0.0,0.0,0.0,0.0,0.0 +0,1.933400,0.0,0.0,0.0,0.0,0.0 +0,1.933500,0.0,0.0,0.0,0.0,0.0 +0,1.933600,0.0,0.0,0.0,0.0,0.0 +0,1.933700,0.0,0.0,0.0,0.0,0.0 +0,1.933800,0.0,0.0,0.0,0.0,0.0 +0,1.933900,0.0,0.0,0.0,0.0,0.0 +0,1.934000,0.0,0.0,0.0,0.0,0.0 +0,1.934100,0.0,0.0,0.0,0.0,0.0 +0,1.934200,0.0,0.0,0.0,0.0,0.0 +0,1.934300,0.0,0.0,0.0,0.0,0.0 +0,1.934400,0.0,0.0,0.0,0.0,0.0 +0,1.934500,0.0,0.0,0.0,0.0,0.0 +0,1.934600,0.0,0.0,0.0,0.0,0.0 +0,1.934700,0.0,0.0,0.0,0.0,0.0 +0,1.934800,0.0,0.0,0.0,0.0,0.0 +0,1.934900,0.0,0.0,0.0,0.0,0.0 +0,1.935000,0.0,0.0,0.0,0.0,0.0 +0,1.935100,0.0,0.0,0.0,0.0,0.0 +0,1.935200,0.0,0.0,0.0,0.0,0.0 +0,1.935300,0.0,0.0,0.0,0.0,0.0 +0,1.935400,0.0,0.0,0.0,0.0,0.0 +0,1.935500,0.0,0.0,0.0,0.0,0.0 +0,1.935600,0.0,0.0,0.0,0.0,0.0 +0,1.935700,0.0,0.0,0.0,0.0,0.0 +0,1.935800,0.0,0.0,0.0,0.0,0.0 +0,1.935900,0.0,0.0,0.0,0.0,0.0 +0,1.936000,0.0,0.0,0.0,0.0,0.0 +0,1.936100,0.0,0.0,0.0,0.0,0.0 +0,1.936200,0.0,0.0,0.0,0.0,0.0 +0,1.936300,0.0,0.0,0.0,0.0,0.0 +0,1.936400,0.0,0.0,0.0,0.0,0.0 +0,1.936500,0.0,0.0,0.0,0.0,0.0 +0,1.936600,0.0,0.0,0.0,0.0,0.0 +0,1.936700,0.0,0.0,0.0,0.0,0.0 +0,1.936800,0.0,0.0,0.0,0.0,0.0 +0,1.936900,0.0,0.0,0.0,0.0,0.0 +0,1.937000,0.0,0.0,0.0,0.0,0.0 +0,1.937100,0.0,0.0,0.0,0.0,0.0 +0,1.937200,0.0,0.0,0.0,0.0,0.0 +0,1.937300,0.0,0.0,0.0,0.0,0.0 +0,1.937400,0.0,0.0,0.0,0.0,0.0 +0,1.937500,0.0,0.0,0.0,0.0,0.0 +0,1.937600,0.0,0.0,0.0,0.0,0.0 +0,1.937700,0.0,0.0,0.0,0.0,0.0 +0,1.937800,0.0,0.0,0.0,0.0,0.0 +0,1.937900,0.0,0.0,0.0,0.0,0.0 +0,1.938000,0.0,0.0,0.0,0.0,0.0 +0,1.938100,0.0,0.0,0.0,0.0,0.0 +0,1.938200,0.0,0.0,0.0,0.0,0.0 +0,1.938300,0.0,0.0,0.0,0.0,0.0 +0,1.938400,0.0,0.0,0.0,0.0,0.0 +0,1.938500,0.0,0.0,0.0,0.0,0.0 +0,1.938600,0.0,0.0,0.0,0.0,0.0 +0,1.938700,0.0,0.0,0.0,0.0,0.0 +0,1.938800,0.0,0.0,0.0,0.0,0.0 +0,1.938900,0.0,0.0,0.0,0.0,0.0 +0,1.939000,0.0,0.0,0.0,0.0,0.0 +0,1.939100,0.0,0.0,0.0,0.0,0.0 +0,1.939200,0.0,0.0,0.0,0.0,0.0 +0,1.939300,0.0,0.0,0.0,0.0,0.0 +0,1.939400,0.0,0.0,0.0,0.0,0.0 +0,1.939500,0.0,0.0,0.0,0.0,0.0 +0,1.939600,0.0,0.0,0.0,0.0,0.0 +0,1.939700,0.0,0.0,0.0,0.0,0.0 +0,1.939800,0.0,0.0,0.0,0.0,0.0 +0,1.939900,0.0,0.0,0.0,0.0,0.0 +0,1.940000,0.0,0.0,0.0,0.0,0.0 +0,1.940100,0.0,0.0,0.0,0.0,0.0 +1,3042.949061,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.940200,0.0,0.0,0.0,0.0,0.0 +0,1.940300,0.0,0.0,0.0,0.0,0.0 +0,1.940400,0.0,0.0,0.0,0.0,0.0 +0,1.940500,0.0,0.0,0.0,0.0,0.0 +0,1.940600,0.0,0.0,0.0,0.0,0.0 +0,1.940700,0.0,0.0,0.0,0.0,0.0 +0,1.940800,0.0,0.0,0.0,0.0,0.0 +0,1.940900,0.0,0.0,0.0,0.0,0.0 +0,1.941000,0.0,0.0,0.0,0.0,0.0 +0,1.941100,0.0,0.0,0.0,0.0,0.0 +0,1.941200,0.0,0.0,0.0,0.0,0.0 +0,1.941300,0.0,0.0,0.0,0.0,0.0 +0,1.941400,0.0,0.0,0.0,0.0,0.0 +0,1.941500,0.0,0.0,0.0,0.0,0.0 +0,1.941600,0.0,0.0,0.0,0.0,0.0 +0,1.941700,0.0,0.0,0.0,0.0,0.0 +0,1.941800,0.0,0.0,0.0,0.0,0.0 +0,1.941900,0.0,0.0,0.0,0.0,0.0 +0,1.942000,0.0,0.0,0.0,0.0,0.0 +0,1.942100,0.0,0.0,0.0,0.0,0.0 +0,1.942200,0.0,0.0,0.0,0.0,0.0 +0,1.942300,0.0,0.0,0.0,0.0,0.0 +0,1.942400,0.0,0.0,0.0,0.0,0.0 +0,1.942500,0.0,0.0,0.0,0.0,0.0 +0,1.942600,0.0,0.0,0.0,0.0,0.0 +0,1.942700,0.0,0.0,0.0,0.0,0.0 +0,1.942800,0.0,0.0,0.0,0.0,0.0 +0,1.942900,0.0,0.0,0.0,0.0,0.0 +0,1.943000,0.0,0.0,0.0,0.0,0.0 +0,1.943100,0.0,0.0,0.0,0.0,0.0 +0,1.943200,0.0,0.0,0.0,0.0,0.0 +0,1.943300,0.0,0.0,0.0,0.0,0.0 +0,1.943400,0.0,0.0,0.0,0.0,0.0 +0,1.943500,0.0,0.0,0.0,0.0,0.0 +0,1.943600,0.0,0.0,0.0,0.0,0.0 +0,1.943700,0.0,0.0,0.0,0.0,0.0 +0,1.943800,0.0,0.0,0.0,0.0,0.0 +0,1.943900,0.0,0.0,0.0,0.0,0.0 +0,1.944000,0.0,0.0,0.0,0.0,0.0 +0,1.944100,0.0,0.0,0.0,0.0,0.0 +0,1.944200,0.0,0.0,0.0,0.0,0.0 +0,1.944300,0.0,0.0,0.0,0.0,0.0 +0,1.944400,0.0,0.0,0.0,0.0,0.0 +0,1.944500,0.0,0.0,0.0,0.0,0.0 +0,1.944600,0.0,0.0,0.0,0.0,0.0 +0,1.944700,0.0,0.0,0.0,0.0,0.0 +0,1.944800,0.0,0.0,0.0,0.0,0.0 +0,1.944900,0.0,0.0,0.0,0.0,0.0 +0,1.945000,0.0,0.0,0.0,0.0,0.0 +0,1.945100,0.0,0.0,0.0,0.0,0.0 +0,1.945200,0.0,0.0,0.0,0.0,0.0 +0,1.945300,0.0,0.0,0.0,0.0,0.0 +0,1.945400,0.0,0.0,0.0,0.0,0.0 +0,1.945500,0.0,0.0,0.0,0.0,0.0 +0,1.945600,0.0,0.0,0.0,0.0,0.0 +0,1.945700,0.0,0.0,0.0,0.0,0.0 +0,1.945800,0.0,0.0,0.0,0.0,0.0 +0,1.945900,0.0,0.0,0.0,0.0,0.0 +0,1.946000,0.0,0.0,0.0,0.0,0.0 +0,1.946100,0.0,0.0,0.0,0.0,0.0 +0,1.946200,0.0,0.0,0.0,0.0,0.0 +0,1.946300,0.0,0.0,0.0,0.0,0.0 +0,1.946400,0.0,0.0,0.0,0.0,0.0 +0,1.946500,0.0,0.0,0.0,0.0,0.0 +0,1.946600,0.0,0.0,0.0,0.0,0.0 +0,1.946700,0.0,0.0,0.0,0.0,0.0 +0,1.946800,0.0,0.0,0.0,0.0,0.0 +0,1.946900,0.0,0.0,0.0,0.0,0.0 +0,1.947000,0.0,0.0,0.0,0.0,0.0 +0,1.947100,0.0,0.0,0.0,0.0,0.0 +0,1.947200,0.0,0.0,0.0,0.0,0.0 +0,1.947300,0.0,0.0,0.0,0.0,0.0 +0,1.947400,0.0,0.0,0.0,0.0,0.0 +0,1.947500,0.0,0.0,0.0,0.0,0.0 +0,1.947600,0.0,0.0,0.0,0.0,0.0 +0,1.947700,0.0,0.0,0.0,0.0,0.0 +0,1.947800,0.0,0.0,0.0,0.0,0.0 +0,1.947900,0.0,0.0,0.0,0.0,0.0 +0,1.948000,0.0,0.0,0.0,0.0,0.0 +0,1.948100,0.0,0.0,0.0,0.0,0.0 +0,1.948200,0.0,0.0,0.0,0.0,0.0 +0,1.948300,0.0,0.0,0.0,0.0,0.0 +0,1.948400,0.0,0.0,0.0,0.0,0.0 +0,1.948500,0.0,0.0,0.0,0.0,0.0 +0,1.948600,0.0,0.0,0.0,0.0,0.0 +0,1.948700,0.0,0.0,0.0,0.0,0.0 +0,1.948800,0.0,0.0,0.0,0.0,0.0 +0,1.948900,0.0,0.0,0.0,0.0,0.0 +0,1.949000,0.0,0.0,0.0,0.0,0.0 +0,1.949100,0.0,0.0,0.0,0.0,0.0 +0,1.949200,0.0,0.0,0.0,0.0,0.0 +0,1.949300,0.0,0.0,0.0,0.0,0.0 +0,1.949400,0.0,0.0,0.0,0.0,0.0 +0,1.949500,0.0,0.0,0.0,0.0,0.0 +0,1.949600,0.0,0.0,0.0,0.0,0.0 +0,1.949700,0.0,0.0,0.0,0.0,0.0 +0,1.949800,0.0,0.0,0.0,0.0,0.0 +0,1.949900,0.0,0.0,0.0,0.0,0.0 +0,1.950000,0.0,0.0,0.0,0.0,0.0 +0,1.950100,0.0,0.0,0.0,0.0,0.0 +0,1.950200,0.0,0.0,0.0,0.0,0.0 +0,1.950300,0.0,0.0,0.0,0.0,0.0 +0,1.950400,0.0,0.0,0.0,0.0,0.0 +0,1.950500,0.0,0.0,0.0,0.0,0.0 +0,1.950600,0.0,0.0,0.0,0.0,0.0 +0,1.950700,0.0,0.0,0.0,0.0,0.0 +0,1.950800,0.0,0.0,0.0,0.0,0.0 +0,1.950900,0.0,0.0,0.0,0.0,0.0 +0,1.951000,0.0,0.0,0.0,0.0,0.0 +0,1.951100,0.0,0.0,0.0,0.0,0.0 +0,1.951200,0.0,0.0,0.0,0.0,0.0 +0,1.951300,0.0,0.0,0.0,0.0,0.0 +0,1.951400,0.0,0.0,0.0,0.0,0.0 +0,1.951500,0.0,0.0,0.0,0.0,0.0 +0,1.951600,0.0,0.0,0.0,0.0,0.0 +0,1.951700,0.0,0.0,0.0,0.0,0.0 +0,1.951800,0.0,0.0,0.0,0.0,0.0 +0,1.951900,0.0,0.0,0.0,0.0,0.0 +0,1.952000,0.0,0.0,0.0,0.0,0.0 +0,1.952100,0.0,0.0,0.0,0.0,0.0 +0,1.952200,0.0,0.0,0.0,0.0,0.0 +0,1.952300,0.0,0.0,0.0,0.0,0.0 +0,1.952400,0.0,0.0,0.0,0.0,0.0 +0,1.952500,0.0,0.0,0.0,0.0,0.0 +0,1.952600,0.0,0.0,0.0,0.0,0.0 +0,1.952700,0.0,0.0,0.0,0.0,0.0 +0,1.952800,0.0,0.0,0.0,0.0,0.0 +0,1.952900,0.0,0.0,0.0,0.0,0.0 +0,1.953000,0.0,0.0,0.0,0.0,0.0 +0,1.953100,0.0,0.0,0.0,0.0,0.0 +0,1.953200,0.0,0.0,0.0,0.0,0.0 +0,1.953300,0.0,0.0,0.0,0.0,0.0 +0,1.953400,0.0,0.0,0.0,0.0,0.0 +0,1.953500,0.0,0.0,0.0,0.0,0.0 +0,1.953600,0.0,0.0,0.0,0.0,0.0 +0,1.953700,0.0,0.0,0.0,0.0,0.0 +0,1.953800,0.0,0.0,0.0,0.0,0.0 +0,1.953900,0.0,0.0,0.0,0.0,0.0 +0,1.954000,0.0,0.0,0.0,0.0,0.0 +0,1.954100,0.0,0.0,0.0,0.0,0.0 +0,1.954200,0.0,0.0,0.0,0.0,0.0 +0,1.954300,0.0,0.0,0.0,0.0,0.0 +0,1.954400,0.0,0.0,0.0,0.0,0.0 +0,1.954500,0.0,0.0,0.0,0.0,0.0 +0,1.954600,0.0,0.0,0.0,0.0,0.0 +0,1.954700,0.0,0.0,0.0,0.0,0.0 +0,1.954800,0.0,0.0,0.0,0.0,0.0 +0,1.954900,0.0,0.0,0.0,0.0,0.0 +0,1.955000,0.0,0.0,0.0,0.0,0.0 +0,1.955100,0.0,0.0,0.0,0.0,0.0 +0,1.955200,0.0,0.0,0.0,0.0,0.0 +0,1.955300,0.0,0.0,0.0,0.0,0.0 +0,1.955400,0.0,0.0,0.0,0.0,0.0 +0,1.955500,0.0,0.0,0.0,0.0,0.0 +0,1.955600,0.0,0.0,0.0,0.0,0.0 +0,1.955700,0.0,0.0,0.0,0.0,0.0 +0,1.955800,0.0,0.0,0.0,0.0,0.0 +0,1.955900,0.0,0.0,0.0,0.0,0.0 +0,1.956000,0.0,0.0,0.0,0.0,0.0 +0,1.956100,0.0,0.0,0.0,0.0,0.0 +0,1.956200,0.0,0.0,0.0,0.0,0.0 +0,1.956300,0.0,0.0,0.0,0.0,0.0 +0,1.956400,0.0,0.0,0.0,0.0,0.0 +0,1.956500,0.0,0.0,0.0,0.0,0.0 +0,1.956600,0.0,0.0,0.0,0.0,0.0 +0,1.956700,0.0,0.0,0.0,0.0,0.0 +0,1.956800,0.0,0.0,0.0,0.0,0.0 +0,1.956900,0.0,0.0,0.0,0.0,0.0 +0,1.957000,0.0,0.0,0.0,0.0,0.0 +0,1.957100,0.0,0.0,0.0,0.0,0.0 +0,1.957200,0.0,0.0,0.0,0.0,0.0 +0,1.957300,0.0,0.0,0.0,0.0,0.0 +0,1.957400,0.0,0.0,0.0,0.0,0.0 +0,1.957500,0.0,0.0,0.0,0.0,0.0 +0,1.957600,0.0,0.0,0.0,0.0,0.0 +0,1.957700,0.0,0.0,0.0,0.0,0.0 +0,1.957800,0.0,0.0,0.0,0.0,0.0 +0,1.957900,0.0,0.0,0.0,0.0,0.0 +0,1.958000,0.0,0.0,0.0,0.0,0.0 +0,1.958100,0.0,0.0,0.0,0.0,0.0 +0,1.958200,0.0,0.0,0.0,0.0,0.0 +0,1.958300,0.0,0.0,0.0,0.0,0.0 +0,1.958400,0.0,0.0,0.0,0.0,0.0 +0,1.958500,0.0,0.0,0.0,0.0,0.0 +0,1.958600,0.0,0.0,0.0,0.0,0.0 +0,1.958700,0.0,0.0,0.0,0.0,0.0 +0,1.958800,0.0,0.0,0.0,0.0,0.0 +0,1.958900,0.0,0.0,0.0,0.0,0.0 +0,1.959000,0.0,0.0,0.0,0.0,0.0 +0,1.959100,0.0,0.0,0.0,0.0,0.0 +0,1.959200,0.0,0.0,0.0,0.0,0.0 +0,1.959300,0.0,0.0,0.0,0.0,0.0 +0,1.959400,0.0,0.0,0.0,0.0,0.0 +0,1.959500,0.0,0.0,0.0,0.0,0.0 +0,1.959600,0.0,0.0,0.0,0.0,0.0 +0,1.959700,0.0,0.0,0.0,0.0,0.0 +0,1.959800,0.0,0.0,0.0,0.0,0.0 +0,1.959900,0.0,0.0,0.0,0.0,0.0 +0,1.960000,0.0,0.0,0.0,0.0,0.0 +0,1.960100,0.0,0.0,0.0,0.0,0.0 +1,3138.027020,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.960200,0.0,0.0,0.0,0.0,0.0 +0,1.960300,0.0,0.0,0.0,0.0,0.0 +0,1.960400,0.0,0.0,0.0,0.0,0.0 +0,1.960500,0.0,0.0,0.0,0.0,0.0 +0,1.960600,0.0,0.0,0.0,0.0,0.0 +0,1.960700,0.0,0.0,0.0,0.0,0.0 +0,1.960800,0.0,0.0,0.0,0.0,0.0 +0,1.960900,0.0,0.0,0.0,0.0,0.0 +0,1.961000,0.0,0.0,0.0,0.0,0.0 +0,1.961100,0.0,0.0,0.0,0.0,0.0 +0,1.961200,0.0,0.0,0.0,0.0,0.0 +0,1.961300,0.0,0.0,0.0,0.0,0.0 +0,1.961400,0.0,0.0,0.0,0.0,0.0 +0,1.961500,0.0,0.0,0.0,0.0,0.0 +0,1.961600,0.0,0.0,0.0,0.0,0.0 +0,1.961700,0.0,0.0,0.0,0.0,0.0 +0,1.961800,0.0,0.0,0.0,0.0,0.0 +0,1.961900,0.0,0.0,0.0,0.0,0.0 +0,1.962000,0.0,0.0,0.0,0.0,0.0 +0,1.962100,0.0,0.0,0.0,0.0,0.0 +0,1.962200,0.0,0.0,0.0,0.0,0.0 +0,1.962300,0.0,0.0,0.0,0.0,0.0 +0,1.962400,0.0,0.0,0.0,0.0,0.0 +0,1.962500,0.0,0.0,0.0,0.0,0.0 +0,1.962600,0.0,0.0,0.0,0.0,0.0 +0,1.962700,0.0,0.0,0.0,0.0,0.0 +0,1.962800,0.0,0.0,0.0,0.0,0.0 +0,1.962900,0.0,0.0,0.0,0.0,0.0 +0,1.963000,0.0,0.0,0.0,0.0,0.0 +0,1.963100,0.0,0.0,0.0,0.0,0.0 +0,1.963200,0.0,0.0,0.0,0.0,0.0 +0,1.963300,0.0,0.0,0.0,0.0,0.0 +0,1.963400,0.0,0.0,0.0,0.0,0.0 +0,1.963500,0.0,0.0,0.0,0.0,0.0 +0,1.963600,0.0,0.0,0.0,0.0,0.0 +0,1.963700,0.0,0.0,0.0,0.0,0.0 +0,1.963800,0.0,0.0,0.0,0.0,0.0 +0,1.963900,0.0,0.0,0.0,0.0,0.0 +0,1.964000,0.0,0.0,0.0,0.0,0.0 +0,1.964100,0.0,0.0,0.0,0.0,0.0 +0,1.964200,0.0,0.0,0.0,0.0,0.0 +0,1.964300,0.0,0.0,0.0,0.0,0.0 +0,1.964400,0.0,0.0,0.0,0.0,0.0 +0,1.964500,0.0,0.0,0.0,0.0,0.0 +0,1.964600,0.0,0.0,0.0,0.0,0.0 +0,1.964700,0.0,0.0,0.0,0.0,0.0 +0,1.964800,0.0,0.0,0.0,0.0,0.0 +0,1.964900,0.0,0.0,0.0,0.0,0.0 +0,1.965000,0.0,0.0,0.0,0.0,0.0 +0,1.965100,0.0,0.0,0.0,0.0,0.0 +0,1.965200,0.0,0.0,0.0,0.0,0.0 +0,1.965300,0.0,0.0,0.0,0.0,0.0 +0,1.965400,0.0,0.0,0.0,0.0,0.0 +0,1.965500,0.0,0.0,0.0,0.0,0.0 +0,1.965600,0.0,0.0,0.0,0.0,0.0 +0,1.965700,0.0,0.0,0.0,0.0,0.0 +0,1.965800,0.0,0.0,0.0,0.0,0.0 +0,1.965900,0.0,0.0,0.0,0.0,0.0 +0,1.966000,0.0,0.0,0.0,0.0,0.0 +0,1.966100,0.0,0.0,0.0,0.0,0.0 +0,1.966200,0.0,0.0,0.0,0.0,0.0 +0,1.966300,0.0,0.0,0.0,0.0,0.0 +0,1.966400,0.0,0.0,0.0,0.0,0.0 +0,1.966500,0.0,0.0,0.0,0.0,0.0 +0,1.966600,0.0,0.0,0.0,0.0,0.0 +0,1.966700,0.0,0.0,0.0,0.0,0.0 +0,1.966800,0.0,0.0,0.0,0.0,0.0 +0,1.966900,0.0,0.0,0.0,0.0,0.0 +0,1.967000,0.0,0.0,0.0,0.0,0.0 +0,1.967100,0.0,0.0,0.0,0.0,0.0 +0,1.967200,0.0,0.0,0.0,0.0,0.0 +0,1.967300,0.0,0.0,0.0,0.0,0.0 +0,1.967400,0.0,0.0,0.0,0.0,0.0 +0,1.967500,0.0,0.0,0.0,0.0,0.0 +0,1.967600,0.0,0.0,0.0,0.0,0.0 +0,1.967700,0.0,0.0,0.0,0.0,0.0 +0,1.967800,0.0,0.0,0.0,0.0,0.0 +0,1.967900,0.0,0.0,0.0,0.0,0.0 +0,1.968000,0.0,0.0,0.0,0.0,0.0 +0,1.968100,0.0,0.0,0.0,0.0,0.0 +0,1.968200,0.0,0.0,0.0,0.0,0.0 +0,1.968300,0.0,0.0,0.0,0.0,0.0 +0,1.968400,0.0,0.0,0.0,0.0,0.0 +0,1.968500,0.0,0.0,0.0,0.0,0.0 +0,1.968600,0.0,0.0,0.0,0.0,0.0 +0,1.968700,0.0,0.0,0.0,0.0,0.0 +0,1.968800,0.0,0.0,0.0,0.0,0.0 +0,1.968900,0.0,0.0,0.0,0.0,0.0 +0,1.969000,0.0,0.0,0.0,0.0,0.0 +0,1.969100,0.0,0.0,0.0,0.0,0.0 +0,1.969200,0.0,0.0,0.0,0.0,0.0 +0,1.969300,0.0,0.0,0.0,0.0,0.0 +0,1.969400,0.0,0.0,0.0,0.0,0.0 +0,1.969500,0.0,0.0,0.0,0.0,0.0 +0,1.969600,0.0,0.0,0.0,0.0,0.0 +0,1.969700,0.0,0.0,0.0,0.0,0.0 +0,1.969800,0.0,0.0,0.0,0.0,0.0 +0,1.969900,0.0,0.0,0.0,0.0,0.0 +0,1.970000,0.0,0.0,0.0,0.0,0.0 +0,1.970100,0.0,0.0,0.0,0.0,0.0 +0,1.970200,0.0,0.0,0.0,0.0,0.0 +0,1.970300,0.0,0.0,0.0,0.0,0.0 +0,1.970400,0.0,0.0,0.0,0.0,0.0 +0,1.970500,0.0,0.0,0.0,0.0,0.0 +0,1.970600,0.0,0.0,0.0,0.0,0.0 +0,1.970700,0.0,0.0,0.0,0.0,0.0 +0,1.970800,0.0,0.0,0.0,0.0,0.0 +0,1.970900,0.0,0.0,0.0,0.0,0.0 +0,1.971000,0.0,0.0,0.0,0.0,0.0 +0,1.971100,0.0,0.0,0.0,0.0,0.0 +0,1.971200,0.0,0.0,0.0,0.0,0.0 +0,1.971300,0.0,0.0,0.0,0.0,0.0 +0,1.971400,0.0,0.0,0.0,0.0,0.0 +0,1.971500,0.0,0.0,0.0,0.0,0.0 +0,1.971600,0.0,0.0,0.0,0.0,0.0 +0,1.971700,0.0,0.0,0.0,0.0,0.0 +0,1.971800,0.0,0.0,0.0,0.0,0.0 +0,1.971900,0.0,0.0,0.0,0.0,0.0 +0,1.972000,0.0,0.0,0.0,0.0,0.0 +0,1.972100,0.0,0.0,0.0,0.0,0.0 +0,1.972200,0.0,0.0,0.0,0.0,0.0 +0,1.972300,0.0,0.0,0.0,0.0,0.0 +0,1.972400,0.0,0.0,0.0,0.0,0.0 +0,1.972500,0.0,0.0,0.0,0.0,0.0 +0,1.972600,0.0,0.0,0.0,0.0,0.0 +0,1.972700,0.0,0.0,0.0,0.0,0.0 +0,1.972800,0.0,0.0,0.0,0.0,0.0 +0,1.972900,0.0,0.0,0.0,0.0,0.0 +0,1.973000,0.0,0.0,0.0,0.0,0.0 +0,1.973100,0.0,0.0,0.0,0.0,0.0 +0,1.973200,0.0,0.0,0.0,0.0,0.0 +0,1.973300,0.0,0.0,0.0,0.0,0.0 +0,1.973400,0.0,0.0,0.0,0.0,0.0 +0,1.973500,0.0,0.0,0.0,0.0,0.0 +0,1.973600,0.0,0.0,0.0,0.0,0.0 +0,1.973700,0.0,0.0,0.0,0.0,0.0 +0,1.973800,0.0,0.0,0.0,0.0,0.0 +0,1.973900,0.0,0.0,0.0,0.0,0.0 +0,1.974000,0.0,0.0,0.0,0.0,0.0 +0,1.974100,0.0,0.0,0.0,0.0,0.0 +0,1.974200,0.0,0.0,0.0,0.0,0.0 +0,1.974300,0.0,0.0,0.0,0.0,0.0 +0,1.974400,0.0,0.0,0.0,0.0,0.0 +0,1.974500,0.0,0.0,0.0,0.0,0.0 +0,1.974600,0.0,0.0,0.0,0.0,0.0 +0,1.974700,0.0,0.0,0.0,0.0,0.0 +0,1.974800,0.0,0.0,0.0,0.0,0.0 +0,1.974900,0.0,0.0,0.0,0.0,0.0 +0,1.975000,0.0,0.0,0.0,0.0,0.0 +0,1.975100,0.0,0.0,0.0,0.0,0.0 +0,1.975200,0.0,0.0,0.0,0.0,0.0 +0,1.975300,0.0,0.0,0.0,0.0,0.0 +0,1.975400,0.0,0.0,0.0,0.0,0.0 +0,1.975500,0.0,0.0,0.0,0.0,0.0 +0,1.975600,0.0,0.0,0.0,0.0,0.0 +0,1.975700,0.0,0.0,0.0,0.0,0.0 +0,1.975800,0.0,0.0,0.0,0.0,0.0 +0,1.975900,0.0,0.0,0.0,0.0,0.0 +0,1.976000,0.0,0.0,0.0,0.0,0.0 +0,1.976100,0.0,0.0,0.0,0.0,0.0 +0,1.976200,0.0,0.0,0.0,0.0,0.0 +0,1.976300,0.0,0.0,0.0,0.0,0.0 +0,1.976400,0.0,0.0,0.0,0.0,0.0 +0,1.976500,0.0,0.0,0.0,0.0,0.0 +0,1.976600,0.0,0.0,0.0,0.0,0.0 +0,1.976700,0.0,0.0,0.0,0.0,0.0 +0,1.976800,0.0,0.0,0.0,0.0,0.0 +0,1.976900,0.0,0.0,0.0,0.0,0.0 +0,1.977000,0.0,0.0,0.0,0.0,0.0 +0,1.977100,0.0,0.0,0.0,0.0,0.0 +0,1.977200,0.0,0.0,0.0,0.0,0.0 +0,1.977300,0.0,0.0,0.0,0.0,0.0 +0,1.977400,0.0,0.0,0.0,0.0,0.0 +0,1.977500,0.0,0.0,0.0,0.0,0.0 +0,1.977600,0.0,0.0,0.0,0.0,0.0 +0,1.977700,0.0,0.0,0.0,0.0,0.0 +0,1.977800,0.0,0.0,0.0,0.0,0.0 +0,1.977900,0.0,0.0,0.0,0.0,0.0 +0,1.978000,0.0,0.0,0.0,0.0,0.0 +0,1.978100,0.0,0.0,0.0,0.0,0.0 +0,1.978200,0.0,0.0,0.0,0.0,0.0 +0,1.978300,0.0,0.0,0.0,0.0,0.0 +0,1.978400,0.0,0.0,0.0,0.0,0.0 +0,1.978500,0.0,0.0,0.0,0.0,0.0 +0,1.978600,0.0,0.0,0.0,0.0,0.0 +0,1.978700,0.0,0.0,0.0,0.0,0.0 +0,1.978800,0.0,0.0,0.0,0.0,0.0 +0,1.978900,0.0,0.0,0.0,0.0,0.0 +0,1.979000,0.0,0.0,0.0,0.0,0.0 +0,1.979100,0.0,0.0,0.0,0.0,0.0 +0,1.979200,0.0,0.0,0.0,0.0,0.0 +0,1.979300,0.0,0.0,0.0,0.0,0.0 +0,1.979400,0.0,0.0,0.0,0.0,0.0 +0,1.979500,0.0,0.0,0.0,0.0,0.0 +0,1.979600,0.0,0.0,0.0,0.0,0.0 +0,1.979700,0.0,0.0,0.0,0.0,0.0 +0,1.979800,0.0,0.0,0.0,0.0,0.0 +0,1.979900,0.0,0.0,0.0,0.0,0.0 +0,1.980000,0.0,0.0,0.0,0.0,0.0 +0,1.980100,0.0,0.0,0.0,0.0,0.0 +1,3235.065129,0.0,0.0,0.0,0.0,0.0,1.0 +0,1.980200,0.0,0.0,0.0,0.0,0.0 +0,1.980300,0.0,0.0,0.0,0.0,0.0 +0,1.980400,0.0,0.0,0.0,0.0,0.0 +0,1.980500,0.0,0.0,0.0,0.0,0.0 +0,1.980600,0.0,0.0,0.0,0.0,0.0 +0,1.980700,0.0,0.0,0.0,0.0,0.0 +0,1.980800,0.0,0.0,0.0,0.0,0.0 +0,1.980900,0.0,0.0,0.0,0.0,0.0 +0,1.981000,0.0,0.0,0.0,0.0,0.0 +0,1.981100,0.0,0.0,0.0,0.0,0.0 +0,1.981200,0.0,0.0,0.0,0.0,0.0 +0,1.981300,0.0,0.0,0.0,0.0,0.0 +0,1.981400,0.0,0.0,0.0,0.0,0.0 +0,1.981500,0.0,0.0,0.0,0.0,0.0 +0,1.981600,0.0,0.0,0.0,0.0,0.0 +0,1.981700,0.0,0.0,0.0,0.0,0.0 +0,1.981800,0.0,0.0,0.0,0.0,0.0 +0,1.981900,0.0,0.0,0.0,0.0,0.0 +0,1.982000,0.0,0.0,0.0,0.0,0.0 +0,1.982100,0.0,0.0,0.0,0.0,0.0 +0,1.982200,0.0,0.0,0.0,0.0,0.0 +0,1.982300,0.0,0.0,0.0,0.0,0.0 +0,1.982400,0.0,0.0,0.0,0.0,0.0 +0,1.982500,0.0,0.0,0.0,0.0,0.0 +0,1.982600,0.0,0.0,0.0,0.0,0.0 +0,1.982700,0.0,0.0,0.0,0.0,0.0 +0,1.982800,0.0,0.0,0.0,0.0,0.0 +0,1.982900,0.0,0.0,0.0,0.0,0.0 +0,1.983000,0.0,0.0,0.0,0.0,0.0 +0,1.983100,0.0,0.0,0.0,0.0,0.0 +0,1.983200,0.0,0.0,0.0,0.0,0.0 +0,1.983300,0.0,0.0,0.0,0.0,0.0 +0,1.983400,0.0,0.0,0.0,0.0,0.0 +0,1.983500,0.0,0.0,0.0,0.0,0.0 +0,1.983600,0.0,0.0,0.0,0.0,0.0 +0,1.983700,0.0,0.0,0.0,0.0,0.0 +0,1.983800,0.0,0.0,0.0,0.0,0.0 +0,1.983900,0.0,0.0,0.0,0.0,0.0 +0,1.984000,0.0,0.0,0.0,0.0,0.0 +0,1.984100,0.0,0.0,0.0,0.0,0.0 +0,1.984200,0.0,0.0,0.0,0.0,0.0 +0,1.984300,0.0,0.0,0.0,0.0,0.0 +0,1.984400,0.0,0.0,0.0,0.0,0.0 +0,1.984500,0.0,0.0,0.0,0.0,0.0 +0,1.984600,0.0,0.0,0.0,0.0,0.0 +0,1.984700,0.0,0.0,0.0,0.0,0.0 +0,1.984800,0.0,0.0,0.0,0.0,0.0 +0,1.984900,0.0,0.0,0.0,0.0,0.0 +0,1.985000,0.0,0.0,0.0,0.0,0.0 +0,1.985100,0.0,0.0,0.0,0.0,0.0 +0,1.985200,0.0,0.0,0.0,0.0,0.0 +0,1.985300,0.0,0.0,0.0,0.0,0.0 +0,1.985400,0.0,0.0,0.0,0.0,0.0 +0,1.985500,0.0,0.0,0.0,0.0,0.0 +0,1.985600,0.0,0.0,0.0,0.0,0.0 +0,1.985700,0.0,0.0,0.0,0.0,0.0 +0,1.985800,0.0,0.0,0.0,0.0,0.0 +0,1.985900,0.0,0.0,0.0,0.0,0.0 +0,1.986000,0.0,0.0,0.0,0.0,0.0 +0,1.986100,0.0,0.0,0.0,0.0,0.0 +0,1.986200,0.0,0.0,0.0,0.0,0.0 +0,1.986300,0.0,0.0,0.0,0.0,0.0 +0,1.986400,0.0,0.0,0.0,0.0,0.0 +0,1.986500,0.0,0.0,0.0,0.0,0.0 +0,1.986600,0.0,0.0,0.0,0.0,0.0 +0,1.986700,0.0,0.0,0.0,0.0,0.0 +0,1.986800,0.0,0.0,0.0,0.0,0.0 +0,1.986900,0.0,0.0,0.0,0.0,0.0 +0,1.987000,0.0,0.0,0.0,0.0,0.0 +0,1.987100,0.0,0.0,0.0,0.0,0.0 +0,1.987200,0.0,0.0,0.0,0.0,0.0 +0,1.987300,0.0,0.0,0.0,0.0,0.0 +0,1.987400,0.0,0.0,0.0,0.0,0.0 +0,1.987500,0.0,0.0,0.0,0.0,0.0 +0,1.987600,0.0,0.0,0.0,0.0,0.0 +0,1.987700,0.0,0.0,0.0,0.0,0.0 +0,1.987800,0.0,0.0,0.0,0.0,0.0 +0,1.987900,0.0,0.0,0.0,0.0,0.0 +0,1.988000,0.0,0.0,0.0,0.0,0.0 +0,1.988100,0.0,0.0,0.0,0.0,0.0 +0,1.988200,0.0,0.0,0.0,0.0,0.0 +0,1.988300,0.0,0.0,0.0,0.0,0.0 +0,1.988400,0.0,0.0,0.0,0.0,0.0 +0,1.988500,0.0,0.0,0.0,0.0,0.0 +0,1.988600,0.0,0.0,0.0,0.0,0.0 +0,1.988700,0.0,0.0,0.0,0.0,0.0 +0,1.988800,0.0,0.0,0.0,0.0,0.0 +0,1.988900,0.0,0.0,0.0,0.0,0.0 +0,1.989000,0.0,0.0,0.0,0.0,0.0 +0,1.989100,0.0,0.0,0.0,0.0,0.0 +0,1.989200,0.0,0.0,0.0,0.0,0.0 +0,1.989300,0.0,0.0,0.0,0.0,0.0 +0,1.989400,0.0,0.0,0.0,0.0,0.0 +0,1.989500,0.0,0.0,0.0,0.0,0.0 +0,1.989600,0.0,0.0,0.0,0.0,0.0 +0,1.989700,0.0,0.0,0.0,0.0,0.0 +0,1.989800,0.0,0.0,0.0,0.0,0.0 +0,1.989900,0.0,0.0,0.0,0.0,0.0 +0,1.990000,0.0,0.0,0.0,0.0,0.0 +0,1.990100,0.0,0.0,0.0,0.0,0.0 +0,1.990200,0.0,0.0,0.0,0.0,0.0 +0,1.990300,0.0,0.0,0.0,0.0,0.0 +0,1.990400,0.0,0.0,0.0,0.0,0.0 +0,1.990500,0.0,0.0,0.0,0.0,0.0 +0,1.990600,0.0,0.0,0.0,0.0,0.0 +0,1.990700,0.0,0.0,0.0,0.0,0.0 +0,1.990800,0.0,0.0,0.0,0.0,0.0 +0,1.990900,0.0,0.0,0.0,0.0,0.0 +0,1.991000,0.0,0.0,0.0,0.0,0.0 +0,1.991100,0.0,0.0,0.0,0.0,0.0 +0,1.991200,0.0,0.0,0.0,0.0,0.0 +0,1.991300,0.0,0.0,0.0,0.0,0.0 +0,1.991400,0.0,0.0,0.0,0.0,0.0 +0,1.991500,0.0,0.0,0.0,0.0,0.0 +0,1.991600,0.0,0.0,0.0,0.0,0.0 +0,1.991700,0.0,0.0,0.0,0.0,0.0 +0,1.991800,0.0,0.0,0.0,0.0,0.0 +0,1.991900,0.0,0.0,0.0,0.0,0.0 +0,1.992000,0.0,0.0,0.0,0.0,0.0 +0,1.992100,0.0,0.0,0.0,0.0,0.0 +0,1.992200,0.0,0.0,0.0,0.0,0.0 +0,1.992300,0.0,0.0,0.0,0.0,0.0 +0,1.992400,0.0,0.0,0.0,0.0,0.0 +0,1.992500,0.0,0.0,0.0,0.0,0.0 +0,1.992600,0.0,0.0,0.0,0.0,0.0 +0,1.992700,0.0,0.0,0.0,0.0,0.0 +0,1.992800,0.0,0.0,0.0,0.0,0.0 +0,1.992900,0.0,0.0,0.0,0.0,0.0 +0,1.993000,0.0,0.0,0.0,0.0,0.0 +0,1.993100,0.0,0.0,0.0,0.0,0.0 +0,1.993200,0.0,0.0,0.0,0.0,0.0 +0,1.993300,0.0,0.0,0.0,0.0,0.0 +0,1.993400,0.0,0.0,0.0,0.0,0.0 +0,1.993500,0.0,0.0,0.0,0.0,0.0 +0,1.993600,0.0,0.0,0.0,0.0,0.0 +0,1.993700,0.0,0.0,0.0,0.0,0.0 +0,1.993800,0.0,0.0,0.0,0.0,0.0 +0,1.993900,0.0,0.0,0.0,0.0,0.0 +0,1.994000,0.0,0.0,0.0,0.0,0.0 +0,1.994100,0.0,0.0,0.0,0.0,0.0 +0,1.994200,0.0,0.0,0.0,0.0,0.0 +0,1.994300,0.0,0.0,0.0,0.0,0.0 +0,1.994400,0.0,0.0,0.0,0.0,0.0 +0,1.994500,0.0,0.0,0.0,0.0,0.0 +0,1.994600,0.0,0.0,0.0,0.0,0.0 +0,1.994700,0.0,0.0,0.0,0.0,0.0 +0,1.994800,0.0,0.0,0.0,0.0,0.0 +0,1.994900,0.0,0.0,0.0,0.0,0.0 +0,1.995000,0.0,0.0,0.0,0.0,0.0 +0,1.995100,0.0,0.0,0.0,0.0,0.0 +0,1.995200,0.0,0.0,0.0,0.0,0.0 +0,1.995300,0.0,0.0,0.0,0.0,0.0 +0,1.995400,0.0,0.0,0.0,0.0,0.0 +0,1.995500,0.0,0.0,0.0,0.0,0.0 +0,1.995600,0.0,0.0,0.0,0.0,0.0 +0,1.995700,0.0,0.0,0.0,0.0,0.0 +0,1.995800,0.0,0.0,0.0,0.0,0.0 +0,1.995900,0.0,0.0,0.0,0.0,0.0 +0,1.996000,0.0,0.0,0.0,0.0,0.0 +0,1.996100,0.0,0.0,0.0,0.0,0.0 +0,1.996200,0.0,0.0,0.0,0.0,0.0 +0,1.996300,0.0,0.0,0.0,0.0,0.0 +0,1.996400,0.0,0.0,0.0,0.0,0.0 +0,1.996500,0.0,0.0,0.0,0.0,0.0 +0,1.996600,0.0,0.0,0.0,0.0,0.0 +0,1.996700,0.0,0.0,0.0,0.0,0.0 +0,1.996800,0.0,0.0,0.0,0.0,0.0 +0,1.996900,0.0,0.0,0.0,0.0,0.0 +0,1.997000,0.0,0.0,0.0,0.0,0.0 +0,1.997100,0.0,0.0,0.0,0.0,0.0 +0,1.997200,0.0,0.0,0.0,0.0,0.0 +0,1.997300,0.0,0.0,0.0,0.0,0.0 +0,1.997400,0.0,0.0,0.0,0.0,0.0 +0,1.997500,0.0,0.0,0.0,0.0,0.0 +0,1.997600,0.0,0.0,0.0,0.0,0.0 +0,1.997700,0.0,0.0,0.0,0.0,0.0 +0,1.997800,0.0,0.0,0.0,0.0,0.0 +0,1.997900,0.0,0.0,0.0,0.0,0.0 +0,1.998000,0.0,0.0,0.0,0.0,0.0 +0,1.998100,0.0,0.0,0.0,0.0,0.0 +0,1.998200,0.0,0.0,0.0,0.0,0.0 +0,1.998300,0.0,0.0,0.0,0.0,0.0 +0,1.998400,0.0,0.0,0.0,0.0,0.0 +0,1.998500,0.0,0.0,0.0,0.0,0.0 +0,1.998600,0.0,0.0,0.0,0.0,0.0 +0,1.998700,0.0,0.0,0.0,0.0,0.0 +0,1.998800,0.0,0.0,0.0,0.0,0.0 +0,1.998900,0.0,0.0,0.0,0.0,0.0 +0,1.999000,0.0,0.0,0.0,0.0,0.0 +0,1.999100,0.0,0.0,0.0,0.0,0.0 +0,1.999200,0.0,0.0,0.0,0.0,0.0 +0,1.999300,0.0,0.0,0.0,0.0,0.0 +0,1.999400,0.0,0.0,0.0,0.0,0.0 +0,1.999500,0.0,0.0,0.0,0.0,0.0 +0,1.999600,0.0,0.0,0.0,0.0,0.0 +0,1.999700,0.0,0.0,0.0,0.0,0.0 +0,1.999800,0.0,0.0,0.0,0.0,0.0 +0,1.999900,0.0,0.0,0.0,0.0,0.0 +0,2.000000,0.0,0.0,0.0,0.0,0.0 diff --git a/examples/ImuFactorsExample.cpp b/examples/ImuFactorsExample.cpp new file mode 100644 index 000000000..a8e50e1f1 --- /dev/null +++ b/examples/ImuFactorsExample.cpp @@ -0,0 +1,269 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file imuFactorsExample + * @brief Test example for using GTSAM ImuFactor and ImuCombinedFactor navigation code. + * @author Garrett (ghemann@gmail.com), Luca Carlone + */ + +/** + * Example of use of the imuFactors (imuFactor and combinedImuFactor) in conjunction with GPS + * - you can test imuFactor (resp. combinedImuFactor) by commenting (resp. uncommenting) + * the line #define USE_COMBINED (few lines below) + * - we read IMU and GPS data from a CSV file, with the following format: + * A row starting with "i" is the first initial position formatted with + * N, E, D, qx, qY, qZ, qW, velN, velE, velD + * A row starting with "0" is an imu measurement + * linAccN, linAccE, linAccD, angVelN, angVelE, angVelD + * A row starting with "1" is a gps correction formatted with + * N, E, D, qX, qY, qZ, qW + * Note that for GPS correction, we're only using the position not the rotation. The + * rotation is provided in the file for ground truth comparison. + */ + +// GTSAM related includes. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Uncomment line below to use the CombinedIMUFactor as opposed to the standard ImuFactor. +// #define USE_COMBINED + +using namespace gtsam; +using namespace std; + +using symbol_shorthand::X; // Pose3 (x,y,z,r,p,y) +using symbol_shorthand::V; // Vel (xdot,ydot,zdot) +using symbol_shorthand::B; // Bias (ax,ay,az,gx,gy,gz) + +const string output_filename = "imuFactorExampleResults.csv"; + +// This will either be PreintegratedImuMeasurements (for ImuFactor) or +// PreintegratedCombinedMeasurements (for CombinedImuFactor). +PreintegrationType *imu_preintegrated_; + +int main(int argc, char* argv[]) +{ + string data_filename; + if (argc < 2) { + printf("using default CSV file\n"); + data_filename = findExampleDataFile("imuAndGPSdata.csv"); + } else { + data_filename = argv[1]; + } + + // Set up output file for plotting errors + FILE* fp_out = fopen(output_filename.c_str(), "w+"); + fprintf(fp_out, "#time(s),x(m),y(m),z(m),qx,qy,qz,qw,gt_x(m),gt_y(m),gt_z(m),gt_qx,gt_qy,gt_qz,gt_qw\n"); + + // Begin parsing the CSV file. Input the first line for initialization. + // From there, we'll iterate through the file and we'll preintegrate the IMU + // or add in the GPS given the input. + ifstream file(data_filename.c_str()); + string value; + + // Format is (N,E,D,qX,qY,qZ,qW,velN,velE,velD) + Eigen::Matrix initial_state = Eigen::Matrix::Zero(); + getline(file, value, ','); // i + for (int i=0; i<9; i++) { + getline(file, value, ','); + initial_state(i) = atof(value.c_str()); + } + getline(file, value, '\n'); + initial_state(9) = atof(value.c_str()); + cout << "initial state:\n" << initial_state.transpose() << "\n\n"; + + // Assemble initial quaternion through gtsam constructor ::quaternion(w,x,y,z); + Rot3 prior_rotation = Rot3::Quaternion(initial_state(6), initial_state(3), + initial_state(4), initial_state(5)); + Point3 prior_point(initial_state.head<3>()); + Pose3 prior_pose(prior_rotation, prior_point); + Vector3 prior_velocity(initial_state.tail<3>()); + imuBias::ConstantBias prior_imu_bias; // assume zero initial bias + + Values initial_values; + int correction_count = 0; + initial_values.insert(X(correction_count), prior_pose); + initial_values.insert(V(correction_count), prior_velocity); + initial_values.insert(B(correction_count), prior_imu_bias); + + // Assemble prior noise model and add it the graph. + noiseModel::Diagonal::shared_ptr pose_noise_model = noiseModel::Diagonal::Sigmas((Vector(6) << 0.01, 0.01, 0.01, 0.5, 0.5, 0.5).finished()); // rad,rad,rad,m, m, m + noiseModel::Diagonal::shared_ptr velocity_noise_model = noiseModel::Isotropic::Sigma(3,0.1); // m/s + noiseModel::Diagonal::shared_ptr bias_noise_model = noiseModel::Isotropic::Sigma(6,1e-3); + + // Add all prior factors (pose, velocity, bias) to the graph. + NonlinearFactorGraph *graph = new NonlinearFactorGraph(); + graph->add(PriorFactor(X(correction_count), prior_pose, pose_noise_model)); + graph->add(PriorFactor(V(correction_count), prior_velocity,velocity_noise_model)); + graph->add(PriorFactor(B(correction_count), prior_imu_bias,bias_noise_model)); + + // We use the sensor specs to build the noise model for the IMU factor. + double accel_noise_sigma = 0.0003924; + double gyro_noise_sigma = 0.000205689024915; + double accel_bias_rw_sigma = 0.004905; + double gyro_bias_rw_sigma = 0.000001454441043; + Matrix33 measured_acc_cov = Matrix33::Identity(3,3) * pow(accel_noise_sigma,2); + Matrix33 measured_omega_cov = Matrix33::Identity(3,3) * pow(gyro_noise_sigma,2); + Matrix33 integration_error_cov = Matrix33::Identity(3,3)*1e-8; // error committed in integrating position from velocities + Matrix33 bias_acc_cov = Matrix33::Identity(3,3) * pow(accel_bias_rw_sigma,2); + Matrix33 bias_omega_cov = Matrix33::Identity(3,3) * pow(gyro_bias_rw_sigma,2); + Matrix66 bias_acc_omega_int = Matrix::Identity(6,6)*1e-5; // error in the bias used for preintegration + + boost::shared_ptr p = PreintegratedCombinedMeasurements::Params::MakeSharedD(0.0); + // PreintegrationBase params: + p->accelerometerCovariance = measured_acc_cov; // acc white noise in continuous + p->integrationCovariance = integration_error_cov; // integration uncertainty continuous + // should be using 2nd order integration + // PreintegratedRotation params: + p->gyroscopeCovariance = measured_omega_cov; // gyro white noise in continuous + // PreintegrationCombinedMeasurements params: + p->biasAccCovariance = bias_acc_cov; // acc bias in continuous + p->biasOmegaCovariance = bias_omega_cov; // gyro bias in continuous + p->biasAccOmegaInt = bias_acc_omega_int; + +#ifdef USE_COMBINED + imu_preintegrated_ = new PreintegratedCombinedMeasurements(p, prior_imu_bias); +#else + imu_preintegrated_ = new PreintegratedImuMeasurements(p, prior_imu_bias); +#endif + + // Store previous state for the imu integration and the latest predicted outcome. + NavState prev_state(prior_pose, prior_velocity); + NavState prop_state = prev_state; + imuBias::ConstantBias prev_bias = prior_imu_bias; + + // Keep track of the total error over the entire run for a simple performance metric. + double current_position_error = 0.0, current_orientation_error = 0.0; + + double output_time = 0.0; + double dt = 0.005; // The real system has noise, but here, results are nearly + // exactly the same, so keeping this for simplicity. + + // All priors have been set up, now iterate through the data file. + while (file.good()) { + + // Parse out first value + getline(file, value, ','); + int type = atoi(value.c_str()); + + if (type == 0) { // IMU measurement + Eigen::Matrix imu = Eigen::Matrix::Zero(); + for (int i=0; i<5; ++i) { + getline(file, value, ','); + imu(i) = atof(value.c_str()); + } + getline(file, value, '\n'); + imu(5) = atof(value.c_str()); + + // Adding the IMU preintegration. + imu_preintegrated_->integrateMeasurement(imu.head<3>(), imu.tail<3>(), dt); + + } else if (type == 1) { // GPS measurement + Eigen::Matrix gps = Eigen::Matrix::Zero(); + for (int i=0; i<6; ++i) { + getline(file, value, ','); + gps(i) = atof(value.c_str()); + } + getline(file, value, '\n'); + gps(6) = atof(value.c_str()); + + correction_count++; + + // Adding IMU factor and GPS factor and optimizing. +#ifdef USE_COMBINED + PreintegratedCombinedMeasurements *preint_imu_combined = dynamic_cast(imu_preintegrated_); + CombinedImuFactor imu_factor(X(correction_count-1), V(correction_count-1), + X(correction_count ), V(correction_count ), + B(correction_count-1), B(correction_count ), + *preint_imu_combined); + graph->add(imu_factor); +#else + PreintegratedImuMeasurements *preint_imu = dynamic_cast(imu_preintegrated_); + ImuFactor imu_factor(X(correction_count-1), V(correction_count-1), + X(correction_count ), V(correction_count ), + B(correction_count-1), + *preint_imu); + graph->add(imu_factor); + imuBias::ConstantBias zero_bias(Vector3(0, 0, 0), Vector3(0, 0, 0)); + graph->add(BetweenFactor(B(correction_count-1), + B(correction_count ), + zero_bias, bias_noise_model)); +#endif + + noiseModel::Diagonal::shared_ptr correction_noise = noiseModel::Isotropic::Sigma(3,1.0); + GPSFactor gps_factor(X(correction_count), + Point3(gps(0), // N, + gps(1), // E, + gps(2)), // D, + correction_noise); + graph->add(gps_factor); + + // Now optimize and compare results. + prop_state = imu_preintegrated_->predict(prev_state, prev_bias); + initial_values.insert(X(correction_count), prop_state.pose()); + initial_values.insert(V(correction_count), prop_state.v()); + initial_values.insert(B(correction_count), prev_bias); + + LevenbergMarquardtOptimizer optimizer(*graph, initial_values); + Values result = optimizer.optimize(); + + // Overwrite the beginning of the preintegration for the next step. + prev_state = NavState(result.at(X(correction_count)), + result.at(V(correction_count))); + prev_bias = result.at(B(correction_count)); + + // Reset the preintegration object. + imu_preintegrated_->resetIntegrationAndSetBias(prev_bias); + + // Print out the position and orientation error for comparison. + Vector3 gtsam_position = prev_state.pose().translation(); + Vector3 position_error = gtsam_position - gps.head<3>(); + current_position_error = position_error.norm(); + + Quaternion gtsam_quat = prev_state.pose().rotation().toQuaternion(); + Quaternion gps_quat(gps(6), gps(3), gps(4), gps(5)); + Quaternion quat_error = gtsam_quat * gps_quat.inverse(); + quat_error.normalize(); + Vector3 euler_angle_error(quat_error.x()*2, + quat_error.y()*2, + quat_error.z()*2); + current_orientation_error = euler_angle_error.norm(); + + // display statistics + cout << "Position error:" << current_position_error << "\t " << "Angular error:" << current_orientation_error << "\n"; + + fprintf(fp_out, "%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f\n", + output_time, gtsam_position(0), gtsam_position(1), gtsam_position(2), + gtsam_quat.x(), gtsam_quat.y(), gtsam_quat.z(), gtsam_quat.w(), + gps(0), gps(1), gps(2), + gps_quat.x(), gps_quat.y(), gps_quat.z(), gps_quat.w()); + + output_time += 1.0; + + } else { + cerr << "ERROR parsing file\n"; + return 1; + } + } + fclose(fp_out); + cout << "Complete, results written to " << output_filename << "\n\n";; + return 0; +} diff --git a/examples/StereoVOExample.cpp b/examples/StereoVOExample.cpp index 19725798c..35d6747bf 100644 --- a/examples/StereoVOExample.cpp +++ b/examples/StereoVOExample.cpp @@ -67,7 +67,7 @@ int main(int argc, char** argv){ initial_estimate.insert(5, Point3(0, -0.5, 5)); //create Levenberg-Marquardt optimizer for resulting factor graph, optimize - LevenbergMarquardtOptimizer optimizer = LevenbergMarquardtOptimizer(graph, initial_estimate); + LevenbergMarquardtOptimizer optimizer(graph, initial_estimate); Values result = optimizer.optimize(); result.print("Final result:\n"); diff --git a/examples/StereoVOExample_large.cpp b/examples/StereoVOExample_large.cpp index e357745be..8b88c772d 100644 --- a/examples/StereoVOExample_large.cpp +++ b/examples/StereoVOExample_large.cpp @@ -105,7 +105,7 @@ int main(int argc, char** argv){ //create Levenberg-Marquardt optimizer to optimize the factor graph LevenbergMarquardtParams params; params.orderingType = Ordering::METIS; - LevenbergMarquardtOptimizer optimizer = LevenbergMarquardtOptimizer(graph, initial_estimate, params); + LevenbergMarquardtOptimizer optimizer(graph, initial_estimate, params); Values result = optimizer.optimize(); cout << "Final result sample:" << endl; diff --git a/examples/easyPoint2KalmanFilter.cpp b/examples/easyPoint2KalmanFilter.cpp index 201ec188b..d68cedb74 100644 --- a/examples/easyPoint2KalmanFilter.cpp +++ b/examples/easyPoint2KalmanFilter.cpp @@ -70,7 +70,7 @@ int main() { // Predict the new value with the EKF class Point2 x1_predict = ekf.predict(factor1); - x1_predict.print("X1 Predict"); + traits::Print(x1_predict, "X1 Predict"); @@ -91,7 +91,7 @@ int main() { // Update the Kalman Filter with the measurement Point2 x1_update = ekf.update(factor2); - x1_update.print("X1 Update"); + traits::Print(x1_update, "X1 Update"); @@ -101,13 +101,13 @@ int main() { difference = Point2(1,0); BetweenFactor factor3(x1, x2, difference, Q); Point2 x2_predict = ekf.predict(factor1); - x2_predict.print("X2 Predict"); + traits::Print(x2_predict, "X2 Predict"); // Update Point2 z2(2.0, 0.0); PriorFactor factor4(x2, z2, R); Point2 x2_update = ekf.update(factor4); - x2_update.print("X2 Update"); + traits::Print(x2_update, "X2 Update"); @@ -117,13 +117,13 @@ int main() { difference = Point2(1,0); BetweenFactor factor5(x2, x3, difference, Q); Point2 x3_predict = ekf.predict(factor5); - x3_predict.print("X3 Predict"); + traits::Print(x3_predict, "X3 Predict"); // Update Point2 z3(3.0, 0.0); PriorFactor factor6(x3, z3, R); Point2 x3_update = ekf.update(factor6); - x3_update.print("X3 Update"); + traits::Print(x3_update, "X3 Update"); return 0; } diff --git a/gtsam.h b/gtsam.h index f9a7483bb..7c5bc99b1 100644 --- a/gtsam.h +++ b/gtsam.h @@ -266,23 +266,12 @@ class Point2 { // Group static gtsam::Point2 identity(); - gtsam::Point2 inverse() const; - gtsam::Point2 compose(const gtsam::Point2& p2) const; - gtsam::Point2 between(const gtsam::Point2& p2) const; - - // Manifold - gtsam::Point2 retract(Vector v) const; - Vector localCoordinates(const gtsam::Point2& p) const; - - // Lie Group - static gtsam::Point2 Expmap(Vector v); - static Vector Logmap(const gtsam::Point2& p); // Standard Interface double x() const; double y() const; Vector vector() const; - double dist(const gtsam::Point2& p2) const; + double distance(const gtsam::Point2& p2) const; double norm() const; // enabling serialization functionality @@ -1368,7 +1357,7 @@ virtual class HessianFactor : gtsam::GaussianFactor { //Standard Interface size_t rows() const; - Matrix info() const; + Matrix information() const; double constantTerm() const; Vector linearTerm() const; @@ -1941,10 +1930,10 @@ virtual class LinearContainerFactor : gtsam::NonlinearFactor { gtsam::JacobianFactor* toJacobian() const; gtsam::HessianFactor* toHessian() const; - static gtsam::NonlinearFactorGraph convertLinearGraph(const gtsam::GaussianFactorGraph& linear_graph, + static gtsam::NonlinearFactorGraph ConvertLinearGraph(const gtsam::GaussianFactorGraph& linear_graph, const gtsam::Values& linearizationPoint); - static gtsam::NonlinearFactorGraph convertLinearGraph(const gtsam::GaussianFactorGraph& linear_graph); + static gtsam::NonlinearFactorGraph ConvertLinearGraph(const gtsam::GaussianFactorGraph& linear_graph); // enabling serialization functionality void serializable() const; diff --git a/gtsam/base/DSFVector.h b/gtsam/base/DSFVector.h index 3c91d68c5..d73accf11 100644 --- a/gtsam/base/DSFVector.h +++ b/gtsam/base/DSFVector.h @@ -13,13 +13,16 @@ * @file DSFVector.h * @date Jun 25, 2010 * @author Kai Ni - * @brief A faster implementation for DSF, which uses vector rather than btree. As a result, the size of the forest is prefixed. + * @brief A faster implementation for DSF, which uses vector rather than btree. */ #pragma once +#include #include + #include + #include #include #include @@ -41,27 +44,26 @@ private: boost::shared_ptr v_;///< Stores parent pointers, representative iff v[i]==i public: - /// constructor that allocate new memory, allows for keys 0...numNodes-1 + /// Constructor that allocates new memory, allows for keys 0...numNodes-1. DSFBase(const size_t numNodes); - /// constructor that uses the existing memory + /// Constructor that uses an existing, pre-allocated vector. DSFBase(const boost::shared_ptr& v_in); - /// find the label of the set in which {key} lives + /// Find the label of the set in which {key} lives. size_t find(size_t key) const; - /// Merge two sets + /// Merge the sets containing i1 and i2. Does nothing if i1 and i2 are already in the same set. void merge(const size_t& i1, const size_t& i2); - /// @deprecated old name +#ifdef GTSAM_ALLOW_DEPRECATED_SINCE_V4 inline size_t findSet(size_t key) const {return find(key);} - - /// @deprecated old name inline void makeUnionInPlace(const size_t& i1, const size_t& i2) {return merge(i1,i2);} +#endif }; /** - * DSFVector additionaly keeps a vector of keys to support more expensive operations + * DSFVector additionally keeps a vector of keys to support more expensive operations * @addtogroup base */ class GTSAM_EXPORT DSFVector: public DSFBase { @@ -70,27 +72,27 @@ private: std::vector keys_; ///< stores keys to support more expensive operations public: - /// constructor that allocate new memory, uses sequential keys 0...numNodes-1 + /// Constructor that allocates new memory, uses sequential keys 0...numNodes-1. DSFVector(const size_t numNodes); - /// constructor that allocates memory, uses given keys + /// Constructor that allocates memory, uses given keys. DSFVector(const std::vector& keys); - /// constructor that uses the existing memory + /// Constructor that uses existing vectors. DSFVector(const boost::shared_ptr& v_in, const std::vector& keys); - // all operations below loop over all keys and hence are *at least* O(n) + // All operations below loop over all keys and hence are *at least* O(n) - /// find whether there is one and only one occurrence for the given {label} + /// Find whether there is one and only one occurrence for the given {label}. bool isSingleton(const size_t& label) const; - /// get the nodes in the tree with the given label + /// Get the nodes in the tree with the given label std::set set(const size_t& label) const; - /// return all sets, i.e. a partition of all elements + /// Return all sets, i.e. a partition of all elements. std::map > sets() const; - /// return all sets, i.e. a partition of all elements + /// Return all sets, i.e. a partition of all elements. std::map > arrays() const; }; diff --git a/gtsam/base/SymmetricBlockMatrix.cpp b/gtsam/base/SymmetricBlockMatrix.cpp index 7cca63092..5eaa2df1c 100644 --- a/gtsam/base/SymmetricBlockMatrix.cpp +++ b/gtsam/base/SymmetricBlockMatrix.cpp @@ -51,32 +51,42 @@ SymmetricBlockMatrix SymmetricBlockMatrix::LikeActiveViewOf( } /* ************************************************************************* */ -VerticalBlockMatrix SymmetricBlockMatrix::choleskyPartial( - DenseIndex nFrontals) { - // Do dense elimination - if (blockStart() != 0) - throw std::invalid_argument( - "Can only do Cholesky when the SymmetricBlockMatrix is not a restricted view, i.e. when blockStart == 0."); - if (!gtsam::choleskyPartial(matrix_, offset(nFrontals))) +Matrix SymmetricBlockMatrix::block(DenseIndex I, DenseIndex J) const { + if (I == J) { + return diagonalBlock(I); + } else if (I < J) { + return aboveDiagonalBlock(I, J); + } else { + return aboveDiagonalBlock(J, I).transpose(); + } +} + +/* ************************************************************************* */ +void SymmetricBlockMatrix::choleskyPartial(DenseIndex nFrontals) { + gttic(VerticalBlockMatrix_choleskyPartial); + DenseIndex topleft = variableColOffsets_[blockStart_]; + if (!gtsam::choleskyPartial(matrix_, offset(nFrontals) - topleft, topleft)) throw CholeskyFailed(); +} - // Split conditional +/* ************************************************************************* */ +VerticalBlockMatrix SymmetricBlockMatrix::split(DenseIndex nFrontals) { + gttic(VerticalBlockMatrix_split); - // Create one big conditionals with many frontal variables. - gttic(Construct_conditional); - const size_t varDim = offset(nFrontals); - VerticalBlockMatrix Ab = VerticalBlockMatrix::LikeActiveViewOf(*this, varDim); - Ab.full() = matrix_.topRows(varDim); - Ab.full().triangularView().setZero(); - gttoc(Construct_conditional); + // Construct a VerticalBlockMatrix that contains [R Sd] + const size_t n1 = offset(nFrontals); + VerticalBlockMatrix RSd = VerticalBlockMatrix::LikeActiveViewOf(*this, n1); + + // Copy into it. + RSd.full() = matrix_.topRows(n1); + RSd.full().triangularView().setZero(); - gttic(Remaining_factor); // Take lower-right block of Ab_ to get the remaining factor blockStart() = nFrontals; - gttoc(Remaining_factor); - return Ab; + return RSd; } + /* ************************************************************************* */ } //\ namespace gtsam diff --git a/gtsam/base/SymmetricBlockMatrix.h b/gtsam/base/SymmetricBlockMatrix.h index 1f81ca1f9..da3a9a8b8 100644 --- a/gtsam/base/SymmetricBlockMatrix.h +++ b/gtsam/base/SymmetricBlockMatrix.h @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- -* GTSAM Copyright 2010, Georgia Tech Research Corporation, +* GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) @@ -19,7 +19,6 @@ #include #include -#include #include #include #include @@ -53,8 +52,8 @@ namespace gtsam { { public: typedef SymmetricBlockMatrix This; - typedef SymmetricBlockMatrixBlockExpr Block; - typedef SymmetricBlockMatrixBlockExpr constBlock; + typedef Eigen::Block Block; + typedef Eigen::Block constBlock; protected: Matrix matrix_; ///< The full matrix @@ -105,12 +104,12 @@ namespace gtsam { throw std::invalid_argument("Requested to create a SymmetricBlockMatrix with dimensions that do not sum to the total size of the provided matrix."); assertInvariants(); } - + /// Copy the block structure, but do not copy the matrix data. If blockStart() has been /// modified, this copies the structure of the corresponding matrix view. In the destination /// SymmetricBlockMatrix, blockStart() will be 0. static SymmetricBlockMatrix LikeActiveViewOf(const SymmetricBlockMatrix& other); - + /// Copy the block structure, but do not copy the matrix data. If blockStart() has been /// modified, this copies the structure of the corresponding matrix view. In the destination /// SymmetricBlockMatrix, blockStart() will be 0. @@ -123,71 +122,165 @@ namespace gtsam { DenseIndex cols() const { return rows(); } /// Block count - DenseIndex nBlocks() const { assertInvariants(); return variableColOffsets_.size() - 1 - blockStart_; } + DenseIndex nBlocks() const { return nActualBlocks() - blockStart_; } - /// Access the block with vertical block index \c i_block and horizontal block index \c j_block. - /// Note that the actual block accessed in the underlying matrix is relative to blockStart(). - Block operator()(DenseIndex i_block, DenseIndex j_block) { - return Block(*this, i_block, j_block); + /// Number of dimensions for variable on this diagonal block. + DenseIndex getDim(DenseIndex block) const { + return calcIndices(block, block, 1, 1)[2]; } - /// Access the block with vertical block index \c i_block and horizontal block index \c j_block. - /// Note that the actual block accessed in the underlying matrix is relative to blockStart(). - constBlock operator()(DenseIndex i_block, DenseIndex j_block) const { - return constBlock(*this, i_block, j_block); + /// @name Block getter methods. + /// @{ + + /// Get a copy of a block (anywhere in the matrix). + /// This method makes a copy - use the methods below if performance is critical. + Matrix block(DenseIndex I, DenseIndex J) const; + + /// Return the J'th diagonal block as a self adjoint view. + Eigen::SelfAdjointView diagonalBlock(DenseIndex J) { + return block_(J, J).selfadjointView(); } - /// Access the range of blocks starting with vertical block index \c i_startBlock, ending with - /// vertical block index \c i_endBlock, starting with horizontal block index \c j_startBlock, - /// and ending with horizontal block index \c j_endBlock. End block indices are exclusive. Note - /// that the actual blocks accessed in the underlying matrix are relative to blockStart(). - Block range(DenseIndex i_startBlock, DenseIndex i_endBlock, DenseIndex j_startBlock, DenseIndex j_endBlock) { - assertInvariants(); - return Block(*this, i_startBlock, j_startBlock, i_endBlock - i_startBlock, j_endBlock - j_startBlock); + /// Return the J'th diagonal block as a self adjoint view. + Eigen::SelfAdjointView diagonalBlock(DenseIndex J) const { + return block_(J, J).selfadjointView(); } - /// Access the range of blocks starting with vertical block index \c i_startBlock, ending with - /// vertical block index \c i_endBlock, starting with horizontal block index \c j_startBlock, - /// and ending with horizontal block index \c j_endBlock. End block indices are exclusive. Note - /// that the actual blocks accessed in the underlying matrix are relative to blockStart(). - constBlock range(DenseIndex i_startBlock, DenseIndex i_endBlock, DenseIndex j_startBlock, DenseIndex j_endBlock) const { - assertInvariants(); - return constBlock(*this, i_startBlock, j_startBlock, i_endBlock - i_startBlock, j_endBlock - j_startBlock); + /// Get the diagonal of the J'th diagonal block. + Vector diagonal(DenseIndex J) const { + return block_(J, J).diagonal(); } - /** Return the full matrix, *not* including any portions excluded by firstBlock(). */ - Block full() - { - return Block(*this, 0, nBlocks(), 0); + /// Get block above the diagonal (I, J). + constBlock aboveDiagonalBlock(DenseIndex I, DenseIndex J) const { + assert(I < J); + return block_(I, J); } - /** Return the full matrix, *not* including any portions excluded by firstBlock(). */ - constBlock full() const - { - return constBlock(*this, 0, nBlocks(), 0); + /// Return the square sub-matrix that contains blocks(i:j, i:j). + Eigen::SelfAdjointView selfadjointView( + DenseIndex I, DenseIndex J) const { + assert(J > I); + return block_(I, I, J - I, J - I).selfadjointView(); } - /** Access to full matrix, including any portions excluded by firstBlock() to other operations. */ - Eigen::SelfAdjointView matrix() const - { - return matrix_; + /// Return the square sub-matrix that contains blocks(i:j, i:j) as a triangular view. + Eigen::TriangularView triangularView(DenseIndex I, + DenseIndex J) const { + assert(J > I); + return block_(I, I, J - I, J - I).triangularView(); } - /** Access to full matrix, including any portions excluded by firstBlock() to other operations. */ - Eigen::SelfAdjointView matrix() - { - return matrix_; + /// Get a range [i,j) from the matrix. Indices are in block units. + constBlock aboveDiagonalRange(DenseIndex i_startBlock, + DenseIndex i_endBlock, + DenseIndex j_startBlock, + DenseIndex j_endBlock) const { + assert(i_startBlock < j_startBlock); + assert(i_endBlock <= j_startBlock); + return block_(i_startBlock, j_startBlock, i_endBlock - i_startBlock, + j_endBlock - j_startBlock); } - /// Return the absolute offset in the underlying matrix of the start of the specified \c block. - DenseIndex offset(DenseIndex block) const - { - assertInvariants(); - DenseIndex actualBlock = block + blockStart_; - checkBlock(actualBlock); - return variableColOffsets_[actualBlock]; + /// Get a range [i,j) from the matrix. Indices are in block units. + Block aboveDiagonalRange(DenseIndex i_startBlock, DenseIndex i_endBlock, + DenseIndex j_startBlock, DenseIndex j_endBlock) { + assert(i_startBlock < j_startBlock); + assert(i_endBlock <= j_startBlock); + return block_(i_startBlock, j_startBlock, i_endBlock - i_startBlock, + j_endBlock - j_startBlock); } + /// @} + /// @name Block setter methods. + /// @{ + + /// Set a diagonal block. Only the upper triangular portion of `xpr` is evaluated. + template + void setDiagonalBlock(DenseIndex I, const XprType& xpr) { + block_(I, I).triangularView() = xpr.template triangularView(); + } + + /// Set an off-diagonal block. Only the upper triangular portion of `xpr` is evaluated. + template + void setOffDiagonalBlock(DenseIndex I, DenseIndex J, const XprType& xpr) { + assert(I != J); + if (I < J) { + block_(I, J) = xpr; + } else { + block_(J, I) = xpr.transpose(); + } + } + + /// Increment the diagonal block by the values in `xpr`. Only reads the upper triangular part of `xpr`. + template + void updateDiagonalBlock(DenseIndex I, const XprType& xpr) { + // TODO(gareth): Eigen won't let us add triangular or self-adjoint views + // here, so we do it manually. + auto dest = block_(I, I); + assert(dest.rows() == xpr.rows()); + assert(dest.cols() == xpr.cols()); + for (DenseIndex col = 0; col < dest.cols(); ++col) { + for (DenseIndex row = 0; row <= col; ++row) { + dest(row, col) += xpr(row, col); + } + } + } + + /// Update an off diagonal block. + /// NOTE(emmett): This assumes noalias(). + template + void updateOffDiagonalBlock(DenseIndex I, DenseIndex J, const XprType& xpr) { + assert(I != J); + if (I < J) { + block_(I, J).noalias() += xpr; + } else { + block_(J, I).noalias() += xpr.transpose(); + } + } + + /// @} + /// @name Accessing the full matrix. + /// @{ + + /// Get self adjoint view. + Eigen::SelfAdjointView selfadjointView() { + return full().selfadjointView(); + } + + /// Get self adjoint view. + Eigen::SelfAdjointView selfadjointView() const { + return full().selfadjointView(); + } + + /// Set the entire active matrix. Only reads the upper triangular part of `xpr`. + template + void setFullMatrix(const XprType& xpr) { + full().triangularView() = xpr.template triangularView(); + } + + /// Set the entire active matrix zero. + void setZero() { + full().triangularView().setZero(); + } + + /// Negate the entire active matrix. + void negate() { + full().triangularView() *= -1.0; + } + + /// Invert the entire active matrix in place. + void invertInPlace() { + const auto identity = Matrix::Identity(rows(), rows()); + full().triangularView() = + selfadjointView() + .llt() + .solve(identity) + .triangularView(); + } + + /// @} + /// Retrieve or modify the first logical block, i.e. the block referenced by block index 0. /// Blocks before it will be inaccessible, except by accessing the underlying matrix using /// matrix(). @@ -197,11 +290,86 @@ namespace gtsam { /// it will be inaccessible, except by accessing the underlying matrix using matrix(). DenseIndex blockStart() const { return blockStart_; } - /// Do partial Cholesky in-place and return the eliminated block matrix, leaving the remaining - /// symmetric matrix in place. - VerticalBlockMatrix choleskyPartial(DenseIndex nFrontals); + /** + * Given the augmented Hessian [A1'A1 A1'A2 A1'b + * A2'A1 A2'A2 A2'b + * b'A1 b'A2 b'b] + * on x1 and x2, does partial Cholesky in-place to obtain [R Sd;0 L] such that + * R'R = A1'A1 + * R'Sd = [A1'A2 A1'b] + * L'L is the augmented Hessian on the the separator x2 + * R and Sd can be interpreted as a GaussianConditional |R*x1 + S*x2 - d]^2 + */ + void choleskyPartial(DenseIndex nFrontals); + + /** + * After partial Cholesky, we can optionally split off R and Sd, to be interpreted as + * a GaussianConditional |R*x1 + S*x2 - d]^2. We leave the symmetric lower block L in place, + * and adjust block_start so now *this refers to it. + */ + VerticalBlockMatrix split(DenseIndex nFrontals); protected: + + /// Number of offsets in the full matrix. + DenseIndex nOffsets() const { + return variableColOffsets_.size(); + } + + /// Number of actual blocks in the full matrix. + DenseIndex nActualBlocks() const { + return nOffsets() - 1; + } + + /// Get an offset for a block index (in the active view). + DenseIndex offset(DenseIndex block) const { + assert(block >= 0); + const DenseIndex actual_index = block + blockStart(); + assert(actual_index < nOffsets()); + return variableColOffsets_[actual_index]; + } + + /// Get an arbitrary block from the matrix. Indices are in block units. + constBlock block_(DenseIndex iBlock, DenseIndex jBlock, + DenseIndex blockRows = 1, DenseIndex blockCols = 1) const { + const std::array indices = + calcIndices(iBlock, jBlock, blockRows, blockCols); + return matrix_.block(indices[0], indices[1], indices[2], indices[3]); + } + + /// Get an arbitrary block from the matrix. Indices are in block units. + Block block_(DenseIndex iBlock, DenseIndex jBlock, DenseIndex blockRows = 1, + DenseIndex blockCols = 1) { + const std::array indices = + calcIndices(iBlock, jBlock, blockRows, blockCols); + return matrix_.block(indices[0], indices[1], indices[2], indices[3]); + } + + /// Get the full matrix as a block. + constBlock full() const { + return block_(0, 0, nBlocks(), nBlocks()); + } + + /// Get the full matrix as a block. + Block full() { + return block_(0, 0, nBlocks(), nBlocks()); + } + + /// Compute the indices into the underlying matrix for a given block. + std::array calcIndices(DenseIndex iBlock, DenseIndex jBlock, + DenseIndex blockRows, + DenseIndex blockCols) const { + assert(blockRows >= 0); + assert(blockCols >= 0); + + // adjust indices to account for start and size of blocks + const DenseIndex denseI = offset(iBlock); + const DenseIndex denseJ = offset(jBlock); + const DenseIndex denseRows = offset(iBlock + blockRows) - denseI; + const DenseIndex denseCols = offset(jBlock + blockCols) - denseJ; + return {{denseI, denseJ, denseRows, denseCols}}; + } + void assertInvariants() const { assert(matrix_.rows() == matrix_.cols()); @@ -209,21 +377,6 @@ namespace gtsam { assert(blockStart_ < (DenseIndex)variableColOffsets_.size()); } - void checkBlock(DenseIndex block) const - { - static_cast(block); //Disable unused varibale warnings. - assert(matrix_.rows() == matrix_.cols()); - assert(matrix_.cols() == variableColOffsets_.back()); - assert(block >= 0); - assert(block < (DenseIndex)variableColOffsets_.size()-1); - assert(variableColOffsets_[block] < matrix_.cols() && variableColOffsets_[block+1] <= matrix_.cols()); - } - - DenseIndex offsetUnchecked(DenseIndex block) const - { - return variableColOffsets_[block + blockStart_]; - } - template void fillOffsets(ITERATOR firstBlockDim, ITERATOR lastBlockDim, bool appendOneDimension) { diff --git a/gtsam/base/SymmetricBlockMatrixBlockExpr.h b/gtsam/base/SymmetricBlockMatrixBlockExpr.h deleted file mode 100644 index dd999ae6c..000000000 --- a/gtsam/base/SymmetricBlockMatrixBlockExpr.h +++ /dev/null @@ -1,337 +0,0 @@ -/* ---------------------------------------------------------------------------- - -* GTSAM Copyright 2010, Georgia Tech Research Corporation, -* Atlanta, Georgia 30332-0415 -* All Rights Reserved -* Authors: Frank Dellaert, et al. (see THANKS for the full author list) - -* See LICENSE for the license information - -* -------------------------------------------------------------------------- */ - -/** -* @file SymmetricBlockMatrixBlockExpr.h -* @brief Matrix expression for a block of a SymmetricBlockMatrix -* @author Richard Roberts -* @date Nov 20, 2013 -*/ -#pragma once - -#include - -namespace gtsam { template class SymmetricBlockMatrixBlockExpr; } -namespace gtsam { class SymmetricBlockMatrix; } - -// traits class for Eigen expressions -namespace Eigen -{ - namespace internal - { - template - struct traits > : - public traits::type> - { - }; - } -} - -namespace gtsam -{ - /// A matrix expression that references a single block of a SymmetricBlockMatrix. Depending on - /// the position of the block, this expression will behave either as a regular matrix block, a - /// transposed matrix block, or a symmetric matrix block. The only reason this class is templated - /// on SymmetricBlockMatrixType is to allow for both const and non-const references. - template - class SymmetricBlockMatrixBlockExpr : public Eigen::EigenBase > - { - protected: - SymmetricBlockMatrixType& xpr_; ///< The referenced SymmetricBlockMatrix - DenseIndex densei_; ///< The scalar indices of the referenced block - DenseIndex densej_; ///< The scalar indices of the referenced block - DenseIndex denseRows_; ///< The scalar size of the referenced block - DenseIndex denseCols_; ///< The scalar size of the referenced block - enum BlockType { Plain, SelfAdjoint, Transposed } blockType_; ///< The type of the referenced block, as determined by the block position - typedef SymmetricBlockMatrixBlockExpr This; - - public: - // Typedefs and constants used in Eigen - typedef typename const_selector::Scalar&, typename Eigen::internal::traits::Scalar>::type ScalarRef; - typedef typename Eigen::internal::traits::Scalar Scalar; - typedef typename Eigen::internal::traits::Index Index; - static const Index ColsAtCompileTime = Eigen::Dynamic; - static const Index RowsAtCompileTime = Eigen::Dynamic; - - typedef typename const_selector::type - DenseMatrixType; - - typedef Eigen::Map > OffDiagonal; - typedef Eigen::SelfAdjointView, Eigen::Upper> SelfAdjointView; - typedef Eigen::TriangularView, Eigen::Upper> TriangularView; - - protected: - mutable Eigen::Block myBlock_; - template friend class SymmetricBlockMatrixBlockExpr; - - public: - /// Create a SymmetricBlockMatrixBlockExpr from the specified block of a SymmetricBlockMatrix. - SymmetricBlockMatrixBlockExpr(SymmetricBlockMatrixType& blockMatrix, Index iBlock, Index jBlock) : - xpr_(blockMatrix), myBlock_(blockMatrix.matrix_.block(0, 0, 0, 0)) - { - initIndices(iBlock, jBlock); - } - - /// Create a SymmetricBlockMatrixBlockExpr from the specified range of blocks of a - /// SymmetricBlockMatrix. - SymmetricBlockMatrixBlockExpr(SymmetricBlockMatrixType& blockMatrix, - Index firstRowBlock, Index firstColBlock, Index rowBlocks, Index colBlocks) : - xpr_(blockMatrix), myBlock_(blockMatrix.matrix_.block(0, 0, 0, 0)) - { - initIndices(firstRowBlock, firstColBlock, rowBlocks, colBlocks); - } - - /// Create a SymmetricBlockMatrixBlockExpr from the specified range of blocks of a - /// SymmetricBlockMatrix. - SymmetricBlockMatrixBlockExpr(SymmetricBlockMatrixType& blockMatrix, Index firstBlock, Index blocks, char /*dummy*/) : - xpr_(blockMatrix), myBlock_(blockMatrix.matrix_.block(0, 0, 0, 0)) - { - initIndices(firstBlock, firstBlock, blocks, blocks); - } - - inline Index rows() const { return blockType_ != Transposed ? denseRows_ : denseCols_; } - inline Index cols() const { return blockType_ != Transposed ? denseCols_ : denseRows_; } - - inline BlockType blockType() const { return blockType_; } - - inline ScalarRef operator()(Index row, Index col) const - { - return coeffInternal(row, col); - } - - inline OffDiagonal knownOffDiagonal() const - { - typedef Eigen::Stride DynamicStride; - - // We can return a Map if we are either on an off-diagonal block, or a block of size 0 or 1 - assert(blockType_ != SelfAdjoint || (denseRows_ <= 1 && denseCols_ <= 1)); - if(blockType_ == Transposed) - { - // Swap the inner and outer stride to produce a transposed Map - Eigen::Block block = const_cast(*this).xpr_.matrix_.block(densei_, densej_, denseRows_, denseCols_); - return Eigen::Map(block.data(), block.cols(), block.rows(), - DynamicStride(block.innerStride(), block.outerStride())); - } - else - { - Eigen::Block block = const_cast(*this).xpr_.matrix_.block(densei_, densej_, denseRows_, denseCols_); - return Eigen::Map(block.data(), block.rows(), block.cols(), - DynamicStride(block.outerStride(), block.innerStride())); - } - } - - inline SelfAdjointView selfadjointView() const - { - assert(blockType_ == SelfAdjoint); - return myBlock_; - } - - inline TriangularView triangularView() const - { - assert(blockType_ == SelfAdjoint); - return myBlock_; - } - - template inline void evalTo(Dest& dst) const - { - // Just try to assign to the object using either a selfadjoint view or a block view - if(blockType_ == SelfAdjoint) - dst = selfadjointView(); - else if(blockType_ == Plain) - dst = myBlock_; - else - dst = myBlock_.transpose(); - } - - //template inline void evalTo(const Eigen::SelfAdjointView& rhs) const - //{ - // if(blockType_ == SelfAdjoint) - // rhs.nestedExpression().triangularView() = triangularView(); - // else - // throw std::invalid_argument("Cannot assign an off-diagonal block to a self-adjoint matrix"); - //} - - //template inline void evalTo(const Eigen::TriangularView& rhs) const - //{ - // if(blockType_ == SelfAdjoint) - // rhs.nestedExpression().triangularView() = triangularView(); - // else - // throw std::invalid_argument("Cannot assign an off-diagonal block to a self-adjoint matrix"); - //} - - template - This& operator=(const Eigen::MatrixBase& rhs) - { - // Just try to assign to the object using either a selfadjoint view or a block view - if(blockType_ == SelfAdjoint) - triangularView() = rhs.derived().template triangularView(); - else if(blockType_ == Plain) - myBlock_ = rhs.derived(); - else - myBlock_.transpose() = rhs.derived(); - return *this; - } - - template - This& operator=(const Eigen::SelfAdjointView& rhs) - { - if(blockType_ == SelfAdjoint) - triangularView() = rhs.nestedExpression().template triangularView(); - else - throw std::invalid_argument("Cannot assign a self-adjoint matrix to an off-diagonal block"); - return *this; - } - - template - This& operator=(const SymmetricBlockMatrixBlockExpr& other) - { - _doAssign(other); - return *this; - } - - This& operator=(const This& other) - { - // This version is required so GCC doesn't synthesize a default operator=. - _doAssign(other); - return *this; - } - - template - This& operator+=(const SymmetricBlockMatrixBlockExpr& other) - { - if(blockType_ == SelfAdjoint) - { - assert((BlockType)other.blockType() == SelfAdjoint); - triangularView() += other.triangularView().nestedExpression(); - } - else if(blockType_ == Plain) - { - assert((BlockType)other.blockType() == Plain || (BlockType)other.blockType() == Transposed); - if((BlockType)other.blockType() == Transposed) - myBlock_ += other.myBlock_.transpose(); - else - myBlock_ += other.myBlock_; - } - else - { - assert((BlockType)other.blockType() == Plain || (BlockType)other.blockType() == Transposed); - if((BlockType)other.blockType() == Transposed) - myBlock_.transpose() += other.myBlock_.transpose(); - else - myBlock_.transpose() += other.myBlock_; - } - return *this; - } - - private: - void initIndices(Index iBlock, Index jBlock, Index blockRows = 1, Index blockCols = 1) - { - if(iBlock == jBlock && blockRows == blockCols) - { - densei_ = xpr_.offset(iBlock); - densej_ = densei_; - if(blockRows > 0) - xpr_.checkBlock(iBlock + blockRows - 1); - denseRows_ = xpr_.offsetUnchecked(iBlock + blockRows) - densei_; - if(blockCols > 0) - xpr_.checkBlock(jBlock + blockCols - 1); - denseCols_ = xpr_.offsetUnchecked(jBlock + blockCols) - densej_; - blockType_ = SelfAdjoint; - } - else - { - if(jBlock > iBlock || (iBlock == jBlock && blockCols > blockRows)) - { - densei_ = xpr_.offset(iBlock); - densej_ = xpr_.offset(jBlock); - if(blockRows > 0) - xpr_.checkBlock(iBlock + blockRows - 1); - denseRows_ = xpr_.offsetUnchecked(iBlock + blockRows) - densei_; - if(blockCols > 0) - xpr_.checkBlock(jBlock + blockCols - 1); - denseCols_ = xpr_.offsetUnchecked(jBlock + blockCols) - densej_; - blockType_ = Plain; - } - else - { - densei_ = xpr_.offset(jBlock); - densej_ = xpr_.offset(iBlock); - if(blockCols > 0) - xpr_.checkBlock(jBlock + blockCols - 1); - denseRows_ = xpr_.offsetUnchecked(jBlock + blockCols) - densei_; - if(blockRows > 0) - xpr_.checkBlock(iBlock + blockRows - 1); - denseCols_ = xpr_.offsetUnchecked(iBlock + blockRows) - densej_; - blockType_ = Transposed; - } - - // Validate that the block does not cross below the diagonal (the indices have already been - // flipped above the diagonal for ranges starting below the diagonal). - if(densei_ + denseRows_ > densej_ + 1) - throw std::invalid_argument("Off-diagonal block ranges may not cross the diagonal"); - } - - new (&myBlock_) Eigen::Block(xpr_.matrix_.block(densei_, densej_, denseRows_, denseCols_)); - } - - template - inline ScalarType coeffInternal(Index row, Index col) const - { - // We leave index checking up to the Block class - if(blockType_ == Plain) - { - return myBlock_(row, col); - } - else if(blockType_ == SelfAdjoint) - { - if(row <= col) - return myBlock_(row, col); - else - return myBlock_.transpose()(row, col); - } - else - { - return myBlock_.transpose()(row, col); - } - } - - template - void _doAssign(const SymmetricBlockMatrixBlockExpr& other) - { - if(blockType_ == SelfAdjoint) - { - assert((BlockType)other.blockType() == SelfAdjoint); - triangularView() = other.triangularView().nestedExpression(); - } - else if(blockType_ == Plain) - { - assert((BlockType)other.blockType() == Plain || (BlockType)other.blockType() == Transposed); - if((BlockType)other.blockType() == Transposed) - myBlock_ = other.myBlock_.transpose(); - else - myBlock_ = other.myBlock_; - } - else - { - assert((BlockType)other.blockType() == Plain || (BlockType)other.blockType() == Transposed); - if((BlockType)other.blockType() == Transposed) - myBlock_.transpose() = other.myBlock_.transpose(); - else - myBlock_.transpose() = other.myBlock_; - } - } - - - }; - -} diff --git a/gtsam/base/Value.h b/gtsam/base/Value.h index 9537baa31..2d5b9d879 100644 --- a/gtsam/base/Value.h +++ b/gtsam/base/Value.h @@ -18,11 +18,12 @@ #pragma once +#include // Configuration from CMake + #include #include #include - namespace gtsam { /** @@ -37,7 +38,7 @@ namespace gtsam { * Values can operate generically on Value objects, retracting or computing * local coordinates for many Value objects of different types. * - * Inheriting from the DerivedValue class templated provides a generic implementation of + * Inheriting from the DerivedValue class template provides a generic implementation of * the pure virtual functions retract_(), localCoordinates_(), and equals_(), eliminating * the need to implement these functions in your class. Note that you must inherit from * DerivedValue templated on the class you are defining. For example you cannot define diff --git a/gtsam/base/VectorSpace.h b/gtsam/base/VectorSpace.h index cc28ac893..5456ae7f5 100644 --- a/gtsam/base/VectorSpace.h +++ b/gtsam/base/VectorSpace.h @@ -311,7 +311,7 @@ struct traits > : typedef Eigen::Matrix Jacobian; typedef OptionalJacobian ChartJacobian; - static TangentVector Local(Fixed origin, Fixed other, + static TangentVector Local(const Fixed& origin, const Fixed& other, ChartJacobian H1 = boost::none, ChartJacobian H2 = boost::none) { if (H1) (*H1) = -Jacobian::Identity(); if (H2) (*H2) = Jacobian::Identity(); @@ -320,7 +320,7 @@ struct traits > : return result; } - static Fixed Retract(Fixed origin, const TangentVector& v, + static Fixed Retract(const Fixed& origin, const TangentVector& v, ChartJacobian H1 = boost::none, ChartJacobian H2 = boost::none) { if (H1) (*H1) = Jacobian::Identity(); if (H2) (*H2) = Jacobian::Identity(); diff --git a/gtsam/base/cholesky.cpp b/gtsam/base/cholesky.cpp index f6e2848f6..7bc5949cc 100644 --- a/gtsam/base/cholesky.cpp +++ b/gtsam/base/cholesky.cpp @@ -13,10 +13,10 @@ * @file cholesky.cpp * @brief Efficient incomplete Cholesky on rank-deficient matrices, todo: constrained Cholesky * @author Richard Roberts + * @author Frank Dellaert * @date Nov 5, 2010 */ -#include #include #include @@ -27,64 +27,53 @@ using namespace std; namespace gtsam { - static const double negativePivotThreshold = -1e-1; - static const double zeroPivotThreshold = 1e-6; - static const double underconstrainedPrior = 1e-5; - static const int underconstrainedExponentDifference = 12; +static const double negativePivotThreshold = -1e-1; +static const double zeroPivotThreshold = 1e-6; +static const double underconstrainedPrior = 1e-5; +static const int underconstrainedExponentDifference = 12; /* ************************************************************************* */ static inline int choleskyStep(Matrix& ATA, size_t k, size_t order) { - - const bool debug = ISDEBUG("choleskyCareful"); - // Get pivot value - double alpha = ATA(k,k); + double alpha = ATA(k, k); // Correct negative pivots from round-off error - if(alpha < negativePivotThreshold) { - if(debug) { - cout << "pivot = " << alpha << endl; - print(ATA, "Partially-factorized matrix: "); - } + if (alpha < negativePivotThreshold) { return -1; - } else if(alpha < 0.0) + } else if (alpha < 0.0) alpha = 0.0; - + const double beta = sqrt(alpha); - if(beta > zeroPivotThreshold) { + if (beta > zeroPivotThreshold) { const double betainv = 1.0 / beta; // Update k,k - ATA(k,k) = beta; + ATA(k, k) = beta; - if(k < (order-1)) { + if (k < (order - 1)) { // Update A(k,k+1:end) <- A(k,k+1:end) / beta typedef Matrix::RowXpr::SegmentReturnType BlockRow; - BlockRow V = ATA.row(k).segment(k+1, order-(k+1)); + BlockRow V = ATA.row(k).segment(k + 1, order - (k + 1)); V *= betainv; // Update A(k+1:end, k+1:end) <- A(k+1:end, k+1:end) - v*v' / alpha - ATA.block(k+1, k+1, order-(k+1), order-(k+1)) -= V.transpose() * V; -// ATA.bottomRightCorner(order-(k+1), order-(k+1)).selfadjointView() -// .rankUpdate(V.adjoint(), -1); + ATA.block(k + 1, k + 1, order - (k + 1), order - (k + 1)) -= V.transpose() * V; + // ATA.bottomRightCorner(order-(k+1), order-(k+1)).selfadjointView() + // .rankUpdate(V.adjoint(), -1); } return 1; } else { // For zero pivots, add the underconstrained variable prior - ATA(k,k) = underconstrainedPrior; - for(size_t j=k+1; j choleskyCareful(Matrix& ATA, int order) { - - const bool debug = ISDEBUG("choleskyCareful"); - +pair choleskyCareful(Matrix& ATA, int order) { // Check that the matrix is square (we do not check for symmetry) assert(ATA.rows() == ATA.cols()); @@ -92,7 +81,7 @@ pair choleskyCareful(Matrix& ATA, int order) { const size_t n = ATA.rows(); // Negative order means factor the entire matrix - if(order < 0) + if (order < 0) order = int(n); assert(size_t(order) <= n); @@ -102,13 +91,11 @@ pair choleskyCareful(Matrix& ATA, int order) { bool success = true; // Factor row-by-row - for(size_t k = 0; k < size_t(order); ++k) { + for (size_t k = 0; k < size_t(order); ++k) { int stepResult = choleskyStep(ATA, k, size_t(order)); - if(stepResult == 1) { - if(debug) cout << "choleskyCareful: Factored through " << k << endl; - if(debug) print(ATA, "ATA: "); - maxrank = k+1; - } else if(stepResult == -1) { + if (stepResult == 1) { + maxrank = k + 1; + } else if (stepResult == -1) { success = false; break; } /* else if(stepResult == 0) Found zero pivot */ @@ -118,72 +105,54 @@ pair choleskyCareful(Matrix& ATA, int order) { } /* ************************************************************************* */ -bool choleskyPartial(Matrix& ABC, size_t nFrontal) { - +bool choleskyPartial(Matrix& ABC, size_t nFrontal, size_t topleft) { gttic(choleskyPartial); + if (nFrontal == 0) + return true; - const bool debug = ISDEBUG("choleskyPartial"); + assert(ABC.cols() == ABC.rows()); + const Eigen::DenseIndex n = ABC.rows() - topleft; + assert(n >= 0 && nFrontal <= size_t(n)); - assert(ABC.rows() == ABC.cols()); - assert(ABC.rows() >= 0 && nFrontal <= size_t(ABC.rows())); + // Create views on blocks + auto A = ABC.block(topleft, topleft, nFrontal, nFrontal); + auto B = ABC.block(topleft, topleft + nFrontal, nFrontal, n - nFrontal); + auto C = ABC.block(topleft + nFrontal, topleft + nFrontal, n - nFrontal, n - nFrontal); - const size_t n = ABC.rows(); - - // Compute Cholesky factorization of A, overwrites A. - gttic(lld); - Eigen::ComputationInfo lltResult; - if(nFrontal > 0) - { - Eigen::LLT llt = ABC.block(0, 0, nFrontal, nFrontal).selfadjointView().llt(); - ABC.block(0, 0, nFrontal, nFrontal).triangularView() = llt.matrixU(); - lltResult = llt.info(); - } - else - { - lltResult = Eigen::Success; - } - gttoc(lld); - - if(debug) cout << "R:\n" << Eigen::MatrixXd(ABC.topLeftCorner(nFrontal,nFrontal).triangularView()) << endl; + // Compute Cholesky factorization A = R'*R, overwrites A. + gttic(LLT); + Eigen::LLT llt(A); + Eigen::ComputationInfo lltResult = llt.info(); + if (lltResult != Eigen::Success) + return false; + auto R = A.triangularView(); + R = llt.matrixU(); + gttoc(LLT); // Compute S = inv(R') * B gttic(compute_S); - if(n - nFrontal > 0) { - ABC.topLeftCorner(nFrontal,nFrontal).triangularView().transpose().solveInPlace( - ABC.topRightCorner(nFrontal, n-nFrontal)); - } - if(debug) cout << "S:\n" << ABC.topRightCorner(nFrontal, n-nFrontal) << endl; + if (nFrontal < n) + R.transpose().solveInPlace(B); gttoc(compute_S); // Compute L = C - S' * S gttic(compute_L); - if(debug) cout << "C:\n" << Eigen::MatrixXd(ABC.bottomRightCorner(n-nFrontal,n-nFrontal).selfadjointView()) << endl; - if(n - nFrontal > 0) - ABC.bottomRightCorner(n-nFrontal,n-nFrontal).selfadjointView().rankUpdate( - ABC.topRightCorner(nFrontal, n-nFrontal).transpose(), -1.0); - if(debug) cout << "L:\n" << Eigen::MatrixXd(ABC.bottomRightCorner(n-nFrontal,n-nFrontal).selfadjointView()) << endl; + if (nFrontal < n) + C.selfadjointView().rankUpdate(B.transpose(), -1.0); gttoc(compute_L); // Check last diagonal element - Eigen does not check it - bool ok; - if(lltResult == Eigen::Success) { - if(nFrontal >= 2) { - int exp2, exp1; - (void)frexp(ABC(nFrontal-2, nFrontal-2), &exp2); - (void)frexp(ABC(nFrontal-1, nFrontal-1), &exp1); - ok = (exp2 - exp1 < underconstrainedExponentDifference); - } else if(nFrontal == 1) { - int exp1; - (void)frexp(ABC(0,0), &exp1); - ok = (exp1 > -underconstrainedExponentDifference); - } else { - ok = true; - } + if (nFrontal >= 2) { + int exp2, exp1; + (void)frexp(R(topleft + nFrontal - 2, topleft + nFrontal - 2), &exp2); + (void)frexp(R(topleft + nFrontal - 1, topleft + nFrontal - 1), &exp1); + return (exp2 - exp1 < underconstrainedExponentDifference); + } else if (nFrontal == 1) { + int exp1; + (void)frexp(R(0, 0), &exp1); + return (exp1 > -underconstrainedExponentDifference); } else { - ok = false; + return true; } - - return ok; -} - } +} // namespace gtsam diff --git a/gtsam/base/cholesky.h b/gtsam/base/cholesky.h index 3377ab251..5e3276ff0 100644 --- a/gtsam/base/cholesky.h +++ b/gtsam/base/cholesky.h @@ -55,10 +55,12 @@ GTSAM_EXPORT std::pair choleskyCareful(Matrix& ATA, int order = -1) * nFrontal determines the split between A, B, and C, with A being of size * nFrontal x nFrontal. * + * if non-zero, factorization proceeds in bottom-right corner starting at topleft + * * @return \c true if the decomposition is successful, \c false if \c A was * not positive-definite. */ -GTSAM_EXPORT bool choleskyPartial(Matrix& ABC, size_t nFrontal); +GTSAM_EXPORT bool choleskyPartial(Matrix& ABC, size_t nFrontal, size_t topleft=0); } diff --git a/gtsam/base/numericalDerivative.h b/gtsam/base/numericalDerivative.h index 6cd28b951..dcb0425b7 100644 --- a/gtsam/base/numericalDerivative.h +++ b/gtsam/base/numericalDerivative.h @@ -320,8 +320,8 @@ typename internal::FixedSizeMatrix::type numericalDerivative41( /** * Compute numerical derivative in argument 2 of 4-argument function * @param h ternary function yielding m-vector - * @param x1 n-dimensional first argument value - * @param x2 second argument value + * @param x1 first argument value + * @param x2 n-dimensional second argument value * @param x3 third argument value * @param x4 fourth argument value * @param delta increment for numerical derivative @@ -333,11 +333,53 @@ typename internal::FixedSizeMatrix::type numericalDerivative42( const X2& x2, const X3& x3, const X4& x4, double delta = 1e-5) { BOOST_STATIC_ASSERT_MSG( (boost::is_base_of::structure_category>::value), "Template argument Y must be a manifold type."); - BOOST_STATIC_ASSERT_MSG( (boost::is_base_of::structure_category>::value), - "Template argument X1 must be a manifold type."); + BOOST_STATIC_ASSERT_MSG( (boost::is_base_of::structure_category>::value), + "Template argument X2 must be a manifold type."); return numericalDerivative11(boost::bind(h, x1, _1, x3, x4), x2, delta); } +/** + * Compute numerical derivative in argument 3 of 4-argument function + * @param h ternary function yielding m-vector + * @param x1 first argument value + * @param x2 second argument value + * @param x3 n-dimensional third argument value + * @param x4 fourth argument value + * @param delta increment for numerical derivative + * @return m*n Jacobian computed via central differencing + */ +template +typename internal::FixedSizeMatrix::type numericalDerivative43( + boost::function h, const X1& x1, + const X2& x2, const X3& x3, const X4& x4, double delta = 1e-5) { + BOOST_STATIC_ASSERT_MSG( (boost::is_base_of::structure_category>::value), + "Template argument Y must be a manifold type."); + BOOST_STATIC_ASSERT_MSG( (boost::is_base_of::structure_category>::value), + "Template argument X3 must be a manifold type."); + return numericalDerivative11(boost::bind(h, x1, x2, _1, x4), x3, delta); +} + +/** + * Compute numerical derivative in argument 4 of 4-argument function + * @param h ternary function yielding m-vector + * @param x1 first argument value + * @param x2 second argument value + * @param x3 third argument value + * @param x4 n-dimensional fourth argument value + * @param delta increment for numerical derivative + * @return m*n Jacobian computed via central differencing + */ +template +typename internal::FixedSizeMatrix::type numericalDerivative44( + boost::function h, const X1& x1, + const X2& x2, const X3& x3, const X4& x4, double delta = 1e-5) { + BOOST_STATIC_ASSERT_MSG( (boost::is_base_of::structure_category>::value), + "Template argument Y must be a manifold type."); + BOOST_STATIC_ASSERT_MSG( (boost::is_base_of::structure_category>::value), + "Template argument X4 must be a manifold type."); + return numericalDerivative11(boost::bind(h, x1, x2, x3, _1), x4, delta); +} + /** * Compute numerical Hessian matrix. Requires a single-argument Lie->scalar * function. This is implemented simply as the derivative of the gradient. diff --git a/gtsam/base/tests/testCholesky.cpp b/gtsam/base/tests/testCholesky.cpp index 5120e9ac6..9b80658cf 100644 --- a/gtsam/base/tests/testCholesky.cpp +++ b/gtsam/base/tests/testCholesky.cpp @@ -23,10 +23,23 @@ using namespace gtsam; using namespace std; /* ************************************************************************* */ -TEST(cholesky, choleskyPartial) { +TEST(cholesky, choleskyPartial0) { // choleskyPartial should only use the upper triangle, so this represents a // symmetric matrix. + Matrix ABC(3,3); + ABC << 4.0375, 3.4584, 3.5735, + 0., 4.7267, 3.8423, + 0., 0., 5.1600; + + // Test passing 0 frontals to partialCholesky + Matrix RSL(ABC); + choleskyPartial(RSL, 0); + EXPECT(assert_equal(ABC, RSL, 1e-9)); +} + +/* ************************************************************************* */ +TEST(cholesky, choleskyPartial) { Matrix ABC = (Matrix(7,7) << 4.0375, 3.4584, 3.5735, 2.4815, 2.1471, 2.7400, 2.2063, 0., 4.7267, 3.8423, 2.3624, 2.8091, 2.9579, 2.5914, diff --git a/gtsam/base/tests/testSymmetricBlockMatrix.cpp b/gtsam/base/tests/testSymmetricBlockMatrix.cpp index da193aec5..c24e12c25 100644 --- a/gtsam/base/tests/testSymmetricBlockMatrix.cpp +++ b/gtsam/base/tests/testSymmetricBlockMatrix.cpp @@ -40,58 +40,41 @@ TEST(SymmetricBlockMatrix, ReadBlocks) Matrix expected1 = (Matrix(2, 2) << 22, 23, 23, 29).finished(); - Matrix actual1 = testBlockMatrix(1, 1); - // Test only writing the upper triangle for efficiency - Matrix actual1t = Z_2x2; - actual1t.triangularView() = testBlockMatrix(1, 1).triangularView(); + Matrix actual1 = testBlockMatrix.diagonalBlock(1); EXPECT(assert_equal(expected1, actual1)); - EXPECT(assert_equal(Matrix(expected1.triangularView()), actual1t)); // Above the diagonal Matrix expected2 = (Matrix(3, 2) << 4, 5, 10, 11, 16, 17).finished(); - Matrix actual2 = testBlockMatrix(0, 1); + Matrix actual2 = testBlockMatrix.aboveDiagonalBlock(0, 1); EXPECT(assert_equal(expected2, actual2)); - - // Below the diagonal - Matrix expected3 = (Matrix(2, 3) << - 4, 10, 16, - 5, 11, 17).finished(); - Matrix actual3 = testBlockMatrix(1, 0); - EXPECT(assert_equal(expected3, actual3)); } /* ************************************************************************* */ TEST(SymmetricBlockMatrix, WriteBlocks) { // On the diagonal - Matrix expected1 = testBlockMatrix(1, 1); + Matrix expected1 = testBlockMatrix.diagonalBlock(1); SymmetricBlockMatrix bm1 = SymmetricBlockMatrix::LikeActiveViewOf(testBlockMatrix); - bm1(1, 1) = expected1.selfadjointView(); // Verified with debugger that this only writes the upper triangle - Matrix actual1 = bm1(1, 1); + + bm1.setDiagonalBlock(1, expected1); + Matrix actual1 = bm1.diagonalBlock(1); EXPECT(assert_equal(expected1, actual1)); - // On the diagonal - Matrix expected1p = testBlockMatrix(1, 1); - SymmetricBlockMatrix bm1p = SymmetricBlockMatrix::LikeActiveViewOf(testBlockMatrix); - bm1p(1, 1) = expected1p; // Verified with debugger that this only writes the upper triangle - Matrix actual1p = bm1p(1, 1); - EXPECT(assert_equal(expected1p, actual1p)); - // Above the diagonal - Matrix expected2 = testBlockMatrix(0, 1); + Matrix expected2 = testBlockMatrix.aboveDiagonalBlock(0, 1); SymmetricBlockMatrix bm2 = SymmetricBlockMatrix::LikeActiveViewOf(testBlockMatrix); - bm2(0, 1) = expected2; - Matrix actual2 = bm2(0, 1); + bm2.setOffDiagonalBlock(0, 1, expected2); + Matrix actual2 = bm2.aboveDiagonalBlock(0, 1); EXPECT(assert_equal(expected2, actual2)); // Below the diagonal - Matrix expected3 = testBlockMatrix(1, 0); + Matrix expected3 = testBlockMatrix.aboveDiagonalBlock(0, 1).transpose(); SymmetricBlockMatrix bm3 = SymmetricBlockMatrix::LikeActiveViewOf(testBlockMatrix); - bm3(1, 0) = expected3; - Matrix actual3 = bm3(1, 0); + bm3.setOffDiagonalBlock(1, 0, expected3); + Matrix actual3 = bm3.aboveDiagonalBlock(0, 1).transpose(); EXPECT(assert_equal(expected3, actual3)); } @@ -103,30 +86,16 @@ TEST(SymmetricBlockMatrix, Ranges) 22, 23, 24, 23, 29, 30, 24, 30, 36).finished(); - Matrix actual1 = testBlockMatrix.range(1, 3, 1, 3).selfadjointView(); - Matrix actual1a = testBlockMatrix.range(1, 3, 1, 3); + Matrix actual1 = testBlockMatrix.selfadjointView(1, 3); EXPECT(assert_equal(expected1, actual1)); - EXPECT(assert_equal(expected1, actual1a)); // Above the diagonal - Matrix expected2 = (Matrix(3, 1) << - 24, - 30, - 36).finished(); - Matrix actual2 = testBlockMatrix.range(1, 3, 2, 3).knownOffDiagonal(); - Matrix actual2a = testBlockMatrix.range(1, 3, 2, 3); + Matrix expected2 = (Matrix(3, 3) << + 4, 5, 6, + 10, 11, 12, + 16, 17, 18).finished(); + Matrix actual2 = testBlockMatrix.aboveDiagonalRange(0, 1, 1, 3); EXPECT(assert_equal(expected2, actual2)); - EXPECT(assert_equal(expected2, actual2a)); - - // Below the diagonal - Matrix expected3 = (Matrix(3, 3) << - 4, 10, 16, - 5, 11, 17, - 6, 12, 18).finished(); - Matrix actual3 = testBlockMatrix.range(1, 3, 0, 1).knownOffDiagonal(); - Matrix actual3a = testBlockMatrix.range(1, 3, 0, 1); - EXPECT(assert_equal(expected3, actual3)); - EXPECT(assert_equal(expected3, actual3a)); } /* ************************************************************************* */ @@ -152,34 +121,51 @@ TEST(SymmetricBlockMatrix, expressions) Matrix b = (Matrix(1, 2) << 5, 6).finished(); SymmetricBlockMatrix bm1(list_of(2)(3)(1)); - bm1.full().triangularView().setZero(); - bm1(1, 1).selfadjointView().rankUpdate(a.transpose()); - EXPECT(assert_equal(Matrix(expected1.full().selfadjointView()), bm1.full().selfadjointView())); + bm1.setZero(); + bm1.diagonalBlock(1).rankUpdate(a.transpose()); + EXPECT(assert_equal(Matrix(expected1.selfadjointView()), bm1.selfadjointView())); SymmetricBlockMatrix bm2(list_of(2)(3)(1)); - bm2.full().triangularView().setZero(); - bm2(0, 1).knownOffDiagonal() += b.transpose() * a; - EXPECT(assert_equal(Matrix(expected2.full().selfadjointView()), bm2.full().selfadjointView())); + bm2.setZero(); + bm2.updateOffDiagonalBlock(0, 1, b.transpose() * a); + EXPECT(assert_equal(Matrix(expected2.selfadjointView()), bm2.selfadjointView())); SymmetricBlockMatrix bm3(list_of(2)(3)(1)); - bm3.full().triangularView().setZero(); - bm3(1, 0).knownOffDiagonal() += a.transpose() * b; - EXPECT(assert_equal(Matrix(expected2.full().selfadjointView()), bm3.full().selfadjointView())); + bm3.setZero(); + bm3.updateOffDiagonalBlock(1, 0, a.transpose() * b); + EXPECT(assert_equal(Matrix(expected2.selfadjointView()), bm3.selfadjointView())); SymmetricBlockMatrix bm4(list_of(2)(3)(1)); - bm4.full().triangularView().setZero(); - bm4(1, 1) += expected1(1, 1); - EXPECT(assert_equal(Matrix(expected1.full().selfadjointView()), bm4.full().selfadjointView())); + bm4.setZero(); + bm4.updateDiagonalBlock(1, expected1.diagonalBlock(1)); + EXPECT(assert_equal(Matrix(expected1.selfadjointView()), bm4.selfadjointView())); SymmetricBlockMatrix bm5(list_of(2)(3)(1)); - bm5.full().triangularView().setZero(); - bm5(0, 1) += expected2(0, 1); - EXPECT(assert_equal(Matrix(expected2.full().selfadjointView()), bm5.full().selfadjointView())); + bm5.setZero(); + bm5.updateOffDiagonalBlock(0, 1, expected2.aboveDiagonalBlock(0, 1)); + EXPECT(assert_equal(Matrix(expected2.selfadjointView()), bm5.selfadjointView())); SymmetricBlockMatrix bm6(list_of(2)(3)(1)); - bm6.full().triangularView().setZero(); - bm6(1, 0) += expected2(1, 0); - EXPECT(assert_equal(Matrix(expected2.full().selfadjointView()), bm6.full().selfadjointView())); + bm6.setZero(); + bm6.updateOffDiagonalBlock(1, 0, expected2.aboveDiagonalBlock(0, 1).transpose()); + EXPECT(assert_equal(Matrix(expected2.selfadjointView()), bm6.selfadjointView())); +} + +/* ************************************************************************* */ +TEST(SymmetricBlockMatrix, inverseInPlace) { + // generate an invertible matrix + const Vector3 a(1.0, 0.2, 2.0), b(0.3, 0.8, -1.0), c(0.1, 0.2, 0.7); + Matrix inputMatrix(3, 3); + inputMatrix.setZero(); + inputMatrix += a * a.transpose(); + inputMatrix += b * b.transpose(); + inputMatrix += c * c.transpose(); + const Matrix expectedInverse = inputMatrix.inverse(); + + SymmetricBlockMatrix symmMatrix(list_of(2)(1), inputMatrix); + // invert in place + symmMatrix.invertInPlace(); + EXPECT(assert_equal(expectedInverse, symmMatrix.selfadjointView())); } /* ************************************************************************* */ diff --git a/gtsam/base/treeTraversal-inst.h b/gtsam/base/treeTraversal-inst.h index 0d670ba2e..7a88f72eb 100644 --- a/gtsam/base/treeTraversal-inst.h +++ b/gtsam/base/treeTraversal-inst.h @@ -29,7 +29,6 @@ #include #include #include -#include namespace gtsam { @@ -158,7 +157,6 @@ void DepthFirstForestParallel(FOREST& forest, DATA& rootData, #ifdef GTSAM_USE_TBB // Typedefs typedef typename FOREST::Node Node; - typedef boost::shared_ptr sharedNode; tbb::task::spawn_root_and_wait( internal::CreateRootTask(forest.roots(), rootData, visitorPre, diff --git a/gtsam/base/treeTraversal/parallelTraversalTasks.h b/gtsam/base/treeTraversal/parallelTraversalTasks.h index ccdd269c3..9b2dae3d0 100644 --- a/gtsam/base/treeTraversal/parallelTraversalTasks.h +++ b/gtsam/base/treeTraversal/parallelTraversalTasks.h @@ -44,8 +44,9 @@ namespace gtsam { boost::shared_ptr myData; VISITOR_POST& visitorPost; - PostOrderTask(const boost::shared_ptr& treeNode, const boost::shared_ptr& myData, VISITOR_POST& visitorPost) : - treeNode(treeNode), myData(myData), visitorPost(visitorPost) {} + PostOrderTask(const boost::shared_ptr& treeNode, + const boost::shared_ptr& myData, VISITOR_POST& visitorPost) + : treeNode(treeNode), myData(myData), visitorPost(visitorPost) {} tbb::task* execute() { @@ -71,10 +72,15 @@ namespace gtsam { bool isPostOrderPhase; PreOrderTask(const boost::shared_ptr& treeNode, const boost::shared_ptr& myData, - VISITOR_PRE& visitorPre, VISITOR_POST& visitorPost, int problemSizeThreshold, - bool makeNewTasks = true) : - treeNode(treeNode), myData(myData), visitorPre(visitorPre), visitorPost(visitorPost), - problemSizeThreshold(problemSizeThreshold), makeNewTasks(makeNewTasks), isPostOrderPhase(false) {} + VISITOR_PRE& visitorPre, VISITOR_POST& visitorPost, int problemSizeThreshold, + bool makeNewTasks = true) + : treeNode(treeNode), + myData(myData), + visitorPre(visitorPre), + visitorPost(visitorPost), + problemSizeThreshold(problemSizeThreshold), + makeNewTasks(makeNewTasks), + isPostOrderPhase(false) {} tbb::task* execute() { @@ -93,8 +99,6 @@ namespace gtsam { // Allocate post-order task as a continuation isPostOrderPhase = true; recycle_as_continuation(); - //PostOrderTask& postOrderTask = - // *new(allocate_continuation()) PostOrderTask(treeNode, myData, visitorPost); bool overThreshold = (treeNode->problemSize() >= problemSizeThreshold); @@ -105,21 +109,18 @@ namespace gtsam { // Process child in a subtask. Important: Run visitorPre before calling // allocate_child so that if visitorPre throws an exception, we will not have // allocated an extra child, this causes a TBB error. - boost::shared_ptr childData = boost::allocate_shared(tbb::scalable_allocator(), visitorPre(child, *myData)); - //childTasks.push_back(*new(postOrderTask.allocate_child()) - // PreOrderTask(child, childData, visitorPre, visitorPost, - // problemSizeThreshold, overThreshold)); - tbb::task* childTask = new(allocate_child()) - PreOrderTask(child, childData, visitorPre, visitorPost, - problemSizeThreshold, overThreshold); - if(firstChild) + boost::shared_ptr childData = boost::allocate_shared( + tbb::scalable_allocator(), visitorPre(child, *myData)); + tbb::task* childTask = + new (allocate_child()) PreOrderTask(child, childData, visitorPre, visitorPost, + problemSizeThreshold, overThreshold); + if (firstChild) childTasks.push_back(*childTask); else firstChild = childTask; } // If we have child tasks, start subtasks and wait for them to complete - //postOrderTask.set_ref_count((int) treeNode->children.size()); set_ref_count((int)treeNode->children.size()); spawn(childTasks); return firstChild; diff --git a/gtsam/config.h.in b/gtsam/config.h.in index 42d5e7517..8433f19b0 100644 --- a/gtsam/config.h.in +++ b/gtsam/config.h.in @@ -64,7 +64,7 @@ #cmakedefine GTSAM_ALLOW_DEPRECATED_SINCE_V4 // Publish flag about Eigen typedef -#cmakedefine GTSAM_USE_VECTOR3_POINTS +#cmakedefine GTSAM_TYPEDEF_POINTS_TO_VECTORS // Support Metis-based nested dissection #cmakedefine GTSAM_SUPPORT_NESTED_DISSECTION diff --git a/gtsam/discrete/DiscreteJunctionTree.cpp b/gtsam/discrete/DiscreteJunctionTree.cpp index 8e6d0f4d8..0e6e2b73e 100644 --- a/gtsam/discrete/DiscreteJunctionTree.cpp +++ b/gtsam/discrete/DiscreteJunctionTree.cpp @@ -23,7 +23,7 @@ namespace gtsam { // Instantiate base classes - template class ClusterTree; + template class EliminatableClusterTree; template class JunctionTree; /* ************************************************************************* */ diff --git a/gtsam/discrete/DiscreteJunctionTree.h b/gtsam/discrete/DiscreteJunctionTree.h index 23924acfd..8c00065d9 100644 --- a/gtsam/discrete/DiscreteJunctionTree.h +++ b/gtsam/discrete/DiscreteJunctionTree.h @@ -26,8 +26,8 @@ namespace gtsam { class DiscreteEliminationTree; /** - * A ClusterTree, i.e., a set of variable clusters with factors, arranged in a tree, with - * the additional property that it represents the clique tree associated with a Bayes net. + * An EliminatableClusterTree, i.e., a set of variable clusters with factors, arranged in a tree, + * with the additional property that it represents the clique tree associated with a Bayes net. * * In GTSAM a junction tree is an intermediate data structure in multifrontal * variable elimination. Each node is a cluster of factors, along with a @@ -39,7 +39,7 @@ namespace gtsam { * BayesTree stores conditionals, that are the product of eliminating the factors in the * corresponding JunctionTree cliques. * - * The tree structure and elimination method are exactly analagous to the EliminationTree, + * The tree structure and elimination method are exactly analogous to the EliminationTree, * except that in the JunctionTree, at each node multiple variables are eliminated at a time. * * \addtogroup Multifrontal @@ -53,7 +53,7 @@ namespace gtsam { typedef boost::shared_ptr shared_ptr; ///< Shared pointer to this class /** - * Build the elimination tree of a factor graph using pre-computed column structure. + * Build the elimination tree of a factor graph using precomputed column structure. * @param factorGraph The factor graph for which to build the elimination tree * @param structure The set of factors involving each variable. If this is not * precomputed, you can call the Create(const FactorGraph&) diff --git a/gtsam/geometry/Cal3Bundler.cpp b/gtsam/geometry/Cal3Bundler.cpp index 368ae6c98..4ad1dffa2 100644 --- a/gtsam/geometry/Cal3Bundler.cpp +++ b/gtsam/geometry/Cal3Bundler.cpp @@ -106,7 +106,7 @@ Point2 Cal3Bundler::calibrate(const Point2& pi, const double tol) const { const int maxIterations = 10; int iteration; for (iteration = 0; iteration < maxIterations; ++iteration) { - if (uncalibrate(pn).distance(pi) <= tol) + if (distance2(uncalibrate(pn), pi) <= tol) break; const double x = pn.x(), y = pn.y(), xx = x * x, yy = y * y; const double rr = xx + yy; diff --git a/gtsam/geometry/Cal3DS2_Base.cpp b/gtsam/geometry/Cal3DS2_Base.cpp index 12060c12d..2071b8792 100644 --- a/gtsam/geometry/Cal3DS2_Base.cpp +++ b/gtsam/geometry/Cal3DS2_Base.cpp @@ -144,7 +144,7 @@ Point2 Cal3DS2_Base::calibrate(const Point2& pi, const double tol) const { const int maxIterations = 10; int iteration; for (iteration = 0; iteration < maxIterations; ++iteration) { - if (uncalibrate(pn).distance(pi) <= tol) break; + if (distance2(uncalibrate(pn), pi) <= tol) break; const double x = pn.x(), y = pn.y(), xy = x * y, xx = x * x, yy = y * y; const double rr = xx + yy; const double g = (1 + k1_ * rr + k2_ * rr * rr); diff --git a/gtsam/geometry/Cal3_S2.cpp b/gtsam/geometry/Cal3_S2.cpp index c131d46f7..54deedfdc 100644 --- a/gtsam/geometry/Cal3_S2.cpp +++ b/gtsam/geometry/Cal3_S2.cpp @@ -51,6 +51,13 @@ Cal3_S2::Cal3_S2(const std::string &path) : infile.close(); } +/* ************************************************************************* */ +ostream& operator<<(ostream& os, const Cal3_S2& cal) { + os << "{fx: " << cal.fx() << ", fy: " << cal.fy() << ", s:" << cal.skew() << ", px:" << cal.px() + << ", py:" << cal.py() << "}"; + return os; +} + /* ************************************************************************* */ void Cal3_S2::print(const std::string& s) const { gtsam::print((Matrix)matrix(), s); diff --git a/gtsam/geometry/Cal3_S2.h b/gtsam/geometry/Cal3_S2.h index ac4b68ccd..6ad7aeb86 100644 --- a/gtsam/geometry/Cal3_S2.h +++ b/gtsam/geometry/Cal3_S2.h @@ -75,6 +75,9 @@ public: /// @name Testable /// @{ + /// Output stream operator + GTSAM_EXPORT friend std::ostream &operator<<(std::ostream &os, const Cal3_S2& cal); + /// print with optional string void print(const std::string& s = "Cal3_S2") const; diff --git a/gtsam/geometry/CalibratedCamera.cpp b/gtsam/geometry/CalibratedCamera.cpp index 2d27b4dc7..026becebe 100644 --- a/gtsam/geometry/CalibratedCamera.cpp +++ b/gtsam/geometry/CalibratedCamera.cpp @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- - * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) diff --git a/gtsam/geometry/CalibratedCamera.h b/gtsam/geometry/CalibratedCamera.h index b1e5917b2..f1fa509c1 100644 --- a/gtsam/geometry/CalibratedCamera.h +++ b/gtsam/geometry/CalibratedCamera.h @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- - * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) @@ -19,6 +19,7 @@ #pragma once #include +#include #include #include #include @@ -28,8 +29,6 @@ namespace gtsam { -class Point2; - class GTSAM_EXPORT CheiralityException: public ThreadsafeException< CheiralityException> { public: @@ -262,6 +261,14 @@ public: /// @name Named Constructors /// @{ + // Create CalibratedCamera, with derivatives + static CalibratedCamera Create(const Pose3& pose, + OptionalJacobian H1 = boost::none) { + if (H1) + *H1 << I_6x6; + return CalibratedCamera(pose); + } + /** * Create a level camera at the given 2D pose and height * @param pose2 specifies the location and viewing direction diff --git a/gtsam/geometry/CameraSet.h b/gtsam/geometry/CameraSet.h index 0df85d3d2..b322a40ab 100644 --- a/gtsam/geometry/CameraSet.h +++ b/gtsam/geometry/CameraSet.h @@ -56,8 +56,7 @@ protected: // Project and fill error vector Vector b(ZDim * m); for (size_t i = 0, row = 0; i < m; i++, row += ZDim) { - Z e = predicted[i] - measured[i]; - b.segment(row) = e.vector(); + b.segment(row) = traits::Local(measured[i], predicted[i]); } return b; } @@ -107,7 +106,8 @@ public: // Allocate result size_t m = this->size(); - std::vector z(m); + std::vector z; + z.reserve(m); // Allocate derivatives if (E) E->resize(ZDim * m, N); @@ -117,7 +117,7 @@ public: for (size_t i = 0; i < m; i++) { MatrixZD Fi; Eigen::Matrix Ei; - z[i] = this->at(i).project2(point, Fs ? &Fi : 0, E ? &Ei : 0); + z.emplace_back(this->at(i).project2(point, Fs ? &Fi : 0, E ? &Ei : 0)); if (Fs) (*Fs)[i] = Fi; if (E) E->block(ZDim * i, 0) = Ei; } @@ -157,28 +157,29 @@ public: for (size_t i = 0; i < m; i++) { // for each camera const MatrixZD& Fi = Fs[i]; + const auto FiT = Fi.transpose(); const Eigen::Matrix Ei_P = // E.block(ZDim * i, 0, ZDim, N) * P; // D = (Dx2) * ZDim - augmentedHessian(i, m) = Fi.transpose() * b.segment(ZDim * i) // F' * b - - Fi.transpose() * (Ei_P * (E.transpose() * b)); // D = (DxZDim) * (ZDimx3) * (N*ZDimm) * (ZDimm x 1) + augmentedHessian.setOffDiagonalBlock(i, m, FiT * b.segment(ZDim * i) // F' * b + - FiT * (Ei_P * (E.transpose() * b))); // D = (DxZDim) * (ZDimx3) * (N*ZDimm) * (ZDimm x 1) // (DxD) = (DxZDim) * ( (ZDimxD) - (ZDimx3) * (3xZDim) * (ZDimxD) ) - augmentedHessian(i, i) = Fi.transpose() - * (Fi - Ei_P * E.block(ZDim * i, 0, ZDim, N).transpose() * Fi); + augmentedHessian.setDiagonalBlock(i, FiT + * (Fi - Ei_P * E.block(ZDim * i, 0, ZDim, N).transpose() * Fi)); // upper triangular part of the hessian for (size_t j = i + 1; j < m; j++) { // for each camera const MatrixZD& Fj = Fs[j]; // (DxD) = (Dx2) * ( (2x2) * (2xD) ) - augmentedHessian(i, j) = -Fi.transpose() - * (Ei_P * E.block(ZDim * j, 0, ZDim, N).transpose() * Fj); + augmentedHessian.setOffDiagonalBlock(i, j, -FiT + * (Ei_P * E.block(ZDim * j, 0, ZDim, N).transpose() * Fj)); } } // end of for over cameras - augmentedHessian(m, m)(0, 0) += b.squaredNorm(); + augmentedHessian.diagonalBlock(m)(0, 0) += b.squaredNorm(); return augmentedHessian; } @@ -252,8 +253,6 @@ public: // G = F' * F - F' * E * P * E' * F // g = F' * (b - E * P * E' * b) - Eigen::Matrix matrixBlock; - // a single point is observed in m cameras size_t m = Fs.size(); // cameras observing current point size_t M = (augmentedHessian.rows() - 1) / D; // all cameras in the group @@ -263,6 +262,7 @@ public: for (size_t i = 0; i < m; i++) { // for each camera in the current factor const MatrixZD& Fi = Fs[i]; + const auto FiT = Fi.transpose(); const Eigen::Matrix Ei_P = E.template block( ZDim * i, 0) * P; @@ -275,17 +275,15 @@ public: // information vector - store previous vector // vectorBlock = augmentedHessian(aug_i, aug_m).knownOffDiagonal(); // add contribution of current factor - augmentedHessian(aug_i, M) = augmentedHessian(aug_i, M).knownOffDiagonal() - + Fi.transpose() * b.segment(ZDim * i) // F' * b - - Fi.transpose() * (Ei_P * (E.transpose() * b)); // D = (DxZDim) * (ZDimx3) * (N*ZDimm) * (ZDimm x 1) + augmentedHessian.updateOffDiagonalBlock(aug_i, M, + FiT * b.segment(ZDim * i) // F' * b + - FiT * (Ei_P * (E.transpose() * b))); // D = (DxZDim) * (ZDimx3) * (N*ZDimm) * (ZDimm x 1) - // (DxD) = (DxZDim) * ( (ZDimxD) - (ZDimx3) * (3xZDim) * (ZDimxD) ) - // main block diagonal - store previous block - matrixBlock = augmentedHessian(aug_i, aug_i); + // (DxD) += (DxZDim) * ( (ZDimxD) - (ZDimx3) * (3xZDim) * (ZDimxD) ) // add contribution of current factor - augmentedHessian(aug_i, aug_i) = matrixBlock - + (Fi.transpose() - * (Fi - Ei_P * E.template block(ZDim * i, 0).transpose() * Fi)); + // TODO(gareth): Eigen doesn't let us pass the expression. Call eval() for now... + augmentedHessian.updateDiagonalBlock(aug_i, + ((FiT * (Fi - Ei_P * E.template block(ZDim * i, 0).transpose() * Fi))).eval()); // upper triangular part of the hessian for (size_t j = i + 1; j < m; j++) { // for each camera @@ -297,14 +295,12 @@ public: // off diagonal block - store previous block // matrixBlock = augmentedHessian(aug_i, aug_j).knownOffDiagonal(); // add contribution of current factor - augmentedHessian(aug_i, aug_j) = - augmentedHessian(aug_i, aug_j).knownOffDiagonal() - - Fi.transpose() - * (Ei_P * E.template block(ZDim * j, 0).transpose() * Fj); + augmentedHessian.updateOffDiagonalBlock(aug_i, aug_j, + -FiT * (Ei_P * E.template block(ZDim * j, 0).transpose() * Fj)); } } // end of for over cameras - augmentedHessian(M, M)(0, 0) += b.squaredNorm(); + augmentedHessian.diagonalBlock(M)(0, 0) += b.squaredNorm(); } private: diff --git a/gtsam/geometry/PinholePose.h b/gtsam/geometry/PinholePose.h index ac889c9d7..43ba78ea2 100644 --- a/gtsam/geometry/PinholePose.h +++ b/gtsam/geometry/PinholePose.h @@ -312,6 +312,16 @@ public: return Base::equals(camera, tol) && K_->equals(e->calibration(), tol); } + /// stream operator + friend std::ostream& operator<<(std::ostream &os, const PinholePose& camera) { + os << "{R: " << camera.pose().rotation().rpy().transpose(); + os << ", t: " << camera.pose().translation().transpose(); + if (!camera.K_) os << ", K: none"; + else os << ", K: " << *camera.K_; + os << "}"; + return os; + } + /// print void print(const std::string& s = "PinholePose") const { Base::print(s); diff --git a/gtsam/geometry/Point2.cpp b/gtsam/geometry/Point2.cpp index bc6132812..2152a7c39 100644 --- a/gtsam/geometry/Point2.cpp +++ b/gtsam/geometry/Point2.cpp @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- - * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) @@ -23,21 +23,11 @@ using namespace std; namespace gtsam { /* ************************************************************************* */ -void Point2::print(const string& s) const { - cout << s << *this << endl; -} - -/* ************************************************************************* */ -bool Point2::equals(const Point2& q, double tol) const { - return (fabs(x_ - q.x()) < tol && fabs(y_ - q.y()) < tol); -} - -/* ************************************************************************* */ -double Point2::norm(OptionalJacobian<1,2> H) const { - double r = sqrt(x_ * x_ + y_ * y_); +double norm2(const Point2& p, OptionalJacobian<1,2> H) { + double r = std::sqrt(p.x() * p.x() + p.y() * p.y()); if (H) { if (fabs(r) > 1e-10) - *H << x_ / r, y_ / r; + *H << p.x() / r, p.y() / r; else *H << 1, 1; // really infinity, why 1 ? } @@ -45,34 +35,66 @@ double Point2::norm(OptionalJacobian<1,2> H) const { } /* ************************************************************************* */ -double Point2::distance(const Point2& point, OptionalJacobian<1,2> H1, - OptionalJacobian<1,2> H2) const { - Point2 d = point - *this; +double distance2(const Point2& p, const Point2& q, OptionalJacobian<1, 2> H1, + OptionalJacobian<1, 2> H2) { + Point2 d = q - p; if (H1 || H2) { Matrix12 H; - double r = d.norm(H); + double r = norm2(d, H); if (H1) *H1 = -H; if (H2) *H2 = H; return r; - } else + } else { return d.norm(); + } } -/* - * Calculate f and h, respectively the parallel and perpendicular distance of - * the intersections of two circles along and from the line connecting the centers. - * Both are dimensionless fractions of the distance d between the circle centers. - * If the circles do not intersect or they are identical, returns boost::none. - * If one solution (touching circles, as determined by tol), h will be exactly zero. - * h is a good measure for how accurate the intersection will be, as when circles touch - * or nearly touch, the intersection is ill-defined with noisy radius measurements. - * @param R_d : R/d, ratio of radius of first circle to distance between centers - * @param r_d : r/d, ratio of radius of second circle to distance between centers - * @param tol: absolute tolerance below which we consider touching circles - */ +#ifndef GTSAM_TYPEDEF_POINTS_TO_VECTORS + +/* ************************************************************************* */ +void Point2::print(const string& s) const { + cout << s << *this << endl; +} + +/* ************************************************************************* */ +bool Point2::equals(const Point2& q, double tol) const { + return (fabs(x() - q.x()) < tol && fabs(y() - q.y()) < tol); +} + +/* ************************************************************************* */ +double Point2::norm(OptionalJacobian<1,2> H) const { + return gtsam::norm2(*this, H); +} + +/* ************************************************************************* */ +double Point2::distance(const Point2& point, OptionalJacobian<1,2> H1, + OptionalJacobian<1,2> H2) const { + return gtsam::distance2(*this, point, H1, H2); +} + +/* ************************************************************************* */ +ostream &operator<<(ostream &os, const Point2& p) { + os << '(' << p.x() << ", " << p.y() << ')'; + return os; +} + +#ifdef GTSAM_ALLOW_DEPRECATED_SINCE_V4 +boost::optional CircleCircleIntersection(double R_d, double r_d, double tol) { + return circleCircleIntersection(R_d, r_d, tol); +} +std::list CircleCircleIntersection(Point2 c1, Point2 c2, boost::optional fh) { + return circleCircleIntersection(c1, c2, fh); +} +std::list CircleCircleIntersection(Point2 c1, double r1, Point2 c2, double r2, double tol) { + return circleCircleIntersection(c1, r1, c2, r2, tol); +} +#endif + +#endif // GTSAM_TYPEDEF_POINTS_TO_VECTORS + /* ************************************************************************* */ // Math inspired by http://paulbourke.net/geometry/circlesphere/ -boost::optional Point2::CircleCircleIntersection(double R_d, double r_d, +boost::optional circleCircleIntersection(double R_d, double r_d, double tol) { double R2_d2 = R_d*R_d; // Yes, RD-D2 ! @@ -83,11 +105,11 @@ boost::optional Point2::CircleCircleIntersection(double R_d, double r_d, // Hence, there are only solutions if >=0 if (h2<-tol) return boost::none; // allow *slightly* negative else if (h2 Point2::CircleCircleIntersection(Point2 c1, Point2 c2, +list circleCircleIntersection(Point2 c1, Point2 c2, boost::optional fh) { list solutions; @@ -116,27 +138,21 @@ list Point2::CircleCircleIntersection(Point2 c1, Point2 c2, } /* ************************************************************************* */ -list Point2::CircleCircleIntersection(Point2 c1, double r1, Point2 c2, +list circleCircleIntersection(Point2 c1, double r1, Point2 c2, double r2, double tol) { // distance between circle centers. - double d = c1.dist(c2); + double d = distance2(c1, c2); // centers coincide, either no solution or infinite number of solutions. if (d<1e-9) return list(); // Calculate f and h given normalized radii double _d = 1.0/d, R_d = r1*_d, r_d=r2*_d; - boost::optional fh = CircleCircleIntersection(R_d,r_d); + boost::optional fh = circleCircleIntersection(R_d,r_d); // Call version that takes fh - return CircleCircleIntersection(c1, c2, fh); -} - -/* ************************************************************************* */ -ostream &operator<<(ostream &os, const Point2& p) { - os << '(' << p.x() << ", " << p.y() << ')'; - return os; + return circleCircleIntersection(c1, c2, fh); } /* ************************************************************************* */ diff --git a/gtsam/geometry/Point2.h b/gtsam/geometry/Point2.h index 3099a8bb3..fb250df6d 100644 --- a/gtsam/geometry/Point2.h +++ b/gtsam/geometry/Point2.h @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- - * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) @@ -22,6 +22,14 @@ namespace gtsam { +#ifdef GTSAM_TYPEDEF_POINTS_TO_VECTORS + + /// As of GTSAM 4, in order to make GTSAM more lean, + /// it is now possible to just typedef Point2 to Vector2 + typedef Vector2 Point2; + +#else + /** * A 2D point * Complies with the Testable Concept @@ -29,69 +37,30 @@ namespace gtsam { * @addtogroup geometry * \nosubgrouping */ -class GTSAM_EXPORT Point2 { +class GTSAM_EXPORT Point2 : public Vector2 { private: - double x_, y_; - public: enum { dimension = 2 }; /// @name Standard Constructors /// @{ /// default constructor - Point2(): x_(0), y_(0) {} +#ifdef GTSAM_ALLOW_DEPRECATED_SINCE_V4 + // Deprecated default constructor initializes to zero, in contrast to new behavior below + Point2() { setZero(); } +#else + Point2() {} +#endif - /// construct from doubles - Point2(double x, double y): x_(x), y_(y) {} + using Vector2::Vector2; /// @} /// @name Advanced Constructors /// @{ /// construct from 2D vector - explicit Point2(const Vector2& v) { - x_ = v(0); - y_ = v(1); - } - - /* - * @brief Circle-circle intersection, given normalized radii. - * Calculate f and h, respectively the parallel and perpendicular distance of - * the intersections of two circles along and from the line connecting the centers. - * Both are dimensionless fractions of the distance d between the circle centers. - * If the circles do not intersect or they are identical, returns boost::none. - * If one solution (touching circles, as determined by tol), h will be exactly zero. - * h is a good measure for how accurate the intersection will be, as when circles touch - * or nearly touch, the intersection is ill-defined with noisy radius measurements. - * @param R_d : R/d, ratio of radius of first circle to distance between centers - * @param r_d : r/d, ratio of radius of second circle to distance between centers - * @param tol: absolute tolerance below which we consider touching circles - * @return optional Point2 with f and h, boost::none if no solution. - */ - static boost::optional CircleCircleIntersection(double R_d, double r_d, - double tol = 1e-9); - - /* - * @brief Circle-circle intersection, from the normalized radii solution. - * @param c1 center of first circle - * @param c2 center of second circle - * @return list of solutions (0,1, or 2). Identical circles will return empty list, as well. - */ - static std::list CircleCircleIntersection(Point2 c1, Point2 c2, boost::optional); - - /** - * @brief Intersect 2 circles - * @param c1 center of first circle - * @param r1 radius of first circle - * @param c2 center of second circle - * @param r2 radius of second circle - * @param tol: absolute tolerance below which we consider touching circles - * @return list of solutions (0,1, or 2). Identical circles will return empty list, as well. - */ - static std::list CircleCircleIntersection(Point2 c1, double r1, - Point2 c2, double r2, double tol = 1e-9); - + explicit Point2(const Vector2& v):Vector2(v) {} /// @} /// @name Testable /// @{ @@ -107,21 +76,7 @@ public: /// @{ /// identity - inline static Point2 identity() {return Point2();} - - /// inverse - inline Point2 operator- () const {return Point2(-x_,-y_);} - - /// add vector on right - inline Point2 operator +(const Vector2& v) const { - return Point2(x_ + v[0], y_ + v[1]); - } - - /// add - inline Point2 operator + (const Point2& q) const {return Point2(x_+q.x_,y_+q.y_);} - - /// subtract - inline Point2 operator - (const Point2& q) const {return Point2(x_-q.x_,y_-q.y_);} + inline static Point2 identity() {return Point2(0,0);} /// @} /// @name Vector Space @@ -137,51 +92,44 @@ public: double distance(const Point2& p2, OptionalJacobian<1,2> H1 = boost::none, OptionalJacobian<1,2> H2 = boost::none) const; - /** @deprecated The following function has been deprecated, use distance above */ - inline double dist(const Point2& p2) const { - return (p2 - *this).norm(); - } - - /// multiply with a scalar - inline Point2 operator * (double s) const {return Point2(x_*s,y_*s);} - - /// divide by a scalar - inline Point2 operator / (double q) const {return Point2(x_/q,y_/q);} - /// @} /// @name Standard Interface /// @{ /// equality - inline bool operator ==(const Point2& q) const {return x_==q.x_ && y_==q.y_;} + inline bool operator ==(const Point2& q) const {return x()==q.x() && y()==q.y();} /// get x - double x() const {return x_;} + inline double x() const {return (*this)[0];} /// get y - double y() const {return y_;} + inline double y() const {return (*this)[1];} - /// return vectorized form (column-wise). TODO: why does this function exist? - Vector2 vector() const { return Vector2(x_, y_); } + /// return vectorized form (column-wise). + const Vector2& vector() const { return *this; } /// @} - /// @name Deprecated - /// @{ - inline void operator += (const Point2& q) {x_+=q.x_;y_+=q.y_;} - inline void operator *= (double s) {x_*=s;y_*=s;} - Point2 inverse() const { return -(*this);} - Point2 compose(const Point2& q) const { return (*this)+q;} - Point2 between(const Point2& q) const { return q-(*this);} - Vector2 localCoordinates(const Point2& q) const { return between(q).vector();} - Point2 retract(const Vector2& v) const { return compose(Point2(v));} - static Vector2 Logmap(const Point2& p) { return p.vector();} - static Point2 Expmap(const Vector2& v) { return Point2(v);} - /// @} - /// Streaming GTSAM_EXPORT friend std::ostream &operator<<(std::ostream &os, const Point2& p); +#ifdef GTSAM_ALLOW_DEPRECATED_SINCE_V4 + /// @name Deprecated + /// @{ + Point2 inverse() const { return -(*this); } + Point2 compose(const Point2& q) const { return (*this)+q;} + Point2 between(const Point2& q) const { return q-(*this);} + Vector2 localCoordinates(const Point2& q) const { return between(q);} + Point2 retract(const Vector2& v) const { return compose(Point2(v));} + static Vector2 Logmap(const Point2& p) { return p;} + static Point2 Expmap(const Vector2& v) { return Point2(v);} + inline double dist(const Point2& p2) const {return distance(p2);} + static boost::optional CircleCircleIntersection(double R_d, double r_d, double tol = 1e-9); + static std::list CircleCircleIntersection(Point2 c1, Point2 c2, boost::optional fh); + static std::list CircleCircleIntersection(Point2 c1, double r1, Point2 c2, double r2, double tol = 1e-9); + /// @} +#endif + private: /// @name Advanced Interface @@ -192,13 +140,25 @@ private: template void serialize(ARCHIVE & ar, const unsigned int /*version*/) { - ar & BOOST_SERIALIZATION_NVP(x_); - ar & BOOST_SERIALIZATION_NVP(y_); - } + ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Vector2);} - /// @} + /// @} }; +template<> +struct traits : public internal::VectorSpace { +}; + +#endif // GTSAM_TYPEDEF_POINTS_TO_VECTORS + +/// Distance of the point from the origin, with Jacobian +double norm2(const Point2& p, OptionalJacobian<1, 2> H = boost::none); + +/// distance between two points +double distance2(const Point2& p1, const Point2& q, + OptionalJacobian<1, 2> H1 = boost::none, + OptionalJacobian<1, 2> H2 = boost::none); + // Convenience typedef typedef std::pair Point2Pair; std::ostream &operator<<(std::ostream &os, const gtsam::Point2Pair &p); @@ -207,10 +167,45 @@ std::ostream &operator<<(std::ostream &os, const gtsam::Point2Pair &p); typedef std::vector Point2Vector; /// multiply with scalar -inline Point2 operator*(double s, const Point2& p) {return p*s;} +inline Point2 operator*(double s, const Point2& p) { +return p * s; +} -template<> -struct traits : public internal::VectorSpace {}; +/* + * @brief Circle-circle intersection, given normalized radii. + * Calculate f and h, respectively the parallel and perpendicular distance of + * the intersections of two circles along and from the line connecting the centers. + * Both are dimensionless fractions of the distance d between the circle centers. + * If the circles do not intersect or they are identical, returns boost::none. + * If one solution (touching circles, as determined by tol), h will be exactly zero. + * h is a good measure for how accurate the intersection will be, as when circles touch + * or nearly touch, the intersection is ill-defined with noisy radius measurements. + * @param R_d : R/d, ratio of radius of first circle to distance between centers + * @param r_d : r/d, ratio of radius of second circle to distance between centers + * @param tol: absolute tolerance below which we consider touching circles + * @return optional Point2 with f and h, boost::none if no solution. + */ +boost::optional circleCircleIntersection(double R_d, double r_d, double tol = 1e-9); + +/* + * @brief Circle-circle intersection, from the normalized radii solution. + * @param c1 center of first circle + * @param c2 center of second circle + * @return list of solutions (0,1, or 2). Identical circles will return empty list, as well. + */ +std::list circleCircleIntersection(Point2 c1, Point2 c2, boost::optional fh); + +/** + * @brief Intersect 2 circles + * @param c1 center of first circle + * @param r1 radius of first circle + * @param c2 center of second circle + * @param r2 radius of second circle + * @param tol: absolute tolerance below which we consider touching circles + * @return list of solutions (0,1, or 2). Identical circles will return empty list, as well. + */ +std::list circleCircleIntersection(Point2 c1, double r1, + Point2 c2, double r2, double tol = 1e-9); } // \ namespace gtsam diff --git a/gtsam/geometry/Point3.cpp b/gtsam/geometry/Point3.cpp index df0f78283..091906d5f 100644 --- a/gtsam/geometry/Point3.cpp +++ b/gtsam/geometry/Point3.cpp @@ -21,7 +21,7 @@ using namespace std; namespace gtsam { -#ifndef GTSAM_USE_VECTOR3_POINTS +#ifndef GTSAM_TYPEDEF_POINTS_TO_VECTORS bool Point3::equals(const Point3 &q, double tol) const { return (fabs(x() - q.x()) < tol && fabs(y() - q.y()) < tol && fabs(z() - q.z()) < tol); @@ -34,11 +34,11 @@ void Point3::print(const string& s) const { /* ************************************************************************* */ double Point3::distance(const Point3 &q, OptionalJacobian<1, 3> H1, OptionalJacobian<1, 3> H2) const { - return gtsam::distance(*this,q,H1,H2); + return gtsam::distance3(*this,q,H1,H2); } double Point3::norm(OptionalJacobian<1,3> H) const { - return gtsam::norm(*this, H); + return gtsam::norm3(*this, H); } Point3 Point3::normalized(OptionalJacobian<3,3> H) const { @@ -57,7 +57,7 @@ double Point3::dot(const Point3 &q, OptionalJacobian<1, 3> H1, /* ************************************************************************* */ ostream &operator<<(ostream &os, const Point3& p) { - os << '[' << p.x() << ", " << p.y() << ", " << p.z() << "]\';"; + os << '[' << p.x() << ", " << p.y() << ", " << p.z() << "]'"; return os; } @@ -80,8 +80,8 @@ Point3 Point3::sub(const Point3 &q, OptionalJacobian<3,3> H1, #endif /* ************************************************************************* */ -double distance(const Point3 &p1, const Point3 &q, OptionalJacobian<1, 3> H1, - OptionalJacobian<1, 3> H2) { +double distance3(const Point3 &p1, const Point3 &q, OptionalJacobian<1, 3> H1, + OptionalJacobian<1, 3> H2) { double d = (q - p1).norm(); if (H1) { *H1 << p1.x() - q.x(), p1.y() - q.y(), p1.z() - q.z(); @@ -94,7 +94,7 @@ double distance(const Point3 &p1, const Point3 &q, OptionalJacobian<1, 3> H1, return d; } -double norm(const Point3 &p, OptionalJacobian<1, 3> H) { +double norm3(const Point3 &p, OptionalJacobian<1, 3> H) { double r = sqrt(p.x() * p.x() + p.y() * p.y() + p.z() * p.z()); if (H) { if (fabs(r) > 1e-10) @@ -106,7 +106,7 @@ double norm(const Point3 &p, OptionalJacobian<1, 3> H) { } Point3 normalize(const Point3 &p, OptionalJacobian<3, 3> H) { - Point3 normalized = p / norm(p); + Point3 normalized = p / p.norm(); if (H) { // 3*3 Derivative double x2 = p.x() * p.x(), y2 = p.y() * p.y(), z2 = p.z() * p.z(); diff --git a/gtsam/geometry/Point3.h b/gtsam/geometry/Point3.h index fd254e51c..99cb6c2e7 100644 --- a/gtsam/geometry/Point3.h +++ b/gtsam/geometry/Point3.h @@ -29,7 +29,7 @@ namespace gtsam { -#ifdef GTSAM_USE_VECTOR3_POINTS +#ifdef GTSAM_TYPEDEF_POINTS_TO_VECTORS /// As of GTSAM 4, in order to make GTSAM more lean, /// it is now possible to just typedef Point3 to Vector3 @@ -51,8 +51,8 @@ class GTSAM_EXPORT Point3 : public Vector3 { /// @name Standard Constructors /// @{ -#ifdef GTSAM_ALLOW_DEPRECATED_SINCE_V4 // Deprecated default constructor initializes to zero, in contrast to new behavior below +#ifdef GTSAM_ALLOW_DEPRECATED_SINCE_V4 Point3() { setZero(); } #endif @@ -124,9 +124,9 @@ class GTSAM_EXPORT Point3 : public Vector3 { Point3 inverse() const { return -(*this);} Point3 compose(const Point3& q) const { return (*this)+q;} Point3 between(const Point3& q) const { return q-(*this);} - Vector3 localCoordinates(const Point3& q) const { return between(q).vector();} + Vector3 localCoordinates(const Point3& q) const { return between(q);} Point3 retract(const Vector3& v) const { return compose(Point3(v));} - static Vector3 Logmap(const Point3& p) { return p.vector();} + static Vector3 Logmap(const Point3& p) { return p;} static Point3 Expmap(const Vector3& v) { return Point3(v);} inline double dist(const Point3& q) const { return (q - *this).norm(); } Point3 normalize(OptionalJacobian<3, 3> H = boost::none) const { return normalized(H);} @@ -153,19 +153,19 @@ struct traits : public internal::VectorSpace {}; template<> struct traits : public internal::VectorSpace {}; -#endif +#endif // GTSAM_TYPEDEF_POINTS_TO_VECTORS // Convenience typedef typedef std::pair Point3Pair; std::ostream &operator<<(std::ostream &os, const gtsam::Point3Pair &p); /// distance between two points -double distance(const Point3& p1, const Point3& q, - OptionalJacobian<1, 3> H1 = boost::none, - OptionalJacobian<1, 3> H2 = boost::none); +double distance3(const Point3& p1, const Point3& q, + OptionalJacobian<1, 3> H1 = boost::none, + OptionalJacobian<1, 3> H2 = boost::none); /// Distance of the point from the origin, with Jacobian -double norm(const Point3& p, OptionalJacobian<1, 3> H = boost::none); +double norm3(const Point3& p, OptionalJacobian<1, 3> H = boost::none); /// normalize, with optional Jacobian Point3 normalize(const Point3& p, OptionalJacobian<3, 3> H = boost::none); @@ -180,10 +180,6 @@ double dot(const Point3& p, const Point3& q, OptionalJacobian<1, 3> H_p = boost::none, OptionalJacobian<1, 3> H_q = boost::none); -// Convenience typedef -typedef std::pair Point3Pair; -std::ostream &operator<<(std::ostream &os, const gtsam::Point3Pair &p); - template struct Range; @@ -193,7 +189,7 @@ struct Range { double operator()(const Point3& p, const Point3& q, OptionalJacobian<1, 3> H1 = boost::none, OptionalJacobian<1, 3> H2 = boost::none) { - return distance(p, q, H1, H2); + return distance3(p, q, H1, H2); } }; diff --git a/gtsam/geometry/Pose2.cpp b/gtsam/geometry/Pose2.cpp index 34b146bee..2a52e98ba 100644 --- a/gtsam/geometry/Pose2.cpp +++ b/gtsam/geometry/Pose2.cpp @@ -53,21 +53,21 @@ void Pose2::print(const string& s) const { /* ************************************************************************* */ bool Pose2::equals(const Pose2& q, double tol) const { - return t_.equals(q.t_, tol) && r_.equals(q.r_, tol); + return equal_with_abs_tol(t_, q.t_, tol) && r_.equals(q.r_, tol); } /* ************************************************************************* */ Pose2 Pose2::Expmap(const Vector3& xi, OptionalJacobian<3, 3> H) { - if (H) *H = Pose2::ExpmapDerivative(xi); assert(xi.size() == 3); - Point2 v(xi(0),xi(1)); - double w = xi(2); + if (H) *H = Pose2::ExpmapDerivative(xi); + const Point2 v(xi(0),xi(1)); + const double w = xi(2); if (std::abs(w) < 1e-10) return Pose2(xi[0], xi[1], xi[2]); else { - Rot2 R(Rot2::fromAngle(w)); - Point2 v_ortho = R_PI_2 * v; // points towards rot center - Point2 t = (v_ortho - R.rotate(v_ortho)) / w; + const Rot2 R(Rot2::fromAngle(w)); + const Point2 v_ortho = R_PI_2 * v; // points towards rot center + const Point2 t = (v_ortho - R.rotate(v_ortho)) / w; return Pose2(R, t); } } @@ -249,7 +249,7 @@ double Pose2::range(const Point2& point, Point2 d = point - t_; if (!Hpose && !Hpoint) return d.norm(); Matrix12 D_r_d; - double r = d.norm(D_r_d); + double r = norm2(d, D_r_d); if (Hpose) { Matrix23 D_d_pose; D_d_pose << -r_.c(), r_.s(), 0.0, @@ -267,7 +267,7 @@ double Pose2::range(const Pose2& pose, Point2 d = pose.t() - t_; if (!Hpose && !Hother) return d.norm(); Matrix12 D_r_d; - double r = d.norm(D_r_d); + double r = norm2(d, D_r_d); if (Hpose) { Matrix23 D_d_pose; D_d_pose << @@ -311,7 +311,7 @@ boost::optional align(const vector& pairs) { if (n<2) return boost::none; // we need at least two pairs // calculate centroids - Point2 cp,cq; + Point2 cp(0,0), cq(0,0); for(const Point2Pair& pair: pairs) { cp += pair.first; cq += pair.second; diff --git a/gtsam/geometry/Pose2.h b/gtsam/geometry/Pose2.h index 31dfb479f..1ba384857 100644 --- a/gtsam/geometry/Pose2.h +++ b/gtsam/geometry/Pose2.h @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- - * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) @@ -52,7 +52,9 @@ public: /// @{ /** default constructor = origin */ - Pose2() {} // default is origin + Pose2() : + r_(traits::Identity()), t_(traits::Identity()) { + } /** copy constructor */ Pose2(const Pose2& pose) : r_(pose.r_), t_(pose.t_) {} @@ -86,7 +88,7 @@ public: /// @{ /** Construct from canonical coordinates \f$ [T_x,T_y,\theta] \f$ (Lie algebra) */ - Pose2(const Vector& v) { + Pose2(const Vector& v) : Pose2() { *this = Expmap(v); } diff --git a/gtsam/geometry/Pose3.cpp b/gtsam/geometry/Pose3.cpp index 3138dfd64..25cd661e8 100644 --- a/gtsam/geometry/Pose3.cpp +++ b/gtsam/geometry/Pose3.cpp @@ -345,7 +345,7 @@ double Pose3::range(const Point3& point, OptionalJacobian<1, 6> H1, return local.norm(); } else { Matrix13 D_r_local; - const double r = norm(local, D_r_local); + const double r = norm3(local, D_r_local); if (H1) *H1 = D_r_local * D_local_pose; if (H2) *H2 = D_r_local * D_local_point; return r; diff --git a/gtsam/geometry/Rot3.h b/gtsam/geometry/Rot3.h index 79b13b93e..bb0278953 100644 --- a/gtsam/geometry/Rot3.h +++ b/gtsam/geometry/Rot3.h @@ -118,6 +118,7 @@ namespace gtsam { * @param q The quaternion */ Rot3(const Quaternion& q); + Rot3(double x, double y, double z, double w) : Rot3(Quaternion(x, y, z, w)) {} /// Random, generates a random axis, then random angle \in [-p,pi] static Rot3 Random(boost::mt19937 & rng); @@ -156,12 +157,17 @@ namespace gtsam { /** * Returns rotation nRb from body to nav frame. + * For vehicle coordinate frame X forward, Y right, Z down: * Positive yaw is to right (as in aircraft heading). * Positive pitch is up (increasing aircraft altitude). * Positive roll is to right (increasing yaw in aircraft). * Tait-Bryan system from Spatial Reference Model (SRM) (x,y,z) = (roll,pitch,yaw) * as described in http://www.sedris.org/wg8home/Documents/WG80462.pdf. - * Assumes vehicle coordinate frame X forward, Y right, Z down. + * + * For vehicle coordinate frame X forward, Y left, Z up: + * Positive yaw is to left (as in aircraft heading). + * Positive pitch is down (decreasing aircraft altitude). + * Positive roll is to right (decreasing yaw in aircraft). */ static Rot3 Ypr(double y, double p, double r) { return RzRyRx(r,p,y);} @@ -179,7 +185,7 @@ namespace gtsam { */ static Rot3 AxisAngle(const Point3& axis, double angle) { #ifdef GTSAM_USE_QUATERNIONS - return gtsam::Quaternion(Eigen::AngleAxis(angle, axis.vector())); + return gtsam::Quaternion(Eigen::AngleAxis(angle, axis)); #else return Rot3(SO3::AxisAngle(axis,angle)); #endif diff --git a/gtsam/geometry/Rot3Q.cpp b/gtsam/geometry/Rot3Q.cpp index f8a01141b..8af9a7144 100644 --- a/gtsam/geometry/Rot3Q.cpp +++ b/gtsam/geometry/Rot3Q.cpp @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- - * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) @@ -92,7 +92,7 @@ namespace gtsam { const Matrix3 R = matrix(); if (H1) *H1 = R * skewSymmetric(-p.x(), -p.y(), -p.z()); if (H2) *H2 = R; - const Vector3 r = R * p.vector(); + const Vector3 r = R * p; return Point3(r.x(), r.y(), r.z()); } diff --git a/gtsam/geometry/Unit3.h b/gtsam/geometry/Unit3.h index 9f21bb82a..cd05af519 100644 --- a/gtsam/geometry/Unit3.h +++ b/gtsam/geometry/Unit3.h @@ -78,7 +78,7 @@ public: /// Construct from 2D point in plane at focal length f /// Unit3(p,1) can be viewed as normalized homogeneous coordinates of 2D point - explicit Unit3(const Point2& p, double f = 1.0) : p_(p.x(), p.y(), f) { + explicit Unit3(const Point2& p, double f) : p_(p.x(), p.y(), f) { p_.normalize(); } diff --git a/gtsam/geometry/tests/testCal3Bundler.cpp b/gtsam/geometry/tests/testCal3Bundler.cpp index e9eb689e1..8de049fa4 100644 --- a/gtsam/geometry/tests/testCal3Bundler.cpp +++ b/gtsam/geometry/tests/testCal3Bundler.cpp @@ -52,7 +52,7 @@ TEST( Cal3Bundler, calibrate ) Point2 pn(0.5, 0.5); Point2 pi = K.uncalibrate(pn); Point2 pn_hat = K.calibrate(pi); - CHECK( pn.equals(pn_hat, 1e-5)); + CHECK( traits::Equals(pn, pn_hat, 1e-5)); } /* ************************************************************************* */ diff --git a/gtsam/geometry/tests/testCal3DS2.cpp b/gtsam/geometry/tests/testCal3DS2.cpp index c5a6be2d6..416665d46 100644 --- a/gtsam/geometry/tests/testCal3DS2.cpp +++ b/gtsam/geometry/tests/testCal3DS2.cpp @@ -48,7 +48,7 @@ TEST( Cal3DS2, calibrate ) Point2 pn(0.5, 0.5); Point2 pi = K.uncalibrate(pn); Point2 pn_hat = K.calibrate(pi); - CHECK( pn.equals(pn_hat, 1e-5)); + CHECK( traits::Equals(pn, pn_hat, 1e-5)); } Point2 uncalibrate_(const Cal3DS2& k, const Point2& pt) { return k.uncalibrate(pt); } diff --git a/gtsam/geometry/tests/testCal3Unified.cpp b/gtsam/geometry/tests/testCal3Unified.cpp index de9a8b739..2c5ffd7fb 100644 --- a/gtsam/geometry/tests/testCal3Unified.cpp +++ b/gtsam/geometry/tests/testCal3Unified.cpp @@ -59,7 +59,7 @@ TEST( Cal3Unified, calibrate) { Point2 pi = K.uncalibrate(p); Point2 pn_hat = K.calibrate(pi); - CHECK( p.equals(pn_hat, 1e-8)); + CHECK( traits::Equals(p, pn_hat, 1e-8)); } Point2 uncalibrate_(const Cal3Unified& k, const Point2& pt) { return k.uncalibrate(pt); } diff --git a/gtsam/geometry/tests/testCalibratedCamera.cpp b/gtsam/geometry/tests/testCalibratedCamera.cpp index cc7a0c0f8..e629eb3c6 100644 --- a/gtsam/geometry/tests/testCalibratedCamera.cpp +++ b/gtsam/geometry/tests/testCalibratedCamera.cpp @@ -30,10 +30,10 @@ using namespace gtsam; GTSAM_CONCEPT_MANIFOLD_INST(CalibratedCamera) // Camera situated at 0.5 meters high, looking down -static const Pose3 pose1(Rot3(Vector3(1, -1, -1).asDiagonal()), +static const Pose3 kDefaultPose(Rot3(Vector3(1, -1, -1).asDiagonal()), Point3(0, 0, 0.5)); -static const CalibratedCamera camera(pose1); +static const CalibratedCamera camera(kDefaultPose); static const Point3 point1(-0.08,-0.08, 0.0); static const Point3 point2(-0.08, 0.08, 0.0); @@ -43,7 +43,19 @@ static const Point3 point4( 0.08,-0.08, 0.0); /* ************************************************************************* */ TEST( CalibratedCamera, constructor) { - CHECK(assert_equal( camera.pose(), pose1)); + CHECK(assert_equal( camera.pose(), kDefaultPose)); +} + +//****************************************************************************** +TEST(CalibratedCamera, Create) { + Matrix actualH; + EXPECT(assert_equal(camera, CalibratedCamera::Create(kDefaultPose, actualH))); + + // Check derivative + boost::function f = // + boost::bind(CalibratedCamera::Create, _1, boost::none); + Matrix numericalH = numericalDerivative11(f, kDefaultPose); + EXPECT(assert_equal(numericalH, actualH, 1e-9)); } /* ************************************************************************* */ @@ -131,8 +143,8 @@ TEST( CalibratedCamera, Dproject_point_pose) // Add a test with more arbitrary rotation TEST( CalibratedCamera, Dproject_point_pose2) { - static const Pose3 pose1(Rot3::Ypr(0.1, -0.1, 0.4), Point3(0, 0, -10)); - static const CalibratedCamera camera(pose1); + static const Pose3 kDefaultPose(Rot3::Ypr(0.1, -0.1, 0.4), Point3(0, 0, -10)); + static const CalibratedCamera camera(kDefaultPose); Matrix Dpose, Dpoint; camera.project(point1, Dpose, Dpoint); Matrix numerical_pose = numericalDerivative21(project2, camera, point1); @@ -152,7 +164,7 @@ TEST( CalibratedCamera, Dproject_point_pose_infinity) Point2 result = camera.project2(pointAtInfinity, Dpose, Dpoint); Matrix numerical_pose = numericalDerivative21(projectAtInfinity, camera, pointAtInfinity); Matrix numerical_point = numericalDerivative22(projectAtInfinity, camera, pointAtInfinity); - CHECK(assert_equal(Point2(), result)); + CHECK(assert_equal(Point2(0,0), result)); CHECK(assert_equal(numerical_pose, Dpose, 1e-7)); CHECK(assert_equal(numerical_point, Dpoint, 1e-7)); } @@ -161,8 +173,8 @@ TEST( CalibratedCamera, Dproject_point_pose_infinity) // Add a test with more arbitrary rotation TEST( CalibratedCamera, Dproject_point_pose2_infinity) { - static const Pose3 pose1(Rot3::Ypr(0.1, -0.1, 0.4), Point3(0, 0, -10)); - static const CalibratedCamera camera(pose1); + static const Pose3 pose(Rot3::Ypr(0.1, -0.1, 0.4), Point3(0, 0, -10)); + static const CalibratedCamera camera(pose); Matrix Dpose, Dpoint; camera.project2(pointAtInfinity, Dpose, Dpoint); Matrix numerical_pose = numericalDerivative21(projectAtInfinity, camera, pointAtInfinity); diff --git a/gtsam/geometry/tests/testCameraSet.cpp b/gtsam/geometry/tests/testCameraSet.cpp index 0afa04411..01f784ae0 100644 --- a/gtsam/geometry/tests/testCameraSet.cpp +++ b/gtsam/geometry/tests/testCameraSet.cpp @@ -44,7 +44,7 @@ TEST(CameraSet, Pinhole) { EXPECT(!set.equals(set2)); // Check measurements - Point2 expected; + Point2 expected(0,0); ZZ z = set.project2(p); EXPECT(assert_equal(expected, z[0])); EXPECT(assert_equal(expected, z[1])); @@ -90,7 +90,7 @@ TEST(CameraSet, Pinhole) { Vector v = Ft * (b - E * P * Et * b); schur << Ft * F - Ft * E * P * Et * F, v, v.transpose(), 30; SymmetricBlockMatrix actualReduced = Set::SchurComplement(Fs, E, P, b); - EXPECT(assert_equal(schur, actualReduced.matrix())); + EXPECT(assert_equal(schur, actualReduced.selfadjointView())); // Check Schur complement update, same order, should just double FastVector allKeys, keys; @@ -99,7 +99,7 @@ TEST(CameraSet, Pinhole) { keys.push_back(1); keys.push_back(2); Set::UpdateSchurComplement(Fs, E, P, b, allKeys, keys, actualReduced); - EXPECT(assert_equal((Matrix )(2.0 * schur), actualReduced.matrix())); + EXPECT(assert_equal((Matrix )(2.0 * schur), actualReduced.selfadjointView())); // Check Schur complement update, keys reversed FastVector keys2; @@ -111,13 +111,13 @@ TEST(CameraSet, Pinhole) { Vector reverse_v = Ft * (reverse_b - E * P * Et * reverse_b); Matrix A(19, 19); A << Ft * F - Ft * E * P * Et * F, reverse_v, reverse_v.transpose(), 30; - EXPECT(assert_equal((Matrix )(2.0 * schur + A), actualReduced.matrix())); + EXPECT(assert_equal((Matrix )(2.0 * schur + A), actualReduced.selfadjointView())); // reprojectionErrorAtInfinity Unit3 pointAtInfinity(0, 0, 1000); EXPECT( assert_equal(pointAtInfinity, - camera.backprojectPointAtInfinity(Point2()))); + camera.backprojectPointAtInfinity(Point2(0,0)))); actualV = set.reprojectionError(pointAtInfinity, measured, Fs, E); EXPECT(assert_equal(expectedV, actualV)); LONGS_EQUAL(2, Fs.size()); diff --git a/gtsam/geometry/tests/testPinholeCamera.cpp b/gtsam/geometry/tests/testPinholeCamera.cpp index 99dcb95bf..a9b68bdec 100644 --- a/gtsam/geometry/tests/testPinholeCamera.cpp +++ b/gtsam/geometry/tests/testPinholeCamera.cpp @@ -153,12 +153,12 @@ TEST( PinholeCamera, backproject2) Rot3 rot(1., 0., 0., 0., 0., 1., 0., -1., 0.); // a camera1 looking down Camera camera(Pose3(rot, origin), K); - Point3 actual = camera.backproject(Point2(), 1.); + Point3 actual = camera.backproject(Point2(0,0), 1.); Point3 expected(0., 1., 0.); pair x = camera.projectSafe(expected); EXPECT(assert_equal(expected, actual)); - EXPECT(assert_equal(Point2(), x.first)); + EXPECT(assert_equal(Point2(0,0), x.first)); EXPECT(x.second); } @@ -169,12 +169,12 @@ TEST( PinholeCamera, backprojectInfinity2) Rot3 rot(1., 0., 0., 0., 0., 1., 0., -1., 0.); // a camera1 looking down Camera camera(Pose3(rot, origin), K); - Unit3 actual = camera.backprojectPointAtInfinity(Point2()); + Unit3 actual = camera.backprojectPointAtInfinity(Point2(0,0)); Unit3 expected(0., 1., 0.); Point2 x = camera.project(expected); EXPECT(assert_equal(expected, actual)); - EXPECT(assert_equal(Point2(), x)); + EXPECT(assert_equal(Point2(0,0), x)); } /* ************************************************************************* */ @@ -184,12 +184,12 @@ TEST( PinholeCamera, backprojectInfinity3) Rot3 rot(1., 0., 0., 0., 1., 0., 0., 0., 1.); // identity Camera camera(Pose3(rot, origin), K); - Unit3 actual = camera.backprojectPointAtInfinity(Point2()); + Unit3 actual = camera.backprojectPointAtInfinity(Point2(0,0)); Unit3 expected(0., 0., 1.); Point2 x = camera.project(expected); EXPECT(assert_equal(expected, actual)); - EXPECT(assert_equal(Point2(), x)); + EXPECT(assert_equal(Point2(0,0), x)); } /* ************************************************************************* */ @@ -278,7 +278,7 @@ TEST( PinholeCamera, range0) { double result = camera.range(point1, D1, D2); Matrix Hexpected1 = numericalDerivative21(range0, camera, point1); Matrix Hexpected2 = numericalDerivative22(range0, camera, point1); - EXPECT_DOUBLES_EQUAL(distance(point1, camera.pose().translation()), result, + EXPECT_DOUBLES_EQUAL(distance3(point1, camera.pose().translation()), result, 1e-9); EXPECT(assert_equal(Hexpected1, D1, 1e-7)); EXPECT(assert_equal(Hexpected2, D2, 1e-7)); diff --git a/gtsam/geometry/tests/testPinholePose.cpp b/gtsam/geometry/tests/testPinholePose.cpp index 0d840de7e..ecbb92061 100644 --- a/gtsam/geometry/tests/testPinholePose.cpp +++ b/gtsam/geometry/tests/testPinholePose.cpp @@ -124,12 +124,12 @@ TEST( PinholePose, backproject2) Rot3 rot(1., 0., 0., 0., 0., 1., 0., -1., 0.); // a camera1 looking down Camera camera(Pose3(rot, origin), K); - Point3 actual = camera.backproject(Point2(), 1.); + Point3 actual = camera.backproject(Point2(0,0), 1.); Point3 expected(0., 1., 0.); pair x = camera.projectSafe(expected); EXPECT(assert_equal(expected, actual)); - EXPECT(assert_equal(Point2(), x.first)); + EXPECT(assert_equal(Point2(0,0), x.first)); EXPECT(x.second); } @@ -212,7 +212,7 @@ TEST( PinholePose, range0) { double result = camera.range(point1, D1, D2); Matrix expectedDcamera = numericalDerivative21(range0, camera, point1); Matrix expectedDpoint = numericalDerivative22(range0, camera, point1); - EXPECT_DOUBLES_EQUAL(distance(point1, camera.pose().translation()), result, 1e-9); + EXPECT_DOUBLES_EQUAL(distance3(point1, camera.pose().translation()), result, 1e-9); EXPECT(assert_equal(expectedDcamera, D1, 1e-7)); EXPECT(assert_equal(expectedDpoint, D2, 1e-7)); } diff --git a/gtsam/geometry/tests/testPinholeSet.cpp b/gtsam/geometry/tests/testPinholeSet.cpp index b8f001f1c..28b7ddac6 100644 --- a/gtsam/geometry/tests/testPinholeSet.cpp +++ b/gtsam/geometry/tests/testPinholeSet.cpp @@ -84,7 +84,7 @@ TEST(PinholeSet, Pinhole) { EXPECT(!set.equals(set2)); // Check measurements - Point2 expected; + Point2 expected(0,0); ZZ z = set.project2(p); EXPECT(assert_equal(expected, z[0])); EXPECT(assert_equal(expected, z[1])); @@ -131,7 +131,7 @@ TEST(PinholeSet, Pinhole) { } EXPECT( assert_equal(pointAtInfinity, - camera.backprojectPointAtInfinity(Point2()))); + camera.backprojectPointAtInfinity(Point2(0,0)))); { PinholeSet::FBlocks Fs; Matrix E; diff --git a/gtsam/geometry/tests/testPoint2.cpp b/gtsam/geometry/tests/testPoint2.cpp index 3a636b9bf..e2a5bcdea 100644 --- a/gtsam/geometry/tests/testPoint2.cpp +++ b/gtsam/geometry/tests/testPoint2.cpp @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- - * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) @@ -27,6 +27,11 @@ using namespace gtsam; GTSAM_CONCEPT_TESTABLE_INST(Point2) GTSAM_CONCEPT_LIE_INST(Point2) +//****************************************************************************** +TEST(Point2 , Constructor) { + Point2 p; +} + //****************************************************************************** TEST(Double , Concept) { BOOST_CONCEPT_ASSERT((IsGroup)); @@ -95,26 +100,26 @@ TEST( Point2, expmap) { /* ************************************************************************* */ TEST( Point2, arithmetic) { - EXPECT(assert_equal( Point2(-5,-6), -Point2(5,6) )); - EXPECT(assert_equal( Point2(5,6), Point2(4,5)+Point2(1,1))); - EXPECT(assert_equal( Point2(3,4), Point2(4,5)-Point2(1,1) )); - EXPECT(assert_equal( Point2(8,6), Point2(4,3)*2)); - EXPECT(assert_equal( Point2(4,6), 2*Point2(2,3))); - EXPECT(assert_equal( Point2(2,3), Point2(4,6)/2)); + EXPECT(assert_equal( Point2(-5,-6), -Point2(5,6) )); + EXPECT(assert_equal( Point2(5,6), Point2(4,5)+Point2(1,1))); + EXPECT(assert_equal( Point2(3,4), Point2(4,5)-Point2(1,1) )); + EXPECT(assert_equal( Point2(8,6), Point2(4,3)*2)); + EXPECT(assert_equal( Point2(4,6), 2*Point2(2,3))); + EXPECT(assert_equal( Point2(2,3), Point2(4,6)/2)); } /* ************************************************************************* */ TEST( Point2, unit) { Point2 p0(10, 0), p1(0, -10), p2(10, 10); - EXPECT(assert_equal(Point2(1, 0), p0.unit(), 1e-6)); - EXPECT(assert_equal(Point2(0,-1), p1.unit(), 1e-6)); - EXPECT(assert_equal(Point2(sqrt(2.0)/2.0, sqrt(2.0)/2.0), p2.unit(), 1e-6)); + EXPECT(assert_equal(Point2(1, 0), Point2(p0.normalized()), 1e-6)); + EXPECT(assert_equal(Point2(0,-1), Point2(p1.normalized()), 1e-6)); + EXPECT(assert_equal(Point2(sqrt(2.0)/2.0, sqrt(2.0)/2.0), Point2(p2.normalized()), 1e-6)); } namespace { /* ************************************************************************* */ // some shared test values - Point2 x1, x2(1, 1), x3(1, 1); + Point2 x1(0,0), x2(1, 1), x3(1, 1); Point2 l1(1, 0), l2(1, 1), l3(2, 2), l4(1, 3); /* ************************************************************************* */ @@ -126,19 +131,19 @@ TEST( Point2, norm ) { Point2 p0(cos(5.0), sin(5.0)); DOUBLES_EQUAL(1, p0.norm(), 1e-6); Point2 p1(4, 5), p2(1, 1); - DOUBLES_EQUAL( 5, p1.distance(p2), 1e-6); + DOUBLES_EQUAL( 5, distance2(p1, p2), 1e-6); DOUBLES_EQUAL( 5, (p2-p1).norm(), 1e-6); Matrix expectedH, actualH; double actual; // exception, for (0,0) derivative is [Inf,Inf] but we return [1,1] - actual = x1.norm(actualH); + actual = norm2(x1, actualH); EXPECT_DOUBLES_EQUAL(0, actual, 1e-9); expectedH = (Matrix(1, 2) << 1.0, 1.0).finished(); EXPECT(assert_equal(expectedH,actualH)); - actual = x2.norm(actualH); + actual = norm2(x2, actualH); EXPECT_DOUBLES_EQUAL(sqrt(2.0), actual, 1e-9); expectedH = numericalDerivative11(norm_proxy, x2); EXPECT(assert_equal(expectedH,actualH)); @@ -151,20 +156,20 @@ TEST( Point2, norm ) { /* ************************************************************************* */ namespace { double distance_proxy(const Point2& location, const Point2& point) { - return location.distance(point); + return distance2(location, point); } } TEST( Point2, distance ) { Matrix expectedH1, actualH1, expectedH2, actualH2; // establish distance is indeed zero - EXPECT_DOUBLES_EQUAL(1, x1.distance(l1), 1e-9); + EXPECT_DOUBLES_EQUAL(1, distance2(x1, l1), 1e-9); // establish distance is indeed 45 degrees - EXPECT_DOUBLES_EQUAL(sqrt(2.0), x1.distance(l2), 1e-9); + EXPECT_DOUBLES_EQUAL(sqrt(2.0), distance2(x1, l2), 1e-9); // Another pair - double actual23 = x2.distance(l3, actualH1, actualH2); + double actual23 = distance2(x2, l3, actualH1, actualH2); EXPECT_DOUBLES_EQUAL(sqrt(2.0), actual23, 1e-9); // Check numerical derivatives @@ -174,7 +179,7 @@ TEST( Point2, distance ) { EXPECT(assert_equal(expectedH2,actualH2)); // Another test - double actual34 = x3.distance(l4, actualH1, actualH2); + double actual34 = distance2(x3, l4, actualH1, actualH2); EXPECT_DOUBLES_EQUAL(2, actual34, 1e-9); // Check numerical derivatives @@ -190,42 +195,42 @@ TEST( Point2, circleCircleIntersection) { double offset = 0.994987; // Test intersections of circle moving from inside to outside - list inside = Point2::CircleCircleIntersection(Point2(0,0),5,Point2(0,0),1); + list inside = circleCircleIntersection(Point2(0,0),5,Point2(0,0),1); EXPECT_LONGS_EQUAL(0,inside.size()); - list touching1 = Point2::CircleCircleIntersection(Point2(0,0),5,Point2(4,0),1); + list touching1 = circleCircleIntersection(Point2(0,0),5,Point2(4,0),1); EXPECT_LONGS_EQUAL(1,touching1.size()); EXPECT(assert_equal(Point2(5,0), touching1.front())); - list common = Point2::CircleCircleIntersection(Point2(0,0),5,Point2(5,0),1); + list common = circleCircleIntersection(Point2(0,0),5,Point2(5,0),1); EXPECT_LONGS_EQUAL(2,common.size()); EXPECT(assert_equal(Point2(4.9, offset), common.front(), 1e-6)); EXPECT(assert_equal(Point2(4.9, -offset), common.back(), 1e-6)); - list touching2 = Point2::CircleCircleIntersection(Point2(0,0),5,Point2(6,0),1); + list touching2 = circleCircleIntersection(Point2(0,0),5,Point2(6,0),1); EXPECT_LONGS_EQUAL(1,touching2.size()); EXPECT(assert_equal(Point2(5,0), touching2.front())); // test rotated case - list rotated = Point2::CircleCircleIntersection(Point2(0,0),5,Point2(0,5),1); + list rotated = circleCircleIntersection(Point2(0,0),5,Point2(0,5),1); EXPECT_LONGS_EQUAL(2,rotated.size()); EXPECT(assert_equal(Point2(-offset, 4.9), rotated.front(), 1e-6)); EXPECT(assert_equal(Point2( offset, 4.9), rotated.back(), 1e-6)); // test r1 smaller = Point2::CircleCircleIntersection(Point2(0,0),1,Point2(5,0),5); + list smaller = circleCircleIntersection(Point2(0,0),1,Point2(5,0),5); EXPECT_LONGS_EQUAL(2,smaller.size()); EXPECT(assert_equal(Point2(0.1, offset), smaller.front(), 1e-6)); EXPECT(assert_equal(Point2(0.1, -offset), smaller.back(), 1e-6)); // test offset case, r1>r2 - list offset1 = Point2::CircleCircleIntersection(Point2(1,1),5,Point2(6,1),1); + list offset1 = circleCircleIntersection(Point2(1,1),5,Point2(6,1),1); EXPECT_LONGS_EQUAL(2,offset1.size()); EXPECT(assert_equal(Point2(5.9, 1+offset), offset1.front(), 1e-6)); EXPECT(assert_equal(Point2(5.9, 1-offset), offset1.back(), 1e-6)); // test offset case, r1 offset2 = Point2::CircleCircleIntersection(Point2(6,1),1,Point2(1,1),5); + list offset2 = circleCircleIntersection(Point2(6,1),1,Point2(1,1),5); EXPECT_LONGS_EQUAL(2,offset2.size()); EXPECT(assert_equal(Point2(5.9, 1-offset), offset2.front(), 1e-6)); EXPECT(assert_equal(Point2(5.9, 1+offset), offset2.back(), 1e-6)); @@ -233,12 +238,14 @@ TEST( Point2, circleCircleIntersection) { } /* ************************************************************************* */ +#ifndef GTSAM_TYPEDEF_POINTS_TO_VECTORS TEST( Point2, stream) { Point2 p(1, 2); std::ostringstream os; os << p; EXPECT(os.str() == "(1, 2)"); } +#endif /* ************************************************************************* */ int main () { diff --git a/gtsam/geometry/tests/testPoint3.cpp b/gtsam/geometry/tests/testPoint3.cpp index 9b6e53323..e2396f7e9 100644 --- a/gtsam/geometry/tests/testPoint3.cpp +++ b/gtsam/geometry/tests/testPoint3.cpp @@ -26,6 +26,11 @@ GTSAM_CONCEPT_LIE_INST(Point3) static Point3 P(0.2, 0.7, -2); +//****************************************************************************** +TEST(Point3 , Constructor) { + Point3 p; +} + //****************************************************************************** TEST(Point3 , Concept) { BOOST_CONCEPT_ASSERT((IsGroup)); @@ -149,12 +154,12 @@ TEST( Point3, cross2) { } /* ************************************************************************* */ -#ifndef GTSAM_USE_VECTOR3_POINTS +#ifndef GTSAM_TYPEDEF_POINTS_TO_VECTORS TEST( Point3, stream) { Point3 p(1, 2, -3); std::ostringstream os; os << p; - EXPECT(os.str() == "[1, 2, -3]';"); + EXPECT(os.str() == "[1, 2, -3]'"); } #endif @@ -178,20 +183,20 @@ TEST (Point3, norm) { Matrix actualH; Point3 point(3,4,5); // arbitrary point double expected = sqrt(50); - EXPECT_DOUBLES_EQUAL(expected, norm(point, actualH), 1e-8); + EXPECT_DOUBLES_EQUAL(expected, norm3(point, actualH), 1e-8); Matrix expectedH = numericalDerivative11(norm_proxy, point); EXPECT(assert_equal(expectedH, actualH, 1e-8)); } /* ************************************************************************* */ double testFunc(const Point3& P, const Point3& Q) { - return distance(P,Q); + return distance3(P, Q); } TEST (Point3, distance) { Point3 P(1., 12.8, -32.), Q(52.7, 4.9, -13.3); Matrix H1, H2; - double d = distance(P, Q, H1, H2); + double d = distance3(P, Q, H1, H2); double expectedDistance = 55.542686; Matrix numH1 = numericalDerivative21(testFunc, P, Q); Matrix numH2 = numericalDerivative22(testFunc, P, Q); diff --git a/gtsam/geometry/tests/testPose2.cpp b/gtsam/geometry/tests/testPose2.cpp index bccfdc1c7..10fd431bc 100644 --- a/gtsam/geometry/tests/testPose2.cpp +++ b/gtsam/geometry/tests/testPose2.cpp @@ -43,7 +43,7 @@ TEST(Pose2 , Concept) { /* ************************************************************************* */ TEST(Pose2, constructors) { - Point2 p; + Point2 p(0,0); Pose2 pose(0,p); Pose2 origin; assert_equal(pose,origin); @@ -371,7 +371,7 @@ TEST(Pose2, compose_c) /* ************************************************************************* */ TEST(Pose2, inverse ) { - Point2 origin, t(1,2); + Point2 origin(0,0), t(1,2); Pose2 gTl(M_PI/2.0, t); // robot at (1,2) looking towards y Pose2 identity, lTg = gTl.inverse(); @@ -409,7 +409,7 @@ namespace { /* ************************************************************************* */ TEST( Pose2, matrix ) { - Point2 origin, t(1,2); + Point2 origin(0,0), t(1,2); Pose2 gTl(M_PI/2.0, t); // robot at (1,2) looking towards y Matrix gMl = matrix(gTl); EXPECT(assert_equal((Matrix(3,3) << @@ -743,7 +743,7 @@ namespace { /* ************************************************************************* */ struct Triangle { size_t i_,j_,k_;}; - boost::optional align(const vector& ps, const vector& qs, + boost::optional align2(const vector& ps, const vector& qs, const pair& trianglePair) { const Triangle& t1 = trianglePair.first, t2 = trianglePair.second; vector correspondences; @@ -762,7 +762,7 @@ TEST(Pose2, align_4) { Triangle t1; t1.i_=0; t1.j_=1; t1.k_=2; Triangle t2; t2.i_=1; t2.j_=2; t2.k_=0; - boost::optional actual = align(ps, qs, make_pair(t1,t2)); + boost::optional actual = align2(ps, qs, make_pair(t1,t2)); EXPECT(assert_equal(expected, *actual)); } diff --git a/gtsam/geometry/tests/testRot3.cpp b/gtsam/geometry/tests/testRot3.cpp index 5e72d4c5b..6f0af3828 100644 --- a/gtsam/geometry/tests/testRot3.cpp +++ b/gtsam/geometry/tests/testRot3.cpp @@ -231,9 +231,9 @@ TEST(Rot3, retract_localCoordinates) /* ************************************************************************* */ TEST(Rot3, expmap_logmap) { - Vector3 d12 = Vector3::Constant(0.1); + Vector d12 = Vector3::Constant(0.1); Rot3 R2 = R.expmap(d12); - EXPECT(assert_equal(d12, (Vector) R.logmap(R2))); + EXPECT(assert_equal(d12, R.logmap(R2))); } /* ************************************************************************* */ diff --git a/gtsam/geometry/tests/testSimpleCamera.cpp b/gtsam/geometry/tests/testSimpleCamera.cpp index 70b3069f2..edf122d3c 100644 --- a/gtsam/geometry/tests/testSimpleCamera.cpp +++ b/gtsam/geometry/tests/testSimpleCamera.cpp @@ -104,12 +104,12 @@ TEST( SimpleCamera, backproject2) Rot3 rot(1., 0., 0., 0., 0., 1., 0., -1., 0.); // a camera looking down SimpleCamera camera(Pose3(rot, origin), K); - Point3 actual = camera.backproject(Point2(), 1.); + Point3 actual = camera.backproject(Point2(0,0), 1.); Point3 expected(0., 1., 0.); pair x = camera.projectSafe(expected); CHECK(assert_equal(expected, actual)); - CHECK(assert_equal(Point2(), x.first)); + CHECK(assert_equal(Point2(0,0), x.first)); CHECK(x.second); } diff --git a/gtsam/geometry/tests/testTriangulation.cpp b/gtsam/geometry/tests/testTriangulation.cpp index c3df95abc..86b7734f7 100644 --- a/gtsam/geometry/tests/testTriangulation.cpp +++ b/gtsam/geometry/tests/testTriangulation.cpp @@ -273,7 +273,7 @@ TEST( triangulation, onePose) { vector measurements; poses += Pose3(); - measurements += Point2(); + measurements += Point2(0,0); CHECK_EXCEPTION(triangulatePoint3(poses, sharedCal, measurements), TriangulationUnderconstrainedException); @@ -282,7 +282,7 @@ TEST( triangulation, onePose) { //****************************************************************************** TEST( triangulation, StereotriangulateNonlinear ) { - Cal3_S2Stereo::shared_ptr stereoK(new Cal3_S2Stereo(1733.75, 1733.75, 0, 689.645, 508.835, 0.0699612)); + auto stereoK = boost::make_shared(1733.75, 1733.75, 0, 689.645, 508.835, 0.0699612); // two camera poses m1, m2 Matrix4 m1, m2; diff --git a/gtsam/geometry/triangulation.h b/gtsam/geometry/triangulation.h index 369c54bea..880c23fd1 100644 --- a/gtsam/geometry/triangulation.h +++ b/gtsam/geometry/triangulation.h @@ -112,7 +112,8 @@ std::pair triangulationGraph( Values values; values.insert(landmarkKey, initialEstimate); // Initial landmark value NonlinearFactorGraph graph; - static SharedNoiseModel unit(noiseModel::Unit::Create(CAMERA::Measurement::dimension)); + static SharedNoiseModel unit(noiseModel::Unit::Create( + traits::dimension)); for (size_t i = 0; i < measurements.size(); i++) { const CAMERA& camera_i = cameras[i]; graph.push_back(TriangulationFactor // @@ -457,7 +458,7 @@ TriangulationResult triangulateSafe(const std::vector& cameras, for(const CAMERA& camera: cameras) { const Pose3& pose = camera.pose(); if (params.landmarkDistanceThreshold > 0 - && distance(pose.translation(), point) + && distance3(pose.translation(), point) > params.landmarkDistanceThreshold) return TriangulationResult::Degenerate(); #ifdef GTSAM_THROW_CHEIRALITY_EXCEPTION @@ -471,7 +472,7 @@ TriangulationResult triangulateSafe(const std::vector& cameras, if (params.dynamicOutlierRejectionThreshold > 0) { const Point2& zi = measured.at(i); Point2 reprojectionError(camera.project(point) - zi); - totalReprojError += reprojectionError.vector().norm(); + totalReprojError += reprojectionError.norm(); } i += 1; } diff --git a/gtsam/inference/BayesTree.h b/gtsam/inference/BayesTree.h index 4d68acb5b..c22a5e257 100644 --- a/gtsam/inference/BayesTree.h +++ b/gtsam/inference/BayesTree.h @@ -30,7 +30,7 @@ namespace gtsam { // Forward declarations template class FactorGraph; - template class ClusterTree; + template class EliminatableClusterTree; /* ************************************************************************* */ /** clique statistics */ @@ -247,7 +247,7 @@ namespace gtsam { void fillNodesIndex(const sharedClique& subtree); // Friend JunctionTree because it directly fills roots and nodes index. - template friend class ClusterTree; + template friend class EliminatableClusterTree; private: /** Serialization function */ diff --git a/gtsam/inference/ClusterTree-inst.h b/gtsam/inference/ClusterTree-inst.h index bd886273a..b042c0c8e 100644 --- a/gtsam/inference/ClusterTree-inst.h +++ b/gtsam/inference/ClusterTree-inst.h @@ -1,5 +1,5 @@ /** - * @file ClusterTree-inst.h + * @file EliminatableClusterTree-inst.h * @date Oct 8, 2013 * @author Kai Ni * @author Richard Roberts @@ -7,16 +7,102 @@ * @brief Collects factorgraph fragments defined on variable clusters, arranged in a tree */ +#pragma once + #include #include #include #include #include -#include - namespace gtsam { +/* ************************************************************************* */ +template +void ClusterTree::Cluster::print(const std::string& s, + const KeyFormatter& keyFormatter) const { + std::cout << s << " (" << problemSize_ << ")"; + PrintKeyVector(orderedFrontalKeys); +} + +/* ************************************************************************* */ +template +std::vector ClusterTree::Cluster::nrFrontalsOfChildren() const { + std::vector nrFrontals; + nrFrontals.reserve(nrChildren()); + for (const sharedNode& child : children) + nrFrontals.push_back(child->nrFrontals()); + return nrFrontals; +} + +/* ************************************************************************* */ +template +void ClusterTree::Cluster::merge(const boost::shared_ptr& cluster) { + // Merge keys. For efficiency, we add keys in reverse order at end, calling reverse after.. + orderedFrontalKeys.insert(orderedFrontalKeys.end(), cluster->orderedFrontalKeys.rbegin(), + cluster->orderedFrontalKeys.rend()); + factors.push_back(cluster->factors); + children.insert(children.end(), cluster->children.begin(), cluster->children.end()); + // Increment problem size + problemSize_ = std::max(problemSize_, cluster->problemSize_); +} + +/* ************************************************************************* */ +template +void ClusterTree::Cluster::mergeChildren( + const std::vector& merge) { + gttic(Cluster_mergeChildren); + assert(merge.size() == this->children.size()); + + // Count how many keys, factors and children we'll end up with + size_t nrKeys = orderedFrontalKeys.size(); + size_t nrFactors = factors.size(); + size_t nrNewChildren = 0; + // Loop over children + size_t i = 0; + for(const sharedNode& child: this->children) { + if (merge[i]) { + nrKeys += child->orderedFrontalKeys.size(); + nrFactors += child->factors.size(); + nrNewChildren += child->nrChildren(); + } else { + nrNewChildren += 1; // we keep the child + } + ++i; + } + + // now reserve space, and really merge + auto oldChildren = this->children; + this->children.clear(); + this->children.reserve(nrNewChildren); + orderedFrontalKeys.reserve(nrKeys); + factors.reserve(nrFactors); + i = 0; + for (const sharedNode& child : oldChildren) { + if (merge[i]) { + this->merge(child); + } else { + this->addChild(child); // we keep the child + } + ++i; + } + std::reverse(orderedFrontalKeys.begin(), orderedFrontalKeys.end()); +} + +/* ************************************************************************* */ +template +void ClusterTree::print(const std::string& s, const KeyFormatter& keyFormatter) const { + treeTraversal::PrintForest(*this, s, keyFormatter); +} + +/* ************************************************************************* */ +template +ClusterTree& ClusterTree::operator=(const This& other) { + // Start by duplicating the tree. + roots_ = treeTraversal::CloneForest(other); + return *this; +} + /* ************************************************************************* */ // Elimination traversal data - stores a pointer to the parent data and collects // the factors resulting from elimination of the children. Also sets up BayesTree @@ -34,6 +120,7 @@ struct EliminationData { size_t myIndexInParent; FastVector childFactors; boost::shared_ptr bayesTreeNode; + EliminationData(EliminationData* _parentData, size_t nChildren) : parentData(_parentData), bayesTreeNode(boost::make_shared()) { if (parentData) { @@ -55,7 +142,7 @@ struct EliminationData { const typename CLUSTERTREE::sharedNode& node, EliminationData& parentData) { assert(node); - EliminationData myData(&parentData, node->children.size()); + EliminationData myData(&parentData, node->nrChildren()); myData.bayesTreeNode->problemSize_ = node->problemSize(); return myData; } @@ -75,120 +162,51 @@ struct EliminationData { } // Function that does the HEAVY lifting - void operator()(const typename CLUSTERTREE::sharedNode& node, - EliminationData& myData) { + void operator()(const typename CLUSTERTREE::sharedNode& node, EliminationData& myData) { assert(node); // Gather factors FactorGraphType gatheredFactors; - gatheredFactors.reserve(node->factors.size() + node->children.size()); + gatheredFactors.reserve(node->factors.size() + node->nrChildren()); gatheredFactors += node->factors; gatheredFactors += myData.childFactors; // Check for Bayes tree orphan subtrees, and add them to our children - for(const sharedFactor& f: node->factors) { - if (const BayesTreeOrphanWrapper* asSubtree = - dynamic_cast*>(f.get())) { + // TODO(frank): should this really happen here? + for (const sharedFactor& factor: node->factors) { + auto asSubtree = dynamic_cast*>(factor.get()); + if (asSubtree) { myData.bayesTreeNode->children.push_back(asSubtree->clique); asSubtree->clique->parent_ = myData.bayesTreeNode; } } // >>>>>>>>>>>>>> Do dense elimination step >>>>>>>>>>>>>>>>>>>>>>>>>>>>> - std::pair, - boost::shared_ptr > eliminationResult = - eliminationFunction_(gatheredFactors, node->orderedFrontalKeys); + auto eliminationResult = eliminationFunction_(gatheredFactors, node->orderedFrontalKeys); // <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - // Store conditional in BayesTree clique, and in the case of ISAM2Clique also store the remaining factor + // Store conditional in BayesTree clique, and in the case of ISAM2Clique also store the + // remaining factor myData.bayesTreeNode->setEliminationResult(eliminationResult); // Fill nodes index - we do this here instead of calling insertRoot at the end to avoid // putting orphan subtrees in the index - they'll already be in the index of the ISAM2 // object they're added to. - for(const Key& j: myData.bayesTreeNode->conditional()->frontals()) + for (const Key& j: myData.bayesTreeNode->conditional()->frontals()) nodesIndex_.insert(std::make_pair(j, myData.bayesTreeNode)); // Store remaining factor in parent's gathered factors if (!eliminationResult.second->empty()) - myData.parentData->childFactors[myData.myIndexInParent] = - eliminationResult.second; + myData.parentData->childFactors[myData.myIndexInParent] = eliminationResult.second; } }; }; /* ************************************************************************* */ template -void ClusterTree::Cluster::print(const std::string& s, - const KeyFormatter& keyFormatter) const { - std::cout << s << " (" << problemSize_ << ")"; - PrintKeyVector(orderedFrontalKeys); -} - -/* ************************************************************************* */ -template -void ClusterTree::Cluster::mergeChildren( - const std::vector& merge) { - gttic(Cluster_mergeChildren); - - // Count how many keys, factors and children we'll end up with - size_t nrKeys = orderedFrontalKeys.size(); - size_t nrFactors = factors.size(); - size_t nrNewChildren = 0; - // Loop over children - size_t i = 0; - for(const sharedNode& child: children) { - if (merge[i]) { - nrKeys += child->orderedFrontalKeys.size(); - nrFactors += child->factors.size(); - nrNewChildren += child->children.size(); - } else { - nrNewChildren += 1; // we keep the child - } - ++i; - } - - // now reserve space, and really merge - orderedFrontalKeys.reserve(nrKeys); - factors.reserve(nrFactors); - typename Node::Children newChildren; - newChildren.reserve(nrNewChildren); - i = 0; - for(const sharedNode& child: children) { - if (merge[i]) { - // Merge keys. For efficiency, we add keys in reverse order at end, calling reverse after.. - orderedFrontalKeys.insert(orderedFrontalKeys.end(), - child->orderedFrontalKeys.rbegin(), child->orderedFrontalKeys.rend()); - // Merge keys, factors, and children. - factors.insert(factors.end(), child->factors.begin(), - child->factors.end()); - newChildren.insert(newChildren.end(), child->children.begin(), - child->children.end()); - // Increment problem size - problemSize_ = std::max(problemSize_, child->problemSize_); - // Increment number of frontal variables - } else { - newChildren.push_back(child); // we keep the child - } - ++i; - } - children = newChildren; - std::reverse(orderedFrontalKeys.begin(), orderedFrontalKeys.end()); -} - -/* ************************************************************************* */ -template -void ClusterTree::print(const std::string& s, - const KeyFormatter& keyFormatter) const { - treeTraversal::PrintForest(*this, s, keyFormatter); -} - -/* ************************************************************************* */ -template -ClusterTree& ClusterTree::operator=( +EliminatableClusterTree& EliminatableClusterTree::operator=( const This& other) { - // Start by duplicating the tree. - roots_ = treeTraversal::CloneForest(other); + ClusterTree::operator=(other); // Assign the remaining factors - these are pointers to factors in the original factor graph and // we do not clone them. @@ -198,41 +216,40 @@ ClusterTree& ClusterTree::operator=( } /* ************************************************************************* */ -template -std::pair, boost::shared_ptr > ClusterTree< - BAYESTREE, GRAPH>::eliminate(const Eliminate& function) const { +template +std::pair, boost::shared_ptr > +EliminatableClusterTree::eliminate(const Eliminate& function) const { gttic(ClusterTree_eliminate); // Do elimination (depth-first traversal). The rootsContainer stores a 'dummy' BayesTree node // that contains all of the roots as its children. rootsContainer also stores the remaining - // uneliminated factors passed up from the roots. + // un-eliminated factors passed up from the roots. boost::shared_ptr result = boost::make_shared(); + typedef EliminationData Data; - Data rootsContainer(0, roots_.size()); - typename Data::EliminationPostOrderVisitor visitorPost(function, - result->nodes_); + Data rootsContainer(0, this->nrRoots()); + + typename Data::EliminationPostOrderVisitor visitorPost(function, result->nodes_); { - TbbOpenMPMixedScope threadLimiter; // Limits OpenMP threads since we're mixing TBB and OpenMP - treeTraversal::DepthFirstForestParallel(*this, rootsContainer, - Data::EliminationPreOrderVisitor, visitorPost, 10); + TbbOpenMPMixedScope threadLimiter; // Limits OpenMP threads since we're mixing TBB and OpenMP + treeTraversal::DepthFirstForestParallel(*this, rootsContainer, Data::EliminationPreOrderVisitor, + visitorPost, 10); } // Create BayesTree from roots stored in the dummy BayesTree node. - result->roots_.insert(result->roots_.end(), - rootsContainer.bayesTreeNode->children.begin(), - rootsContainer.bayesTreeNode->children.end()); + result->roots_.insert(result->roots_.end(), rootsContainer.bayesTreeNode->children.begin(), + rootsContainer.bayesTreeNode->children.end()); // Add remaining factors that were not involved with eliminated variables - boost::shared_ptr remaining = boost::make_shared< - FactorGraphType>(); - remaining->reserve( - remainingFactors_.size() + rootsContainer.childFactors.size()); + boost::shared_ptr remaining = boost::make_shared(); + remaining->reserve(remainingFactors_.size() + rootsContainer.childFactors.size()); remaining->push_back(remainingFactors_.begin(), remainingFactors_.end()); - for(const sharedFactor& factor: rootsContainer.childFactors) { + for (const sharedFactor& factor : rootsContainer.childFactors) { if (factor) remaining->push_back(factor); } + // Return result return std::make_pair(result, remaining); } -} +} // namespace gtsam diff --git a/gtsam/inference/ClusterTree.h b/gtsam/inference/ClusterTree.h index b00532d22..e225bac5f 100644 --- a/gtsam/inference/ClusterTree.h +++ b/gtsam/inference/ClusterTree.h @@ -1,5 +1,5 @@ /** - * @file ClusterTree.h + * @file EliminatableClusterTree.h * @date Oct 8, 2013 * @author Kai Ni * @author Richard Roberts @@ -21,57 +21,182 @@ namespace gtsam { * each factor \f$ f_i \f$ is associated with a single cluster and \f$ scope(f_i) \sub C_k \f$. * \nosubgrouping */ -template +template class ClusterTree { -public: - typedef GRAPH FactorGraphType; ///< The factor graph type - typedef typename GRAPH::FactorType FactorType; ///< The type of factors - typedef ClusterTree This; ///< This class - typedef boost::shared_ptr shared_ptr; ///< Shared pointer to this class - typedef boost::shared_ptr sharedFactor; ///< Shared pointer to a factor - typedef BAYESTREE BayesTreeType; ///< The BayesTree type produced by elimination - typedef typename BayesTreeType::ConditionalType ConditionalType; ///< The type of conditionals - typedef boost::shared_ptr sharedConditional; ///< Shared pointer to a conditional - typedef typename FactorGraphType::Eliminate Eliminate; ///< Typedef for an eliminate subroutine + public: + typedef GRAPH FactorGraphType; ///< The factor graph type + typedef ClusterTree This; ///< This class + typedef boost::shared_ptr shared_ptr; ///< Shared pointer to this class + typedef typename GRAPH::FactorType FactorType; ///< The type of factors + typedef boost::shared_ptr sharedFactor; ///< Shared pointer to a factor + + /// A Cluster is just a collection of factors + // TODO(frank): re-factor JunctionTree so we can make members private struct Cluster { - typedef Ordering Keys; - typedef FastVector Factors; typedef FastVector > Children; + Children children; ///< sub-trees - Cluster() { - } - Cluster(Key key, const Factors& factors) : - factors(factors) { - orderedFrontalKeys.push_back(key); - } + typedef Ordering Keys; + Keys orderedFrontalKeys; ///< Frontal keys of this node + + FactorGraphType factors; ///< Factors associated with this node - Keys orderedFrontalKeys; ///< Frontal keys of this node - Factors factors; ///< Factors associated with this node - Children children; ///< sub-trees int problemSize_; + Cluster() : problemSize_(0) {} + + virtual ~Cluster() {} + + const Cluster& operator[](size_t i) const { + return *(children[i]); + } + + /// Construct from factors associated with a single key + template + Cluster(Key key, const CONTAINER& factorsToAdd) + : problemSize_(0) { + addFactors(key, factorsToAdd); + } + + /// Add factors associated with a single key + template + void addFactors(Key key, const CONTAINER& factorsToAdd) { + orderedFrontalKeys.push_back(key); + factors.push_back(factorsToAdd); + problemSize_ += factors.size(); + } + + /// Add a child cluster + void addChild(const boost::shared_ptr& cluster) { + children.push_back(cluster); + problemSize_ = std::max(problemSize_, cluster->problemSize_); + } + + size_t nrChildren() const { + return children.size(); + } + + size_t nrFactors() const { + return factors.size(); + } + + size_t nrFrontals() const { + return orderedFrontalKeys.size(); + } + int problemSize() const { return problemSize_; } /// print this node - void print(const std::string& s = "", const KeyFormatter& keyFormatter = - DefaultKeyFormatter) const; + virtual void print(const std::string& s = "", + const KeyFormatter& keyFormatter = DefaultKeyFormatter) const; + + /// Return a vector with nrFrontal keys for each child + std::vector nrFrontalsOfChildren() const; + + /// Merge in given cluster + void merge(const boost::shared_ptr& cluster); /// Merge all children for which bit is set into this node void mergeChildren(const std::vector& merge); }; - typedef boost::shared_ptr sharedCluster; ///< Shared pointer to Cluster - typedef Cluster Node; ///< Define Node=Cluster for compatibility with tree traversal functions - typedef sharedCluster sharedNode; ///< Define Node=Cluster for compatibility with tree traversal functions + typedef boost::shared_ptr sharedCluster; ///< Shared pointer to Cluster + + // Define Node=Cluster for compatibility with tree traversal functions + typedef Cluster Node; + typedef sharedCluster sharedNode; /** concept check */ GTSAM_CONCEPT_TESTABLE_TYPE(FactorType); -protected: + protected: FastVector roots_; + + /// @name Standard Constructors + /// @{ + + /** Copy constructor - makes a deep copy of the tree structure, but only pointers to factors are + * copied, factors are not cloned. */ + ClusterTree(const This& other) { + *this = other; + } + + /// @} + + public: + + /// Default constructor + ClusterTree() {} + + /// @name Testable + /// @{ + + /** Print the cluster tree */ + void print(const std::string& s = "", + const KeyFormatter& keyFormatter = DefaultKeyFormatter) const; + + /// @} + + /// @name Advanced Interface + /// @{ + + void addRoot(const boost::shared_ptr& cluster) { + roots_.push_back(cluster); + } + + void addChildrenAsRoots(const boost::shared_ptr& cluster) { + for (auto child : cluster->children) + this->addRoot(child); + } + + size_t nrRoots() const { + return roots_.size(); + } + + /** Return the set of roots (one for a tree, multiple for a forest) */ + const FastVector& roots() const { + return roots_; + } + + const Cluster& operator[](size_t i) const { + return *(roots_[i]); + } + + /// @} + + protected: + /// @name Details + + /// Assignment operator - makes a deep copy of the tree structure, but only pointers to factors + /// are copied, factors are not cloned. + This& operator=(const This& other); + + /// @} +}; + +/** + * A cluster-tree that eliminates to a Bayes tree. + */ +template +class EliminatableClusterTree : public ClusterTree { + public: + typedef BAYESTREE BayesTreeType; ///< The BayesTree type produced by elimination + typedef GRAPH FactorGraphType; ///< The factor graph type + typedef EliminatableClusterTree This; ///< This class + typedef boost::shared_ptr shared_ptr; ///< Shared pointer to this class + + typedef typename BAYESTREE::ConditionalType ConditionalType; ///< The type of conditionals + typedef boost::shared_ptr + sharedConditional; ///< Shared pointer to a conditional + + typedef typename GRAPH::Eliminate Eliminate; ///< Typedef for an eliminate subroutine + typedef typename GRAPH::FactorType FactorType; ///< The type of factors + typedef boost::shared_ptr sharedFactor; ///< Shared pointer to a factor + + protected: FastVector remainingFactors_; /// @name Standard Constructors @@ -79,19 +204,13 @@ protected: /** Copy constructor - makes a deep copy of the tree structure, but only pointers to factors are * copied, factors are not cloned. */ - ClusterTree(const This& other) {*this = other;} - - /// @} - -public: - /// @name Testable - /// @{ - - /** Print the cluster tree */ - void print(const std::string& s = "", const KeyFormatter& keyFormatter = DefaultKeyFormatter) const; + EliminatableClusterTree(const This& other) : ClusterTree(other) { + *this = other; + } /// @} + public: /// @name Standard Interface /// @{ @@ -100,23 +219,22 @@ public: * in GaussianFactorGraph.h * @return The Bayes tree and factor graph resulting from elimination */ - std::pair, boost::shared_ptr > - eliminate(const Eliminate& function) const; + std::pair, boost::shared_ptr > eliminate( + const Eliminate& function) const; /// @} /// @name Advanced Interface /// @{ - /** Return the set of roots (one for a tree, multiple for a forest) */ - const FastVector& roots() const {return roots_;} - /** Return the remaining factors that are not pulled into elimination */ - const FastVector& remainingFactors() const {return remainingFactors_;} + const FastVector& remainingFactors() const { + return remainingFactors_; + } /// @} -protected: + protected: /// @name Details /// Assignment operator - makes a deep copy of the tree structure, but only pointers to factors @@ -124,11 +242,10 @@ protected: This& operator=(const This& other); /// Default constructor to be used in derived classes - ClusterTree() {} + EliminatableClusterTree() {} /// @} - }; - } +#include diff --git a/gtsam/inference/FactorGraph.h b/gtsam/inference/FactorGraph.h index fcafc9b42..38f30f5a3 100644 --- a/gtsam/inference/FactorGraph.h +++ b/gtsam/inference/FactorGraph.h @@ -354,3 +354,5 @@ namespace gtsam { }; // FactorGraph } // namespace gtsam + +#include \ No newline at end of file diff --git a/gtsam/inference/JunctionTree-inst.h b/gtsam/inference/JunctionTree-inst.h index 8fcdd1eac..04472f7e3 100644 --- a/gtsam/inference/JunctionTree-inst.h +++ b/gtsam/inference/JunctionTree-inst.h @@ -54,7 +54,7 @@ struct ConstructorTraversalData { // pointer in its parent. ConstructorTraversalData myData = ConstructorTraversalData(&parentData); myData.myJTNode = boost::make_shared(node->key, node->factors); - parentData.myJTNode->children.push_back(myData.myJTNode); + parentData.myJTNode->addChild(myData.myJTNode); return myData; } @@ -99,20 +99,20 @@ struct ConstructorTraversalData { // Merge our children if they are in our clique - if our conditional has // exactly one fewer parent than our child's conditional. const size_t myNrParents = myConditional->nrParents(); - const size_t nrChildren = node->children.size(); + const size_t nrChildren = node->nrChildren(); assert(childConditionals.size() == nrChildren); // decide which children to merge, as index into children + std::vector nrFrontals = node->nrFrontalsOfChildren(); std::vector merge(nrChildren, false); - size_t myNrFrontals = 1, i = 0; - for(const sharedNode& child: node->children) { + size_t myNrFrontals = 1; + for (size_t i = 0;inrParents()) { // Increment number of frontal variables - myNrFrontals += child->orderedFrontalKeys.size(); + myNrFrontals += nrFrontals[i]; merge[i] = true; } - ++i; } // now really merge @@ -145,10 +145,7 @@ JunctionTree::JunctionTree( Data::ConstructorTraversalVisitorPostAlg2); // Assign roots from the dummy node - typedef typename JunctionTree::Node Node; - const typename Node::Children& children = rootData.myJTNode->children; - Base::roots_.reserve(children.size()); - Base::roots_.insert(Base::roots_.begin(), children.begin(), children.end()); + this->addChildrenAsRoots(rootData.myJTNode); // Transfer remaining factors from elimination tree Base::remainingFactors_ = eliminationTree.remainingFactors(); diff --git a/gtsam/inference/JunctionTree.h b/gtsam/inference/JunctionTree.h index cdf38b97c..e01f3721a 100644 --- a/gtsam/inference/JunctionTree.h +++ b/gtsam/inference/JunctionTree.h @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- - * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) @@ -28,15 +28,13 @@ namespace gtsam { template class EliminationTree; /** - * A JunctionTree is a ClusterTree, i.e., a set of variable clusters with factors, arranged - * in a tree, with the additional property that it represents the clique tree associated - * with a Bayes net. + * A JunctionTree is a cluster tree, a set of variable clusters with factors, arranged in a tree, + * with the additional property that it represents the clique tree associated with a Bayes Net. * - * In GTSAM a junction tree is an intermediate data structure in multifrontal - * variable elimination. Each node is a cluster of factors, along with a - * clique of variables that are eliminated all at once. In detail, every node k represents - * a clique (maximal fully connected subset) of an associated chordal graph, such as a - * chordal Bayes net resulting from elimination. + * In GTSAM a junction tree is an intermediate data structure in multifrontal variable + * elimination. Each node is a cluster of factors, along with a clique of variables that are + * eliminated all at once. In detail, every node k represents a clique (maximal fully connected + * subset) of an associated chordal graph, such as a chordal Bayes net resulting from elimination. * * The difference with the BayesTree is that a JunctionTree stores factors, whereas a * BayesTree stores conditionals, that are the product of eliminating the factors in the @@ -49,13 +47,13 @@ namespace gtsam { * \nosubgrouping */ template - class JunctionTree : public ClusterTree { + class JunctionTree : public EliminatableClusterTree { public: typedef JunctionTree This; ///< This class typedef boost::shared_ptr shared_ptr; ///< Shared pointer to this class - typedef ClusterTree Base; ///< Our base class + typedef EliminatableClusterTree Base; ///< Our base class protected: @@ -65,7 +63,7 @@ namespace gtsam { /** Build the junction tree from an elimination tree. */ template static This FromEliminationTree(const ETREE& eliminationTree) { return This(eliminationTree); } - + /** Build the junction tree from an elimination tree. */ template JunctionTree(const EliminationTree& eliminationTree); diff --git a/gtsam/inference/Ordering.cpp b/gtsam/inference/Ordering.cpp index 931610639..e12c32df3 100644 --- a/gtsam/inference/Ordering.cpp +++ b/gtsam/inference/Ordering.cpp @@ -72,7 +72,7 @@ Ordering Ordering::ColamdConstrained(const VariableIndex& variableIndex, for(size_t factorIndex: column) { A[count++] = (int) factorIndex; // copy sparse column } - p[index + 1] = count; // column j (base 1) goes from A[j-1] to A[j]-1 + p[index + 1] = count; // column j (base 1) goes from A[j-1] to A[j]-1 // Store key in array and increment index keys[index] = key_factors.first; ++index; @@ -123,6 +123,7 @@ Ordering Ordering::ColamdConstrainedLast(const VariableIndex& variableIndex, std::vector cmember(n, 0); // Build a mapping to look up sorted Key indices by Key + // TODO(frank): think of a way to not build this FastMap keyIndices; size_t j = 0; for (auto key_factors: variableIndex) diff --git a/gtsam/inference/Ordering.h b/gtsam/inference/Ordering.h index 8af2649c5..ae7a10f44 100644 --- a/gtsam/inference/Ordering.h +++ b/gtsam/inference/Ordering.h @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- - * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) @@ -79,7 +79,10 @@ public: /// it is faster to use COLAMD(const VariableIndex&) template static Ordering Colamd(const FactorGraph& graph) { - return Colamd(VariableIndex(graph)); + if (graph.empty()) + return Ordering(); + else + return Colamd(VariableIndex(graph)); } /// Compute a fill-reducing ordering using COLAMD from a VariableIndex. @@ -96,8 +99,10 @@ public: template static Ordering ColamdConstrainedLast(const FactorGraph& graph, const std::vector& constrainLast, bool forceOrder = false) { - return ColamdConstrainedLast(VariableIndex(graph), constrainLast, - forceOrder); + if (graph.empty()) + return Ordering(); + else + return ColamdConstrainedLast(VariableIndex(graph), constrainLast, forceOrder); } /// Compute a fill-reducing ordering using constrained COLAMD from a VariableIndex. This @@ -121,8 +126,10 @@ public: template static Ordering ColamdConstrainedFirst(const FactorGraph& graph, const std::vector& constrainFirst, bool forceOrder = false) { - return ColamdConstrainedFirst(VariableIndex(graph), constrainFirst, - forceOrder); + if (graph.empty()) + return Ordering(); + else + return ColamdConstrainedFirst(VariableIndex(graph), constrainFirst, forceOrder); } /// Compute a fill-reducing ordering using constrained COLAMD from a VariableIndex. This @@ -148,7 +155,10 @@ public: template static Ordering ColamdConstrained(const FactorGraph& graph, const FastMap& groups) { - return ColamdConstrained(VariableIndex(graph), groups); + if (graph.empty()) + return Ordering(); + else + return ColamdConstrained(VariableIndex(graph), groups); } /// Compute a fill-reducing ordering using constrained COLAMD from a VariableIndex. In this @@ -190,6 +200,8 @@ public: template static Ordering Create(OrderingType orderingType, const FactorGraph& graph) { + if (graph.empty()) + return Ordering(); switch (orderingType) { case COLAMD: diff --git a/gtsam/inference/Symbol.h b/gtsam/inference/Symbol.h index 102761273..2d7ede8e7 100644 --- a/gtsam/inference/Symbol.h +++ b/gtsam/inference/Symbol.h @@ -33,8 +33,8 @@ namespace gtsam { */ class GTSAM_EXPORT Symbol { protected: - const unsigned char c_; - const std::uint64_t j_; + unsigned char c_; + std::uint64_t j_; public: diff --git a/gtsam/inference/tests/testOrdering.cpp b/gtsam/inference/tests/testOrdering.cpp index 52528ad7f..0d23d9655 100644 --- a/gtsam/inference/tests/testOrdering.cpp +++ b/gtsam/inference/tests/testOrdering.cpp @@ -30,36 +30,64 @@ using namespace boost::assign; namespace example { SymbolicFactorGraph symbolicChain() { - SymbolicFactorGraph sfg; - sfg.push_factor(0, 1); - sfg.push_factor(1, 2); - sfg.push_factor(2, 3); - sfg.push_factor(3, 4); - sfg.push_factor(4, 5); - return sfg; + SymbolicFactorGraph symbolicGraph; + symbolicGraph.push_factor(0, 1); + symbolicGraph.push_factor(1, 2); + symbolicGraph.push_factor(2, 3); + symbolicGraph.push_factor(3, 4); + symbolicGraph.push_factor(4, 5); + return symbolicGraph; } } /* ************************************************************************* */ TEST(Ordering, constrained_ordering) { - // create graph with wanted variable set = 2, 4 - SymbolicFactorGraph sfg = example::symbolicChain(); + SymbolicFactorGraph symbolicGraph = example::symbolicChain(); // unconstrained version - Ordering actUnconstrained = Ordering::Colamd(sfg); - Ordering expUnconstrained = Ordering(list_of(0)(1)(2)(3)(4)(5)); - EXPECT(assert_equal(expUnconstrained, actUnconstrained)); + { + Ordering actual = Ordering::Colamd(symbolicGraph); + Ordering expected = Ordering(list_of(0)(1)(2)(3)(4)(5)); + EXPECT(assert_equal(expected, actual)); + } // constrained version - push one set to the end - Ordering actConstrained = Ordering::ColamdConstrainedLast(sfg, list_of(2)(4)); - Ordering expConstrained = Ordering(list_of(0)(1)(5)(3)(4)(2)); - EXPECT(assert_equal(expConstrained, actConstrained)); + { + Ordering actual = Ordering::ColamdConstrainedLast(symbolicGraph, list_of(2)(4)); + Ordering expected = Ordering(list_of(0)(1)(5)(3)(4)(2)); + EXPECT(assert_equal(expected, actual)); + } // constrained version - push one set to the start - Ordering actConstrained2 = Ordering::ColamdConstrainedFirst(sfg, - list_of(2)(4)); - Ordering expConstrained2 = Ordering(list_of(2)(4)(0)(1)(3)(5)); - EXPECT(assert_equal(expConstrained2, actConstrained2)); + { + Ordering actual = Ordering::ColamdConstrainedFirst(symbolicGraph, list_of(2)(4)); + Ordering expected = Ordering(list_of(2)(4)(0)(1)(3)(5)); + EXPECT(assert_equal(expected, actual)); + } + + // Make sure giving empty constraints does not break the code + { + Ordering actual = Ordering::ColamdConstrainedLast(symbolicGraph, {}); + Ordering expected = Ordering(list_of(0)(1)(2)(3)(4)(5)); + EXPECT(assert_equal(expected, actual)); + } + { + Ordering actual = Ordering::ColamdConstrainedFirst(symbolicGraph, {}); + Ordering expected = Ordering(list_of(0)(1)(2)(3)(4)(5)); + EXPECT(assert_equal(expected, actual)); + } + + // Make sure giving empty graph does not break the code + SymbolicFactorGraph emptyGraph; + Ordering empty; + { + Ordering actual = Ordering::ColamdConstrainedLast(emptyGraph, list_of(2)(4)); + EXPECT(assert_equal(empty, actual)); + } + { + Ordering actual = Ordering::ColamdConstrainedFirst(emptyGraph, list_of(2)(4)); + EXPECT(assert_equal(empty, actual)); + } } /* ************************************************************************* */ @@ -68,7 +96,7 @@ TEST(Ordering, grouped_constrained_ordering) { // create graph with constrained groups: // 1: 2, 4 // 2: 5 - SymbolicFactorGraph sfg = example::symbolicChain(); + SymbolicFactorGraph symbolicGraph = example::symbolicChain(); // constrained version - push one set to the end FastMap constraints; @@ -76,40 +104,40 @@ TEST(Ordering, grouped_constrained_ordering) { constraints[4] = 1; constraints[5] = 2; - Ordering actConstrained = Ordering::ColamdConstrained(sfg, constraints); - Ordering expConstrained = list_of(0)(1)(3)(2)(4)(5); - EXPECT(assert_equal(expConstrained, actConstrained)); + Ordering actual = Ordering::ColamdConstrained(symbolicGraph, constraints); + Ordering expected = list_of(0)(1)(3)(2)(4)(5); + EXPECT(assert_equal(expected, actual)); } /* ************************************************************************* */ TEST(Ordering, csr_format) { // Example in METIS manual - SymbolicFactorGraph sfg; - sfg.push_factor(0, 1); - sfg.push_factor(1, 2); - sfg.push_factor(2, 3); - sfg.push_factor(3, 4); - sfg.push_factor(5, 6); - sfg.push_factor(6, 7); - sfg.push_factor(7, 8); - sfg.push_factor(8, 9); - sfg.push_factor(10, 11); - sfg.push_factor(11, 12); - sfg.push_factor(12, 13); - sfg.push_factor(13, 14); + SymbolicFactorGraph symbolicGraph; + symbolicGraph.push_factor(0, 1); + symbolicGraph.push_factor(1, 2); + symbolicGraph.push_factor(2, 3); + symbolicGraph.push_factor(3, 4); + symbolicGraph.push_factor(5, 6); + symbolicGraph.push_factor(6, 7); + symbolicGraph.push_factor(7, 8); + symbolicGraph.push_factor(8, 9); + symbolicGraph.push_factor(10, 11); + symbolicGraph.push_factor(11, 12); + symbolicGraph.push_factor(12, 13); + symbolicGraph.push_factor(13, 14); - sfg.push_factor(0, 5); - sfg.push_factor(5, 10); - sfg.push_factor(1, 6); - sfg.push_factor(6, 11); - sfg.push_factor(2, 7); - sfg.push_factor(7, 12); - sfg.push_factor(3, 8); - sfg.push_factor(8, 13); - sfg.push_factor(4, 9); - sfg.push_factor(9, 14); + symbolicGraph.push_factor(0, 5); + symbolicGraph.push_factor(5, 10); + symbolicGraph.push_factor(1, 6); + symbolicGraph.push_factor(6, 11); + symbolicGraph.push_factor(2, 7); + symbolicGraph.push_factor(7, 12); + symbolicGraph.push_factor(3, 8); + symbolicGraph.push_factor(8, 13); + symbolicGraph.push_factor(4, 9); + symbolicGraph.push_factor(9, 14); - MetisIndex mi(sfg); + MetisIndex mi(symbolicGraph); vector xadjExpected, adjExpected; xadjExpected += 0, 2, 5, 8, 11, 13, 16, 20, 24, 28, 31, 33, 36, 39, 42, 44; @@ -122,16 +150,16 @@ TEST(Ordering, csr_format) { /* ************************************************************************* */ TEST(Ordering, csr_format_2) { - SymbolicFactorGraph sfg; + SymbolicFactorGraph symbolicGraph; - sfg.push_factor(0); - sfg.push_factor(0, 1); - sfg.push_factor(1, 2); - sfg.push_factor(2, 3); - sfg.push_factor(3, 4); - sfg.push_factor(4, 1); + symbolicGraph.push_factor(0); + symbolicGraph.push_factor(0, 1); + symbolicGraph.push_factor(1, 2); + symbolicGraph.push_factor(2, 3); + symbolicGraph.push_factor(3, 4); + symbolicGraph.push_factor(4, 1); - MetisIndex mi(sfg); + MetisIndex mi(symbolicGraph); vector xadjExpected, adjExpected; xadjExpected += 0, 1, 4, 6, 8, 10; @@ -144,16 +172,16 @@ TEST(Ordering, csr_format_2) { /* ************************************************************************* */ TEST(Ordering, csr_format_3) { - SymbolicFactorGraph sfg; + SymbolicFactorGraph symbolicGraph; - sfg.push_factor(100); - sfg.push_factor(100, 101); - sfg.push_factor(101, 102); - sfg.push_factor(102, 103); - sfg.push_factor(103, 104); - sfg.push_factor(104, 101); + symbolicGraph.push_factor(100); + symbolicGraph.push_factor(100, 101); + symbolicGraph.push_factor(101, 102); + symbolicGraph.push_factor(102, 103); + symbolicGraph.push_factor(103, 104); + symbolicGraph.push_factor(104, 101); - MetisIndex mi(sfg); + MetisIndex mi(symbolicGraph); vector xadjExpected, adjExpected; xadjExpected += 0, 1, 4, 6, 8, 10; @@ -174,16 +202,16 @@ TEST(Ordering, csr_format_3) { /* ************************************************************************* */ #ifdef GTSAM_SUPPORT_NESTED_DISSECTION TEST(Ordering, csr_format_4) { - SymbolicFactorGraph sfg; + SymbolicFactorGraph symbolicGraph; - sfg.push_factor(Symbol('x', 1)); - sfg.push_factor(Symbol('x', 1), Symbol('x', 2)); - sfg.push_factor(Symbol('x', 2), Symbol('x', 3)); - sfg.push_factor(Symbol('x', 3), Symbol('x', 4)); - sfg.push_factor(Symbol('x', 4), Symbol('x', 5)); - sfg.push_factor(Symbol('x', 5), Symbol('x', 6)); + symbolicGraph.push_factor(Symbol('x', 1)); + symbolicGraph.push_factor(Symbol('x', 1), Symbol('x', 2)); + symbolicGraph.push_factor(Symbol('x', 2), Symbol('x', 3)); + symbolicGraph.push_factor(Symbol('x', 3), Symbol('x', 4)); + symbolicGraph.push_factor(Symbol('x', 4), Symbol('x', 5)); + symbolicGraph.push_factor(Symbol('x', 5), Symbol('x', 6)); - MetisIndex mi(sfg); + MetisIndex mi(symbolicGraph); vector xadjExpected, adjExpected; xadjExpected += 0, 1, 3, 5, 7, 9, 10; @@ -196,29 +224,29 @@ TEST(Ordering, csr_format_4) { EXPECT(adjExpected.size() == mi.adj().size()); EXPECT(adjExpected == adjAcutal); - Ordering metOrder = Ordering::Metis(sfg); + Ordering metOrder = Ordering::Metis(symbolicGraph); // Test different symbol types - sfg.push_factor(Symbol('l', 1)); - sfg.push_factor(Symbol('x', 1), Symbol('l', 1)); - sfg.push_factor(Symbol('x', 2), Symbol('l', 1)); - sfg.push_factor(Symbol('x', 3), Symbol('l', 1)); - sfg.push_factor(Symbol('x', 4), Symbol('l', 1)); + symbolicGraph.push_factor(Symbol('l', 1)); + symbolicGraph.push_factor(Symbol('x', 1), Symbol('l', 1)); + symbolicGraph.push_factor(Symbol('x', 2), Symbol('l', 1)); + symbolicGraph.push_factor(Symbol('x', 3), Symbol('l', 1)); + symbolicGraph.push_factor(Symbol('x', 4), Symbol('l', 1)); - Ordering metOrder2 = Ordering::Metis(sfg); + Ordering metOrder2 = Ordering::Metis(symbolicGraph); } #endif /* ************************************************************************* */ #ifdef GTSAM_SUPPORT_NESTED_DISSECTION TEST(Ordering, metis) { - SymbolicFactorGraph sfg; + SymbolicFactorGraph symbolicGraph; - sfg.push_factor(0); - sfg.push_factor(0, 1); - sfg.push_factor(1, 2); + symbolicGraph.push_factor(0); + symbolicGraph.push_factor(0, 1); + symbolicGraph.push_factor(1, 2); - MetisIndex mi(sfg); + MetisIndex mi(symbolicGraph); vector xadjExpected, adjExpected; xadjExpected += 0, 1, 3, 4; @@ -228,7 +256,7 @@ TEST(Ordering, metis) { EXPECT(adjExpected.size() == mi.adj().size()); EXPECT(adjExpected == mi.adj()); - Ordering metis = Ordering::Metis(sfg); + Ordering metis = Ordering::Metis(symbolicGraph); } #endif /* ************************************************************************* */ @@ -236,15 +264,15 @@ TEST(Ordering, metis) { TEST(Ordering, MetisLoop) { // create linear graph - SymbolicFactorGraph sfg = example::symbolicChain(); + SymbolicFactorGraph symbolicGraph = example::symbolicChain(); // add loop closure - sfg.push_factor(0, 5); + symbolicGraph.push_factor(0, 5); // METIS #if !defined(__APPLE__) { - Ordering actual = Ordering::Create(Ordering::METIS, sfg); + Ordering actual = Ordering::Create(Ordering::METIS, symbolicGraph); // - P( 0 4 1) // | - P( 2 | 4 1) // | | - P( 3 | 4 2) @@ -254,7 +282,7 @@ TEST(Ordering, MetisLoop) { } #else { - Ordering actual = Ordering::Create(Ordering::METIS, sfg); + Ordering actual = Ordering::Create(Ordering::METIS, symbolicGraph); // - P( 1 0 3) // | - P( 4 | 0 3) // | | - P( 5 | 0 4) @@ -269,7 +297,7 @@ TEST(Ordering, MetisLoop) { TEST(Ordering, Create) { // create chain graph - SymbolicFactorGraph sfg = example::symbolicChain(); + SymbolicFactorGraph symbolicGraph = example::symbolicChain(); // COLAMD { @@ -278,7 +306,7 @@ TEST(Ordering, Create) { //| | - P( 2 | 3) //| | | - P( 1 | 2) //| | | | - P( 0 | 1) - Ordering actual = Ordering::Create(Ordering::COLAMD, sfg); + Ordering actual = Ordering::Create(Ordering::COLAMD, symbolicGraph); Ordering expected = Ordering(list_of(0)(1)(2)(3)(4)(5)); EXPECT(assert_equal(expected, actual)); } @@ -286,7 +314,7 @@ TEST(Ordering, Create) { #ifdef GTSAM_SUPPORT_NESTED_DISSECTION // METIS { - Ordering actual = Ordering::Create(Ordering::METIS, sfg); + Ordering actual = Ordering::Create(Ordering::METIS, symbolicGraph); //- P( 1 0 2) //| - P( 3 4 | 2) //| | - P( 5 | 4) @@ -296,7 +324,7 @@ TEST(Ordering, Create) { #endif // CUSTOM - CHECK_EXCEPTION(Ordering::Create(Ordering::CUSTOM, sfg), runtime_error); + CHECK_EXCEPTION(Ordering::Create(Ordering::CUSTOM, symbolicGraph), runtime_error); } /* ************************************************************************* */ diff --git a/gtsam/linear/BinaryJacobianFactor.h b/gtsam/linear/BinaryJacobianFactor.h index 23d11964c..462258762 100644 --- a/gtsam/linear/BinaryJacobianFactor.h +++ b/gtsam/linear/BinaryJacobianFactor.h @@ -73,12 +73,12 @@ struct BinaryJacobianFactor: JacobianFactor { Eigen::Block b(Ab, 0, N1 + N2); // We perform I += A'*A to the upper triangle - (*info)(slot1, slot1).selfadjointView().rankUpdate(A1.transpose()); - (*info)(slot1, slot2).knownOffDiagonal() += A1.transpose() * A2; - (*info)(slot1, slotB).knownOffDiagonal() += A1.transpose() * b; - (*info)(slot2, slot2).selfadjointView().rankUpdate(A2.transpose()); - (*info)(slot2, slotB).knownOffDiagonal() += A2.transpose() * b; - (*info)(slotB, slotB)(0, 0) += b.transpose() * b; + info->diagonalBlock(slot1).rankUpdate(A1.transpose()); + info->updateOffDiagonalBlock(slot1, slot2, A1.transpose() * A2); + info->updateOffDiagonalBlock(slot1, slotB, A1.transpose() * b); + info->diagonalBlock(slot2).rankUpdate(A2.transpose()); + info->updateOffDiagonalBlock(slot2, slotB, A2.transpose() * b); + info->updateDiagonalBlock(slotB, b.transpose() * b); } } }; diff --git a/gtsam/linear/GaussianFactorGraph.cpp b/gtsam/linear/GaussianFactorGraph.cpp index ff67b9cb1..a4df04cf9 100644 --- a/gtsam/linear/GaussianFactorGraph.cpp +++ b/gtsam/linear/GaussianFactorGraph.cpp @@ -48,7 +48,7 @@ namespace gtsam { /* ************************************************************************* */ GaussianFactorGraph::Keys GaussianFactorGraph::keys() const { KeySet keys; - for(const sharedFactor& factor: *this) + for (const sharedFactor& factor: *this) if (factor) keys.insert(factor->begin(), factor->end()); return keys; @@ -57,8 +57,8 @@ namespace gtsam { /* ************************************************************************* */ std::map GaussianFactorGraph::getKeyDimMap() const { map spec; - for ( const GaussianFactor::shared_ptr &gf: *this ) { - for ( GaussianFactor::const_iterator it = gf->begin() ; it != gf->end() ; it++ ) { + for (const GaussianFactor::shared_ptr& gf : *this) { + for (GaussianFactor::const_iterator it = gf->begin(); it != gf->end(); it++) { map::iterator it2 = spec.find(*it); if ( it2 == spec.end() ) { spec.insert(make_pair(*it, gf->getDim(it))); @@ -78,7 +78,7 @@ namespace gtsam { /* ************************************************************************* */ GaussianFactorGraph GaussianFactorGraph::clone() const { GaussianFactorGraph result; - for(const sharedFactor& f: *this) { + for (const sharedFactor& f : *this) { if (f) result.push_back(f->clone()); else @@ -90,9 +90,9 @@ namespace gtsam { /* ************************************************************************* */ GaussianFactorGraph GaussianFactorGraph::negate() const { GaussianFactorGraph result; - for(const sharedFactor& f: *this) { - if (f) - result.push_back(f->negate()); + for (const sharedFactor& factor: *this) { + if (factor) + result.push_back(factor->negate()); else result.push_back(sharedFactor()); // Passes on null factors so indices remain valid } @@ -104,8 +104,9 @@ namespace gtsam { // First find dimensions of each variable typedef std::map KeySizeMap; KeySizeMap dims; - for(const sharedFactor& factor: *this) { - if (!static_cast(factor)) continue; + for (const sharedFactor& factor : *this) { + if (!static_cast(factor)) + continue; for (GaussianFactor::const_iterator key = factor->begin(); key != factor->end(); ++key) { @@ -116,7 +117,7 @@ namespace gtsam { // Compute first scalar column of each variable size_t currentColIndex = 0; KeySizeMap columnIndices = dims; - for(const KeySizeMap::value_type& col: dims) { + for (const KeySizeMap::value_type& col : dims) { columnIndices[col.first] = currentColIndex; currentColIndex += dims[col.first]; } @@ -125,7 +126,7 @@ namespace gtsam { typedef boost::tuple triplet; vector entries; size_t row = 0; - for(const sharedFactor& factor: *this) { + for (const sharedFactor& factor : *this) { if (!static_cast(factor)) continue; // Convert to JacobianFactor if necessary @@ -209,25 +210,21 @@ namespace gtsam { // combine all factors and get upper-triangular part of Hessian Scatter scatter(*this, optionalOrdering); HessianFactor combined(*this, scatter); - Matrix result = combined.info(); - // Fill in lower-triangular part of Hessian - result.triangularView() = result.transpose(); - return result; + return combined.info().selfadjointView();; } /* ************************************************************************* */ pair GaussianFactorGraph::hessian( boost::optional optionalOrdering) const { Matrix augmented = augmentedHessian(optionalOrdering); - return make_pair( - augmented.topLeftCorner(augmented.rows() - 1, augmented.rows() - 1), - augmented.col(augmented.rows() - 1).head(augmented.rows() - 1)); + size_t n = augmented.rows() - 1; + return make_pair(augmented.topLeftCorner(n, n), augmented.topRightCorner(n, 1)); } /* ************************************************************************* */ VectorValues GaussianFactorGraph::hessianDiagonal() const { VectorValues d; - for(const sharedFactor& factor: *this) { + for (const sharedFactor& factor : *this) { if(factor){ VectorValues di = factor->hessianDiagonal(); d.addInPlace_(di); @@ -239,11 +236,11 @@ namespace gtsam { /* ************************************************************************* */ map GaussianFactorGraph::hessianBlockDiagonal() const { map blocks; - for(const sharedFactor& factor: *this) { + for (const sharedFactor& factor : *this) { if (!factor) continue; map BD = factor->hessianBlockDiagonal(); map::const_iterator it = BD.begin(); - for(;it!=BD.end();it++) { + for (;it!=BD.end();++it) { Key j = it->first; // variable key for this block const Matrix& Bj = it->second; if (blocks.count(j)) @@ -262,6 +259,30 @@ namespace gtsam { return BaseEliminateable::eliminateMultifrontal(ordering, function)->optimize(); } + /* ************************************************************************* */ + // TODO(frank): can we cache memory across invocations + VectorValues GaussianFactorGraph::optimizeDensely() const { + gttic(GaussianFactorGraph_optimizeDensely); + + // Combine all factors in a single HessianFactor (as done in augmentedHessian) + Scatter scatter(*this); + HessianFactor combined(*this, scatter); + + // TODO(frank): cast to large dynamic matrix :-( + // NOTE(frank): info only valid (I think) in upper triangle. No problem for LLT... + Matrix augmented = combined.info().selfadjointView(); + + // Do Cholesky Factorization + size_t n = augmented.rows() - 1; + auto AtA = augmented.topLeftCorner(n, n); + auto eta = augmented.topRightCorner(n, 1); + Eigen::LLT llt(AtA); + + // Solve and convert, re-using scatter data structure + Vector solution = llt.solve(eta); + return VectorValues(solution, scatter); + } + /* ************************************************************************* */ namespace { JacobianFactor::shared_ptr convertToJacobianFactorPtr(const GaussianFactor::shared_ptr &gf) { @@ -277,8 +298,8 @@ namespace gtsam { VectorValues GaussianFactorGraph::gradient(const VectorValues& x0) const { VectorValues g = VectorValues::Zero(x0); - for(const sharedFactor& Ai_G: *this) { - JacobianFactor::shared_ptr Ai = convertToJacobianFactorPtr(Ai_G); + for (const sharedFactor& factor: *this) { + JacobianFactor::shared_ptr Ai = convertToJacobianFactorPtr(factor); Vector e = Ai->error_vector(x0); Ai->transposeMultiplyAdd(1.0, e, g); } @@ -289,7 +310,7 @@ namespace gtsam { VectorValues GaussianFactorGraph::gradientAtZero() const { // Zero-out the gradient VectorValues g; - for(const sharedFactor& factor: *this) { + for (const sharedFactor& factor: *this) { if (!factor) continue; VectorValues gi = factor->gradientAtZero(); g.addInPlace_(gi); @@ -329,8 +350,8 @@ namespace gtsam { /* ************************************************************************* */ Errors GaussianFactorGraph::operator*(const VectorValues& x) const { Errors e; - for(const GaussianFactor::shared_ptr& Ai_G: *this) { - JacobianFactor::shared_ptr Ai = convertToJacobianFactorPtr(Ai_G); + for (const GaussianFactor::shared_ptr& factor: *this) { + JacobianFactor::shared_ptr Ai = convertToJacobianFactorPtr(factor); e.push_back((*Ai) * x); } return e; @@ -339,7 +360,7 @@ namespace gtsam { /* ************************************************************************* */ void GaussianFactorGraph::multiplyHessianAdd(double alpha, const VectorValues& x, VectorValues& y) const { - for(const GaussianFactor::shared_ptr& f: *this) + for (const GaussianFactor::shared_ptr& f: *this) f->multiplyHessianAdd(alpha, x, y); } @@ -351,8 +372,8 @@ namespace gtsam { /* ************************************************************************* */ void GaussianFactorGraph::multiplyInPlace(const VectorValues& x, const Errors::iterator& e) const { Errors::iterator ei = e; - for(const GaussianFactor::shared_ptr& Ai_G: *this) { - JacobianFactor::shared_ptr Ai = convertToJacobianFactorPtr(Ai_G); + for (const GaussianFactor::shared_ptr& factor: *this) { + JacobianFactor::shared_ptr Ai = convertToJacobianFactorPtr(factor); *ei = (*Ai)*x; ei++; } @@ -361,7 +382,7 @@ namespace gtsam { /* ************************************************************************* */ bool hasConstraints(const GaussianFactorGraph& factors) { typedef JacobianFactor J; - for(const GaussianFactor::shared_ptr& factor: factors) { + for (const GaussianFactor::shared_ptr& factor: factors) { J::shared_ptr jacobian(boost::dynamic_pointer_cast(factor)); if (jacobian && jacobian->get_model() && jacobian->get_model()->isConstrained()) { return true; @@ -376,8 +397,8 @@ namespace gtsam { VectorValues& x) const { // For each factor add the gradient contribution Errors::const_iterator ei = e.begin(); - for(const sharedFactor& Ai_G: *this) { - JacobianFactor::shared_ptr Ai = convertToJacobianFactorPtr(Ai_G); + for (const sharedFactor& factor: *this) { + JacobianFactor::shared_ptr Ai = convertToJacobianFactorPtr(factor); Ai->transposeMultiplyAdd(alpha, *(ei++), x); } } @@ -385,8 +406,8 @@ namespace gtsam { ///* ************************************************************************* */ //void residual(const GaussianFactorGraph& fg, const VectorValues &x, VectorValues &r) { // Key i = 0 ; - // for(const GaussianFactor::shared_ptr& Ai_G: fg) { - // JacobianFactor::shared_ptr Ai = convertToJacobianFactorPtr(Ai_G); + // for (const GaussianFactor::shared_ptr& factor, fg) { + // JacobianFactor::shared_ptr Ai = convertToJacobianFactorPtr(factor); // r[i] = Ai->getb(); // i++; // } @@ -399,10 +420,10 @@ namespace gtsam { //void multiply(const GaussianFactorGraph& fg, const VectorValues &x, VectorValues &r) { // r.setZero(); // Key i = 0; - // for(const GaussianFactor::shared_ptr& Ai_G: fg) { - // JacobianFactor::shared_ptr Ai = convertToJacobianFactorPtr(Ai_G); + // for (const GaussianFactor::shared_ptr& factor, fg) { + // JacobianFactor::shared_ptr Ai = convertToJacobianFactorPtr(factor); // Vector &y = r[i]; - // for(JacobianFactor::const_iterator j = Ai->begin(); j != Ai->end(); ++j) { + // for (JacobianFactor::const_iterator j = Ai->begin(); j != Ai->end(); ++j) { // y += Ai->getA(j) * x[*j]; // } // ++i; @@ -414,9 +435,9 @@ namespace gtsam { { VectorValues x; Errors::const_iterator ei = e.begin(); - for(const sharedFactor& Ai_G: *this) { - JacobianFactor::shared_ptr Ai = convertToJacobianFactorPtr(Ai_G); - for(JacobianFactor::const_iterator j = Ai->begin(); j != Ai->end(); ++j) { + for (const sharedFactor& factor: *this) { + JacobianFactor::shared_ptr Ai = convertToJacobianFactorPtr(factor); + for (JacobianFactor::const_iterator j = Ai->begin(); j != Ai->end(); ++j) { // Create the value as a zero vector if it does not exist. pair xi = x.tryInsert(*j, Vector()); if(xi.second) @@ -432,8 +453,8 @@ namespace gtsam { Errors GaussianFactorGraph::gaussianErrors(const VectorValues& x) const { Errors e; - for(const sharedFactor& Ai_G: *this) { - JacobianFactor::shared_ptr Ai = convertToJacobianFactorPtr(Ai_G); + for (const sharedFactor& factor: *this) { + JacobianFactor::shared_ptr Ai = convertToJacobianFactorPtr(factor); e.push_back(Ai->error_vector(x)); } return e; diff --git a/gtsam/linear/GaussianFactorGraph.h b/gtsam/linear/GaussianFactorGraph.h index d969f77ad..49cba482d 100644 --- a/gtsam/linear/GaussianFactorGraph.h +++ b/gtsam/linear/GaussianFactorGraph.h @@ -246,6 +246,11 @@ namespace gtsam { VectorValues optimize(OptionalOrdering ordering = boost::none, const Eliminate& function = EliminationTraitsType::DefaultEliminate) const; + /** + * Optimize using Eigen's dense Cholesky factorization + */ + VectorValues optimizeDensely() const; + /** * Compute the gradient of the energy function, * \f$ \nabla_{x=x_0} \left\Vert \Sigma^{-1} A x - b \right\Vert^2 \f$, diff --git a/gtsam/linear/GaussianJunctionTree.cpp b/gtsam/linear/GaussianJunctionTree.cpp index 982c17bd3..b038e5452 100644 --- a/gtsam/linear/GaussianJunctionTree.cpp +++ b/gtsam/linear/GaussianJunctionTree.cpp @@ -23,7 +23,7 @@ namespace gtsam { // Instantiate base classes - template class ClusterTree; + template class EliminatableClusterTree; template class JunctionTree; /* ************************************************************************* */ diff --git a/gtsam/linear/GaussianJunctionTree.h b/gtsam/linear/GaussianJunctionTree.h index f944d417b..67e5a374b 100644 --- a/gtsam/linear/GaussianJunctionTree.h +++ b/gtsam/linear/GaussianJunctionTree.h @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- - * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) @@ -26,21 +26,9 @@ namespace gtsam { class GaussianEliminationTree; /** - * A ClusterTree, i.e., a set of variable clusters with factors, arranged in a tree, with - * the additional property that it represents the clique tree associated with a Bayes net. - * - * In GTSAM a junction tree is an intermediate data structure in multifrontal - * variable elimination. Each node is a cluster of factors, along with a - * clique of variables that are eliminated all at once. In detail, every node k represents - * a clique (maximal fully connected subset) of an associated chordal graph, such as a - * chordal Bayes net resulting from elimination. - * - * The difference with the BayesTree is that a JunctionTree stores factors, whereas a - * BayesTree stores conditionals, that are the product of eliminating the factors in the - * corresponding JunctionTree cliques. - * - * The tree structure and elimination method are exactly analagous to the EliminationTree, - * except that in the JunctionTree, at each node multiple variables are eliminated at a time. + * A junction tree specialized to Gaussian factors, i.e., it is a cluster tree with Gaussian + * factors stored in each cluster. It can be eliminated into a Gaussian Bayes tree with the same + * structure, which is essentially doing multifrontal sparse matrix factorization. * * \addtogroup Multifrontal * \nosubgrouping @@ -51,7 +39,7 @@ namespace gtsam { typedef JunctionTree Base; ///< Base class typedef GaussianJunctionTree This; ///< This class typedef boost::shared_ptr shared_ptr; ///< Shared pointer to this class - + /** * Build the elimination tree of a factor graph using pre-computed column structure. * @param factorGraph The factor graph for which to build the elimination tree diff --git a/gtsam/linear/HessianFactor-inl.h b/gtsam/linear/HessianFactor-inl.h index 4a21ab0ff..957ae4519 100644 --- a/gtsam/linear/HessianFactor-inl.h +++ b/gtsam/linear/HessianFactor-inl.h @@ -29,10 +29,10 @@ namespace gtsam { if((DenseIndex)Base::keys_.size() != augmentedInformation.nBlocks() - 1) throw std::invalid_argument( "Error in HessianFactor constructor input. Number of provided keys plus\n" - "one for the information vector must equal the number of provided matrix blocks."); + "one for the information vector must equal the number of provided matrix blocks. "); // Check RHS dimension - if(augmentedInformation(0, augmentedInformation.nBlocks() - 1).cols() != 1) + if(augmentedInformation.getDim(augmentedInformation.nBlocks() - 1) != 1) throw std::invalid_argument( "Error in HessianFactor constructor input. The last provided matrix block\n" "must be the information vector, but the last provided block had more than one column."); diff --git a/gtsam/linear/HessianFactor.cpp b/gtsam/linear/HessianFactor.cpp index 2d635d3c6..29b2b8591 100644 --- a/gtsam/linear/HessianFactor.cpp +++ b/gtsam/linear/HessianFactor.cpp @@ -57,10 +57,33 @@ using namespace boost::adaptors; namespace gtsam { +/* ************************************************************************* */ +void HessianFactor::Allocate(const Scatter& scatter) { + gttic(HessianFactor_Allocate); + + // Allocate with dimensions for each variable plus 1 at the end for the information vector + const size_t n = scatter.size(); + keys_.resize(n); + FastVector dims(n + 1); + DenseIndex slot = 0; + for(const SlotEntry& slotentry: scatter) { + keys_[slot] = slotentry.key; + dims[slot] = slotentry.dimension; + ++slot; + } + dims.back() = 1; + info_ = SymmetricBlockMatrix(dims); +} + +/* ************************************************************************* */ +HessianFactor::HessianFactor(const Scatter& scatter) { + Allocate(scatter); +} + /* ************************************************************************* */ HessianFactor::HessianFactor() : info_(cref_list_of<1>(1)) { - linearTerm().setZero(); + assert(info_.rows() == 1); constantTerm() = 0.0; } @@ -70,9 +93,9 @@ HessianFactor::HessianFactor(Key j, const Matrix& G, const Vector& g, double f) if (G.rows() != G.cols() || G.rows() != g.size()) throw invalid_argument( "Attempting to construct HessianFactor with inconsistent matrix and/or vector dimensions"); - info_(0, 0) = G; - info_(0, 1) = g; - info_(1, 1)(0, 0) = f; + info_.setDiagonalBlock(0, G); + linearTerm() = g; + constantTerm() = f; } /* ************************************************************************* */ @@ -83,9 +106,9 @@ HessianFactor::HessianFactor(Key j, const Vector& mu, const Matrix& Sigma) : if (Sigma.rows() != Sigma.cols() || Sigma.rows() != mu.size()) throw invalid_argument( "Attempting to construct HessianFactor with inconsistent matrix and/or vector dimensions"); - info_(0, 0) = Sigma.inverse(); // G - info_(0, 1) = info_(0, 0).selfadjointView() * mu; // g - info_(1, 1)(0, 0) = mu.dot(info_(0, 1).knownOffDiagonal().col(0)); // f + info_.setDiagonalBlock(0, Sigma.inverse()); // G + linearTerm() = info_.diagonalBlock(0) * mu; // g + constantTerm() = mu.dot(linearTerm().col(0)); // f } /* ************************************************************************* */ @@ -94,12 +117,11 @@ HessianFactor::HessianFactor(Key j1, Key j2, const Matrix& G11, double f) : GaussianFactor(cref_list_of<2>(j1)(j2)), info_( cref_list_of<3>(G11.cols())(G22.cols())(1)) { - info_(0, 0) = G11; - info_(0, 1) = G12; - info_(0, 2) = g1; - info_(1, 1) = G22; - info_(1, 2) = g2; - info_(2, 2)(0, 0) = f; + info_.setDiagonalBlock(0, G11); + info_.setOffDiagonalBlock(0, 1, G12); + info_.setDiagonalBlock(1, G22); + linearTerm() << g1, g2; + constantTerm() = f; } /* ************************************************************************* */ @@ -115,16 +137,14 @@ HessianFactor::HessianFactor(Key j1, Key j2, Key j3, const Matrix& G11, || G22.cols() != g2.size() || G33.cols() != g3.size()) throw invalid_argument( "Inconsistent matrix and/or vector dimensions in HessianFactor constructor"); - info_(0, 0) = G11; - info_(0, 1) = G12; - info_(0, 2) = G13; - info_(0, 3) = g1; - info_(1, 1) = G22; - info_(1, 2) = G23; - info_(1, 3) = g2; - info_(2, 2) = G33; - info_(2, 3) = g3; - info_(3, 3)(0, 0) = f; + info_.setDiagonalBlock(0, G11); + info_.setOffDiagonalBlock(0, 1, G12); + info_.setOffDiagonalBlock(0, 2, G13); + info_.setDiagonalBlock(1, G22); + info_.setOffDiagonalBlock(1, 2, G23); + info_.setDiagonalBlock(2, G33); + linearTerm() << g1, g2, g3; + constantTerm() = f; } /* ************************************************************************* */ @@ -174,11 +194,16 @@ HessianFactor::HessianFactor(const std::vector& js, size_t index = 0; for (size_t i = 0; i < variable_count; ++i) { for (size_t j = i; j < variable_count; ++j) { - info_(i, j) = Gs[index++]; + if (i == j) { + info_.setDiagonalBlock(i, Gs[index]); + } else { + info_.setOffDiagonalBlock(i, j, Gs[index]); + } + index++; } - info_(i, variable_count) = gs[i]; + info_.setOffDiagonalBlock(i, variable_count, gs[i]); } - info_(variable_count, variable_count)(0, 0) = f; + constantTerm() = f; } /* ************************************************************************* */ @@ -186,17 +211,17 @@ namespace { void _FromJacobianHelper(const JacobianFactor& jf, SymmetricBlockMatrix& info) { gttic(HessianFactor_fromJacobian); const SharedDiagonal& jfModel = jf.get_model(); + auto A = jf.matrixObject().full(); if (jfModel) { if (jf.get_model()->isConstrained()) throw invalid_argument( "Cannot construct HessianFactor from JacobianFactor with constrained noise model"); - info.full().triangularView() = - jf.matrixObject().full().transpose() - * (jfModel->invsigmas().array() * jfModel->invsigmas().array()).matrix().asDiagonal() - * jf.matrixObject().full(); + + auto D = (jfModel->invsigmas().array() * jfModel->invsigmas().array()).matrix().asDiagonal(); + + info.setFullMatrix(A.transpose() * D * A); } else { - info.full().triangularView() = jf.matrixObject().full().transpose() - * jf.matrixObject().full(); + info.setFullMatrix(A.transpose() * A); } } } @@ -227,32 +252,13 @@ HessianFactor::HessianFactor(const GaussianFactor& gf) : HessianFactor::HessianFactor(const GaussianFactorGraph& factors, boost::optional scatter) { gttic(HessianFactor_MergeConstructor); - boost::optional computedScatter; - if (!scatter) { - computedScatter = Scatter(factors); - scatter = computedScatter; - } - // Allocate and copy keys - gttic(allocate); - // Allocate with dimensions for each variable plus 1 at the end for the information vector - const size_t n = scatter->size(); - keys_.resize(n); - FastVector dims(n + 1); - DenseIndex slot = 0; - for(const SlotEntry& slotentry: *scatter) { - keys_[slot] = slotentry.key; - dims[slot] = slotentry.dimension; - ++slot; - } - dims.back() = 1; - info_ = SymmetricBlockMatrix(dims); - info_.full().triangularView().setZero(); - gttoc(allocate); + Allocate(scatter ? *scatter : Scatter(factors)); // Form A' * A gttic(update); - for(const GaussianFactor::shared_ptr& factor: factors) + info_.setZero(); + for(const auto& factor: factors) if (factor) factor->updateHessian(keys_, &info_); gttoc(update); @@ -266,7 +272,7 @@ void HessianFactor::print(const std::string& s, for (const_iterator key = begin(); key != end(); ++key) cout << formatter(*key) << "(" << getDim(key) << ") "; cout << "\n"; - gtsam::print(Matrix(info_.full().selfadjointView()), + gtsam::print(Matrix(info_.selfadjointView()), "Augmented information matrix: "); } @@ -281,22 +287,25 @@ bool HessianFactor::equals(const GaussianFactor& lf, double tol) const { /* ************************************************************************* */ Matrix HessianFactor::augmentedInformation() const { - return info_.full().selfadjointView(); + return info_.selfadjointView(); +} + +/* ************************************************************************* */ +Eigen::SelfAdjointView +HessianFactor::informationView() const { + return info_.selfadjointView(0, size()); } /* ************************************************************************* */ Matrix HessianFactor::information() const { - return info_.range(0, size(), 0, size()).selfadjointView(); + return informationView(); } /* ************************************************************************* */ VectorValues HessianFactor::hessianDiagonal() const { VectorValues d; - // Loop over all variables - for (DenseIndex j = 0; j < (DenseIndex) size(); ++j) { - // Get the diagonal block, and insert its diagonal - Matrix B = info_(j, j).selfadjointView(); - d.insert(keys_[j], B.diagonal()); + for (DenseIndex j = 0; j < (DenseIndex)size(); ++j) { + d.insert(keys_[j], info_.diagonal(j)); } return d; } @@ -314,8 +323,7 @@ map HessianFactor::hessianBlockDiagonal() const { // Loop over all variables for (DenseIndex j = 0; j < (DenseIndex) size(); ++j) { // Get the diagonal block, and insert it - Matrix B = info_(j, j).selfadjointView(); - blocks.insert(make_pair(keys_[j], B)); + blocks.emplace(keys_[j], info_.diagonalBlock(j)); } return blocks; } @@ -334,28 +342,44 @@ std::pair HessianFactor::jacobian() const { double HessianFactor::error(const VectorValues& c) const { // error 0.5*(f - 2*x'*g + x'*G*x) const double f = constantTerm(); + if (empty()) { + return 0.5 * f; + } double xtg = 0, xGx = 0; // extract the relevant subset of the VectorValues // NOTE may not be as efficient const Vector x = c.vector(keys()); - xtg = x.dot(linearTerm()); - xGx = x.transpose() * info_.range(0, size(), 0, size()).selfadjointView() * x; + xtg = x.dot(linearTerm().col(0)); + auto AtA = informationView(); + xGx = x.transpose() * AtA * x; return 0.5 * (f - 2.0 * xtg + xGx); } /* ************************************************************************* */ void HessianFactor::updateHessian(const FastVector& infoKeys, - SymmetricBlockMatrix* info) const { + SymmetricBlockMatrix* info) const { gttic(updateHessian_HessianFactor); + assert(info); // Apply updates to the upper triangle - DenseIndex n = size(), N = info->nBlocks() - 1; - vector slots(n + 1); - for (DenseIndex j = 0; j <= n; ++j) { - const DenseIndex J = (j == n) ? N : Slot(infoKeys, keys_[j]); + DenseIndex nrVariablesInThisFactor = size(), nrBlocksInInfo = info->nBlocks() - 1; + vector slots(nrVariablesInThisFactor + 1); + // Loop over this factor's blocks with indices (i,j) + // For every block (i,j), we determine the block (I,J) in info. + for (DenseIndex j = 0; j <= nrVariablesInThisFactor; ++j) { + const bool rhs = (j == nrVariablesInThisFactor); + const DenseIndex J = rhs ? nrBlocksInInfo : Slot(infoKeys, keys_[j]); slots[j] = J; for (DenseIndex i = 0; i <= j; ++i) { - const DenseIndex I = slots[i]; // because i<=j, slots[i] is valid. - (*info)(I, J) += info_(i, j); + const DenseIndex I = slots[i]; // because i<=j, slots[i] is valid. + + if (i == j) { + assert(I == J); + info->updateDiagonalBlock(I, info_.diagonalBlock(i)); + } else { + assert(i < j); + assert(I != J); + info->updateOffDiagonalBlock(I, J, info_.aboveDiagonalBlock(i, j)); + } } } } @@ -363,8 +387,8 @@ void HessianFactor::updateHessian(const FastVector& infoKeys, /* ************************************************************************* */ GaussianFactor::shared_ptr HessianFactor::negate() const { shared_ptr result = boost::make_shared(*this); - result->info_.full().triangularView() = - -result->info_.full().triangularView().nestedExpression(); // Negate the information matrix of the result + // Negate the information matrix of the result + result->info_.negate(); return result; } @@ -386,12 +410,13 @@ void HessianFactor::multiplyHessianAdd(double alpha, const VectorValues& x, Vector xj = x.at(keys_[j]); DenseIndex i = 0; for (; i < j; ++i) - y[i] += info_(i, j).knownOffDiagonal() * xj; + y[i] += info_.aboveDiagonalBlock(i, j) * xj; + // blocks on the diagonal are only half - y[i] += info_(j, j).selfadjointView() * xj; + y[i] += info_.diagonalBlock(j) * xj; // for below diagonal, we take transpose block from upper triangular part for (i = j + 1; i < (DenseIndex) size(); ++i) - y[i] += info_(i, j).knownOffDiagonal() * xj; + y[i] += info_.aboveDiagonalBlock(j, i).transpose() * xj; } // copy to yvalues @@ -411,7 +436,7 @@ VectorValues HessianFactor::gradientAtZero() const { VectorValues g; size_t n = size(); for (size_t j = 0; j < n; ++j) - g.insert(keys_[j], -info_(j, n).knownOffDiagonal()); + g.insert(keys_[j], -info_.aboveDiagonalBlock(j, n)); return g; } @@ -424,31 +449,80 @@ void HessianFactor::gradientAtZero(double* d) const { /* ************************************************************************* */ Vector HessianFactor::gradient(Key key, const VectorValues& x) const { - Factor::const_iterator i = find(key); + const Factor::const_iterator it_i = find(key); + const DenseIndex I = std::distance(begin(), it_i); + // Sum over G_ij*xj for all xj connecting to xi Vector b = Vector::Zero(x.at(key).size()); - for (Factor::const_iterator j = begin(); j != end(); ++j) { + for (Factor::const_iterator it_j = begin(); it_j != end(); ++it_j) { + const DenseIndex J = std::distance(begin(), it_j); + // Obtain Gij from the Hessian factor // Hessian factor only stores an upper triangular matrix, so be careful when i>j - Matrix Gij; - if (i > j) { - Matrix Gji = info(j, i); - Gij = Gji.transpose(); - } else { - Gij = info(i, j); - } + const Matrix Gij = info_.block(I, J); // Accumulate Gij*xj to gradf - b += Gij * x.at(*j); + b += Gij * x.at(*it_j); } // Subtract the linear term gi - b += -linearTerm(i); + b += -linearTerm(it_i); return b; } /* ************************************************************************* */ -std::pair, - boost::shared_ptr > EliminateCholesky( - const GaussianFactorGraph& factors, const Ordering& keys) { +boost::shared_ptr HessianFactor::eliminateCholesky(const Ordering& keys) { + gttic(HessianFactor_eliminateCholesky); + + GaussianConditional::shared_ptr conditional; + + try { + // Do dense elimination + size_t nFrontals = keys.size(); + assert(nFrontals <= size()); + info_.choleskyPartial(nFrontals); + + // TODO(frank): pre-allocate GaussianConditional and write into it + const VerticalBlockMatrix Ab = info_.split(nFrontals); + conditional = boost::make_shared(keys_, nFrontals, Ab); + + // Erase the eliminated keys in this factor + keys_.erase(begin(), begin() + nFrontals); + } catch (const CholeskyFailed& e) { + throw IndeterminantLinearSystemException(keys.front()); + } + + // Return result + return conditional; +} + +/* ************************************************************************* */ +VectorValues HessianFactor::solve() { + gttic(HessianFactor_solve); + + // Do Cholesky Factorization + const size_t n = size(); + assert(info_.nBlocks() == n + 1); + info_.choleskyPartial(n); + auto R = info_.triangularView(0, n); + auto eta = linearTerm(); + + // Solve + const Vector solution = R.solve(eta); + + // Parse into VectorValues + VectorValues delta; + std::size_t offset = 0; + for (DenseIndex j = 0; j < (DenseIndex)n; ++j) { + const DenseIndex dim = info_.getDim(j); + delta.insert(keys_[j], solution.segment(offset, dim)); + offset += dim; + } + + return delta; +} + +/* ************************************************************************* */ +std::pair, boost::shared_ptr > +EliminateCholesky(const GaussianFactorGraph& factors, const Ordering& keys) { gttic(EliminateCholesky); // Build joint factor @@ -459,23 +533,11 @@ std::pair, } catch (std::invalid_argument&) { throw InvalidDenseElimination( "EliminateCholesky was called with a request to eliminate variables that are not\n" - "involved in the provided factors."); + "involved in the provided factors."); } // Do dense elimination - GaussianConditional::shared_ptr conditional; - try { - size_t numberOfKeysToEliminate = keys.size(); - VerticalBlockMatrix Ab = jointFactor->info_.choleskyPartial( - numberOfKeysToEliminate); - conditional = boost::make_shared(jointFactor->keys(), - numberOfKeysToEliminate, Ab); - // Erase the eliminated keys in the remaining factor - jointFactor->keys_.erase(jointFactor->begin(), - jointFactor->begin() + numberOfKeysToEliminate); - } catch (const CholeskyFailed& e) { - throw IndeterminantLinearSystemException(keys.front()); - } + auto conditional = jointFactor->eliminateCholesky(keys); // Return result return make_pair(conditional, jointFactor); diff --git a/gtsam/linear/HessianFactor.h b/gtsam/linear/HessianFactor.h index b74d557ea..e28bcdd81 100644 --- a/gtsam/linear/HessianFactor.h +++ b/gtsam/linear/HessianFactor.h @@ -35,12 +35,6 @@ namespace gtsam { class GaussianBayesNet; class GaussianFactorGraph; - GTSAM_EXPORT std::pair, boost::shared_ptr > - EliminatePreferCholesky(const GaussianFactorGraph& factors, const Ordering& keys); - - GTSAM_EXPORT std::pair, boost::shared_ptr > - EliminateCholesky(const GaussianFactorGraph& factors, const Ordering& keys); - /** * @brief A Gaussian factor using the canonical parameters (information form) * @@ -206,7 +200,9 @@ namespace gtsam { * @param variable An iterator pointing to the slot in this factor. You can * use, for example, begin() + 2 to get the 3rd variable in this factor. */ - virtual DenseIndex getDim(const_iterator variable) const { return info_(variable-this->begin(), 0).rows(); } + virtual DenseIndex getDim(const_iterator variable) const { + return info_.getDim(std::distance(begin(), variable)); + } /** Return the number of columns and rows of the Hessian matrix, including the information vector. */ size_t rows() const { return info_.rows(); } @@ -217,80 +213,54 @@ namespace gtsam { * @return a HessianFactor with negated Hessian matrices */ virtual GaussianFactor::shared_ptr negate() const; - + /** Check if the factor is empty. TODO: How should this be defined? */ virtual bool empty() const { return size() == 0 /*|| rows() == 0*/; } - /** Return a view of the block at (j1,j2) of the upper-triangular part of the - * information matrix \f$ H \f$, no data is copied. See HessianFactor class documentation - * above to explain that only the upper-triangular part of the information matrix is stored - * and returned by this function. - * @param j1 Which block row to get, as an iterator pointing to the slot in this factor. You can - * use, for example, begin() + 2 to get the 3rd variable in this factor. - * @param j2 Which block column to get, as an iterator pointing to the slot in this factor. You can - * use, for example, begin() + 2 to get the 3rd variable in this factor. - * @return A view of the requested block, not a copy. + /** Return the constant term \f$ f \f$ as described above + * @return The constant term \f$ f \f$ */ - constBlock info(const_iterator j1, const_iterator j2) const { return info_(j1-begin(), j2-begin()); } - - /** Return a view of the block at (j1,j2) of the upper-triangular part of the - * information matrix \f$ H \f$, no data is copied. See HessianFactor class documentation - * above to explain that only the upper-triangular part of the information matrix is stored - * and returned by this function. - * @param j1 Which block row to get, as an iterator pointing to the slot in this factor. You can - * use, for example, begin() + 2 to get the 3rd variable in this factor. - * @param j2 Which block column to get, as an iterator pointing to the slot in this factor. You can - * use, for example, begin() + 2 to get the 3rd variable in this factor. - * @return A view of the requested block, not a copy. - */ - Block info(iterator j1, iterator j2) { return info_(j1-begin(), j2-begin()); } - - /** Return the upper-triangular part of the full *augmented* information matrix, - * as described above. See HessianFactor class documentation above to explain that only the - * upper-triangular part of the information matrix is stored and returned by this function. - */ - SymmetricBlockMatrix::constBlock info() const { return info_.full(); } - - /** Return the upper-triangular part of the full *augmented* information matrix, - * as described above. See HessianFactor class documentation above to explain that only the - * upper-triangular part of the information matrix is stored and returned by this function. - */ - SymmetricBlockMatrix::Block info() { return info_.full(); } + double constantTerm() const { + const auto view = info_.diagonalBlock(size()); + return view(0, 0); + } /** Return the constant term \f$ f \f$ as described above * @return The constant term \f$ f \f$ */ - double constantTerm() const { return info_(this->size(), this->size())(0,0); } - - /** Return the constant term \f$ f \f$ as described above - * @return The constant term \f$ f \f$ - */ - double& constantTerm() { return info_(this->size(), this->size())(0,0); } + double& constantTerm() { return info_.diagonalBlock(size())(0, 0); } /** Return the part of linear term \f$ g \f$ as described above corresponding to the requested variable. * @param j Which block row to get, as an iterator pointing to the slot in this factor. You can * use, for example, begin() + 2 to get the 3rd variable in this factor. * @return The linear term \f$ g \f$ */ - constBlock::OffDiagonal::ColXpr linearTerm(const_iterator j) const { - return info_(j-begin(), size()).knownOffDiagonal().col(0); } - - /** Return the part of linear term \f$ g \f$ as described above corresponding to the requested variable. - * @param j Which block row to get, as an iterator pointing to the slot in this factor. You can - * use, for example, begin() + 2 to get the 3rd variable in this factor. - * @return The linear term \f$ g \f$ */ - Block::OffDiagonal::ColXpr linearTerm(iterator j) { - return info_(j-begin(), size()).knownOffDiagonal().col(0); } + SymmetricBlockMatrix::constBlock linearTerm(const_iterator j) const { + assert(!empty()); + return info_.aboveDiagonalBlock(j - begin(), size()); + } /** Return the complete linear term \f$ g \f$ as described above. * @return The linear term \f$ g \f$ */ - constBlock::OffDiagonal::ColXpr linearTerm() const { - return info_.range(0, this->size(), this->size(), this->size() + 1).knownOffDiagonal().col(0); } + SymmetricBlockMatrix::constBlock linearTerm() const { + assert(!empty()); + // get the last column (except the bottom right block) + return info_.aboveDiagonalRange(0, size(), size(), size() + 1); + } /** Return the complete linear term \f$ g \f$ as described above. * @return The linear term \f$ g \f$ */ - Block::OffDiagonal::ColXpr linearTerm() { - return info_.range(0, this->size(), this->size(), this->size() + 1).knownOffDiagonal().col(0); } - + SymmetricBlockMatrix::Block linearTerm() { + assert(!empty()); + return info_.aboveDiagonalRange(0, size(), size(), size() + 1); + } + + /// Return underlying information matrix. + const SymmetricBlockMatrix& info() const { return info_; } + + /// Return non-const information matrix. + /// TODO(gareth): Review the sanity of having non-const access to this. + SymmetricBlockMatrix& info() { return info_; } + /** Return the augmented information matrix represented by this GaussianFactor. * The augmented information matrix contains the information matrix with an * additional column holding the information vector, and an additional row @@ -308,6 +278,9 @@ namespace gtsam { */ virtual Matrix augmentedInformation() const; + /// Return self-adjoint view onto the information matrix (NOT augmented). + Eigen::SelfAdjointView informationView() const; + /** Return the non-augmented information matrix represented by this * GaussianFactor. */ @@ -322,11 +295,7 @@ namespace gtsam { /// Return the block diagonal of the Hessian for this factor virtual std::map hessianBlockDiagonal() const; - /** - * Return (dense) matrix associated with factor - * @param ordering of variables needed for matrix column order - * @param set weight to true to bake in the weights - */ + /// Return (dense) matrix associated with factor virtual std::pair jacobian() const; /** @@ -336,16 +305,21 @@ namespace gtsam { */ virtual Matrix augmentedJacobian() const; - /** Return the full augmented Hessian matrix of this factor as a SymmetricBlockMatrix object. */ - const SymmetricBlockMatrix& matrixObject() const { return info_; } - /** Update an information matrix by adding the information corresponding to this factor * (used internally during elimination). - * @param scatter A mapping from variable index to slot index in this HessianFactor + * @param keys THe ordered vector of keys for the information matrix to be updated * @param info The information matrix to be updated */ void updateHessian(const FastVector& keys, SymmetricBlockMatrix* info) const; + /** Update another Hessian factor + * @param other the HessianFactor to be updated + */ + void updateHessian(HessianFactor* other) const { + assert(other); + updateHessian(other->keys_, &other->info_); + } + /** y += alpha * A'*A*x */ void multiplyHessianAdd(double alpha, const VectorValues& x, VectorValues& y) const; @@ -362,44 +336,33 @@ namespace gtsam { Vector gradient(Key key, const VectorValues& x) const; /** - * Densely partially eliminate with Cholesky factorization. JacobianFactors are - * left-multiplied with their transpose to form the Hessian using the conversion constructor - * HessianFactor(const JacobianFactor&). - * - * If any factors contain constrained noise models, this function will fail because our current - * implementation cannot handle constrained noise models in Cholesky factorization. The - * function EliminatePreferCholesky() automatically does QR instead when this is the case. - * - * Variables are eliminated in the order specified in \c keys. - * - * @param factors Factors to combine and eliminate - * @param keys The variables to eliminate and their elimination ordering - * @return The conditional and remaining factor - * - * \addtogroup LinearSolving */ - friend GTSAM_EXPORT std::pair, boost::shared_ptr > - EliminateCholesky(const GaussianFactorGraph& factors, const Ordering& keys); + * In-place elimination that returns a conditional on (ordered) keys specified, and leaves + * this factor to be on the remaining keys (separator) only. Does dense partial Cholesky. + */ + boost::shared_ptr eliminateCholesky(const Ordering& keys); - /** - * Densely partially eliminate with Cholesky factorization. JacobianFactors are - * left-multiplied with their transpose to form the Hessian using the conversion constructor - * HessianFactor(const JacobianFactor&). - * - * This function will fall back on QR factorization for any cliques containing JacobianFactor's - * with constrained noise models. - * - * Variables are eliminated in the order specified in \c keys. - * - * @param factors Factors to combine and eliminate - * @param keys The variables to eliminate and their elimination ordering - * @return The conditional and remaining factor - * - * \addtogroup LinearSolving */ - friend GTSAM_EXPORT std::pair, boost::shared_ptr > - EliminatePreferCholesky(const GaussianFactorGraph& factors, const Ordering& keys); + /// Solve the system A'*A delta = A'*b in-place, return delta as VectorValues + VectorValues solve(); + + +#ifdef GTSAM_ALLOW_DEPRECATED_SINCE_V4 + /// @name Deprecated + /// @{ + const SymmetricBlockMatrix& matrixObject() const { return info_; } + /// @} +#endif private: + /// Allocate for given scatter pattern + void Allocate(const Scatter& scatter); + + /// Constructor with given scatter pattern, allocating but not initializing storage. + HessianFactor(const Scatter& scatter); + + friend class NonlinearFactorGraph; + friend class NonlinearClusterTree; + /** Serialization function */ friend class boost::serialization::access; template @@ -409,6 +372,43 @@ namespace gtsam { } }; +/** +* Densely partially eliminate with Cholesky factorization. JacobianFactors are +* left-multiplied with their transpose to form the Hessian using the conversion constructor +* HessianFactor(const JacobianFactor&). +* +* If any factors contain constrained noise models, this function will fail because our current +* implementation cannot handle constrained noise models in Cholesky factorization. The +* function EliminatePreferCholesky() automatically does QR instead when this is the case. +* +* Variables are eliminated in the order specified in \c keys. +* +* @param factors Factors to combine and eliminate +* @param keys The variables to eliminate and their elimination ordering +* @return The conditional and remaining factor +* +* \addtogroup LinearSolving */ +GTSAM_EXPORT std::pair, boost::shared_ptr > + EliminateCholesky(const GaussianFactorGraph& factors, const Ordering& keys); + +/** +* Densely partially eliminate with Cholesky factorization. JacobianFactors are +* left-multiplied with their transpose to form the Hessian using the conversion constructor +* HessianFactor(const JacobianFactor&). +* +* This function will fall back on QR factorization for any cliques containing JacobianFactor's +* with constrained noise models. +* +* Variables are eliminated in the order specified in \c keys. +* +* @param factors Factors to combine and eliminate +* @param keys The variables to eliminate and their elimination ordering +* @return The conditional and remaining factor +* +* \addtogroup LinearSolving */ +GTSAM_EXPORT std::pair, boost::shared_ptr > + EliminatePreferCholesky(const GaussianFactorGraph& factors, const Ordering& keys); + /// traits template<> struct traits : public Testable {}; diff --git a/gtsam/linear/JacobianFactor.cpp b/gtsam/linear/JacobianFactor.cpp index 999d7a325..06c8f3f64 100644 --- a/gtsam/linear/JacobianFactor.cpp +++ b/gtsam/linear/JacobianFactor.cpp @@ -104,10 +104,10 @@ JacobianFactor::JacobianFactor(const Key i1, const Matrix& A1, Key i2, /* ************************************************************************* */ JacobianFactor::JacobianFactor(const HessianFactor& factor) : Base(factor), Ab_( - VerticalBlockMatrix::LikeActiveViewOf(factor.matrixObject(), + VerticalBlockMatrix::LikeActiveViewOf(factor.info(), factor.rows())) { // Copy Hessian into our matrix and then do in-place Cholesky - Ab_.full() = factor.matrixObject().full(); + Ab_.full() = factor.info().selfadjointView(); // Do Cholesky to get a Jacobian size_t maxrank; @@ -532,10 +532,10 @@ void JacobianFactor::updateHessian(const FastVector& infoKeys, // Fill off-diagonal blocks with Ai'*Aj for (DenseIndex i = 0; i < j; ++i) { const DenseIndex I = slots[i]; // because iupdateOffDiagonalBlock(I, J, Ab_(i).transpose() * Ab_j); } // Fill diagonal block with Aj'*Aj - (*info)(J, J).selfadjointView().rankUpdate(Ab_j.transpose()); + info->diagonalBlock(J).rankUpdate(Ab_j.transpose()); } } } diff --git a/gtsam/linear/JacobianFactor.h b/gtsam/linear/JacobianFactor.h index 3795f096e..14ff46241 100644 --- a/gtsam/linear/JacobianFactor.h +++ b/gtsam/linear/JacobianFactor.h @@ -37,6 +37,11 @@ namespace gtsam { class Ordering; class JacobianFactor; + /** + * Multiply all factors and eliminate the given keys from the resulting factor using a QR + * variant that handles constraints (zero sigmas). Computation happens in noiseModel::Gaussian::QR + * Returns a conditional on those keys, and a new factor on the separator. + */ GTSAM_EXPORT std::pair, boost::shared_ptr > EliminateQR(const GaussianFactorGraph& factors, const Ordering& keys); @@ -178,12 +183,12 @@ namespace gtsam { * which in fact stores an augmented information matrix. */ virtual Matrix augmentedInformation() const; - + /** Return the non-augmented information matrix represented by this * GaussianFactor. */ virtual Matrix information() const; - + /// Return the diagonal of the Hessian for this factor virtual VectorValues hessianDiagonal() const; @@ -197,7 +202,7 @@ namespace gtsam { * @brief Returns (dense) A,b pair associated with factor, bakes in the weights */ virtual std::pair jacobian() const; - + /** * @brief Returns (dense) A,b pair associated with factor, does not bake in weights */ @@ -319,7 +324,7 @@ namespace gtsam { /** set noiseModel correctly */ void setModel(bool anyConstrained, const Vector& sigmas); - + /** * Densely partially eliminate with QR factorization, this is usually provided as an argument to * one of the factor graph elimination functions (see EliminateableFactorGraph). HessianFactors @@ -348,7 +353,7 @@ namespace gtsam { /// Internal function to fill blocks and set dimensions template void fillTerms(const TERMS& terms, const Vector& b, const SharedDiagonal& noiseModel); - + private: /** Unsafe Constructor that creates an uninitialized Jacobian of right size diff --git a/gtsam/linear/NoiseModel.cpp b/gtsam/linear/NoiseModel.cpp index 02dd37ea9..4d9c7883b 100644 --- a/gtsam/linear/NoiseModel.cpp +++ b/gtsam/linear/NoiseModel.cpp @@ -886,6 +886,30 @@ DCS::shared_ptr DCS::Create(double c, const ReweightScheme reweight) { return shared_ptr(new DCS(c, reweight)); } +/* ************************************************************************* */ +// L2WithDeadZone +/* ************************************************************************* */ + +L2WithDeadZone::L2WithDeadZone(double k, const ReweightScheme reweight) : Base(reweight), k_(k) { + if (k_ <= 0) { + throw runtime_error("mEstimator L2WithDeadZone takes only positive double in constructor."); + } +} + +void L2WithDeadZone::print(const std::string &s="") const { + std::cout << s << ": L2WithDeadZone (" << k_ << ")" << std::endl; +} + +bool L2WithDeadZone::equals(const Base &expected, double tol) const { + const L2WithDeadZone* p = dynamic_cast(&expected); + if (p == NULL) return false; + return fabs(k_ - p->k_) < tol; +} + +L2WithDeadZone::shared_ptr L2WithDeadZone::Create(double k, const ReweightScheme reweight) { + return shared_ptr(new L2WithDeadZone(k, reweight)); +} + } // namespace mEstimator /* ************************************************************************* */ diff --git a/gtsam/linear/NoiseModel.h b/gtsam/linear/NoiseModel.h index 3a8a6744c..e495921c2 100644 --- a/gtsam/linear/NoiseModel.h +++ b/gtsam/linear/NoiseModel.h @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- - * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) @@ -662,7 +662,29 @@ namespace gtsam { Base(const ReweightScheme reweight = Block):reweight_(reweight) {} virtual ~Base() {} - /// robust error function to implement + /* + * This method is responsible for returning the total penalty for a given amount of error. + * For example, this method is responsible for implementing the quadratic function for an + * L2 penalty, the absolute value function for an L1 penalty, etc. + * + * TODO(mike): There is currently a bug in GTSAM, where none of the mEstimator classes + * implement a residual function, and GTSAM calls the weight function to evaluate the + * total penalty, rather than calling the residual function. The weight function should be + * used during iteratively reweighted least squares optimization, but should not be used to + * evaluate the total penalty. The long-term solution is for all mEstimators to implement + * both a weight and a residual function, and for GTSAM to call the residual function when + * evaluating the total penalty. But for now, I'm leaving this residual method as pure + * virtual, so the existing mEstimators can inherit this default fallback behavior. + */ + virtual double residual(double error) const { return 0; }; + + /* + * This method is responsible for returning the weight function for a given amount of error. + * The weight function is related to the analytic derivative of the residual function. See + * http://research.microsoft.com/en-us/um/people/zhang/INRIA/Publis/Tutorial-Estim/node24.html + * for details. This method is required when optimizing cost functions with robust penalties + * using iteratively re-weighted least squares. + */ virtual double weight(double error) const = 0; virtual void print(const std::string &s) const = 0; @@ -916,6 +938,45 @@ namespace gtsam { } }; + /// L2WithDeadZone implements a standard L2 penalty, but with a dead zone of width 2*k, + /// centered at the origin. The resulting penalty within the dead zone is always zero, and + /// grows quadratically outside the dead zone. In this sense, the L2WithDeadZone penalty is + /// "robust to inliers", rather than being robust to outliers. This penalty can be used to + /// create barrier functions in a general way. + class GTSAM_EXPORT L2WithDeadZone : public Base { + protected: + double k_; + + public: + typedef boost::shared_ptr shared_ptr; + + L2WithDeadZone(double k, const ReweightScheme reweight = Block); + double residual(double error) const { + const double abs_error = fabs(error); + return (abs_error < k_) ? 0.0 : 0.5*(k_-abs_error)*(k_-abs_error); + } + double weight(double error) const { + // note that this code is slightly uglier than above, because there are three distinct + // cases to handle (left of deadzone, deadzone, right of deadzone) instead of the two + // cases (deadzone, non-deadzone) above. + if (fabs(error) <= k_) return 0.0; + else if (error > k_) return (-k_+error)/error; + else return (k_+error)/error; + } + void print(const std::string &s) const; + bool equals(const Base& expected, double tol=1e-8) const; + static shared_ptr Create(double k, const ReweightScheme reweight = Block); + + private: + /** Serialization function */ + friend class boost::serialization::access; + template + void serialize(ARCHIVE & ar, const unsigned int /*version*/) { + ar & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Base); + ar & BOOST_SERIALIZATION_NVP(k_); + } + }; + } ///\namespace mEstimator /** @@ -976,7 +1037,9 @@ namespace gtsam { { throw std::invalid_argument("unwhiten is not currently supported for robust noise models."); } inline virtual double distance(const Vector& v) const { return this->whiten(v).squaredNorm(); } - + // TODO(mike): fold the use of the m-estimator residual(...) function into distance(...) + inline virtual double distance_non_whitened(const Vector& v) const + { return robust_->residual(v.norm()); } // TODO: these are really robust iterated re-weighting support functions virtual void WhitenSystem(Vector& b) const; virtual void WhitenSystem(std::vector& A, Vector& b) const; @@ -997,7 +1060,7 @@ namespace gtsam { ar & boost::serialization::make_nvp("noise_", const_cast(noise_)); } }; - + // Helper function GTSAM_EXPORT boost::optional checkIfDiagonal(const Matrix M); diff --git a/gtsam/linear/RegularHessianFactor.h b/gtsam/linear/RegularHessianFactor.h index cf714e71d..f4df9d96b 100644 --- a/gtsam/linear/RegularHessianFactor.h +++ b/gtsam/linear/RegularHessianFactor.h @@ -125,12 +125,12 @@ public: const double* xj = x + key * D; DenseIndex i = 0; for (; i < j; ++i) - y_[i] += info_(i, j).knownOffDiagonal() * ConstDMap(xj); + y_[i] += info_.aboveDiagonalBlock(i, j) * ConstDMap(xj); // blocks on the diagonal are only half - y_[i] += info_(j, j).selfadjointView() * ConstDMap(xj); + y_[i] += info_.diagonalBlock(j) * ConstDMap(xj); // for below diagonal, we take transpose block from upper triangular part for (i = j + 1; i < (DenseIndex) size(); ++i) - y_[i] += info_(i, j).knownOffDiagonal() * ConstDMap(xj); + y_[i] += info_.aboveDiagonalBlock(j, i).transpose() * ConstDMap(xj); } // copy to yvalues @@ -155,16 +155,16 @@ public: for (DenseIndex j = 0; j < (DenseIndex) size(); ++j) { DenseIndex i = 0; for (; i < j; ++i) - y_[i] += info_(i, j).knownOffDiagonal() + y_[i] += info_.aboveDiagonalBlock(i, j) * ConstDMap(x + offsets[keys_[j]], offsets[keys_[j] + 1] - offsets[keys_[j]]); // blocks on the diagonal are only half - y_[i] += info_(j, j).selfadjointView() + y_[i] += info_.diagonalBlock(j) * ConstDMap(x + offsets[keys_[j]], offsets[keys_[j] + 1] - offsets[keys_[j]]); // for below diagonal, we take transpose block from upper triangular part for (i = j + 1; i < (DenseIndex) size(); ++i) - y_[i] += info_(i, j).knownOffDiagonal() + y_[i] += info_.aboveDiagonalBlock(j, i).transpose() * ConstDMap(x + offsets[keys_[j]], offsets[keys_[j] + 1] - offsets[keys_[j]]); } @@ -182,8 +182,7 @@ public: for (DenseIndex pos = 0; pos < (DenseIndex) size(); ++pos) { Key j = keys_[pos]; // Get the diagonal block, and insert its diagonal - const Matrix& B = info_(pos, pos).selfadjointView(); - DMap(d + D * j) += B.diagonal(); + DMap(d + D * j) += info_.diagonal(pos); } } @@ -194,8 +193,7 @@ public: for (DenseIndex pos = 0; pos < (DenseIndex) size(); ++pos) { Key j = keys_[pos]; // Get the diagonal block, and insert its diagonal - VectorD dj = -info_(pos, size()).knownOffDiagonal(); - DMap(d + D * j) += dj; + DMap(d + D * j) -= info_.aboveDiagonalBlock(pos, size());; } } diff --git a/gtsam/linear/Scatter.cpp b/gtsam/linear/Scatter.cpp index 719b3d16c..db5c25442 100644 --- a/gtsam/linear/Scatter.cpp +++ b/gtsam/linear/Scatter.cpp @@ -40,14 +40,15 @@ Scatter::Scatter(const GaussianFactorGraph& gfg, // If we have an ordering, pre-fill the ordered variables first if (ordering) { - for (Key key: *ordering) { - push_back(SlotEntry(key, 0)); + for (Key key : *ordering) { + add(key, 0); } } // Now, find dimensions of variables and/or extend - for (const GaussianFactor::shared_ptr& factor: gfg) { - if (!factor) continue; + for (const auto& factor : gfg) { + if (!factor) + continue; // TODO: Fix this hack to cope with zero-row Jacobians that come from BayesTreeOrphanWrappers const JacobianFactor* asJacobian = dynamic_cast(factor.get()); @@ -61,7 +62,7 @@ Scatter::Scatter(const GaussianFactorGraph& gfg, if (it!=end()) it->dimension = factor->getDim(variable); else - push_back(SlotEntry(key, factor->getDim(variable))); + add(key, factor->getDim(variable)); } } @@ -74,6 +75,11 @@ Scatter::Scatter(const GaussianFactorGraph& gfg, erase(std::remove_if(begin(), end(), SlotEntry::Zero), end()); } +/* ************************************************************************* */ +void Scatter::add(Key key, size_t dim) { + emplace_back(SlotEntry(key, dim)); +} + /* ************************************************************************* */ FastVector::iterator Scatter::find(Key key) { iterator it = begin(); diff --git a/gtsam/linear/Scatter.h b/gtsam/linear/Scatter.h index 39bfa6b8d..793961c59 100644 --- a/gtsam/linear/Scatter.h +++ b/gtsam/linear/Scatter.h @@ -50,10 +50,16 @@ struct GTSAM_EXPORT SlotEntry { */ class Scatter : public FastVector { public: - /// Constructor + /// Default Constructor + Scatter() {} + + /// Construct from gaussian factor graph, with optional (partial or complete) ordering Scatter(const GaussianFactorGraph& gfg, boost::optional ordering = boost::none); + /// Add a key/dim pair + void add(Key key, size_t dim); + private: /// Find the SlotEntry with the right key (linear time worst case) diff --git a/gtsam/linear/SubgraphSolver.cpp b/gtsam/linear/SubgraphSolver.cpp index 70212b5b1..22d39a7f2 100644 --- a/gtsam/linear/SubgraphSolver.cpp +++ b/gtsam/linear/SubgraphSolver.cpp @@ -144,12 +144,12 @@ SubgraphSolver::splitGraph(const GaussianFactorGraph &jfg) { if (gf->keys().size() == 1) augment = true; else { - const Key u = gf->keys()[0], v = gf->keys()[1], u_root = D.findSet(u), - v_root = D.findSet(v); + const Key u = gf->keys()[0], v = gf->keys()[1], u_root = D.find(u), + v_root = D.find(v); if (u_root != v_root) { t++; augment = true; - D.makeUnionInPlace(u_root, v_root); + D.merge(u_root, v_root); } } if (augment) diff --git a/gtsam/linear/VectorValues.cpp b/gtsam/linear/VectorValues.cpp index bce339dca..35afddb3a 100644 --- a/gtsam/linear/VectorValues.cpp +++ b/gtsam/linear/VectorValues.cpp @@ -47,15 +47,24 @@ namespace gtsam { VectorValues::VectorValues(const Vector& x, const Dims& dims) { typedef pair Pair; size_t j = 0; - for(const Pair& v: dims) { + for (const Pair& v : dims) { Key key; size_t n; boost::tie(key, n) = v; - values_.insert(make_pair(key, x.segment(j,n))); + values_.insert(make_pair(key, x.segment(j, n))); j += n; } } + /* ************************************************************************* */ + VectorValues::VectorValues(const Vector& x, const Scatter& scatter) { + size_t j = 0; + for (const SlotEntry& v : scatter) { + values_.insert(make_pair(v.key, x.segment(j, v.dimension))); + j += v.dimension; + } + } + /* ************************************************************************* */ VectorValues VectorValues::Zero(const VectorValues& other) { diff --git a/gtsam/linear/VectorValues.h b/gtsam/linear/VectorValues.h index 0c752728a..cb1e08f2d 100644 --- a/gtsam/linear/VectorValues.h +++ b/gtsam/linear/VectorValues.h @@ -17,11 +17,12 @@ #pragma once +#include +#include #include #include #include #include -#include #include @@ -124,9 +125,12 @@ namespace gtsam { template VectorValues(ITERATOR first, ITERATOR last) : values_(first, last) {} - /** Constructor from Vector. */ + /// Constructor from Vector, with Dims VectorValues(const Vector& c, const Dims& dims); + /// Constructor from Vector, with Scatter + VectorValues(const Vector& c, const Scatter& scatter); + /** Create a VectorValues with the same structure as \c other, but filled with zeros. */ static VectorValues Zero(const VectorValues& other); diff --git a/gtsam/linear/linearAlgorithms-inst.h b/gtsam/linear/linearAlgorithms-inst.h index 0583d1803..ac8c2d7c7 100644 --- a/gtsam/linear/linearAlgorithms-inst.h +++ b/gtsam/linear/linearAlgorithms-inst.h @@ -57,8 +57,8 @@ namespace gtsam // Take any ancestor results we'll need for(Key parent: clique->conditional_->parents()) myData.cliqueResults.insert(std::make_pair(parent, myData.parentData->cliqueResults.at(parent))); + // Solve and store in our results - //collectedResult.insert(clique->conditional()->solve(collectedResult/*myData.ancestorResults*/)); { GaussianConditional& c = *clique->conditional(); // Solve matrix @@ -82,17 +82,24 @@ namespace gtsam vectorPos += parentVector.size(); } } - xS = c.getb() - c.get_S() * xS; - Vector soln = c.get_R().triangularView().solve(xS); + + // NOTE(gareth): We can no longer write: xS = b - S * xS + // This is because Eigen (as of 3.3) no longer evaluates S * xS into + // a temporary, and the operation trashes valus in xS. + // See: http://eigen.tuxfamily.org/index.php?title=3.3 + const Vector rhs = c.getb() - c.get_S() * xS; + + // TODO(gareth): Inline instantiation of Eigen::Solve and check flag + const Vector solution = c.get_R().triangularView().solve(rhs); // Check for indeterminant solution - if(soln.hasNaN()) throw IndeterminantLinearSystemException(c.keys().front()); + if(solution.hasNaN()) throw IndeterminantLinearSystemException(c.keys().front()); // Insert solution into a VectorValues DenseIndex vectorPosition = 0; for(GaussianConditional::const_iterator frontal = c.beginFrontals(); frontal != c.endFrontals(); ++frontal) { VectorValues::const_iterator r = - collectedResult.insert(*frontal, soln.segment(vectorPosition, c.getDim(frontal))); + collectedResult.insert(*frontal, solution.segment(vectorPosition, c.getDim(frontal))); myData.cliqueResults.insert(make_pair(r->first, r)); vectorPosition += c.getDim(frontal); } diff --git a/gtsam/linear/tests/testGaussianBayesNet.cpp b/gtsam/linear/tests/testGaussianBayesNet.cpp index 2a1dc088f..89b44f1f8 100644 --- a/gtsam/linear/tests/testGaussianBayesNet.cpp +++ b/gtsam/linear/tests/testGaussianBayesNet.cpp @@ -36,17 +36,23 @@ using namespace gtsam; static const Key _x_=0, _y_=1; -static GaussianBayesNet smallBayesNet = list_of - (GaussianConditional(_x_, (Vector(1) << 9.0).finished(), (Matrix(1, 1) << 1.0).finished(), _y_, (Matrix(1, 1) << 1.0).finished())) - (GaussianConditional(_y_, (Vector(1) << 5.0).finished(), (Matrix(1, 1) << 1.0).finished())); +static GaussianBayesNet smallBayesNet = + list_of(GaussianConditional(_x_, Vector1::Constant(9), I_1x1, _y_, I_1x1))( + GaussianConditional(_y_, Vector1::Constant(5), I_1x1)); + +static GaussianBayesNet noisyBayesNet = + list_of(GaussianConditional(_x_, Vector1::Constant(9), I_1x1, _y_, I_1x1, + noiseModel::Diagonal::Sigmas(Vector1::Constant(2))))( + GaussianConditional(_y_, Vector1::Constant(5), I_1x1, + noiseModel::Diagonal::Sigmas(Vector1::Constant(3)))); /* ************************************************************************* */ -TEST( GaussianBayesNet, matrix ) +TEST( GaussianBayesNet, Matrix ) { Matrix R; Vector d; boost::tie(R,d) = smallBayesNet.matrix(); // find matrix and RHS - Matrix R1 = (Matrix(2, 2) << + Matrix R1 = (Matrix2() << 1.0, 1.0, 0.0, 1.0 ).finished(); @@ -57,31 +63,55 @@ TEST( GaussianBayesNet, matrix ) } /* ************************************************************************* */ -TEST( GaussianBayesNet, optimize ) +TEST( GaussianBayesNet, NoisyMatrix ) { + Matrix R; Vector d; + boost::tie(R,d) = noisyBayesNet.matrix(); // find matrix and RHS + + Matrix R1 = (Matrix2() << + 0.5, 0.5, + 0.0, 1./3. + ).finished(); + Vector d1 = Vector2(9./2., 5./3.); + + EXPECT(assert_equal(R,R1)); + EXPECT(assert_equal(d,d1)); +} + +/* ************************************************************************* */ +TEST(GaussianBayesNet, Optimize) { + VectorValues expected = + map_list_of(_x_, Vector1::Constant(4))(_y_, Vector1::Constant(5)); VectorValues actual = smallBayesNet.optimize(); + EXPECT(assert_equal(expected, actual)); +} - VectorValues expected = map_list_of - (_x_, (Vector(1) << 4.0).finished()) - (_y_, (Vector(1) << 5.0).finished()); +/* ************************************************************************* */ +TEST(GaussianBayesNet, NoisyOptimize) { + Matrix R; + Vector d; + boost::tie(R, d) = noisyBayesNet.matrix(); // find matrix and RHS + const Vector x = R.inverse() * d; + VectorValues expected = map_list_of(_x_, x.head(1))(_y_, x.tail(1)); - EXPECT(assert_equal(expected,actual)); + VectorValues actual = noisyBayesNet.optimize(); + EXPECT(assert_equal(expected, actual)); } /* ************************************************************************* */ TEST( GaussianBayesNet, optimizeIncomplete ) { static GaussianBayesNet incompleteBayesNet = list_of - (GaussianConditional(_x_, (Vector(1) << 9.0).finished(), (Matrix(1, 1) << 1.0).finished(), _y_, (Matrix(1, 1) << 1.0).finished())); + (GaussianConditional(_x_, Vector1::Constant(9), I_1x1, _y_, I_1x1)); VectorValues solutionForMissing = map_list_of - (_y_, (Vector(1) << 5.0).finished()); + (_y_, Vector1::Constant(5)); VectorValues actual = incompleteBayesNet.optimize(solutionForMissing); VectorValues expected = map_list_of - (_x_, (Vector(1) << 4.0).finished()) - (_y_, (Vector(1) << 5.0).finished()); + (_x_, Vector1::Constant(4)) + (_y_, Vector1::Constant(5)); EXPECT(assert_equal(expected,actual)); } @@ -95,13 +125,13 @@ TEST( GaussianBayesNet, optimize3 ) // NOTE: we are supplying a new RHS here VectorValues expected = map_list_of - (_x_, (Vector(1) << -1.0).finished()) - (_y_, (Vector(1) << 5.0).finished()); + (_x_, Vector1::Constant(-1)) + (_y_, Vector1::Constant(5)); // Test different RHS version VectorValues gx = map_list_of - (_x_, (Vector(1) << 4.0).finished()) - (_y_, (Vector(1) << 5.0).finished()); + (_x_, Vector1::Constant(4)) + (_y_, Vector1::Constant(5)); VectorValues actual = smallBayesNet.backSubstitute(gx); EXPECT(assert_equal(expected, actual)); } @@ -114,11 +144,11 @@ TEST( GaussianBayesNet, backSubstituteTranspose ) // 5 1 1 3 VectorValues x = map_list_of - (_x_, (Vector(1) << 2.0).finished()) - (_y_, (Vector(1) << 5.0).finished()), + (_x_, Vector1::Constant(2)) + (_y_, Vector1::Constant(5)), expected = map_list_of - (_x_, (Vector(1) << 2.0).finished()) - (_y_, (Vector(1) << 3.0).finished()); + (_x_, Vector1::Constant(2)) + (_y_, Vector1::Constant(3)); VectorValues actual = smallBayesNet.backSubstituteTranspose(x); EXPECT(assert_equal(expected, actual)); @@ -130,15 +160,15 @@ TEST( GaussianBayesNet, DeterminantTest ) { GaussianBayesNet cbn; cbn += GaussianConditional( - 0, Vector2(3.0, 4.0 ), (Matrix(2, 2) << 1.0, 3.0, 0.0, 4.0 ).finished(), - 1, (Matrix(2, 2) << 2.0, 1.0, 2.0, 3.0).finished(), noiseModel::Isotropic::Sigma(2, 2.0)); + 0, Vector2(3.0, 4.0), (Matrix2() << 1.0, 3.0, 0.0, 4.0).finished(), + 1, (Matrix2() << 2.0, 1.0, 2.0, 3.0).finished(), noiseModel::Isotropic::Sigma(2, 2.0)); cbn += GaussianConditional( - 1, Vector2(5.0, 6.0 ), (Matrix(2, 2) << 1.0, 1.0, 0.0, 3.0 ).finished(), - 2, (Matrix(2, 2) << 1.0, 0.0, 5.0, 2.0).finished(), noiseModel::Isotropic::Sigma(2, 2.0)); + 1, Vector2(5.0, 6.0), (Matrix2() << 1.0, 1.0, 0.0, 3.0).finished(), + 2, (Matrix2() << 1.0, 0.0, 5.0, 2.0).finished(), noiseModel::Isotropic::Sigma(2, 2.0)); cbn += GaussianConditional( - 3, Vector2(7.0, 8.0 ), (Matrix(2, 2) << 1.0, 1.0, 0.0, 5.0 ).finished(), noiseModel::Isotropic::Sigma(2, 2.0)); + 3, Vector2(7.0, 8.0), (Matrix2() << 1.0, 1.0, 0.0, 5.0).finished(), noiseModel::Isotropic::Sigma(2, 2.0)); double expectedDeterminant = 60.0 / 64.0; double actualDeterminant = cbn.determinant(); @@ -161,21 +191,21 @@ TEST(GaussianBayesNet, ComputeSteepestDescentPoint) { // Create an arbitrary Bayes Net GaussianBayesNet gbn; gbn += GaussianConditional::shared_ptr(new GaussianConditional( - 0, Vector2(1.0,2.0), (Matrix(2, 2) << 3.0,4.0,0.0,6.0).finished(), - 3, (Matrix(2, 2) << 7.0,8.0,9.0,10.0).finished(), - 4, (Matrix(2, 2) << 11.0,12.0,13.0,14.0).finished())); + 0, Vector2(1.0,2.0), (Matrix2() << 3.0,4.0,0.0,6.0).finished(), + 3, (Matrix2() << 7.0,8.0,9.0,10.0).finished(), + 4, (Matrix2() << 11.0,12.0,13.0,14.0).finished())); gbn += GaussianConditional::shared_ptr(new GaussianConditional( - 1, Vector2(15.0,16.0), (Matrix(2, 2) << 17.0,18.0,0.0,20.0).finished(), - 2, (Matrix(2, 2) << 21.0,22.0,23.0,24.0).finished(), - 4, (Matrix(2, 2) << 25.0,26.0,27.0,28.0).finished())); + 1, Vector2(15.0,16.0), (Matrix2() << 17.0,18.0,0.0,20.0).finished(), + 2, (Matrix2() << 21.0,22.0,23.0,24.0).finished(), + 4, (Matrix2() << 25.0,26.0,27.0,28.0).finished())); gbn += GaussianConditional::shared_ptr(new GaussianConditional( - 2, Vector2(29.0,30.0), (Matrix(2, 2) << 31.0,32.0,0.0,34.0).finished(), - 3, (Matrix(2, 2) << 35.0,36.0,37.0,38.0).finished())); + 2, Vector2(29.0,30.0), (Matrix2() << 31.0,32.0,0.0,34.0).finished(), + 3, (Matrix2() << 35.0,36.0,37.0,38.0).finished())); gbn += GaussianConditional::shared_ptr(new GaussianConditional( - 3, Vector2(39.0,40.0), (Matrix(2, 2) << 41.0,42.0,0.0,44.0).finished(), - 4, (Matrix(2, 2) << 45.0,46.0,47.0,48.0).finished())); + 3, Vector2(39.0,40.0), (Matrix2() << 41.0,42.0,0.0,44.0).finished(), + 4, (Matrix2() << 45.0,46.0,47.0,48.0).finished())); gbn += GaussianConditional::shared_ptr(new GaussianConditional( - 4, Vector2(49.0,50.0), (Matrix(2, 2) << 51.0,52.0,0.0,54.0).finished())); + 4, Vector2(49.0,50.0), (Matrix2() << 51.0,52.0,0.0,54.0).finished())); // Compute the Hessian numerically Matrix hessian = numericalHessian( diff --git a/gtsam/linear/tests/testGaussianBayesTree.cpp b/gtsam/linear/tests/testGaussianBayesTree.cpp index 738a6d59f..e5634c357 100644 --- a/gtsam/linear/tests/testGaussianBayesTree.cpp +++ b/gtsam/linear/tests/testGaussianBayesTree.cpp @@ -130,7 +130,7 @@ TEST(GaussianBayesTree, complicatedMarginal) { // Create the conditionals to go in the BayesTree GaussianBayesTree bt; bt.insertRoot( - MakeClique(GaussianConditional(pair_list_of (11, (Matrix(3,1) << 0.0971, 0, 0).finished()) + MakeClique(GaussianConditional(pair_list_of (11, (Matrix(3,1) << 0.0971, 0, 0).finished()) (12, (Matrix(3,2) << 0.3171, 0.4387, 0.9502, 0.3816, 0, 0.7655).finished()), 2, Vector3(0.2638, 0.1455, 0.1361)), list_of (MakeClique(GaussianConditional(pair_list_of (9, (Matrix(3,1) << 0.7952, 0, 0).finished()) diff --git a/gtsam/linear/tests/testGaussianFactorGraph.cpp b/gtsam/linear/tests/testGaussianFactorGraph.cpp index 8f936e4b2..45f652d05 100644 --- a/gtsam/linear/tests/testGaussianFactorGraph.cpp +++ b/gtsam/linear/tests/testGaussianFactorGraph.cpp @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- - * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) @@ -27,7 +27,7 @@ #include #include -#include // for operator += +#include // for operator += using namespace boost::assign; #include @@ -36,7 +36,7 @@ using namespace boost::assign; using namespace std; using namespace gtsam; -//static SharedDiagonal +// static SharedDiagonal // sigma0_1 = noiseModel::Isotropic::Sigma(2,0.1), sigma_02 = noiseModel::Isotropic::Sigma(2,0.2), // constraintModel = noiseModel::Constrained::All(2); @@ -56,11 +56,11 @@ TEST(GaussianFactorGraph, initialization) { // Test sparse, which takes a vector and returns a matrix, used in MATLAB // Note that this the augmented vector and the RHS is in column 7 - Matrix expectedIJS = (Matrix(3, 22) << - 1., 2., 1., 2., 3., 4., 3., 4., 3., 4., 5., 6., 5., 6., 5., 6., 7., 8., 7., 8., 7., 8., - 1., 2., 7., 7., 1., 2., 3., 4., 7., 7., 1., 2., 5., 6., 7., 7., 3., 4., 5., 6., 7., 7., - 10., 10., -1., -1., -10., -10., 10., 10., 2., -1., -5., -5., 5., 5., 0., 1., -5., -5., 5., 5., -1., 1.5 - ).finished(); + Matrix expectedIJS = + (Matrix(3, 22) << 1., 2., 1., 2., 3., 4., 3., 4., 3., 4., 5., 6., 5., 6., 5., 6., 7., 8., 7., + 8., 7., 8., 1., 2., 7., 7., 1., 2., 3., 4., 7., 7., 1., 2., 5., 6., 7., 7., 3., 4., 5., 6., + 7., 7., 10., 10., -1., -1., -10., -10., 10., 10., 2., -1., -5., -5., 5., 5., 0., 1., -5., + -5., 5., 5., -1., 1.5).finished(); Matrix actualIJS = fg.sparseJacobian_(); EQUALITY(expectedIJS, actualIJS); } @@ -98,7 +98,8 @@ TEST(GaussianFactorGraph, sparseJacobian) { GaussianFactorGraph gfg; SharedDiagonal model = noiseModel::Isotropic::Sigma(2, 0.5); gfg.add(0, (Matrix(2, 3) << 1., 2., 3., 5., 6., 7.).finished(), Vector2(4., 8.), model); - gfg.add(0, (Matrix(2, 3) << 9.,10., 0., 0., 0., 0.).finished(), 1, (Matrix(2, 2) << 11., 12., 14., 15.).finished(), Vector2(13.,16.), model); + gfg.add(0, (Matrix(2, 3) << 9., 10., 0., 0., 0., 0.).finished(), 1, + (Matrix(2, 2) << 11., 12., 14., 15.).finished(), Vector2(13., 16.), model); Matrix actual = gfg.sparseJacobian_(); @@ -121,73 +122,73 @@ TEST(GaussianFactorGraph, matrices) { GaussianFactorGraph gfg; SharedDiagonal model = noiseModel::Unit::Create(2); gfg.add(0, A00, Vector2(4., 8.), model); - gfg.add(0, A10, 1, A11, Vector2(13.,16.), model); + gfg.add(0, A10, 1, A11, Vector2(13., 16.), model); - Matrix Ab(4,6); - Ab << - 1, 2, 3, 0, 0, 4, - 5, 6, 7, 0, 0, 8, - 9,10, 0,11,12,13, - 0, 0, 0,14,15,16; + Matrix Ab(4, 6); + Ab << 1, 2, 3, 0, 0, 4, 5, 6, 7, 0, 0, 8, 9, 10, 0, 11, 12, 13, 0, 0, 0, 14, 15, 16; // augmented versions EXPECT(assert_equal(Ab, gfg.augmentedJacobian())); EXPECT(assert_equal(Ab.transpose() * Ab, gfg.augmentedHessian())); // jacobian - Matrix A = Ab.leftCols(Ab.cols()-1); - Vector b = Ab.col(Ab.cols()-1); - Matrix actualA; Vector actualb; boost::tie(actualA,actualb) = gfg.jacobian(); + Matrix A = Ab.leftCols(Ab.cols() - 1); + Vector b = Ab.col(Ab.cols() - 1); + Matrix actualA; + Vector actualb; + boost::tie(actualA, actualb) = gfg.jacobian(); EXPECT(assert_equal(A, actualA)); EXPECT(assert_equal(b, actualb)); // hessian Matrix L = A.transpose() * A; Vector eta = A.transpose() * b; - Matrix actualL; Vector actualeta; boost::tie(actualL,actualeta) = gfg.hessian(); + Matrix actualL; + Vector actualeta; + boost::tie(actualL, actualeta) = gfg.hessian(); EXPECT(assert_equal(L, actualL)); EXPECT(assert_equal(eta, actualeta)); // hessianBlockDiagonal - VectorValues expectLdiagonal; // Make explicit that diagonal is sum-squares of columns - expectLdiagonal.insert(0, Vector3(1+25+81, 4+36+100, 9+49)); - expectLdiagonal.insert(1, Vector2(121+196, 144+225)); + VectorValues expectLdiagonal; // Make explicit that diagonal is sum-squares of columns + expectLdiagonal.insert(0, Vector3(1 + 25 + 81, 4 + 36 + 100, 9 + 49)); + expectLdiagonal.insert(1, Vector2(121 + 196, 144 + 225)); EXPECT(assert_equal(expectLdiagonal, gfg.hessianDiagonal())); // hessianBlockDiagonal - map actualBD = gfg.hessianBlockDiagonal(); - LONGS_EQUAL(2,actualBD.size()); - EXPECT(assert_equal(A00.transpose()*A00 + A10.transpose()*A10,actualBD[0])); - EXPECT(assert_equal(A11.transpose()*A11,actualBD[1])); + map actualBD = gfg.hessianBlockDiagonal(); + LONGS_EQUAL(2, actualBD.size()); + EXPECT(assert_equal(A00.transpose() * A00 + A10.transpose() * A10, actualBD[0])); + EXPECT(assert_equal(A11.transpose() * A11, actualBD[1])); } /* ************************************************************************* */ +/// Factor graph with 2 2D factors on 3 2D variables static GaussianFactorGraph createSimpleGaussianFactorGraph() { GaussianFactorGraph fg; + Key x1 = 2, x2 = 0, l1 = 1; SharedDiagonal unit2 = noiseModel::Unit::Create(2); // linearized prior on x1: c[_x1_]+x1=0 i.e. x1=-c[_x1_] - fg += JacobianFactor(2, 10*I_2x2, -1.0*Vector::Ones(2), unit2); + fg += JacobianFactor(x1, 10 * I_2x2, -1.0 * Vector::Ones(2), unit2); // odometry between x1 and x2: x2-x1=[0.2;-0.1] - fg += JacobianFactor(0, 10*I_2x2, 2, -10*I_2x2, Vector2(2.0, -1.0), unit2); + fg += JacobianFactor(x2, 10 * I_2x2, x1, -10 * I_2x2, Vector2(2.0, -1.0), unit2); // measurement between x1 and l1: l1-x1=[0.0;0.2] - fg += JacobianFactor(1, 5*I_2x2, 2, -5*I_2x2, Vector2(0.0, 1.0), unit2); + fg += JacobianFactor(l1, 5 * I_2x2, x1, -5 * I_2x2, Vector2(0.0, 1.0), unit2); // measurement between x2 and l1: l1-x2=[-0.2;0.3] - fg += JacobianFactor(0, -5*I_2x2, 1, 5*I_2x2, Vector2(-1.0, 1.5), unit2); + fg += JacobianFactor(x2, -5 * I_2x2, l1, 5 * I_2x2, Vector2(-1.0, 1.5), unit2); return fg; } /* ************************************************************************* */ -TEST( GaussianFactorGraph, gradient ) -{ +TEST(GaussianFactorGraph, gradient) { GaussianFactorGraph fg = createSimpleGaussianFactorGraph(); // Construct expected gradient - // 2*f(x) = 100*(x1+c[X(1)])^2 + 100*(x2-x1-[0.2;-0.1])^2 + 25*(l1-x1-[0.0;0.2])^2 + 25*(l1-x2-[-0.2;0.3])^2 + // 2*f(x) = 100*(x1+c[X(1)])^2 + 100*(x2-x1-[0.2;-0.1])^2 + 25*(l1-x1-[0.0;0.2])^2 + + // 25*(l1-x2-[-0.2;0.3])^2 // worked out: df/dx1 = 100*[0.1;0.1] + 100*[0.2;-0.1]) + 25*[0.0;0.2] = [10+20;10-10+5] = [30;5] - VectorValues expected = map_list_of - (1, Vector2(5.0, -12.5)) - (2, Vector2(30.0, 5.0)) - (0, Vector2(-25.0, 17.5)); + VectorValues expected = map_list_of(1, Vector2(5.0, -12.5))(2, Vector2(30.0, 5.0))( + 0, Vector2(-25.0, 17.5)); // Check the gradient at delta=0 VectorValues zero = VectorValues::Zero(expected); @@ -202,18 +203,14 @@ TEST( GaussianFactorGraph, gradient ) } /* ************************************************************************* */ -TEST( GaussianFactorGraph, transposeMultiplication ) -{ +TEST(GaussianFactorGraph, transposeMultiplication) { GaussianFactorGraph A = createSimpleGaussianFactorGraph(); - Errors e; e += - Vector2(0.0, 0.0), - Vector2(15.0, 0.0), - Vector2(0.0,-5.0), - Vector2(-7.5,-5.0); + Errors e; + e += Vector2(0.0, 0.0), Vector2(15.0, 0.0), Vector2(0.0, -5.0), Vector2(-7.5, -5.0); VectorValues expected; - expected.insert(1, Vector2(-37.5,-50.0)); + expected.insert(1, Vector2(-37.5, -50.0)); expected.insert(2, Vector2(-150.0, 25.0)); expected.insert(0, Vector2(187.5, 25.0)); @@ -222,8 +219,7 @@ TEST( GaussianFactorGraph, transposeMultiplication ) } /* ************************************************************************* */ -TEST(GaussianFactorGraph, eliminate_empty ) -{ +TEST(GaussianFactorGraph, eliminate_empty) { // eliminate an empty factor GaussianFactorGraph gfg; gfg.add(JacobianFactor()); @@ -243,25 +239,31 @@ TEST(GaussianFactorGraph, eliminate_empty ) } /* ************************************************************************* */ -TEST( GaussianFactorGraph, matrices2 ) -{ +TEST(GaussianFactorGraph, matrices2) { GaussianFactorGraph gfg = createSimpleGaussianFactorGraph(); - Matrix A; Vector b; boost::tie(A,b) = gfg.jacobian(); - Matrix AtA; Vector eta; boost::tie(AtA,eta) = gfg.hessian(); - EXPECT(assert_equal(A.transpose()*A, AtA)); - EXPECT(assert_equal(A.transpose()*b, eta)); + Matrix A; + Vector b; + boost::tie(A, b) = gfg.jacobian(); + Matrix AtA; + Vector eta; + boost::tie(AtA, eta) = gfg.hessian(); + EXPECT(assert_equal(A.transpose() * A, AtA)); + EXPECT(assert_equal(A.transpose() * b, eta)); + Matrix expectedAtA(6, 6); + expectedAtA << 125, 0, -25, 0, -100, 0, // + 0, 125, 0, -25, 0, -100, // + -25, 0, 50, 0, -25, 0, // + 0, -25, 0, 50, 0, -25, // + -100, 0, -25, 0, 225, 0, // + 0, -100, 0, -25, 0, 225; + EXPECT(assert_equal(expectedAtA, AtA)); } - /* ************************************************************************* */ -TEST( GaussianFactorGraph, multiplyHessianAdd ) -{ +TEST(GaussianFactorGraph, multiplyHessianAdd) { GaussianFactorGraph gfg = createSimpleGaussianFactorGraph(); - VectorValues x = map_list_of - (0, Vector2(1,2)) - (1, Vector2(3,4)) - (2, Vector2(5,6)); + VectorValues x = map_list_of(0, Vector2(1, 2))(1, Vector2(3, 4))(2, Vector2(5, 6)); VectorValues expected; expected.insert(0, Vector2(-450, -450)); @@ -274,7 +276,7 @@ TEST( GaussianFactorGraph, multiplyHessianAdd ) // now, do it with non-zero y gfg.multiplyHessianAdd(1.0, x, actual); - EXPECT(assert_equal(2*expected, actual)); + EXPECT(assert_equal(2 * expected, actual)); } /* ************************************************************************* */ @@ -286,20 +288,20 @@ static GaussianFactorGraph createGaussianFactorGraphWithHessianFactor() { } /* ************************************************************************* */ -TEST( GaussianFactorGraph, multiplyHessianAdd2 ) -{ +TEST(GaussianFactorGraph, multiplyHessianAdd2) { GaussianFactorGraph gfg = createGaussianFactorGraphWithHessianFactor(); // brute force - Matrix AtA; Vector eta; boost::tie(AtA,eta) = gfg.hessian(); - Vector X(6); X<<1,2,3,4,5,6; - Vector Y(6); Y<<-450, -450, 300, 400, 2950, 3450; - EXPECT(assert_equal(Y,AtA*X)); + Matrix AtA; + Vector eta; + boost::tie(AtA, eta) = gfg.hessian(); + Vector X(6); + X << 1, 2, 3, 4, 5, 6; + Vector Y(6); + Y << -450, -450, 300, 400, 2950, 3450; + EXPECT(assert_equal(Y, AtA * X)); - VectorValues x = map_list_of - (0, Vector2(1,2)) - (1, Vector2(3,4)) - (2, Vector2(5,6)); + VectorValues x = map_list_of(0, Vector2(1, 2))(1, Vector2(3, 4))(2, Vector2(5, 6)); VectorValues expected; expected.insert(0, Vector2(-450, -450)); @@ -312,24 +314,26 @@ TEST( GaussianFactorGraph, multiplyHessianAdd2 ) // now, do it with non-zero y gfg.multiplyHessianAdd(1.0, x, actual); - EXPECT(assert_equal(2*expected, actual)); + EXPECT(assert_equal(2 * expected, actual)); } /* ************************************************************************* */ -TEST( GaussianFactorGraph, matricesMixed ) -{ +TEST(GaussianFactorGraph, matricesMixed) { GaussianFactorGraph gfg = createGaussianFactorGraphWithHessianFactor(); - Matrix A; Vector b; boost::tie(A,b) = gfg.jacobian(); // incorrect ! - Matrix AtA; Vector eta; boost::tie(AtA,eta) = gfg.hessian(); // correct - EXPECT(assert_equal(A.transpose()*A, AtA)); - Vector expected = - (Vector(6) << -25, 17.5, 5, -13.5, 29, 4).finished(); + Matrix A; + Vector b; + boost::tie(A, b) = gfg.jacobian(); // incorrect ! + Matrix AtA; + Vector eta; + boost::tie(AtA, eta) = gfg.hessian(); // correct + EXPECT(assert_equal(A.transpose() * A, AtA)); + Vector expected = -(Vector(6) << -25, 17.5, 5, -13.5, 29, 4).finished(); EXPECT(assert_equal(expected, eta)); - EXPECT(assert_equal(A.transpose()*b, eta)); + EXPECT(assert_equal(A.transpose() * b, eta)); } /* ************************************************************************* */ -TEST( GaussianFactorGraph, gradientAtZero ) -{ +TEST(GaussianFactorGraph, gradientAtZero) { GaussianFactorGraph gfg = createGaussianFactorGraphWithHessianFactor(); VectorValues expected; VectorValues actual = gfg.gradientAtZero(); @@ -340,29 +344,28 @@ TEST( GaussianFactorGraph, gradientAtZero ) } /* ************************************************************************* */ -TEST( GaussianFactorGraph, clone ) { +TEST(GaussianFactorGraph, clone) { // 2 variables, frontal has dim=4 VerticalBlockMatrix blockMatrix(list_of(4)(2)(1), 4); - blockMatrix.matrix() << - 1.0, 0.0, 2.0, 0.0, 3.0, 0.0, 0.1, - 0.0, 1.0, 0.0, 2.0, 0.0, 3.0, 0.2, - 0.0, 0.0, 3.0, 0.0, 4.0, 0.0, 0.3, - 0.0, 0.0, 0.0, 3.0, 0.0, 4.0, 0.4; + blockMatrix.matrix() << 1.0, 0.0, 2.0, 0.0, 3.0, 0.0, 0.1, 0.0, 1.0, 0.0, 2.0, 0.0, 3.0, 0.2, 0.0, + 0.0, 3.0, 0.0, 4.0, 0.0, 0.3, 0.0, 0.0, 0.0, 3.0, 0.0, 4.0, 0.4; GaussianConditional cg(list_of(1)(2), 1, blockMatrix); GaussianFactorGraph init_graph = createGaussianFactorGraphWithHessianFactor(); - init_graph.push_back(GaussianFactor::shared_ptr()); /// Add null factor + init_graph.push_back(GaussianFactor::shared_ptr()); /// Add null factor init_graph.push_back(GaussianConditional(cg)); - GaussianFactorGraph exp_graph = createGaussianFactorGraphWithHessianFactor(); // Created separately - exp_graph.push_back(GaussianFactor::shared_ptr()); /// Add null factor + GaussianFactorGraph exp_graph = + createGaussianFactorGraphWithHessianFactor(); // Created separately + exp_graph.push_back(GaussianFactor::shared_ptr()); /// Add null factor exp_graph.push_back(GaussianConditional(cg)); GaussianFactorGraph actCloned = init_graph.clone(); - EXPECT(assert_equal(init_graph, actCloned)); // Same as the original version + EXPECT(assert_equal(init_graph, actCloned)); // Same as the original version // Apply an in-place change to init_graph and compare - JacobianFactor::shared_ptr jacFactor0 = boost::dynamic_pointer_cast(init_graph.at(0)); + JacobianFactor::shared_ptr jacFactor0 = + boost::dynamic_pointer_cast(init_graph.at(0)); CHECK(jacFactor0); jacFactor0->getA(jacFactor0->begin()) *= 7.; EXPECT(assert_inequal(init_graph, exp_graph)); @@ -370,9 +373,9 @@ TEST( GaussianFactorGraph, clone ) { } /* ************************************************************************* */ -TEST( GaussianFactorGraph, negate ) { +TEST(GaussianFactorGraph, negate) { GaussianFactorGraph init_graph = createGaussianFactorGraphWithHessianFactor(); - init_graph.push_back(GaussianFactor::shared_ptr()); /// Add null factor + init_graph.push_back(GaussianFactor::shared_ptr()); /// Add null factor GaussianFactorGraph actNegation = init_graph.negate(); GaussianFactorGraph expNegation; expNegation.push_back(init_graph.at(0)->negate()); @@ -385,8 +388,7 @@ TEST( GaussianFactorGraph, negate ) { } /* ************************************************************************* */ -TEST( GaussianFactorGraph, hessianDiagonal ) -{ +TEST(GaussianFactorGraph, hessianDiagonal) { GaussianFactorGraph gfg = createGaussianFactorGraphWithHessianFactor(); VectorValues expected; Matrix infoMatrix = gfg.hessian().first; @@ -399,6 +401,16 @@ TEST( GaussianFactorGraph, hessianDiagonal ) EXPECT(assert_equal(expected, actual)); } +TEST(GaussianFactorGraph, DenseSolve) { + GaussianFactorGraph fg = createSimpleGaussianFactorGraph(); + VectorValues expected = fg.optimize(); + VectorValues actual = fg.optimizeDensely(); + EXPECT(assert_equal(expected, actual)); +} + /* ************************************************************************* */ -int main() { TestResult tr; return TestRegistry::runAllTests(tr);} +int main() { + TestResult tr; + return TestRegistry::runAllTests(tr); +} /* ************************************************************************* */ diff --git a/gtsam/linear/tests/testHessianFactor.cpp b/gtsam/linear/tests/testHessianFactor.cpp index 911100337..61fa8bd2c 100644 --- a/gtsam/linear/tests/testHessianFactor.cpp +++ b/gtsam/linear/tests/testHessianFactor.cpp @@ -53,8 +53,8 @@ TEST(HessianFactor, emptyConstructor) { HessianFactor f; DOUBLES_EQUAL(0.0, f.constantTerm(), 1e-9); // Constant term should be zero - EXPECT(assert_equal(Vector(), f.linearTerm())); // Linear term should be empty - EXPECT(assert_equal((Matrix) Z_1x1, f.info())); // Full matrix should be 1-by-1 zero matrix + //EXPECT(assert_equal(Vector(), f.linearTerm())); // Linear term should be empty + EXPECT(assert_equal((Matrix) Z_1x1, f.info().selfadjointView())); // Full matrix should be 1-by-1 zero matrix DOUBLES_EQUAL(0.0, f.error(VectorValues()), 1e-9); // Should have zero error } @@ -103,7 +103,7 @@ TEST(HessianFactor, Constructor1) HessianFactor factor(0, G, g, f); // extract underlying parts - EXPECT(assert_equal(G, Matrix(factor.info(factor.begin(), factor.begin())))); + EXPECT(assert_equal(G, Matrix(factor.info().diagonalBlock(0)))); EXPECT_DOUBLES_EQUAL(f, factor.constantTerm(), 1e-10); EXPECT(assert_equal(g, Vector(factor.linearTerm()))); EXPECT_LONGS_EQUAL(1, (long)factor.size()); @@ -118,7 +118,6 @@ TEST(HessianFactor, Constructor1) EXPECT_DOUBLES_EQUAL(expected, actual, 1e-10); } - /* ************************************************************************* */ TEST(HessianFactor, Constructor1b) { @@ -132,7 +131,7 @@ TEST(HessianFactor, Constructor1b) double f = dot(g,mu); // Check - EXPECT(assert_equal(G, Matrix(factor.info(factor.begin(), factor.begin())))); + EXPECT(assert_equal(G, Matrix(factor.info().diagonalBlock(0)))); EXPECT_DOUBLES_EQUAL(f, factor.constantTerm(), 1e-10); EXPECT(assert_equal(g, Vector(factor.linearTerm()))); EXPECT_LONGS_EQUAL(1, (long)factor.size()); @@ -167,9 +166,9 @@ TEST(HessianFactor, Constructor2) Vector linearExpected(3); linearExpected << g1, g2; EXPECT(assert_equal(linearExpected, factor.linearTerm())); - EXPECT(assert_equal(G11, factor.info(factor.begin(), factor.begin()))); - EXPECT(assert_equal(G12, factor.info(factor.begin(), factor.begin()+1))); - EXPECT(assert_equal(G22, factor.info(factor.begin()+1, factor.begin()+1))); + EXPECT(assert_equal(G11, factor.info().diagonalBlock(0))); + EXPECT(assert_equal(G12, factor.info().aboveDiagonalBlock(0, 1))); + EXPECT(assert_equal(G22, factor.info().diagonalBlock(1))); // Check case when vector values is larger than factor VectorValues dxLarge = pair_list_of @@ -218,12 +217,12 @@ TEST(HessianFactor, Constructor3) Vector linearExpected(6); linearExpected << g1, g2, g3; EXPECT(assert_equal(linearExpected, factor.linearTerm())); - EXPECT(assert_equal(G11, factor.info(factor.begin()+0, factor.begin()+0))); - EXPECT(assert_equal(G12, factor.info(factor.begin()+0, factor.begin()+1))); - EXPECT(assert_equal(G13, factor.info(factor.begin()+0, factor.begin()+2))); - EXPECT(assert_equal(G22, factor.info(factor.begin()+1, factor.begin()+1))); - EXPECT(assert_equal(G23, factor.info(factor.begin()+1, factor.begin()+2))); - EXPECT(assert_equal(G33, factor.info(factor.begin()+2, factor.begin()+2))); + EXPECT(assert_equal(G11, factor.info().diagonalBlock(0))); + EXPECT(assert_equal(G12, factor.info().aboveDiagonalBlock(0, 1))); + EXPECT(assert_equal(G13, factor.info().aboveDiagonalBlock(0, 2))); + EXPECT(assert_equal(G22, factor.info().diagonalBlock(1))); + EXPECT(assert_equal(G23, factor.info().aboveDiagonalBlock(1, 2))); + EXPECT(assert_equal(G33, factor.info().diagonalBlock(2))); } /* ************************************************************************* */ @@ -271,12 +270,12 @@ TEST(HessianFactor, ConstructorNWay) Vector linearExpected(6); linearExpected << g1, g2, g3; EXPECT(assert_equal(linearExpected, factor.linearTerm())); - EXPECT(assert_equal(G11, factor.info(factor.begin()+0, factor.begin()+0))); - EXPECT(assert_equal(G12, factor.info(factor.begin()+0, factor.begin()+1))); - EXPECT(assert_equal(G13, factor.info(factor.begin()+0, factor.begin()+2))); - EXPECT(assert_equal(G22, factor.info(factor.begin()+1, factor.begin()+1))); - EXPECT(assert_equal(G23, factor.info(factor.begin()+1, factor.begin()+2))); - EXPECT(assert_equal(G33, factor.info(factor.begin()+2, factor.begin()+2))); + EXPECT(assert_equal(G11, factor.info().diagonalBlock(0))); + EXPECT(assert_equal(G12, factor.info().aboveDiagonalBlock(0, 1))); + EXPECT(assert_equal(G13, factor.info().aboveDiagonalBlock(0, 2))); + EXPECT(assert_equal(G22, factor.info().diagonalBlock(1))); + EXPECT(assert_equal(G23, factor.info().aboveDiagonalBlock(1, 2))); + EXPECT(assert_equal(G33, factor.info().diagonalBlock(2))); } /* ************************************************************************* */ @@ -499,7 +498,7 @@ TEST(HessianFactor, combine) { -100.0000, 0.0, 20.0000, 0.0, 80.0000, 0.0, -20.0000, 0.0, -100.0000, 0.0, 20.0000, 0.0, 80.0000, 14.0000, 25.0000, -17.5000, -5.0000, 3.5000, -20.0000, 14.0000, 7.4500).finished(); - EXPECT(assert_equal(expected, Matrix(actual.matrixObject().full()), tol)); + EXPECT(assert_equal(expected, Matrix(actual.info().selfadjointView()), tol)); } @@ -575,6 +574,23 @@ TEST(HessianFactor, hessianDiagonal) EXPECT(assert_equal(G22,actualBD[1])); } +/* ************************************************************************* */ +TEST(HessianFactor, Solve) +{ + Matrix2 A; + A << 1, 2, 3, 4; + Matrix2 G = A.transpose() * A; + Vector2 b(5, 6); + Vector2 g = A.transpose() * b; + double f = 0; + Key key(55); + HessianFactor factor(key, G, g, f); + + VectorValues expected; + expected.insert(key, A.inverse() * b); + EXPECT(assert_equal(expected, factor.solve())); +} + /* ************************************************************************* */ int main() { TestResult tr; return TestRegistry::runAllTests(tr);} /* ************************************************************************* */ diff --git a/gtsam/linear/tests/testNoiseModel.cpp b/gtsam/linear/tests/testNoiseModel.cpp index d4403d3e3..6b130bea0 100644 --- a/gtsam/linear/tests/testNoiseModel.cpp +++ b/gtsam/linear/tests/testNoiseModel.cpp @@ -448,6 +448,15 @@ TEST(NoiseModel, WhitenInPlace) } /* ************************************************************************* */ + +/* + * These tests are responsible for testing the weight functions for the m-estimators in GTSAM. + * The weight function is related to the analytic derivative of the residual function. See + * http://research.microsoft.com/en-us/um/people/zhang/INRIA/Publis/Tutorial-Estim/node24.html + * for details. This weight function is required when optimizing cost functions with robust + * penalties using iteratively re-weighted least squares. + */ + TEST(NoiseModel, robustFunctionHuber) { const double k = 5.0, error1 = 1.0, error2 = 10.0; @@ -478,6 +487,26 @@ TEST(NoiseModel, robustFunctionDCS) DOUBLES_EQUAL(0.00039211, weight2, 1e-8); } +TEST(NoiseModel, robustFunctionL2WithDeadZone) +{ + const double k = 1.0, e0 = -10.0, e1 = -1.01, e2 = -0.99, e3 = 0.99, e4 = 1.01, e5 = 10.0; + const mEstimator::L2WithDeadZone::shared_ptr lsdz = mEstimator::L2WithDeadZone::Create(k); + + DOUBLES_EQUAL(0.9, lsdz->weight(e0), 1e-8); + DOUBLES_EQUAL(0.00990099009, lsdz->weight(e1), 1e-8); + DOUBLES_EQUAL(0.0, lsdz->weight(e2), 1e-8); + DOUBLES_EQUAL(0.0, lsdz->weight(e3), 1e-8); + DOUBLES_EQUAL(0.00990099009, lsdz->weight(e4), 1e-8); + DOUBLES_EQUAL(0.9, lsdz->weight(e5), 1e-8); + + DOUBLES_EQUAL(40.5, lsdz->residual(e0), 1e-8); + DOUBLES_EQUAL(0.00005, lsdz->residual(e1), 1e-8); + DOUBLES_EQUAL(0.0, lsdz->residual(e2), 1e-8); + DOUBLES_EQUAL(0.0, lsdz->residual(e3), 1e-8); + DOUBLES_EQUAL(0.00005, lsdz->residual(e4), 1e-8); + DOUBLES_EQUAL(40.5, lsdz->residual(e5), 1e-8); +} + /* ************************************************************************* */ TEST(NoiseModel, robustNoiseHuber) { @@ -550,6 +579,31 @@ TEST(NoiseModel, robustNoiseDCS) DOUBLES_EQUAL(sqrt_weight*a11, A(1,1), 1e-8); } +TEST(NoiseModel, robustNoiseL2WithDeadZone) +{ + double dead_zone_size = 1.0; + SharedNoiseModel robust = noiseModel::Robust::Create( + noiseModel::mEstimator::L2WithDeadZone::Create(dead_zone_size), + Unit::Create(3)); + +/* + * TODO(mike): There is currently a bug in GTSAM, where none of the mEstimator classes + * implement a residual function, and GTSAM calls the weight function to evaluate the + * total penalty, rather than calling the residual function. The weight function should be + * used during iteratively reweighted least squares optimization, but should not be used to + * evaluate the total penalty. The long-term solution is for all mEstimators to implement + * both a weight and a residual function, and for GTSAM to call the residual function when + * evaluating the total penalty. This bug causes the test below to fail, so I'm leaving it + * commented out until the underlying bug in GTSAM is fixed. + * + * for (int i = 0; i < 5; i++) { + * Vector3 error = Vector3(i, 0, 0); + * DOUBLES_EQUAL(0.5*max(0,i-1)*max(0,i-1), robust->distance(error), 1e-8); + * } + */ + +} + /* ************************************************************************* */ #define TEST_GAUSSIAN(gaussian)\ EQUALITY(info, gaussian->information());\ diff --git a/gtsam/linear/tests/testRegularHessianFactor.cpp b/gtsam/linear/tests/testRegularHessianFactor.cpp index f53803dd1..1618451f3 100644 --- a/gtsam/linear/tests/testRegularHessianFactor.cpp +++ b/gtsam/linear/tests/testRegularHessianFactor.cpp @@ -128,9 +128,8 @@ TEST(RegularHessianFactor, Constructors) EXPECT(assert_equal(2*expected_y, fast_y)); // check some expressions - EXPECT(assert_equal(G12,factor.info(i1,i2).knownOffDiagonal())); - EXPECT(assert_equal(G22,factor.info(i2,i2).selfadjointView())); - EXPECT(assert_equal((Matrix)G12.transpose(),factor.info(i2,i1).knownOffDiagonal())); + EXPECT(assert_equal(G12,factor.info().aboveDiagonalBlock(i1 - factor.begin(), i2 - factor.begin()))); + EXPECT(assert_equal(G22,factor.info().diagonalBlock(i2 - factor.begin()))); } } diff --git a/gtsam/linear/tests/testVectorValues.cpp b/gtsam/linear/tests/testVectorValues.cpp index 949ec3a59..7e972903a 100644 --- a/gtsam/linear/tests/testVectorValues.cpp +++ b/gtsam/linear/tests/testVectorValues.cpp @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- - * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) @@ -188,6 +188,14 @@ TEST(VectorValues, convert) VectorValues actual(x,dims); EXPECT(assert_equal(expected, actual)); + Scatter scatter; + scatter.emplace_back(0,1); + scatter.emplace_back(1,2); + scatter.emplace_back(2,2); + scatter.emplace_back(5,2); + VectorValues actual2(x,scatter); + EXPECT(assert_equal(expected, actual2)); + // Test other direction, note vector() is not guaranteed to give right result FastVector keys = list_of(0)(1)(2)(5); EXPECT(assert_equal(x, actual.vector(keys))); diff --git a/gtsam/navigation/ImuFactor.cpp b/gtsam/navigation/ImuFactor.cpp index 7210f4dd2..cc1dc087e 100644 --- a/gtsam/navigation/ImuFactor.cpp +++ b/gtsam/navigation/ImuFactor.cpp @@ -96,8 +96,9 @@ void PreintegratedImuMeasurements::integrateMeasurements( void PreintegratedImuMeasurements::mergeWith(const PreintegratedImuMeasurements& pim12, // Matrix9* H1, Matrix9* H2) { PreintegrationType::mergeWith(pim12, H1, H2); - preintMeasCov_ = - *H1 * preintMeasCov_ * H1->transpose() + *H2 * pim12.preintMeasCov_ * H2->transpose(); + // NOTE(gareth): Temporary P is needed as of Eigen 3.3 + const Matrix9 P = *H1 * preintMeasCov_ * H1->transpose(); + preintMeasCov_ = P + *H2 * pim12.preintMeasCov_ * H2->transpose(); } #endif //------------------------------------------------------------------------------ diff --git a/gtsam/navigation/ManifoldPreintegration.h b/gtsam/navigation/ManifoldPreintegration.h index 8a9d44755..92d3f4814 100644 --- a/gtsam/navigation/ManifoldPreintegration.h +++ b/gtsam/navigation/ManifoldPreintegration.h @@ -75,7 +75,7 @@ public: /// @{ NavState deltaXij() const override { return deltaXij_; } Rot3 deltaRij() const override { return deltaXij_.attitude(); } - Vector3 deltaPij() const override { return deltaXij_.position().vector(); } + Vector3 deltaPij() const override { return deltaXij_.position(); } Vector3 deltaVij() const override { return deltaXij_.velocity(); } Matrix3 delRdelBiasOmega() const { return delRdelBiasOmega_; } diff --git a/gtsam/nonlinear/DoglegOptimizer.cpp b/gtsam/nonlinear/DoglegOptimizer.cpp index a91515e9c..97326f06c 100644 --- a/gtsam/nonlinear/DoglegOptimizer.cpp +++ b/gtsam/nonlinear/DoglegOptimizer.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include @@ -25,8 +26,6 @@ #include -using namespace std; - namespace gtsam { /* ************************************************************************* */ @@ -51,10 +50,41 @@ std::string DoglegParams::verbosityDLTranslator(VerbosityDL verbosityDL) const { } /* ************************************************************************* */ -void DoglegOptimizer::iterate(void) { +namespace internal { +struct DoglegState : public NonlinearOptimizerState { + const double delta; + + DoglegState(const Values& values, double error, double delta, unsigned int iterations = 0) + : NonlinearOptimizerState(values, error, iterations), delta(delta) {} +}; +} + +typedef internal::DoglegState State; + +/* ************************************************************************* */ +DoglegOptimizer::DoglegOptimizer(const NonlinearFactorGraph& graph, const Values& initialValues, + const DoglegParams& params) + : NonlinearOptimizer( + graph, std::unique_ptr( + new State(initialValues, graph.error(initialValues), params.deltaInitial))), + params_(ensureHasOrdering(params, graph)) {} + +DoglegOptimizer::DoglegOptimizer(const NonlinearFactorGraph& graph, const Values& initialValues, + const Ordering& ordering) + : NonlinearOptimizer(graph, std::unique_ptr( + new State(initialValues, graph.error(initialValues), 1.0))) { + params_.ordering = ordering; +} + +double DoglegOptimizer::getDelta() const { + return static_cast(state_.get())->delta; +} + +/* ************************************************************************* */ +GaussianFactorGraph::shared_ptr DoglegOptimizer::iterate(void) { // Linearize graph - GaussianFactorGraph::shared_ptr linear = graph_.linearize(state_.values); + GaussianFactorGraph::shared_ptr linear = graph_.linearize(state_->values); // Pull out parameters we'll use const bool dlVerbose = (params_.verbosityDL > DoglegParams::SILENT); @@ -66,31 +96,30 @@ void DoglegOptimizer::iterate(void) { GaussianBayesTree bt = *linear->eliminateMultifrontal(*params_.ordering, params_.getEliminationFunction()); VectorValues dx_u = bt.optimizeGradientSearch(); VectorValues dx_n = bt.optimize(); - result = DoglegOptimizerImpl::Iterate(state_.Delta, DoglegOptimizerImpl::ONE_STEP_PER_ITERATION, - dx_u, dx_n, bt, graph_, state_.values, state_.error, dlVerbose); + result = DoglegOptimizerImpl::Iterate(getDelta(), DoglegOptimizerImpl::ONE_STEP_PER_ITERATION, + dx_u, dx_n, bt, graph_, state_->values, state_->error, dlVerbose); } else if ( params_.isSequential() ) { GaussianBayesNet bn = *linear->eliminateSequential(*params_.ordering, params_.getEliminationFunction()); VectorValues dx_u = bn.optimizeGradientSearch(); VectorValues dx_n = bn.optimize(); - result = DoglegOptimizerImpl::Iterate(state_.Delta, DoglegOptimizerImpl::ONE_STEP_PER_ITERATION, - dx_u, dx_n, bn, graph_, state_.values, state_.error, dlVerbose); + result = DoglegOptimizerImpl::Iterate(getDelta(), DoglegOptimizerImpl::ONE_STEP_PER_ITERATION, + dx_u, dx_n, bn, graph_, state_->values, state_->error, dlVerbose); } else if ( params_.isIterative() ) { - throw runtime_error("Dogleg is not currently compatible with the linear conjugate gradient solver"); + throw std::runtime_error("Dogleg is not currently compatible with the linear conjugate gradient solver"); } else { - throw runtime_error("Optimization parameter is invalid: DoglegParams::elimination"); + throw std::runtime_error("Optimization parameter is invalid: DoglegParams::elimination"); } // Maybe show output if(params_.verbosity >= NonlinearOptimizerParams::DELTA) result.dx_d.print("delta"); // Create new state with new values and new error - state_.values = state_.values.retract(result.dx_d); - state_.error = result.f_error; - state_.Delta = result.Delta; - ++state_.iterations; + state_.reset(new State(state_->values.retract(result.dx_d), result.f_error, result.delta, + state_->iterations + 1)); + return linear; } /* ************************************************************************* */ diff --git a/gtsam/nonlinear/DoglegOptimizer.h b/gtsam/nonlinear/DoglegOptimizer.h index 8a43b4d96..7013908e5 100644 --- a/gtsam/nonlinear/DoglegOptimizer.h +++ b/gtsam/nonlinear/DoglegOptimizer.h @@ -11,7 +11,7 @@ /** * @file DoglegOptimizer.h - * @brief + * @brief * @author Richard Roberts * @date Feb 26, 2012 */ @@ -45,7 +45,7 @@ public: virtual ~DoglegParams() {} - virtual void print(const std::string& str = "") const { + void print(const std::string& str = "") const override { NonlinearOptimizerParams::print(str); std::cout << " deltaInitial: " << deltaInitial << "\n"; std::cout.flush(); @@ -62,24 +62,6 @@ private: std::string verbosityDLTranslator(VerbosityDL verbosityDL) const; }; -/** - * State for DoglegOptimizer - */ -class GTSAM_EXPORT DoglegState : public NonlinearOptimizerState { -public: - double Delta; - - DoglegState() {} - - virtual ~DoglegState() {} - -protected: - DoglegState(const NonlinearFactorGraph& graph, const Values& values, const DoglegParams& params, unsigned int iterations = 0) : - NonlinearOptimizerState(graph, values, iterations), Delta(params.deltaInitial) {} - - friend class DoglegOptimizer; -}; - /** * This class performs Dogleg nonlinear optimization */ @@ -87,7 +69,6 @@ class GTSAM_EXPORT DoglegOptimizer : public NonlinearOptimizer { protected: DoglegParams params_; - DoglegState state_; public: typedef boost::shared_ptr shared_ptr; @@ -104,8 +85,7 @@ public: * @param params The optimization parameters */ DoglegOptimizer(const NonlinearFactorGraph& graph, const Values& initialValues, - const DoglegParams& params = DoglegParams()) : - NonlinearOptimizer(graph), params_(ensureHasOrdering(params, graph)), state_(graph, initialValues, params_) {} + const DoglegParams& params = DoglegParams()); /** Standard constructor, requires a nonlinear factor graph, initial * variable assignments, and optimization parameters. For convenience this @@ -114,10 +94,8 @@ public: * @param graph The nonlinear factor graph to optimize * @param initialValues The initial variable assignments */ - DoglegOptimizer(const NonlinearFactorGraph& graph, const Values& initialValues, const Ordering& ordering) : - NonlinearOptimizer(graph) { - params_.ordering = ordering; - state_ = DoglegState(graph, initialValues, params_); } + DoglegOptimizer(const NonlinearFactorGraph& graph, const Values& initialValues, + const Ordering& ordering); /// @} @@ -131,31 +109,19 @@ public: * containing the updated variable assignments, which may be retrieved with * values(). */ - virtual void iterate(); + GaussianFactorGraph::shared_ptr iterate() override; /** Read-only access the parameters */ const DoglegParams& params() const { return params_; } - /** Read/write access the parameters. */ - DoglegParams& params() { return params_; } - - /** Read-only access the last state */ - const DoglegState& state() const { return state_; } - - /** Read/write access the last state. When modifying the state, the error, etc. must be consistent before calling iterate() */ - DoglegState& state() { return state_; } - - /** Access the current trust region radius Delta */ - double getDelta() const { return state_.Delta; } + /** Access the current trust region radius delta */ + double getDelta() const; /// @} protected: /** Access the parameters (base class version) */ - virtual const NonlinearOptimizerParams& _params() const { return params_; } - - /** Access the state (base class version) */ - virtual const NonlinearOptimizerState& _state() const { return state_; } + virtual const NonlinearOptimizerParams& _params() const override { return params_; } /** Internal function for computing a COLAMD ordering if no ordering is specified */ DoglegParams ensureHasOrdering(DoglegParams params, const NonlinearFactorGraph& graph) const; diff --git a/gtsam/nonlinear/DoglegOptimizerImpl.cpp b/gtsam/nonlinear/DoglegOptimizerImpl.cpp index 671dfe8f8..c319f26e6 100644 --- a/gtsam/nonlinear/DoglegOptimizerImpl.cpp +++ b/gtsam/nonlinear/DoglegOptimizerImpl.cpp @@ -23,24 +23,24 @@ using namespace std; namespace gtsam { /* ************************************************************************* */ VectorValues DoglegOptimizerImpl::ComputeDoglegPoint( - double Delta, const VectorValues& dx_u, const VectorValues& dx_n, const bool verbose) { + double delta, const VectorValues& dx_u, const VectorValues& dx_n, const bool verbose) { - // Get magnitude of each update and find out which segment Delta falls in - assert(Delta >= 0.0); - double DeltaSq = Delta*Delta; + // Get magnitude of each update and find out which segment delta falls in + assert(delta >= 0.0); + double deltaSq = delta*delta; double x_u_norm_sq = dx_u.squaredNorm(); double x_n_norm_sq = dx_n.squaredNorm(); if(verbose) cout << "Steepest descent magnitude " << std::sqrt(x_u_norm_sq) << ", Newton's method magnitude " << std::sqrt(x_n_norm_sq) << endl; - if(DeltaSq < x_u_norm_sq) { + if(deltaSq < x_u_norm_sq) { // Trust region is smaller than steepest descent update - VectorValues x_d = std::sqrt(DeltaSq / x_u_norm_sq) * dx_u; - if(verbose) cout << "In steepest descent region with fraction " << std::sqrt(DeltaSq / x_u_norm_sq) << " of steepest descent magnitude" << endl; + VectorValues x_d = std::sqrt(deltaSq / x_u_norm_sq) * dx_u; + if(verbose) cout << "In steepest descent region with fraction " << std::sqrt(deltaSq / x_u_norm_sq) << " of steepest descent magnitude" << endl; return x_d; - } else if(DeltaSq < x_n_norm_sq) { + } else if(deltaSq < x_n_norm_sq) { // Trust region boundary is between steepest descent point and Newton's method point - return ComputeBlend(Delta, dx_u, dx_n, verbose); + return ComputeBlend(delta, dx_u, dx_n, verbose); } else { - assert(DeltaSq >= x_n_norm_sq); + assert(deltaSq >= x_n_norm_sq); if(verbose) cout << "In pure Newton's method region" << endl; // Trust region is larger than Newton's method point return dx_n; @@ -48,7 +48,7 @@ VectorValues DoglegOptimizerImpl::ComputeDoglegPoint( } /* ************************************************************************* */ -VectorValues DoglegOptimizerImpl::ComputeBlend(double Delta, const VectorValues& x_u, const VectorValues& x_n, const bool verbose) { +VectorValues DoglegOptimizerImpl::ComputeBlend(double delta, const VectorValues& x_u, const VectorValues& x_n, const bool verbose) { // See doc/trustregion.lyx or doc/trustregion.pdf @@ -60,7 +60,7 @@ VectorValues DoglegOptimizerImpl::ComputeBlend(double Delta, const VectorValues& // Compute quadratic formula terms const double a = uu - 2.*un + nn; const double b = 2. * (un - uu); - const double c = uu - Delta*Delta; + const double c = uu - delta*delta; double sqrt_b_m4ac = std::sqrt(b*b - 4*a*c); // Compute blending parameter diff --git a/gtsam/nonlinear/DoglegOptimizerImpl.h b/gtsam/nonlinear/DoglegOptimizerImpl.h index dea4113f7..cead7f9db 100644 --- a/gtsam/nonlinear/DoglegOptimizerImpl.h +++ b/gtsam/nonlinear/DoglegOptimizerImpl.h @@ -32,7 +32,7 @@ namespace gtsam { struct GTSAM_EXPORT DoglegOptimizerImpl { struct GTSAM_EXPORT IterationResult { - double Delta; + double delta; VectorValues dx_d; double f_error; }; @@ -58,7 +58,7 @@ struct GTSAM_EXPORT DoglegOptimizerImpl { /** * Compute the update point for one iteration of the Dogleg algorithm, given - * an initial trust region radius \f$ \Delta \f$. The trust region radius is + * an initial trust region radius \f$ \delta \f$. The trust region radius is * adapted based on the error of a NonlinearFactorGraph \f$ f(x) \f$, and * depending on the update mode \c mode. * @@ -80,24 +80,24 @@ struct GTSAM_EXPORT DoglegOptimizerImpl { * @tparam F For normal usage this will be NonlinearFactorGraph. * @tparam VALUES The Values or TupleValues to pass to F::error() to evaluate * the error function. - * @param Delta The initial trust region radius. + * @param delta The initial trust region radius. * @param mode See DoglegOptimizerImpl::TrustRegionAdaptationMode * @param Rd The Bayes' net or tree as described above. * @param f The original nonlinear factor graph with which to evaluate the - * accuracy of \f$ M(\delta x) \f$ to adjust \f$ \Delta \f$. + * accuracy of \f$ M(\delta x) \f$ to adjust \f$ \delta \f$. * @param x0 The linearization point about which \f$ \bayesNet \f$ was created * @param ordering The variable ordering used to create\f$ \bayesNet \f$ * @param f_error The result of f.error(x0). - * @return A DoglegIterationResult containing the new \c Delta, the linear + * @return A DoglegIterationResult containing the new \c delta, the linear * update \c dx_d, and the resulting nonlinear error \c f_error. */ template static IterationResult Iterate( - double Delta, TrustRegionAdaptationMode mode, const VectorValues& dx_u, const VectorValues& dx_n, + double delta, TrustRegionAdaptationMode mode, const VectorValues& dx_u, const VectorValues& dx_n, const M& Rd, const F& f, const VALUES& x0, const double f_error, const bool verbose=false); /** - * Compute the dogleg point given a trust region radius \f$ \Delta \f$. The + * Compute the dogleg point given a trust region radius \f$ \delta \f$. The * dogleg point is the intersection between the dogleg path and the trust * region boundary, see doc/trustregion.pdf for more details. * @@ -113,30 +113,30 @@ struct GTSAM_EXPORT DoglegOptimizerImpl { * upper-triangular and \f$ d \f$ is a vector, in GTSAM represented as a * GaussianBayesNet, containing GaussianConditional s. * - * @param Delta The trust region radius + * @param delta The trust region radius * @param dx_u The steepest descent point, i.e. the Cauchy point * @param dx_n The Gauss-Newton point * @return The dogleg point \f$ \delta x_d \f$ */ - static VectorValues ComputeDoglegPoint(double Delta, const VectorValues& dx_u, const VectorValues& dx_n, const bool verbose=false); + static VectorValues ComputeDoglegPoint(double delta, const VectorValues& dx_u, const VectorValues& dx_n, const bool verbose=false); /** Compute the point on the line between the steepest descent point and the * Newton's method point intersecting the trust region boundary. * Mathematically, computes \f$ \tau \f$ such that \f$ 0<\tau<1 \f$ and - * \f$ \| (1-\tau)\delta x_u + \tau\delta x_n \| = \Delta \f$, where \f$ \Delta \f$ + * \f$ \| (1-\tau)\delta x_u + \tau\delta x_n \| = \delta \f$, where \f$ \delta \f$ * is the trust region radius. - * @param Delta Trust region radius + * @param delta Trust region radius * @param x_u Steepest descent minimizer * @param x_n Newton's method minimizer */ - static VectorValues ComputeBlend(double Delta, const VectorValues& x_u, const VectorValues& x_n, const bool verbose=false); + static VectorValues ComputeBlend(double delta, const VectorValues& x_u, const VectorValues& x_n, const bool verbose=false); }; /* ************************************************************************* */ template typename DoglegOptimizerImpl::IterationResult DoglegOptimizerImpl::Iterate( - double Delta, TrustRegionAdaptationMode mode, const VectorValues& dx_u, const VectorValues& dx_n, + double delta, TrustRegionAdaptationMode mode, const VectorValues& dx_u, const VectorValues& dx_n, const M& Rd, const F& f, const VALUES& x0, const double f_error, const bool verbose) { gttic(M_error); @@ -151,10 +151,10 @@ typename DoglegOptimizerImpl::IterationResult DoglegOptimizerImpl::Iterate( while(stay) { gttic(Dog_leg_point); // Compute dog leg point - result.dx_d = ComputeDoglegPoint(Delta, dx_u, dx_n, verbose); + result.dx_d = ComputeDoglegPoint(delta, dx_u, dx_n, verbose); gttoc(Dog_leg_point); - if(verbose) std::cout << "Delta = " << Delta << ", dx_d_norm = " << result.dx_d.norm() << std::endl; + if(verbose) std::cout << "delta = " << delta << ", dx_d_norm = " << result.dx_d.norm() << std::endl; gttic(retract); // Compute expmapped solution @@ -174,7 +174,7 @@ typename DoglegOptimizerImpl::IterationResult DoglegOptimizerImpl::Iterate( if(verbose) std::cout << std::setprecision(15) << "f error: " << f_error << " -> " << result.f_error << std::endl; if(verbose) std::cout << std::setprecision(15) << "M error: " << M_error << " -> " << new_M_error << std::endl; - gttic(adjust_Delta); + gttic(adjust_delta); // Compute gain ratio. Here we take advantage of the invariant that the // Bayes' net error at zero is equal to the nonlinear error const double rho = fabs(f_error - result.f_error) < 1e-15 || fabs(M_error - new_M_error) < 1e-15 ? @@ -186,35 +186,35 @@ typename DoglegOptimizerImpl::IterationResult DoglegOptimizerImpl::Iterate( if(rho >= 0.75) { // M agrees very well with f, so try to increase lambda const double dx_d_norm = result.dx_d.norm(); - const double newDelta = std::max(Delta, 3.0 * dx_d_norm); // Compute new Delta + const double newDelta = std::max(delta, 3.0 * dx_d_norm); // Compute new delta if(mode == ONE_STEP_PER_ITERATION || mode == SEARCH_REDUCE_ONLY) - stay = false; // If not searching, just return with the new Delta + stay = false; // If not searching, just return with the new delta else if(mode == SEARCH_EACH_ITERATION) { - if(fabs(newDelta - Delta) < 1e-15 || lastAction == DECREASED_DELTA) + if(fabs(newDelta - delta) < 1e-15 || lastAction == DECREASED_DELTA) stay = false; // Searching, but Newton's solution is within trust region so keep the same trust region else { - stay = true; // Searching and increased Delta, so try again to increase Delta + stay = true; // Searching and increased delta, so try again to increase delta lastAction = INCREASED_DELTA; } } else { assert(false); } - Delta = newDelta; // Update Delta from new Delta + delta = newDelta; // Update delta from new delta } else if(0.75 > rho && rho >= 0.25) { - // M agrees so-so with f, keep the same Delta + // M agrees so-so with f, keep the same delta stay = false; } else if(0.25 > rho && rho >= 0.0) { - // M does not agree well with f, decrease Delta until it does + // M does not agree well with f, decrease delta until it does double newDelta; bool hitMinimumDelta; - if(Delta > 1e-5) { - newDelta = 0.5 * Delta; + if(delta > 1e-5) { + newDelta = 0.5 * delta; hitMinimumDelta = false; } else { - newDelta = Delta; + newDelta = delta; hitMinimumDelta = true; } if(mode == ONE_STEP_PER_ITERATION || /* mode == SEARCH_EACH_ITERATION && */ lastAction == INCREASED_DELTA || hitMinimumDelta) @@ -225,19 +225,19 @@ typename DoglegOptimizerImpl::IterationResult DoglegOptimizerImpl::Iterate( } else { assert(false); } - Delta = newDelta; // Update Delta from new Delta + delta = newDelta; // Update delta from new delta } else { - // f actually increased, so keep decreasing Delta until f does not decrease. + // f actually increased, so keep decreasing delta until f does not decrease. // NOTE: NaN and Inf solutions also will fall into this case, so that we - // decrease Delta if the solution becomes undetermined. + // decrease delta if the solution becomes undetermined. assert(0.0 > rho); - if(Delta > 1e-5) { - Delta *= 0.5; + if(delta > 1e-5) { + delta *= 0.5; stay = true; lastAction = DECREASED_DELTA; } else { - if(verbose) std::cout << "Warning: Dog leg stopping because cannot decrease error with minimum Delta" << std::endl; + if(verbose) std::cout << "Warning: Dog leg stopping because cannot decrease error with minimum delta" << std::endl; result.dx_d.setZero(); // Set delta to zero - don't allow error to increase result.f_error = f_error; stay = false; @@ -247,7 +247,7 @@ typename DoglegOptimizerImpl::IterationResult DoglegOptimizerImpl::Iterate( } // dx_d and f_error have already been filled in during the loop - result.Delta = Delta; + result.delta = delta; return result; } diff --git a/gtsam/nonlinear/Expression-inl.h b/gtsam/nonlinear/Expression-inl.h index e59201ca7..259bb1efe 100644 --- a/gtsam/nonlinear/Expression-inl.h +++ b/gtsam/nonlinear/Expression-inl.h @@ -263,26 +263,15 @@ template ScalarMultiplyExpression::ScalarMultiplyExpression(double s, const Expression& e) : Expression(boost::make_shared>(s, e)) {} -template -SumExpression::SumExpression(const std::vector>& expressions) - : Expression(boost::make_shared>(expressions)) {} template -SumExpression SumExpression::operator+(const Expression& e) const { - SumExpression copy = *this; - boost::static_pointer_cast>(copy.root_)->add(e); - return copy; -} +BinarySumExpression::BinarySumExpression(const Expression& e1, const Expression& e2) + : Expression(boost::make_shared>(e1, e2)) {} template -SumExpression& SumExpression::operator+=(const Expression& e) { - boost::static_pointer_cast>(this->root_)->add(e); +Expression& Expression::operator+=(const Expression& e) { + root_ = boost::make_shared>(*this, e); return *this; } -template -size_t SumExpression::nrTerms() const { - return boost::static_pointer_cast>(this->root_)->nrTerms(); -} - } // namespace gtsam diff --git a/gtsam/nonlinear/Expression.h b/gtsam/nonlinear/Expression.h index 6ed6bb4a5..7d02d479c 100644 --- a/gtsam/nonlinear/Expression.h +++ b/gtsam/nonlinear/Expression.h @@ -174,6 +174,9 @@ public: /// Return size needed for memory buffer in traceExecution size_t traceSize() const; + /// Add another expression to this expression + Expression& operator+=(const Expression& e); + protected: /// Default constructor, for serialization @@ -217,24 +220,19 @@ class ScalarMultiplyExpression : public Expression { }; /** - * A SumExpression is a specialization of Expression that just sums the arguments + * A BinarySumExpression is a specialization of Expression that adds two expressions together * It optimizes the Jacobian calculation for this specific case */ template -class SumExpression : public Expression { +class BinarySumExpression : public Expression { // Check that T is a vector space BOOST_CONCEPT_ASSERT((gtsam::IsVectorSpace)); public: - explicit SumExpression(const std::vector>& expressions); - - // Syntactic sugar to allow e1 + e2 + e3... - SumExpression operator+(const Expression& e) const; - SumExpression& operator+=(const Expression& e); - - size_t nrTerms() const; + explicit BinarySumExpression(const Expression& e1, const Expression& e2); }; + /** * Create an expression out of a linear function f:T->A with (constant) Jacobian dTdA * TODO(frank): create a more efficient version like ScalarMultiplyExpression. This version still @@ -272,13 +270,14 @@ ScalarMultiplyExpression operator*(double s, const Expression& e) { * Expression a(0), b(1), c = a + b; */ template -SumExpression operator+(const Expression& e1, const Expression& e2) { - return SumExpression({e1, e2}); +BinarySumExpression operator+(const Expression& e1, const Expression& e2) { + return BinarySumExpression(e1, e2); } /// Construct an expression that subtracts one expression from another template -SumExpression operator-(const Expression& e1, const Expression& e2) { +BinarySumExpression operator-(const Expression& e1, const Expression& e2) { + // TODO(frank, abe): Implement an actual negate operator instead of multiplying by -1 return e1 + (-1.0) * e2; } diff --git a/gtsam/nonlinear/ExtendedKalmanFilter-inl.h b/gtsam/nonlinear/ExtendedKalmanFilter-inl.h index e0c4da94e..e85aceb15 100644 --- a/gtsam/nonlinear/ExtendedKalmanFilter-inl.h +++ b/gtsam/nonlinear/ExtendedKalmanFilter-inl.h @@ -61,16 +61,14 @@ namespace gtsam { } /* ************************************************************************* */ - template - ExtendedKalmanFilter::ExtendedKalmanFilter(Key key_initial, T x_initial, - noiseModel::Gaussian::shared_ptr P_initial) { - - // Set the initial linearization point to the provided mean - x_ = x_initial; - + template + ExtendedKalmanFilter::ExtendedKalmanFilter( + Key key_initial, T x_initial, noiseModel::Gaussian::shared_ptr P_initial) + : x_(x_initial) // Set the initial linearization point + { // Create a Jacobian Prior Factor directly P_initial. // Since x0 is set to the provided mean, the b vector in the prior will be zero - // TODO Frank asks: is there a reason why noiseModel is not simply P_initial ? + // TODO(Frank): is there a reason why noiseModel is not simply P_initial? int n = traits::GetDimension(x_initial); priorFactor_ = JacobianFactor::shared_ptr( new JacobianFactor(key_initial, P_initial->R(), Vector::Zero(n), diff --git a/gtsam/nonlinear/GaussNewtonOptimizer.cpp b/gtsam/nonlinear/GaussNewtonOptimizer.cpp index d12c56b6f..c31451e56 100644 --- a/gtsam/nonlinear/GaussNewtonOptimizer.cpp +++ b/gtsam/nonlinear/GaussNewtonOptimizer.cpp @@ -17,36 +17,52 @@ */ #include +#include #include #include -using namespace std; - namespace gtsam { -/* ************************************************************************* */ -void GaussNewtonOptimizer::iterate() { - gttic(GaussNewtonOptimizer_Iterate); +typedef internal::NonlinearOptimizerState State; - const NonlinearOptimizerState& current = state_; +/* ************************************************************************* */ +GaussNewtonOptimizer::GaussNewtonOptimizer(const NonlinearFactorGraph& graph, + const Values& initialValues, + const GaussNewtonParams& params) + : NonlinearOptimizer( + graph, std::unique_ptr(new State(initialValues, graph.error(initialValues)))), + params_(ensureHasOrdering(params, graph)) {} + +GaussNewtonOptimizer::GaussNewtonOptimizer(const NonlinearFactorGraph& graph, + const Values& initialValues, const Ordering& ordering) + : NonlinearOptimizer( + graph, std::unique_ptr(new State(initialValues, graph.error(initialValues)))) { + params_.ordering = ordering; +} + +/* ************************************************************************* */ +GaussianFactorGraph::shared_ptr GaussNewtonOptimizer::iterate() { + gttic(GaussNewtonOptimizer_Iterate); // Linearize graph gttic(GaussNewtonOptimizer_Linearize); - GaussianFactorGraph::shared_ptr linear = graph_.linearize(current.values); + GaussianFactorGraph::shared_ptr linear = graph_.linearize(state_->values); gttoc(GaussNewtonOptimizer_Linearize); // Solve Factor Graph gttic(GaussNewtonOptimizer_Solve); - const VectorValues delta = solve(*linear, current.values, params_); + const VectorValues delta = solve(*linear, params_); gttoc(GaussNewtonOptimizer_Solve); // Maybe show output - if(params_.verbosity >= NonlinearOptimizerParams::DELTA) delta.print("delta"); + if (params_.verbosity >= NonlinearOptimizerParams::DELTA) + delta.print("delta"); // Create new state with new values and new error - state_.values = current.values.retract(delta); - state_.error = graph_.error(state_.values); - ++ state_.iterations; + Values newValues = state_->values.retract(delta); + state_.reset(new State(std::move(newValues), graph_.error(newValues), state_->iterations + 1)); + + return linear; } /* ************************************************************************* */ diff --git a/gtsam/nonlinear/GaussNewtonOptimizer.h b/gtsam/nonlinear/GaussNewtonOptimizer.h index 8b41a979c..3e75fc23d 100644 --- a/gtsam/nonlinear/GaussNewtonOptimizer.h +++ b/gtsam/nonlinear/GaussNewtonOptimizer.h @@ -30,14 +30,6 @@ class GaussNewtonOptimizer; class GTSAM_EXPORT GaussNewtonParams : public NonlinearOptimizerParams { }; -class GTSAM_EXPORT GaussNewtonState : public NonlinearOptimizerState { -protected: - GaussNewtonState(const NonlinearFactorGraph& graph, const Values& values, unsigned int iterations = 0) : - NonlinearOptimizerState(graph, values, iterations) {} - - friend class GaussNewtonOptimizer; -}; - /** * This class performs Gauss-Newton nonlinear optimization */ @@ -45,7 +37,6 @@ class GTSAM_EXPORT GaussNewtonOptimizer : public NonlinearOptimizer { protected: GaussNewtonParams params_; - GaussNewtonState state_; public: /// @name Standard interface @@ -59,9 +50,8 @@ public: * @param initialValues The initial variable assignments * @param params The optimization parameters */ - GaussNewtonOptimizer(const NonlinearFactorGraph& graph, const Values& initialValues, - const GaussNewtonParams& params = GaussNewtonParams()) : - NonlinearOptimizer(graph), params_(ensureHasOrdering(params, graph)), state_(graph, initialValues) {} + GaussNewtonOptimizer(const NonlinearFactorGraph& graph, const Values& initialValues, + const GaussNewtonParams& params = GaussNewtonParams()); /** Standard constructor, requires a nonlinear factor graph, initial * variable assignments, and optimization parameters. For convenience this @@ -70,10 +60,8 @@ public: * @param graph The nonlinear factor graph to optimize * @param initialValues The initial variable assignments */ - GaussNewtonOptimizer(const NonlinearFactorGraph& graph, const Values& initialValues, const Ordering& ordering) : - NonlinearOptimizer(graph), state_(graph, initialValues) { - params_.ordering = ordering; } - + GaussNewtonOptimizer(const NonlinearFactorGraph& graph, const Values& initialValues, + const Ordering& ordering); /// @} /// @name Advanced interface @@ -86,28 +74,16 @@ public: * containing the updated variable assignments, which may be retrieved with * values(). */ - virtual void iterate(); + GaussianFactorGraph::shared_ptr iterate() override; /** Read-only access the parameters */ const GaussNewtonParams& params() const { return params_; } - /** Read/write access the parameters. */ - GaussNewtonParams& params() { return params_; } - - /** Read-only access the last state */ - const GaussNewtonState& state() const { return state_; } - - /** Read/write access the last state. When modifying the state, the error, etc. must be consistent before calling iterate() */ - GaussNewtonState& state() { return state_; } - /// @} protected: /** Access the parameters (base class version) */ - virtual const NonlinearOptimizerParams& _params() const { return params_; } - - /** Access the state (base class version) */ - virtual const NonlinearOptimizerState& _state() const { return state_; } + const NonlinearOptimizerParams& _params() const override { return params_; } /** Internal function for computing a COLAMD ordering if no ordering is specified */ GaussNewtonParams ensureHasOrdering(GaussNewtonParams params, const NonlinearFactorGraph& graph) const; diff --git a/gtsam/nonlinear/ISAM2-inl.h b/gtsam/nonlinear/ISAM2-inl.h index ccaf898d3..f04e16b7d 100644 --- a/gtsam/nonlinear/ISAM2-inl.h +++ b/gtsam/nonlinear/ISAM2-inl.h @@ -140,6 +140,7 @@ bool optimizeWildfireNode(const boost::shared_ptr& clique, double thresh // Solve clique if it was replaced, or if any parents were changed above the // threshold or themselves replaced. + // TODO(gareth): This code shares a lot of logic w/ linearAlgorithms-inst, potentially refactor if(recalculate) { // Temporary copy of the original values, to check how much they change @@ -188,16 +189,21 @@ bool optimizeWildfireNode(const boost::shared_ptr& clique, double thresh vectorPos += parentVector.size(); } } - xS = c.getb() - c.get_S() * xS; - Vector soln = c.get_R().triangularView().solve(xS); + + // NOTE(gareth): We can no longer write: xS = b - S * xS + // This is because Eigen (as of 3.3) no longer evaluates S * xS into + // a temporary, and the operation trashes valus in xS. + // See: http://eigen.tuxfamily.org/index.php?title=3.3 + const Vector rhs = c.getb() - c.get_S() * xS; + const Vector solution = c.get_R().triangularView().solve(rhs); // Check for indeterminant solution - if(soln.hasNaN()) throw IndeterminantLinearSystemException(c.keys().front()); + if(solution.hasNaN()) throw IndeterminantLinearSystemException(c.keys().front()); // Insert solution into a VectorValues DenseIndex vectorPosition = 0; for(GaussianConditional::const_iterator frontal = c.beginFrontals(); frontal != c.endFrontals(); ++frontal) { - clique->solnPointers_.at(*frontal)->second = soln.segment(vectorPosition, c.getDim(frontal)); + clique->solnPointers_.at(*frontal)->second = solution.segment(vectorPosition, c.getDim(frontal)); vectorPosition += c.getDim(frontal); } } diff --git a/gtsam/nonlinear/ISAM2.cpp b/gtsam/nonlinear/ISAM2.cpp index a0244ce14..18296b393 100644 --- a/gtsam/nonlinear/ISAM2.cpp +++ b/gtsam/nonlinear/ISAM2.cpp @@ -1004,7 +1004,7 @@ void ISAM2::updateDelta(bool forceFullSolve) const gttic(Copy_dx_d); // Update Delta and linear step - doglegDelta_ = doglegResult.Delta; + doglegDelta_ = doglegResult.delta; delta_ = doglegResult.dx_d; // Copy the VectorValues containing with the linear solution gttoc(Copy_dx_d); } diff --git a/gtsam/nonlinear/LevenbergMarquardtOptimizer.cpp b/gtsam/nonlinear/LevenbergMarquardtOptimizer.cpp index fdd86d36b..5f29c3bdf 100644 --- a/gtsam/nonlinear/LevenbergMarquardtOptimizer.cpp +++ b/gtsam/nonlinear/LevenbergMarquardtOptimizer.cpp @@ -11,392 +11,286 @@ /** * @file LevenbergMarquardtOptimizer.cpp - * @brief + * @brief A nonlinear optimizer that uses the Levenberg-Marquardt trust-region scheme * @author Richard Roberts + * @author Frank Dellaert * @author Luca Carlone - * @date Feb 26, 2012 + * @date Feb 26, 2012 */ #include -#include +#include +#include +#include #include -#include -#include +#include +#include +#include #include -#include -#include #include +#include +#include +#include #include +#include #include #include -#include using namespace std; namespace gtsam { using boost::adaptors::map_values; +typedef internal::LevenbergMarquardtState State; /* ************************************************************************* */ -LevenbergMarquardtParams::VerbosityLM LevenbergMarquardtParams::verbosityLMTranslator( - const std::string &src) { - std::string s = src; - boost::algorithm::to_upper(s); - if (s == "SILENT") - return LevenbergMarquardtParams::SILENT; - if (s == "SUMMARY") - return LevenbergMarquardtParams::SUMMARY; - if (s == "LAMBDA") - return LevenbergMarquardtParams::LAMBDA; - if (s == "TRYLAMBDA") - return LevenbergMarquardtParams::TRYLAMBDA; - if (s == "TRYCONFIG") - return LevenbergMarquardtParams::TRYCONFIG; - if (s == "TRYDELTA") - return LevenbergMarquardtParams::TRYDELTA; - if (s == "DAMPED") - return LevenbergMarquardtParams::DAMPED; +LevenbergMarquardtOptimizer::LevenbergMarquardtOptimizer(const NonlinearFactorGraph& graph, + const Values& initialValues, + const LevenbergMarquardtParams& params) + : NonlinearOptimizer( + graph, std::unique_ptr(new State(initialValues, graph.error(initialValues), + params.lambdaInitial, params.lambdaFactor))), + params_(LevenbergMarquardtParams::EnsureHasOrdering(params, graph)) {} - /* default is silent */ - return LevenbergMarquardtParams::SILENT; +LevenbergMarquardtOptimizer::LevenbergMarquardtOptimizer(const NonlinearFactorGraph& graph, + const Values& initialValues, + const Ordering& ordering, + const LevenbergMarquardtParams& params) + : NonlinearOptimizer( + graph, std::unique_ptr(new State(initialValues, graph.error(initialValues), + params.lambdaInitial, params.lambdaFactor))), + params_(LevenbergMarquardtParams::ReplaceOrdering(params, ordering)) {} + +/* ************************************************************************* */ +void LevenbergMarquardtOptimizer::initTime() { + startTime_ = boost::posix_time::microsec_clock::universal_time(); } /* ************************************************************************* */ -std::string LevenbergMarquardtParams::verbosityLMTranslator( - VerbosityLM value) { - std::string s; - switch (value) { - case LevenbergMarquardtParams::SILENT: - s = "SILENT"; - break; - case LevenbergMarquardtParams::SUMMARY: - s = "SUMMARY"; - break; - case LevenbergMarquardtParams::TERMINATION: - s = "TERMINATION"; - break; - case LevenbergMarquardtParams::LAMBDA: - s = "LAMBDA"; - break; - case LevenbergMarquardtParams::TRYLAMBDA: - s = "TRYLAMBDA"; - break; - case LevenbergMarquardtParams::TRYCONFIG: - s = "TRYCONFIG"; - break; - case LevenbergMarquardtParams::TRYDELTA: - s = "TRYDELTA"; - break; - case LevenbergMarquardtParams::DAMPED: - s = "DAMPED"; - break; - default: - s = "UNDEFINED"; - break; - } - return s; +double LevenbergMarquardtOptimizer::lambda() const { + auto currentState = static_cast(state_.get()); + return currentState->lambda; } /* ************************************************************************* */ -void LevenbergMarquardtParams::print(const std::string& str) const { - NonlinearOptimizerParams::print(str); - std::cout << " lambdaInitial: " << lambdaInitial << "\n"; - std::cout << " lambdaFactor: " << lambdaFactor << "\n"; - std::cout << " lambdaUpperBound: " << lambdaUpperBound << "\n"; - std::cout << " lambdaLowerBound: " << lambdaLowerBound << "\n"; - std::cout << " minModelFidelity: " << minModelFidelity << "\n"; - std::cout << " diagonalDamping: " << diagonalDamping << "\n"; - std::cout << " minDiagonal: " << minDiagonal << "\n"; - std::cout << " maxDiagonal: " << maxDiagonal << "\n"; - std::cout << " verbosityLM: " - << verbosityLMTranslator(verbosityLM) << "\n"; - std::cout.flush(); +int LevenbergMarquardtOptimizer::getInnerIterations() const { + auto currentState = static_cast(state_.get()); + return currentState->totalNumberInnerIterations; } /* ************************************************************************* */ GaussianFactorGraph::shared_ptr LevenbergMarquardtOptimizer::linearize() const { - return graph_.linearize(state_.values); + return graph_.linearize(state_->values); } /* ************************************************************************* */ -void LevenbergMarquardtOptimizer::increaseLambda() { - if (params_.useFixedLambdaFactor) { - state_.lambda *= params_.lambdaFactor; - } else { - state_.lambda *= params_.lambdaFactor; - params_.lambdaFactor *= 2.0; - } - state_.reuseDiagonal = true; -} - -/* ************************************************************************* */ -void LevenbergMarquardtOptimizer::decreaseLambda(double stepQuality) { - - if (params_.useFixedLambdaFactor) { - state_.lambda /= params_.lambdaFactor; - } else { - // CHECK_GT(step_quality, 0.0); - state_.lambda *= std::max(1.0 / 3.0, 1.0 - pow(2.0 * stepQuality - 1.0, 3)); - params_.lambdaFactor = 2.0; - } - state_.lambda = std::max(params_.lambdaLowerBound, state_.lambda); - state_.reuseDiagonal = false; - -} - -/* ************************************************************************* */ -GaussianFactorGraph::shared_ptr LevenbergMarquardtOptimizer::buildDampedSystem( - const GaussianFactorGraph& linear) { - +GaussianFactorGraph LevenbergMarquardtOptimizer::buildDampedSystem( + const GaussianFactorGraph& linear, const VectorValues& sqrtHessianDiagonal) const { gttic(damp); + auto currentState = static_cast(state_.get()); + if (params_.verbosityLM >= LevenbergMarquardtParams::DAMPED) - cout << "building damped system with lambda " << state_.lambda << endl; + std::cout << "building damped system with lambda " << currentState->lambda << std::endl; - // Only retrieve diagonal vector when reuse_diagonal = false - if (params_.diagonalDamping && state_.reuseDiagonal == false) { - state_.hessianDiagonal = linear.hessianDiagonal(); - for(Vector& v: state_.hessianDiagonal | map_values) { - for (int aa = 0; aa < v.size(); aa++) { - v(aa) = std::min(std::max(v(aa), params_.minDiagonal), - params_.maxDiagonal); - v(aa) = sqrt(v(aa)); - } - } - } // reuse diagonal - - // for each of the variables, add a prior - double sigma = 1.0 / std::sqrt(state_.lambda); - GaussianFactorGraph::shared_ptr dampedPtr = linear.cloneToPtr(); - GaussianFactorGraph &damped = (*dampedPtr); - damped.reserve(damped.size() + state_.values.size()); - if (params_.diagonalDamping) { - for(const VectorValues::KeyValuePair& key_vector: state_.hessianDiagonal) { - // Fill in the diagonal of A with diag(hessian) - try { - Matrix A = Eigen::DiagonalMatrix( - state_.hessianDiagonal.at(key_vector.first)); - size_t dim = key_vector.second.size(); - Vector b = Vector::Zero(dim); - SharedDiagonal model = noiseModel::Isotropic::Sigma(dim, sigma); - damped += boost::make_shared(key_vector.first, A, b, - model); - } catch (const std::exception& e) { - // Don't attempt any damping if no key found in diagonal - continue; - } - } - } else { - // Straightforward damping: - - // initialize noise model cache to a reasonable default size - NoiseCacheVector noises(6); - for(const Values::KeyValuePair& key_value: state_.values) { - size_t dim = key_value.value.dim(); - - if (dim > noises.size()) - noises.resize(dim); - - NoiseCacheItem& item = noises[dim-1]; - - // Initialize noise model, A and b if we haven't done so already - if(!item.model) { - item.A = Matrix::Identity(dim, dim); - item.b = Vector::Zero(dim); - item.model = noiseModel::Isotropic::Sigma(dim, sigma); - } - damped += boost::make_shared(key_value.key, item.A, item.b, item.model); - } - } - gttoc(damp); - return dampedPtr; + if (params_.diagonalDamping) + return currentState->buildDampedSystem(linear, sqrtHessianDiagonal); + else + return currentState->buildDampedSystem(linear); } /* ************************************************************************* */ // Log current error/lambda to file inline void LevenbergMarquardtOptimizer::writeLogFile(double currentError){ + auto currentState = static_cast(state_.get()); + if (!params_.logFile.empty()) { ofstream os(params_.logFile.c_str(), ios::app); boost::posix_time::ptime currentTime = boost::posix_time::microsec_clock::universal_time(); - os << /*inner iterations*/ state_.totalNumberInnerIterations << "," - << 1e-6 * (currentTime - state_.startTime).total_microseconds() << "," - << /*current error*/ currentError << "," << state_.lambda << "," - << /*outer iterations*/ state_.iterations << endl; + os << /*inner iterations*/ currentState->totalNumberInnerIterations << "," + << 1e-6 * (currentTime - startTime_).total_microseconds() << "," + << /*current error*/ currentError << "," << currentState->lambda << "," + << /*outer iterations*/ currentState->iterations << endl; } } /* ************************************************************************* */ -void LevenbergMarquardtOptimizer::iterate() { +bool LevenbergMarquardtOptimizer::tryLambda(const GaussianFactorGraph& linear, + const VectorValues& sqrtHessianDiagonal) { + auto currentState = static_cast(state_.get()); + bool verbose = (params_.verbosityLM >= LevenbergMarquardtParams::TRYLAMBDA); + +#ifdef GTSAM_USING_NEW_BOOST_TIMERS + boost::timer::cpu_timer lamda_iteration_timer; + lamda_iteration_timer.start(); +#else + boost::timer lamda_iteration_timer; + lamda_iteration_timer.restart(); +#endif + + if (verbose) + cout << "trying lambda = " << currentState->lambda << endl; + + // Build damped system for this lambda (adds prior factors that make it like gradient descent) + auto dampedSystem = buildDampedSystem(linear, sqrtHessianDiagonal); + + // Try solving + double modelFidelity = 0.0; + bool step_is_successful = false; + bool stopSearchingLambda = false; + double newError = numeric_limits::infinity(), costChange; + Values newValues; + VectorValues delta; + + bool systemSolvedSuccessfully; + try { + // ============ Solve is where most computation happens !! ================= + delta = solve(dampedSystem, params_); + systemSolvedSuccessfully = true; + } catch (const IndeterminantLinearSystemException& e) { + systemSolvedSuccessfully = false; + } + + if (systemSolvedSuccessfully) { + if (verbose) + cout << "linear delta norm = " << delta.norm() << endl; + if (params_.verbosityLM >= LevenbergMarquardtParams::TRYDELTA) + delta.print("delta"); + + // cost change in the linearized system (old - new) + double newlinearizedError = linear.error(delta); + + double linearizedCostChange = currentState->error - newlinearizedError; + if (verbose) + cout << "newlinearizedError = " << newlinearizedError + << " linearizedCostChange = " << linearizedCostChange << endl; + + if (linearizedCostChange >= 0) { // step is valid + // update values + gttic(retract); + // ============ This is where the solution is updated ==================== + newValues = currentState->values.retract(delta); + // ======================================================================= + gttoc(retract); + + // compute new error + gttic(compute_error); + if (verbose) + cout << "calculating error:" << endl; + newError = graph_.error(newValues); + gttoc(compute_error); + + if (verbose) + cout << "old error (" << currentState->error << ") new (tentative) error (" << newError + << ")" << endl; + + // cost change in the original, nonlinear system (old - new) + costChange = currentState->error - newError; + + if (linearizedCostChange > + 1e-20) { // the (linear) error has to decrease to satisfy this condition + // fidelity of linearized model VS original system between + modelFidelity = costChange / linearizedCostChange; + // if we decrease the error in the nonlinear system and modelFidelity is above threshold + step_is_successful = modelFidelity > params_.minModelFidelity; + if (verbose) + cout << "modelFidelity: " << modelFidelity << endl; + } // else we consider the step non successful and we either increase lambda or stop if error + // change is small + + double minAbsoluteTolerance = params_.relativeErrorTol * currentState->error; + // if the change is small we terminate + if (fabs(costChange) < minAbsoluteTolerance) { + if (verbose) + cout << "fabs(costChange)=" << fabs(costChange) + << " minAbsoluteTolerance=" << minAbsoluteTolerance + << " (relativeErrorTol=" << params_.relativeErrorTol << ")" << endl; + stopSearchingLambda = true; + } + } + } // if (systemSolvedSuccessfully) + + if (params_.verbosityLM == LevenbergMarquardtParams::SUMMARY) { +// do timing +#ifdef GTSAM_USING_NEW_BOOST_TIMERS + double iterationTime = 1e-9 * lamda_iteration_timer.elapsed().wall; +#else + double iterationTime = lamda_iteration_timer.elapsed(); +#endif + if (currentState->iterations == 0) + cout << "iter cost cost_change lambda success iter_time" << endl; + + cout << boost::format("% 4d % 8e % 3.2e % 3.2e % 4d % 3.2e") % currentState->iterations % + newError % costChange % currentState->lambda % systemSolvedSuccessfully % + iterationTime << endl; + } + + if (step_is_successful) { + // we have successfully decreased the cost and we have good modelFidelity + // NOTE(frank): As we return immediately after this, we move the newValues + // TODO(frank): make Values actually support move. Does not seem to happen now. + state_ = currentState->decreaseLambda(params_, modelFidelity, std::move(newValues), newError); + return true; + } else if (!stopSearchingLambda) { // we failed to solved the system or had no decrease in cost + if (verbose) + cout << "increasing lambda" << endl; + State* modifiedState = static_cast(state_.get()); + modifiedState->increaseLambda(params_); // TODO(frank): make this functional with Values move + + // check if lambda is too big + if (modifiedState->lambda >= params_.lambdaUpperBound) { + if (params_.verbosity >= NonlinearOptimizerParams::TERMINATION || + params_.verbosityLM == LevenbergMarquardtParams::SUMMARY) + cout << "Warning: Levenberg-Marquardt giving up because " + "cannot decrease error with maximum lambda" << endl; + return true; + } else { + return false; // only case where we will keep trying + } + } else { // the change in the cost is very small and it is not worth trying bigger lambdas + if (verbose) + cout << "Levenberg-Marquardt: stopping as relative cost reduction is small" << endl; + return true; + } +} + +/* ************************************************************************* */ +GaussianFactorGraph::shared_ptr LevenbergMarquardtOptimizer::iterate() { + auto currentState = static_cast(state_.get()); gttic(LM_iterate); - // Pull out parameters we'll use - const NonlinearOptimizerParams::Verbosity nloVerbosity = params_.verbosity; - const LevenbergMarquardtParams::VerbosityLM lmVerbosity = params_.verbosityLM; - // Linearize graph - if (lmVerbosity >= LevenbergMarquardtParams::DAMPED) + if (params_.verbosityLM >= LevenbergMarquardtParams::DAMPED) cout << "linearizing = " << endl; GaussianFactorGraph::shared_ptr linear = linearize(); - if(state_.totalNumberInnerIterations==0) { // write initial error - writeLogFile(state_.error); + if(currentState->totalNumberInnerIterations==0) { // write initial error + writeLogFile(currentState->error); - if (lmVerbosity == LevenbergMarquardtParams::SUMMARY) { - cout << "Initial error: " << state_.error << ", values: " << state_.values.size() - << std::endl; + if (params_.verbosityLM == LevenbergMarquardtParams::SUMMARY) { + cout << "Initial error: " << currentState->error + << ", values: " << currentState->values.size() << std::endl; + } + } + + // Only calculate diagonal of Hessian (expensive) once per outer iteration, if we need it + VectorValues sqrtHessianDiagonal; + if (params_.diagonalDamping) { + sqrtHessianDiagonal = linear->hessianDiagonal(); + for (Vector& v : sqrtHessianDiagonal | map_values) { + v = v.cwiseMax(params_.minDiagonal).cwiseMin(params_.maxDiagonal).cwiseSqrt(); } } // Keep increasing lambda until we make make progress - while (true) { + while (!tryLambda(*linear, sqrtHessianDiagonal)) { + auto newState = static_cast(state_.get()); + writeLogFile(newState->error); + } -#ifdef GTSAM_USING_NEW_BOOST_TIMERS - boost::timer::cpu_timer lamda_iteration_timer; - lamda_iteration_timer.start(); -#else - boost::timer lamda_iteration_timer; - lamda_iteration_timer.restart(); -#endif - - if (lmVerbosity >= LevenbergMarquardtParams::TRYLAMBDA) - cout << "trying lambda = " << state_.lambda << endl; - - // Build damped system for this lambda (adds prior factors that make it like gradient descent) - GaussianFactorGraph::shared_ptr dampedSystemPtr = buildDampedSystem(*linear); - GaussianFactorGraph &dampedSystem = (*dampedSystemPtr); - - // Try solving - double modelFidelity = 0.0; - bool step_is_successful = false; - bool stopSearchingLambda = false; - double newError = numeric_limits::infinity(), costChange; - Values newValues; - VectorValues delta; - - bool systemSolvedSuccessfully; - try { - // ============ Solve is where most computation happens !! ================= - delta = solve(dampedSystem, state_.values, params_); - systemSolvedSuccessfully = true; - } catch (const IndeterminantLinearSystemException& e) { - systemSolvedSuccessfully = false; - } - - if (systemSolvedSuccessfully) { - state_.reuseDiagonal = true; - - if (lmVerbosity >= LevenbergMarquardtParams::TRYLAMBDA) - cout << "linear delta norm = " << delta.norm() << endl; - if (lmVerbosity >= LevenbergMarquardtParams::TRYDELTA) - delta.print("delta"); - - // cost change in the linearized system (old - new) - double newlinearizedError = linear->error(delta); - - double linearizedCostChange = state_.error - newlinearizedError; - if (lmVerbosity >= LevenbergMarquardtParams::TRYLAMBDA) - cout << "newlinearizedError = " << newlinearizedError << - " linearizedCostChange = " << linearizedCostChange << endl; - - if (linearizedCostChange >= 0) { // step is valid - // update values - gttic(retract); - // ============ This is where the solution is updated ==================== - newValues = state_.values.retract(delta); - // ======================================================================= - gttoc(retract); - - // compute new error - gttic(compute_error); - if (lmVerbosity >= LevenbergMarquardtParams::TRYLAMBDA) - cout << "calculating error:" << endl; - newError = graph_.error(newValues); - gttoc(compute_error); - - if (lmVerbosity >= LevenbergMarquardtParams::TRYLAMBDA) - cout << "old error (" << state_.error - << ") new (tentative) error (" << newError << ")" << endl; - - // cost change in the original, nonlinear system (old - new) - costChange = state_.error - newError; - - if (linearizedCostChange > 1e-20) { // the (linear) error has to decrease to satisfy this condition - // fidelity of linearized model VS original system between - modelFidelity = costChange / linearizedCostChange; - // if we decrease the error in the nonlinear system and modelFidelity is above threshold - step_is_successful = modelFidelity > params_.minModelFidelity; - if (lmVerbosity >= LevenbergMarquardtParams::TRYLAMBDA) - cout << "modelFidelity: " << modelFidelity << endl; - } // else we consider the step non successful and we either increase lambda or stop if error change is small - - double minAbsoluteTolerance = params_.relativeErrorTol * state_.error; - // if the change is small we terminate - if (fabs(costChange) < minAbsoluteTolerance){ - if (lmVerbosity >= LevenbergMarquardtParams::TRYLAMBDA) - cout << "fabs(costChange)="<= LevenbergMarquardtParams::TRYLAMBDA) - cout << "increasing lambda" << endl; - increaseLambda(); - writeLogFile(state_.error); - - // check if lambda is too big - if (state_.lambda >= params_.lambdaUpperBound) { - if (nloVerbosity >= NonlinearOptimizerParams::TERMINATION || - lmVerbosity == LevenbergMarquardtParams::SUMMARY) - cout << "Warning: Levenberg-Marquardt giving up because " - "cannot decrease error with maximum lambda" << endl; - break; - } - } else { // the change in the cost is very small and it is not worth trying bigger lambdas - writeLogFile(state_.error); - if (lmVerbosity >= LevenbergMarquardtParams::TRYLAMBDA) - cout << "Levenberg-Marquardt: stopping as relative cost reduction is small" << endl; - break; - } - } // end while - - // Increment the iteration counter - ++state_.iterations; -} - -/* ************************************************************************* */ -LevenbergMarquardtParams LevenbergMarquardtOptimizer::ensureHasOrdering( - LevenbergMarquardtParams params, const NonlinearFactorGraph& graph) const { - if (!params.ordering) - params.ordering = Ordering::Create(params.orderingType, graph); - return params; + return linear; } } /* namespace gtsam */ diff --git a/gtsam/nonlinear/LevenbergMarquardtOptimizer.h b/gtsam/nonlinear/LevenbergMarquardtOptimizer.h index 2be4a218e..904e08770 100644 --- a/gtsam/nonlinear/LevenbergMarquardtOptimizer.h +++ b/gtsam/nonlinear/LevenbergMarquardtOptimizer.h @@ -11,173 +11,38 @@ /** * @file LevenbergMarquardtOptimizer.h - * @brief + * @brief A nonlinear optimizer that uses the Levenberg-Marquardt trust-region scheme * @author Richard Roberts - * @date Feb 26, 2012 + * @author Frank Dellaert + * @author Luca Carlone + * @date Feb 26, 2012 */ #pragma once #include +#include #include -#include class NonlinearOptimizerMoreOptimizationTest; namespace gtsam { -class LevenbergMarquardtOptimizer; - -/** Parameters for Levenberg-Marquardt optimization. Note that this parameters - * class inherits from NonlinearOptimizerParams, which specifies the parameters - * common to all nonlinear optimization algorithms. This class also contains - * all of those parameters. - */ -class GTSAM_EXPORT LevenbergMarquardtParams: public NonlinearOptimizerParams { - -public: - /** See LevenbergMarquardtParams::lmVerbosity */ - enum VerbosityLM { - SILENT = 0, SUMMARY, TERMINATION, LAMBDA, TRYLAMBDA, TRYCONFIG, DAMPED, TRYDELTA - }; - - static VerbosityLM verbosityLMTranslator(const std::string &s); - static std::string verbosityLMTranslator(VerbosityLM value); - -public: - - double lambdaInitial; ///< The initial Levenberg-Marquardt damping term (default: 1e-5) - double lambdaFactor; ///< The amount by which to multiply or divide lambda when adjusting lambda (default: 10.0) - double lambdaUpperBound; ///< The maximum lambda to try before assuming the optimization has failed (default: 1e5) - double lambdaLowerBound; ///< The minimum lambda used in LM (default: 0) - VerbosityLM verbosityLM; ///< The verbosity level for Levenberg-Marquardt (default: SILENT), see also NonlinearOptimizerParams::verbosity - double minModelFidelity; ///< Lower bound for the modelFidelity to accept the result of an LM iteration - std::string logFile; ///< an optional CSV log file, with [iteration, time, error, lambda] - bool diagonalDamping; ///< if true, use diagonal of Hessian - bool useFixedLambdaFactor; ///< if true applies constant increase (or decrease) to lambda according to lambdaFactor - double minDiagonal; ///< when using diagonal damping saturates the minimum diagonal entries (default: 1e-6) - double maxDiagonal; ///< when using diagonal damping saturates the maximum diagonal entries (default: 1e32) - - LevenbergMarquardtParams() - : verbosityLM(SILENT), - diagonalDamping(false), - minDiagonal(1e-6), - maxDiagonal(1e32) { - SetLegacyDefaults(this); - } - - static void SetLegacyDefaults(LevenbergMarquardtParams* p) { - // Relevant NonlinearOptimizerParams: - p->maxIterations = 100; - p->relativeErrorTol = 1e-5; - p->absoluteErrorTol = 1e-5; - // LM-specific: - p->lambdaInitial = 1e-5; - p->lambdaFactor = 10.0; - p->lambdaUpperBound = 1e5; - p->lambdaLowerBound = 0.0; - p->minModelFidelity = 1e-3; - p->diagonalDamping = false; - p->useFixedLambdaFactor = true; - } - - // these do seem to work better for SFM - static void SetCeresDefaults(LevenbergMarquardtParams* p) { - // Relevant NonlinearOptimizerParams: - p->maxIterations = 50; - p->absoluteErrorTol = 0; // No corresponding option in CERES - p->relativeErrorTol = 1e-6; // This is function_tolerance - // LM-specific: - p->lambdaUpperBound = 1e32; - p->lambdaLowerBound = 1e-16; - p->lambdaInitial = 1e-04; - p->lambdaFactor = 2.0; - p->minModelFidelity = 1e-3; // options.min_relative_decrease in CERES - p->diagonalDamping = true; - p->useFixedLambdaFactor = false; // This is important - } - - static LevenbergMarquardtParams LegacyDefaults() { - LevenbergMarquardtParams p; - SetLegacyDefaults(&p); - return p; - } - - static LevenbergMarquardtParams CeresDefaults() { - LevenbergMarquardtParams p; - SetCeresDefaults(&p); - return p; - } - - virtual ~LevenbergMarquardtParams() {} - virtual void print(const std::string& str = "") const; - - /// @name Getters/Setters, mainly for MATLAB. Use fields above in C++. - /// @{ - bool getDiagonalDamping() const { return diagonalDamping; } - double getlambdaFactor() const { return lambdaFactor; } - double getlambdaInitial() const { return lambdaInitial; } - double getlambdaLowerBound() const { return lambdaLowerBound; } - double getlambdaUpperBound() const { return lambdaUpperBound; } - std::string getLogFile() const { return logFile; } - std::string getVerbosityLM() const { return verbosityLMTranslator(verbosityLM);} - void setDiagonalDamping(bool flag) { diagonalDamping = flag; } - void setlambdaFactor(double value) { lambdaFactor = value; } - void setlambdaInitial(double value) { lambdaInitial = value; } - void setlambdaLowerBound(double value) { lambdaLowerBound = value; } - void setlambdaUpperBound(double value) { lambdaUpperBound = value; } - void setLogFile(const std::string& s) { logFile = s; } - void setUseFixedLambdaFactor(bool flag) { useFixedLambdaFactor = flag;} - void setVerbosityLM(const std::string& s) { verbosityLM = verbosityLMTranslator(s);} - // @} -}; - -/** - * State for LevenbergMarquardtOptimizer - */ -class GTSAM_EXPORT LevenbergMarquardtState: public NonlinearOptimizerState { - -public: - double lambda; - boost::posix_time::ptime startTime; - int totalNumberInnerIterations; //< The total number of inner iterations in the optimization (for each iteration, LM may try multiple iterations with different lambdas) - VectorValues hessianDiagonal; //< we only update hessianDiagonal when reuseDiagonal = false - bool reuseDiagonal; ///< an additional option in Ceres for diagonalDamping - - LevenbergMarquardtState() {} // used in LM constructor but immediately overwritten - - void initTime() { - startTime = boost::posix_time::microsec_clock::universal_time(); - } - - virtual ~LevenbergMarquardtState() { - } - -protected: - LevenbergMarquardtState(const NonlinearFactorGraph& graph, - const Values& initialValues, const LevenbergMarquardtParams& params, - unsigned int iterations = 0) : - NonlinearOptimizerState(graph, initialValues, iterations), lambda( - params.lambdaInitial), totalNumberInnerIterations(0),reuseDiagonal(false) { - initTime(); - } - - friend class LevenbergMarquardtOptimizer; -}; - /** * This class performs Levenberg-Marquardt nonlinear optimization */ class GTSAM_EXPORT LevenbergMarquardtOptimizer: public NonlinearOptimizer { protected: - LevenbergMarquardtParams params_; ///< LM parameters - LevenbergMarquardtState state_; ///< optimization state + const LevenbergMarquardtParams params_; ///< LM parameters + boost::posix_time::ptime startTime_; + + void initTime(); public: typedef boost::shared_ptr shared_ptr; - /// @name Standard interface + /// @name Constructors/Destructor /// @{ /** Standard constructor, requires a nonlinear factor graph, initial @@ -188,12 +53,8 @@ public: * @param initialValues The initial variable assignments * @param params The optimization parameters */ - LevenbergMarquardtOptimizer( - const NonlinearFactorGraph& graph, const Values& initialValues, - const LevenbergMarquardtParams& params = LevenbergMarquardtParams()) - : NonlinearOptimizer(graph), - params_(ensureHasOrdering(params, graph)), - state_(graph, initialValues, params_) {} + LevenbergMarquardtOptimizer(const NonlinearFactorGraph& graph, const Values& initialValues, + const LevenbergMarquardtParams& params = LevenbergMarquardtParams()); /** Standard constructor, requires a nonlinear factor graph, initial * variable assignments, and optimization parameters. For convenience this @@ -202,33 +63,27 @@ public: * @param graph The nonlinear factor graph to optimize * @param initialValues The initial variable assignments */ - LevenbergMarquardtOptimizer( - const NonlinearFactorGraph& graph, const Values& initialValues, - const Ordering& ordering, - const LevenbergMarquardtParams& params = LevenbergMarquardtParams()) - : NonlinearOptimizer(graph), params_(params) { - params_.ordering = ordering; - state_ = LevenbergMarquardtState(graph, initialValues, params_); + LevenbergMarquardtOptimizer(const NonlinearFactorGraph& graph, const Values& initialValues, + const Ordering& ordering, + const LevenbergMarquardtParams& params = LevenbergMarquardtParams()); + + /** Virtual destructor */ + virtual ~LevenbergMarquardtOptimizer() { } + /// @} + + /// @name Standard interface + /// @{ + /// Access the current damping value - double lambda() const { - return state_.lambda; - } - - // Apply policy to increase lambda if the current update was successful (stepQuality not used in the naive policy) - void increaseLambda(); - - // Apply policy to decrease lambda if the current update was NOT successful (stepQuality not used in the naive policy) - void decreaseLambda(double stepQuality); + double lambda() const; /// Access the current number of inner iterations - int getInnerIterations() const { - return state_.totalNumberInnerIterations; - } + int getInnerIterations() const; /// print - virtual void print(const std::string& str = "") const { + void print(const std::string& str = "") const { std::cout << str << "LevenbergMarquardtOptimizer" << std::endl; this->params_.print(" parameters:\n"); } @@ -238,73 +93,37 @@ public: /// @name Advanced interface /// @{ - /** Virtual destructor */ - virtual ~LevenbergMarquardtOptimizer() { - } - /** Perform a single iteration, returning a new NonlinearOptimizer class * containing the updated variable assignments, which may be retrieved with * values(). */ - virtual void iterate(); + GaussianFactorGraph::shared_ptr iterate() override; /** Read-only access the parameters */ const LevenbergMarquardtParams& params() const { return params_; } - /** Read/write access the parameters */ - LevenbergMarquardtParams& params() { - return params_; - } - - /** Read-only access the last state */ - const LevenbergMarquardtState& state() const { - return state_; - } - - /** Read/write access the last state. When modifying the state, the error, etc. must be consistent before calling iterate() */ - LevenbergMarquardtState& state() { - return state_; - } - - /** Build a damped system for a specific lambda */ - GaussianFactorGraph::shared_ptr buildDampedSystem(const GaussianFactorGraph& linear); - friend class ::NonlinearOptimizerMoreOptimizationTest; - - /** Small struct to cache objects needed for damping. - * This is used in buildDampedSystem */ - struct NoiseCacheItem { - Matrix A; - Vector b; - SharedDiagonal model; - }; - - /// Noise model Cache - typedef std::vector NoiseCacheVector; - void writeLogFile(double currentError); + /** linearize, can be overwritten */ + virtual GaussianFactorGraph::shared_ptr linearize() const; + + /** Build a damped system for a specific lambda -- for testing only */ + GaussianFactorGraph buildDampedSystem(const GaussianFactorGraph& linear, + const VectorValues& sqrtHessianDiagonal) const; + + /** Inner loop, changes state, returns true if successful or giving up */ + bool tryLambda(const GaussianFactorGraph& linear, const VectorValues& sqrtHessianDiagonal); + /// @} protected: /** Access the parameters (base class version) */ - virtual const NonlinearOptimizerParams& _params() const { + const NonlinearOptimizerParams& _params() const override { return params_; } - - /** Access the state (base class version) */ - virtual const NonlinearOptimizerState& _state() const { - return state_; - } - - /** Internal function for computing a COLAMD ordering if no ordering is specified */ - LevenbergMarquardtParams ensureHasOrdering(LevenbergMarquardtParams params, - const NonlinearFactorGraph& graph) const; - - /** linearize, can be overwritten */ - virtual GaussianFactorGraph::shared_ptr linearize() const; }; } diff --git a/gtsam/nonlinear/LevenbergMarquardtParams.cpp b/gtsam/nonlinear/LevenbergMarquardtParams.cpp new file mode 100644 index 000000000..5d558a43a --- /dev/null +++ b/gtsam/nonlinear/LevenbergMarquardtParams.cpp @@ -0,0 +1,108 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file LevenbergMarquardtParams.cpp + * @brief Parameters for Levenberg-Marquardt trust-region scheme + * @author Richard Roberts + * @author Frank Dellaert + * @author Luca Carlone + * @date Feb 26, 2012 + */ + +#include +#include +#include +#include +#include + +using namespace std; + +namespace gtsam { + +/* ************************************************************************* */ +LevenbergMarquardtParams::VerbosityLM LevenbergMarquardtParams::verbosityLMTranslator( + const std::string &src) { + std::string s = src; + boost::algorithm::to_upper(s); + if (s == "SILENT") + return LevenbergMarquardtParams::SILENT; + if (s == "SUMMARY") + return LevenbergMarquardtParams::SUMMARY; + if (s == "LAMBDA") + return LevenbergMarquardtParams::LAMBDA; + if (s == "TRYLAMBDA") + return LevenbergMarquardtParams::TRYLAMBDA; + if (s == "TRYCONFIG") + return LevenbergMarquardtParams::TRYCONFIG; + if (s == "TRYDELTA") + return LevenbergMarquardtParams::TRYDELTA; + if (s == "DAMPED") + return LevenbergMarquardtParams::DAMPED; + + /* default is silent */ + return LevenbergMarquardtParams::SILENT; +} + +/* ************************************************************************* */ +std::string LevenbergMarquardtParams::verbosityLMTranslator( + VerbosityLM value) { + std::string s; + switch (value) { + case LevenbergMarquardtParams::SILENT: + s = "SILENT"; + break; + case LevenbergMarquardtParams::SUMMARY: + s = "SUMMARY"; + break; + case LevenbergMarquardtParams::TERMINATION: + s = "TERMINATION"; + break; + case LevenbergMarquardtParams::LAMBDA: + s = "LAMBDA"; + break; + case LevenbergMarquardtParams::TRYLAMBDA: + s = "TRYLAMBDA"; + break; + case LevenbergMarquardtParams::TRYCONFIG: + s = "TRYCONFIG"; + break; + case LevenbergMarquardtParams::TRYDELTA: + s = "TRYDELTA"; + break; + case LevenbergMarquardtParams::DAMPED: + s = "DAMPED"; + break; + default: + s = "UNDEFINED"; + break; + } + return s; +} + +/* ************************************************************************* */ +void LevenbergMarquardtParams::print(const std::string& str) const { + NonlinearOptimizerParams::print(str); + std::cout << " lambdaInitial: " << lambdaInitial << "\n"; + std::cout << " lambdaFactor: " << lambdaFactor << "\n"; + std::cout << " lambdaUpperBound: " << lambdaUpperBound << "\n"; + std::cout << " lambdaLowerBound: " << lambdaLowerBound << "\n"; + std::cout << " minModelFidelity: " << minModelFidelity << "\n"; + std::cout << " diagonalDamping: " << diagonalDamping << "\n"; + std::cout << " minDiagonal: " << minDiagonal << "\n"; + std::cout << " maxDiagonal: " << maxDiagonal << "\n"; + std::cout << " verbosityLM: " + << verbosityLMTranslator(verbosityLM) << "\n"; + std::cout.flush(); +} + +} /* namespace gtsam */ + diff --git a/gtsam/nonlinear/LevenbergMarquardtParams.h b/gtsam/nonlinear/LevenbergMarquardtParams.h new file mode 100644 index 000000000..abb8c3c22 --- /dev/null +++ b/gtsam/nonlinear/LevenbergMarquardtParams.h @@ -0,0 +1,145 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file LevenbergMarquardtParams.h + * @brief Parameters for Levenberg-Marquardt trust-region scheme + * @author Richard Roberts + * @author Frank Dellaert + * @author Luca Carlone + * @date Feb 26, 2012 + */ + +#pragma once + +#include +#include + +namespace gtsam { + +/** Parameters for Levenberg-Marquardt optimization. Note that this parameters + * class inherits from NonlinearOptimizerParams, which specifies the parameters + * common to all nonlinear optimization algorithms. This class also contains + * all of those parameters. + */ +class GTSAM_EXPORT LevenbergMarquardtParams: public NonlinearOptimizerParams { + +public: + /** See LevenbergMarquardtParams::lmVerbosity */ + enum VerbosityLM { + SILENT = 0, SUMMARY, TERMINATION, LAMBDA, TRYLAMBDA, TRYCONFIG, DAMPED, TRYDELTA + }; + + static VerbosityLM verbosityLMTranslator(const std::string &s); + static std::string verbosityLMTranslator(VerbosityLM value); + +public: + + double lambdaInitial; ///< The initial Levenberg-Marquardt damping term (default: 1e-5) + double lambdaFactor; ///< The amount by which to multiply or divide lambda when adjusting lambda (default: 10.0) + double lambdaUpperBound; ///< The maximum lambda to try before assuming the optimization has failed (default: 1e5) + double lambdaLowerBound; ///< The minimum lambda used in LM (default: 0) + VerbosityLM verbosityLM; ///< The verbosity level for Levenberg-Marquardt (default: SILENT), see also NonlinearOptimizerParams::verbosity + double minModelFidelity; ///< Lower bound for the modelFidelity to accept the result of an LM iteration + std::string logFile; ///< an optional CSV log file, with [iteration, time, error, lambda] + bool diagonalDamping; ///< if true, use diagonal of Hessian + bool useFixedLambdaFactor; ///< if true applies constant increase (or decrease) to lambda according to lambdaFactor + double minDiagonal; ///< when using diagonal damping saturates the minimum diagonal entries (default: 1e-6) + double maxDiagonal; ///< when using diagonal damping saturates the maximum diagonal entries (default: 1e32) + + LevenbergMarquardtParams() + : verbosityLM(SILENT), + diagonalDamping(false), + minDiagonal(1e-6), + maxDiagonal(1e32) { + SetLegacyDefaults(this); + } + + static void SetLegacyDefaults(LevenbergMarquardtParams* p) { + // Relevant NonlinearOptimizerParams: + p->maxIterations = 100; + p->relativeErrorTol = 1e-5; + p->absoluteErrorTol = 1e-5; + // LM-specific: + p->lambdaInitial = 1e-5; + p->lambdaFactor = 10.0; + p->lambdaUpperBound = 1e5; + p->lambdaLowerBound = 0.0; + p->minModelFidelity = 1e-3; + p->diagonalDamping = false; + p->useFixedLambdaFactor = true; + } + + // these do seem to work better for SFM + static void SetCeresDefaults(LevenbergMarquardtParams* p) { + // Relevant NonlinearOptimizerParams: + p->maxIterations = 50; + p->absoluteErrorTol = 0; // No corresponding option in CERES + p->relativeErrorTol = 1e-6; // This is function_tolerance + // LM-specific: + p->lambdaUpperBound = 1e32; + p->lambdaLowerBound = 1e-16; + p->lambdaInitial = 1e-04; + p->lambdaFactor = 2.0; + p->minModelFidelity = 1e-3; // options.min_relative_decrease in CERES + p->diagonalDamping = true; + p->useFixedLambdaFactor = false; // This is important + } + + static LevenbergMarquardtParams LegacyDefaults() { + LevenbergMarquardtParams p; + SetLegacyDefaults(&p); + return p; + } + + static LevenbergMarquardtParams CeresDefaults() { + LevenbergMarquardtParams p; + SetCeresDefaults(&p); + return p; + } + + static LevenbergMarquardtParams EnsureHasOrdering(LevenbergMarquardtParams params, + const NonlinearFactorGraph& graph) { + if (!params.ordering) + params.ordering = Ordering::Create(params.orderingType, graph); + return params; + } + + static LevenbergMarquardtParams ReplaceOrdering(LevenbergMarquardtParams params, + const Ordering& ordering) { + params.ordering = ordering; + return params; + } + + virtual ~LevenbergMarquardtParams() {} + void print(const std::string& str = "") const override; + + /// @name Getters/Setters, mainly for MATLAB. Use fields above in C++. + /// @{ + bool getDiagonalDamping() const { return diagonalDamping; } + double getlambdaFactor() const { return lambdaFactor; } + double getlambdaInitial() const { return lambdaInitial; } + double getlambdaLowerBound() const { return lambdaLowerBound; } + double getlambdaUpperBound() const { return lambdaUpperBound; } + std::string getLogFile() const { return logFile; } + std::string getVerbosityLM() const { return verbosityLMTranslator(verbosityLM);} + void setDiagonalDamping(bool flag) { diagonalDamping = flag; } + void setlambdaFactor(double value) { lambdaFactor = value; } + void setlambdaInitial(double value) { lambdaInitial = value; } + void setlambdaLowerBound(double value) { lambdaLowerBound = value; } + void setlambdaUpperBound(double value) { lambdaUpperBound = value; } + void setLogFile(const std::string& s) { logFile = s; } + void setUseFixedLambdaFactor(bool flag) { useFixedLambdaFactor = flag;} + void setVerbosityLM(const std::string& s) { verbosityLM = verbosityLMTranslator(s);} + // @} +}; + +} diff --git a/gtsam/nonlinear/LinearContainerFactor.cpp b/gtsam/nonlinear/LinearContainerFactor.cpp index 0b5622f28..4f19f36f8 100644 --- a/gtsam/nonlinear/LinearContainerFactor.cpp +++ b/gtsam/nonlinear/LinearContainerFactor.cpp @@ -11,14 +11,13 @@ #include #include - namespace gtsam { /* ************************************************************************* */ void LinearContainerFactor::initializeLinearizationPoint(const Values& linearizationPoint) { if (!linearizationPoint.empty()) { linearizationPoint_ = Values(); - for(const gtsam::Key& key: this->keys()) { + for (Key key : keys()) { linearizationPoint_->insert(key, linearizationPoint.at(key)); } } else { @@ -81,7 +80,7 @@ double LinearContainerFactor::error(const Values& c) const { // Extract subset of values for comparison Values csub; - for(const gtsam::Key& key: keys()) + for (Key key : keys()) csub.insert(key, c.at(key)); // create dummy ordering for evaluation @@ -110,7 +109,7 @@ GaussianFactor::shared_ptr LinearContainerFactor::linearize(const Values& c) con // Extract subset of values Values subsetC; - for(const gtsam::Key& key: this->keys()) + for (Key key : keys()) subsetC.insert(key, c.at(key)); // Determine delta between linearization points using new ordering @@ -122,10 +121,11 @@ GaussianFactor::shared_ptr LinearContainerFactor::linearize(const Values& c) con jacFactor->getb() = -jacFactor->unweighted_error(delta); } else { HessianFactor::shared_ptr hesFactor = boost::dynamic_pointer_cast(linFactor); - SymmetricBlockMatrix::constBlock Gview = hesFactor->matrixObject().range(0, hesFactor->size(), 0, hesFactor->size()); + + const auto view = hesFactor->informationView(); Vector deltaVector = delta.vector(keys()); - Vector G_delta = Gview.selfadjointView() * deltaVector; - hesFactor->constantTerm() += deltaVector.dot(G_delta) - 2.0 * deltaVector.dot(hesFactor->linearTerm()); + Vector G_delta = view * deltaVector; + hesFactor->constantTerm() += deltaVector.dot(G_delta) - 2.0 * deltaVector.dot(hesFactor->linearTerm().col(0)); hesFactor->linearTerm() -= G_delta; } @@ -165,14 +165,13 @@ NonlinearFactor::shared_ptr LinearContainerFactor::negateToNonlinear() const { } /* ************************************************************************* */ -NonlinearFactorGraph LinearContainerFactor::convertLinearGraph( - const GaussianFactorGraph& linear_graph, const Values& linearizationPoint) -{ +NonlinearFactorGraph LinearContainerFactor::ConvertLinearGraph( + const GaussianFactorGraph& linear_graph, const Values& linearizationPoint) { NonlinearFactorGraph result; - for(const GaussianFactor::shared_ptr& f: linear_graph) + result.reserve(linear_graph.size()); + for (const auto& f : linear_graph) if (f) - result.push_back(NonlinearFactorGraph::sharedFactor( - new LinearContainerFactor(f, linearizationPoint))); + result += boost::make_shared(f, linearizationPoint); return result; } diff --git a/gtsam/nonlinear/LinearContainerFactor.h b/gtsam/nonlinear/LinearContainerFactor.h index 307c7f001..928b59e77 100644 --- a/gtsam/nonlinear/LinearContainerFactor.h +++ b/gtsam/nonlinear/LinearContainerFactor.h @@ -11,7 +11,6 @@ #include - namespace gtsam { // Forward declarations @@ -141,9 +140,16 @@ public: * Utility function for converting linear graphs to nonlinear graphs * consisting of LinearContainerFactors. */ - static NonlinearFactorGraph convertLinearGraph(const GaussianFactorGraph& linear_graph, + static NonlinearFactorGraph ConvertLinearGraph(const GaussianFactorGraph& linear_graph, const Values& linearizationPoint = Values()); +#ifdef GTSAM_ALLOW_DEPRECATED_SINCE_V4 + static NonlinearFactorGraph convertLinearGraph(const GaussianFactorGraph& linear_graph, + const Values& linearizationPoint = Values()) { + return ConvertLinearGraph(linear_graph, linearizationPoint); + } +#endif + protected: void initializeLinearizationPoint(const Values& linearizationPoint); diff --git a/gtsam/nonlinear/Marginals.cpp b/gtsam/nonlinear/Marginals.cpp index ac8fa4e89..68da1250e 100644 --- a/gtsam/nonlinear/Marginals.cpp +++ b/gtsam/nonlinear/Marginals.cpp @@ -82,9 +82,7 @@ Matrix Marginals::marginalCovariance(Key variable) const { /* ************************************************************************* */ JointMarginal Marginals::jointMarginalCovariance(const std::vector& variables) const { JointMarginal info = jointMarginalInformation(variables); - info.blockMatrix_.full().triangularView() = - info.blockMatrix_.full().selfadjointView().llt().solve( - Matrix::Identity(info.blockMatrix_.full().rows(), info.blockMatrix_.full().rows())).triangularView(); + info.blockMatrix_.invertInPlace(); return info; } diff --git a/gtsam/nonlinear/Marginals.h b/gtsam/nonlinear/Marginals.h index ad723015d..85f694bd2 100644 --- a/gtsam/nonlinear/Marginals.h +++ b/gtsam/nonlinear/Marginals.h @@ -91,13 +91,6 @@ protected: FastMap indices_; public: - /** A block view of the joint marginal - this stores a reference to the - * JointMarginal object, so the JointMarginal object must be kept in scope - * while this block view is needed, otherwise assign this block object to a - * Matrix to store it. - */ - typedef SymmetricBlockMatrix::constBlock Block; - /** Access a block, corresponding to a pair of variables, of the joint * marginal. Each block is accessed by its "vertical position", * corresponding to the variable with nonlinear Key \c iVariable and @@ -111,19 +104,21 @@ public: * @param iVariable The nonlinear Key specifying the "vertical position" of the requested block * @param jVariable The nonlinear Key specifying the "horizontal position" of the requested block */ - Block operator()(Key iVariable, Key jVariable) const { - return blockMatrix_(indices_.at(iVariable), indices_.at(jVariable)); } + Matrix operator()(Key iVariable, Key jVariable) const { + const auto indexI = indices_.at(iVariable); + const auto indexJ = indices_.at(jVariable); + return blockMatrix_.block(indexI, indexJ); + } /** Synonym for operator() */ - Block at(Key iVariable, Key jVariable) const { - return (*this)(iVariable, jVariable); } + Matrix at(Key iVariable, Key jVariable) const { + return (*this)(iVariable, jVariable); + } - /** The full, dense covariance/information matrix of the joint marginal. This returns - * a reference to the JointMarginal object, so the JointMarginal object must be kept - * in scope while this view is needed. Otherwise assign this block object to a Matrix - * to store it. - */ - Eigen::SelfAdjointView fullMatrix() const { return blockMatrix_.matrix(); } + /** The full, dense covariance/information matrix of the joint marginal. */ + Matrix fullMatrix() const { + return blockMatrix_.selfadjointView(); + } /** Print */ void print(const std::string& s = "", const KeyFormatter& formatter = DefaultKeyFormatter) const; diff --git a/gtsam/nonlinear/NonlinearConjugateGradientOptimizer.cpp b/gtsam/nonlinear/NonlinearConjugateGradientOptimizer.cpp index 6d7196ff5..32aead750 100644 --- a/gtsam/nonlinear/NonlinearConjugateGradientOptimizer.cpp +++ b/gtsam/nonlinear/NonlinearConjugateGradientOptimizer.cpp @@ -17,16 +17,17 @@ */ #include +#include #include #include #include #include -using namespace std; - namespace gtsam { +typedef internal::NonlinearOptimizerState State; + /** * @brief Return the gradient vector of a nonlinear factor graph * @param nfg the graph @@ -40,8 +41,11 @@ static VectorValues gradientInPlace(const NonlinearFactorGraph &nfg, return linear->gradientAtZero(); } -double NonlinearConjugateGradientOptimizer::System::error( - const State &state) const { +NonlinearConjugateGradientOptimizer::NonlinearConjugateGradientOptimizer( + const NonlinearFactorGraph& graph, const Values& initialValues, const Parameters& params) + : Base(graph, std::unique_ptr(new State(initialValues, graph.error(initialValues)))) {} + +double NonlinearConjugateGradientOptimizer::System::error(const State& state) const { return graph_.error(state); } @@ -57,21 +61,26 @@ NonlinearConjugateGradientOptimizer::System::State NonlinearConjugateGradientOpt return current.retract(step); } -void NonlinearConjugateGradientOptimizer::iterate() { +GaussianFactorGraph::shared_ptr NonlinearConjugateGradientOptimizer::iterate() { + Values newValues; int dummy; - boost::tie(state_.values, dummy) = nonlinearConjugateGradient( - System(graph_), state_.values, params_, true /* single iterations */); - ++state_.iterations; - state_.error = graph_.error(state_.values); + boost::tie(newValues, dummy) = nonlinearConjugateGradient( + System(graph_), state_->values, params_, true /* single iteration */); + state_.reset(new State(newValues, graph_.error(newValues), state_->iterations + 1)); + + // NOTE(frank): We don't linearize this system, so we must return null here. + return nullptr; } const Values& NonlinearConjugateGradientOptimizer::optimize() { // Optimize until convergence System system(graph_); - boost::tie(state_.values, state_.iterations) = // - nonlinearConjugateGradient(system, state_.values, params_, false); - state_.error = graph_.error(state_.values); - return state_.values; + Values newValues; + int iterations; + boost::tie(newValues, iterations) = + nonlinearConjugateGradient(system, state_->values, params_, false); + state_.reset(new State(std::move(newValues), graph_.error(newValues), iterations)); + return state_->values; } } /* namespace gtsam */ diff --git a/gtsam/nonlinear/NonlinearConjugateGradientOptimizer.h b/gtsam/nonlinear/NonlinearConjugateGradientOptimizer.h index 04d4734a4..fa39d2097 100644 --- a/gtsam/nonlinear/NonlinearConjugateGradientOptimizer.h +++ b/gtsam/nonlinear/NonlinearConjugateGradientOptimizer.h @@ -25,16 +25,7 @@ namespace gtsam { /** An implementation of the nonlinear CG method using the template below */ -class GTSAM_EXPORT NonlinearConjugateGradientState: public NonlinearOptimizerState { -public: - typedef NonlinearOptimizerState Base; - NonlinearConjugateGradientState(const NonlinearFactorGraph& graph, - const Values& values) : - Base(graph, values) { - } -}; - -class GTSAM_EXPORT NonlinearConjugateGradientOptimizer: public NonlinearOptimizer { +class GTSAM_EXPORT NonlinearConjugateGradientOptimizer : public NonlinearOptimizer { /* a class for the nonlinearConjugateGradient template */ class System { @@ -63,29 +54,24 @@ public: typedef boost::shared_ptr shared_ptr; protected: - NonlinearConjugateGradientState state_; Parameters params_; + const NonlinearOptimizerParams& _params() const override { + return params_; + } + public: /// Constructor NonlinearConjugateGradientOptimizer(const NonlinearFactorGraph& graph, - const Values& initialValues, const Parameters& params = Parameters()) : - Base(graph), state_(graph, initialValues), params_(params) { - } + const Values& initialValues, const Parameters& params = Parameters()); /// Destructor virtual ~NonlinearConjugateGradientOptimizer() { } - virtual void iterate(); - virtual const Values& optimize(); - virtual const NonlinearOptimizerState& _state() const { - return state_; - } - virtual const NonlinearOptimizerParams& _params() const { - return params_; - } + GaussianFactorGraph::shared_ptr iterate() override; + const Values& optimize() override; }; /** Implement the golden-section line search algorithm */ @@ -156,7 +142,7 @@ boost::tuple nonlinearConjugateGradient(const S &system, // GTSAM_CONCEPT_MANIFOLD_TYPE(V); - int iteration = 0; + size_t iteration = 0; // check if we're already close enough double currentError = system.error(initial); diff --git a/gtsam/nonlinear/NonlinearEquality.h b/gtsam/nonlinear/NonlinearEquality.h index 0d8d717bc..c6aa52ab2 100644 --- a/gtsam/nonlinear/NonlinearEquality.h +++ b/gtsam/nonlinear/NonlinearEquality.h @@ -260,7 +260,7 @@ public: std::cout << s << ": NonlinearEquality1(" << keyFormatter(this->key()) << ")," << "\n"; this->noiseModel_->print(); - value_.print("Value"); + traits::Print(value_, "Value"); } private: diff --git a/gtsam/nonlinear/NonlinearFactor.h b/gtsam/nonlinear/NonlinearFactor.h index 505f58394..dd4c9123a 100644 --- a/gtsam/nonlinear/NonlinearFactor.h +++ b/gtsam/nonlinear/NonlinearFactor.h @@ -131,7 +131,8 @@ public: } /** - * Creates a shared_ptr clone of the factor with different keys using + * Creates a shared_ptr clone of the + * factor with different keys using * a map from old->new keys */ shared_ptr rekey(const std::map& rekey_mapping) const; diff --git a/gtsam/nonlinear/NonlinearFactorGraph.cpp b/gtsam/nonlinear/NonlinearFactorGraph.cpp index ae95fa72b..56234c13c 100644 --- a/gtsam/nonlinear/NonlinearFactorGraph.cpp +++ b/gtsam/nonlinear/NonlinearFactorGraph.cpp @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include #include // for GTSAM_USE_TBB @@ -132,8 +134,8 @@ void NonlinearFactorGraph::saveGraph(std::ostream &stm, const Values& values, // Find bounds double minX = numeric_limits::infinity(), maxX = -numeric_limits::infinity(); double minY = numeric_limits::infinity(), maxY = -numeric_limits::infinity(); - for(Key key: keys) { - if(values.exists(key)) { + for (const Key& key : keys) { + if (values.exists(key)) { boost::optional xy = getXY(values.at(key), formatting); if(xy) { if(xy->x() < minX) @@ -164,8 +166,8 @@ void NonlinearFactorGraph::saveGraph(std::ostream &stm, const Values& values, if (formatting.mergeSimilarFactors) { // Remove duplicate factors std::set > structure; - for(const sharedFactor& factor: *this){ - if(factor) { + for (const sharedFactor& factor : factors_) { + if (factor) { vector factorKeys = factor->keys(); std::sort(factorKeys.begin(), factorKeys.end()); structure.insert(factorKeys); @@ -194,8 +196,8 @@ void NonlinearFactorGraph::saveGraph(std::ostream &stm, const Values& values, } } else { // Create factors and variable connections - for(size_t i = 0; i < this->size(); ++i) { - const NonlinearFactor::shared_ptr& factor = this->at(i); + for(size_t i = 0; i < size(); ++i) { + const NonlinearFactor::shared_ptr& factor = at(i); if(formatting.plotFactorPoints) { const FastVector& keys = factor->keys(); if (formatting.binaryEdges && keys.size()==2) { @@ -245,7 +247,7 @@ double NonlinearFactorGraph::error(const Values& values) const { gttic(NonlinearFactorGraph_error); double total_error = 0.; // iterate over all the factors_ to accumulate the log probabilities - for(const sharedFactor& factor: this->factors_) { + for(const sharedFactor& factor: factors_) { if(factor) total_error += factor->error(values); } @@ -269,9 +271,9 @@ SymbolicFactorGraph::shared_ptr NonlinearFactorGraph::symbolic() const { // Generate the symbolic factor graph SymbolicFactorGraph::shared_ptr symbolic = boost::make_shared(); - symbolic->reserve(this->size()); + symbolic->reserve(size()); - for(const sharedFactor& factor: *this) { + for (const sharedFactor& factor: factors_) { if(factor) *symbolic += SymbolicFactor(*factor); else @@ -319,17 +321,17 @@ GaussianFactorGraph::shared_ptr NonlinearFactorGraph::linearize(const Values& li #ifdef GTSAM_USE_TBB - linearFG->resize(this->size()); + linearFG->resize(size()); TbbOpenMPMixedScope threadLimiter; // Limits OpenMP threads since we're mixing TBB and OpenMP - tbb::parallel_for(tbb::blocked_range(0, this->size()), + tbb::parallel_for(tbb::blocked_range(0, size()), _LinearizeOneFactor(*this, linearizationPoint, *linearFG)); #else - linearFG->reserve(this->size()); + linearFG->reserve(size()); // linearize all factors - for(const sharedFactor& factor: this->factors_) { + for(const sharedFactor& factor: factors_) { if(factor) { (*linearFG) += factor->linearize(linearizationPoint); } else @@ -341,10 +343,70 @@ GaussianFactorGraph::shared_ptr NonlinearFactorGraph::linearize(const Values& li return linearFG; } +/* ************************************************************************* */ +static Scatter scatterFromValues(const Values& values, boost::optional ordering) { + gttic(scatterFromValues); + + Scatter scatter; + scatter.reserve(values.size()); + + if (!ordering) { + // use "natural" ordering with keys taken from the initial values + for (const auto& key_value : values) { + scatter.add(key_value.key, key_value.value.dim()); + } + } else { + // copy ordering into keys and lookup dimension in values, is O(n*log n) + for (Key key : *ordering) { + const Value& value = values.at(key); + scatter.add(key, value.dim()); + } + } + + return scatter; +} + +/* ************************************************************************* */ +HessianFactor::shared_ptr NonlinearFactorGraph::linearizeToHessianFactor( + const Values& values, boost::optional ordering, const Dampen& dampen) const { + gttic(NonlinearFactorGraph_linearizeToHessianFactor); + + Scatter scatter = scatterFromValues(values, ordering); + + // NOTE(frank): we are heavily leaning on friendship below + HessianFactor::shared_ptr hessianFactor(new HessianFactor(scatter)); + + // Initialize so we can rank-update below + hessianFactor->info_.setZero(); + + // linearize all factors straight into the Hessian + // TODO(frank): this saves on creating the graph, but still mallocs a gaussianFactor! + for (const sharedFactor& nonlinearFactor : factors_) { + if (nonlinearFactor) { + const auto& gaussianFactor = nonlinearFactor->linearize(values); + gaussianFactor->updateHessian(hessianFactor->keys_, &hessianFactor->info_); + } + } + + if (dampen) dampen(hessianFactor); + + return hessianFactor; +} + +/* ************************************************************************* */ +Values NonlinearFactorGraph::updateCholesky(const Values& values, + boost::optional ordering, + const Dampen& dampen) const { + gttic(NonlinearFactorGraph_updateCholesky); + auto hessianFactor = linearizeToHessianFactor(values, ordering, dampen); + VectorValues delta = hessianFactor->solve(); + return values.retract(delta); +} + /* ************************************************************************* */ NonlinearFactorGraph NonlinearFactorGraph::clone() const { NonlinearFactorGraph result; - for(const sharedFactor& f: *this) { + for (const sharedFactor& f : factors_) { if (f) result.push_back(f->clone()); else @@ -356,7 +418,7 @@ NonlinearFactorGraph NonlinearFactorGraph::clone() const { /* ************************************************************************* */ NonlinearFactorGraph NonlinearFactorGraph::rekey(const std::map& rekey_mapping) const { NonlinearFactorGraph result; - for(const sharedFactor& f: *this) { + for (const sharedFactor& f : factors_) { if (f) result.push_back(f->rekey(rekey_mapping)); else diff --git a/gtsam/nonlinear/NonlinearFactorGraph.h b/gtsam/nonlinear/NonlinearFactorGraph.h index 3702d8a8f..323461459 100644 --- a/gtsam/nonlinear/NonlinearFactorGraph.h +++ b/gtsam/nonlinear/NonlinearFactorGraph.h @@ -25,6 +25,9 @@ #include #include +#include +#include + namespace gtsam { // Forward declarations @@ -136,14 +139,30 @@ namespace gtsam { */ Ordering orderingCOLAMDConstrained(const FastMap& constraints) const; - /** - * linearize a nonlinear factor graph - */ + /// Linearize a nonlinear factor graph boost::shared_ptr linearize(const Values& linearizationPoint) const; + /// typdef for dampen functions used below + typedef std::function& hessianFactor)> Dampen; + /** - * Clone() performs a deep-copy of the graph, including all of the factors + * Instead of producing a GaussianFactorGraph, pre-allocate and linearize directly + * into a HessianFactor. Avoids the many mallocs and pointer indirection in constructing + * a new graph, and hence useful in case a dense solve is appropriate for your problem. + * An optional ordering can be given that still decides how the Hessian is laid out. + * An optional lambda function can be used to apply damping on the filled Hessian. + * No parallelism is exploited, because all the factors write in the same memory. */ + boost::shared_ptr linearizeToHessianFactor( + const Values& values, boost::optional ordering = boost::none, + const Dampen& dampen = nullptr) const; + + /// Linearize and solve in one pass. + /// Calls linearizeToHessianFactor, densely solves the normal equations, and updates the values. + Values updateCholesky(const Values& values, boost::optional ordering = boost::none, + const Dampen& dampen = nullptr) const; + + /// Clone() performs a deep-copy of the graph, including all of the factors NonlinearFactorGraph clone() const; /** diff --git a/gtsam/nonlinear/NonlinearOptimizer.cpp b/gtsam/nonlinear/NonlinearOptimizer.cpp index bb7b9717b..e1efa2061 100644 --- a/gtsam/nonlinear/NonlinearOptimizer.cpp +++ b/gtsam/nonlinear/NonlinearOptimizer.cpp @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- - * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) @@ -17,7 +17,7 @@ */ #include - +#include #include #include #include @@ -39,48 +39,74 @@ using namespace std; namespace gtsam { /* ************************************************************************* */ -void NonlinearOptimizer::defaultOptimize() { +// NOTE(frank): unique_ptr by-value takes ownership, as discussed in +// http://stackoverflow.com/questions/8114276/ +NonlinearOptimizer::NonlinearOptimizer(const NonlinearFactorGraph& graph, + std::unique_ptr state) + : graph_(graph), state_(std::move(state)) {} - const NonlinearOptimizerParams& params = this->_params(); - double currentError = this->error(); +/* ************************************************************************* */ +NonlinearOptimizer::~NonlinearOptimizer() {} + +/* ************************************************************************* */ +double NonlinearOptimizer::error() const { + return state_->error; +} + +size_t NonlinearOptimizer::iterations() const { + return state_->iterations; +} + +const Values& NonlinearOptimizer::values() const { + return state_->values; +} + +/* ************************************************************************* */ +void NonlinearOptimizer::defaultOptimize() { + const NonlinearOptimizerParams& params = _params(); + double currentError = error(); // check if we're already close enough - if(currentError <= params.errorTol) { + if (currentError <= params.errorTol) { if (params.verbosity >= NonlinearOptimizerParams::ERROR) cout << "Exiting, as error = " << currentError << " < " << params.errorTol << endl; return; } // Maybe show output - if (params.verbosity >= NonlinearOptimizerParams::VALUES) this->values().print("Initial values"); - if (params.verbosity >= NonlinearOptimizerParams::ERROR) cout << "Initial error: " << currentError << endl; + if (params.verbosity >= NonlinearOptimizerParams::VALUES) + values().print("Initial values"); + if (params.verbosity >= NonlinearOptimizerParams::ERROR) + cout << "Initial error: " << currentError << endl; // Return if we already have too many iterations - if(this->iterations() >= params.maxIterations){ + if (iterations() >= params.maxIterations) { if (params.verbosity >= NonlinearOptimizerParams::TERMINATION) { - cout << "iterations: " << this->iterations() << " >? " << params.maxIterations << endl; - } + cout << "iterations: " << iterations() << " >? " << params.maxIterations << endl; + } return; } // Iterative loop do { // Do next iteration - currentError = this->error(); - this->iterate(); + currentError = error(); + iterate(); tictoc_finishedIteration(); // Maybe show output - if(params.verbosity >= NonlinearOptimizerParams::VALUES) this->values().print("newValues"); - if(params.verbosity >= NonlinearOptimizerParams::ERROR) cout << "newError: " << this->error() << endl; - } while(this->iterations() < params.maxIterations && - !checkConvergence(params.relativeErrorTol, params.absoluteErrorTol, - params.errorTol, currentError, this->error(), params.verbosity)); + if (params.verbosity >= NonlinearOptimizerParams::VALUES) + values().print("newValues"); + if (params.verbosity >= NonlinearOptimizerParams::ERROR) + cout << "newError: " << error() << endl; + } while (iterations() < params.maxIterations && + !checkConvergence(params.relativeErrorTol, params.absoluteErrorTol, params.errorTol, + currentError, error(), params.verbosity)); // Printing if verbose if (params.verbosity >= NonlinearOptimizerParams::TERMINATION) { - cout << "iterations: " << this->iterations() << " >? " << params.maxIterations << endl; - if (this->iterations() >= params.maxIterations) + cout << "iterations: " << iterations() << " >? " << params.maxIterations << endl; + if (iterations() >= params.maxIterations) cout << "Terminating because reached maximum iterations" << endl; } } @@ -98,38 +124,41 @@ const Values& NonlinearOptimizer::optimizeSafely() { } /* ************************************************************************* */ -VectorValues NonlinearOptimizer::solve(const GaussianFactorGraph &gfg, - const Values& initial, const NonlinearOptimizerParams& params) const { - +VectorValues NonlinearOptimizer::solve(const GaussianFactorGraph& gfg, + const NonlinearOptimizerParams& params) const { // solution of linear solver is an update to the linearization point VectorValues delta; + boost::optional optionalOrdering; + if (params.ordering) + optionalOrdering.reset(*params.ordering); // Check which solver we are using if (params.isMultifrontal()) { // Multifrontal QR or Cholesky (decided by params.getEliminationFunction()) - delta = gfg.optimize(*params.ordering, params.getEliminationFunction()); + delta = gfg.optimize(optionalOrdering, params.getEliminationFunction()); } else if (params.isSequential()) { // Sequential QR or Cholesky (decided by params.getEliminationFunction()) - delta = gfg.eliminateSequential(*params.ordering, - params.getEliminationFunction(), boost::none, params.orderingType)->optimize(); + delta = gfg.eliminateSequential(optionalOrdering, params.getEliminationFunction(), boost::none, + params.orderingType)->optimize(); } else if (params.isIterative()) { - // Conjugate Gradient -> needs params.iterativeParams if (!params.iterativeParams) throw std::runtime_error("NonlinearOptimizer::solve: cg parameter has to be assigned ..."); - if (boost::shared_ptr pcg = boost::dynamic_pointer_cast(params.iterativeParams) ) { + if (boost::shared_ptr pcg = + boost::dynamic_pointer_cast(params.iterativeParams)) { delta = PCGSolver(*pcg).optimize(gfg); - } - else if (boost::shared_ptr spcg = boost::dynamic_pointer_cast(params.iterativeParams) ) { + } else if (boost::shared_ptr spcg = + boost::dynamic_pointer_cast(params.iterativeParams)) { + if (!params.ordering) + throw std::runtime_error("SubgraphSolver needs an ordering"); delta = SubgraphSolver(gfg, *spcg, *params.ordering).optimize(); - } - else { - throw std::runtime_error("NonlinearOptimizer::solve: special cg parameter type is not handled in LM solver ..."); + } else { + throw std::runtime_error( + "NonlinearOptimizer::solve: special cg parameter type is not handled in LM solver ..."); } } else { - throw std::runtime_error( - "NonlinearOptimizer::solve: Optimization parameter is invalid"); + throw std::runtime_error("NonlinearOptimizer::solve: Optimization parameter is invalid"); } // return update @@ -138,47 +167,52 @@ VectorValues NonlinearOptimizer::solve(const GaussianFactorGraph &gfg, /* ************************************************************************* */ bool checkConvergence(double relativeErrorTreshold, double absoluteErrorTreshold, - double errorThreshold, double currentError, double newError, - NonlinearOptimizerParams::Verbosity verbosity) { - - if ( verbosity >= NonlinearOptimizerParams::ERROR ) { - if ( newError <= errorThreshold ) + double errorThreshold, double currentError, double newError, + NonlinearOptimizerParams::Verbosity verbosity) { + if (verbosity >= NonlinearOptimizerParams::ERROR) { + if (newError <= errorThreshold) cout << "errorThreshold: " << newError << " < " << errorThreshold << endl; else cout << "errorThreshold: " << newError << " > " << errorThreshold << endl; } - if ( newError <= errorThreshold ) return true ; + if (newError <= errorThreshold) + return true; // check if diverges double absoluteDecrease = currentError - newError; if (verbosity >= NonlinearOptimizerParams::ERROR) { if (absoluteDecrease <= absoluteErrorTreshold) - cout << "absoluteDecrease: " << setprecision(12) << absoluteDecrease << " < " << absoluteErrorTreshold << endl; + cout << "absoluteDecrease: " << setprecision(12) << absoluteDecrease << " < " + << absoluteErrorTreshold << endl; else - cout << "absoluteDecrease: " << setprecision(12) << absoluteDecrease << " >= " << absoluteErrorTreshold << endl; + cout << "absoluteDecrease: " << setprecision(12) << absoluteDecrease + << " >= " << absoluteErrorTreshold << endl; } // calculate relative error decrease and update currentError double relativeDecrease = absoluteDecrease / currentError; if (verbosity >= NonlinearOptimizerParams::ERROR) { if (relativeDecrease <= relativeErrorTreshold) - cout << "relativeDecrease: " << setprecision(12) << relativeDecrease << " < " << relativeErrorTreshold << endl; + cout << "relativeDecrease: " << setprecision(12) << relativeDecrease << " < " + << relativeErrorTreshold << endl; else - cout << "relativeDecrease: " << setprecision(12) << relativeDecrease << " >= " << relativeErrorTreshold << endl; + cout << "relativeDecrease: " << setprecision(12) << relativeDecrease + << " >= " << relativeErrorTreshold << endl; } - bool converged = (relativeErrorTreshold && (relativeDecrease <= relativeErrorTreshold)) - || (absoluteDecrease <= absoluteErrorTreshold); + bool converged = (relativeErrorTreshold && (relativeDecrease <= relativeErrorTreshold)) || + (absoluteDecrease <= absoluteErrorTreshold); if (verbosity >= NonlinearOptimizerParams::TERMINATION && converged) { - - if(absoluteDecrease >= 0.0) + if (absoluteDecrease >= 0.0) cout << "converged" << endl; else cout << "Warning: stopping nonlinear iterations because error increased" << endl; cout << "errorThreshold: " << newError << " optimize(); +Values result = optimizer->optimize(); // The new optimizer has results and statistics -cout << "Converged in " << final->iterations() << " iterations " - "with final error " << final->error() << endl; - -// The values are a const_shared_ptr (boost::shared_ptr) -Values::const_shared_ptr result = final->values(); - -// Use the results -useTheResult(result); +cout << "Converged in " << optimizer.iterations() << " iterations " + "with final error " << optimizer.error() << endl; \endcode * * Example of setting parameters before optimization: @@ -112,29 +61,23 @@ params.relativeErrorTol = 1e-3; params.absoluteErrorTol = 1e-3; // Optimize -Values::const_shared_ptr result = DoglegOptimizer(graph, initialValues, params).optimized(); +Values result = DoglegOptimizer(graph, initialValues, params).optimize(); \endcode * * This interface also exposes an iterate() method, which performs one - * iteration, returning a NonlinearOptimizer containing the adjusted variable - * assignment. The optimize() method simply calls iterate() multiple times, + * iteration. The optimize() method simply calls iterate() multiple times, * until the error changes less than a threshold. We expose iterate() so that * you can easily control what happens between iterations, such as drawing or * printing, moving points from behind the camera to in front, etc. * - * To modify the graph, values, or parameters between iterations, call the - * update() functions, which preserve all other state (for example, the trust - * region size in DoglegOptimizer). Derived optimizer classes also have - * additional update methods, not in this abstract interface, for updating - * algorithm-specific state. - * - * For more flexibility, since all functions are virtual, you may override them - * in your own derived class. + * For more flexibility you may override virtual methods in your own derived class. */ class GTSAM_EXPORT NonlinearOptimizer { protected: - NonlinearFactorGraph graph_; + NonlinearFactorGraph graph_; ///< The graph with nonlinear factors + + std::unique_ptr state_; ///< PIMPL'd state public: /** A shared pointer to this class */ @@ -163,13 +106,13 @@ public: const Values& optimizeSafely(); /// return error - double error() const { return _state().error; } + double error() const; /// return number of iterations - int iterations() const { return _state().iterations; } + size_t iterations() const; /// return values - const Values& values() const { return _state().values; } + const Values& values() const; /// @} @@ -177,17 +120,17 @@ public: /// @{ /** Virtual destructor */ - virtual ~NonlinearOptimizer() {} + virtual ~NonlinearOptimizer(); /** Default function to do linear solve, i.e. optimize a GaussianFactorGraph */ virtual VectorValues solve(const GaussianFactorGraph &gfg, - const Values& initial, const NonlinearOptimizerParams& params) const; + const NonlinearOptimizerParams& params) const; /** Perform a single iteration, returning a new NonlinearOptimizer class * containing the updated variable assignments, which may be retrieved with * values(). */ - virtual void iterate() = 0; + virtual GaussianFactorGraph::shared_ptr iterate() = 0; /// @} @@ -197,13 +140,11 @@ protected: */ void defaultOptimize(); - virtual const NonlinearOptimizerState& _state() const = 0; - virtual const NonlinearOptimizerParams& _params() const = 0; - /** Constructor for initial construction of base classes. */ - NonlinearOptimizer(const NonlinearFactorGraph& graph) : graph_(graph) {} - + /** Constructor for initial construction of base classes. Takes ownership of state. */ + NonlinearOptimizer(const NonlinearFactorGraph& graph, + std::unique_ptr state); }; /** Check whether the relative error decrease is less than relativeErrorTreshold, diff --git a/gtsam/nonlinear/NonlinearOptimizerParams.h b/gtsam/nonlinear/NonlinearOptimizerParams.h index ca75bb02a..88fc0f850 100644 --- a/gtsam/nonlinear/NonlinearOptimizerParams.h +++ b/gtsam/nonlinear/NonlinearOptimizerParams.h @@ -38,7 +38,7 @@ public: SILENT, TERMINATION, ERROR, VALUES, DELTA, LINEAR }; - int maxIterations; ///< The maximum iterations to stop iterating (default 100) + size_t maxIterations; ///< The maximum iterations to stop iterating (default 100) double relativeErrorTol; ///< The maximum relative error decrease to stop iterating (default 1e-5) double absoluteErrorTol; ///< The maximum absolute error decrease to stop iterating (default 1e-5) double errorTol; ///< The maximum total error to stop iterating (default 0.0) @@ -54,7 +54,7 @@ public: } virtual void print(const std::string& str = "") const; - int getMaxIterations() const { + size_t getMaxIterations() const { return maxIterations; } double getRelativeErrorTol() const { diff --git a/gtsam/nonlinear/Values.cpp b/gtsam/nonlinear/Values.cpp index e21661fee..1bd8b3a73 100644 --- a/gtsam/nonlinear/Values.cpp +++ b/gtsam/nonlinear/Values.cpp @@ -36,6 +36,7 @@ #include #include +#include #include using namespace std; @@ -47,12 +48,32 @@ namespace gtsam { this->insert(other); } + /* ************************************************************************* */ + Values::Values(Values&& other) : values_(std::move(other.values_)) { + } + + /* ************************************************************************* */ + Values::Values(const Values& other, const VectorValues& delta) { + for (const_iterator key_value = other.begin(); key_value != other.end(); ++key_value) { + VectorValues::const_iterator it = delta.find(key_value->key); + Key key = key_value->key; // Non-const duplicate to deal with non-const insert argument + if (it != delta.end()) { + const Vector& v = it->second; + Value* retractedValue(key_value->value.retract_(v)); // Retract + values_.insert(key, retractedValue); // Add retracted result directly to result values + } else { + values_.insert(key, key_value->value.clone_()); // Add original version to result values + } + } + } + /* ************************************************************************* */ void Values::print(const string& str, const KeyFormatter& keyFormatter) const { cout << str << "Values with " << size() << " values:" << endl; for(const_iterator key_value = begin(); key_value != end(); ++key_value) { cout << "Value " << keyFormatter(key_value->key) << ": "; key_value->value.print(""); + cout << "\n"; } } @@ -78,23 +99,8 @@ namespace gtsam { } /* ************************************************************************* */ - Values Values::retract(const VectorValues& delta) const - { - Values result; - - for(const_iterator key_value = begin(); key_value != end(); ++key_value) { - VectorValues::const_iterator vector_item = delta.find(key_value->key); - Key key = key_value->key; // Non-const duplicate to deal with non-const insert argument - if(vector_item != delta.end()) { - const Vector& singleDelta = vector_item->second; - Value* retractedValue(key_value->value.retract_(singleDelta)); // Retract - result.values_.insert(key, retractedValue); // Add retracted result directly to result values - } else { - result.values_.insert(key, key_value->value.clone_()); // Add original version to result values - } - } - - return result; + Values Values::retract(const VectorValues& delta) const { + return Values(*this, delta); } /* ************************************************************************* */ diff --git a/gtsam/nonlinear/Values.h b/gtsam/nonlinear/Values.h index a61d01f23..bf17f1f0d 100644 --- a/gtsam/nonlinear/Values.h +++ b/gtsam/nonlinear/Values.h @@ -146,6 +146,12 @@ namespace gtsam { /** Copy constructor duplicates all keys and values */ Values(const Values& other); + /** Move constructor */ + Values(Values&& other); + + /** Construct from a Values and an update vector: identical to other.retract(delta) */ + Values(const Values& other, const VectorValues& delta); + /** Constructor from a Filtered view copies out all values */ template Values(const Filtered& view); diff --git a/gtsam/nonlinear/internal/CallRecord.h b/gtsam/nonlinear/internal/CallRecord.h index 6616f0a83..e58c40203 100644 --- a/gtsam/nonlinear/internal/CallRecord.h +++ b/gtsam/nonlinear/internal/CallRecord.h @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- - * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) diff --git a/gtsam/nonlinear/internal/ExpressionNode.h b/gtsam/nonlinear/internal/ExpressionNode.h index 966f43da8..d11908b54 100644 --- a/gtsam/nonlinear/internal/ExpressionNode.h +++ b/gtsam/nonlinear/internal/ExpressionNode.h @@ -175,7 +175,7 @@ public: /// Print virtual void print(const std::string& indent = "") const { - std::cout << indent << "Leaf, key = " << key_ << std::endl; + std::cout << indent << "Leaf, key = " << DefaultKeyFormatter(key_) << std::endl; } /// Return keys that play in this expression @@ -310,11 +310,13 @@ public: assert(reinterpret_cast(ptr) % TraceAlignment == 0); // Create a Record in the memory pointed to by ptr - // Calling the construct will record the traces for all arguments + // Calling the constructor will record the traces for all arguments // Write an Expression execution trace in record->trace // Iff Constant or Leaf, this will not write to traceStorage, only to trace. // Iff the expression is functional, write all Records in traceStorage buffer // Return value of type T is recorded in record->value + // NOTE(frank, abe): The destructor on this record is never called due to this placement new + // Records must only contain statically sized objects! Record* record = new (ptr) Record(values, *expression1_, ptr); // Our trace parameter is set to point to the Record @@ -389,6 +391,7 @@ public: ExecutionTrace trace1; ExecutionTrace trace2; + // TODO(frank): These aren't needed kill them! A1 value1; A2 value2; @@ -632,91 +635,82 @@ class ScalarMultiplyNode : public ExpressionNode { } }; + //----------------------------------------------------------------------------- -/// Sum Expression +/// Binary Sum Expression template -class SumExpressionNode : public ExpressionNode { +class BinarySumNode : public ExpressionNode { typedef ExpressionNode NodeT; - std::vector> expressions_; + boost::shared_ptr > expression1_; + boost::shared_ptr > expression2_; public: - explicit SumExpressionNode(const std::vector>& expressions) { + explicit BinarySumNode() { this->traceSize_ = upAligned(sizeof(Record)); - for (const Expression& e : expressions) - add(e); } - void add(const Expression& e) { - expressions_.push_back(e.root()); - this->traceSize_ += e.traceSize(); + /// Constructor with a binary function f, and two input arguments + BinarySumNode(const Expression& e1, const Expression& e2) + : expression1_(e1.root()), expression2_(e2.root()) { + this->traceSize_ = // + upAligned(sizeof(Record)) + e1.traceSize() + e2.traceSize(); } /// Destructor - virtual ~SumExpressionNode() {} - - size_t nrTerms() const { - return expressions_.size(); - } + virtual ~BinarySumNode() {} /// Print virtual void print(const std::string& indent = "") const { - std::cout << indent << "SumExpressionNode" << std::endl; - for (const auto& node : expressions_) - node->print(indent + " "); + std::cout << indent << "BinarySumNode" << std::endl; + expression1_->print(indent + " "); + expression2_->print(indent + " "); } /// Return value virtual T value(const Values& values) const { - auto it = expressions_.begin(); - T sum = (*it)->value(values); - for (++it; it != expressions_.end(); ++it) - sum = sum + (*it)->value(values); - return sum; + return expression1_->value(values) + expression2_->value(values); } /// Return keys that play in this expression virtual std::set keys() const { - std::set keys; - for (const auto& node : expressions_) { - std::set myKeys = node->keys(); - keys.insert(myKeys.begin(), myKeys.end()); - } + std::set keys = expression1_->keys(); + std::set myKeys = expression2_->keys(); + keys.insert(myKeys.begin(), myKeys.end()); return keys; } /// Return dimensions for each argument virtual void dims(std::map& map) const { - for (const auto& node : expressions_) - node->dims(map); + expression1_->dims(map); + expression2_->dims(map); } // Inner Record Class struct Record : public CallRecordImplementor::dimension> { - std::vector> traces_; - - explicit Record(size_t nrArguments) : traces_(nrArguments) {} + ExecutionTrace trace1; + ExecutionTrace trace2; /// Print to std::cout void print(const std::string& indent) const { - std::cout << indent << "SumExpressionNode::Record {" << std::endl; - for (const auto& trace : traces_) - trace.print(indent); + std::cout << indent << "BinarySumNode::Record {" << std::endl; + trace1.print(indent); + trace2.print(indent); std::cout << indent << "}" << std::endl; } - /// If the SumExpression is the root, we just start as many pipelines as there are terms. + /// If the BinarySumExpression is the root, we just start as many pipelines as there are terms. void startReverseAD4(JacobianMap& jacobians) const { - for (const auto& trace : traces_) - // NOTE(frank): equivalent to trace.reverseAD1(dTdA, jacobians) with dTdA=Identity - trace.startReverseAD1(jacobians); + // NOTE(frank): equivalent to trace.reverseAD1(dTdA, jacobians) with dTdA=Identity + trace1.startReverseAD1(jacobians); + trace2.startReverseAD1(jacobians); } /// If we are not the root, we simply pass on the adjoint matrix dFdT to all terms template void reverseAD4(const MatrixType& dFdT, JacobianMap& jacobians) const { - for (const auto& trace : traces_) - // NOTE(frank): equivalent to trace.reverseAD1(dFdT * dTdA, jacobians) with dTdA=Identity - trace.reverseAD1(dFdT, jacobians); + // NOTE(frank): equivalent to trace.reverseAD1(dFdT * dTdA, jacobians) with dTdA=Identity + trace1.reverseAD1(dFdT, jacobians); + trace2.reverseAD1(dFdT, jacobians); } }; @@ -724,17 +718,13 @@ class SumExpressionNode : public ExpressionNode { virtual T traceExecution(const Values& values, ExecutionTrace& trace, ExecutionTraceStorage* ptr) const { assert(reinterpret_cast(ptr) % TraceAlignment == 0); - size_t nrArguments = expressions_.size(); - Record* record = new (ptr) Record(nrArguments); - ptr += upAligned(sizeof(Record)); - size_t i = 0; - T sum = traits::Identity(); - for (const auto& node : expressions_) { - sum = sum + node->traceExecution(values, record->traces_[i++], ptr); - ptr += node->traceSize(); - } + Record* record = new (ptr) Record(); trace.setFunction(record); - return sum; + + ExecutionTraceStorage* ptr1 = ptr + upAligned(sizeof(Record)); + ExecutionTraceStorage* ptr2 = ptr1 + expression1_->traceSize(); + return expression1_->traceExecution(values, record->trace1, ptr1) + + expression2_->traceExecution(values, record->trace2, ptr2); } }; diff --git a/gtsam/nonlinear/internal/LevenbergMarquardtState.h b/gtsam/nonlinear/internal/LevenbergMarquardtState.h new file mode 100644 index 000000000..19a390c45 --- /dev/null +++ b/gtsam/nonlinear/internal/LevenbergMarquardtState.h @@ -0,0 +1,160 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file LevenbergMarquardtState.h + * @brief A LevenbergMarquardtState class containing most of the logic for Levenberg-Marquardt + * @author Frank Dellaert + * @date April 2016 + */ + +#include "NonlinearOptimizerState.h" + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include + +namespace gtsam { + +namespace internal { + +// TODO(frank): once Values supports move, we can make State completely functional. +// As it is now, increaseLambda is non-const or otherwise we make a Values copy every time +// decreaseLambda would also benefit from a working Values move constructor +struct LevenbergMarquardtState : public NonlinearOptimizerState { + typedef LevenbergMarquardtState This; + + // TODO(frank): make these const once increaseLambda can be made const + double lambda; + double currentFactor; + int totalNumberInnerIterations; ///< The total number of inner iterations in the + // optimization (for each iteration, LM tries multiple + // inner iterations with different lambdas) + + LevenbergMarquardtState(const Values& initialValues, double error, double lambda, + double currentFactor, unsigned int iterations = 0, + unsigned int totalNumberInnerIterations = 0) + : NonlinearOptimizerState(initialValues, error, iterations), + lambda(lambda), + currentFactor(currentFactor), + totalNumberInnerIterations(totalNumberInnerIterations) {} + + // Constructor version that takes ownership of values + LevenbergMarquardtState(Values&& initialValues, double error, double lambda, double currentFactor, + unsigned int iterations = 0, unsigned int totalNumberInnerIterations = 0) + : NonlinearOptimizerState(initialValues, error, iterations), + lambda(lambda), + currentFactor(currentFactor), + totalNumberInnerIterations(totalNumberInnerIterations) {} + + // Applies policy to *increase* lambda: should be used if the current update was NOT successful + // TODO(frank): non-const method until Values properly support std::move + void increaseLambda(const LevenbergMarquardtParams& params) { + lambda *= currentFactor; + totalNumberInnerIterations += 1; + if (!params.useFixedLambdaFactor) { + currentFactor *= 2.0; + } + } + + // Apply policy to decrease lambda if the current update was successful + // stepQuality not used in the naive policy) + // Take ownsership of newValues, must be passed an rvalue + std::unique_ptr decreaseLambda(const LevenbergMarquardtParams& params, double stepQuality, + Values&& newValues, double newError) const { + double newLambda = lambda, newFactor = currentFactor; + if (params.useFixedLambdaFactor) { + newLambda /= currentFactor; + } else { + // TODO(frank): odd that currentFactor is not used to change lambda here... + newLambda *= std::max(1.0 / 3.0, 1.0 - pow(2.0 * stepQuality - 1.0, 3)); + newFactor = 2.0 * currentFactor; + } + newLambda = std::max(params.lambdaLowerBound, newLambda); + return std::unique_ptr(new This(std::move(newValues), newError, newLambda, newFactor, + iterations + 1, totalNumberInnerIterations + 1)); + } + + /** Small struct to cache objects needed for damping. + * This is used in buildDampedSystem */ + struct CachedModel { + CachedModel() {} // default int makes zero-size matrices + CachedModel(int dim, double sigma) + : A(Matrix::Identity(dim, dim)), + b(Vector::Zero(dim)), + model(noiseModel::Isotropic::Sigma(dim, sigma)) {} + CachedModel(int dim, double sigma, const Vector& diagonal) + : A(Eigen::DiagonalMatrix(diagonal)), + b(Vector::Zero(dim)), + model(noiseModel::Isotropic::Sigma(dim, sigma)) {} + Matrix A; + Vector b; + SharedDiagonal model; + }; + + // Small cache of A|b|model indexed by dimension. Can save many mallocs. + mutable std::vector noiseModelCache; + CachedModel* getCachedModel(size_t dim) const { + if (dim > noiseModelCache.size()) + noiseModelCache.resize(dim); + CachedModel* item = &noiseModelCache[dim - 1]; + if (!item->model) + *item = CachedModel(dim, 1.0 / std::sqrt(lambda)); + return item; + }; + + /// Build a damped system for a specific lambda, vanilla version + GaussianFactorGraph buildDampedSystem(GaussianFactorGraph damped /* gets copied */) const { + noiseModelCache.resize(0); + // for each of the variables, add a prior + damped.reserve(damped.size() + values.size()); + for (const auto& key_value : values) { + const Key key = key_value.key; + const size_t dim = key_value.value.dim(); + const CachedModel* item = getCachedModel(dim); + damped += boost::make_shared(key, item->A, item->b, item->model); + } + return damped; + } + + /// Build a damped system, use hessianDiagonal per variable (more expensive) + GaussianFactorGraph buildDampedSystem(GaussianFactorGraph damped, // gets copied + const VectorValues& sqrtHessianDiagonal) const { + noiseModelCache.resize(0); + damped.reserve(damped.size() + values.size()); + for (const auto& key_vector : sqrtHessianDiagonal) { + try { + const Key key = key_vector.first; + const size_t dim = key_vector.second.size(); + CachedModel* item = getCachedModel(dim); + item->A.diagonal() = sqrtHessianDiagonal.at(key); // use diag(hessian) + damped += boost::make_shared(key, item->A, item->b, item->model); + } catch (const std::out_of_range& e) { + continue; // Don't attempt any damping if no key found in diagonal + } + } + return damped; + } +}; + +} // namespace internal + +} /* namespace gtsam */ diff --git a/gtsam/nonlinear/internal/NonlinearOptimizerState.h b/gtsam/nonlinear/internal/NonlinearOptimizerState.h new file mode 100644 index 000000000..0c65d91f9 --- /dev/null +++ b/gtsam/nonlinear/internal/NonlinearOptimizerState.h @@ -0,0 +1,56 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file NonlinearOptimizerState.h + * @brief Private class for NonlinearOptimizer state + * @author Richard Roberts + * @author Frank Dellaert + * @date Sep 7, 2009 + */ + +#pragma once + +#include + +namespace gtsam { +namespace internal { + +/** + * Base class for a nonlinear optimization state, including the current estimate + * of the variable values, error, and number of iterations. Optimizers derived + * from NonlinearOptimizer usually also define a derived state class containing + * additional state specific to the algorithm (for example, Dogleg state + * contains the current trust region radius). + */ +struct NonlinearOptimizerState { + public: + /** The current estimate of the variable values. */ + const Values values; + + /** The factor graph error on the current values. */ + const double error; + + /** The number of optimization iterations performed. */ + const size_t iterations; + + virtual ~NonlinearOptimizerState() {} + + NonlinearOptimizerState(const Values& values, double error, size_t iterations = 0) + : values(values), error(error), iterations(iterations) {} + + // Constructor version that takes ownership of values + NonlinearOptimizerState(Values&& values, double error, size_t iterations = 0) + : values(std::move(values)), error(error), iterations(iterations) {} +}; + +} // namespace internal +} // namespace gtsam diff --git a/gtsam/nonlinear/tests/testExpression.cpp b/gtsam/nonlinear/tests/testExpression.cpp index dece9bad8..bde79e780 100644 --- a/gtsam/nonlinear/tests/testExpression.cpp +++ b/gtsam/nonlinear/tests/testExpression.cpp @@ -80,7 +80,7 @@ TEST(Expression, Leaves) { // Unary(Leaf) namespace unary { Point2 f1(const Point3& p, OptionalJacobian<2, 3> H) { - return Point2(); + return Point2(0,0); } double f2(const Point3& p, OptionalJacobian<1, 3> H) { return 0.0; @@ -111,24 +111,43 @@ TEST(Expression, Unary3) { } /* ************************************************************************* */ +class Class : public Point3 { + public: + enum {dimension = 3}; + using Point3::Point3; + const Vector3& vector() const { return *this; } + inline static Class identity() { return Class(0,0,0); } + double norm(OptionalJacobian<1,3> H = boost::none) const { + return norm3(*this, H); + } + bool equals(const Class &q, double tol) const { + return (fabs(x() - q.x()) < tol && fabs(y() - q.y()) < tol && fabs(z() - q.z()) < tol); + } + void print(const string& s) const { cout << s << *this << endl;} +}; + +namespace gtsam { +template<> struct traits : public internal::VectorSpace {}; +} + // Nullary Method TEST(Expression, NullaryMethod) { // Create expression - Expression p(67); - Expression norm(>sam::norm, p); + Expression p(67); + Expression norm_(p, &Class::norm); // Create Values Values values; - values.insert(67, Point3(3, 4, 5)); + values.insert(67, Class(3, 4, 5)); // Check dims as map std::map map; - norm.dims(map); + norm_.dims(map); LONGS_EQUAL(1, map.size()); // Get value and Jacobians std::vector H(1); - double actual = norm.value(values, H); + double actual = norm_.value(values, H); // Check all EXPECT(actual == sqrt(50)); @@ -288,18 +307,18 @@ TEST(Expression, ternary) { /* ************************************************************************* */ TEST(Expression, ScalarMultiply) { const Key key(67); - const Point3_ sum_ = 23 * Point3_(key); + const Point3_ expr = 23 * Point3_(key); set expected_keys = list_of(key); - EXPECT(expected_keys == sum_.keys()); + EXPECT(expected_keys == expr.keys()); map actual_dims, expected_dims = map_list_of(key, 3); - sum_.dims(actual_dims); + expr.dims(actual_dims); EXPECT(actual_dims == expected_dims); // Check dims as map std::map map; - sum_.dims(map); + expr.dims(map); LONGS_EQUAL(1, map.size()); Values values; @@ -307,16 +326,16 @@ TEST(Expression, ScalarMultiply) { // Check value const Point3 expected(23, 0, 46); - EXPECT(assert_equal(expected, sum_.value(values))); + EXPECT(assert_equal(expected, expr.value(values))); // Check value + Jacobians std::vector H(1); - EXPECT(assert_equal(expected, sum_.value(values, H))); + EXPECT(assert_equal(expected, expr.value(values, H))); EXPECT(assert_equal(23 * I_3x3, H[0])); } /* ************************************************************************* */ -TEST(Expression, Sum) { +TEST(Expression, BinarySum) { const Key key(67); const Point3_ sum_ = Point3_(key) + Point3_(Point3(1, 1, 1)); @@ -349,9 +368,31 @@ TEST(Expression, Sum) { TEST(Expression, TripleSum) { const Key key(67); const Point3_ p1_(Point3(1, 1, 1)), p2_(key); - const SumExpression sum_ = p1_ + p2_ + p1_; + const Expression sum_ = p1_ + p2_ + p1_; + + LONGS_EQUAL(1, sum_.keys().size()); + + Values values; + values.insert(key, Point3(2, 2, 2)); + + // Check value + const Point3 expected(4, 4, 4); + EXPECT(assert_equal(expected, sum_.value(values))); + + // Check value + Jacobians + std::vector H(1); + EXPECT(assert_equal(expected, sum_.value(values, H))); + EXPECT(assert_equal(I_3x3, H[0])); +} + +/* ************************************************************************* */ +TEST(Expression, PlusEqual) { + const Key key(67); + const Point3_ p1_(Point3(1, 1, 1)), p2_(key); + Expression sum_ = p1_; + sum_ += p2_; + sum_ += p1_; - LONGS_EQUAL(3, sum_.nrTerms()); LONGS_EQUAL(1, sum_.keys().size()); Values values; @@ -370,7 +411,7 @@ TEST(Expression, TripleSum) { /* ************************************************************************* */ TEST(Expression, SumOfUnaries) { const Key key(67); - const Double_ norm_(>sam::norm, Point3_(key)); + const Double_ norm_(>sam::norm3, Point3_(key)); const Double_ sum_ = norm_ + norm_; Values values; @@ -389,7 +430,7 @@ TEST(Expression, SumOfUnaries) { TEST(Expression, UnaryOfSum) { const Key key1(42), key2(67); const Point3_ sum_ = Point3_(key1) + Point3_(key2); - const Double_ norm_(>sam::norm, sum_); + const Double_ norm_(>sam::norm3, sum_); map actual_dims, expected_dims = map_list_of(key1, 3)(key2, 3); norm_.dims(actual_dims); diff --git a/gtsam/nonlinear/tests/testValues.cpp b/gtsam/nonlinear/tests/testValues.cpp index b7c4efeca..c82ba3391 100644 --- a/gtsam/nonlinear/tests/testValues.cpp +++ b/gtsam/nonlinear/tests/testValues.cpp @@ -31,6 +31,7 @@ using namespace boost::assign; #include #include +#include using namespace gtsam; using namespace std; @@ -47,9 +48,9 @@ class TestValueData { public: static int ConstructorCount; static int DestructorCount; - TestValueData(const TestValueData& other) { /*cout << "Copy constructor" << endl;*/ ++ ConstructorCount; } - TestValueData() { /*cout << "Default constructor" << endl;*/ ++ ConstructorCount; } - ~TestValueData() { /*cout << "Destructor" << endl;*/ ++ DestructorCount; } + TestValueData(const TestValueData& other) { ++ ConstructorCount; } + TestValueData() { ++ ConstructorCount; } + ~TestValueData() { ++ DestructorCount; } }; int TestValueData::ConstructorCount = 0; int TestValueData::DestructorCount = 0; @@ -76,7 +77,6 @@ namespace gtsam { template <> struct traits : public internal::Manifold {}; } - /* ************************************************************************* */ TEST( Values, equals1 ) { @@ -198,28 +198,14 @@ TEST(Values, basic_functions) } -///* ************************************************************************* */ -//TEST(Values, dim_zero) -//{ -// Values config0; -// config0.insert(key1, Vector2(Vector2(2.0, 3.0)); -// config0.insert(key2, Vector3(5.0, 6.0, 7.0)); -// LONGS_EQUAL(5, config0.dim()); -// -// VectorValues expected; -// expected.insert(key1, zero(2)); -// expected.insert(key2, zero(3)); -// CHECK(assert_equal(expected, config0.zero())); -//} - /* ************************************************************************* */ -TEST(Values, expmap_a) +TEST(Values, retract_full) { Values config0; config0.insert(key1, Vector3(1.0, 2.0, 3.0)); config0.insert(key2, Vector3(5.0, 6.0, 7.0)); - VectorValues increment = pair_list_of + VectorValues delta = pair_list_of (key1, Vector3(1.0, 1.1, 1.2)) (key2, Vector3(1.3, 1.4, 1.5)); @@ -227,51 +213,35 @@ TEST(Values, expmap_a) expected.insert(key1, Vector3(2.0, 3.1, 4.2)); expected.insert(key2, Vector3(6.3, 7.4, 8.5)); - CHECK(assert_equal(expected, config0.retract(increment))); + CHECK(assert_equal(expected, config0.retract(delta))); + CHECK(assert_equal(expected, Values(config0, delta))); } /* ************************************************************************* */ -TEST(Values, expmap_b) +TEST(Values, retract_partial) { Values config0; config0.insert(key1, Vector3(1.0, 2.0, 3.0)); config0.insert(key2, Vector3(5.0, 6.0, 7.0)); - VectorValues increment = pair_list_of + VectorValues delta = pair_list_of (key2, Vector3(1.3, 1.4, 1.5)); Values expected; expected.insert(key1, Vector3(1.0, 2.0, 3.0)); expected.insert(key2, Vector3(6.3, 7.4, 8.5)); - CHECK(assert_equal(expected, config0.retract(increment))); + CHECK(assert_equal(expected, config0.retract(delta))); + CHECK(assert_equal(expected, Values(config0, delta))); } /* ************************************************************************* */ -//TEST(Values, expmap_c) -//{ -// Values config0; -// config0.insert(key1, Vector3(1.0, 2.0, 3.0)); -// config0.insert(key2, Vector3(5.0, 6.0, 7.0)); -// -// Vector increment = Vector6( -// 1.0, 1.1, 1.2, -// 1.3, 1.4, 1.5); -// -// Values expected; -// expected.insert(key1, Vector3(2.0, 3.1, 4.2)); -// expected.insert(key2, Vector3(6.3, 7.4, 8.5)); -// -// CHECK(assert_equal(expected, config0.retract(increment))); -//} - -/* ************************************************************************* */ -TEST(Values, expmap_d) +TEST(Values, equals) { Values config0; config0.insert(key1, Vector3(1.0, 2.0, 3.0)); config0.insert(key2, Vector3(5.0, 6.0, 7.0)); - //config0.print("config0"); + CHECK(equal(config0, config0)); CHECK(config0.equals(config0)); @@ -279,8 +249,8 @@ TEST(Values, expmap_d) poseconfig.insert(key1, Pose2(1, 2, 3)); poseconfig.insert(key2, Pose2(0.3, 0.4, 0.5)); - CHECK(equal(config0, config0)); - CHECK(config0.equals(config0)); + CHECK(equal(poseconfig, poseconfig)); + CHECK(poseconfig.equals(poseconfig)); } /* ************************************************************************* */ @@ -453,8 +423,8 @@ TEST(Values, Symbol_filter) { } /* ************************************************************************* */ +// Check that Value destructors are called when Values container is deleted TEST(Values, Destructors) { - // Check that Value destructors are called when Values container is deleted { Values values; { @@ -469,11 +439,95 @@ TEST(Values, Destructors) { // GenericValue in insert() // but I'm sure some advanced programmer can figure out // a way to avoid the temporary, or optimize it out - LONGS_EQUAL(4+2, (long)TestValueData::ConstructorCount); - LONGS_EQUAL(2+2, (long)TestValueData::DestructorCount); + LONGS_EQUAL(4 + 2, (long)TestValueData::ConstructorCount); + LONGS_EQUAL(2 + 2, (long)TestValueData::DestructorCount); + } + LONGS_EQUAL(4 + 2, (long)TestValueData::ConstructorCount); + LONGS_EQUAL(4 + 2, (long)TestValueData::DestructorCount); +} + +/* ************************************************************************* */ +TEST(Values, copy_constructor) { + { + Values values; + TestValueData::ConstructorCount = 0; + TestValueData::DestructorCount = 0; + { + TestValue value1; + TestValue value2; + EXPECT_LONGS_EQUAL(2, (long)TestValueData::ConstructorCount); + EXPECT_LONGS_EQUAL(0, (long)TestValueData::DestructorCount); + values.insert(0, value1); + values.insert(1, value2); + } + EXPECT_LONGS_EQUAL(6, (long)TestValueData::ConstructorCount); + EXPECT_LONGS_EQUAL(4, (long)TestValueData::DestructorCount); + + // Copy constructor + { + Values copied(values); // makes 2 extra copies + EXPECT_LONGS_EQUAL(8, (long)TestValueData::ConstructorCount); + EXPECT_LONGS_EQUAL(4, (long)TestValueData::DestructorCount); + } + EXPECT_LONGS_EQUAL(8, (long)TestValueData::ConstructorCount); + EXPECT_LONGS_EQUAL(6, (long)TestValueData::DestructorCount); // copied destructed ! + } + EXPECT_LONGS_EQUAL(8, (long)TestValueData::ConstructorCount); + EXPECT_LONGS_EQUAL(8, (long)TestValueData::DestructorCount); // values destructed ! +} + +/* ************************************************************************* */ +// small class with a constructor to create an rvalue +struct TestValues : Values { + using Values::Values; // inherits move constructor + + TestValues(const TestValue& value1, const TestValue& value2) { + insert(0, value1); + insert(1, value2); + } +}; +static_assert(std::is_move_constructible::value, ""); +static_assert(std::is_move_constructible::value, ""); + +// test move semantics +TEST(Values, move_constructor) { + { + TestValueData::ConstructorCount = 0; + TestValueData::DestructorCount = 0; + TestValue value1; + TestValue value2; + EXPECT_LONGS_EQUAL(2, (long)TestValueData::ConstructorCount); + EXPECT_LONGS_EQUAL(0, (long)TestValueData::DestructorCount); + TestValues values(TestValues(value1, value2)); // Move happens here ! (could be optimization?) + EXPECT_LONGS_EQUAL(2, values.size()); + EXPECT_LONGS_EQUAL(6, (long)TestValueData::ConstructorCount); // yay ! We don't copy + EXPECT_LONGS_EQUAL(2, (long)TestValueData::DestructorCount); // extra insert copies + } + EXPECT_LONGS_EQUAL(6, (long)TestValueData::ConstructorCount); + EXPECT_LONGS_EQUAL(6, (long)TestValueData::DestructorCount); +} + +// test use of std::move +TEST(Values, std_move) { + { + TestValueData::ConstructorCount = 0; + TestValueData::DestructorCount = 0; + { + TestValue value1; + TestValue value2; + TestValues values(value1, value2); + EXPECT_LONGS_EQUAL(6, (long)TestValueData::ConstructorCount); + EXPECT_LONGS_EQUAL(2, (long)TestValueData::DestructorCount); + EXPECT_LONGS_EQUAL(2, values.size()); + TestValues moved(std::move(values)); // Move happens here ! + EXPECT_LONGS_EQUAL(2, values.size()); // Uh oh! Should be 0 ! + EXPECT_LONGS_EQUAL(2, moved.size()); + EXPECT_LONGS_EQUAL(8, (long)TestValueData::ConstructorCount); // Uh oh! Should be 6 :-( + EXPECT_LONGS_EQUAL(2, (long)TestValueData::DestructorCount); // extra insert copies + } + EXPECT_LONGS_EQUAL(8, (long)TestValueData::ConstructorCount); + EXPECT_LONGS_EQUAL(8, (long)TestValueData::DestructorCount); } - LONGS_EQUAL(4+2, (long)TestValueData::ConstructorCount); - LONGS_EQUAL(4+2, (long)TestValueData::DestructorCount); } /* ************************************************************************* */ @@ -511,6 +565,8 @@ TEST(Values, VectorFixedInsertFixedRead) { } /* ************************************************************************* */ +// NOTE(frank): test is broken, because the scheme it tested was *very* slow. +// TODO(frank): find long-term solution. that works w matlab/python. //TEST(Values, VectorFixedInsertDynamicRead) { // Values values; // Vector3 v; v << 5.0, 6.0, 7.0; @@ -531,6 +587,7 @@ TEST(Values, MatrixDynamicInsertFixedRead) { CHECK(assert_equal((Vector)expected, values.at(key1))); CHECK_EXCEPTION(values.at(key1), exception); } + /* ************************************************************************* */ int main() { TestResult tr; return TestRegistry::runAllTests(tr); } /* ************************************************************************* */ diff --git a/gtsam/slam/EssentialMatrixFactor.h b/gtsam/slam/EssentialMatrixFactor.h index e668d27d3..e6b312b95 100644 --- a/gtsam/slam/EssentialMatrixFactor.h +++ b/gtsam/slam/EssentialMatrixFactor.h @@ -139,7 +139,7 @@ public: const KeyFormatter& keyFormatter = DefaultKeyFormatter) const { Base::print(s); std::cout << " EssentialMatrixFactor2 with measurements\n (" - << dP1_.transpose() << ")' and (" << pn_.vector().transpose() + << dP1_.transpose() << ")' and (" << pn_.transpose() << ")'" << std::endl; } @@ -162,7 +162,7 @@ public: // The point d*P1 = (x,y,1) is computed in constructor as dP1_ // Project to normalized image coordinates, then uncalibrate - Point2 pn; + Point2 pn(0,0); if (!DE && !Dd) { Point3 _1T2 = E.direction().point3(); @@ -195,7 +195,7 @@ public: } Point2 reprojectionError = pn - pn_; - return f_ * reprojectionError.vector(); + return f_ * reprojectionError; } }; diff --git a/gtsam/slam/GeneralSFMFactor.h b/gtsam/slam/GeneralSFMFactor.h index 0f187db75..9356aceb2 100644 --- a/gtsam/slam/GeneralSFMFactor.h +++ b/gtsam/slam/GeneralSFMFactor.h @@ -107,7 +107,7 @@ public: */ void print(const std::string& s = "SFMFactor", const KeyFormatter& keyFormatter = DefaultKeyFormatter) const { Base::print(s, keyFormatter); - measured_.print(s + ".z"); + traits::Print(measured_, s + ".z"); } /** @@ -115,15 +115,14 @@ public: */ bool equals(const NonlinearFactor &p, double tol = 1e-9) const { const This* e = dynamic_cast(&p); - return e && Base::equals(p, tol) && this->measured_.equals(e->measured_, tol); + return e && Base::equals(p, tol) && traits::Equals(this->measured_, e->measured_, tol); } /** h(x)-z */ Vector evaluateError(const CAMERA& camera, const LANDMARK& point, boost::optional H1=boost::none, boost::optional H2=boost::none) const { try { - Point2 reprojError(camera.project2(point,H1,H2) - measured_); - return reprojError.vector(); + return camera.project2(point,H1,H2) - measured_; } catch( CheiralityException& e) { if (H1) *H1 = JacobianC::Zero(); @@ -145,8 +144,7 @@ public: try { const CAMERA& camera = values.at(key1); const LANDMARK& point = values.at(key2); - Point2 reprojError(camera.project2(point, H1, H2) - measured()); - b = -reprojError.vector(); + b = measured() - camera.project2(point, H1, H2); } catch (CheiralityException& e) { H1.setZero(); H2.setZero(); @@ -243,7 +241,7 @@ public: */ void print(const std::string& s = "SFMFactor2", const KeyFormatter& keyFormatter = DefaultKeyFormatter) const { Base::print(s, keyFormatter); - measured_.print(s + ".z"); + traits::Print(measured_, s + ".z"); } /** @@ -251,7 +249,7 @@ public: */ bool equals(const NonlinearFactor &p, double tol = 1e-9) const { const This* e = dynamic_cast(&p); - return e && Base::equals(p, tol) && this->measured_.equals(e->measured_, tol); + return e && Base::equals(p, tol) && traits::Equals(this->measured_, e->measured_, tol); } /** h(x)-z */ @@ -262,8 +260,7 @@ public: { try { Camera camera(pose3,calib); - Point2 reprojError(camera.project(point, H1, H2, H3) - measured_); - return reprojError.vector(); + return camera.project(point, H1, H2, H3) - measured_; } catch( CheiralityException& e) { if (H1) *H1 = Matrix::Zero(2, 6); diff --git a/gtsam/slam/ProjectionFactor.h b/gtsam/slam/ProjectionFactor.h index dee8e925f..d13c28e11 100644 --- a/gtsam/slam/ProjectionFactor.h +++ b/gtsam/slam/ProjectionFactor.h @@ -56,7 +56,9 @@ namespace gtsam { typedef boost::shared_ptr shared_ptr; /// Default constructor - GenericProjectionFactor() : throwCheirality_(false), verboseCheirality_(false) {} + GenericProjectionFactor() : + measured_(0, 0), throwCheirality_(false), verboseCheirality_(false) { + } /** * Constructor @@ -108,7 +110,7 @@ namespace gtsam { */ void print(const std::string& s = "", const KeyFormatter& keyFormatter = DefaultKeyFormatter) const { std::cout << s << "GenericProjectionFactor, z = "; - measured_.print(); + traits::Print(measured_); if(this->body_P_sensor_) this->body_P_sensor_->print(" sensor pose in body frame: "); Base::print("", keyFormatter); @@ -119,7 +121,7 @@ namespace gtsam { const This *e = dynamic_cast(&p); return e && Base::equals(p, tol) - && this->measured_.equals(e->measured_, tol) + && traits::Equals(this->measured_, e->measured_, tol) && this->K_->equals(*e->K_, tol) && ((!body_P_sensor_ && !e->body_P_sensor_) || (body_P_sensor_ && e->body_P_sensor_ && body_P_sensor_->equals(*e->body_P_sensor_))); } @@ -134,16 +136,14 @@ namespace gtsam { PinholeCamera camera(pose.compose(*body_P_sensor_, H0), *K_); Point2 reprojectionError(camera.project(point, H1, H2, boost::none) - measured_); *H1 = *H1 * H0; - return reprojectionError.vector(); + return reprojectionError; } else { PinholeCamera camera(pose.compose(*body_P_sensor_), *K_); - Point2 reprojectionError(camera.project(point, H1, H2, boost::none) - measured_); - return reprojectionError.vector(); + return camera.project(point, H1, H2, boost::none) - measured_; } } else { PinholeCamera camera(pose, *K_); - Point2 reprojectionError(camera.project(point, H1, H2, boost::none) - measured_); - return reprojectionError.vector(); + return camera.project(point, H1, H2, boost::none) - measured_; } } catch( CheiralityException& e) { if (H1) *H1 = Matrix::Zero(2,6); diff --git a/gtsam/slam/ReferenceFrameFactor.h b/gtsam/slam/ReferenceFrameFactor.h index 966ade343..68b42f210 100644 --- a/gtsam/slam/ReferenceFrameFactor.h +++ b/gtsam/slam/ReferenceFrameFactor.h @@ -84,7 +84,7 @@ public: * each degree of freedom. */ ReferenceFrameFactor(Key globalKey, Key transKey, Key localKey, double sigma = 1e-2) - : Base(noiseModel::Isotropic::Sigma(POINT::dimension, sigma), + : Base(noiseModel::Isotropic::Sigma(traits::dimension, sigma), globalKey, transKey, localKey) {} virtual ~ReferenceFrameFactor(){} @@ -100,7 +100,7 @@ public: boost::optional Dlocal = boost::none) const { Point newlocal = transform_point(trans, global, Dtrans, Dforeign); if (Dlocal) - *Dlocal = -1* Matrix::Identity(Point::dimension,Point::dimension); + *Dlocal = -1* Matrix::Identity(traits::dimension, traits::dimension); return traits::Local(local,newlocal); } diff --git a/gtsam/slam/RegularImplicitSchurFactor.h b/gtsam/slam/RegularImplicitSchurFactor.h index 973798a64..7c481d0c8 100644 --- a/gtsam/slam/RegularImplicitSchurFactor.h +++ b/gtsam/slam/RegularImplicitSchurFactor.h @@ -130,7 +130,7 @@ public: // Do the Schur complement SymmetricBlockMatrix augmentedHessian = // Set::SchurComplement(FBlocks_, E_, b_); - return augmentedHessian.matrix(); + return augmentedHessian.selfadjointView(); } /// *Compute* full information matrix diff --git a/gtsam/slam/SmartFactorBase.h b/gtsam/slam/SmartFactorBase.h index 3128390c7..93d2ff218 100644 --- a/gtsam/slam/SmartFactorBase.h +++ b/gtsam/slam/SmartFactorBase.h @@ -189,7 +189,7 @@ public: bool areMeasurementsEqual = true; for (size_t i = 0; i < measured_.size(); i++) { - if (this->measured_.at(i).equals(e->measured_.at(i), tol) == false) + if (traits::Equals(this->measured_.at(i), e->measured_.at(i), tol) == false) areMeasurementsEqual = false; break; } diff --git a/gtsam/slam/SmartProjectionFactor.h b/gtsam/slam/SmartProjectionFactor.h index af7ca64c6..64b300b86 100644 --- a/gtsam/slam/SmartProjectionFactor.h +++ b/gtsam/slam/SmartProjectionFactor.h @@ -499,8 +499,8 @@ public: return Base::totalReprojectionError(cameras, *result_); else if (params_.degeneracyMode == HANDLE_INFINITY) { // Otherwise, manage the exceptions with rotation-only factors - const Point2& z0 = this->measured_.at(0); - Unit3 backprojected = cameras.front().backprojectPointAtInfinity(z0); + Unit3 backprojected = cameras.front().backprojectPointAtInfinity( + this->measured_.at(0)); return Base::totalReprojectionError(cameras, backprojected); } else // if we don't want to manage the exceptions we discard the factor diff --git a/gtsam/slam/TriangulationFactor.h b/gtsam/slam/TriangulationFactor.h index e97cd2730..811d92fbc 100644 --- a/gtsam/slam/TriangulationFactor.h +++ b/gtsam/slam/TriangulationFactor.h @@ -78,12 +78,11 @@ public: bool verboseCheirality = false) : Base(model, pointKey), camera_(camera), measured_(measured), throwCheirality_( throwCheirality), verboseCheirality_(verboseCheirality) { - if (model && model->dim() != Measurement::dimension) + if (model && model->dim() != traits::dimension) throw std::invalid_argument( "TriangulationFactor must be created with " - + boost::lexical_cast((int) Measurement::dimension) + + boost::lexical_cast((int) traits::dimension) + "-dimensional noise model."); - } /** Virtual destructor */ @@ -105,7 +104,7 @@ public: DefaultKeyFormatter) const { std::cout << s << "TriangulationFactor,"; camera_.print("camera"); - measured_.print("z"); + traits::Print(measured_, "z"); Base::print("", keyFormatter); } @@ -113,25 +112,24 @@ public: virtual bool equals(const NonlinearFactor& p, double tol = 1e-9) const { const This *e = dynamic_cast(&p); return e && Base::equals(p, tol) && this->camera_.equals(e->camera_, tol) - && this->measured_.equals(e->measured_, tol); + && traits::Equals(this->measured_, e->measured_, tol); } /// Evaluate error h(x)-z and optionally derivatives Vector evaluateError(const Point3& point, boost::optional H2 = boost::none) const { try { - Measurement error(camera_.project2(point, boost::none, H2) - measured_); - return error.vector(); + return traits::Local(measured_, camera_.project2(point, boost::none, H2)); } catch (CheiralityException& e) { if (H2) - *H2 = Matrix::Zero(Measurement::dimension, 3); + *H2 = Matrix::Zero(traits::dimension, 3); if (verboseCheirality_) std::cout << e.what() << ": Landmark " << DefaultKeyFormatter(this->key()) << " moved behind camera" << std::endl; if (throwCheirality_) throw e; - return Eigen::Matrix::Constant(2.0 * camera_.calibration().fx()); + return Eigen::Matrix::dimension,1>::Constant(2.0 * camera_.calibration().fx()); } } @@ -153,14 +151,14 @@ public: // Allocate memory for Jacobian factor, do only once if (Ab.rows() == 0) { std::vector dimensions(1, 3); - Ab = VerticalBlockMatrix(dimensions, Measurement::dimension, true); - A.resize(Measurement::dimension,3); - b.resize(Measurement::dimension); + Ab = VerticalBlockMatrix(dimensions, traits::dimension, true); + A.resize(traits::dimension,3); + b.resize(traits::dimension); } // Would be even better if we could pass blocks to project const Point3& point = x.at(key()); - b = -(camera_.project2(point, boost::none, A) - measured_).vector(); + b = traits::Local(camera_.project2(point, boost::none, A), measured_); if (noiseModel_) this->noiseModel_->WhitenSystem(A, b); diff --git a/gtsam/slam/expressions.h b/gtsam/slam/expressions.h index e81c76bd6..f9f7125cc 100644 --- a/gtsam/slam/expressions.h +++ b/gtsam/slam/expressions.h @@ -40,6 +40,14 @@ inline Point3_ transform_from(const Pose3_& x, const Point3_& p) { return Point3_(x, &Pose3::transform_from, p); } +inline Point3_ rotate(const Rot3_& x, const Point3_& p) { + return Point3_(x, &Rot3::rotate, p); +} + +inline Point3_ unrotate(const Rot3_& x, const Point3_& p) { + return Point3_(x, &Rot3::unrotate, p); +} + // Projection typedef Expression Cal3_S2_; @@ -58,40 +66,37 @@ inline Point2_ project(const Unit3_& p_cam) { namespace internal { // Helper template for project2 expression below -template -Point2 project4(const CAMERA& camera, const POINT& p, - OptionalJacobian<2, CAMERA::dimension> Dcam, - OptionalJacobian<2, FixedDimension::value> Dpoint) { +template +Point2 project4(const CAMERA& camera, const POINT& p, OptionalJacobian<2, CAMERA::dimension> Dcam, + OptionalJacobian<2, FixedDimension::value> Dpoint) { return camera.project2(p, Dcam, Dpoint); } } -template -Point2_ project2(const Expression& camera_, - const Expression& p_) { +template +Point2_ project2(const Expression& camera_, const Expression& p_) { return Point2_(internal::project4, camera_, p_); } namespace internal { // Helper template for project3 expression below -template +template inline Point2 project6(const Pose3& x, const Point3& p, const Cal3_S2& K, - OptionalJacobian<2, 6> Dpose, OptionalJacobian<2, 3> Dpoint, - OptionalJacobian<2, 5> Dcal) { + OptionalJacobian<2, 6> Dpose, OptionalJacobian<2, 3> Dpoint, + OptionalJacobian<2, 5> Dcal) { return PinholeCamera(x, K).project(p, Dpose, Dpoint, Dcal); } } -template +template inline Point2_ project3(const Pose3_& x, const Expression& p, - const Expression& K) { + const Expression& K) { return Point2_(internal::project6, x, p, K); } -template +template Point2_ uncalibrate(const Expression& K, const Point2_& xy_hat) { return Point2_(K, &CALIBRATION::uncalibrate, xy_hat); } -} // \namespace gtsam - +} // \namespace gtsam diff --git a/gtsam/slam/tests/testAntiFactor.cpp b/gtsam/slam/tests/testAntiFactor.cpp index 1dc897599..7a95e0fa9 100644 --- a/gtsam/slam/tests/testAntiFactor.cpp +++ b/gtsam/slam/tests/testAntiFactor.cpp @@ -64,19 +64,14 @@ TEST( AntiFactor, NegativeHessian) GaussianFactor::shared_ptr antiGaussian = antiFactor->linearize(values); HessianFactor::shared_ptr antiHessian = boost::dynamic_pointer_cast(antiGaussian); + Matrix expected_information = -originalHessian->information(); + Matrix actual_information = antiHessian->information(); + EXPECT(assert_equal(expected_information, actual_information)); + + Vector expected_linear = -originalHessian->linearTerm(); + Vector actual_linear = antiHessian->linearTerm(); + EXPECT(assert_equal(expected_linear, actual_linear)); - // Compare Hessian blocks - size_t variable_count = originalFactor->size(); - for(size_t i = 0; i < variable_count; ++i){ - for(size_t j = i; j < variable_count; ++j){ - Matrix expected_G = -Matrix(originalHessian->info(originalHessian->begin()+i, originalHessian->begin()+j)); - Matrix actual_G = antiHessian->info(antiHessian->begin()+i, antiHessian->begin()+j); - CHECK(assert_equal(expected_G, actual_G, 1e-5)); - } - Vector expected_g = -originalHessian->linearTerm(originalHessian->begin()+i); - Vector actual_g = antiHessian->linearTerm(antiHessian->begin()+i); - CHECK(assert_equal(expected_g, actual_g, 1e-5)); - } double expected_f = -originalHessian->constantTerm(); double actual_f = antiHessian->constantTerm(); EXPECT_DOUBLES_EQUAL(expected_f, actual_f, 1e-5); diff --git a/gtsam/slam/tests/testEssentialMatrixFactor.cpp b/gtsam/slam/tests/testEssentialMatrixFactor.cpp index 8ac6c48b6..2e3d613d6 100644 --- a/gtsam/slam/tests/testEssentialMatrixFactor.cpp +++ b/gtsam/slam/tests/testEssentialMatrixFactor.cpp @@ -222,8 +222,7 @@ TEST (EssentialMatrixFactor2, factor) { // Check evaluation Point3 P1 = data.tracks[i].p, P2 = data.cameras[1].pose().transform_to(P1); const Point2 pi = PinholeBase::Project(P2); - Point2 reprojectionError(pi - pB(i)); - Vector expected = reprojectionError.vector(); + Point2 expected(pi - pB(i)); Matrix Hactual1, Hactual2; double d(baseline / P1.z()); @@ -296,8 +295,7 @@ TEST (EssentialMatrixFactor3, factor) { // Check evaluation Point3 P1 = data.tracks[i].p; const Point2 pi = camera2.project(P1); - Point2 reprojectionError(pi - pB(i)); - Vector expected = reprojectionError.vector(); + Point2 expected(pi - pB(i)); Matrix Hactual1, Hactual2; double d(baseline / P1.z()); @@ -438,8 +436,7 @@ TEST (EssentialMatrixFactor2, extraTest) { // Check evaluation Point3 P1 = data.tracks[i].p; const Point2 pi = camera2.project(P1); - Point2 reprojectionError(pi - pB(i)); - Vector expected = reprojectionError.vector(); + Point2 expected(pi - pB(i)); Matrix Hactual1, Hactual2; double d(baseline / P1.z()); @@ -507,8 +504,7 @@ TEST (EssentialMatrixFactor3, extraTest) { // Check evaluation Point3 P1 = data.tracks[i].p; const Point2 pi = camera2.project(P1); - Point2 reprojectionError(pi - pB(i)); - Vector expected = reprojectionError.vector(); + Point2 expected(pi - pB(i)); Matrix Hactual1, Hactual2; double d(baseline / P1.z()); diff --git a/gtsam/slam/tests/testSlamExpressions.cpp b/gtsam/slam/tests/testSlamExpressions.cpp new file mode 100644 index 000000000..66b236ac2 --- /dev/null +++ b/gtsam/slam/tests/testSlamExpressions.cpp @@ -0,0 +1,53 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file testSlamExpressions.cpp + * @author Frank Dellaert + * @brief test expressions for SLAM + */ + +#include +#include +#include + +#include + +#include + +using namespace std; +using namespace gtsam; + +/* ************************************************************************* */ +TEST(SlamExpressions, project2) { + typedef Expression CalibratedCamera_; + + Rot3_ rot3_expr('r', 0); // unknown rotation ! + Point3_ t_expr(Point3(1, 2, 3)); // known translation + Pose3_ pose_expr(&Pose3::Create, rot3_expr, t_expr); + CalibratedCamera_ camera_expr(&CalibratedCamera::Create, pose_expr); + Point3_ point3_expr('p', 12); // unknown 3D point with index 12, for funsies + Point2_ point2_expr = project2(camera_expr, point3_expr); + + // Set the linearization point + Values values; + values.insert(Symbol('r', 0), Rot3()); + values.insert(Symbol('p', 12), Point3(4, 5, 6)); + + EXPECT_CORRECT_EXPRESSION_JACOBIANS(point2_expr, values, 1e-7, 1e-5); +} + +/* ************************************************************************* */ +int main() { + TestResult tr; + return TestRegistry::runAllTests(tr); +} +/* ************************************************************************* */ diff --git a/gtsam/slam/tests/testSmartFactorBase.cpp b/gtsam/slam/tests/testSmartFactorBase.cpp index 96052bd0f..f69f4c113 100644 --- a/gtsam/slam/tests/testSmartFactorBase.cpp +++ b/gtsam/slam/tests/testSmartFactorBase.cpp @@ -55,8 +55,8 @@ struct traits : public Testable {}; TEST(SmartFactorBase, Pinhole) { PinholeFactor f= PinholeFactor(unit2); - f.add(Point2(), 1); - f.add(Point2(), 2); + f.add(Point2(0,0), 1); + f.add(Point2(0,0), 2); EXPECT_LONGS_EQUAL(2 * 2, f.dim()); } diff --git a/gtsam/slam/tests/testSmartProjectionCameraFactor.cpp b/gtsam/slam/tests/testSmartProjectionCameraFactor.cpp index 7eefb2398..0db8149eb 100644 --- a/gtsam/slam/tests/testSmartProjectionCameraFactor.cpp +++ b/gtsam/slam/tests/testSmartProjectionCameraFactor.cpp @@ -300,20 +300,14 @@ TEST( SmartProjectionCameraFactor, perturbPoseAndOptimizeFromSfM_tracks ) { SfM_Track track1; for (size_t i = 0; i < 3; ++i) { - SfM_Measurement measures; - measures.first = i + 1; // cameras are from 1 to 3 - measures.second = measurements_cam1.at(i); - track1.measurements.push_back(measures); + track1.measurements.emplace_back(i + 1, measurements_cam1.at(i)); } SmartFactor::shared_ptr smartFactor1(new SmartFactor(unit2)); smartFactor1->add(track1); SfM_Track track2; for (size_t i = 0; i < 3; ++i) { - SfM_Measurement measures; - measures.first = i + 1; // cameras are from 1 to 3 - measures.second = measurements_cam2.at(i); - track2.measurements.push_back(measures); + track2.measurements.emplace_back(i + 1, measurements_cam2.at(i)); } SmartFactor::shared_ptr smartFactor2(new SmartFactor(unit2)); smartFactor2->add(track2); @@ -651,8 +645,7 @@ TEST( SmartProjectionCameraFactor, comparisonGeneralSfMFactor ) { values.insert(l1, expectedPoint); // note: we get rid of possible errors in the triangulation Vector e1 = sfm1.evaluateError(values.at(c1), values.at(l1)); Vector e2 = sfm2.evaluateError(values.at(c2), values.at(l1)); - double actualError = 0.5 - * (e1.norm() * e1.norm() + e2.norm() * e2.norm()); + double actualError = 0.5 * (e1.squaredNorm() + e2.squaredNorm()); double actualErrorGraph = generalGraph.error(values); DOUBLES_EQUAL(expectedErrorGraph, actualErrorGraph, 1e-7); diff --git a/gtsam/symbolic/SymbolicJunctionTree.cpp b/gtsam/symbolic/SymbolicJunctionTree.cpp index 00a52497b..261f682b0 100644 --- a/gtsam/symbolic/SymbolicJunctionTree.cpp +++ b/gtsam/symbolic/SymbolicJunctionTree.cpp @@ -23,7 +23,7 @@ namespace gtsam { // Instantiate base class - template class ClusterTree; + template class EliminatableClusterTree; template class JunctionTree; /* ************************************************************************* */ diff --git a/gtsam/symbolic/SymbolicJunctionTree.h b/gtsam/symbolic/SymbolicJunctionTree.h index 709488cbf..fdc5450b3 100644 --- a/gtsam/symbolic/SymbolicJunctionTree.h +++ b/gtsam/symbolic/SymbolicJunctionTree.h @@ -26,7 +26,7 @@ namespace gtsam { class SymbolicEliminationTree; /** - * A ClusterTree, i.e., a set of variable clusters with factors, arranged in a tree, with + * A EliminatableClusterTree, i.e., a set of variable clusters with factors, arranged in a tree, with * the additional property that it represents the clique tree associated with a Bayes net. * * In GTSAM a junction tree is an intermediate data structure in multifrontal diff --git a/gtsam_unstable/dynamics/PoseRTV.cpp b/gtsam_unstable/dynamics/PoseRTV.cpp index c1afe3882..c8c46ee7b 100644 --- a/gtsam_unstable/dynamics/PoseRTV.cpp +++ b/gtsam_unstable/dynamics/PoseRTV.cpp @@ -172,7 +172,7 @@ double PoseRTV::range(const PoseRTV& other, const Point3 t1 = pose().translation(H1 ? &D_t1_pose : 0); const Point3 t2 = other.pose().translation(H2 ? &D_t2_other : 0); Matrix13 D_d_t1, D_d_t2; - double d = distance(t1, t2, H1 ? &D_d_t1 : 0, H2 ? &D_d_t2 : 0); + double d = distance3(t1, t2, H1 ? &D_d_t1 : 0, H2 ? &D_d_t2 : 0); if (H1) *H1 << D_d_t1 * D_t1_pose, 0,0,0; if (H2) *H2 << D_d_t2 * D_t2_other, 0,0,0; return d; diff --git a/gtsam_unstable/examples/ConcurrentCalibration.cpp b/gtsam_unstable/examples/ConcurrentCalibration.cpp index b44b14b63..28f7e8444 100644 --- a/gtsam_unstable/examples/ConcurrentCalibration.cpp +++ b/gtsam_unstable/examples/ConcurrentCalibration.cpp @@ -115,7 +115,7 @@ int main(int argc, char** argv){ params.verbosity = NonlinearOptimizerParams::ERROR; //create Levenberg-Marquardt optimizer to optimize the factor graph - LevenbergMarquardtOptimizer optimizer = LevenbergMarquardtOptimizer(graph, initial_estimate,params); + LevenbergMarquardtOptimizer optimizer(graph, initial_estimate,params); // Values result = optimizer.optimize(); string K_values_file = "K_values.txt"; diff --git a/gtsam_unstable/examples/SmartProjectionFactorExample.cpp b/gtsam_unstable/examples/SmartProjectionFactorExample.cpp index de1d3f77b..c5ba616ed 100644 --- a/gtsam_unstable/examples/SmartProjectionFactorExample.cpp +++ b/gtsam_unstable/examples/SmartProjectionFactorExample.cpp @@ -112,7 +112,7 @@ int main(int argc, char** argv){ cout << "Optimizing" << endl; //create Levenberg-Marquardt optimizer to optimize the factor graph - LevenbergMarquardtOptimizer optimizer = LevenbergMarquardtOptimizer(graph, initial_estimate, params); + LevenbergMarquardtOptimizer optimizer(graph, initial_estimate, params); Values result = optimizer.optimize(); cout << "Final result sample:" << endl; diff --git a/gtsam_unstable/examples/SmartStereoProjectionFactorExample.cpp b/gtsam_unstable/examples/SmartStereoProjectionFactorExample.cpp index d3680460f..40ad0cb52 100644 --- a/gtsam_unstable/examples/SmartStereoProjectionFactorExample.cpp +++ b/gtsam_unstable/examples/SmartStereoProjectionFactorExample.cpp @@ -134,7 +134,7 @@ int main(int argc, char** argv){ cout << "Optimizing" << endl; //create Levenberg-Marquardt optimizer to optimize the factor graph - LevenbergMarquardtOptimizer optimizer = LevenbergMarquardtOptimizer(graph, initial_estimate, params); + LevenbergMarquardtOptimizer optimizer(graph, initial_estimate, params); Values result = optimizer.optimize(); cout << "Final result sample:" << endl; diff --git a/gtsam_unstable/geometry/Event.h b/gtsam_unstable/geometry/Event.h index 615b1d467..40c70696b 100644 --- a/gtsam_unstable/geometry/Event.h +++ b/gtsam_unstable/geometry/Event.h @@ -85,7 +85,7 @@ public: OptionalJacobian<1, 3> H2 = boost::none) const { static const double Speed = 330; Matrix13 D1, D2; - double distance = gtsam::distance(location_, microphone, D1, D2); + double distance = gtsam::distance3(location_, microphone, D1, D2); if (H1) // derivative of toa with respect to event *H1 << 1.0, D1 / Speed; diff --git a/gtsam_unstable/geometry/SimPolygon2D.cpp b/gtsam_unstable/geometry/SimPolygon2D.cpp index f610e4d0f..ba1445b20 100644 --- a/gtsam_unstable/geometry/SimPolygon2D.cpp +++ b/gtsam_unstable/geometry/SimPolygon2D.cpp @@ -46,7 +46,7 @@ SimPolygon2D SimPolygon2D::createRectangle(const Point2& p, double height, doubl bool SimPolygon2D::equals(const SimPolygon2D& p, double tol) const { if (p.size() != size()) return false; for (size_t i=0; i::Equals(landmarks_[i], p.landmarks_[i], tol)) return false; return true; } @@ -55,7 +55,7 @@ bool SimPolygon2D::equals(const SimPolygon2D& p, double tol) const { void SimPolygon2D::print(const string& s) const { cout << "SimPolygon " << s << ": " << endl; for(const Point2& p: landmarks_) - p.print(" "); + traits::Print(p, " "); } /* ************************************************************************* */ @@ -151,7 +151,7 @@ SimPolygon2D SimPolygon2D::randomTriangle( Pose2 xC = xB.retract(Vector::Unit(3,0)*dBC); // use triangle equality to verify non-degenerate triangle - double dAC = xA.t().distance(xC.t()); + double dAC = distance2(xA.t(), xC.t()); // form a triangle and test if it meets requirements SimPolygon2D test_tri = SimPolygon2D::createTriangle(xA.t(), xB.t(), xC.t()); @@ -164,7 +164,7 @@ SimPolygon2D SimPolygon2D::randomTriangle( insideBox(side_len, test_tri.landmark(0)) && insideBox(side_len, test_tri.landmark(1)) && insideBox(side_len, test_tri.landmark(2)) && - test_tri.landmark(1).distance(test_tri.landmark(2)) > min_side_len && + distance2(test_tri.landmark(1), test_tri.landmark(2)) > min_side_len && !nearExisting(lms, test_tri.landmark(0), min_vertex_dist) && !nearExisting(lms, test_tri.landmark(1), min_vertex_dist) && !nearExisting(lms, test_tri.landmark(2), min_vertex_dist) && @@ -260,7 +260,7 @@ Point2 SimPolygon2D::randomBoundedPoint2(double boundary_size, return p; } throw runtime_error("Failed to find a place for a landmark!"); - return Point2(); + return Point2(0,0); } /* ***************************************************************** */ @@ -272,7 +272,7 @@ Point2 SimPolygon2D::randomBoundedPoint2(double boundary_size, return p; } throw runtime_error("Failed to find a place for a landmark!"); - return Point2(); + return Point2(0,0); } /* ***************************************************************** */ @@ -285,7 +285,7 @@ Point2 SimPolygon2D::randomBoundedPoint2(double boundary_size, return p; } throw runtime_error("Failed to find a place for a landmark!"); - return Point2(); + return Point2(0,0); } /* ***************************************************************** */ @@ -303,7 +303,7 @@ Point2 SimPolygon2D::randomBoundedPoint2( return p; } throw runtime_error("Failed to find a place for a landmark!"); - return Point2(); + return Point2(0,0); } /* ***************************************************************** */ @@ -320,7 +320,7 @@ bool SimPolygon2D::insideBox(double s, const Point2& p) { bool SimPolygon2D::nearExisting(const std::vector& S, const Point2& p, double threshold) { for(const Point2& Sp: S) - if (Sp.distance(p) < threshold) + if (distance2(Sp, p) < threshold) return true; return false; } diff --git a/gtsam_unstable/geometry/SimWall2D.cpp b/gtsam_unstable/geometry/SimWall2D.cpp index e294a360d..111d23b91 100644 --- a/gtsam_unstable/geometry/SimWall2D.cpp +++ b/gtsam_unstable/geometry/SimWall2D.cpp @@ -14,13 +14,14 @@ using namespace std; /* ************************************************************************* */ void SimWall2D::print(const std::string& s) const { std::cout << "SimWall2D " << s << ":" << std::endl; - a_.print(" a"); - b_.print(" b"); + traits::Print(a_, " a"); + traits::Print(b_, " b"); } /* ************************************************************************* */ bool SimWall2D::equals(const SimWall2D& other, double tol) const { - return a_.equals(other.a_, tol) && b_.equals(other.b_, tol); + return traits::Equals(a_, other.a_, tol) && + traits::Equals(b_, other.b_, tol); } /* ************************************************************************* */ @@ -37,8 +38,8 @@ bool SimWall2D::intersects(const SimWall2D& B, boost::optional pt) cons if (debug) cout << "len: " << len << endl; Point2 Ba = transform.transform_to(B.a()), Bb = transform.transform_to(B.b()); - if (debug) Ba.print("Ba"); - if (debug) Bb.print("Bb"); + if (debug) traits::Print(Ba, "Ba"); + if (debug) traits::Print(Bb, "Bb"); // check sides of line if (Ba.y() * Bb.y() > 0.0 || @@ -73,7 +74,7 @@ bool SimWall2D::intersects(const SimWall2D& B, boost::optional pt) cons } // find lower point by y - Point2 low, high; + Point2 low(0,0), high(0,0); if (Ba.y() > Bb.y()) { high = Ba; low = Bb; @@ -81,8 +82,8 @@ bool SimWall2D::intersects(const SimWall2D& B, boost::optional pt) cons high = Bb; low = Ba; } - if (debug) high.print("high"); - if (debug) low.print("low"); + if (debug) traits::Print(high, "high"); + if (debug) traits::Print(low, "low"); // find x-intercept double slope = (high.y() - low.y())/(high.x() - low.x()); @@ -138,7 +139,7 @@ std::pair moveWithBounce(const Pose2& cur_pose, double step_size, Point2 cur_intersection; if (wall.intersects(traj,cur_intersection)) { collision = true; - if (cur_pose.t().distance(cur_intersection) < cur_pose.t().distance(intersection)) { + if (distance2(cur_pose.t(), cur_intersection) < distance2(cur_pose.t(), intersection)) { intersection = cur_intersection; closest_wall = wall; } @@ -154,7 +155,7 @@ std::pair moveWithBounce(const Pose2& cur_pose, double step_size, norm = norm / norm.norm(); // Simple check to make sure norm is on side closest robot - if (cur_pose.t().distance(intersection + norm) > cur_pose.t().distance(intersection - norm)) + if (distance2(cur_pose.t(), intersection + norm) > distance2(cur_pose.t(), intersection - norm)) norm = - norm; // using the reflection diff --git a/gtsam_unstable/geometry/SimWall2D.h b/gtsam_unstable/geometry/SimWall2D.h index 38bba2ee3..c143bc36d 100644 --- a/gtsam_unstable/geometry/SimWall2D.h +++ b/gtsam_unstable/geometry/SimWall2D.h @@ -43,7 +43,7 @@ namespace gtsam { SimWall2D scale(double s) const { return SimWall2D(s*a_, s*b_); } /** geometry */ - double length() const { return a_.distance(b_); } + double length() const { return distance2(a_, b_); } Point2 midpoint() const; /** diff --git a/gtsam_unstable/geometry/tests/testSimPolygon2D.cpp b/gtsam_unstable/geometry/tests/testSimPolygon2D.cpp index 37cdfa0ba..6528f3f91 100644 --- a/gtsam_unstable/geometry/tests/testSimPolygon2D.cpp +++ b/gtsam_unstable/geometry/tests/testSimPolygon2D.cpp @@ -16,7 +16,7 @@ const double tol=1e-5; TEST(testPolygon, triangle_basic) { // create a triangle from points, extract landmarks/walls, check occupancy - Point2 pA, pB(2.0, 0.0), pC(0.0, 1.0); + Point2 pA(0,0), pB(2.0, 0.0), pC(0.0, 1.0); // construct and extract data SimPolygon2D actTriangle = SimPolygon2D::createTriangle(pA, pB, pC); diff --git a/gtsam_unstable/geometry/tests/testSimWall2D.cpp b/gtsam_unstable/geometry/tests/testSimWall2D.cpp index 62f458402..3bde734b2 100644 --- a/gtsam_unstable/geometry/tests/testSimWall2D.cpp +++ b/gtsam_unstable/geometry/tests/testSimWall2D.cpp @@ -24,7 +24,7 @@ TEST(testSimWall2D2D, construction ) { /* ************************************************************************* */ TEST(testSimWall2D2D, equals ) { - Point2 p1(1.0, 0.0), p2(1.0, 2.0), p3; + Point2 p1(1.0, 0.0), p2(1.0, 2.0), p3(0,0); SimWall2D w1(p1, p2), w2(p1, p3); EXPECT(assert_equal(w1, w1)); EXPECT(assert_inequal(w1, w2)); @@ -34,7 +34,7 @@ TEST(testSimWall2D2D, equals ) { /* ************************************************************************* */ TEST(testSimWall2D2D, intersection1 ) { SimWall2D w1(2.0, 2.0, 6.0, 2.0), w2(4.0, 4.0, 4.0, 0.0); - Point2 pt; + Point2 pt(0,0); EXPECT(w1.intersects(w2)); EXPECT(w2.intersects(w1)); w1.intersects(w2, pt); diff --git a/gtsam_unstable/linear/ActiveSetSolver-inl.h b/gtsam_unstable/linear/ActiveSetSolver-inl.h new file mode 100644 index 000000000..18dc07aec --- /dev/null +++ b/gtsam_unstable/linear/ActiveSetSolver-inl.h @@ -0,0 +1,290 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file ActiveSetSolver-inl.h + * @brief Implmentation of ActiveSetSolver. + * @author Ivan Dario Jimenez + * @author Duy Nguyen Ta + * @date 2/11/16 + */ + +#include + +/******************************************************************************/ +// Convenient macros to reduce syntactic noise. undef later. +#define Template template +#define This ActiveSetSolver + +/******************************************************************************/ + +namespace gtsam { + +/* We have to make sure the new solution with alpha satisfies all INACTIVE inequality constraints + * If some inactive inequality constraints complain about the full step (alpha = 1), + * we have to adjust alpha to stay within the inequality constraints' feasible regions. + * + * For each inactive inequality j: + * - We already have: aj'*xk - bj <= 0, since xk satisfies all inequality constraints + * - We want: aj'*(xk + alpha*p) - bj <= 0 + * - If aj'*p <= 0, we have: aj'*(xk + alpha*p) <= aj'*xk <= bj, for all alpha>0 + * it's good! + * - We only care when aj'*p > 0. In this case, we need to choose alpha so that + * aj'*xk + alpha*aj'*p - bj <= 0 --> alpha <= (bj - aj'*xk) / (aj'*p) + * We want to step as far as possible, so we should choose alpha = (bj - aj'*xk) / (aj'*p) + * + * We want the minimum of all those alphas among all inactive inequality. + */ +Template boost::tuple This::computeStepSize( + const InequalityFactorGraph& workingSet, const VectorValues& xk, + const VectorValues& p, const double& maxAlpha) const { + double minAlpha = maxAlpha; + int closestFactorIx = -1; + for (size_t factorIx = 0; factorIx < workingSet.size(); ++factorIx) { + const LinearInequality::shared_ptr& factor = workingSet.at(factorIx); + double b = factor->getb()[0]; + // only check inactive factors + if (!factor->active()) { + // Compute a'*p + double aTp = factor->dotProductRow(p); + + // Check if a'*p >0. Don't care if it's not. + if (aTp <= 0) + continue; + + // Compute a'*xk + double aTx = factor->dotProductRow(xk); + + // alpha = (b - a'*xk) / (a'*p) + double alpha = (b - aTx) / aTp; + // We want the minimum of all those max alphas + if (alpha < minAlpha) { + closestFactorIx = factorIx; + minAlpha = alpha; + } + } + } + return boost::make_tuple(minAlpha, closestFactorIx); +} + +/******************************************************************************/ +/* + * The goal of this function is to find currently active inequality constraints + * that violate the condition to be active. The one that violates the condition + * the most will be removed from the active set. See Nocedal06book, pg 469-471 + * + * Find the BAD active inequality that pulls x strongest to the wrong direction + * of its constraint (i.e. it is pulling towards >0, while its feasible region is <=0) + * + * For active inequality constraints (those that are enforced as equality constraints + * in the current working set), we want lambda < 0. + * This is because: + * - From the Lagrangian L = f - lambda*c, we know that the constraint force + * is (lambda * \grad c) = \grad f. Intuitively, to keep the solution x stay + * on the constraint surface, the constraint force has to balance out with + * other unconstrained forces that are pulling x towards the unconstrained + * minimum point. The other unconstrained forces are pulling x toward (-\grad f), + * hence the constraint force has to be exactly \grad f, so that the total + * force is 0. + * - We also know that at the constraint surface c(x)=0, \grad c points towards + (>= 0), + * while we are solving for - (<=0) constraint. + * - We want the constraint force (lambda * \grad c) to pull x towards the - (<=0) direction + * i.e., the opposite direction of \grad c where the inequality constraint <=0 is satisfied. + * That means we want lambda < 0. + * - This is because when the constrained force pulls x towards the infeasible region (+), + * the unconstrained force is pulling x towards the opposite direction into + * the feasible region (again because the total force has to be 0 to make x stay still) + * So we can drop this constraint to have a lower error but feasible solution. + * + * In short, active inequality constraints with lambda > 0 are BAD, because they + * violate the condition to be active. + * + * And we want to remove the worst one with the largest lambda from the active set. + * + */ +Template int This::identifyLeavingConstraint( + const InequalityFactorGraph& workingSet, + const VectorValues& lambdas) const { + int worstFactorIx = -1; + // preset the maxLambda to 0.0: if lambda is <= 0.0, the constraint is either + // inactive or a good inequality constraint, so we don't care! + double maxLambda = 0.0; + for (size_t factorIx = 0; factorIx < workingSet.size(); ++factorIx) { + const LinearInequality::shared_ptr& factor = workingSet.at(factorIx); + if (factor->active()) { + double lambda = lambdas.at(factor->dualKey())[0]; + if (lambda > maxLambda) { + worstFactorIx = factorIx; + maxLambda = lambda; + } + } + } + return worstFactorIx; +} + +//****************************************************************************** +Template JacobianFactor::shared_ptr This::createDualFactor( + Key key, const InequalityFactorGraph& workingSet, + const VectorValues& delta) const { + // Transpose the A matrix of constrained factors to have the jacobian of the + // dual key + TermsContainer Aterms = collectDualJacobians( + key, problem_.equalities, equalityVariableIndex_); + TermsContainer AtermsInequalities = collectDualJacobians( + key, workingSet, inequalityVariableIndex_); + Aterms.insert(Aterms.end(), AtermsInequalities.begin(), + AtermsInequalities.end()); + + // Collect the gradients of unconstrained cost factors to the b vector + if (Aterms.size() > 0) { + Vector b = problem_.costGradient(key, delta); + // to compute the least-square approximation of dual variables + return boost::make_shared(Aterms, b); + } else { + return boost::make_shared(); + } +} + +/******************************************************************************/ +/* This function will create a dual graph that solves for the + * lagrange multipliers for the current working set. + * You can use lagrange multipliers as a necessary condition for optimality. + * The factor graph that is being solved is f' = -lambda * g' + * where f is the optimized function and g is the function resulting from + * aggregating the working set. + * The lambdas give you information about the feasibility of a constraint. + * if lambda < 0 the constraint is Ok + * if lambda = 0 you are on the constraint + * if lambda > 0 you are violating the constraint. + */ +Template GaussianFactorGraph::shared_ptr This::buildDualGraph( + const InequalityFactorGraph& workingSet, const VectorValues& delta) const { + GaussianFactorGraph::shared_ptr dualGraph(new GaussianFactorGraph()); + for (Key key : constrainedKeys_) { + // Each constrained key becomes a factor in the dual graph + JacobianFactor::shared_ptr dualFactor = + createDualFactor(key, workingSet, delta); + if (!dualFactor->empty()) dualGraph->push_back(dualFactor); + } + return dualGraph; +} + +//****************************************************************************** +Template GaussianFactorGraph +This::buildWorkingGraph(const InequalityFactorGraph& workingSet, + const VectorValues& xk) const { + GaussianFactorGraph workingGraph; + workingGraph.push_back(POLICY::buildCostFunction(problem_, xk)); + workingGraph.push_back(problem_.equalities); + for (const LinearInequality::shared_ptr& factor : workingSet) + if (factor->active()) workingGraph.push_back(factor); + return workingGraph; +} + +//****************************************************************************** +Template typename This::State This::iterate( + const typename This::State& state) const { + // Algorithm 16.3 from Nocedal06book. + // Solve with the current working set eqn 16.39, but instead of solving for p + // solve for x + GaussianFactorGraph workingGraph = + buildWorkingGraph(state.workingSet, state.values); + VectorValues newValues = workingGraph.optimize(); + // If we CAN'T move further + // if p_k = 0 is the original condition, modified by Duy to say that the state + // update is zero. + if (newValues.equals(state.values, 1e-7)) { + // Compute lambda from the dual graph + GaussianFactorGraph::shared_ptr dualGraph = buildDualGraph(state.workingSet, + newValues); + VectorValues duals = dualGraph->optimize(); + int leavingFactor = identifyLeavingConstraint(state.workingSet, duals); + // If all inequality constraints are satisfied: We have the solution!! + if (leavingFactor < 0) { + return State(newValues, duals, state.workingSet, true, + state.iterations + 1); + } else { + // Inactivate the leaving constraint + InequalityFactorGraph newWorkingSet = state.workingSet; + newWorkingSet.at(leavingFactor)->inactivate(); + return State(newValues, duals, newWorkingSet, false, + state.iterations + 1); + } + } else { + // If we CAN make some progress, i.e. p_k != 0 + // Adapt stepsize if some inactive constraints complain about this move + double alpha; + int factorIx; + VectorValues p = newValues - state.values; + boost::tie(alpha, factorIx) = // using 16.41 + computeStepSize(state.workingSet, state.values, p, POLICY::maxAlpha); + // also add to the working set the one that complains the most + InequalityFactorGraph newWorkingSet = state.workingSet; + if (factorIx >= 0) + newWorkingSet.at(factorIx)->activate(); + // step! + newValues = state.values + alpha * p; + return State(newValues, state.duals, newWorkingSet, false, + state.iterations + 1); + } +} + +//****************************************************************************** +Template InequalityFactorGraph This::identifyActiveConstraints( + const InequalityFactorGraph& inequalities, + const VectorValues& initialValues, const VectorValues& duals, + bool useWarmStart) const { + InequalityFactorGraph workingSet; + for (const LinearInequality::shared_ptr& factor : inequalities) { + LinearInequality::shared_ptr workingFactor(new LinearInequality(*factor)); + if (useWarmStart && duals.size() > 0) { + if (duals.exists(workingFactor->dualKey())) workingFactor->activate(); + else workingFactor->inactivate(); + } else { + double error = workingFactor->error(initialValues); + // Safety guard. This should not happen unless users provide a bad init + if (error > 0) throw InfeasibleInitialValues(); + if (fabs(error) < 1e-7) + workingFactor->activate(); + else + workingFactor->inactivate(); + } + workingSet.push_back(workingFactor); + } + return workingSet; +} + +//****************************************************************************** +Template std::pair This::optimize( + const VectorValues& initialValues, const VectorValues& duals, + bool useWarmStart) const { + // Initialize workingSet from the feasible initialValues + InequalityFactorGraph workingSet = identifyActiveConstraints( + problem_.inequalities, initialValues, duals, useWarmStart); + State state(initialValues, duals, workingSet, false, 0); + + /// main loop of the solver + while (!state.converged) state = iterate(state); + + return std::make_pair(state.values, state.duals); +} + +//****************************************************************************** +Template std::pair This::optimize() const { + INITSOLVER initSolver(problem_); + VectorValues initValues = initSolver.solve(); + return optimize(initValues); +} + +} + +#undef Template +#undef This \ No newline at end of file diff --git a/gtsam_unstable/linear/ActiveSetSolver.h b/gtsam_unstable/linear/ActiveSetSolver.h new file mode 100644 index 000000000..a5c60f311 --- /dev/null +++ b/gtsam_unstable/linear/ActiveSetSolver.h @@ -0,0 +1,204 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file ActiveSetSolver.h + * @brief Active set method for solving LP, QP problems + * @author Ivan Dario Jimenez + * @author Duy Nguyen Ta + * @date 1/25/16 + */ +#pragma once + +#include +#include +#include + +namespace gtsam { + +/** + * This class implements the active set algorithm for solving convex + * Programming problems. + * + * @tparam PROBLEM Type of the problem to solve, e.g. LP (linear program) or + * QP (quadratic program). + * @tparam POLICY specific detail policy tailored for the particular program + * @tparam INITSOLVER Solver for an initial feasible solution of this problem. + */ +template +class ActiveSetSolver { +public: + /// This struct contains the state information for a single iteration + struct State { + VectorValues values; //!< current best values at each step + VectorValues duals; //!< current values of dual variables at each step + InequalityFactorGraph workingSet; /*!< keep track of current active/inactive + inequality constraints */ + bool converged; //!< True if the algorithm has converged to a solution + size_t iterations; /*!< Number of iterations. Incremented at the end of + each iteration. */ + + /// Default constructor + State() + : values(), duals(), workingSet(), converged(false), iterations(0) {} + + /// Constructor with initial values + State(const VectorValues& initialValues, const VectorValues& initialDuals, + const InequalityFactorGraph& initialWorkingSet, bool _converged, + size_t _iterations) + : values(initialValues), + duals(initialDuals), + workingSet(initialWorkingSet), + converged(_converged), + iterations(_iterations) {} + }; + +protected: + const PROBLEM& problem_; //!< the particular [convex] problem to solve + VariableIndex equalityVariableIndex_, + inequalityVariableIndex_; /*!< index to corresponding factors to build + dual graphs */ + KeySet constrainedKeys_; /*!< all constrained keys, will become factors in + dual graphs */ + + /// Vector of key matrix pairs. Matrices are usually the A term for a factor. + typedef std::vector > TermsContainer; + +public: + /// Constructor + ActiveSetSolver(const PROBLEM& problem) : problem_(problem) { + equalityVariableIndex_ = VariableIndex(problem_.equalities); + inequalityVariableIndex_ = VariableIndex(problem_.inequalities); + constrainedKeys_ = problem_.equalities.keys(); + constrainedKeys_.merge(problem_.inequalities.keys()); + } + + /** + * Optimize with provided initial values + * For this version, it is the responsibility of the caller to provide + * a feasible initial value, otherwise, an exception will be thrown. + * @return a pair of solutions + */ + std::pair optimize( + const VectorValues& initialValues, + const VectorValues& duals = VectorValues(), + bool useWarmStart = false) const; + + /** + * For this version the caller will not have to provide an initial value + * @return a pair of solutions + */ + std::pair optimize() const; + +protected: + /** + * Compute minimum step size alpha to move from the current point @p xk to the + * next feasible point along a direction @p p: x' = xk + alpha*p, + * where alpha \in [0,maxAlpha]. + * + * For QP, maxAlpha = 1. For LP: maxAlpha = Inf. + * + * @return a tuple of (minAlpha, closestFactorIndex) where closestFactorIndex + * is the closest inactive inequality constraint that blocks xk to move + * further and that has the minimum alpha, or (-1, maxAlpha) if there is no + * such inactive blocking constraint. + * + * If there is a blocking constraint, the closest one will be added to the + * working set and become active in the next iteration. + */ + boost::tuple computeStepSize( + const InequalityFactorGraph& workingSet, const VectorValues& xk, + const VectorValues& p, const double& maxAlpha) const; + + /** + * Finds the active constraints in the given factor graph and returns the + * Dual Jacobians used to build a dual factor graph. + */ + template + TermsContainer collectDualJacobians(Key key, const FactorGraph& graph, + const VariableIndex& variableIndex) const { + /* + * Iterates through each factor in the factor graph and checks + * whether it's active. If the factor is active it reutrns the A + * term of the factor. + */ + TermsContainer Aterms; + if (variableIndex.find(key) != variableIndex.end()) { + for (size_t factorIx : variableIndex[key]) { + typename FACTOR::shared_ptr factor = graph.at(factorIx); + if (!factor->active()) + continue; + Matrix Ai = factor->getA(factor->find(key)).transpose(); + Aterms.push_back(std::make_pair(factor->dualKey(), Ai)); + } + } + return Aterms; + } + + /** + * Creates a dual factor from the current workingSet and the key of the + * the variable used to created the dual factor. + */ + JacobianFactor::shared_ptr createDualFactor( + Key key, const InequalityFactorGraph& workingSet, + const VectorValues& delta) const; + +public: /// Just for testing... + + /// Builds a dual graph from the current working set. + GaussianFactorGraph::shared_ptr buildDualGraph( + const InequalityFactorGraph& workingSet, const VectorValues& delta) const; + + /** + * Build a working graph of cost, equality and active inequality constraints + * to solve at each iteration. + * @param workingSet the collection of all cost and constrained factors + * @param xk current solution, used to build a special quadratic cost in LP + * @return a new better solution + */ + GaussianFactorGraph buildWorkingGraph( + const InequalityFactorGraph& workingSet, + const VectorValues& xk = VectorValues()) const; + + /// Iterate 1 step, return a new state with a new workingSet and values + State iterate(const State& state) const; + + /// Identify active constraints based on initial values. + InequalityFactorGraph identifyActiveConstraints( + const InequalityFactorGraph& inequalities, + const VectorValues& initialValues, + const VectorValues& duals = VectorValues(), + bool useWarmStart = false) const; + + /// Identifies active constraints that shouldn't be active anymore. + int identifyLeavingConstraint(const InequalityFactorGraph& workingSet, + const VectorValues& lambdas) const; + +}; + +/** + * Find the max key in a problem. + * Useful to determine unique keys for additional slack variables + */ +template +Key maxKey(const PROBLEM& problem) { + auto keys = problem.cost.keys(); + Key maxKey = *std::max_element(keys.begin(), keys.end()); + if (!problem.equalities.empty()) + maxKey = std::max(maxKey, *problem.equalities.keys().rbegin()); + if (!problem.inequalities.empty()) + maxKey = std::max(maxKey, *problem.inequalities.keys().rbegin()); + return maxKey; +} + +} // namespace gtsam + +#include \ No newline at end of file diff --git a/gtsam_unstable/linear/EqualityFactorGraph.h b/gtsam_unstable/linear/EqualityFactorGraph.h new file mode 100644 index 000000000..43befdbe0 --- /dev/null +++ b/gtsam_unstable/linear/EqualityFactorGraph.h @@ -0,0 +1,51 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file EqualityFactorGraph.h + * @brief Factor graph of all LinearEquality factors + * @date Dec 8, 2014 + * @author Duy-Nguyen Ta + */ + +#pragma once + +#include +#include + +namespace gtsam { + +/** + * Collection of all Linear Equality constraints Ax=b of + * a Programming problem as a Factor Graph + */ +class EqualityFactorGraph: public FactorGraph { +public: + typedef boost::shared_ptr shared_ptr; + + /// Compute error of a guess. + double error(const VectorValues& x) const { + double total_error = 0.; + for (const sharedFactor& factor : *this) { + if (factor) + total_error += factor->error(x); + } + return total_error; + } +}; + +/// traits +template<> struct traits : public Testable< + EqualityFactorGraph> { +}; + +} // \ namespace gtsam + diff --git a/gtsam_unstable/linear/InequalityFactorGraph.h b/gtsam_unstable/linear/InequalityFactorGraph.h new file mode 100644 index 000000000..c87645697 --- /dev/null +++ b/gtsam_unstable/linear/InequalityFactorGraph.h @@ -0,0 +1,69 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file InequalityFactorGraph.h + * @brief Factor graph of all LinearInequality factors + * @date Dec 8, 2014 + * @author Duy-Nguyen Ta + */ + +#pragma once + +#include +#include +#include +#include + +namespace gtsam { + +/** + * Collection of all Linear Inequality constraints Ax-b <= 0 of + * a Programming problem as a Factor Graph + */ +class InequalityFactorGraph: public FactorGraph { +private: + typedef FactorGraph Base; + +public: + typedef boost::shared_ptr shared_ptr; + + /** print */ + void print(const std::string& str, const KeyFormatter& keyFormatter = + DefaultKeyFormatter) const { + Base::print(str, keyFormatter); + } + + /** equals */ + bool equals(const InequalityFactorGraph& other, double tol = 1e-9) const { + return Base::equals(other, tol); + } + + /** + * Compute error of a guess. + * Infinity error if it violates an inequality; zero otherwise. */ + double error(const VectorValues& x) const { + for (const sharedFactor& factor : *this) { + if (factor) + if (factor->error(x) > 1e-7) + return std::numeric_limits::infinity(); + } + return 0.0; + } +}; + +/// traits +template<> +struct traits : public Testable { +}; + +} // \ namespace gtsam + diff --git a/gtsam_unstable/linear/InfeasibleInitialValues.h b/gtsam_unstable/linear/InfeasibleInitialValues.h new file mode 100644 index 000000000..60adb872e --- /dev/null +++ b/gtsam_unstable/linear/InfeasibleInitialValues.h @@ -0,0 +1,45 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file InfeasibleInitialValues.h + * @brief Exception thrown when given Infeasible Initial Values. + * @date jan 24, 2015 + * @author Duy-Nguyen Ta + */ + +#pragma once + +namespace gtsam { +/* ************************************************************************* */ +/** An exception indicating that the provided initial value is infeasible + * Also used to inzdicatethat the noise model dimension passed into a + * JacobianFactor has a different dimensionality than the factor. */ +class InfeasibleInitialValues: public ThreadsafeException< + InfeasibleInitialValues> { +public: + InfeasibleInitialValues() { + } + + virtual ~InfeasibleInitialValues() throw () { + } + + virtual const char *what() const throw () { + if (description_.empty()) + description_ = + "An infeasible initial value was provided for the solver.\n"; + return description_.c_str(); + } + +private: + mutable std::string description_; +}; +} diff --git a/gtsam_unstable/linear/InfeasibleOrUnboundedProblem.h b/gtsam_unstable/linear/InfeasibleOrUnboundedProblem.h new file mode 100644 index 000000000..f7c5a5c79 --- /dev/null +++ b/gtsam_unstable/linear/InfeasibleOrUnboundedProblem.h @@ -0,0 +1,40 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file InfeasibleOrUnboundedProblem.h + * @brief Throw when the problem is either infeasible or unbounded + * @author Ivan Dario Jimenez + * @date 1/24/16 + */ + +#pragma once + +namespace gtsam { + +class InfeasibleOrUnboundedProblem: public ThreadsafeException< + InfeasibleOrUnboundedProblem> { +public: + InfeasibleOrUnboundedProblem() { + } + virtual ~InfeasibleOrUnboundedProblem() throw () { + } + + virtual const char* what() const throw () { + if (description_.empty()) + description_ = "The problem is either infeasible or unbounded.\n"; + return description_.c_str(); + } + +private: + mutable std::string description_; +}; +} diff --git a/gtsam_unstable/linear/LP.h b/gtsam_unstable/linear/LP.h new file mode 100644 index 000000000..fc00c2240 --- /dev/null +++ b/gtsam_unstable/linear/LP.h @@ -0,0 +1,102 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file LP.h + * @brief Struct used to hold a Linear Programming Problem + * @author Ivan Dario Jimenez + * @date 1/24/16 + */ + +#pragma once + +#include +#include +#include + +#include + +namespace gtsam { + +using namespace std; + +/// Mapping between variable's key and its corresponding dimensionality +using KeyDimMap = std::map; +/* + * Iterates through every factor in a linear graph and generates a + * mapping between every factor key and it's corresponding dimensionality. + */ +template +KeyDimMap collectKeyDim(const LinearGraph& linearGraph) { + KeyDimMap keyDimMap; + for (const typename LinearGraph::sharedFactor& factor : linearGraph) { + if (!factor) continue; + for (Key key : factor->keys()) + keyDimMap[key] = factor->getDim(factor->find(key)); + } + return keyDimMap; +} + +/** + * Data structure of a Linear Program + */ +struct LP { + using shared_ptr = boost::shared_ptr; + + LinearCost cost; //!< Linear cost factor + EqualityFactorGraph equalities; //!< Linear equality constraints: cE(x) = 0 + InequalityFactorGraph inequalities; //!< Linear inequality constraints: cI(x) <= 0 +private: + mutable KeyDimMap cachedConstrainedKeyDimMap_; //!< cached key-dim map of all variables in the constraints + +public: + /// check feasibility + bool isFeasible(const VectorValues& x) const { + return (equalities.error(x) == 0 && inequalities.error(x) == 0); + } + + /// print + void print(const string& s = "") const { + std::cout << s << std::endl; + cost.print("Linear cost: "); + equalities.print("Linear equality factors: "); + inequalities.print("Linear inequality factors: "); + } + + /// equals + bool equals(const LP& other, double tol = 1e-9) const { + return cost.equals(other.cost) && equalities.equals(other.equalities) + && inequalities.equals(other.inequalities); + } + + const KeyDimMap& constrainedKeyDimMap() const { + if (!cachedConstrainedKeyDimMap_.empty()) + return cachedConstrainedKeyDimMap_; + // Collect key-dim map of all variables in the constraints + cachedConstrainedKeyDimMap_ = collectKeyDim(equalities); + KeyDimMap keysDim2 = collectKeyDim(inequalities); + cachedConstrainedKeyDimMap_.insert(keysDim2.begin(), keysDim2.end()); + return cachedConstrainedKeyDimMap_; + } + + Vector costGradient(Key key, const VectorValues& delta) const { + Vector g = Vector::Zero(delta.at(key).size()); + Factor::const_iterator it = cost.find(key); + if (it != cost.end()) g = cost.getA(it).transpose(); + return g; + } +}; + +/// traits +template<> struct traits : public Testable { +}; + +} diff --git a/gtsam_unstable/linear/LPInitSolver.cpp b/gtsam_unstable/linear/LPInitSolver.cpp new file mode 100644 index 000000000..8c3df3132 --- /dev/null +++ b/gtsam_unstable/linear/LPInitSolver.cpp @@ -0,0 +1,110 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file LPInitSolver.h + * @brief This finds a feasible solution for an LP problem + * @author Duy Nguyen Ta + * @author Ivan Dario Jimenez + * @date 6/16/16 + */ + +#include +#include +#include + +namespace gtsam { + +/******************************************************************************/ +VectorValues LPInitSolver::solve() const { + // Build the graph to solve for the initial value of the initial problem + GaussianFactorGraph::shared_ptr initOfInitGraph = buildInitOfInitGraph(); + VectorValues x0 = initOfInitGraph->optimize(); + double y0 = compute_y0(x0); + Key yKey = maxKey(lp_) + 1; // the unique key for y0 + VectorValues xy0(x0); + xy0.insert(yKey, Vector::Constant(1, y0)); + + // Formulate and solve the initial LP + LP::shared_ptr initLP = buildInitialLP(yKey); + + // solve the initialLP + LPSolver lpSolveInit(*initLP); + VectorValues xyInit = lpSolveInit.optimize(xy0).first; + double yOpt = xyInit.at(yKey)[0]; + xyInit.erase(yKey); + if (yOpt > 0) + throw InfeasibleOrUnboundedProblem(); + else + return xyInit; +} + +/******************************************************************************/ +LP::shared_ptr LPInitSolver::buildInitialLP(Key yKey) const { + LP::shared_ptr initLP(new LP()); + initLP->cost = LinearCost(yKey, I_1x1); // min y + initLP->equalities = lp_.equalities; // st. Ax = b + initLP->inequalities = + addSlackVariableToInequalities(yKey, + lp_.inequalities); // Cx-y <= d + return initLP; +} + +/******************************************************************************/ +GaussianFactorGraph::shared_ptr LPInitSolver::buildInitOfInitGraph() const { + // first add equality constraints Ax = b + GaussianFactorGraph::shared_ptr initGraph( + new GaussianFactorGraph(lp_.equalities)); + + // create factor ||x||^2 and add to the graph + const KeyDimMap& constrainedKeyDim = lp_.constrainedKeyDimMap(); + for (Key key : constrainedKeyDim | boost::adaptors::map_keys) { + size_t dim = constrainedKeyDim.at(key); + initGraph->push_back( + JacobianFactor(key, Matrix::Identity(dim, dim), Vector::Zero(dim))); + } + return initGraph; +} + +/******************************************************************************/ +double LPInitSolver::compute_y0(const VectorValues& x0) const { + double y0 = -std::numeric_limits::infinity(); + for (const auto& factor : lp_.inequalities) { + double error = factor->error(x0); + if (error > y0) y0 = error; + } + return y0; +} + +/******************************************************************************/ +std::vector > LPInitSolver::collectTerms( + const LinearInequality& factor) const { + std::vector > terms; + for (Factor::const_iterator it = factor.begin(); it != factor.end(); it++) { + terms.push_back(make_pair(*it, factor.getA(it))); + } + return terms; +} + +/******************************************************************************/ +InequalityFactorGraph LPInitSolver::addSlackVariableToInequalities( + Key yKey, const InequalityFactorGraph& inequalities) const { + InequalityFactorGraph slackInequalities; + for (const auto& factor : lp_.inequalities) { + std::vector > terms = collectTerms(*factor); // Cx + terms.push_back(make_pair(yKey, Matrix::Constant(1, 1, -1.0))); // -y + double d = factor->getb()[0]; + slackInequalities.push_back(LinearInequality(terms, d, factor->dualKey())); + } + return slackInequalities; +} + +} \ No newline at end of file diff --git a/gtsam_unstable/linear/LPInitSolver.h b/gtsam_unstable/linear/LPInitSolver.h new file mode 100644 index 000000000..4eb672fbc --- /dev/null +++ b/gtsam_unstable/linear/LPInitSolver.h @@ -0,0 +1,89 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file LPInitSolver.h + * @brief This LPInitSolver implements the strategy in Matlab. + * @author Duy Nguyen Ta + * @author Ivan Dario Jimenez + * @date 1/24/16 + */ + +#pragma once + +#include +#include +#include + +namespace gtsam { +/** + * This LPInitSolver implements the strategy in Matlab: + * http://www.mathworks.com/help/optim/ug/linear-programming-algorithms.html#brozyzb-9 + * Solve for x and y: + * min y + * st Ax = b + * Cx - y <= d + * where y \in R, x \in R^n, and Ax = b and Cx <= d is the constraints of the original problem. + * + * If the solution for this problem {x*,y*} has y* <= 0, we'll have x* a feasible initial point + * of the original problem + * otherwise, if y* > 0 or the problem has no solution, the original problem is infeasible. + * + * The initial value of this initial problem can be found by solving + * min ||x||^2 + * s.t. Ax = b + * to have a solution x0 + * then y = max_j ( Cj*x0 - dj ) -- due to the constraints y >= Cx - d + * + * WARNING: If some xj in the inequality constraints does not exist in the equality constraints, + * set them as zero for now. If that is the case, the original problem doesn't have a unique + * solution (it could be either infeasible or unbounded). + * So, if the initialization fails because we enforce xj=0 in the problematic + * inequality constraint, we can't conclude that the problem is infeasible. + * However, whether it is infeasible or unbounded, we don't have a unique solution anyway. + */ +class LPInitSolver { +private: + const LP& lp_; + +public: + /// Construct with an LP problem + LPInitSolver(const LP& lp) : lp_(lp) {} + + ///@return a feasible initialization point + VectorValues solve() const; + +private: + /// build initial LP + LP::shared_ptr buildInitialLP(Key yKey) const; + + /** + * Build the following graph to solve for an initial value of the initial problem + * min ||x||^2 s.t. Ax = b + */ + GaussianFactorGraph::shared_ptr buildInitOfInitGraph() const; + + /// y = max_j ( Cj*x0 - dj ) -- due to the inequality constraints y >= Cx - d + double compute_y0(const VectorValues& x0) const; + + /// Collect all terms of a factor into a container. + std::vector> collectTerms( + const LinearInequality& factor) const; + + /// Turn Cx <= d into Cx - y <= d factors + InequalityFactorGraph addSlackVariableToInequalities(Key yKey, + const InequalityFactorGraph& inequalities) const; + + // friend class for unit-testing private methods + FRIEND_TEST(LPInitSolver, initialization); +}; + +} diff --git a/gtsam_unstable/linear/LPSolver.cpp b/gtsam_unstable/linear/LPSolver.cpp new file mode 100644 index 000000000..c1319a5ec --- /dev/null +++ b/gtsam_unstable/linear/LPSolver.cpp @@ -0,0 +1,25 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file LPSolver.cpp + * @brief + * @author Duy Nguyen Ta + * @author Ivan Dario Jimenez + * @date 1/26/16 + */ + +#include + +namespace gtsam { +constexpr double LPPolicy::maxAlpha; +} + diff --git a/gtsam_unstable/linear/LPSolver.h b/gtsam_unstable/linear/LPSolver.h new file mode 100644 index 000000000..91cee3941 --- /dev/null +++ b/gtsam_unstable/linear/LPSolver.h @@ -0,0 +1,80 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file LPSolver.h + * @brief Policy of ActiveSetSolver to solve Linear Programming Problems + * @author Duy Nguyen Ta + * @author Ivan Dario Jimenez + * @date 6/16/16 + */ + +#include +#include +#include + +#include +#include + +namespace gtsam { + +/// Policy for ActivetSetSolver to solve Linear Programming \sa LP problems +struct LPPolicy { + /// Maximum alpha for line search x'=xk + alpha*p, where p is the cost gradient + /// For LP, maxAlpha = Infinity + static constexpr double maxAlpha = std::numeric_limits::infinity(); + + /** + * Create the factor ||x-xk - (-g)||^2 where xk is the current feasible solution + * on the constraint surface and g is the gradient of the linear cost, + * i.e. -g is the direction we wish to follow to decrease the cost. + * + * Essentially, we try to match the direction d = x-xk with -g as much as possible + * subject to the condition that x needs to be on the constraint surface, i.e., d is + * along the surface's subspace. + * + * The least-square solution of this quadratic subject to a set of linear constraints + * is the projection of the gradient onto the constraints' subspace + */ + static GaussianFactorGraph buildCostFunction(const LP& lp, + const VectorValues& xk) { + GaussianFactorGraph graph; + for (LinearCost::const_iterator it = lp.cost.begin(); it != lp.cost.end(); + ++it) { + size_t dim = lp.cost.getDim(it); + Vector b = xk.at(*it) - lp.cost.getA(it).transpose(); // b = xk-g + graph.push_back(JacobianFactor(*it, Matrix::Identity(dim, dim), b)); + } + + KeySet allKeys = lp.inequalities.keys(); + allKeys.merge(lp.equalities.keys()); + allKeys.merge(KeySet(lp.cost.keys())); + // Add corresponding factors for all variables that are not explicitly in + // the cost function. Gradients of the cost function wrt to these variables + // are zero (g=0), so b=xk + if (lp.cost.keys().size() != allKeys.size()) { + KeySet difference; + std::set_difference(allKeys.begin(), allKeys.end(), lp.cost.begin(), + lp.cost.end(), + std::inserter(difference, difference.end())); + for (Key k : difference) { + size_t dim = lp.constrainedKeyDimMap().at(k); + graph.push_back( + JacobianFactor(k, Matrix::Identity(dim, dim), xk.at(k))); + } + } + return graph; + } +}; + +using LPSolver = ActiveSetSolver; + +} \ No newline at end of file diff --git a/gtsam_unstable/linear/LinearCost.h b/gtsam_unstable/linear/LinearCost.h new file mode 100644 index 000000000..b489510af --- /dev/null +++ b/gtsam_unstable/linear/LinearCost.h @@ -0,0 +1,124 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file LinearCost.h + * @brief LinearCost derived from JacobianFactor to support linear cost functions c'x + * @date Nov 27, 2014 + * @author Duy-Nguyen Ta + */ + +#pragma once + +#include + +namespace gtsam { + +typedef Eigen::RowVectorXd RowVector; + +/** + * This class defines a linear cost function c'x + * which is a JacobianFactor with only one row + */ +class LinearCost: public JacobianFactor { +public: + typedef LinearCost This; ///< Typedef to this class + typedef JacobianFactor Base; ///< Typedef to base class + typedef boost::shared_ptr shared_ptr; ///< shared_ptr to this class + +public: + /** default constructor for I/O */ + LinearCost() : + Base() { + } + + /** Conversion from HessianFactor */ + explicit LinearCost(const HessianFactor& hf) { + throw std::runtime_error("Cannot convert HessianFactor to LinearCost"); + } + + /** Conversion from JacobianFactor */ + explicit LinearCost(const JacobianFactor& jf) : + Base(jf) { + if (jf.isConstrained()) { + throw std::runtime_error( + "Cannot convert a constrained JacobianFactor to LinearCost"); + } + + if (jf.get_model()->dim() != 1) { + throw std::runtime_error( + "Only support single-valued linear cost factor!"); + } + } + + /** Construct unary factor */ + LinearCost(Key i1, const RowVector& A1) : + Base(i1, A1, Vector1::Zero()) { + } + + /** Construct binary factor */ + LinearCost(Key i1, const RowVector& A1, Key i2, const RowVector& A2, double b) : + Base(i1, A1, i2, A2, Vector1::Zero()) { + } + + /** Construct ternary factor */ + LinearCost(Key i1, const RowVector& A1, Key i2, const RowVector& A2, Key i3, + const RowVector& A3) : + Base(i1, A1, i2, A2, i3, A3, Vector1::Zero()) { + } + + /** Construct an n-ary factor + * @tparam TERMS A container whose value type is std::pair, specifying the + * collection of keys and matrices making up the factor. */ + template + LinearCost(const TERMS& terms) : + Base(terms, Vector1::Zero()) { + } + + /** Virtual destructor */ + virtual ~LinearCost() { + } + + /** equals */ + virtual bool equals(const GaussianFactor& lf, double tol = 1e-9) const { + return Base::equals(lf, tol); + } + + /** print */ + virtual void print(const std::string& s = "", const KeyFormatter& formatter = + DefaultKeyFormatter) const { + Base::print(s + " LinearCost: ", formatter); + } + + /** Clone this LinearCost */ + virtual GaussianFactor::shared_ptr clone() const { + return boost::static_pointer_cast < GaussianFactor + > (boost::make_shared < LinearCost > (*this)); + } + + /** Special error_vector for constraints (A*x-b) */ + Vector error_vector(const VectorValues& c) const { + return unweighted_error(c); + } + + /** Special error for single-valued inequality constraints. */ + virtual double error(const VectorValues& c) const { + return error_vector(c)[0]; + } +}; +// \ LinearCost + +/// traits +template<> struct traits : public Testable { +}; + +} // \ namespace gtsam + diff --git a/gtsam_unstable/linear/LinearEquality.h b/gtsam_unstable/linear/LinearEquality.h index bc1b2bc12..2463ef31c 100644 --- a/gtsam_unstable/linear/LinearEquality.h +++ b/gtsam_unstable/linear/LinearEquality.h @@ -9,11 +9,11 @@ * -------------------------------------------------------------------------- */ -/* - * LinearEquality.h - * @brief: LinearEquality derived from Base with constrained noise model - * @date: Nov 27, 2014 - * @author: thduynguyen +/** + * @file LinearEquality.h + * @brief LinearEquality derived from Base with constrained noise model + * @date Nov 27, 2014 + * @author Duy-Nguyen Ta */ #pragma once @@ -23,7 +23,7 @@ namespace gtsam { /** - * This class defines Linear constraints by inherit Base + * This class defines a linear equality constraints, inheriting JacobianFactor * with the special Constrained noise model */ class LinearEquality: public JacobianFactor { @@ -41,6 +41,17 @@ public: Base() { } + /** + * Construct from a constrained noisemodel JacobianFactor with a dual key. + */ + explicit LinearEquality(const JacobianFactor& jf, Key dualKey) : + Base(jf), dualKey_(dualKey) { + if (!jf.isConstrained()) { + throw std::runtime_error( + "Cannot convert an unconstrained JacobianFactor to LinearEquality"); + } + } + /** Conversion from HessianFactor (does Cholesky to obtain Jacobian matrix) */ explicit LinearEquality(const HessianFactor& hf) { throw std::runtime_error("Cannot convert HessianFactor to LinearEquality"); @@ -90,15 +101,19 @@ public: /** Clone this LinearEquality */ virtual GaussianFactor::shared_ptr clone() const { - return boost::static_pointer_cast( - boost::make_shared(*this)); + return boost::static_pointer_cast < GaussianFactor + > (boost::make_shared < LinearEquality > (*this)); } /// dual key - Key dualKey() const { return dualKey_; } + Key dualKey() const { + return dualKey_; + } /// for active set method: equality constraints are always active - bool active() const { return true; } + bool active() const { + return true; + } /** Special error_vector for constraints (A*x-b) */ Vector error_vector(const VectorValues& c) const { @@ -113,11 +128,12 @@ public: return 0.0; } -}; // \ LinearEquality - +}; +// \ LinearEquality /// traits -template<> struct traits : public Testable {}; +template<> struct traits : public Testable { +}; } // \ namespace gtsam diff --git a/gtsam_unstable/linear/LinearEqualityFactorGraph.h b/gtsam_unstable/linear/LinearEqualityFactorGraph.h deleted file mode 100644 index 9c067ae3d..000000000 --- a/gtsam_unstable/linear/LinearEqualityFactorGraph.h +++ /dev/null @@ -1,37 +0,0 @@ -/* ---------------------------------------------------------------------------- - - * GTSAM Copyright 2010, Georgia Tech Research Corporation, - * Atlanta, Georgia 30332-0415 - * All Rights Reserved - * Authors: Frank Dellaert, et al. (see THANKS for the full author list) - - * See LICENSE for the license information - - * -------------------------------------------------------------------------- */ - -/* - * LinearEqualityFactorGraph.h - * @brief: Factor graph of all LinearEquality factors - * @date: Dec 8, 2014 - * @author: thduynguyen - */ - -#pragma once - -#include -#include - -namespace gtsam { - -class LinearEqualityFactorGraph : public FactorGraph { -public: - typedef boost::shared_ptr shared_ptr; -}; - -/// traits -template<> struct traits : public Testable< - LinearEqualityFactorGraph> { -}; - -} // \ namespace gtsam - diff --git a/gtsam_unstable/linear/LinearInequality.h b/gtsam_unstable/linear/LinearInequality.h index 7c62c3d54..1a31bd4e4 100644 --- a/gtsam_unstable/linear/LinearInequality.h +++ b/gtsam_unstable/linear/LinearInequality.h @@ -9,24 +9,26 @@ * -------------------------------------------------------------------------- */ -/* - * LinearInequality.h - * @brief: LinearInequality derived from Base with constrained noise model - * @date: Nov 27, 2014 - * @author: thduynguyen +/** + * @file LinearInequality.h + * @brief LinearInequality derived from Base with constrained noise model + * @date Nov 27, 2014 + * @author Duy-Nguyen Ta + * @author Ivan Dario Jimenez */ #pragma once #include +#include namespace gtsam { typedef Eigen::RowVectorXd RowVector; /** - * This class defines Linear constraints by inherit Base - * with the special Constrained noise model + * This class defines a linear inequality constraint Ax-b <= 0, + * inheriting JacobianFactor with the special Constrained noise model */ class LinearInequality: public JacobianFactor { public: @@ -44,35 +46,49 @@ public: Base(), active_(true) { } - /** Conversion from HessianFactor (does Cholesky to obtain Jacobian matrix) */ + /** Conversion from HessianFactor */ explicit LinearInequality(const HessianFactor& hf) { throw std::runtime_error( "Cannot convert HessianFactor to LinearInequality"); } + /** Conversion from JacobianFactor */ + explicit LinearInequality(const JacobianFactor& jf, Key dualKey) : + Base(jf), dualKey_(dualKey), active_(true) { + if (!jf.isConstrained()) { + throw std::runtime_error( + "Cannot convert an unconstrained JacobianFactor to LinearInequality"); + } + + if (jf.get_model()->dim() != 1) { + throw std::runtime_error("Only support single-valued inequality factor!"); + } + } + /** Construct unary factor */ LinearInequality(Key i1, const RowVector& A1, double b, Key dualKey) : - Base(i1, A1, (Vector(1) << b).finished(), noiseModel::Constrained::All(1)), dualKey_( - dualKey), active_(true) { + Base(i1, A1, (Vector(1) << b).finished(), + noiseModel::Constrained::All(1)), dualKey_(dualKey), active_(true) { } /** Construct binary factor */ - LinearInequality(Key i1, const RowVector& A1, Key i2, const RowVector& A2, double b, - Key dualKey) : - Base(i1, A1, i2, A2, (Vector(1) << b).finished(), noiseModel::Constrained::All(1)), dualKey_( - dualKey), active_(true) { + LinearInequality(Key i1, const RowVector& A1, Key i2, const RowVector& A2, + double b, Key dualKey) : + Base(i1, A1, i2, A2, (Vector(1) << b).finished(), + noiseModel::Constrained::All(1)), dualKey_(dualKey), active_(true) { } /** Construct ternary factor */ - LinearInequality(Key i1, const RowVector& A1, Key i2, const RowVector& A2, Key i3, - const RowVector& A3, double b, Key dualKey) : + LinearInequality(Key i1, const RowVector& A1, Key i2, const RowVector& A2, + Key i3, const RowVector& A3, double b, Key dualKey) : Base(i1, A1, i2, A2, i3, A3, (Vector(1) << b).finished(), noiseModel::Constrained::All(1)), dualKey_(dualKey), active_(true) { } /** Construct an n-ary factor * @tparam TERMS A container whose value type is std::pair, specifying the - * collection of keys and matrices making up the factor. */ + * collection of keys and matrices making up the factor. + * In this inequality factor, each matrix must have only one row!! */ template LinearInequality(const TERMS& terms, double b, Key dualKey) : Base(terms, (Vector(1) << b).finished(), noiseModel::Constrained::All(1)), dualKey_( @@ -99,21 +115,29 @@ public: /** Clone this LinearInequality */ virtual GaussianFactor::shared_ptr clone() const { - return boost::static_pointer_cast( - boost::make_shared(*this)); + return boost::static_pointer_cast < GaussianFactor + > (boost::make_shared < LinearInequality > (*this)); } /// dual key - Key dualKey() const { return dualKey_; } + Key dualKey() const { + return dualKey_; + } /// return true if this constraint is active - bool active() const { return active_; } + bool active() const { + return active_; + } /// Make this inequality constraint active - void activate() { active_ = true; } + void activate() { + active_ = true; + } /// Make this inequality constraint inactive - void inactivate() { active_ = false; } + void inactivate() { + active_ = false; + } /** Special error_vector for constraints (A*x-b) */ Vector error_vector(const VectorValues& c) const { @@ -136,10 +160,12 @@ public: return aTp; } -}; // \ LinearInequality +}; +// \ LinearInequality /// traits -template<> struct traits : public Testable {}; +template<> struct traits : public Testable { +}; } // \ namespace gtsam diff --git a/gtsam_unstable/linear/LinearInequalityFactorGraph.h b/gtsam_unstable/linear/LinearInequalityFactorGraph.h deleted file mode 100644 index eca271941..000000000 --- a/gtsam_unstable/linear/LinearInequalityFactorGraph.h +++ /dev/null @@ -1,52 +0,0 @@ -/* ---------------------------------------------------------------------------- - - * GTSAM Copyright 2010, Georgia Tech Research Corporation, - * Atlanta, Georgia 30332-0415 - * All Rights Reserved - * Authors: Frank Dellaert, et al. (see THANKS for the full author list) - - * See LICENSE for the license information - - * -------------------------------------------------------------------------- */ - -/* - * LinearInequalityFactorGraph.h - * @brief: Factor graph of all LinearInequality factors - * @date: Dec 8, 2014 - * @author: thduynguyen - */ - -#pragma once - -#include -#include - -namespace gtsam { - -class LinearInequalityFactorGraph: public FactorGraph { -private: - typedef FactorGraph Base; - -public: - typedef boost::shared_ptr shared_ptr; - - /** print */ - void print(const std::string& str, const KeyFormatter& keyFormatter = - DefaultKeyFormatter) const { - Base::print(str, keyFormatter); - } - - /** equals */ - bool equals(const LinearInequalityFactorGraph& other, - double tol = 1e-9) const { - return Base::equals(other, tol); - } -}; - -/// traits -template<> struct traits : public Testable< - LinearInequalityFactorGraph> { -}; - -} // \ namespace gtsam - diff --git a/gtsam_unstable/linear/QP.h b/gtsam_unstable/linear/QP.h index 111ab506f..e610eb934 100644 --- a/gtsam_unstable/linear/QP.h +++ b/gtsam_unstable/linear/QP.h @@ -9,29 +9,34 @@ * -------------------------------------------------------------------------- */ -/* - * QP.h - * @brief: Factor graphs of a Quadratic Programming problem - * @date: Dec 8, 2014 - * @author: thduynguyen +/** + * @file QP.h + * @brief Factor graphs of a Quadratic Programming problem + * @date Dec 8, 2014 + * @author Duy-Nguyen Ta */ #pragma once #include -#include -#include +#include +#include +#include namespace gtsam { /** - * struct contains factor graphs of a Quadratic Programming problem + * Struct contains factor graphs of a Quadratic Programming problem */ struct QP { GaussianFactorGraph cost; //!< Quadratic cost factors - LinearEqualityFactorGraph equalities; //!< linear equality constraints - LinearInequalityFactorGraph inequalities; //!< linear inequality constraints + EqualityFactorGraph equalities; //!< linear equality constraints: cE(x) = 0 + InequalityFactorGraph inequalities; //!< linear inequality constraints: cI(x) <= 0 +private: + mutable VariableIndex cachedCostVariableIndex_; + +public: /** default constructor */ QP() : cost(), equalities(), inequalities() { @@ -39,8 +44,8 @@ struct QP { /** constructor */ QP(const GaussianFactorGraph& _cost, - const LinearEqualityFactorGraph& _linearEqualities, - const LinearInequalityFactorGraph& _linearInequalities) : + const EqualityFactorGraph& _linearEqualities, + const InequalityFactorGraph& _linearInequalities) : cost(_cost), equalities(_linearEqualities), inequalities( _linearInequalities) { } @@ -52,6 +57,23 @@ struct QP { equalities.print("Linear equality factors: "); inequalities.print("Linear inequality factors: "); } + + const VariableIndex& costVariableIndex() const { + if (cachedCostVariableIndex_.size() == 0) + cachedCostVariableIndex_ = VariableIndex(cost); + return cachedCostVariableIndex_; + } + + Vector costGradient(Key key, const VectorValues& delta) const { + Vector g = Vector::Zero(delta.at(key).size()); + if (costVariableIndex().find(key) != costVariableIndex().end()) { + for (size_t factorIx : costVariableIndex()[key]) { + GaussianFactor::shared_ptr factor = cost.at(factorIx); + g += factor->gradient(key, delta); + } + } + return g; + } }; } // namespace gtsam diff --git a/gtsam_unstable/linear/QPInitSolver.h b/gtsam_unstable/linear/QPInitSolver.h new file mode 100644 index 000000000..6742e9223 --- /dev/null +++ b/gtsam_unstable/linear/QPInitSolver.h @@ -0,0 +1,54 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file QPInitSolver.h + * @brief This finds a feasible solution for a QP problem + * @author Duy Nguyen Ta + * @author Ivan Dario Jimenez + * @date 6/16/16 + */ + +#pragma once + +#include + +namespace gtsam { + +/** + * This class finds a feasible solution for a QP problem. + * This uses the Matlab strategy for initialization + * For details, see + * http://www.mathworks.com/help/optim/ug/quadratic-programming-algorithms.html#brrzwpf-22 + */ +class QPInitSolver { + const QP& qp_; +public: + /// Constructor with a QP problem + QPInitSolver(const QP& qp) : qp_(qp) {} + + ///@return a feasible initialization point + VectorValues solve() const { + // Make an LP with any linear cost function. It doesn't matter for + // initialization. + LP initProblem; + // make an unrelated key for a random variable cost + Key newKey = maxKey(qp_) + 1; + initProblem.cost = LinearCost(newKey, Vector::Ones(1)); + initProblem.equalities = qp_.equalities; + initProblem.inequalities = qp_.inequalities; + LPInitSolver initSolver(initProblem); + return initSolver.solve(); + } +}; + + +} \ No newline at end of file diff --git a/gtsam_unstable/linear/QPSParser.cpp b/gtsam_unstable/linear/QPSParser.cpp new file mode 100644 index 000000000..748c4db38 --- /dev/null +++ b/gtsam_unstable/linear/QPSParser.cpp @@ -0,0 +1,126 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file QPParser.cpp + * @author Ivan Dario Jimenez + * @date 3/5/16 + */ + +#define BOOST_SPIRIT_USE_PHOENIX_V3 1 + +#include +#include +#include + +#include +#include +#include +#include + +namespace bf = boost::fusion; +namespace qi = boost::spirit::qi; + +namespace gtsam { +typedef qi::grammar> base_grammar; + +struct QPSParser::MPSGrammar: base_grammar { + typedef std::vector Chars; + RawQP * rqp_; + boost::function const&)> setName; + boost::function const &)> addRow; + boost::function< + void(bf::vector const &)> rhsSingle; + boost::function< + void( + bf::vector)> rhsDouble; + boost::function< + void(bf::vector)> colSingle; + boost::function< + void( + bf::vector const &)> colDouble; + boost::function< + void(bf::vector const &)> addQuadTerm; + boost::function< + void( + bf::vector const &)> addBound; + boost::function< + void(bf::vector const &)> addBoundFr; + MPSGrammar(RawQP * rqp) : + base_grammar(start), rqp_(rqp), setName( + boost::bind(&RawQP::setName, rqp, ::_1)), addRow( + boost::bind(&RawQP::addRow, rqp, ::_1)), rhsSingle( + boost::bind(&RawQP::addRHS, rqp, ::_1)), rhsDouble( + boost::bind(&RawQP::addRHSDouble, rqp, ::_1)), colSingle( + boost::bind(&RawQP::addColumn, rqp, ::_1)), colDouble( + boost::bind(&RawQP::addColumnDouble, rqp, ::_1)), addQuadTerm( + boost::bind(&RawQP::addQuadTerm, rqp, ::_1)), addBound( + boost::bind(&RawQP::addBound, rqp, ::_1)), addBoundFr( + boost::bind(&RawQP::addBoundFr, rqp, ::_1)) { + using namespace boost::spirit; + using namespace boost::spirit::qi; + character = lexeme[alnum | '_' | '-' | '.']; + title = lexeme[character >> *(blank | character)]; + word = lexeme[+character]; + name = lexeme[lit("NAME") >> *blank >> title >> +space][setName]; + row = lexeme[*blank >> character >> +blank >> word >> *blank][addRow]; + rhs_single = lexeme[*blank >> word >> +blank >> word >> +blank >> double_ + >> *blank][rhsSingle]; + rhs_double = lexeme[(*blank >> word >> +blank >> word >> +blank >> double_ + >> +blank >> word >> +blank >> double_)[rhsDouble] >> *blank]; + col_single = lexeme[*blank >> word >> +blank >> word >> +blank >> double_ + >> *blank][colSingle]; + col_double = lexeme[*blank + >> (word >> +blank >> word >> +blank >> double_ >> +blank >> word + >> +blank >> double_)[colDouble] >> *blank]; + quad_l = lexeme[*blank >> word >> +blank >> word >> +blank >> double_ + >> *blank][addQuadTerm]; + bound = lexeme[*blank >> word >> +blank >> word >> +blank >> word >> +blank + >> double_ >> *blank][addBound]; + bound_fr = lexeme[*blank >> word >> +blank >> word >> +blank >> word + >> *blank][addBoundFr]; + rows = lexeme[lit("ROWS") >> *blank >> eol >> +(row >> eol)]; + rhs = lexeme[lit("RHS") >> *blank >> eol + >> +((rhs_double | rhs_single) >> eol)]; + cols = lexeme[lit("COLUMNS") >> *blank >> eol + >> +((col_double | col_single) >> eol)]; + quad = lexeme[lit("QUADOBJ") >> *blank >> eol >> +(quad_l >> eol)]; + bounds = lexeme[lit("BOUNDS") >> +space >> +((bound | bound_fr) >> eol)]; + ranges = lexeme[lit("RANGES") >> +space]; + end = lexeme[lit("ENDATA") >> *space]; + start = lexeme[name >> rows >> cols >> rhs >> -ranges >> bounds >> quad + >> end]; + } + + qi::rule, char()> character; + qi::rule, Chars()> word, title; + qi::rule > row, end, col_single, + col_double, rhs_single, rhs_double, ranges, bound, bound_fr, bounds, quad, + quad_l, rows, cols, rhs, name, start; +}; + +QP QPSParser::Parse() { + RawQP rawData; + std::fstream stream(fileName_.c_str()); + stream.unsetf(std::ios::skipws); + boost::spirit::basic_istream_iterator begin(stream); + boost::spirit::basic_istream_iterator last; + + if (!parse(begin, last, MPSGrammar(&rawData)) || begin != last) { + throw QPSParserException(); + } + + return rawData.makeQP(); +} + +} diff --git a/gtsam_unstable/linear/QPSParser.h b/gtsam_unstable/linear/QPSParser.h new file mode 100644 index 000000000..088168829 --- /dev/null +++ b/gtsam_unstable/linear/QPSParser.h @@ -0,0 +1,40 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file QPParser.h + * @brief QPS parser implementation + * @author Ivan Dario Jimenez + * @date 3/5/16 + */ + +#pragma once + +#include +#include + +namespace gtsam { + +class QPSParser { + +private: + std::string fileName_; + struct MPSGrammar; +public: + + QPSParser(const std::string& fileName) : + fileName_(findExampleDataFile(fileName)) { + } + + QP Parse(); +}; +} + diff --git a/gtsam_unstable/linear/QPSParserException.h b/gtsam_unstable/linear/QPSParserException.h new file mode 100644 index 000000000..ed4c79bdd --- /dev/null +++ b/gtsam_unstable/linear/QPSParserException.h @@ -0,0 +1,42 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file QPSParserException.h + * @brief Exception thrown if there is an error parsing a QPS file + * @author Ivan Dario Jimenez + * @date 3/5/16 + */ + +#pragma once + +namespace gtsam { + +class QPSParserException: public ThreadsafeException { +public: + QPSParserException() { + } + + virtual ~QPSParserException() throw () { + } + + virtual const char *what() const throw () { + if (description_.empty()) + description_ = "There is a problem parsing the QPS file.\n"; + return description_.c_str(); + } + +private: + mutable std::string description_; +}; + +} + diff --git a/gtsam_unstable/linear/QPSolver.cpp b/gtsam_unstable/linear/QPSolver.cpp index 9fd58af78..5a4ac79ca 100644 --- a/gtsam_unstable/linear/QPSolver.cpp +++ b/gtsam_unstable/linear/QPSolver.cpp @@ -1,252 +1,23 @@ -/* - * QPSolver.cpp - * @brief: - * @date: Apr 15, 2014 - * @author: thduynguyen +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file QPSolver.cpp + * @brief + * @date Apr 15, 2014 + * @author Duy-Nguyen Ta */ -#include -#include #include -#include - -using namespace std; - namespace gtsam { - -//****************************************************************************** -QPSolver::QPSolver(const QP& qp) : qp_(qp) { - baseGraph_ = qp_.cost; - baseGraph_.push_back(qp_.equalities.begin(), qp_.equalities.end()); - costVariableIndex_ = VariableIndex(qp_.cost); - equalityVariableIndex_ = VariableIndex(qp_.equalities); - inequalityVariableIndex_ = VariableIndex(qp_.inequalities); - constrainedKeys_ = qp_.equalities.keys(); - constrainedKeys_.merge(qp_.inequalities.keys()); -} - -//****************************************************************************** -VectorValues QPSolver::solveWithCurrentWorkingSet( - const LinearInequalityFactorGraph& workingSet) const { - GaussianFactorGraph workingGraph = baseGraph_; - for(const LinearInequality::shared_ptr& factor: workingSet) { - if (factor->active()) - workingGraph.push_back(factor); - } - return workingGraph.optimize(); -} - -//****************************************************************************** -JacobianFactor::shared_ptr QPSolver::createDualFactor(Key key, - const LinearInequalityFactorGraph& workingSet, const VectorValues& delta) const { - - // Transpose the A matrix of constrained factors to have the jacobian of the dual key - std::vector > Aterms = collectDualJacobians - < LinearEquality > (key, qp_.equalities, equalityVariableIndex_); - std::vector > AtermsInequalities = collectDualJacobians - < LinearInequality > (key, workingSet, inequalityVariableIndex_); - Aterms.insert(Aterms.end(), AtermsInequalities.begin(), - AtermsInequalities.end()); - - // Collect the gradients of unconstrained cost factors to the b vector - if (Aterms.size() > 0) { - Vector b = Vector::Zero(delta.at(key).size()); - if (costVariableIndex_.find(key) != costVariableIndex_.end()) { - for(size_t factorIx: costVariableIndex_[key]) { - GaussianFactor::shared_ptr factor = qp_.cost.at(factorIx); - b += factor->gradient(key, delta); - } - } - return boost::make_shared(Aterms, b, noiseModel::Constrained::All(b.rows())); - } - else { - return boost::make_shared(); - } -} - -//****************************************************************************** -GaussianFactorGraph::shared_ptr QPSolver::buildDualGraph( - const LinearInequalityFactorGraph& workingSet, const VectorValues& delta) const { - GaussianFactorGraph::shared_ptr dualGraph(new GaussianFactorGraph()); - for(Key key: constrainedKeys_) { - // Each constrained key becomes a factor in the dual graph - JacobianFactor::shared_ptr dualFactor = createDualFactor(key, workingSet, delta); - if (!dualFactor->empty()) - dualGraph->push_back(dualFactor); - } - return dualGraph; -} - -//****************************************************************************** -int QPSolver::identifyLeavingConstraint( - const LinearInequalityFactorGraph& workingSet, - const VectorValues& lambdas) const { - int worstFactorIx = -1; - // preset the maxLambda to 0.0: if lambda is <= 0.0, the constraint is either - // inactive or a good inequality constraint, so we don't care! - double maxLambda = 0.0; - for (size_t factorIx = 0; factorIx < workingSet.size(); ++factorIx) { - const LinearInequality::shared_ptr& factor = workingSet.at(factorIx); - if (factor->active()) { - double lambda = lambdas.at(factor->dualKey())[0]; - if (lambda > maxLambda) { - worstFactorIx = factorIx; - maxLambda = lambda; - } - } - } - return worstFactorIx; -} - -//****************************************************************************** -/* We have to make sure the new solution with alpha satisfies all INACTIVE inequality constraints - * If some inactive inequality constraints complain about the full step (alpha = 1), - * we have to adjust alpha to stay within the inequality constraints' feasible regions. - * - * For each inactive inequality j: - * - We already have: aj'*xk - bj <= 0, since xk satisfies all inequality constraints - * - We want: aj'*(xk + alpha*p) - bj <= 0 - * - If aj'*p <= 0, we have: aj'*(xk + alpha*p) <= aj'*xk <= bj, for all alpha>0 - * it's good! - * - We only care when aj'*p > 0. In this case, we need to choose alpha so that - * aj'*xk + alpha*aj'*p - bj <= 0 --> alpha <= (bj - aj'*xk) / (aj'*p) - * We want to step as far as possible, so we should choose alpha = (bj - aj'*xk) / (aj'*p) - * - * We want the minimum of all those alphas among all inactive inequality. - */ -boost::tuple QPSolver::computeStepSize( - const LinearInequalityFactorGraph& workingSet, const VectorValues& xk, - const VectorValues& p) const { - static bool debug = false; - - double minAlpha = 1.0; - int closestFactorIx = -1; - for(size_t factorIx = 0; factorIxgetb()[0]; - // only check inactive factors - if (!factor->active()) { - // Compute a'*p - double aTp = factor->dotProductRow(p); - - // Check if a'*p >0. Don't care if it's not. - if (aTp <= 0) - continue; - - // Compute a'*xk - double aTx = factor->dotProductRow(xk); - - // alpha = (b - a'*xk) / (a'*p) - double alpha = (b - aTx) / aTp; - if (debug) - cout << "alpha: " << alpha << endl; - - // We want the minimum of all those max alphas - if (alpha < minAlpha) { - closestFactorIx = factorIx; - minAlpha = alpha; - } - } - - } - - return boost::make_tuple(minAlpha, closestFactorIx); -} - -//****************************************************************************** -QPState QPSolver::iterate(const QPState& state) const { - static bool debug = false; - - // Solve with the current working set - VectorValues newValues = solveWithCurrentWorkingSet(state.workingSet); - if (debug) - newValues.print("New solution:"); - - // If we CAN'T move further - if (newValues.equals(state.values, 1e-5)) { - // Compute lambda from the dual graph - if (debug) - cout << "Building dual graph..." << endl; - GaussianFactorGraph::shared_ptr dualGraph = buildDualGraph(state.workingSet, newValues); - if (debug) - dualGraph->print("Dual graph: "); - VectorValues duals = dualGraph->optimize(); - if (debug) - duals.print("Duals :"); - - int leavingFactor = identifyLeavingConstraint(state.workingSet, duals); - if (debug) - cout << "leavingFactor: " << leavingFactor << endl; - - // If all inequality constraints are satisfied: We have the solution!! - if (leavingFactor < 0) { - return QPState(newValues, duals, state.workingSet, true); - } - else { - // Inactivate the leaving constraint - LinearInequalityFactorGraph newWorkingSet = state.workingSet; - newWorkingSet.at(leavingFactor)->inactivate(); - return QPState(newValues, duals, newWorkingSet, false); - } - } - else { - // If we CAN make some progress - // Adapt stepsize if some inactive constraints complain about this move - double alpha; - int factorIx; - VectorValues p = newValues - state.values; - boost::tie(alpha, factorIx) = // - computeStepSize(state.workingSet, state.values, p); - if (debug) - cout << "alpha, factorIx: " << alpha << " " << factorIx << " " - << endl; - - // also add to the working set the one that complains the most - LinearInequalityFactorGraph newWorkingSet = state.workingSet; - if (factorIx >= 0) - newWorkingSet.at(factorIx)->activate(); - - // step! - newValues = state.values + alpha * p; - - return QPState(newValues, state.duals, newWorkingSet, false); - } -} - -//****************************************************************************** -LinearInequalityFactorGraph QPSolver::identifyActiveConstraints( - const LinearInequalityFactorGraph& inequalities, - const VectorValues& initialValues) const { - LinearInequalityFactorGraph workingSet; - for(const LinearInequality::shared_ptr& factor: inequalities){ - LinearInequality::shared_ptr workingFactor(new LinearInequality(*factor)); - double error = workingFactor->error(initialValues); - if (fabs(error)>1e-7){ - workingFactor->inactivate(); - } else { - workingFactor->activate(); - } - workingSet.push_back(workingFactor); - } - return workingSet; -} - -//****************************************************************************** -pair QPSolver::optimize( - const VectorValues& initialValues) const { - - // Initialize workingSet from the feasible initialValues - LinearInequalityFactorGraph workingSet = - identifyActiveConstraints(qp_.inequalities, initialValues); - QPState state(initialValues, VectorValues(), workingSet, false); - - /// main loop of the solver - while (!state.converged) { - state = iterate(state); - } - - return make_pair(state.values, state.duals); -} - -} /* namespace gtsam */ +constexpr double QPPolicy::maxAlpha; +} \ No newline at end of file diff --git a/gtsam_unstable/linear/QPSolver.h b/gtsam_unstable/linear/QPSolver.h index 7929bc1cc..9efc23a67 100644 --- a/gtsam_unstable/linear/QPSolver.h +++ b/gtsam_unstable/linear/QPSolver.h @@ -1,188 +1,43 @@ -/* - * QPSolver.h - * @brief: A quadratic programming solver implements the active set method - * @date: Apr 15, 2014 - * @author: thduynguyen +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file QPSolver.h + * @brief Policy of ActiveSetSolver to solve Quadratic Programming Problems + * @author Duy Nguyen Ta + * @author Ivan Dario Jimenez + * @date 6/16/16 */ -#pragma once - -#include #include - -#include -#include +#include +#include +#include +#include namespace gtsam { -/// This struct holds the state of QPSolver at each iteration -struct QPState { - VectorValues values; - VectorValues duals; - LinearInequalityFactorGraph workingSet; - bool converged; +/// Policy for ActivetSetSolver to solve Linear Programming \sa QP problems +struct QPPolicy { + /// Maximum alpha for line search x'=xk + alpha*p, where p is the cost gradient + /// For QP, maxAlpha = 1 is the minimum point of the quadratic cost + static constexpr double maxAlpha = 1.0; - /// default constructor - QPState() : - values(), duals(), workingSet(), converged(false) { - } - - /// constructor with initial values - QPState(const VectorValues& initialValues, const VectorValues& initialDuals, - const LinearInequalityFactorGraph& initialWorkingSet, bool _converged) : - values(initialValues), duals(initialDuals), workingSet(initialWorkingSet), converged( - _converged) { + /// Simply the cost of the QP problem + static const GaussianFactorGraph& buildCostFunction( + const QP& qp, const VectorValues& xk = VectorValues()) { + return qp.cost; } }; -/** - * This class implements the active set method to solve quadratic programming problems - * encoded in a GaussianFactorGraph with special mixed constrained noise models, in which - * a negative sigma denotes an inequality <=0 constraint, - * a zero sigma denotes an equality =0 constraint, - * and a positive sigma denotes a normal Gaussian noise model. - */ -class QPSolver { +using QPSolver = ActiveSetSolver; - const QP& qp_; //!< factor graphs of the QP problem, can't be modified! - GaussianFactorGraph baseGraph_; //!< factor graphs of cost factors and linear equalities. The working set of inequalities will be added to this base graph in the process. - VariableIndex costVariableIndex_, equalityVariableIndex_, - inequalityVariableIndex_; - KeySet constrainedKeys_; //!< all constrained keys, will become factors in the dual graph - -public: - /// Constructor - QPSolver(const QP& qp); - - /// Find solution with the current working set - VectorValues solveWithCurrentWorkingSet( - const LinearInequalityFactorGraph& workingSet) const; - - /// @name Build the dual graph - /// @{ - - /// Collect the Jacobian terms for a dual factor - template - std::vector > collectDualJacobians(Key key, - const FactorGraph& graph, - const VariableIndex& variableIndex) const { - std::vector > Aterms; - if (variableIndex.find(key) != variableIndex.end()) { - for(size_t factorIx: variableIndex[key]){ - typename FACTOR::shared_ptr factor = graph.at(factorIx); - if (!factor->active()) continue; - Matrix Ai = factor->getA(factor->find(key)).transpose(); - Aterms.push_back(std::make_pair(factor->dualKey(), Ai)); - } - } - return Aterms; - } - - /// Create a dual factor - JacobianFactor::shared_ptr createDualFactor(Key key, - const LinearInequalityFactorGraph& workingSet, - const VectorValues& delta) const; - - /** - * Build the dual graph to solve for the Lagrange multipliers. - * - * The Lagrangian function is: - * L(X,lambdas) = f(X) - \sum_k lambda_k * c_k(X), - * where the unconstrained part is - * f(X) = 0.5*X'*G*X - X'*g + 0.5*f0 - * and the linear equality constraints are - * c1(X), c2(X), ..., cm(X) - * - * Take the derivative of L wrt X at the solution and set it to 0, we have - * \grad f(X) = \sum_k lambda_k * \grad c_k(X) (*) - * - * For each set of rows of (*) corresponding to a variable xi involving in some constraints - * we have: - * \grad f(xi) = \frac{\partial f}{\partial xi}' = \sum_j G_ij*xj - gi - * \grad c_k(xi) = \frac{\partial c_k}{\partial xi}' - * - * Note: If xi does not involve in any constraint, we have the trivial condition - * \grad f(Xi) = 0, which should be satisfied as a usual condition for unconstrained variables. - * - * So each variable xi involving in some constraints becomes a linear factor A*lambdas - b = 0 - * on the constraints' lambda multipliers, as follows: - * - The jacobian term A_k for each lambda_k is \grad c_k(xi) - * - The constant term b is \grad f(xi), which can be computed from all unconstrained - * Hessian factors connecting to xi: \grad f(xi) = \sum_j G_ij*xj - gi - */ - GaussianFactorGraph::shared_ptr buildDualGraph( - const LinearInequalityFactorGraph& workingSet, - const VectorValues& delta) const; - - /// @} - - /** - * The goal of this function is to find currently active inequality constraints - * that violate the condition to be active. The one that violates the condition - * the most will be removed from the active set. See Nocedal06book, pg 469-471 - * - * Find the BAD active inequality that pulls x strongest to the wrong direction - * of its constraint (i.e. it is pulling towards >0, while its feasible region is <=0) - * - * For active inequality constraints (those that are enforced as equality constraints - * in the current working set), we want lambda < 0. - * This is because: - * - From the Lagrangian L = f - lambda*c, we know that the constraint force - * is (lambda * \grad c) = \grad f. Intuitively, to keep the solution x stay - * on the constraint surface, the constraint force has to balance out with - * other unconstrained forces that are pulling x towards the unconstrained - * minimum point. The other unconstrained forces are pulling x toward (-\grad f), - * hence the constraint force has to be exactly \grad f, so that the total - * force is 0. - * - We also know that at the constraint surface c(x)=0, \grad c points towards + (>= 0), - * while we are solving for - (<=0) constraint. - * - We want the constraint force (lambda * \grad c) to pull x towards the - (<=0) direction - * i.e., the opposite direction of \grad c where the inequality constraint <=0 is satisfied. - * That means we want lambda < 0. - * - This is because when the constrained force pulls x towards the infeasible region (+), - * the unconstrained force is pulling x towards the opposite direction into - * the feasible region (again because the total force has to be 0 to make x stay still) - * So we can drop this constraint to have a lower error but feasible solution. - * - * In short, active inequality constraints with lambda > 0 are BAD, because they - * violate the condition to be active. - * - * And we want to remove the worst one with the largest lambda from the active set. - * - */ - int identifyLeavingConstraint(const LinearInequalityFactorGraph& workingSet, - const VectorValues& lambdas) const; - - /** - * Compute step size alpha for the new solution x' = xk + alpha*p, where alpha \in [0,1] - * - * @return a tuple of (alpha, factorIndex, sigmaIndex) where (factorIndex, sigmaIndex) - * is the constraint that has minimum alpha, or (-1,-1) if alpha = 1. - * This constraint will be added to the working set and become active - * in the next iteration - */ - boost::tuple computeStepSize( - const LinearInequalityFactorGraph& workingSet, const VectorValues& xk, - const VectorValues& p) const; - - /** Iterate 1 step, return a new state with a new workingSet and values */ - QPState iterate(const QPState& state) const; - - /** - * Identify active constraints based on initial values. - */ - LinearInequalityFactorGraph identifyActiveConstraints( - const LinearInequalityFactorGraph& inequalities, - const VectorValues& initialValues) const; - - /** Optimize with a provided initial values - * For this version, it is the responsibility of the caller to provide - * a feasible initial value. - * @return a pair of solutions - */ - std::pair optimize( - const VectorValues& initialValues) const; - -}; - -} /* namespace gtsam */ +} \ No newline at end of file diff --git a/gtsam_unstable/linear/RawQP.cpp b/gtsam_unstable/linear/RawQP.cpp new file mode 100644 index 000000000..ec71cae5b --- /dev/null +++ b/gtsam_unstable/linear/RawQP.cpp @@ -0,0 +1,271 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file RawQP.cpp + * @brief + * @author Ivan Dario Jimenez + * @date 3/5/16 + */ + +#include +#include + +using boost::fusion::at_c; + +namespace gtsam { + +void RawQP::setName( + boost::fusion::vector, std::vector, + std::vector> const &name) { + name_ = std::string(at_c < 1 > (name).begin(), at_c < 1 > (name).end()); + if (debug) { + std::cout << "Parsing file: " << name_ << std::endl; + } +} + +void RawQP::addColumn( + boost::fusion::vector, std::vector, + std::vector, std::vector, std::vector, double, + std::vector> const &vars) { + + std::string var_(at_c < 1 > (vars).begin(), at_c < 1 > (vars).end()); + std::string row_(at_c < 3 > (vars).begin(), at_c < 3 > (vars).end()); + Matrix11 coefficient = at_c < 5 > (vars) * I_1x1; + + if (!varname_to_key.count(var_)) + varname_to_key[var_] = Symbol('X', varNumber++); + if (row_ == obj_name) { + g[varname_to_key[var_]] = coefficient; + return; + } + (*row_to_constraint_v[row_])[row_][varname_to_key[var_]] = coefficient; + if (debug) { + std::cout << "Added Column for Var: " << var_ << " Row: " << row_ + << " Coefficient: " << coefficient << std::endl; + } + +} + +void RawQP::addColumnDouble( + boost::fusion::vector, std::vector, + std::vector, std::vector, double, std::vector, + std::vector, std::vector, double> const &vars) { + + std::string var_(at_c < 0 > (vars).begin(), at_c < 0 > (vars).end()); + std::string row1_(at_c < 2 > (vars).begin(), at_c < 2 > (vars).end()); + std::string row2_(at_c < 6 > (vars).begin(), at_c < 6 > (vars).end()); + Matrix11 coefficient1 = at_c < 4 > (vars) * I_1x1; + Matrix11 coefficient2 = at_c < 8 > (vars) * I_1x1; + if (!varname_to_key.count(var_)) + varname_to_key.insert( { var_, Symbol('X', varNumber++) }); + if (row1_ == obj_name) + g[varname_to_key[var_]] = coefficient1; + else + (*row_to_constraint_v[row1_])[row1_][varname_to_key[var_]] = coefficient1; + if (row2_ == obj_name) + g[varname_to_key[var_]] = coefficient2; + else + (*row_to_constraint_v[row2_])[row2_][varname_to_key[var_]] = coefficient2; +} + +void RawQP::addRHS( + boost::fusion::vector, std::vector, + std::vector, std::vector, std::vector, double, + std::vector> const &vars) { + + std::string var_(at_c < 1 > (vars).begin(), at_c < 1 > (vars).end()); + std::string row_(at_c < 3 > (vars).begin(), at_c < 3 > (vars).end()); + double coefficient = at_c < 5 > (vars); + if (row_ == obj_name) + f = -coefficient; + else + b[row_] = coefficient; + + if (debug) { + std::cout << "Added RHS for Var: " << var_ << " Row: " << row_ + << " Coefficient: " << coefficient << std::endl; + } +} + +void RawQP::addRHSDouble( + boost::fusion::vector, std::vector, + std::vector, std::vector, std::vector, double, + std::vector, std::vector, std::vector, double> const &vars) { + + std::string var_(at_c < 1 > (vars).begin(), at_c < 1 > (vars).end()); + std::string row1_(at_c < 3 > (vars).begin(), at_c < 3 > (vars).end()); + std::string row2_(at_c < 7 > (vars).begin(), at_c < 7 > (vars).end()); + double coefficient1 = at_c < 5 > (vars); + double coefficient2 = at_c < 9 > (vars); + if (row1_ == obj_name) + f = -coefficient1; + else + b[row1_] = coefficient1; + + if (row2_ == obj_name) + f = -coefficient2; + else + b[row2_] = coefficient2; + + if (debug) { + std::cout << "Added RHS for Var: " << var_ << " Row: " << row1_ + << " Coefficient: " << coefficient1 << std::endl; + std::cout << " " << "Row: " << row2_ + << " Coefficient: " << coefficient2 << std::endl; + } +} + +void RawQP::addRow( + boost::fusion::vector, char, std::vector, + std::vector, std::vector> const &vars) { + + std::string name_(at_c < 3 > (vars).begin(), at_c < 3 > (vars).end()); + char type = at_c < 1 > (vars); + switch (type) { + case 'N': + obj_name = name_; + break; + case 'L': + row_to_constraint_v[name_] = &IL; + break; + case 'G': + row_to_constraint_v[name_] = &IG; + break; + case 'E': + row_to_constraint_v[name_] = &E; + break; + default: + std::cout << "invalid type: " << type << std::endl; + break; + } + if (debug) { + std::cout << "Added Row Type: " << type << " Name: " << name_ << std::endl; + } +} + +void RawQP::addBound( + boost::fusion::vector, std::vector, + std::vector, std::vector, std::vector, + std::vector, std::vector, double> const &vars) { + + std::string type_(at_c < 1 > (vars).begin(), at_c < 1 > (vars).end()); + std::string var_(at_c < 5 > (vars).begin(), at_c < 5 > (vars).end()); + double number = at_c < 7 > (vars); + if (type_.compare(std::string("UP")) == 0) + up[varname_to_key[var_]] = number; + else if (type_.compare(std::string("LO")) == 0) + lo[varname_to_key[var_]] = number; + else + std::cout << "Invalid Bound Type: " << type_ << std::endl; + + if (debug) { + std::cout << "Added Bound Type: " << type_ << " Var: " << var_ + << " Amount: " << number << std::endl; + } +} + +void RawQP::addBoundFr( + boost::fusion::vector, std::vector, + std::vector, std::vector, std::vector, + std::vector, std::vector> const &vars) { + std::string type_(at_c < 1 > (vars).begin(), at_c < 1 > (vars).end()); + std::string var_(at_c < 5 > (vars).begin(), at_c < 5 > (vars).end()); + Free.push_back(varname_to_key[var_]); + if (debug) { + std::cout << "Added Free Bound Type: " << type_ << " Var: " << var_ + << " Amount: " << std::endl; + } +} + +void RawQP::addQuadTerm( + boost::fusion::vector, std::vector, + std::vector, std::vector, std::vector, double, + std::vector> const &vars) { + std::string var1_(at_c < 1 > (vars).begin(), at_c < 1 > (vars).end()); + std::string var2_(at_c < 3 > (vars).begin(), at_c < 3 > (vars).end()); + Matrix11 coefficient = at_c < 5 > (vars) * I_1x1; + + H[varname_to_key[var1_]][varname_to_key[var2_]] = coefficient; + H[varname_to_key[var2_]][varname_to_key[var1_]] = coefficient; + if (debug) { + std::cout << "Added QuadTerm for Var: " << var1_ << " Row: " << var2_ + << " Coefficient: " << coefficient << std::endl; + } +} + +QP RawQP::makeQP() { + std::vector < Key > keys; + std::vector < Matrix > Gs; + std::vector < Vector > gs; + for (auto kv : varname_to_key) { + keys.push_back(kv.second); + } + std::sort(keys.begin(), keys.end()); + for (unsigned int i = 0; i < keys.size(); ++i) { + for (unsigned int j = i; j < keys.size(); ++j) { + Gs.push_back(H[keys[i]][keys[j]]); + } + } + for (Key key1 : keys) { + gs.push_back(-g[key1]); + } + int dual_key_num = keys.size() + 1; + QP madeQP; + auto obj = HessianFactor(keys, Gs, gs, f); + + madeQP.cost.push_back(obj); + + for (auto kv : E) { + std::map keyMatrixMap; + for (auto km : kv.second) { + keyMatrixMap.insert(km); + } + madeQP.equalities.push_back( + LinearEquality(keyMatrixMap, b[kv.first] * I_1x1, dual_key_num++)); + } + + for (auto kv : IG) { + std::map keyMatrixMap; + for (auto km : kv.second) { + km.second = -km.second; + keyMatrixMap.insert(km); + } + madeQP.inequalities.push_back( + LinearInequality(keyMatrixMap, -b[kv.first], dual_key_num++)); + } + + for (auto kv : IL) { + std::map keyMatrixMap; + for (auto km : kv.second) { + keyMatrixMap.insert(km); + } + madeQP.inequalities.push_back( + LinearInequality(keyMatrixMap, b[kv.first], dual_key_num++)); + } + + for (Key k : keys) { + if (std::find(Free.begin(), Free.end(), k) != Free.end()) + continue; + if (up.count(k) == 1) + madeQP.inequalities.push_back( + LinearInequality(k, I_1x1, up[k], dual_key_num++)); + if (lo.count(k) == 1) + madeQP.inequalities.push_back( + LinearInequality(k, -I_1x1, lo[k], dual_key_num++)); + else + madeQP.inequalities.push_back( + LinearInequality(k, -I_1x1, 0, dual_key_num++)); + } + return madeQP; +} +} + diff --git a/gtsam_unstable/linear/RawQP.h b/gtsam_unstable/linear/RawQP.h new file mode 100644 index 000000000..aadf11e50 --- /dev/null +++ b/gtsam_unstable/linear/RawQP.h @@ -0,0 +1,106 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file RawQP.h + * @brief + * @author Ivan Dario Jimenez + * @date 3/5/16 + */ + +#pragma once + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +namespace gtsam { +class RawQP { +private: + typedef std::unordered_map coefficient_v; + typedef std::unordered_map constraint_v; + + std::unordered_map row_to_constraint_v; + constraint_v E; + constraint_v IG; + constraint_v IL; + unsigned int varNumber; + std::unordered_map b; + std::unordered_map g; + std::unordered_map varname_to_key; + std::unordered_map > H; + double f; + std::string obj_name; + std::string name_; + std::unordered_map up; + std::unordered_map lo; + std::vector Free; + const bool debug = false; + +public: + RawQP() : + row_to_constraint_v(), E(), IG(), IL(), varNumber(1), b(), g(), varname_to_key(), H(), f(), obj_name(), name_(), up(), lo(), Free() { + } + + void setName( + boost::fusion::vector, std::vector, + std::vector> const & name); + + void addColumn( + boost::fusion::vector, std::vector, + std::vector, std::vector, std::vector, double, + std::vector> const & vars); + + void addColumnDouble( + boost::fusion::vector, std::vector, + std::vector, std::vector, double, std::vector, + std::vector, std::vector, double> const & vars); + + void addRHS( + boost::fusion::vector, std::vector, + std::vector, std::vector, std::vector, double, + std::vector> const & vars); + + void addRHSDouble( + boost::fusion::vector, std::vector, + std::vector, std::vector, std::vector, double, + std::vector, std::vector, std::vector, double> const & vars); + + void addRow( + boost::fusion::vector, char, std::vector, + std::vector, std::vector> const & vars); + + void addBound( + boost::fusion::vector, std::vector, + std::vector, std::vector, std::vector, + std::vector, std::vector, double> const & vars); + + void addBoundFr( + boost::fusion::vector, std::vector, + std::vector, std::vector, std::vector, + std::vector, std::vector> const & vars); + + void addQuadTerm( + boost::fusion::vector, std::vector, + std::vector, std::vector, std::vector, double, + std::vector> const & vars); + + QP makeQP(); +} +; +} diff --git a/gtsam_unstable/linear/tests/testLPSolver.cpp b/gtsam_unstable/linear/tests/testLPSolver.cpp new file mode 100644 index 000000000..8bf6be56b --- /dev/null +++ b/gtsam_unstable/linear/tests/testLPSolver.cpp @@ -0,0 +1,255 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file testQPSolver.cpp + * @brief Test simple QP solver for a linear inequality constraint + * @date Apr 10, 2014 + * @author Duy-Nguyen Ta + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +using namespace std; +using namespace gtsam; +using namespace gtsam::symbol_shorthand; + +static const Vector kOne = Vector::Ones(1), kZero = Vector::Zero(1); + +/* ************************************************************************* */ +/** + * min -x1-x2 + * s.t. x1 + 2x2 <= 4 + * 4x1 + 2x2 <= 12 + * -x1 + x2 <= 1 + * x1, x2 >= 0 + */ +LP simpleLP1() { + LP lp; + lp.cost = LinearCost(1, Vector2(-1., -1.)); // min -x1-x2 (max x1+x2) + lp.inequalities.push_back( + LinearInequality(1, Vector2(-1, 0), 0, 1)); // x1 >= 0 + lp.inequalities.push_back( + LinearInequality(1, Vector2(0, -1), 0, 2)); // x2 >= 0 + lp.inequalities.push_back( + LinearInequality(1, Vector2(1, 2), 4, 3)); // x1 + 2*x2 <= 4 + lp.inequalities.push_back( + LinearInequality(1, Vector2(4, 2), 12, 4)); // 4x1 + 2x2 <= 12 + lp.inequalities.push_back( + LinearInequality(1, Vector2(-1, 1), 1, 5)); // -x1 + x2 <= 1 + return lp; +} + +/* ************************************************************************* */ +namespace gtsam { + +TEST(LPInitSolver, infinite_loop_single_var) { + LP initchecker; + initchecker.cost = LinearCost(1, Vector3(0, 0, 1)); // min alpha + initchecker.inequalities.push_back( + LinearInequality(1, Vector3(-2, -1, -1), -2, 1)); //-2x-y-alpha <= -2 + initchecker.inequalities.push_back( + LinearInequality(1, Vector3(-1, 2, -1), 6, 2)); // -x+2y-alpha <= 6 + initchecker.inequalities.push_back( + LinearInequality(1, Vector3(-1, 0, -1), 0, 3)); // -x - alpha <= 0 + initchecker.inequalities.push_back( + LinearInequality(1, Vector3(1, 0, -1), 20, 4)); // x - alpha <= 20 + initchecker.inequalities.push_back( + LinearInequality(1, Vector3(0, -1, -1), 0, 5)); // -y - alpha <= 0 + LPSolver solver(initchecker); + VectorValues starter; + starter.insert(1, Vector3(0, 0, 2)); + VectorValues results, duals; + boost::tie(results, duals) = solver.optimize(starter); + VectorValues expected; + expected.insert(1, Vector3(13.5, 6.5, -6.5)); + CHECK(assert_equal(results, expected, 1e-7)); +} + +TEST(LPInitSolver, infinite_loop_multi_var) { + LP initchecker; + Key X = symbol('X', 1); + Key Y = symbol('Y', 1); + Key Z = symbol('Z', 1); + initchecker.cost = LinearCost(Z, kOne); // min alpha + initchecker.inequalities.push_back( + LinearInequality(X, -2.0 * kOne, Y, -1.0 * kOne, Z, -1.0 * kOne, -2, + 1)); //-2x-y-alpha <= -2 + initchecker.inequalities.push_back( + LinearInequality(X, -1.0 * kOne, Y, 2.0 * kOne, Z, -1.0 * kOne, 6, + 2)); // -x+2y-alpha <= 6 + initchecker.inequalities.push_back(LinearInequality( + X, -1.0 * kOne, Z, -1.0 * kOne, 0, 3)); // -x - alpha <= 0 + initchecker.inequalities.push_back(LinearInequality( + X, 1.0 * kOne, Z, -1.0 * kOne, 20, 4)); // x - alpha <= 20 + initchecker.inequalities.push_back(LinearInequality( + Y, -1.0 * kOne, Z, -1.0 * kOne, 0, 5)); // -y - alpha <= 0 + LPSolver solver(initchecker); + VectorValues starter; + starter.insert(X, kZero); + starter.insert(Y, kZero); + starter.insert(Z, Vector::Constant(1, 2.0)); + VectorValues results, duals; + boost::tie(results, duals) = solver.optimize(starter); + VectorValues expected; + expected.insert(X, Vector::Constant(1, 13.5)); + expected.insert(Y, Vector::Constant(1, 6.5)); + expected.insert(Z, Vector::Constant(1, -6.5)); + CHECK(assert_equal(results, expected, 1e-7)); +} + +TEST(LPInitSolver, initialization) { + LP lp = simpleLP1(); + LPInitSolver initSolver(lp); + + GaussianFactorGraph::shared_ptr initOfInitGraph = + initSolver.buildInitOfInitGraph(); + VectorValues x0 = initOfInitGraph->optimize(); + VectorValues expected_x0; + expected_x0.insert(1, Vector::Zero(2)); + CHECK(assert_equal(expected_x0, x0, 1e-10)); + + double y0 = initSolver.compute_y0(x0); + double expected_y0 = 0.0; + DOUBLES_EQUAL(expected_y0, y0, 1e-7); + + Key yKey = 2; + LP::shared_ptr initLP = initSolver.buildInitialLP(yKey); + LP expectedInitLP; + expectedInitLP.cost = LinearCost(yKey, kOne); + expectedInitLP.inequalities.push_back(LinearInequality( + 1, Vector2(-1, 0), 2, Vector::Constant(1, -1), 0, 1)); // -x1 - y <= 0 + expectedInitLP.inequalities.push_back(LinearInequality( + 1, Vector2(0, -1), 2, Vector::Constant(1, -1), 0, 2)); // -x2 - y <= 0 + expectedInitLP.inequalities.push_back( + LinearInequality(1, Vector2(1, 2), 2, Vector::Constant(1, -1), 4, + 3)); // x1 + 2*x2 - y <= 4 + expectedInitLP.inequalities.push_back( + LinearInequality(1, Vector2(4, 2), 2, Vector::Constant(1, -1), 12, + 4)); // 4x1 + 2x2 - y <= 12 + expectedInitLP.inequalities.push_back( + LinearInequality(1, Vector2(-1, 1), 2, Vector::Constant(1, -1), 1, + 5)); // -x1 + x2 - y <= 1 + CHECK(assert_equal(expectedInitLP, *initLP, 1e-10)); + LPSolver lpSolveInit(*initLP); + VectorValues xy0(x0); + xy0.insert(yKey, Vector::Constant(1, y0)); + VectorValues xyInit = lpSolveInit.optimize(xy0).first; + VectorValues expected_init; + expected_init.insert(1, Vector::Ones(2)); + expected_init.insert(2, Vector::Constant(1, -1)); + CHECK(assert_equal(expected_init, xyInit, 1e-10)); + + VectorValues x = initSolver.solve(); + CHECK(lp.isFeasible(x)); +} +} + +/* ************************************************************************* */ +/** + * TEST gtsam solver with an over-constrained system + * x + y = 1 + * x - y = 5 + * x + 2y = 6 + */ +TEST(LPSolver, overConstrainedLinearSystem) { + GaussianFactorGraph graph; + Matrix A1 = Vector3(1, 1, 1); + Matrix A2 = Vector3(1, -1, 2); + Vector b = Vector3(1, 5, 6); + JacobianFactor factor(1, A1, 2, A2, b, noiseModel::Constrained::All(3)); + graph.push_back(factor); + + VectorValues x = graph.optimize(); + // This check confirms that gtsam linear constraint solver can't handle + // over-constrained system + CHECK(factor.error(x) != 0.0); +} + +TEST(LPSolver, overConstrainedLinearSystem2) { + GaussianFactorGraph graph; + graph.push_back(JacobianFactor(1, I_1x1, 2, I_1x1, kOne, + noiseModel::Constrained::All(1))); + graph.push_back(JacobianFactor(1, I_1x1, 2, -I_1x1, 5 * kOne, + noiseModel::Constrained::All(1))); + graph.push_back(JacobianFactor(1, I_1x1, 2, 2 * I_1x1, 6 * kOne, + noiseModel::Constrained::All(1))); + VectorValues x = graph.optimize(); + // This check confirms that gtsam linear constraint solver can't handle + // over-constrained system + CHECK(graph.error(x) != 0.0); +} + +/* ************************************************************************* */ +TEST(LPSolver, simpleTest1) { + LP lp = simpleLP1(); + LPSolver lpSolver(lp); + VectorValues init; + init.insert(1, Vector::Zero(2)); + + VectorValues x1 = + lpSolver.buildWorkingGraph(InequalityFactorGraph(), init).optimize(); + VectorValues expected_x1; + expected_x1.insert(1, Vector::Ones(2)); + CHECK(assert_equal(expected_x1, x1, 1e-10)); + + VectorValues result, duals; + boost::tie(result, duals) = lpSolver.optimize(init); + VectorValues expectedResult; + expectedResult.insert(1, Vector2(8. / 3., 2. / 3.)); + CHECK(assert_equal(expectedResult, result, 1e-10)); +} + +/* ************************************************************************* */ +TEST(LPSolver, testWithoutInitialValues) { + LP lp = simpleLP1(); + LPSolver lpSolver(lp); + VectorValues result, duals, expectedResult; + expectedResult.insert(1, Vector2(8. / 3., 2. / 3.)); + boost::tie(result, duals) = lpSolver.optimize(); + CHECK(assert_equal(expectedResult, result)); +} + +/** + * TODO: More TEST cases: + * - Infeasible + * - Unbounded + * - Underdetermined + */ +/* ************************************************************************* */ +TEST(LPSolver, LinearCost) { + LinearCost cost(1, Vector3(2., 4., 6.)); + VectorValues x; + x.insert(1, Vector3(1., 3., 5.)); + double error = cost.error(x); + double expectedError = 44.0; + DOUBLES_EQUAL(expectedError, error, 1e-100); +} + +/* ************************************************************************* */ +int main() { + TestResult tr; + return TestRegistry::runAllTests(tr); +} +/* ************************************************************************* */ diff --git a/gtsam_unstable/linear/tests/testLinearEquality.cpp b/gtsam_unstable/linear/tests/testLinearEquality.cpp index 90f3de586..fa94dd255 100644 --- a/gtsam_unstable/linear/tests/testLinearEquality.cpp +++ b/gtsam_unstable/linear/tests/testLinearEquality.cpp @@ -12,7 +12,7 @@ /** * @file testLinearEquality.cpp * @brief Unit tests for LinearEquality - * @author thduynguyen + * @author Duy-Nguyen Ta **/ #include @@ -28,20 +28,20 @@ using namespace std; using namespace gtsam; using namespace boost::assign; -GTSAM_CONCEPT_TESTABLE_INST(LinearEquality) +GTSAM_CONCEPT_TESTABLE_INST (LinearEquality) namespace { - namespace simple { - // Terms we'll use - const vector > terms = list_of > - (make_pair(5, Matrix3::Identity())) - (make_pair(10, 2*Matrix3::Identity())) - (make_pair(15, 3*Matrix3::Identity())); +namespace simple { +// Terms we'll use +const vector > terms = list_of < pair + > (make_pair(5, Matrix3::Identity()))( + make_pair(10, 2 * Matrix3::Identity()))( + make_pair(15, 3 * Matrix3::Identity())); - // RHS and sigmas - const Vector b = (Vector(3) << 1., 2., 3.).finished(); - const SharedDiagonal noise = noiseModel::Constrained::All(3); - } +// RHS and sigmas +const Vector b = (Vector(3) << 1., 2., 3.).finished(); +const SharedDiagonal noise = noiseModel::Constrained::All(3); +} } /* ************************************************************************* */ @@ -53,7 +53,7 @@ TEST(LinearEquality, constructors_and_accessors) { // One term constructor LinearEquality expected( - boost::make_iterator_range(terms.begin(), terms.begin() + 1), b, 0); + boost::make_iterator_range(terms.begin(), terms.begin() + 1), b, 0); LinearEquality actual(terms[0].first, terms[0].second, b, 0); EXPECT(assert_equal(expected, actual)); LONGS_EQUAL((long)terms[0].first, (long)actual.keys().back()); @@ -65,9 +65,9 @@ TEST(LinearEquality, constructors_and_accessors) { // Two term constructor LinearEquality expected( - boost::make_iterator_range(terms.begin(), terms.begin() + 2), b, 0); + boost::make_iterator_range(terms.begin(), terms.begin() + 2), b, 0); LinearEquality actual(terms[0].first, terms[0].second, - terms[1].first, terms[1].second, b, 0); + terms[1].first, terms[1].second, b, 0); EXPECT(assert_equal(expected, actual)); LONGS_EQUAL((long)terms[1].first, (long)actual.keys().back()); EXPECT(assert_equal(terms[1].second, actual.getA(actual.end() - 1))); @@ -78,9 +78,9 @@ TEST(LinearEquality, constructors_and_accessors) { // Three term constructor LinearEquality expected( - boost::make_iterator_range(terms.begin(), terms.begin() + 3), b, 0); + boost::make_iterator_range(terms.begin(), terms.begin() + 3), b, 0); LinearEquality actual(terms[0].first, terms[0].second, - terms[1].first, terms[1].second, terms[2].first, terms[2].second, b, 0); + terms[1].first, terms[1].second, terms[2].first, terms[2].second, b, 0); EXPECT(assert_equal(expected, actual)); LONGS_EQUAL((long)terms[2].first, (long)actual.keys().back()); EXPECT(assert_equal(terms[2].second, actual.getA(actual.end() - 1))); @@ -93,10 +93,10 @@ TEST(LinearEquality, constructors_and_accessors) /* ************************************************************************* */ TEST(LinearEquality, Hessian_conversion) { HessianFactor hessian(0, (Matrix(4,4) << - 1.57, 2.695, -1.1, -2.35, - 2.695, 11.3125, -0.65, -10.225, - -1.1, -0.65, 1, 0.5, - -2.35, -10.225, 0.5, 9.25).finished(), + 1.57, 2.695, -1.1, -2.35, + 2.695, 11.3125, -0.65, -10.225, + -1.1, -0.65, 1, 0.5, + -2.35, -10.225, 0.5, 9.25).finished(), (Vector(4) << -7.885, -28.5175, 2.75, 25.675).finished(), 73.1725); @@ -169,8 +169,8 @@ TEST(LinearEquality, matrices) augmentedJacobianExpected << jacobianExpected, rhsExpected; Matrix augmentedHessianExpected = - augmentedJacobianExpected.transpose() * simple::noise->R().transpose() - * simple::noise->R() * augmentedJacobianExpected; + augmentedJacobianExpected.transpose() * simple::noise->R().transpose() + * simple::noise->R() * augmentedJacobianExpected; // Whitened Jacobian EXPECT(assert_equal(jacobianExpected, factor.jacobian().first)); @@ -210,8 +210,8 @@ TEST(LinearEquality, operators ) // test gradient at zero Matrix A; Vector b2; boost::tie(A,b2) = lf.jacobian(); VectorValues expectedG; - expectedG.insert(1, (Vector(2) << 0.2, -0.1).finished()); - expectedG.insert(2, (Vector(2) << -0.2, 0.1).finished()); + expectedG.insert(1, (Vector(2) << 0.2, -0.1).finished()); + expectedG.insert(2, (Vector(2) << -0.2, 0.1).finished()); VectorValues actualG = lf.gradientAtZero(); EXPECT(assert_equal(expectedG, actualG)); } @@ -233,5 +233,8 @@ TEST(LinearEquality, empty ) } /* ************************************************************************* */ -int main() { TestResult tr; return TestRegistry::runAllTests(tr);} +int main() { + TestResult tr; + return TestRegistry::runAllTests(tr); +} /* ************************************************************************* */ diff --git a/gtsam_unstable/linear/tests/testQPSolver.cpp b/gtsam_unstable/linear/tests/testQPSolver.cpp index 7442540f5..bc9dd1f98 100644 --- a/gtsam_unstable/linear/tests/testQPSolver.cpp +++ b/gtsam_unstable/linear/tests/testQPSolver.cpp @@ -19,14 +19,14 @@ #include #include #include - +#include #include using namespace std; using namespace gtsam; using namespace gtsam::symbol_shorthand; -const Matrix One = I_1x1; +static const Vector kOne = Vector::Ones(1), kZero = Vector::Zero(1); /* ************************************************************************* */ // Create test graph according to Forst10book_pg171Ex5 @@ -37,15 +37,17 @@ QP createTestCase() { // Note the Hessian encodes: // 0.5*x1'*G11*x1 + x1'*G12*x2 + 0.5*x2'*G22*x2 - x1'*g1 - x2'*g2 + 0.5*f // Hence, we have G11=2, G12 = -1, g1 = +3, G22 = 2, g2 = 0, f = 10 + //TODO: THIS TEST MIGHT BE WRONG : the last parameter might be 5 instead of 10 because the form of the equation + // Should be 0.5x'Gx + gx + f : Nocedal 449 qp.cost.push_back( - HessianFactor(X(1), X(2), 2.0 * Matrix::Ones(1, 1), -Matrix::Ones(1, 1), 3.0 * I_1x1, - 2.0 * Matrix::Ones(1, 1), Z_1x1, 10.0)); + HessianFactor(X(1), X(2), 2.0 * I_1x1, -I_1x1, 3.0 * I_1x1, 2.0 * I_1x1, + Z_1x1, 10.0)); // Inequality constraints qp.inequalities.push_back(LinearInequality(X(1), I_1x1, X(2), I_1x1, 2, 0)); // x1 + x2 <= 2 --> x1 + x2 -2 <= 0, --> b=2 - qp.inequalities.push_back(LinearInequality(X(1), -I_1x1, 0, 1)); // -x1 <= 0 - qp.inequalities.push_back(LinearInequality(X(2), -I_1x1, 0, 2)); // -x2 <= 0 - qp.inequalities.push_back(LinearInequality(X(1), I_1x1, 1.5, 3)); // x1 <= 3/2 + qp.inequalities.push_back(LinearInequality(X(1), -I_1x1, 0, 1)); // -x1 <= 0 + qp.inequalities.push_back(LinearInequality(X(2), -I_1x1, 0, 2)); // -x2 <= 0 + qp.inequalities.push_back(LinearInequality(X(1), I_1x1, 1.5, 3)); // x1 <= 3/2 return qp; } @@ -53,8 +55,8 @@ QP createTestCase() { TEST(QPSolver, TestCase) { VectorValues values; double x1 = 5, x2 = 7; - values.insert(X(1), x1 * Matrix::Ones(1, 1)); - values.insert(X(2), x2 * Matrix::Ones(1, 1)); + values.insert(X(1), x1 * I_1x1); + values.insert(X(2), x2 * I_1x1); QP qp = createTestCase(); DOUBLES_EQUAL(29, x1 * x1 - x1 * x2 + x2 * x2 - 3 * x1 + 5, 1e-9); DOUBLES_EQUAL(29, qp.cost[0]->error(values), 1e-9); @@ -67,15 +69,15 @@ TEST(QPSolver, constraintsAux) { VectorValues lambdas; lambdas.insert(0, (Vector(1) << -0.5).finished()); - lambdas.insert(1, (Vector(1) << 0.0).finished()); - lambdas.insert(2, (Vector(1) << 0.3).finished()); - lambdas.insert(3, (Vector(1) << 0.1).finished()); + lambdas.insert(1, kZero); + lambdas.insert(2, (Vector(1) << 0.3).finished()); + lambdas.insert(3, (Vector(1) << 0.1).finished()); int factorIx = solver.identifyLeavingConstraint(qp.inequalities, lambdas); LONGS_EQUAL(2, factorIx); VectorValues lambdas2; lambdas2.insert(0, (Vector(1) << -0.5).finished()); - lambdas2.insert(1, (Vector(1) << 0.0).finished()); + lambdas2.insert(1, kZero); lambdas2.insert(2, (Vector(1) << -0.3).finished()); lambdas2.insert(3, (Vector(1) << -0.1).finished()); int factorIx2 = solver.identifyLeavingConstraint(qp.inequalities, lambdas2); @@ -92,14 +94,14 @@ QP createEqualityConstrainedTest() { // 0.5*x1'*G11*x1 + x1'*G12*x2 + 0.5*x2'*G22*x2 - x1'*g1 - x2'*g2 + 0.5*f // Hence, we have G11=2, G12 = 0, g1 = 0, G22 = 2, g2 = 0, f = 0 qp.cost.push_back( - HessianFactor(X(1), X(2), 2.0 * Matrix::Ones(1, 1), Z_1x1, Z_1x1, - 2.0 * Matrix::Ones(1, 1), Z_1x1, 0.0)); + HessianFactor(X(1), X(2), 2.0 * I_1x1, Z_1x1, Z_1x1, 2.0 * I_1x1, Z_1x1, + 0.0)); // Equality constraints // x1 + x2 = 1 --> x1 + x2 -1 = 0, hence we negate the b vector - Matrix A1 = (Matrix(1, 1) << 1).finished(); - Matrix A2 = (Matrix(1, 1) << 1).finished(); - Vector b = -(Vector(1) << 1).finished(); + Matrix A1 = I_1x1; + Matrix A2 = I_1x1; + Vector b = -kOne; qp.equalities.push_back(LinearEquality(X(1), A1, X(2), A2, b, 0)); return qp; @@ -132,20 +134,19 @@ TEST(QPSolver, indentifyActiveConstraints) { currentSolution.insert(X(1), Z_1x1); currentSolution.insert(X(2), Z_1x1); - LinearInequalityFactorGraph workingSet = - solver.identifyActiveConstraints(qp.inequalities, currentSolution); + InequalityFactorGraph workingSet = solver.identifyActiveConstraints( + qp.inequalities, currentSolution); - CHECK(!workingSet.at(0)->active()); // inactive - CHECK(workingSet.at(1)->active()); // active - CHECK(workingSet.at(2)->active()); // active - CHECK(!workingSet.at(3)->active()); // inactive + CHECK(!workingSet.at(0)->active()); // inactive + CHECK(workingSet.at(1)->active());// active + CHECK(workingSet.at(2)->active());// active + CHECK(!workingSet.at(3)->active());// inactive - VectorValues solution = solver.solveWithCurrentWorkingSet(workingSet); + VectorValues solution = solver.buildWorkingGraph(workingSet).optimize(); VectorValues expectedSolution; - expectedSolution.insert(X(1), (Vector(1) << 0.0).finished()); - expectedSolution.insert(X(2), (Vector(1) << 0.0).finished()); + expectedSolution.insert(X(1), kZero); + expectedSolution.insert(X(2), kZero); CHECK(assert_equal(expectedSolution, solution, 1e-100)); - } /* ************************************************************************* */ @@ -158,13 +159,13 @@ TEST(QPSolver, iterate) { currentSolution.insert(X(2), Z_1x1); std::vector expectedSolutions(4), expectedDuals(4); - expectedSolutions[0].insert(X(1), (Vector(1) << 0.0).finished()); - expectedSolutions[0].insert(X(2), (Vector(1) << 0.0).finished()); + expectedSolutions[0].insert(X(1), kZero); + expectedSolutions[0].insert(X(2), kZero); expectedDuals[0].insert(1, (Vector(1) << 3).finished()); - expectedDuals[0].insert(2, (Vector(1) << 0).finished()); + expectedDuals[0].insert(2, kZero); expectedSolutions[1].insert(X(1), (Vector(1) << 1.5).finished()); - expectedSolutions[1].insert(X(2), (Vector(1) << 0.0).finished()); + expectedSolutions[1].insert(X(2), kZero); expectedDuals[1].insert(3, (Vector(1) << 1.5).finished()); expectedSolutions[2].insert(X(1), (Vector(1) << 1.5).finished()); @@ -173,10 +174,11 @@ TEST(QPSolver, iterate) { expectedSolutions[3].insert(X(1), (Vector(1) << 1.5).finished()); expectedSolutions[3].insert(X(2), (Vector(1) << 0.5).finished()); - LinearInequalityFactorGraph workingSet = - solver.identifyActiveConstraints(qp.inequalities, currentSolution); + InequalityFactorGraph workingSet = solver.identifyActiveConstraints( + qp.inequalities, currentSolution); - QPState state(currentSolution, VectorValues(), workingSet, false); + QPSolver::State state(currentSolution, VectorValues(), workingSet, false, + 100); int it = 0; while (!state.converged) { @@ -209,6 +211,64 @@ TEST(QPSolver, optimizeForst10book_pg171Ex5) { CHECK(assert_equal(expectedSolution, solution, 1e-100)); } +pair testParser(QPSParser parser) { + QP exampleqp = parser.Parse(); + QP expectedqp; + Key X1(Symbol('X', 1)), X2(Symbol('X', 2)); + // min f(x,y) = 4 + 1.5x -y + 0.58x^2 + 2xy + 2yx + 10y^2 + expectedqp.cost.push_back( + HessianFactor(X1, X2, 8.0 * I_1x1, 2.0 * I_1x1, -1.5 * kOne, 10.0 * I_1x1, + 2.0 * kOne, 4.0)); + // 2x + y >= 2 + // -x + 2y <= 6 + expectedqp.inequalities.push_back( + LinearInequality(X1, -2.0 * I_1x1, X2, -I_1x1, -2, 0)); + expectedqp.inequalities.push_back( + LinearInequality(X1, -I_1x1, X2, 2.0 * I_1x1, 6, 1)); + // x<= 20 + expectedqp.inequalities.push_back(LinearInequality(X1, I_1x1, 20, 4)); + //x >= 0 + expectedqp.inequalities.push_back(LinearInequality(X1, -I_1x1, 0, 2)); + // y > = 0 + expectedqp.inequalities.push_back(LinearInequality(X2, -I_1x1, 0, 3)); + return std::make_pair(expectedqp, exampleqp); +} +; + +TEST(QPSolver, ParserSyntaticTest) { + auto expectedActual = testParser(QPSParser("QPExample.QPS")); + CHECK(assert_equal(expectedActual.first.cost, expectedActual.second.cost, + 1e-7)); + CHECK(assert_equal(expectedActual.first.inequalities, + expectedActual.second.inequalities, 1e-7)); + CHECK(assert_equal(expectedActual.first.equalities, + expectedActual.second.equalities, 1e-7)); +} + +TEST(QPSolver, ParserSemanticTest) { + auto expected_actual = testParser(QPSParser("QPExample.QPS")); + VectorValues actualSolution, expectedSolution; + boost::tie(expectedSolution, boost::tuples::ignore) = + QPSolver(expected_actual.first).optimize(); + boost::tie(actualSolution, boost::tuples::ignore) = + QPSolver(expected_actual.second).optimize(); + CHECK(assert_equal(actualSolution, expectedSolution, 1e-7)); +} + +TEST(QPSolver, QPExampleTest){ + QP problem = QPSParser("QPExample.QPS").Parse(); + VectorValues actualSolution; + auto solver = QPSolver(problem); + boost::tie(actualSolution, boost::tuples::ignore) = solver.optimize(); + VectorValues expectedSolution; + expectedSolution.insert(Symbol('X',1),0.7625*I_1x1); + expectedSolution.insert(Symbol('X',2),0.4750*I_1x1); + double error_expected = problem.cost.error(expectedSolution); + double error_actual = problem.cost.error(actualSolution); + CHECK(assert_equal(expectedSolution, actualSolution, 1e-7)) + CHECK(assert_equal(error_expected, error_actual)) +} + /* ************************************************************************* */ // Create Matlab's test graph as in http://www.mathworks.com/help/optim/ug/quadprog.html QP createTestMatlabQPEx() { @@ -219,19 +279,22 @@ QP createTestMatlabQPEx() { // 0.5*x1'*G11*x1 + x1'*G12*x2 + 0.5*x2'*G22*x2 - x1'*g1 - x2'*g2 + 0.5*f // Hence, we have G11=1, G12 = -1, g1 = +2, G22 = 2, g2 = +6, f = 0 qp.cost.push_back( - HessianFactor(X(1), X(2), 1.0 * I_1x1, -Matrix::Ones(1, 1), 2.0 * I_1x1, - 2.0 * Matrix::Ones(1, 1), 6 * I_1x1, 1000.0)); + HessianFactor(X(1), X(2), 1.0 * I_1x1, -I_1x1, 2.0 * I_1x1, 2.0 * I_1x1, + 6 * I_1x1, 1000.0)); // Inequality constraints - qp.inequalities.push_back(LinearInequality(X(1), One, X(2), One, 2, 0)); // x1 + x2 <= 2 - qp.inequalities.push_back(LinearInequality(X(1), -One, X(2), 2*One, 2, 1)); //-x1 + 2*x2 <=2 - qp.inequalities.push_back(LinearInequality(X(1), 2*One, X(2), One, 3, 2)); // 2*x1 + x2 <=3 - qp.inequalities.push_back(LinearInequality(X(1), -One, 0, 3)); // -x1 <= 0 - qp.inequalities.push_back(LinearInequality(X(2), -One, 0, 4)); // -x2 <= 0 + qp.inequalities.push_back(LinearInequality(X(1), I_1x1, X(2), I_1x1, 2, 0)); // x1 + x2 <= 2 + qp.inequalities.push_back( + LinearInequality(X(1), -I_1x1, X(2), 2 * I_1x1, 2, 1)); //-x1 + 2*x2 <=2 + qp.inequalities.push_back( + LinearInequality(X(1), 2 * I_1x1, X(2), I_1x1, 3, 2)); // 2*x1 + x2 <=3 + qp.inequalities.push_back(LinearInequality(X(1), -I_1x1, 0, 3)); // -x1 <= 0 + qp.inequalities.push_back(LinearInequality(X(2), -I_1x1, 0, 4)); // -x2 <= 0 return qp; } +///* ************************************************************************* */ TEST(QPSolver, optimizeMatlabEx) { QP qp = createTestMatlabQPEx(); QPSolver solver(qp); @@ -246,20 +309,35 @@ TEST(QPSolver, optimizeMatlabEx) { CHECK(assert_equal(expectedSolution, solution, 1e-7)); } +///* ************************************************************************* */ +TEST(QPSolver, optimizeMatlabExNoinitials) { + QP qp = createTestMatlabQPEx(); + QPSolver solver(qp); + VectorValues solution; + boost::tie(solution, boost::tuples::ignore) = solver.optimize(); + VectorValues expectedSolution; + expectedSolution.insert(X(1), (Vector(1) << 2.0 / 3.0).finished()); + expectedSolution.insert(X(2), (Vector(1) << 4.0 / 3.0).finished()); + CHECK(assert_equal(expectedSolution, solution, 1e-7)); +} + /* ************************************************************************* */ // Create test graph as in Nocedal06book, Ex 16.4, pg. 475 QP createTestNocedal06bookEx16_4() { QP qp; - qp.cost.push_back(JacobianFactor(X(1), Matrix::Ones(1, 1), I_1x1)); - qp.cost.push_back(JacobianFactor(X(2), Matrix::Ones(1, 1), 2.5 * I_1x1)); + qp.cost.push_back(JacobianFactor(X(1), I_1x1, I_1x1)); + qp.cost.push_back(JacobianFactor(X(2), I_1x1, 2.5 * I_1x1)); // Inequality constraints - qp.inequalities.push_back(LinearInequality(X(1), -One, X(2), 2 * One, 2, 0)); - qp.inequalities.push_back(LinearInequality(X(1), One, X(2), 2 * One, 6, 1)); - qp.inequalities.push_back(LinearInequality(X(1), One, X(2), -2 * One, 2, 2)); - qp.inequalities.push_back(LinearInequality(X(1), -One, 0.0, 3)); - qp.inequalities.push_back(LinearInequality(X(2), -One, 0.0, 4)); + qp.inequalities.push_back( + LinearInequality(X(1), -I_1x1, X(2), 2 * I_1x1, 2, 0)); + qp.inequalities.push_back( + LinearInequality(X(1), I_1x1, X(2), 2 * I_1x1, 6, 1)); + qp.inequalities.push_back( + LinearInequality(X(1), I_1x1, X(2), -2 * I_1x1, 2, 2)); + qp.inequalities.push_back(LinearInequality(X(1), -I_1x1, 0.0, 3)); + qp.inequalities.push_back(LinearInequality(X(2), -I_1x1, 0.0, 4)); return qp; } @@ -280,28 +358,45 @@ TEST(QPSolver, optimizeNocedal06bookEx16_4) { } /* ************************************************************************* */ - TEST(QPSolver, failedSubproblem) { QP qp; qp.cost.push_back(JacobianFactor(X(1), I_2x2, Z_2x1)); qp.cost.push_back(HessianFactor(X(1), Z_2x2, Z_2x1, 100.0)); qp.inequalities.push_back( - LinearInequality(X(1), (Matrix(1,2) << -1.0, 0.0).finished(), -1.0, 0)); + LinearInequality(X(1), (Matrix(1, 2) << -1.0, 0.0).finished(), -1.0, 0)); VectorValues expected; expected.insert(X(1), (Vector(2) << 1.0, 0.0).finished()); VectorValues initialValues; - initialValues.insert(X(1), (Vector(2) << 10.0, 100.0).finished()); + initialValues.insert(X(1), (Vector(2) << 10.0, 100.0).finished()); QPSolver solver(qp); VectorValues solution; boost::tie(solution, boost::tuples::ignore) = solver.optimize(initialValues); -// graph.print("Graph: "); -// solution.print("Solution: "); + CHECK(assert_equal(expected, solution, 1e-7)); } +/* ************************************************************************* */ +TEST(QPSolver, infeasibleInitial) { + QP qp; + qp.cost.push_back(JacobianFactor(X(1), I_2x2, Vector::Zero(2))); + qp.cost.push_back(HessianFactor(X(1), Z_2x2, Vector::Zero(2), 100.0)); + qp.inequalities.push_back( + LinearInequality(X(1), (Matrix(1, 2) << -1.0, 0.0).finished(), -1.0, 0)); + + VectorValues expected; + expected.insert(X(1), (Vector(2) << 1.0, 0.0).finished()); + + VectorValues initialValues; + initialValues.insert(X(1), (Vector(2) << -10.0, 100.0).finished()); + + QPSolver solver(qp); + VectorValues solution; + CHECK_EXCEPTION(solver.optimize(initialValues), InfeasibleInitialValues); +} + /* ************************************************************************* */ int main() { TestResult tr; diff --git a/gtsam_unstable/nonlinear/BatchFixedLagSmoother.cpp b/gtsam_unstable/nonlinear/BatchFixedLagSmoother.cpp index 405321ffc..a0ede5f74 100644 --- a/gtsam_unstable/nonlinear/BatchFixedLagSmoother.cpp +++ b/gtsam_unstable/nonlinear/BatchFixedLagSmoother.cpp @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- - * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) @@ -22,13 +22,13 @@ #include #include #include -//#include -#include + +using namespace std; namespace gtsam { /* ************************************************************************* */ -void BatchFixedLagSmoother::print(const std::string& s, +void BatchFixedLagSmoother::print(const string& s, const KeyFormatter& keyFormatter) const { FixedLagSmoother::print(s, keyFormatter); // TODO: What else to print? @@ -45,7 +45,7 @@ bool BatchFixedLagSmoother::equals(const FixedLagSmoother& rhs, /* ************************************************************************* */ Matrix BatchFixedLagSmoother::marginalCovariance(Key key) const { - throw std::runtime_error( + throw runtime_error( "BatchFixedLagSmoother::marginalCovariance not implemented"); } @@ -54,17 +54,12 @@ FixedLagSmoother::Result BatchFixedLagSmoother::update( const NonlinearFactorGraph& newFactors, const Values& newTheta, const KeyTimestampMap& timestamps) { - const bool debug = ISDEBUG("BatchFixedLagSmoother update"); - if (debug) { - std::cout << "BatchFixedLagSmoother::update() START" << std::endl; - } - // Update all of the internal variables with the new information gttic(augment_system); // Add the new variables to theta theta_.insert(newTheta); // Add new variables to the end of the ordering - for(const Values::ConstKeyValuePair& key_value: newTheta) { + for (const auto& key_value : newTheta) { ordering_.push_back(key_value.key); } // Augment Delta @@ -79,19 +74,10 @@ FixedLagSmoother::Result BatchFixedLagSmoother::update( // Get current timestamp double current_timestamp = getCurrentTimestamp(); - if (debug) - std::cout << "Current Timestamp: " << current_timestamp << std::endl; // Find the set of variables to be marginalized out - std::set marginalizableKeys = findKeysBefore( + KeyVector marginalizableKeys = findKeysBefore( current_timestamp - smootherLag_); - if (debug) { - std::cout << "Marginalizable Keys: "; - for(Key key: marginalizableKeys) { - std::cout << DefaultKeyFormatter(key) << " "; - } - std::cout << std::endl; - } // Reorder gttic(reorder); @@ -113,17 +99,13 @@ FixedLagSmoother::Result BatchFixedLagSmoother::update( } gttoc(marginalize); - if (debug) { - std::cout << "BatchFixedLagSmoother::update() FINISH" << std::endl; - } - return result; } /* ************************************************************************* */ void BatchFixedLagSmoother::insertFactors( const NonlinearFactorGraph& newFactors) { - for(const NonlinearFactor::shared_ptr& factor: newFactors) { + for(const auto& factor: newFactors) { Key index; // Insert the factor into an existing hole in the factor graph, if possible if (availableSlots_.size() > 0) { @@ -143,7 +125,7 @@ void BatchFixedLagSmoother::insertFactors( /* ************************************************************************* */ void BatchFixedLagSmoother::removeFactors( - const std::set& deleteFactors) { + const set& deleteFactors) { for(size_t slot: deleteFactors) { if (factors_.at(slot)) { // Remove references to this factor from the FactorIndex @@ -156,14 +138,14 @@ void BatchFixedLagSmoother::removeFactors( availableSlots_.push(slot); } else { // TODO: Throw an error?? - std::cout << "Attempting to remove a factor from slot " << slot - << ", but it is already NULL." << std::endl; + cout << "Attempting to remove a factor from slot " << slot + << ", but it is already NULL." << endl; } } } /* ************************************************************************* */ -void BatchFixedLagSmoother::eraseKeys(const std::set& keys) { +void BatchFixedLagSmoother::eraseKeys(const KeyVector& keys) { for(Key key: keys) { // Erase the key from the values @@ -182,50 +164,20 @@ void BatchFixedLagSmoother::eraseKeys(const std::set& keys) { // Remove marginalized keys from the ordering and delta for(Key key: keys) { - ordering_.erase(std::find(ordering_.begin(), ordering_.end(), key)); + ordering_.erase(find(ordering_.begin(), ordering_.end(), key)); delta_.erase(key); } } /* ************************************************************************* */ -void BatchFixedLagSmoother::reorder(const std::set& marginalizeKeys) { - - const bool debug = ISDEBUG("BatchFixedLagSmoother reorder"); - - if (debug) { - std::cout << "BatchFixedLagSmoother::reorder() START" << std::endl; - } - - if (debug) { - std::cout << "Marginalizable Keys: "; - for(Key key: marginalizeKeys) { - std::cout << DefaultKeyFormatter(key) << " "; - } - std::cout << std::endl; - } - +void BatchFixedLagSmoother::reorder(const KeyVector& marginalizeKeys) { // COLAMD groups will be used to place marginalize keys in Group 0, and everything else in Group 1 - ordering_ = Ordering::ColamdConstrainedFirst(factors_, - std::vector(marginalizeKeys.begin(), marginalizeKeys.end())); - - if (debug) { - ordering_.print("New Ordering: "); - } - - if (debug) { - std::cout << "BatchFixedLagSmoother::reorder() FINISH" << std::endl; - } + ordering_ = Ordering::ColamdConstrainedFirst(factors_, marginalizeKeys); } /* ************************************************************************* */ FixedLagSmoother::Result BatchFixedLagSmoother::optimize() { - const bool debug = ISDEBUG("BatchFixedLagSmoother optimize"); - - if (debug) { - std::cout << "BatchFixedLagSmoother::optimize() START" << std::endl; - } - // Create output result structure Result result; result.nonlinearVariables = theta_.size() - linearKeys_.size(); @@ -247,20 +199,9 @@ FixedLagSmoother::Result BatchFixedLagSmoother::optimize() { // check if we're already close enough if (result.error <= errorTol) { - if (debug) { - std::cout << "BatchFixedLagSmoother::optimize Exiting, as error = " - << result.error << " < " << errorTol << std::endl; - } return result; } - if (debug) { - std::cout << "BatchFixedLagSmoother::optimize linearValues: " - << linearKeys_.size() << std::endl; - std::cout << "BatchFixedLagSmoother::optimize Initial error: " - << result.error << std::endl; - } - // Use a custom optimization loop so the linearization points can be controlled double previousError; VectorValues newDelta; @@ -276,19 +217,14 @@ FixedLagSmoother::Result BatchFixedLagSmoother::optimize() { // Keep increasing lambda until we make make progress while (true) { - if (debug) { - std::cout << "BatchFixedLagSmoother::optimize trying lambda = " - << lambda << std::endl; - } - // Add prior factors at the current solution gttic(damp); GaussianFactorGraph dampedFactorGraph(linearFactorGraph); dampedFactorGraph.reserve(linearFactorGraph.size() + delta_.size()); { // for each of the variables, add a prior at the current solution - double sigma = 1.0 / std::sqrt(lambda); - for(const VectorValues::KeyValuePair& key_value: delta_) { + double sigma = 1.0 / sqrt(lambda); + for(const auto& key_value: delta_) { size_t dim = key_value.second.size(); Matrix A = Matrix::Identity(dim, dim); Vector b = key_value.second; @@ -314,13 +250,6 @@ FixedLagSmoother::Result BatchFixedLagSmoother::optimize() { double error = factors_.error(evalpoint); gttoc(compute_error); - if (debug) { - std::cout << "BatchFixedLagSmoother::optimize linear delta norm = " - << newDelta.norm() << std::endl; - std::cout << "BatchFixedLagSmoother::optimize next error = " << error - << std::endl; - } - if (error < result.error) { // Keep this change // Update the error value @@ -332,7 +261,7 @@ FixedLagSmoother::Result BatchFixedLagSmoother::optimize() { // Put the linearization points and deltas back for specific variables if (enforceConsistency_ && (linearKeys_.size() > 0)) { theta_.update(linearKeys_); - for(const Values::ConstKeyValuePair& key_value: linearKeys_) { + for(const auto& key_value: linearKeys_) { delta_.at(key_value.key) = newDelta.at(key_value.key); } } @@ -347,9 +276,9 @@ FixedLagSmoother::Result BatchFixedLagSmoother::optimize() { // Reject this change if (lambda >= lambdaUpperBound) { // The maximum lambda has been used. Print a warning and end the search. - std::cout + cout << "Warning: Levenberg-Marquardt giving up because cannot decrease error with maximum lambda" - << std::endl; + << endl; break; } else { // Increase lambda and continue searching @@ -360,65 +289,30 @@ FixedLagSmoother::Result BatchFixedLagSmoother::optimize() { } gttoc(optimizer_iteration); - if (debug) { - std::cout << "BatchFixedLagSmoother::optimize using lambda = " << lambda - << std::endl; - } - result.iterations++; } while (result.iterations < maxIterations && !checkConvergence(relativeErrorTol, absoluteErrorTol, errorTol, previousError, result.error, NonlinearOptimizerParams::SILENT)); - if (debug) { - std::cout << "BatchFixedLagSmoother::optimize newError: " << result.error - << std::endl; - } - - if (debug) { - std::cout << "BatchFixedLagSmoother::optimize() FINISH" << std::endl; - } - return result; } /* ************************************************************************* */ -void BatchFixedLagSmoother::marginalize(const std::set& marginalizeKeys) { +void BatchFixedLagSmoother::marginalize(const KeyVector& marginalizeKeys) { // In order to marginalize out the selected variables, the factors involved in those variables // must be identified and removed. Also, the effect of those removed factors on the // remaining variables needs to be accounted for. This will be done with linear container factors // from the result of a partial elimination. This function removes the marginalized factors and // adds the linearized factors back in. - const bool debug = ISDEBUG("BatchFixedLagSmoother marginalize"); - - if (debug) - std::cout << "BatchFixedLagSmoother::marginalize Begin" << std::endl; - - if (debug) { - std::cout << "BatchFixedLagSmoother::marginalize Marginalize Keys: "; - for(Key key: marginalizeKeys) { - std::cout << DefaultKeyFormatter(key) << " "; - } - std::cout << std::endl; - } - // Identify all of the factors involving any marginalized variable. These must be removed. - std::set removedFactorSlots; - VariableIndex variableIndex(factors_); + set removedFactorSlots; + const VariableIndex variableIndex(factors_); for(Key key: marginalizeKeys) { const FastVector& slots = variableIndex[key]; removedFactorSlots.insert(slots.begin(), slots.end()); } - if (debug) { - std::cout << "BatchFixedLagSmoother::marginalize Removed Factor Slots: "; - for(size_t slot: removedFactorSlots) { - std::cout << slot << " "; - } - std::cout << std::endl; - } - // Add the removed factors to a factor graph NonlinearFactorGraph removedFactors; for(size_t slot: removedFactorSlots) { @@ -427,20 +321,9 @@ void BatchFixedLagSmoother::marginalize(const std::set& marginalizeKeys) { } } - if (debug) { - PrintSymbolicGraph(removedFactors, - "BatchFixedLagSmoother::marginalize Removed Factors: "); - } - // Calculate marginal factors on the remaining keys - NonlinearFactorGraph marginalFactors = calculateMarginalFactors( - removedFactors, theta_, marginalizeKeys, - parameters_.getEliminationFunction()); - - if (debug) { - PrintSymbolicGraph(removedFactors, - "BatchFixedLagSmoother::marginalize Marginal Factors: "); - } + NonlinearFactorGraph marginalFactors = CalculateMarginalFactors( + removedFactors, theta_, marginalizeKeys, parameters_.getEliminationFunction()); // Remove marginalized factors from the factor graph removeFactors(removedFactorSlots); @@ -453,140 +336,96 @@ void BatchFixedLagSmoother::marginalize(const std::set& marginalizeKeys) { } /* ************************************************************************* */ -void BatchFixedLagSmoother::PrintKeySet(const std::set& keys, - const std::string& label) { - std::cout << label; - for(gtsam::Key key: keys) { - std::cout << " " << gtsam::DefaultKeyFormatter(key); +void BatchFixedLagSmoother::PrintKeySet(const set& keys, + const string& label) { + cout << label; + for(Key key: keys) { + cout << " " << DefaultKeyFormatter(key); } - std::cout << std::endl; + cout << endl; } /* ************************************************************************* */ -void BatchFixedLagSmoother::PrintKeySet(const gtsam::KeySet& keys, - const std::string& label) { - std::cout << label; - for(gtsam::Key key: keys) { - std::cout << " " << gtsam::DefaultKeyFormatter(key); +void BatchFixedLagSmoother::PrintKeySet(const KeySet& keys, + const string& label) { + cout << label; + for(Key key: keys) { + cout << " " << DefaultKeyFormatter(key); } - std::cout << std::endl; + cout << endl; } /* ************************************************************************* */ void BatchFixedLagSmoother::PrintSymbolicFactor( const NonlinearFactor::shared_ptr& factor) { - std::cout << "f("; + cout << "f("; if (factor) { for(Key key: factor->keys()) { - std::cout << " " << gtsam::DefaultKeyFormatter(key); + cout << " " << DefaultKeyFormatter(key); } } else { - std::cout << " NULL"; + cout << " NULL"; } - std::cout << " )" << std::endl; + cout << " )" << endl; } /* ************************************************************************* */ void BatchFixedLagSmoother::PrintSymbolicFactor( const GaussianFactor::shared_ptr& factor) { - std::cout << "f("; + cout << "f("; for(Key key: factor->keys()) { - std::cout << " " << gtsam::DefaultKeyFormatter(key); + cout << " " << DefaultKeyFormatter(key); } - std::cout << " )" << std::endl; + cout << " )" << endl; } /* ************************************************************************* */ void BatchFixedLagSmoother::PrintSymbolicGraph( - const NonlinearFactorGraph& graph, const std::string& label) { - std::cout << label << std::endl; - for(const NonlinearFactor::shared_ptr& factor: graph) { + const NonlinearFactorGraph& graph, const string& label) { + cout << label << endl; + for(const auto& factor: graph) { PrintSymbolicFactor(factor); } } /* ************************************************************************* */ void BatchFixedLagSmoother::PrintSymbolicGraph(const GaussianFactorGraph& graph, - const std::string& label) { - std::cout << label << std::endl; - for(const GaussianFactor::shared_ptr& factor: graph) { + const string& label) { + cout << label << endl; + for(const auto& factor: graph) { PrintSymbolicFactor(factor); } } /* ************************************************************************* */ -NonlinearFactorGraph BatchFixedLagSmoother::calculateMarginalFactors( - const NonlinearFactorGraph& graph, const Values& theta, - const std::set& marginalizeKeys, +GaussianFactorGraph BatchFixedLagSmoother::CalculateMarginalFactors( + const GaussianFactorGraph& graph, const KeyVector& keys, const GaussianFactorGraph::Eliminate& eliminateFunction) { - - const bool debug = ISDEBUG("BatchFixedLagSmoother calculateMarginalFactors"); - - if (debug) - std::cout << "BatchFixedLagSmoother::calculateMarginalFactors START" - << std::endl; - - if (debug) - PrintKeySet(marginalizeKeys, - "BatchFixedLagSmoother::calculateMarginalFactors Marginalize Keys: "); - - // Get the set of all keys involved in the factor graph - KeySet allKeys(graph.keys()); - if (debug) - PrintKeySet(allKeys, - "BatchFixedLagSmoother::calculateMarginalFactors All Keys: "); - - if (!std::includes(allKeys.begin(), allKeys.end(), marginalizeKeys.begin(), - marginalizeKeys.end())) { - throw std::runtime_error("Some keys found in marginalizeKeys do not" - " occur in the graph."); - } - - // Calculate the set of RemainingKeys = AllKeys \Intersect marginalizeKeys - KeySet remainingKeys; - std::set_difference(allKeys.begin(), allKeys.end(), marginalizeKeys.begin(), - marginalizeKeys.end(), std::inserter(remainingKeys, remainingKeys.end())); - if (debug) - PrintKeySet(remainingKeys, - "BatchFixedLagSmoother::calculateMarginalFactors Remaining Keys: "); - - if (marginalizeKeys.size() == 0) { + if (keys.size() == 0) { // There are no keys to marginalize. Simply return the input factors - if (debug) - std::cout << "BatchFixedLagSmoother::calculateMarginalFactors FINISH" - << std::endl; return graph; } else { - - // Create the linear factor graph - GaussianFactorGraph linearFactorGraph = *graph.linearize(theta); // .first is the eliminated Bayes tree, while .second is the remaining factor graph - GaussianFactorGraph marginalLinearFactors = - *linearFactorGraph.eliminatePartialMultifrontal( - std::vector(marginalizeKeys.begin(), marginalizeKeys.end())).second; + return *graph.eliminatePartialMultifrontal(keys, eliminateFunction).second; + } +} + +/* ************************************************************************* */ +NonlinearFactorGraph BatchFixedLagSmoother::CalculateMarginalFactors( + const NonlinearFactorGraph& graph, const Values& theta, const KeyVector& keys, + const GaussianFactorGraph::Eliminate& eliminateFunction) { + if (keys.size() == 0) { + // There are no keys to marginalize. Simply return the input factors + return graph; + } else { + // Create the linear factor graph + const auto linearFactorGraph = graph.linearize(theta); + + const auto marginalLinearFactors = + CalculateMarginalFactors(*linearFactorGraph, keys, eliminateFunction); // Wrap in nonlinear container factors - NonlinearFactorGraph marginalFactors; - marginalFactors.reserve(marginalLinearFactors.size()); - for(const GaussianFactor::shared_ptr& gaussianFactor: marginalLinearFactors) { - marginalFactors += boost::make_shared( - gaussianFactor, theta); - if (debug) { - std::cout - << "BatchFixedLagSmoother::calculateMarginalFactors Marginal Factor: "; - PrintSymbolicFactor(marginalFactors.back()); - } - } - - if (debug) - PrintSymbolicGraph(marginalFactors, - "BatchFixedLagSmoother::calculateMarginalFactors All Marginal Factors: "); - - if (debug) - std::cout << "BatchFixedLagSmoother::calculateMarginalFactors FINISH" - << std::endl; - - return marginalFactors; + return LinearContainerFactor::ConvertLinearGraph(marginalLinearFactors, theta); } } diff --git a/gtsam_unstable/nonlinear/BatchFixedLagSmoother.h b/gtsam_unstable/nonlinear/BatchFixedLagSmoother.h index 605f3a5e8..27fe94451 100644 --- a/gtsam_unstable/nonlinear/BatchFixedLagSmoother.h +++ b/gtsam_unstable/nonlinear/BatchFixedLagSmoother.h @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- - * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) @@ -103,8 +103,26 @@ public: /// Calculate marginal covariance on given variable Matrix marginalCovariance(Key key) const; - static NonlinearFactorGraph calculateMarginalFactors(const NonlinearFactorGraph& graph, const Values& theta, - const std::set& marginalizeKeys, const GaussianFactorGraph::Eliminate& eliminateFunction); + /// Marginalize specific keys from a linear graph. + /// Does not check whether keys actually exist in graph. + /// In that case will fail somewhere deep within elimination + static GaussianFactorGraph CalculateMarginalFactors( + const GaussianFactorGraph& graph, const KeyVector& keys, + const GaussianFactorGraph::Eliminate& eliminateFunction = EliminatePreferCholesky); + + /// Marginalize specific keys from a nonlinear graph, wrap in LinearContainers + static NonlinearFactorGraph CalculateMarginalFactors( + const NonlinearFactorGraph& graph, const Values& theta, const KeyVector& keys, + const GaussianFactorGraph::Eliminate& eliminateFunction = EliminatePreferCholesky); + +#ifdef GTSAM_ALLOW_DEPRECATED_SINCE_V4 + static NonlinearFactorGraph calculateMarginalFactors( + const NonlinearFactorGraph& graph, const Values& theta, const std::set& keys, + const GaussianFactorGraph::Eliminate& eliminateFunction = EliminatePreferCholesky) { + KeyVector keyVector(keys.begin(), keys.end()); + return CalculateMarginalFactors(graph, theta, keyVector, eliminateFunction); + } +#endif protected: @@ -147,16 +165,16 @@ protected: void removeFactors(const std::set& deleteFactors); /** Erase any keys associated with timestamps before the provided time */ - void eraseKeys(const std::set& keys); + void eraseKeys(const KeyVector& keys); /** Use colamd to update into an efficient ordering */ - void reorder(const std::set& marginalizeKeys = std::set()); + void reorder(const KeyVector& marginalizeKeys = KeyVector()); /** Optimize the current graph using a modified version of L-M */ Result optimize(); /** Marginalize out selected variables */ - void marginalize(const std::set& marginalizableKeys); + void marginalize(const KeyVector& marginalizableKeys); private: /** Private methods for printing debug information */ diff --git a/gtsam_unstable/nonlinear/FixedLagSmoother.cpp b/gtsam_unstable/nonlinear/FixedLagSmoother.cpp index 3eecb58e0..62ee07a16 100644 --- a/gtsam_unstable/nonlinear/FixedLagSmoother.cpp +++ b/gtsam_unstable/nonlinear/FixedLagSmoother.cpp @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- - * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) @@ -36,7 +36,7 @@ bool FixedLagSmoother::equals(const FixedLagSmoother& rhs, double tol) const { /* ************************************************************************* */ void FixedLagSmoother::updateKeyTimestampMap(const KeyTimestampMap& timestamps) { // Loop through each key and add/update it in the map - for(const KeyTimestampMap::value_type& key_timestamp: timestamps) { + for(const auto& key_timestamp: timestamps) { // Check to see if this key already exists in the database KeyTimestampMap::iterator keyIter = keyTimestampMap_.find(key_timestamp.first); @@ -64,7 +64,7 @@ void FixedLagSmoother::updateKeyTimestampMap(const KeyTimestampMap& timestamps) } /* ************************************************************************* */ -void FixedLagSmoother::eraseKeyTimestampMap(const std::set& keys) { +void FixedLagSmoother::eraseKeyTimestampMap(const KeyVector& keys) { for(Key key: keys) { // Erase the key from the Timestamp->Key map double timestamp = keyTimestampMap_.at(key); @@ -92,21 +92,21 @@ double FixedLagSmoother::getCurrentTimestamp() const { } /* ************************************************************************* */ -std::set FixedLagSmoother::findKeysBefore(double timestamp) const { - std::set keys; +KeyVector FixedLagSmoother::findKeysBefore(double timestamp) const { + KeyVector keys; TimestampKeyMap::const_iterator end = timestampKeyMap_.lower_bound(timestamp); for(TimestampKeyMap::const_iterator iter = timestampKeyMap_.begin(); iter != end; ++iter) { - keys.insert(iter->second); + keys.push_back(iter->second); } return keys; } /* ************************************************************************* */ -std::set FixedLagSmoother::findKeysAfter(double timestamp) const { - std::set keys; +KeyVector FixedLagSmoother::findKeysAfter(double timestamp) const { + KeyVector keys; TimestampKeyMap::const_iterator begin = timestampKeyMap_.upper_bound(timestamp); for(TimestampKeyMap::const_iterator iter = begin; iter != timestampKeyMap_.end(); ++iter) { - keys.insert(iter->second); + keys.push_back(iter->second); } return keys; } diff --git a/gtsam_unstable/nonlinear/FixedLagSmoother.h b/gtsam_unstable/nonlinear/FixedLagSmoother.h index f212b38e7..4868a7cf1 100644 --- a/gtsam_unstable/nonlinear/FixedLagSmoother.h +++ b/gtsam_unstable/nonlinear/FixedLagSmoother.h @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- - * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) @@ -24,7 +24,9 @@ #include #include #include + #include +#include namespace gtsam { @@ -111,16 +113,16 @@ protected: void updateKeyTimestampMap(const KeyTimestampMap& newTimestamps); /** Erase keys from the Key-Timestamps database */ - void eraseKeyTimestampMap(const std::set& keys); + void eraseKeyTimestampMap(const KeyVector& keys); /** Find the most recent timestamp of the system */ double getCurrentTimestamp() const; /** Find all of the keys associated with timestamps before the provided time */ - std::set findKeysBefore(double timestamp) const; + KeyVector findKeysBefore(double timestamp) const; /** Find all of the keys associated with timestamps before the provided time */ - std::set findKeysAfter(double timestamp) const; + KeyVector findKeysAfter(double timestamp) const; }; // FixedLagSmoother diff --git a/gtsam_unstable/nonlinear/IncrementalFixedLagSmoother.cpp b/gtsam_unstable/nonlinear/IncrementalFixedLagSmoother.cpp index ddfd88cae..d3c34ff5e 100644 --- a/gtsam_unstable/nonlinear/IncrementalFixedLagSmoother.cpp +++ b/gtsam_unstable/nonlinear/IncrementalFixedLagSmoother.cpp @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- - * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) @@ -88,7 +88,7 @@ FixedLagSmoother::Result IncrementalFixedLagSmoother::update( std::cout << "Current Timestamp: " << current_timestamp << std::endl; // Find the set of variables to be marginalized out - std::set marginalizableKeys = findKeysBefore( + KeyVector marginalizableKeys = findKeysBefore( current_timestamp - smootherLag_); if (debug) { @@ -174,7 +174,7 @@ void IncrementalFixedLagSmoother::eraseKeysBefore(double timestamp) { /* ************************************************************************* */ void IncrementalFixedLagSmoother::createOrderingConstraints( - const std::set& marginalizableKeys, + const KeyVector& marginalizableKeys, boost::optional >& constrainedKeys) const { if (marginalizableKeys.size() > 0) { constrainedKeys = FastMap(); diff --git a/gtsam_unstable/nonlinear/IncrementalFixedLagSmoother.h b/gtsam_unstable/nonlinear/IncrementalFixedLagSmoother.h index 31ae20c50..77d052a21 100644 --- a/gtsam_unstable/nonlinear/IncrementalFixedLagSmoother.h +++ b/gtsam_unstable/nonlinear/IncrementalFixedLagSmoother.h @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- - * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) @@ -117,7 +117,7 @@ protected: void eraseKeysBefore(double timestamp); /** Fill in an iSAM2 ConstrainedKeys structure such that the provided keys are eliminated before all others */ - void createOrderingConstraints(const std::set& marginalizableKeys, + void createOrderingConstraints(const KeyVector& marginalizableKeys, boost::optional >& constrainedKeys) const; private: diff --git a/gtsam_unstable/nonlinear/LinearizedFactor.cpp b/gtsam_unstable/nonlinear/LinearizedFactor.cpp index a18c24256..e285955a7 100644 --- a/gtsam_unstable/nonlinear/LinearizedFactor.cpp +++ b/gtsam_unstable/nonlinear/LinearizedFactor.cpp @@ -139,21 +139,7 @@ LinearizedHessianFactor::LinearizedHessianFactor() { /* ************************************************************************* */ LinearizedHessianFactor::LinearizedHessianFactor( const HessianFactor::shared_ptr& hessian, const Values& lin_points) -: Base(hessian, lin_points) { - - // Create the dims array - size_t *dims = (size_t*)alloca(sizeof(size_t)*(hessian->size() + 1)); - size_t index = 0; - for(HessianFactor::const_iterator iter = hessian->begin(); iter != hessian->end(); ++iter) { - dims[index++] = hessian->getDim(iter); - } - dims[index] = 1; - - // Update the BlockInfo accessor - info_ = SymmetricBlockMatrix(dims, dims+hessian->size()+1); - // Copy the augmented matrix holding G, g, and f - info_.full() = hessian->info(); -} + : Base(hessian, lin_points), info_(hessian->info()) {} /* ************************************************************************* */ void LinearizedHessianFactor::print(const std::string& s, const KeyFormatter& keyFormatter) const { @@ -165,7 +151,7 @@ void LinearizedHessianFactor::print(const std::string& s, const KeyFormatter& ke std::cout << keyFormatter(key) << " "; std::cout << std::endl; - gtsam::print(Matrix(info_.full()), "Ab^T * Ab: "); + gtsam::print(Matrix(info_.selfadjointView()), "Ab^T * Ab: "); lin_points_.print("Linearization Point: "); } @@ -176,9 +162,9 @@ bool LinearizedHessianFactor::equals(const NonlinearFactor& expected, double tol const This *e = dynamic_cast (&expected); if (e) { - Matrix thisMatrix = this->info_.full(); + Matrix thisMatrix = this->info_.selfadjointView(); thisMatrix(thisMatrix.rows()-1, thisMatrix.cols()-1) = 0.0; - Matrix rhsMatrix = e->info_.full(); + Matrix rhsMatrix = e->info_.selfadjointView(); rhsMatrix(rhsMatrix.rows()-1, rhsMatrix.cols()-1) = 0.0; return Base::equals(expected, tol) @@ -234,16 +220,20 @@ LinearizedHessianFactor::linearize(const Values& c) const { //newInfo.rangeColumn(0, this->size(), this->size(), 0) -= squaredTerm().selfadjointView() * dx; Vector g = linearTerm() - squaredTerm() * dx; std::vector gs; + std::size_t offset = 0; for(DenseIndex i = 0; i < info_.nBlocks()-1; ++i) { - gs.push_back(g.segment(info_.offset(i), info_.offset(i+1) - info_.offset(i))); + const std::size_t dim = info_.getDim(i); + gs.push_back(g.segment(offset, dim)); + offset += dim; } // G2 = G1 // Do Nothing std::vector Gs; for(DenseIndex i = 0; i < info_.nBlocks()-1; ++i) { - for(DenseIndex j = i; j < info_.nBlocks()-1; ++j) { - Gs.push_back(info_(i,j)); + Gs.push_back(info_.diagonalBlock(i)); + for(DenseIndex j = i + 1; j < info_.nBlocks()-1; ++j) { + Gs.push_back(info_.aboveDiagonalBlock(i, j)); } } diff --git a/gtsam_unstable/nonlinear/LinearizedFactor.h b/gtsam_unstable/nonlinear/LinearizedFactor.h index c6710bd70..f9fa6033f 100644 --- a/gtsam_unstable/nonlinear/LinearizedFactor.h +++ b/gtsam_unstable/nonlinear/LinearizedFactor.h @@ -178,8 +178,9 @@ public: /** hessian block data types */ typedef SymmetricBlockMatrix::Block Block; ///< A block from the Hessian matrix typedef SymmetricBlockMatrix::constBlock constBlock; ///< A block from the Hessian matrix (const version) - typedef SymmetricBlockMatrix::Block::OffDiagonal::ColXpr Column; ///< A column containing the linear term h - typedef SymmetricBlockMatrix::constBlock::OffDiagonal::ColXpr constColumn; ///< A column containing the linear term h (const version) + + typedef SymmetricBlockMatrix::Block::ColXpr Column; ///< A column containing the linear term h + typedef SymmetricBlockMatrix::constBlock::ColXpr constColumn; ///< A column containing the linear term h (const version) protected: @@ -216,19 +217,26 @@ public: /** Return the constant term \f$ f \f$ as described above * @return The constant term \f$ f \f$ */ - double constantTerm() const { return info_(this->size(), this->size())(0,0); }; + double constantTerm() const { + const auto block = info_.diagonalBlock(size()); + return block(0, 0); + } /** Return the part of linear term \f$ g \f$ as described above corresponding to the requested variable. * @param j Which block row to get, as an iterator pointing to the slot in this factor. You can * use, for example, begin() + 2 to get the 3rd variable in this factor. * @return The linear term \f$ g \f$ */ - constColumn linearTerm(const_iterator j) const { return info_(j - this->begin(), this->size()).knownOffDiagonal().col(0); } + constColumn linearTerm(const_iterator j) const { + return info_.aboveDiagonalRange(j - begin(), size(), size(), size() + 1).col(0); + } /** Return the complete linear term \f$ g \f$ as described above. * @return The linear term \f$ g \f$ */ - constColumn linearTerm() const { return info_.range(0, this->size(), this->size(), this->size() + 1).knownOffDiagonal().col(0); }; + constColumn linearTerm() const { + return info_.aboveDiagonalRange(0, size(), size(), size() + 1).col(0); + } - /** Return a view of the block at (j1,j2) of the upper-triangular part of the + /** Return a copy of the block at (j1,j2) of the upper-triangular part of the * squared term \f$ H \f$, no data is copied. See HessianFactor class documentation * above to explain that only the upper-triangular part of the information matrix is stored * and returned by this function. @@ -236,19 +244,24 @@ public: * use, for example, begin() + 2 to get the 3rd variable in this factor. * @param j2 Which block column to get, as an iterator pointing to the slot in this factor. You can * use, for example, begin() + 2 to get the 3rd variable in this factor. - * @return A view of the requested block, not a copy. + * @return A copy of the requested block. */ - constBlock squaredTerm(const_iterator j1, const_iterator j2) const { return info_(j1-begin(), j2-begin()); } + Matrix squaredTerm(const_iterator j1, const_iterator j2) const { + const DenseIndex J1 = j1 - begin(); + const DenseIndex J2 = j2 - begin(); + return info_.block(J1, J2); + } /** Return the upper-triangular part of the full squared term, as described above. * See HessianFactor class documentation above to explain that only the * upper-triangular part of the information matrix is stored and returned by this function. */ - constBlock::SelfAdjointView squaredTerm() const { return info_.range(0, this->size(), 0, this->size()).selfadjointView(); } - + Eigen::SelfAdjointView squaredTerm() const { + return info_.selfadjointView(0, size()); + } /** get the dimension of the factor (number of rows on linearization) */ - size_t dim() const { return info_.rows() - 1; }; + size_t dim() const { return info_.rows() - 1; } /** Calculate the error of the factor */ double error(const Values& c) const; diff --git a/gtsam_unstable/nonlinear/NonlinearClusterTree.h b/gtsam_unstable/nonlinear/NonlinearClusterTree.h new file mode 100644 index 000000000..b1f463c26 --- /dev/null +++ b/gtsam_unstable/nonlinear/NonlinearClusterTree.h @@ -0,0 +1,101 @@ +/** + * @file NonlinearClusterTree.h + * @author Frank Dellaert + * @date March, 2016 + */ + +#pragma once + +#include +#include +#include + +namespace gtsam { +class NonlinearClusterTree : public ClusterTree { + public: + NonlinearClusterTree() {} + + struct NonlinearCluster : Cluster { + // Given graph, index, add factors with specified keys into + // Factors are erased in the graph + // TODO(frank): fairly hacky and inefficient. Think about iterating the graph once instead + NonlinearCluster(const VariableIndex& variableIndex, const std::vector& keys, + NonlinearFactorGraph* graph) { + for (const Key key : keys) { + std::vector factors; + for (auto i : variableIndex[key]) + if (graph->at(i)) { + factors.push_back(graph->at(i)); + graph->remove(i); + } + Cluster::addFactors(key, factors); + } + } + + GaussianFactorGraph::shared_ptr linearize(const Values& values) { + return factors.linearize(values); + } + + static NonlinearCluster* DownCast(const boost::shared_ptr& cluster) { + auto nonlinearCluster = boost::dynamic_pointer_cast(cluster); + if (!nonlinearCluster) + throw std::runtime_error("Expected NonlinearCluster"); + return nonlinearCluster.get(); + } + + // linearize local custer factors straight into hessianFactor, which is returned + // If no ordering given, uses colamd + HessianFactor::shared_ptr linearizeToHessianFactor( + const Values& values, boost::optional ordering = boost::none, + const NonlinearFactorGraph::Dampen& dampen = nullptr) const { + if (!ordering) + ordering.reset(Ordering::ColamdConstrainedFirst(factors, orderedFrontalKeys, true)); + return factors.linearizeToHessianFactor(values, *ordering, dampen); + } + + // Recursively eliminate subtree rooted at this Cluster into a Bayes net and factor on parent + // TODO(frank): Use TBB to support deep trees and parallelism + std::pair linearizeAndEliminate( + const Values& values, boost::optional ordering = boost::none, + const NonlinearFactorGraph::Dampen& dampen = nullptr) const { + // Linearize and create HessianFactor f(front,separator) + HessianFactor::shared_ptr localFactor = linearizeToHessianFactor(values, ordering, dampen); + + // Get contributions f(front) from children, as well as p(children|front) + GaussianBayesNet bayesNet; + for (const auto& child : children) { + auto message = DownCast(child)->linearizeAndEliminate(values, &bayesNet); + message->updateHessian(localFactor.get()); + } + auto gaussianConditional = localFactor->eliminateCholesky(orderedFrontalKeys); + bayesNet.add(gaussianConditional); + return {bayesNet, localFactor}; + } + + // Recursively eliminate subtree rooted at this Cluster + // Version that updates existing Bayes net and returns a new Hessian factor on parent clique + // It is possible to pass in a nullptr for the bayesNet if only interested in the new factor + HessianFactor::shared_ptr linearizeAndEliminate( + const Values& values, GaussianBayesNet* bayesNet, + boost::optional ordering = boost::none, + const NonlinearFactorGraph::Dampen& dampen = nullptr) const { + auto bayesNet_newFactor_pair = linearizeAndEliminate(values, ordering, dampen); + if (bayesNet) { + bayesNet->push_back(bayesNet_newFactor_pair.first); + } + return bayesNet_newFactor_pair.second; + } + }; + + // Linearize and update linearization point with values + Values updateCholesky(const Values& values) { + GaussianBayesNet bayesNet; + for (const auto& root : roots_) { + auto result = NonlinearCluster::DownCast(root)->linearizeAndEliminate(values); + bayesNet.push_back(result.first); + } + VectorValues delta = bayesNet.optimize(); + return values.retract(delta); + } +}; +} // namespace gtsam diff --git a/gtsam_unstable/nonlinear/tests/testNonlinearClusterTree.cpp b/gtsam_unstable/nonlinear/tests/testNonlinearClusterTree.cpp new file mode 100644 index 000000000..9391814d4 --- /dev/null +++ b/gtsam_unstable/nonlinear/tests/testNonlinearClusterTree.cpp @@ -0,0 +1,155 @@ +/** + * @file testNonlinearClusterTree.cpp + * @author Frank Dellaert + * @date March, 2016 + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include + +using namespace gtsam; + +static const Symbol x1('x', 1), x2('x', 2), x3('x', 3); +static const Symbol l1('l', 1), l2('l', 2); + +/* ************************************************************************* */ +NonlinearFactorGraph planarSLAMGraph() { + NonlinearFactorGraph graph; + + // Prior on pose x1 at the origin. + Pose2 prior(0.0, 0.0, 0.0); + auto priorNoise = noiseModel::Diagonal::Sigmas(Vector3(0.3, 0.3, 0.1)); + graph.add(PriorFactor(x1, prior, priorNoise)); + + // Two odometry factors + Pose2 odometry(2.0, 0.0, 0.0); + auto odometryNoise = noiseModel::Diagonal::Sigmas(Vector3(0.2, 0.2, 0.1)); + graph.add(BetweenFactor(x1, x2, odometry, odometryNoise)); + graph.add(BetweenFactor(x2, x3, odometry, odometryNoise)); + + // Add Range-Bearing measurements to two different landmarks + auto measurementNoise = noiseModel::Diagonal::Sigmas(Vector2(0.1, 0.2)); + Rot2 bearing11 = Rot2::fromDegrees(45), bearing21 = Rot2::fromDegrees(90), + bearing32 = Rot2::fromDegrees(90); + double range11 = std::sqrt(4.0 + 4.0), range21 = 2.0, range32 = 2.0; + graph.add(BearingRangeFactor(x1, l1, bearing11, range11, measurementNoise)); + graph.add(BearingRangeFactor(x2, l1, bearing21, range21, measurementNoise)); + graph.add(BearingRangeFactor(x3, l2, bearing32, range32, measurementNoise)); + + return graph; +} + +/* ************************************************************************* */ +// Create initial estimate +Values planarSLAMValues() { + Values initial; + initial.insert(l1, Point2(1.8, 2.1)); + initial.insert(l2, Point2(4.1, 1.8)); + initial.insert(x1, Pose2(0.5, 0.0, 0.2)); + initial.insert(x2, Pose2(2.3, 0.1, -0.2)); + initial.insert(x3, Pose2(4.1, 0.1, 0.1)); + return initial; +} + +/* ************************************************************************* */ +TEST(NonlinearClusterTree, Clusters) { + NonlinearFactorGraph graph = planarSLAMGraph(); + Values initial = planarSLAMValues(); + + // Build the clusters + // NOTE(frank): Order matters here as factors are removed! + VariableIndex variableIndex(graph); + typedef NonlinearClusterTree::NonlinearCluster Cluster; + auto marginalCluster = boost::shared_ptr(new Cluster(variableIndex, {x1}, &graph)); + auto landmarkCluster = boost::shared_ptr(new Cluster(variableIndex, {l1, l2}, &graph)); + auto rootCluster = boost::shared_ptr(new Cluster(variableIndex, {x2, x3}, &graph)); + + EXPECT_LONGS_EQUAL(3, marginalCluster->nrFactors()); + EXPECT_LONGS_EQUAL(2, landmarkCluster->nrFactors()); + EXPECT_LONGS_EQUAL(1, rootCluster->nrFactors()); + + EXPECT_LONGS_EQUAL(1, marginalCluster->nrFrontals()); + EXPECT_LONGS_EQUAL(2, landmarkCluster->nrFrontals()); + EXPECT_LONGS_EQUAL(2, rootCluster->nrFrontals()); + + // Test linearize + auto gfg = marginalCluster->linearize(initial); + EXPECT_LONGS_EQUAL(3, gfg->size()); + + // Calculate expected result of only evaluating the marginalCluster + Ordering ordering; + ordering.push_back(x1); + auto expected = gfg->eliminatePartialSequential(ordering); + auto expectedFactor = boost::dynamic_pointer_cast(expected.second->at(0)); + if (!expectedFactor) + throw std::runtime_error("Expected HessianFactor"); + + // Linearize and eliminate the marginalCluster + auto actual = marginalCluster->linearizeAndEliminate(initial); + const GaussianBayesNet& bayesNet = actual.first; + const HessianFactor& factor = *actual.second; + EXPECT(assert_equal(*expected.first->at(0), *bayesNet.at(0), 1e-6)); + EXPECT(assert_equal(*expectedFactor, factor, 1e-6)); +} + +/* ************************************************************************* */ +static NonlinearClusterTree Construct() { + // Build the clusters + // NOTE(frank): Order matters here as factors are removed! + NonlinearFactorGraph graph = planarSLAMGraph(); + VariableIndex variableIndex(graph); + typedef NonlinearClusterTree::NonlinearCluster Cluster; + auto marginalCluster = boost::shared_ptr(new Cluster(variableIndex, {x1}, &graph)); + auto landmarkCluster = boost::shared_ptr(new Cluster(variableIndex, {l1, l2}, &graph)); + auto rootCluster = boost::shared_ptr(new Cluster(variableIndex, {x2, x3}, &graph)); + + // Build the tree + NonlinearClusterTree clusterTree; + clusterTree.addRoot(rootCluster); + rootCluster->addChild(landmarkCluster); + landmarkCluster->addChild(marginalCluster); + + return clusterTree; +} + +/* ************************************************************************* */ +TEST(NonlinearClusterTree, Construct) { + NonlinearClusterTree clusterTree = Construct(); + + EXPECT_LONGS_EQUAL(3, clusterTree[0].problemSize()); + EXPECT_LONGS_EQUAL(3, clusterTree[0][0].problemSize()); + EXPECT_LONGS_EQUAL(3, clusterTree[0][0][0].problemSize()); +} + +/* ************************************************************************* */ +TEST(NonlinearClusterTree, Solve) { + NonlinearClusterTree clusterTree = Construct(); + + Values expected; + expected.insert(l1, Point2(2, 2)); + expected.insert(l2, Point2(4, 2)); + expected.insert(x1, Pose2(0, 0, 0)); + expected.insert(x2, Pose2(2, 0, 0)); + expected.insert(x3, Pose2(4, 0, 0)); + + Values values = planarSLAMValues(); + for (size_t i = 0; i < 4; i++) + values = clusterTree.updateCholesky(values); + + EXPECT(assert_equal(expected, values, 1e-7)); +} + +/* ************************************************************************* */ +int main() { + TestResult tr; + return TestRegistry::runAllTests(tr); +} +/* ************************************************************************* */ diff --git a/gtsam_unstable/slam/InvDepthFactor3.h b/gtsam_unstable/slam/InvDepthFactor3.h index 7509fe3b2..0d10b0123 100644 --- a/gtsam_unstable/slam/InvDepthFactor3.h +++ b/gtsam_unstable/slam/InvDepthFactor3.h @@ -24,17 +24,17 @@ namespace gtsam { * Ternary factor representing a visual measurement that includes inverse depth */ template -class InvDepthFactor3: public gtsam::NoiseModelFactor3 { +class InvDepthFactor3: public NoiseModelFactor3 { protected: // Keep a copy of measurement and calibration for I/O - gtsam::Point2 measured_; ///< 2D measurement - boost::shared_ptr K_; ///< shared pointer to calibration object + Point2 measured_; ///< 2D measurement + boost::shared_ptr K_; ///< shared pointer to calibration object public: /// shorthand for base class type - typedef gtsam::NoiseModelFactor3 Base; + typedef NoiseModelFactor3 Base; /// shorthand for this class typedef InvDepthFactor3 This; @@ -43,7 +43,9 @@ public: typedef boost::shared_ptr shared_ptr; /// Default constructor - InvDepthFactor3() : K_(new gtsam::Cal3_S2(444, 555, 666, 777, 888)) {} + InvDepthFactor3() : + measured_(0.0, 0.0), K_(new Cal3_S2(444, 555, 666, 777, 888)) { + } /** * Constructor @@ -55,8 +57,8 @@ public: * @param invDepthKey is the index of inverse depth * @param K shared pointer to the constant calibration */ - InvDepthFactor3(const gtsam::Point2& measured, const gtsam::SharedNoiseModel& model, - const gtsam::Key poseKey, gtsam::Key pointKey, gtsam::Key invDepthKey, const Cal3_S2::shared_ptr& K) : + InvDepthFactor3(const Point2& measured, const SharedNoiseModel& model, + const Key poseKey, Key pointKey, Key invDepthKey, const Cal3_S2::shared_ptr& K) : Base(model, poseKey, pointKey, invDepthKey), measured_(measured), K_(K) {} /** Virtual destructor */ @@ -68,44 +70,43 @@ public: * @param keyFormatter optional formatter useful for printing Symbols */ void print(const std::string& s = "InvDepthFactor3", - const gtsam::KeyFormatter& keyFormatter = gtsam::DefaultKeyFormatter) const { + const KeyFormatter& keyFormatter = DefaultKeyFormatter) const { Base::print(s, keyFormatter); - measured_.print(s + ".z"); + traits::Print(measured_, s + ".z"); } /// equals - virtual bool equals(const gtsam::NonlinearFactor& p, double tol = 1e-9) const { + virtual bool equals(const NonlinearFactor& p, double tol = 1e-9) const { const This *e = dynamic_cast(&p); - return e && Base::equals(p, tol) && this->measured_.equals(e->measured_, tol) && this->K_->equals(*e->K_, tol); + return e && Base::equals(p, tol) && traits::Equals(this->measured_, e->measured_, tol) && this->K_->equals(*e->K_, tol); } /// Evaluate error h(x)-z and optionally derivatives - gtsam::Vector evaluateError(const POSE& pose, const Vector5& point, const INVDEPTH& invDepth, - boost::optional H1=boost::none, - boost::optional H2=boost::none, - boost::optional H3=boost::none) const { + Vector evaluateError(const POSE& pose, const Vector5& point, const INVDEPTH& invDepth, + boost::optional H1=boost::none, + boost::optional H2=boost::none, + boost::optional H3=boost::none) const { try { - InvDepthCamera3 camera(pose, K_); - gtsam::Point2 reprojectionError(camera.project(point, invDepth, H1, H2, H3) - measured_); - return reprojectionError.vector(); + InvDepthCamera3 camera(pose, K_); + return camera.project(point, invDepth, H1, H2, H3) - measured_; } catch( CheiralityException& e) { if (H1) *H1 = Matrix::Zero(2,6); if (H2) *H2 = Matrix::Zero(2,5); if (H3) *H2 = Matrix::Zero(2,1); std::cout << e.what() << ": Landmark "<< DefaultKeyFormatter(this->key2()) << " moved behind camera " << DefaultKeyFormatter(this->key1()) << std::endl; - return gtsam::Vector::Ones(2) * 2.0 * K_->fx(); + return Vector::Ones(2) * 2.0 * K_->fx(); } - return (gtsam::Vector(1) << 0.0).finished(); + return (Vector(1) << 0.0).finished(); } /** return the measurement */ - const gtsam::Point2& imagePoint() const { + const Point2& imagePoint() const { return measured_; } /** return the calibration object */ - inline const gtsam::Cal3_S2::shared_ptr calibration() const { + inline const Cal3_S2::shared_ptr calibration() const { return K_; } diff --git a/gtsam_unstable/slam/InvDepthFactorVariant1.h b/gtsam_unstable/slam/InvDepthFactorVariant1.h index e9f894faf..ad66eee5b 100644 --- a/gtsam_unstable/slam/InvDepthFactorVariant1.h +++ b/gtsam_unstable/slam/InvDepthFactorVariant1.h @@ -41,7 +41,9 @@ public: typedef boost::shared_ptr shared_ptr; /// Default constructor - InvDepthFactorVariant1() : K_(new Cal3_S2(444, 555, 666, 777, 888)) {} + InvDepthFactorVariant1() : + measured_(0.0, 0.0), K_(new Cal3_S2(444, 555, 666, 777, 888)) { + } /** * Constructor @@ -64,17 +66,17 @@ public: * @param keyFormatter optional formatter useful for printing Symbols */ void print(const std::string& s = "InvDepthFactorVariant1", - const gtsam::KeyFormatter& keyFormatter = gtsam::DefaultKeyFormatter) const { + const KeyFormatter& keyFormatter = DefaultKeyFormatter) const { Base::print(s, keyFormatter); - measured_.print(s + ".z"); + traits::Print(measured_, s + ".z"); } /// equals - virtual bool equals(const gtsam::NonlinearFactor& p, double tol = 1e-9) const { + virtual bool equals(const NonlinearFactor& p, double tol = 1e-9) const { const This *e = dynamic_cast(&p); return e && Base::equals(p, tol) - && this->measured_.equals(e->measured_, tol) + && traits::Equals(this->measured_, e->measured_, tol) && this->K_->equals(*e->K_, tol); } @@ -86,22 +88,21 @@ public: Point3 world_P_landmark = Point3(x, y, z) + Point3(cos(theta)*cos(phi)/rho, sin(theta)*cos(phi)/rho, sin(phi)/rho); // Project landmark into Pose2 PinholeCamera camera(pose, *K_); - gtsam::Point2 reprojectionError(camera.project(world_P_landmark) - measured_); - return reprojectionError.vector(); + return camera.project(world_P_landmark) - measured_; } catch( CheiralityException& e) { std::cout << e.what() << ": Inverse Depth Landmark [" << DefaultKeyFormatter(this->key2()) << "]" << " moved behind camera [" << DefaultKeyFormatter(this->key1()) <<"]" << std::endl; - return gtsam::Vector::Ones(2) * 2.0 * K_->fx(); + return Vector::Ones(2) * 2.0 * K_->fx(); } - return (gtsam::Vector(1) << 0.0).finished(); + return (Vector(1) << 0.0).finished(); } /// Evaluate error h(x)-z and optionally derivatives Vector evaluateError(const Pose3& pose, const Vector6& landmark, - boost::optional H1=boost::none, - boost::optional H2=boost::none) const { + boost::optional H1=boost::none, + boost::optional H2=boost::none) const { if (H1) { (*H1) = numericalDerivative11( @@ -118,7 +119,7 @@ public: } /** return the measurement */ - const gtsam::Point2& imagePoint() const { + const Point2& imagePoint() const { return measured_; } diff --git a/gtsam_unstable/slam/InvDepthFactorVariant2.h b/gtsam_unstable/slam/InvDepthFactorVariant2.h index ec2615ed6..c6b5d5af8 100644 --- a/gtsam_unstable/slam/InvDepthFactorVariant2.h +++ b/gtsam_unstable/slam/InvDepthFactorVariant2.h @@ -43,7 +43,9 @@ public: typedef boost::shared_ptr shared_ptr; /// Default constructor - InvDepthFactorVariant2() : K_(new Cal3_S2(444, 555, 666, 777, 888)) {} + InvDepthFactorVariant2() : + measured_(0.0, 0.0), K_(new Cal3_S2(444, 555, 666, 777, 888)) { + } /** * Constructor @@ -67,17 +69,17 @@ public: * @param keyFormatter optional formatter useful for printing Symbols */ void print(const std::string& s = "InvDepthFactorVariant2", - const gtsam::KeyFormatter& keyFormatter = gtsam::DefaultKeyFormatter) const { + const KeyFormatter& keyFormatter = DefaultKeyFormatter) const { Base::print(s, keyFormatter); - measured_.print(s + ".z"); + traits::Print(measured_, s + ".z"); } /// equals - virtual bool equals(const gtsam::NonlinearFactor& p, double tol = 1e-9) const { + virtual bool equals(const NonlinearFactor& p, double tol = 1e-9) const { const This *e = dynamic_cast(&p); return e && Base::equals(p, tol) - && this->measured_.equals(e->measured_, tol) + && traits::Equals(this->measured_, e->measured_, tol) && this->K_->equals(*e->K_, tol) && traits::Equals(this->referencePoint_, e->referencePoint_, tol); } @@ -89,22 +91,21 @@ public: Point3 world_P_landmark = referencePoint_ + Point3(cos(theta)*cos(phi)/rho, sin(theta)*cos(phi)/rho, sin(phi)/rho); // Project landmark into Pose2 PinholeCamera camera(pose, *K_); - gtsam::Point2 reprojectionError(camera.project(world_P_landmark) - measured_); - return reprojectionError.vector(); + return camera.project(world_P_landmark) - measured_; } catch( CheiralityException& e) { std::cout << e.what() << ": Inverse Depth Landmark [" << DefaultKeyFormatter(this->key2()) << "]" << " moved behind camera [" << DefaultKeyFormatter(this->key1()) <<"]" << std::endl; - return gtsam::Vector::Ones(2) * 2.0 * K_->fx(); + return Vector::Ones(2) * 2.0 * K_->fx(); } - return (gtsam::Vector(1) << 0.0).finished(); + return (Vector(1) << 0.0).finished(); } /// Evaluate error h(x)-z and optionally derivatives Vector evaluateError(const Pose3& pose, const Vector3& landmark, - boost::optional H1=boost::none, - boost::optional H2=boost::none) const { + boost::optional H1=boost::none, + boost::optional H2=boost::none) const { if (H1) { (*H1) = numericalDerivative11( @@ -121,7 +122,7 @@ public: } /** return the measurement */ - const gtsam::Point2& imagePoint() const { + const Point2& imagePoint() const { return measured_; } diff --git a/gtsam_unstable/slam/InvDepthFactorVariant3.h b/gtsam_unstable/slam/InvDepthFactorVariant3.h index cc5878d85..3041f5f23 100644 --- a/gtsam_unstable/slam/InvDepthFactorVariant3.h +++ b/gtsam_unstable/slam/InvDepthFactorVariant3.h @@ -41,7 +41,9 @@ public: typedef boost::shared_ptr shared_ptr; /// Default constructor - InvDepthFactorVariant3a() : K_(new Cal3_S2(444, 555, 666, 777, 888)) {} + InvDepthFactorVariant3a() : + measured_(0.0, 0.0), K_(new Cal3_S2(444, 555, 666, 777, 888)) { + } /** * Constructor @@ -66,17 +68,17 @@ public: * @param keyFormatter optional formatter useful for printing Symbols */ void print(const std::string& s = "InvDepthFactorVariant3a", - const gtsam::KeyFormatter& keyFormatter = gtsam::DefaultKeyFormatter) const { + const KeyFormatter& keyFormatter = DefaultKeyFormatter) const { Base::print(s, keyFormatter); - measured_.print(s + ".z"); + traits::Print(measured_, s + ".z"); } /// equals - virtual bool equals(const gtsam::NonlinearFactor& p, double tol = 1e-9) const { + virtual bool equals(const NonlinearFactor& p, double tol = 1e-9) const { const This *e = dynamic_cast(&p); return e && Base::equals(p, tol) - && this->measured_.equals(e->measured_, tol) + && traits::Equals(this->measured_, e->measured_, tol) && this->K_->equals(*e->K_, tol); } @@ -89,22 +91,21 @@ public: Point3 world_P_landmark = pose.transform_from(pose_P_landmark); // Project landmark into Pose2 PinholeCamera camera(pose, *K_); - gtsam::Point2 reprojectionError(camera.project(world_P_landmark) - measured_); - return reprojectionError.vector(); + return camera.project(world_P_landmark) - measured_; } catch( CheiralityException& e) { std::cout << e.what() << ": Inverse Depth Landmark [" << DefaultKeyFormatter(this->key1()) << "," << DefaultKeyFormatter(this->key2()) << "]" << " moved behind camera [" << DefaultKeyFormatter(this->key1()) << "]" << std::endl; - return gtsam::Vector::Ones(2) * 2.0 * K_->fx(); + return Vector::Ones(2) * 2.0 * K_->fx(); } return (Vector(1) << 0.0).finished(); } /// Evaluate error h(x)-z and optionally derivatives Vector evaluateError(const Pose3& pose, const Vector3& landmark, - boost::optional H1=boost::none, - boost::optional H2=boost::none) const { + boost::optional H1=boost::none, + boost::optional H2=boost::none) const { if(H1) { (*H1) = numericalDerivative11(boost::bind(&InvDepthFactorVariant3a::inverseDepthError, this, _1, landmark), pose); @@ -117,7 +118,7 @@ public: } /** return the measurement */ - const gtsam::Point2& imagePoint() const { + const Point2& imagePoint() const { return measured_; } @@ -160,7 +161,9 @@ public: typedef boost::shared_ptr shared_ptr; /// Default constructor - InvDepthFactorVariant3b() : K_(new Cal3_S2(444, 555, 666, 777, 888)) {} + InvDepthFactorVariant3b() : + measured_(0.0, 0.0), K_(new Cal3_S2(444, 555, 666, 777, 888)) { + } /** * Constructor @@ -185,17 +188,17 @@ public: * @param keyFormatter optional formatter useful for printing Symbols */ void print(const std::string& s = "InvDepthFactorVariant3", - const gtsam::KeyFormatter& keyFormatter = gtsam::DefaultKeyFormatter) const { + const KeyFormatter& keyFormatter = DefaultKeyFormatter) const { Base::print(s, keyFormatter); - measured_.print(s + ".z"); + traits::Print(measured_, s + ".z"); } /// equals - virtual bool equals(const gtsam::NonlinearFactor& p, double tol = 1e-9) const { + virtual bool equals(const NonlinearFactor& p, double tol = 1e-9) const { const This *e = dynamic_cast(&p); return e && Base::equals(p, tol) - && this->measured_.equals(e->measured_, tol) + && traits::Equals(this->measured_, e->measured_, tol) && this->K_->equals(*e->K_, tol); } @@ -208,23 +211,22 @@ public: Point3 world_P_landmark = pose1.transform_from(pose1_P_landmark); // Project landmark into Pose2 PinholeCamera camera(pose2, *K_); - gtsam::Point2 reprojectionError(camera.project(world_P_landmark) - measured_); - return reprojectionError.vector(); + return camera.project(world_P_landmark) - measured_; } catch( CheiralityException& e) { std::cout << e.what() << ": Inverse Depth Landmark [" << DefaultKeyFormatter(this->key1()) << "," << DefaultKeyFormatter(this->key3()) << "]" << " moved behind camera " << DefaultKeyFormatter(this->key2()) << std::endl; - return gtsam::Vector::Ones(2) * 2.0 * K_->fx(); + return Vector::Ones(2) * 2.0 * K_->fx(); } return (Vector(1) << 0.0).finished(); } /// Evaluate error h(x)-z and optionally derivatives Vector evaluateError(const Pose3& pose1, const Pose3& pose2, const Vector3& landmark, - boost::optional H1=boost::none, - boost::optional H2=boost::none, - boost::optional H3=boost::none) const { + boost::optional H1=boost::none, + boost::optional H2=boost::none, + boost::optional H3=boost::none) const { if(H1) (*H1) = numericalDerivative11(boost::bind(&InvDepthFactorVariant3b::inverseDepthError, this, _1, pose2, landmark), pose1); @@ -239,7 +241,7 @@ public: } /** return the measurement */ - const gtsam::Point2& imagePoint() const { + const Point2& imagePoint() const { return measured_; } diff --git a/gtsam_unstable/slam/MultiProjectionFactor.h b/gtsam_unstable/slam/MultiProjectionFactor.h index dc250fd9d..3e1263bb9 100644 --- a/gtsam_unstable/slam/MultiProjectionFactor.h +++ b/gtsam_unstable/slam/MultiProjectionFactor.h @@ -101,9 +101,9 @@ namespace gtsam { virtual ~MultiProjectionFactor() {} /// @return a deep copy of this factor - virtual gtsam::NonlinearFactor::shared_ptr clone() const { - return boost::static_pointer_cast( - gtsam::NonlinearFactor::shared_ptr(new This(*this))); } + virtual NonlinearFactor::shared_ptr clone() const { + return boost::static_pointer_cast( + NonlinearFactor::shared_ptr(new This(*this))); } /** * print @@ -143,20 +143,20 @@ namespace gtsam { // // if(body_P_sensor_) { // if(H1) { -// gtsam::Matrix H0; +// Matrix H0; // PinholeCamera camera(pose.compose(*body_P_sensor_, H0), *K_); // Point2 reprojectionError(camera.project(point, H1, H2) - measured_); // *H1 = *H1 * H0; -// return reprojectionError.vector(); +// return reprojectionError; // } else { // PinholeCamera camera(pose.compose(*body_P_sensor_), *K_); // Point2 reprojectionError(camera.project(point, H1, H2) - measured_); -// return reprojectionError.vector(); +// return reprojectionError; // } // } else { // PinholeCamera camera(pose, *K_); // Point2 reprojectionError(camera.project(point, H1, H2) - measured_); -// return reprojectionError.vector(); +// return reprojectionError; // } // } @@ -168,20 +168,20 @@ namespace gtsam { try { if(body_P_sensor_) { if(H1) { - gtsam::Matrix H0; + Matrix H0; PinholeCamera camera(pose.compose(*body_P_sensor_, H0), *K_); Point2 reprojectionError(camera.project(point, H1, H2) - measured_); *H1 = *H1 * H0; - return reprojectionError.vector(); + return reprojectionError; } else { PinholeCamera camera(pose.compose(*body_P_sensor_), *K_); Point2 reprojectionError(camera.project(point, H1, H2) - measured_); - return reprojectionError.vector(); + return reprojectionError; } } else { PinholeCamera camera(pose, *K_); Point2 reprojectionError(camera.project(point, H1, H2) - measured_); - return reprojectionError.vector(); + return reprojectionError; } } catch( CheiralityException& e) { if (H1) *H1 = Matrix::Zero(2,6); diff --git a/gtsam_unstable/slam/ProjectionFactorPPP.h b/gtsam_unstable/slam/ProjectionFactorPPP.h index adfc1d108..19b8d56e6 100644 --- a/gtsam_unstable/slam/ProjectionFactorPPP.h +++ b/gtsam_unstable/slam/ProjectionFactorPPP.h @@ -54,7 +54,9 @@ namespace gtsam { typedef boost::shared_ptr shared_ptr; /// Default constructor - ProjectionFactorPPP() : throwCheirality_(false), verboseCheirality_(false) {} + ProjectionFactorPPP() : + measured_(0.0, 0.0), throwCheirality_(false), verboseCheirality_(false) { + } /** * Constructor @@ -94,9 +96,9 @@ namespace gtsam { virtual ~ProjectionFactorPPP() {} /// @return a deep copy of this factor - virtual gtsam::NonlinearFactor::shared_ptr clone() const { - return boost::static_pointer_cast( - gtsam::NonlinearFactor::shared_ptr(new This(*this))); } + virtual NonlinearFactor::shared_ptr clone() const { + return boost::static_pointer_cast( + NonlinearFactor::shared_ptr(new This(*this))); } /** * print @@ -105,7 +107,7 @@ namespace gtsam { */ void print(const std::string& s = "", const KeyFormatter& keyFormatter = DefaultKeyFormatter) const { std::cout << s << "ProjectionFactorPPP, z = "; - measured_.print(); + traits::Print(measured_); Base::print("", keyFormatter); } @@ -114,7 +116,7 @@ namespace gtsam { const This *e = dynamic_cast(&p); return e && Base::equals(p, tol) - && this->measured_.equals(e->measured_, tol) + && traits::Equals(this->measured_, e->measured_, tol) && this->K_->equals(*e->K_, tol); } @@ -125,16 +127,15 @@ namespace gtsam { boost::optional H3 = boost::none) const { try { if(H1 || H2 || H3) { - gtsam::Matrix H0, H02; + Matrix H0, H02; PinholeCamera camera(pose.compose(transform, H0, H02), *K_); Point2 reprojectionError(camera.project(point, H1, H3, boost::none) - measured_); *H2 = *H1 * H02; *H1 = *H1 * H0; - return reprojectionError.vector(); + return reprojectionError; } else { PinholeCamera camera(pose.compose(transform), *K_); - Point2 reprojectionError(camera.project(point, H1, H3, boost::none) - measured_); - return reprojectionError.vector(); + return camera.project(point, H1, H3, boost::none) - measured_; } } catch( CheiralityException& e) { if (H1) *H1 = Matrix::Zero(2,6); diff --git a/gtsam_unstable/slam/ProjectionFactorPPPC.h b/gtsam_unstable/slam/ProjectionFactorPPPC.h index 2fd622ea1..369075abf 100644 --- a/gtsam_unstable/slam/ProjectionFactorPPPC.h +++ b/gtsam_unstable/slam/ProjectionFactorPPPC.h @@ -52,7 +52,9 @@ namespace gtsam { typedef boost::shared_ptr shared_ptr; /// Default constructor - ProjectionFactorPPPC() : throwCheirality_(false), verboseCheirality_(false) {} + ProjectionFactorPPPC() : + measured_(0.0, 0.0), throwCheirality_(false), verboseCheirality_(false) { + } /** * Constructor @@ -89,9 +91,9 @@ namespace gtsam { virtual ~ProjectionFactorPPPC() {} /// @return a deep copy of this factor - virtual gtsam::NonlinearFactor::shared_ptr clone() const { - return boost::static_pointer_cast( - gtsam::NonlinearFactor::shared_ptr(new This(*this))); } + virtual NonlinearFactor::shared_ptr clone() const { + return boost::static_pointer_cast( + NonlinearFactor::shared_ptr(new This(*this))); } /** * print @@ -100,7 +102,7 @@ namespace gtsam { */ void print(const std::string& s = "", const KeyFormatter& keyFormatter = DefaultKeyFormatter) const { std::cout << s << "ProjectionFactorPPPC, z = "; - measured_.print(); + traits::Print(measured_); Base::print("", keyFormatter); } @@ -109,7 +111,7 @@ namespace gtsam { const This *e = dynamic_cast(&p); return e && Base::equals(p, tol) - && this->measured_.equals(e->measured_, tol); + && traits::Equals(this->measured_, e->measured_, tol); } /// Evaluate error h(x)-z and optionally derivatives @@ -120,16 +122,15 @@ namespace gtsam { boost::optional H4 = boost::none) const { try { if(H1 || H2 || H3 || H4) { - gtsam::Matrix H0, H02; + Matrix H0, H02; PinholeCamera camera(pose.compose(transform, H0, H02), K); Point2 reprojectionError(camera.project(point, H1, H3, H4) - measured_); *H2 = *H1 * H02; *H1 = *H1 * H0; - return reprojectionError.vector(); + return reprojectionError; } else { PinholeCamera camera(pose.compose(transform), K); - Point2 reprojectionError(camera.project(point, H1, H3, H4) - measured_); - return reprojectionError.vector(); + return camera.project(point, H1, H3, H4) - measured_; } } catch( CheiralityException& e) { if (H1) *H1 = Matrix::Zero(2,6); diff --git a/gtsam_unstable/slam/SmartRangeFactor.h b/gtsam_unstable/slam/SmartRangeFactor.h index 0447f2e39..5e107ea58 100644 --- a/gtsam_unstable/slam/SmartRangeFactor.h +++ b/gtsam_unstable/slam/SmartRangeFactor.h @@ -101,11 +101,11 @@ public: // loop over all circles for(const Circle2& it: circles) { // distance between circle centers. - double d = circle1.center.dist(it.center); + double d = distance2(circle1.center, it.center); if (d < 1e-9) continue; // skip circles that are in the same location // Find f and h, the intersection points in normalized circles - boost::optional fh = Point2::CircleCircleIntersection( + boost::optional fh = circleCircleIntersection( circle1.radius / d, it.radius / d); // Check if this pair is better by checking h = fh->y() // if h is large, the intersections are well defined. @@ -116,15 +116,15 @@ public: } // use best fh to find actual intersection points - std::list intersections = Point2::CircleCircleIntersection( + std::list intersections = circleCircleIntersection( circle1.center, best_circle->center, best_fh); // pick winner based on other measurements double error1 = 0, error2 = 0; Point2 p1 = intersections.front(), p2 = intersections.back(); for(const Circle2& it: circles) { - error1 += it.center.dist(p1); - error2 += it.center.dist(p2); + error1 += distance2(it.center, p1); + error2 += distance2(it.center, p2); } return (error1 < error2) ? p1 : p2; //gttoc_(triangulate); diff --git a/gtsam_unstable/slam/TSAMFactors.h b/gtsam_unstable/slam/TSAMFactors.h index aae4e413d..6c2f55195 100644 --- a/gtsam_unstable/slam/TSAMFactors.h +++ b/gtsam_unstable/slam/TSAMFactors.h @@ -48,9 +48,7 @@ public: Vector evaluateError(const Pose2& pose, const Point2& point, boost::optional H1 = boost::none, boost::optional H2 = boost::none) const { - Point2 d = pose.transform_to(point, H1, H2); - Point2 e = d - measured_; - return e.vector(); + return pose.transform_to(point, H1, H2) - measured_; } }; @@ -99,12 +97,12 @@ public: *H3 = D_e_point_g * D_point_g_base2; if (H4) *H4 = D_e_point_g * D_point_g_point; - return (d - measured_).vector(); + return d - measured_; } else { Pose2 pose_g = base1.compose(pose); Point2 point_g = base2.transform_from(point); Point2 d = pose_g.transform_to(point_g); - return (d - measured_).vector(); + return d - measured_; } } }; diff --git a/matlab.h b/matlab.h index 72889dc4b..5e144730d 100644 --- a/matlab.h +++ b/matlab.h @@ -91,7 +91,7 @@ Matrix extractPoint2(const Values& values) { Values::ConstFiltered points = values.filter(); Matrix result(points.size(), 2); for(const auto& key_value: points) - result.row(j++) = key_value.value.vector(); + result.row(j++) = key_value.value; return result; } diff --git a/python/gtsam_examples/ImuFactorExample.py b/python/gtsam_examples/ImuFactorExample.py index 0c80c2fb5..781dae118 100644 --- a/python/gtsam_examples/ImuFactorExample.py +++ b/python/gtsam_examples/ImuFactorExample.py @@ -69,7 +69,7 @@ class ImuFactorExample(PreintegrationExample): # get measurements and add them to PIM measuredOmega = self.runner.measuredAngularVelocity(t) measuredAcc = self.runner.measuredSpecificForce(t) - pim.integrateMeasurement(measuredAcc, measuredOmega, self.dt, H9, H9) + pim.integrateMeasurement(measuredAcc, measuredOmega, self.dt) # Plot IMU many times if k % 10 == 0: diff --git a/python/gtsam_examples/PreintegrationExample.py b/python/gtsam_examples/PreintegrationExample.py index 6b0d83b10..b441ffecb 100644 --- a/python/gtsam_examples/PreintegrationExample.py +++ b/python/gtsam_examples/PreintegrationExample.py @@ -101,7 +101,7 @@ class PreintegrationExample(object): actualPose = self.scenario.pose(t) plotPose3(POSES_FIG, actualPose, 0.3) t = actualPose.translation() - self.maxDim = max([abs(t.x()), abs(t.y()), abs(t.z()), self.maxDim]) + self.maxDim = max([abs(t[0]), abs(t[1]), abs(t[2]), self.maxDim]) ax = plt.gca() ax.set_xlim3d(-self.maxDim, self.maxDim) ax.set_ylim3d(-self.maxDim, self.maxDim) diff --git a/python/gtsam_utils/plot.py b/python/gtsam_utils/plot.py index 01ec85009..8863f427e 100644 --- a/python/gtsam_utils/plot.py +++ b/python/gtsam_utils/plot.py @@ -33,7 +33,7 @@ def plot3DPoints(fignum, values, linespec, marginals=None): def plotPose3OnAxes(ax, pose, axisLength=0.1): # get rotation and translation (center) gRp = pose.rotation().matrix() # rotation from pose to global - C = pose.translation().vector() + C = pose.translation() # draw the camera axes xAxis = C + gRp[:, 0] * axisLength diff --git a/python/handwritten/CMakeLists.txt b/python/handwritten/CMakeLists.txt index 00900206c..fd022dd17 100644 --- a/python/handwritten/CMakeLists.txt +++ b/python/handwritten/CMakeLists.txt @@ -18,6 +18,13 @@ set_target_properties(gtsam_python PROPERTIES SKIP_BUILD_RPATH TRUE CLEAN_DIRECT_OUTPUT 1 ) + +target_include_directories(gtsam_python SYSTEM PUBLIC ${EIGEN3_INCLUDE_DIR}) +target_include_directories(gtsam_python SYSTEM PUBLIC ${NUMPY_INCLUDE_DIRS}) +target_include_directories(gtsam_python SYSTEM PUBLIC ${PYTHON_INCLUDE_DIRS}) +target_include_directories(gtsam_python SYSTEM PUBLIC ${Boost_INCLUDE_DIRS}) +target_include_directories(gtsam_python SYSTEM PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../include/) + target_link_libraries(gtsam_python ${Boost_PYTHON${BOOST_PYTHON_VERSION_SUFFIX_UPPERCASE}_LIBRARY} ${PYTHON_LIBRARY} gtsam) diff --git a/python/handwritten/common.h b/python/handwritten/common.h new file mode 100644 index 000000000..72d2ae846 --- /dev/null +++ b/python/handwritten/common.h @@ -0,0 +1,31 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @brief common macros used by handwritten exports of the python module + * @author Ellon Paiva Mendes (LAAS-CNRS) + **/ + +#pragma once + + /* Fix to avoid registration warnings */ +// Solution taken from https://github.com/BVLC/caffe/pull/4069/commits/673e8cfc0b8f05f9fa3ebbad7cc6202822e5d9c5 +#define REGISTER_SHARED_PTR_TO_PYTHON(PTR) do { \ + const boost::python::type_info info = \ + boost::python::type_id >(); \ + const boost::python::converter::registration* reg = \ + boost::python::converter::registry::query(info); \ + if (reg == NULL) { \ + boost::python::register_ptr_to_python >(); \ + } else if ((*reg).m_to_python == NULL) { \ + boost::python::register_ptr_to_python >(); \ + } \ +} while (0) diff --git a/python/handwritten/geometry/Cal3_S2.cpp b/python/handwritten/geometry/Cal3_S2.cpp index 339cd6a3c..440b21742 100644 --- a/python/handwritten/geometry/Cal3_S2.cpp +++ b/python/handwritten/geometry/Cal3_S2.cpp @@ -19,7 +19,7 @@ #define NO_IMPORT_ARRAY #include -#include "gtsam/geometry/Cal3_S2.h" +#include using namespace boost::python; using namespace gtsam; @@ -36,11 +36,12 @@ Vector3 (Cal3_S2::*calibrate2)(const Vector3 &) const = &Cal3_S2::calibrate; void exportCal3_S2(){ -class_("Cal3_S2", init<>()) +class_ >("Cal3_S2", init<>()) .def(init()) .def(init()) - .def(init()) + .def(init(args("fov","w","h"))) .def(init()) + .def(repr(self)) .def("print", &Cal3_S2::print, print_overloads(args("s"))) .def("equals", &Cal3_S2::equals, equals_overloads(args("q","tol"))) .def("fx",&Cal3_S2::fx) @@ -58,5 +59,6 @@ class_("Cal3_S2", init<>()) .def("calibrate",calibrate2) .def("between",&Cal3_S2::between, between_overloads()) ; +register_ptr_to_python< boost::shared_ptr >(); -} \ No newline at end of file +} diff --git a/python/handwritten/geometry/Point2.cpp b/python/handwritten/geometry/Point2.cpp index 7af3f8cf6..99a97adc9 100644 --- a/python/handwritten/geometry/Point2.cpp +++ b/python/handwritten/geometry/Point2.cpp @@ -25,23 +25,26 @@ using namespace boost::python; using namespace gtsam; +#ifndef GTSAM_TYPEDEF_POINTS_TO_VECTORS BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(print_overloads, Point2::print, 0, 1) BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(equals_overloads, Point2::equals, 1, 2) BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(compose_overloads, Point2::compose, 1, 3) +BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(distance_overloads, Point2::distance, 1, 3) +#endif void exportPoint2(){ +#ifndef GTSAM_TYPEDEF_POINTS_TO_VECTORS class_("Point2", init<>()) .def(init()) .def(init()) .def("identity", &Point2::identity) - .def("dist", &Point2::dist) - .def("distance", &Point2::distance) + .def("distance", &Point2::distance, distance_overloads(args("q","H1","H2"))) .def("equals", &Point2::equals, equals_overloads(args("q","tol"))) .def("norm", &Point2::norm) .def("print", &Point2::print, print_overloads(args("s"))) .def("unit", &Point2::unit) - .def("vector", &Point2::vector) + .def("vector", &Point2::vector, return_value_policy()) .def("x", &Point2::x) .def("y", &Point2::y) .def(self * other()) // __mult__ @@ -54,5 +57,5 @@ void exportPoint2(){ .def(repr(self)) .def(self == self) ; - -} \ No newline at end of file +#endif +} diff --git a/python/handwritten/geometry/Point3.cpp b/python/handwritten/geometry/Point3.cpp index de5c8e556..7935d6b37 100644 --- a/python/handwritten/geometry/Point3.cpp +++ b/python/handwritten/geometry/Point3.cpp @@ -25,31 +25,32 @@ using namespace boost::python; using namespace gtsam; +#ifndef GTSAM_TYPEDEF_POINTS_TO_VECTORS BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(print_overloads, Point3::print, 0, 1) BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(equals_overloads, Point3::equals, 1, 2) BOOST_PYTHON_MEMBER_FUNCTION_OVERLOADS(norm_overloads, Point3::norm, 0, 1) +#endif void exportPoint3(){ +#ifndef GTSAM_TYPEDEF_POINTS_TO_VECTORS class_("Point3") .def(init<>()) .def(init()) .def(init()) - .def("identity", &Point3::identity) - .staticmethod("identity") - .def("cross", &Point3::cross) - .def("distance", &Point3::distance) - .def("dot", &Point3::dot) - .def("equals", &Point3::equals, equals_overloads(args("q","tol"))) - .def("norm", &Point3::norm, norm_overloads(args("OptionalJacobian<1,3>"))) - .def("normalized", &Point3::normalized) - .def("print", &Point3::print, print_overloads(args("s"))) -#ifndef GTSAM_USE_VECTOR3_POINTS .def("vector", &Point3::vector, return_value_policy()) .def("x", &Point3::x) .def("y", &Point3::y) .def("z", &Point3::z) -#endif + .def("print", &Point3::print, print_overloads(args("s"))) + .def("equals", &Point3::equals, equals_overloads(args("q","tol"))) + .def("distance", &Point3::distance) + .def("cross", &Point3::cross) + .def("dot", &Point3::dot) + .def("norm", &Point3::norm, norm_overloads(args("OptionalJacobian<1,3>"))) + .def("normalized", &Point3::normalized) + .def("identity", &Point3::identity) + .staticmethod("identity") .def(self * other()) .def(other() * self) .def(self + self) @@ -58,7 +59,10 @@ class_("Point3") .def(self / other()) .def(self_ns::str(self)) .def(repr(self)) - .def(self == self) -; + .def(self == self); +#endif +class_("Point3Pair", init()) + .def_readwrite("first", &Point3Pair::first) + .def_readwrite("second", &Point3Pair::second); } diff --git a/python/handwritten/geometry/Rot3.cpp b/python/handwritten/geometry/Rot3.cpp index b840718a3..440559e3e 100644 --- a/python/handwritten/geometry/Rot3.cpp +++ b/python/handwritten/geometry/Rot3.cpp @@ -53,6 +53,8 @@ void exportRot3(){ class_("Rot3") .def(init()) .def(init()) + .def(init()) + .def(init()) .def(init()) .def(init()) .def("Quaternion", Quaternion_0, arg("q"), "Creates a Rot3 from an array [w,x,y,z] representing a quaternion") @@ -81,6 +83,8 @@ void exportRot3(){ .def("RzRyRx", RzRyRx_0, (arg("x"),arg("y"),arg("z")), "Rotations around Z, Y, then X axes as in http://en.wikipedia.org/wiki/Rotation_matrix, counterclockwise when looking from unchanging axis" ) .def("RzRyRx", RzRyRx_1, arg("xyz"), "Rotations around Z, Y, then X axes as in http://en.wikipedia.org/wiki/Rotation_matrix, counterclockwise when looking from unchanging axis" ) .staticmethod("RzRyRx") + .def("Ypr", &Rot3::Ypr) + .staticmethod("Ypr") .def("identity", &Rot3::identity) .staticmethod("identity") .def("AdjointMap", &Rot3::AdjointMap) diff --git a/python/handwritten/linear/NoiseModel.cpp b/python/handwritten/linear/NoiseModel.cpp index 3612f7e14..e918e509d 100644 --- a/python/handwritten/linear/NoiseModel.cpp +++ b/python/handwritten/linear/NoiseModel.cpp @@ -28,6 +28,8 @@ #include "gtsam/linear/NoiseModel.h" +#include "python/handwritten/common.h" + using namespace boost::python; using namespace gtsam; using namespace gtsam::noiseModel; @@ -100,6 +102,7 @@ void exportNoiseModels(){ class_("Base") .def("print", pure_virtual(&Base::print)) ; + register_ptr_to_python< boost::shared_ptr >(); // NOTE: We should use "Base" in "bases<...>", and not "BaseCallback" (it was not clear at the begining) class_, bases >("Gaussian", no_init) @@ -110,7 +113,7 @@ void exportNoiseModels(){ .def("Covariance",&Gaussian::Covariance, Gaussian_Covariance_overloads()) .staticmethod("Covariance") ; - register_ptr_to_python< boost::shared_ptr >(); + REGISTER_SHARED_PTR_TO_PYTHON(Gaussian); class_, bases >("Diagonal", no_init) .def("Sigmas",&Diagonal::Sigmas, Diagonal_Sigmas_overloads()) @@ -120,7 +123,7 @@ void exportNoiseModels(){ .def("Precisions",&Diagonal::Precisions, Diagonal_Precisions_overloads()) .staticmethod("Precisions") ; - register_ptr_to_python< boost::shared_ptr >(); + REGISTER_SHARED_PTR_TO_PYTHON(Diagonal); class_, bases >("Isotropic", no_init) .def("Sigma",&Isotropic::Sigma, Isotropic_Sigma_overloads()) @@ -130,12 +133,12 @@ void exportNoiseModels(){ .def("Precision",&Isotropic::Precision, Isotropic_Precision_overloads()) .staticmethod("Precision") ; - register_ptr_to_python< boost::shared_ptr >(); + REGISTER_SHARED_PTR_TO_PYTHON(Isotropic); class_, bases >("Unit", no_init) .def("Create",&Unit::Create) .staticmethod("Create") ; - register_ptr_to_python< boost::shared_ptr >(); + REGISTER_SHARED_PTR_TO_PYTHON(Unit); } diff --git a/python/handwritten/navigation/ImuFactor.cpp b/python/handwritten/navigation/ImuFactor.cpp index afc6f331d..0cf3062b5 100644 --- a/python/handwritten/navigation/ImuFactor.cpp +++ b/python/handwritten/navigation/ImuFactor.cpp @@ -22,6 +22,8 @@ #include "gtsam/navigation/ImuFactor.h" #include "gtsam/navigation/GPSFactor.h" +#include "python/handwritten/common.h" + using namespace boost::python; using namespace gtsam; @@ -78,7 +80,7 @@ void exportImuFactor() { .staticmethod("MakeSharedU"); // NOTE(frank): https://mail.python.org/pipermail/cplusplus-sig/2016-January/017362.html - register_ptr_to_python< boost::shared_ptr >(); + REGISTER_SHARED_PTR_TO_PYTHON(PreintegrationParams); class_( #ifdef GTSAM_TANGENT_PREINTEGRATION @@ -105,21 +107,21 @@ void exportImuFactor() { .def("error", &ImuFactor::error) .def(init()) .def(repr(self)); - register_ptr_to_python>(); + REGISTER_SHARED_PTR_TO_PYTHON(ImuFactor); class_, boost::shared_ptr>("ImuFactor2") .def("error", &ImuFactor2::error) .def(init()) .def(repr(self)); - register_ptr_to_python>(); + REGISTER_SHARED_PTR_TO_PYTHON(ImuFactor2); class_, boost::shared_ptr>("GPSFactor") .def("error", &GPSFactor::error) .def(init()); - register_ptr_to_python>(); + REGISTER_SHARED_PTR_TO_PYTHON(GPSFactor); class_, boost::shared_ptr>("GPSFactor2") .def("error", &GPSFactor2::error) .def(init()); - register_ptr_to_python>(); + REGISTER_SHARED_PTR_TO_PYTHON(GPSFactor2); } diff --git a/python/handwritten/nonlinear/LevenbergMarquardtOptimizer.cpp b/python/handwritten/nonlinear/LevenbergMarquardtOptimizer.cpp index f1c6a0b73..58e1d116a 100644 --- a/python/handwritten/nonlinear/LevenbergMarquardtOptimizer.cpp +++ b/python/handwritten/nonlinear/LevenbergMarquardtOptimizer.cpp @@ -15,7 +15,7 @@ void exportLevenbergMarquardtOptimizer() { .def_readwrite("maxIterations", &GaussNewtonParams::maxIterations) .def_readwrite("relativeErrorTol", &GaussNewtonParams::relativeErrorTol); - class_( + class_( "GaussNewtonOptimizer", init()) .def("optimize", &GaussNewtonOptimizer::optimize, @@ -31,7 +31,7 @@ void exportLevenbergMarquardtOptimizer() { .def("setUseFixedLambdaFactor", &LevenbergMarquardtParams::setUseFixedLambdaFactor) .def("setVerbosityLM", &LevenbergMarquardtParams::setVerbosityLM); - class_( + class_( "LevenbergMarquardtOptimizer", init()) .def("optimize", &LevenbergMarquardtOptimizer::optimize, diff --git a/python/handwritten/nonlinear/NonlinearFactor.cpp b/python/handwritten/nonlinear/NonlinearFactor.cpp index 9a130d8e9..8ccc123fc 100644 --- a/python/handwritten/nonlinear/NonlinearFactor.cpp +++ b/python/handwritten/nonlinear/NonlinearFactor.cpp @@ -28,7 +28,7 @@ using namespace gtsam; // All pure virtual methods should be wrapped. Non-pure may be wrapped if we want to mimic the // overloading through inheritance in Python. // See: http://www.boost.org/doc/libs/1_59_0/libs/python/doc/tutorial/doc/html/python/exposing.html#python.class_virtual_functions -struct NonlinearFactorCallback : NonlinearFactor, wrapper +struct NonlinearFactorWrap : NonlinearFactor, wrapper { double error (const Values & values) const { return this->get_override("error")(values); @@ -41,9 +41,35 @@ struct NonlinearFactorCallback : NonlinearFactor, wrapper } }; -void exportNonlinearFactor(){ +// Similarly for NoiseModelFactor: +struct NoiseModelFactorWrap : NoiseModelFactor, wrapper { + // NOTE(frank): Add all these again as I can't figure out how to derive + double error (const Values & values) const { + return this->get_override("error")(values); + } + size_t dim () const { + return this->get_override("dim")(); + } + boost::shared_ptr linearize(const Values & values) const { + return this->get_override("linearize")(values); + } + Vector unwhitenedError(const Values& x, + boost::optional&> H = boost::none) const { + return this->get_override("unwhitenedError")(x, H); + } +}; - class_("NonlinearFactor") - ; +void exportNonlinearFactor() { + class_("NonlinearFactor") + .def("error", pure_virtual(&NonlinearFactor::error)) + .def("dim", pure_virtual(&NonlinearFactor::dim)) + .def("linearize", pure_virtual(&NonlinearFactor::linearize)); + register_ptr_to_python >(); -} \ No newline at end of file + class_("NoiseModelFactor") + .def("error", pure_virtual(&NoiseModelFactor::error)) + .def("dim", pure_virtual(&NoiseModelFactor::dim)) + .def("linearize", pure_virtual(&NoiseModelFactor::linearize)) + .def("unwhitenedError", pure_virtual(&NoiseModelFactor::unwhitenedError)); + register_ptr_to_python >(); +} diff --git a/python/handwritten/nonlinear/NonlinearFactorGraph.cpp b/python/handwritten/nonlinear/NonlinearFactorGraph.cpp index 55929f3f1..6898133de 100644 --- a/python/handwritten/nonlinear/NonlinearFactorGraph.cpp +++ b/python/handwritten/nonlinear/NonlinearFactorGraph.cpp @@ -40,12 +40,15 @@ void exportNonlinearFactorGraph(){ typedef NonlinearFactorGraph::sharedFactor sharedFactor; void (NonlinearFactorGraph::*push_back1)(const sharedFactor&) = &NonlinearFactorGraph::push_back; + void (NonlinearFactorGraph::*push_back2)(const NonlinearFactorGraph&) = &NonlinearFactorGraph::push_back; void (NonlinearFactorGraph::*add1)(const sharedFactor&) = &NonlinearFactorGraph::add; class_("NonlinearFactorGraph", init<>()) .def("size",&NonlinearFactorGraph::size) .def("push_back", push_back1) + .def("push_back", push_back2) .def("add", add1) + .def("error", &NonlinearFactorGraph::error) .def("resize", &NonlinearFactorGraph::resize) .def("empty", &NonlinearFactorGraph::empty) .def("print", &NonlinearFactorGraph::print, print_overloads(args("s"))) diff --git a/python/handwritten/nonlinear/Values.cpp b/python/handwritten/nonlinear/Values.cpp index 0d1349972..9e4aad83f 100644 --- a/python/handwritten/nonlinear/Values.cpp +++ b/python/handwritten/nonlinear/Values.cpp @@ -47,6 +47,8 @@ void exportValues(){ void (Values::*insert_pose3) (Key, const gtsam::Pose3&) = &Values::insert; void (Values::*insert_bias) (Key, const Bias&) = &Values::insert; void (Values::*insert_navstate) (Key, const NavState&) = &Values::insert; + void (Values::*insert_vector) (Key, const gtsam::Vector&) = &Values::insert; + void (Values::*insert_vector2) (Key, const gtsam::Vector2&) = &Values::insert; void (Values::*insert_vector3) (Key, const gtsam::Vector3&) = &Values::insert; class_("Values", init<>()) @@ -67,6 +69,8 @@ void exportValues(){ .def("insert", insert_pose3) .def("insert", insert_bias) .def("insert", insert_navstate) + .def("insert", insert_vector) + .def("insert", insert_vector2) .def("insert", insert_vector3) .def("atPoint2", &Values::at) .def("atRot2", &Values::at) @@ -76,6 +80,8 @@ void exportValues(){ .def("atPose3", &Values::at) .def("atConstantBias", &Values::at) .def("atNavState", &Values::at) + .def("atVector", &Values::at) + .def("atVector2", &Values::at) .def("atVector3", &Values::at) .def("exists", exists1) .def("keys", &Values::keys) diff --git a/tests/simulated2D.h b/tests/simulated2D.h index 0012f5f45..3245652be 100644 --- a/tests/simulated2D.h +++ b/tests/simulated2D.h @@ -140,7 +140,7 @@ namespace simulated2D { /// Return error and optional derivative Vector evaluateError(const Pose& x, boost::optional H = boost::none) const { - return (prior(x, H) - measured_).vector(); + return (prior(x, H) - measured_); } virtual ~GenericPrior() {} @@ -186,7 +186,7 @@ namespace simulated2D { Vector evaluateError(const Pose& x1, const Pose& x2, boost::optional H1 = boost::none, boost::optional H2 = boost::none) const { - return (odo(x1, x2, H1, H2) - measured_).vector(); + return (odo(x1, x2, H1, H2) - measured_); } virtual ~GenericOdometry() {} @@ -233,7 +233,7 @@ namespace simulated2D { Vector evaluateError(const Pose& x1, const Landmark& x2, boost::optional H1 = boost::none, boost::optional H2 = boost::none) const { - return (mea(x1, x2, H1, H2) - measured_).vector(); + return (mea(x1, x2, H1, H2) - measured_); } virtual ~GenericMeasurement() {} diff --git a/tests/simulated2DConstraints.h b/tests/simulated2DConstraints.h index ccc734cfd..7d399dc02 100644 --- a/tests/simulated2DConstraints.h +++ b/tests/simulated2DConstraints.h @@ -111,7 +111,7 @@ namespace simulated2D { * @return a scalar distance between values */ template - double range_trait(const T1& a, const T2& b) { return a.dist(b); } + double range_trait(const T1& a, const T2& b) { return distance2(a, b); } /** * Binary inequality constraint forcing the range between points diff --git a/tests/smallExample.h b/tests/smallExample.h index 215655593..d3a69b0bd 100644 --- a/tests/smallExample.h +++ b/tests/smallExample.h @@ -180,7 +180,7 @@ inline boost::shared_ptr sharedNonlinearFactorGraph( new NonlinearFactorGraph); // prior on x1 - Point2 mu; + Point2 mu(0,0); shared_nlf f1(new simulated2D::Prior(mu, sigma0_1, X(1))); nlfg->push_back(f1); @@ -337,7 +337,7 @@ struct UnaryFactor: public gtsam::NoiseModelFactor1 { Vector evaluateError(const Point2& x, boost::optional A = boost::none) const { if (A) *A = H(x); - return (h(x) - z_).vector(); + return (h(x) - z_); } }; @@ -593,11 +593,11 @@ inline boost::tuple planarGraph(size_t N) { Values zeros; for (size_t x = 1; x <= N; x++) for (size_t y = 1; y <= N; y++) - zeros.insert(key(x, y), Point2()); + zeros.insert(key(x, y), Point2(0,0)); VectorValues xtrue; for (size_t x = 1; x <= N; x++) for (size_t y = 1; y <= N; y++) - xtrue.insert(key(x, y), Point2((double)x, (double)y).vector()); + xtrue.insert(key(x, y), Point2((double)x, (double)y)); // linearize around zero boost::shared_ptr gfg = nlfg.linearize(zeros); diff --git a/tests/testBoundingConstraint.cpp b/tests/testBoundingConstraint.cpp index b0b748d95..a5d1a195c 100644 --- a/tests/testBoundingConstraint.cpp +++ b/tests/testBoundingConstraint.cpp @@ -181,7 +181,7 @@ TEST( testBoundingConstraint, unary_simple_optimization2) { /* ************************************************************************* */ TEST( testBoundingConstraint, MaxDistance_basics) { gtsam::Key key1 = 1, key2 = 2; - Point2 pt1, pt2(1.0, 0.0), pt3(2.0, 0.0), pt4(3.0, 0.0); + Point2 pt1(0,0), pt2(1.0, 0.0), pt3(2.0, 0.0), pt4(3.0, 0.0); iq2D::PoseMaxDistConstraint rangeBound(key1, key2, 2.0, mu); EXPECT_DOUBLES_EQUAL(2.0, rangeBound.threshold(), tol); EXPECT(!rangeBound.isGreaterThan()); @@ -220,7 +220,7 @@ TEST( testBoundingConstraint, MaxDistance_basics) { /* ************************************************************************* */ TEST( testBoundingConstraint, MaxDistance_simple_optimization) { - Point2 pt1, pt2_init(5.0, 0.0), pt2_goal(2.0, 0.0); + Point2 pt1(0,0), pt2_init(5.0, 0.0), pt2_goal(2.0, 0.0); Symbol x1('x',1), x2('x',2); NonlinearFactorGraph graph; @@ -246,7 +246,7 @@ TEST( testBoundingConstraint, avoid_demo) { Symbol x1('x',1), x2('x',2), x3('x',3), l1('l',1); double radius = 1.0; - Point2 x1_pt, x2_init(2.0, 0.5), x2_goal(2.0, 1.0), x3_pt(4.0, 0.0), l1_pt(2.0, 0.0); + Point2 x1_pt(0,0), x2_init(2.0, 0.5), x2_goal(2.0, 1.0), x3_pt(4.0, 0.0), l1_pt(2.0, 0.0); Point2 odo(2.0, 0.0); NonlinearFactorGraph graph; diff --git a/tests/testDoglegOptimizer.cpp b/tests/testDoglegOptimizer.cpp index a2bb57e1c..954afa220 100644 --- a/tests/testDoglegOptimizer.cpp +++ b/tests/testDoglegOptimizer.cpp @@ -139,7 +139,7 @@ TEST(DoglegOptimizer, Iterate) { VectorValues dx_u = gbn.optimizeGradientSearch(); VectorValues dx_n = gbn.optimize(); DoglegOptimizerImpl::IterationResult result = DoglegOptimizerImpl::Iterate(Delta, DoglegOptimizerImpl::SEARCH_EACH_ITERATION, dx_u, dx_n, gbn, fg, config, fg.error(config)); - Delta = result.Delta; + Delta = result.delta; EXPECT(result.f_error < fg.error(config)); // Check that error decreases Values newConfig(config.retract(result.dx_d)); config = newConfig; diff --git a/tests/testExpressionFactor.cpp b/tests/testExpressionFactor.cpp index 4fda27cdb..b6b196acc 100644 --- a/tests/testExpressionFactor.cpp +++ b/tests/testExpressionFactor.cpp @@ -193,7 +193,7 @@ TEST(ExpressionFactor, Binary) { internal::ExecutionTraceStorage traceStorage[size]; internal::ExecutionTrace trace; Point2 value = binary.traceExecution(values, trace, traceStorage); - EXPECT(assert_equal(Point2(),value, 1e-9)); + EXPECT(assert_equal(Point2(0,0),value, 1e-9)); // trace.print(); // Expected Jacobians @@ -248,7 +248,7 @@ TEST(ExpressionFactor, Shallow) { internal::ExecutionTraceStorage traceStorage[size]; internal::ExecutionTrace trace; Point2 value = expression.traceExecution(values, trace, traceStorage); - EXPECT(assert_equal(Point2(),value, 1e-9)); + EXPECT(assert_equal(Point2(0,0),value, 1e-9)); // trace.print(); // Expected Jacobians diff --git a/tests/testExtendedKalmanFilter.cpp b/tests/testExtendedKalmanFilter.cpp index 00ab4a16c..b3e8a3449 100644 --- a/tests/testExtendedKalmanFilter.cpp +++ b/tests/testExtendedKalmanFilter.cpp @@ -226,7 +226,7 @@ public: *H2 = Matrix::Identity(dim(),dim()); // Return the error between the prediction and the supplied value of p2 - return (p2 - prediction).vector(); + return (p2 - prediction); } }; @@ -400,7 +400,7 @@ TEST( ExtendedKalmanFilter, nonlinear ) { ExtendedKalmanFilter ekf(X(0), x_initial, P_initial); // Enter Predict-Update Loop - Point2 x_predict, x_update; + Point2 x_predict(0,0), x_update(0,0); for(unsigned int i = 0; i < 10; ++i){ // Create motion factor NonlinearMotionModel motionFactor(X(i), X(i+1)); diff --git a/tests/testLie.cpp b/tests/testLie.cpp index c153adf5f..a134a899c 100644 --- a/tests/testLie.cpp +++ b/tests/testLie.cpp @@ -40,7 +40,7 @@ template<> struct traits : internal::LieGroupTraits { << m.second.theta() << ")" << endl; } static bool Equals(const Product& m1, const Product& m2, double tol = 1e-8) { - return m1.first.equals(m2.first, tol) && m1.second.equals(m2.second, tol); + return traits::Equals(m1.first, m2.first, tol) && m1.second.equals(m2.second, tol); } }; } diff --git a/tests/testManifold.cpp b/tests/testManifold.cpp index 65d26eb98..286e3ff5e 100644 --- a/tests/testManifold.cpp +++ b/tests/testManifold.cpp @@ -78,7 +78,7 @@ TEST(Manifold, Identity) { EXPECT_DOUBLES_EQUAL(0.0, traits::Identity(), 0.0); EXPECT(assert_equal(Matrix(Matrix24::Zero()), Matrix(traits::Identity()))); EXPECT(assert_equal(Pose3(), traits::Identity())); - EXPECT(assert_equal(Point2(), traits::Identity())); + EXPECT(assert_equal(Point2(0,0), traits::Identity())); } //****************************************************************************** @@ -166,7 +166,7 @@ template<> struct traits : internal::ManifoldTraits TEST(Manifold, ProductManifold) { BOOST_CONCEPT_ASSERT((IsManifold)); - MyPoint2Pair pair1; + MyPoint2Pair pair1(Point2(0,0),Point2(0,0)); Vector4 d; d << 1,2,3,4; MyPoint2Pair expected(Point2(1,2),Point2(3,4)); diff --git a/tests/testNonlinearEquality.cpp b/tests/testNonlinearEquality.cpp index 86080b673..95843e5ab 100644 --- a/tests/testNonlinearEquality.cpp +++ b/tests/testNonlinearEquality.cpp @@ -417,7 +417,7 @@ TEST( testNonlinearEqualityConstraint, odo_simple_optimize ) { graph.push_back(factor); Values initValues; - initValues.insert(key1, Point2()); + initValues.insert(key1, Point2(0,0)); initValues.insert(key2, badPt); Values actual = LevenbergMarquardtOptimizer(graph, initValues).optimize(); @@ -454,7 +454,7 @@ TEST (testNonlinearEqualityConstraint, two_pose ) { Values initialEstimate; initialEstimate.insert(x1, pt_x1); - initialEstimate.insert(x2, Point2()); + initialEstimate.insert(x2, Point2(0,0)); initialEstimate.insert(l1, Point2(1.0, 6.0)); // ground truth initialEstimate.insert(l2, Point2(-4.0, 0.0)); // starting with a separate reference frame diff --git a/tests/testNonlinearFactorGraph.cpp b/tests/testNonlinearFactorGraph.cpp index ee60f9714..9556a8018 100644 --- a/tests/testNonlinearFactorGraph.cpp +++ b/tests/testNonlinearFactorGraph.cpp @@ -1,6 +1,6 @@ /* ---------------------------------------------------------------------------- - * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * GTSAM Copyright 2010, Georgia Tech Research Corporation, * Atlanta, Georgia 30332-0415 * All Rights Reserved * Authors: Frank Dellaert, et al. (see THANKS for the full author list) @@ -9,7 +9,7 @@ * -------------------------------------------------------------------------- */ -/** +/** * @file testNonlinearFactorGraph.cpp * @brief Unit tests for Non-Linear Factor NonlinearFactorGraph * @brief testNonlinearFactorGraph @@ -107,9 +107,9 @@ TEST( NonlinearFactorGraph, linearize ) { NonlinearFactorGraph fg = createNonlinearFactorGraph(); Values initial = createNoisyValues(); - GaussianFactorGraph linearized = *fg.linearize(initial); + GaussianFactorGraph linearFG = *fg.linearize(initial); GaussianFactorGraph expected = createGaussianFactorGraph(); - CHECK(assert_equal(expected,linearized)); // Needs correct linearizations + CHECK(assert_equal(expected,linearFG)); // Needs correct linearizations } /* ************************************************************************* */ @@ -165,6 +165,38 @@ TEST( NonlinearFactorGraph, symbolic ) EXPECT(assert_equal(expected, actual)); } +/* ************************************************************************* */ +TEST(NonlinearFactorGraph, UpdateCholesky) { + NonlinearFactorGraph fg = createNonlinearFactorGraph(); + Values initial = createNoisyValues(); + + // solve conventionally + GaussianFactorGraph linearFG = *fg.linearize(initial); + auto delta = linearFG.optimizeDensely(); + auto expected = initial.retract(delta); + + // solve with new method + EXPECT(assert_equal(expected, fg.updateCholesky(initial))); + + // solve with Ordering + Ordering ordering; + ordering += L(1), X(2), X(1); + EXPECT(assert_equal(expected, fg.updateCholesky(initial, ordering))); + + // solve with new method, heavily damped + auto dampen = [](const HessianFactor::shared_ptr& hessianFactor) { + auto iterator = hessianFactor->begin(); + for (; iterator != hessianFactor->end(); iterator++) { + const auto index = std::distance(hessianFactor->begin(), iterator); + auto block = hessianFactor->info().diagonalBlock(index); + for (int j = 0; j < block.rows(); j++) { + block(j, j) += 1e9; + } + } + }; + EXPECT(assert_equal(initial, fg.updateCholesky(initial, boost::none, dampen), 1e-6)); +} + /* ************************************************************************* */ int main() { TestResult tr; return TestRegistry::runAllTests(tr); } /* ************************************************************************* */ diff --git a/tests/testNonlinearISAM.cpp b/tests/testNonlinearISAM.cpp index 3c49d54af..617a8cc1c 100644 --- a/tests/testNonlinearISAM.cpp +++ b/tests/testNonlinearISAM.cpp @@ -117,9 +117,9 @@ TEST(testNonlinearISAM, markov_chain_with_disconnects ) { new_factors += PriorFactor(lm3, landmark3, model2); // Initialize to origin - new_init.insert(lm1, Point2()); - new_init.insert(lm2, Point2()); - new_init.insert(lm3, Point2()); + new_init.insert(lm1, Point2(0,0)); + new_init.insert(lm2, Point2(0,0)); + new_init.insert(lm3, Point2(0,0)); } isamChol.update(new_factors, new_init); @@ -194,9 +194,9 @@ TEST(testNonlinearISAM, markov_chain_with_reconnect ) { new_factors += PriorFactor(lm3, landmark3, model2); // Initialize to origin - new_init.insert(lm1, Point2()); - new_init.insert(lm2, Point2()); - new_init.insert(lm3, Point2()); + new_init.insert(lm1, Point2(0,0)); + new_init.insert(lm2, Point2(0,0)); + new_init.insert(lm3, Point2(0,0)); } // Reconnect with observation later diff --git a/tests/testNonlinearOptimizer.cpp b/tests/testNonlinearOptimizer.cpp index 7a22abc67..9ddbbb1b2 100644 --- a/tests/testNonlinearOptimizer.cpp +++ b/tests/testNonlinearOptimizer.cpp @@ -32,9 +32,11 @@ #include +#include #include #include // for operator += using namespace boost::assign; +using boost::adaptors::map_values; #include #include @@ -263,13 +265,6 @@ TEST_UNSAFE(NonlinearOptimizer, MoreOptimization) { // Try LM and Dogleg LevenbergMarquardtParams params = LevenbergMarquardtParams::LegacyDefaults(); - // params.setVerbosityLM("TRYDELTA"); - // params.setVerbosity("TERMINATION"); - params.lambdaUpperBound = 1e9; -// params.relativeErrorTol = 0; -// params.absoluteErrorTol = 0; - //params.lambdaInitial = 10; - { LevenbergMarquardtOptimizer optimizer(fg, init, params); @@ -297,9 +292,11 @@ TEST_UNSAFE(NonlinearOptimizer, MoreOptimization) { // test the diagonal GaussianFactorGraph::shared_ptr linear = optimizer.linearize(); - GaussianFactorGraph damped = *optimizer.buildDampedSystem(*linear); - VectorValues d = linear->hessianDiagonal(), // - expectedDiagonal = d + params.lambdaInitial * d; + VectorValues d = linear->hessianDiagonal(); + VectorValues sqrtHessianDiagonal = d; + for (Vector& v : sqrtHessianDiagonal | map_values) v = v.cwiseSqrt(); + GaussianFactorGraph damped = optimizer.buildDampedSystem(*linear, sqrtHessianDiagonal); + VectorValues expectedDiagonal = d + params.lambdaInitial * d; EXPECT(assert_equal(expectedDiagonal, damped.hessianDiagonal())); // test convergence (does not!) @@ -311,7 +308,7 @@ TEST_UNSAFE(NonlinearOptimizer, MoreOptimization) { EXPECT(assert_equal(expectedGradient,linear->gradientAtZero())); // Check that the gradient is zero for damped system (it is not!) - damped = *optimizer.buildDampedSystem(*linear); + damped = optimizer.buildDampedSystem(*linear, sqrtHessianDiagonal); VectorValues actualGradient = damped.gradientAtZero(); EXPECT(assert_equal(expectedGradient,actualGradient)); @@ -364,8 +361,9 @@ TEST(NonlinearOptimizer, MoreOptimizationWithHuber) { expected.insert(1, Pose2(1,0,M_PI/2)); expected.insert(2, Pose2(1,1,M_PI)); + LevenbergMarquardtParams params; EXPECT(assert_equal(expected, GaussNewtonOptimizer(fg, init).optimize())); - EXPECT(assert_equal(expected, LevenbergMarquardtOptimizer(fg, init).optimize())); + EXPECT(assert_equal(expected, LevenbergMarquardtOptimizer(fg, init, params).optimize())); EXPECT(assert_equal(expected, DoglegOptimizer(fg, init).optimize())); } @@ -463,7 +461,7 @@ TEST( NonlinearOptimizer, logfile ) } /* ************************************************************************* */ -// Minimal traits example +//// Minimal traits example struct MyType : public Vector3 { using Vector3::Vector3; }; @@ -471,11 +469,13 @@ struct MyType : public Vector3 { namespace gtsam { template <> struct traits { - static bool Equals(const MyType&, const MyType&, double tol) {return true;} + static bool Equals(const MyType& a, const MyType& b, double tol) { + return (a - b).array().abs().maxCoeff() < tol; + } static void Print(const MyType&, const string&) {} - static int GetDimension(const MyType&) { return 3;} - static MyType Retract(const MyType&, const Vector3&) {return MyType();} - static Vector3 Local(const MyType&, const MyType&) {return Vector3();} + static int GetDimension(const MyType&) { return 3; } + static MyType Retract(const MyType& a, const Vector3& b) { return a + b; } + static Vector3 Local(const MyType& a, const MyType& b) { return b - a; } }; } diff --git a/timing/timeAdaptAutoDiff.cpp b/timing/timeAdaptAutoDiff.cpp index 3a9b5297a..8950c636b 100644 --- a/timing/timeAdaptAutoDiff.cpp +++ b/timing/timeAdaptAutoDiff.cpp @@ -68,7 +68,7 @@ int main() { values.insert(2,Vector3(0,0,1)); typedef AdaptAutoDiff AdaptedSnavely; Expression expression(AdaptedSnavely(), Expression(1), Expression(2)); - f2 = boost::make_shared >(model, z.vector(), expression); + f2 = boost::make_shared >(model, z, expression); time("Point2_(AdaptedSnavely(), camera, point): ", f2, values); return 0; diff --git a/timing/timeCholesky.cpp b/timing/timeCholesky.cpp new file mode 100644 index 000000000..4dd349593 --- /dev/null +++ b/timing/timeCholesky.cpp @@ -0,0 +1,60 @@ +/* ---------------------------------------------------------------------------- + + * GTSAM Copyright 2010, Georgia Tech Research Corporation, + * Atlanta, Georgia 30332-0415 + * All Rights Reserved + * Authors: Frank Dellaert, et al. (see THANKS for the full author list) + + * See LICENSE for the license information + + * -------------------------------------------------------------------------- */ + +/** + * @file timeCholesky.cpp + * @brief time Cholesky factorization + * @author Frank Dellaert + * @date March 4, 2016 + */ + +#include + +#include +#include +#include // std::setprecision + +using namespace std; +using namespace gtsam; + +//#define TERNARY + +int main() { + + Matrix top = (Matrix(7,7) << + 4.0375, 3.4584, 3.5735, 2.4815, 2.1471, 2.7400, 2.2063, + 0., 4.7267, 3.8423, 2.3624, 2.8091, 2.9579, 2.5914, + 0., 0., 5.1600, 2.0797, 3.4690, 3.2419, 2.9992, + 0., 0., 0., 1.8786, 1.0535, 1.4250, 1.3347, + 0., 0., 0., 0., 3.0788, 2.6283, 2.3791, + 0., 0., 0., 0., 0., 2.9227, 2.4056, + 0., 0., 0., 0., 0., 0., 2.5776).finished(); + + Matrix ABC(100,100); + ABC.topLeftCorner<7,7>() = top; + cout << setprecision(3); + + size_t n = 100000; + for (size_t nFrontal = 1; nFrontal <= 7; nFrontal++) { + auto timeLog = clock(); + for (size_t i = 0; i < n; i++) { + Matrix RSL(ABC); + choleskyPartial(RSL, nFrontal); + } + auto timeLog2 = clock(); + auto seconds = (double)(timeLog2 - timeLog) / CLOCKS_PER_SEC; + cout << "partialCholesky " << nFrontal << ": "; + auto ms = ((double)seconds * 1000000 / n); + cout << ms << " ms, " << ms/nFrontal << " ms/dim" << endl; + } + + return 0; +} diff --git a/timing/timePinholeCamera.cpp b/timing/timePinholeCamera.cpp index 458f88db1..1578bb0a8 100644 --- a/timing/timePinholeCamera.cpp +++ b/timing/timePinholeCamera.cpp @@ -64,7 +64,7 @@ int main() long timeLog = clock(); Point2 measurement(0,0); for(int i = 0; i < n; i++) - measurement.localCoordinates(camera.project(point1)); + camera.project(point1)-measurement; long timeLog2 = clock(); double seconds = (double)(timeLog2-timeLog)/CLOCKS_PER_SEC; cout << ((double)seconds*1e9/n) << " nanosecs/call" << endl; diff --git a/timing/timeSFMBAL.h b/timing/timeSFMBAL.h index 1642af7e8..1ca9f82d2 100644 --- a/timing/timeSFMBAL.h +++ b/timing/timeSFMBAL.h @@ -67,6 +67,7 @@ int optimize(const SfM_data& db, const NonlinearFactorGraph& graph, // Set parameters to be similar to ceres LevenbergMarquardtParams params; LevenbergMarquardtParams::SetCeresDefaults(¶ms); +// params.setLinearSolverType("SEQUENTIAL_CHOLESKY"); // params.setVerbosityLM("SUMMARY"); if (gUseSchur) { diff --git a/timing/timeSFMBALautodiff.cpp b/timing/timeSFMBALautodiff.cpp index 867953257..eb1a46606 100644 --- a/timing/timeSFMBALautodiff.cpp +++ b/timing/timeSFMBALautodiff.cpp @@ -62,11 +62,11 @@ int main(int argc, char* argv[]) { // readBAL converts to GTSAM format, so we need to convert back ! Pose3 openGLpose = gtsam2openGL(camera.pose()); Vector9 v9; - v9 << Pose3::Logmap(openGLpose), camera.calibration().vector(); + v9 << Pose3::Logmap(openGLpose), camera.calibration(); initial.insert(C(i++), v9); } for (const SfM_Track& track: db.tracks) { - Vector3 v3 = track.p.vector(); + Vector3 v3 = track.p; initial.insert(P(j++), v3); } diff --git a/wrap/matlab.h b/wrap/matlab.h index 162aaa0e2..de3027eac 100644 --- a/wrap/matlab.h +++ b/wrap/matlab.h @@ -60,15 +60,15 @@ using namespace boost; // not usual, but for conciseness of generated code // "Unique" key to signal calling the matlab object constructor with a raw pointer // to a shared pointer of the same C++ object type as the MATLAB type. // Also present in utilities.h -static const uint64_t ptr_constructor_key = - (uint64_t('G') << 56) | - (uint64_t('T') << 48) | - (uint64_t('S') << 40) | - (uint64_t('A') << 32) | - (uint64_t('M') << 24) | - (uint64_t('p') << 16) | - (uint64_t('t') << 8) | - (uint64_t('r')); +static const boost::uint64_t ptr_constructor_key = + (boost::uint64_t('G') << 56) | + (boost::uint64_t('T') << 48) | + (boost::uint64_t('S') << 40) | + (boost::uint64_t('A') << 32) | + (boost::uint64_t('M') << 24) | + (boost::uint64_t('p') << 16) | + (boost::uint64_t('t') << 8) | + (boost::uint64_t('r')); //***************************************************************************** // Utilities @@ -244,9 +244,9 @@ template T myGetScalar(const mxArray* array) { switch (mxGetClassID(array)) { case mxINT64_CLASS: - return (T) *(int64_t*) mxGetData(array); + return (T) *(boost::int64_t*) mxGetData(array); case mxUINT64_CLASS: - return (T) *(uint64_t*) mxGetData(array); + return (T) *(boost::uint64_t*) mxGetData(array); default: // hope for the best! return (T) mxGetScalar(array); @@ -349,7 +349,7 @@ mxArray* create_object(const std::string& classname, void *pointer, bool isVirtu int nargin = 2; // First input argument is pointer constructor key input[0] = mxCreateNumericMatrix(1, 1, mxUINT64_CLASS, mxREAL); - *reinterpret_cast(mxGetData(input[0])) = ptr_constructor_key; + *reinterpret_cast(mxGetData(input[0])) = ptr_constructor_key; // Second input argument is the pointer input[1] = mxCreateNumericMatrix(1, 1, mxUINT32OR64_CLASS, mxREAL); *reinterpret_cast(mxGetData(input[1])) = pointer;