sequenzo 0.1.31__cp310-cp310-macosx_10_9_x86_64.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.
- _sequenzo_fastcluster.cpython-310-darwin.so +0 -0
- sequenzo/__init__.py +349 -0
- sequenzo/big_data/__init__.py +12 -0
- sequenzo/big_data/clara/__init__.py +26 -0
- sequenzo/big_data/clara/clara.py +476 -0
- sequenzo/big_data/clara/utils/__init__.py +27 -0
- sequenzo/big_data/clara/utils/aggregatecases.py +92 -0
- sequenzo/big_data/clara/utils/davies_bouldin.py +91 -0
- sequenzo/big_data/clara/utils/get_weighted_diss.cpython-310-darwin.so +0 -0
- sequenzo/big_data/clara/utils/wfcmdd.py +205 -0
- sequenzo/big_data/clara/visualization.py +88 -0
- sequenzo/clustering/KMedoids.py +178 -0
- sequenzo/clustering/__init__.py +30 -0
- sequenzo/clustering/clustering_c_code.cpython-310-darwin.so +0 -0
- sequenzo/clustering/hierarchical_clustering.py +1256 -0
- sequenzo/clustering/sequenzo_fastcluster/fastcluster.py +495 -0
- sequenzo/clustering/sequenzo_fastcluster/src/fastcluster.cpp +1877 -0
- sequenzo/clustering/sequenzo_fastcluster/src/fastcluster_python.cpp +1264 -0
- sequenzo/clustering/src/KMedoid.cpp +263 -0
- sequenzo/clustering/src/PAM.cpp +237 -0
- sequenzo/clustering/src/PAMonce.cpp +265 -0
- sequenzo/clustering/src/cluster_quality.cpp +496 -0
- sequenzo/clustering/src/cluster_quality.h +128 -0
- sequenzo/clustering/src/cluster_quality_backup.cpp +570 -0
- sequenzo/clustering/src/module.cpp +228 -0
- sequenzo/clustering/src/weightedinertia.cpp +111 -0
- sequenzo/clustering/utils/__init__.py +27 -0
- sequenzo/clustering/utils/disscenter.py +122 -0
- sequenzo/data_preprocessing/__init__.py +22 -0
- sequenzo/data_preprocessing/helpers.py +303 -0
- sequenzo/datasets/__init__.py +41 -0
- sequenzo/datasets/biofam.csv +2001 -0
- sequenzo/datasets/biofam_child_domain.csv +2001 -0
- sequenzo/datasets/biofam_left_domain.csv +2001 -0
- sequenzo/datasets/biofam_married_domain.csv +2001 -0
- sequenzo/datasets/chinese_colonial_territories.csv +12 -0
- sequenzo/datasets/country_co2_emissions.csv +194 -0
- sequenzo/datasets/country_co2_emissions_global_deciles.csv +195 -0
- sequenzo/datasets/country_co2_emissions_global_quintiles.csv +195 -0
- sequenzo/datasets/country_co2_emissions_local_deciles.csv +195 -0
- sequenzo/datasets/country_co2_emissions_local_quintiles.csv +195 -0
- sequenzo/datasets/country_gdp_per_capita.csv +194 -0
- sequenzo/datasets/dyadic_children.csv +61 -0
- sequenzo/datasets/dyadic_parents.csv +61 -0
- sequenzo/datasets/mvad.csv +713 -0
- sequenzo/datasets/pairfam_activity_by_month.csv +1028 -0
- sequenzo/datasets/pairfam_activity_by_year.csv +1028 -0
- sequenzo/datasets/pairfam_family_by_month.csv +1028 -0
- sequenzo/datasets/pairfam_family_by_year.csv +1028 -0
- sequenzo/datasets/political_science_aid_shock.csv +166 -0
- sequenzo/datasets/political_science_donor_fragmentation.csv +157 -0
- sequenzo/define_sequence_data.py +1400 -0
- sequenzo/dissimilarity_measures/__init__.py +31 -0
- sequenzo/dissimilarity_measures/c_code.cpython-310-darwin.so +0 -0
- sequenzo/dissimilarity_measures/get_distance_matrix.py +762 -0
- sequenzo/dissimilarity_measures/get_substitution_cost_matrix.py +246 -0
- sequenzo/dissimilarity_measures/src/DHDdistance.cpp +148 -0
- sequenzo/dissimilarity_measures/src/LCPdistance.cpp +114 -0
- sequenzo/dissimilarity_measures/src/LCPspellDistance.cpp +215 -0
- sequenzo/dissimilarity_measures/src/OMdistance.cpp +247 -0
- sequenzo/dissimilarity_measures/src/OMspellDistance.cpp +281 -0
- sequenzo/dissimilarity_measures/src/__init__.py +0 -0
- sequenzo/dissimilarity_measures/src/dist2matrix.cpp +63 -0
- sequenzo/dissimilarity_measures/src/dp_utils.h +160 -0
- sequenzo/dissimilarity_measures/src/module.cpp +40 -0
- sequenzo/dissimilarity_measures/src/setup.py +30 -0
- sequenzo/dissimilarity_measures/src/utils.h +25 -0
- sequenzo/dissimilarity_measures/src/xsimd/.github/cmake-test/main.cpp +6 -0
- sequenzo/dissimilarity_measures/src/xsimd/benchmark/main.cpp +159 -0
- sequenzo/dissimilarity_measures/src/xsimd/benchmark/xsimd_benchmark.hpp +565 -0
- sequenzo/dissimilarity_measures/src/xsimd/docs/source/conf.py +37 -0
- sequenzo/dissimilarity_measures/src/xsimd/examples/mandelbrot.cpp +330 -0
- sequenzo/dissimilarity_measures/src/xsimd/examples/pico_bench.hpp +246 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/common/xsimd_common_arithmetic.hpp +266 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/common/xsimd_common_complex.hpp +112 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/common/xsimd_common_details.hpp +323 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/common/xsimd_common_logical.hpp +218 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/common/xsimd_common_math.hpp +2583 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/common/xsimd_common_memory.hpp +880 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/common/xsimd_common_rounding.hpp +72 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/common/xsimd_common_swizzle.hpp +174 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/common/xsimd_common_trigo.hpp +978 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_avx.hpp +1924 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_avx2.hpp +1144 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_avx512bw.hpp +656 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_avx512cd.hpp +28 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_avx512dq.hpp +244 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_avx512er.hpp +20 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_avx512f.hpp +2650 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_avx512ifma.hpp +20 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_avx512pf.hpp +20 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_avx512vbmi.hpp +77 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_avx512vbmi2.hpp +131 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_avx512vnni_avx512bw.hpp +20 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_avx512vnni_avx512vbmi2.hpp +20 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_avxvnni.hpp +20 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_common.hpp +24 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_common_fwd.hpp +77 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_constants.hpp +393 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_emulated.hpp +788 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_fma3_avx.hpp +93 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_fma3_avx2.hpp +46 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_fma3_sse.hpp +97 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_fma4.hpp +92 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_i8mm_neon64.hpp +17 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_isa.hpp +142 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_neon.hpp +3142 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_neon64.hpp +1543 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_rvv.hpp +1513 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_scalar.hpp +1260 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_sse2.hpp +2024 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_sse3.hpp +67 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_sse4_1.hpp +339 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_sse4_2.hpp +44 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_ssse3.hpp +186 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_sve.hpp +1155 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_vsx.hpp +892 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/arch/xsimd_wasm.hpp +1780 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/config/xsimd_arch.hpp +240 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/config/xsimd_config.hpp +484 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/config/xsimd_cpuid.hpp +269 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/config/xsimd_inline.hpp +27 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/math/xsimd_rem_pio2.hpp +719 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/memory/xsimd_aligned_allocator.hpp +349 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/memory/xsimd_alignment.hpp +91 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_all_registers.hpp +55 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_api.hpp +2765 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_avx2_register.hpp +44 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_avx512bw_register.hpp +51 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_avx512cd_register.hpp +51 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_avx512dq_register.hpp +51 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_avx512er_register.hpp +51 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_avx512f_register.hpp +77 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_avx512ifma_register.hpp +51 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_avx512pf_register.hpp +51 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_avx512vbmi2_register.hpp +51 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_avx512vbmi_register.hpp +51 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_avx512vnni_avx512bw_register.hpp +54 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_avx512vnni_avx512vbmi2_register.hpp +53 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_avx_register.hpp +64 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_avxvnni_register.hpp +44 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_batch.hpp +1524 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_batch_constant.hpp +300 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_common_arch.hpp +47 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_emulated_register.hpp +80 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_fma3_avx2_register.hpp +50 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_fma3_avx_register.hpp +50 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_fma3_sse_register.hpp +50 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_fma4_register.hpp +50 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_i8mm_neon64_register.hpp +55 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_neon64_register.hpp +55 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_neon_register.hpp +154 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_register.hpp +94 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_rvv_register.hpp +506 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_sse2_register.hpp +59 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_sse3_register.hpp +49 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_sse4_1_register.hpp +48 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_sse4_2_register.hpp +48 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_ssse3_register.hpp +48 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_sve_register.hpp +156 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_traits.hpp +337 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_utils.hpp +536 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_vsx_register.hpp +77 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/types/xsimd_wasm_register.hpp +59 -0
- sequenzo/dissimilarity_measures/src/xsimd/include/xsimd/xsimd.hpp +75 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/architectures/dummy.cpp +7 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/doc/explicit_use_of_an_instruction_set.cpp +13 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/doc/explicit_use_of_an_instruction_set_mean.cpp +24 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/doc/explicit_use_of_an_instruction_set_mean_aligned.cpp +25 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/doc/explicit_use_of_an_instruction_set_mean_arch_independent.cpp +28 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/doc/explicit_use_of_an_instruction_set_mean_tag_dispatch.cpp +25 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/doc/manipulating_abstract_batches.cpp +7 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/doc/manipulating_parametric_batches.cpp +8 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/doc/sum.hpp +31 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/doc/sum_avx2.cpp +3 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/doc/sum_sse2.cpp +3 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/doc/writing_vectorized_code.cpp +11 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/main.cpp +31 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_api.cpp +230 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_arch.cpp +217 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_basic_math.cpp +183 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_batch.cpp +1049 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_batch_bool.cpp +508 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_batch_cast.cpp +409 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_batch_complex.cpp +712 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_batch_constant.cpp +286 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_batch_float.cpp +141 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_batch_int.cpp +365 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_batch_manip.cpp +308 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_bitwise_cast.cpp +222 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_complex_exponential.cpp +226 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_complex_hyperbolic.cpp +183 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_complex_power.cpp +265 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_complex_trigonometric.cpp +236 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_conversion.cpp +248 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_custom_default_arch.cpp +28 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_error_gamma.cpp +170 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_explicit_batch_instantiation.cpp +32 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_exponential.cpp +202 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_extract_pair.cpp +92 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_fp_manipulation.cpp +77 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_gnu_source.cpp +30 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_hyperbolic.cpp +167 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_load_store.cpp +304 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_memory.cpp +61 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_poly_evaluation.cpp +64 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_power.cpp +184 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_rounding.cpp +199 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_select.cpp +101 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_shuffle.cpp +760 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_sum.cpp +4 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_sum.hpp +34 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_traits.cpp +172 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_trigonometric.cpp +208 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_utils.hpp +611 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_wasm/test_wasm_playwright.py +123 -0
- sequenzo/dissimilarity_measures/src/xsimd/test/test_xsimd_api.cpp +1460 -0
- sequenzo/dissimilarity_measures/utils/__init__.py +16 -0
- sequenzo/dissimilarity_measures/utils/get_LCP_length_for_2_seq.py +44 -0
- sequenzo/dissimilarity_measures/utils/get_sm_trate_substitution_cost_matrix.cpython-310-darwin.so +0 -0
- sequenzo/dissimilarity_measures/utils/seqconc.cpython-310-darwin.so +0 -0
- sequenzo/dissimilarity_measures/utils/seqdss.cpython-310-darwin.so +0 -0
- sequenzo/dissimilarity_measures/utils/seqdur.cpython-310-darwin.so +0 -0
- sequenzo/dissimilarity_measures/utils/seqlength.cpython-310-darwin.so +0 -0
- sequenzo/multidomain/__init__.py +23 -0
- sequenzo/multidomain/association_between_domains.py +311 -0
- sequenzo/multidomain/cat.py +597 -0
- sequenzo/multidomain/combt.py +519 -0
- sequenzo/multidomain/dat.py +81 -0
- sequenzo/multidomain/idcd.py +139 -0
- sequenzo/multidomain/linked_polyad.py +292 -0
- sequenzo/openmp_setup.py +233 -0
- sequenzo/prefix_tree/__init__.py +62 -0
- sequenzo/prefix_tree/hub.py +114 -0
- sequenzo/prefix_tree/individual_level_indicators.py +1321 -0
- sequenzo/prefix_tree/spell_individual_level_indicators.py +580 -0
- sequenzo/prefix_tree/spell_level_indicators.py +297 -0
- sequenzo/prefix_tree/system_level_indicators.py +544 -0
- sequenzo/prefix_tree/utils.py +54 -0
- sequenzo/seqhmm/__init__.py +95 -0
- sequenzo/seqhmm/advanced_optimization.py +305 -0
- sequenzo/seqhmm/bootstrap.py +411 -0
- sequenzo/seqhmm/build_hmm.py +142 -0
- sequenzo/seqhmm/build_mhmm.py +136 -0
- sequenzo/seqhmm/build_nhmm.py +121 -0
- sequenzo/seqhmm/fit_mhmm.py +62 -0
- sequenzo/seqhmm/fit_model.py +61 -0
- sequenzo/seqhmm/fit_nhmm.py +76 -0
- sequenzo/seqhmm/formulas.py +289 -0
- sequenzo/seqhmm/forward_backward_nhmm.py +276 -0
- sequenzo/seqhmm/gradients_nhmm.py +306 -0
- sequenzo/seqhmm/hmm.py +291 -0
- sequenzo/seqhmm/mhmm.py +314 -0
- sequenzo/seqhmm/model_comparison.py +238 -0
- sequenzo/seqhmm/multichannel_em.py +282 -0
- sequenzo/seqhmm/multichannel_utils.py +138 -0
- sequenzo/seqhmm/nhmm.py +270 -0
- sequenzo/seqhmm/nhmm_utils.py +191 -0
- sequenzo/seqhmm/predict.py +137 -0
- sequenzo/seqhmm/predict_mhmm.py +142 -0
- sequenzo/seqhmm/simulate.py +878 -0
- sequenzo/seqhmm/utils.py +218 -0
- sequenzo/seqhmm/visualization.py +910 -0
- sequenzo/sequence_characteristics/__init__.py +40 -0
- sequenzo/sequence_characteristics/complexity_index.py +49 -0
- sequenzo/sequence_characteristics/overall_cross_sectional_entropy.py +220 -0
- sequenzo/sequence_characteristics/plot_characteristics.py +593 -0
- sequenzo/sequence_characteristics/simple_characteristics.py +311 -0
- sequenzo/sequence_characteristics/state_frequencies_and_entropy_per_sequence.py +39 -0
- sequenzo/sequence_characteristics/turbulence.py +155 -0
- sequenzo/sequence_characteristics/variance_of_spell_durations.py +86 -0
- sequenzo/sequence_characteristics/within_sequence_entropy.py +43 -0
- sequenzo/suffix_tree/__init__.py +66 -0
- sequenzo/suffix_tree/hub.py +114 -0
- sequenzo/suffix_tree/individual_level_indicators.py +1679 -0
- sequenzo/suffix_tree/spell_individual_level_indicators.py +493 -0
- sequenzo/suffix_tree/spell_level_indicators.py +248 -0
- sequenzo/suffix_tree/system_level_indicators.py +535 -0
- sequenzo/suffix_tree/utils.py +56 -0
- sequenzo/version_check.py +283 -0
- sequenzo/visualization/__init__.py +29 -0
- sequenzo/visualization/plot_mean_time.py +222 -0
- sequenzo/visualization/plot_modal_state.py +276 -0
- sequenzo/visualization/plot_most_frequent_sequences.py +147 -0
- sequenzo/visualization/plot_relative_frequency.py +405 -0
- sequenzo/visualization/plot_sequence_index.py +1175 -0
- sequenzo/visualization/plot_single_medoid.py +153 -0
- sequenzo/visualization/plot_state_distribution.py +651 -0
- sequenzo/visualization/plot_transition_matrix.py +190 -0
- sequenzo/visualization/utils/__init__.py +23 -0
- sequenzo/visualization/utils/utils.py +310 -0
- sequenzo/with_event_history_analysis/__init__.py +35 -0
- sequenzo/with_event_history_analysis/sequence_analysis_multi_state_model.py +850 -0
- sequenzo/with_event_history_analysis/sequence_history_analysis.py +283 -0
- sequenzo-0.1.31.dist-info/METADATA +286 -0
- sequenzo-0.1.31.dist-info/RECORD +299 -0
- sequenzo-0.1.31.dist-info/WHEEL +5 -0
- sequenzo-0.1.31.dist-info/licenses/LICENSE +28 -0
- sequenzo-0.1.31.dist-info/top_level.txt +2 -0
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"""
|
|
2
|
+
@Author : Yuqi Liang 梁彧祺, Sebastian Daza
|
|
3
|
+
@File : plot_transition_matrix.py
|
|
4
|
+
@Time : 13/02/2025 12:39
|
|
5
|
+
@Desc :
|
|
6
|
+
This implementation closely follows ggseqplot's `ggseqtrplot` function.
|
|
7
|
+
|
|
8
|
+
TODO: Current implementation only handles STS (State-Transition-State) format.
|
|
9
|
+
DSS (Distinct-State-Sequence) format will be addressed in future updates.
|
|
10
|
+
(https://maraab23.github.io/ggseqplot/articles/ggseqplot.html)
|
|
11
|
+
"""
|
|
12
|
+
import numpy as np
|
|
13
|
+
import matplotlib.pyplot as plt
|
|
14
|
+
import seaborn as sns
|
|
15
|
+
from typing import Optional
|
|
16
|
+
from sequenzo.define_sequence_data import SequenceData
|
|
17
|
+
from sequenzo.visualization.utils import (
|
|
18
|
+
save_and_show_results,
|
|
19
|
+
show_plot_title
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def compute_transition_matrix(seqdata: SequenceData, with_missing: bool = False, weights="auto") -> np.ndarray:
|
|
24
|
+
"""
|
|
25
|
+
Compute transition rate matrix using vectorized operations for optimal performance.
|
|
26
|
+
|
|
27
|
+
:param seqdata: SequenceData object containing sequence information and states
|
|
28
|
+
:param with_missing: Flag to include missing values in computation
|
|
29
|
+
:param weights: (np.ndarray or "auto") Weights for sequences. If "auto", uses seqdata.weights if available
|
|
30
|
+
:return: numpy.ndarray containing the transition rate matrix
|
|
31
|
+
"""
|
|
32
|
+
# Process weights
|
|
33
|
+
if isinstance(weights, str) and weights == "auto":
|
|
34
|
+
weights = getattr(seqdata, "weights", None)
|
|
35
|
+
|
|
36
|
+
if weights is not None:
|
|
37
|
+
weights = np.asarray(weights, dtype=float).reshape(-1)
|
|
38
|
+
if len(weights) != len(seqdata.values):
|
|
39
|
+
raise ValueError("Length of weights must equal number of sequences.")
|
|
40
|
+
|
|
41
|
+
num_states = len(seqdata.states)
|
|
42
|
+
A = seqdata.to_dataframe().to_numpy()
|
|
43
|
+
n, T = A.shape
|
|
44
|
+
|
|
45
|
+
if weights is None:
|
|
46
|
+
w = np.ones(n)
|
|
47
|
+
else:
|
|
48
|
+
w = np.asarray(weights, dtype=float)
|
|
49
|
+
|
|
50
|
+
# Flatten arrays while synchronizing weights for each transition
|
|
51
|
+
current = A[:, :-1].flatten()
|
|
52
|
+
nxt = A[:, 1:].flatten()
|
|
53
|
+
w_pair = np.repeat(w, T-1) # Each sequence weight replicated (T-1) times
|
|
54
|
+
|
|
55
|
+
# Filter valid transitions (states are encoded as 1, 2, 3, ..., num_states)
|
|
56
|
+
valid = (current >= 1) & (current <= num_states) & (nxt >= 1) & (nxt <= num_states)
|
|
57
|
+
current, nxt, w_pair = current[valid], nxt[valid], w_pair[valid]
|
|
58
|
+
|
|
59
|
+
# Compute weighted transition counts
|
|
60
|
+
# Create mapping from state codes to matrix indices
|
|
61
|
+
state_codes = sorted(set(current) | set(nxt))
|
|
62
|
+
code_to_idx = {code: idx for idx, code in enumerate(state_codes)}
|
|
63
|
+
|
|
64
|
+
# Use only the actual number of unique states for matrix size
|
|
65
|
+
actual_num_states = len(state_codes)
|
|
66
|
+
trans = np.zeros((actual_num_states, actual_num_states), dtype=float)
|
|
67
|
+
|
|
68
|
+
for c, n2, ww in zip(current, nxt, w_pair):
|
|
69
|
+
trans[code_to_idx[int(c)], code_to_idx[int(n2)]] += ww
|
|
70
|
+
|
|
71
|
+
# Compute transition rates
|
|
72
|
+
row_sums = trans.sum(axis=1, keepdims=True)
|
|
73
|
+
row_sums = np.where(row_sums == 0, 1.0, row_sums)
|
|
74
|
+
transition_rates = trans / row_sums
|
|
75
|
+
|
|
76
|
+
# Create a properly sized matrix with correct mapping to original states
|
|
77
|
+
final_matrix = np.zeros((num_states, num_states), dtype=float)
|
|
78
|
+
|
|
79
|
+
# Map back to the original state positions
|
|
80
|
+
for i, from_code in enumerate(state_codes):
|
|
81
|
+
for j, to_code in enumerate(state_codes):
|
|
82
|
+
final_matrix[from_code-1, to_code-1] = transition_rates[i, j]
|
|
83
|
+
|
|
84
|
+
return final_matrix
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def print_transition_matrix(seqdata: SequenceData, transition_rates: np.ndarray) -> None:
|
|
88
|
+
"""
|
|
89
|
+
Print the transition rate matrix with improved readability.
|
|
90
|
+
Uses consistent decimal format for all probabilities.
|
|
91
|
+
|
|
92
|
+
:param seqdata: SequenceData object containing state information
|
|
93
|
+
:param transition_rates: numpy array containing transition rates
|
|
94
|
+
"""
|
|
95
|
+
state_labels = seqdata.labels
|
|
96
|
+
|
|
97
|
+
# Calculate max width needed for state labels
|
|
98
|
+
max_label_width = max(len(s) for s in state_labels) + 3 # +3 for arrow
|
|
99
|
+
|
|
100
|
+
# Print header
|
|
101
|
+
print("\nTransition Rate Matrix:")
|
|
102
|
+
print("-" * 100) # Separator line
|
|
103
|
+
|
|
104
|
+
# Print column headers
|
|
105
|
+
print(" " * max_label_width, end=" ")
|
|
106
|
+
for label in state_labels:
|
|
107
|
+
# Use shorter labels for columns by taking first word
|
|
108
|
+
short_label = label.split('&')[0].strip()
|
|
109
|
+
print(f"{short_label:>10}", end=" ")
|
|
110
|
+
print("\n" + "-" * 100) # Separator line
|
|
111
|
+
|
|
112
|
+
# Print each row
|
|
113
|
+
for i, from_state in enumerate(state_labels):
|
|
114
|
+
# Print row label
|
|
115
|
+
print(f"{from_state:>{max_label_width}} ->", end=" ")
|
|
116
|
+
|
|
117
|
+
# Print transition rates
|
|
118
|
+
for prob in transition_rates[i]:
|
|
119
|
+
# Consistent format for all values
|
|
120
|
+
print(f"{prob:>10.4f}", end=" ")
|
|
121
|
+
print() # New line after each row
|
|
122
|
+
|
|
123
|
+
print("-" * 100) # Separator line
|
|
124
|
+
print("Note: Values represent transition probabilities (range 0-1)")
|
|
125
|
+
print(" All values shown with 4 decimal places for consistency")
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def plot_transition_matrix(seqdata: SequenceData,
|
|
129
|
+
weights="auto",
|
|
130
|
+
title: str = "State Transition Rate Matrix",
|
|
131
|
+
fontsize: int = 12,
|
|
132
|
+
save_as: Optional[str] = None,
|
|
133
|
+
dpi: int = 200,
|
|
134
|
+
format: str = ".2f") -> None:
|
|
135
|
+
"""
|
|
136
|
+
Plot state transition rate matrix as a heatmap.
|
|
137
|
+
|
|
138
|
+
:param seqdata: SequenceData object containing sequence information
|
|
139
|
+
:param weights: (np.ndarray or "auto") Weights for sequences. If "auto", uses seqdata.weights if available
|
|
140
|
+
:param title: optional title for the plot
|
|
141
|
+
:param fontsize: base font size for labels
|
|
142
|
+
:param save_as: optional file path to save the plot
|
|
143
|
+
:param dpi: resolution of the saved plot
|
|
144
|
+
:param format: format string for annotations (default "%.2f")
|
|
145
|
+
"""
|
|
146
|
+
|
|
147
|
+
# Compute transition matrix with weights
|
|
148
|
+
transition_matrix = compute_transition_matrix(seqdata, weights=weights)
|
|
149
|
+
transition_matrix = np.array(transition_matrix)
|
|
150
|
+
|
|
151
|
+
# Set figure size
|
|
152
|
+
plt.figure(figsize=(12, 10))
|
|
153
|
+
|
|
154
|
+
# Use fresh color scheme
|
|
155
|
+
cmap = sns.color_palette("light:#5A9", as_cmap=True)
|
|
156
|
+
|
|
157
|
+
# Generate heatmap using pre-formatted annotation strings
|
|
158
|
+
ax = sns.heatmap(
|
|
159
|
+
transition_matrix,
|
|
160
|
+
annot=True,
|
|
161
|
+
fmt=format,
|
|
162
|
+
cmap=cmap,
|
|
163
|
+
xticklabels=seqdata.labels,
|
|
164
|
+
yticklabels=seqdata.labels,
|
|
165
|
+
linewidths=0.5,
|
|
166
|
+
linecolor="gray",
|
|
167
|
+
cbar_kws={"shrink": 0.8},
|
|
168
|
+
square=True,
|
|
169
|
+
annot_kws={"fontsize": fontsize - 2}
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
# Show all the borderlines
|
|
173
|
+
for _, spine in ax.spines.items():
|
|
174
|
+
spine.set_visible(True)
|
|
175
|
+
|
|
176
|
+
# Adjust format
|
|
177
|
+
if title:
|
|
178
|
+
show_plot_title(plt.gca(), title, show=True, fontsize=fontsize+2, fontweight='bold', pad=20)
|
|
179
|
+
|
|
180
|
+
plt.xlabel("State at t + 1", fontsize=fontsize, labelpad=10)
|
|
181
|
+
plt.ylabel("State at t", fontsize=fontsize, labelpad=10)
|
|
182
|
+
|
|
183
|
+
# Adjust label rotation and alignment
|
|
184
|
+
plt.xticks(rotation=45, ha="right")
|
|
185
|
+
plt.yticks(rotation=0)
|
|
186
|
+
|
|
187
|
+
# Adjust layout
|
|
188
|
+
plt.tight_layout()
|
|
189
|
+
|
|
190
|
+
save_and_show_results(save_as, dpi=dpi)
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""
|
|
2
|
+
@Author : Yuqi Liang 梁彧祺
|
|
3
|
+
@File : __init__.py.py
|
|
4
|
+
@Time : 01/03/2025 10:16
|
|
5
|
+
@Desc :
|
|
6
|
+
"""
|
|
7
|
+
from .utils import (set_up_time_labels_for_x_axis,
|
|
8
|
+
create_standalone_legend,
|
|
9
|
+
save_figure_to_buffer,
|
|
10
|
+
combine_plot_with_legend,
|
|
11
|
+
save_and_show_results,
|
|
12
|
+
determine_layout,
|
|
13
|
+
show_plot_title,
|
|
14
|
+
show_group_title)
|
|
15
|
+
|
|
16
|
+
__all__ = ['set_up_time_labels_for_x_axis',
|
|
17
|
+
'create_standalone_legend',
|
|
18
|
+
'save_figure_to_buffer',
|
|
19
|
+
'combine_plot_with_legend',
|
|
20
|
+
'save_and_show_results',
|
|
21
|
+
'determine_layout',
|
|
22
|
+
'show_plot_title',
|
|
23
|
+
'show_group_title']
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
"""
|
|
2
|
+
@Author : Yuqi Liang 梁彧祺
|
|
3
|
+
@File : utils.py
|
|
4
|
+
@Time : 01/03/2025 10:16
|
|
5
|
+
@Desc :
|
|
6
|
+
"""
|
|
7
|
+
import numpy as np
|
|
8
|
+
import matplotlib.pyplot as plt
|
|
9
|
+
from matplotlib.axes import Axes
|
|
10
|
+
|
|
11
|
+
from io import BytesIO
|
|
12
|
+
from PIL import Image
|
|
13
|
+
from typing import Tuple, Optional, List, Dict, Any
|
|
14
|
+
|
|
15
|
+
from sequenzo import SequenceData
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def set_up_time_labels_for_x_axis(seqdata: SequenceData,
|
|
19
|
+
ax: Axes,
|
|
20
|
+
color: str = "gray") -> None:
|
|
21
|
+
"""
|
|
22
|
+
Helper function to set up time labels for the x-axis.
|
|
23
|
+
|
|
24
|
+
:param seqdata: (SequenceData) A SequenceData object containing time information
|
|
25
|
+
:param ax: (matplotlib.axes.Axes) The axes to set labels on
|
|
26
|
+
"""
|
|
27
|
+
# Extract time labels (year or age)
|
|
28
|
+
time_labels = np.array(seqdata.cleaned_time)
|
|
29
|
+
|
|
30
|
+
# Determine the number of time steps
|
|
31
|
+
num_time_steps = len(time_labels)
|
|
32
|
+
|
|
33
|
+
# Dynamic X-Tick Adjustment
|
|
34
|
+
if num_time_steps <= 10:
|
|
35
|
+
# If 10 or fewer time points, show all labels
|
|
36
|
+
xtick_positions = np.arange(num_time_steps)
|
|
37
|
+
elif num_time_steps <= 20:
|
|
38
|
+
# If 10-20 time points, show every 2nd label
|
|
39
|
+
xtick_positions = np.arange(0, num_time_steps, step=2)
|
|
40
|
+
else:
|
|
41
|
+
# More than 20 time points -> Pick 10 evenly spaced tick positions
|
|
42
|
+
xtick_positions = np.linspace(0, num_time_steps - 1, num=10, dtype=int)
|
|
43
|
+
|
|
44
|
+
# Set x-ticks and labels dynamically
|
|
45
|
+
ax.set_xticks(xtick_positions)
|
|
46
|
+
ax.set_xticklabels(time_labels[xtick_positions], fontsize=10, rotation=0, ha="center", color=color)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def create_standalone_legend(
|
|
50
|
+
colors: Dict[str, str],
|
|
51
|
+
labels: List[str],
|
|
52
|
+
ncol: int = 5,
|
|
53
|
+
figsize: Tuple[int, int] = (8, 1),
|
|
54
|
+
fontsize: int = 10,
|
|
55
|
+
dpi: int = 200
|
|
56
|
+
) -> BytesIO:
|
|
57
|
+
"""
|
|
58
|
+
Creates a standalone legend image without borders.
|
|
59
|
+
|
|
60
|
+
Parameters:
|
|
61
|
+
colors: Dictionary mapping labels to color values
|
|
62
|
+
labels: List of state labels to include in the legend
|
|
63
|
+
ncol: Number of columns in the legend
|
|
64
|
+
figsize: Size of the figure (width, height)
|
|
65
|
+
fontsize: Font size for legend text
|
|
66
|
+
dpi: Resolution of the output image
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
BytesIO: In-memory buffer containing the legend image
|
|
70
|
+
"""
|
|
71
|
+
# Create a new figure for the legend
|
|
72
|
+
legend_fig = plt.figure(figsize=figsize)
|
|
73
|
+
ax = legend_fig.add_subplot(111)
|
|
74
|
+
ax.axis('off') # Hide the axes
|
|
75
|
+
|
|
76
|
+
# Create handles for the legend
|
|
77
|
+
handles = [plt.Rectangle((0, 0), 1, 1, color=colors.get(s, "gray")) for s in labels]
|
|
78
|
+
|
|
79
|
+
# Create the legend without a frame
|
|
80
|
+
legend = ax.legend(
|
|
81
|
+
handles,
|
|
82
|
+
labels,
|
|
83
|
+
loc='center',
|
|
84
|
+
ncol=min(ncol, len(labels)),
|
|
85
|
+
frameon=False, # No border around legend
|
|
86
|
+
fontsize=fontsize
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
# Save to memory buffer
|
|
90
|
+
buffer = BytesIO()
|
|
91
|
+
legend_fig.savefig(
|
|
92
|
+
buffer,
|
|
93
|
+
format='png',
|
|
94
|
+
dpi=dpi,
|
|
95
|
+
bbox_inches='tight',
|
|
96
|
+
pad_inches=0 # Remove padding
|
|
97
|
+
)
|
|
98
|
+
plt.close(legend_fig)
|
|
99
|
+
buffer.seek(0)
|
|
100
|
+
|
|
101
|
+
return buffer
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def combine_plot_with_legend(
|
|
105
|
+
main_image_buffer: BytesIO,
|
|
106
|
+
legend_buffer: BytesIO,
|
|
107
|
+
output_path: Optional[str] = None,
|
|
108
|
+
dpi: int = 200,
|
|
109
|
+
padding: int = 10
|
|
110
|
+
) -> Image.Image:
|
|
111
|
+
"""
|
|
112
|
+
Combines a main plot image with a legend image, placing the legend below the main plot.
|
|
113
|
+
This means that it saves the combined image to a file if an output path is provided,
|
|
114
|
+
which is different from the function `save_and_show_results` as that is responsible for visualizations that do not require cropping.
|
|
115
|
+
|
|
116
|
+
Parameters:
|
|
117
|
+
main_image_buffer: Buffer containing the main plot image
|
|
118
|
+
legend_buffer: Buffer containing the legend image
|
|
119
|
+
output_path: Optional path to save the combined image
|
|
120
|
+
dpi: Resolution for the saved image
|
|
121
|
+
padding: Padding between main image and legend in pixels
|
|
122
|
+
|
|
123
|
+
Returns:
|
|
124
|
+
PIL.Image: The combined image
|
|
125
|
+
"""
|
|
126
|
+
# Open images from buffers
|
|
127
|
+
main_img = Image.open(main_image_buffer)
|
|
128
|
+
legend_img = Image.open(legend_buffer)
|
|
129
|
+
|
|
130
|
+
# Calculate dimensions for combined image
|
|
131
|
+
combined_width = max(main_img.width, legend_img.width)
|
|
132
|
+
combined_height = main_img.height + padding + legend_img.height
|
|
133
|
+
|
|
134
|
+
# Create new blank image
|
|
135
|
+
combined_img = Image.new('RGB', (combined_width, combined_height), (255, 255, 255))
|
|
136
|
+
|
|
137
|
+
# Paste main image at top
|
|
138
|
+
combined_img.paste(main_img, (0, 0))
|
|
139
|
+
|
|
140
|
+
# Center legend relative to main image width (not combined width)
|
|
141
|
+
legend_x = (main_img.width - legend_img.width) // 2
|
|
142
|
+
# Ensure legend doesn't go outside the combined image bounds
|
|
143
|
+
legend_x = max(0, min(legend_x, combined_width - legend_img.width))
|
|
144
|
+
combined_img.paste(legend_img, (legend_x, main_img.height + padding))
|
|
145
|
+
|
|
146
|
+
# Save if output path is provided
|
|
147
|
+
if output_path:
|
|
148
|
+
combined_img.save(output_path, dpi=(dpi, dpi))
|
|
149
|
+
|
|
150
|
+
return combined_img
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def save_figure_to_buffer(fig, dpi: int = 200) -> BytesIO:
|
|
154
|
+
"""
|
|
155
|
+
Saves a matplotlib figure to a BytesIO buffer.
|
|
156
|
+
|
|
157
|
+
Parameters:
|
|
158
|
+
fig: Matplotlib figure to save
|
|
159
|
+
dpi: Resolution of the output image
|
|
160
|
+
|
|
161
|
+
Returns:
|
|
162
|
+
BytesIO: Buffer containing the figure image
|
|
163
|
+
"""
|
|
164
|
+
buffer = BytesIO()
|
|
165
|
+
fig.savefig(buffer, format='png', dpi=dpi, bbox_inches='tight')
|
|
166
|
+
plt.close(fig)
|
|
167
|
+
buffer.seek(0)
|
|
168
|
+
return buffer
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
def save_and_show_results(save_as=None, dpi=200, show=True):
|
|
172
|
+
"""
|
|
173
|
+
Save and optionally display matplotlib figure.
|
|
174
|
+
|
|
175
|
+
Parameters:
|
|
176
|
+
- save_as: Optional filename to save the figure to
|
|
177
|
+
- dpi: Resolution for saved image
|
|
178
|
+
- show: Whether to display the figure (default: True)
|
|
179
|
+
|
|
180
|
+
Returns:
|
|
181
|
+
- The current figure object (plt.gcf())
|
|
182
|
+
"""
|
|
183
|
+
if save_as:
|
|
184
|
+
if not any(save_as.endswith(ext) for ext in ['.png', '.jpg', '.jpeg', '.pdf', '.svg']):
|
|
185
|
+
save_as += '.png'
|
|
186
|
+
plt.savefig(save_as, dpi=dpi, bbox_inches='tight')
|
|
187
|
+
|
|
188
|
+
# Get the current figure before closing it
|
|
189
|
+
current_fig = plt.gcf()
|
|
190
|
+
|
|
191
|
+
# Show if explicitly requested or if saving (for visual confirmation)
|
|
192
|
+
if show or save_as:
|
|
193
|
+
plt.show()
|
|
194
|
+
|
|
195
|
+
# Prevent memory leak by closing after show/save
|
|
196
|
+
plt.close()
|
|
197
|
+
|
|
198
|
+
# Return the figure that was current before closing
|
|
199
|
+
return current_fig
|
|
200
|
+
|
|
201
|
+
|
|
202
|
+
|
|
203
|
+
def determine_layout(num_items: int,
|
|
204
|
+
layout: str = 'column',
|
|
205
|
+
nrows: Optional[int] = None,
|
|
206
|
+
ncols: Optional[int] = None) -> Tuple[int, int]:
|
|
207
|
+
"""
|
|
208
|
+
Determine subplot layout (rows, columns) based on the number of items to plot.
|
|
209
|
+
TODO: 1. change to all visualizations that require multiple graphs 2. 发包,因为我也改了颜色了
|
|
210
|
+
|
|
211
|
+
Parameters:
|
|
212
|
+
num_items (int): Total number of subplots needed.
|
|
213
|
+
layout (str): Layout strategy ('column' or 'grid'), used if nrows/ncols not provided.
|
|
214
|
+
nrows (int, optional): Number of rows (manual override).
|
|
215
|
+
ncols (int, optional): Number of columns (manual override).
|
|
216
|
+
|
|
217
|
+
Returns:
|
|
218
|
+
Tuple[int, int]: A tuple of (nrows, ncols) for subplot layout.
|
|
219
|
+
|
|
220
|
+
Raises:
|
|
221
|
+
ValueError: If layout config is invalid or does not fit all subplots.
|
|
222
|
+
"""
|
|
223
|
+
# Check partial input
|
|
224
|
+
if (nrows is None and ncols is not None) or (ncols is None and nrows is not None):
|
|
225
|
+
raise ValueError("If manually specifying layout, both 'nrows' and 'ncols' must be provided.")
|
|
226
|
+
|
|
227
|
+
# Manual override
|
|
228
|
+
if nrows is not None and ncols is not None:
|
|
229
|
+
total_slots = nrows * ncols
|
|
230
|
+
if total_slots < num_items:
|
|
231
|
+
raise ValueError(f"Provided layout ({nrows}x{ncols}) is too small for {num_items} plots.")
|
|
232
|
+
return nrows, ncols
|
|
233
|
+
|
|
234
|
+
# Automatic layout
|
|
235
|
+
if layout == 'column':
|
|
236
|
+
# Use up to 3 columns, but never exceed the number of items.
|
|
237
|
+
# This avoids allocating invisible (but space-occupying) subplots
|
|
238
|
+
# that cause extra blank space on the right when num_items < 3.
|
|
239
|
+
ncols = int(min(3, max(1, num_items)))
|
|
240
|
+
nrows = (num_items + ncols - 1) // ncols
|
|
241
|
+
elif layout == 'grid':
|
|
242
|
+
ncols = int(np.ceil(np.sqrt(num_items)))
|
|
243
|
+
nrows = (num_items + ncols - 1) // ncols
|
|
244
|
+
else:
|
|
245
|
+
raise ValueError(f"Unsupported layout style: '{layout}'")
|
|
246
|
+
|
|
247
|
+
return nrows, ncols
|
|
248
|
+
|
|
249
|
+
|
|
250
|
+
def show_plot_title(ax: Axes,
|
|
251
|
+
title: Optional[str],
|
|
252
|
+
show: bool = True,
|
|
253
|
+
fontsize: Optional[int] = None,
|
|
254
|
+
pad: Optional[int] = None,
|
|
255
|
+
loc: Optional[str] = None,
|
|
256
|
+
color: Optional[str] = None,
|
|
257
|
+
fontweight: Optional[str] = None) -> None:
|
|
258
|
+
"""
|
|
259
|
+
Conditionally set a matplotlib axis title.
|
|
260
|
+
|
|
261
|
+
Parameters:
|
|
262
|
+
ax: Target axis
|
|
263
|
+
title: Title text; if None or empty, nothing will be set
|
|
264
|
+
show: If False, do nothing
|
|
265
|
+
fontsize, pad, loc, color, fontweight: forwarded to ax.set_title if provided
|
|
266
|
+
"""
|
|
267
|
+
if not show or not title:
|
|
268
|
+
return
|
|
269
|
+
kwargs = {}
|
|
270
|
+
if fontsize is not None:
|
|
271
|
+
kwargs["fontsize"] = fontsize
|
|
272
|
+
if pad is not None:
|
|
273
|
+
kwargs["pad"] = pad
|
|
274
|
+
if loc is not None:
|
|
275
|
+
kwargs["loc"] = loc
|
|
276
|
+
if color is not None:
|
|
277
|
+
kwargs["color"] = color
|
|
278
|
+
if fontweight is not None:
|
|
279
|
+
kwargs["fontweight"] = fontweight
|
|
280
|
+
ax.set_title(title, **kwargs)
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
def show_group_title(ax: Axes,
|
|
284
|
+
text: Optional[str],
|
|
285
|
+
show: bool = True,
|
|
286
|
+
fontsize: Optional[int] = None,
|
|
287
|
+
x: float = 0.95,
|
|
288
|
+
y: float = 1.02,
|
|
289
|
+
ha: str = 'right',
|
|
290
|
+
va: str = 'bottom',
|
|
291
|
+
color: str = 'black') -> None:
|
|
292
|
+
"""
|
|
293
|
+
Conditionally place a group title as axis-anchored text.
|
|
294
|
+
|
|
295
|
+
Parameters:
|
|
296
|
+
ax: Target axis
|
|
297
|
+
text: Text content; if None/empty, nothing will be placed
|
|
298
|
+
show: If False, do nothing
|
|
299
|
+
fontsize: Font size
|
|
300
|
+
x, y: Coordinates in axis fraction coordinates
|
|
301
|
+
ha, va: Horizontal/vertical alignment
|
|
302
|
+
color: Text color
|
|
303
|
+
"""
|
|
304
|
+
if not show or not text:
|
|
305
|
+
return
|
|
306
|
+
kwargs = {"transform": ax.transAxes, "ha": ha, "va": va, "color": color}
|
|
307
|
+
if fontsize is not None:
|
|
308
|
+
kwargs["fontsize"] = fontsize
|
|
309
|
+
ax.text(x, y, text, **kwargs)
|
|
310
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"""
|
|
2
|
+
@Author : Yuqi Liang 梁彧祺
|
|
3
|
+
@File : __init__.py
|
|
4
|
+
@Time : 30/09/2025 23:34
|
|
5
|
+
@Desc : Event History Analysis module for sequence analysis
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .sequence_analysis_multi_state_model import (
|
|
9
|
+
SAMM,
|
|
10
|
+
sequence_analysis_multi_state_model,
|
|
11
|
+
plot_samm,
|
|
12
|
+
seqsammseq,
|
|
13
|
+
set_typology,
|
|
14
|
+
seqsammeha,
|
|
15
|
+
# Keep old names for backward compatibility
|
|
16
|
+
seqsamm
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
from .sequence_history_analysis import (
|
|
20
|
+
seqsha,
|
|
21
|
+
person_level_to_person_period
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
__all__ = [
|
|
25
|
+
'SAMM',
|
|
26
|
+
'sequence_analysis_multi_state_model',
|
|
27
|
+
'plot_samm',
|
|
28
|
+
'seqsammseq',
|
|
29
|
+
'set_typology',
|
|
30
|
+
'seqsammeha',
|
|
31
|
+
'seqsha',
|
|
32
|
+
'person_level_to_person_period',
|
|
33
|
+
# Keep old names for backward compatibility
|
|
34
|
+
'seqsamm'
|
|
35
|
+
]
|