snappy 3.3__cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- snappy/CyOpenGL.cpython-310-aarch64-linux-gnu.so +0 -0
- snappy/SnapPy.cpython-310-aarch64-linux-gnu.so +0 -0
- snappy/SnapPy.ico +0 -0
- snappy/SnapPy.png +0 -0
- snappy/SnapPyHP.cpython-310-aarch64-linux-gnu.so +0 -0
- snappy/__init__.py +534 -0
- snappy/app.py +604 -0
- snappy/app_menus.py +372 -0
- snappy/browser.py +998 -0
- snappy/cache.py +25 -0
- snappy/canonical.py +249 -0
- snappy/cusps/__init__.py +280 -0
- snappy/cusps/cusp_area_matrix.py +98 -0
- snappy/cusps/cusp_areas_from_matrix.py +96 -0
- snappy/cusps/maximal_cusp_area_matrix.py +136 -0
- snappy/cusps/short_slopes_for_cusp.py +217 -0
- snappy/cusps/test.py +22 -0
- snappy/cusps/trig_cusp_area_matrix.py +63 -0
- snappy/database.py +454 -0
- snappy/db_utilities.py +79 -0
- snappy/decorated_isosig.py +717 -0
- snappy/dev/__init__.py +0 -0
- snappy/dev/extended_ptolemy/__init__.py +8 -0
- snappy/dev/extended_ptolemy/closed.py +106 -0
- snappy/dev/extended_ptolemy/complexVolumesClosed.py +149 -0
- snappy/dev/extended_ptolemy/direct.py +42 -0
- snappy/dev/extended_ptolemy/extended.py +406 -0
- snappy/dev/extended_ptolemy/giac_helper.py +43 -0
- snappy/dev/extended_ptolemy/giac_rur.py +129 -0
- snappy/dev/extended_ptolemy/gluing.py +46 -0
- snappy/dev/extended_ptolemy/phc_wrapper.py +220 -0
- snappy/dev/extended_ptolemy/printMatrices.py +70 -0
- snappy/dev/vericlosed/__init__.py +1 -0
- snappy/dev/vericlosed/computeApproxHyperbolicStructureNew.py +159 -0
- snappy/dev/vericlosed/computeApproxHyperbolicStructureOrb.py +90 -0
- snappy/dev/vericlosed/computeVerifiedHyperbolicStructure.py +111 -0
- snappy/dev/vericlosed/gimbalLoopFinder.py +130 -0
- snappy/dev/vericlosed/hyperbolicStructure.py +313 -0
- snappy/dev/vericlosed/krawczykCertifiedEdgeLengthsEngine.py +165 -0
- snappy/dev/vericlosed/oneVertexTruncatedComplex.py +122 -0
- snappy/dev/vericlosed/orb/__init__.py +1 -0
- snappy/dev/vericlosed/orb/orb_solution_for_snappea_finite_triangulation_mac +0 -0
- snappy/dev/vericlosed/parseVertexGramMatrixFile.py +47 -0
- snappy/dev/vericlosed/polishApproxHyperbolicStructure.py +61 -0
- snappy/dev/vericlosed/test.py +54 -0
- snappy/dev/vericlosed/truncatedComplex.py +176 -0
- snappy/dev/vericlosed/verificationError.py +58 -0
- snappy/dev/vericlosed/verifyHyperbolicStructureEngine.py +177 -0
- snappy/doc/_images/SnapPy-196.png +0 -0
- snappy/doc/_images/m004_paper_plane_on_systole.jpg +0 -0
- snappy/doc/_images/m125_paper_plane.jpg +0 -0
- snappy/doc/_images/mac.png +0 -0
- snappy/doc/_images/o9_00000_systole_paper_plane.jpg +0 -0
- snappy/doc/_images/o9_00000_systole_paper_plane_closer.jpg +0 -0
- snappy/doc/_images/plink-action.png +0 -0
- snappy/doc/_images/ubuntu.png +0 -0
- snappy/doc/_images/win7.png +0 -0
- snappy/doc/_sources/additional_classes.rst.txt +40 -0
- snappy/doc/_sources/bugs.rst.txt +14 -0
- snappy/doc/_sources/censuses.rst.txt +52 -0
- snappy/doc/_sources/credits.rst.txt +81 -0
- snappy/doc/_sources/development.rst.txt +261 -0
- snappy/doc/_sources/index.rst.txt +215 -0
- snappy/doc/_sources/installing.rst.txt +249 -0
- snappy/doc/_sources/manifold.rst.txt +6 -0
- snappy/doc/_sources/manifoldhp.rst.txt +46 -0
- snappy/doc/_sources/news.rst.txt +425 -0
- snappy/doc/_sources/other.rst.txt +25 -0
- snappy/doc/_sources/platonic_census.rst.txt +20 -0
- snappy/doc/_sources/plink.rst.txt +102 -0
- snappy/doc/_sources/ptolemy.rst.txt +66 -0
- snappy/doc/_sources/ptolemy_classes.rst.txt +42 -0
- snappy/doc/_sources/ptolemy_examples1.rst.txt +298 -0
- snappy/doc/_sources/ptolemy_examples2.rst.txt +363 -0
- snappy/doc/_sources/ptolemy_examples3.rst.txt +301 -0
- snappy/doc/_sources/ptolemy_examples4.rst.txt +61 -0
- snappy/doc/_sources/ptolemy_prelim.rst.txt +105 -0
- snappy/doc/_sources/screenshots.rst.txt +21 -0
- snappy/doc/_sources/snap.rst.txt +87 -0
- snappy/doc/_sources/snappy.rst.txt +28 -0
- snappy/doc/_sources/spherogram.rst.txt +103 -0
- snappy/doc/_sources/todo.rst.txt +47 -0
- snappy/doc/_sources/triangulation.rst.txt +11 -0
- snappy/doc/_sources/tutorial.rst.txt +49 -0
- snappy/doc/_sources/verify.rst.txt +210 -0
- snappy/doc/_sources/verify_internals.rst.txt +79 -0
- snappy/doc/_static/SnapPy-horizontal-128.png +0 -0
- snappy/doc/_static/SnapPy.ico +0 -0
- snappy/doc/_static/_sphinx_javascript_frameworks_compat.js +123 -0
- snappy/doc/_static/basic.css +906 -0
- snappy/doc/_static/css/badge_only.css +1 -0
- snappy/doc/_static/css/fonts/Roboto-Slab-Bold.woff +0 -0
- snappy/doc/_static/css/fonts/Roboto-Slab-Bold.woff2 +0 -0
- snappy/doc/_static/css/fonts/Roboto-Slab-Regular.woff +0 -0
- snappy/doc/_static/css/fonts/Roboto-Slab-Regular.woff2 +0 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.eot +0 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.svg +2671 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.ttf +0 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.woff +0 -0
- snappy/doc/_static/css/fonts/fontawesome-webfont.woff2 +0 -0
- snappy/doc/_static/css/fonts/lato-bold-italic.woff +0 -0
- snappy/doc/_static/css/fonts/lato-bold-italic.woff2 +0 -0
- snappy/doc/_static/css/fonts/lato-bold.woff +0 -0
- snappy/doc/_static/css/fonts/lato-bold.woff2 +0 -0
- snappy/doc/_static/css/fonts/lato-normal-italic.woff +0 -0
- snappy/doc/_static/css/fonts/lato-normal-italic.woff2 +0 -0
- snappy/doc/_static/css/fonts/lato-normal.woff +0 -0
- snappy/doc/_static/css/fonts/lato-normal.woff2 +0 -0
- snappy/doc/_static/css/theme.css +4 -0
- snappy/doc/_static/doctools.js +149 -0
- snappy/doc/_static/documentation_options.js +13 -0
- snappy/doc/_static/file.png +0 -0
- snappy/doc/_static/fonts/Lato/lato-bold.eot +0 -0
- snappy/doc/_static/fonts/Lato/lato-bold.ttf +0 -0
- snappy/doc/_static/fonts/Lato/lato-bold.woff +0 -0
- snappy/doc/_static/fonts/Lato/lato-bold.woff2 +0 -0
- snappy/doc/_static/fonts/Lato/lato-bolditalic.eot +0 -0
- snappy/doc/_static/fonts/Lato/lato-bolditalic.ttf +0 -0
- snappy/doc/_static/fonts/Lato/lato-bolditalic.woff +0 -0
- snappy/doc/_static/fonts/Lato/lato-bolditalic.woff2 +0 -0
- snappy/doc/_static/fonts/Lato/lato-italic.eot +0 -0
- snappy/doc/_static/fonts/Lato/lato-italic.ttf +0 -0
- snappy/doc/_static/fonts/Lato/lato-italic.woff +0 -0
- snappy/doc/_static/fonts/Lato/lato-italic.woff2 +0 -0
- snappy/doc/_static/fonts/Lato/lato-regular.eot +0 -0
- snappy/doc/_static/fonts/Lato/lato-regular.ttf +0 -0
- snappy/doc/_static/fonts/Lato/lato-regular.woff +0 -0
- snappy/doc/_static/fonts/Lato/lato-regular.woff2 +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.eot +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.ttf +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-bold.woff2 +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.eot +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.ttf +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff +0 -0
- snappy/doc/_static/fonts/RobotoSlab/roboto-slab-v7-regular.woff2 +0 -0
- snappy/doc/_static/jquery.js +2 -0
- snappy/doc/_static/js/badge_only.js +1 -0
- snappy/doc/_static/js/theme.js +1 -0
- snappy/doc/_static/js/versions.js +228 -0
- snappy/doc/_static/language_data.js +192 -0
- snappy/doc/_static/minus.png +0 -0
- snappy/doc/_static/plus.png +0 -0
- snappy/doc/_static/pygments.css +75 -0
- snappy/doc/_static/searchtools.js +635 -0
- snappy/doc/_static/snappy_furo.css +33 -0
- snappy/doc/_static/snappy_sphinx_rtd_theme.css +42 -0
- snappy/doc/_static/sphinx_highlight.js +154 -0
- snappy/doc/additional_classes.html +1500 -0
- snappy/doc/bugs.html +132 -0
- snappy/doc/censuses.html +453 -0
- snappy/doc/credits.html +184 -0
- snappy/doc/development.html +385 -0
- snappy/doc/doc-latest/additional_classes.html +1500 -0
- snappy/doc/doc-latest/bugs.html +132 -0
- snappy/doc/doc-latest/censuses.html +453 -0
- snappy/doc/doc-latest/credits.html +184 -0
- snappy/doc/doc-latest/development.html +385 -0
- snappy/doc/doc-latest/genindex.html +1349 -0
- snappy/doc/doc-latest/index.html +287 -0
- snappy/doc/doc-latest/installing.html +346 -0
- snappy/doc/doc-latest/manifold.html +3632 -0
- snappy/doc/doc-latest/manifoldhp.html +180 -0
- snappy/doc/doc-latest/news.html +438 -0
- snappy/doc/doc-latest/objects.inv +0 -0
- snappy/doc/doc-latest/other.html +160 -0
- snappy/doc/doc-latest/platonic_census.html +376 -0
- snappy/doc/doc-latest/plink.html +210 -0
- snappy/doc/doc-latest/ptolemy.html +253 -0
- snappy/doc/doc-latest/ptolemy_classes.html +1144 -0
- snappy/doc/doc-latest/ptolemy_examples1.html +409 -0
- snappy/doc/doc-latest/ptolemy_examples2.html +471 -0
- snappy/doc/doc-latest/ptolemy_examples3.html +414 -0
- snappy/doc/doc-latest/ptolemy_examples4.html +195 -0
- snappy/doc/doc-latest/ptolemy_prelim.html +248 -0
- snappy/doc/doc-latest/py-modindex.html +165 -0
- snappy/doc/doc-latest/screenshots.html +141 -0
- snappy/doc/doc-latest/search.html +135 -0
- snappy/doc/doc-latest/searchindex.js +1 -0
- snappy/doc/doc-latest/snap.html +202 -0
- snappy/doc/doc-latest/snappy.html +181 -0
- snappy/doc/doc-latest/spherogram.html +1346 -0
- snappy/doc/doc-latest/todo.html +166 -0
- snappy/doc/doc-latest/triangulation.html +1676 -0
- snappy/doc/doc-latest/tutorial.html +159 -0
- snappy/doc/doc-latest/verify.html +330 -0
- snappy/doc/doc-latest/verify_internals.html +1235 -0
- snappy/doc/genindex.html +1349 -0
- snappy/doc/index.html +287 -0
- snappy/doc/installing.html +346 -0
- snappy/doc/manifold.html +3632 -0
- snappy/doc/manifoldhp.html +180 -0
- snappy/doc/news.html +438 -0
- snappy/doc/objects.inv +0 -0
- snappy/doc/other.html +160 -0
- snappy/doc/platonic_census.html +376 -0
- snappy/doc/plink.html +210 -0
- snappy/doc/ptolemy.html +253 -0
- snappy/doc/ptolemy_classes.html +1144 -0
- snappy/doc/ptolemy_examples1.html +409 -0
- snappy/doc/ptolemy_examples2.html +471 -0
- snappy/doc/ptolemy_examples3.html +414 -0
- snappy/doc/ptolemy_examples4.html +195 -0
- snappy/doc/ptolemy_prelim.html +248 -0
- snappy/doc/py-modindex.html +165 -0
- snappy/doc/screenshots.html +141 -0
- snappy/doc/search.html +135 -0
- snappy/doc/searchindex.js +1 -0
- snappy/doc/snap.html +202 -0
- snappy/doc/snappy.html +181 -0
- snappy/doc/spherogram.html +1346 -0
- snappy/doc/todo.html +166 -0
- snappy/doc/triangulation.html +1676 -0
- snappy/doc/tutorial.html +159 -0
- snappy/doc/verify.html +330 -0
- snappy/doc/verify_internals.html +1235 -0
- snappy/drilling/__init__.py +456 -0
- snappy/drilling/barycentric.py +103 -0
- snappy/drilling/constants.py +5 -0
- snappy/drilling/crush.py +270 -0
- snappy/drilling/cusps.py +125 -0
- snappy/drilling/debug.py +242 -0
- snappy/drilling/epsilons.py +6 -0
- snappy/drilling/exceptions.py +55 -0
- snappy/drilling/moves.py +620 -0
- snappy/drilling/peripheral_curves.py +210 -0
- snappy/drilling/perturb.py +188 -0
- snappy/drilling/shorten.py +36 -0
- snappy/drilling/subdivide.py +274 -0
- snappy/drilling/test.py +23 -0
- snappy/drilling/test_cases.py +132 -0
- snappy/drilling/tracing.py +351 -0
- snappy/exceptions.py +26 -0
- snappy/export_stl.py +120 -0
- snappy/exterior_to_link/__init__.py +2 -0
- snappy/exterior_to_link/barycentric_geometry.py +463 -0
- snappy/exterior_to_link/exceptions.py +6 -0
- snappy/exterior_to_link/geodesic_map.json +14408 -0
- snappy/exterior_to_link/hyp_utils.py +112 -0
- snappy/exterior_to_link/link_projection.py +323 -0
- snappy/exterior_to_link/main.py +198 -0
- snappy/exterior_to_link/mcomplex_with_expansion.py +261 -0
- snappy/exterior_to_link/mcomplex_with_link.py +687 -0
- snappy/exterior_to_link/mcomplex_with_memory.py +162 -0
- snappy/exterior_to_link/pl_utils.py +491 -0
- snappy/exterior_to_link/put_in_S3.py +156 -0
- snappy/exterior_to_link/rational_linear_algebra.py +130 -0
- snappy/exterior_to_link/rational_linear_algebra_wrapped.py +135 -0
- snappy/exterior_to_link/simplify_to_base_tri.py +114 -0
- snappy/exterior_to_link/stored_moves.py +475 -0
- snappy/exterior_to_link/test.py +31 -0
- snappy/filedialog.py +28 -0
- snappy/geometric_structure/__init__.py +212 -0
- snappy/geometric_structure/cusp_neighborhood/__init__.py +3 -0
- snappy/geometric_structure/cusp_neighborhood/complex_cusp_cross_section.py +691 -0
- snappy/geometric_structure/cusp_neighborhood/cusp_cross_section_base.py +480 -0
- snappy/geometric_structure/cusp_neighborhood/exceptions.py +41 -0
- snappy/geometric_structure/cusp_neighborhood/real_cusp_cross_section.py +294 -0
- snappy/geometric_structure/cusp_neighborhood/tiles_for_cusp_neighborhood.py +156 -0
- snappy/geometric_structure/cusp_neighborhood/vertices.py +35 -0
- snappy/geometric_structure/geodesic/__init__.py +0 -0
- snappy/geometric_structure/geodesic/add_core_curves.py +152 -0
- snappy/geometric_structure/geodesic/avoid_core_curves.py +369 -0
- snappy/geometric_structure/geodesic/canonical_representatives.py +52 -0
- snappy/geometric_structure/geodesic/check_away_from_core_curve.py +60 -0
- snappy/geometric_structure/geodesic/constants.py +6 -0
- snappy/geometric_structure/geodesic/exceptions.py +22 -0
- snappy/geometric_structure/geodesic/fixed_points.py +106 -0
- snappy/geometric_structure/geodesic/geodesic_start_point_info.py +435 -0
- snappy/geometric_structure/geodesic/graph_trace_helper.py +67 -0
- snappy/geometric_structure/geodesic/line.py +30 -0
- snappy/geometric_structure/geodesic/multiplicity.py +127 -0
- snappy/geometric_structure/geodesic/tiles_for_geodesic.py +128 -0
- snappy/geometric_structure/test.py +22 -0
- snappy/gui.py +121 -0
- snappy/horoviewer.py +443 -0
- snappy/hyperboloid/__init__.py +212 -0
- snappy/hyperboloid/distances.py +259 -0
- snappy/hyperboloid/horoball.py +19 -0
- snappy/hyperboloid/line.py +35 -0
- snappy/hyperboloid/point.py +9 -0
- snappy/hyperboloid/triangle.py +29 -0
- snappy/info_icon.gif +0 -0
- snappy/infowindow.py +65 -0
- snappy/isometry_signature.py +389 -0
- snappy/len_spec/__init__.py +609 -0
- snappy/len_spec/geodesic_info.py +129 -0
- snappy/len_spec/geodesic_key_info_dict.py +116 -0
- snappy/len_spec/geodesic_piece.py +146 -0
- snappy/len_spec/geometric_structure.py +182 -0
- snappy/len_spec/geometry.py +136 -0
- snappy/len_spec/length_spectrum_geodesic_info.py +185 -0
- snappy/len_spec/spine.py +128 -0
- snappy/len_spec/test.py +24 -0
- snappy/len_spec/test_cases.py +69 -0
- snappy/len_spec/tile.py +276 -0
- snappy/len_spec/word.py +86 -0
- snappy/manifolds/HTWKnots/alternating.gz +0 -0
- snappy/manifolds/HTWKnots/nonalternating.gz +0 -0
- snappy/manifolds/__init__.py +3 -0
- snappy/margulis/__init__.py +332 -0
- snappy/margulis/cusp_neighborhood_neighborhood.py +66 -0
- snappy/margulis/geodesic_neighborhood.py +152 -0
- snappy/margulis/margulis_info.py +21 -0
- snappy/margulis/mu_from_neighborhood_pair.py +175 -0
- snappy/margulis/neighborhood.py +29 -0
- snappy/margulis/test.py +22 -0
- snappy/math_basics.py +187 -0
- snappy/matrix.py +525 -0
- snappy/number.py +657 -0
- snappy/numeric_output_checker.py +345 -0
- snappy/pari.py +41 -0
- snappy/phone_home.py +57 -0
- snappy/polyviewer.py +259 -0
- snappy/ptolemy/__init__.py +17 -0
- snappy/ptolemy/component.py +103 -0
- snappy/ptolemy/coordinates.py +2290 -0
- snappy/ptolemy/fieldExtensions.py +153 -0
- snappy/ptolemy/findLoops.py +473 -0
- snappy/ptolemy/geometricRep.py +59 -0
- snappy/ptolemy/homology.py +165 -0
- snappy/ptolemy/magma/default.magma_template +229 -0
- snappy/ptolemy/magma/radicalsOfPrimaryDecomposition.magma_template +79 -0
- snappy/ptolemy/manifoldMethods.py +395 -0
- snappy/ptolemy/matrix.py +350 -0
- snappy/ptolemy/numericalSolutionsToGroebnerBasis.py +113 -0
- snappy/ptolemy/polynomial.py +856 -0
- snappy/ptolemy/processComponents.py +173 -0
- snappy/ptolemy/processFileBase.py +247 -0
- snappy/ptolemy/processFileDispatch.py +46 -0
- snappy/ptolemy/processMagmaFile.py +392 -0
- snappy/ptolemy/processRurFile.py +150 -0
- snappy/ptolemy/ptolemyGeneralizedObstructionClass.py +102 -0
- snappy/ptolemy/ptolemyObstructionClass.py +64 -0
- snappy/ptolemy/ptolemyVariety.py +995 -0
- snappy/ptolemy/ptolemyVarietyPrimeIdealGroebnerBasis.py +140 -0
- snappy/ptolemy/reginaWrapper.py +698 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c2.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c3.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c4.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c5.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c6.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files/DT_mcbbiceaibjklmdfgh__sl2_c7.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m003__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m003__sl3_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m015__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m015__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m015__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/regina_testing_files_generalized/m015__sl3_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/rur.py +545 -0
- snappy/ptolemy/solutionsToPrimeIdealGroebnerBasis.py +277 -0
- snappy/ptolemy/test.py +1126 -0
- snappy/ptolemy/testing_files/3_1__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/3_1__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/4_1__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/4_1__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/4_1__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/4_1__sl4_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/4_1__sl4_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/5_2__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/5_2__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c2.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c3.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c4.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c5.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c6.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/DT_mcbbiceaibjklmdfgh__sl2_c7.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/data/pgl2/OrientableCuspedCensus/03_tetrahedra/m019__sl2_c0.magma_out +95 -0
- snappy/ptolemy/testing_files/data/pgl2/OrientableCuspedCensus/03_tetrahedra/m019__sl2_c1.magma_out +95 -0
- snappy/ptolemy/testing_files/m015__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c2.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c3.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c4.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c5.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c6.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/m135__sl2_c7.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/s000__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/s000__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/t00000__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/t00000__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/v0000__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/v0000__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/v0000__sl2_c2.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files/v0000__sl2_c3.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m003__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m003__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m003__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m003__sl3_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m004__sl2_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m004__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m015__sl2_c1.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_generalized/m015__sl3_c0.magma_out.bz2 +0 -0
- snappy/ptolemy/testing_files_rur/m052__sl3_c0.rur.bz2 +0 -0
- snappy/ptolemy/utilities.py +236 -0
- snappy/raytracing/__init__.py +64 -0
- snappy/raytracing/additional_horospheres.py +64 -0
- snappy/raytracing/additional_len_spec_choices.py +63 -0
- snappy/raytracing/cohomology_fractal.py +197 -0
- snappy/raytracing/eyeball.py +124 -0
- snappy/raytracing/finite_raytracing_data.py +237 -0
- snappy/raytracing/finite_viewer.py +590 -0
- snappy/raytracing/geodesic_tube_info.py +174 -0
- snappy/raytracing/geodesics.py +246 -0
- snappy/raytracing/geodesics_window.py +258 -0
- snappy/raytracing/gui_utilities.py +293 -0
- snappy/raytracing/hyperboloid_navigation.py +556 -0
- snappy/raytracing/hyperboloid_utilities.py +234 -0
- snappy/raytracing/ideal_raytracing_data.py +592 -0
- snappy/raytracing/inside_viewer.py +974 -0
- snappy/raytracing/pack.py +22 -0
- snappy/raytracing/raytracing_data.py +126 -0
- snappy/raytracing/raytracing_view.py +454 -0
- snappy/raytracing/shaders/Eye.png +0 -0
- snappy/raytracing/shaders/NonGeometric.png +0 -0
- snappy/raytracing/shaders/__init__.py +101 -0
- snappy/raytracing/shaders/fragment.glsl +1744 -0
- snappy/raytracing/test.py +29 -0
- snappy/raytracing/tooltip.py +146 -0
- snappy/raytracing/upper_halfspace_utilities.py +98 -0
- snappy/raytracing/view_scale_controller.py +98 -0
- snappy/raytracing/zoom_slider/__init__.py +263 -0
- snappy/raytracing/zoom_slider/inward.png +0 -0
- snappy/raytracing/zoom_slider/inward18.png +0 -0
- snappy/raytracing/zoom_slider/outward.png +0 -0
- snappy/raytracing/zoom_slider/outward18.png +0 -0
- snappy/raytracing/zoom_slider/test.py +20 -0
- snappy/sage_helper.py +119 -0
- snappy/settings.py +407 -0
- snappy/shell.py +53 -0
- snappy/snap/__init__.py +117 -0
- snappy/snap/character_varieties.py +375 -0
- snappy/snap/find_field.py +372 -0
- snappy/snap/fox_milnor.py +271 -0
- snappy/snap/fundamental_polyhedron.py +569 -0
- snappy/snap/generators.py +39 -0
- snappy/snap/interval_reps.py +81 -0
- snappy/snap/kernel_structures.py +128 -0
- snappy/snap/mcomplex_base.py +18 -0
- snappy/snap/nsagetools.py +716 -0
- snappy/snap/peripheral/__init__.py +1 -0
- snappy/snap/peripheral/dual_cellulation.py +219 -0
- snappy/snap/peripheral/link.py +127 -0
- snappy/snap/peripheral/peripheral.py +159 -0
- snappy/snap/peripheral/surface.py +522 -0
- snappy/snap/peripheral/test.py +35 -0
- snappy/snap/polished_reps.py +335 -0
- snappy/snap/shapes.py +152 -0
- snappy/snap/slice_obs_HKL/__init__.py +194 -0
- snappy/snap/slice_obs_HKL/basics.py +236 -0
- snappy/snap/slice_obs_HKL/direct.py +217 -0
- snappy/snap/slice_obs_HKL/poly_norm.py +212 -0
- snappy/snap/slice_obs_HKL/rep_theory.py +424 -0
- snappy/snap/t3mlite/__init__.py +2 -0
- snappy/snap/t3mlite/arrow.py +243 -0
- snappy/snap/t3mlite/corner.py +22 -0
- snappy/snap/t3mlite/edge.py +172 -0
- snappy/snap/t3mlite/face.py +37 -0
- snappy/snap/t3mlite/files.py +211 -0
- snappy/snap/t3mlite/homology.py +53 -0
- snappy/snap/t3mlite/linalg.py +419 -0
- snappy/snap/t3mlite/mcomplex.py +1499 -0
- snappy/snap/t3mlite/perm4.py +320 -0
- snappy/snap/t3mlite/setup.py +12 -0
- snappy/snap/t3mlite/simplex.py +199 -0
- snappy/snap/t3mlite/spun.py +297 -0
- snappy/snap/t3mlite/surface.py +519 -0
- snappy/snap/t3mlite/test.py +20 -0
- snappy/snap/t3mlite/test_vs_regina.py +86 -0
- snappy/snap/t3mlite/tetrahedron.py +109 -0
- snappy/snap/t3mlite/vertex.py +42 -0
- snappy/snap/test.py +139 -0
- snappy/snap/utilities.py +288 -0
- snappy/test.py +213 -0
- snappy/test_cases.py +263 -0
- snappy/testing.py +131 -0
- snappy/tiling/__init__.py +2 -0
- snappy/tiling/dict_based_set.py +79 -0
- snappy/tiling/floor.py +49 -0
- snappy/tiling/hyperboloid_dict.py +54 -0
- snappy/tiling/iter_utils.py +78 -0
- snappy/tiling/lifted_tetrahedron.py +22 -0
- snappy/tiling/lifted_tetrahedron_set.py +54 -0
- snappy/tiling/quotient_dict.py +70 -0
- snappy/tiling/real_hash_dict.py +164 -0
- snappy/tiling/test.py +23 -0
- snappy/tiling/tile.py +224 -0
- snappy/tiling/triangle.py +33 -0
- snappy/tkterminal.py +920 -0
- snappy/twister/__init__.py +20 -0
- snappy/twister/main.py +646 -0
- snappy/twister/surfaces/S_0_1 +3 -0
- snappy/twister/surfaces/S_0_2 +3 -0
- snappy/twister/surfaces/S_0_4 +7 -0
- snappy/twister/surfaces/S_0_4_Lantern +8 -0
- snappy/twister/surfaces/S_1 +3 -0
- snappy/twister/surfaces/S_1_1 +4 -0
- snappy/twister/surfaces/S_1_2 +5 -0
- snappy/twister/surfaces/S_1_2_5 +6 -0
- snappy/twister/surfaces/S_2 +6 -0
- snappy/twister/surfaces/S_2_1 +8 -0
- snappy/twister/surfaces/S_2_heeg +10 -0
- snappy/twister/surfaces/S_3 +8 -0
- snappy/twister/surfaces/S_3_1 +10 -0
- snappy/twister/surfaces/S_4_1 +12 -0
- snappy/twister/surfaces/S_5_1 +14 -0
- snappy/twister/surfaces/heeg_fig8 +9 -0
- snappy/twister/twister_core.cpython-310-aarch64-linux-gnu.so +0 -0
- snappy/upper_halfspace/__init__.py +146 -0
- snappy/upper_halfspace/ideal_point.py +29 -0
- snappy/verify/__init__.py +13 -0
- snappy/verify/canonical.py +542 -0
- snappy/verify/complex_volume/__init__.py +18 -0
- snappy/verify/complex_volume/adjust_torsion.py +86 -0
- snappy/verify/complex_volume/closed.py +168 -0
- snappy/verify/complex_volume/compute_ptolemys.py +90 -0
- snappy/verify/complex_volume/cusped.py +56 -0
- snappy/verify/complex_volume/extended_bloch.py +201 -0
- snappy/verify/cusp_translations.py +85 -0
- snappy/verify/edge_equations.py +80 -0
- snappy/verify/exceptions.py +254 -0
- snappy/verify/hyperbolicity.py +224 -0
- snappy/verify/interval_newton_shapes_engine.py +523 -0
- snappy/verify/interval_tree.py +400 -0
- snappy/verify/krawczyk_shapes_engine.py +518 -0
- snappy/verify/real_algebra.py +286 -0
- snappy/verify/shapes.py +25 -0
- snappy/verify/square_extensions.py +1005 -0
- snappy/verify/test.py +72 -0
- snappy/verify/volume.py +128 -0
- snappy/version.py +2 -0
- snappy-3.3.dist-info/METADATA +58 -0
- snappy-3.3.dist-info/RECORD +541 -0
- snappy-3.3.dist-info/WHEEL +6 -0
- snappy-3.3.dist-info/entry_points.txt +2 -0
- snappy-3.3.dist-info/top_level.txt +28 -0
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
from . import constants
|
|
2
|
+
from . import exceptions
|
|
3
|
+
|
|
4
|
+
from .line import R13LineWithMatrix
|
|
5
|
+
from .fixed_points import r13_fixed_line_of_psl2c_matrix
|
|
6
|
+
from .multiplicity import compute_and_verify_multiplicity
|
|
7
|
+
from .graph_trace_helper import find_lifted_tetrahedra_containing_point
|
|
8
|
+
|
|
9
|
+
from .. import word_to_psl2c_matrix
|
|
10
|
+
|
|
11
|
+
from ...tiling.lifted_tetrahedron import LiftedTetrahedron
|
|
12
|
+
from ...hyperboloid import r13_dot, o13_inverse # type: ignore
|
|
13
|
+
from ...hyperboloid.distances import distance_r13_points
|
|
14
|
+
from ...hyperboloid.line import R13Line
|
|
15
|
+
from ...snap.t3mlite import simplex # type: ignore
|
|
16
|
+
from ...snap.t3mlite import Tetrahedron, Vertex, Mcomplex # type: ignore
|
|
17
|
+
from ...exceptions import InsufficientPrecisionError # type: ignore
|
|
18
|
+
from ...matrix import make_identity_matrix # type: ignore
|
|
19
|
+
|
|
20
|
+
from typing import Tuple, Sequence, Optional, Any
|
|
21
|
+
|
|
22
|
+
__all__ = ['compute_geodsic_info', 'GeodesicStartPointInfo', 'sample_line']
|
|
23
|
+
|
|
24
|
+
def sample_line(line : R13Line):
|
|
25
|
+
"""
|
|
26
|
+
Pick a point on a line in the hyperboloid model.
|
|
27
|
+
Returns an unnormalised time-like vector computed
|
|
28
|
+
as the weighted average of the two light-like
|
|
29
|
+
endpoints of the line.
|
|
30
|
+
|
|
31
|
+
The ratio of the weights is some fixed number picked at random so
|
|
32
|
+
that we avoid picking a point that lies, e.g., on an edge of the
|
|
33
|
+
triangulation (which happens for some geodesics in some
|
|
34
|
+
triangulated hyperbolic manifolds when picking equal weights for
|
|
35
|
+
the fixed points computed by r13_fixed_points_of_psl2c_matrix).
|
|
36
|
+
|
|
37
|
+
Note that we want to avoid picking a point that is far away from
|
|
38
|
+
the fundamental polyhedron. By the choices we made, this is not
|
|
39
|
+
the case: the fundamental polyhedron is contains the origin in the
|
|
40
|
+
hyperboloid model. r13_fixed_points_of_psl2c_matrix returns
|
|
41
|
+
light-like vectors of the form (1, ...) so the average corresponds
|
|
42
|
+
to taking the mid-point in the Klein model and is thus the point
|
|
43
|
+
on the line closest to the origin. Furthermore, the bias is close
|
|
44
|
+
enough to 1 (the log is ~0.22, so we move the point by ~0.11
|
|
45
|
+
units in hyperbolic space).
|
|
46
|
+
"""
|
|
47
|
+
|
|
48
|
+
RF = line.points[0][0].parent()
|
|
49
|
+
bias = RF(constants.start_point_bias)
|
|
50
|
+
|
|
51
|
+
return line.points[0] + bias * line.points[1]
|
|
52
|
+
|
|
53
|
+
# @dataclass
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
class GeodesicStartPointInfo:
|
|
57
|
+
"""
|
|
58
|
+
Information needed to trace a closed geodesic through a triangulation
|
|
59
|
+
given as snappy.snap.t3mlite.Mcomplex with geometric structure added
|
|
60
|
+
by add_r13_geometry.
|
|
61
|
+
|
|
62
|
+
The basic information consists of a line in the hyperboloid model
|
|
63
|
+
that is a lift of the closed geodesic and a start and end point on or
|
|
64
|
+
close to that line such that the line segment from the start to the
|
|
65
|
+
end point maps to a simple closed curve in the manifold isotopic to
|
|
66
|
+
the closed geodesic.
|
|
67
|
+
|
|
68
|
+
If a client has instantiated this class with the basic information,
|
|
69
|
+
it can call find_tet_or_core_curve. The method find_tet_or_core_curve
|
|
70
|
+
will either:
|
|
71
|
+
|
|
72
|
+
1. Detect that the closed geodesic is actually a core curve of a
|
|
73
|
+
filled cusp and set core_curve_cusp and core_curve_multiplicity
|
|
74
|
+
accordingly. This means that instead tracing the geodesic
|
|
75
|
+
through the triangulation, the client has to unfill the
|
|
76
|
+
corresponding cusp instead.
|
|
77
|
+
2. Apply a Decktransformation to the line and points such that
|
|
78
|
+
start point is either in the interior of a tetrahedron (in the
|
|
79
|
+
fundamental domain) or in the union of two (lifted) tetrahedra
|
|
80
|
+
(in the universal cover which is the hyperboloid model). That
|
|
81
|
+
is, if the start point is on a face of the triangulation, it
|
|
82
|
+
will return the two adjacent tetrahedra. If the start point is
|
|
83
|
+
in the interior of a tetrahedron, the client can attempt to
|
|
84
|
+
trace the geodesic through the triangulation. The client can
|
|
85
|
+
use the given (lifted) tetrahedra to develop a tube about the
|
|
86
|
+
geodesic to compute its injectivity radius.
|
|
87
|
+
|
|
88
|
+
There is an additional field index that can be used by clients for
|
|
89
|
+
book-keeping purposes, for example, to store the index of the cusp
|
|
90
|
+
obtained by drilling this geodesic.
|
|
91
|
+
|
|
92
|
+
The start and end point are unnormalised time-like vectors. Note
|
|
93
|
+
that normalisation is not required for many applications (such as
|
|
94
|
+
computing the intersection of the line segment from the start to
|
|
95
|
+
the end point with a plane) and will enlarge the intervals when
|
|
96
|
+
performing verified computations.
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
def __init__(self,
|
|
100
|
+
# The triangulation
|
|
101
|
+
mcomplex : Mcomplex,
|
|
102
|
+
|
|
103
|
+
# Word were are drilling
|
|
104
|
+
word : str,
|
|
105
|
+
|
|
106
|
+
# Trace of corresponding PSL(2,C)-matrix.
|
|
107
|
+
trace : Any,
|
|
108
|
+
|
|
109
|
+
# A point on or near the line corresponding to the closed geodesic.
|
|
110
|
+
|
|
111
|
+
# It is a light-like R13-vector. Using Any as type annotation because
|
|
112
|
+
# this might be a SimpleVector or SageMath type.
|
|
113
|
+
unnormalised_start_point : Any,
|
|
114
|
+
|
|
115
|
+
# Optional: image of the point under the matrix corresponding to
|
|
116
|
+
# the closed geodesic and fixing the given line (set-wise).
|
|
117
|
+
unnormalised_end_point : Optional[Any] = None,
|
|
118
|
+
|
|
119
|
+
# Line corresponding to the closed geodesic with matrix.
|
|
120
|
+
# Must be given if we want to detect whether this geodesic
|
|
121
|
+
# is a core curve.
|
|
122
|
+
line : Optional[R13LineWithMatrix] = None,
|
|
123
|
+
|
|
124
|
+
# Output of find_tet_or_core_curve: if not None, the start point
|
|
125
|
+
# is guaranteed to be in this tetrahedron (as part of the
|
|
126
|
+
# fundamental domain).
|
|
127
|
+
tet : Optional[Tetrahedron] = None,
|
|
128
|
+
|
|
129
|
+
# Output of find_tet_or_core_curve: if non-empty, the start point
|
|
130
|
+
# is guaranteed to be in the union of the lifted tetrahedra.
|
|
131
|
+
# A lifted tetrahedron is encoded as a pair of a tetrahedron
|
|
132
|
+
# (in the fundamental domain) and an O(1,3)-matrix and is the
|
|
133
|
+
# image of this tetrahedron under the matrix.
|
|
134
|
+
# domain and a O(1,3)-matrix that needs to be applied
|
|
135
|
+
|
|
136
|
+
lifted_tetrahedra : Sequence[LiftedTetrahedron] = (),
|
|
137
|
+
|
|
138
|
+
# Output of find_tet_or_core_curve: if not None, the geodesic
|
|
139
|
+
# corresponds to the core curve for this cusp.
|
|
140
|
+
core_curve_cusp : Optional[Vertex] = None,
|
|
141
|
+
|
|
142
|
+
# Output of find_tet_or_core_corve: sign (+1/-1) indicating whether
|
|
143
|
+
# the given geodesic and the core curve run parallel or
|
|
144
|
+
# anti-parallel.
|
|
145
|
+
core_curve_multiplicity : Optional[int] = None,
|
|
146
|
+
|
|
147
|
+
# Field filled by client to indicate which index the cusp resulting
|
|
148
|
+
# from drilling this geodesic is supposed to have.
|
|
149
|
+
index : Optional[int] = None):
|
|
150
|
+
|
|
151
|
+
self.mcomplex = mcomplex
|
|
152
|
+
self.word = word
|
|
153
|
+
self.trace = trace
|
|
154
|
+
self.unnormalised_start_point = unnormalised_start_point
|
|
155
|
+
self.unnormalised_end_point = unnormalised_end_point
|
|
156
|
+
self.line = line
|
|
157
|
+
self.tet = tet
|
|
158
|
+
self.lifted_tetrahedra = lifted_tetrahedra
|
|
159
|
+
self.core_curve_cusp = core_curve_cusp
|
|
160
|
+
self.core_curve_multiplicity = core_curve_multiplicity
|
|
161
|
+
self.index = index
|
|
162
|
+
|
|
163
|
+
def find_tet_or_core_curve(self) -> None:
|
|
164
|
+
"""
|
|
165
|
+
Apply Deck-transformations to the start and end point and hyperbolic
|
|
166
|
+
line until we either detected that the given geodesic corresponds to
|
|
167
|
+
a core curve (only if line is not None) or we have captured the start
|
|
168
|
+
point in one or two tetrahedra (in case the start close is on or very
|
|
169
|
+
close to a face).
|
|
170
|
+
This method also computes the distance of the geodesic to the core
|
|
171
|
+
curves (only if line is not None) and raises an exception if we could
|
|
172
|
+
not ensure that this distance is positive.
|
|
173
|
+
"""
|
|
174
|
+
|
|
175
|
+
self._graph_trace()
|
|
176
|
+
|
|
177
|
+
def _graph_trace(self):
|
|
178
|
+
self.tet = None
|
|
179
|
+
self.lifted_tetrahedra = ()
|
|
180
|
+
self.core_curve_cusp = None
|
|
181
|
+
self.core_curve_multiplicity = None
|
|
182
|
+
|
|
183
|
+
# Walks from tetrahedron to tetrahedron (transforming the start point
|
|
184
|
+
# and other data) trying to get the start_point closer and closer to
|
|
185
|
+
# one of the tetrahedra.
|
|
186
|
+
# Stops when the start_point appears to be in a tetrahedron or on the
|
|
187
|
+
# face of a tetrahedron or when (the lift of) the geodesic was really
|
|
188
|
+
# close to (a lift of) a core curve.
|
|
189
|
+
|
|
190
|
+
if self.mcomplex.verified:
|
|
191
|
+
epsilon = 0
|
|
192
|
+
def key(face_and_signed_distance):
|
|
193
|
+
return face_and_signed_distance[1].center()
|
|
194
|
+
else:
|
|
195
|
+
epsilon = _compute_epsilon(self.mcomplex.RF)
|
|
196
|
+
def key(face_and_signed_distance):
|
|
197
|
+
return face_and_signed_distance[1]
|
|
198
|
+
|
|
199
|
+
# Face through which tetrahedron was entered - to avoid we are
|
|
200
|
+
# going back through the face we just came from. Initialized to
|
|
201
|
+
# simplex.T for the first iteration.
|
|
202
|
+
tet = self.mcomplex.baseTet
|
|
203
|
+
entry_cell = simplex.T
|
|
204
|
+
|
|
205
|
+
for i in range(constants.graph_trace_max_steps):
|
|
206
|
+
# See whether the geodesic is close to a core curve.
|
|
207
|
+
# v is the vertex of the simplex for that core curve.
|
|
208
|
+
# Or None
|
|
209
|
+
v = self._find_cusp_if_core_curve(tet, entry_cell, epsilon)
|
|
210
|
+
|
|
211
|
+
if v is not None:
|
|
212
|
+
# Verify that the the geodesic is really the core curve and
|
|
213
|
+
# determine whether the geodesic and core curve or parallel
|
|
214
|
+
# or anti-parallel.
|
|
215
|
+
self.core_curve_multiplicity = self._multiplicity_of_core_curve(
|
|
216
|
+
tet, v)
|
|
217
|
+
self.core_curve_cusp = tet.Class[v]
|
|
218
|
+
return
|
|
219
|
+
|
|
220
|
+
# Compute the signed distance of the start point to the
|
|
221
|
+
# planes supporting a face for each face of the tetrahedron.
|
|
222
|
+
#
|
|
223
|
+
# The maximum value tells us which face to cross next.
|
|
224
|
+
#
|
|
225
|
+
# Note that we only care about the maximum value, so we can used
|
|
226
|
+
# the unnormalised start point (that is a time-like vector that
|
|
227
|
+
# is not necessarily a unit vector). Since we compare the value
|
|
228
|
+
# for different faces though, we need to use the normalised
|
|
229
|
+
# plane equations.
|
|
230
|
+
#
|
|
231
|
+
faces_and_signed_distances = [
|
|
232
|
+
(face, r13_dot(self.unnormalised_start_point, tet.R13_planes[face]))
|
|
233
|
+
for face in simplex.TwoSubsimplices ]
|
|
234
|
+
|
|
235
|
+
# If we cannot confirm that the start point is outside the current
|
|
236
|
+
# tetrahedron, stop.
|
|
237
|
+
#
|
|
238
|
+
# Note the subtle difference here between using
|
|
239
|
+
# signed_distance > epsilon to determine whether to stop
|
|
240
|
+
# signed_distance < -epsilon to determine whether the start point
|
|
241
|
+
# is inside.
|
|
242
|
+
#
|
|
243
|
+
if not any( signed_distance > epsilon
|
|
244
|
+
for face, signed_distance
|
|
245
|
+
in faces_and_signed_distances ):
|
|
246
|
+
|
|
247
|
+
self.lifted_tetrahedra = find_lifted_tetrahedra_containing_point(
|
|
248
|
+
LiftedTetrahedron(
|
|
249
|
+
tet, make_identity_matrix(ring=self.mcomplex.RF, n=4)),
|
|
250
|
+
faces_and_signed_distances,
|
|
251
|
+
self.unnormalised_start_point,
|
|
252
|
+
epsilon)
|
|
253
|
+
|
|
254
|
+
if len(self.lifted_tetrahedra) == 1:
|
|
255
|
+
# We verified that there is a unique tetrahedron containing
|
|
256
|
+
# the start point.
|
|
257
|
+
# Signal to the client that we can start tracing the geodesic
|
|
258
|
+
# throguh the triangulation from this tetrahedron:
|
|
259
|
+
self.tet = self.lifted_tetrahedra[0].tet
|
|
260
|
+
|
|
261
|
+
return
|
|
262
|
+
|
|
263
|
+
# Find face for which the signed distance is largest.
|
|
264
|
+
#
|
|
265
|
+
# For intervals, we compare by using the center of each interval.
|
|
266
|
+
#
|
|
267
|
+
# This is fine in that we use the signed distances here to
|
|
268
|
+
# heuristically guide us the right tetrahedron containing the
|
|
269
|
+
# start point - and have code to explicitly check at the end that
|
|
270
|
+
# the start point is really contained in the resulting tetrahedron
|
|
271
|
+
# or pair of neighboring tetrahedra.
|
|
272
|
+
# Also note that if two largest signed distance are really close
|
|
273
|
+
# to each other, then making either choice will probably eventually
|
|
274
|
+
# get us to the tetrahedron containing the start point.
|
|
275
|
+
#
|
|
276
|
+
face, worst_distance = max(
|
|
277
|
+
[ face_and_signed_distance
|
|
278
|
+
for face_and_signed_distance in faces_and_signed_distances
|
|
279
|
+
if face_and_signed_distance[0] != entry_cell],
|
|
280
|
+
key=key)
|
|
281
|
+
|
|
282
|
+
self._transform(tet.O13_matrices[face])
|
|
283
|
+
entry_cell = tet.Gluing[face].image(face)
|
|
284
|
+
tet = tet.Neighbor[face]
|
|
285
|
+
|
|
286
|
+
raise exceptions.UnfinishedGraphTraceGeodesicError(
|
|
287
|
+
constants.graph_trace_max_steps)
|
|
288
|
+
|
|
289
|
+
def _transform(self, m): # m is Decktransformation O(1,3)-matrix
|
|
290
|
+
"""
|
|
291
|
+
Transform the data by matrix.
|
|
292
|
+
"""
|
|
293
|
+
|
|
294
|
+
self.unnormalised_start_point = m * self.unnormalised_start_point
|
|
295
|
+
if self.unnormalised_end_point:
|
|
296
|
+
self.unnormalised_end_point = m * self.unnormalised_end_point
|
|
297
|
+
if self.line:
|
|
298
|
+
self.line = self.line.transformed(m)
|
|
299
|
+
|
|
300
|
+
def _find_cusp_if_core_curve(
|
|
301
|
+
self,
|
|
302
|
+
tet : Tetrahedron,
|
|
303
|
+
entry_cell : int,
|
|
304
|
+
epsilon) -> Optional[int]:
|
|
305
|
+
"""
|
|
306
|
+
Check that the lift of the geodesic is close to the lifts of the core
|
|
307
|
+
curves at the vertices of the tetrahedron adjacent to entry_cell
|
|
308
|
+
where entry_cell is either in simplex.TwoSubsimplices or simplex.T.
|
|
309
|
+
|
|
310
|
+
If close, returns the vertex of the tetrahedron (in
|
|
311
|
+
simplex.ZeroSubsimplices), else None.
|
|
312
|
+
"""
|
|
313
|
+
|
|
314
|
+
# Bail if we do not know the line that is the lift of the geodesic.
|
|
315
|
+
#
|
|
316
|
+
# This happens when perturbing the start and end point:
|
|
317
|
+
# in a first pass, it is determined which geodesics are curve
|
|
318
|
+
# curves. The corresponding cusps are unfilled and the geodesics
|
|
319
|
+
# dropped. Thus, future passes no longer need to check which
|
|
320
|
+
# geodesics are core curves - and the code perturbing
|
|
321
|
+
# the start and end point is dropping the line.
|
|
322
|
+
if not self.line:
|
|
323
|
+
return None
|
|
324
|
+
|
|
325
|
+
# For each vertex of the entry_cell
|
|
326
|
+
for v in simplex.ZeroSubsimplices:
|
|
327
|
+
if not simplex.is_subset(v, entry_cell):
|
|
328
|
+
continue
|
|
329
|
+
# Determine whether that vertex of the tetrahedron
|
|
330
|
+
# corresponds to a filled cusp and get (the corresponding
|
|
331
|
+
# lift of) the core curve.
|
|
332
|
+
core_curve = tet.core_curves.get(v)
|
|
333
|
+
if not core_curve:
|
|
334
|
+
continue
|
|
335
|
+
# Compute the inner products between the endpoints
|
|
336
|
+
# of the lifted core curve and geodesic. These endpoints
|
|
337
|
+
# are light-like. Thus, if they are co-linear (corresponding
|
|
338
|
+
# to the same point), the inner product will be zero.
|
|
339
|
+
p = [[ -r13_dot(pt0, pt1)
|
|
340
|
+
for pt0 in self.line.r13_line.points ]
|
|
341
|
+
for pt1 in tet.core_curves[v].r13_line.points ]
|
|
342
|
+
|
|
343
|
+
# We do not know which end of the line corresponding
|
|
344
|
+
# to the geodesic corresponds to which end of the line
|
|
345
|
+
# corresponding to the core curve. So check both cases.
|
|
346
|
+
#
|
|
347
|
+
# Note that there are two reasons we do not know this:
|
|
348
|
+
# we do not know whether the core curve and geodesic are
|
|
349
|
+
# parallel or anti-parallel. And
|
|
350
|
+
# r13_fixed_points_of_psl2c_matrix makes no guarantee
|
|
351
|
+
# on whether the attracting or repelling fixed point is
|
|
352
|
+
# returned first.
|
|
353
|
+
if not (p[0][0] > epsilon or p[1][1] > epsilon):
|
|
354
|
+
return v
|
|
355
|
+
if not (p[0][1] > epsilon or p[1][0] > epsilon):
|
|
356
|
+
return v
|
|
357
|
+
|
|
358
|
+
return None
|
|
359
|
+
|
|
360
|
+
def _multiplicity_of_core_curve(self,
|
|
361
|
+
tet : Tetrahedron,
|
|
362
|
+
vertex : int) -> int:
|
|
363
|
+
"""
|
|
364
|
+
Verify that geodesic is indeed a multiple of the core curve (including
|
|
365
|
+
sign).
|
|
366
|
+
"""
|
|
367
|
+
|
|
368
|
+
if self.line is None:
|
|
369
|
+
raise Exception(
|
|
370
|
+
"There is a bug in the code: it is trying to verify that "
|
|
371
|
+
"geodesic is a core curve without being given a line.")
|
|
372
|
+
|
|
373
|
+
try:
|
|
374
|
+
return compute_and_verify_multiplicity(
|
|
375
|
+
tet.core_curves[vertex],
|
|
376
|
+
self.line,
|
|
377
|
+
self.mcomplex)
|
|
378
|
+
except InsufficientPrecisionError:
|
|
379
|
+
raise InsufficientPrecisionError(
|
|
380
|
+
"Geodesic is very close to a core curve but could not verify "
|
|
381
|
+
"it is the core curve. Increasing the precision will probably "
|
|
382
|
+
"fix this.")
|
|
383
|
+
|
|
384
|
+
def compute_geodesic_start_point_info(mcomplex : Mcomplex,
|
|
385
|
+
word) -> GeodesicStartPointInfo:
|
|
386
|
+
"""
|
|
387
|
+
Compute basic information about a geodesic given a word.
|
|
388
|
+
|
|
389
|
+
add_r13_geometry must have been called on the Mcomplex.
|
|
390
|
+
"""
|
|
391
|
+
|
|
392
|
+
m = word_to_psl2c_matrix(mcomplex, word)
|
|
393
|
+
_verify_not_parabolic(m, mcomplex, word)
|
|
394
|
+
# Line fixed by matrix
|
|
395
|
+
line : R13LineWithMatrix = r13_fixed_line_of_psl2c_matrix(m)
|
|
396
|
+
|
|
397
|
+
# Pick a point on the line
|
|
398
|
+
start_point = sample_line(line.r13_line)
|
|
399
|
+
|
|
400
|
+
g = GeodesicStartPointInfo(
|
|
401
|
+
mcomplex=mcomplex,
|
|
402
|
+
word=word,
|
|
403
|
+
trace=m.trace(),
|
|
404
|
+
unnormalised_start_point=start_point,
|
|
405
|
+
unnormalised_end_point=line.o13_matrix * start_point,
|
|
406
|
+
line=line)
|
|
407
|
+
|
|
408
|
+
# Determines whether geodesic corresponds to a core curve.
|
|
409
|
+
# Applies Decktransformations so that start point lies within
|
|
410
|
+
# the interior of one tetrahedron in the fundamental domain or
|
|
411
|
+
# within the union of two tetrahedra neighboring in the hyperboloid
|
|
412
|
+
# model.
|
|
413
|
+
#
|
|
414
|
+
# See GeodesicStartPointInfo for details.
|
|
415
|
+
g.find_tet_or_core_curve()
|
|
416
|
+
|
|
417
|
+
return g
|
|
418
|
+
|
|
419
|
+
def _verify_not_parabolic(m, mcomplex, word):
|
|
420
|
+
"""
|
|
421
|
+
Raise exception when user gives a word corresponding to a parabolic
|
|
422
|
+
matrix.
|
|
423
|
+
"""
|
|
424
|
+
|
|
425
|
+
if mcomplex.verified:
|
|
426
|
+
epsilon = 0
|
|
427
|
+
else:
|
|
428
|
+
epsilon = _compute_epsilon(mcomplex.RF)
|
|
429
|
+
|
|
430
|
+
tr = m.trace()
|
|
431
|
+
if not (abs(tr - 2) > epsilon and abs(tr + 2) > epsilon):
|
|
432
|
+
raise exceptions.WordAppearsToBeParabolic(word, tr)
|
|
433
|
+
|
|
434
|
+
def _compute_epsilon(RF):
|
|
435
|
+
return RF(0.5) ** (RF.prec() // 2)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
from ...tiling.lifted_tetrahedron import LiftedTetrahedron
|
|
2
|
+
from ...snap.t3mlite import simplex # type: ignore
|
|
3
|
+
from ...hyperboloid import r13_dot
|
|
4
|
+
from ...exceptions import InsufficientPrecisionError # type: ignore
|
|
5
|
+
|
|
6
|
+
def find_lifted_tetrahedra_containing_point(
|
|
7
|
+
lifted_tetrahedron : LiftedTetrahedron,
|
|
8
|
+
faces_and_signed_distances,
|
|
9
|
+
lifted_pt,
|
|
10
|
+
epsilon):
|
|
11
|
+
|
|
12
|
+
# Report faces for which we cannot confirm that the start point
|
|
13
|
+
# is to the inside of the plane supporting that face.
|
|
14
|
+
faces = [ face
|
|
15
|
+
for face, signed_distance
|
|
16
|
+
in faces_and_signed_distances
|
|
17
|
+
if not signed_distance < -epsilon ]
|
|
18
|
+
|
|
19
|
+
if len(faces) == 0:
|
|
20
|
+
# Signal to the client that we can start with this tetrahedron
|
|
21
|
+
# when developing a tube about the geodesic.
|
|
22
|
+
return [ lifted_tetrahedron ]
|
|
23
|
+
|
|
24
|
+
if len(faces) == 1:
|
|
25
|
+
# The start point is probably on the face of the tetrahedron,
|
|
26
|
+
# that is, we could verify it lies to the right side of the
|
|
27
|
+
# supporting planes for three faces but not one:
|
|
28
|
+
face, = faces
|
|
29
|
+
|
|
30
|
+
# Even though we cannot verify that the start point lies
|
|
31
|
+
# exactly on the face, we can verify that the start point
|
|
32
|
+
# lies in the interior of the union of two neighboring
|
|
33
|
+
# tetrahedra. That is, the union is a hexahedron and
|
|
34
|
+
# it suffices to check that the start point lies to the
|
|
35
|
+
# inside of the six faces of the tetrahedron.
|
|
36
|
+
#
|
|
37
|
+
# _graph_trace already checked the three faces of the given
|
|
38
|
+
# tetrahedron. But it is left to check this for the neighboring
|
|
39
|
+
# tetrahedron.
|
|
40
|
+
|
|
41
|
+
tet = lifted_tetrahedron.tet
|
|
42
|
+
m = lifted_tetrahedron.o13_matrix
|
|
43
|
+
|
|
44
|
+
# Find the other tetrahedron of the neighboring tetrahedra.
|
|
45
|
+
other_tet = tet.Neighbor[face]
|
|
46
|
+
other_pt = tet.O13_matrices[face] * lifted_pt
|
|
47
|
+
other_face = tet.Gluing[face].image(face)
|
|
48
|
+
|
|
49
|
+
for f in simplex.TwoSubsimplices:
|
|
50
|
+
if f == other_face:
|
|
51
|
+
continue
|
|
52
|
+
if not r13_dot(other_pt, other_tet.R13_planes[f]) < epsilon:
|
|
53
|
+
raise InsufficientPrecisionError(
|
|
54
|
+
"Failed to find lift of geodesic and prove that "
|
|
55
|
+
"it intersects tetrahedra of the fundamental domain. "
|
|
56
|
+
"Increasing the precision will probably fix this "
|
|
57
|
+
"problem.")
|
|
58
|
+
|
|
59
|
+
return [ lifted_tetrahedron,
|
|
60
|
+
LiftedTetrahedron(
|
|
61
|
+
other_tet,
|
|
62
|
+
m * other_tet.O13_matrices[other_face]) ]
|
|
63
|
+
|
|
64
|
+
raise InsufficientPrecisionError(
|
|
65
|
+
"Start point chosen on geodesic too close to 1-skeleton of "
|
|
66
|
+
"triangulation to verify it is not on the 1-skeleton. "
|
|
67
|
+
"Increasing the precision will probably fix this problem.")
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from ...hyperboloid import o13_inverse # type: ignore
|
|
2
|
+
from ...hyperboloid.line import R13Line
|
|
3
|
+
|
|
4
|
+
__all__ = [ 'R13LineWithMatrix' ]
|
|
5
|
+
|
|
6
|
+
class R13LineWithMatrix:
|
|
7
|
+
"""
|
|
8
|
+
A line in the hyperboloid model together with a O(1,3)-matrix moving
|
|
9
|
+
the line forward by the given complex length (with real positive part)
|
|
10
|
+
(the matrix is fixing the line set-wise).
|
|
11
|
+
"""
|
|
12
|
+
def __init__(self,
|
|
13
|
+
r13_line : R13Line,
|
|
14
|
+
o13_matrix,
|
|
15
|
+
complex_length):
|
|
16
|
+
self.r13_line = r13_line
|
|
17
|
+
self.o13_matrix = o13_matrix
|
|
18
|
+
self.complex_length = complex_length
|
|
19
|
+
|
|
20
|
+
def transformed(self, m):
|
|
21
|
+
"""
|
|
22
|
+
Returns image of line with matrix under given O13-matrix m.
|
|
23
|
+
|
|
24
|
+
That is, the matrix will be conjugated by m so that the new
|
|
25
|
+
matrix will fix the image of the line (set-wise).
|
|
26
|
+
"""
|
|
27
|
+
return R13LineWithMatrix(
|
|
28
|
+
self.r13_line.transformed(m),
|
|
29
|
+
m * self.o13_matrix * o13_inverse(m),
|
|
30
|
+
self.complex_length)
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
from .line import R13LineWithMatrix
|
|
2
|
+
from ...hyperboloid.distances import distance_r13_points
|
|
3
|
+
from ...hyperboloid import o13_inverse
|
|
4
|
+
from ...exceptions import InsufficientPrecisionError
|
|
5
|
+
|
|
6
|
+
def compute_and_verify_multiplicity(line : R13LineWithMatrix,
|
|
7
|
+
line_power : R13LineWithMatrix,
|
|
8
|
+
mcomplex):
|
|
9
|
+
"""
|
|
10
|
+
Assume that line and line_power are created from matrices from the geometric
|
|
11
|
+
representation.
|
|
12
|
+
|
|
13
|
+
Verify that the matrix of line_power is a signed multiple of the matrix
|
|
14
|
+
of line and return the multiple.
|
|
15
|
+
"""
|
|
16
|
+
|
|
17
|
+
# First use real length to compute multiple up to sign.
|
|
18
|
+
multiplicity = _compute_absolute_multiplicity(
|
|
19
|
+
line.complex_length.real(),
|
|
20
|
+
line_power.complex_length.real(),
|
|
21
|
+
mcomplex.verified)
|
|
22
|
+
|
|
23
|
+
sign = _determine_and_verify_sign(
|
|
24
|
+
multiplicity,
|
|
25
|
+
line.o13_matrix,
|
|
26
|
+
line_power.o13_matrix,
|
|
27
|
+
mcomplex)
|
|
28
|
+
|
|
29
|
+
return sign * multiplicity
|
|
30
|
+
|
|
31
|
+
_epsilon = 0.001
|
|
32
|
+
_max_multiple = 500
|
|
33
|
+
|
|
34
|
+
def _compute_absolute_multiplicity(
|
|
35
|
+
length,
|
|
36
|
+
length_multiple,
|
|
37
|
+
verified):
|
|
38
|
+
|
|
39
|
+
r = length_multiple / length
|
|
40
|
+
|
|
41
|
+
if verified:
|
|
42
|
+
is_int, r_int = r.is_int()
|
|
43
|
+
if not is_int:
|
|
44
|
+
raise InsufficientPrecisionError(
|
|
45
|
+
"When verifying that a geodesic is a multiple of another "
|
|
46
|
+
"geodesic, the interval for the multiplicity does not contain "
|
|
47
|
+
"a unique integer.")
|
|
48
|
+
else:
|
|
49
|
+
r_int = r.round()
|
|
50
|
+
if abs(r_int - r) > _epsilon:
|
|
51
|
+
raise InsufficientPrecisionError(
|
|
52
|
+
"When verifying that a geodesic is a multiple of another "
|
|
53
|
+
"geodesic, the floating point approximation for the "
|
|
54
|
+
"multiplicity is too far off an integer.")
|
|
55
|
+
r_int = int(r_int)
|
|
56
|
+
|
|
57
|
+
if not r_int > 0:
|
|
58
|
+
if verified:
|
|
59
|
+
raise RuntimeError(
|
|
60
|
+
"When verifying that a geodesic is a multiple of another "
|
|
61
|
+
"geodesic, we got zero for multiplicity. This is a bug.")
|
|
62
|
+
else:
|
|
63
|
+
raise InsufficientPrecisionError(
|
|
64
|
+
"When verifying that a geodesic is a multiple of another "
|
|
65
|
+
"geodesic, we got zero for multiplicity. Increasing the "
|
|
66
|
+
"precision might help.")
|
|
67
|
+
if not r_int < _max_multiple:
|
|
68
|
+
raise RuntimeError(
|
|
69
|
+
"When verifying that a geodesic is a multiple of another "
|
|
70
|
+
"geodesic, we got a multiple (%d) higher than what we support "
|
|
71
|
+
"(%d)" % (r_int, _max_multiple))
|
|
72
|
+
|
|
73
|
+
return r_int
|
|
74
|
+
|
|
75
|
+
def _determine_and_verify_sign(multiplicity, m, m_power, mcomplex):
|
|
76
|
+
"""
|
|
77
|
+
Given matrices m and m_power coming from the geometric representation,
|
|
78
|
+
verify that either m^multiplicity = m_power^sign for either sign = +1
|
|
79
|
+
or sign = -1. Return sign.
|
|
80
|
+
"""
|
|
81
|
+
|
|
82
|
+
base_pt = mcomplex.R13_baseTetInCenter
|
|
83
|
+
|
|
84
|
+
# Compute image of base point under m^multiplicity.
|
|
85
|
+
pt = base_pt
|
|
86
|
+
for i in range(multiplicity):
|
|
87
|
+
pt = m * pt
|
|
88
|
+
|
|
89
|
+
# Check whether it is equal to image under m_power
|
|
90
|
+
if _are_images_of_basepoints_equal(
|
|
91
|
+
pt, m_power * base_pt, mcomplex):
|
|
92
|
+
return +1
|
|
93
|
+
|
|
94
|
+
# Check whether it is equal to image under m_power^-1
|
|
95
|
+
if _are_images_of_basepoints_equal(
|
|
96
|
+
pt, o13_inverse(m_power) * base_pt, mcomplex):
|
|
97
|
+
return -1
|
|
98
|
+
|
|
99
|
+
raise RuntimeError(
|
|
100
|
+
"Given geodesic is not a multiple of other given geodesic.")
|
|
101
|
+
|
|
102
|
+
def _are_images_of_basepoints_equal(pt0, pt1, mcomplex):
|
|
103
|
+
"""
|
|
104
|
+
Given two images of the base point under Deck transformations,
|
|
105
|
+
check whether they are the same (and thus correspond to the same
|
|
106
|
+
Deck transformation).
|
|
107
|
+
"""
|
|
108
|
+
|
|
109
|
+
# We use that the the base point is the incenter of the base
|
|
110
|
+
# tetrahedron. Thus, we know that if the minimum distance for
|
|
111
|
+
# them to be distinct is the in-radius of the base tetrahedron.
|
|
112
|
+
#
|
|
113
|
+
# We add in a factor of 1/2 for safety.
|
|
114
|
+
|
|
115
|
+
d = distance_r13_points(pt0, pt1)
|
|
116
|
+
if d < mcomplex.baseTetInRadius / 2:
|
|
117
|
+
return True
|
|
118
|
+
if d > mcomplex.baseTetInRadius / 2:
|
|
119
|
+
return False
|
|
120
|
+
|
|
121
|
+
raise InsufficientPrecisionError(
|
|
122
|
+
"When determining whether a geodesic is a multiple of another "
|
|
123
|
+
"geodesic, we could not verify that the images of the base point "
|
|
124
|
+
"under the corresponding matrices are the same or not.\n"
|
|
125
|
+
"Distance between basepoints: %r\n"
|
|
126
|
+
"Cut-off: %r" % (d, mcomplex.baseTetInRadius / 2))
|
|
127
|
+
|