py-cmdtabs 1.2.0__tar.gz → 1.2.1__tar.gz
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.
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/PKG-INFO +1 -1
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/setup.cfg +2 -0
- py_cmdtabs-1.2.1/src/py_cmdtabs/__init__.py +16 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/src/py_cmdtabs/cli_manager.py +136 -13
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/src/py_cmdtabs/cmdtabs.py +178 -73
- py_cmdtabs-1.2.1/src/py_cmdtabs/main_modules.py +326 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/src/py_cmdtabs.egg-info/PKG-INFO +1 -1
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/src/py_cmdtabs.egg-info/SOURCES.txt +3 -3
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/src/py_cmdtabs.egg-info/entry_points.txt +2 -0
- py_cmdtabs-1.2.1/tests/cli_example_report/Report.html +4111 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/launch.sh +1 -1
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/outputs/wide_table +1 -1
- py_cmdtabs-1.2.1/tests/cli_example_report/styles.css +130 -0
- py_cmdtabs-1.2.1/tests/cli_example_report/subtemplates/aggregate_column_data +52 -0
- py_cmdtabs-1.2.1/tests/cli_example_report/subtemplates/column_filter +77 -0
- py_cmdtabs-1.2.1/tests/cli_example_report/subtemplates/create_metric_table +27 -0
- py_cmdtabs-1.2.1/tests/cli_example_report/subtemplates/desaggregate_column_data +24 -0
- py_cmdtabs-1.2.1/tests/cli_example_report/subtemplates/excel_to_tabular +51 -0
- py_cmdtabs-1.2.1/tests/cli_example_report/subtemplates/filter_by_list +61 -0
- py_cmdtabs-1.2.1/tests/cli_example_report/subtemplates/get_columns +24 -0
- py_cmdtabs-1.2.1/tests/cli_example_report/subtemplates/intersect_columns +46 -0
- py_cmdtabs-1.2.1/tests/cli_example_report/subtemplates/merge_tabular +23 -0
- py_cmdtabs-1.2.1/tests/cli_example_report/subtemplates/records_count +15 -0
- py_cmdtabs-1.2.1/tests/cli_example_report/subtemplates/show_n_exec +48 -0
- py_cmdtabs-1.2.1/tests/cli_example_report/subtemplates/standard_name_replacer +30 -0
- py_cmdtabs-1.2.1/tests/cli_example_report/subtemplates/subset_table +41 -0
- py_cmdtabs-1.2.1/tests/cli_example_report/subtemplates/table_linker +46 -0
- py_cmdtabs-1.2.1/tests/cli_example_report/subtemplates/tag_table +36 -0
- py_cmdtabs-1.2.1/tests/cli_example_report/subtemplates/transform_to_latex +24 -0
- py_cmdtabs-1.2.1/tests/cli_example_report/subtemplates/transpose_table +14 -0
- py_cmdtabs-1.2.1/tests/cli_example_report/tables/organization +9 -0
- py_cmdtabs-1.2.1/tests/cli_example_report/template.txt +87 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/test_cli_manager.py +43 -49
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/test_cmdtabs_lib.py +13 -14
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/test_expanded_methods.py +2 -3
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/test_input_parsing.py +60 -6
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/test_io.py +2 -3
- py_cmdtabs-1.2.0/src/py_cmdtabs/__init__.py +0 -2
- py_cmdtabs-1.2.0/src/py_cmdtabs/main_modules.py +0 -245
- py_cmdtabs-1.2.0/tests/cli_example_report/Report.html +0 -3796
- py_cmdtabs-1.2.0/tests/cli_example_report/subtemplates/aggregate_column_data +0 -55
- py_cmdtabs-1.2.0/tests/cli_example_report/subtemplates/column_filter +0 -88
- py_cmdtabs-1.2.0/tests/cli_example_report/subtemplates/create_metric_table +0 -50
- py_cmdtabs-1.2.0/tests/cli_example_report/subtemplates/desaggregate_column_data +0 -25
- py_cmdtabs-1.2.0/tests/cli_example_report/subtemplates/example +0 -64
- py_cmdtabs-1.2.0/tests/cli_example_report/subtemplates/example_written +0 -71
- py_cmdtabs-1.2.0/tests/cli_example_report/subtemplates/excel_to_tabular +0 -56
- py_cmdtabs-1.2.0/tests/cli_example_report/subtemplates/filter_by_list +0 -64
- py_cmdtabs-1.2.0/tests/cli_example_report/subtemplates/general +0 -41
- py_cmdtabs-1.2.0/tests/cli_example_report/subtemplates/get_columns +0 -29
- py_cmdtabs-1.2.0/tests/cli_example_report/subtemplates/intersect_columns +0 -59
- py_cmdtabs-1.2.0/tests/cli_example_report/subtemplates/merge_tabular +0 -25
- py_cmdtabs-1.2.0/tests/cli_example_report/subtemplates/records_count +0 -16
- py_cmdtabs-1.2.0/tests/cli_example_report/subtemplates/standard_name_replacer +0 -35
- py_cmdtabs-1.2.0/tests/cli_example_report/subtemplates/subset_table +0 -45
- py_cmdtabs-1.2.0/tests/cli_example_report/subtemplates/table_linker +0 -47
- py_cmdtabs-1.2.0/tests/cli_example_report/subtemplates/tag_table +0 -49
- py_cmdtabs-1.2.0/tests/cli_example_report/subtemplates/transform_to_latex +0 -25
- py_cmdtabs-1.2.0/tests/cli_example_report/subtemplates/transpose_table +0 -16
- py_cmdtabs-1.2.0/tests/cli_example_report/template.txt +0 -104
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/.readthedocs.yml +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/AUTHORS.rst +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/CHANGELOG.rst +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/CONTRIBUTING.rst +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/LICENSE.txt +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/README.rst +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/docs/Makefile +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/docs/_static/.gitignore +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/docs/authors.rst +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/docs/changelog.rst +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/docs/conf.py +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/docs/contributing.rst +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/docs/index.rst +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/docs/license.rst +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/docs/readme.rst +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/docs/requirements.txt +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/make_package.sh +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/pyproject.toml +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/requirements.txt +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/setup.py +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/src/py_cmdtabs.egg-info/dependency_links.txt +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/src/py_cmdtabs.egg-info/not-zip-safe +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/src/py_cmdtabs.egg-info/requires.txt +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/src/py_cmdtabs.egg-info/top_level.txt +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/__init__.py +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/example +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/outputs/blackfiltered_long_table +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/outputs/filtered_long_table +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/outputs/ref_filtered_disease_cluster_ref_rnd +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/outputs/subset_table/disease_cluster_ref_rnd_chunk0 +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/outputs/subset_table/disease_cluster_ref_rnd_chunk1 +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/outputs/subset_table/disease_cluster_ref_rnd_chunk2 +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/outputs/subset_table2/disease_cluster_ref_rnd_chunk0 +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/outputs/subset_table2/disease_cluster_ref_rnd_chunk1 +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/special_files/hoja1.png +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/special_files/hoja2.png +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/special_files/scRNAseq.htm +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/special_files/scRNAseq.xlsx +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/special_files/scRNAseq_archivos/filelist.xml +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/special_files/scRNAseq_archivos/sheet001.htm +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/special_files/scRNAseq_archivos/sheet002.htm +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/special_files/scRNAseq_archivos/stylesheet.css +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/special_files/scRNAseq_archivos/tabstrip.htm +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/special_files/~$scRNAseq.xlsx +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/tables/cluster_genes_dis_agg +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/tables/cluster_genes_dis_agg2 +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/tables/cluster_genes_dis_desagg +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/tables/cluster_genes_dis_desagg_3cols +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/tables/cluster_genes_dis_desagg_4cols +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/tables/cluster_stats +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/tables/clusts_to_filter +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/tables/disease_cluster +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/tables/disease_cluster_ref_rnd +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/tables/disease_cluster_uniq +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/tables/disease_gene +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/tables/long_disease_cluster +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/tables/long_table +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/tables/metrics_table +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/tables/mondo_to_orpha +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/tables/nets_to_filter +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/tables/simple_table +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/cli_example_report/tables/tracker +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/conftest.py +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/agg_2index_2values.txt +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/agg_data_3_columns.txt +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/all_metrics +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/blacklist +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/blacklist_partial +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/cluster_genes.xlsx +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/cluster_genes_dis_agg +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/cluster_genes_dis_desagg +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/cluster_stats +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/cluster_stats_header +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/dis_gene_attrs +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/disease_cluster +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/disease_cluster_uniq +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/disease_gene +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/filterlist +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/filterlist_partial +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/hp_long_list.txt +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ids2count +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ids2count_short +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/metric_table +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/mondo_genes +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/mondo_genes.gz +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/TEST_file +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/TEST_file_transposed +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/agg_2index_2values.txt +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/agg_2index_2values_several_aggregators.txt +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/agg_data_3_columns_result.txt +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/cluster_genes_dis_AGG +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/cluster_genes_dis_AGG_stdin +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/cluster_genes_dis_DESAGG +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/cluster_genes_dis_DESAGG_stdin +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/cluster_genes_from_excel.txt +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/column_matching_hard +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/column_matching_hard_various_keys +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/column_matching_hard_various_keys_and_every_columns +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/column_matching_hard_various_keys_and_every_columns_header +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/column_matching_hard_various_keys_and_some_columns +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/column_matching_soft +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/column_matching_soft_1_column +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/column_matching_soft_1_column_reverse +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/column_matching_soft_1_column_uniq +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/column_matching_soft_and_every_columns +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/column_matching_soft_and_some_columns +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/ids2count +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/intersect_columns_count +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/intersect_columns_default +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/intersect_columns_default_stdin_a +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/intersect_columns_default_stdin_b +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/intersect_columns_full +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/linked_table +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/linked_table3 +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/linked_table_2 +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/linked_table_matches +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/merge_disease_cluster_gene +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/metric_table +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/mondo_genes_transposed +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/mondo_genes_transposed.gz +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/replaced_name +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/replaced_name_untranslated +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/subset_table +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/subset_table_fold/mondo_genes_chunk0 +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/subset_table_fold/mondo_genes_chunk1 +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/subset_table_fold/mondo_genes_chunk2 +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/tag_table +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/tag_table_header +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/transposed_cluster_genes_dis_AGG +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/transposed_cluster_genes_dis_DESAGG +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/transposed_cluster_genes_from_excel.txt +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/transposed_column_matching_hard +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/transposed_intersect_columns_default +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/transposed_linked_table +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/transposed_merge_disease_cluster_gene +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/transposed_metric_table +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/transposed_replaced_name +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/ref_output_scripts/transposed_tag_table +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/simple_table +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/tracker +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/transposed/all_metrics +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/transposed/cluster_genes.xlsx +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/transposed/cluster_genes_dis_agg +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/transposed/cluster_genes_dis_desagg +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/transposed/cluster_stats +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/transposed/disease_cluster +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/transposed/disease_cluster_uniq +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/transposed/disease_gene +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/data_tests/transposed/tranpose_data.py +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tests/test_compressed_pipes.sh +0 -0
- {py_cmdtabs-1.2.0 → py_cmdtabs-1.2.1}/tox.ini +0 -0
|
@@ -39,6 +39,8 @@ testing =
|
|
|
39
39
|
|
|
40
40
|
[options.entry_points]
|
|
41
41
|
console_scripts =
|
|
42
|
+
cmdtabs = py_cmdtabs.cli_manager:cmdtabs
|
|
43
|
+
cmdtabs_merge = py_cmdtabs.cli_manager:cmdtabs_merge
|
|
42
44
|
aggregate_column_data = py_cmdtabs.cli_manager:aggregate_column_data
|
|
43
45
|
column_filter = py_cmdtabs.cli_manager:column_filter
|
|
44
46
|
create_metric_table = py_cmdtabs.cli_manager:create_metric_table
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
|
|
3
|
+
if sys.version_info[:2] >= (3, 8):
|
|
4
|
+
# TODO: Import directly (no need for conditional) when `python_requires = >= 3.8`
|
|
5
|
+
from importlib.metadata import PackageNotFoundError, version # pragma: no cover
|
|
6
|
+
else:
|
|
7
|
+
from importlib_metadata import PackageNotFoundError, version # pragma: no cover
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
# Change here if project is renamed and does not equal the package name
|
|
11
|
+
dist_name = __name__
|
|
12
|
+
__version__ = version(dist_name)
|
|
13
|
+
except PackageNotFoundError: # pragma: no cover
|
|
14
|
+
__version__ = "unknown"
|
|
15
|
+
finally:
|
|
16
|
+
del version, PackageNotFoundError
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
import argparse
|
|
2
|
-
import sys
|
|
3
|
-
import os
|
|
4
|
-
import codecs
|
|
5
|
-
|
|
6
|
-
from py_cmdtabs.cmdtabs import CmdTabs
|
|
1
|
+
import argparse, sys, os, codecs
|
|
7
2
|
from py_cmdtabs.main_modules import *
|
|
8
3
|
|
|
9
4
|
## TYPES
|
|
10
5
|
def based_0(string): return int(string) - 1
|
|
11
|
-
def list_based_0(string):
|
|
6
|
+
def list_based_0(string):
|
|
7
|
+
from py_cmdtabs.cmdtabs import CmdTabs
|
|
8
|
+
return CmdTabs.parse_column_indices(string.split(','))
|
|
12
9
|
def list_str(values): return values.split(',')
|
|
13
10
|
def unescaped_str(arg_str): return codecs.decode(str(arg_str), 'unicode_escape')
|
|
11
|
+
def nested_int_list(arg_str): return [ [int(col) - 1 for col in str_cols.split(',')] for str_cols in arg_str.split(';')]
|
|
14
12
|
|
|
15
13
|
## Common options
|
|
16
14
|
def add_common_options(parser, flags_to_skip = [], help_replacer={}):
|
|
@@ -82,7 +80,7 @@ def create_metric_table(args=None):
|
|
|
82
80
|
add_common_options(parser, flags_to_skip=["--input_file"])
|
|
83
81
|
parser.add_argument("metric_file", metavar='M',
|
|
84
82
|
help="File with tabulated metrics")
|
|
85
|
-
parser.add_argument("attributes", metavar='A',
|
|
83
|
+
parser.add_argument("attributes", metavar='A', type=list_str,
|
|
86
84
|
help="String with comma separated attributes")
|
|
87
85
|
parser.add_argument("output_file", metavar='O',
|
|
88
86
|
help="Output file path")
|
|
@@ -110,10 +108,10 @@ def excel_to_tabular(args=None):
|
|
|
110
108
|
add_common_options(parser, flags_to_skip=["--compressed_in"], help_replacer={"--input_file": "Input xlsx file"})
|
|
111
109
|
parser.add_argument("-o", "--output_file", dest="output_file",
|
|
112
110
|
help="Path to output file")
|
|
113
|
-
parser.add_argument("-c", "--columns2extract", dest="columns2extract", default=[
|
|
114
|
-
help="
|
|
115
|
-
parser.add_argument("-r", "--rows2extract", dest="rows2extract", default=[
|
|
116
|
-
help="
|
|
111
|
+
parser.add_argument("-c", "--columns2extract", dest="columns2extract", default=[], type=list_based_0,
|
|
112
|
+
help="Comma-separated column position(s) to extract (1 based). If not used, all columns will be extracted")
|
|
113
|
+
parser.add_argument("-r", "--rows2extract", dest="rows2extract", default=[], type=list_based_0,
|
|
114
|
+
help="Comma-separated row position(s) to extract (1 based). If not used, all rows will be extracted")
|
|
117
115
|
parser.add_argument("-s", "--sheet_number", dest="sheet_number", default=0, type=based_0,
|
|
118
116
|
help="Sheet number to work with. Default 1")
|
|
119
117
|
|
|
@@ -292,4 +290,129 @@ def transpose_table(args=None):
|
|
|
292
290
|
parser.add_argument("-o", "--output_file", dest="output_file", default=None,
|
|
293
291
|
help="Path to output file")
|
|
294
292
|
opts = parser.parse_args(args)
|
|
295
|
-
main_transpose_table(opts)
|
|
293
|
+
main_transpose_table(opts)
|
|
294
|
+
|
|
295
|
+
def cmdtabs(args=None):
|
|
296
|
+
if args == None: args = sys.argv[1:]
|
|
297
|
+
parser = argparse.ArgumentParser(description=f'Usage: {os.path.basename(__file__)} [options]')
|
|
298
|
+
add_common_options(parser)
|
|
299
|
+
parser.add_argument("-c", "--columns", dest="columns", default=[0], type=list_based_0,
|
|
300
|
+
help="Index of columns in base 1 to compare")
|
|
301
|
+
parser.add_argument("-H", "--header", dest="header", default=False, action='store_true',
|
|
302
|
+
help="Indicate if files have header")
|
|
303
|
+
parser.add_argument("-I", "--index_file", dest="index_file", default=None,
|
|
304
|
+
help="Path to index file")
|
|
305
|
+
parser.add_argument("-o", "--output_file", dest="output_file", default=None,
|
|
306
|
+
help="Path to output file")
|
|
307
|
+
parser.add_argument("-s", "--separator", dest="separator", default="\t", type=unescaped_str,
|
|
308
|
+
help="Input table column character separator")
|
|
309
|
+
parser.add_argument("-t", "--tags", dest="tags", default= [],
|
|
310
|
+
help="Strings or files (only first line will be used) sepparated by commas", type=list_str)
|
|
311
|
+
parser.add_argument("-u", "--remove_untranslated", dest="remove_untranslated", default=False, action='store_true',
|
|
312
|
+
help="Activate this flag for outputting the untranslated entries")
|
|
313
|
+
parser.add_argument("-w", "--whole", dest="whole", default=False, action='store_true',
|
|
314
|
+
help="Indicate if you want the whole table and tabular environment to be returned with the table transformed")
|
|
315
|
+
|
|
316
|
+
parser.add_argument("--aggregate", dest="aggregate", default=False, action='store_true',
|
|
317
|
+
help="Aggregate table columns")
|
|
318
|
+
parser.add_argument("--agg_ref_col_index", dest="agg_col_index",
|
|
319
|
+
help="Column index (1 based) to use as reference", type=list_based_0)
|
|
320
|
+
parser.add_argument("--agg_col", dest="col_aggregate",
|
|
321
|
+
help="Column(s) index (1 based) to extract data and join for each id in column index (if more than one, comma separated)", type=list_based_0)
|
|
322
|
+
parser.add_argument("--agg_mode", dest="agg_mode", default="concatenate",
|
|
323
|
+
help="Mode to perform aggregation. Current available: max,min,mean,median,sum,std,var,IQR,PC25,PC75,count & concatenate. Default (concatenate) is string concatenation by defined separator. More than one aggregation mode can be used separated by commas")
|
|
324
|
+
parser.add_argument("--agg_sep", dest="agg_sep", default=",",
|
|
325
|
+
help="Character separator when collapse data")
|
|
326
|
+
parser.add_argument("--count-cols", dest="count_cols", default=None, type=list_based_0,
|
|
327
|
+
help="Index of columns in base 1 to count")
|
|
328
|
+
parser.add_argument("--desaggregate", dest="desaggregate", default=False, action='store_true',
|
|
329
|
+
help="Desaggregate table columns")
|
|
330
|
+
parser.add_argument("--desagg_col", dest="desagg_col",
|
|
331
|
+
help="Column index (1 based) to use as reference", type=list_based_0)
|
|
332
|
+
parser.add_argument("--desagg_sep", dest="desagg_sep", default=",",
|
|
333
|
+
help="Character separator when to split string column")
|
|
334
|
+
parser.add_argument("--excel_cols", dest="excColumns2extract", default=[], type=list_based_0,
|
|
335
|
+
help="Comma-separated column position(s) to extract (1 based). If not used, all columns will be extracted")
|
|
336
|
+
parser.add_argument("--excel_rows", dest="excRows2extract", default=[], type=list_based_0,
|
|
337
|
+
help="Comma-separated row position(s) to extract (1 based). If not used, all rows will be extracted")
|
|
338
|
+
parser.add_argument("--excel_sheet_number", dest="excSheet_number", default=0, type=based_0,
|
|
339
|
+
help="Sheet number to work with. Default 1")
|
|
340
|
+
parser.add_argument("--file_type", dest="file_type", default='text',
|
|
341
|
+
help="Default text. Other options;excel")
|
|
342
|
+
parser.add_argument("--from", dest="frm", default=0, type=based_0,
|
|
343
|
+
help="Column in index file to take reference value. Default 1. Numeration is 1 based")
|
|
344
|
+
parser.add_argument("--to", dest="to", default=1, type=based_0,
|
|
345
|
+
help="Column in index file to take the value that will be used in substitution. Default 2. Numeration is 1 based")
|
|
346
|
+
parser.add_argument("--latex", dest="to_latex", default=False, action='store_true',
|
|
347
|
+
help="Write table in latex code")
|
|
348
|
+
parser.add_argument("--sample_attributes", dest="sample_attributes", default=[], type=list_str,
|
|
349
|
+
help="Define sample atributtes (comma separated list) to colapse a long table in a wide metric table")
|
|
350
|
+
parser.add_argument("--corrupted", dest="corrupted",
|
|
351
|
+
help="File where corrupted metrics are stored")
|
|
352
|
+
parser.add_argument("--offset", dest="offset", default=[], type=list_str,
|
|
353
|
+
help="To subset N rows from table. Indicate as 'start_row,number_row' where start_row es the line to begin the extraction (1 based) and number_row is the amount of lines to extract")
|
|
354
|
+
parser.add_argument("--split_out", dest="split_out", default=False, action='store_true',
|
|
355
|
+
help="Split output table in several files")
|
|
356
|
+
parser.add_argument("--sp_chunk_size", dest="sp_chunk_size", default= 0, type=int,
|
|
357
|
+
help="To split the ouput table in chunks on K lines in different files.")
|
|
358
|
+
parser.add_argument("--sp_file_number", dest="sp_file_number", default= 0, type=int,
|
|
359
|
+
help="To split the output table in N files with the same number of lines.")
|
|
360
|
+
parser.add_argument("--extract_cols", dest="extract_cols", default=[], type=list_str,
|
|
361
|
+
help="Columns to extract from table, comma separated (based 1)")
|
|
362
|
+
parser.add_argument("--ext_col_match", dest="ext_col_match", type=list_based_0,
|
|
363
|
+
help="Select columns where search keywords. Format: x,y,z..")
|
|
364
|
+
parser.add_argument("--ext_keywords", dest="ext_keywords",
|
|
365
|
+
help="Keywords for select rows. Format: key1_col1&key2_col1%%key1_col2&key2_col2")
|
|
366
|
+
parser.add_argument("--ext_keyword_file", dest="ext_keyword_file",
|
|
367
|
+
help="File with one keyword per line. They will be used to search in all the specified columns in --ext_col_match")
|
|
368
|
+
parser.add_argument("--ext_search_mode", dest="ext_search_mode", default='c', choices=['c', 's'],
|
|
369
|
+
help="c for match in every columns set, s some match in some column. Default c")
|
|
370
|
+
parser.add_argument("--ext_match_mode", dest="ext_match_mode", default='i', choices=['i', 'c'],
|
|
371
|
+
help="i string must include the keyword, c for fullmatch. Default i")
|
|
372
|
+
parser.add_argument("--ext_reverse", dest="ext_reverse", default=False, action='store_true',
|
|
373
|
+
help="Select not matching")
|
|
374
|
+
parser.add_argument("--ext_stats", dest="ext_stats", default=False, action='store_true',
|
|
375
|
+
help="Print row extraction statistics")
|
|
376
|
+
parser.add_argument("--uniq", dest="uniq", default=False, action='store_true',
|
|
377
|
+
help="Make rows unique")
|
|
378
|
+
opts = parser.parse_args(args)
|
|
379
|
+
main_cmdtabs(opts)
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
def cmdtabs_merge(args=None):
|
|
383
|
+
if args == None: args = sys.argv[1:]
|
|
384
|
+
parser = argparse.ArgumentParser(description=f'Usage: {os.path.basename(__file__)} [options]')
|
|
385
|
+
add_common_options(parser)
|
|
386
|
+
parser.add_argument("-H", "--header", dest="header", default=False, action='store_true',
|
|
387
|
+
help="Indicate if files have header")
|
|
388
|
+
parser.add_argument("-o", "--output_file", dest="output_file", default=None,
|
|
389
|
+
help="Path to output file")
|
|
390
|
+
parser.add_argument("-s", "--separator", dest="separator", default="\t", type=unescaped_str,
|
|
391
|
+
help="Input table column character separator")
|
|
392
|
+
parser.add_argument("-a", "--a_file", dest="a_file",
|
|
393
|
+
help="Path to input file")
|
|
394
|
+
parser.add_argument("-b", "--b_file", dest="b_file",
|
|
395
|
+
help="Path to input file")
|
|
396
|
+
parser.add_argument("-A", "--a_cols", dest="a_cols", default=[0], type=list_based_0,
|
|
397
|
+
help="Index of columns in base 1 to compare")
|
|
398
|
+
parser.add_argument("-B", "--b_cols", dest="b_cols", default=[0], type=list_based_0,
|
|
399
|
+
help="Index of columns in base 1 to compare")
|
|
400
|
+
parser.add_argument("-c", "--count", dest="count", default=False, action='store_true',
|
|
401
|
+
help="Only compute number of matches")
|
|
402
|
+
parser.add_argument("--full", dest="full", default=False, action='store_true',
|
|
403
|
+
help="Give full record")
|
|
404
|
+
parser.add_argument("-k", "--keep", dest="keep", default='c', choices=['a', 'b', 'c', 'ab'],
|
|
405
|
+
help="Keep records. c for common, 'a' for specific of file a, 'b' for specific of file b and 'ab' for specific of file a AND b")
|
|
406
|
+
|
|
407
|
+
parser.add_argument("--tables", dest="tables", default=None, type=list_str,
|
|
408
|
+
help="Path to tables, comma separated. Paths could include wildcards")
|
|
409
|
+
parser.add_argument("--fill_character", dest="fill_character", default="-",
|
|
410
|
+
help="Character to fill when a field is empty")
|
|
411
|
+
parser.add_argument("--columns2add", dest="columns2add", default=[], type=nested_int_list,
|
|
412
|
+
help="For each file to add to the first file, column indexes 1 based comma separated. To separate each column set, use semicolon ;")
|
|
413
|
+
parser.add_argument("--union", dest="union", default=False, action='store_true',
|
|
414
|
+
help="If a row in a file has not match in the merging table is added to it")
|
|
415
|
+
opts = parser.parse_args(args)
|
|
416
|
+
main_cmdtabs_merge(opts)
|
|
417
|
+
|
|
418
|
+
|
|
@@ -1,25 +1,21 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
import gzip
|
|
3
|
-
import os
|
|
4
|
-
import warnings
|
|
5
|
-
import copy
|
|
1
|
+
import sys, gzip, os, warnings, copy
|
|
6
2
|
import os.path
|
|
7
|
-
import numpy as np
|
|
8
3
|
from collections import defaultdict
|
|
9
|
-
import openpyxl
|
|
10
|
-
import py_exp_calc.exp_calc as pxc
|
|
11
4
|
|
|
12
5
|
class CmdTabs:
|
|
13
6
|
transposed = False
|
|
14
7
|
compressed_input = False
|
|
15
8
|
compressed_output = False
|
|
16
9
|
|
|
17
|
-
def load_input_data(input_path, sep="\t", limit=-1, first_only=False, add_empty_fields=True):
|
|
18
|
-
|
|
10
|
+
def load_input_data(input_path, sep="\t", limit=-1, first_only=False, add_empty_fields=True, fill_character = "", autodetect_compression=False):
|
|
11
|
+
is_compressed = CmdTabs.compressed_input
|
|
12
|
+
if autodetect_compression: is_compressed = input_path.endswith('.gz')
|
|
13
|
+
|
|
14
|
+
open_file = gzip.open if is_compressed else open
|
|
19
15
|
if limit > 0: # THis is due to ruby compute de cuts in other way and this fix enables ruby mode. Think if adapt to python way
|
|
20
16
|
limit -= 1
|
|
21
17
|
if input_path == '-':
|
|
22
|
-
if
|
|
18
|
+
if is_compressed:
|
|
23
19
|
input_data = gzip.decompress(sys.stdin.buffer.read()).decode().strip().split('\n')
|
|
24
20
|
else:
|
|
25
21
|
input_data = sys.stdin
|
|
@@ -32,9 +28,10 @@ class CmdTabs:
|
|
|
32
28
|
#print('---', file=sys.stderr)
|
|
33
29
|
#print(repr(), file=sys.stderr)
|
|
34
30
|
fields = line.rstrip().split(sep, limit)
|
|
31
|
+
fields = [ fill_character if field == "" else field for field in fields]
|
|
35
32
|
if add_empty_fields:
|
|
36
33
|
limit_fields = 0 if limit <= 0 else limit
|
|
37
|
-
fields = fields + ( [
|
|
34
|
+
fields = fields + ( [fill_character] * (fields_number - len(fields) - limit_fields) )
|
|
38
35
|
input_data_arr.append(fields)
|
|
39
36
|
if first_only:
|
|
40
37
|
break
|
|
@@ -54,40 +51,40 @@ class CmdTabs:
|
|
|
54
51
|
loaded_files[key_id] = CmdTabs.load_input_data(file, sep, limit, add_empty_fields=add_empty_fields)
|
|
55
52
|
return loaded_files
|
|
56
53
|
|
|
57
|
-
def load_files(files_path): #NO TEST # Cleaning an filling behaviour could be sent to load_input_data as options and use on load_several_files
|
|
54
|
+
def load_files(files_path, fill_character = '-'): #NO TEST # Cleaning an filling behaviour could be sent to load_input_data as options and use on load_several_files
|
|
58
55
|
files = {}
|
|
59
56
|
for file_name in files_path:
|
|
60
57
|
input_table = CmdTabs.load_input_data(file_name)
|
|
61
58
|
file = []
|
|
62
59
|
for fields in input_table:
|
|
63
60
|
if fields.count('') == len(fields): continue #skip blank records
|
|
64
|
-
file.append([
|
|
61
|
+
file.append([ fill_character if field == "" else field for field in fields])
|
|
65
62
|
files[file_name] = file
|
|
66
63
|
return files
|
|
67
64
|
|
|
68
65
|
def build_pattern(col_filter, keywords):
|
|
69
66
|
pattern = defaultdict(lambda: False )
|
|
70
67
|
if col_filter != None and keywords != None:
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
68
|
+
if isinstance(keywords, str): # search keywords from given string as species the % and & characters. % is delimiter of keywrod per column and & us delimiter of keywrods in th same column
|
|
69
|
+
keys_per_col = keywords.split('%')
|
|
70
|
+
if len(keys_per_col) != len(col_filter): os.abort('Number of keywords not equal to number of filtering columns')
|
|
71
|
+
for i, col in enumerate(col_filter): pattern[col] = keys_per_col[i].split('&')
|
|
72
|
+
elif isinstance(keywords, list): # search keywords from given list (file) in any column
|
|
73
|
+
for i, col in enumerate(col_filter): pattern[col] = keywords
|
|
77
74
|
return pattern
|
|
78
75
|
|
|
79
|
-
def index_array(
|
|
80
|
-
|
|
76
|
+
def index_array(table, col_from=0, col_to=1, header=False):
|
|
77
|
+
index = defaultdict(lambda: False)
|
|
81
78
|
if type(col_to) != list:
|
|
82
79
|
f = lambda x: x[col_to]
|
|
83
80
|
else:
|
|
84
81
|
f = lambda x: [x[c] for c in col_to]
|
|
85
82
|
if header:
|
|
86
|
-
head =
|
|
87
|
-
|
|
88
|
-
for
|
|
89
|
-
|
|
90
|
-
return
|
|
83
|
+
head = table.pop(0)
|
|
84
|
+
index['header'] = f(head)
|
|
85
|
+
for row in table:
|
|
86
|
+
index[row[col_from]] = f(row)
|
|
87
|
+
return index
|
|
91
88
|
|
|
92
89
|
def index_metrics(input_data, attributes):
|
|
93
90
|
n_attrib = len(attributes)
|
|
@@ -115,16 +112,43 @@ class CmdTabs:
|
|
|
115
112
|
query[metric_name] = metric
|
|
116
113
|
return metric_names, indexed_metrics
|
|
117
114
|
|
|
118
|
-
def parse_column_indices(
|
|
115
|
+
def parse_column_indices(col_str_idxs, has_header= False, table=None):
|
|
116
|
+
if has_header:
|
|
117
|
+
col_str_idxs = CmdTabs.get_name_to_index_equivalences(col_str_idxs, table[0], idx_offset=1)
|
|
118
|
+
|
|
119
119
|
cols = []
|
|
120
|
-
for col in
|
|
120
|
+
for col in col_str_idxs:
|
|
121
121
|
if "-" in col: # Range of columns (both ends included)
|
|
122
122
|
start, end = col.split("-")
|
|
123
|
-
range_cols = [
|
|
123
|
+
range_cols = [i - 1 for i in range(int(start), int(end) + 1)]
|
|
124
124
|
cols.extend(range_cols)
|
|
125
125
|
else: # Single column
|
|
126
126
|
cols.append(int(col) - 1)
|
|
127
127
|
return cols
|
|
128
|
+
|
|
129
|
+
def get_name_to_index_equivalences(string_list_to_convert, referece_string_list, idx_offset=1):
|
|
130
|
+
cols_header_dict = dict([(col_name, str(idx+idx_offset)) for idx, col_name in enumerate(referece_string_list)])
|
|
131
|
+
cols_to_get_processed = []
|
|
132
|
+
try:
|
|
133
|
+
for col in string_list_to_convert:
|
|
134
|
+
if col.isdigit(): #Single numeric column case: If the column specifier is a number, we leave as it is
|
|
135
|
+
cols_to_get_processed.append(col)
|
|
136
|
+
elif "-" in col and not "%-%" in col: #Range of numeric column case or named column with hyphen
|
|
137
|
+
start_col, end_col = col.split("-")
|
|
138
|
+
if start_col.isdigit() and end_col.isdigit(): #We check if the column specifier is a range of numeric columns, if so we leave as it is
|
|
139
|
+
cols_to_get_processed.append(col)
|
|
140
|
+
else: #This is an edge of a named column with a hyphen in the name but not numeric range, we convert to number
|
|
141
|
+
cols_to_get_processed.append(cols_header_dict[col])
|
|
142
|
+
elif "%-%" not in col: # Single named column case: This is the case of a single column name, we convert to number
|
|
143
|
+
cols_to_get_processed.append(cols_header_dict[col])
|
|
144
|
+
else: # Range of named columns case: This is the case of a range of column names, we convert to numbers and keep the range format
|
|
145
|
+
start_col, end_col = col.split("%-%")
|
|
146
|
+
start_col = cols_header_dict[start_col]
|
|
147
|
+
end_col = cols_header_dict[end_col]
|
|
148
|
+
cols_to_get_processed.append(f"{start_col}-{end_col}")
|
|
149
|
+
except KeyError as e:
|
|
150
|
+
raise KeyError(f"Column '{e.args[0]}' not found in header. Available columns: {', '.join(cols_header_dict.keys())}")
|
|
151
|
+
return cols_to_get_processed
|
|
128
152
|
|
|
129
153
|
def load_and_parse_tags(tags, sep):
|
|
130
154
|
parsed_tags = []
|
|
@@ -146,6 +170,7 @@ class CmdTabs:
|
|
|
146
170
|
|
|
147
171
|
|
|
148
172
|
def aggregate_column(input_table, col_index, cols_agg, sep, agg_mode="concatenate"):
|
|
173
|
+
import py_exp_calc.exp_calc as pxc
|
|
149
174
|
aggregated_data = defaultdict(lambda: False )
|
|
150
175
|
if type(cols_agg) == int: cols_agg = [cols_agg]
|
|
151
176
|
if type(col_index) == int: col_index = [col_index]
|
|
@@ -161,6 +186,7 @@ class CmdTabs:
|
|
|
161
186
|
return aggregated_data_arr
|
|
162
187
|
|
|
163
188
|
def _make_one_or_several_aggregation(aggregated_column, aggregation_modes, sep):
|
|
189
|
+
import numpy as np
|
|
164
190
|
make_aggregation = {"concatenate": lambda agg_col: sep.join(agg_col),
|
|
165
191
|
"mean": np.mean, "median": np.median, "max": np.max, "min": np.min, "sum": np.sum, "std": np.std, "var": np.var,
|
|
166
192
|
"count": lambda agg_col: len(agg_col), "IQR": lambda agg_col: np.percentile(agg_col, 75) - np.percentile(agg_col, 25),
|
|
@@ -251,6 +277,34 @@ class CmdTabs:
|
|
|
251
277
|
if not drop_line: linked_table.append(fields)
|
|
252
278
|
return linked_table
|
|
253
279
|
|
|
280
|
+
def merge_tables2mainTab(main_table, table_paths, column_idxs, sep = "\t", fill_character='-', header = False, union= False):
|
|
281
|
+
table_length = len(main_table[0])
|
|
282
|
+
for i, table_path in enumerate(table_paths):
|
|
283
|
+
supp_file = CmdTabs.load_input_data(table_path, sep=sep)
|
|
284
|
+
id_col, data_cols = column_idxs[i]
|
|
285
|
+
supp_file_idx = CmdTabs.index_array(supp_file, id_col, data_cols, header = header)
|
|
286
|
+
for i,row in enumerate(main_table):
|
|
287
|
+
if i == 0 and header: # if we're in first row an is header, search for the header record in the index
|
|
288
|
+
id = 'header'
|
|
289
|
+
else:
|
|
290
|
+
id = row[0]
|
|
291
|
+
supp_data = supp_file_idx.get(id)
|
|
292
|
+
if supp_data:
|
|
293
|
+
if type(supp_data) == list:# list with several row fields
|
|
294
|
+
row.extend(supp_data)
|
|
295
|
+
else:
|
|
296
|
+
row.append(supp_data) # one single field as one single value
|
|
297
|
+
CmdTabs.row_start_fill(row, fill_character, table_length) # When there is no match, fill the gap
|
|
298
|
+
if union: # Add rows present in supp file but not in main_table
|
|
299
|
+
for item in (set(supp_file_idx.keys()) - set([r[0] for r in main_table])):
|
|
300
|
+
new_row = [item]
|
|
301
|
+
CmdTabs.row_start_fill(new_row, fill_character, table_length)
|
|
302
|
+
new_row.extend(supp_file_idx[item])
|
|
303
|
+
main_table.append(new_row)
|
|
304
|
+
table_length += len(supp_file_idx[list(supp_file_idx.keys())[0]])
|
|
305
|
+
|
|
306
|
+
for row in main_table: CmdTabs.row_end_fill(row, fill_character, table_length) # When there is no match, fill the gap
|
|
307
|
+
|
|
254
308
|
def tag_file(input_file, tags, header):
|
|
255
309
|
taged_file = []
|
|
256
310
|
n_row = 0
|
|
@@ -264,23 +318,23 @@ class CmdTabs:
|
|
|
264
318
|
n_row += 1
|
|
265
319
|
return taged_file
|
|
266
320
|
|
|
267
|
-
def
|
|
268
|
-
|
|
321
|
+
def match_pattern(line, all_patterns, search_mode, match_mode, reverse = False ):
|
|
322
|
+
match_pat = False
|
|
269
323
|
for col, patterns in all_patterns.items():
|
|
270
324
|
is_match = False
|
|
271
325
|
for pattern in patterns:
|
|
272
326
|
is_match = CmdTabs.expanded_match(line[col], pattern, match_mode)
|
|
273
327
|
if is_match: break
|
|
274
328
|
if is_match and search_mode == 's':
|
|
275
|
-
|
|
329
|
+
match_pat = False
|
|
276
330
|
break
|
|
277
331
|
elif not is_match and search_mode == 'c':
|
|
278
|
-
|
|
332
|
+
match_pat = True
|
|
279
333
|
break
|
|
280
334
|
elif not is_match:
|
|
281
|
-
|
|
282
|
-
if reverse:
|
|
283
|
-
return
|
|
335
|
+
match_pat = True
|
|
336
|
+
if reverse: match_pat = not match_pat
|
|
337
|
+
return match_pat
|
|
284
338
|
|
|
285
339
|
def expanded_match(string, pattern, match_mode):
|
|
286
340
|
is_match = False
|
|
@@ -288,16 +342,16 @@ class CmdTabs:
|
|
|
288
342
|
if string == pattern and match_mode == 'c': is_match = True
|
|
289
343
|
return is_match
|
|
290
344
|
|
|
291
|
-
def filter_columns(input_table,
|
|
292
|
-
pattern = CmdTabs.build_pattern(
|
|
345
|
+
def filter_columns(input_table, cols_to_show, cols_to_match = None, keywords = None, search_mode = None, match_mode = None, reverse = False):
|
|
346
|
+
pattern = CmdTabs.build_pattern(cols_to_match, keywords)
|
|
293
347
|
filtered_table = []
|
|
294
348
|
for line in input_table:
|
|
295
|
-
if not pattern or not CmdTabs.
|
|
296
|
-
filtered_table.append(CmdTabs.extract_fields(line,
|
|
349
|
+
if not pattern or not CmdTabs.match_pattern(line, pattern, search_mode, match_mode, reverse):
|
|
350
|
+
filtered_table.append(CmdTabs.extract_fields(line, cols_to_show) )
|
|
297
351
|
return filtered_table
|
|
298
352
|
|
|
299
353
|
def extract_fields(arr_sub, indexes):
|
|
300
|
-
if indexes == [
|
|
354
|
+
if indexes == []:
|
|
301
355
|
return arr_sub
|
|
302
356
|
else:
|
|
303
357
|
return [ str(arr_sub[idx]) for idx in indexes] # The str instruction is used to ensure that always we have string data (i.e: when this function is used with excel objecb it could extrac numerical data)
|
|
@@ -310,23 +364,38 @@ class CmdTabs:
|
|
|
310
364
|
for fields in file:
|
|
311
365
|
id = fields.pop(0)
|
|
312
366
|
local_length = len(fields)
|
|
313
|
-
|
|
314
|
-
parent_table[id] = [fill_character] * table_length
|
|
315
|
-
elif len(parent_table[id]) < table_length:
|
|
316
|
-
diference = table_length - len(parent_table[id])
|
|
317
|
-
parent_table[id].extend( [fill_character] * diference)
|
|
367
|
+
CmdTabs.row_start_fill_dict(parent_table, id, fill_character, table_length)
|
|
318
368
|
parent_table[id].extend(fields)
|
|
319
369
|
table_length += local_length
|
|
320
|
-
|
|
321
|
-
parent_table_arr = []
|
|
370
|
+
|
|
371
|
+
parent_table_arr = [] # Fill rows that have not full length (the sum of the row lengths of the all merged tables)
|
|
322
372
|
for id, fields in parent_table.items():
|
|
323
|
-
|
|
324
|
-
if diference > 0: fields.extend([fill_character] * diference)
|
|
373
|
+
CmdTabs.row_end_fill(fields, fill_character, table_length)
|
|
325
374
|
record = [id]
|
|
326
375
|
record.extend(fields)
|
|
327
376
|
parent_table_arr.append(record)
|
|
328
377
|
return parent_table_arr
|
|
329
378
|
|
|
379
|
+
def row_start_fill_dict(indexed_table, row_id, fill_character, table_length):
|
|
380
|
+
if not indexed_table.get(row_id):
|
|
381
|
+
indexed_table[row_id] = [fill_character] * table_length
|
|
382
|
+
elif len(indexed_table[row_id]) < table_length:
|
|
383
|
+
diference = table_length - len(indexed_table[row_id])
|
|
384
|
+
indexed_table[row_id].extend( [fill_character] * diference)
|
|
385
|
+
|
|
386
|
+
def row_start_fill(row, fill_character, table_length):
|
|
387
|
+
n_fields = len(row)
|
|
388
|
+
if n_fields == 0:
|
|
389
|
+
row = [fill_character] * table_length
|
|
390
|
+
elif n_fields < table_length:
|
|
391
|
+
diference = table_length - n_fields
|
|
392
|
+
row.extend( [fill_character] * diference)
|
|
393
|
+
return row
|
|
394
|
+
|
|
395
|
+
def row_end_fill(row, fill_character, table_length):
|
|
396
|
+
diference = table_length - len(row)
|
|
397
|
+
if diference > 0: row.extend([fill_character] * diference)
|
|
398
|
+
|
|
330
399
|
def merge_and_filter_tables(input_files, options):
|
|
331
400
|
header = []
|
|
332
401
|
filtered_table = []
|
|
@@ -337,7 +406,8 @@ class CmdTabs:
|
|
|
337
406
|
header = file.pop(0)
|
|
338
407
|
else:
|
|
339
408
|
file.pop(0)
|
|
340
|
-
|
|
409
|
+
|
|
410
|
+
fields = CmdTabs.filter_columns(file, options['cols_to_show'], options['col_filter'], options['keywords'], options['search_mode'], options['match_mode'], options['reverse'])
|
|
341
411
|
filtered_table.extend(fields)
|
|
342
412
|
if options.get('uniq') != None and options['uniq']: filtered_table = CmdTabs.get_uniq(filtered_table)
|
|
343
413
|
if len(header) > 0:
|
|
@@ -374,12 +444,13 @@ class CmdTabs:
|
|
|
374
444
|
return storage
|
|
375
445
|
|
|
376
446
|
def extract_rows(table, rows2extract):
|
|
377
|
-
if rows2extract == [
|
|
447
|
+
if rows2extract == []:
|
|
378
448
|
return table
|
|
379
449
|
else:
|
|
380
450
|
return [ row for idx, row in enumerate(table) if idx in rows2extract ]
|
|
381
451
|
|
|
382
452
|
def get_table_from_excel(file, sheet_number):
|
|
453
|
+
import openpyxl
|
|
383
454
|
x = openpyxl.load_workbook(file)
|
|
384
455
|
sheets = x.sheetnames # list excel sheets by name
|
|
385
456
|
ws = x[sheets[sheet_number]] #select sheet by index (so, we select by sheet order)
|
|
@@ -406,25 +477,23 @@ class CmdTabs:
|
|
|
406
477
|
common = [[r] for r in common_set]
|
|
407
478
|
return common, a_only, b_only
|
|
408
479
|
|
|
409
|
-
def
|
|
410
|
-
|
|
411
|
-
if
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
if
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
for line in output_data:
|
|
427
|
-
print(sep.join([str(l) for l in line]))
|
|
480
|
+
def get_subset(common, a_only, b_only, full_a_rec, full_b_rec, keep_subset='c', full=False):
|
|
481
|
+
# As the groups are list with nested list with only one element: [['str1'], ['str2']..] the full mode need to access to 0 element to be use as key in full_X_rec
|
|
482
|
+
if keep_subset == 'c':
|
|
483
|
+
result = common
|
|
484
|
+
if full: result = [full_a_rec[r[0]] + full_b_rec[r[0]] for r in common]
|
|
485
|
+
elif keep_subset == 'a':
|
|
486
|
+
result = a_only
|
|
487
|
+
if full: result = [full_a_rec[r[0]] for r in a_only]
|
|
488
|
+
elif keep_subset == 'b':
|
|
489
|
+
result = b_only
|
|
490
|
+
if full: result = [full_b_rec[r[0]] for r in b_only]
|
|
491
|
+
elif keep_subset == 'ab':
|
|
492
|
+
if full:
|
|
493
|
+
a_only = [full_a_rec[r[0]] for r in a_only]
|
|
494
|
+
b_only = [full_b_rec[r[0]] for r in b_only]
|
|
495
|
+
result = a_only + b_only
|
|
496
|
+
return result
|
|
428
497
|
|
|
429
498
|
def transpose(table):
|
|
430
499
|
transposed_table = list(map(list, zip(*table)))
|
|
@@ -454,4 +523,40 @@ class CmdTabs:
|
|
|
454
523
|
final_table += [f"\\end{{tabular}}\n\\label{{table:{name}}}\n\\end{{table}}"]
|
|
455
524
|
else:
|
|
456
525
|
final_table = latex_table
|
|
457
|
-
return final_table
|
|
526
|
+
return final_table
|
|
527
|
+
|
|
528
|
+
def write_output_data(output_data, output_path=None, sep="\t"):
|
|
529
|
+
open_file = gzip.open if CmdTabs.compressed_output else open
|
|
530
|
+
if CmdTabs.transposed:
|
|
531
|
+
output_data = CmdTabs.transpose(output_data)
|
|
532
|
+
|
|
533
|
+
if output_path != None:
|
|
534
|
+
with open_file(output_path, 'wt') as out_file:
|
|
535
|
+
for line in output_data:
|
|
536
|
+
out_file.write(sep.join([str(l) for l in line]) + "\n")
|
|
537
|
+
else:
|
|
538
|
+
if CmdTabs.compressed_output:
|
|
539
|
+
columns_joined = []
|
|
540
|
+
for line in output_data:
|
|
541
|
+
columns_joined.append(sep.join([str(l) for l in line]))
|
|
542
|
+
all_joined = "\n".join(columns_joined) + "\n"
|
|
543
|
+
sys.stdout.buffer.write(gzip.compress(bytes(all_joined, 'utf-8')))
|
|
544
|
+
else:
|
|
545
|
+
for line in output_data:
|
|
546
|
+
print(sep.join([str(l) for l in line]))
|
|
547
|
+
|
|
548
|
+
def split_by_nFiles(input_table, file_number, output_folder, file_name='table', header = []):
|
|
549
|
+
chunk_size = len(input_table) // file_number
|
|
550
|
+
init_line = 1 if len(header) > 0 else 0
|
|
551
|
+
if len(input_table) % file_number > 0: chunk_size += 1
|
|
552
|
+
chunk_counter = 0
|
|
553
|
+
for idx in range(init_line, len(input_table), chunk_size):
|
|
554
|
+
CmdTabs.write_output_data(header+input_table[idx:idx+chunk_size], os.path.join(output_folder, f"{file_name}_chunk{chunk_counter}"))
|
|
555
|
+
chunk_counter += 1
|
|
556
|
+
|
|
557
|
+
def split_by_chunk(input_table, chunk_size, output_folder, file_name='table', header = []):
|
|
558
|
+
init_line = 1 if len(header) > 0 else 0
|
|
559
|
+
chunk_counter = 0
|
|
560
|
+
for idx in range(init_line, len(input_table), chunk_size):
|
|
561
|
+
CmdTabs.write_output_data(header+input_table[idx:idx+chunk_size], os.path.join(output_folder, f"{file_name}_chunk{chunk_counter}"))
|
|
562
|
+
chunk_counter += 1
|