deepchopper-cli
Advanced tools
+581
| # Changelog | ||
| All notable changes to this project will be documented in this file. | ||
| ## [unreleased] | ||
| ### 🚀 Features | ||
| - Add poetry-plugin-export | ||
| ### 🐛 Bug Fixes | ||
| - Fix incorrect usage of references in function arguments | ||
| - Update pre-commit hooks versions | ||
| - Update macOS runner version to 13 | ||
| ### 💼 Other | ||
| - Update thiserror requirement from 1.0 to 2.0 | ||
| - Update noodles requirement from 0.84.0 to 0.85.0 | ||
| - *(deps)* Bump actions/attest-build-provenance from 1 to 2 | ||
| - Update noodles requirement from 0.87.0 to 0.88.0 | ||
| ### 🚜 Refactor | ||
| - Update dependencies versions and function signatures | ||
| ### 📚 Documentation | ||
| - Update troubleshooting section in tutorial | ||
| - Update tutorial.md with memory error solution | ||
| - Update tutorial with additional information | ||
| ## [py-cli-v1.2.6] - 2024-11-05 | ||
| ### 🚀 Features | ||
| - Add function to split dataset with both adapters | ||
| - Allow to parse multi targets | ||
| ### 🐛 Bug Fixes | ||
| - Update datasets and evaluate versions | ||
| - Fix typo | ||
| - Update usage of vectorize_targets | ||
| ### 💼 Other | ||
| - *(deps)* Bump crazy-max/ghaction-github-labeler from 5.0.0 to 5.1.0 | ||
| - Update noodles requirement from 0.83.0 to 0.84.0 | ||
| - Update project versions to 1.2.6 | ||
| ### 🚜 Refactor | ||
| - Add multiprocessing context to improve performance | ||
| - Update data["target"] to use .numpy() for consistency | ||
| ### 📚 Documentation | ||
| - Update documentation for DeepChopper model architecture | ||
| - Update citation link in README.md | ||
| ### 🎨 Styling | ||
| - Update pre-commit configs and CLI help message | ||
| - Update table formatting in README.md | ||
| - Update meta tags and author information | ||
| - Fix typo in tutorial.md output flag typo | ||
| - Update authors in pyproject.toml and LICENSE | ||
| - Update CLI help messages for DeepChopper features | ||
| ### ⚙️ Miscellaneous Tasks | ||
| - Update labels and workflows configurations | ||
| ## [py-cli-v1.2.5] - 2024-10-18 | ||
| ### 🚀 Features | ||
| - Update version to 1.2.5 | ||
| ### 📚 Documentation | ||
| - Update version in __init__.py and bumpversion files | ||
| - Add compatibility matrices for Conda and PyPI installations | ||
| - Add link to PyPI support section | ||
| - Update compatibility matrices format | ||
| - Update installation documentation in README | ||
| ### 🎨 Styling | ||
| - Update typer.Option syntax in CLI file | ||
| ## [py-cli-v1.2.4beta] - 2024-10-15 | ||
| ### 🚀 Features | ||
| - Update version to 1.2.4 | ||
| ## [py-cli-v1.2.4] - 2024-10-14 | ||
| ### 🚀 Features | ||
| - Update dependencies versions for rayon, walkdir, pyo3, bstr, lazy_static, tempfile, parquet, arrow, flate2, and clap | ||
| - Add Samtools for BAM to FASTQ conversion | ||
| - Update documentation and repository URLs | ||
| ### 📚 Documentation | ||
| - Add link to updated documentation in README.md | ||
| - Update troubleshooting section in tutorial | ||
| - Add CLI documentation | ||
| ### 🎨 Styling | ||
| - Fix typos in tutorial.md commands | ||
| - Update Rust flags order and add release profile settings | ||
| - Simplify error message in FqDataModule | ||
| - Update tutorial section title for clarity | ||
| ### 🧪 Testing | ||
| - Add raw data to test file | ||
| ## [py-cli-v1.2.3] - 2024-10-13 | ||
| ### 🚀 Features | ||
| - Bump project version to 1.2.3 in Cargo.toml and pyproject.toml | ||
| ### 🐛 Bug Fixes | ||
| - Update dependencies versions to latest versions | ||
| - Update package versions to 1.2.1 | ||
| ### 🚜 Refactor | ||
| - Update dependencies versions in pyproject.toml | ||
| ### 🎨 Styling | ||
| - Remove unnecessary empty lines | ||
| ## [py-cli-v1.2.2] - 2024-10-13 | ||
| ### 🚀 Features | ||
| - Update project versions to 1.2.2 | ||
| ### 🚜 Refactor | ||
| - Update CLI options in chop function | ||
| - Add type check for fastq_path and data_path | ||
| ### 🎨 Styling | ||
| - Update variable name in predict function | ||
| ## [py-cli-v1.2.1] - 2024-10-12 | ||
| ### 🐛 Bug Fixes | ||
| - Update version to 1.2.1 in multiple files | ||
| ### 🚜 Refactor | ||
| - Update project versions to 1.2.0 | ||
| ### 📚 Documentation | ||
| - Update installation dependencies and tutorial content | ||
| ### 🎨 Styling | ||
| - Remove commented out dependency | ||
| ## [py-cli-v1.2.0] - 2024-10-11 | ||
| ### 🚀 Features | ||
| - Update current_version to "1.0.1" in bumpversion config | ||
| ### 🚜 Refactor | ||
| - Update version numbers to 1.1.0 in configuration files | ||
| ### 📚 Documentation | ||
| - Update Quick Start link in README.md | ||
| - Update tutorial and add logging function | ||
| ### 🎨 Styling | ||
| - Fix indentation and variable naming convention | ||
| - Update Python versions in workflows and pyproject.toml | ||
| ### ⚙️ Miscellaneous Tasks | ||
| - Update deepchopper-cli dependency to version 1.0.1 | ||
| - Update Python version to 3.10 and build args | ||
| - Update Python versions for build jobs | ||
| ## [py-cli-v1.0.1] - 2024-10-11 | ||
| ### 🐛 Bug Fixes | ||
| - Update project versions to 1.0.1 | ||
| ## [py-cli-v1.0.0] - 2024-10-11 | ||
| ### 🐛 Bug Fixes | ||
| - Update version to 1.0.0 in multiple files | ||
| ## [py-cli-v0.1.0] - 2024-10-11 | ||
| ### 🐛 Bug Fixes | ||
| - Update Python version to 3.10 in CI workflow | ||
| ### 📚 Documentation | ||
| - Add bumpversion configuration file | ||
| ### ⚡ Performance | ||
| - Improve Python CLI release build performance | ||
| ### 🎨 Styling | ||
| - Update PythonVersion to use quotes | ||
| ### ⚙️ Miscellaneous Tasks | ||
| - Update PyPI release condition | ||
| - Remove redundant pytest job configurations | ||
| ## [deepchopper-v0.1.0] - 2024-10-11 | ||
| ### 🚀 Features | ||
| - Add logo images for DeepChopper | ||
| - Update derive_builder version and add lexical dependency | ||
| - Add error module and EncodingError type | ||
| - Add functions to convert between k-mer target region and original target region | ||
| - *(output)* Add functions for generating and removing intervals | ||
| - Add split and writefq modules | ||
| - Add function to write FASTQ records | ||
| - *(output)* Add functions to write fastq records | ||
| - Add function to encode multiple FASTQ files | ||
| - Add function `summary_record_len` to Python module | ||
| - Add pynvim dependency | ||
| - Implement Display trait for FqEncoder and FqEncoderOption | ||
| - Add Python script for running deepchopper | ||
| - Add FqEncoder class and its dependencies | ||
| - *(src/fq_encode.rs)* Add logging statements | ||
| - Add 1000_records.fq.gz test data | ||
| - *(output)* Add function to extract records by IDs | ||
| - Add logging task and test_log() function | ||
| - Add .gitkeep file to notebooks folder | ||
| - Add support for parallel file processing | ||
| - Add functions to encode FASTQ files | ||
| - *(utils)* Add function to load kmer to ID mapping | ||
| - *(utils)* Add functions to load and save SafeTensors | ||
| - Add serde_json dependency and encode to JSON format | ||
| - Add ParquetData struct and refactor encode_fq_to_parquet function | ||
| - Add function to encode FQ path to Parquet | ||
| - Add encode_parqut task for Parquet encoding | ||
| - Add function to encode FASTQ paths to JSON | ||
| - Add custom build function in TensorEncoderBuilder | ||
| - Add datasets and ipykernel dependencies | ||
| - Add seqeval dependency | ||
| - Add test_input.parquet file | ||
| - Add tokenizers module | ||
| - Add tokenizers to pyproject.toml and update load_dataset in tasks.py | ||
| - Add data split functionality to test function | ||
| - Add KmerOverlapPreTokenizer for tokenization | ||
| - Add KmerPreTokenizer and KmerDecoder classes | ||
| - Add torchinfo to pyproject.toml | ||
| - Add evaluate package "^0.4.1" | ||
| - Add training functionality for deepchopper model | ||
| - Add hyena model and quality usage to training file | ||
| - *(utils)* Add function to collect and split dataset | ||
| - Add hyena_model_train to .gitignore and update dataset loading function | ||
| - Add dataset splitting function and test cases | ||
| - Update PyTorch versions and add NVIDIA CUDA packages | ||
| - Update training script with new dataset and options | ||
| - Update dependencies and training configurations | ||
| - Add functions for label region extraction and smoothing | ||
| - Update training script for 600000 samples and 15 epochs | ||
| - Add import statement for typing Annotated | ||
| - Add show_metrics option to load_trainer function | ||
| - Add optional output_path parameter to main function | ||
| - Add chunking functionality for Parquet encoding | ||
| - Add logging and encoding features | ||
| - Add optimizations for release build configurations | ||
| - Create folder for chunk parquet files | ||
| - Add functions to load model and dataset from checkpoint | ||
| - Add web UI functionality and launch interface | ||
| - Add prediction function for DNA sequence processing | ||
| - Add new checkpoint files and configurations | ||
| - Improve performance by using parallel iterator for mapping | ||
| - Add function to collect and split dataset with prefix | ||
| - Add BenchmarkCNN model and LitBenchmarkCNN class | ||
| - Add configuration files for FqDataModule and CNN model | ||
| - Add max_train_samples, max_val_samples, max_test_samples | ||
| - Update model_checkpoint filename pattern | ||
| - Update model hyperparameters and configurations | ||
| - *(configs)* Update early stopping patience and batch sizes | ||
| - Update scheduler type and add transformer model | ||
| - Add TokenClassificationModel with transformer encoder | ||
| - Add configurations for Hyena and Transformer models | ||
| - Update transformer model configuration | ||
| - Add CustomWriter callback for writing predictions | ||
| - Update data path and number of workers in eval script | ||
| - Add smooth module and majority voting function | ||
| - Add candle-core dependency and new smooth utils | ||
| - Add test_predicts function in smooth.rs | ||
| - *(python, smooth/predict, smooth/stat)* Add function and struct properties | ||
| - Add parallel reading of BAM records | ||
| - Update code for collecting statistics and overlap results | ||
| - Save more data to StatResult | ||
| - Add max_process_intervals to OverlapOptions | ||
| - Add ContinuousIntervalLoss criterion to models | ||
| - Add option for specifying number of threads | ||
| - Add diff, blat and chop | ||
| - Update dependencies and default values | ||
| - Add KanModel class for deep learning model | ||
| - Update dependencies and refactor function signatures in DeepChopper | ||
| - Add new functionality for reverse complement function | ||
| - Add new features for selecting reads by type and name | ||
| - Update sample name and data folder paths | ||
| - Add new predict script and adjust data settings | ||
| - Remove parse name @region|id | ||
| - Add new script fq2fa.rs | ||
| - Add new prediction task for HEK293T_RNA004 dataset | ||
| - Add option to filter records by length | ||
| - Update noodles dependency to version 0.78.0 | ||
| - Add Precision-Recall Curve metric to TokenClassificationLit model | ||
| - Introduce new function to read records from file | ||
| - Update sample_name and data_folder variables | ||
| - Add script for computing distance matrix | ||
| - Add option for selecting chop type | ||
| - Add script chop option ct, mcr, and new binary replace | ||
| - Update candle-core version to 0.6.0, add HashSet usage | ||
| - Update project name and description | ||
| - Add script for generating fusion circle plot | ||
| - Update pre-commit repos to latest versions | ||
| - Add chop command to DeepChopper CLI | ||
| - Add DeepChopper model class for pretrained models | ||
| - Add UI functionality and improve predict CLI | ||
| - Add file input option for dataset loading | ||
| - Update DeepChopper commands and documentation | ||
| - Add main function to run CLI app | ||
| - Update tutorial with GPU support for predicting reads | ||
| - Update dependencies in pyproject.toml | ||
| - Add new dependencies for project | ||
| - Add scikit-learn dependency | ||
| - Add train and eval modules, update dependencies | ||
| - Add maturin configuration to pyproject.toml | ||
| - Add new CLI module for DeepChopper | ||
| ### 🐛 Bug Fixes | ||
| - *(src/output/writefq.rs)* Add missing argument in function call | ||
| - Update maturin command in Makefile | ||
| - Handle FileNotFoundError with logging instead of raising | ||
| - Update pytorch-cu121 URL to cu118 | ||
| - Update ruff-pre-commit to v0.2.2 | ||
| - Fix invalid index assignment in vertorize_target function | ||
| - Update forward method signature in CNN model | ||
| - Update noodles crate version to 0.68.0 | ||
| - Update batch size to 32 | ||
| - Update batch size to 18 | ||
| - Update data_path and num_workers in eval script | ||
| - Update condition to check for intervals_number \<= 4 | ||
| - Remove read with unmap, supp, secondary | ||
| - Correct indexing in id_list2seq functions | ||
| - Use pyo3 new features | ||
| - Correct typos in function names and update dependencies in Cargo.toml | ||
| - Accepet gzip fq, bgzip fq and fq | ||
| - Update sample name in predict script to match model number | ||
| - Update precision and recall calculation methods | ||
| - Update predict CLI output path handling | ||
| - Update pre-commit hook versions | ||
| - Update CLI command to use new tool name | ||
| - Fix default value for number of GPUs | ||
| - Update default value for gpus to "auto" | ||
| - Update predict_data_path with as_posix() method | ||
| - Update gradio version to ^5.0.1 | ||
| - Update method signature in DeepChopper class | ||
| - Update versions for noodles and candle-core | ||
| - Fix getting qname from record in read_bam_records | ||
| - Fix import path in encode_fq.py | ||
| - Update requires-python to support Python 3.10+ | ||
| ### 💼 Other | ||
| - Remove unnecessary crate-type "rlib" | ||
| - Add GitHub actions and labels configuration files | ||
| ### 🚜 Refactor | ||
| - Update package name in __init__.py | ||
| - Remove unused code and improve code readability | ||
| - Update target region calculation and error message | ||
| - Move types into separate file | ||
| - Rename `KmerTable` to `Kmer2IdTable` and add `Id2KmerTable` | ||
| - Rename function `generate_records_by_remove_interval` to `split_records_by_remove_interval` | ||
| - *(fq_encode)* Remove unused variable and refactor code | ||
| - *(fq_encode)* Change type of 'qual' parameter to Matrix | ||
| - *(test)* Refactor test_rust.py | ||
| - Update function signatures and error handling | ||
| - Rename references to "panda" to "deepchopper" | ||
| - *(python)* Refactor kmerids_to_seq function | ||
| - *(option)* Refactor FqEncoderOption structfeat(run.py): add save to npz | ||
| - Clean and rename files, update tasks file | ||
| - Clean up and improve logging and code structure | ||
| - Improve error handling and data processing | ||
| - Remove debug and warn log statements | ||
| - Remove unnecessary code and update dependencies | ||
| - Modify FqEncoder to use noodles for FASTQ reading | ||
| - Update function names and data encoding in encode_fq.py | ||
| - Update variable names in FqEncoderOption structure | ||
| - Simplify crate-type definition and function names | ||
| - Remove unnecessary code and improve performance | ||
| - Consolidate crate-type and encode_qual functions | ||
| - Update encoder_seq method to support overlap option | ||
| - Remove commented-out code and optimize kmer processing | ||
| - Remove unused code and optimize vectorization | ||
| - Update logging in fq_encode/triat.rs and Cargo.toml | ||
| - Add imports and remove redundant code | ||
| - Remove unused imports and variables | ||
| - Remove commented-out code and unused imports | ||
| - Simplify dataset sampling and processing | ||
| - Remove unused kmer_size parameter in encode_fq.py | ||
| - Update import statement in predict.py | ||
| - Update dependencies and refactor code for efficiency | ||
| - Update function name and arguments in predict.py | ||
| - Improve unmaped intervals generation | ||
| - Update output directory variable to use Path object | ||
| - Update function parameters for smooth_label_region | ||
| - Remove unnecessary import in test module | ||
| - Update CNN model configurations and structure | ||
| - Update imports and metrics in CNN module | ||
| - Update file paths to use pathlib in FqDataModule | ||
| - Update configurations and model parameters | ||
| - Update accuracy calculation and loss computation in CNN module | ||
| - Update evaluation config and model in deepchopper | ||
| - Update model and module names, refactor class names | ||
| - Update CNN model architecture and forward method | ||
| - Update batch size and model filter configurations | ||
| - Rename train files to hg_train files | ||
| - Simplify error message handling in model files | ||
| - Update model import paths to llm | ||
| - Add prediction functionality and configurations | ||
| - *(utils)* Update function arguments to accept i64 types | ||
| - *(utils)* Replace summary_predict_i64 with summary_predict_generic | ||
| - Add merge method to StatResult impl | ||
| - Increase line length to 120 and update logging levels | ||
| - Remove unnecessary print statements and add input parameters | ||
| - Add support for SA tag in BAM records | ||
| - Update HashMap imports to use ahash crate | ||
| - Update fastq writer instantiation in utils.rs | ||
| - Update function name and improve code readability | ||
| - Update model and checkpoint paths for vcap_004 | ||
| - Update record filtering logic to use parallel iterators | ||
| - Add error context for reading records and names | ||
| - Improve reading and filtering of records | ||
| - Improve name selection logic | ||
| - Improve code readability and efficiency | ||
| - Update function return type and variable names | ||
| - Remove unused code and comments | ||
| - Update deepchopper CLI predict function | ||
| - Update Cargo.toml and remove unnecessary imports | ||
| - Update function parameters in deepchopper/ui/main.py | ||
| - Improve dataset loading logic and input processing | ||
| - Improve data loading and processing in predict function | ||
| - Rename ui function to web | ||
| - Improve code formatting in README.md | ||
| - Improve handling of GPU availability and selection | ||
| - Remove unnecessary modules from package import | ||
| - Update converting byte slices to vectors | ||
| - Update import statement for cli in __init__.py | ||
| ### 📚 Documentation | ||
| - Add documentation for token classification model | ||
| - Add function documentation for predict.py | ||
| - Add function documentation for highlighting targets | ||
| - Add module docstrings for TokenClassificationLit and BenchmarkCNN | ||
| - Add Sherlock logo images | ||
| - Update DeepChopper README and tutorial | ||
| - Update link to tutorial file in README | ||
| - Update documentation content in index.html | ||
| - Update tutorial.md with corrected URLs and commands | ||
| - Update README with GPU flag usage | ||
| - Update storage space recommendation in tutorial | ||
| - Update license to Apache License Version 2.0 | ||
| - Add GitHub workflow for releasing Python CLI | ||
| - Add LICENSE and README.md files | ||
| - Update license and add readme file path | ||
| ### 🎨 Styling | ||
| - Update README.md logo URL | ||
| - Remove unnecessary code and print statements | ||
| - Update dependencies and clean up code bases | ||
| - Remove unnecessary blank lines and print statement | ||
| - Update Cargo.toml and src/lib.rs formatting | ||
| - Add debug log statement in FqEncoder | ||
| - Update Cargo.toml crate-type formatting | ||
| - Update crate-type in Cargo.toml and line-length in pyproject.toml | ||
| - Improve code formatting for better readability | ||
| - Update pre-commit hook version to v0.3.0 | ||
| - Update crate-type in Cargo.toml and clean up code | ||
| - Update training script configurations | ||
| - Improve command help messages and option annotations | ||
| - Update help message capitalization | ||
| - Improve code formatting and remove redundant print | ||
| - Update formatting for crate type and function arguments | ||
| - Update code formatting and remove unused imports | ||
| - Update monitor metrics to "val/f1" and remove unused imports | ||
| - Add example input array to TokenClassificationLit | ||
| - Remove unnecessary comment and empty lines | ||
| - Update crate-type formatting in Cargo.toml | ||
| - Update README.md formatting and text | ||
| - Update paths and sample names in scripts | ||
| - Update rustflags for target x86_64-apple-darwin | ||
| - Improve file creation comments and paths in code | ||
| - Remove unnecessary target.x86_64-apple-darwin config | ||
| - Remove unnecessary references in ParquetEncoder | ||
| - Fix formatting in basic_module.py | ||
| - Remove unused import from fq2fa.rs | ||
| - Add clippy lint allowances in several functions | ||
| - Improve ChopType display and comparison | ||
| - Update argument type and add annotation for clarity | ||
| - Reorder imports for better readability | ||
| - Remove unused imports and comments | ||
| - Improve code formatting and remove unnecessary lines | ||
| - Update versions for gradio and fastapi | ||
| - Improve command-line interface instructions | ||
| - Update variable type and add custom CSS styling | ||
| - Remove unnecessary file exclusion in .gitignore | ||
| - Update project description and license in pyproject.toml | ||
| - Update typer and gradio versions | ||
| - Comment out unused import statements | ||
| ### 🧪 Testing | ||
| - *(fa)* Add tests for reading fasta and fastx files | ||
| - Add test for reading fastq file | ||
| - Add test for encoding large size FASTQ file | ||
| - Add test for encoding FASTQ files from paths | ||
| - Add test for encoding FASTQ to JSON conversion | ||
| - Rename summar_bam_record_len to summary_bam_record_len | ||
| - Tokenize and align labels and quals for training dataset | ||
| ### ⚙️ Miscellaneous Tasks | ||
| - Add test_log function for logging | ||
| - Update .gitignore to exclude massif.out.\* | ||
| - Add task.slurm to .gitignore | ||
| - Update exclude paths in pyproject.toml | ||
| - Update .gitignore for wandb and checkpoints | ||
| - Update file paths for hg train scripts | ||
| - Remove unnecessary code block in notebook | ||
| - Update depen | ||
| - Add setup_panic to eval.rs and select.rs | ||
| - Update file paths in chop.sh and internal.rs files | ||
| - Remove unnecessary checkpoint files | ||
| - Remove unused test files | ||
| - Remove redundant Windows x86 target | ||
| - Remove unnecessary target configurations | ||
| - Remove redundant aarch64 platform configurations | ||
| - Remove unused musllinux job and related steps | ||
| - Update dependencies and remove unused binaries | ||
| - Update concurrency configuration and CLI import | ||
| - Update PyO3/maturin-action arguments for releasing Python CLI | ||
| <!-- generated by git-cliff --> |
+84
| # git-cliff ~ default configuration file | ||
| # https://git-cliff.org/docs/configuration | ||
| # | ||
| # Lines starting with "#" are comments. | ||
| # Configuration options are organized into tables and keys. | ||
| # See documentation for more information on available options. | ||
| [changelog] | ||
| # template for the changelog header | ||
| header = """ | ||
| # Changelog\n | ||
| All notable changes to this project will be documented in this file.\n | ||
| """ | ||
| # template for the changelog body | ||
| # https://keats.github.io/tera/docs/#introduction | ||
| body = """ | ||
| {% if version %}\ | ||
| ## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }} | ||
| {% else %}\ | ||
| ## [unreleased] | ||
| {% endif %}\ | ||
| {% for group, commits in commits | group_by(attribute="group") %} | ||
| ### {{ group | striptags | trim | upper_first }} | ||
| {% for commit in commits %} | ||
| - {% if commit.scope %}*({{ commit.scope }})* {% endif %}\ | ||
| {% if commit.breaking %}[**breaking**] {% endif %}\ | ||
| {{ commit.message | upper_first }}\ | ||
| {% endfor %} | ||
| {% endfor %}\n | ||
| """ | ||
| # template for the changelog footer | ||
| footer = """ | ||
| <!-- generated by git-cliff --> | ||
| """ | ||
| # remove the leading and trailing s | ||
| trim = true | ||
| # postprocessors | ||
| postprocessors = [ | ||
| # { pattern = '<REPO>', replace = "https://github.com/orhun/git-cliff" }, # replace repository URL | ||
| ] | ||
| # render body even when there are no releases to process | ||
| # render_always = true | ||
| # output file path | ||
| # output = "test.md" | ||
| [git] | ||
| # parse the commits based on https://www.conventionalcommits.org | ||
| conventional_commits = true | ||
| # filter out the commits that are not conventional | ||
| filter_unconventional = true | ||
| # process each line of a commit as an individual commit | ||
| split_commits = false | ||
| # regex for preprocessing the commit messages | ||
| commit_preprocessors = [ | ||
| # Replace issue numbers | ||
| #{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](<REPO>/issues/${2}))"}, | ||
| # Check spelling of the commit with https://github.com/crate-ci/typos | ||
| # If the spelling is incorrect, it will be automatically fixed. | ||
| #{ pattern = '.*', replace_command = 'typos --write-changes -' }, | ||
| ] | ||
| # regex for parsing and grouping commits | ||
| commit_parsers = [ | ||
| { message = "^feat", group = "<!-- 0 -->🚀 Features" }, | ||
| { message = "^fix", group = "<!-- 1 -->🐛 Bug Fixes" }, | ||
| { message = "^doc", group = "<!-- 3 -->📚 Documentation" }, | ||
| { message = "^perf", group = "<!-- 4 -->⚡ Performance" }, | ||
| { message = "^refactor", group = "<!-- 2 -->🚜 Refactor" }, | ||
| { message = "^style", group = "<!-- 5 -->🎨 Styling" }, | ||
| { message = "^test", group = "<!-- 6 -->🧪 Testing" }, | ||
| { message = "^chore\\(release\\): prepare for", skip = true }, | ||
| { message = "^chore\\(deps.*\\)", skip = true }, | ||
| { message = "^chore\\(pr\\)", skip = true }, | ||
| { message = "^chore\\(pull\\)", skip = true }, | ||
| { message = "^chore|^ci", group = "<!-- 7 -->⚙️ Miscellaneous Tasks" }, | ||
| { body = ".*security", group = "<!-- 8 -->🛡️ Security" }, | ||
| { message = "^revert", group = "<!-- 9 -->◀️ Revert" }, | ||
| { message = ".*", group = "<!-- 10 -->💼 Other" }, | ||
| ] | ||
| # filter out the commits that are not matched by commit parsers | ||
| filter_commits = false | ||
| # sort the tags topologically | ||
| topo_order = false | ||
| # sort the commits inside sections by oldest/newest order | ||
| sort_commits = "oldest" |
| # DeepChopper Parameter Optimization Guidelines | ||
| This guide provides recommendations for tuning DeepChopper parameters across different research contexts and dataset characteristics. | ||
| ## Core Parameters | ||
| ### Sliding Window Size (`--smooth-window`) | ||
| The sliding window size controls the smoothing applied to adapter probability scores and significantly impacts detection sensitivity and read fragmentation. | ||
| This parameter is applied first in the processing pipeline. | ||
| **Recommendation**: Start with the default value of 21. If your analysis reveals excessive fragmentation, increase to 31. If you suspect missed adapters, decrease to 11. | ||
| ### Minimum Interval Size (`--min-interval-size`) | ||
| This parameter determines the minimum length of sequence that can be classified as an adapter region. | ||
| This parameter is applied after the smoothing process during adapter region identification. | ||
| | Value | Use Case | | ||
| | ----- | ------------------------------------------------------------ | | ||
| | 8-10 | Increased sensitivity to detect very short adapter fragments | | ||
| | 13 | **Default - Balanced detection for typical adapter lengths** | | ||
| | 15-20 | Higher precision, reduces false positives in noisy data | | ||
| **Recommendation**: For RNA004 chemistry or newer protocols with cleaner data, consider increasing to 15 to reduce false positives. | ||
| ### Maximum Process Intervals (`--max-process-intervals`) | ||
| Limits how many adapter regions are processed per read. | ||
| This parameter is applied after the smoothing process. | ||
| | Value | Use Case | | ||
| | ----- | ------------------------------------------------ | | ||
| | 2-3 | Conservative approach for high-quality data | | ||
| | 4 | **Default - Suitable for most applications** | | ||
| | 5-8 | For highly fragmented reads or complex libraries | | ||
| **Recommendation**: Monitor read fragmentation metrics after processing. If reads are being over-fragmented, decrease this value. | ||
| ### Minimum Read Length (`--min-read-length`) | ||
| Specifies the minimum length of sequences to retain after chopping. | ||
| This parameter is applied after the smoothing process during the final filtering stage. | ||
| | Value | Use Case | | ||
| | ----- | ----------------------------------------------- | | ||
| | 10 | Small RNA or short fragment applications | | ||
| | 20 | **Default - General purpose** | | ||
| | 50+ | When only substantial fragments are of interest | | ||
| **Recommendation**: Adjust based on your downstream application requirements. | ||
| ## Chemistry-Specific Recommendations | ||
| ### RNA002 | ||
| - Default parameters are optimized based on extensive testing with RNA002 chemistry | ||
| - No adjustments needed for typical RNA002 datasets | ||
| ### RNA004 | ||
| - Default parameters work well due to DeepChopper's zero-shot capability | ||
| - Consider increasing `--min-interval-size` to 15 to account for cleaner data | ||
| - May benefit from increasing `--smooth-window` to 31 for reduced false positives | ||
| ### Newer Chemistries | ||
| - Start with RNA004 recommendations | ||
| - If performance is suboptimal, first adjust `--smooth-window` and `--min-interval-size` | ||
| - Monitor fragmentation metrics to guide further tuning | ||
| **Processing Order**: DeepChopper applies parameters in this sequence: | ||
| 1. Smoothing (`--smooth-window`) | ||
| 2. Adapter region identification (`--min-interval-size`) | ||
| 3. Processing adapter regions (`--max-process-intervals`) | ||
| 4. Final filtering (`--min-read-length`) | ||
| ## Performance Metrics to Monitor | ||
| When tuning parameters, pay attention to these key metrics: | ||
| - **Percentage of chimeric alignments** before and after processing | ||
| - **Number of segments per read** after processing | ||
| - **Read length distribution** after processing | ||
| - **Proportion of cDNA-supported alignments** before and after processing | ||
| ## Need Help? | ||
| If you encounter difficulty optimizing DeepChopper for your specific dataset, please open an issue on our GitHub repository with a description of your data characteristics and the results you're observing. |
| import sys | ||
| import deepchopper | ||
| def compare(p1,p2): | ||
| assert len(p1) == len(p2) | ||
| for key, value in p1.items(): | ||
| if p2[key].prediction != value.prediction: | ||
| print(f"{key} has diff prediction") | ||
| print("all same") | ||
| def main(): | ||
| p1 = sys.argv[1] | ||
| p2 = sys.argv[2] | ||
| p1p = deepchopper.load_predicts_from_batch_pts(p1) | ||
| p2p = deepchopper.load_predicts_from_batch_pts(p2) | ||
| compare(p1p, p2p) | ||
| if __name__ == "__main__": | ||
| main() |
| #!/bin/bash | ||
| set -euo pipefail # Combines the set commands into one line | ||
| # Paths to checkpoint files | ||
| hyena_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-04-08_23-19-20/checkpoints/epoch_005_f1_0.9933.ckpt" | ||
| # train with both rna 002 data | ||
| # hyena_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-11-14_14-14-01/checkpoints/epoch_010_f1_0.9930.ckpt" | ||
| # rna 004 only | ||
| # hyena_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-07-02_15-20-53/checkpoints/epoch_008_f1_0.9946.ckpt" | ||
| cnn_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-04-07_12-01-37/checkpoints/epoch_036_f1_0.9914.ckpt" | ||
| caduceus_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-05-25_19-42-45/checkpoints/epoch_002_f1_0.9982.ckpt" | ||
| # Default model selection | ||
| sample_name="F121-9_dorado_with_trim" | ||
| data_folder="rebutt/F121-9_dorado_with_trim.fastq_chunks" | ||
| num_workers=15 | ||
| batch_size=64 | ||
| # get the model from the command line | ||
| if [ "$#" -eq 0 ]; then | ||
| echo "Please select a valid model: cnn, hyena, or caduceus." | ||
| exit 1 | ||
| elif [ "$#" -eq 1 ]; then | ||
| model=$1 | ||
| else | ||
| echo "Error: Too many arguments." | ||
| echo "Please provide only one argument: cnn, hyena, or caduceus." | ||
| exit 1 | ||
| fi | ||
| # Set the checkpoint path based on the selected model | ||
| if [ "$model" = "cnn" ]; then | ||
| ckpt_path="$cnn_ckpt_path" | ||
| elif [ "$model" = "hyena" ]; then | ||
| ckpt_path="$hyena_ckpt_path" | ||
| elif [ "$model" = "caduceus" ]; then | ||
| ckpt_path="$caduceus_ckpt_path" | ||
| else | ||
| echo "Error: Model not supported." | ||
| echo "Please select a valid model: cnn, hyena, or caduceus." | ||
| exit 1 | ||
| fi | ||
| # Iterate over each .parquet file in the data folder and evaluate | ||
| for data_path in "$data_folder"/*.parquet; do | ||
| # Extract filename without extension | ||
| filename=$(basename -- "$data_path") | ||
| filename="${filename%.*}" | ||
| # Define output directory using the filename | ||
| output_dir="/projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/${sample_name}_${model}/${filename}" | ||
| echo "Evaluating file: $data_path" | ||
| echo "Output directory: $output_dir" | ||
| poe eval \ | ||
| ckpt_path="$ckpt_path" \ | ||
| model="$model" \ | ||
| +data.predict_data_path="$data_path" \ | ||
| trainer=gpu \ | ||
| data.num_workers=$num_workers \ | ||
| data.batch_size=$batch_size \ | ||
| paths.output_dir="$output_dir" \ | ||
| paths.log_dir="$output_dir" \ | ||
| tags=["eval"] \ | ||
| extras.print_config=False | ||
| done |
| #!/bin/bash | ||
| set -euo pipefail # Combines the set commands into one line | ||
| # Paths to checkpoint files | ||
| hyena_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-04-08_23-19-20/checkpoints/epoch_005_f1_0.9933.ckpt" | ||
| # train with both rna 002 data | ||
| # hyena_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-11-14_14-14-01/checkpoints/epoch_010_f1_0.9930.ckpt" | ||
| # rna 004 only | ||
| # hyena_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-07-02_15-20-53/checkpoints/epoch_008_f1_0.9946.ckpt" | ||
| cnn_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-04-07_12-01-37/checkpoints/epoch_036_f1_0.9914.ckpt" | ||
| caduceus_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-05-25_19-42-45/checkpoints/epoch_002_f1_0.9982.ckpt" | ||
| # Default model selection | ||
| sample_name="HCT116_dorado_with_trim" | ||
| data_folder="rebutt/HCT116_dorado_with_trim.fastq_chunks" | ||
| num_workers=15 | ||
| batch_size=64 | ||
| # get the model from the command line | ||
| if [ "$#" -eq 0 ]; then | ||
| echo "Please select a valid model: cnn, hyena, or caduceus." | ||
| exit 1 | ||
| elif [ "$#" -eq 1 ]; then | ||
| model=$1 | ||
| else | ||
| echo "Error: Too many arguments." | ||
| echo "Please provide only one argument: cnn, hyena, or caduceus." | ||
| exit 1 | ||
| fi | ||
| # Set the checkpoint path based on the selected model | ||
| if [ "$model" = "cnn" ]; then | ||
| ckpt_path="$cnn_ckpt_path" | ||
| elif [ "$model" = "hyena" ]; then | ||
| ckpt_path="$hyena_ckpt_path" | ||
| elif [ "$model" = "caduceus" ]; then | ||
| ckpt_path="$caduceus_ckpt_path" | ||
| else | ||
| echo "Error: Model not supported." | ||
| echo "Please select a valid model: cnn, hyena, or caduceus." | ||
| exit 1 | ||
| fi | ||
| # Iterate over each .parquet file in the data folder and evaluate | ||
| for data_path in "$data_folder"/*.parquet; do | ||
| # Extract filename without extension | ||
| filename=$(basename -- "$data_path") | ||
| filename="${filename%.*}" | ||
| # Define output directory using the filename | ||
| output_dir="/projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/${sample_name}_${model}/${filename}" | ||
| echo "Evaluating file: $data_path" | ||
| echo "Output directory: $output_dir" | ||
| poe eval \ | ||
| ckpt_path="$ckpt_path" \ | ||
| model="$model" \ | ||
| +data.predict_data_path="$data_path" \ | ||
| trainer=gpu \ | ||
| data.num_workers=$num_workers \ | ||
| data.batch_size=$batch_size \ | ||
| paths.output_dir="$output_dir" \ | ||
| paths.log_dir="$output_dir" \ | ||
| tags=["eval"] \ | ||
| extras.print_config=False | ||
| done |
| #!/bin/bash | ||
| set -euo pipefail # Combines the set commands into one line | ||
| # Paths to checkpoint files | ||
| hyena_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-04-08_23-19-20/checkpoints/epoch_005_f1_0.9933.ckpt" | ||
| # train with both rna 002 data | ||
| # hyena_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-11-14_14-14-01/checkpoints/epoch_010_f1_0.9930.ckpt" | ||
| # rna 004 only | ||
| # hyena_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-07-02_15-20-53/checkpoints/epoch_008_f1_0.9946.ckpt" | ||
| cnn_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-04-07_12-01-37/checkpoints/epoch_036_f1_0.9914.ckpt" | ||
| caduceus_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-05-25_19-42-45/checkpoints/epoch_002_f1_0.9982.ckpt" | ||
| # Default model selection | ||
| sample_name="HepG2_dorado_with_trim.fastq" | ||
| data_folder="rebutt/HepG2_dorado_with_trim.fastq_chunks" | ||
| num_workers=15 | ||
| batch_size=64 | ||
| # get the model from the command line | ||
| if [ "$#" -eq 0 ]; then | ||
| echo "Please select a valid model: cnn, hyena, or caduceus." | ||
| exit 1 | ||
| elif [ "$#" -eq 1 ]; then | ||
| model=$1 | ||
| else | ||
| echo "Error: Too many arguments." | ||
| echo "Please provide only one argument: cnn, hyena, or caduceus." | ||
| exit 1 | ||
| fi | ||
| # Set the checkpoint path based on the selected model | ||
| if [ "$model" = "cnn" ]; then | ||
| ckpt_path="$cnn_ckpt_path" | ||
| elif [ "$model" = "hyena" ]; then | ||
| ckpt_path="$hyena_ckpt_path" | ||
| elif [ "$model" = "caduceus" ]; then | ||
| ckpt_path="$caduceus_ckpt_path" | ||
| else | ||
| echo "Error: Model not supported." | ||
| echo "Please select a valid model: cnn, hyena, or caduceus." | ||
| exit 1 | ||
| fi | ||
| # Iterate over each .parquet file in the data folder and evaluate | ||
| for data_path in "$data_folder"/*.parquet; do | ||
| # Extract filename without extension | ||
| filename=$(basename -- "$data_path") | ||
| filename="${filename%.*}" | ||
| # Define output directory using the filename | ||
| output_dir="/projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/${sample_name}_${model}/${filename}" | ||
| echo "Evaluating file: $data_path" | ||
| echo "Output directory: $output_dir" | ||
| poe eval \ | ||
| ckpt_path="$ckpt_path" \ | ||
| model="$model" \ | ||
| +data.predict_data_path="$data_path" \ | ||
| trainer=gpu \ | ||
| data.num_workers=$num_workers \ | ||
| data.batch_size=$batch_size \ | ||
| paths.output_dir="$output_dir" \ | ||
| paths.log_dir="$output_dir" \ | ||
| tags=["eval"] \ | ||
| extras.print_config=False | ||
| done |
Sorry, the diff of this file is not supported yet
| #!/bin/bash | ||
| set -euo pipefail # Combines the set commands into one line | ||
| # Paths to checkpoint files | ||
| hyena_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-04-08_23-19-20/checkpoints/epoch_005_f1_0.9933.ckpt" | ||
| # train with both rna 002 data | ||
| # hyena_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-11-14_14-14-01/checkpoints/epoch_010_f1_0.9930.ckpt" | ||
| # rna 004 only | ||
| # hyena_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-07-02_15-20-53/checkpoints/epoch_008_f1_0.9946.ckpt" | ||
| cnn_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-04-07_12-01-37/checkpoints/epoch_036_f1_0.9914.ckpt" | ||
| caduceus_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-05-25_19-42-45/checkpoints/epoch_002_f1_0.9982.ckpt" | ||
| # Default model selection | ||
| sample_name="MCF7_dorado_with_trim" | ||
| data_folder="rebutt/MCF7_dorado_with_trim.fastq_chunks" | ||
| num_workers=15 | ||
| batch_size=64 | ||
| # get the model from the command line | ||
| if [ "$#" -eq 0 ]; then | ||
| echo "Please select a valid model: cnn, hyena, or caduceus." | ||
| exit 1 | ||
| elif [ "$#" -eq 1 ]; then | ||
| model=$1 | ||
| else | ||
| echo "Error: Too many arguments." | ||
| echo "Please provide only one argument: cnn, hyena, or caduceus." | ||
| exit 1 | ||
| fi | ||
| # Set the checkpoint path based on the selected model | ||
| if [ "$model" = "cnn" ]; then | ||
| ckpt_path="$cnn_ckpt_path" | ||
| elif [ "$model" = "hyena" ]; then | ||
| ckpt_path="$hyena_ckpt_path" | ||
| elif [ "$model" = "caduceus" ]; then | ||
| ckpt_path="$caduceus_ckpt_path" | ||
| else | ||
| echo "Error: Model not supported." | ||
| echo "Please select a valid model: cnn, hyena, or caduceus." | ||
| exit 1 | ||
| fi | ||
| # Iterate over each .parquet file in the data folder and evaluate | ||
| for data_path in "$data_folder"/*.parquet; do | ||
| # Extract filename without extension | ||
| filename=$(basename -- "$data_path") | ||
| filename="${filename%.*}" | ||
| # Define output directory using the filename | ||
| output_dir="/projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/${sample_name}_${model}/${filename}" | ||
| echo "Evaluating file: $data_path" | ||
| echo "Output directory: $output_dir" | ||
| poe eval \ | ||
| ckpt_path="$ckpt_path" \ | ||
| model="$model" \ | ||
| +data.predict_data_path="$data_path" \ | ||
| trainer=gpu \ | ||
| data.num_workers=$num_workers \ | ||
| data.batch_size=$batch_size \ | ||
| paths.output_dir="$output_dir" \ | ||
| paths.log_dir="$output_dir" \ | ||
| tags=["eval"] \ | ||
| extras.print_config=False | ||
| done |
| #!/bin/bash | ||
| measure() { | ||
| command_to_run="$@" | ||
| # Check if nvidia-smi is available (for NVIDIA GPUs) | ||
| if command -v nvidia-smi &>/dev/null; then | ||
| has_nvidia=true | ||
| else | ||
| has_nvidia=false | ||
| echo "Note: nvidia-smi not found. GPU monitoring will be disabled." | ||
| fi | ||
| # Get CPU info | ||
| cpu_mhz=$(grep -m 1 "cpu MHz" /proc/cpuinfo | awk '{print $4}') | ||
| cpu_cores=$(nproc) | ||
| total_cpu_mhz=$(echo "$cpu_mhz * $cpu_cores" | bc) | ||
| # Record start time | ||
| start_time=$(date +%s.%N) | ||
| # Run the command | ||
| eval "$command_to_run" & | ||
| cmd_pid=$! | ||
| # Initialize peak tracking | ||
| peak_cpu_percent=0 | ||
| peak_mem_kb=0 | ||
| peak_gpu_percent=0 | ||
| peak_gpu_mem_mb=0 | ||
| # Create temporary files for GPU monitoring | ||
| if $has_nvidia; then | ||
| gpu_util_file=$(mktemp) | ||
| gpu_mem_file=$(mktemp) | ||
| fi | ||
| # Monitor usage while command runs | ||
| while ps -p $cmd_pid >/dev/null 2>&1; do | ||
| # Get all child PIDs including the parent | ||
| pids=$(pstree -p $cmd_pid | grep -o '([0-9]\+)' | tr -d '()' | tr '\n' ' ')$cmd_pid | ||
| # Get current total CPU usage percentage across all processes | ||
| current_cpu=0 | ||
| for pid in $pids; do | ||
| if ps -p $pid >/dev/null 2>&1; then | ||
| pid_cpu=$(ps -p $pid -o %cpu= | tr -d ' ') | ||
| current_cpu=$(echo "$current_cpu + $pid_cpu" | bc 2>/dev/null || echo "$current_cpu") | ||
| fi | ||
| done | ||
| # Get current total memory usage in KB across all processes | ||
| current_mem=0 | ||
| for pid in $pids; do | ||
| if ps -p $pid >/dev/null 2>&1; then | ||
| pid_mem=$(ps -p $pid -o rss= | tr -d ' ') | ||
| current_mem=$(echo "$current_mem + $pid_mem" | bc 2>/dev/null || echo "$current_mem") | ||
| fi | ||
| done | ||
| # Get GPU usage if available | ||
| if $has_nvidia; then | ||
| # Get GPU utilization percentage | ||
| gpu_util=$(nvidia-smi --query-gpu=utilization.gpu --format=csv,noheader,nounits | awk '{sum+=$1} END {print sum}') | ||
| echo "$gpu_util" >>"$gpu_util_file" | ||
| # Get GPU memory usage in MB | ||
| gpu_mem=$(nvidia-smi --query-gpu=memory.used --format=csv,noheader,nounits | awk '{sum+=$1} END {print sum}') | ||
| echo "$gpu_mem" >>"$gpu_mem_file" | ||
| fi | ||
| # Update peaks if current is higher | ||
| if [[ -n "$current_cpu" ]] && (($(echo "$current_cpu > $peak_cpu_percent" | bc -l 2>/dev/null))); then | ||
| peak_cpu_percent=$current_cpu | ||
| fi | ||
| if [[ -n "$current_mem" ]] && ((current_mem > peak_mem_kb)); then | ||
| peak_mem_kb=$current_mem | ||
| fi | ||
| sleep 0.1 # Faster sampling rate | ||
| done | ||
| # Calculate total runtime | ||
| end_time=$(date +%s.%N) | ||
| total_time=$(echo "scale=3; $end_time - $start_time" | bc -l) | ||
| # Get peak GPU values if available | ||
| if $has_nvidia; then | ||
| peak_gpu_percent=$(sort -nr "$gpu_util_file" | head -1) | ||
| peak_gpu_mem_mb=$(sort -nr "$gpu_mem_file" | head -1) | ||
| rm -f "$gpu_util_file" "$gpu_mem_file" | ||
| fi | ||
| # Convert peak CPU percentage to absolute CPU usage | ||
| peak_cpu_mhz=$(echo "scale=2; $peak_cpu_percent * $total_cpu_mhz / 100" | bc) | ||
| # Format CPU usage in appropriate units (MHz, GHz) | ||
| if (($(echo "$peak_cpu_mhz >= 1000" | bc -l))); then | ||
| peak_cpu_ghz=$(echo "scale=2; $peak_cpu_mhz / 1000" | bc) | ||
| cpu_unit="${peak_cpu_ghz}G" | ||
| else | ||
| cpu_unit="${peak_cpu_mhz}M" | ||
| fi | ||
| # Format memory usage in appropriate units (KB, MB, GB) | ||
| if ((peak_mem_kb >= 1048576)); then | ||
| peak_mem_gb=$(echo "scale=2; $peak_mem_kb / 1048576" | bc) | ||
| mem_unit="${peak_mem_gb}G" | ||
| elif ((peak_mem_kb >= 1024)); then | ||
| peak_mem_mb=$(echo "scale=2; $peak_mem_kb / 1024" | bc) | ||
| mem_unit="${peak_mem_mb}M" | ||
| else | ||
| mem_unit="${peak_mem_kb}K" | ||
| fi | ||
| # Format GPU memory usage | ||
| if $has_nvidia; then | ||
| if ((peak_gpu_mem_mb >= 1024)); then | ||
| peak_gpu_mem_gb=$(echo "scale=2; $peak_gpu_mem_mb / 1024" | bc) | ||
| gpu_mem_unit="${peak_gpu_mem_gb}G" | ||
| else | ||
| gpu_mem_unit="${peak_gpu_mem_mb}M" | ||
| fi | ||
| fi | ||
| # Output results in a simple format | ||
| echo "runtime: $total_time s" | ||
| echo "peak_cpu: $cpu_unit" | ||
| echo "peak_mem: $mem_unit" | ||
| if $has_nvidia; then | ||
| echo "peak_gpu: ${peak_gpu_percent}%" | ||
| echo "peak_gpu_mem: $gpu_mem_unit" | ||
| fi | ||
| } | ||
| # Check if arguments were provided | ||
| if [ $# -eq 0 ]; then | ||
| echo "Usage: $0 command [arguments]" | ||
| exit 1 | ||
| fi | ||
| # Call the measure function with all arguments | ||
| measure "$@" |
| # DeepChopper Model Upload Guide | ||
| This guide explains how to use the enhanced `modle2hub.py` script to push DeepChopper models to Hugging Face Hub with comprehensive metadata. | ||
| ## Features | ||
| ### Enhanced Script (`modle2hub.py`) | ||
| The script now includes: | ||
| 1. **Comprehensive Model Card Generation** | ||
| - Automatic extraction of F1 scores from checkpoint filenames | ||
| - Detailed model architecture documentation | ||
| - Training details and hyperparameters | ||
| - Usage examples and limitations | ||
| - Proper citations and references | ||
| - Contact information and support links | ||
| - **Automatic upload of README.md to Hugging Face Hub** | ||
| 2. **Two-Stage Upload Process** | ||
| - Stage 1: Upload model weights using `push_to_hub()` | ||
| - Stage 2: Upload model card (README.md) using Hugging Face Hub API | ||
| - Ensures both model and documentation are properly synced | ||
| 3. **Rich CLI Interface** | ||
| - Beautiful terminal output with Rich formatting | ||
| - Interactive confirmations | ||
| - Progress indicators for long operations | ||
| - Detailed error messages with troubleshooting tips | ||
| 4. **Advanced Options** | ||
| - Custom F1 score specification | ||
| - Custom model descriptions | ||
| - Private repository support | ||
| - Custom commit messages | ||
| - HF API token support | ||
| 5. **Validation and Error Handling** | ||
| - Checkpoint file validation | ||
| - Clear error messages | ||
| - Troubleshooting guidance | ||
| - Automatic cleanup of temporary files | ||
| ## Usage | ||
| ### Basic Usage | ||
| ```bash | ||
| python scripts/modle2hub.py epoch_012_f1_0.9947.ckpt | ||
| ``` | ||
| This will: | ||
| - Auto-detect the F1 score (0.9947) from the filename | ||
| - Use the default model name: `yangliz5/deepchopper` | ||
| - Generate a comprehensive model card | ||
| - Push to Hugging Face Hub (public repository) | ||
| ### Advanced Usage | ||
| ```bash | ||
| python scripts/modle2hub.py epoch_012_f1_0.9947.ckpt \ | ||
| --model-name username/deepchopper-v2 \ | ||
| --f1-score 0.9947 \ | ||
| --description "Custom model description" \ | ||
| --commit-message "Upload DeepChopper v2.0" \ | ||
| --private \ | ||
| --token YOUR_HF_TOKEN | ||
| ``` | ||
| ### Options | ||
| - `--model-name, -m`: Model repository ID (format: username/model-name) | ||
| - `--f1-score, -f`: F1 score to include in the model card | ||
| - `--description, -d`: Custom model description | ||
| - `--commit-message, -c`: Git commit message | ||
| - `--private, -p`: Make the repository private | ||
| - `--token, -t`: Hugging Face API token (or use HF_TOKEN env var) | ||
| ## Model Card Content | ||
| The generated model card includes: | ||
| ### Metadata (YAML frontmatter) | ||
| - Tags: genomics, bioinformatics, nanopore, rna-sequencing, chimera-detection, etc. | ||
| - License: MIT | ||
| - Language: DNA | ||
| - Pipeline tag: token-classification | ||
| - Library name: deepchopper | ||
| ### Sections | ||
| 1. **Model Details**: Architecture, authors, paper references | ||
| 2. **Model Architecture**: Detailed breakdown of layers and dimensions | ||
| 3. **Uses**: Direct use cases and downstream applications | ||
| 4. **Training Details**: Data, procedure, hyperparameters | ||
| 5. **Evaluation**: Metrics and results | ||
| 6. **How to Use**: Installation and usage examples (Python API, CLI, Web UI) | ||
| 7. **Limitations**: Platform-specific constraints | ||
| 8. **Citation**: BibTeX format | ||
| 9. **Contact & Support**: Links to documentation and issues | ||
| ## Enhanced DeepChopper Class | ||
| The `DeepChopper` class in `deepchopper/models/dc_hg.py` has been improved with: | ||
| 1. **Comprehensive Documentation** | ||
| - Detailed docstrings for all methods | ||
| - Usage examples | ||
| - Parameter descriptions | ||
| - Return type documentation | ||
| 2. **Enhanced `to_hub` Method** | ||
| - Support for commit messages | ||
| - Private repository option | ||
| - Token authentication | ||
| - Proper type hints | ||
| 3. **Better Type Safety** | ||
| - Modern Python type hints (using `|` for unions) | ||
| - Keyword-only arguments for better API design | ||
| ## Prerequisites | ||
| Before uploading, ensure you have: | ||
| 1. **Hugging Face Account** | ||
| ```bash | ||
| huggingface-cli login | ||
| ``` | ||
| 2. **Required Dependencies** | ||
| ```bash | ||
| pip install huggingface-hub rich typer | ||
| ``` | ||
| 3. **Valid Checkpoint File** | ||
| - Should be a PyTorch Lightning checkpoint (.ckpt) | ||
| - Contains trained model weights | ||
| ## How It Works | ||
| ### Upload Process | ||
| The script performs a two-stage upload: | ||
| 1. **Model Upload** | ||
| - Loads the checkpoint using `DeepChopper.from_checkpoint()` | ||
| - Pushes model weights and configuration to Hugging Face Hub | ||
| - Uses PyTorch Lightning's serialization format | ||
| 2. **Model Card Upload** | ||
| - Generates comprehensive README.md with metadata | ||
| - Uses Hugging Face Hub API to upload the model card | ||
| - Creates a separate commit for documentation | ||
| - Ensures proper rendering on the Hugging Face model page | ||
| This two-stage approach ensures that both the model and its documentation are properly synchronized on Hugging Face Hub. | ||
| ## Example Workflow | ||
| 1. Train your DeepChopper model | ||
| 2. Identify the best checkpoint (e.g., `epoch_012_f1_0.9947.ckpt`) | ||
| 3. Login to Hugging Face: `huggingface-cli login` | ||
| 4. Run the upload script: | ||
| ```bash | ||
| python scripts/modle2hub.py epoch_012_f1_0.9947.ckpt \ | ||
| --model-name username/deepchopper-finetuned | ||
| ``` | ||
| 5. Review the model card preview (optional) | ||
| 6. Confirm the upload | ||
| 7. Script uploads model weights (Stage 1) | ||
| 8. Script uploads model card README.md (Stage 2) | ||
| 9. Share your model at `https://huggingface.co/username/deepchopper-finetuned` | ||
| ## Troubleshooting | ||
| ### Authentication Errors | ||
| - Run `huggingface-cli login` and enter your token | ||
| - Or pass `--token YOUR_TOKEN` to the script | ||
| - Or set `HF_TOKEN` environment variable | ||
| ### Checkpoint Loading Errors | ||
| - Ensure the checkpoint is a valid PyTorch Lightning checkpoint | ||
| - Check that the file is not corrupted | ||
| - Verify the model architecture matches | ||
| ### PyTorch 2.6+ Compatibility | ||
| **Note:** PyTorch 2.6 changed the default value of `weights_only` in `torch.load` from `False` to `True` for security reasons. DeepChopper checkpoints contain optimizer/scheduler configurations (`functools.partial`) which require `weights_only=False` to load. | ||
| **This is already handled in the code** - the `from_checkpoint` method explicitly sets `weights_only=False`. Only load checkpoints from trusted sources. | ||
| If you encounter errors like: | ||
| ``` | ||
| WeightsUnpickler error: Unsupported global: GLOBAL functools.partial | ||
| ``` | ||
| This means you're using an older version of the code. Update to the latest version which includes the fix. | ||
| ### Network Errors | ||
| - Check your internet connection | ||
| - Ensure Hugging Face Hub is accessible | ||
| - Try with a smaller test repository first | ||
| ### Model Card Not Showing | ||
| If you uploaded a model but the model card (README.md) is not visible: | ||
| 1. **Check the upload logs**: Look for "Uploading model card (README.md)..." in the progress output | ||
| 2. **Verify on Hugging Face**: Go to your model page and check the "Files and versions" tab | ||
| 3. **Manual fix**: You can manually upload the README.md: | ||
| ```bash | ||
| # The script creates a temporary README.md, you can regenerate it | ||
| python scripts/modle2hub.py YOUR_CHECKPOINT.ckpt --model-name username/model-name | ||
| # Then manually upload at https://huggingface.co/username/model-name/tree/main | ||
| ``` | ||
| 4. **Re-run with latest version**: Make sure you're using the latest version of the script that includes the two-stage upload process | ||
| ## Best Practices | ||
| 1. **Naming Convention** | ||
| - Use descriptive model names: `username/deepchopper-{variant}` | ||
| - Include version numbers for multiple versions | ||
| 2. **Documentation** | ||
| - Add F1 scores for performance tracking | ||
| - Include custom descriptions for special models | ||
| - Update commit messages to describe changes | ||
| 3. **Privacy** | ||
| - Use `--private` for sensitive or unpublished models | ||
| - Make public only when ready for community use | ||
| 4. **Version Control** | ||
| - Tag releases in Git before uploading | ||
| - Keep track of which checkpoint corresponds to which HF model | ||
| ## Additional Resources | ||
| - [DeepChopper Documentation](https://github.com/ylab-hi/DeepChopper/blob/main/documentation/tutorial.md) | ||
| - [Hugging Face Hub Documentation](https://huggingface.co/docs/hub/index) | ||
| - [DeepChopper Paper](https://www.biorxiv.org/content/10.1101/2024.10.23.619929v2) |
| """Script to push DeepChopper models to Hugging Face Hub with comprehensive metadata.""" | ||
| import os | ||
| from pathlib import Path | ||
| from typing import Optional | ||
| import deepchopper | ||
| import typer | ||
| from huggingface_hub import HfApi | ||
| from rich.console import Console | ||
| from rich.panel import Panel | ||
| from rich.progress import Progress, SpinnerColumn, TextColumn | ||
| app = typer.Typer( | ||
| context_settings={"help_option_names": ["-h", "--help"]}, | ||
| help="Push DeepChopper models to Hugging Face Hub with comprehensive metadata.", | ||
| ) | ||
| console = Console() | ||
| def create_model_card( | ||
| model_name: str, | ||
| ckpt_path: str, | ||
| f1_score: Optional[float] = None, | ||
| description: Optional[str] = None, | ||
| ) -> str: | ||
| """Generate a comprehensive model card for the Hugging Face Hub. | ||
| Args: | ||
| model_name: The name/identifier for the model on Hugging Face Hub | ||
| ckpt_path: Path to the checkpoint file | ||
| f1_score: Optional F1 score from checkpoint filename or manual input | ||
| description: Optional custom description | ||
| Returns: | ||
| A formatted markdown string containing the model card | ||
| """ | ||
| # Try to extract F1 score from checkpoint filename if not provided | ||
| if f1_score is None: | ||
| ckpt_filename = Path(ckpt_path).name | ||
| if "f1" in ckpt_filename.lower(): | ||
| try: | ||
| # Extract number after 'f1' or 'f1_' | ||
| import re | ||
| match = re.search(r'f1[_-]?([\d.]+)', ckpt_filename, re.IGNORECASE) | ||
| if match: | ||
| f1_score = float(match.group(1)) | ||
| except (ValueError, AttributeError): | ||
| pass | ||
| # Default description | ||
| if description is None: | ||
| description = ( | ||
| "DeepChopper is a genomic language model designed to accurately detect and remove " | ||
| "chimera artifacts in Nanopore direct RNA sequencing data. It uses a HyenaDNA backbone " | ||
| "with a token classification head to identify artificial adapter sequences within reads." | ||
| ) | ||
| model_card = f"""--- | ||
| tags: | ||
| - genomics | ||
| - bioinformatics | ||
| - nanopore | ||
| - rna-sequencing | ||
| - chimera-detection | ||
| - token-classification | ||
| - hyenadna | ||
| - pytorch | ||
| - lightning | ||
| license: apache-2.0 | ||
| datasets: | ||
| - nanopore-drna-seq | ||
| language: | ||
| - dna | ||
| library_name: deepchopper | ||
| pipeline_tag: token-classification | ||
| --- | ||
| # DeepChopper: Chimera Detection for Nanopore Direct RNA Sequencing | ||
| {description} | ||
| ## Model Details | ||
| ### Model Description | ||
| DeepChopper leverages the HyenaDNA-small-32k backbone, a genomic foundation model, combined with a specialized token classification head to detect chimeric artifacts in nanopore direct RNA sequencing reads. The model processes both sequence information and base quality scores to make accurate predictions. | ||
| - **Developed by:** YLab Team ([Li et al., 2024](https://www.biorxiv.org/content/10.1101/2024.10.23.619929v2)) | ||
| - **Model type:** Token Classification | ||
| - **Language(s):** DNA sequences | ||
| - **License:** Apache 2.0 | ||
| - **Base Model:** HyenaDNA-small-32k-seqlen | ||
| - **Repository:** [DeepChopper GitHub](https://github.com/ylab-hi/DeepChopper) | ||
| - **Paper:** [A Genomic Language Model for Chimera Artifact Detection](https://www.biorxiv.org/content/10.1101/2024.10.23.619929v2) | ||
| ### Model Architecture | ||
| - **Backbone:** HyenaDNA-small-32k (256 dimensions) | ||
| - **Classification Head:** | ||
| - Linear Layer 1: 256 → 1024 dimensions | ||
| - Linear Layer 2: 1024 → 1024 dimensions | ||
| - Output Layer: 1024 → 2 classes (artifact/non-artifact) | ||
| - Quality Score Integration: Identity layer for base quality incorporation | ||
| - **Input:** | ||
| - Tokenized DNA sequences (vocabulary size: 12) | ||
| - Base quality scores | ||
| - **Output:** Per-base classification (artifact vs. non-artifact) | ||
| ## Uses | ||
| ### Direct Use | ||
| DeepChopper is designed for: | ||
| - Detecting chimeric artifacts in Nanopore direct RNA sequencing data | ||
| - Identifying adapter sequences within base-called reads | ||
| - Preprocessing RNA-seq data before downstream transcriptomics analysis | ||
| - Improving accuracy of transcript annotation and gene fusion detection | ||
| ### Downstream Use | ||
| The cleaned data can be used for: | ||
| - Transcript isoform analysis | ||
| - Gene expression quantification | ||
| - Novel transcript discovery | ||
| - Gene fusion detection | ||
| - Alternative splicing analysis | ||
| ### Out-of-Scope Use | ||
| This model is NOT designed for: | ||
| - DNA sequencing data (it's specifically trained on RNA sequences) | ||
| - PacBio or Illumina sequencing platforms | ||
| - Genome assembly or variant calling | ||
| ## Training Details | ||
| ### Training Data | ||
| The model was trained on Nanopore direct RNA sequencing data with manually curated annotations of chimeric artifacts and adapter sequences. | ||
| ### Training Procedure | ||
| - **Optimizer:** Adam (lr=0.0002, weight_decay=0) | ||
| - **Learning Rate Scheduler:** ReduceLROnPlateau (mode=min, factor=0.1, patience=10) | ||
| - **Loss Function:** Continuous Interval Loss (CrossEntropyLoss with no penalty) | ||
| - **Framework:** PyTorch Lightning | ||
| ### Training Hyperparameters | ||
| - Learning Rate: 0.0002 | ||
| - Batch Size: Configured per experiment | ||
| - Weight Decay: 0 | ||
| - Backbone: Fine-tuned (not frozen) | ||
| ## Evaluation | ||
| ### Testing Data & Metrics | ||
| """ | ||
| if f1_score is not None: | ||
| model_card += f"- **F1 Score:** {f1_score:.4f}\n" | ||
| model_card += """ | ||
| The model is evaluated on held-out test sets using: | ||
| - F1 Score (primary metric) | ||
| - Precision | ||
| - Recall | ||
| ### Results | ||
| DeepChopper significantly improves downstream analysis quality by accurately removing chimeric artifacts that would otherwise confound transcriptome analyses. | ||
| ## How to Use | ||
| ### Installation | ||
| ```bash | ||
| pip install deepchopper | ||
| ``` | ||
| ### Python API | ||
| ```python | ||
| import deepchopper | ||
| # Load the pretrained model | ||
| model = deepchopper.DeepChopper.from_pretrained("MODEL_NAME") | ||
| # The model is ready for inference | ||
| # Use with deepchopper's predict pipeline | ||
| ``` | ||
| ### Command Line Interface | ||
| ```bash | ||
| # Step 1: Encode your FASTQ data | ||
| deepchopper encode input.fq | ||
| # Step 2: Predict chimeric artifacts | ||
| deepchopper predict input.parquet --output predictions | ||
| # Step 3: Remove artifacts and generate clean FASTQ | ||
| deepchopper chop predictions input.fq | ||
| ``` | ||
| For GPU acceleration: | ||
| ```bash | ||
| deepchopper predict input.parquet --output predictions --gpus 1 | ||
| ``` | ||
| ### Web Interface | ||
| Try DeepChopper online without installation: | ||
| - [Hugging Face Space](https://huggingface.co/spaces/yangliz5/deepchopper) | ||
| - Or run locally: `deepchopper web` | ||
| ## Limitations | ||
| - **Platform-specific:** Optimized for Nanopore direct RNA sequencing | ||
| - **Read length:** Best performance on reads up to 32k bases (model context window) | ||
| - **Species:** Trained primarily on human RNA sequences | ||
| - **Computational requirements:** GPU recommended for large datasets | ||
| ## Citation | ||
| If you use DeepChopper in your research, please cite: | ||
| ```bibtex | ||
| @article{Li2024.10.23.619929, | ||
| author = {Li, Yangyang and Wang, Ting-You and Guo, Qingxiang and Ren, Yanan and Lu, Xiaotong and Cao, Qi and Yang, Rendong}, | ||
| title = {A Genomic Language Model for Chimera Artifact Detection in Nanopore Direct RNA Sequencing}, | ||
| year = {2024}, | ||
| doi = {10.1101/2024.10.23.619929}, | ||
| journal = {bioRxiv} | ||
| } | ||
| ``` | ||
| ## Contact & Support | ||
| - **Issues:** [GitHub Issues](https://github.com/ylab-hi/DeepChopper/issues) | ||
| - **Documentation:** [Full Tutorial](https://github.com/ylab-hi/DeepChopper/blob/main/documentation/tutorial.md) | ||
| - **Repository:** [GitHub](https://github.com/ylab-hi/DeepChopper) | ||
| ## Model Card Authors | ||
| YLab Team | ||
| ## Model Card Contact | ||
| For questions about this model, please open an issue on the [GitHub repository](https://github.com/ylab-hi/DeepChopper/issues). | ||
| """ | ||
| return model_card.replace("MODEL_NAME", model_name) | ||
| @app.command() | ||
| def main( | ||
| ckpt_path: str = typer.Argument(..., help="Path to the checkpoint file (.ckpt)"), | ||
| model_name: str = typer.Option( | ||
| "yangliz5/deepchopper", | ||
| "--model-name", "-m", | ||
| help="Model name/identifier on Hugging Face Hub (format: username/model-name)" | ||
| ), | ||
| f1_score: Optional[float] = typer.Option( | ||
| None, | ||
| "--f1-score", "-f", | ||
| help="F1 score to include in model card (auto-detected from filename if not provided)" | ||
| ), | ||
| description: Optional[str] = typer.Option( | ||
| None, | ||
| "--description", "-d", | ||
| help="Custom model description for the model card" | ||
| ), | ||
| commit_message: str = typer.Option( | ||
| "Upload DeepChopper model", | ||
| "--commit-message", "-c", | ||
| help="Commit message for the Hugging Face Hub" | ||
| ), | ||
| private: bool = typer.Option( | ||
| False, | ||
| "--private", "-p", | ||
| help="Make the model repository private" | ||
| ), | ||
| token: Optional[str] = typer.Option( | ||
| None, | ||
| "--token", "-t", | ||
| help="Hugging Face API token (uses HF_TOKEN environment variable if not provided)" | ||
| ), | ||
| ) -> None: | ||
| """ | ||
| Push a DeepChopper checkpoint to Hugging Face Hub with comprehensive metadata. | ||
| This script: | ||
| - Validates the checkpoint file | ||
| - Loads the model from the checkpoint | ||
| - Generates a comprehensive model card | ||
| - Pushes the model to Hugging Face Hub with proper tags and metadata | ||
| Example usage: | ||
| python modle2hub.py epoch_012_f1_0.9947.ckpt --model-name username/deepchopper-v1 | ||
| python modle2hub.py model.ckpt -m username/my-model -f 0.9947 --private | ||
| """ | ||
| # Validate checkpoint path | ||
| ckpt_file = Path(ckpt_path) | ||
| if not ckpt_file.exists(): | ||
| console.print(f"[bold red]Error:[/bold red] Checkpoint file not found: {ckpt_path}") | ||
| raise typer.Exit(code=1) | ||
| if not ckpt_file.suffix == ".ckpt": | ||
| console.print(f"[bold yellow]Warning:[/bold yellow] File doesn't have .ckpt extension: {ckpt_path}") | ||
| # Display configuration | ||
| console.print(Panel.fit( | ||
| f"[bold cyan]DeepChopper Model Upload Configuration[/bold cyan]\n\n" | ||
| f"[bold]Checkpoint:[/bold] {ckpt_path}\n" | ||
| f"[bold]Model Name:[/bold] {model_name}\n" | ||
| f"[bold]F1 Score:[/bold] {f1_score if f1_score else 'Auto-detect from filename'}\n" | ||
| f"[bold]Private:[/bold] {private}\n" | ||
| f"[bold]Commit Message:[/bold] {commit_message}", | ||
| title="Upload Configuration", | ||
| border_style="cyan" | ||
| )) | ||
| # Generate model card | ||
| console.print("\n[bold cyan]Generating model card...[/bold cyan]") | ||
| model_card_content = create_model_card(model_name, ckpt_path, f1_score, description) | ||
| # Show model card preview | ||
| if typer.confirm("\nWould you like to preview the model card?", default=False): | ||
| console.print(Panel(model_card_content, title="Model Card Preview", border_style="green")) | ||
| # Confirm upload | ||
| if not typer.confirm("\nProceed with upload to Hugging Face Hub?", default=True): | ||
| console.print("[yellow]Upload cancelled.[/yellow]") | ||
| raise typer.Exit(code=0) | ||
| try: | ||
| with Progress( | ||
| SpinnerColumn(), | ||
| TextColumn("[progress.description]{task.description}"), | ||
| console=console, | ||
| ) as progress: | ||
| # Load model | ||
| task = progress.add_task("Loading model from checkpoint...", total=None) | ||
| model = deepchopper.DeepChopper.from_checkpoint(ckpt_path) # type: ignore[attr-defined] | ||
| progress.update(task, completed=True) | ||
| # Prepare token | ||
| hf_token = token if token else os.environ.get("HF_TOKEN") | ||
| # Push model to hub | ||
| task = progress.add_task("Pushing model to Hugging Face Hub...", total=None) | ||
| # Prepare push_to_hub kwargs | ||
| push_kwargs = { | ||
| "repo_id": model_name, | ||
| "commit_message": commit_message, | ||
| "private": private, | ||
| } | ||
| if hf_token: | ||
| push_kwargs["token"] = hf_token | ||
| model.push_to_hub(**push_kwargs) | ||
| progress.update(task, completed=True) | ||
| # Upload model card | ||
| task = progress.add_task("Uploading model card (README_HG.md)...", total=None) | ||
| api = HfApi(token=hf_token) | ||
| # Create temporary model card file | ||
| model_card_path = Path("README_HG.md") | ||
| with open(model_card_path, "w", encoding="utf-8") as f: | ||
| f.write(model_card_content) | ||
| # Upload the README.md file | ||
| api.upload_file( | ||
| path_or_fileobj=str(model_card_path), | ||
| path_in_repo="README_HG.md", | ||
| repo_id=model_name, | ||
| commit_message=f"{commit_message} - Add model card", | ||
| repo_type="model", | ||
| ) | ||
| progress.update(task, completed=True) | ||
| # Clean up temporary model card | ||
| if model_card_path.exists(): | ||
| model_card_path.unlink() | ||
| # Success message | ||
| console.print(Panel.fit( | ||
| f"[bold green]✓ Success![/bold green]\n\n" | ||
| f"Model successfully pushed to: [bold cyan]https://huggingface.co/{model_name}[/bold cyan]\n\n" | ||
| f"To use this model:\n" | ||
| f"[dim]import deepchopper\n" | ||
| f"model = deepchopper.DeepChopper.from_pretrained('{model_name}')[/dim]", | ||
| title="Upload Complete", | ||
| border_style="green" | ||
| )) | ||
| except Exception as e: | ||
| console.print(f"\n[bold red]Error during upload:[/bold red] {str(e)}") | ||
| console.print("\n[yellow]Troubleshooting tips:[/yellow]") | ||
| console.print("1. Make sure you're logged in: [dim]huggingface-cli login[/dim]") | ||
| console.print("2. Check your internet connection") | ||
| console.print("3. Verify the model name format: [dim]username/model-name[/dim]") | ||
| console.print("4. Ensure you have write permissions for this repository") | ||
| # Clean up temporary files | ||
| readme_path = Path("README_HG.md") | ||
| if readme_path.exists(): | ||
| readme_path.unlink() | ||
| raise typer.Exit(code=1) | ||
| if __name__ == "__main__": | ||
| app() |
| #!/bin/bash | ||
| set -euo pipefail # Combines the set commands into one line | ||
| # Paths to checkpoint files | ||
| hyena_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-04-08_23-19-20/checkpoints/epoch_005_f1_0.9933.ckpt" | ||
| # train with both rna 002 data | ||
| # hyena_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-11-14_14-14-01/checkpoints/epoch_010_f1_0.9930.ckpt" | ||
| # rna 004 only | ||
| # hyena_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-07-02_15-20-53/checkpoints/epoch_008_f1_0.9946.ckpt" | ||
| cnn_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-04-07_12-01-37/checkpoints/epoch_036_f1_0.9914.ckpt" | ||
| caduceus_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-05-25_19-42-45/checkpoints/epoch_002_f1_0.9982.ckpt" | ||
| # Default model selection | ||
| sample_name="WTC11_dorado_with_trim" | ||
| data_folder="rebutt/WTC11_dorado_with_trim.fastq_chunks" | ||
| num_workers=15 | ||
| batch_size=64 | ||
| # get the model from the command line | ||
| if [ "$#" -eq 0 ]; then | ||
| echo "Please select a valid model: cnn, hyena, or caduceus." | ||
| exit 1 | ||
| elif [ "$#" -eq 1 ]; then | ||
| model=$1 | ||
| else | ||
| echo "Error: Too many arguments." | ||
| echo "Please provide only one argument: cnn, hyena, or caduceus." | ||
| exit 1 | ||
| fi | ||
| # Set the checkpoint path based on the selected model | ||
| if [ "$model" = "cnn" ]; then | ||
| ckpt_path="$cnn_ckpt_path" | ||
| elif [ "$model" = "hyena" ]; then | ||
| ckpt_path="$hyena_ckpt_path" | ||
| elif [ "$model" = "caduceus" ]; then | ||
| ckpt_path="$caduceus_ckpt_path" | ||
| else | ||
| echo "Error: Model not supported." | ||
| echo "Please select a valid model: cnn, hyena, or caduceus." | ||
| exit 1 | ||
| fi | ||
| # Iterate over each .parquet file in the data folder and evaluate | ||
| for data_path in "$data_folder"/*.parquet; do | ||
| # Extract filename without extension | ||
| filename=$(basename -- "$data_path") | ||
| filename="${filename%.*}" | ||
| # Define output directory using the filename | ||
| output_dir="/projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/${sample_name}_${model}/${filename}" | ||
| echo "Evaluating file: $data_path" | ||
| echo "Output directory: $output_dir" | ||
| poe eval \ | ||
| ckpt_path="$ckpt_path" \ | ||
| model="$model" \ | ||
| +data.predict_data_path="$data_path" \ | ||
| trainer=gpu \ | ||
| data.num_workers=$num_workers \ | ||
| data.batch_size=$batch_size \ | ||
| paths.output_dir="$output_dir" \ | ||
| paths.log_dir="$output_dir" \ | ||
| tags=["eval"] \ | ||
| extras.print_config=False | ||
| done |
Sorry, the diff of this file is not supported yet
@@ -1,2 +0,2 @@ | ||
| # bump-my-version bump minor --allow-dirty | ||
| # bump-my-version bump minor --allow-dirty | ||
@@ -3,0 +3,0 @@ [tool.bumpversion] |
| [build] | ||
| rustflags = ["-Z", "threads=8", "-Ctarget-cpu=native"] | ||
| rustflags = ["-Ctarget-cpu=native"] | ||
| [target.aarch64-apple-darwin] | ||
| rustflags = ["-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup"] |
@@ -23,3 +23,3 @@ name: github | ||
| - name: Checkout | ||
| uses: actions/checkout@v4 | ||
| uses: actions/checkout@v5 | ||
| - name: Run Labeler | ||
@@ -26,0 +26,0 @@ uses: crazy-max/ghaction-github-labeler@v5 |
@@ -39,4 +39,4 @@ # This file is autogenerated by maturin v1.7.4 | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-python@v5 | ||
| - uses: actions/checkout@v5 | ||
| - uses: actions/setup-python@v6 | ||
| with: | ||
@@ -53,7 +53,7 @@ python-version: ${{ matrix.python-version }} | ||
| - name: Upload wheels | ||
| uses: actions/upload-artifact@v4 | ||
| uses: actions/upload-artifact@v5 | ||
| with: | ||
| name: wheels-linux-${{ matrix.platform.target }}-py${{ matrix.python-version }} | ||
| path: ./py_cli/dist | ||
| - name: pytest | ||
| - name: Test CLI | ||
| if: ${{ startsWith(matrix.platform.target, 'x86_64') }} | ||
@@ -69,3 +69,3 @@ shell: bash | ||
| if: ${{ !startsWith(matrix.platform.target, 'x86') && matrix.platform.target != 'ppc64' }} | ||
| uses: uraimo/run-on-arch-action@v2 | ||
| uses: uraimo/run-on-arch-action@v3 | ||
| with: | ||
@@ -102,4 +102,4 @@ arch: ${{ matrix.platform.target }} | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-python@v5 | ||
| - uses: actions/checkout@v5 | ||
| - uses: actions/setup-python@v6 | ||
| with: | ||
@@ -116,3 +116,3 @@ python-version: ${{ matrix.python-version }} | ||
| - name: Upload wheels | ||
| uses: actions/upload-artifact@v4 | ||
| uses: actions/upload-artifact@v5 | ||
| with: | ||
@@ -129,8 +129,6 @@ name: wheels-musllinux-${{ matrix.platform.target }}-py${{ matrix.python-version }} | ||
| target: x64 | ||
| - runner: windows-latest | ||
| target: x86 | ||
| python-version: ["3.10", "3.11", "3.12"] | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-python@v5 | ||
| - uses: actions/checkout@v5 | ||
| - uses: actions/setup-python@v6 | ||
| with: | ||
@@ -146,4 +144,6 @@ python-version: ${{ matrix.python-version }} | ||
| working-directory: ./py_cli | ||
| env: | ||
| RUSTFLAGS: "-C target-cpu=x86-64" | ||
| - name: Upload wheels | ||
| uses: actions/upload-artifact@v4 | ||
| uses: actions/upload-artifact@v5 | ||
| with: | ||
@@ -168,10 +168,10 @@ name: wheels-windows-${{ matrix.platform.target }}-py${{ matrix.python-version }} | ||
| platform: | ||
| - runner: macos-12 | ||
| - runner: macos-latest | ||
| target: x86_64 | ||
| - runner: macos-14 | ||
| - runner: macos-latest | ||
| target: aarch64 | ||
| python-version: ["3.10", "3.11", "3.12"] | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-python@v5 | ||
| - uses: actions/checkout@v5 | ||
| - uses: actions/setup-python@v6 | ||
| with: | ||
@@ -186,4 +186,6 @@ python-version: ${{ matrix.python-version }} | ||
| working-directory: ./py_cli | ||
| env: | ||
| RUSTFLAGS: "-C link-args=-Wl,-undefined,dynamic_lookup" | ||
| - name: Upload wheels | ||
| uses: actions/upload-artifact@v4 | ||
| uses: actions/upload-artifact@v5 | ||
| with: | ||
@@ -199,2 +201,3 @@ name: wheels-macos-${{ matrix.platform.target }}-py${{ matrix.python-version }} | ||
| pip install deepchopper-cli --find-links dist --force-reinstall | ||
| python3 -c "import sys; print(f'Python: {sys.executable}'); print(f'Version: {sys.version}')" | ||
| deepchopper-chop --help | ||
@@ -205,3 +208,3 @@ | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/checkout@v5 | ||
| - name: Build sdist | ||
@@ -214,3 +217,3 @@ uses: PyO3/maturin-action@v1 | ||
| - name: Upload sdist | ||
| uses: actions/upload-artifact@v4 | ||
| uses: actions/upload-artifact@v5 | ||
| with: | ||
@@ -233,5 +236,5 @@ name: wheels-sdist | ||
| steps: | ||
| - uses: actions/download-artifact@v4 | ||
| - uses: actions/download-artifact@v6 | ||
| - name: Generate artifact attestation | ||
| uses: actions/attest-build-provenance@v1 | ||
| uses: actions/attest-build-provenance@v3 | ||
| with: | ||
@@ -238,0 +241,0 @@ subject-path: "wheels-*/*" |
@@ -39,4 +39,4 @@ # This file is autogenerated by maturin v1.7.4 | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-python@v5 | ||
| - uses: actions/checkout@v5 | ||
| - uses: actions/setup-python@v6 | ||
| with: | ||
@@ -52,7 +52,7 @@ python-version: ${{ matrix.python-version }} | ||
| - name: Upload wheels | ||
| uses: actions/upload-artifact@v4 | ||
| uses: actions/upload-artifact@v5 | ||
| with: | ||
| name: wheels-linux-${{ matrix.platform.target }}-py${{ matrix.python-version }} | ||
| path: dist | ||
| - name: pytest | ||
| - name: Test CLI | ||
| if: ${{ startsWith(matrix.platform.target, 'x86_64') }} | ||
@@ -66,17 +66,2 @@ shell: bash | ||
| deepchopper -h | ||
| - name: pytest | ||
| if: ${{ !startsWith(matrix.platform.target, 'x86') && matrix.platform.target != 'ppc64' }} | ||
| uses: uraimo/run-on-arch-action@v2 | ||
| with: | ||
| arch: ${{ matrix.platform.target }} | ||
| distro: ubuntu22.04 | ||
| githubToken: ${{ github.token }} | ||
| install: | | ||
| apt-get update | ||
| apt-get install -y --no-install-recommends python3 python3-pip | ||
| pip3 install -U pip pytest | ||
| run: | | ||
| set -e | ||
| pip3 install deepchopper --find-links dist --force-reinstall | ||
| deepchopper -h | ||
@@ -92,4 +77,4 @@ windows: | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-python@v5 | ||
| - uses: actions/checkout@v5 | ||
| - uses: actions/setup-python@v6 | ||
| with: | ||
@@ -104,8 +89,11 @@ python-version: ${{ matrix.python-version }} | ||
| sccache: "true" | ||
| env: | ||
| # Override the native CPU target with baseline | ||
| RUSTFLAGS: "-C target-cpu=x86-64 -C target-feature=+sse2" | ||
| - name: Upload wheels | ||
| uses: actions/upload-artifact@v4 | ||
| uses: actions/upload-artifact@v5 | ||
| with: | ||
| name: wheels-windows-${{ matrix.platform.target }}-py${{ matrix.python-version }} | ||
| path: dist | ||
| - name: pytest | ||
| - name: Test CLI | ||
| if: ${{ !startsWith(matrix.platform.target, 'aarch64') }} | ||
@@ -126,10 +114,10 @@ shell: bash | ||
| platform: | ||
| - runner: macos-12 | ||
| - runner: macos-latest | ||
| target: x86_64 | ||
| - runner: macos-14 | ||
| - runner: macos-latest | ||
| target: aarch64 | ||
| python-version: ["3.10", "3.11", "3.12"] | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/setup-python@v5 | ||
| - uses: actions/checkout@v5 | ||
| - uses: actions/setup-python@v6 | ||
| with: | ||
@@ -144,7 +132,7 @@ python-version: ${{ matrix.python-version }} | ||
| - name: Upload wheels | ||
| uses: actions/upload-artifact@v4 | ||
| uses: actions/upload-artifact@v5 | ||
| with: | ||
| name: wheels-macos-${{ matrix.platform.target }}-py${{ matrix.python-version }} | ||
| path: dist | ||
| - name: pytest | ||
| - name: Test CLI | ||
| run: | | ||
@@ -160,3 +148,3 @@ set -e | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| - uses: actions/checkout@v5 | ||
| - name: Build sdist | ||
@@ -168,3 +156,3 @@ uses: PyO3/maturin-action@v1 | ||
| - name: Upload sdist | ||
| uses: actions/upload-artifact@v4 | ||
| uses: actions/upload-artifact@v5 | ||
| with: | ||
@@ -187,5 +175,5 @@ name: wheels-sdist | ||
| steps: | ||
| - uses: actions/download-artifact@v4 | ||
| - uses: actions/download-artifact@v6 | ||
| - name: Generate artifact attestation | ||
| uses: actions/attest-build-provenance@v1 | ||
| uses: actions/attest-build-provenance@v3 | ||
| with: | ||
@@ -192,0 +180,0 @@ subject-path: "wheels-*/*" |
+2
-1
@@ -595,2 +595,3 @@ /build* | ||
| analysis_data | ||
| poetry.lock | ||
| issues_resolve |
@@ -6,3 +6,3 @@ default_language_version: | ||
| - repo: https://github.com/pre-commit/pre-commit-hooks | ||
| rev: v5.0.0 | ||
| rev: v6.0.0 | ||
| hooks: | ||
@@ -33,3 +33,3 @@ - id: check-yaml | ||
| - repo: https://github.com/charliermarsh/ruff-pre-commit | ||
| rev: "v0.7.0" | ||
| rev: v0.14.5 | ||
| hooks: | ||
@@ -61,3 +61,3 @@ - id: ruff | ||
| - repo: https://github.com/shellcheck-py/shellcheck-py | ||
| rev: v0.10.0.1 | ||
| rev: v0.11.0.1 | ||
| hooks: | ||
@@ -68,16 +68,10 @@ - id: shellcheck | ||
| - repo: https://github.com/executablebooks/mdformat | ||
| rev: 0.7.18 | ||
| rev: 1.0.0 | ||
| hooks: | ||
| - id: mdformat | ||
| args: ["--number"] | ||
| additional_dependencies: | ||
| - mdformat-gfm | ||
| - mdformat-tables | ||
| - mdformat_frontmatter | ||
| # - mdformat-toc | ||
| # - mdformat-black | ||
| # jupyter notebook cell output clearing | ||
| - repo: https://github.com/kynan/nbstripout | ||
| rev: 0.7.1 | ||
| rev: 0.8.2 | ||
| hooks: | ||
@@ -88,3 +82,3 @@ - id: nbstripout | ||
| - repo: https://github.com/nbQA-dev/nbQA | ||
| rev: 1.8.7 | ||
| rev: 1.9.1 | ||
| hooks: | ||
@@ -91,0 +85,0 @@ - id: nbqa-black |
+35
-38
| [package] | ||
| name = "deepchopper" | ||
| version = "1.2.6" | ||
| version = "1.2.8" | ||
| edition = "2021" | ||
@@ -102,35 +102,36 @@ authors = ["Yangyang Li <yangyang.li@northwestern.edu>"] | ||
| [profile.release] | ||
| lto = true | ||
| codegen-units = 1 | ||
| lto = "thin" | ||
| codegen-units = 16 | ||
| opt-level = 3 | ||
| # panic = "abort" | ||
| [dependencies] | ||
| thiserror = "1.0" | ||
| thiserror = "2.0" | ||
| anyhow = "1.0" | ||
| walkdir = { version = "2.5" } | ||
| rayon = { version = "1.10" } | ||
| pyo3 = { version = "0.21.2", features = [ | ||
| "abi3-py310", | ||
| "extension-module", | ||
| "anyhow", | ||
| rayon = { version = "1.11" } | ||
| pyo3 = { version = "0.23.5", features = [ | ||
| "abi3-py310", | ||
| "extension-module", | ||
| "anyhow", | ||
| ] } | ||
| ctrlc = "3.4" | ||
| ctrlc = "3.5" | ||
| log = "0.4" | ||
| pyo3-log = "0.10" | ||
| noodles = { version = "0.84.0", features = [ | ||
| "bgzf", | ||
| "core", | ||
| "csi", | ||
| "fasta", | ||
| "fastq", | ||
| "sam", | ||
| "bam", | ||
| pyo3-log = "0.12" | ||
| noodles = { version = "0.101.0", features = [ | ||
| "bgzf", | ||
| "core", | ||
| "csi", | ||
| "fasta", | ||
| "fastq", | ||
| "sam", | ||
| "bam", | ||
| ] } | ||
| bio = "2.0" | ||
| bio = "3.0" | ||
| needletail = "0.5" | ||
| ahash = "0.8.11" | ||
| numpy = "0.21" | ||
| ndarray = { version = "0.15", features = ["serde", "rayon"] } | ||
| ahash = "0.8.12" | ||
| numpy = "0.23" | ||
| ndarray = { version = "0.16", features = ["serde", "rayon"] } | ||
| num-traits = { version = "0.2" } | ||
@@ -140,27 +141,23 @@ serde = "1.0" | ||
| serde_json = "1.0" | ||
| rand = "0.8" | ||
| rand_distr = "0.4" | ||
| bitvec = "1.0" | ||
| itertools = "0.13.0" | ||
| itertools = "0.14.0" | ||
| derive_builder = "0.20" | ||
| lexical = "7.0" | ||
| bstr = "1.10.0" | ||
| bstr = "1.12.1" | ||
| lazy_static = "1.5.0" | ||
| tempfile = "3.13" | ||
| parquet = "52.2.0" | ||
| arrow = "52.2" | ||
| candle-core = { git = "https://github.com/huggingface/candle.git", version = "0.7.2" } | ||
| colored = "2" | ||
| tempfile = "3.23" | ||
| parquet = "55.2" | ||
| arrow = "55.2" | ||
| candle-core = { git = "https://github.com/huggingface/candle.git", version = "0.9.2-alpha.1" } | ||
| colored = "3" | ||
| textwrap = "0.16" | ||
| flate2 = { version = "1.0.34", features = [ | ||
| "zlib-ng", | ||
| ], default-features = false } | ||
| flate2 = { version = "1.1.5", features = ["zlib-rs"], default-features = false } | ||
| # binaries | ||
| clap = { version = "4.5.20", features = ["derive"] } | ||
| clap = { version = "4.5.52", features = ["derive"] } | ||
| env_logger = "0.11" | ||
| human-panic = "2.0" | ||
| sysinfo = "0.37" | ||
| [dev-dependencies] | ||
@@ -170,2 +167,2 @@ | ||
| [build-dependencies] | ||
| pyo3-build-config = "0.22" | ||
| pyo3-build-config = "0.27" |
@@ -14,3 +14,3 @@ _target_: deepchopper.data.fq_datamodule.FqDataModule | ||
| pin_memory: False | ||
| max_val_samples: 3000 | ||
| max_test_samples: 3000 | ||
| max_val_samples: 30000 | ||
| max_test_samples: 30000 |
@@ -19,3 +19,3 @@ # @package _global_ | ||
| tags: ["vcap_004_300000"] | ||
| tags: ["vcap_004_fintune"] | ||
@@ -32,7 +32,16 @@ seed: 12345 | ||
| test_data_path: ${paths.root_dir}/data/vcap_004_300000_samples/test.parquet | ||
| batch_size: 12 | ||
| num_workers: 63 | ||
| batch_size: 20 | ||
| num_workers: 30 | ||
| pin_memory: False | ||
| max_val_samples: 3000 | ||
| # max_val_samples: 3000 | ||
| model: | ||
| optimizer: | ||
| lr: 0.00001 # Lower LR for fine-tuning (1e-5) | ||
| weight_decay: 0.01 # Small weight decay for regularization during fine-tuning | ||
| scheduler: | ||
| factor: 0.5 # More gradual LR reduction for fine-tuning (0.5 instead of 0.1) | ||
| patience: 10 # Patience for LR reduction | ||
| logger: | ||
@@ -39,0 +48,0 @@ wandb: |
@@ -6,3 +6,3 @@ _target_: deepchopper.models.basic_module.TokenClassificationLit | ||
| _partial_: true | ||
| lr: 0.00002 | ||
| lr: 0.00001 | ||
| weight_decay: 0.0 | ||
@@ -9,0 +9,0 @@ |
+1
-0
@@ -8,2 +8,3 @@ # Contributing to DeepChopper | ||
| 1. Fork the repository on GitHub. | ||
| 2. Clone your fork locally: | ||
@@ -10,0 +11,0 @@ |
@@ -7,4 +7,4 @@ """DeepChopper package.""" | ||
| __version__ = "1.2.6" | ||
| __version__ = "1.2.8" | ||
| __all__ = ["models", "utils", "data", "train", "eval", "DeepChopper", "ui", "cli", "__version__"] | ||
| __all__ = ["DeepChopper", "__version__", "cli", "data", "eval", "models", "train", "ui", "utils"] |
+23
-4
@@ -107,5 +107,18 @@ import logging | ||
| num_workers: int = typer.Option(0, "--workers", "-w", help="Number of workers"), | ||
| model: str = typer.Option( | ||
| "rna002", | ||
| "--model", | ||
| "-m", | ||
| help="Model name (choices: rna002, rna004)", | ||
| show_choices=True, | ||
| case_sensitive=False, | ||
| metavar="MODEL", | ||
| rich_help_panel="Model", | ||
| callback=lambda v: v.lower() | ||
| if v.lower() in {"rna002", "rna004"} | ||
| else typer.BadParameter("Model must be one of: rna002, rna004"), | ||
| ), | ||
| limit_predict_batches: int | None = typer.Option(None, "--limit-batches", help="Limit prediction batches"), | ||
| max_sample: int | None = typer.Option(None, "--max-sample", help="Maximum number of samples to process"), | ||
| verbose: bool = typer.Option(False, "--verbose", "-v", help="Enable verbose output"), | ||
| max_sample: int | None = typer.Option(None, "--max-sample", "-m", help="Maximum number of samples to process"), | ||
| limit_predict_batches: int | None = typer.Option(None, "--limit-batches", "-l", help="Limit prediction batches"), | ||
| ): | ||
@@ -119,2 +132,4 @@ """Predict the given dataset using DeepChopper.""" | ||
| lightning.seed_everything(42, workers=True) | ||
| tokenizer = deepchopper.models.llm.load_tokenizer_from_hyena_model(model_name="hyenadna-small-32k-seqlen") | ||
@@ -130,3 +145,7 @@ datamodule: LightningDataModule = deepchopper.data.fq_datamodule.FqDataModule( | ||
| model = deepchopper.DeepChopper.from_pretrained("yangliz5/deepchopper") | ||
| model = ( | ||
| deepchopper.DeepChopper.from_pretrained("yangliz5/deepchopper") | ||
| if model == "rna002": | ||
| else deepchopper.DeepChopper.from_pretrained("yangliz5/deepchopper-rna004") | ||
| ) | ||
| output_path = Path(output_path or "predictions") | ||
@@ -153,3 +172,3 @@ callbacks = [deepchopper.models.callbacks.CustomWriter(output_dir=output_path, write_interval="batch")] | ||
| callbacks=callbacks, | ||
| deterministic=False, | ||
| deterministic=True, | ||
| logger=False, | ||
@@ -156,0 +175,0 @@ limit_predict_batches=limit_predict_batches, |
@@ -7,2 +7,2 @@ """Data.""" | ||
| __all__ = ["encode_one_fq_file", "encode_fq_files_in_folder_to_parquet", "load_and_split_dataset", "fq_datamodule"] | ||
| __all__ = ["encode_fq_files_in_folder_to_parquet", "encode_one_fq_file", "fq_datamodule", "load_and_split_dataset"] |
@@ -10,5 +10,132 @@ from functools import partial | ||
| class DeepChopper: | ||
| @classmethod | ||
| def from_pretrained(cls, model_name: str, **kwargs) -> "DeepChopper": | ||
| """Load a pretrained model.""" | ||
| """DeepChopper: A genomic language model for chimera artifact detection. | ||
| This class provides convenient methods to load DeepChopper models from checkpoints or | ||
| from pretrained models on the Hugging Face Hub, and to push trained models to the Hub. | ||
| Example: | ||
| Load a pretrained model: | ||
| >>> model = DeepChopper.from_pretrained("yangliz5/deepchopper") | ||
| Load from a local checkpoint: | ||
| >>> model = DeepChopper.from_checkpoint("path/to/checkpoint.ckpt") | ||
| Push a model to Hugging Face Hub: | ||
| >>> model = DeepChopper.to_hub("username/model-name", "path/to/checkpoint.ckpt") | ||
| """ | ||
| @staticmethod | ||
| def to_hub( | ||
| model_name: str, | ||
| checkpoint_path: str, | ||
| *, | ||
| commit_message: str = "Upload DeepChopper model", | ||
| private: bool = False, | ||
| token: str | None = None, | ||
| ): | ||
| """Load a model from a checkpoint and push it to the Hugging Face Hub. | ||
| Args: | ||
| model_name: The repository ID on Hugging Face Hub (format: username/model-name) | ||
| checkpoint_path: Path to the local checkpoint file (.ckpt) | ||
| commit_message: Commit message for the upload (default: "Upload DeepChopper model") | ||
| private: Whether to create a private repository (default: False) | ||
| token: Hugging Face API token. If None, uses the stored token from `huggingface-cli login` | ||
| Returns: | ||
| The loaded TokenClassificationLit model | ||
| Example: | ||
| >>> model = DeepChopper.to_hub( | ||
| ... "username/deepchopper-v1", | ||
| ... "epoch_012_f1_0.9947.ckpt", | ||
| ... commit_message="Upload DeepChopper v1.0", | ||
| ... private=False | ||
| ... ) | ||
| """ | ||
| model = DeepChopper.from_checkpoint(checkpoint_path) | ||
| # Prepare kwargs for push_to_hub | ||
| push_kwargs = { | ||
| "repo_id": model_name, | ||
| "commit_message": commit_message, | ||
| "private": private, | ||
| } | ||
| if token is not None: | ||
| push_kwargs["token"] = token | ||
| model.push_to_hub(**push_kwargs) | ||
| return model | ||
| @staticmethod | ||
| def from_checkpoint(checkpoint_path: str): | ||
| """Load a DeepChopper model from a local checkpoint file. | ||
| This method creates a new TokenClassificationLit model with the HyenaDNA backbone | ||
| and loads the weights from the specified checkpoint file. | ||
| Args: | ||
| checkpoint_path: Path to the checkpoint file (.ckpt) containing model weights | ||
| Returns: | ||
| A TokenClassificationLit model loaded with the checkpoint weights | ||
| Example: | ||
| >>> model = DeepChopper.from_checkpoint("epoch_012_f1_0.9947.ckpt") | ||
| Note: | ||
| This function loads checkpoints with weights_only=False to support PyTorch Lightning | ||
| checkpoints containing optimizer/scheduler configs. Only load checkpoints from trusted sources. | ||
| """ | ||
| model = TokenClassificationLit( | ||
| net=llm.hyena.TokenClassificationModule( | ||
| number_of_classes=2, | ||
| backbone_name="hyenadna-small-32k-seqlen", | ||
| freeze_backbone=False, | ||
| head=llm.TokenClassificationHead( | ||
| input_size=256, | ||
| lin1_size=1024, | ||
| lin2_size=1024, | ||
| num_class=2, | ||
| use_identity_layer_for_qual=True, | ||
| use_qual=True, | ||
| ), | ||
| ), | ||
| optimizer=partial( # type: ignore[arg-type] | ||
| torch.optim.Adam, | ||
| lr=0.0002, | ||
| weight_decay=0, | ||
| ), | ||
| scheduler=partial(torch.optim.lr_scheduler.ReduceLROnPlateau, mode="min", factor=0.1, patience=10), # type: ignore[arg-type] | ||
| criterion=basic_module.ContinuousIntervalLoss(lambda_penalty=0), | ||
| compile=False, | ||
| ) | ||
| # weights_only=False is required for PyTorch Lightning checkpoints that contain | ||
| # optimizer/scheduler configs (functools.partial). Only use with trusted checkpoints. | ||
| checkpoint = torch.load(checkpoint_path, map_location="cpu", weights_only=False) | ||
| model.load_state_dict(checkpoint["state_dict"]) | ||
| return model | ||
| @staticmethod | ||
| def from_pretrained(model_name: str): | ||
| """Load a pretrained DeepChopper model from the Hugging Face Hub. | ||
| This method downloads and loads a pretrained model from the Hugging Face Hub. | ||
| The model architecture is automatically configured to match the expected | ||
| HyenaDNA-based token classification setup. | ||
| Args: | ||
| model_name: The repository ID on Hugging Face Hub (e.g., "yangliz5/deepchopper") | ||
| Returns: | ||
| A TokenClassificationLit model loaded with pretrained weights | ||
| Example: | ||
| >>> model = DeepChopper.from_pretrained("yangliz5/deepchopper") | ||
| Note: | ||
| This requires an internet connection to download the model from Hugging Face Hub. | ||
| The model will be cached locally after the first download. | ||
| """ | ||
| return TokenClassificationLit.from_pretrained( | ||
@@ -29,3 +156,3 @@ model_name, | ||
| ), | ||
| optimizer=partial( | ||
| optimizer=partial( # type: ignore[arg-type] | ||
| torch.optim.Adam, | ||
@@ -35,5 +162,5 @@ lr=0.0002, | ||
| ), | ||
| scheduler=partial(torch.optim.lr_scheduler.ReduceLROnPlateau, mode="min", factor=0.1, patience=10), | ||
| scheduler=partial(torch.optim.lr_scheduler.ReduceLROnPlateau, mode="min", factor=0.1, patience=10), # type: ignore[arg-type] | ||
| criterion=basic_module.ContinuousIntervalLoss(lambda_penalty=0), | ||
| compile=False, | ||
| ) |
@@ -20,7 +20,10 @@ """hyena model components and utilities.""" | ||
| __all__ = [ | ||
| "compute_metrics", | ||
| "IGNORE_INDEX", | ||
| "DataCollatorForTokenClassificationWithQual", | ||
| "HyenadnaMaxLengths", | ||
| "TokenClassification", | ||
| "TokenClassificationConfig", | ||
| "TokenClassificationHead", | ||
| "TokenClassificationConfig", | ||
| "DataCollatorForTokenClassificationWithQual", | ||
| "TokenClassificationModule", | ||
| "compute_metrics", | ||
| "load_tokenizer_from_hyena_model", | ||
@@ -30,5 +33,2 @@ "tokenize_and_align_labels_and_quals", | ||
| "tokenize_dataset", | ||
| "HyenadnaMaxLengths", | ||
| "IGNORE_INDEX", | ||
| "TokenClassificationModule", | ||
| ] |
@@ -117,5 +117,12 @@ from functools import partial | ||
| def to_list(data): | ||
| return list(data) | ||
| def tokenize_and_align_labels_and_quals(data, tokenizer, max_length, pad_qual=0, pad_label=IGNORE_INDEX): | ||
| tokenized_inputs = tokenizer(data["seq"], max_length=max_length, truncation=True, padding=True) | ||
| if isinstance(data["qual"], bytes): | ||
| data["qual"] = torch.Tensor(to_list(data["qual"])) | ||
| if len(data["seq"]) >= max_length: | ||
@@ -122,0 +129,0 @@ if data["target"][1] + 2 > max_length: |
@@ -12,3 +12,3 @@ import multiprocessing | ||
| import deepchopper | ||
| from deepchopper.deepchopper import default, encode_qual, remove_intervals_and_keep_left, smooth_label_region | ||
| from deepchopper.deepchopper import default, remove_intervals_and_keep_left, smooth_label_region | ||
| from deepchopper.models.llm import ( | ||
@@ -30,6 +30,8 @@ tokenize_and_align_labels_and_quals, | ||
| input_qual = deepchopper.encode_qual(qual, default.KMER_SIZE) | ||
| yield { | ||
| "id": record_id, | ||
| "seq": seq, | ||
| "qual": encode_qual(qual, default.KMER_SIZE), | ||
| "qual": torch.Tensor(input_qual), | ||
| "target": [0, 0], | ||
@@ -71,3 +73,3 @@ } | ||
| accelerator=accelerator, | ||
| devices=-1, | ||
| devices="auto", | ||
| deterministic=False, | ||
@@ -74,0 +76,0 @@ logger=False, |
@@ -19,20 +19,20 @@ """Utils.""" | ||
| __all__ = [ | ||
| "load_safetensor", | ||
| "save_ndarray_to_safetensor", | ||
| "load_kmer2id", | ||
| "instantiate_callbacks", | ||
| "instantiate_loggers", | ||
| "log_hyperparameters", | ||
| "RankedLogger", | ||
| "print_config_tree", | ||
| "alignment_predict", | ||
| "device", | ||
| "extras", | ||
| "task_wrapper", | ||
| "get_metric_value", | ||
| "device", | ||
| "highlight_target", | ||
| "highlight_targets", | ||
| "hightlight_predict", | ||
| "hightlight_predicts", | ||
| "instantiate_callbacks", | ||
| "instantiate_loggers", | ||
| "load_kmer2id", | ||
| "load_safetensor", | ||
| "log_hyperparameters", | ||
| "print_config_tree", | ||
| "save_ndarray_to_safetensor", | ||
| "summary_predict", | ||
| "alignment_predict", | ||
| "highlight_targets", | ||
| "hightlight_predicts", | ||
| "task_wrapper", | ||
| ] |
@@ -314,2 +314,2 @@ <!DOCTYPE html> | ||
| </html> | ||
| </html> |
@@ -1,1 +0,1 @@ | ||
| @-webkit-keyframes spinAround{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spinAround{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.slider{position:relative;width:100%}.slider-container{display:flex;flex-wrap:nowrap;flex-direction:row;overflow:hidden;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);min-height:100%}.slider-container.is-vertical{flex-direction:column}.slider-container .slider-item{flex:none}.slider-container .slider-item .image.is-covered img{-o-object-fit:cover;object-fit:cover;-o-object-position:center center;object-position:center center;height:100%;width:100%}.slider-container .slider-item .video-container{height:0;padding-bottom:0;padding-top:56.25%;margin:0;position:relative}.slider-container .slider-item .video-container.is-1by1,.slider-container .slider-item .video-container.is-square{padding-top:100%}.slider-container .slider-item .video-container.is-4by3{padding-top:75%}.slider-container .slider-item .video-container.is-21by9{padding-top:42.857143%}.slider-container .slider-item .video-container embed,.slider-container .slider-item .video-container iframe,.slider-container .slider-item .video-container object{position:absolute;top:0;left:0;width:100%!important;height:100%!important}.slider-navigation-next,.slider-navigation-previous{display:flex;justify-content:center;align-items:center;position:absolute;width:42px;height:42px;background:#fff center center no-repeat;background-size:20px 20px;border:1px solid #fff;border-radius:25091983px;box-shadow:0 2px 5px #3232321a;top:50%;margin-top:-20px;left:0;cursor:pointer;transition:opacity .3s,-webkit-transform .3s;transition:transform .3s,opacity .3s;transition:transform .3s,opacity .3s,-webkit-transform .3s}.slider-navigation-next:hover,.slider-navigation-previous:hover{-webkit-transform:scale(1.2);transform:scale(1.2)}.slider-navigation-next.is-hidden,.slider-navigation-previous.is-hidden{display:none;opacity:0}.slider-navigation-next svg,.slider-navigation-previous svg{width:25%}.slider-navigation-next{left:auto;right:0;background:#fff center center no-repeat;background-size:20px 20px}.slider-pagination{display:none;justify-content:center;align-items:center;position:absolute;bottom:0;left:0;right:0;padding:.5rem 1rem;text-align:center}.slider-pagination .slider-page{background:#fff;width:10px;height:10px;border-radius:25091983px;display:inline-block;margin:0 3px;box-shadow:0 2px 5px #3232321a;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;cursor:pointer}.slider-pagination .slider-page.is-active,.slider-pagination .slider-page:hover{-webkit-transform:scale(1.4);transform:scale(1.4)}@media screen and (min-width:800px){.slider-pagination{display:flex}}.hero.has-carousel{position:relative}.hero.has-carousel+.hero-body,.hero.has-carousel+.hero-footer,.hero.has-carousel+.hero-head{z-index:10;overflow:hidden}.hero.has-carousel .hero-carousel{position:absolute;top:0;left:0;bottom:0;right:0;height:auto;border:none;margin:auto;padding:0;z-index:0}.hero.has-carousel .hero-carousel .slider{width:100%;max-width:100%;overflow:hidden;height:100%!important;max-height:100%;z-index:0}.hero.has-carousel .hero-carousel .slider .has-background{max-height:100%}.hero.has-carousel .hero-carousel .slider .has-background .is-background{-o-object-fit:cover;object-fit:cover;-o-object-position:center center;object-position:center center;height:100%;width:100%}.hero.has-carousel .hero-body{margin:0 3rem;z-index:10} | ||
| @-webkit-keyframes spinAround{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spinAround{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}.slider{position:relative;width:100%}.slider-container{display:flex;flex-wrap:nowrap;flex-direction:row;overflow:hidden;-webkit-transform:translate3d(0,0,0);transform:translate3d(0,0,0);min-height:100%}.slider-container.is-vertical{flex-direction:column}.slider-container .slider-item{flex:none}.slider-container .slider-item .image.is-covered img{-o-object-fit:cover;object-fit:cover;-o-object-position:center center;object-position:center center;height:100%;width:100%}.slider-container .slider-item .video-container{height:0;padding-bottom:0;padding-top:56.25%;margin:0;position:relative}.slider-container .slider-item .video-container.is-1by1,.slider-container .slider-item .video-container.is-square{padding-top:100%}.slider-container .slider-item .video-container.is-4by3{padding-top:75%}.slider-container .slider-item .video-container.is-21by9{padding-top:42.857143%}.slider-container .slider-item .video-container embed,.slider-container .slider-item .video-container iframe,.slider-container .slider-item .video-container object{position:absolute;top:0;left:0;width:100%!important;height:100%!important}.slider-navigation-next,.slider-navigation-previous{display:flex;justify-content:center;align-items:center;position:absolute;width:42px;height:42px;background:#fff center center no-repeat;background-size:20px 20px;border:1px solid #fff;border-radius:25091983px;box-shadow:0 2px 5px #3232321a;top:50%;margin-top:-20px;left:0;cursor:pointer;transition:opacity .3s,-webkit-transform .3s;transition:transform .3s,opacity .3s;transition:transform .3s,opacity .3s,-webkit-transform .3s}.slider-navigation-next:hover,.slider-navigation-previous:hover{-webkit-transform:scale(1.2);transform:scale(1.2)}.slider-navigation-next.is-hidden,.slider-navigation-previous.is-hidden{display:none;opacity:0}.slider-navigation-next svg,.slider-navigation-previous svg{width:25%}.slider-navigation-next{left:auto;right:0;background:#fff center center no-repeat;background-size:20px 20px}.slider-pagination{display:none;justify-content:center;align-items:center;position:absolute;bottom:0;left:0;right:0;padding:.5rem 1rem;text-align:center}.slider-pagination .slider-page{background:#fff;width:10px;height:10px;border-radius:25091983px;display:inline-block;margin:0 3px;box-shadow:0 2px 5px #3232321a;transition:-webkit-transform .3s;transition:transform .3s;transition:transform .3s,-webkit-transform .3s;cursor:pointer}.slider-pagination .slider-page.is-active,.slider-pagination .slider-page:hover{-webkit-transform:scale(1.4);transform:scale(1.4)}@media screen and (min-width:800px){.slider-pagination{display:flex}}.hero.has-carousel{position:relative}.hero.has-carousel+.hero-body,.hero.has-carousel+.hero-footer,.hero.has-carousel+.hero-head{z-index:10;overflow:hidden}.hero.has-carousel .hero-carousel{position:absolute;top:0;left:0;bottom:0;right:0;height:auto;border:none;margin:auto;padding:0;z-index:0}.hero.has-carousel .hero-carousel .slider{width:100%;max-width:100%;overflow:hidden;height:100%!important;max-height:100%;z-index:0}.hero.has-carousel .hero-carousel .slider .has-background{max-height:100%}.hero.has-carousel .hero-carousel .slider .has-background .is-background{-o-object-fit:cover;object-fit:cover;-o-object-position:center center;object-position:center center;height:100%;width:100%}.hero.has-carousel .hero-body{margin:0 3rem;z-index:10} |
@@ -1,1 +0,1 @@ | ||
| @-webkit-keyframes spinAround{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spinAround{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}input[type=range].slider{-webkit-appearance:none;-moz-appearance:none;appearance:none;margin:1rem 0;background:0 0;touch-action:none}input[type=range].slider.is-fullwidth{display:block;width:100%}input[type=range].slider:focus{outline:0}input[type=range].slider:not([orient=vertical])::-webkit-slider-runnable-track{width:100%}input[type=range].slider:not([orient=vertical])::-moz-range-track{width:100%}input[type=range].slider:not([orient=vertical])::-ms-track{width:100%}input[type=range].slider:not([orient=vertical]).has-output+output,input[type=range].slider:not([orient=vertical]).has-output-tooltip+output{width:3rem;background:#4a4a4a;border-radius:4px;padding:.4rem .8rem;font-size:.75rem;line-height:.75rem;text-align:center;text-overflow:ellipsis;white-space:nowrap;color:#fff;overflow:hidden;pointer-events:none;z-index:200}input[type=range].slider:not([orient=vertical]).has-output-tooltip:disabled+output,input[type=range].slider:not([orient=vertical]).has-output:disabled+output{opacity:.5}input[type=range].slider:not([orient=vertical]).has-output{display:inline-block;vertical-align:middle;width:calc(100% - (4.2rem))}input[type=range].slider:not([orient=vertical]).has-output+output{display:inline-block;margin-left:.75rem;vertical-align:middle}input[type=range].slider:not([orient=vertical]).has-output-tooltip{display:block}input[type=range].slider:not([orient=vertical]).has-output-tooltip+output{position:absolute;left:0;top:-.1rem}input[type=range].slider[orient=vertical]{-webkit-appearance:slider-vertical;-moz-appearance:slider-vertical;appearance:slider-vertical;-webkit-writing-mode:bt-lr;-ms-writing-mode:bt-lr;writing-mode:bt-lr}input[type=range].slider[orient=vertical]::-webkit-slider-runnable-track{height:100%}input[type=range].slider[orient=vertical]::-moz-range-track{height:100%}input[type=range].slider[orient=vertical]::-ms-track{height:100%}input[type=range].slider::-webkit-slider-runnable-track{cursor:pointer;animate:.2s;box-shadow:0 0 0 #7a7a7a;background:#dbdbdb;border-radius:4px;border:0 solid #7a7a7a}input[type=range].slider::-moz-range-track{cursor:pointer;animate:.2s;box-shadow:0 0 0 #7a7a7a;background:#dbdbdb;border-radius:4px;border:0 solid #7a7a7a}input[type=range].slider::-ms-track{cursor:pointer;animate:.2s;box-shadow:0 0 0 #7a7a7a;background:#dbdbdb;border-radius:4px;border:0 solid #7a7a7a}input[type=range].slider::-ms-fill-lower{background:#dbdbdb;border-radius:4px}input[type=range].slider::-ms-fill-upper{background:#dbdbdb;border-radius:4px}input[type=range].slider::-webkit-slider-thumb{box-shadow:none;border:1px solid #b5b5b5;border-radius:4px;background:#fff;cursor:pointer}input[type=range].slider::-moz-range-thumb{box-shadow:none;border:1px solid #b5b5b5;border-radius:4px;background:#fff;cursor:pointer}input[type=range].slider::-ms-thumb{box-shadow:none;border:1px solid #b5b5b5;border-radius:4px;background:#fff;cursor:pointer}input[type=range].slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none}input[type=range].slider.is-circle::-webkit-slider-thumb{border-radius:290486px}input[type=range].slider.is-circle::-moz-range-thumb{border-radius:290486px}input[type=range].slider.is-circle::-ms-thumb{border-radius:290486px}input[type=range].slider:active::-webkit-slider-thumb{-webkit-transform:scale(1.25);transform:scale(1.25)}input[type=range].slider:active::-moz-range-thumb{transform:scale(1.25)}input[type=range].slider:active::-ms-thumb{transform:scale(1.25)}input[type=range].slider:disabled{opacity:.5;cursor:not-allowed}input[type=range].slider:disabled::-webkit-slider-thumb{cursor:not-allowed;-webkit-transform:scale(1);transform:scale(1)}input[type=range].slider:disabled::-moz-range-thumb{cursor:not-allowed;transform:scale(1)}input[type=range].slider:disabled::-ms-thumb{cursor:not-allowed;transform:scale(1)}input[type=range].slider:not([orient=vertical]){min-height:calc((1rem + 2px) * 1.25)}input[type=range].slider:not([orient=vertical])::-webkit-slider-runnable-track{height:.5rem}input[type=range].slider:not([orient=vertical])::-moz-range-track{height:.5rem}input[type=range].slider:not([orient=vertical])::-ms-track{height:.5rem}input[type=range].slider[orient=vertical]::-webkit-slider-runnable-track{width:.5rem}input[type=range].slider[orient=vertical]::-moz-range-track{width:.5rem}input[type=range].slider[orient=vertical]::-ms-track{width:.5rem}input[type=range].slider::-webkit-slider-thumb{height:1rem;width:1rem}input[type=range].slider::-moz-range-thumb{height:1rem;width:1rem}input[type=range].slider::-ms-thumb{height:1rem;width:1rem}input[type=range].slider::-ms-thumb{margin-top:0}input[type=range].slider::-webkit-slider-thumb{margin-top:-.25rem}input[type=range].slider[orient=vertical]::-webkit-slider-thumb{margin-top:auto;margin-left:-.25rem}input[type=range].slider.is-small:not([orient=vertical]){min-height:calc((.75rem + 2px) * 1.25)}input[type=range].slider.is-small:not([orient=vertical])::-webkit-slider-runnable-track{height:.375rem}input[type=range].slider.is-small:not([orient=vertical])::-moz-range-track{height:.375rem}input[type=range].slider.is-small:not([orient=vertical])::-ms-track{height:.375rem}input[type=range].slider.is-small[orient=vertical]::-webkit-slider-runnable-track{width:.375rem}input[type=range].slider.is-small[orient=vertical]::-moz-range-track{width:.375rem}input[type=range].slider.is-small[orient=vertical]::-ms-track{width:.375rem}input[type=range].slider.is-small::-webkit-slider-thumb{height:.75rem;width:.75rem}input[type=range].slider.is-small::-moz-range-thumb{height:.75rem;width:.75rem}input[type=range].slider.is-small::-ms-thumb{height:.75rem;width:.75rem}input[type=range].slider.is-small::-ms-thumb{margin-top:0}input[type=range].slider.is-small::-webkit-slider-thumb{margin-top:-.1875rem}input[type=range].slider.is-small[orient=vertical]::-webkit-slider-thumb{margin-top:auto;margin-left:-.1875rem}input[type=range].slider.is-medium:not([orient=vertical]){min-height:calc((1.25rem + 2px) * 1.25)}input[type=range].slider.is-medium:not([orient=vertical])::-webkit-slider-runnable-track{height:.625rem}input[type=range].slider.is-medium:not([orient=vertical])::-moz-range-track{height:.625rem}input[type=range].slider.is-medium:not([orient=vertical])::-ms-track{height:.625rem}input[type=range].slider.is-medium[orient=vertical]::-webkit-slider-runnable-track{width:.625rem}input[type=range].slider.is-medium[orient=vertical]::-moz-range-track{width:.625rem}input[type=range].slider.is-medium[orient=vertical]::-ms-track{width:.625rem}input[type=range].slider.is-medium::-webkit-slider-thumb{height:1.25rem;width:1.25rem}input[type=range].slider.is-medium::-moz-range-thumb{height:1.25rem;width:1.25rem}input[type=range].slider.is-medium::-ms-thumb{height:1.25rem;width:1.25rem}input[type=range].slider.is-medium::-ms-thumb{margin-top:0}input[type=range].slider.is-medium::-webkit-slider-thumb{margin-top:-.3125rem}input[type=range].slider.is-medium[orient=vertical]::-webkit-slider-thumb{margin-top:auto;margin-left:-.3125rem}input[type=range].slider.is-large:not([orient=vertical]){min-height:calc((1.5rem + 2px) * 1.25)}input[type=range].slider.is-large:not([orient=vertical])::-webkit-slider-runnable-track{height:.75rem}input[type=range].slider.is-large:not([orient=vertical])::-moz-range-track{height:.75rem}input[type=range].slider.is-large:not([orient=vertical])::-ms-track{height:.75rem}input[type=range].slider.is-large[orient=vertical]::-webkit-slider-runnable-track{width:.75rem}input[type=range].slider.is-large[orient=vertical]::-moz-range-track{width:.75rem}input[type=range].slider.is-large[orient=vertical]::-ms-track{width:.75rem}input[type=range].slider.is-large::-webkit-slider-thumb{height:1.5rem;width:1.5rem}input[type=range].slider.is-large::-moz-range-thumb{height:1.5rem;width:1.5rem}input[type=range].slider.is-large::-ms-thumb{height:1.5rem;width:1.5rem}input[type=range].slider.is-large::-ms-thumb{margin-top:0}input[type=range].slider.is-large::-webkit-slider-thumb{margin-top:-.375rem}input[type=range].slider.is-large[orient=vertical]::-webkit-slider-thumb{margin-top:auto;margin-left:-.375rem}input[type=range].slider.is-white::-moz-range-track{background:#fff!important}input[type=range].slider.is-white::-webkit-slider-runnable-track{background:#fff!important}input[type=range].slider.is-white::-ms-track{background:#fff!important}input[type=range].slider.is-white::-ms-fill-lower{background:#fff}input[type=range].slider.is-white::-ms-fill-upper{background:#fff}input[type=range].slider.is-white .has-output-tooltip+output,input[type=range].slider.is-white.has-output+output{background-color:#fff;color:#0a0a0a}input[type=range].slider.is-black::-moz-range-track{background:#0a0a0a!important}input[type=range].slider.is-black::-webkit-slider-runnable-track{background:#0a0a0a!important}input[type=range].slider.is-black::-ms-track{background:#0a0a0a!important}input[type=range].slider.is-black::-ms-fill-lower{background:#0a0a0a}input[type=range].slider.is-black::-ms-fill-upper{background:#0a0a0a}input[type=range].slider.is-black .has-output-tooltip+output,input[type=range].slider.is-black.has-output+output{background-color:#0a0a0a;color:#fff}input[type=range].slider.is-light::-moz-range-track{background:#f5f5f5!important}input[type=range].slider.is-light::-webkit-slider-runnable-track{background:#f5f5f5!important}input[type=range].slider.is-light::-ms-track{background:#f5f5f5!important}input[type=range].slider.is-light::-ms-fill-lower{background:#f5f5f5}input[type=range].slider.is-light::-ms-fill-upper{background:#f5f5f5}input[type=range].slider.is-light .has-output-tooltip+output,input[type=range].slider.is-light.has-output+output{background-color:#f5f5f5;color:#363636}input[type=range].slider.is-dark::-moz-range-track{background:#363636!important}input[type=range].slider.is-dark::-webkit-slider-runnable-track{background:#363636!important}input[type=range].slider.is-dark::-ms-track{background:#363636!important}input[type=range].slider.is-dark::-ms-fill-lower{background:#363636}input[type=range].slider.is-dark::-ms-fill-upper{background:#363636}input[type=range].slider.is-dark .has-output-tooltip+output,input[type=range].slider.is-dark.has-output+output{background-color:#363636;color:#f5f5f5}input[type=range].slider.is-primary::-moz-range-track{background:#00d1b2!important}input[type=range].slider.is-primary::-webkit-slider-runnable-track{background:#00d1b2!important}input[type=range].slider.is-primary::-ms-track{background:#00d1b2!important}input[type=range].slider.is-primary::-ms-fill-lower{background:#00d1b2}input[type=range].slider.is-primary::-ms-fill-upper{background:#00d1b2}input[type=range].slider.is-primary .has-output-tooltip+output,input[type=range].slider.is-primary.has-output+output{background-color:#00d1b2;color:#fff}input[type=range].slider.is-link::-moz-range-track{background:#3273dc!important}input[type=range].slider.is-link::-webkit-slider-runnable-track{background:#3273dc!important}input[type=range].slider.is-link::-ms-track{background:#3273dc!important}input[type=range].slider.is-link::-ms-fill-lower{background:#3273dc}input[type=range].slider.is-link::-ms-fill-upper{background:#3273dc}input[type=range].slider.is-link .has-output-tooltip+output,input[type=range].slider.is-link.has-output+output{background-color:#3273dc;color:#fff}input[type=range].slider.is-info::-moz-range-track{background:#209cee!important}input[type=range].slider.is-info::-webkit-slider-runnable-track{background:#209cee!important}input[type=range].slider.is-info::-ms-track{background:#209cee!important}input[type=range].slider.is-info::-ms-fill-lower{background:#209cee}input[type=range].slider.is-info::-ms-fill-upper{background:#209cee}input[type=range].slider.is-info .has-output-tooltip+output,input[type=range].slider.is-info.has-output+output{background-color:#209cee;color:#fff}input[type=range].slider.is-success::-moz-range-track{background:#23d160!important}input[type=range].slider.is-success::-webkit-slider-runnable-track{background:#23d160!important}input[type=range].slider.is-success::-ms-track{background:#23d160!important}input[type=range].slider.is-success::-ms-fill-lower{background:#23d160}input[type=range].slider.is-success::-ms-fill-upper{background:#23d160}input[type=range].slider.is-success .has-output-tooltip+output,input[type=range].slider.is-success.has-output+output{background-color:#23d160;color:#fff}input[type=range].slider.is-warning::-moz-range-track{background:#ffdd57!important}input[type=range].slider.is-warning::-webkit-slider-runnable-track{background:#ffdd57!important}input[type=range].slider.is-warning::-ms-track{background:#ffdd57!important}input[type=range].slider.is-warning::-ms-fill-lower{background:#ffdd57}input[type=range].slider.is-warning::-ms-fill-upper{background:#ffdd57}input[type=range].slider.is-warning .has-output-tooltip+output,input[type=range].slider.is-warning.has-output+output{background-color:#ffdd57;color:rgba(0,0,0,.7)}input[type=range].slider.is-danger::-moz-range-track{background:#ff3860!important}input[type=range].slider.is-danger::-webkit-slider-runnable-track{background:#ff3860!important}input[type=range].slider.is-danger::-ms-track{background:#ff3860!important}input[type=range].slider.is-danger::-ms-fill-lower{background:#ff3860}input[type=range].slider.is-danger::-ms-fill-upper{background:#ff3860}input[type=range].slider.is-danger .has-output-tooltip+output,input[type=range].slider.is-danger.has-output+output{background-color:#ff3860;color:#fff} | ||
| @-webkit-keyframes spinAround{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}@keyframes spinAround{from{-webkit-transform:rotate(0);transform:rotate(0)}to{-webkit-transform:rotate(359deg);transform:rotate(359deg)}}input[type=range].slider{-webkit-appearance:none;-moz-appearance:none;appearance:none;margin:1rem 0;background:0 0;touch-action:none}input[type=range].slider.is-fullwidth{display:block;width:100%}input[type=range].slider:focus{outline:0}input[type=range].slider:not([orient=vertical])::-webkit-slider-runnable-track{width:100%}input[type=range].slider:not([orient=vertical])::-moz-range-track{width:100%}input[type=range].slider:not([orient=vertical])::-ms-track{width:100%}input[type=range].slider:not([orient=vertical]).has-output+output,input[type=range].slider:not([orient=vertical]).has-output-tooltip+output{width:3rem;background:#4a4a4a;border-radius:4px;padding:.4rem .8rem;font-size:.75rem;line-height:.75rem;text-align:center;text-overflow:ellipsis;white-space:nowrap;color:#fff;overflow:hidden;pointer-events:none;z-index:200}input[type=range].slider:not([orient=vertical]).has-output-tooltip:disabled+output,input[type=range].slider:not([orient=vertical]).has-output:disabled+output{opacity:.5}input[type=range].slider:not([orient=vertical]).has-output{display:inline-block;vertical-align:middle;width:calc(100% - (4.2rem))}input[type=range].slider:not([orient=vertical]).has-output+output{display:inline-block;margin-left:.75rem;vertical-align:middle}input[type=range].slider:not([orient=vertical]).has-output-tooltip{display:block}input[type=range].slider:not([orient=vertical]).has-output-tooltip+output{position:absolute;left:0;top:-.1rem}input[type=range].slider[orient=vertical]{-webkit-appearance:slider-vertical;-moz-appearance:slider-vertical;appearance:slider-vertical;-webkit-writing-mode:bt-lr;-ms-writing-mode:bt-lr;writing-mode:bt-lr}input[type=range].slider[orient=vertical]::-webkit-slider-runnable-track{height:100%}input[type=range].slider[orient=vertical]::-moz-range-track{height:100%}input[type=range].slider[orient=vertical]::-ms-track{height:100%}input[type=range].slider::-webkit-slider-runnable-track{cursor:pointer;animate:.2s;box-shadow:0 0 0 #7a7a7a;background:#dbdbdb;border-radius:4px;border:0 solid #7a7a7a}input[type=range].slider::-moz-range-track{cursor:pointer;animate:.2s;box-shadow:0 0 0 #7a7a7a;background:#dbdbdb;border-radius:4px;border:0 solid #7a7a7a}input[type=range].slider::-ms-track{cursor:pointer;animate:.2s;box-shadow:0 0 0 #7a7a7a;background:#dbdbdb;border-radius:4px;border:0 solid #7a7a7a}input[type=range].slider::-ms-fill-lower{background:#dbdbdb;border-radius:4px}input[type=range].slider::-ms-fill-upper{background:#dbdbdb;border-radius:4px}input[type=range].slider::-webkit-slider-thumb{box-shadow:none;border:1px solid #b5b5b5;border-radius:4px;background:#fff;cursor:pointer}input[type=range].slider::-moz-range-thumb{box-shadow:none;border:1px solid #b5b5b5;border-radius:4px;background:#fff;cursor:pointer}input[type=range].slider::-ms-thumb{box-shadow:none;border:1px solid #b5b5b5;border-radius:4px;background:#fff;cursor:pointer}input[type=range].slider::-webkit-slider-thumb{-webkit-appearance:none;appearance:none}input[type=range].slider.is-circle::-webkit-slider-thumb{border-radius:290486px}input[type=range].slider.is-circle::-moz-range-thumb{border-radius:290486px}input[type=range].slider.is-circle::-ms-thumb{border-radius:290486px}input[type=range].slider:active::-webkit-slider-thumb{-webkit-transform:scale(1.25);transform:scale(1.25)}input[type=range].slider:active::-moz-range-thumb{transform:scale(1.25)}input[type=range].slider:active::-ms-thumb{transform:scale(1.25)}input[type=range].slider:disabled{opacity:.5;cursor:not-allowed}input[type=range].slider:disabled::-webkit-slider-thumb{cursor:not-allowed;-webkit-transform:scale(1);transform:scale(1)}input[type=range].slider:disabled::-moz-range-thumb{cursor:not-allowed;transform:scale(1)}input[type=range].slider:disabled::-ms-thumb{cursor:not-allowed;transform:scale(1)}input[type=range].slider:not([orient=vertical]){min-height:calc((1rem + 2px) * 1.25)}input[type=range].slider:not([orient=vertical])::-webkit-slider-runnable-track{height:.5rem}input[type=range].slider:not([orient=vertical])::-moz-range-track{height:.5rem}input[type=range].slider:not([orient=vertical])::-ms-track{height:.5rem}input[type=range].slider[orient=vertical]::-webkit-slider-runnable-track{width:.5rem}input[type=range].slider[orient=vertical]::-moz-range-track{width:.5rem}input[type=range].slider[orient=vertical]::-ms-track{width:.5rem}input[type=range].slider::-webkit-slider-thumb{height:1rem;width:1rem}input[type=range].slider::-moz-range-thumb{height:1rem;width:1rem}input[type=range].slider::-ms-thumb{height:1rem;width:1rem}input[type=range].slider::-ms-thumb{margin-top:0}input[type=range].slider::-webkit-slider-thumb{margin-top:-.25rem}input[type=range].slider[orient=vertical]::-webkit-slider-thumb{margin-top:auto;margin-left:-.25rem}input[type=range].slider.is-small:not([orient=vertical]){min-height:calc((.75rem + 2px) * 1.25)}input[type=range].slider.is-small:not([orient=vertical])::-webkit-slider-runnable-track{height:.375rem}input[type=range].slider.is-small:not([orient=vertical])::-moz-range-track{height:.375rem}input[type=range].slider.is-small:not([orient=vertical])::-ms-track{height:.375rem}input[type=range].slider.is-small[orient=vertical]::-webkit-slider-runnable-track{width:.375rem}input[type=range].slider.is-small[orient=vertical]::-moz-range-track{width:.375rem}input[type=range].slider.is-small[orient=vertical]::-ms-track{width:.375rem}input[type=range].slider.is-small::-webkit-slider-thumb{height:.75rem;width:.75rem}input[type=range].slider.is-small::-moz-range-thumb{height:.75rem;width:.75rem}input[type=range].slider.is-small::-ms-thumb{height:.75rem;width:.75rem}input[type=range].slider.is-small::-ms-thumb{margin-top:0}input[type=range].slider.is-small::-webkit-slider-thumb{margin-top:-.1875rem}input[type=range].slider.is-small[orient=vertical]::-webkit-slider-thumb{margin-top:auto;margin-left:-.1875rem}input[type=range].slider.is-medium:not([orient=vertical]){min-height:calc((1.25rem + 2px) * 1.25)}input[type=range].slider.is-medium:not([orient=vertical])::-webkit-slider-runnable-track{height:.625rem}input[type=range].slider.is-medium:not([orient=vertical])::-moz-range-track{height:.625rem}input[type=range].slider.is-medium:not([orient=vertical])::-ms-track{height:.625rem}input[type=range].slider.is-medium[orient=vertical]::-webkit-slider-runnable-track{width:.625rem}input[type=range].slider.is-medium[orient=vertical]::-moz-range-track{width:.625rem}input[type=range].slider.is-medium[orient=vertical]::-ms-track{width:.625rem}input[type=range].slider.is-medium::-webkit-slider-thumb{height:1.25rem;width:1.25rem}input[type=range].slider.is-medium::-moz-range-thumb{height:1.25rem;width:1.25rem}input[type=range].slider.is-medium::-ms-thumb{height:1.25rem;width:1.25rem}input[type=range].slider.is-medium::-ms-thumb{margin-top:0}input[type=range].slider.is-medium::-webkit-slider-thumb{margin-top:-.3125rem}input[type=range].slider.is-medium[orient=vertical]::-webkit-slider-thumb{margin-top:auto;margin-left:-.3125rem}input[type=range].slider.is-large:not([orient=vertical]){min-height:calc((1.5rem + 2px) * 1.25)}input[type=range].slider.is-large:not([orient=vertical])::-webkit-slider-runnable-track{height:.75rem}input[type=range].slider.is-large:not([orient=vertical])::-moz-range-track{height:.75rem}input[type=range].slider.is-large:not([orient=vertical])::-ms-track{height:.75rem}input[type=range].slider.is-large[orient=vertical]::-webkit-slider-runnable-track{width:.75rem}input[type=range].slider.is-large[orient=vertical]::-moz-range-track{width:.75rem}input[type=range].slider.is-large[orient=vertical]::-ms-track{width:.75rem}input[type=range].slider.is-large::-webkit-slider-thumb{height:1.5rem;width:1.5rem}input[type=range].slider.is-large::-moz-range-thumb{height:1.5rem;width:1.5rem}input[type=range].slider.is-large::-ms-thumb{height:1.5rem;width:1.5rem}input[type=range].slider.is-large::-ms-thumb{margin-top:0}input[type=range].slider.is-large::-webkit-slider-thumb{margin-top:-.375rem}input[type=range].slider.is-large[orient=vertical]::-webkit-slider-thumb{margin-top:auto;margin-left:-.375rem}input[type=range].slider.is-white::-moz-range-track{background:#fff!important}input[type=range].slider.is-white::-webkit-slider-runnable-track{background:#fff!important}input[type=range].slider.is-white::-ms-track{background:#fff!important}input[type=range].slider.is-white::-ms-fill-lower{background:#fff}input[type=range].slider.is-white::-ms-fill-upper{background:#fff}input[type=range].slider.is-white .has-output-tooltip+output,input[type=range].slider.is-white.has-output+output{background-color:#fff;color:#0a0a0a}input[type=range].slider.is-black::-moz-range-track{background:#0a0a0a!important}input[type=range].slider.is-black::-webkit-slider-runnable-track{background:#0a0a0a!important}input[type=range].slider.is-black::-ms-track{background:#0a0a0a!important}input[type=range].slider.is-black::-ms-fill-lower{background:#0a0a0a}input[type=range].slider.is-black::-ms-fill-upper{background:#0a0a0a}input[type=range].slider.is-black .has-output-tooltip+output,input[type=range].slider.is-black.has-output+output{background-color:#0a0a0a;color:#fff}input[type=range].slider.is-light::-moz-range-track{background:#f5f5f5!important}input[type=range].slider.is-light::-webkit-slider-runnable-track{background:#f5f5f5!important}input[type=range].slider.is-light::-ms-track{background:#f5f5f5!important}input[type=range].slider.is-light::-ms-fill-lower{background:#f5f5f5}input[type=range].slider.is-light::-ms-fill-upper{background:#f5f5f5}input[type=range].slider.is-light .has-output-tooltip+output,input[type=range].slider.is-light.has-output+output{background-color:#f5f5f5;color:#363636}input[type=range].slider.is-dark::-moz-range-track{background:#363636!important}input[type=range].slider.is-dark::-webkit-slider-runnable-track{background:#363636!important}input[type=range].slider.is-dark::-ms-track{background:#363636!important}input[type=range].slider.is-dark::-ms-fill-lower{background:#363636}input[type=range].slider.is-dark::-ms-fill-upper{background:#363636}input[type=range].slider.is-dark .has-output-tooltip+output,input[type=range].slider.is-dark.has-output+output{background-color:#363636;color:#f5f5f5}input[type=range].slider.is-primary::-moz-range-track{background:#00d1b2!important}input[type=range].slider.is-primary::-webkit-slider-runnable-track{background:#00d1b2!important}input[type=range].slider.is-primary::-ms-track{background:#00d1b2!important}input[type=range].slider.is-primary::-ms-fill-lower{background:#00d1b2}input[type=range].slider.is-primary::-ms-fill-upper{background:#00d1b2}input[type=range].slider.is-primary .has-output-tooltip+output,input[type=range].slider.is-primary.has-output+output{background-color:#00d1b2;color:#fff}input[type=range].slider.is-link::-moz-range-track{background:#3273dc!important}input[type=range].slider.is-link::-webkit-slider-runnable-track{background:#3273dc!important}input[type=range].slider.is-link::-ms-track{background:#3273dc!important}input[type=range].slider.is-link::-ms-fill-lower{background:#3273dc}input[type=range].slider.is-link::-ms-fill-upper{background:#3273dc}input[type=range].slider.is-link .has-output-tooltip+output,input[type=range].slider.is-link.has-output+output{background-color:#3273dc;color:#fff}input[type=range].slider.is-info::-moz-range-track{background:#209cee!important}input[type=range].slider.is-info::-webkit-slider-runnable-track{background:#209cee!important}input[type=range].slider.is-info::-ms-track{background:#209cee!important}input[type=range].slider.is-info::-ms-fill-lower{background:#209cee}input[type=range].slider.is-info::-ms-fill-upper{background:#209cee}input[type=range].slider.is-info .has-output-tooltip+output,input[type=range].slider.is-info.has-output+output{background-color:#209cee;color:#fff}input[type=range].slider.is-success::-moz-range-track{background:#23d160!important}input[type=range].slider.is-success::-webkit-slider-runnable-track{background:#23d160!important}input[type=range].slider.is-success::-ms-track{background:#23d160!important}input[type=range].slider.is-success::-ms-fill-lower{background:#23d160}input[type=range].slider.is-success::-ms-fill-upper{background:#23d160}input[type=range].slider.is-success .has-output-tooltip+output,input[type=range].slider.is-success.has-output+output{background-color:#23d160;color:#fff}input[type=range].slider.is-warning::-moz-range-track{background:#ffdd57!important}input[type=range].slider.is-warning::-webkit-slider-runnable-track{background:#ffdd57!important}input[type=range].slider.is-warning::-ms-track{background:#ffdd57!important}input[type=range].slider.is-warning::-ms-fill-lower{background:#ffdd57}input[type=range].slider.is-warning::-ms-fill-upper{background:#ffdd57}input[type=range].slider.is-warning .has-output-tooltip+output,input[type=range].slider.is-warning.has-output+output{background-color:#ffdd57;color:rgba(0,0,0,.7)}input[type=range].slider.is-danger::-moz-range-track{background:#ff3860!important}input[type=range].slider.is-danger::-webkit-slider-runnable-track{background:#ff3860!important}input[type=range].slider.is-danger::-ms-track{background:#ff3860!important}input[type=range].slider.is-danger::-ms-fill-lower{background:#ff3860}input[type=range].slider.is-danger::-ms-fill-upper{background:#ff3860}input[type=range].slider.is-danger .has-output-tooltip+output,input[type=range].slider.is-danger.has-output+output{background-color:#ff3860;color:#fff} |
@@ -132,7 +132,4 @@ body { | ||
| .eql-cntrb { | ||
| .eql-cntrb { | ||
| font-size: smaller; | ||
| } | ||
@@ -1,1 +0,1 @@ | ||
| !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.bulmaCarousel=e():t.bulmaCarousel=e()}("undefined"!=typeof self?self:this,function(){return function(i){var n={};function s(t){if(n[t])return n[t].exports;var e=n[t]={i:t,l:!1,exports:{}};return i[t].call(e.exports,e,e.exports,s),e.l=!0,e.exports}return s.m=i,s.c=n,s.d=function(t,e,i){s.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:i})},s.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return s.d(e,"a",e),e},s.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},s.p="",s(s.s=5)}([function(t,e,i){"use strict";i.d(e,"d",function(){return s}),i.d(e,"e",function(){return r}),i.d(e,"b",function(){return o}),i.d(e,"c",function(){return a}),i.d(e,"a",function(){return l});var n=i(2),s=function(e,t){(t=Array.isArray(t)?t:t.split(" ")).forEach(function(t){e.classList.remove(t)})},r=function(t){return t.getBoundingClientRect().width||t.offsetWidth},o=function(t){return t.getBoundingClientRect().height||t.offsetHeight},a=function(t){var e=1<arguments.length&&void 0!==arguments[1]&&arguments[1],i=t.offsetHeight;if(e){var n=window.getComputedStyle(t);i+=parseInt(n.marginTop)+parseInt(n.marginBottom)}return i},l=function(t,e){if(!e)return window.getComputedStyle(t);if(Object(n.b)(e)){var i="";Object.keys(e).forEach(function(t){i+=t+": "+e[t]+";"}),t.style.cssText+=i}}},function(t,e,i){"use strict";e.a=function(){var t=!1;try{var e=Object.defineProperty({},"passive",{get:function(){t=!0}});window.addEventListener("testPassive",null,e),window.removeEventListener("testPassive",null,e)}catch(t){}return t}},function(t,e,i){"use strict";i.d(e,"a",function(){return s}),i.d(e,"c",function(){return r}),i.d(e,"b",function(){return o});var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},s=function(t){return"function"==typeof t},r=function(t){return"string"==typeof t||!!t&&"object"===(void 0===t?"undefined":n(t))&&"[object String]"===Object.prototype.toString.call(t)},o=function(t){return("function"==typeof t||"object"===(void 0===t?"undefined":n(t))&&!!t)&&!Array.isArray(t)}},function(t,e,i){"use strict";var n=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var s=function(){function e(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:[];!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this.events=new Map(t)}return n(e,[{key:"on",value:function(t,e){var i=this;return this.events.set(t,[].concat(function(t){if(Array.isArray(t)){for(var e=0,i=Array(t.length);e<t.length;e++)i[e]=t[e];return i}return Array.from(t)}(this.events.has(t)?this.events.get(t):[]),[e])),function(){return i.events.set(t,i.events.get(t).filter(function(t){return t!==e}))}}},{key:"emit",value:function(t){for(var e=arguments.length,i=Array(1<e?e-1:0),n=1;n<e;n++)i[n-1]=arguments[n];return this.events.has(t)&&this.events.get(t).map(function(t){return t.apply(void 0,i)})}}]),e}();e.a=s},function(t,e,i){"use strict";var n=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var s=function(){function s(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:0,e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:0;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,s),this._x=t,this._y=e}return n(s,[{key:"add",value:function(t){return new s(this._x+t._x,this._y+t._y)}},{key:"sub",value:function(t){return new s(this._x-t._x,this._y-t._y)}},{key:"distance",value:function(t){var e=this._x-t._x,i=this._y-t._y;return Math.sqrt(Math.pow(e,2)+Math.pow(i,2))}},{key:"max",value:function(t){return new s(Math.max(this._x,t._x),Math.max(this._y,t._y))}},{key:"equals",value:function(t){return this==t||!(!t||null==t)&&(this._x==t._x&&this._y==t._y)}},{key:"inside",value:function(t,e){return this._x>=t._x&&this._x<=e._x&&this._y>=t._y&&this._y<=e._y}},{key:"constrain",value:function(t,e){if(t._x>e._x||t._y>e._y)return this;var i=this._x,n=this._y;return null!==t._x&&(i=Math.max(i,t._x)),null!==e._x&&(i=Math.min(i,e._x)),null!==t._y&&(n=Math.max(n,t._y)),null!==e._y&&(n=Math.min(n,e._y)),new s(i,n)}},{key:"reposition",value:function(t){t.style.top=this._y+"px",t.style.left=this._x+"px"}},{key:"toString",value:function(){return"("+this._x+","+this._y+")"}},{key:"x",get:function(){return this._x},set:function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:0;return this._x=t,this}},{key:"y",get:function(){return this._y},set:function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:0;return this._y=t,this}}]),s}();e.a=s},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n=i(6),s=i(0),a=i(2),r=i(3),l=i(7),h=i(9),u=i(10),d=i(11),c=i(13),f=i(15),p=i(18),v=i(19),y=i(22),_=i(23),g=i(24),b=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var i=arguments[e];for(var n in i)Object.prototype.hasOwnProperty.call(i,n)&&(t[n]=i[n])}return t},w=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var o=function(t){function o(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{};!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,o);var r=function(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}(this,(o.__proto__||Object.getPrototypeOf(o)).call(this));if(r.element=Object(a.c)(t)?document.querySelector(t):t,!r.element)throw new Error("An invalid selector or non-DOM node has been provided.");r._clickEvents=["click","touch"];var i=r.element.dataset?Object.keys(r.element.dataset).filter(function(t){return Object.keys(y.a).includes(t)}).reduce(function(t,e){return b({},t,(i={},n=e,s=r.element.dataset[e],n in i?Object.defineProperty(i,n,{value:s,enumerable:!0,configurable:!0,writable:!0}):i[n]=s,i));var i,n,s},{}):{};return r.options=b({},y.a,e,i),r._id=Object(n.a)("slider"),r.onShow=r.onShow.bind(r),r._init(),r}return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}(o,r["a"]),w(o,[{key:"_init",value:function(){return this._items=Array.from(this.element.children),this._breakpoint=new h.a(this),this._autoplay=new l.a(this),this._navigation=new c.a(this),this._pagination=new f.a(this),this._infinite=new u.a(this),this._loop=new d.a(this),this._swipe=new p.a(this),this._build(),Object(a.a)(this.options.onReady)&&this.options.onReady(this),this}},{key:"_build",value:function(){var i=this;this.node=document.createRange().createContextualFragment(Object(_.a)(this.id)),this._ui={wrapper:this.node.firstChild,container:this.node.querySelector(".slider-container")},this.element.appendChild(this.node),this._ui.wrapper.classList.add("is-loading"),this._ui.container.style.opacity=0,this._transitioner=new v.a(this),this._slides=this._items.map(function(t,e){return i._createSlide(t,e)}),this.reset(),this._bindEvents(),this._ui.container.style.opacity=1,this._ui.wrapper.classList.remove("is-loading")}},{key:"_bindEvents",value:function(){this.on("show",this.onShow)}},{key:"_unbindEvents",value:function(){this.off("show",this.onShow)}},{key:"_createSlide",value:function(t,e){var i=document.createRange().createContextualFragment(Object(g.a)()).firstChild;return i.dataset.sliderIndex=e,i.appendChild(t),i}},{key:"_setDimensions",value:function(){var e=this;this.options.vertical?(this._ui.wrapper.style.height=Object(s.c)(this._slides[0])*this.slidesToShow,this.options.centerMode&&(this._ui.wrapper.style.padding=this.options.centerPadding+" 0px")):this.options.centerMode&&(this._ui.wrapper.style.padding="0px "+this.options.centerPadding),this._wrapperWidth=Object(s.e)(this._ui.wrapper),this._wrapperHeight=Object(s.c)(this._ui.wrapper),this.options.vertical?(this._slideWidth=Math.ceil(this._wrapperWidth),this._containerHeight=Math.ceil(Object(s.c)(this._slides[0])*this._slides.length),this._ui.container.style.height=this._containerHeight+"px"):(this._slideWidth=Math.ceil(this._wrapperWidth/this.slidesToShow),this._containerWidth=Math.ceil(this._slideWidth*this._slides.length),this._ui.container.style.width=this._containerWidth+"px"),this._slides.forEach(function(t){t.style.width=e._slideWidth+"px"})}},{key:"_setHeight",value:function(){"translate"!==this.options.effect&&(this._ui.container.style.height=Object(s.c)(this._slides[this.state.index])+"px")}},{key:"_setClasses",value:function(){var e=this;this._slides.forEach(function(t){Object(s.d)(t,"is-active is-current is-slide-previous is-slide-next"),Math.abs((e.state.index-1)%e.state.length)===parseInt(t.dataset.sliderIndex,10)&&t.classList.add("is-slide-previous"),Math.abs(e.state.index%e.state.length)===parseInt(t.dataset.sliderIndex,10)&&t.classList.add("is-current"),Math.abs((e.state.index+1)%e.state.length)===parseInt(t.dataset.sliderIndex,10)&&t.classList.add("is-slide-next")})}},{key:"onShow",value:function(t){this._navigation.refresh(),this._pagination.refresh(),this._setClasses()}},{key:"next",value:function(){!this.options.loop&&!this.options.infinite&&this.state.index+this.slidesToScroll>this.state.length-this.slidesToShow&&!this.options.centerMode?this.state.next=this.state.index:this.state.next=this.state.index+this.slidesToScroll,this.show()}},{key:"previous",value:function(){this.options.loop||this.options.infinite||0!==this.state.index?this.state.next=this.state.index-this.slidesToScroll:this.state.next=this.state.index,this.show()}},{key:"start",value:function(){this._autoplay.start()}},{key:"pause",value:function(){this._autoplay.pause()}},{key:"stop",value:function(){this._autoplay.stop()}},{key:"show",value:function(t){var e=1<arguments.length&&void 0!==arguments[1]&&arguments[1];!this.state.length||this.state.length<=this.slidesToShow||("Number"==typeof t&&(this.state.next=t),this.options.loop&&this._loop.apply(),this.options.infinite&&this._infinite.apply(),this.state.index!==this.state.next&&(this.emit("before:show",this.state),this._transitioner.apply(e,this._setHeight.bind(this)),this.emit("after:show",this.state),this.emit("show",this)))}},{key:"reset",value:function(){var e=this;this.state={length:this._items.length,index:Math.abs(this.options.initialSlide),next:Math.abs(this.options.initialSlide),prev:void 0},this.options.loop&&this.options.infinite&&(this.options.loop=!1),this.options.slidesToScroll>this.options.slidesToShow&&(this.options.slidesToScroll=this.slidesToShow),this._breakpoint.init(),this.state.index>=this.state.length&&0!==this.state.index&&(this.state.index=this.state.index-this.slidesToScroll),this.state.length<=this.slidesToShow&&(this.state.index=0),this._ui.wrapper.appendChild(this._navigation.init().render()),this._ui.wrapper.appendChild(this._pagination.init().render()),this.options.navigationSwipe?this._swipe.bindEvents():this._swipe._bindEvents(),this._breakpoint.apply(),this._slides.forEach(function(t){return e._ui.container.appendChild(t)}),this._transitioner.init().apply(!0,this._setHeight.bind(this)),this.options.autoplay&&this._autoplay.init().start()}},{key:"destroy",value:function(){var e=this;this._unbindEvents(),this._items.forEach(function(t){e.element.appendChild(t)}),this.node.remove()}},{key:"id",get:function(){return this._id}},{key:"index",set:function(t){this._index=t},get:function(){return this._index}},{key:"length",set:function(t){this._length=t},get:function(){return this._length}},{key:"slides",get:function(){return this._slides},set:function(t){this._slides=t}},{key:"slidesToScroll",get:function(){return"translate"===this.options.effect?this._breakpoint.getSlidesToScroll():1}},{key:"slidesToShow",get:function(){return"translate"===this.options.effect?this._breakpoint.getSlidesToShow():1}},{key:"direction",get:function(){return"rtl"===this.element.dir.toLowerCase()||"rtl"===this.element.style.direction?"rtl":"ltr"}},{key:"wrapper",get:function(){return this._ui.wrapper}},{key:"wrapperWidth",get:function(){return this._wrapperWidth||0}},{key:"container",get:function(){return this._ui.container}},{key:"containerWidth",get:function(){return this._containerWidth||0}},{key:"slideWidth",get:function(){return this._slideWidth||0}},{key:"transitioner",get:function(){return this._transitioner}}],[{key:"attach",value:function(){var i=this,t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:".slider",n=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},s=new Array,e=Object(a.c)(t)?document.querySelectorAll(t):Array.isArray(t)?t:[t];return[].forEach.call(e,function(t){if(void 0===t[i.constructor.name]){var e=new o(t,n);t[i.constructor.name]=e,s.push(e)}else s.push(t[i.constructor.name])}),s}}]),o}();e.default=o},function(t,e,i){"use strict";i.d(e,"a",function(){return n});var n=function(){return(0<arguments.length&&void 0!==arguments[0]?arguments[0]:"")+([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,function(t){return(t^crypto.getRandomValues(new Uint8Array(1))[0]&15>>t/4).toString(16)})}},function(t,e,i){"use strict";var n=i(3),s=i(8),r=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();Symbol("onVisibilityChange"),Symbol("onMouseEnter"),Symbol("onMouseLeave");var o=function(t){function i(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,i);var e=function(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}(this,(i.__proto__||Object.getPrototypeOf(i)).call(this));return e.slider=t,e.onVisibilityChange=e.onVisibilityChange.bind(e),e.onMouseEnter=e.onMouseEnter.bind(e),e.onMouseLeave=e.onMouseLeave.bind(e),e}return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}(i,n["a"]),r(i,[{key:"init",value:function(){return this._bindEvents(),this}},{key:"_bindEvents",value:function(){document.addEventListener("visibilitychange",this.onVisibilityChange),this.slider.options.pauseOnHover&&(this.slider.container.addEventListener(s.a,this.onMouseEnter),this.slider.container.addEventListener(s.b,this.onMouseLeave))}},{key:"_unbindEvents",value:function(){document.removeEventListener("visibilitychange",this.onVisibilityChange),this.slider.container.removeEventListener(s.a,this.onMouseEnter),this.slider.container.removeEventListener(s.b,this.onMouseLeave)}},{key:"start",value:function(){var t=this;this.stop(),this.slider.options.autoplay&&(this.emit("start",this),this._interval=setInterval(function(){t._hovering&&t.slider.options.pauseOnHover||(!t.slider.options.centerMode&&t.slider.state.next>=t.slider.state.length-t.slider.slidesToShow&&!t.slider.options.loop&&!t.slider.options.infinite?t.stop():t.slider.next())},this.slider.options.autoplaySpeed))}},{key:"stop",value:function(){this._interval=clearInterval(this._interval),this.emit("stop",this)}},{key:"pause",value:function(){var t=this,e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:0;this.paused||(this.timer&&this.stop(),this.paused=!0,0===e?(this.paused=!1,this.start()):this.slider.on("transition:end",function(){t&&(t.paused=!1,t.run?t.start():t.stop())}))}},{key:"onVisibilityChange",value:function(t){document.hidden?this.stop():this.start()}},{key:"onMouseEnter",value:function(t){this._hovering=!0,this.slider.options.pauseOnHover&&this.pause()}},{key:"onMouseLeave",value:function(t){this._hovering=!1,this.slider.options.pauseOnHover&&this.pause()}}]),i}();e.a=o},function(t,e,i){"use strict";i.d(e,"a",function(){return o}),i.d(e,"b",function(){return a});window.navigator.pointerEnabled||window.navigator.msPointerEnabled,window.navigator.msPointerEnabled&&1<window.navigator.msMaxTouchPoints||window.navigator.pointerEnabled&&window.navigator.maxTouchPoints,navigator.userAgent.match(/(Android);?[\s\/]+([\d.]+)?/),navigator.userAgent.match(/(iPad).*OS\s([\d_]+)/),navigator.userAgent.match(/(iPod)(.*OS\s([\d_]+))?/),!navigator.userAgent.match(/(iPad).*OS\s([\d_]+)/)&&navigator.userAgent.match(/(iPhone\sOS)\s([\d_]+)/),0<=navigator.userAgent.toLowerCase().indexOf("safari")&&navigator.userAgent.toLowerCase().indexOf("chrome")<0&&navigator.userAgent.toLowerCase().indexOf("android"),/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(navigator.userAgent);var n=!!("ontouchstart"in window),s=!!("PointerEvent"in window),r=n||window.DocumentTouch&&document instanceof DocumentTouch||navigator.maxTouchPoints,o=r&&s?"pointerenter":"mouseenter",a=r&&s?"pointerleave":"mouseleave"},function(t,e,i){"use strict";var n=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var s=Symbol("onResize"),r=function(){function e(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this.slider=t,this.options=t.options,this[s]=this[s].bind(this),this._bindEvents()}return n(e,[{key:"init",value:function(){return this._defaultBreakpoint={slidesToShow:this.options.slidesToShow,slidesToScroll:this.options.slidesToScroll},this.options.breakpoints.sort(function(t,e){return parseInt(t.changePoint,10)>parseInt(e.changePoint,10)}),this._currentBreakpoint=this._getActiveBreakpoint(),this}},{key:"destroy",value:function(){this._unbindEvents()}},{key:"_bindEvents",value:function(){window.addEventListener("resize",this[s]),window.addEventListener("orientationchange",this[s])}},{key:"_unbindEvents",value:function(){window.removeEventListener("resize",this[s]),window.removeEventListener("orientationchange",this[s])}},{key:"_getActiveBreakpoint",value:function(){var t=!0,e=!1,i=void 0;try{for(var n,s=this.options.breakpoints[Symbol.iterator]();!(t=(n=s.next()).done);t=!0){var r=n.value;if(r.changePoint>=window.innerWidth)return r}}catch(t){e=!0,i=t}finally{try{!t&&s.return&&s.return()}finally{if(e)throw i}}return this._defaultBreakpoint}},{key:"getSlidesToShow",value:function(){return this._currentBreakpoint?this._currentBreakpoint.slidesToShow:this._defaultBreakpoint.slidesToShow}},{key:"getSlidesToScroll",value:function(){return this._currentBreakpoint?this._currentBreakpoint.slidesToScroll:this._defaultBreakpoint.slidesToScroll}},{key:"apply",value:function(){this.slider.state.index>=this.slider.state.length&&0!==this.slider.state.index&&(this.slider.state.index=this.slider.state.index-this._currentBreakpoint.slidesToScroll),this.slider.state.length<=this._currentBreakpoint.slidesToShow&&(this.slider.state.index=0),this.options.loop&&this.slider._loop.init().apply(),this.options.infinite&&this.slider._infinite.init().apply(),this.slider._setDimensions(),this.slider._transitioner.init().apply(!0,this.slider._setHeight.bind(this.slider)),this.slider._setClasses(),this.slider._navigation.refresh(),this.slider._pagination.refresh()}},{key:s,value:function(t){var e=this._getActiveBreakpoint();e.slidesToShow!==this._currentBreakpoint.slidesToShow&&(this._currentBreakpoint=e,this.apply())}}]),e}();e.a=r},function(t,e,i){"use strict";var n=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var s=function(){function e(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this.slider=t}return n(e,[{key:"init",value:function(){if(this.slider.options.infinite&&"translate"===this.slider.options.effect){this.slider.options.centerMode?this._infiniteCount=Math.ceil(this.slider.slidesToShow+this.slider.slidesToShow/2):this._infiniteCount=this.slider.slidesToShow;for(var t=[],e=0,i=this.slider.state.length;i>this.slider.state.length-1-this._infiniteCount;i-=1)e=i-1,t.unshift(this._cloneSlide(this.slider.slides[e],e-this.slider.state.length));for(var n=[],s=0;s<this._infiniteCount+this.slider.state.length;s+=1)n.push(this._cloneSlide(this.slider.slides[s%this.slider.state.length],s+this.slider.state.length));this.slider.slides=[].concat(t,function(t){if(Array.isArray(t)){for(var e=0,i=Array(t.length);e<t.length;e++)i[e]=t[e];return i}return Array.from(t)}(this.slider.slides),n)}return this}},{key:"apply",value:function(){}},{key:"onTransitionEnd",value:function(t){this.slider.options.infinite&&(this.slider.state.next>=this.slider.state.length?(this.slider.state.index=this.slider.state.next=this.slider.state.next-this.slider.state.length,this.slider.transitioner.apply(!0)):this.slider.state.next<0&&(this.slider.state.index=this.slider.state.next=this.slider.state.length+this.slider.state.next,this.slider.transitioner.apply(!0)))}},{key:"_cloneSlide",value:function(t,e){var i=t.cloneNode(!0);return i.dataset.sliderIndex=e,i.dataset.cloned=!0,(i.querySelectorAll("[id]")||[]).forEach(function(t){t.setAttribute("id","")}),i}}]),e}();e.a=s},function(t,e,i){"use strict";var n=i(12),s=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var r=function(){function e(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this.slider=t}return s(e,[{key:"init",value:function(){return this}},{key:"apply",value:function(){this.slider.options.loop&&(0<this.slider.state.next?this.slider.state.next<this.slider.state.length?this.slider.state.next>this.slider.state.length-this.slider.slidesToShow&&Object(n.a)(this.slider._slides[this.slider.state.length-1],this.slider.wrapper)?this.slider.state.next=0:this.slider.state.next=Math.min(Math.max(this.slider.state.next,0),this.slider.state.length-this.slider.slidesToShow):this.slider.state.next=0:this.slider.state.next<=0-this.slider.slidesToScroll?this.slider.state.next=this.slider.state.length-this.slider.slidesToShow:this.slider.state.next=0)}}]),e}();e.a=r},function(t,e,i){"use strict";i.d(e,"a",function(){return n});var n=function(t,e){var i=t.getBoundingClientRect();return e=e||document.documentElement,0<=i.top&&0<=i.left&&i.bottom<=(window.innerHeight||e.clientHeight)&&i.right<=(window.innerWidth||e.clientWidth)}},function(t,e,i){"use strict";var n=i(14),s=i(1),r=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var o=function(){function e(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this.slider=t,this._clickEvents=["click","touch"],this._supportsPassive=Object(s.a)(),this.onPreviousClick=this.onPreviousClick.bind(this),this.onNextClick=this.onNextClick.bind(this),this.onKeyUp=this.onKeyUp.bind(this)}return r(e,[{key:"init",value:function(){return this.node=document.createRange().createContextualFragment(Object(n.a)(this.slider.options.icons)),this._ui={previous:this.node.querySelector(".slider-navigation-previous"),next:this.node.querySelector(".slider-navigation-next")},this._unbindEvents(),this._bindEvents(),this.refresh(),this}},{key:"destroy",value:function(){this._unbindEvents()}},{key:"_bindEvents",value:function(){var e=this;this.slider.wrapper.addEventListener("keyup",this.onKeyUp),this._clickEvents.forEach(function(t){e._ui.previous.addEventListener(t,e.onPreviousClick),e._ui.next.addEventListener(t,e.onNextClick)})}},{key:"_unbindEvents",value:function(){var e=this;this.slider.wrapper.removeEventListener("keyup",this.onKeyUp),this._clickEvents.forEach(function(t){e._ui.previous.removeEventListener(t,e.onPreviousClick),e._ui.next.removeEventListener(t,e.onNextClick)})}},{key:"onNextClick",value:function(t){this._supportsPassive||t.preventDefault(),this.slider.options.navigation&&this.slider.next()}},{key:"onPreviousClick",value:function(t){this._supportsPassive||t.preventDefault(),this.slider.options.navigation&&this.slider.previous()}},{key:"onKeyUp",value:function(t){this.slider.options.keyNavigation&&("ArrowRight"===t.key||"Right"===t.key?this.slider.next():"ArrowLeft"!==t.key&&"Left"!==t.key||this.slider.previous())}},{key:"refresh",value:function(){this.slider.options.loop||this.slider.options.infinite||(this.slider.options.navigation&&this.slider.state.length>this.slider.slidesToShow?(this._ui.previous.classList.remove("is-hidden"),this._ui.next.classList.remove("is-hidden"),0===this.slider.state.next?(this._ui.previous.classList.add("is-hidden"),this._ui.next.classList.remove("is-hidden")):this.slider.state.next>=this.slider.state.length-this.slider.slidesToShow&&!this.slider.options.centerMode?(this._ui.previous.classList.remove("is-hidden"),this._ui.next.classList.add("is-hidden")):this.slider.state.next>=this.slider.state.length-1&&this.slider.options.centerMode&&(this._ui.previous.classList.remove("is-hidden"),this._ui.next.classList.add("is-hidden"))):(this._ui.previous.classList.add("is-hidden"),this._ui.next.classList.add("is-hidden")))}},{key:"render",value:function(){return this.node}}]),e}();e.a=o},function(t,e,i){"use strict";e.a=function(t){return'<div class="slider-navigation-previous">'+t.previous+'</div>\n<div class="slider-navigation-next">'+t.next+"</div>"}},function(t,e,i){"use strict";var n=i(16),s=i(17),r=i(1),o=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var a=function(){function e(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this.slider=t,this._clickEvents=["click","touch"],this._supportsPassive=Object(r.a)(),this.onPageClick=this.onPageClick.bind(this),this.onResize=this.onResize.bind(this)}return o(e,[{key:"init",value:function(){return this._pages=[],this.node=document.createRange().createContextualFragment(Object(n.a)()),this._ui={container:this.node.firstChild},this._count=Math.ceil((this.slider.state.length-this.slider.slidesToShow)/this.slider.slidesToScroll),this._draw(),this.refresh(),this}},{key:"destroy",value:function(){this._unbindEvents()}},{key:"_bindEvents",value:function(){var i=this;window.addEventListener("resize",this.onResize),window.addEventListener("orientationchange",this.onResize),this._clickEvents.forEach(function(e){i._pages.forEach(function(t){return t.addEventListener(e,i.onPageClick)})})}},{key:"_unbindEvents",value:function(){var i=this;window.removeEventListener("resize",this.onResize),window.removeEventListener("orientationchange",this.onResize),this._clickEvents.forEach(function(e){i._pages.forEach(function(t){return t.removeEventListener(e,i.onPageClick)})})}},{key:"_draw",value:function(){if(this._ui.container.innerHTML="",this.slider.options.pagination&&this.slider.state.length>this.slider.slidesToShow){for(var t=0;t<=this._count;t++){var e=document.createRange().createContextualFragment(Object(s.a)()).firstChild;e.dataset.index=t*this.slider.slidesToScroll,this._pages.push(e),this._ui.container.appendChild(e)}this._bindEvents()}}},{key:"onPageClick",value:function(t){this._supportsPassive||t.preventDefault(),this.slider.state.next=t.currentTarget.dataset.index,this.slider.show()}},{key:"onResize",value:function(){this._draw()}},{key:"refresh",value:function(){var e=this,t=void 0;(t=this.slider.options.infinite?Math.ceil(this.slider.state.length-1/this.slider.slidesToScroll):Math.ceil((this.slider.state.length-this.slider.slidesToShow)/this.slider.slidesToScroll))!==this._count&&(this._count=t,this._draw()),this._pages.forEach(function(t){t.classList.remove("is-active"),parseInt(t.dataset.index,10)===e.slider.state.next%e.slider.state.length&&t.classList.add("is-active")})}},{key:"render",value:function(){return this.node}}]),e}();e.a=a},function(t,e,i){"use strict";e.a=function(){return'<div class="slider-pagination"></div>'}},function(t,e,i){"use strict";e.a=function(){return'<div class="slider-page"></div>'}},function(t,e,i){"use strict";var n=i(4),s=i(1),r=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var o=function(){function e(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this.slider=t,this._supportsPassive=Object(s.a)(),this.onStartDrag=this.onStartDrag.bind(this),this.onMoveDrag=this.onMoveDrag.bind(this),this.onStopDrag=this.onStopDrag.bind(this),this._init()}return r(e,[{key:"_init",value:function(){}},{key:"bindEvents",value:function(){var e=this;this.slider.container.addEventListener("dragstart",function(t){e._supportsPassive||t.preventDefault()}),this.slider.container.addEventListener("mousedown",this.onStartDrag),this.slider.container.addEventListener("touchstart",this.onStartDrag),window.addEventListener("mousemove",this.onMoveDrag),window.addEventListener("touchmove",this.onMoveDrag),window.addEventListener("mouseup",this.onStopDrag),window.addEventListener("touchend",this.onStopDrag),window.addEventListener("touchcancel",this.onStopDrag)}},{key:"unbindEvents",value:function(){var e=this;this.slider.container.removeEventListener("dragstart",function(t){e._supportsPassive||t.preventDefault()}),this.slider.container.removeEventListener("mousedown",this.onStartDrag),this.slider.container.removeEventListener("touchstart",this.onStartDrag),window.removeEventListener("mousemove",this.onMoveDrag),window.removeEventListener("touchmove",this.onMoveDrag),window.removeEventListener("mouseup",this.onStopDrag),window.removeEventListener("mouseup",this.onStopDrag),window.removeEventListener("touchcancel",this.onStopDrag)}},{key:"onStartDrag",value:function(t){if(t.touches){if(1<t.touches.length)return;t=t.touches[0]}this._origin=new n.a(t.screenX,t.screenY),this.width=this.slider.wrapperWidth,this.slider.transitioner.disable()}},{key:"onMoveDrag",value:function(t){if(this._origin){var e=t.touches?t.touches[0]:t;this._lastTranslate=new n.a(e.screenX-this._origin.x,e.screenY-this._origin.y),t.touches&&Math.abs(this._lastTranslate.x)>Math.abs(this._lastTranslate.y)&&(this._supportsPassive||t.preventDefault(),t.stopPropagation())}}},{key:"onStopDrag",value:function(t){this._origin&&this._lastTranslate&&(Math.abs(this._lastTranslate.x)>.2*this.width?this._lastTranslate.x<0?this.slider.next():this.slider.previous():this.slider.show(!0)),this._origin=null,this._lastTranslate=null}}]),e}();e.a=o},function(t,e,i){"use strict";var n=i(20),s=i(21),r=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var o=function(){function e(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this.slider=t,this.options=t.options,this._animating=!1,this._animation=void 0,this._translate=new s.a(this,t,t.options),this._fade=new n.a(this,t,t.options)}return r(e,[{key:"init",value:function(){return this._fade.init(),this._translate.init(),this}},{key:"isAnimating",value:function(){return this._animating}},{key:"enable",value:function(){this._animation&&this._animation.enable()}},{key:"disable",value:function(){this._animation&&this._animation.disable()}},{key:"apply",value:function(t,e){if(!this._animating||t){switch(this.options.effect){case"fade":this._animation=this._fade;break;case"translate":default:this._animation=this._translate}this._animationCallback=e,t?this._animation&&this._animation.disable():(this._animation&&this._animation.enable(),this._animating=!0),this._animation&&this._animation.apply(),t&&this.end()}}},{key:"end",value:function(){this._animating=!1,this._animation=void 0,this.slider.state.index=this.slider.state.next,this._animationCallback&&this._animationCallback()}}]),e}();e.a=o},function(t,e,i){"use strict";var s=i(0),r=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var i=arguments[e];for(var n in i)Object.prototype.hasOwnProperty.call(i,n)&&(t[n]=i[n])}return t},o=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var n=function(){function n(t,e){var i=2<arguments.length&&void 0!==arguments[2]?arguments[2]:{};!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,n),this.transitioner=t,this.slider=e,this.options=r({},i)}return o(n,[{key:"init",value:function(){var i=this;return"fade"===this.options.effect&&this.slider.slides.forEach(function(t,e){Object(s.a)(t,{position:"absolute",left:0,top:0,bottom:0,"z-index":t.dataset.sliderIndex==i.slider.state.index?0:-2,opacity:t.dataset.sliderIndex==i.slider.state.index?1:0})}),this}},{key:"enable",value:function(){var e=this;this._oldSlide=this.slider.slides.filter(function(t){return t.dataset.sliderIndex==e.slider.state.index})[0],this._newSlide=this.slider.slides.filter(function(t){return t.dataset.sliderIndex==e.slider.state.next})[0],this._newSlide&&(this._newSlide.addEventListener("transitionend",this.onTransitionEnd.bind(this)),this._newSlide.style.transition=this.options.duration+"ms "+this.options.timing,this._oldSlide&&(this._oldSlide.addEventListener("transitionend",this.onTransitionEnd.bind(this)),this._oldSlide.style.transition=this.options.duration+"ms "+this.options.timing))}},{key:"disable",value:function(){var e=this;this._oldSlide=this.slider.slides.filter(function(t){return t.dataset.sliderIndex==e.slider.state.index})[0],this._newSlide=this.slider.slides.filter(function(t){return t.dataset.sliderIndex==e.slider.state.next})[0],this._newSlide&&(this._newSlide.removeEventListener("transitionend",this.onTransitionEnd.bind(this)),this._newSlide.style.transition="none",this._oldSlide&&(this._oldSlide.removeEventListener("transitionend",this.onTransitionEnd.bind(this)),this._oldSlide.style.transition="none"))}},{key:"apply",value:function(t){var e=this;this._oldSlide=this.slider.slides.filter(function(t){return t.dataset.sliderIndex==e.slider.state.index})[0],this._newSlide=this.slider.slides.filter(function(t){return t.dataset.sliderIndex==e.slider.state.next})[0],this._oldSlide&&this._newSlide&&(Object(s.a)(this._oldSlide,{opacity:0}),Object(s.a)(this._newSlide,{opacity:1,"z-index":t?0:-1}))}},{key:"onTransitionEnd",value:function(t){"fade"===this.options.effect&&(this.transitioner.isAnimating()&&t.target==this._newSlide&&(this._newSlide&&(Object(s.a)(this._newSlide,{"z-index":0}),this._newSlide.removeEventListener("transitionend",this.onTransitionEnd.bind(this))),this._oldSlide&&(Object(s.a)(this._oldSlide,{"z-index":-2}),this._oldSlide.removeEventListener("transitionend",this.onTransitionEnd.bind(this)))),this.transitioner.end())}}]),n}();e.a=n},function(t,e,i){"use strict";var r=i(4),o=i(0),s=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var i=arguments[e];for(var n in i)Object.prototype.hasOwnProperty.call(i,n)&&(t[n]=i[n])}return t},a=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var n=function(){function n(t,e){var i=2<arguments.length&&void 0!==arguments[2]?arguments[2]:{};!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,n),this.transitioner=t,this.slider=e,this.options=s({},i),this.onTransitionEnd=this.onTransitionEnd.bind(this)}return a(n,[{key:"init",value:function(){return this._position=new r.a(this.slider.container.offsetLeft,this.slider.container.offsetTop),this._bindEvents(),this}},{key:"destroy",value:function(){this._unbindEvents()}},{key:"_bindEvents",value:function(){this.slider.container.addEventListener("transitionend",this.onTransitionEnd)}},{key:"_unbindEvents",value:function(){this.slider.container.removeEventListener("transitionend",this.onTransitionEnd)}},{key:"enable",value:function(){this.slider.container.style.transition=this.options.duration+"ms "+this.options.timing}},{key:"disable",value:function(){this.slider.container.style.transition="none"}},{key:"apply",value:function(){var e=this,t=void 0;if("translate"===this.options.effect){var i=this.slider.slides.filter(function(t){return t.dataset.sliderIndex==e.slider.state.next})[0],n=new r.a(i.offsetLeft,i.offsetTop);t=this.options.centerMode?new r.a(Math.round(Object(o.e)(this.slider.container)),Math.round(Object(o.b)(this.slider.container))):new r.a(Math.round(Object(o.e)(this.slider.container)-Object(o.e)(this.slider.wrapper)),Math.round(Object(o.b)(this.slider.container)-Object(o.b)(this.slider.wrapper)));var s=new r.a(Math.min(Math.max(-1*n.x,-1*t.x),0),Math.min(Math.max(-1*n.y,-1*t.y),0));this.options.loop&&(!this.options.vertical&&Math.abs(this._position.x)>t.x?(s.x=0,this.slider.state.next=0):this.options.vertical&&Math.abs(this._position.y)>t.y&&(s.y=0,this.slider.state.next=0)),this._position.x=s.x,this._position.y=s.y,this.options.centerMode&&(this._position.x=this._position.x+this.slider.wrapperWidth/2-Object(o.e)(i)/2),"rtl"===this.slider.direction&&(this._position.x=-this._position.x,this._position.y=-this._position.y),this.slider.container.style.transform="translate3d("+this._position.x+"px, "+this._position.y+"px, 0)",n.x>t.x&&this.slider.transitioner.end()}}},{key:"onTransitionEnd",value:function(t){"translate"===this.options.effect&&(this.transitioner.isAnimating()&&t.target==this.slider.container&&this.options.infinite&&this.slider._infinite.onTransitionEnd(t),this.transitioner.end())}}]),n}();e.a=n},function(t,e,i){"use strict";e.a={initialSlide:0,slidesToScroll:1,slidesToShow:1,navigation:!0,navigationKeys:!0,navigationSwipe:!0,pagination:!0,loop:!1,infinite:!1,effect:"translate",duration:300,timing:"ease",autoplay:!1,autoplaySpeed:3e3,pauseOnHover:!0,breakpoints:[{changePoint:480,slidesToShow:1,slidesToScroll:1},{changePoint:640,slidesToShow:2,slidesToScroll:2},{changePoint:768,slidesToShow:3,slidesToScroll:3}],onReady:null,icons:{previous:'<svg viewBox="0 0 50 80" xml:space="preserve">\n <polyline fill="currentColor" stroke-width=".5em" stroke-linecap="round" stroke-linejoin="round" points="45.63,75.8 0.375,38.087 45.63,0.375 "/>\n </svg>',next:'<svg viewBox="0 0 50 80" xml:space="preserve">\n <polyline fill="currentColor" stroke-width=".5em" stroke-linecap="round" stroke-linejoin="round" points="0.375,0.375 45.63,38.087 0.375,75.8 "/>\n </svg>'}}},function(t,e,i){"use strict";e.a=function(t){return'<div id="'+t+'" class="slider" tabindex="0">\n <div class="slider-container"></div>\n </div>'}},function(t,e,i){"use strict";e.a=function(){return'<div class="slider-item"></div>'}}]).default}); | ||
| !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.bulmaCarousel=e():t.bulmaCarousel=e()}("undefined"!=typeof self?self:this,function(){return function(i){var n={};function s(t){if(n[t])return n[t].exports;var e=n[t]={i:t,l:!1,exports:{}};return i[t].call(e.exports,e,e.exports,s),e.l=!0,e.exports}return s.m=i,s.c=n,s.d=function(t,e,i){s.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:i})},s.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return s.d(e,"a",e),e},s.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},s.p="",s(s.s=5)}([function(t,e,i){"use strict";i.d(e,"d",function(){return s}),i.d(e,"e",function(){return r}),i.d(e,"b",function(){return o}),i.d(e,"c",function(){return a}),i.d(e,"a",function(){return l});var n=i(2),s=function(e,t){(t=Array.isArray(t)?t:t.split(" ")).forEach(function(t){e.classList.remove(t)})},r=function(t){return t.getBoundingClientRect().width||t.offsetWidth},o=function(t){return t.getBoundingClientRect().height||t.offsetHeight},a=function(t){var e=1<arguments.length&&void 0!==arguments[1]&&arguments[1],i=t.offsetHeight;if(e){var n=window.getComputedStyle(t);i+=parseInt(n.marginTop)+parseInt(n.marginBottom)}return i},l=function(t,e){if(!e)return window.getComputedStyle(t);if(Object(n.b)(e)){var i="";Object.keys(e).forEach(function(t){i+=t+": "+e[t]+";"}),t.style.cssText+=i}}},function(t,e,i){"use strict";e.a=function(){var t=!1;try{var e=Object.defineProperty({},"passive",{get:function(){t=!0}});window.addEventListener("testPassive",null,e),window.removeEventListener("testPassive",null,e)}catch(t){}return t}},function(t,e,i){"use strict";i.d(e,"a",function(){return s}),i.d(e,"c",function(){return r}),i.d(e,"b",function(){return o});var n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},s=function(t){return"function"==typeof t},r=function(t){return"string"==typeof t||!!t&&"object"===(void 0===t?"undefined":n(t))&&"[object String]"===Object.prototype.toString.call(t)},o=function(t){return("function"==typeof t||"object"===(void 0===t?"undefined":n(t))&&!!t)&&!Array.isArray(t)}},function(t,e,i){"use strict";var n=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var s=function(){function e(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:[];!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this.events=new Map(t)}return n(e,[{key:"on",value:function(t,e){var i=this;return this.events.set(t,[].concat(function(t){if(Array.isArray(t)){for(var e=0,i=Array(t.length);e<t.length;e++)i[e]=t[e];return i}return Array.from(t)}(this.events.has(t)?this.events.get(t):[]),[e])),function(){return i.events.set(t,i.events.get(t).filter(function(t){return t!==e}))}}},{key:"emit",value:function(t){for(var e=arguments.length,i=Array(1<e?e-1:0),n=1;n<e;n++)i[n-1]=arguments[n];return this.events.has(t)&&this.events.get(t).map(function(t){return t.apply(void 0,i)})}}]),e}();e.a=s},function(t,e,i){"use strict";var n=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var s=function(){function s(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:0,e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:0;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,s),this._x=t,this._y=e}return n(s,[{key:"add",value:function(t){return new s(this._x+t._x,this._y+t._y)}},{key:"sub",value:function(t){return new s(this._x-t._x,this._y-t._y)}},{key:"distance",value:function(t){var e=this._x-t._x,i=this._y-t._y;return Math.sqrt(Math.pow(e,2)+Math.pow(i,2))}},{key:"max",value:function(t){return new s(Math.max(this._x,t._x),Math.max(this._y,t._y))}},{key:"equals",value:function(t){return this==t||!(!t||null==t)&&(this._x==t._x&&this._y==t._y)}},{key:"inside",value:function(t,e){return this._x>=t._x&&this._x<=e._x&&this._y>=t._y&&this._y<=e._y}},{key:"constrain",value:function(t,e){if(t._x>e._x||t._y>e._y)return this;var i=this._x,n=this._y;return null!==t._x&&(i=Math.max(i,t._x)),null!==e._x&&(i=Math.min(i,e._x)),null!==t._y&&(n=Math.max(n,t._y)),null!==e._y&&(n=Math.min(n,e._y)),new s(i,n)}},{key:"reposition",value:function(t){t.style.top=this._y+"px",t.style.left=this._x+"px"}},{key:"toString",value:function(){return"("+this._x+","+this._y+")"}},{key:"x",get:function(){return this._x},set:function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:0;return this._x=t,this}},{key:"y",get:function(){return this._y},set:function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:0;return this._y=t,this}}]),s}();e.a=s},function(t,e,i){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var n=i(6),s=i(0),a=i(2),r=i(3),l=i(7),h=i(9),u=i(10),d=i(11),c=i(13),f=i(15),p=i(18),v=i(19),y=i(22),_=i(23),g=i(24),b=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var i=arguments[e];for(var n in i)Object.prototype.hasOwnProperty.call(i,n)&&(t[n]=i[n])}return t},w=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var o=function(t){function o(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{};!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,o);var r=function(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}(this,(o.__proto__||Object.getPrototypeOf(o)).call(this));if(r.element=Object(a.c)(t)?document.querySelector(t):t,!r.element)throw new Error("An invalid selector or non-DOM node has been provided.");r._clickEvents=["click","touch"];var i=r.element.dataset?Object.keys(r.element.dataset).filter(function(t){return Object.keys(y.a).includes(t)}).reduce(function(t,e){return b({},t,(i={},n=e,s=r.element.dataset[e],n in i?Object.defineProperty(i,n,{value:s,enumerable:!0,configurable:!0,writable:!0}):i[n]=s,i));var i,n,s},{}):{};return r.options=b({},y.a,e,i),r._id=Object(n.a)("slider"),r.onShow=r.onShow.bind(r),r._init(),r}return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}(o,r["a"]),w(o,[{key:"_init",value:function(){return this._items=Array.from(this.element.children),this._breakpoint=new h.a(this),this._autoplay=new l.a(this),this._navigation=new c.a(this),this._pagination=new f.a(this),this._infinite=new u.a(this),this._loop=new d.a(this),this._swipe=new p.a(this),this._build(),Object(a.a)(this.options.onReady)&&this.options.onReady(this),this}},{key:"_build",value:function(){var i=this;this.node=document.createRange().createContextualFragment(Object(_.a)(this.id)),this._ui={wrapper:this.node.firstChild,container:this.node.querySelector(".slider-container")},this.element.appendChild(this.node),this._ui.wrapper.classList.add("is-loading"),this._ui.container.style.opacity=0,this._transitioner=new v.a(this),this._slides=this._items.map(function(t,e){return i._createSlide(t,e)}),this.reset(),this._bindEvents(),this._ui.container.style.opacity=1,this._ui.wrapper.classList.remove("is-loading")}},{key:"_bindEvents",value:function(){this.on("show",this.onShow)}},{key:"_unbindEvents",value:function(){this.off("show",this.onShow)}},{key:"_createSlide",value:function(t,e){var i=document.createRange().createContextualFragment(Object(g.a)()).firstChild;return i.dataset.sliderIndex=e,i.appendChild(t),i}},{key:"_setDimensions",value:function(){var e=this;this.options.vertical?(this._ui.wrapper.style.height=Object(s.c)(this._slides[0])*this.slidesToShow,this.options.centerMode&&(this._ui.wrapper.style.padding=this.options.centerPadding+" 0px")):this.options.centerMode&&(this._ui.wrapper.style.padding="0px "+this.options.centerPadding),this._wrapperWidth=Object(s.e)(this._ui.wrapper),this._wrapperHeight=Object(s.c)(this._ui.wrapper),this.options.vertical?(this._slideWidth=Math.ceil(this._wrapperWidth),this._containerHeight=Math.ceil(Object(s.c)(this._slides[0])*this._slides.length),this._ui.container.style.height=this._containerHeight+"px"):(this._slideWidth=Math.ceil(this._wrapperWidth/this.slidesToShow),this._containerWidth=Math.ceil(this._slideWidth*this._slides.length),this._ui.container.style.width=this._containerWidth+"px"),this._slides.forEach(function(t){t.style.width=e._slideWidth+"px"})}},{key:"_setHeight",value:function(){"translate"!==this.options.effect&&(this._ui.container.style.height=Object(s.c)(this._slides[this.state.index])+"px")}},{key:"_setClasses",value:function(){var e=this;this._slides.forEach(function(t){Object(s.d)(t,"is-active is-current is-slide-previous is-slide-next"),Math.abs((e.state.index-1)%e.state.length)===parseInt(t.dataset.sliderIndex,10)&&t.classList.add("is-slide-previous"),Math.abs(e.state.index%e.state.length)===parseInt(t.dataset.sliderIndex,10)&&t.classList.add("is-current"),Math.abs((e.state.index+1)%e.state.length)===parseInt(t.dataset.sliderIndex,10)&&t.classList.add("is-slide-next")})}},{key:"onShow",value:function(t){this._navigation.refresh(),this._pagination.refresh(),this._setClasses()}},{key:"next",value:function(){!this.options.loop&&!this.options.infinite&&this.state.index+this.slidesToScroll>this.state.length-this.slidesToShow&&!this.options.centerMode?this.state.next=this.state.index:this.state.next=this.state.index+this.slidesToScroll,this.show()}},{key:"previous",value:function(){this.options.loop||this.options.infinite||0!==this.state.index?this.state.next=this.state.index-this.slidesToScroll:this.state.next=this.state.index,this.show()}},{key:"start",value:function(){this._autoplay.start()}},{key:"pause",value:function(){this._autoplay.pause()}},{key:"stop",value:function(){this._autoplay.stop()}},{key:"show",value:function(t){var e=1<arguments.length&&void 0!==arguments[1]&&arguments[1];!this.state.length||this.state.length<=this.slidesToShow||("Number"==typeof t&&(this.state.next=t),this.options.loop&&this._loop.apply(),this.options.infinite&&this._infinite.apply(),this.state.index!==this.state.next&&(this.emit("before:show",this.state),this._transitioner.apply(e,this._setHeight.bind(this)),this.emit("after:show",this.state),this.emit("show",this)))}},{key:"reset",value:function(){var e=this;this.state={length:this._items.length,index:Math.abs(this.options.initialSlide),next:Math.abs(this.options.initialSlide),prev:void 0},this.options.loop&&this.options.infinite&&(this.options.loop=!1),this.options.slidesToScroll>this.options.slidesToShow&&(this.options.slidesToScroll=this.slidesToShow),this._breakpoint.init(),this.state.index>=this.state.length&&0!==this.state.index&&(this.state.index=this.state.index-this.slidesToScroll),this.state.length<=this.slidesToShow&&(this.state.index=0),this._ui.wrapper.appendChild(this._navigation.init().render()),this._ui.wrapper.appendChild(this._pagination.init().render()),this.options.navigationSwipe?this._swipe.bindEvents():this._swipe._bindEvents(),this._breakpoint.apply(),this._slides.forEach(function(t){return e._ui.container.appendChild(t)}),this._transitioner.init().apply(!0,this._setHeight.bind(this)),this.options.autoplay&&this._autoplay.init().start()}},{key:"destroy",value:function(){var e=this;this._unbindEvents(),this._items.forEach(function(t){e.element.appendChild(t)}),this.node.remove()}},{key:"id",get:function(){return this._id}},{key:"index",set:function(t){this._index=t},get:function(){return this._index}},{key:"length",set:function(t){this._length=t},get:function(){return this._length}},{key:"slides",get:function(){return this._slides},set:function(t){this._slides=t}},{key:"slidesToScroll",get:function(){return"translate"===this.options.effect?this._breakpoint.getSlidesToScroll():1}},{key:"slidesToShow",get:function(){return"translate"===this.options.effect?this._breakpoint.getSlidesToShow():1}},{key:"direction",get:function(){return"rtl"===this.element.dir.toLowerCase()||"rtl"===this.element.style.direction?"rtl":"ltr"}},{key:"wrapper",get:function(){return this._ui.wrapper}},{key:"wrapperWidth",get:function(){return this._wrapperWidth||0}},{key:"container",get:function(){return this._ui.container}},{key:"containerWidth",get:function(){return this._containerWidth||0}},{key:"slideWidth",get:function(){return this._slideWidth||0}},{key:"transitioner",get:function(){return this._transitioner}}],[{key:"attach",value:function(){var i=this,t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:".slider",n=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},s=new Array,e=Object(a.c)(t)?document.querySelectorAll(t):Array.isArray(t)?t:[t];return[].forEach.call(e,function(t){if(void 0===t[i.constructor.name]){var e=new o(t,n);t[i.constructor.name]=e,s.push(e)}else s.push(t[i.constructor.name])}),s}}]),o}();e.default=o},function(t,e,i){"use strict";i.d(e,"a",function(){return n});var n=function(){return(0<arguments.length&&void 0!==arguments[0]?arguments[0]:"")+([1e7]+-1e3+-4e3+-8e3+-1e11).replace(/[018]/g,function(t){return(t^crypto.getRandomValues(new Uint8Array(1))[0]&15>>t/4).toString(16)})}},function(t,e,i){"use strict";var n=i(3),s=i(8),r=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();Symbol("onVisibilityChange"),Symbol("onMouseEnter"),Symbol("onMouseLeave");var o=function(t){function i(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,i);var e=function(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}(this,(i.__proto__||Object.getPrototypeOf(i)).call(this));return e.slider=t,e.onVisibilityChange=e.onVisibilityChange.bind(e),e.onMouseEnter=e.onMouseEnter.bind(e),e.onMouseLeave=e.onMouseLeave.bind(e),e}return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}(i,n["a"]),r(i,[{key:"init",value:function(){return this._bindEvents(),this}},{key:"_bindEvents",value:function(){document.addEventListener("visibilitychange",this.onVisibilityChange),this.slider.options.pauseOnHover&&(this.slider.container.addEventListener(s.a,this.onMouseEnter),this.slider.container.addEventListener(s.b,this.onMouseLeave))}},{key:"_unbindEvents",value:function(){document.removeEventListener("visibilitychange",this.onVisibilityChange),this.slider.container.removeEventListener(s.a,this.onMouseEnter),this.slider.container.removeEventListener(s.b,this.onMouseLeave)}},{key:"start",value:function(){var t=this;this.stop(),this.slider.options.autoplay&&(this.emit("start",this),this._interval=setInterval(function(){t._hovering&&t.slider.options.pauseOnHover||(!t.slider.options.centerMode&&t.slider.state.next>=t.slider.state.length-t.slider.slidesToShow&&!t.slider.options.loop&&!t.slider.options.infinite?t.stop():t.slider.next())},this.slider.options.autoplaySpeed))}},{key:"stop",value:function(){this._interval=clearInterval(this._interval),this.emit("stop",this)}},{key:"pause",value:function(){var t=this,e=0<arguments.length&&void 0!==arguments[0]?arguments[0]:0;this.paused||(this.timer&&this.stop(),this.paused=!0,0===e?(this.paused=!1,this.start()):this.slider.on("transition:end",function(){t&&(t.paused=!1,t.run?t.start():t.stop())}))}},{key:"onVisibilityChange",value:function(t){document.hidden?this.stop():this.start()}},{key:"onMouseEnter",value:function(t){this._hovering=!0,this.slider.options.pauseOnHover&&this.pause()}},{key:"onMouseLeave",value:function(t){this._hovering=!1,this.slider.options.pauseOnHover&&this.pause()}}]),i}();e.a=o},function(t,e,i){"use strict";i.d(e,"a",function(){return o}),i.d(e,"b",function(){return a});window.navigator.pointerEnabled||window.navigator.msPointerEnabled,window.navigator.msPointerEnabled&&1<window.navigator.msMaxTouchPoints||window.navigator.pointerEnabled&&window.navigator.maxTouchPoints,navigator.userAgent.match(/(Android);?[\s\/]+([\d.]+)?/),navigator.userAgent.match(/(iPad).*OS\s([\d_]+)/),navigator.userAgent.match(/(iPod)(.*OS\s([\d_]+))?/),!navigator.userAgent.match(/(iPad).*OS\s([\d_]+)/)&&navigator.userAgent.match(/(iPhone\sOS)\s([\d_]+)/),0<=navigator.userAgent.toLowerCase().indexOf("safari")&&navigator.userAgent.toLowerCase().indexOf("chrome")<0&&navigator.userAgent.toLowerCase().indexOf("android"),/(iPhone|iPod|iPad).*AppleWebKit(?!.*Safari)/i.test(navigator.userAgent);var n=!!("ontouchstart"in window),s=!!("PointerEvent"in window),r=n||window.DocumentTouch&&document instanceof DocumentTouch||navigator.maxTouchPoints,o=r&&s?"pointerenter":"mouseenter",a=r&&s?"pointerleave":"mouseleave"},function(t,e,i){"use strict";var n=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var s=Symbol("onResize"),r=function(){function e(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this.slider=t,this.options=t.options,this[s]=this[s].bind(this),this._bindEvents()}return n(e,[{key:"init",value:function(){return this._defaultBreakpoint={slidesToShow:this.options.slidesToShow,slidesToScroll:this.options.slidesToScroll},this.options.breakpoints.sort(function(t,e){return parseInt(t.changePoint,10)>parseInt(e.changePoint,10)}),this._currentBreakpoint=this._getActiveBreakpoint(),this}},{key:"destroy",value:function(){this._unbindEvents()}},{key:"_bindEvents",value:function(){window.addEventListener("resize",this[s]),window.addEventListener("orientationchange",this[s])}},{key:"_unbindEvents",value:function(){window.removeEventListener("resize",this[s]),window.removeEventListener("orientationchange",this[s])}},{key:"_getActiveBreakpoint",value:function(){var t=!0,e=!1,i=void 0;try{for(var n,s=this.options.breakpoints[Symbol.iterator]();!(t=(n=s.next()).done);t=!0){var r=n.value;if(r.changePoint>=window.innerWidth)return r}}catch(t){e=!0,i=t}finally{try{!t&&s.return&&s.return()}finally{if(e)throw i}}return this._defaultBreakpoint}},{key:"getSlidesToShow",value:function(){return this._currentBreakpoint?this._currentBreakpoint.slidesToShow:this._defaultBreakpoint.slidesToShow}},{key:"getSlidesToScroll",value:function(){return this._currentBreakpoint?this._currentBreakpoint.slidesToScroll:this._defaultBreakpoint.slidesToScroll}},{key:"apply",value:function(){this.slider.state.index>=this.slider.state.length&&0!==this.slider.state.index&&(this.slider.state.index=this.slider.state.index-this._currentBreakpoint.slidesToScroll),this.slider.state.length<=this._currentBreakpoint.slidesToShow&&(this.slider.state.index=0),this.options.loop&&this.slider._loop.init().apply(),this.options.infinite&&this.slider._infinite.init().apply(),this.slider._setDimensions(),this.slider._transitioner.init().apply(!0,this.slider._setHeight.bind(this.slider)),this.slider._setClasses(),this.slider._navigation.refresh(),this.slider._pagination.refresh()}},{key:s,value:function(t){var e=this._getActiveBreakpoint();e.slidesToShow!==this._currentBreakpoint.slidesToShow&&(this._currentBreakpoint=e,this.apply())}}]),e}();e.a=r},function(t,e,i){"use strict";var n=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var s=function(){function e(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this.slider=t}return n(e,[{key:"init",value:function(){if(this.slider.options.infinite&&"translate"===this.slider.options.effect){this.slider.options.centerMode?this._infiniteCount=Math.ceil(this.slider.slidesToShow+this.slider.slidesToShow/2):this._infiniteCount=this.slider.slidesToShow;for(var t=[],e=0,i=this.slider.state.length;i>this.slider.state.length-1-this._infiniteCount;i-=1)e=i-1,t.unshift(this._cloneSlide(this.slider.slides[e],e-this.slider.state.length));for(var n=[],s=0;s<this._infiniteCount+this.slider.state.length;s+=1)n.push(this._cloneSlide(this.slider.slides[s%this.slider.state.length],s+this.slider.state.length));this.slider.slides=[].concat(t,function(t){if(Array.isArray(t)){for(var e=0,i=Array(t.length);e<t.length;e++)i[e]=t[e];return i}return Array.from(t)}(this.slider.slides),n)}return this}},{key:"apply",value:function(){}},{key:"onTransitionEnd",value:function(t){this.slider.options.infinite&&(this.slider.state.next>=this.slider.state.length?(this.slider.state.index=this.slider.state.next=this.slider.state.next-this.slider.state.length,this.slider.transitioner.apply(!0)):this.slider.state.next<0&&(this.slider.state.index=this.slider.state.next=this.slider.state.length+this.slider.state.next,this.slider.transitioner.apply(!0)))}},{key:"_cloneSlide",value:function(t,e){var i=t.cloneNode(!0);return i.dataset.sliderIndex=e,i.dataset.cloned=!0,(i.querySelectorAll("[id]")||[]).forEach(function(t){t.setAttribute("id","")}),i}}]),e}();e.a=s},function(t,e,i){"use strict";var n=i(12),s=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var r=function(){function e(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this.slider=t}return s(e,[{key:"init",value:function(){return this}},{key:"apply",value:function(){this.slider.options.loop&&(0<this.slider.state.next?this.slider.state.next<this.slider.state.length?this.slider.state.next>this.slider.state.length-this.slider.slidesToShow&&Object(n.a)(this.slider._slides[this.slider.state.length-1],this.slider.wrapper)?this.slider.state.next=0:this.slider.state.next=Math.min(Math.max(this.slider.state.next,0),this.slider.state.length-this.slider.slidesToShow):this.slider.state.next=0:this.slider.state.next<=0-this.slider.slidesToScroll?this.slider.state.next=this.slider.state.length-this.slider.slidesToShow:this.slider.state.next=0)}}]),e}();e.a=r},function(t,e,i){"use strict";i.d(e,"a",function(){return n});var n=function(t,e){var i=t.getBoundingClientRect();return e=e||document.documentElement,0<=i.top&&0<=i.left&&i.bottom<=(window.innerHeight||e.clientHeight)&&i.right<=(window.innerWidth||e.clientWidth)}},function(t,e,i){"use strict";var n=i(14),s=i(1),r=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var o=function(){function e(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this.slider=t,this._clickEvents=["click","touch"],this._supportsPassive=Object(s.a)(),this.onPreviousClick=this.onPreviousClick.bind(this),this.onNextClick=this.onNextClick.bind(this),this.onKeyUp=this.onKeyUp.bind(this)}return r(e,[{key:"init",value:function(){return this.node=document.createRange().createContextualFragment(Object(n.a)(this.slider.options.icons)),this._ui={previous:this.node.querySelector(".slider-navigation-previous"),next:this.node.querySelector(".slider-navigation-next")},this._unbindEvents(),this._bindEvents(),this.refresh(),this}},{key:"destroy",value:function(){this._unbindEvents()}},{key:"_bindEvents",value:function(){var e=this;this.slider.wrapper.addEventListener("keyup",this.onKeyUp),this._clickEvents.forEach(function(t){e._ui.previous.addEventListener(t,e.onPreviousClick),e._ui.next.addEventListener(t,e.onNextClick)})}},{key:"_unbindEvents",value:function(){var e=this;this.slider.wrapper.removeEventListener("keyup",this.onKeyUp),this._clickEvents.forEach(function(t){e._ui.previous.removeEventListener(t,e.onPreviousClick),e._ui.next.removeEventListener(t,e.onNextClick)})}},{key:"onNextClick",value:function(t){this._supportsPassive||t.preventDefault(),this.slider.options.navigation&&this.slider.next()}},{key:"onPreviousClick",value:function(t){this._supportsPassive||t.preventDefault(),this.slider.options.navigation&&this.slider.previous()}},{key:"onKeyUp",value:function(t){this.slider.options.keyNavigation&&("ArrowRight"===t.key||"Right"===t.key?this.slider.next():"ArrowLeft"!==t.key&&"Left"!==t.key||this.slider.previous())}},{key:"refresh",value:function(){this.slider.options.loop||this.slider.options.infinite||(this.slider.options.navigation&&this.slider.state.length>this.slider.slidesToShow?(this._ui.previous.classList.remove("is-hidden"),this._ui.next.classList.remove("is-hidden"),0===this.slider.state.next?(this._ui.previous.classList.add("is-hidden"),this._ui.next.classList.remove("is-hidden")):this.slider.state.next>=this.slider.state.length-this.slider.slidesToShow&&!this.slider.options.centerMode?(this._ui.previous.classList.remove("is-hidden"),this._ui.next.classList.add("is-hidden")):this.slider.state.next>=this.slider.state.length-1&&this.slider.options.centerMode&&(this._ui.previous.classList.remove("is-hidden"),this._ui.next.classList.add("is-hidden"))):(this._ui.previous.classList.add("is-hidden"),this._ui.next.classList.add("is-hidden")))}},{key:"render",value:function(){return this.node}}]),e}();e.a=o},function(t,e,i){"use strict";e.a=function(t){return'<div class="slider-navigation-previous">'+t.previous+'</div>\n<div class="slider-navigation-next">'+t.next+"</div>"}},function(t,e,i){"use strict";var n=i(16),s=i(17),r=i(1),o=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var a=function(){function e(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this.slider=t,this._clickEvents=["click","touch"],this._supportsPassive=Object(r.a)(),this.onPageClick=this.onPageClick.bind(this),this.onResize=this.onResize.bind(this)}return o(e,[{key:"init",value:function(){return this._pages=[],this.node=document.createRange().createContextualFragment(Object(n.a)()),this._ui={container:this.node.firstChild},this._count=Math.ceil((this.slider.state.length-this.slider.slidesToShow)/this.slider.slidesToScroll),this._draw(),this.refresh(),this}},{key:"destroy",value:function(){this._unbindEvents()}},{key:"_bindEvents",value:function(){var i=this;window.addEventListener("resize",this.onResize),window.addEventListener("orientationchange",this.onResize),this._clickEvents.forEach(function(e){i._pages.forEach(function(t){return t.addEventListener(e,i.onPageClick)})})}},{key:"_unbindEvents",value:function(){var i=this;window.removeEventListener("resize",this.onResize),window.removeEventListener("orientationchange",this.onResize),this._clickEvents.forEach(function(e){i._pages.forEach(function(t){return t.removeEventListener(e,i.onPageClick)})})}},{key:"_draw",value:function(){if(this._ui.container.innerHTML="",this.slider.options.pagination&&this.slider.state.length>this.slider.slidesToShow){for(var t=0;t<=this._count;t++){var e=document.createRange().createContextualFragment(Object(s.a)()).firstChild;e.dataset.index=t*this.slider.slidesToScroll,this._pages.push(e),this._ui.container.appendChild(e)}this._bindEvents()}}},{key:"onPageClick",value:function(t){this._supportsPassive||t.preventDefault(),this.slider.state.next=t.currentTarget.dataset.index,this.slider.show()}},{key:"onResize",value:function(){this._draw()}},{key:"refresh",value:function(){var e=this,t=void 0;(t=this.slider.options.infinite?Math.ceil(this.slider.state.length-1/this.slider.slidesToScroll):Math.ceil((this.slider.state.length-this.slider.slidesToShow)/this.slider.slidesToScroll))!==this._count&&(this._count=t,this._draw()),this._pages.forEach(function(t){t.classList.remove("is-active"),parseInt(t.dataset.index,10)===e.slider.state.next%e.slider.state.length&&t.classList.add("is-active")})}},{key:"render",value:function(){return this.node}}]),e}();e.a=a},function(t,e,i){"use strict";e.a=function(){return'<div class="slider-pagination"></div>'}},function(t,e,i){"use strict";e.a=function(){return'<div class="slider-page"></div>'}},function(t,e,i){"use strict";var n=i(4),s=i(1),r=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var o=function(){function e(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this.slider=t,this._supportsPassive=Object(s.a)(),this.onStartDrag=this.onStartDrag.bind(this),this.onMoveDrag=this.onMoveDrag.bind(this),this.onStopDrag=this.onStopDrag.bind(this),this._init()}return r(e,[{key:"_init",value:function(){}},{key:"bindEvents",value:function(){var e=this;this.slider.container.addEventListener("dragstart",function(t){e._supportsPassive||t.preventDefault()}),this.slider.container.addEventListener("mousedown",this.onStartDrag),this.slider.container.addEventListener("touchstart",this.onStartDrag),window.addEventListener("mousemove",this.onMoveDrag),window.addEventListener("touchmove",this.onMoveDrag),window.addEventListener("mouseup",this.onStopDrag),window.addEventListener("touchend",this.onStopDrag),window.addEventListener("touchcancel",this.onStopDrag)}},{key:"unbindEvents",value:function(){var e=this;this.slider.container.removeEventListener("dragstart",function(t){e._supportsPassive||t.preventDefault()}),this.slider.container.removeEventListener("mousedown",this.onStartDrag),this.slider.container.removeEventListener("touchstart",this.onStartDrag),window.removeEventListener("mousemove",this.onMoveDrag),window.removeEventListener("touchmove",this.onMoveDrag),window.removeEventListener("mouseup",this.onStopDrag),window.removeEventListener("mouseup",this.onStopDrag),window.removeEventListener("touchcancel",this.onStopDrag)}},{key:"onStartDrag",value:function(t){if(t.touches){if(1<t.touches.length)return;t=t.touches[0]}this._origin=new n.a(t.screenX,t.screenY),this.width=this.slider.wrapperWidth,this.slider.transitioner.disable()}},{key:"onMoveDrag",value:function(t){if(this._origin){var e=t.touches?t.touches[0]:t;this._lastTranslate=new n.a(e.screenX-this._origin.x,e.screenY-this._origin.y),t.touches&&Math.abs(this._lastTranslate.x)>Math.abs(this._lastTranslate.y)&&(this._supportsPassive||t.preventDefault(),t.stopPropagation())}}},{key:"onStopDrag",value:function(t){this._origin&&this._lastTranslate&&(Math.abs(this._lastTranslate.x)>.2*this.width?this._lastTranslate.x<0?this.slider.next():this.slider.previous():this.slider.show(!0)),this._origin=null,this._lastTranslate=null}}]),e}();e.a=o},function(t,e,i){"use strict";var n=i(20),s=i(21),r=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var o=function(){function e(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this.slider=t,this.options=t.options,this._animating=!1,this._animation=void 0,this._translate=new s.a(this,t,t.options),this._fade=new n.a(this,t,t.options)}return r(e,[{key:"init",value:function(){return this._fade.init(),this._translate.init(),this}},{key:"isAnimating",value:function(){return this._animating}},{key:"enable",value:function(){this._animation&&this._animation.enable()}},{key:"disable",value:function(){this._animation&&this._animation.disable()}},{key:"apply",value:function(t,e){if(!this._animating||t){switch(this.options.effect){case"fade":this._animation=this._fade;break;case"translate":default:this._animation=this._translate}this._animationCallback=e,t?this._animation&&this._animation.disable():(this._animation&&this._animation.enable(),this._animating=!0),this._animation&&this._animation.apply(),t&&this.end()}}},{key:"end",value:function(){this._animating=!1,this._animation=void 0,this.slider.state.index=this.slider.state.next,this._animationCallback&&this._animationCallback()}}]),e}();e.a=o},function(t,e,i){"use strict";var s=i(0),r=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var i=arguments[e];for(var n in i)Object.prototype.hasOwnProperty.call(i,n)&&(t[n]=i[n])}return t},o=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var n=function(){function n(t,e){var i=2<arguments.length&&void 0!==arguments[2]?arguments[2]:{};!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,n),this.transitioner=t,this.slider=e,this.options=r({},i)}return o(n,[{key:"init",value:function(){var i=this;return"fade"===this.options.effect&&this.slider.slides.forEach(function(t,e){Object(s.a)(t,{position:"absolute",left:0,top:0,bottom:0,"z-index":t.dataset.sliderIndex==i.slider.state.index?0:-2,opacity:t.dataset.sliderIndex==i.slider.state.index?1:0})}),this}},{key:"enable",value:function(){var e=this;this._oldSlide=this.slider.slides.filter(function(t){return t.dataset.sliderIndex==e.slider.state.index})[0],this._newSlide=this.slider.slides.filter(function(t){return t.dataset.sliderIndex==e.slider.state.next})[0],this._newSlide&&(this._newSlide.addEventListener("transitionend",this.onTransitionEnd.bind(this)),this._newSlide.style.transition=this.options.duration+"ms "+this.options.timing,this._oldSlide&&(this._oldSlide.addEventListener("transitionend",this.onTransitionEnd.bind(this)),this._oldSlide.style.transition=this.options.duration+"ms "+this.options.timing))}},{key:"disable",value:function(){var e=this;this._oldSlide=this.slider.slides.filter(function(t){return t.dataset.sliderIndex==e.slider.state.index})[0],this._newSlide=this.slider.slides.filter(function(t){return t.dataset.sliderIndex==e.slider.state.next})[0],this._newSlide&&(this._newSlide.removeEventListener("transitionend",this.onTransitionEnd.bind(this)),this._newSlide.style.transition="none",this._oldSlide&&(this._oldSlide.removeEventListener("transitionend",this.onTransitionEnd.bind(this)),this._oldSlide.style.transition="none"))}},{key:"apply",value:function(t){var e=this;this._oldSlide=this.slider.slides.filter(function(t){return t.dataset.sliderIndex==e.slider.state.index})[0],this._newSlide=this.slider.slides.filter(function(t){return t.dataset.sliderIndex==e.slider.state.next})[0],this._oldSlide&&this._newSlide&&(Object(s.a)(this._oldSlide,{opacity:0}),Object(s.a)(this._newSlide,{opacity:1,"z-index":t?0:-1}))}},{key:"onTransitionEnd",value:function(t){"fade"===this.options.effect&&(this.transitioner.isAnimating()&&t.target==this._newSlide&&(this._newSlide&&(Object(s.a)(this._newSlide,{"z-index":0}),this._newSlide.removeEventListener("transitionend",this.onTransitionEnd.bind(this))),this._oldSlide&&(Object(s.a)(this._oldSlide,{"z-index":-2}),this._oldSlide.removeEventListener("transitionend",this.onTransitionEnd.bind(this)))),this.transitioner.end())}}]),n}();e.a=n},function(t,e,i){"use strict";var r=i(4),o=i(0),s=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var i=arguments[e];for(var n in i)Object.prototype.hasOwnProperty.call(i,n)&&(t[n]=i[n])}return t},a=function(){function n(t,e){for(var i=0;i<e.length;i++){var n=e[i];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,n.key,n)}}return function(t,e,i){return e&&n(t.prototype,e),i&&n(t,i),t}}();var n=function(){function n(t,e){var i=2<arguments.length&&void 0!==arguments[2]?arguments[2]:{};!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,n),this.transitioner=t,this.slider=e,this.options=s({},i),this.onTransitionEnd=this.onTransitionEnd.bind(this)}return a(n,[{key:"init",value:function(){return this._position=new r.a(this.slider.container.offsetLeft,this.slider.container.offsetTop),this._bindEvents(),this}},{key:"destroy",value:function(){this._unbindEvents()}},{key:"_bindEvents",value:function(){this.slider.container.addEventListener("transitionend",this.onTransitionEnd)}},{key:"_unbindEvents",value:function(){this.slider.container.removeEventListener("transitionend",this.onTransitionEnd)}},{key:"enable",value:function(){this.slider.container.style.transition=this.options.duration+"ms "+this.options.timing}},{key:"disable",value:function(){this.slider.container.style.transition="none"}},{key:"apply",value:function(){var e=this,t=void 0;if("translate"===this.options.effect){var i=this.slider.slides.filter(function(t){return t.dataset.sliderIndex==e.slider.state.next})[0],n=new r.a(i.offsetLeft,i.offsetTop);t=this.options.centerMode?new r.a(Math.round(Object(o.e)(this.slider.container)),Math.round(Object(o.b)(this.slider.container))):new r.a(Math.round(Object(o.e)(this.slider.container)-Object(o.e)(this.slider.wrapper)),Math.round(Object(o.b)(this.slider.container)-Object(o.b)(this.slider.wrapper)));var s=new r.a(Math.min(Math.max(-1*n.x,-1*t.x),0),Math.min(Math.max(-1*n.y,-1*t.y),0));this.options.loop&&(!this.options.vertical&&Math.abs(this._position.x)>t.x?(s.x=0,this.slider.state.next=0):this.options.vertical&&Math.abs(this._position.y)>t.y&&(s.y=0,this.slider.state.next=0)),this._position.x=s.x,this._position.y=s.y,this.options.centerMode&&(this._position.x=this._position.x+this.slider.wrapperWidth/2-Object(o.e)(i)/2),"rtl"===this.slider.direction&&(this._position.x=-this._position.x,this._position.y=-this._position.y),this.slider.container.style.transform="translate3d("+this._position.x+"px, "+this._position.y+"px, 0)",n.x>t.x&&this.slider.transitioner.end()}}},{key:"onTransitionEnd",value:function(t){"translate"===this.options.effect&&(this.transitioner.isAnimating()&&t.target==this.slider.container&&this.options.infinite&&this.slider._infinite.onTransitionEnd(t),this.transitioner.end())}}]),n}();e.a=n},function(t,e,i){"use strict";e.a={initialSlide:0,slidesToScroll:1,slidesToShow:1,navigation:!0,navigationKeys:!0,navigationSwipe:!0,pagination:!0,loop:!1,infinite:!1,effect:"translate",duration:300,timing:"ease",autoplay:!1,autoplaySpeed:3e3,pauseOnHover:!0,breakpoints:[{changePoint:480,slidesToShow:1,slidesToScroll:1},{changePoint:640,slidesToShow:2,slidesToScroll:2},{changePoint:768,slidesToShow:3,slidesToScroll:3}],onReady:null,icons:{previous:'<svg viewBox="0 0 50 80" xml:space="preserve">\n <polyline fill="currentColor" stroke-width=".5em" stroke-linecap="round" stroke-linejoin="round" points="45.63,75.8 0.375,38.087 45.63,0.375 "/>\n </svg>',next:'<svg viewBox="0 0 50 80" xml:space="preserve">\n <polyline fill="currentColor" stroke-width=".5em" stroke-linecap="round" stroke-linejoin="round" points="0.375,0.375 45.63,38.087 0.375,75.8 "/>\n </svg>'}}},function(t,e,i){"use strict";e.a=function(t){return'<div id="'+t+'" class="slider" tabindex="0">\n <div class="slider-container"></div>\n </div>'}},function(t,e,i){"use strict";e.a=function(){return'<div class="slider-item"></div>'}}]).default}); |
@@ -461,2 +461,2 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
| /******/ ])["default"]; | ||
| }); | ||
| }); |
@@ -1,1 +0,1 @@ | ||
| !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.bulmaSlider=e():t.bulmaSlider=e()}("undefined"!=typeof self?self:this,function(){return function(n){var r={};function i(t){if(r[t])return r[t].exports;var e=r[t]={i:t,l:!1,exports:{}};return n[t].call(e.exports,e,e.exports,i),e.l=!0,e.exports}return i.m=n,i.c=r,i.d=function(t,e,n){i.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:n})},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="",i(i.s=0)}([function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),n.d(e,"isString",function(){return l});var r=n(1),i=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r])}return t},u=function(){function r(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(t,e,n){return e&&r(t.prototype,e),n&&r(t,n),t}}(),o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};var l=function(t){return"string"==typeof t||!!t&&"object"===(void 0===t?"undefined":o(t))&&"[object String]"===Object.prototype.toString.call(t)},a=function(t){function o(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{};!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,o);var n=function(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}(this,(o.__proto__||Object.getPrototypeOf(o)).call(this));if(n.element="string"==typeof t?document.querySelector(t):t,!n.element)throw new Error("An invalid selector or non-DOM node has been provided.");return n._clickEvents=["click"],n.options=i({},e),n.onSliderInput=n.onSliderInput.bind(n),n.init(),n}return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}(o,r["a"]),u(o,[{key:"init",value:function(){if(this._id="bulmaSlider"+(new Date).getTime()+Math.floor(Math.random()*Math.floor(9999)),this.output=this._findOutputForSlider(),this._bindEvents(),this.output&&this.element.classList.contains("has-output-tooltip")){var t=this._getSliderOutputPosition();this.output.style.left=t.position}this.emit("bulmaslider:ready",this.element.value)}},{key:"_findOutputForSlider",value:function(){var e=this,n=null,t=document.getElementsByTagName("output")||[];return Array.from(t).forEach(function(t){if(t.htmlFor==e.element.getAttribute("id"))return n=t,!0}),n}},{key:"_getSliderOutputPosition",value:function(){var t,e=window.getComputedStyle(this.element,null),n=parseInt(e.getPropertyValue("width"),10);t=this.element.getAttribute("min")?this.element.getAttribute("min"):0;var r=(this.element.value-t)/(this.element.getAttribute("max")-t);return{position:(r<0?0:1<r?n:n*r)+"px"}}},{key:"_bindEvents",value:function(){this.output&&this.element.addEventListener("input",this.onSliderInput,!1)}},{key:"onSliderInput",value:function(t){if(t.preventDefault(),this.element.classList.contains("has-output-tooltip")){var e=this._getSliderOutputPosition();this.output.style.left=e.position}var n=this.output.hasAttribute("data-prefix")?this.output.getAttribute("data-prefix"):"",r=this.output.hasAttribute("data-postfix")?this.output.getAttribute("data-postfix"):"";this.output.value=n+this.element.value+r,this.emit("bulmaslider:ready",this.element.value)}}],[{key:"attach",value:function(){var n=this,t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:'input[type="range"].slider',r=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},i=new Array;return(l(t)?document.querySelectorAll(t):Array.isArray(t)?t:[t]).forEach(function(t){if(void 0===t[n.constructor.name]){var e=new o(t,r);t[n.constructor.name]=e,i.push(e)}else i.push(t[n.constructor.name])}),i}}]),o}();e.default=a},function(t,e,n){"use strict";var r=function(){function r(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(t,e,n){return e&&r(t.prototype,e),n&&r(t,n),t}}();var i=function(){function e(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:[];!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this._listeners=new Map(t),this._middlewares=new Map}return r(e,[{key:"listenerCount",value:function(t){return this._listeners.has(t)?this._listeners.get(t).length:0}},{key:"removeListeners",value:function(){var e=this,t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:null,n=1<arguments.length&&void 0!==arguments[1]&&arguments[1];null!==t?Array.isArray(t)?name.forEach(function(t){return e.removeListeners(t,n)}):(this._listeners.delete(t),n&&this.removeMiddleware(t)):this._listeners=new Map}},{key:"middleware",value:function(t,e){var n=this;Array.isArray(t)?name.forEach(function(t){return n.middleware(t,e)}):(Array.isArray(this._middlewares.get(t))||this._middlewares.set(t,[]),this._middlewares.get(t).push(e))}},{key:"removeMiddleware",value:function(){var e=this,t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:null;null!==t?Array.isArray(t)?name.forEach(function(t){return e.removeMiddleware(t)}):this._middlewares.delete(t):this._middlewares=new Map}},{key:"on",value:function(t,e){var n=this,r=2<arguments.length&&void 0!==arguments[2]&&arguments[2];if(Array.isArray(t))t.forEach(function(t){return n.on(t,e)});else{var i=(t=t.toString()).split(/,|, | /);1<i.length?i.forEach(function(t){return n.on(t,e)}):(Array.isArray(this._listeners.get(t))||this._listeners.set(t,[]),this._listeners.get(t).push({once:r,callback:e}))}}},{key:"once",value:function(t,e){this.on(t,e,!0)}},{key:"emit",value:function(n,r){var i=this,o=2<arguments.length&&void 0!==arguments[2]&&arguments[2];n=n.toString();var u=this._listeners.get(n),l=null,a=0,s=o;if(Array.isArray(u))for(u.forEach(function(t,e){o||(l=i._middlewares.get(n),Array.isArray(l)?(l.forEach(function(t){t(r,function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:null;null!==t&&(r=t),a++},n)}),a>=l.length&&(s=!0)):s=!0),s&&(t.once&&(u[e]=null),t.callback(r))});-1!==u.indexOf(null);)u.splice(u.indexOf(null),1)}}]),e}();e.a=i}]).default}); | ||
| !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.bulmaSlider=e():t.bulmaSlider=e()}("undefined"!=typeof self?self:this,function(){return function(n){var r={};function i(t){if(r[t])return r[t].exports;var e=r[t]={i:t,l:!1,exports:{}};return n[t].call(e.exports,e,e.exports,i),e.l=!0,e.exports}return i.m=n,i.c=r,i.d=function(t,e,n){i.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:n})},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},i.p="",i(i.s=0)}([function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),n.d(e,"isString",function(){return l});var r=n(1),i=Object.assign||function(t){for(var e=1;e<arguments.length;e++){var n=arguments[e];for(var r in n)Object.prototype.hasOwnProperty.call(n,r)&&(t[r]=n[r])}return t},u=function(){function r(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(t,e,n){return e&&r(t.prototype,e),n&&r(t,n),t}}(),o="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t};var l=function(t){return"string"==typeof t||!!t&&"object"===(void 0===t?"undefined":o(t))&&"[object String]"===Object.prototype.toString.call(t)},a=function(t){function o(t){var e=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{};!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,o);var n=function(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}(this,(o.__proto__||Object.getPrototypeOf(o)).call(this));if(n.element="string"==typeof t?document.querySelector(t):t,!n.element)throw new Error("An invalid selector or non-DOM node has been provided.");return n._clickEvents=["click"],n.options=i({},e),n.onSliderInput=n.onSliderInput.bind(n),n.init(),n}return function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}(o,r["a"]),u(o,[{key:"init",value:function(){if(this._id="bulmaSlider"+(new Date).getTime()+Math.floor(Math.random()*Math.floor(9999)),this.output=this._findOutputForSlider(),this._bindEvents(),this.output&&this.element.classList.contains("has-output-tooltip")){var t=this._getSliderOutputPosition();this.output.style.left=t.position}this.emit("bulmaslider:ready",this.element.value)}},{key:"_findOutputForSlider",value:function(){var e=this,n=null,t=document.getElementsByTagName("output")||[];return Array.from(t).forEach(function(t){if(t.htmlFor==e.element.getAttribute("id"))return n=t,!0}),n}},{key:"_getSliderOutputPosition",value:function(){var t,e=window.getComputedStyle(this.element,null),n=parseInt(e.getPropertyValue("width"),10);t=this.element.getAttribute("min")?this.element.getAttribute("min"):0;var r=(this.element.value-t)/(this.element.getAttribute("max")-t);return{position:(r<0?0:1<r?n:n*r)+"px"}}},{key:"_bindEvents",value:function(){this.output&&this.element.addEventListener("input",this.onSliderInput,!1)}},{key:"onSliderInput",value:function(t){if(t.preventDefault(),this.element.classList.contains("has-output-tooltip")){var e=this._getSliderOutputPosition();this.output.style.left=e.position}var n=this.output.hasAttribute("data-prefix")?this.output.getAttribute("data-prefix"):"",r=this.output.hasAttribute("data-postfix")?this.output.getAttribute("data-postfix"):"";this.output.value=n+this.element.value+r,this.emit("bulmaslider:ready",this.element.value)}}],[{key:"attach",value:function(){var n=this,t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:'input[type="range"].slider',r=1<arguments.length&&void 0!==arguments[1]?arguments[1]:{},i=new Array;return(l(t)?document.querySelectorAll(t):Array.isArray(t)?t:[t]).forEach(function(t){if(void 0===t[n.constructor.name]){var e=new o(t,r);t[n.constructor.name]=e,i.push(e)}else i.push(t[n.constructor.name])}),i}}]),o}();e.default=a},function(t,e,n){"use strict";var r=function(){function r(t,e){for(var n=0;n<e.length;n++){var r=e[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(t,r.key,r)}}return function(t,e,n){return e&&r(t.prototype,e),n&&r(t,n),t}}();var i=function(){function e(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:[];!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this._listeners=new Map(t),this._middlewares=new Map}return r(e,[{key:"listenerCount",value:function(t){return this._listeners.has(t)?this._listeners.get(t).length:0}},{key:"removeListeners",value:function(){var e=this,t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:null,n=1<arguments.length&&void 0!==arguments[1]&&arguments[1];null!==t?Array.isArray(t)?name.forEach(function(t){return e.removeListeners(t,n)}):(this._listeners.delete(t),n&&this.removeMiddleware(t)):this._listeners=new Map}},{key:"middleware",value:function(t,e){var n=this;Array.isArray(t)?name.forEach(function(t){return n.middleware(t,e)}):(Array.isArray(this._middlewares.get(t))||this._middlewares.set(t,[]),this._middlewares.get(t).push(e))}},{key:"removeMiddleware",value:function(){var e=this,t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:null;null!==t?Array.isArray(t)?name.forEach(function(t){return e.removeMiddleware(t)}):this._middlewares.delete(t):this._middlewares=new Map}},{key:"on",value:function(t,e){var n=this,r=2<arguments.length&&void 0!==arguments[2]&&arguments[2];if(Array.isArray(t))t.forEach(function(t){return n.on(t,e)});else{var i=(t=t.toString()).split(/,|, | /);1<i.length?i.forEach(function(t){return n.on(t,e)}):(Array.isArray(this._listeners.get(t))||this._listeners.set(t,[]),this._listeners.get(t).push({once:r,callback:e}))}}},{key:"once",value:function(t,e){this.on(t,e,!0)}},{key:"emit",value:function(n,r){var i=this,o=2<arguments.length&&void 0!==arguments[2]&&arguments[2];n=n.toString();var u=this._listeners.get(n),l=null,a=0,s=o;if(Array.isArray(u))for(u.forEach(function(t,e){o||(l=i._middlewares.get(n),Array.isArray(l)?(l.forEach(function(t){t(r,function(){var t=0<arguments.length&&void 0!==arguments[0]?arguments[0]:null;null!==t&&(r=t),a++},n)}),a>=l.length&&(s=!0)):s=!0),s&&(t.once&&(u[e]=null),t.callback(r))});-1!==u.indexOf(null);)u.splice(u.indexOf(null),1)}}]),e}();e.a=i}]).default}); |
@@ -18,5 +18,5 @@ window.HELP_IMPROVE_VIDEOJS = false; | ||
| var carousels = bulmaCarousel.attach('.carousel', options); | ||
| bulmaSlider.attach(); | ||
| }) |
+277
-22
@@ -14,6 +14,27 @@ # Tutorial: Using DeepChopper for Nanopore Direct-RNA Sequencing Data Analysis | ||
| - [3. Encoding Data with DeepChopper](#3-encoding-data-with-deepchopper) | ||
| - [Basic Usage](#basic-usage) | ||
| - [For Large Datasets](#for-large-datasets) | ||
| - [Advanced Options](#advanced-options) | ||
| - [Parameter Guide](#parameter-guide) | ||
| - [4. Predicting Adapter to Detect Artificial Chimeric Reads](#4-predicting-adapter-to-detect-artificial-chimeric-reads) | ||
| - [Basic Usage](#basic-usage-1) | ||
| - [Model Selection](#model-selection) | ||
| - [Advanced Options](#advanced-options-1) | ||
| - [For Chunked Data](#for-chunked-data) | ||
| - [Hardware Acceleration](#hardware-acceleration) | ||
| - [5. Chopping Artificial Sequences](#5-chopping-artificial-sequences) | ||
| - [Basic Usage](#basic-usage-2) | ||
| - [For Chunked Predictions](#for-chunked-predictions) | ||
| - [Advanced Options](#advanced-options-2) | ||
| - [Parameter Guide](#parameter-guide-1) | ||
| - [Understanding the Output](#understanding-the-output) | ||
| - [Performance Notes](#performance-notes) | ||
| - [6. Web Interface (Optional)](#6-web-interface-optional) | ||
| - [Next Steps](#next-steps) | ||
| - [Troubleshooting](#troubleshooting) | ||
| - [Memory Issues](#memory-issues) | ||
| - [Performance Issues](#performance-issues) | ||
| - [Model and Results Issues](#model-and-results-issues) | ||
| - [Hardware and Compatibility Issues](#hardware-and-compatibility-issues) | ||
| - [Getting Help](#getting-help) | ||
@@ -46,3 +67,3 @@ ## Prerequisites | ||
| # Install Dorado (if not already installed) | ||
| # Run Dorado without trimming | ||
| # Run Dorado without trimming to preserve all sequences | ||
| dorado basecaller --no-trim rna002_70bps_hac@v3 200cases.pod5 > raw_no_trim.bam | ||
@@ -54,9 +75,10 @@ | ||
| ⚠️ **Important**: Use the `--not_trim` option to preserve potential chimeric sequences. | ||
| Replace `200cases.pod5` with the directory containing your POD5 files. Use `rna002_70bps_hac@v3` for RNA002 kit or `rna004_130bps_hac@v5.0.0` for RNA004 kit. | ||
| Replace `200cases.pod5` with the directory containing your POD5 files. | ||
| The output will be a FASTQ file containing the basecalled sequences. | ||
| The output will be a FASTQ file containing the basecalled sequences with all adapters preserved for DeepChopper analysis. | ||
| **Note**: For convenience, you can download a pre-prepared FASTQ file directly: | ||
| 📝 **Note**: You can also use Dorado WITH trimming (default behavior without `--no-trim`), then apply DeepChopper. Dorado's trimming removes 3' end adapters, and DeepChopper can identify and remove internal adapter regions that Dorado doesn't detect. Both approaches work well with DeepChopper. | ||
| **For convenience**, you can download a pre-prepared FASTQ file for testing: | ||
| ```bash | ||
@@ -70,2 +92,4 @@ wget https://raw.githubusercontent.com/ylab-hi/DeepChopper/refs/heads/main/tests/data/raw_no_trim.fastq | ||
| ### Basic Usage | ||
| ```bash | ||
@@ -76,10 +100,37 @@ # Encode the FASTQ file | ||
| ### For Large Datasets | ||
| For large datasets, use chunking to avoid memory issues: | ||
| ```bash | ||
| deepchopper encode raw_no_trim.fastq --chunk --chunk-size 100000 | ||
| # Use chunking with default chunk size (1,000,000 reads) | ||
| deepchopper encode raw_no_trim.fastq --chunk | ||
| # Specify custom chunk size for better memory control | ||
| deepchopper encode raw_no_trim.fastq --chunk --chunk-size 100000 | ||
| ``` | ||
| 🔍 **Output**: Look for `raw_no_trim.parquet` or multiple `.parquet` files under `raw_no_trim.fq_chunks` if chunking. | ||
| ### Advanced Options | ||
| ```bash | ||
| # Enable verbose output to see progress | ||
| deepchopper encode raw_no_trim.fastq --verbose | ||
| # Combine chunking with verbose output | ||
| deepchopper encode raw_no_trim.fastq --chunk --chunk-size 50000 --verbose | ||
| ``` | ||
| ### Parameter Guide | ||
| - `--chunk, -c`: Enable chunking for large datasets | ||
| - `--chunk-size, -s`: Number of reads per chunk (default: 1,000,000) | ||
| - `--verbose, -v`: Show detailed progress information | ||
| 🔍 **Output**: | ||
| - Without chunking: `raw_no_trim.parquet` | ||
| - With chunking: Multiple `.parquet` files under `raw_no_trim.fq_chunks/` directory | ||
| 💡 **Tip**: Use chunking for datasets with >1M reads to prevent memory issues. | ||
| ## 4. Predicting Adapter to Detect Artificial Chimeric Reads | ||
@@ -89,13 +140,50 @@ | ||
| ### Basic Usage | ||
| ```bash | ||
| # Predict artifical sequences for reads | ||
| # Predict artificial sequences for reads (default: RNA002 model) | ||
| deepchopper predict raw_no_trim.parquet --output predictions | ||
| # Predict artifical sequences for reads using GPU | ||
| # Predict artificial sequences for reads using GPU | ||
| deepchopper predict raw_no_trim.parquet --output predictions --gpus 2 | ||
| ``` | ||
| For chunked data: | ||
| ### Model Selection | ||
| DeepChopper supports different models optimized for different RNA sequencing kits: | ||
| ```bash | ||
| # Use RNA002 model (default - for RNA002 sequencing kit) | ||
| deepchopper predict raw_no_trim.parquet --output predictions --model rna002 | ||
| # Use RNA004 model (for RNA004 sequencing kit) | ||
| deepchopper predict raw_no_trim.parquet --output predictions --model rna004 | ||
| ``` | ||
| 🎯 **Important**: Choose the model that matches your sequencing kit: | ||
| - `rna002`: For data generated with the RNA002 sequencing kit | ||
| - `rna004`: For data generated with the RNA004 sequencing kit (newer version with improved chemistry) | ||
| ### Advanced Options | ||
| ```bash | ||
| # Limit the number of samples to process (useful for testing) | ||
| deepchopper predict raw_no_trim.parquet --output predictions --max-sample 1000 | ||
| # Adjust batch size for memory management | ||
| deepchopper predict raw_no_trim.parquet --output predictions --batch-size 8 | ||
| # Combine multiple options | ||
| deepchopper predict raw_no_trim.parquet \ | ||
| --output predictions \ | ||
| --model rna004 \ | ||
| --gpus 1 \ | ||
| --batch-size 16 \ | ||
| --workers 4 | ||
| ``` | ||
| ### For Chunked Data | ||
| ```bash | ||
| deepchopper predict raw_no_trim.fq_chunks/raw_no_trim.fq_0.parquet --output predictions_chunk1 | ||
@@ -109,2 +197,10 @@ deepchopper predict raw_no_trim.fq_chunks/raw_no_trim.fq_1.parquet --output predictions_chunk2 | ||
| ### Hardware Acceleration | ||
| DeepChopper automatically detects and uses available hardware acceleration: | ||
| - **CUDA GPUs**: Specified with `--gpus N` (where N is the number of GPUs) | ||
| - **Apple Silicon (M1/M2/M3)**: Automatically uses Metal Performance Shaders (MPS) when `--gpus 1` is specified | ||
| - **CPU**: Default when no GPU is specified or available | ||
| ## 5. Chopping Artificial Sequences | ||
@@ -114,2 +210,4 @@ | ||
| ### Basic Usage | ||
| ```bash | ||
@@ -120,3 +218,3 @@ # Chop artificial sequences | ||
| For chunked predictions: | ||
| ### For Chunked Predictions | ||
@@ -127,32 +225,189 @@ ```bash | ||
| ### Advanced Options | ||
| ```bash | ||
| # Specify output prefix | ||
| deepchopper chop predictions/0 raw_no_trim.fastq --prefix my_cleaned_data | ||
| # Control memory usage with batch size (useful for large datasets) | ||
| deepchopper chop predictions/0 raw_no_trim.fastq --max-batch 5000 | ||
| # Adjust smoothing and filtering parameters | ||
| deepchopper chop predictions/0 raw_no_trim.fastq \ | ||
| --smooth-window 21 \ | ||
| --min-interval-size 13 \ | ||
| --min-read-length 20 | ||
| # Include chopped sequences in output | ||
| deepchopper chop predictions/0 raw_no_trim.fastq --output-chopped | ||
| # Use multiple threads for faster processing | ||
| deepchopper chop predictions/0 raw_no_trim.fastq --threads 4 | ||
| ``` | ||
| ### Parameter Guide | ||
| Key parameters you can adjust: | ||
| - `--prefix, -o`: Custom output file prefix | ||
| - `--max-batch`: Maximum batch size for memory management (default: auto) | ||
| - `--threads`: Number of threads to use (default: 2) | ||
| - `--smooth-window`: Smooth window size for prediction smoothing (default: 21) | ||
| - `--min-interval-size`: Minimum interval size to consider (default: 13) | ||
| - `--min-read-length`: Minimum read length after chopping (default: 20) | ||
| - `--approved-intervals`: Number of approved intervals (default: 20) | ||
| - `--output-chopped`: Output the chopped sequences separately | ||
| - `--chop-type`: Type of chopping to perform (default: "all") | ||
| 🎉 **Success**: Look for the output file with the `.chop.fq.bgz` suffix. | ||
| This command takes the original FASTQ file (`raw_no_trim.fastq`) and the predictions (`predictions`), and produces a new FASTQ file (with suffix `.chop.fq.bgz`) with the chimeric reads chopped. | ||
| This command takes the original FASTQ file (`raw_no_trim.fastq`) and the predictions (`predictions`), and produces a new FASTQ file (with suffix `.chop.fq.bgz`) with the chimeric-artifact chopped. | ||
| ### Understanding the Output | ||
| The default output is a compressed file in BGZIP format: | ||
| - **Format**: BGZIP-compressed FASTQ (`.chop.fq.bgz`) | ||
| - **View**: Use `zless -S OUTPUT` to view the output file contents in a terminal | ||
| - **The `-S` flag**: Prevents line wrapping, making it easier to read long sequences | ||
| - **Compatibility**: Can be directly used with most bioinformatics tools that support BGZIP | ||
| ### Performance Notes | ||
| The default parameters used in DeepChopper are optimized based on extensive testing and validation during our research, as detailed in our paper. | ||
| These parameters have been shown to provide robust and reliable results across a wide range of sequencing data. | ||
| **Processing Time**: | ||
| - Demo data: ~20-30 minutes | ||
| - Large datasets: May vary depending on: | ||
| - Machine specifications | ||
| - CPU/GPU availability | ||
| - Number of threads used | ||
| - Batch size settings | ||
| **Memory Management**: | ||
| - Lower batch sizes = less memory but slower processing | ||
| - Higher batch sizes = more memory but faster processing | ||
| ## 6. Web Interface (Optional) | ||
| DeepChopper also provides a user-friendly web interface for quick tests and demonstrations: | ||
| ```bash | ||
| # Launch the web interface | ||
| deepchopper web | ||
| ``` | ||
| This will start a local web server where you can: | ||
| - Upload single FASTQ records | ||
| - Visualize predictions in real-time | ||
| - Test DeepChopper without command-line operations | ||
| ⚠️ **Note**: The web interface is designed for quick tests with single reads. For production use with large datasets, use the command-line interface. | ||
| 🌐 **Online Version**: Try DeepChopper online at [Hugging Face Spaces](https://huggingface.co/spaces/yangliz5/deepchopper) without any installation! | ||
| ## Next Steps | ||
| - Explore advanced DeepChopper options with `deepchopper --help` | ||
| - Use your cleaned data for downstream analyses | ||
| - Check our documentation for integration with other bioinformatics tools | ||
| - **Advanced Parameters**: Check [our documentation](./parameters.md) for detailed parameters of the `chop` command | ||
| - **CLI Options**: Explore all available options with `deepchopper --help`, `deepchopper encode --help`, `deepchopper predict --help`, etc. | ||
| - **Downstream Analysis**: Use your cleaned data for: | ||
| - Transcript annotation | ||
| - Gene expression quantification | ||
| - Gene fusion detection | ||
| - Alternative splicing analysis | ||
| ## Troubleshooting | ||
| - **Issue**: Out of memory errors | ||
| ### Memory Issues | ||
| **Solution**: Try using the `--chunk` option in the encode step | ||
| - **Issue**: Out of memory errors when encoding | ||
| **Solution**: | ||
| - Use the `--chunk` option: `deepchopper encode input.fastq --chunk` | ||
| - Reduce chunk size: `deepchopper encode input.fastq --chunk --chunk-size 50000` | ||
| - Process smaller batches of files if dealing with multiple FASTQ files | ||
| - **Issue**: Out of memory errors for CPU or CUDA (GPU) when predicting | ||
| **Solution**: | ||
| - Reduce batch size: `deepchopper predict input.parquet --batch-size 4` | ||
| - Use `--max-sample` for testing: `deepchopper predict input.parquet --max-sample 1000` | ||
| - For large datasets, process in chunks | ||
| - **Issue**: Out of memory when chopping | ||
| **Solution**: | ||
| - Reduce the number of threads: `deepchopper chop predictions/0 input.fastq --threads 1` | ||
| ### Performance Issues | ||
| - **Issue**: Slow processing | ||
| **Solution**: Ensure you're using GPU acceleration if available | ||
| **Solution**: | ||
| - **Issue**: Unexpected results | ||
| - Enable GPU acceleration: `deepchopper predict input.parquet --gpus 1` | ||
| - Use chunked encoding for better memory efficiency: `deepchopper encode input.fastq --chunk` | ||
| - Increase threads for chopping: `deepchopper chop predictions/0 input.fastq --threads 4` | ||
| - Increase batch size (if memory allows): `deepchopper predict input.parquet --batch-size 16` | ||
| **Solution**: Verify input data quality and check DeepChopper version | ||
| - **Issue**: Apple Silicon (M1/M2/M3) not using GPU | ||
| **Solution**: | ||
| - Specify `--gpus 1` to enable MPS acceleration | ||
| - Ensure PyTorch was installed with MPS support | ||
| - Check with: `python -c "import torch; print(torch.backends.mps.is_available())"` | ||
| ### Model and Results Issues | ||
| - **Issue**: Unexpected results or poor performance | ||
| **Solution**: | ||
| - **Verify model selection**: Use `--model rna002` for RNA002 data or `--model rna004` for RNA004 data | ||
| - **Try both workflows**: You can use Dorado with or without trimming - both work well with DeepChopper | ||
| - Verify input data quality (check FASTQ quality scores) | ||
| - Check DeepChopper version: `deepchopper --version` | ||
| - Review the prediction output files before chopping | ||
| ### Hardware and Compatibility Issues | ||
| - **Issue**: GPU driver compatibility error | ||
| **Solution**: Update your GPU driver or install a compatible PyTorch version e.g., `pip install torch --force-reinstall --index-url https://download.pytorch.org/whl/cu118` to install a CUDA 11.8 compatible version. | ||
| **Solution**: | ||
| For more help, visit our [GitHub Issues](https://github.com/ylab-hi/DeepChopper/issues) page. | ||
| - Update your GPU driver to the latest version | ||
| - Install a compatible PyTorch version: | ||
| - CUDA 11.8: `pip install torch --force-reinstall --index-url https://download.pytorch.org/whl/cu118` | ||
| - CUDA 12.1: `pip install torch --force-reinstall --index-url https://download.pytorch.org/whl/cu121` | ||
| - CPU only: `pip install torch --force-reinstall --index-url https://download.pytorch.org/whl/cpu` | ||
| - **Issue**: `deepchopper-chop` command not found | ||
| **Solution**: | ||
| - Install the Rust-based chopper: `pip install deepchopper-cli` or follow installation guide | ||
| - Ensure the binary is in your PATH | ||
| - Try reinstalling: `pip install --force-reinstall deepchopper` | ||
| ### Getting Help | ||
| If you encounter issues not covered here: | ||
| 1. Check the [GitHub Issues](https://github.com/ylab-hi/DeepChopper/issues) for similar problems | ||
| 2. Review the [full documentation](https://github.com/ylab-hi/DeepChopper) | ||
| 3. Use `--verbose` flag to see detailed error messages | ||
| 4. Open a new issue with: | ||
| - DeepChopper version (`deepchopper --version`) | ||
| - Command you ran | ||
| - Full error message | ||
| - System information (OS, Python version, GPU if applicable) | ||
| Happy sequencing, and may your data be artifical-chimera-free! 🧬🔍 |
+5
-5
@@ -42,6 +42,6 @@ # reasons you might want to use `environment.yaml` instead of `requirements.txt`: | ||
| - pip: | ||
| - gradio==5.0.1 | ||
| - fastapi==0.112.2 | ||
| - deepchopper-cli>=1.0.1 | ||
| - maturin>=1.2.1,<2 | ||
| - gradio==5.0.1 | ||
| - fastapi==0.112.2 | ||
| - deepchopper-cli>=1.0.1 | ||
| - maturin>=1.2.1,<2 | ||
@@ -53,2 +53,2 @@ # --------- loggers --------- # | ||
| # - comet-ml | ||
| # - aim>=3.16.2 # no lower than 3.16.2, see https://github.com/aimhubio/aim/issues/2550 | ||
| # - aim>=3.16.2 # no lower than 3.16.2, see https://github.com/aimhubio/aim/issues/2550 |
+27
-12
@@ -1,4 +0,4 @@ | ||
| Metadata-Version: 2.3 | ||
| Metadata-Version: 2.4 | ||
| Name: deepchopper-cli | ||
| Version: 1.2.6 | ||
| Version: 1.2.8 | ||
| Classifier: Development Status :: 5 - Production/Stable | ||
@@ -21,5 +21,3 @@ Classifier: Environment :: Console | ||
| Home-Page: https://serde.rs | ||
| Author: Yangyang Li <yangyang.li@northwestern.edu> | ||
| Author-email: Yangyang Li <yangyang.li@northwestern.edu> | ||
| License: Apache-2.0 | ||
| Requires-Python: >=3.10 | ||
@@ -49,3 +47,3 @@ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM | ||
| - [PyPI Support](#pypi-support) | ||
| - [🛠️ Usage](#️-usage) | ||
| - [🛠️ Usage](#%EF%B8%8F-usage) | ||
| - [Command-Line Interface](#command-line-interface) | ||
@@ -61,5 +59,7 @@ - [Python Library](#python-library) | ||
| 🧬 DeepChopper leverages language model to accurately detect and chop artificial sequences which may cause chimeric reads, ensuring higher quality and more reliable sequencing results. | ||
| By integrating seamlessly with existing workflows, DeepChopper provides a robust solution for researchers and bioinformatics working with NanoPore direct-RNA sequencing data. | ||
| 🧬 DeepChopper leverages a language model to accurately detect and chop artificial sequences that may cause chimeric reads, ensuring higher quality and more reliable sequencing results. | ||
| By integrating seamlessly with existing workflows, DeepChopper provides a robust solution for researchers and bioinformaticians working with Nanopore direct-RNA sequencing data. | ||
| 📘 **FEATURED:** We provide a comprehensive tutorial that includes an example dataset in our [full documentation](./documentation/tutorial.md). | ||
| ## 🚀 Quick Start: Try DeepChopper Online | ||
@@ -118,5 +118,5 @@ | ||
| | :------------: | :----------: | :---------: | :-----------------: | :------------: | | ||
| | 3.10 | ✅ | ✅ | ✅ | ✅ | | ||
| | 3.11 | ✅ | ✅ | ✅ | ✅ | | ||
| | 3.12 | ✅ | ✅ | ✅ | ✅ | | ||
| | 3.10 | ✅ | ✅ | ✅ | ✅ | | ||
| | 3.11 | ✅ | ✅ | ✅ | ✅ | | ||
| | 3.12 | ✅ | ✅ | ✅ | ✅ | | ||
@@ -158,2 +158,17 @@ 🆘 Trouble installing? Check our [Troubleshooting Guide](https://github.com/ylab-hi/DeepChopper/blob/main/documentation/tutorial.md#troubleshooting) or [open an issue](https://github.com/ylab-hi/DeepChopper/issues). | ||
| **Memory Optimization:** For large datasets (>5M reads), use the `--chunk-size` parameter to control memory usage: | ||
| ```bash | ||
| # Low memory (~1-2GB): Slower but memory-efficient | ||
| deepchopper chop <predictions> raw.fq --chunk-size 1000 | ||
| # Balanced (default, ~5-10GB): Good balance of speed and memory | ||
| deepchopper chop <predictions> raw.fq --chunk-size 10000 | ||
| # High performance (~20-50GB): Fastest, requires more memory | ||
| deepchopper chop <predictions> raw.fq --chunk-size 50000 | ||
| ``` | ||
| The chop command uses **streaming mode** to minimize memory usage. Instead of loading all reads into memory at once (which can require 100GB+ for 20M reads), it processes records in configurable chunks and writes results incrementally. | ||
| Want a GUI? Launch the web interface (note: limited to one FASTQ record at a time): | ||
@@ -188,3 +203,3 @@ | ||
| publisher = {Cold Spring Harbor Laboratory}, | ||
| abstract = {Chimera artifacts in nanopore direct RNA sequencing (dRNA-seq) data can confound transcriptome analyses, yet no existing tools are capable of detecting and removing them due to limitations in basecalling models. We present DeepChopper, a genomic language model that accurately identifies and eliminates adapter sequences within base-called dRNA-seq reads, effectively removing chimeric read artifacts. DeepChopper significantly improves critical downstream analyses, including transcript annotation and gene fusion detection, enhancing the reliability and utility of nanopore dRNA-seq for transcriptomics research.Competing Interest StatementThe authors have declared no competing interest.}, | ||
| abstract = {Chimera artifacts in nanopore direct RNA sequencing (dRNA-seq) data can confound transcriptome analyses, yet no existing tools are capable of detecting and removing them due to limitations in basecalling models. We present DeepChopper, a genomic language model that accurately identifies and eliminates adapter sequences within base-called dRNA-seq reads, effectively removing chimeric read artifacts. DeepChopper significantly improves critical downstream analyses, including transcript annotation and gene fusion detection, enhancing the reliability and utility of nanopore dRNA-seq for transcriptomics research. Competing Interests: The authors have declared no competing interests.}, | ||
| URL = {https://www.biorxiv.org/content/early/2024/10/25/2024.10.23.619929}, | ||
@@ -226,3 +241,3 @@ eprint = {https://www.biorxiv.org/content/early/2024/10/25/2024.10.23.619929.full.pdf}, | ||
| --- | ||
| ______________________________________________________________________ | ||
@@ -229,0 +244,0 @@ DeepChopper is developed with ❤️ by the YLab team. |
+14
-14
@@ -7,3 +7,3 @@ [build-system] | ||
| name = "deepchopper-cli" | ||
| version = "1.2.6" | ||
| version = "1.2.8" | ||
| description = "CLI for DeepChopper: A Genomic Language Model for Chimera Artifact Detection" | ||
@@ -16,15 +16,15 @@ authors = [{ name = "Yangyang Li", email = "yangyang.li@northwestern.edu" }] | ||
| classifiers = [ | ||
| "Development Status :: 5 - Production/Stable", | ||
| "Environment :: Console", | ||
| "Intended Audience :: Science/Research", | ||
| "License :: OSI Approved :: Apache Software License", | ||
| "Operating System :: OS Independent", | ||
| "Programming Language :: Python", | ||
| "Programming Language :: Python :: 3", | ||
| "Programming Language :: Python :: 3 :: Only", | ||
| "Programming Language :: Python :: 3.10", | ||
| "Programming Language :: Python :: 3.11", | ||
| "Programming Language :: Python :: 3.12", | ||
| "Programming Language :: Rust", | ||
| "Topic :: Scientific/Engineering", | ||
| "Development Status :: 5 - Production/Stable", | ||
| "Environment :: Console", | ||
| "Intended Audience :: Science/Research", | ||
| "License :: OSI Approved :: Apache Software License", | ||
| "Operating System :: OS Independent", | ||
| "Programming Language :: Python", | ||
| "Programming Language :: Python :: 3", | ||
| "Programming Language :: Python :: 3 :: Only", | ||
| "Programming Language :: Python :: 3.10", | ||
| "Programming Language :: Python :: 3.11", | ||
| "Programming Language :: Python :: 3.12", | ||
| "Programming Language :: Rust", | ||
| "Topic :: Scientific/Engineering", | ||
| ] | ||
@@ -31,0 +31,0 @@ |
+25
-8
@@ -18,3 +18,3 @@ # <img src="./documentation/logo.webp" alt="logo" height="100"/> **DeepChopper** [](https://github.com/ylab-hi/DeepChopper/stargazers) | ||
| - [PyPI Support](#pypi-support) | ||
| - [🛠️ Usage](#️-usage) | ||
| - [🛠️ Usage](#%EF%B8%8F-usage) | ||
| - [Command-Line Interface](#command-line-interface) | ||
@@ -30,5 +30,7 @@ - [Python Library](#python-library) | ||
| 🧬 DeepChopper leverages language model to accurately detect and chop artificial sequences which may cause chimeric reads, ensuring higher quality and more reliable sequencing results. | ||
| By integrating seamlessly with existing workflows, DeepChopper provides a robust solution for researchers and bioinformatics working with NanoPore direct-RNA sequencing data. | ||
| 🧬 DeepChopper leverages a language model to accurately detect and chop artificial sequences that may cause chimeric reads, ensuring higher quality and more reliable sequencing results. | ||
| By integrating seamlessly with existing workflows, DeepChopper provides a robust solution for researchers and bioinformaticians working with Nanopore direct-RNA sequencing data. | ||
| 📘 **FEATURED:** We provide a comprehensive tutorial that includes an example dataset in our [full documentation](./documentation/tutorial.md). | ||
| ## 🚀 Quick Start: Try DeepChopper Online | ||
@@ -87,5 +89,5 @@ | ||
| | :------------: | :----------: | :---------: | :-----------------: | :------------: | | ||
| | 3.10 | ✅ | ✅ | ✅ | ✅ | | ||
| | 3.11 | ✅ | ✅ | ✅ | ✅ | | ||
| | 3.12 | ✅ | ✅ | ✅ | ✅ | | ||
| | 3.10 | ✅ | ✅ | ✅ | ✅ | | ||
| | 3.11 | ✅ | ✅ | ✅ | ✅ | | ||
| | 3.12 | ✅ | ✅ | ✅ | ✅ | | ||
@@ -127,2 +129,17 @@ 🆘 Trouble installing? Check our [Troubleshooting Guide](https://github.com/ylab-hi/DeepChopper/blob/main/documentation/tutorial.md#troubleshooting) or [open an issue](https://github.com/ylab-hi/DeepChopper/issues). | ||
| **Memory Optimization:** For large datasets (>5M reads), use the `--chunk-size` parameter to control memory usage: | ||
| ```bash | ||
| # Low memory (~1-2GB): Slower but memory-efficient | ||
| deepchopper chop <predictions> raw.fq --chunk-size 1000 | ||
| # Balanced (default, ~5-10GB): Good balance of speed and memory | ||
| deepchopper chop <predictions> raw.fq --chunk-size 10000 | ||
| # High performance (~20-50GB): Fastest, requires more memory | ||
| deepchopper chop <predictions> raw.fq --chunk-size 50000 | ||
| ``` | ||
| The chop command uses **streaming mode** to minimize memory usage. Instead of loading all reads into memory at once (which can require 100GB+ for 20M reads), it processes records in configurable chunks and writes results incrementally. | ||
| Want a GUI? Launch the web interface (note: limited to one FASTQ record at a time): | ||
@@ -157,3 +174,3 @@ | ||
| publisher = {Cold Spring Harbor Laboratory}, | ||
| abstract = {Chimera artifacts in nanopore direct RNA sequencing (dRNA-seq) data can confound transcriptome analyses, yet no existing tools are capable of detecting and removing them due to limitations in basecalling models. We present DeepChopper, a genomic language model that accurately identifies and eliminates adapter sequences within base-called dRNA-seq reads, effectively removing chimeric read artifacts. DeepChopper significantly improves critical downstream analyses, including transcript annotation and gene fusion detection, enhancing the reliability and utility of nanopore dRNA-seq for transcriptomics research.Competing Interest StatementThe authors have declared no competing interest.}, | ||
| abstract = {Chimera artifacts in nanopore direct RNA sequencing (dRNA-seq) data can confound transcriptome analyses, yet no existing tools are capable of detecting and removing them due to limitations in basecalling models. We present DeepChopper, a genomic language model that accurately identifies and eliminates adapter sequences within base-called dRNA-seq reads, effectively removing chimeric read artifacts. DeepChopper significantly improves critical downstream analyses, including transcript annotation and gene fusion detection, enhancing the reliability and utility of nanopore dRNA-seq for transcriptomics research. Competing Interests: The authors have declared no competing interests.}, | ||
| URL = {https://www.biorxiv.org/content/early/2024/10/25/2024.10.23.619929}, | ||
@@ -195,3 +212,3 @@ eprint = {https://www.biorxiv.org/content/early/2024/10/25/2024.10.23.619929.full.pdf}, | ||
| --- | ||
| ______________________________________________________________________ | ||
@@ -198,0 +215,0 @@ DeepChopper is developed with ❤️ by the YLab team. |
+14
-14
@@ -7,3 +7,3 @@ [build-system] | ||
| name = "deepchopper-cli" | ||
| version = "1.2.6" | ||
| version = "1.2.8" | ||
| description = "CLI for DeepChopper: A Genomic Language Model for Chimera Artifact Detection" | ||
@@ -16,15 +16,15 @@ authors = [{ name = "Yangyang Li", email = "yangyang.li@northwestern.edu" }] | ||
| classifiers = [ | ||
| "Development Status :: 5 - Production/Stable", | ||
| "Environment :: Console", | ||
| "Intended Audience :: Science/Research", | ||
| "License :: OSI Approved :: Apache Software License", | ||
| "Operating System :: OS Independent", | ||
| "Programming Language :: Python", | ||
| "Programming Language :: Python :: 3", | ||
| "Programming Language :: Python :: 3 :: Only", | ||
| "Programming Language :: Python :: 3.10", | ||
| "Programming Language :: Python :: 3.11", | ||
| "Programming Language :: Python :: 3.12", | ||
| "Programming Language :: Rust", | ||
| "Topic :: Scientific/Engineering", | ||
| "Development Status :: 5 - Production/Stable", | ||
| "Environment :: Console", | ||
| "Intended Audience :: Science/Research", | ||
| "License :: OSI Approved :: Apache Software License", | ||
| "Operating System :: OS Independent", | ||
| "Programming Language :: Python", | ||
| "Programming Language :: Python :: 3", | ||
| "Programming Language :: Python :: 3 :: Only", | ||
| "Programming Language :: Python :: 3.10", | ||
| "Programming Language :: Python :: 3.11", | ||
| "Programming Language :: Python :: 3.12", | ||
| "Programming Language :: Rust", | ||
| "Topic :: Scientific/Engineering", | ||
| ] | ||
@@ -31,0 +31,0 @@ |
+25
-8
@@ -18,3 +18,3 @@ # <img src="./documentation/logo.webp" alt="logo" height="100"/> **DeepChopper** [](https://github.com/ylab-hi/DeepChopper/stargazers) | ||
| - [PyPI Support](#pypi-support) | ||
| - [🛠️ Usage](#️-usage) | ||
| - [🛠️ Usage](#%EF%B8%8F-usage) | ||
| - [Command-Line Interface](#command-line-interface) | ||
@@ -30,5 +30,7 @@ - [Python Library](#python-library) | ||
| 🧬 DeepChopper leverages language model to accurately detect and chop artificial sequences which may cause chimeric reads, ensuring higher quality and more reliable sequencing results. | ||
| By integrating seamlessly with existing workflows, DeepChopper provides a robust solution for researchers and bioinformatics working with NanoPore direct-RNA sequencing data. | ||
| 🧬 DeepChopper leverages a language model to accurately detect and chop artificial sequences that may cause chimeric reads, ensuring higher quality and more reliable sequencing results. | ||
| By integrating seamlessly with existing workflows, DeepChopper provides a robust solution for researchers and bioinformaticians working with Nanopore direct-RNA sequencing data. | ||
| 📘 **FEATURED:** We provide a comprehensive tutorial that includes an example dataset in our [full documentation](./documentation/tutorial.md). | ||
| ## 🚀 Quick Start: Try DeepChopper Online | ||
@@ -87,5 +89,5 @@ | ||
| | :------------: | :----------: | :---------: | :-----------------: | :------------: | | ||
| | 3.10 | ✅ | ✅ | ✅ | ✅ | | ||
| | 3.11 | ✅ | ✅ | ✅ | ✅ | | ||
| | 3.12 | ✅ | ✅ | ✅ | ✅ | | ||
| | 3.10 | ✅ | ✅ | ✅ | ✅ | | ||
| | 3.11 | ✅ | ✅ | ✅ | ✅ | | ||
| | 3.12 | ✅ | ✅ | ✅ | ✅ | | ||
@@ -127,2 +129,17 @@ 🆘 Trouble installing? Check our [Troubleshooting Guide](https://github.com/ylab-hi/DeepChopper/blob/main/documentation/tutorial.md#troubleshooting) or [open an issue](https://github.com/ylab-hi/DeepChopper/issues). | ||
| **Memory Optimization:** For large datasets (>5M reads), use the `--chunk-size` parameter to control memory usage: | ||
| ```bash | ||
| # Low memory (~1-2GB): Slower but memory-efficient | ||
| deepchopper chop <predictions> raw.fq --chunk-size 1000 | ||
| # Balanced (default, ~5-10GB): Good balance of speed and memory | ||
| deepchopper chop <predictions> raw.fq --chunk-size 10000 | ||
| # High performance (~20-50GB): Fastest, requires more memory | ||
| deepchopper chop <predictions> raw.fq --chunk-size 50000 | ||
| ``` | ||
| The chop command uses **streaming mode** to minimize memory usage. Instead of loading all reads into memory at once (which can require 100GB+ for 20M reads), it processes records in configurable chunks and writes results incrementally. | ||
| Want a GUI? Launch the web interface (note: limited to one FASTQ record at a time): | ||
@@ -157,3 +174,3 @@ | ||
| publisher = {Cold Spring Harbor Laboratory}, | ||
| abstract = {Chimera artifacts in nanopore direct RNA sequencing (dRNA-seq) data can confound transcriptome analyses, yet no existing tools are capable of detecting and removing them due to limitations in basecalling models. We present DeepChopper, a genomic language model that accurately identifies and eliminates adapter sequences within base-called dRNA-seq reads, effectively removing chimeric read artifacts. DeepChopper significantly improves critical downstream analyses, including transcript annotation and gene fusion detection, enhancing the reliability and utility of nanopore dRNA-seq for transcriptomics research.Competing Interest StatementThe authors have declared no competing interest.}, | ||
| abstract = {Chimera artifacts in nanopore direct RNA sequencing (dRNA-seq) data can confound transcriptome analyses, yet no existing tools are capable of detecting and removing them due to limitations in basecalling models. We present DeepChopper, a genomic language model that accurately identifies and eliminates adapter sequences within base-called dRNA-seq reads, effectively removing chimeric read artifacts. DeepChopper significantly improves critical downstream analyses, including transcript annotation and gene fusion detection, enhancing the reliability and utility of nanopore dRNA-seq for transcriptomics research. Competing Interests: The authors have declared no competing interests.}, | ||
| URL = {https://www.biorxiv.org/content/early/2024/10/25/2024.10.23.619929}, | ||
@@ -195,3 +212,3 @@ eprint = {https://www.biorxiv.org/content/early/2024/10/25/2024.10.23.619929.full.pdf}, | ||
| --- | ||
| ______________________________________________________________________ | ||
@@ -198,0 +215,0 @@ DeepChopper is developed with ❤️ by the YLab team. |
| [toolchain] | ||
| channel = "nightly" | ||
| channel = "stable" |
+42
-15
| #!/bin/bash | ||
| set -euo pipefail # Combines the set commands into one line | ||
| predict_folder="vcap_caduceus" | ||
| # predict_folder="vcap_caduceus" | ||
| cargo run --bin predict -r -- \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap_004_hyena/RNA004.fastq_0/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap_004_hyena/RNA004.fastq_1/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap_004_hyena/RNA004.fastq_2/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap_004_hyena/RNA004.fastq_3/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap_004_hyena/RNA004.fastq_4/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap_004_hyena/RNA004.fastq_5/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap_004_hyena/RNA004.fastq_6/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap_004_hyena/RNA004.fastq_7/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap_004_hyena/RNA004.fastq_8/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap_004_hyena/RNA004.fastq_9/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap_004_hyena/RNA004.fastq_10/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap_004_hyena/RNA004.fastq_11/predicts/0/ \ | ||
| --fq data/dorado_without_trim_fqs/RNA004.fastq -t 10 -o vcap_004_hyena_all | ||
| cargo run --bin deepchopper-chop -r -- \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap002_hyena_both_model_hyena/VCaP.fastq_0/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap002_hyena_both_model_hyena/VCaP.fastq_1/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap002_hyena_both_model_hyena/VCaP.fastq_2/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap002_hyena_both_model_hyena/VCaP.fastq_3/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap002_hyena_both_model_hyena/VCaP.fastq_4/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap002_hyena_both_model_hyena/VCaP.fastq_5/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap002_hyena_both_model_hyena/VCaP.fastq_6/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap002_hyena_both_model_hyena/VCaP.fastq_7/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap002_hyena_both_model_hyena/VCaP.fastq_8/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap002_hyena_both_model_hyena/VCaP.fastq_9/predicts/0/ \ | ||
| --fq data/dorado_without_trim_fqs/VCaP.fastq -t 10 -o vcap002_hyena_both_model | ||
| cargo run --bin deepchopper-chop -r -- \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap002_dorado_with_trim_hyena/vcap002_dorado_with_trim.fastq_0/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap002_dorado_with_trim_hyena/vcap002_dorado_with_trim.fastq_1/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap002_dorado_with_trim_hyena/vcap002_dorado_with_trim.fastq_2/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap002_dorado_with_trim_hyena/vcap002_dorado_with_trim.fastq_3/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap002_dorado_with_trim_hyena/vcap002_dorado_with_trim.fastq_4/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap002_dorado_with_trim_hyena/vcap002_dorado_with_trim.fastq_5/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap002_dorado_with_trim_hyena/vcap002_dorado_with_trim.fastq_6/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap002_dorado_with_trim_hyena/vcap002_dorado_with_trim.fastq_7/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap002_dorado_with_trim_hyena/vcap002_dorado_with_trim.fastq_8/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap002_dorado_with_trim_hyena/vcap002_dorado_with_trim.fastq_9/predicts/0/ \ | ||
| --fq vcap002_dorado_with_trim.fastq -t 10 -s 21 -o vcap002_dorado_with_trim_hyena | ||
| cargo run --bin predict -r -- \ | ||
@@ -48,1 +61,15 @@ --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap_004_cnn_model_cnn/RNA004.fastq_0/predicts/0/ \ | ||
| --fq data/dorado_without_trim_fqs/VCaP.fastq --ct internal --mcr 70 -t 10 -o vcap_002_hyena_only_internal_mcr_70 | ||
| cargo run --bin predict -r -- \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap/VCaP.fastq_0/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap/VCaP.fastq_1/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap/VCaP.fastq_2/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap/VCaP.fastq_3/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap/VCaP.fastq_4/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap/VCaP.fastq_5/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap/VCaP.fastq_6/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap/VCaP.fastq_7/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap/VCaP.fastq_8/predicts/0/ \ | ||
| --pdt /projects/b1171/ylk4626/project/DeepChopper/logs/eval/runs/vcap/VCaP.fastq_9/predicts/0/ \ | ||
| --fq data/dorado_without_trim_fqs/VCaP.fastq -t 10 -s 11 -o vcap_002_doroda_without_trim_w11 |
@@ -7,2 +7,5 @@ #!/bin/bash | ||
| # train with both rna 002 data | ||
| # hyena_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-11-14_14-14-01/checkpoints/epoch_010_f1_0.9930.ckpt" | ||
| # rna 004 only | ||
@@ -15,6 +18,6 @@ # hyena_ckpt_path="/projects/b1171/ylk4626/project/DeepChopper/logs/train/runs/2024-07-02_15-20-53/checkpoints/epoch_008_f1_0.9946.ckpt" | ||
| # Default model selection | ||
| sample_name="MCF7_hyena_model" | ||
| data_folder="data/dorado_without_trim_fqs/MCF7.fastq_chunks" | ||
| sample_name="F121-9_dorado_with_trim2" | ||
| data_folder="rebutt/F121-9_dorado_with_trim2.fastq_chunks" | ||
| num_workers=60 | ||
| num_workers=15 | ||
| batch_size=64 | ||
@@ -21,0 +24,0 @@ |
@@ -39,3 +39,3 @@ use anyhow::Result; | ||
| let decoder = bgzf::MultithreadedReader::with_worker_count(worker_count, file); | ||
| let decoder = bgzf::io::MultithreadedReader::with_worker_count(worker_count, file); | ||
@@ -42,0 +42,0 @@ let mut reader = bam::io::Reader::from(decoder); |
+5
-3
@@ -35,3 +35,5 @@ use anyhow::Result; | ||
| fn compare_length<P: AsRef<Path>>(fq: P, chop_fq: P) -> Result<HashMap<String, usize>> { | ||
| let mut fq_reader = File::open(fq).map(BufReader::new).map(fastq::Reader::new)?; | ||
| let mut fq_reader = File::open(fq) | ||
| .map(BufReader::new) | ||
| .map(fastq::io::Reader::new)?; | ||
| let fq_records: Result<HashMap<String, FastqRecord>> = fq_reader | ||
@@ -50,3 +52,3 @@ .records() | ||
| .map(BufReader::new) | ||
| .map(fastq::Reader::new)?; | ||
| .map(fastq::io::Reader::new)?; | ||
| let chop_records: Result<HashMap<String, FastqRecord>> = chop_reader | ||
@@ -78,3 +80,3 @@ .records() | ||
| log::warn!("{} not found in chop fq", name); | ||
| return Some((name.clone(), fq_record.sequence().len())); | ||
| Some((name.clone(), fq_record.sequence().len())) | ||
| } | ||
@@ -81,0 +83,0 @@ }) |
+251
-64
@@ -0,2 +1,6 @@ | ||
| use std::fs::File; | ||
| use std::num::NonZeroUsize; | ||
| use std::path::PathBuf; | ||
| use std::sync::Mutex; | ||
| use std::thread; | ||
@@ -7,3 +11,6 @@ use ahash::HashMap; | ||
| use clap::Parser; | ||
| use noodles::bgzf; | ||
| use noodles::fastq; | ||
| use rayon::prelude::*; | ||
| use sysinfo::System; | ||
@@ -66,2 +73,7 @@ use deepchopper::default; | ||
| /// chunk size for streaming processing (reduce for lower memory, increase for better performance) | ||
| /// Typical values: 1000 (low memory), 10000 (balanced), 50000 (high performance) | ||
| #[arg(long = "chunk-size", default_value = "10000")] | ||
| chunk_size: usize, | ||
| /// Turn debugging information on | ||
@@ -72,2 +84,119 @@ #[arg(short, long, action = clap::ArgAction::Count)] | ||
| /// Get current process memory usage in bytes | ||
| /// | ||
| /// Returns: **Current RSS (Resident Set Size)** - actual physical RAM used NOW | ||
| /// | ||
| /// This is NOT: | ||
| /// - MaxRSS (peak RSS) - we calculate that separately by tracking max(current_rss) | ||
| /// - VmSize (virtual memory) - we don't track this, it includes unused address space | ||
| /// | ||
| /// What RSS includes: | ||
| /// - Actual physical RAM pages mapped to this process | ||
| /// - All heap allocations across all threads | ||
| /// - Thread stacks for main thread + all Rayon workers | ||
| /// - Shared library code pages currently in memory | ||
| /// | ||
| /// Important: Only tracks THIS process (same PID), not other jobs on HPC node. | ||
| fn get_memory_usage_bytes(sys: &mut System) -> u64 { | ||
| let pid = sysinfo::Pid::from_u32(std::process::id()); | ||
| // Refresh system info to get latest memory stats | ||
| sys.refresh_all(); | ||
| if let Some(process) = sys.process(pid) { | ||
| // Returns current RSS (Resident Set Size) in bytes - actual physical RAM used | ||
| process.memory() | ||
| } else { | ||
| 0 | ||
| } | ||
| } | ||
| /// Format bytes into human-readable memory size (MB, GB, etc.) | ||
| fn format_memory(bytes: u64) -> String { | ||
| const KB: u64 = 1024; | ||
| const MB: u64 = KB * 1024; | ||
| const GB: u64 = MB * 1024; | ||
| const TB: u64 = GB * 1024; | ||
| if bytes >= TB { | ||
| format!("{:.2} TB", bytes as f64 / TB as f64) | ||
| } else if bytes >= GB { | ||
| format!("{:.2} GB", bytes as f64 / GB as f64) | ||
| } else if bytes >= MB { | ||
| format!("{:.1} MB", bytes as f64 / MB as f64) | ||
| } else if bytes >= KB { | ||
| format!("{:.1} KB", bytes as f64 / KB as f64) | ||
| } else { | ||
| format!("{} B", bytes) | ||
| } | ||
| } | ||
| /// Process a chunk of FASTQ records with their predictions | ||
| fn process_chunk( | ||
| chunk: &[noodles::fastq::Record], | ||
| all_predicts: &HashMap<String, Predict>, | ||
| cli: &Cli, | ||
| ) -> Result<Vec<noodles::fastq::Record>> { | ||
| let results = chunk | ||
| .par_iter() | ||
| .filter_map(|fq_record| { | ||
| let id = String::from_utf8(fq_record.definition().name().to_vec()).unwrap(); | ||
| // Look up prediction for this FASTQ record | ||
| let predict = match all_predicts.get(&id) { | ||
| Some(p) => p, | ||
| None => return None, // Skip records without predictions | ||
| }; | ||
| if predict.seq.len() < default::MIN_READ_LEN { | ||
| return Some(Ok(vec![fq_record.clone()])); | ||
| } | ||
| let smooth_intervals = predict.smooth_and_select_intervals( | ||
| cli.smooth_window_size, | ||
| cli.min_interval_size, | ||
| cli.approved_interval_number, | ||
| ); | ||
| if smooth_intervals.len() > cli.max_process_intervals || smooth_intervals.is_empty() { | ||
| return Some(Ok(vec![fq_record.clone()])); | ||
| } | ||
| if predict.seq.len() != fq_record.quality_scores().len() { | ||
| // truncate seq prediction, do not process | ||
| log::debug!("truncate seq prediction, do not process: {}", id); | ||
| return Some(Ok(vec![fq_record.clone()])); | ||
| } | ||
| let result = if cli.output_chopped_seqs { | ||
| output::split_noodle_records_by_intervals( | ||
| BStr::new(&predict.seq), | ||
| id.as_bytes().into(), | ||
| fq_record.quality_scores(), | ||
| &smooth_intervals, | ||
| ) | ||
| } else { | ||
| output::split_noodle_records_by_remove_intervals( | ||
| BStr::new(&predict.seq), | ||
| id.as_bytes().into(), | ||
| fq_record.quality_scores(), | ||
| &smooth_intervals, | ||
| cli.min_read_length_after_chop, | ||
| true, // NOTE: add annotation for terminal or internal chop | ||
| &cli.chop_type, | ||
| ) | ||
| }; | ||
| Some(result) | ||
| }) | ||
| .collect::<Result<Vec<_>>>()? | ||
| .into_par_iter() | ||
| .flatten() | ||
| .collect(); | ||
| Ok(results) | ||
| } | ||
| /// Main function that processes FASTQ records with predictions using streaming mode | ||
| /// to minimize memory usage. Records are processed in configurable chunks and written | ||
| /// incrementally to reduce memory footprint. | ||
| fn main() -> Result<()> { | ||
@@ -86,2 +215,7 @@ let start = std::time::Instant::now(); | ||
| // Initialize system info for memory monitoring (only for this process, not all processes) | ||
| let mut sys = System::new(); | ||
| let initial_mem = get_memory_usage_bytes(&mut sys); | ||
| log::info!("Initial memory usage: {}", format_memory(initial_mem)); | ||
| rayon::ThreadPoolBuilder::new() | ||
@@ -110,74 +244,112 @@ .num_threads(cli.threads.unwrap()) | ||
| let all_predicts_number = all_predicts.len(); | ||
| log::info!("Collect {} predicts", all_predicts_number); | ||
| let mem_after_predictions = get_memory_usage_bytes(&mut sys); | ||
| log::info!( | ||
| "Collected {} predictions (memory: {}, +{})", | ||
| all_predicts_number, | ||
| format_memory(mem_after_predictions), | ||
| format_memory(mem_after_predictions.saturating_sub(initial_mem)) | ||
| ); | ||
| // load fq file | ||
| let mut _records = output::read_noodel_records_from_fq_or_zip_fq(&cli.fq)?; | ||
| let fq_records = _records | ||
| .into_par_iter() | ||
| .map(|record| { | ||
| let id = String::from_utf8(record.definition().name().to_vec()).unwrap(); | ||
| (id, record) | ||
| }) | ||
| .collect::<HashMap<_, _>>(); | ||
| log::info!( | ||
| "Load {} fq records from {}", | ||
| fq_records.len(), | ||
| cli.fq.display() | ||
| "Processing FASTQ records in chunks of {} (streaming mode to reduce memory)", | ||
| cli.chunk_size | ||
| ); | ||
| let res = all_predicts | ||
| .into_par_iter() | ||
| .map(|(id, predict)| { | ||
| let fq_record = fq_records.get(&id).expect("id not found"); | ||
| // Determine output directory to create temp file in the same filesystem as final output. | ||
| // This prevents "Invalid cross-device link" errors when renaming across filesystems. | ||
| let output_dir = if let Some(ref prefix) = cli.output_prefix { | ||
| std::path::Path::new(prefix) | ||
| .parent() | ||
| .unwrap_or_else(|| std::path::Path::new(".")) | ||
| .to_path_buf() | ||
| } else { | ||
| cli.fq | ||
| .parent() | ||
| .unwrap_or_else(|| std::path::Path::new(".")) | ||
| .to_path_buf() | ||
| }; | ||
| if predict.seq.len() < default::MIN_READ_LEN { | ||
| return Ok(vec![fq_record.clone()]); | ||
| // Create temporary output file in the same directory as the final output | ||
| let temp_output = output_dir.join(format!(".deepchopper_temp_{}.fq.gz", std::process::id())); | ||
| // Set up the writer for incremental writing | ||
| let worker_count = NonZeroUsize::new(cli.threads.unwrap_or(2)) | ||
| .map(|count| count.min(thread::available_parallelism().unwrap())) | ||
| .unwrap(); | ||
| let sink = File::create(&temp_output)?; | ||
| let encoder = bgzf::io::MultithreadedWriter::with_worker_count(worker_count, sink); | ||
| let writer = Mutex::new(fastq::io::Writer::new(encoder)); | ||
| // Stream FASTQ records and process with parallel chunks | ||
| let streaming_reader = output::StreamingFastqReader::new(&cli.fq)?; | ||
| let mut current_chunk = Vec::new(); | ||
| let mut total_fq_count = 0; | ||
| let mut total_output_count = 0; | ||
| let mut peak_memory = mem_after_predictions; | ||
| for record_result in streaming_reader { | ||
| let fq_record = record_result?; | ||
| current_chunk.push(fq_record); | ||
| total_fq_count += 1; | ||
| // Process chunk when it reaches the desired size | ||
| if current_chunk.len() >= cli.chunk_size { | ||
| let chunk_results = process_chunk(¤t_chunk, &all_predicts, &cli)?; | ||
| // Write chunk results immediately | ||
| { | ||
| let mut writer_guard = writer.lock().unwrap(); | ||
| for record in &chunk_results { | ||
| writer_guard.write_record(record)?; | ||
| } | ||
| total_output_count += chunk_results.len(); | ||
| } | ||
| let smooth_intervals = predict.smooth_and_select_intervals( | ||
| cli.smooth_window_size, | ||
| cli.min_interval_size, | ||
| cli.approved_interval_number, | ||
| ); | ||
| current_chunk.clear(); | ||
| if smooth_intervals.len() > cli.max_process_intervals || smooth_intervals.is_empty() { | ||
| return Ok(vec![fq_record.clone()]); | ||
| // Track peak memory and progress logging every 10 chunks (or in debug mode every chunk) | ||
| if cli.debug > 0 || (total_fq_count / cli.chunk_size) % 10 == 0 { | ||
| let current_mem = get_memory_usage_bytes(&mut sys); | ||
| peak_memory = peak_memory.max(current_mem); | ||
| let chunks_processed = total_fq_count / cli.chunk_size; | ||
| log::info!( | ||
| "Progress: {} chunks ({} reads) -> {} output records | RSS: {}", | ||
| chunks_processed, | ||
| total_fq_count, | ||
| total_output_count, | ||
| format_memory(current_mem) | ||
| ); | ||
| } | ||
| } | ||
| } | ||
| if predict.seq.len() != fq_record.quality_scores().len() { | ||
| // truncate seq prediction, do not process | ||
| return Ok(vec![fq_record.clone()]); | ||
| }; | ||
| // Process remaining records in the last chunk | ||
| if !current_chunk.is_empty() { | ||
| let chunk_results = process_chunk(¤t_chunk, &all_predicts, &cli)?; | ||
| if cli.output_chopped_seqs { | ||
| output::split_noodle_records_by_intervals( | ||
| BStr::new(&predict.seq), | ||
| id.as_bytes().into(), | ||
| fq_record.quality_scores(), | ||
| &smooth_intervals, | ||
| ) | ||
| } else { | ||
| output::split_noodle_records_by_remove_intervals( | ||
| BStr::new(&predict.seq), | ||
| id.as_bytes().into(), | ||
| fq_record.quality_scores(), | ||
| &smooth_intervals, | ||
| cli.min_read_length_after_chop, | ||
| true, // NOTE: add annotation for terminal or internal chop | ||
| &cli.chop_type, | ||
| ) | ||
| // Write remaining results | ||
| { | ||
| let mut writer_guard = writer.lock().unwrap(); | ||
| for record in &chunk_results { | ||
| writer_guard.write_record(record)?; | ||
| } | ||
| }) | ||
| .collect::<Result<Vec<_>>>()? | ||
| .into_par_iter() | ||
| .flatten() | ||
| .collect::<Vec<_>>(); | ||
| total_output_count += chunk_results.len(); | ||
| } | ||
| } | ||
| // Close the writer by dropping it | ||
| drop(writer); | ||
| log::info!( | ||
| "Processed {} FASTQ records, generated {} output records", | ||
| total_fq_count, | ||
| total_output_count | ||
| ); | ||
| // Determine final output filename with correct record count | ||
| let output_file = if let Some(prefix) = cli.output_prefix { | ||
| format!( | ||
| "{}.{}pd.{}record.chop.fq.bgz", | ||
| prefix, | ||
| all_predicts_number, | ||
| res.len() | ||
| "{}.{}pd.{}record.chop.fq.gz", | ||
| prefix, all_predicts_number, total_output_count | ||
| ) | ||
@@ -187,6 +359,4 @@ } else { | ||
| format!( | ||
| "{}.{}pd.{}record.chop.fq.bgz", | ||
| file_stem, | ||
| all_predicts_number, | ||
| res.len() | ||
| "{}.{}pd.{}record.chop.fq.gz", | ||
| file_stem, all_predicts_number, total_output_count | ||
| ) | ||
@@ -199,10 +369,27 @@ }; | ||
| output::write_fq_parallel_for_noodle_record(&res, output_file.clone().into(), cli.threads)?; | ||
| // Rename temp file to final output file | ||
| if let Err(e) = std::fs::rename(&temp_output, &output_file) { | ||
| // Clean up temp file on error | ||
| let _ = std::fs::remove_file(&temp_output); | ||
| return Err(e.into()); | ||
| } | ||
| log::info!("Write {} records to {}", res.len(), output_file); | ||
| log::info!("Wrote {} records to {}", total_output_count, output_file); | ||
| // Final memory and timing report | ||
| let final_mem = get_memory_usage_bytes(&mut sys); | ||
| peak_memory = peak_memory.max(final_mem); | ||
| let elapsed = start.elapsed(); | ||
| log::info!("elapsed time: {:.2?}", elapsed); | ||
| // Peak memory = MaxRSS (maximum RSS observed during execution) | ||
| // Final memory = Current RSS at end | ||
| // Both show actual physical RAM used (not virtual memory) | ||
| log::info!( | ||
| "Completed in {:.2?} | Peak RSS: {} | Final RSS: {}", | ||
| elapsed, | ||
| format_memory(peak_memory), | ||
| format_memory(final_mem) | ||
| ); | ||
| Ok(()) | ||
| } |
+1
-1
@@ -29,3 +29,3 @@ use clap::Parser; | ||
| .map(BufReader::new) | ||
| .map(fastq::Reader::new)?; | ||
| .map(fastq::io::Reader::new)?; | ||
@@ -32,0 +32,0 @@ let mut records: Vec<RecordData> = Vec::new(); |
@@ -47,3 +47,3 @@ use anyhow::Result; | ||
| let decoder = bgzf::MultithreadedReader::with_worker_count(worker_count, file); | ||
| let decoder = bgzf::io::MultithreadedReader::with_worker_count(worker_count, file); | ||
@@ -92,3 +92,3 @@ let mut reader = bam::io::Reader::from(decoder); | ||
| let decoder = bgzf::MultithreadedReader::with_worker_count(worker_count, file); | ||
| let decoder = bgzf::io::MultithreadedReader::with_worker_count(worker_count, file); | ||
| let mut reader = bam::io::Reader::from(decoder); | ||
@@ -95,0 +95,0 @@ let header = reader.read_header()?; |
+1
-1
@@ -60,3 +60,3 @@ use ahash::HashSet; | ||
| let file = File::open(bam.as_ref())?; | ||
| let decoder = bgzf::MultithreadedReader::with_worker_count(worker_count, file); | ||
| let decoder = bgzf::io::MultithreadedReader::with_worker_count(worker_count, file); | ||
| let mut reader = bam::io::Reader::from(decoder); | ||
@@ -63,0 +63,0 @@ let header = reader.read_header()?; |
@@ -93,3 +93,3 @@ use anyhow::Result; | ||
| let bamdecoder = bgzf::MultithreadedReader::with_worker_count(worker_count, bamfile); | ||
| let bamdecoder = bgzf::io::MultithreadedReader::with_worker_count(worker_count, bamfile); | ||
| let mut bamreader = bam::io::Reader::from(bamdecoder); | ||
@@ -118,3 +118,3 @@ let _header = bamreader.read_header()?; | ||
| let cpdecoder = bgzf::MultithreadedReader::with_worker_count(worker_count, cpfile); | ||
| let cpdecoder = bgzf::io::MultithreadedReader::with_worker_count(worker_count, cpfile); | ||
| let mut cpreader = bam::io::Reader::from(cpdecoder); | ||
@@ -121,0 +121,0 @@ let _header = cpreader.read_header()?; |
@@ -110,9 +110,8 @@ use std::{ | ||
| match self.encode_record(id, seq, qual).context(format!( | ||
| "encode fq read id {} error", | ||
| String::from_utf8_lossy(id) | ||
| )) { | ||
| Ok(result) => Some(result), | ||
| Err(_e) => None, | ||
| } | ||
| self.encode_record(id, seq, qual) | ||
| .context(format!( | ||
| "encode fq read id {} error", | ||
| String::from_utf8_lossy(id) | ||
| )) | ||
| .ok() | ||
| }) | ||
@@ -119,0 +118,0 @@ .collect(); |
@@ -35,2 +35,3 @@ use crate::default::{BASES, KMER_SIZE, QUAL_OFFSET, VECTORIZED_TARGET}; | ||
| #[new] | ||
| #[pyo3(signature = (kmer_size, qual_offset, bases, vectorized_target, threads = None))] | ||
| fn py_new( | ||
@@ -37,0 +38,0 @@ kmer_size: u8, |
@@ -65,9 +65,8 @@ use std::{ | ||
| let qual = data.qual.as_ref(); | ||
| match self.encode_record(id, seq, qual).context(format!( | ||
| "encode fq read id {} error", | ||
| String::from_utf8_lossy(id) | ||
| )) { | ||
| Ok(result) => Some(result), | ||
| Err(_e) => None, | ||
| } | ||
| self.encode_record(id, seq, qual) | ||
| .context(format!( | ||
| "encode fq read id {} error", | ||
| String::from_utf8_lossy(id) | ||
| )) | ||
| .ok() | ||
| }) | ||
@@ -74,0 +73,0 @@ .collect(); |
@@ -131,3 +131,3 @@ use std::{ | ||
| .map(BufReader::new) | ||
| .map(fastq::Reader::new)?; | ||
| .map(fastq::io::Reader::new)?; | ||
@@ -295,9 +295,8 @@ let mut records: Vec<RecordData> = Vec::new(); | ||
| match self.encode_record(id, seq, qual).context(format!( | ||
| "encode fq read id {} error", | ||
| String::from_utf8_lossy(id) | ||
| )) { | ||
| Ok(result) => Some(result), | ||
| Err(_e) => None, | ||
| } | ||
| self.encode_record(id, seq, qual) | ||
| .context(format!( | ||
| "encode fq read id {} error", | ||
| String::from_utf8_lossy(id) | ||
| )) | ||
| .ok() | ||
| }) | ||
@@ -304,0 +303,0 @@ .collect(); |
@@ -42,3 +42,3 @@ use anyhow::Result; | ||
| .split(|&c| c == b'|') | ||
| .last() | ||
| .next_back() | ||
| .context("Failed to get number part")?; | ||
@@ -45,0 +45,0 @@ |
+4
-6
@@ -57,6 +57,6 @@ use itertools::Itertools; | ||
| // Ensure the number of targets is even. | ||
| assert!(targets.len() % 2 == 0); | ||
| assert!(targets.len().is_multiple_of(2)); | ||
| let mut result = vec![0; length]; | ||
| for (start, end) in targets.into_iter().tuples() { | ||
| for (start, end) in targets.iter().tuples() { | ||
| if start > end || end > &length { | ||
@@ -75,3 +75,2 @@ return Err(Error::from(EncodingError::TargetRegionInvalid)); | ||
| #[pyfunction(name = "vectorize_targets")] | ||
@@ -446,3 +445,3 @@ pub fn py_vectorize_targets(targets: Vec<usize>, length: usize) -> Result<Vec<usize>> { | ||
| let length = 15; | ||
| let result = vectorize_targets(targets, length).unwrap(); | ||
| let result = vectorize_targets(&targets, length).unwrap(); | ||
| assert_eq!(result, vec![1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0]); | ||
@@ -455,6 +454,5 @@ } | ||
| let length = 15; | ||
| let result = vectorize_targets(targets, length); | ||
| let result = vectorize_targets(&targets, length); | ||
| assert!(result.is_err()); | ||
| } | ||
| } |
@@ -114,2 +114,3 @@ use anyhow::Result; | ||
| #[new] | ||
| #[pyo3(signature = (qname, mapping_quality, cigar, left_softclip, right_softclip, is_forward, is_mapped, is_supplementary, is_secondary, quality, sa_tag=None))] | ||
| fn new( | ||
@@ -150,8 +151,8 @@ qname: String, | ||
| // Convert JSON string to Python bytes | ||
| Ok(PyBytes::new_bound(py, serialized.as_bytes()).into()) | ||
| Ok(PyBytes::new(py, serialized.as_bytes()).into()) | ||
| } | ||
| fn __setstate__(&mut self, py: Python, state: PyObject) -> PyResult<()> { | ||
| // Expect a bytes object for state | ||
| let state_bytes: &PyBytes = state.extract(py)?; | ||
| // Convert PyObject to PyBytes | ||
| let state_bytes = state.downcast_bound::<PyBytes>(py)?; | ||
@@ -194,3 +195,3 @@ // Deserialize the JSON string into the current instance | ||
| let decoder = bgzf::MultithreadedReader::with_worker_count(worker_count, file); | ||
| let decoder = bgzf::io::MultithreadedReader::with_worker_count(worker_count, file); | ||
@@ -337,2 +338,3 @@ let mut reader = bam::io::Reader::from(decoder); | ||
| #[pyo3(name = "read_bam_records_parallel")] | ||
| #[pyo3(signature = (path, threads = None))] | ||
| pub fn py_read_bam_records_parallel( | ||
@@ -339,0 +341,0 @@ path: &str, |
+208
-19
| use std::fs::File; | ||
| use std::io::BufReader; | ||
| use std::io::{BufReader, Read}; | ||
| use std::num::NonZeroUsize; | ||
@@ -8,2 +8,3 @@ use std::path::{Path, PathBuf}; | ||
| use anyhow::Result; | ||
| use flate2::read::GzDecoder; | ||
| use noodles::fastq::{self as fastq, record::Definition}; | ||
@@ -39,22 +40,162 @@ | ||
| /// Represents different types of file compression formats | ||
| /// | ||
| /// This enum is used to identify and handle various compression formats commonly used for files. | ||
| /// It can be used in Python through the deepbiop.utils module. | ||
| /// | ||
| /// # Variants | ||
| /// | ||
| /// * `Uncompress` - Uncompressed/raw file format | ||
| /// * `Gzip` - Standard gzip compression (.gz files) | ||
| /// * `Bgzip` - Blocked gzip format, commonly used in bioinformatics | ||
| /// * `Zip` - ZIP archive format | ||
| /// * `Bzip2` - bzip2 compression format | ||
| /// * `Xz` - XZ compression format (LZMA2) | ||
| /// * `Zstd` - Zstandard compression format | ||
| /// * `Unknown` - Unknown or unrecognized compression format | ||
| #[derive(Debug, PartialEq, Clone, Eq, Hash)] | ||
| pub enum CompressedType { | ||
| Uncompress, | ||
| Gzip, | ||
| Bgzip, | ||
| Zip, | ||
| Bzip2, | ||
| Xz, | ||
| Zstd, | ||
| Unknown, | ||
| } | ||
| /// Determines the compression type of a file by examining its header/signature | ||
| /// | ||
| /// This function reads the first few bytes of a file and checks for known magic numbers | ||
| /// or file signatures to identify the compression format used. | ||
| /// | ||
| /// # Arguments | ||
| /// | ||
| /// * `file_path` - Path to the file to check, can be any type that converts to a Path | ||
| /// | ||
| /// # Returns | ||
| /// | ||
| /// * `Result<CompressedType>` - The detected compression type wrapped in a Result | ||
| /// | ||
| /// # Errors | ||
| /// | ||
| /// Returns an error if: | ||
| /// * The file cannot be opened | ||
| /// * There are issues reading the file header | ||
| pub fn check_compressed_type<P: AsRef<Path>>(file_path: P) -> Result<CompressedType> { | ||
| let mut file = File::open(file_path)?; | ||
| let mut buffer = [0u8; 18]; // Large enough for BGZF detection | ||
| // Read the first few bytes | ||
| let bytes_read = file.read(&mut buffer)?; | ||
| if bytes_read < 2 { | ||
| return Ok(CompressedType::Uncompress); | ||
| } | ||
| // Check magic numbers/file signatures | ||
| match &buffer[..] { | ||
| // Check for BGZF first (starts with gzip magic number + specific extra fields) | ||
| [0x1f, 0x8b, 0x08, 0x04, ..] if bytes_read >= 18 => { | ||
| // Check for BGZF extra field | ||
| let xlen = u16::from_le_bytes([buffer[10], buffer[11]]) as usize; | ||
| if xlen >= 6 && buffer[12] == 0x42 // B | ||
| && buffer[13] == 0x43 // C | ||
| && buffer[14] == 0x02 // Length of subfield (2) | ||
| && buffer[15] == 0x00 | ||
| // Length of subfield (2) | ||
| { | ||
| Ok(CompressedType::Bgzip) | ||
| } else { | ||
| Ok(CompressedType::Gzip) | ||
| } | ||
| } | ||
| // Regular Gzip: starts with 0x1F 0x8B | ||
| [0x1f, 0x8b, ..] => Ok(CompressedType::Gzip), | ||
| // Zip: starts with "PK\x03\x04" or "PK\x05\x06" (empty archive) or "PK\x07\x08" (spanned archive) | ||
| [0x50, 0x4b, 0x03, 0x04, ..] | ||
| | [0x50, 0x4b, 0x05, 0x06, ..] | ||
| | [0x50, 0x4b, 0x07, 0x08, ..] => Ok(CompressedType::Zip), | ||
| // Bzip2: starts with "BZh" | ||
| [0x42, 0x5a, 0x68, ..] => Ok(CompressedType::Bzip2), | ||
| // XZ: starts with 0xFD "7zXZ" | ||
| [0xfd, 0x37, 0x7a, 0x58, 0x5a, 0x00, ..] => Ok(CompressedType::Xz), | ||
| // Zstandard: starts with magic number 0xFD2FB528 | ||
| [0x28, 0xb5, 0x2f, 0xfd, ..] => Ok(CompressedType::Zstd), | ||
| // If no compression signature is found, assume it's a normal file | ||
| _ => { | ||
| // Additional check for text/binary content could be added here | ||
| Ok(CompressedType::Uncompress) | ||
| } | ||
| } | ||
| } | ||
| /// Creates a reader for a file that may be compressed | ||
| /// | ||
| /// This function detects the compression type of the file and returns an appropriate reader. | ||
| /// Currently supports uncompressed files, gzip, and bgzip formats. | ||
| /// | ||
| /// # Arguments | ||
| /// * `file_path` - Path to the file to read, can be compressed or uncompressed | ||
| /// | ||
| /// # Returns | ||
| /// * `Ok(Box<dyn io::Read>)` - A boxed reader appropriate for the file's compression | ||
| /// * `Err` - If the file cannot be opened or has an unsupported compression type | ||
| pub fn create_reader_for_compressed_file<P: AsRef<Path>>( | ||
| file_path: P, | ||
| ) -> Result<Box<dyn io::Read>> { | ||
| let compressed_type = check_compressed_type(file_path.as_ref())?; | ||
| let file = File::open(file_path)?; | ||
| Ok(match compressed_type { | ||
| CompressedType::Uncompress => Box::new(file), | ||
| CompressedType::Gzip => Box::new(GzDecoder::new(file)), | ||
| CompressedType::Bgzip => Box::new(bgzf::io::Reader::new(file)), | ||
| _ => return Err(anyhow::anyhow!("unsupported compression type")), | ||
| }) | ||
| } | ||
| pub fn read_noodel_records_from_fq_or_zip_fq<P: AsRef<Path>>( | ||
| file_path: P, | ||
| ) -> Result<Vec<FastqRecord>> { | ||
| let extension = file_path.as_ref().extension().unwrap(); | ||
| if extension == "bgz" { | ||
| log::info!("Reading from bgz file"); | ||
| read_noodle_records_from_bzip_fq(file_path) | ||
| } else if extension == "gz" { | ||
| log::info!("Reading from gz file"); | ||
| read_noodle_records_from_gzip_fq(file_path) | ||
| } else { | ||
| log::info!("Reading from fq file"); | ||
| read_noodle_records_from_fq(file_path) | ||
| let reader = create_reader_for_compressed_file(&file_path)?; | ||
| let mut reader = fastq::io::Reader::new(BufReader::new(reader)); | ||
| reader.records().map(|record| Ok(record?)).collect() | ||
| } | ||
| /// Streaming reader for FASTQ records that owns the underlying reader | ||
| /// | ||
| /// This struct provides an iterator interface for reading FASTQ records | ||
| /// without loading all records into memory at once. | ||
| pub struct StreamingFastqReader { | ||
| reader: fastq::io::Reader<BufReader<Box<dyn io::Read>>>, | ||
| } | ||
| impl StreamingFastqReader { | ||
| /// Creates a new streaming reader for a FASTQ file (compressed or uncompressed) | ||
| pub fn new<P: AsRef<Path>>(file_path: P) -> Result<Self> { | ||
| let reader = create_reader_for_compressed_file(&file_path)?; | ||
| let reader = fastq::io::Reader::new(BufReader::new(reader)); | ||
| Ok(Self { reader }) | ||
| } | ||
| } | ||
| impl Iterator for StreamingFastqReader { | ||
| type Item = Result<FastqRecord>; | ||
| fn next(&mut self) -> Option<Self::Item> { | ||
| self.reader.records().next().map(|r| r.map_err(Into::into)) | ||
| } | ||
| } | ||
| pub fn read_noodle_records_from_fq<P: AsRef<Path>>(file_path: P) -> Result<Vec<FastqRecord>> { | ||
| let mut reader = File::open(file_path) | ||
| .map(BufReader::new) | ||
| .map(fastq::Reader::new)?; | ||
| .map(fastq::io::Reader::new)?; | ||
| let records: Result<Vec<FastqRecord>> = reader | ||
@@ -93,3 +234,3 @@ .records() | ||
| let sink = File::create(file_path)?; | ||
| let encoder = bgzf::MultithreadedWriter::with_worker_count(worker_count, sink); | ||
| let encoder = bgzf::io::MultithreadedWriter::with_worker_count(worker_count, sink); | ||
@@ -119,3 +260,3 @@ let mut writer = fastq::io::Writer::new(encoder); | ||
| let sink = File::create(file_path)?; | ||
| let encoder = bgzf::MultithreadedWriter::with_worker_count(worker_count, sink); | ||
| let encoder = bgzf::io::MultithreadedWriter::with_worker_count(worker_count, sink); | ||
@@ -135,3 +276,3 @@ let mut writer = fastq::io::Writer::new(encoder); | ||
| .map(BufReader::new) | ||
| .map(fastq::Reader::new)?; | ||
| .map(fastq::io::Reader::new)?; | ||
@@ -150,4 +291,4 @@ let records: Result<Vec<FastqRecord>> = reader | ||
| pub fn read_noodle_records_from_bzip_fq<P: AsRef<Path>>(file_path: P) -> Result<Vec<FastqRecord>> { | ||
| let decoder = bgzf::Reader::new(File::open(file_path)?); | ||
| let mut reader = fastq::Reader::new(decoder); | ||
| let decoder = bgzf::io::Reader::new(File::open(file_path)?); | ||
| let mut reader = fastq::io::Reader::new(decoder); | ||
@@ -212,2 +353,50 @@ let records: Result<Vec<FastqRecord>> = reader | ||
| #[test] | ||
| fn test_streaming_fastq_reader() { | ||
| // Create test FASTQ records | ||
| let test_records = vec![ | ||
| RecordData { | ||
| id: b"read1".into(), | ||
| seq: b"ATCGATCG".into(), | ||
| qual: b"IIIIIIII".into(), | ||
| }, | ||
| RecordData { | ||
| id: b"read2".into(), | ||
| seq: b"GCTAGCTA".into(), | ||
| qual: b"HHHHHHHH".into(), | ||
| }, | ||
| RecordData { | ||
| id: b"read3".into(), | ||
| seq: b"AAAATTTT".into(), | ||
| qual: b"JJJJJJJJ".into(), | ||
| }, | ||
| ]; | ||
| // Write test data to a temporary gzip file | ||
| let file = NamedTempFile::new().unwrap(); | ||
| let file_path = file.path().to_path_buf(); | ||
| write_zip_fq_parallel(&test_records, file_path.clone(), Some(2)).unwrap(); | ||
| // Test streaming reader | ||
| let mut streaming_reader = StreamingFastqReader::new(&file_path).unwrap(); | ||
| let mut count = 0; | ||
| while let Some(result) = streaming_reader.next() { | ||
| let record = result.unwrap(); | ||
| assert!(count < test_records.len()); | ||
| let id = record.definition().name(); | ||
| let seq = record.sequence(); | ||
| let qual = record.quality_scores(); | ||
| assert_eq!(id, test_records[count].id.as_slice()); | ||
| assert_eq!(seq, test_records[count].seq.as_slice()); | ||
| assert_eq!(qual, test_records[count].qual.as_slice()); | ||
| count += 1; | ||
| } | ||
| assert_eq!(count, test_records.len()); | ||
| } | ||
| #[test] | ||
| fn test_write_fq_with_file_path() { | ||
@@ -258,4 +447,4 @@ let records = vec![ | ||
| let decoder = bgzf::Reader::new(file.reopen().unwrap()); | ||
| let mut reader = fastq::Reader::new(decoder); | ||
| let decoder = bgzf::io::Reader::new(file.reopen().unwrap()); | ||
| let mut reader = fastq::io::Reader::new(decoder); | ||
@@ -262,0 +451,0 @@ let actual_result: Vec<RecordData> = reader |
+78
-10
@@ -5,3 +5,3 @@ use crate::{ | ||
| fq_encode::{self, Encoder}, | ||
| kmer::{self, vectorize_target, py_vectorize_targets}, | ||
| kmer::{self, py_vectorize_targets, vectorize_target}, | ||
| output::{self, write_json, write_parquet}, | ||
@@ -27,3 +27,3 @@ smooth::{self}, | ||
| #[pyfunction] | ||
| fn encode_qual(qual: String, qual_offset: u8) -> Vec<u8> { | ||
| fn encode_qual(qual: String, qual_offset: u8) -> Vec<usize> { | ||
| let quals = qual.as_bytes(); | ||
@@ -34,3 +34,3 @@ quals | ||
| // Convert ASCII to Phred score for Phred+33 encoding | ||
| q - qual_offset | ||
| (q - qual_offset) as usize | ||
| }) | ||
@@ -49,3 +49,3 @@ .collect() | ||
| fn register_default_module(parent_module: &Bound<'_, PyModule>) -> PyResult<()> { | ||
| let child_module = PyModule::new_bound(parent_module.py(), "default")?; | ||
| let child_module = PyModule::new(parent_module.py(), "default")?; | ||
| child_module.add("QUAL_OFFSET", QUAL_OFFSET)?; | ||
@@ -62,2 +62,3 @@ child_module.add("BASES", String::from_utf8_lossy(BASES))?; | ||
| #[new] | ||
| #[pyo3(signature= (option, tensor_max_width=None, tensor_max_seq_len=None))] | ||
| fn py_new( | ||
@@ -173,2 +174,3 @@ option: fq_encode::FqEncoderOption, | ||
| #[pyfunction] | ||
| #[pyo3(signature = (records_data, file_path=None))] | ||
| fn write_fq(records_data: Vec<PyRecordData>, file_path: Option<PathBuf>) -> Result<()> { | ||
@@ -216,2 +218,3 @@ let records: Vec<fq_encode::RecordData> = records_data | ||
| #[pyfunction] | ||
| #[pyo3(signature = (start, end, k, seq_len=None))] | ||
| fn to_kmer_target_region( | ||
@@ -281,2 +284,12 @@ start: usize, | ||
| #[pyfunction] | ||
| #[pyo3(signature = ( | ||
| fq_paths, | ||
| k, | ||
| bases, | ||
| qual_offset, | ||
| vectorized_target, | ||
| parallel_for_files, | ||
| max_width=None, | ||
| max_seq_len=None | ||
| ))] | ||
| fn encode_fq_paths_to_tensor( | ||
@@ -320,5 +333,5 @@ py: Python, | ||
| Ok(( | ||
| input.into_pyarray_bound(py), | ||
| target.into_pyarray_bound(py), | ||
| qual.into_pyarray_bound(py), | ||
| input.into_pyarray(py), | ||
| target.into_pyarray(py), | ||
| qual.into_pyarray(py), | ||
| kmer2id, | ||
@@ -330,2 +343,11 @@ )) | ||
| #[pyfunction] | ||
| #[pyo3(signature = ( | ||
| fq_path, | ||
| k, | ||
| bases, | ||
| qual_offset, | ||
| vectorized_target, | ||
| max_width=None, | ||
| max_seq_len=None | ||
| ))] | ||
| fn encode_fq_path_to_tensor( | ||
@@ -368,5 +390,5 @@ py: Python, | ||
| Ok(( | ||
| input.into_pyarray_bound(py), | ||
| target.into_pyarray_bound(py), | ||
| qual.into_pyarray_bound(py), | ||
| input.into_pyarray(py), | ||
| target.into_pyarray(py), | ||
| qual.into_pyarray(py), | ||
| kmer2id, | ||
@@ -377,2 +399,3 @@ )) | ||
| #[pyfunction] | ||
| #[pyo3(signature = (fq_path, k, bases, qual_offset, vectorized_target, result_path=None))] | ||
| fn encode_fq_path_to_json( | ||
@@ -436,2 +459,3 @@ fq_path: PathBuf, | ||
| #[pyfunction] | ||
| #[pyo3(signature = (fq_path, k, bases, qual_offset, vectorized_target, result_path=None))] | ||
| fn encode_fq_path_to_parquet( | ||
@@ -503,2 +527,14 @@ fq_path: PathBuf, | ||
| #[pyfunction] | ||
| #[pyo3(signature = ( | ||
| internal_fq_path, | ||
| terminal_fq_path, | ||
| negative_fq_path, | ||
| total_reads, | ||
| train_ratio, | ||
| val_ratio, | ||
| test_ratio, | ||
| internal_adapter_ratio, | ||
| positive_ratio, | ||
| prefix=None | ||
| ))] | ||
| fn collect_and_split_dataset( | ||
@@ -532,2 +568,16 @@ internal_fq_path: PathBuf, | ||
| #[pyfunction] | ||
| #[pyo3(signature = ( | ||
| internal_fq_path, | ||
| terminal_fq_path, | ||
| natural_terminal_fq_path, | ||
| negative_fq_path, | ||
| total_reads, | ||
| train_ratio, | ||
| val_ratio, | ||
| test_ratio, | ||
| internal_adapter_ratio, | ||
| natural_terminal_adapter_ratio, | ||
| positive_ratio, | ||
| prefix=None | ||
| ))] | ||
| fn collect_and_split_dataset_with_natural_terminal_adapters( | ||
@@ -562,4 +612,22 @@ internal_fq_path: PathBuf, | ||
| } | ||
| #[allow(clippy::too_many_arguments)] | ||
| #[pyfunction] | ||
| #[pyo3(signature = ( | ||
| internal_fq_path, | ||
| terminal_fq_path, | ||
| natural_terminal_fq_path, | ||
| both_fq_path, | ||
| negative_fq_path, | ||
| total_reads, | ||
| train_ratio, | ||
| val_ratio, | ||
| test_ratio, | ||
| internal_adapter_ratio, | ||
| terminal_adapter_ratio, | ||
| both_terminal_adapter_ratio, | ||
| natural_terminal_adapter_ratio, | ||
| positive_ratio, | ||
| prefix=None | ||
| ))] | ||
| fn collect_and_split_dataset_with_natural_terminal_adapters_and_both_adapters( | ||
@@ -566,0 +634,0 @@ internal_fq_path: PathBuf, |
+0
-23
@@ -185,24 +185,1 @@ use std::fs::File; | ||
| } | ||
| #[cfg(test)] | ||
| mod tests { | ||
| use super::*; | ||
| #[test] | ||
| fn test_blat() { | ||
| let seq = "TCCCTCCCACCCCCTCTCCATCATCCATATCATCCCACATCCTCCTATCCC"; | ||
| let blat_cli = "/projects/b1171/ylk4626/project/DeepChopper/tmp/blat"; | ||
| let hg38_2bit = "/projects/b1171/ylk4626/project/scan_data/hg38.2bit"; | ||
| let _result = blat(seq, blat_cli, hg38_2bit, None).unwrap(); | ||
| } | ||
| #[test] | ||
| fn test_parse_psl() { | ||
| let file = "output2.psl"; | ||
| let seq = "TCCCTCCCACCCCCTCTCCATCATCCATATCATCCCACATCCTCCTATCCC"; | ||
| let blat_cli = "/projects/b1171/ylk4626/project/DeepChopper/tmp/blat"; | ||
| let hg38_2bit = "/projects/b1171/ylk4626/project/scan_data/hg38.2bit"; | ||
| let alignments = blat(seq, blat_cli, hg38_2bit, Some(file)).unwrap(); | ||
| println!("{:?}", alignments); | ||
| } | ||
| } |
@@ -51,2 +51,3 @@ use std::ops::Range; | ||
| #[new] | ||
| #[pyo3(signature=(prediction, seq, id, is_truncated, qual=None))] | ||
| pub fn new( | ||
@@ -127,2 +128,3 @@ prediction: Vec<i8>, | ||
| #[pyo3(signature=(smooth_interval, text_width = None))] | ||
| pub fn show_info( | ||
@@ -155,8 +157,8 @@ &self, | ||
| // Convert JSON string to Python bytes | ||
| Ok(PyBytes::new_bound(py, serialized.as_bytes()).into()) | ||
| Ok(PyBytes::new(py, serialized.as_bytes()).into()) | ||
| } | ||
| fn __setstate__(&mut self, py: Python, state: PyObject) -> PyResult<()> { | ||
| // Expect a bytes object for state | ||
| let state_bytes: &PyBytes = state.extract(py)?; | ||
| // Convert PyObject to PyBytes | ||
| let state_bytes = state.downcast_bound::<PyBytes>(py)?; | ||
@@ -214,2 +216,3 @@ // Deserialize the JSON string into the current instance | ||
| #[pyfunction] | ||
| #[pyo3(signature = (pt_path, ignore_label = -100, max_predicts = None))] | ||
| pub fn load_predicts_from_batch_pts( | ||
@@ -226,3 +229,3 @@ pt_path: PathBuf, | ||
| .filter_map(|e| e.ok()) | ||
| .filter(|e| e.path().extension().map_or(false, |ext| ext == "pt")) | ||
| .filter(|e| e.path().extension().is_some_and(|ext| ext == "pt")) | ||
| .collect(); | ||
@@ -229,0 +232,0 @@ |
@@ -160,3 +160,3 @@ use anyhow::Result; | ||
| // Convert JSON string to Python bytes | ||
| Ok(PyBytes::new_bound(py, serialized.as_bytes()).into()) | ||
| Ok(PyBytes::new(py, serialized.as_bytes()).into()) | ||
| } | ||
@@ -166,3 +166,3 @@ | ||
| // Expect a bytes object for state | ||
| let state_bytes: &PyBytes = state.extract(py)?; | ||
| let state_bytes = state.downcast_bound::<PyBytes>(py)?; | ||
@@ -169,0 +169,0 @@ // Deserialize the JSON string into the current instance |
@@ -44,3 +44,3 @@ use ahash::HashMap; | ||
| // Adjust window size to be odd | ||
| let window_size = if window_size % 2 == 0 { | ||
| let window_size = if window_size.is_multiple_of(2) { | ||
| window_size + 1 | ||
@@ -47,0 +47,0 @@ } else { |
+12
-12
@@ -134,9 +134,9 @@ use anyhow::Result; | ||
| .map(BufReader::new) | ||
| .map(fastq::Reader::new)?; | ||
| .map(fastq::io::Reader::new)?; | ||
| let mut terminal_fq_reader = File::open(terminal_fq_path.as_ref()) | ||
| .map(BufReader::new) | ||
| .map(fastq::Reader::new)?; | ||
| .map(fastq::io::Reader::new)?; | ||
| let mut negative_fq_reader = File::open(negative_fq_path.as_ref()) | ||
| .map(BufReader::new) | ||
| .map(fastq::Reader::new)?; | ||
| .map(fastq::io::Reader::new)?; | ||
@@ -311,12 +311,12 @@ let train_data_path = format!("train{}.fq", prefix.unwrap_or_default()); | ||
| .map(BufReader::new) | ||
| .map(fastq::Reader::new)?; | ||
| .map(fastq::io::Reader::new)?; | ||
| let mut terminal_fq_reader = File::open(terminal_fq_path.as_ref()) | ||
| .map(BufReader::new) | ||
| .map(fastq::Reader::new)?; | ||
| .map(fastq::io::Reader::new)?; | ||
| let mut natural_terminal_fq_reader = File::open(natural_terminal_fq_path.as_ref()) | ||
| .map(BufReader::new) | ||
| .map(fastq::Reader::new)?; | ||
| .map(fastq::io::Reader::new)?; | ||
| let mut negative_fq_reader = File::open(negative_fq_path.as_ref()) | ||
| .map(BufReader::new) | ||
| .map(fastq::Reader::new)?; | ||
| .map(fastq::io::Reader::new)?; | ||
@@ -527,15 +527,15 @@ let train_data_path = format!("train{}.fq", prefix.unwrap_or_default()); | ||
| .map(BufReader::new) | ||
| .map(fastq::Reader::new)?; | ||
| .map(fastq::io::Reader::new)?; | ||
| let mut terminal_fq_reader = File::open(terminal_fq_path.as_ref()) | ||
| .map(BufReader::new) | ||
| .map(fastq::Reader::new)?; | ||
| .map(fastq::io::Reader::new)?; | ||
| let mut natural_terminal_fq_reader = File::open(natural_terminal_fq_path.as_ref()) | ||
| .map(BufReader::new) | ||
| .map(fastq::Reader::new)?; | ||
| .map(fastq::io::Reader::new)?; | ||
| let mut both_fq_reader = File::open(both_fq_path.as_ref()) | ||
| .map(BufReader::new) | ||
| .map(fastq::Reader::new)?; | ||
| .map(fastq::io::Reader::new)?; | ||
| let mut negative_fq_reader = File::open(negative_fq_path.as_ref()) | ||
| .map(BufReader::new) | ||
| .map(fastq::Reader::new)?; | ||
| .map(fastq::io::Reader::new)?; | ||
@@ -542,0 +542,0 @@ let train_data_path = format!("train{}.fq", prefix.unwrap_or_default()); |
+1
-0
@@ -6,2 +6,3 @@ use colored::Colorize; | ||
| #[pyfunction] | ||
| #[pyo3(signature = (sequence, targets, text_width = None))] | ||
| pub fn highlight_targets( | ||
@@ -8,0 +9,0 @@ sequence: &str, |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
121072380
0.52%253
4.98%12458
85.94%