Full Code of BioOmics/iSeq for AI

main fb3f19bdbedc cached
24 files
1.2 MB
818.5k tokens
1 requests
Download .txt
Showing preview only (1,318K chars total). Download the full file or copy to clipboard to get everything.
Repository: BioOmics/iSeq
Branch: main
Commit: fb3f19bdbedc
Files: 24
Total size: 1.2 MB

Directory structure:
gitextract_o5hgf_3g/

├── INSTALL.md
├── LICENSE
├── README.md
├── bin/
│   └── iseq
├── docs/
│   ├── ChineseTutorial.md
│   ├── Examples.md
│   └── benchmark/
│       ├── README.md
│       ├── TestFasterqDump/
│       │   ├── testFasterqDump.log
│       │   └── timefasterqDump.sh
│       ├── TestiSeq-2GB/
│       │   ├── TestiSeq-2GB.bash
│       │   ├── timeENA.log
│       │   ├── timeFQ.log
│       │   ├── timeGSAFTP.log
│       │   ├── timeGSAHW.log
│       │   └── timeSRA.log
│       ├── TestiSeq-540MB/
│       │   ├── TestiSeq-540MB.bash
│       │   ├── timeENA.log
│       │   ├── timeFQ.log
│       │   ├── timeGSAFTP.log
│       │   ├── timeGSAHW.log
│       │   └── timeSRA.log
│       ├── benchmark.ipynb
│       └── iSeq-Table S1.xlsx
└── iSeq.yml

================================================
FILE CONTENTS
================================================

================================================
FILE: INSTALL.md
================================================
## Install the latest version of iSeq

```bash
version="1.9.8"
wget "https://github.com/BioOmics/iSeq/releases/download/v${version}/iSeq-v${version}.tar.gz"
tar -zvxf "iSeq-v${version}.tar.gz"
cd iSeq-v${version}/bin/
chmod +x iseq
echo 'export PATH=$PATH:'$(pwd) >> ~/.bashrc
source ~/.bashrc
```

Anyway, as long as you install the following dependencies and **add them to the environment variables**, **iSeq** can be used.

- [pigz](https://github.com/madler/pigz) (>=2.8), compressing FASTQ files into gzip format by multiple threads
- [wget](https://www.gnu.org/software/wget/) (>=1.16), downloading files by ftp or http
- [axel](https://github.com/axel-download-accelerator/axel) (>=2.17), downloading files by multiple threads
- [aspera](https://github.com/IBM/aspera-cli) (=4.4.0), downloading files by Aspera
- [sra-tools](https://github.com/ncbi/sra-tools) (>=2.11.0), fetching SRA download links

```{bash}
# all softwares can be installed by conda
conda create -n iseq -c conda-forge -c bioconda pigz wget axel aspera-cli sra-tools
# Check sotfware version
pigz --version | awk 'NR==1{print $2}'
wget --version | awk 'NR==1{print $3}'
axel --version | awk 'NR==1{print $2}'
ascp --version | awk 'NR==2{print $3}'
srapath --version | awk 'NR==2{print $3}'
# Use the following command to check whether dependent software is installed
iseq --version
```

> [!IMPORTANT]
> Using **Ubuntu on Windows**, installing `Wget` through `conda` may lead to "unable to resolve host address", which in turn may prevent `iSeq` from fetching data. You can don't install `wget` by `conda`. Or, this issue also can be resolved by following command:
> ```bash
> conda activate iseq
> # Map the system's built-in wget to the conda environment, ensuring that wget is properly installed.
> ln -sf /usr/bin/wget $(which wget)
> # Including the 'srapath'. you can install SRA Toolkit and then change the path below to your own.
> ln -sf ~/YourPathway/sratoolkit/bin/srapath $(which srapath)

## How to install dependencies from source on Linux/macOS

### 1. pigz

- Source install (non-Root)

```bash
wget https://zlib.net/pigz/pigz.tar.gz
tar -zvxf pigz.tar.gz
cd pigz
make
echo 'export PATH=$PATH:'$(pwd) >> ~/.bashrc
source ~/.bashrc
# Check sotfware version
pigz --version | awk 'NR==1{print $2}'
```

- apt install for Ubuntu (Root permission required)

```bash
sudo apt install pigz
```

- yum install for Centos (Root permission required)

```bash
sudo yum install pigz
```

- brew install for macOS (non-Root)

```bash
brew install pigz
```

### 2. wget

**`wget` is generally included in most Linux distributions and does not need to be installed by ourselves**

- Source install (non-Root)

```bash
wget https://ftp.gnu.org/gnu/wget/wget-latest.tar.gz
tar -zvxf wget-latest.tar.gz
cd wget-1.24.5 # change software version
./configure --prefix=$(pwd)
make
cd src
echo 'export PATH=$PATH:'$(pwd) >> ~/.bashrc
source ~/.bashrc
# Check sotfware version
wget --version | awk 'NR==1{print $3}'
```

- apt install for Ubuntu (Root permission required)

```bash
sudo apt install wget
```

- yum install for Centos (Root permission required)

```bash
sudo yum install wget
```

- brew install for macOS (non-Root)

```bash
brew install wget
```

### 3. axel

- Source install (non-Root)

```bash
# see "https://github.com/axel-download-accelerator/axel/releases" to fetch the latest version of axel
wget https://github.com/axel-download-accelerator/axel/releases/download/v2.17.14/axel-2.17.14.tar.gz
tar -zvxf axel-2.17.14.tar.gz # change software version
cd axel-2.17.14 # change software version
./configure --prefix=$(pwd)
make && make install
echo 'export PATH=$PATH:'$(pwd) >> ~/.bashrc
source ~/.bashrc
# Check sotfware version
axel --version | awk 'NR==1{print $2}'
```

- apt install for Ubuntu (Root permission required)

```bash
sudo apt install axel
```

- yum install for Centos (Root permission required)

```bash
sudo yum install axel
```

- brew install for macOS (non-Root)

```bash
brew install axel
```

### 4. aspera

- Source install (only support non-Root)

```bash
# see "https://www.ibm.com/aspera/connect" to fetch the latest version of aspera
wget https://d3gcli72yxqn2z.cloudfront.net/downloads/connect/latest/bin/ibm-aspera-connect_4.2.8.540_linux_x86_64.tar.gz
tar -zvxf ibm-aspera-connect_4.2.8.540_linux_x86_64.tar.gz # change software version
bash ibm-aspera-connect_4.2.8.540_linux_x86_64.sh # change software version
echo 'export PATH=$PATH:~/.aspera/connect/bin' >> ~/.bashrc
source ~/.bashrc
# Check sotfware version
ascp --version | awk 'NR==2{print $3}'
```

- brew & ruby install for macOS (non-Root)

```bash
brew install ruby
export PATH="$HOMEBREW_PREFIX/opt/ruby/bin:$PATH"
gem install aspera-cli
export PATH="$HOMEBREW_PREFIX/lib/ruby/gems/3.4.0/bin:$PATH"
ascli config ascp install
mkdir -p $HOME/.local/bin
cp $HOME/.aspera/sdk/ascp $HOME/.local/bin
```

### 5. sra-tools

- Source install (non-Root)

```bash
# see "https://ftp-trace.ncbi.nlm.nih.gov/sra/sdk/current" to choose the appropriate platform
# e.g. for Ubuntu
wget https://ftp-trace.ncbi.nlm.nih.gov/sra/sdk/current/sratoolkit.current-ubuntu64.tar.gz
tar -zvxf sratoolkit.current-ubuntu64.tar.gz
cd sratoolkit.3.1.0-ubuntu64/bin/ # change software version
echo 'export PATH=$PATH:'$(pwd) >> ~/.bashrc
source ~/.bashrc
# Check sotfware version
srapath --version | awk 'NR==2{print $3}'
```

- brew install for macOS (non-Root)

```bash
brew install sratoolkit
```

## Check iSeq version finally

```bash
iseq --version
```






================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2024 BioOmics

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

================================================
FILE: README.md
================================================
[![Anaconda-Server Badge](https://anaconda.org/bioconda/iseq/badges/version.svg)](https://anaconda.org/bioconda/iseq)
[![Anaconda-Server Badge](https://anaconda.org/bioconda/iseq/badges/downloads.svg)](https://anaconda.org/bioconda/iseq)
[![Anaconda-Server Badge](https://anaconda.org/bioconda/iseq/badges/latest_release_date.svg)](https://anaconda.org/bioconda/iseq)
[![Anaconda-Server Badge](https://anaconda.org/bioconda/iseq/badges/license.svg)](https://anaconda.org/bioconda/iseq)
[![Anaconda-Server Badge](https://anaconda.org/bioconda/iseq/badges/platforms.svg)](https://anaconda.org/bioconda/iseq)
[![GitHub Downloads](https://img.shields.io/github/downloads/BioOmics/iSeq/total.svg?style=social&logo=github&label=Download)](https://github.com/BioOmics/iSeq/releases)

# [iSeq](https://github.com/BioOmics/iSeq): An [i](https://github.com/BioOmics/iSeq)ntegrated tool to fetch public [Seq](https://github.com/BioOmics/iSeq)uencing data
**Cite us**: Haoyu Chao, Zhuojin Li, Dijun Chen, Ming Chen, iSeq: An integrated tool to fetch public sequencing data, ***Bioinformatics***, 2024, btae641, https://doi.org/10.1093/bioinformatics/btae641
        
        
        
        
        
        
        
        
        
        
        
        
## Description

**iSeq** is a Bash script that allows you to download sequencing data and metadata from **[GSA](https://ngdc.cncb.ac.cn/gsa/)**, **[SRA](https://www.ncbi.nlm.nih.gov/sra/)**, **[ENA](https://www.ebi.ac.uk/ena/)**, and **[DDBJ](https://www.ddbj.nig.ac.jp/)** databases. See [Detail Pipeline](https://github.com/BioOmics/iSeq/blob/main/docs/img/iSeq-Pipeline-Detail.png) for iSeq. Here is the basic pipeline of iSeq: 

![iSeq-pipeline](https://github.com/BioOmics/iSeq/blob/main/docs/img/iSeq-Pipeline.png)

> [!IMPORTANT]
> To use iSeq, Your system must be **connected to the network** and **support FTP, HTTP, and HTTPS protocols**.

## Update Notes:

### 2025.11.20
- **⚠️Update Notice**: Due to recent changes in the **GSA API**, we have updated the way iseq retrieves metadata. The metadata fetching process has been modified accordingly to ensure compatibility with the latest GSA API. **Everyone please update iSeq version (≥ 1.9.8)**

<details>
<summary>More Updates</summary>

### 2025.10.21
- **New `-Q`, `--quiet` option**: Added this option to suppress download progress bars. Useful when logging clean outputs.
- Fixed a bug where `--database` option failed to switch when ENA was inaccessible.
- If the MD5 check ultimately fails, delete the partially downloaded files.

### 2025.10.09
- Fixed a bug when checking md5 of SRA files.

### 2025.09.04
- **⚠️Update Notice**: Due to recent changes in the **ENA API**, we have updated the way iseq retrieves metadata. The metadata fetching process has been modified accordingly to ensure compatibility with the latest ENA API. **Everyone please update iSeq version (≥ 1.9.5)**

### 2025.07.22
- **New `-r`, `--protocol` option** to specify the protocol only when downloading files from ENA.

### 2025.06.16
- When using `-e`, `--merge`, create symbolic links or retain the original Run files to avoid re-downloading them after merging.  
- Fixed the issue mentioned in [#40](https://github.com/BioOmics/iSeq/issues/40): modified the behavior so that batch downloads do not terminate upon encountering an error, and instead continue until all items are processed.  
- Added an error message when download failures occur, such as `Download failures detected, please check fail.log for details.`  
- Fixed a bug where incomplete downloads from GSA were incorrectly reported as successful.

### 2025.05.23
- Fixed the issue mentioned in [#39](https://github.com/BioOmics/iSeq/issues/39). The problem was that using both `-d sra` and `-g` together would skip the MD5 check in `vdb-validate`.
- **New `-k`, `--skip-md5` option**: Added this option to disable MD5 checks.

### 2025.04.25
- Fixed a bug that occurred when re-downloading with empty metadata.  
- Fixed a bug where the while loop exited abnormally with a non-zero exit code.  

### 2025.04.22
- Fixed the issue mentioned in [#33](https://github.com/BioOmics/iSeq/issues/33). `-s`, `--speed` re-enable use.
- Fix the exception when the metadata file is empty, mentioned in [#34](https://github.com/BioOmics/iSeq/issues/34)
- Bug fix to resolve the issue of MD5 checksum failure when downloading ONT or HiFi third-generation sequencing gzip data.

### 2025.04.02
- Fixed the issue mentioned in [#27](https://github.com/BioOmics/iSeq/issues/27) and [Rednote](http://xhslink.com/a/A0TnUnKlvVg9): In `sra-tools` > 3.0.0, running `vdb-validate` without specifying the SRA file path causes it to re-download the file, leading to a stuck process. Specifying the path (e.g., `vdb-validate ./SRR931847`) resolves the issue.

### 2025.03.14
- Fixed the issue mentioned in [#26](https://github.com/BioOmics/iSeq/issues/26#issuecomment-2721427208). The cause was that the data was `paired-end` but had only `one link`, such as `SRR23680070`.

### 2025.03.11
- Input file can contain accessions from different databases.
- `-p` and `-a` can be used simultaneously , with `-a` taking priority.
- Fixed some bugs when retrying download data from GSA.
	
### 2024.12.26
- Fixed the bugs mentioned in [#16](https://github.com/BioOmics/iSeq/issues/16), [#17](https://github.com/BioOmics/iSeq/issues/17) (2024.12.16) and https://github.com/BioOmics/iSeq/issues/19 (2024.12.26).

### 2024.11.21
-  **Dependency update for aspera-cli**:
The version requirement for aspera-cli has been updated from `aspera-cli` to `aspera-cli=4.14.0`.

### 2024.10.23
- **New `-s`, `--speed` option** to set the download speed limit (MB/s) (default: 1000 MB/s). Such as `iseq -i SRR7706354 -s 10`
-  **Dependency update for sra-tools**:
The version requirement for sra-tools has been updated from `sra-tools=2.11` to `sra-tools>=2.11.0`.


### 2024.09.14
-  **New `-e` option for merging FASTQ files**:
Added a `-e` option to merge multiple FASTQ files into a single file for each `Experiment (-e ex)`, `Sample (-e sa)`, or `Study (-e st)`.

-  **New `-i` option for input**:
`iSeq` can now accept a `file` containing multiple accession numbers as input by `-i fileName`.

-  **API change for GSA metadata download**:
The API endpoint has been updated from `getRunInfo` to `getRunInfoByCra` for downloading GSA metadata.


	
-  **Save result to personal directory**:
The output results will now be saved in the user's personal directory by `-o` option.

-  **Updated regex for SAMC matching**:
The matching pattern for SAMC has been changed from `SAMC[A-Z]?[0-9]+` to `SAMC[0-9]+`.

- **Fix some bugs**

</details>




## Features
-  **Multiple Database Support**: Supports multiple bioinformatics databases (GSA/SRA/ENA/DDBJ/GEO).
-  **Multiple Input Formats**: Supports multiple accessions (Project, Study, Sample, Experiment, or Run accession).
-  **Metadata Download**: Supports download sample metadata for each accession.
<details>
<summary>More features</summary>
	
-  **File Format Selection**: Users can choose to directly download gzip-formatted FASTQ files or download SRA files and convert them to FASTQ format.
-  **Multi-threading Support**: Supports the use of multi-threading to accelerate the conversion of SRA to FASTQ files or the compression of FASTQ files.
-  **File Merging**: For experiment-level accession, the script can merge multiple FASTQ files into one.
-  **Parallel Download**: Supports parallel download connections, allowing the specification of the number of connections to speed up download speeds.
-  **Support for Aspera High-speed Download**: For GSA/ENA databases, the script supports high-speed data transfer using Aspera.
-  **Automatic Retry Mechanism**: If a download or verification fails, the script will automatically retry until a set number of attempts have been reached.
-  **Automated File Verification**: After the download is complete, the script will automatically verify the integrity of the files, including checking file sizes and MD5 checksums.
-  **Error Handling**: The script provides error messages and suggestions for solutions when encountering errors.
</details>

## Installation

### 1. **iSeq** can be installed by conda easily
```{bash}
conda install bioconda::iseq
```
- If conda Found conflicts! You can try `conda install -c conda-forge -c bioconda iseq`

### 2. The latest version of iSeq can also be installed from source, see [INSTALL](https://github.com/BioOmics/iSeq/blob/main/INSTALL.md)
```{bash}
# Use the following command to check whether dependent software is installed
iseq --version
```
## Example ([See more](https://github.com/BioOmics/iSeq/blob/main/docs/Examples.md))

1. Download all Run sequencing data and metadata associated with an accession.

```
iseq -i PRJNA211801
```

![e01](./docs/img/e01.png)

2. Batch download by Aspera with `-a` to directly download gzip-formatted FASTQ files with `-g`.

```bash
iseq -i SRR_Acc_List.txt -a -g
```

![e13](./docs/img/e13.png)


## Usage  ([中文教程](https://github.com/BioOmics/iSeq/blob/main/docs/ChineseTutorial.md)✨)

```{bash}
$ iseq --help

Usage:
  iseq -i accession [options]

Required option:
  -i, --input     [text|file]   Single accession or a file containing multiple accessions.
                                Note: Only one accession per line in the file

Optional options:
  -m, --metadata                Skip the sequencing data downloads and only fetch the metadata for the accession.
  -g, --gzip                    Download FASTQ files in gzip format directly (*.fastq.gz).
                                Note: if *.fastq.gz files are not available, SRA files will be downloaded and converted to *.fastq.gz files.
  -q, --fastq                   Convert SRA files to FASTQ format.
  -t, --threads   int           The number of threads to use for converting SRA to FASTQ files or compressing FASTQ files (default: 8).
  -e, --merge     [ex|sa|st]    Merge multiple fastq files into one fastq file for each Experiment, Sample or Study.
  -d, --database  [ena|sra]     Specify the database to download SRA sequencing data (default: ena).
                                Note: new SRA files may not be available in the ENA database, even if you specify "ena".
  -p, --parallel  int           Download sequencing data in parallel, the number of connections needs to be specified, such as -p 10.
                                Note: breakpoint continuation cannot be shared between different numbers of connections.
  -a, --aspera                  Use Aspera to download sequencing data, only support GSA/ENA database.
  -s, --speed     int           Download speed limit (MB/s) (default: 1000 MB/s).
  -k, --skip-md5                Skip the md5 check for the downloaded files.
  -r, --protocol  [ftp|https]   Specify the protocol only when downloading files from ENA (default: ftp).
  -Q, --quiet                   Suppress download progress bars.
  -o, --output    text          The output directory. If not exists, it will be created (default: current directory).
  -h, --help                    Show the help information.
  -v, --version                 Show the script version.
```

### 1. `-i`, `--input`

Input the accession you want to download, You also can input a file containing multiple accessions (Only one accession per line in the file).

```bash
iseq -i PRJNA211801
```
Firstly, **iSeq** will retrieve the metadata of the accession, then proceed to download each Run contained within. 

Currently **supports 6 accession formats** from the following **5 databases**, with supported accession prefixes as follows:

| Databases | BioProject | Study | BioSample | Sample | Experiment | Run  |
| --------- | ---------- | ----- | --------- | ------ | ---------- | ---- |
| **GSA**   | PRJC       | CRA   | SAMC      | \      | CRX        | CRR  |
| **SRA**   | PRJNA      | SRP   | SAMN      | SRS    | SRX        | SRR  |
| **ENA**   | PRJEB      | ERP   | SAME      | ERS    | ERX        | ERR  |
| **DDBJ**  | PRJDB      | DRP   | SAMD      | DRS    | DRX        | DRR  |
| **GEO**   | GSE        | \     | GSM       | \      | \          | \    |

Additionally, for the two data formats (`GSE/GSM`) from the GEO database, it will directly retrieve the associated `PRJNA/SAMN`, then proceed to obtain the contained Runs and download the sequencing data. Therefore, essentially, it still downloads sequencing data from the SRA database.

Here are some examples:

| Accession Type | Prefixes                       | Example                                                     |
| -------------- | ------------------------------ | ----------------------------------------------------------- |
| BioProject     | PRJEB, PRJNA, PRJDB, PRJC, GSE | PRJEB42779, PRJNA480016, PRJDB14838, PRJCA000613, GSE122139 |
| Study          | ERP, DRP, SRP, CRA             | ERP126685, DRP009283, SRP158268, CRA000553                  |
| BioSample      | SAMD, SAME, SAMN, SAMC         | SAMD00258402, SAMEA7997453, SAMN06479985, SAMC017083        |
| Sample         | ERS, DRS, SRS, GSM             | ERS5684710, DRS259711, SRS2024210, GSM7417667               |
| Experiment     | ERX, DRX, SRX, CRX             | ERX5050800, DRX406443, SRX4563689, CRX020217                |
| Run            | ERR, DRR, SRR, CRR             | ERR5260405, DRR421224, SRR7706354, CRR311377                |

In summary, regardless of the data format of your accession among the six options, it will eventually download and **check the MD5 value** of each contained Run. If the MD5 value does not match that in the public database, it will attempt a maximum of **three rounds** of re-downloading. If successful after three attempts of downloading and verification, the file name will be stored in `success.log`; otherwise, if the download fails, the file name will be stored in `fail.log`.

### 2. `-m`, `--metadata `

Download only the sample information of the accession and skip the download of sequencing data.

```bash
iseq -i PRJNA211801 -m
iseq -i CRR343031 -m
```
Therefore, regardless of whether the `-m` parameter is used or not, the sample information of the accession will be obtained. If metadata cannot be retrieved, the **iSeq** program will exit without proceeding to the subsequent download.

> [!NOTE]
> **Note 1**: If the retrieved accession is in the **SRA/ENA/DDBJ/GEO** databases, **iSeq** will first search in the ENA database. If sample information can be retrieved, it will download metadata in **`TSV` format** via the [ENA API](https://www.ebi.ac.uk/ena/portal/api/swagger-ui/index.html), typically containing 191 columns. However, some recently released data in the SRA database may not be promptly synchronized to the ENA database. Therefore, if metadata cannot be obtained from the ENA database, **iSeq** will directly download metadata in **`CSV` format** via the [SRA Database Backend](https://trace.ncbi.nlm.nih.gov/Traces/sra-db-be/), typically containing 30 columns. To maintain consistency with the TSV format, it will be converted to TSV format using `sed -i 's/,/\t/g'`. However, if a single field contains a comma, it may cause column disorder. Ultimately, you will obtain sample information named **`${accession}.metadata.tsv`**.

> [!NOTE]
> **Note 2**: If the retrieved accession is in the **GSA** database, **iSeq** will obtain sample information via GSA's [getRunInfo](https://ngdc.cncb.ac.cn/gsa/search/getRunInfo) interface, downloading metadata in **`CSV` format**, typically containing 25 columns. The metadata obtained above will be saved as `${accession}.metadata.csv`. To supplement more detailed metadata information, iSeq will automatically obtain metadata information for the Project to which the accession belongs via GSA's [exportExcelFile](https://ngdc.cncb.ac.cn/gsa/file/exportExcelFile) interface, downloading metadata in **`XLSX`** format, typically with 3 sheets: `Sample`, `Experiment`, `Run`. The final metadata information will be saved as `${accession}.metadata.xlsx`. In summary, you will ultimately obtain sample information named **`${accession}.metadata.csv`** and **`CRA*.metadata.xlsx`**.

### 3. `-g`, `--gzip`

Directly download FASTQ files in **gzip format**. If direct download is not possible, SRA files will be downloaded and converted to gzip format using multi-threading for decomposition and compression.

```bash
iseq -i SRR1178105 -g
```
Since the majority of data formats stored directly in the **GSA** database are in gzip format, if the accession being searched for is from the GSA database, whether the `-g` parameter is used or not, you can directly download FASTQ files in gzip format. 

If the accession is from the **SRA/ENA/DDBJ/GEO** databases, **iSeq** will first attempt to access the ENA database. If it can directly download FASTQ files in gzip format, it will do so; otherwise, it will download SRA files and convert them to FASTQ format using the `fasterq-dump` tool, then compress the FASTQ files using the `pigz` tool, ultimately obtaining FASTQ files in gzip format.

> [!TIP]
> [parallel-fastq-dump](https://github.com/rvalieris/parallel-fastq-dump) can also convert SRA to gzip-compressed FASTQ files, typically **2-3 times** faster than `fasterq-dump + pigz`. However, considering **IO limitations**, `iSeq` currently does not support `parallel-fastq-dump`.

### 4. `-q`, `--fastq`

After downloading the SRA files, they will be decomposed into multiple **uncompressed FASTQ** files.

```bash
iseq -i SRR1178105 -q
```
This parameter is only effective when the accession is from the **SRA/ENA/DDBJ/GEO** databases and the downloaded files are **SRA files**. After downloading the SRA files, **iSeq** will use the `fasterq-dump` tool to convert them into FASTQ files. Additionally, you can specify the number of threads for conversion using the `-t` parameter.

> [!NOTE]
> **Note1**: `-q` is particularly useful for downloading **single-cell data**, especially for scATAC-Seq data, as it can effectively decompose the files into four parts: `I1`, `R1`, `R2`, `R3`. However, if FASTQ files are directly downloaded via the `-g` parameter, only `R1` and `R3` files will be obtained (e.g., [SRR13450125](https://www.ebi.ac.uk/ena/browser/view/SRR13450125)), which may cause issues during subsequent data analysis.

> [!NOTE]
> **Note 2**: When `-q` and `-g` are used together, the SRA file will first be downloaded, then converted to `FASTQ` files using the `fasterq-dump` tool, and finally compressed into gzip format using `pigz`. It does not directly download `FASTQ` files in gzip format, which is very useful for obtaining comprehensive single-cell data.

### 5. `-t`, `--threads`

Specifies the number of threads to use for decompressing SRA files into FASTQ files or compressing FASTQ files. The default value is `8`.

```bash
iseq -i SRR1178105 -q -t 10
```
Considering that sequencing data files are generally large, you can specify the number of threads for decomposition using the `-t` parameter. However, more threads does not necessarily mean better performance because excessive threads can lead to **high CPU or IO loads**, especially since `fasterq-dump` consumes a considerable amount of IO, potentially impacting the execution of other tasks. Based on the [benchmark evaluation](https://github.com/BioOmics/iSeq/blob/main/docs/img/benchmark.png), we recommend a maximum thread count of 15.

### 6. `-e`, `--merge`

Merge **multiple FASTQ** files into **one FASTQ** file for each Experiment (`ex`), Sample (`sa`) or Study (`st`) .

```bash
iseq -i SRX003906 -g -e ex
```
Although in most cases, an Experiment contains only one Run, some sequencing data may have multiple Runs within an Experiment (e.g., [SRX003906](https://www.ebi.ac.uk/ena/browser/view/SRX003906), [CRX020217](https://ngdc.cncb.ac.cn/gsa/search?searchTerm=CRX020217)). Hence, you can use the `-e` parameter to merge multiple FASTQ files from an Experiment into one. Considering paired-end sequencing, where `fastq_1` and `fastq_2` files need to be merged simultaneously and the sequence names in corresponding lines need to remain consistent, **iSeq** will merge multiple FASTQ files in the **same order**. Ultimately, for **single-end** sequencing data, a single file **`SRX*.fastq.gz`** will be generated, and for **paired-end** sequencing data, two files **`SRX*_1.fastq.gz`** and **`SRX*_2.fastq.gz`** will be generated.

> [!NOTE]
> **Note 1**: If the accession is a **Run ID**, the `-e` parameter cannot be used (see below). Currently, **iSeq** supports merging **both gzip-compressed and uncompressed FASTQ** files, but does not support merging files such as **BAM files and tar.gz** files.
- `-e ex`: merge all fastq files of the same **Experiment** into one fastq file. Accepted accession format: `ERX, DRX, SRX, CRX`.
- `-e sa`: merge all fastq files of the same **Sample** into one fastq file. Accepted accession format: `ERS, DRS, SRS, SAMC, GSM`.
- `-e st`: merge all fastq files of the same **Study** into one fastq file. Accepted accession format: `ERP, DRP, SRP, CRA`.

> [!NOTE]
> **Note 2**: Normally, when an Experiment contains only one Run, identical Runs should have the **same prefix**. For example, `SRR52991314_1.fq.gz` and `SRR52991314_2.fq.gz` have the same prefix `SRR52991314`. In this case, **iSeq** will directly **rename** them to **`SRX*_1.fastq.gz`** and **`SRX*_2.fastq.gz`**. However, there are exceptions, such as in [CRX006713](https://ngdc.cncb.ac.cn/gsa/search?searchTerm=CRX006713) where a Run `CRR007192` contains files with different prefixes. In such cases, **iSeq** will **rename** them as **`SRX*_original_filename`**, for example, they will be renamed as `CRX006713_CRD015671.gz` and `CRX006713_CRD015672.gz`.

### 7. `-d`, `--database`

Specifies the database for downloading SRA files, supporting **ENA** and **SRA** databases.

```bash
iseq -i SRR1178105 -d sra 
```
By default, **iSeq** will automatically detect available databases, so specifying the `-d` parameter is **usually unnecessary**. However, some SRA files may download **slowly** from the ENA database. In such cases, you can force downloading from the SRA database by specifying `-d sra`.

> [!NOTE]
> **Note**: If the corresponding SRA file is not found in the **ENA** database, even if the `-d ena` parameter is specified, **iSeq** will still automatically switch to downloading from the **SRA** database.

### 8. `-p`, `--parallel`

Enables **multi-threaded downloading** and requires specifying the number of threads.

```bash
iseq -i PRJNA211801 -p 10
```
Considering that `wget` may be slow in some cases, you can use the `-p` parameter to let **iSeq** utilize the `axel` tool for multi-threaded downloading.

> [!NOTE]
> **Note 1**: The **resumable download** feature of multi-threaded downloading is only effective within the **same thread**. That is, if the `-p 10` parameter is used for the first download, it must also be used for the second download to enable resumable download.

> [!NOTE]
> **Note 2**: As mentioned, **iSeq** will maintain 10 connections throughout the download process. Therefore, you will see multiple occurrences of the same `Connection * finished` popping up during the download process. This is because some connections are released immediately after completing the download and then new connections are established for downloading.

### 9. `-a`, `--aspera`

Use Aspera for downloading.

```bash
iseq -i PRJNA211801 -a -g
```
As Aspera offers faster download speeds, you can use the `-a` parameter to instruct **iSeq** to use the `ascp` tool for downloading. Unfortunately, Aspera downloading is currently **only supported by the GSA and ENA databases**. The **NCBI SRA** database cannot utilize Aspera for downloading as it predominantly employs Google Cloud and AWS Cloud technologies and other reasons, see [Avoid-using-ascp](https://github.com/ncbi/sra-tools/wiki/Avoid-using-ascp-directly-for-downloads).

> [!NOTE]
> **Note 1**: When accessing the **GSA** database, if download links from **Huawei Cloud** are available, **iSeq** will prioritize downloading through Huawei Cloud, even if the `-a` parameter is used. This is because Huawei Cloud offers faster and more stable download speeds. Therefore, when downloading GSA data, it's **recommended to use the `-a` paramete**r. This way, if access to Huawei Cloud is unavailable, downloading through the Aspera channel is still relatively fast. Otherwise, you'll have to resort to downloading via `wget` or `axel`, which are slower methods.

> [!NOTE]
> **Note 2**: Since `Aspera` requires a key file, **iSeq** will **automatically search for the key** file in the `conda` environment or the `~/.aspera` directory. If the key file is not found, downloading will not be possible.

### 10. `-o`, `--output`

The output directory. If not exists, it will be created (default: current directory).

### 11. `-s`, `--speed`

Download speed limit (MB/s) (default: 1000 MB/s) for `Wget`, `AXEL` and `Aspera`.

### 12 `-k`, `--skip-md5`

Starting from v1.9.2, you can choose to skip the MD5 file integrity check. If you want to perform the MD5 check again after skipping it, simply remove the `-k` parameter and run the same command.

### 13 `-r`, `--protocol`

Starting from v1.9.4, you can specify the protocol only when downloading files from ENA. This is because, in some cases, HTTPS can be faster than FTP.

### 14 `-Q`, `--quiet`

Starting from v1.9.7, you can use the `-Q` or `--quiet` option to suppress download progress bars and non-essential messages from all download and conversion tools (wget, axel, ascp, fasterq-dump), making batch processing or logging cleaner.

## Output

- If the query accession in **SRA/ENA/DDBJ/GEO** database, the following files will be generated:

| Output        | Description                                                  |
| ------------- | ------------------------------------------------------------ |
| SRA files     | Can be converted to FASTQ files using `-q` option            |
| .metadata.tsv | Metadata for query accession                                 |
| success.log   | Save the SRA file name that has been downloaded successfully |
| fail.log      | Save the SRA file name that has been downloaded failed       |

- If the query accession in **GSA** database, the following files will be generated:

| Output         | Description                                                  |
| -------------- | ------------------------------------------------------------ |
| GSA files      | Mostly in *.gz format, and a few are bam/tar/bz2 format      |
| .metadata.csv  | Metadata for query accession                                 |
| .metadata.xlsx | Metadata for Project including query accession in xlsx format |
| success.log    | Save the GSA file name that has been downloaded successfully |
| fail.log       | Save the GSA file name that has been downloaded failed       |


## Inspired 

**iSeq** was inspired by **[fastq-dl](https://github.com/rpetit3/fastq-dl), [fetchngs](https://github.com/nf-core/fetchngs), [pysradb](https://github.com/saketkc/pysradb), [Kingfisher](https://github.com/wwood/kingfisher-download)**. These excellent tools may also be very helpful. Below are multiple comparisons of different software: 

| Software name                                                | Program languages | Supported databases      | Supported accessions     | Supported formats        | Supported methods       | Fetch metadata | MD5 check | Resumable download | Parallel  download | Merge FASTQ | Skip downloaded | Conda installable | URL                                                 |
| ------------------------------------------------------------ | ----------------- | ------------------------ | ------------------------ | ------------------------ | ---------------------- | -------------- | --------- | ------------------ | ------------------ | ----------- | --------------- | ----------------- | --------------------------------------------------- |
| **iSeq**                                                     | Shell             | GSA, SRA, ENA, DDBJ, GEO | All                      | fq, fq.gz, sra, bam      | wget,  axel, aspera    | ✔              | ✔         | ✔                  | ✔                  | ✔           | ✔               | ✔                 | [🔗](https://github.com/BioOmics/iSeq)               |
| [edgeturbo](https://ngdc.cncb.ac.cn/ettrans/download/)       | C                 | GSA                      | All denied               | fq, fq.gz, bam           | edgeturbo download     | ❌              | ❌         | ✔                  | ❌                  | ❌           | ❌               | ❌                 | [🔗](https://ngdc.cncb.ac.cn/ettrans/download/)      |
| [SRA Toolkit](https://github.com/ncbi/sra-tools)             | C                 | SRA, ENA, DDBJ           | All denied expect Run ID | fq, fq.gz, sra           | prefetch               | ❌              | ✔         | ✔                  | ❌                  | ❌           | ✔               | ✔                 | [🔗](https://github.com/ncbi/sra-tools)              |
| [enaBrowserTools](https://github.com/enasequence/enaBrowserTools) | Python            | SRA, ENA, DDBJ           | All except GSA/GEO ID    | fq, fq.gz, sra           | urllib, aspera         | ✔              | ✔         | ✔                  | ❌                  | ❌           | ✔               | ✔                 | [🔗](https://github.com/enasequence/enaBrowserTools) |
| [fastq-dl](https://github.com/rpetit3/fastq-dl)              | Python            | SRA, ENA, DDBJ           | All except GSA/GEO ID    | fq, fq.gz, sra, sra.lite | wget                   | ✔              | ✔         | ❌                  | ❌                  | ✔           | ✔               | ✔                 | [🔗](https://github.com/rpetit3/fastq-dl)            |
| [fetchngs](https://github.com/nf-core/fetchngs)              | Python            | SRA, ENA, DDBJ, GEO      | All except GSA ID        | fq, fq.gz                | wget, aspera, prefetch | ✔              | ✔         | ✔                  | ❌                  | ❌           | ✔               | ❌                 | [🔗](https://github.com/nf-core/fetchngs)            |
| [pysradb](https://github.com/saketkc/pysradb)                | Python            | SRA, ENA, DDBJ, GEO      | All except GSA ID        | fq, fq.gz, sra, bam      | requests, aspera       | ✔              | ✔         | ✔                  | ❌                  | ❌           | ✔               | ✔                 | [🔗](https://github.com/saketkc/pysradb)             |
| [Kingfisher](https://github.com/wwood/kingfisher-download)   | Python            | SRA, ENA, DDBJ           | All except GSA/GEO ID    | fq, fq.gz, sra           | curl, aria2c, aspera   | ✔              | ✔         | ❌                  | ✔                  | ❌           | ✔               | ✔                 | [🔗](https://github.com/wwood/kingfisher-download)   |
| [ffq](https://github.com/pachterlab/ffq/tree/master)   | Python            | SRA, ENA, DDBJ, GEO           | All except GSA ID    | fq, fq.gz, sra, bam           | requests   | ✔              | ✔         | ❌                  | ❌                  | ❌           | ❌               | ✔                 | [🔗](https://github.com/pachterlab/ffq/tree/master)   |

## Contributing
Contributions to **iSeq** are welcome! If you have any suggestions, bug reports, or feature requests, please open an issue on the project's GitHub repository. If you would like to contribute code, please fork the repository, make your changes, and submit a pull request.

**Cite us**: [https://doi.org/10.1101/2024.05.16.594538](https://doi.org/10.1093/bioinformatics/btae641)

## License
This project is licensed under the [MIT License](LICENSE).













================================================
FILE: bin/iseq
================================================
#!/bin/bash
# Author: BioOmics (https://github.com/BioOmics)
# Last modified: 2025-11-20
# =======================================
function CheckSoftware(){
    local software1=$1
    local software2=$2
    if command -v $software1 >/dev/null 2>&1; then
        # echo -e "\033[1;34m Software check OK: \033[1;32m${software1}\033[0m"
        sleep 0.01
    else
        echo -e "\033[1;31mError\033[0m: \033[1;32m${software1}\033[0m can not be found in your PATH environment variable."
        echo -e "\033[1;34mHow to solve?\033[0m Please install \033[1;32m${software2}\033[0m by conda (e.g. \033[1;32mconda install -c conda-forge -c bioconda ${software2} -y\033[0m) or other ways and add it to the PATH environment variable."
        echo -e "All required software:\033[1;32m wget, sra-tools, axel, aspera, pigz \033[0m"
        exit 1
    fi
}
CheckSoftware wget wget
CheckSoftware axel axel
CheckSoftware pigz pigz
CheckSoftware ascp "aspera-cli=4.14.0"
CheckSoftware md5sum coreutils
CheckSoftware srapath "sra-tools>=2.11.0"
CheckSoftware vdb-validate sra-tools
# =======================================

function usage() {
cat << EOF

Description:
  Download sequencing data and matadata for each Run from [GSA, SRA, ENA or DDBJ] databases.

Usage:
  $(basename $0) -i accession [options]

Accepted accession formats:
    1.    Projects: PRJEB, PRJNA, PRJDB, PRJC, GSE
    2.     Studies: ERP, DRP, SRP, CRA
    3.  BioSamples: SAMD, SAME, SAMN, SAMC
    4.     Samples: ERS, DRS, SRS, GSM
    5. Experiments: ERX, DRX, SRX, CRX
    6.        Runs: ERR, DRR, SRR, CRR

Required option:
  -i, --input     [text|file]   Single accession or a file containing multiple accessions.
                                Note: Only one accession per line in the file.

Optional options:
  -m, --metadata                Skip the sequencing data downloads and only fetch the metadata for the accession.
  -g, --gzip                    Download FASTQ files in gzip format directly (*.fastq.gz).
                                Note: if *.fastq.gz files are not available, SRA files will be downloaded and converted to *.fastq.gz files.
  -q, --fastq                   Convert SRA files to FASTQ format.
  -t, --threads   int           The number of threads to use for converting SRA to FASTQ files or compressing FASTQ files (default: 8).
  -e, --merge     [ex|sa|st]    Merge multiple fastq files into one fastq file for each Experiment, Sample or Study.
                                ex: merge all fastq files of the same Experiment into one fastq file. Accession format: ERX, DRX, SRX, CRX.
                                sa: merge all fastq files of the same Sample into one fastq file. Accession format: ERS, DRS, SRS, SAMC, GSM.
                                st: merge all fastq files of the same Study into one fastq file. Accession format: ERP, DRP, SRP, CRA.
  -d, --database  [ena|sra]     Specify the database to download SRA sequencing data (default: ena).
                                Note: new SRA files may not be available in the ENA database, even if you specify "ena".
  -p, --parallel  int           Download sequencing data in parallel, the number of connections needs to be specified, such as -p 10.
                                Note: breakpoint continuation cannot be shared between different numbers of connections.
  -a, --aspera                  Use Aspera to download sequencing data, only support GSA/ENA database.
  -s, --speed     int           Download speed limit (MB/s) (default: 1000 MB/s).
  -k, --skip-md5                Skip the md5 check for the downloaded files.
  -r, --protocol  [ftp|https]   Specify the protocol only when downloading files from ENA (default: ftp).
  -Q, --quiet                   Suppress download progress bars.
  -o, --output    text          The output directory. If not exists, it will be created (default: current directory).
  -h, --help                    Show the help information.
  -v, --version                 Show the script version.

See example:
    https://github.com/BioOmics/iSeq/blob/main/docs/Examples.md

More information:
    https://github.com/BioOmics/iSeq

EOF
}

function checkParameter(){
    local parameterName=$1
    local value=$2
    if [[ -z $value || $value == -* ]]; then
        echo -e "\033[1;31mError\033[0m: No parameter provided for \"$1\""
        echo -e "\033[1;32mHow to solve?\033[0m Please specify [ex|sa|st] by \"$1\" option"
        exit 1
    else
        return 0
    fi
}

while [[ $# -gt 0 ]]; do
  case $1 in
    -i|--input) checkParameter $1 $2; if [[ $? -eq 0 ]]; then input=$2;shift 2; fi ;;
    -m|--metadata) metadata=1 ; shift 1 ;;
    -d|--database) checkParameter $1 $2; if [[ $? -eq 0 ]]; then database=$2;shift 2; fi ;;
    -q|--fastq) fastq=1 ; shift 1 ;;
    -g|--gzip) gzip=1 ; shift 1 ;;
    -e|--merge) checkParameter $1 $2; if [[ $? -eq 0 ]]; then merge=$2;shift 2; fi ;;
    -t|--threads) checkParameter $1 $2; if [[ $? -eq 0 ]]; then threads=$2;shift 2; fi ;;
    -p|--parallel) checkParameter $1 $2; if [[ $? -eq 0 ]]; then parallel=$2;shift 2; fi ;;
    -a|--aspera) aspera=1 ; shift 1 ;;
    -s|--speed) checkParameter $1 $2; if [[ $? -eq 0 ]]; then speed=$2;shift 2; fi ;;
    -k|--skip-md5) skip_md5=1 ; shift 1 ;;
    -r|--protocol) checkParameter $1 $2; if [[ $? -eq 0 ]]; then protocol=$2;shift 2; fi ;;
    -Q|--quiet) quiet=1 ; shift 1 ;;
    -o|--output) checkParameter $1 $2; if [[ $? -eq 0 ]]; then output=$2;shift 2; fi ;;
    -h|--help) usage; exit 0 ;;
    -v|--version) echo "Version 1.9.8"; exit 0 ;;
    *) echo -e "\033[1;31mError\033[0m: Invalid option: $1"; echo -e "\033[1;32mHow to solve?\033[0m Please remove $1 option"; exit 1 ;;
  esac
done
# ==================================================
# ================parameters========================
# ==================================================

# --------------------"-i"--------------------------
# Check if input is provided
if [[ -z "$input" ]]; then
  echo -e "\033[1;31mError\033[0m: No input provided"
  echo -e "\033[1;32mHow to solve?\033[0m Please provide the input by \"-i\" option"
  exit 1
fi

# --------------------Check if input is a file or single accession--------------------------
accessions=()
if file "$input" | grep -q 'text'; then
    sed -i 's/\r$//' "$input"
    while IFS= read -r line; do
        accessions+=("$line")
    done < "$input"
else
    accessions+=("$input")
fi

# --------------------"-m"--------------------------
# if not use -m, then use 0
if [[ -z "$metadata" ]]; then
    metadata=0
fi

# --------------------"-d"--------------------------
# if not use -d, then use auto detect
if [[ -z "$database" ]]; then
    database="auto"
else
    if ! [[ "$database" =~ ^([eE][nN][aA]|[sS][rR][aA])$ ]]; then
        echo -e "\033[1;31mError\033[0m: Invalid database: $database"
        echo -e "\033[1;32mHow to solve?\033[0m Please use \"ena\" or \"sra\" for the \"-d\" option"
        exit 1
    fi
fi

# --------------------"-g"--------------------------
# if not use -g, then use 0
if [[ -z "$gzip" ]]; then
    gzip=0
fi

# --------------------"-q"--------------------------
# if not use -q, then use 0
if [[ -z "$fastq" ]]; then
    fastq=0
else
    CheckSoftware fasterq-dump sra-tools
fi

# --------------------"-e"--------------------------
# if not use -e, then use 0
if [[ -z "$merge" ]]; then
    merge=0
else
    CheckSoftware fasterq-dump sra-tools
    if [[ $merge =~ ^[eE][xX]$ ]]; then
        for accession in ${accessions[@]}; do
            if [[ $accession =~ ^[CEDS]RR[0-9]{6,}$ ]]; then
                echo -e "\033[1;31mError\033[0m: $accession is a Run ID, can not use -e option"
                echo -e "\033[1;32mHow to solve?\033[0m Please use a Project, Study, Sample, or Experiment accession for the \"-i\" option"
                exit 1
            fi
        done
    elif [[ $merge =~ ^[sS][aA]$ ]]; then
        for accession in ${accessions[@]}; do
            if [[ $accession =~ ^[CEDS]RR[0-9]{6,}$ || $accession =~ ^[CEDS]RX[0-9]{6,}$ ]]; then
                echo -e "\033[1;31mError\033[0m: $accession is a Run ID or Experiment ID, can not use -e option"
                echo -e "\033[1;32mHow to solve?\033[0m Please use a Project, Study, or Sample accession for the \"-i\" option"
                exit 1
            fi
        done
    elif [[ $merge =~ ^[sS][tT]$ ]]; then
        for accession in ${accessions[@]}; do
            if [[ $accession =~ ^[CEDS]RR[0-9]{6,}$ || $accession =~ ^[CEDS]RX[0-9]{6,}$ || $accession =~ ^[EDS]RS[0-9]{6,}$ || $accession =~ ^SAM[CEDN][A-Z]?[0-9]+$ ]]; then
                echo -e "\033[1;31mError\033[0m: $accession is a Run ID, Experiment ID, or Sample ID, can not use -e option"
                echo -e "\033[1;32mHow to solve?\033[0m Please use a Project or Study accession for the \"-i\" option"
                exit 1
            fi
        done
    else
        echo -e "\033[1;31mError\033[0m: Invalid merge: $merge"
        echo -e "\033[1;32mHow to solve?\033[0m Please use \"ex\", \"sa\", or \"st\" for the \"-e\" option"
        exit 1
    fi
fi

# --------------------"-t"--------------------------
# if not use -t, then use 8
if [[ -z "$threads" ]]; then
    threads=8
fi

# --------------------"-p"--------------------------
# if not use -p, then use 0
if [[ -z "$parallel" ]]; then
    parallel=0
elif [[ ! $parallel =~ ^[1-9][0-9]*$ ]]; then
        echo -e "\033[1;31mError\033[0m: Invalid parallel: $parallel"
        echo -e "\033[1;32mHow to solve?\033[0m Please use a positive integer for the \"-p\" option"
        exit 1
else
    CheckSoftware axel axel
fi

# --------------------"-a"--------------------------
# if not use -a, then use 0
if [[ -z "$aspera" ]]; then
    aspera=0
elif [[ $aspera -eq 1 && $parallel -gt 0 ]]; then
    echo -e "\033[1;33mNote\033[0m: -a and -p options were used at the same time, -a will be used first"
elif [[ $aspera -eq 1 && $database =~ ^[sS][rR][aA]$ ]]; then
    echo -e "\033[1;31mError\033[0m: SRA database does not support Aspera download"
    echo -e "\033[1;32mHow to solve?\033[0m Please remove -a option or switch to the ENA database by \"-d ena\""
    exit 1
else
    for accession in ${accessions[@]}; do
        if [[ $accession =~ ^PRJC[A-Z][0-9]+$ || $accession =~ ^SAMC[0-9]+$ || $accession =~ ^CRA[0-9]+$ || $accession =~ ^CRX[0-9]+$ || $accession =~ ^CRR[0-9]+$ ]]; then
            if [[ ! -f .asperaGSA.openssh ]]; then
                wget --user-agent="Mozilla/5.0" https://ngdc.cncb.ac.cn/gsa/file/downFile?fileName=download/aspera01.openssh -O .asperaGSA.openssh --quiet
            fi

            if [[ ! -f ".asperaGSA.openssh" ]]; then
                echo -e "\033[1;31mError\033[0m: .asperaGSA.openssh is not exist"
                echo -e "\033[1;32mHow to solve?\033[0m Please download GSA Aspera key file from https://ngdc.cncb.ac.cn/gsa/file/downFile?fileName=download/aspera01.openssh and rename it to .asperaGSA.openssh"
                exit 1
            fi
            ascpKeyFile=.asperaGSA.openssh
            
        else
            CheckSoftware ascp aspera-cli
            ascpPath=$(command -v ascp)
            ascpKeyFile1=$(dirname $ascpPath)/../etc/aspera/aspera_bypass_rsa.pem
            ascpKeyFile2=$(dirname $ascpPath)/../etc/aspera_tokenauth_id_rsa
            if [[ -f $ascpKeyFile1 ]]; then
                ascpKeyFile=$ascpKeyFile1
            elif [[ -f $ascpKeyFile2 ]]; then
                ascpKeyFile=$ascpKeyFile2
            else
                echo -e "\033[1;31mError\033[0m: Aspera key file not found in the path: \033[1;31m$ascpKeyFile1\033[0m OR \033[1;31m$ascpKeyFile2\033[0m"
                echo -e "\033[1;32mHow to solve?\033[0m Please copy the Aspera key file in the above path and rename it"
                exit 1
            fi
        fi
    done
fi

# --------------------"-s"--------------------------
# if not use -s, then use 1000
if [[ -z "$speed" ]]; then
    speed=1000
else
    if [[ ! $speed =~ ^[1-9][0-9]*$ ]]; then
        echo -e "\033[1;31mError\033[0m: Invalid speed: $speed"
        echo -e "\033[1;32mHow to solve?\033[0m Please use a positive integer for the \"-s\" option, such as \"-s 1000\" means 1000 MB/s"
        exit 1
    fi
fi

# --------------------"-k"--------------------------
# if not use -k, then use 0
if [[ -z "$skip_md5" ]]; then
    skip_md5=0
fi

# --------------------"-r"--------------------------
# if not use -r, then use ftp
if [[ -z "$protocol" ]]; then
    protocol="ftp"
else
    if ! [[ "$protocol" =~ ^(ftp|https)$ ]]; then
        echo -e "\033[1;31mError\033[0m: Invalid protocol: $protocol"
        echo -e "\033[1;32mHow to solve?\033[0m Please use \"ftp\" or \"https\" for the \"-r\" option"
        exit 1
    fi
fi

# --------------------"-Q"--------------------------
# if not use -Q, then use 0
if [[ -z "$quiet" ]]; then
    quiet=0
fi

# --------------------"-o"--------------------------
# if use -o, cd to output directory
if [[ -z "$output" ]]; then
    output=$(pwd)
else
    if [[ ! -d $output ]]; then
        mkdir -p $output
    fi
    if [[ ! -w $output ]]; then
        echo -e "\033[1;31mError\033[0m: The output directory is not writable"
        echo -e "\033[1;32mHow to solve?\033[0m Please check the write permission of the output directory"
        exit 1
    fi
    cd $output
fi

# ==================================================
# ==================function========================
# ==================================================

function CheckFile(){
    if [[ ! -f $1 ]]; then
        echo -e "\033[1;31mError\033[0m: $1 is not exist"
        echo -e "\033[1;32mHow to solve?\033[0m Please check the accession in $1"
        exit 1
    fi

    if [[ ! -s $1 ]]; then
        echo -e "\033[1;31mError\033[0m: $1 is empty"
        echo -e "\033[1;32mHow to solve?\033[0m Please check the content in $1"
        exit 1
    fi
}

function executeDownload(){
    local link=$1
    local SaveName=$2

    local wget_version=$(wget --version| head -1| awk 'NR==1{print $3}')
    if [[ $(echo "$wget_version" | awk '{print ($1 < 1.16)}') -eq 1 ]]; then
        local wget_params="--progress=bar"
    else
        local wget_params="--quiet --show-progress"
    fi

    if [[ $quiet -eq 1 ]]; then
        wget_params="--quiet"
    fi

    if [[ $parallel -gt 0 ]]; then
        maxSpeed=$(awk -v speed=$speed 'BEGIN{print speed*1024*1024}')
        if [[ $quiet -eq 1 ]]; then
            axel -n $parallel -o "$SaveName" -a -c "$link" -s ${maxSpeed} >/dev/null 2>&1
        else
            axel -n $parallel -o "$SaveName" -a -c "$link" -s ${maxSpeed}
        fi
    else
        wget -c "$link" -O "$SaveName" $wget_params --limit-rate=${speed}M
    fi
}

function executeAspera(){
    local link=$1
    local DB=$2
    if [[ $DB == "ENA" ]]; then
        ascpPath=$(command -v ascp)
        ascpKeyFile1=$(dirname $ascpPath)/../etc/aspera/aspera_bypass_rsa.pem
        ascpKeyFile2=$(dirname $ascpPath)/../etc/aspera_tokenauth_id_rsa
        if [[ -f $ascpKeyFile1 ]]; then
            ascpKeyFile=$ascpKeyFile1
        elif [[ -f $ascpKeyFile2 ]]; then
            ascpKeyFile=$ascpKeyFile2
        else
            echo -e "\033[1;31mError\033[0m: Aspera key file not found in the path: \033[1;31m$ascpKeyFile1\033[0m OR \033[1;31m$ascpKeyFile2\033[0m"
            echo -e "\033[1;32mHow to solve?\033[0m Please copy the Aspera key file in the above path and rename it"
            exit 1
        fi

        local asperaLink=$(echo $link | sed 's/ftp.sra.ebi.ac.uk\//era-fasp@fasp.sra.ebi.ac.uk:/g')

    elif [[ $DB == "GSA" ]]; then
        if [[ ! -f .asperaGSA.openssh ]]; then
            wget --user-agent="Mozilla/5.0" https://ngdc.cncb.ac.cn/gsa/file/downFile?fileName=download/aspera01.openssh -O .asperaGSA.openssh --quiet
        fi

        if [[ ! -f ".asperaGSA.openssh" ]]; then
            echo -e "\033[1;31mError\033[0m: .asperaGSA.openssh is not exist"
            echo -e "\033[1;32mHow to solve?\033[0m Please download GSA Aspera key file from https://ngdc.cncb.ac.cn/gsa/file/downFile?fileName=download/aspera01.openssh and rename it to .asperaGSA.openssh"
            exit 1
        fi
        ascpKeyFile=.asperaGSA.openssh

        local asperaLink=$(echo $link | sed 's/ftp:\/\/download.big.ac.cn\//aspera01@download.cncb.ac.cn:/g')

    fi

    if [[ $quiet -eq 1 ]]; then
        ascp -q -P 33001 -i "$ascpKeyFile" -QT -l "${speed}M" -k1 -d "$asperaLink" . 
    else
        ascp -P 33001 -i "$ascpKeyFile" -QT -l "${speed}M" -k1 -d "$asperaLink" .
    fi
}

function validateQuery() {
    local accession="$1"
    if [[ $accession =~ ^PRJ[EDN][A-Z][0-9]+$ || $accession =~ ^[EDS]RP[0-9]{6,}$ ]]; then
        echo "$accession"
    elif [[ $accession =~ ^SAM[EDN][A-Z]?[0-9]+$ || $accession =~ ^[EDS]RS[0-9]{6,}$ ]]; then
        echo "$accession"
    elif [[ $accession =~ ^[EDS]RX[0-9]{6,}$ ]]; then # {6,} means at least 6 digits
        echo "$accession"
    elif [[ $accession =~ ^[EDS]RR[0-9]{6,}$ ]]; then
        echo "$accession"
    elif [[ $accession =~ ^GSE[0-9]+$ ]]; then
        local bioproject=$(wget -qO- "https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=$accession" | grep -oe "PRJ[EDN][A-Z][0-9]\+" | uniq)
        if [[ -z $bioproject ]]; then
            echo -e "\033[1;31mError\033[0m: $accession is not valid GEO Series accession." >&2
            exit 1
        fi
        echo -e "\033[32mNote\033[0m: $accession belongs to $bioproject" >&2
        echo "$bioproject"
    elif [[ $accession =~ ^GSM[0-9]+$ ]]; then
        local biosample=$(wget -qO- "https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=$accession" | grep -oe "SAM[EDN][A-Z]\?[0-9]\+" | uniq)
        if [[ -z $biosample ]]; then
            echo -e "\033[1;31mError\033[0m: $accession is not a valid GEO Sample accession." >&2
            exit 1
        fi
        echo -e "\033[32mNote\033[0m: $accession belongs to $biosample" >&2
        echo "$biosample"
    else
        echo -e "\033[1;31mError\033[0m: $accession is not a valid Study, Sample, Experiment, or Run accession." >&2
        exit 1
    fi
}

function getSRAMetadata() {
   local accession="$1"
   local query=$(validateQuery "$accession")
    if [[ -z $query ]]; then
         exit 1
    fi
	wget -c "https://www.ebi.ac.uk/ena/portal/api/filereport?accession=$query&result=read_run&fields=study_accession,secondary_study_accession,sample_accession,secondary_sample_accession,experiment_accession,run_accession,submission_accession,tax_id,scientific_name,instrument_platform,instrument_model,library_name,nominal_length,library_layout,library_strategy,library_source,library_selection,read_count,base_count,center_name,first_public,last_updated,experiment_title,study_title,study_alias,experiment_alias,run_alias,fastq_bytes,fastq_md5,fastq_ftp,fastq_aspera,fastq_galaxy,submitted_bytes,submitted_md5,submitted_ftp,submitted_aspera,submitted_galaxy,submitted_format,sra_bytes,sra_md5,sra_ftp,sra_aspera,sra_galaxy,sample_alias,broker_name,sample_title,nominal_sdev,first_created,bam_ftp,bam_bytes,bam_md5&format=tsv&download=true&limit=0" -O $accession.metadata.tsv --quiet
    #wget -c "https://www.ebi.ac.uk/ena/portal/api/search?result=read_run&format=tsv&query=\"$query\"&fields=all" -O $accession.metadata.tsv --quiet
    if [[ -z $(awk -vFS="\t" 'NR==2 {print $1}' $accession.metadata.tsv) ]]; then
        echo -e "\033[93mNote\033[0m: No metadata information found for $accession in the ENA database, try to download from the SRA database"
        database="sra"
        wget --quiet --output-document="$accession.xml" "https://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=sra&term=${accession}&usehistory=y"
        WebEnv=$(grep -oP '<WebEnv>\K[^<]+' $accession.xml)
        QueryKey=$(grep -oP '<QueryKey>\K[^<]+' $accession.xml)
        rm -f $accession.xml
        wget --quiet --output-document="$accession.metadata.tsv" "https://trace.ncbi.nlm.nih.gov/Traces/sra-db-be/sra-db-be.cgi?rettype=runinfo&WebEnv=${WebEnv}&query_key=${QueryKey}"
        sed -i "s/,/\t/g" $accession.metadata.tsv

        if [[ -z $(awk -vFS="\t" 'NR==2 {print $1}' $accession.metadata.tsv) ]]; then
            echo -e "\033[1;31mError\033[0m: No metadata information found for $accession in the all databases"
            echo -e "\033[1;32mHow to solve?\033[0m 1. Check your accession format: $accession; 2. $accession is not available in the SRA database; 3. Network is not available on your server"
            rm -f $accession.metadata.tsv
            exit 1
        fi
    fi
}

function downloadSRA() {
    local SRR=$1 # only SRR_ID
    local SRALink=$(grep "$SRR" $accession.metadata.tsv | tr "\t" "\n" | grep -e "ftp.sra.ebi.ac.uk/vol[0-9]/[sde]rr" | grep -v "lite" | uniq)
    local FASTQLink=$(grep "$SRR" $accession.metadata.tsv | tr "\t" "\n" | grep -e "ftp.sra.ebi.ac.uk/vol[0-9]/fastq" | uniq)

    if [[ $gzip -eq 1 && ! -z $FASTQLink && ! $database =~ ^[sS][rR][aA]$ && $fastq -eq 0 ]]; then 
        echo -e "\033[32mNote\033[0m: -g used, download FASTQ files in gzip format directly"
        local layout=$(grep "$SRR" $accession.metadata.tsv | awk '{if($0~"PAIRED"){print "paired"}else{print "single"}}' | uniq)
        local linkNum=$(echo $FASTQLink | tr ";" "\n" | wc -l) # even single-end data may have multiple links, such as SRR18030918
        if [[ $layout == "single" && $linkNum -eq 1 ]]; then
            local link=$(echo $FASTQLink | tr ";" "\n" | grep "fastq.gz")
            if [[ $aspera -eq 1 ]]; then
                echo -e "File size: $(wget --spider "ftp://$link" 2>&1 | grep SIZE | awk '{printf "%.2fG", ($5/1024/1024/1024)}')\tDatabase: ENA\tMode: Aspera"
                executeAspera "$link" "ENA"
            else
                if [[ $protocol == "https" ]]; then
                    echo -e "File size: $(wget --spider "https://$link" 2>&1 | grep Length | awk '{printf "%.2fG", ($2/1024/1024/1024)}')\tDatabase: ENA\tMode: https"
                    executeDownload "https://$link" $(basename $link)
                else
                    echo -e "File size: $(wget --spider "ftp://$link" 2>&1 | grep SIZE | awk '{printf "%.2fG", ($5/1024/1024/1024)}')\tDatabase: ENA\tMode: ftp"
                    executeDownload "ftp://$link" $(basename $link)
                fi
            fi
        else
            if [[ $layout == "single" ]]; then
                echo -e "\033[93mNote\033[0m: $SRR is single-end data, but has multiple links"
            fi

            if [[ $linkNum -eq 2 ]]; then
                local link1=$(echo $FASTQLink | tr ";" "\n" | grep "_1.fastq.gz")
                local link2=$(echo $FASTQLink | tr ";" "\n" | grep "_2.fastq.gz")
                if [[ $aspera -eq 1 ]]; then
                    echo -e "File size: $(wget --spider "ftp://$link1" 2>&1 | grep SIZE | awk '{printf "%.2fG", ($5/1024/1024/1024)}')\tDatabase: ENA\tMode: Aspera"
                    executeAspera "$link1" "ENA"
                    echo -e "File size: $(wget --spider "ftp://$link2" 2>&1 | grep SIZE | awk '{printf "%.2fG", ($5/1024/1024/1024)}')\tDatabase: ENA\tMode: Aspera"
                    executeAspera "$link2" "ENA"
                else
                    if [[ $protocol == "https" ]]; then
                        echo -e "File size: $(wget --spider "https://$link1" 2>&1 | grep Length | awk '{printf "%.2fG", ($2/1024/1024/1024)}')\tDatabase: ENA\tMode: https"
                        executeDownload "https://$link1" $(basename $link1)
                        echo -e "File size: $(wget --spider "https://$link2" 2>&1 | grep Length | awk '{printf "%.2fG", ($2/1024/1024/1024)}')\tDatabase: ENA\tMode: https"
                        executeDownload "https://$link2" $(basename $link2)
                    else
                        echo -e "File size: $(wget --spider "ftp://$link1" 2>&1 | grep SIZE | awk '{printf "%.2fG", ($5/1024/1024/1024)}')\tDatabase: ENA\tMode: ftp"
                        executeDownload "ftp://$link1" $(basename $link1)
                        echo -e "File size: $(wget --spider "ftp://$link2" 2>&1 | grep SIZE | awk '{printf "%.2fG", ($5/1024/1024/1024)}')\tDatabase: ENA\tMode: ftp"
                        executeDownload "ftp://$link2" $(basename $link2)
                    fi
                fi
            else
                echo -e "\033[93mNote\033[0m: $SRR is paired-end data, but has only one link" # such as SRR23680070
                local link=$(echo $FASTQLink | tr ";" "\n" | grep ".fastq.gz")
                if [[ $aspera -eq 1 ]]; then
                    echo -e "File size: $(wget --spider "ftp://$link" 2>&1 | grep SIZE | awk '{printf "%.2fG", ($5/1024/1024/1024)}')\tDatabase: ENA\tMode: Aspera"
                    executeAspera "$link" "ENA"
                else
                    if [[ $protocol == "https" ]]; then
                        echo -e "File size: $(wget --spider "https://$link" 2>&1 | grep Length | awk '{printf "%.2fG", ($2/1024/1024/1024)}')\tDatabase: ENA\tMode: https"
                        executeDownload "https://$link" $(basename $link)
                    else
                        echo -e "File size: $(wget --spider "ftp://$link" 2>&1 | grep SIZE | awk '{printf "%.2fG", ($5/1024/1024/1024)}')\tDatabase: ENA\tMode: ftp"
                        executeDownload "ftp://$link" $(basename $link)
                    fi
                fi
            fi  
        fi
    else
        if [[ $database =~ ^[sS][rR][aA]$ || -z $SRALink ]]; then
            if [[ $database =~ ^[eE][nN][aA]$ ]]; then
                echo -e "\033[93mNote\033[0m: The SRA file of $SRR is not available in the ENA database, switch to the SRA database"
            fi
            if [[ $gzip -eq 1 && $fastq -eq 0 && ! $database =~ ^[sS][rR][aA]$ ]]; then
                echo -e "\033[93mNote\033[0m: $SRR FASTQ file is also not available in the ENA database, switch to download SRA file"
            fi
            if [[ $gzip -eq 1 && $database =~ ^[sS][rR][aA]$ ]]; then
                echo -e "\033[92mNote\033[0m: SRA database used, will download SRA file and convert to FASTQ file in gzip format"
            fi
            if [[ $aspera -eq 1 ]]; then
                echo -e "\033[93mNote\033[0m: SRA database does not support Aspera download, switch to download SRA file by https"
            fi
            local link=$(srapath $SRR) # srapath may can't find the SRR file, e.g ERR1143237
            if [[ -z $link ]]; then
                echo -e "\033[1;31mError\033[0m: The sequencing file of $SRR is not available in all databases"
                exit 1
            fi
            echo -e "File size: $(wget --spider $link 2>&1 | grep Length | awk '{printf "%.2fG", ($2/1024/1024/1024)}')\tDatabase: SRA\tMode: https"
            executeDownload $link $SRR
        else
            if [[ $gzip -eq 1 && $fastq -eq 0 ]]; then
                echo -e "\033[93mNote\033[0m: $SRR FASTQ file is not available in the ENA database, switch to download SRA file"
            fi
            if [[ $aspera -eq 1 ]]; then
                echo -e "File size: $(wget --spider "ftp://$SRALink" 2>&1 | grep SIZE | awk '{printf "%.2fG", ($5/1024/1024/1024)}')\tDatabase: ENA\tMode: Aspera"
                executeAspera "$SRALink" "ENA"
            else
                if [[ $protocol == "https" ]]; then
                    echo -e "File size: $(wget --spider "https://$SRALink" 2>&1 | grep Length | awk '{printf "%.2fG", ($2/1024/1024/1024)}')\tDatabase: ENA\tMode: https"
                    executeDownload "https://$SRALink" $SRR
                else
                    echo -e "File size: $(wget --spider "ftp://$SRALink" 2>&1 | grep SIZE | awk '{printf "%.2fG", ($5/1024/1024/1024)}')\tDatabase: ENA\tMode: ftp"
                    executeDownload "ftp://$SRALink" $SRR
                fi
            fi
        fi
    fi
}

count=1 
function checkSRA() {
    local SRR=$1 # only SRR_ID
    if [[ $gzip -eq 1 && $fastq -eq 0 && ! $database =~ ^[sS][rR][aA]$ ]]; then

        mapfile -t fastq_files < <(grep "$SRR" "${accession}.metadata.tsv" | grep -o "${SRR}\(_[^;/[:space:]]*\)\?\.fastq\.gz")

        if [[ ${#fastq_files[@]} -gt 0 ]]; then
            all_pass=true
            for file in "${fastq_files[@]}"; do
                if [[ ! -f $file ]]; then
                    all_pass=false
                    break
                fi

                md5=$(md5sum "$file" | awk '{print $1}')
                if ! grep -q "$md5" "${accession}.metadata.tsv"; then
                    echo -e "\033[91mMD5 mismatch for:\033[0m $file"
                    all_pass=false
                    break
                fi
            done

            if [[ "$all_pass" == true ]]; then
                echo -e "\033[92m${SRR} download and md5 check successful, save ${SRR} in success.log\033[0m"
                echo -e "$(date)\t$SRR" >> success.log
                sed -i "/$SRR/d" fail.log 2>/dev/null
            elif [[ $count -le 1 ]]; then
                echo -e "\033[93mNote\033[0m: ${SRR} validate failed, retry ${count} times"
                downloadSRA "$SRR"
                count=$((count+1))
                checkSRA "$SRR"
            elif [[ $count -le 2 ]]; then
                echo -e "\033[93mNote\033[0m: ${SRR} validate failed, remove the files and retry ${count} times"
                rm -f "${fastq_files[@]}"
                downloadSRA "$SRR"
                count=$((count+1))
                checkSRA "$SRR"
            else
				for f in "${fastq_files[@]}"; do
					[[ -f "$f" ]] && rm -f "$f"
				done
                echo -e "\033[91m${SRR} md5 check failed after trying ${count} times, save Run ID in fail.log\033[0m"
                echo -e "$(date)\t$SRR" >> fail.log
                #exit 1
                touch "$tmp_fail_flag"
            fi
        else
            echo -e "\033[93mNote\033[0m: No FASTQ files found for ${SRR}"
            if [[ $count -le 2 ]]; then
                count=$((count+1))
                downloadSRA "$SRR"
                checkSRA "$SRR"
            else
				for f in "${fastq_files[@]}"; do
					[[ -f "$f" ]] && rm -f "$f"
				done
                echo -e "\033[91m${SRR} failed: no FASTQ files after retry, saving to fail.log\033[0m"
                echo -e "$(date)\t$SRR" >> fail.log
                touch "$tmp_fail_flag"
            fi
        fi
    else
        vdb-validate ./$SRR > $SRR.log 2>&1
        if [[ $? -eq 0 ]]; then
            echo -e "\033[92m${SRR} download and md5 check successful, save ${SRR} in success.log\033[0m"
            echo -e "$(date)\t$SRR" >> success.log
            sed -i "/$SRR/d" fail.log 2>/dev/null
            rm -f $SRR.log
        elif [[ $count -le 1 ]]; then # retry times
            echo -e "\033[93mNote\033[0m: ${SRR} validate failed, retry ${count} times"
            downloadSRA $SRR
            count=$((count+1))
            checkSRA $SRR
        elif [[ $count -le 2 ]]; then # retry times
            echo -e "\033[93mNote\033[0m: ${SRR} validate failed, remove the file and retry ${count} times"
            if [[ -f "$SRR" ]]; then rm -f "$SRR"; fi
            downloadSRA $SRR
            count=$((count+1))
            checkSRA $SRR
        else
            if [[ -f "$SRR" ]]; then rm -f "$SRR"; fi
            echo -e "\033[91m${SRR} md5 check failed after trying ${count} times, save Run ID in fail.log\033[0m"
            echo -e "$(date)\t$SRR" >> fail.log
            touch "$tmp_fail_flag"
        fi
    fi
}

function getGSAxlsx(){
    local cra=$1
    wget --quiet --post-data="type=3&dlAcession=${cra}" \
    --user-agent="Mozilla/5.0" \
    --output-document="${cra}.metadata.xlsx" "https://ngdc.cncb.ac.cn/gsa/file/exportExcelFile"
}

function getGSAMetadata() {
    local accession=$1
    if [[ $accession =~ ^CRR[0-9]+$ || $accession =~ ^CRX[0-9]+$ ]]; then
        CRA=$(wget --user-agent="Mozilla/5.0" -qO-  https://ngdc.cncb.ac.cn/gsa/search?searchTerm=${accession} | grep -v "example" |  grep -oe "CRA[0-9]\+" | uniq)
        if [[ -z $CRA ]]; then
            echo -e "\033[1;31mError\033[0m: Cannot infer the Project ID (CRA*) for $accession." >&2
            echo -e "\033[1;32mHow to solve?\033[0m 1. Check your internet connection (You can try \"wget https://ngdc.cncb.ac.cn/gsa/search?searchTerm=${accession}\" for a test). 2. Check the format of $accession."
            exit 1
        fi
        wget --quiet --post-data="searchTerm=${CRA}&totalDatas=9999&downLoadCount=9999" \
                --user-agent="Mozilla/5.0" \
                --output-document="${accession}.tmp" "https://ngdc.cncb.ac.cn/gsa/search/getRunInfoByCra"
        awk -vaccession=${accession} 'NR==1{print $0}NR>1{if($0~accession)print $0}' ${accession}.tmp > ${accession}.metadata.csv
        rm ${accession}.tmp

        if [[ ! -f ${CRA}.metadata.xlsx ]]; then
            echo -e "\033[32mNote\033[0m: ${accession} belongs to ${CRA}, ${CRA}.metadata.xlsx will also be downloaded"
            getGSAxlsx $CRA
        fi
    elif [[ $accession =~ ^PRJC[A-Z][0-9]+$ || $accession =~ ^SAMC[0-9]+$ || $accession =~ ^CRA[0-9]+$ ]]; then
        if [[ $accession =~ ^PRJC[A-Z][0-9]+$ || $accession =~ ^SAMC[0-9]+$ ]]; then
            wget --quiet --post-data="searchTerm=%26quot%3B${accession}%26quot%3BtotalDatas=9999%3BdownLoadCount=9999" \
            --user-agent="Mozilla/5.0" \
            --output-document="${accession}.metadata.csv" "https://ngdc.cncb.ac.cn/gsa/search/getRunInfo"
        elif [[ $accession =~ ^CRA[0-9]+$ ]]; then
            wget --quiet --post-data="searchTerm=${accession}&totalDatas=9999&downLoadCount=9999" \
            --user-agent="Mozilla/5.0" \
            --output-document="${accession}.metadata.csv" "https://ngdc.cncb.ac.cn/gsa/search/getRunInfoByCra"
        fi

        if [[ $(awk -F, 'NR==2{print $1}' ${accession}.metadata.csv) == "" ]]; then
            echo -e "\033[1;31mError\033[0m: $accession is not a valid Study, Sample, or Experiment accession." >&2
            rm ${accession}.metadata.csv
            exit 1
        fi

        CRA=$(grep -oe "CRA[0-9]\+" ${accession}.metadata.csv | uniq) # when accession is PRJ, CRA may be more than one
        while IFS= read -r cra; do
            if [[ ! -f ${cra}.metadata.xlsx ]]; then
                if [[ $accession =~ ^CRA[0-9]+$ ]]; then
                    echo -e "\033[32mNote\033[0m: ${cra}.metadata.xlsx will also be downloaded"
                else
                    echo -e "\033[32mNote\033[0m: ${accession} belongs to ${cra}, ${cra}.metadata.xlsx will also be downloaded"
                fi
                getGSAxlsx "$cra"
            fi
        done <<< "$CRA"
    else
        echo -e "\033[1;31mError\033[0m: $accession is not a valid Study, Sample, Experiment, or Run accession." >&2
        exit 1
    fi
}

function downloadGSA() {
    local CRR=$1 # only CRR_ID
    local CRA=$(grep "$CRR" ${accession}.metadata.csv | grep -o "CRA[0-9]\+" | uniq)
    local allLinks=$(wget -qO- --user-agent="Mozilla/5.0" https://ngdc.cncb.ac.cn/gsa/browse/${CRA}/${CRR} | grep -oE '(https|ftp)://[^"]*\.(gz|bam|tar|bz2)' | sort | uniq)
    local httpsLink=$(echo $allLinks | tr " " "\n" | grep "https://download.cncb.ac.cn")
    local ftpLink=$(echo $allLinks | tr " " "\n" | grep "ftp://download.big.ac.cn")
    local HuaWeiLink=$(echo $allLinks | tr " " "\n" | grep "huaweicloud")

    if [[ ! -z $HuaWeiLink ]]; then # use HuaWei Cloud to download firstly, even if aspera is available
        if [[ $aspera -eq 1 ]]; then 
            echo -e "\033[92mNote\033[0m: HUAWEI Cloud is available, which is faster than Aspera, so HUAWEI Cloud will be used first, even if -a option is used"
        fi
        for link in $HuaWeiLink; do
            local SaveName=$(basename $link)
            if [[ $(grep -c $SaveName success.log) -ge "1" ]]; then
                echo -e "\033[32mNote\033[0m: ${SaveName} has been downloaded successfully, please check success.log for details. If you want to download it again, please remove it from success.log (sed -i '/$$SaveName/d' success.log)"
            else 
                echo -e "File size: $(wget --user-agent="Mozilla/5.0" --spider $link 2>&1 | grep Length | awk '{printf "%.2fG", ($2/1024/1024/1024)}')\tDatabase: GSA\tMode: HUAWEI Cloud"
                executeDownload $link $SaveName
                if [[ $skip_md5 -eq 0 ]]; then
                    checkGSA $SaveName $CRR
                else
                    echo -e "\033[32mNote\033[0m: Skip md5 check for $SaveName, as -k option is used"
                fi
            fi
        done
    elif [[ $aspera -eq 1 ]]; then
        for link in $ftpLink; do
            local SaveName=$(basename $link)
            if [[ $(grep -c $SaveName success.log) -ge "1" ]]; then
                echo -e "\033[32mNote\033[0m: ${SaveName} has been downloaded successfully, please check success.log for details. If you want to download it again, please remove it from success.log (sed -i '/$$SaveName/d' success.log)"
            else
                echo -e "File size: $(wget --user-agent="Mozilla/5.0" --spider $link 2>&1 | grep SIZE | awk '{printf "%.2fG", ($5/1024/1024/1024)}')\tDatabase: GSA\tMode: Aspera"
                executeAspera $link "GSA"
                if [[ $skip_md5 -eq 0 ]]; then
                    checkGSA $SaveName $CRR
                else
                    echo -e "\033[32mNote\033[0m: Skip md5 check for $SaveName, as -k option is used"
                fi
            fi
        done
    else
        for link in $ftpLink; do
            local SaveName=$(basename $link)
            if [[ $(grep -c $SaveName success.log) -ge "1" ]]; then
                echo -e "\033[32mNote\033[0m: ${SaveName} has been downloaded successfully, please check success.log for details. If you want to download it again, please remove it from success.log (sed -i '/$$SaveName/d' success.log)"
            else
                echo -e "File size: $(wget --user-agent="Mozilla/5.0" --spider $link 2>&1 | grep SIZE | awk '{printf "%.2fG", ($5/1024/1024/1024)}')\tDatabase: GSA\tMode: ftp"
                executeDownload $link $SaveName
                if [[ $skip_md5 -eq 0 ]]; then
                    checkGSA $SaveName $CRR
                else
                    echo -e "\033[32mNote\033[0m: Skip md5 check for $SaveName, as -k option is used"
                fi
            fi
        done
    fi
}

count=1 
function checkGSA() {
    local filename=$1 # CRR file name
    local CRR=$2

    if [[ ! -f $CRA.md5sum.txt ]]; then
        md5URL=$(echo "https://download.cncb.ac.cn/"$(grep -oe "gsa[0-9]\+/$CRA\|gsa/$CRA" ${accession}.metadata.csv | uniq)"/md5sum.txt")
        wget --user-agent="Mozilla/5.0" "$md5URL" -O $CRA.md5sum.txt --quiet
    fi

    if ! command -v md5sum >/dev/null 2>&1 || [[ ! -s $CRA.md5sum.txt ]]; then
        echo -e "\033[32mNote\033[0m: Skip md5 check for $filename, as md5sum command is not available or $CRA.md5sum.txt is empty"
        CheckFile $filename
        echo -e "\033[92m${filename} download successful, save ${filename} in success.log\033[0m"
        echo -e "$(date)\t$filename" >> success.log
        sed -i "/$filename/d" fail.log 2>/dev/null
    else
        local md5sum=$(grep "$filename" $CRA.md5sum.txt | awk '{print tolower($1)}')
        if [[ -f $filename && $(md5sum $filename | awk '{print $1}') == $md5sum ]]; then
            echo -e "\033[92m${filename} download and md5 check successful, save ${filename} in success.log\033[0m"
            echo -e "$(date)\t$filename" >> success.log
            sed -i "/$filename/d" fail.log 2>/dev/null
        elif [[ $count -le 1 ]]; then # retry times
            echo -e "\033[93mNote\033[0m: ${filename} validate failed, retry ${count} times"
            count=$((count+1))
            downloadGSA $CRR
        elif [[ $count -le 2 ]]; then # retry times
            echo -e "\033[93mNote\033[0m: ${filename} validate failed, remove the file and retry ${count} times"
            rm -f $filename
            count=$((count+1))
            downloadGSA $CRR
        else
            echo -e "\033[91m${filename} md5 check failed after trying ${count} times, save ${filename} in fail.log\033[0m"
            echo -e "$(date)\t$filename" >> fail.log
            #exit 1
            touch "$tmp_fail_flag"
        fi
    fi
}

function mergeSRArun(){
    local metadata=$1

    if [[ $merge == "ex" ]]; then
        local experimentList=$(grep -oe "[EDS]RX[0-9]\+" $metadata | sort | uniq)
    elif [[ $merge == "sa" ]]; then
        local experimentList=$(grep -oe "SAM[EDN][A-Z]*[0-9]\+" $metadata | sort | uniq)
    elif [[ $merge == "st" ]]; then
        local experimentList=$(grep -oe "PRJ[EDN][A-Z][0-9]\+" $metadata | sort | uniq)
    fi

    for experiment in $experimentList; do
        local runList=$(awk -vFS="\t" -v experiment=$experiment 'NR>1 && $0~experiment {print $1}' $metadata)
        local layout=$(grep $experiment $metadata | awk '{if($0~"PAIRED"){print "paired"}else{print "single"}}' | uniq)
        local SRR=$(echo $runList | awk '{print $1}') # get the first run ID
        if [[ $gzip -eq 1 && ( -f ${SRR}_1.fastq.gz || -f ${SRR}_2.fastq.gz || -f ${SRR}.fastq.gz ) ]]; then
            if [[ -f ${experiment}.fastq.gz || -f ${experiment}_1.fastq.gz ]]; then
                echo -e "\033[32mNote\033[0m: ${experiment} has been merged, skip"
            else
                if [[ $(echo $runList | wc -w) -eq 1 ]]; then # if only one run in the experiment, just rename it
                    if [[ $layout == "single" ]]; then
                            echo -e "\033[32mNote\033[0m: $experiment only has one run, rename $runList to $experiment.fastq.gz"
                            ln -s ${runList}.fastq.gz ${experiment}.fastq.gz
                    else
                        echo -e "\033[32mNote\033[0m: $experiment only has one run, rename $runList to ${experiment}_1.fastq.gz and ${experiment}_2.fastq.gz"
                        ln -s ${runList}_1.fastq.gz ${experiment}_1.fastq.gz
                        ln -s ${runList}_2.fastq.gz ${experiment}_2.fastq.gz
                    fi
                else
                    if [[ $layout == "single" ]]; then
                        echo -e "\033[32mNote\033[0m: Those runs: \n$(for run in $runList; do echo $run.fastq.gz; done) \nwill be merged into $experiment.fastq.gz, may take a while"
                        cat $(for run in $runList; do echo $run.fastq.gz; done) > ${experiment}.fastq.gz
                        # for run in $runList; do rm -f $run.fastq.gz; done
                    else
                        echo -e "\033[32mNote\033[0m: Those runs: \n$(for run in $runList; do echo ${run}_1.fastq.gz; done) \nwill be merged into ${experiment}_1.fastq.gz, may take a while"
                        cat $(for run in $runList; do echo ${run}_1.fastq.gz; done) > ${experiment}_1.fastq.gz
                        # for run in $runList; do rm -f ${run}_1.fastq.gz; done
                        echo -e "\033[32mNote\033[0m: Those runs: \n$(for run in $runList; do echo ${run}_2.fastq.gz; done) \nwill be merged into ${experiment}_2.fastq.gz, may take a while"
                        cat $(for run in $runList; do echo ${run}_2.fastq.gz; done) > ${experiment}_2.fastq.gz
                        # for run in $runList; do rm -f ${run}_2.fastq.gz; done
                    fi
                fi
            fi
        elif [[ -f ${SRR}.fastq || -f ${SRR}_1.fastq || -f ${SRR}_2.fastq ]]; then
            if [[ -f ${experiment}.fastq || -f ${experiment}_1.fastq ]]; then
                echo -e "\033[32mNote\033[0m: ${experiment} has been merged, skip"
            else
                if [[ $(echo $runList | wc -w) -eq 1 ]]; then # if only one run in the experiment, just rename it
                    if [[ $layout == "single" ]]; then
                        if [[ $runList =~ _1.fastq ]]; then # maybe is a single cell data
                            echo -e "\033[32mNote\033[0m: $experiment only has one run, rename $runList to ${experiment}_1.fastq"
                            ln -s ${runList}_1.fastq ${experiment}_1.fastq
                        else
                            echo -e "\033[32mNote\033[0m: $experiment only has one run, rename $runList to $experiment.fastq"
                            ln -s ${runList}.fastq ${experiment}.fastq
                        fi
                    else
                        echo -e "\033[32mNote\033[0m: $experiment only has one run, rename $runList to ${experiment}_1.fastq and ${experiment}_2.fastq"
                        ln -s ${runList}_1.fastq ${experiment}_1.fastq
                        ln -s ${runList}_2.fastq ${experiment}_2.fastq
                    fi
                else
                    if [[ $layout == "single" ]]; then
                        echo -e "\033[32mNote\033[0m: Those runs: \n$(for run in $runList; do echo $run.fastq; done) \nwill be merged into $experiment.fastq, may take a while"
                        cat $(for run in $runList; do echo $run.fastq; done) > ${experiment}.fastq
                        # for run in $runList; do rm -f $run.fastq; done
                    else
                        echo -e "\033[32mNote\033[0m: Those runs: \n$(for run in $runList; do echo ${run}_1.fastq; done) \nwill be merged into ${experiment}_1.fastq, may take a while"
                        cat $(for run in $runList; do echo ${run}_1.fastq; done) > ${experiment}_1.fastq
                        # for run in $runList; do rm -f ${run}_1.fastq; done
                        echo -e "\033[32mNote\033[0m: Those runs: \n$(for run in $runList; do echo ${run}_2.fastq; done) \nwill be merged into ${experiment}_2.fastq, may take a while"
                        cat $(for run in $runList; do echo ${run}_2.fastq; done) > ${experiment}_2.fastq
                        # for run in $runList; do rm -f ${run}_2.fastq; done
                    fi
                fi
            fi
        else
            echo -e "\033[1;31mError\033[0m: $SRR can't be found when merge $experiment" >&2
            exit 1
        fi
    done
}

function mergeGSArun(){
    local metadata=$1
    if [[ $merge == "ex" ]]; then
        local experimentList=$(grep -oe "CRX[0-9]\+" $metadata | sort | uniq)
    elif [[ $merge == "sa" ]]; then
        local experimentList=$(grep -oe "SAMC[0-9]\+" $metadata | sort | uniq)
    elif [[ $merge == "st" ]]; then
        local experimentList=$(grep -oe "PRJC[A-Z][0-9]\+" $metadata | sort | uniq)
    fi

    for experiment in $experimentList; do
        local colNum=$(grep $experiment $metadata | cut -d "," -f7 | awk -vFS="|" '{print NF}' | uniq)
        local rowNum=$(grep $experiment $metadata | wc -l)

        if [[ $rowNum -eq 1 ]]; then # if only one run in the experiment, just rename it
            local CRR=$(grep $experiment $metadata | cut -d "," -f1)
            local prefixes=$(grep $experiment $metadata | cut -d "," -f7 | 
                            awk -vFS="|" '{for(i=1;i<=NF;i++) print $i}' | 
                            awk -F"/" '{print $NF}' | 
                            awk -F '[._]' '{print $1}' | uniq)
            if [[ $CRR == $prefixes ]]; then # Due to one CRR may have multiple files, so need to check if the CRR is the same as the prefixe of those files
                grep $experiment $metadata | cut -d "," -f7 | awk -vFS="|" '{for(i=1;i<=NF;i++) print $i}' | awk -F"/" '{print $NF}' | while read filename; do
                    if [[ -f ${filename/$CRR/$experiment} && ! -f $filename ]]; then
                        echo -e "\033[32mNote\033[0m: ${filename/$CRR/$experiment} has been merged (here renamed), skip"
                    else
                        echo -e "\033[32mNote\033[0m: $experiment only has one run $CRR, rename $filename to ${filename/$CRR/$experiment}"
                        ln -s $filename ${filename/$CRR/$experiment}
                    fi
                done
            else
                echo -e "\033[32mNote\033[0m: $experiment only has one run ($CRR), however, the prefix ($(echo $prefixes)) of the files are different, rename them:"
                grep $experiment $metadata | cut -d "," -f7 | awk -vFS="|" '{for(i=1;i<=NF;i++) print $i}' | awk -F"/" '{print $NF}' | while read filename; do
                    if [[ -f ${experiment}_${filename} && ! -f $filename ]]; then
                        echo -e "\033[32mNote\033[0m: ${experiment}_${filename} has been merged (here renamed), skip"
                    else
                        echo -e "\033[32mNote\033[0m: Rename $filename to ${experiment}_${filename}"
                        ln -s $filename ${experiment}_${filename}
                    fi
                done
            fi
        else
            for ((i=1; i<=$colNum; i++)); do
                local files=$(grep $experiment $metadata | cut -d "," -f7 | awk -vFS="|" -v i=$i '{print $i}' | awk -F"/" '{print $NF}')
                local prefix=$(echo $files | awk -F"[._]" '{print $1}' | uniq)
                local CRR=$(grep $prefix $metadata | cut -d "," -f1 | uniq)
                local example_file=$(echo $files | cut -d " " -f1)
                if [[ $example_file =~ [fastq|fq].gz ]]; then # only can merge [fastq|fq].gz files
                    if [[ $CRR == $prefix ]]; then
                        if [[ -f ${example_file/$prefix/$experiment} ]]; then
                            echo -e "\033[32mNote\033[0m: ${example_file/$prefix/$experiment} has been merged, skip"
                        else
                            echo -e "\033[32mNote\033[0m: Those files: \n$(for file in $files; do echo $file; done) \nwill be merged into ${example_file/$prefix/$experiment}, may take a while"
                            cat $(for file in $files; do echo $file; done) > ${example_file/$prefix/$experiment}
                            # for file in $files; do rm -f $file; done
                        fi
                    else
                        if [[ -f ${experiment}_${example_file} ]]; then
                            echo -e "\033[32mNote\033[0m: ${experiment}_${example_file} has been merged, skip"
                        else
                            echo -e "\033[32mNote\033[0m: Those files: \n$(for file in $files; do echo $file; done) \nwill be merged into ${experiment}_${example_file}, may take a while"
                            cat $(for file in $files; do echo $file; done) > ${experiment}_${example_file}
                            # for file in $files; do rm -f $file; done
                        fi

                    fi
                else
                    echo -e "\033[93mNote\033[0m: Those files: \n$(for file in $files; do echo $file; done) \nwill not be merged, as they are not end with [fastq|fq].gz"
                fi
            done
        fi
    done
}

# ==================================================
# ==================process=========================
# ==================================================

tmp_fail_flag=".has_failed.flag"
rm -f $tmp_fail_flag

printf "%s\n" "${accessions[@]}" | while read -r accession; do
(
    if [[ $accession =~ ^PRJC[A-Z][0-9]+$ || $accession =~ ^SAMC[0-9]+$ || $accession =~ ^CRA[0-9]+$ || $accession =~ ^CRX[0-9]+$ || $accession =~ ^CRR[0-9]+$ ]]; then
        if [[ -s ${accession}.metadata.csv ]]; then
            echo -e "\033[32mNote\033[0m: ${accession}.metadata.csv exists, skip downloading metadata for $accession"
        else
            getGSAMetadata $accession
            CheckFile $accession.metadata.csv
        fi

        if [[ $metadata -eq 0 ]]; then
            awk -F, 'NR>1{split($5, filenames, "|");split($6, fileSizes, "|")
                for (i=1; i<=length(filenames); i++) {fileSize = fileSizes[i] / (1024 * 1024 * 1024);printf "      %s %.2fG \t ", filenames[i], fileSize}
                printf "\n"}' ${accession}.metadata.csv
            echo -e "\033[32mNote\033[0m: Above Run will be downloaded. You can see the details in ${accession}.metadata.csv"
            CRA=$(grep -oe "CRA[0-9]\+" ${accession}.metadata.csv | uniq)

            for CRR in $(awk -F, 'NR>1{print $1}' ${accession}.metadata.csv | sort -u); do
                if [[ ! -f success.log ]]; then
                    touch success.log
                fi
            
                # check all CRR files
                filenames=$(awk -F, -v cr=$CRR 'NR>1 && $1==cr {
                    split($5, arr, "|");
                    for (i in arr) print arr[i];
                }' ${accession}.metadata.csv)
            
                all_present=true
                for fname in $filenames; do
                    if ! grep -q "$fname" success.log; then
                        all_present=false
                        break
                    fi
                done
            
                if $all_present; then
                    echo -e "\033[32mNote\033[0m: ${CRR} has been downloaded successfully, please check success.log for details. If you want to download it again, please remove it from success.log (sed -i '/${CRR}/d' success.log)"
                else
                    downloadGSA $CRR
                fi
            done

            rm -f $CRA.md5sum.txt

            if [[ "$merge" != 0 && $? -eq 0 ]]; then
                echo -e "\033[32mNote\033[0m: All Runs have been downloaded, start to merge them"
                mergeGSArun ${accession}.metadata.csv
            fi
        else
            echo -e "\033[32mNote\033[0m: You choose to skip downloading GSA files (-m used), only retrieve the metadata for each accession, see ${accession}.metadata.csv"
        fi

    else
        if [[ -s $accession.metadata.tsv ]]; then
            echo -e "\033[32mNote\033[0m: $accession.metadata.tsv exists, skip downloading metadata for $accession"
        else
            getSRAMetadata $accession
            CheckFile $accession.metadata.tsv
        fi

        if [[ $metadata -eq 0 ]]; then
            FASTQLinktmp=$(grep -o 'ftp\.sra\.ebi\.ac\.uk/vol[0-9]/fastq/[^ ]*\.fastq\.gz' $accession.metadata.tsv)
            if [[ $gzip -eq 1 && ! -z $FASTQLinktmp && $fastq -eq 0 ]]; then
                awk -v FS="\t" 'NR>1{split($30, filenames, ";"); split($28, fileSizes, ";");
                    for (i=1; i<=length(filenames); i++) { split(filenames[i], parts, "/");file_extension = parts[length(parts)];
                        fileSize = fileSizes[i] / (1024 * 1024 * 1024);printf "      %s %.2fG \t ", file_extension, fileSize;}printf "\n"}' ${accession}.metadata.tsv
            else
                awk -v FS="\t" 'NR>1{size7 = $7/1024;size8 = $8/1024;size39 = $39/1024/1024/1024;
                    if (size7 == 0 && size8 != 0) {if ($0~"lite"){printf "      %s\t>%.2fG\n", $1, size39} else {printf "      %s\t%.2fG\n", $1, size39}} 
                    else {printf "      %s\t%.2fG\n", $1, size8}}' $accession.metadata.tsv
            fi
            echo -e "\033[32mNote\033[0m: Above Run will be downloaded. You can see the details in $accession.metadata.tsv"

            for SRR in $(awk -vFS="\t" 'NR>1 {print $1}' $accession.metadata.tsv); do
                if [[ ! -f success.log ]]; then
                    touch success.log
                fi
                if [[ $(grep -c $SRR success.log) -ge "1" ]]; then
                    echo -e "\033[32mNote\033[0m: ${SRR} has been downloaded successfully, please check success.log for details. If you want to download it again, please remove it from success.log (sed -i '/$SRR/d' success.log)"
                elif [[ -f $SRR ]]; then
                    if [[ $skip_md5 -eq 0 ]]; then
                        checkSRA $SRR
                    else
                        echo -e "\033[32mNote\033[0m: Skip md5 check for $SRR, as -k option is used"
                    fi
                else
                    downloadSRA $SRR
                    if [[ $skip_md5 -eq 0 ]]; then
                        checkSRA $SRR
                    else
                        echo -e "\033[32mNote\033[0m: Skip md5 check for $SRR, as -k option is used"
                    fi
                fi

                SRX=$(grep $SRR $accession.metadata.tsv | grep -oe "[EDS]RX[0-9]\+" | sort | uniq)
                if [[ ($fastq -eq 1 || "$merge" != 0 || $gzip -eq 1) && -f $SRR 
                && ! -f ${SRR}_1.fastq.gz && ! -f ${SRR}_2.fastq.gz && ! -f ${SRR}.fastq.gz 
                && ! -f ${SRX}_1.fastq.gz && ! -f ${SRX}_2.fastq.gz && ! -f ${SRX}.fastq.gz ]]; then # if SRA file is not exist, means fastq files have been downloaded
                    echo -e "\033[32mNote\033[0m: Converting $SRR to fastq files using $threads threads"
                    SrrPath=$(dirname $(realpath $SRR))

                    if [[ $quiet -eq 1 ]]; then
                        fasterq-dump -p -S --include-technical -e $threads -O "$SrrPath" "$SrrPath/$SRR" > /dev/null 2>&1
                    else
                        fasterq-dump -p -S --include-technical -e $threads -O "$SrrPath" "$SrrPath/$SRR"
                    fi
                    
                    rm -rf fasterq.tmp*
                    if [[ $gzip -eq 1 && -f $SRR ]]; then
                        ls ${SRR}*fastq | while read fastq; do
                            echo -e "\033[32mNote\033[0m: Compressing $fastq to $fastq.gz using $threads threads, may take a while"
                            pigz -p $threads $fastq
                        done
                    fi
                fi
            done

            if [[ "$merge" != 0 && $? -eq 0 ]]; then
                echo -e "\033[32mNote\033[0m: All Runs have been downloaded, start to merge them"
                mergeSRArun $accession.metadata.tsv
            fi
        else
            echo -e "\033[32mNote\033[0m: You choose to skip downloading SRA files (-m used), only retrieve the metadata for each accession, see $accession.metadata.tsv"
        fi
    fi

    if [[ $? -eq 0 ]]; then
        total_equals=$(( ($(tput cols) - ${#accession} - 22) / 2 ))
        equals=$(printf "%-${total_equals}s" "=")
        echo "${equals// /=}${accession} download finished${equals// /=}"
    fi
)
done

if [[ -f $tmp_fail_flag ]]; then
    echo -e "\033[1;31mError\033[0m: Download failures detected. Please check \033[4mfail.log\033[0m for details."
    echo -e "\033[93mNote:\033[0m You can re-run the script to retry failed items."
    exit 1
fi


================================================
FILE: docs/ChineseTutorial.md
================================================
## iSeq使用方法 
- 中文纯手打,英文是由ChatGPT翻译的😀
```{bash}
$ iseq --help

Usage:
  iseq -i accession [options]

Required option:
  -i, --input     [text|file]   Single accession or a file containing multiple accessions.
                                Note: Only one accession per line in the file.

Optional options:
  -m, --metadata                Skip the sequencing data downloads and only fetch the metadata for the accession.
  -g, --gzip                    Download FASTQ files in gzip format directly (*.fastq.gz).
                                Note: if *.fastq.gz files are not available, SRA files will be downloaded and converted to *.fastq.gz files.
  -q, --fastq                   Convert SRA files to FASTQ format.
  -t, --threads   int           The number of threads to use for converting SRA to FASTQ files or compressing FASTQ files (default: 8).
  -e, --merge     [ex|sa|st]    Merge multiple fastq files into one fastq file for each Experiment, Sample or Study.
                                ex: merge all fastq files of the same Experiment into one fastq file. Accession format: ERX, DRX, SRX, CRX.
                                sa: merge all fastq files of the same Sample into one fastq file. Accession format: ERS, DRS, SRS, SAMC, GSM.
                                st: merge all fastq files of the same Study into one fastq file. Accession format: ERP, DRP, SRP, CRA.
  -d, --database  [ena|sra]     Specify the database to download SRA sequencing data (default: ena).
                                Note: new SRA files may not be available in the ENA database, even if you specify "ena".
  -p, --parallel  int           Download sequencing data in parallel, the number of connections needs to be specified, such as -p 10.
                                Note: breakpoint continuation cannot be shared between different numbers of connections.
  -a, --aspera                  Use Aspera to download sequencing data, only support GSA/ENA database.
  -s, --speed     int           Download speed limit (MB/s) (default: 1000 MB/s).
  -k, --skip-md5                Skip the md5 check for the downloaded files.
  -r, --protocol  [ftp|https]   Specify the protocol only when downloading files from ENA (default: ftp).
  -Q, --quiet                   Suppress download progress bars.
  -o, --output    text          The output directory. If not exists, it will be created (default: current directory).
  -h, --help                    Show the help information.
  -v, --version                 Show the script version.
```

### 1. `-i`, `--input`

输入你想下载的accession,首先获取accession的metadata,然后逐一对包含在内的Run ID进行下载。v1.1.0版本之后可以接收文件输入,每行一个accession。这个文件最好在linux下通过vim编辑,要不然从windows上传的话可能文字编码有问题影响下载(如win通常是`CR LF`, 而Linux能识别的是`LF`格式的)。

```bash
iseq -i PRJNA211801
```

目前支持以下5个数据库的6种数据格式,支持的accession前缀如下:

| Databases | BioProject | Study | BioSample | Sample | Experiment | Run  |
| --------- | ---------- | ----- | --------- | ------ | ---------- | ---- |
| **GSA**   | PRJC       | CRA   | SAMC      | \      | CRX        | CRR  |
| **SRA**   | PRJNA      | SRP   | SAMN      | SRS    | SRX        | SRR  |
| **ENA**   | PRJEB      | ERP   | SAME      | ERS    | ERX        | ERR  |
| **DDBJ**  | PRJDB      | DRP   | SAMD      | DRS    | DRX        | DRR  |
| **GEO**   | GSE        | \     | GSM       | \      | \          | \    |

其中对于来自于GEO数据库的两种数据格式`GSE/GSM`,会直接获取到与之关联的`PRJNA/SAMN`,然后获取到包含在内的Run ID并进行测序数据的下载。因此,本质上还是从SRA数据库中下载测序数据。

以下是一些例子:

| Accession Type | Prefixes                       | Example                                                     |
| -------------- | ------------------------------ | ----------------------------------------------------------- |
| BioProject     | PRJEB, PRJNA, PRJDB, PRJC, GSE | PRJEB42779, PRJNA480016, PRJDB14838, PRJCA000613, GSE122139 |
| Study          | ERP, DRP, SRP, CRA             | ERP126685, DRP009283, SRP158268, CRA000553                  |
| BioSample      | SAMD, SAME, SAMN, SAMC         | SAMD00258402, SAMEA7997453, SAMN06479985, SAMC017083        |
| Sample         | ERS, DRS, SRS, GSM             | ERS5684710, DRS259711, SRS2024210, GSM7417667               |
| Experiment     | ERX, DRX, SRX, CRX             | ERX5050800, DRX406443, SRX4563689, CRX020217                |
| Run            | ERR, DRR, SRR, CRR             | ERR5260405, DRR421224, SRR7706354, CRR311377                |

总之,无论你的accession是6种数据格式的哪一种,最终都会对其中包含的Run ID逐一下载并检查文件的md5值,如果md5值和公共数据库中的不一致,则会进行至多3轮的重新下载。如果在3次尝试内下载并校验成功,则会将文件名存入`success.log`中,否则,下载失败,文件名将会存入`fail.log`中。

### 2. `-m`, `--metadata `

只下载accession的样本信息,跳过测序数据的下载。

```bash
iseq -i PRJNA211801 -m
iseq -i CRR343031 -m
```

因此,无论使用不使用`-m`参数,accession的样本信息都会被获取到,如果metadata获取不到的话,iSeq程序会退出,不会执行后续下载。

> [!NOTE]
> **注意1**:如果检索的accession在SRA/ENA/DDBJ/GEO数据库中,iSeq会首先在ENA数据库中进行检索,如果可以检索到样本信息,则会通过[ENA API](https://www.ebi.ac.uk/ena/portal/api/swagger-ui/index.html)下载`TSV`格式的metadata,通常有191列。但是,有些最新在SRA数据库中公开的数据可能不会及时同步到ENA数据库中。因此,如果一旦无法在ENA数据库中获取到metadata的信息,则直接通过[SRA Database Backend](https://trace.ncbi.nlm.nih.gov/Traces/sra-db-be/)下载`CSV`格式的metadata,通常有30列。为了和TSV格式保持一致,会通过`sed -i 's/,/\t/g'`的方式改为TSV格式,如何单个字段含有逗号,可能会造成列的混乱。最终,你将得到名字为`${accession}.metadata.tsv`的样本信息。

> [!NOTE]
>**注意2**:如果检索的accession在GSA数据库中,iSeq会通过GSA的[getRunInfo](https://ngdc.cncb.ac.cn/gsa/search/getRunInfo)接口获取样本信息,下载`CSV`格式的metadata,通常有25列,上述得到的metadata信息会被保存为`${accession}.metadata.csv`文件。为了补充更加详细的metadata信息,iSeq会自动通过GSA的[exportExcelFile](https://ngdc.cncb.ac.cn/gsa/file/exportExcelFile)接口获取accession所属的Project的metadata信息,下载`XLSX`格式的metadata,通常有3个sheet,分别是`Sample`, `Experiment`, `Run`。最终得到的metadata信息会被保存为`${accession}.metadata.xlsx`文件。总而言之,你最终将得到名字为`${accession}.metadata.csv`和`CRA*.metadata.xlsx`的样本信息。

### 3. `-g`, `--gzip`

直接下载gzip格式的FASTQ文件,如果不能直接下载,则会下载SRA文件并通过多线程分解和压缩转换为gzip格式。

```bash
iseq -i SRR1178105 -g
```

由于`GSA`数据库直接存储的格式大多数为`gzip`格式,因此,如果检索的accession来自于`GSA`数据库,无论是否使用`-g` 参数都可以直接下载`gzip`格式的FASTQ文件。如果accession来自于`SRA/ENA/DDBJ/GEO`数据库,那么iSeq会首先访问`ENA`数据库,如果可以直接下载`gzip`格式的FASTQ文件,则会直接下载,否则,会下载`SRA`文件并通过`fasterq-dump`工具转换为`FASTQ`, 然后通过`pigz`工具对`FASTQ`文件进行压缩,最终得到`gzip`格式的FASTQ文件。

### 4. `-q`, `--fastq`

将下载完成的SRA文件分解为多个未压缩的FASTQ格式。

```bash
iseq -i SRR1178105 -q
```

该参数只有在accession来自于`SRA/ENA/DDBJ/GEO`数据库,并且下载的文件为SRA文件时才有效。总之,SRA文件下载完成后,iSeq会通过`fasterq-dump`工具转换为`FASTQ`文件,除此之外,可以通过`-t`参数指定转换的线程数。

> [!NOTE]
> **注意1**:`-q`在下载单细胞数据,尤其对于scATAC-Seq数据,可以很好的分解出`I1`, `R1`, `R2`, `R3`四个文件。而如果通过`-g`参数直接下载FASTQ文件,只会得到`R1`, `R3`两个文件(如:[SRR13450125](https://www.ebi.ac.uk/ena/browser/view/SRR13450125)),这可能会导致后续数据分析时出现问题。

> [!NOTE]
> **`注意2`**:`-q`和`-g`同时使用的时候,会先下载SRA文件,然后通过`fasterq-dump`工具转换为`FASTQ`文件,最后通过`pigz`压缩为gzip格式。并不是直接下载gzip格式的FASTQ文件,这对获取全面的单细胞数据非常有用。

### 5. `-t`, `--threads`

指定分解SRA文件为FASTQ文件或者压缩FASTQ文件的线程数,默认为8。

```bash
iseq -i SRR1178105 -q -t 10
```

考虑到测序数据一般都是大文件,因此,可以通过`-t`参数指定分解的线程数,但是,线程数不是越多越好,因为线程数过多会导致CPU或者IO负载过高,尤其是`fasterq-dump`会占用大量IO,从而影响其他任务的执行。

### 6. `-e`, `--merge`

将Experiment中的多个FASTQ文件合并为一个FASTQ文件。 v1.1.0版本之后,不仅可以对同一个Experiment中的多个FASTQ文件合并,还可以选择不用的参数对Sample (-e sa)或者Study (-e st)进行合并。

```bash
iseq -i SRX003906 -g -e ex
```

虽然大多数情况下,一个Experiment仅包含一个Run,但是有些测序数据中的Experiment中可能包含多个Run(如[SRX003906](https://www.ebi.ac.uk/ena/browser/view/SRX003906), [CRX020217](https://ngdc.cncb.ac.cn/gsa/search?searchTerm=CRX020217)),因此,可以通过`-e`参数将Experiment中的多个FASTQ文件合并为一个FASTQ文件。考虑到双端测序时,`fastq_1`和`fastq_2`文件需要同时合并且对应行号的序列名需要保持一致,因此,iSeq会按照相同的顺序合并多个FASTQ文件。最终,对于单端测序数据会生成一个文件:`SRX*.fastq.gz`,对于双端测序数据会生成两个文件:`SRX*_1.fastq.gz`和`SRX*_2.fastq.gz`。对于Sample (-e sa)或者Study (-e st)同理。

> [!NOTE]
> **注意1**:如果accession是Run ID,则不能使用`-e`参数,反正就是你想合并的时候,输入的accession必须大于等于要合并的那一级所需要的accession。目前,iSeq支持合并gzip压缩和未压缩的FASTQ文件,对于bam文件和tar.gz文件等暂不支持合并。

> [!NOTE]
> **注意2**:正常情况下,一个Experiment仅包含一个Run时,相同的Run应该有相同的前缀。如`SRR52991314_1.fq.gz`和`SRR52991314_2.fq.gz`都有相同的前缀名`SRR52991314`,此时,iSeq会直接重命名为`SRX*_1.fastq.gz`和`SRX*_2.fastq.gz`。但是有例外的情况,如[CRX006713](https://ngdc.cncb.ac.cn/gsa/search?searchTerm=CRX006713)中包含有一个Run为`CRR007192`,但是该Run包含多个前缀名不同的文件,此时,iSeq会直接重命名为`SRX*_原本的文件名`,如这里将直接重命名为:`CRX006713_CRD015671.gz`和`CRX006713_CRD015672.gz`。

### 7. `-d`, `--database`

指定下载SRA文件的数据库,支持`ena`和`sra`两种数据库。

```bash
iseq -i SRR1178105 -d sra 
```

通常情况下,iSeq默认会自动检测可用的数据库,所以不需要指定`-d`参数。但是,有些SRA文件可能在ENA数据库中下载速度较慢,此时可以通过`-d sra`强制指定从SRA数据库下载数据。

> [!NOTE]
> **注意**:如果在ENA数据库中没有找到对应的SRA文件,即使指定了`-d ena`参数,iSeq依旧会自动切换到SRA数据库进行下载。

### 8. `-p`, `--parallel`

开启多线程下载,需要指定下载的线程数。

```bash
iseq -i PRJNA211801 -p 10
```

考虑到`wget`在部分情况下下载速度较慢,因此,可以通过`-p`参数让`iSeq`调用`axel`工具进行多线程下载。

> [!NOTE]
> **注意1**:多线程下载的断点续传功能只能在同一个线程内有效,即如果在第一次下载时使用了`-p 10`参数,那么在第二次下载时也需要使用`-p 10`参数,否则无法实现断点续传。

> [!NOTE]
> **注意2**:如上,iSeq将全程保持10个连接进行下载,因此在下载的过程中你将多次看到相同的`Connection * finished`弹出,这是因为有些连接下载完成后会立即释放,然后重新建立新的连接进行下载。

### 9. `-a`, `--aspera`

使用Aspera进行下载。

```bash
iseq -i PRJNA211801 -a -g
```

由于`Aspera`下载速度较快,因此,可以通过`-a`参数让`iSeq`调用`ascp`工具进行下载。可惜的是,目前仅有`GSA`和`ENA`数据库支持`Aspera`下载,`NCBI SRA`数据库由于广泛采用了`Google Cloud` 和 `AWS Cloud`技术以及其他原因(请看[Avoid-using-ascp](https://github.com/ncbi/sra-tools/wiki/Avoid-using-ascp-directly-for-downloads)),暂无法使用`Aspera`进行下载。

> [!NOTE]
> **注意1**:在访问`GSA`数据库时,如果存在`HUAWEI Cloud`的下载链接,`iSeq`会优先通过`HUAWEI Cloud`通道下载,即使使用了`-a`参数,`iSeq`也会自动切换到`HUAWEI Cloud`下载。这么做的原因是`HUAWEI Cloud`下载速度更快和稳定。因此,在下载`GSA`数据时,推荐使用`-a`参数,这样如果访问不到`HUAWEI Cloud`通道,通过`Aspera`通道下载速度也不慢,否则,只能通过`wget`或者`axel`进行下载,而这两种方式下载速度较慢。

> [!NOTE]
> **注意2**:由于`Aspera`需要key文件,因此,`iSeq`会自动在`conda`环境或者`~/.aspera`目录下查找key文件,如果没有找到,则无法下载。

### 10. `-o`, `--output`

v1.1.0之后可以选择输出文件的位置,如果不存在相应的文件夹,则创建

```bash
iseq -i SRR931847 -o PRJNA211801
```

### 11. `-s`, `--speed`

v1.2.0之后可以选择限速下载,单位是MB/s
```bash
iseq -i SRR931847 -s 10
```

### 12 `-k`, `--skip-md5`

v1.9.2之后可以选择跳过md5文件完整性检验。当你初次跳过后, 想再次进行md5检验,只需要删除-k参数,执行相同的代码就可以了。

### 13 `-r`, `--protocol`

从 v1.9.4 开始,当在 ENA 下载文件时可以指定协议。这样做是因为有时候通过 HTTPS 下载的速度会比 FTP 更快。

### 14 `-Q `,`--quiet`

从v1.9.7开始,可以使用-Q或--quiet选项来不显示进度条,避免log文件反复写入进度信息。



================================================
FILE: docs/Examples.md
================================================
# Examples of using iSeq

## Basic examples
1. Download all Run sequencing data and metadata associated with a Project

   ```
   iseq -i PRJNA211801
   ```

   ![e01](./img/e01.png)

   if you run the same code again, iSeq will **skip** downloaded data

   ![e01_1](./img/e01_1.png)

   ```bash
   iseq -i CRA000553
   ```

   iSeq will prioritize access to the **HUAWEI Cloud** when accessing the **GSA** database.

   ![e02](./img/e02.png)

   ```bash
   iseq -i GSE122139
   ```

   If the **MD5 check fails** after the sequencing data is downloaded, iSeq will attempt to re-download up to 3 times. If it still fails, the ID will be stored in the **fail.log file**.

   ![e03](./img/e03.png)

   ```bash
   iseq -i SRR931847 -o PRJNA211801
   ```

   iSeq will save result in `PRJNA211801` directory.

   ![e13](./img/e14.png)

3. Download all sequencing data and metadata associated with an Experiment or a BioSample

   ```bash
   iseq -i SRX477044
   iseq -i CRX020217
   iseq -i GSM7417667
   ```

4. Download a single sequencing data and metadata associated with a Run

   ```bash
   iseq -i SRR1178105
   iseq -i CRR311377
   ```

5. Only download metadata information

   ```bash
   iseq -i PRJNA211801 -m
   ```

   ![e04](./img/e04.png)

6. Download SRA files and convert them to FASTQ files

   ```bash
   iseq -i SRR1178105 -q
   ```

   ![e05](./img/e05.png)

7. Download sequencing data in parallel with 10 connections

   ```bash
   iseq -i SRR1178105 -p 10
   ```

   ![e06](./img/e06.png)

8. Download sequencing data by Aspera

   ```bash
   iseq -i SRR1178105 -a
   ```

   ![e07](./img/e07.png)

   ```bash
   iseq -i CRR311377 -a
   ```
   
   When accessing the GSA database using Aspera, it will still prioritize access to the HUAWEI Cloud. If it is not available, it will proceed with the normal download using Aspera

   ![e07_1](./img/e07_1.png)

9.  Download gzip-formatted FASTQ files directly

     ```bash
     iseq -i SRR1178105 -g
     ```

     ![e08](./img/e08.png)

9.  Merge multiple FASTQ files into one FASTQ file
    
    - Merge multiple FASTQ files into one FASTQ file for `each Experiment`.
    

     ```bash
     iseq -i CRX020217 -e ex
     ```

     ![e09](./img/e09_1.png)

    - Merge multiple FASTQ files into one FASTQ file for `each Sample`.
    

     ```bash
     rm success.log
     iseq -i SAMC017083 -e sa
     ```

     ![e09](./img/e09_2.png)

    - Merge multiple FASTQ files into one FASTQ file for `each Study`.
    

     ```bash
      rm success.log
      iseq -i PRJCA000613 -e st
     ```

     ![e09](./img/e09_3.png)

9.  Download sequencing data from SRA database

     ```bash
      iseq -i SRR1178105 -d sra
     ```
     ![e10](./img/e10.png)


## Advanced examples

1. Use 10 connections to download SRA files in parallel with `-p 10`, then demultiplex into FASTQ files with the default 8 threads using `-q` and quickly compress with `-g`. Finally, merge Runs from the same Experiment with `-e`.

   ```bash
   iseq -i SRX2993509 -q -g -p 10 -e ex
   ```

   ![e11](./img/e11.png)

2.  Use Aspera with `-a` to directly download gzip-formatted FASTQ files with `-g`, and then merge Runs from the same Experiment. If there is only one Run, rename it with `-e`.

    ```bash
    iseq -i PRJNA211801 -a -g -e ex
    ```

    ![e12](./img/e12.png)

3. Batch download by giving a file and using Aspera with `-a` to directly download gzip-formatted FASTQ files with `-g`.

   ```bash
   iseq -i SRR_Acc_List.txt -a -g
   ```
   
   ![e13](./img/e13.png)

































































================================================
FILE: docs/benchmark/README.md
================================================
## Stability
iSeq demonstrated high stability, successfully downloading and passing integrity checks for a large number of NGS files from GSA and INSDC-related databases.

## Efficiency

- FTP Channel: Prioritizing ENA's FTP channel, iSeq showed fastest and stable download speeds with Aspera, while supporting parallel downloads with AXEL.
- Cloud Storage: AXEL was faster for AWS Cloud channel from SRA, while Wget was faster for HUAWEI Cloud channel from GSA.
- Gzip-formatted FASTQ Files Download: Directly fetching gzip-formatted FASTQ files proved to be the fastest method, with the option to use "--fastq" and "--gzip" parameters for specific data types. Increasing threads notably improved compression speed.

## Overview
![benchmark_result](https://github.com/BioOmics/iSeq/blob/main/docs/img/benchmark.png)


================================================
FILE: docs/benchmark/TestFasterqDump/testFasterqDump.log
================================================
2	Convert SRA to FASTQ	74
2	Compress FASTQ	803
3	Convert SRA to FASTQ	66
3	Compress FASTQ	528
4	Convert SRA to FASTQ	64
4	Compress FASTQ	404
5	Convert SRA to FASTQ	53
5	Compress FASTQ	333
6	Convert SRA to FASTQ	53
6	Compress FASTQ	289
7	Convert SRA to FASTQ	50
7	Compress FASTQ	251
8	Convert SRA to FASTQ	67
8	Compress FASTQ	228
9	Convert SRA to FASTQ	75
9	Compress FASTQ	206
10	Convert SRA to FASTQ	77
10	Compress FASTQ	190
11	Convert SRA to FASTQ	76
11	Compress FASTQ	171
12	Convert SRA to FASTQ	62
12	Compress FASTQ	153
13	Convert SRA to FASTQ	72
13	Compress FASTQ	163
14	Convert SRA to FASTQ	82
14	Compress FASTQ	129
15	Convert SRA to FASTQ	70
15	Compress FASTQ	124
16	Convert SRA to FASTQ	71
16	Compress FASTQ	119
17	Convert SRA to FASTQ	59
17	Compress FASTQ	114
18	Convert SRA to FASTQ	62
18	Compress FASTQ	103
19	Convert SRA to FASTQ	66
19	Compress FASTQ	99
20	Convert SRA to FASTQ	68
20	Compress FASTQ	94
21	Convert SRA to FASTQ	81
21	Compress FASTQ	88
22	Convert SRA to FASTQ	67
22	Compress FASTQ	86
23	Convert SRA to FASTQ	72
23	Compress FASTQ	82
24	Convert SRA to FASTQ	80
24	Compress FASTQ	80
25	Convert SRA to FASTQ	66
25	Compress FASTQ	78
26	Convert SRA to FASTQ	64
26	Compress FASTQ	70
27	Convert SRA to FASTQ	65
27	Compress FASTQ	71
28	Convert SRA to FASTQ	66
28	Compress FASTQ	70
29	Convert SRA to FASTQ	70
29	Compress FASTQ	72
30	Convert SRA to FASTQ	85
30	Compress FASTQ	71
31	Convert SRA to FASTQ	67
31	Compress FASTQ	71
32	Convert SRA to FASTQ	77
32	Compress FASTQ	71
33	Convert SRA to FASTQ	74
33	Compress FASTQ	67
34	Convert SRA to FASTQ	78
34	Compress FASTQ	65
35	Convert SRA to FASTQ	84
35	Compress FASTQ	60
36	Convert SRA to FASTQ	95
36	Compress FASTQ	66
37	Convert SRA to FASTQ	86
37	Compress FASTQ	61
38	Convert SRA to FASTQ	81
38	Compress FASTQ	67
39	Convert SRA to FASTQ	80
39	Compress FASTQ	68
40	Convert SRA to FASTQ	88
40	Compress FASTQ	64


================================================
FILE: docs/benchmark/TestFasterqDump/timefasterqDump.sh
================================================



================================================
FILE: docs/benchmark/TestiSeq-2GB/TestiSeq-2GB.bash
================================================
#!/bin/bash

if command -v iseq >/dev/null 2>&1; then
    sleep 0
else
    echo "iseq is not installed"
    echo "Please install iseq first"
    echo "conda create -n iseq -c conda-forge -c bioconda iseq"
    exit 1
fi

calculate_time_difference() {
    start_time=$1
    end_time=$2
    method=$3
    diff=$((end_time - start_time))
    echo -e "${method}\t${diff}"
}

# Create a directory to store the downloaded files
if [ ! -d "iseq" ]; then
    mkdir iseq
fi



cd ./iseq
# =======================================ENA=============================================
for ((i=1; i<=20; i++)); do
    # SRX3662754 (SE, 540 MB)
    SRX=SRX3662754
    # CRX917377 (SE, 540 MB)
    CRX=CRX917377

    # Perform tests for ENA FTP download by Wget
    start=$(date +%s)
    iseq -i $SRX
    end=$(date +%s)
    calculate_time_difference $start $end "Wget" >> ../timeENA.log
    rm -rf *


    # Perform tests for ENA FTP download by Aspera
    start=$(date +%s)
    iseq -i $SRX -a
    end=$(date +%s)
    calculate_time_difference $start $end "Aspera" >> ../timeENA.log
    rm -rf *


    # Perform tests for ENA FTP download by 10 parallel by AXEL
    start=$(date +%s)
    iseq -i $SRX -p 10
    end=$(date +%s)
    calculate_time_difference $start $end "AXEL" >> ../timeENA.log
    rm -rf *
# =======================================ENA=============================================

# =======================================SRA=============================================
    # Perform tests for SRA HTTPS download by Wget
    start=$(date +%s)
    iseq -i $SRX -d sra
    end=$(date +%s)
    calculate_time_difference $start $end "Wget" >> ../timeSRA.log
    rm -rf *


    # Perform tests for SRA HTTPS download by AXEL
    start=$(date +%s)
    iseq -i $SRX -d sra -p 10
    end=$(date +%s)
    calculate_time_difference $start $end "AXEL" >> ../timeSRA.log
    rm -rf *
# =======================================SRA=============================================

# =======================================ENA FQ/FQ.GZ====================================
    # Perform tests to compare the time taken for directly downloading fq.gz files versus downloading fq files and then compressing them into fq.gz.
    start=$(date +%s)
    iseq -i $SRX -a -q
    end=$(date +%s)
    calculate_time_difference $start $end "--fastq" >> ../timeFQ.log
    rm -rf *


    start=$(date +%s)
    iseq -i $SRX -a -q -g
    end=$(date +%s)
    calculate_time_difference $start $end "--fastq+gzip" >> ../timeFQ.log
    rm -rf *

    start=$(date +%s)
    iseq -i $SRX -a -g
    end=$(date +%s)
    calculate_time_difference $start $end "--gzip" >> ../timeFQ.log
    rm -rf *
# =======================================ENA FQ/FQ.GZ====================================


# =======================================GSA FTP=============================================
    # Perform tests for GSA FTP download by Wget
    start=$(date +%s)
    iseq -i $CRX -m
    wget ftp://download.big.ac.cn/gsa2/CRA014342/CRR1007729/CRR1007729.fq.gz
    end=$(date +%s)
    calculate_time_difference $start $end "Wget" >> ../timeGSAFTP.log
    rm -rf *


    # Perform tests for GSA FTP download by AXEL
    start=$(date +%s)
    iseq -i $CRX -m
    axel -n 10 -a -c ftp://download.big.ac.cn/gsa2/CRA014342/CRR1007729/CRR1007729.fq.gz
    end=$(date +%s)
    calculate_time_difference $start $end "AXEL" >> ../timeGSAFTP.log
    rm -rf *

    # Perform tests for GSA FTP download by Aspera
    start=$(date +%s)
    iseq -i $CRX -m
    wget https://ngdc.cncb.ac.cn/gsa/file/downFile?fileName=download/aspera01.openssh -O .asperaGSA.openssh --quiet
    ascp -P 33001 -i .asperaGSA.openssh -QT -l 1000m -k1 -d aspera01@download.cncb.ac.cn:gsa2/CRA014342/CRR1007729/CRR1007729.fq.gz .
    end=$(date +%s)
    calculate_time_difference $start $end "Aspera" >> ../timeGSAFTP.log
    rm -rf *
# =======================================GSA HUAWEI_CLOUD=============================================
    # Perform tests for GSA HUAWEI_CLOUD download by AXEL
    start=$(date +%s)
    iseq -i $CRX -m
    axel -n 10 -a -c https://cncb-gsa.obs.cn-north-4.myhuaweicloud.com/data/gsapub/CRA014342/CRR1007729/CRR1007729.fq.gz
    end=$(date +%s)
    calculate_time_difference $start $end "AXEL" >> ../timeGSAHW.log
    rm -rf *

    # Perform tests for GSA HUAWEI_CLOUD download by Wget
    start=$(date +%s)
    iseq -i $CRX -m
    wget https://cncb-gsa.obs.cn-north-4.myhuaweicloud.com/data/gsapub/CRA014342/CRR1007729/CRR1007729.fq.gz
    end=$(date +%s)
    calculate_time_difference $start $end "Wget" >> ../timeGSAHW.log
    rm -rf *
done
cd ..

================================================
FILE: docs/benchmark/TestiSeq-2GB/timeENA.log
================================================
Wget	583
Aspera	215
AXEL	59
Wget	976
Aspera	87
AXEL	73
Wget	607
Aspera	208
AXEL	69
Wget	187
Aspera	312
AXEL	54
Wget	150
Aspera	196
AXEL	129
Wget	522
Aspera	275
AXEL	113
Wget	671
Aspera	147
AXEL	70
Wget	151
Aspera	154
AXEL	46
Wget	142
Aspera	36
AXEL	50
Wget	1330
Aspera	51
AXEL	96
Wget	155
Aspera	57
AXEL	76
Wget	113
Aspera	246
AXEL	55
Wget	860
Aspera	732
AXEL	126
Wget	750
Aspera	53
AXEL	49
Wget	1137
Aspera	57
AXEL	104
Wget	909
Aspera	275
AXEL	74
Wget	804
Aspera	83
AXEL	67
Wget	94
Aspera	314
AXEL	53
Wget	814
Aspera	52
AXEL	93
Wget	1444
Aspera	48
AXEL	75
Wget	781
Aspera	23
AXEL	65
Wget	992
Aspera	440
AXEL	103
Wget	812
Aspera	26
AXEL	95
Wget	268
Aspera	30
AXEL	130
Wget	314
Aspera	35
AXEL	147
Wget	1206
Aspera	32
AXEL	100
Wget	600
Aspera	36
AXEL	157
Wget	354
Aspera	33
AXEL	130
Wget	118
Aspera	32
AXEL	253
Wget	98
Aspera	16
AXEL	128
Wget	990
Aspera	59
AXEL	121
Wget	520
Aspera	33
AXEL	177
Wget	216
Aspera	43
AXEL	140
Wget	887
Aspera	53
AXEL	103
Wget	1022
Aspera	55
AXEL	64
Wget	57
Aspera	50
AXEL	211
Wget	354
Aspera	315
AXEL	156
Wget	669
Aspera	53
AXEL	135
Wget	1339
Aspera	47
AXEL	92
Wget	431
Aspera	95
AXEL	56


================================================
FILE: docs/benchmark/TestiSeq-2GB/timeFQ.log
================================================
--fastq	537
--fastq+gzip	316
--gzip	42
--fastq	116
--fastq+gzip	211
--gzip	149
--fastq	293
--fastq+gzip	315
--gzip	144
--fastq	109
--fastq+gzip	240
--gzip	176
--fastq	154
--fastq+gzip	487
--gzip	43
--fastq	79
--fastq+gzip	245
--gzip	43
--fastq	78
--fastq+gzip	242
--gzip	56
--fastq	79
--fastq+gzip	236
--gzip	49
--fastq	69
--fastq+gzip	389
--gzip	43
--fastq	74
--fastq+gzip	282
--gzip	1196
--fastq	354
--fastq+gzip	160
--gzip	43
--fastq	166
--fastq+gzip	243
--gzip	62
--fastq	373
--fastq+gzip	218
--gzip	89
--fastq	326
--fastq+gzip	378
--gzip	253
--fastq	190
--fastq+gzip	400
--gzip	98
--fastq	879
--fastq+gzip	176
--gzip	69
--fastq	185
--fastq+gzip	352
--gzip	62
--fastq	142
--fastq+gzip	282
--gzip	54
--fastq	223
--fastq+gzip	253
--gzip	811
--fastq	78
--fastq+gzip	312
--gzip	1534
--fastq	291
--fastq+gzip	419
--gzip	32
--fastq	46
--fastq+gzip	250
--gzip	250
--fastq	341
--fastq+gzip	323
--gzip	35
--fastq	50
--fastq+gzip	389
--gzip	298
--fastq	55
--fastq+gzip	367
--gzip	39
--fastq	54
--fastq+gzip	259
--gzip	40
--fastq	62
--fastq+gzip	450
--gzip	70
--fastq	176
--fastq+gzip	185
--gzip	50
--fastq	52
--fastq+gzip	284
--gzip	61
--fastq	56
--fastq+gzip	297
--gzip	46
--fastq	58
--fastq+gzip	264
--gzip	129
--fastq	134
--fastq+gzip	247
--gzip	44
--fastq	366
--fastq+gzip	221
--gzip	262
--fastq	449
--fastq+gzip	379
--gzip	59
--fastq	86
--fastq+gzip	273
--gzip	66
--fastq	75
--fastq+gzip	281
--gzip	69
--fastq	91
--fastq+gzip	286
--gzip	66
--fastq	118
--fastq+gzip	498
--gzip	60
--fastq	280
--fastq+gzip	228
--gzip	75
--fastq	228
--fastq+gzip	200
--gzip	72


================================================
FILE: docs/benchmark/TestiSeq-2GB/timeGSAFTP.log
================================================
Wget	1085
AXEL	148
Aspera	89
Wget	1244
AXEL	134
Aspera	87
Wget	956
AXEL	137
Aspera	92
Wget	1083
AXEL	171
Aspera	87
Wget	1113
AXEL	172
Aspera	98
Wget	983
AXEL	125
Aspera	100
Wget	1214
AXEL	111
Aspera	94
Wget	1080
AXEL	119
Aspera	96
Wget	1433
AXEL	186
Aspera	98
Wget	1281
AXEL	155
Aspera	84
Wget	1171
AXEL	117
Aspera	18
Wget	1124
AXEL	174
Aspera	88
Wget	1839
AXEL	164
Aspera	16
Wget	1340
AXEL	165
Aspera	87
Wget	1262
AXEL	147
Aspera	85
Wget	1256
AXEL	170
Aspera	83
Wget	1245
AXEL	141
Aspera	96
Wget	819
AXEL	127
Aspera	93
Wget	1257
AXEL	140
Aspera	95
Wget	1101
AXEL	133
Aspera	85
Wget	1180
AXEL	113
Aspera	76
Wget	1237
AXEL	139
Aspera	76
Wget	787
AXEL	131
Aspera	88
Wget	929
AXEL	151
Aspera	89
Wget	861
AXEL	138
Aspera	102
Wget	878
AXEL	104
Aspera	99
Wget	1095
AXEL	143
Aspera	121
Wget	807
AXEL	118
Aspera	87
Wget	971
AXEL	115
Aspera	83
Wget	1322
AXEL	166
Aspera	97
Wget	1226
AXEL	158
Aspera	13
Wget	1088
AXEL	139
Aspera	13
Wget	1099
AXEL	142
Aspera	87
Wget	1274
AXEL	177
Aspera	87
Wget	1819
AXEL	180
Aspera	91
Wget	1201
AXEL	136
Aspera	13
Wget	1131
AXEL	151
Aspera	81
Wget	1289
AXEL	123
Aspera	82
Wget	1200
AXEL	154
Aspera	82
Wget	944
AXEL	105
Aspera	80


================================================
FILE: docs/benchmark/TestiSeq-2GB/timeGSAHW.log
================================================
AXEL	21
Wget	10
AXEL	20
Wget	14
AXEL	16
Wget	16
AXEL	17
Wget	10
AXEL	13
Wget	11
AXEL	9
Wget	15
AXEL	22
Wget	15
AXEL	21
Wget	11
AXEL	21
Wget	13
AXEL	17
Wget	17
AXEL	15
Wget	11
AXEL	10
Wget	11
AXEL	15
Wget	16
AXEL	21
Wget	11
AXEL	21
Wget	10
AXEL	15
Wget	11
AXEL	29
Wget	13
AXEL	14
Wget	11
AXEL	29
Wget	10
AXEL	13
Wget	10
AXEL	18
Wget	9
AXEL	20
Wget	8
AXEL	19
Wget	13
AXEL	26
Wget	9
AXEL	20
Wget	8
AXEL	23
Wget	9
AXEL	20
Wget	9
AXEL	20
Wget	10
AXEL	20
Wget	10
AXEL	19
Wget	8
AXEL	21
Wget	8
AXEL	21
Wget	16
AXEL	21
Wget	10
AXEL	21
Wget	10
AXEL	21
Wget	11
AXEL	21
Wget	9
AXEL	21
Wget	8
AXEL	21
Wget	10
AXEL	23
Wget	8
AXEL	19
Wget	8


================================================
FILE: docs/benchmark/TestiSeq-2GB/timeSRA.log
================================================
Wget	125
AXEL	75
Wget	261
AXEL	79
Wget	87
AXEL	85
Wget	95
AXEL	64
Wget	120
AXEL	86
Wget	108
AXEL	59
Wget	76
AXEL	63
Wget	80
AXEL	77
Wget	111
AXEL	84
Wget	67
AXEL	66
Wget	109
AXEL	67
Wget	195
AXEL	62
Wget	218
AXEL	50
Wget	167
AXEL	103
Wget	74
AXEL	152
Wget	106
AXEL	181
Wget	94
AXEL	102
Wget	159
AXEL	141
Wget	75
AXEL	78
Wget	129
AXEL	77
Wget	102
AXEL	51
Wget	117
AXEL	68
Wget	82
AXEL	53
Wget	91
AXEL	54
Wget	100
AXEL	45
Wget	84
AXEL	44
Wget	98
AXEL	36
Wget	94
AXEL	41
Wget	84
AXEL	48
Wget	104
AXEL	46
Wget	85
AXEL	43
Wget	122
AXEL	39
Wget	84
AXEL	49
Wget	88
AXEL	63
Wget	120
AXEL	57
Wget	101
AXEL	62
Wget	80
AXEL	46
Wget	98
AXEL	49
Wget	98
AXEL	58
Wget	98
AXEL	43


================================================
FILE: docs/benchmark/TestiSeq-540MB/TestiSeq-540MB.bash
================================================
#!/bin/bash

if command -v iseq >/dev/null 2>&1; then
    sleep 0
else
    echo "iseq is not installed"
    echo "Please install iseq first"
    exit 1
fi

calculate_time_difference() {
    start_time=$1
    end_time=$2
    method=$3
    diff=$((end_time - start_time))
    echo -e "${method}\t${diff}"
}

# Create a directory to store the downloaded files
if [ ! -d "iseq" ]; then
    mkdir iseq
fi

cd ./iseq
# =======================================ENA=============================================
for ((i=1; i<=20; i++)); do
    # SRX1663467 (PE, 2 GB)
    SRX=SRX1663467
    # CRX095512 (SE, 2 GB)
    CRX=CRX095512

    # Perform tests for ENA FTP download by Wget
    start=$(date +%s)
    iseq -i $SRX
    end=$(date +%s)
    calculate_time_difference $start $end "Wget" >> ../timeENA.log
    rm -rf *


    # Perform tests for ENA FTP download by Aspera
    start=$(date +%s)
    iseq -i $SRX -a
    end=$(date +%s)
    calculate_time_difference $start $end "Aspera" >> ../timeENA.log
    rm -rf *


    # Perform tests for ENA FTP download by 10 parallel by AXEL
    start=$(date +%s)
    iseq -i $SRX -p 10
    end=$(date +%s)
    calculate_time_difference $start $end "AXEL" >> ../timeENA.log
    rm -rf *
# =======================================ENA=============================================

# =======================================SRA=============================================
    # Perform tests for SRA HTTPS download by Wget
    start=$(date +%s)
    iseq -i $SRX -d sra
    end=$(date +%s)
    calculate_time_difference $start $end "Wget" >> ../timeSRA.log
    rm -rf *


    # Perform tests for SRA HTTPS download by AXEL
    start=$(date +%s)
    iseq -i $SRX -d sra -p 10
    end=$(date +%s)
    calculate_time_difference $start $end "AXEL" >> ../timeSRA.log
    rm -rf *
# =======================================SRA=============================================

# =======================================ENA FQ/FQ.GZ====================================
    # Perform tests to compare the time taken for directly downloading fq.gz files versus downloading fq files and then compressing them into fq.gz.
    start=$(date +%s)
    iseq -i $SRX -a -q
    end=$(date +%s)
    calculate_time_difference $start $end "--fastq" >> ../timeFQ.log
    rm -rf *


    start=$(date +%s)
    iseq -i $SRX -a -q -g
    end=$(date +%s)
    calculate_time_difference $start $end "--fastq+gzip" >> ../timeFQ.log
    rm -rf *

    start=$(date +%s)
    iseq -i $SRX -a -g
    end=$(date +%s)
    calculate_time_difference $start $end "--gzip" >> ../timeFQ.log
    rm -rf *
# =======================================ENA FQ/FQ.GZ====================================


# =======================================GSA FTP=============================================
    # Perform tests for GSA FTP download by Wget
    start=$(date +%s)
    iseq -i $CRX -m
    wget ftp://download.big.ac.cn/gsa3/CRA002399/CRR120307/CRR120307.fastq.gz
    end=$(date +%s)
    calculate_time_difference $start $end "Wget" >> ../timeGSAFTP.log
    rm -rf *


    # Perform tests for GSA FTP download by AXEL
    start=$(date +%s)
    iseq -i $CRX -m
    axel -n 10 -a -c ftp://download.big.ac.cn/gsa3/CRA002399/CRR120307/CRR120307.fastq.gz
    end=$(date +%s)
    calculate_time_difference $start $end "AXEL" >> ../timeGSAFTP.log
    rm -rf *

    # Perform tests for GSA FTP download by Aspera
    start=$(date +%s)
    iseq -i $CRX -m
    wget https://ngdc.cncb.ac.cn/gsa/file/downFile?fileName=download/aspera01.openssh -O .asperaGSA.openssh --quiet
    ascp -P 33001 -i .asperaGSA.openssh -QT -l 1000m -k1 -d aspera01@download.cncb.ac.cn:gsa3/CRA002399/CRR120307/CRR120307.fastq.gz .
    end=$(date +%s)
    calculate_time_difference $start $end "Aspera" >> ../timeGSAFTP.log
    rm -rf *
# =======================================GSA HUAWEI_CLOUD=============================================
    # Perform tests for GSA HUAWEI_CLOUD download by AXEL
    start=$(date +%s)
    iseq -i ${CRX} -p 10
    end=$(date +%s)
    calculate_time_difference $start $end "AXEL" >> ../timeGSAHW.log
    rm -rf *

    # Perform tests for GSA HUAWEI_CLOUD download by Wget
    start=$(date +%s)
    iseq -i ${CRX}
    end=$(date +%s)
    calculate_time_difference $start $end "Wget" >> ../timeGSAHW.log
    rm -rf *
done
cd ..

================================================
FILE: docs/benchmark/TestiSeq-540MB/timeENA.log
================================================
Wget	781
Aspera	23
AXEL	65
Wget	992
Aspera	440
AXEL	103
Wget	812
Aspera	26
AXEL	95
Wget	268
Aspera	30
AXEL	130
Wget	314
Aspera	35
AXEL	147
Wget	1206
Aspera	32
AXEL	100
Wget	600
Aspera	36
AXEL	157
Wget	354
Aspera	33
AXEL	130
Wget	118
Aspera	32
AXEL	253
Wget	98
Aspera	16
AXEL	128
Wget	990
Aspera	59
AXEL	121
Wget	520
Aspera	33
AXEL	177
Wget	216
Aspera	43
AXEL	140
Wget	887
Aspera	53
AXEL	103
Wget	1022
Aspera	55
AXEL	64
Wget	57
Aspera	50
AXEL	211
Wget	354
Aspera	315
AXEL	156
Wget	669
Aspera	53
AXEL	135
Wget	1339
Aspera	47
AXEL	92
Wget	431
Aspera	95
AXEL	56


================================================
FILE: docs/benchmark/TestiSeq-540MB/timeFQ.log
================================================
--fastq	291
--fastq+gzip	419
--gzip	32
--fastq	46
--fastq+gzip	250
--gzip	250
--fastq	341
--fastq+gzip	323
--gzip	35
--fastq	50
--fastq+gzip	389
--gzip	298
--fastq	55
--fastq+gzip	367
--gzip	39
--fastq	54
--fastq+gzip	259
--gzip	40
--fastq	62
--fastq+gzip	450
--gzip	70
--fastq	176
--fastq+gzip	185
--gzip	50
--fastq	52
--fastq+gzip	284
--gzip	61
--fastq	56
--fastq+gzip	297
--gzip	46
--fastq	58
--fastq+gzip	264
--gzip	129
--fastq	134
--fastq+gzip	247
--gzip	44
--fastq	366
--fastq+gzip	221
--gzip	262
--fastq	449
--fastq+gzip	379
--gzip	59
--fastq	86
--fastq+gzip	273
--gzip	66
--fastq	75
--fastq+gzip	281
--gzip	69
--fastq	91
--fastq+gzip	286
--gzip	66
--fastq	118
--fastq+gzip	498
--gzip	60
--fastq	280
--fastq+gzip	228
--gzip	75
--fastq	228
--fastq+gzip	200
--gzip	72


================================================
FILE: docs/benchmark/TestiSeq-540MB/timeGSAFTP.log
================================================
Wget	1180
AXEL	113
Aspera	76
Wget	1237
AXEL	139
Aspera	76
Wget	787
AXEL	131
Aspera	88
Wget	929
AXEL	151
Aspera	89
Wget	861
AXEL	138
Aspera	102
Wget	878
AXEL	104
Aspera	99
Wget	1095
AXEL	143
Aspera	121
Wget	807
AXEL	118
Aspera	87
Wget	971
AXEL	115
Aspera	83
Wget	1322
AXEL	166
Aspera	97
Wget	1226
AXEL	158
Aspera	13
Wget	1088
AXEL	139
Aspera	13
Wget	1099
AXEL	142
Aspera	87
Wget	1274
AXEL	177
Aspera	87
Wget	1819
AXEL	180
Aspera	91
Wget	1201
AXEL	136
Aspera	13
Wget	1131
AXEL	151
Aspera	81
Wget	1289
AXEL	123
Aspera	82
Wget	1200
AXEL	154
Aspera	82
Wget	944
AXEL	105
Aspera	80


================================================
FILE: docs/benchmark/TestiSeq-540MB/timeGSAHW.log
================================================
AXEL	18
Wget	9
AXEL	20
Wget	8
AXEL	19
Wget	13
AXEL	26
Wget	9
AXEL	20
Wget	8
AXEL	23
Wget	9
AXEL	20
Wget	9
AXEL	20
Wget	10
AXEL	20
Wget	10
AXEL	19
Wget	8
AXEL	21
Wget	8
AXEL	21
Wget	16
AXEL	21
Wget	10
AXEL	21
Wget	10
AXEL	21
Wget	11
AXEL	21
Wget	9
AXEL	21
Wget	8
AXEL	21
Wget	10
AXEL	23
Wget	8
AXEL	19
Wget	8


================================================
FILE: docs/benchmark/TestiSeq-540MB/timeSRA.log
================================================
Wget	102
AXEL	51
Wget	117
AXEL	68
Wget	82
AXEL	53
Wget	91
AXEL	54
Wget	100
AXEL	45
Wget	84
AXEL	44
Wget	98
AXEL	36
Wget	94
AXEL	41
Wget	84
AXEL	48
Wget	104
AXEL	46
Wget	85
AXEL	43
Wget	122
AXEL	39
Wget	84
AXEL	49
Wget	88
AXEL	63
Wget	120
AXEL	57
Wget	101
AXEL	62
Wget	80
AXEL	46
Wget	98
AXEL	49
Wget	98
AXEL	58
Wget	98
AXEL	43


================================================
FILE: docs/benchmark/benchmark.ipynb
================================================
{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 187,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "library(ggplot2)\n",
    "library(patchwork)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [],
   "source": [
    "theme_chy <- function() {theme(\n",
    "      axis.text = element_text(size = 12, colour = \"black\"),\n",
    "      axis.line = element_line(colour = \"black\"),\n",
    "      title = element_text(size = 15, colour = \"black\"),\n",
    "      legend.text = element_text(size = 12, colour = \"black\"),\n",
    "      legend.title = element_text(size = 15, colour = \"black\"),\n",
    "      panel.background = element_blank()\n",
    "    )\n",
    "}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 188,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "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fz6AW2+9lZlvu+027N76mEqlvG/Q63LSiffxZqu/9v9i4X5R/aXXqO+T5s2b5434ZeZuq4lc133++ef/8z//0/vTMIwHH3zwpptuev75519++eX3339/1apVq1atuv/++6+88spHH300N950KrhkN5qmCSCVSgGIRqMATjjhBO+m2a1UKhUKhbx/ewEpV2tr62c/+1mvXae8vPzEE08cN27cuHHjJk6cmFt86dMO9GvK2rx5s1eLctVVV82aNauhoeGBBx644447zj///IkTJ/ZAzvu9s88++/777//kk09isZhX9zV9+vTcX/7MmTNfeumlv//97z/72c+8sfS5RQ2vPX9PB+/UefJAL5Y+r5eDmnZQvLEOn/nMZ7p91SuAn3322XvaPZlMvvbaaxdeeKF3FT3yyCPedq+kcv7553fdJdse47Vtet1j5syZs8+seiWVIUOGdNp+/fXXA6ioqHjttddyt2cnqOgHJZWD+5qUUl49TEVFRWNjIzNHo1Gvo8TkyZO79irWJZWD0Nzc7D1IzZ8/33uIefTRR3MTeLVbRFRbWxsOhwHMnj07N0F5eTmAf/zjH52O7NUtI6eksv8XC/eLkopuU+l7YrHYSy+9BOBLX/pStwkuuugiAG+88UZtbS2AeDx+77333nvvvdmfu9/vnzlz5pw5cy699FIAXoVy1ltvveWN88rlVcrbtj106FAAXmeYDz74oOvZ33vvvXvvvfcvf/nL3t/FvHnzANxxxx1ee0+W91jXDxzo15T14IMPegPxfvOb33gtMeFw+KGHHgKwePHiu++++3DnfCAoKio67rjjALzyyiveUPnp06fnJhg9evSwYcOY+b777vMuh9wGFXRcAl3nEMvOO9kp5aFcLH1Mb0c17YA9+eSTAIQQ27dv7zbB+vXrvS/3gQceYGallNfw3mn0IjN7XZJuvvlm789sl+I777wzN1lLS4vXp/6qq67ytnjdloqLi3MHiDFzIpEYN25c9tS855LKiBEjADz++OOdtn/3u9/18tDXSyoH+jV51q1b51WDXHDBBZ3Sf/WrXwVgmuaHH36Yu12XVA6OV8HolUJGjx7dNYFXLeklGD9+fKdXveGQVVVVuaNMlFLZIffZksr+XyzcUVJ59dVX8/Y+e5wOKn2PNzfR6aefvpc0kyZNAnDqqad6f3p9twYNGvT44483NDQw8/bt22+//Xav+uv111/3kuUOfvzBD36watWq1tbWefPmjRkzBoDP59u0aVP2FN7EfCUlJU888cS2bdtc133//fe9Tk3V1dVevQ3vOah4VUNjx45dtWoVMyulVq5cmftQv2LFijx9YL3jIL4mKaX3OByJRHLHmXrq6+vLysoATJgwITfiekHloosuatiraDSa3cULKr/85S/3lDj3Rtlfvfjii9kf23XXXdc1wezZs/eSwHVdb/DjlClTvOkpV6xYcfHFF9u27U3OljtXxX5eLNwRVO67777D9K57gA4qfUxDQ4NlWfv82d1xxx3exeA1gWzdutW7H3m8JnfP7bffnt3LCyqXX375kCFDOpVoDcN47LHHck+xfv36kSNH5ibw/lFSUrJ48eJssj0FlXXr1mU7+FdUVHiP54WFhX/84x+9nmChUOi222479E+sVxzc1+QNwQPw8MMPd5vemwrMC/nZjfsz+BE5pUzuCCp70W0PwH6mpaUl2z/l+eef75qgubk5+6vudk6dTz755KijjvISeIcioj/84Q9epaU3K49nPy8WZs5OpzR48OD7778/7++6B+ig0sd4desAcgsNXWXnZLznnnu8LY2NjbfeeusJJ5xQVlYWCoUmTJhw+eWXdxri6wUVr7vRDTfcMGzYMNu2KyoqLrnkko8++qjrWaLR6D333PO5z32uurq6sLBwypQpt912W3Nzc26aPQUVZt6wYcMVV1wxcuTIUCh04oknXnfddVu2bGHmp59+urKysqCgIPfW2bccxNe0atUqr4/ctGnTcvu2duLNCWYYxjvvvONt0UHloHnDRIQQnX60WdmOiLW1td0maGhouO6668aPHx8MBk855ZSXX37ZcRyvAiB3pD3v38XCzMuWLTv11FP9fn9paemeni2OcMR77hinDTRf//rXH3vssVmzZnW7YoemaVmpVEpKadu2VyTN2rhx4/Dhw30+n9f5fgDSvb80TdMO2E9+8pNwOPz1r3+903avg4a3as7ApIOKpmnaAfM6vzz33HO5E7j99a9//cUvfgHgW9/6Vq/lrLfpoKJpmnbApk6d+uMf/9hxnAsvvHDIkCGTJk0qLCy8+OKL29rarr76am8E2MCkg4q2ixDCNM3cKVs0TduTO+64Y/78+eedd55pmmvWrBk+fPjll18+Z86c3DULBiDdUK9pmqbljX4m1TRN0/JGBxVN0zQtb3RQ0TRN0/JGBxVN0zQtb3RQ0TRN0/JGBxVN0zQtb3RQ0TRN0/JGBxVN0zQtb3RQ0TRN0/JGBxVN0zQtb3RQ0TRN0/JGBxVN0zQtb3RQ0TRN0/JGBxVN0zQtb3RQ0TRN0/JGBxVN0zQtb3RQ0TRN0/JGBxVN0zQtb3RQ0TRN0/JGBxVN0zQtb3RQ0TRN0/JGBxVN0zQtb3RQ0TRN0/JGBxVN0zQtb3RQ0TRN0/JGBxVN0zQtb3RQ0TRN0/JGBxVN0zQtb3RQ0TRN0/JGBxVN0zQtb3RQ0TRN0/JGBxVN0zQtb3RQ0TRN0/JGBxVN0zQtb3RQ0TRN0/JGBxVN0zQtb3RQ0TRN0/JGBxVN0zQtb3RQ0TRN0/JGBxVN0zQtb/4/EIJqvsO0WEEAAAAASUVORK5CYII=",
      "text/plain": [
       "plot without title"
      ]
     },
     "metadata": {
      "image/png": {
       "height": 300,
       "width": 270
      }
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "timeENA1 <- read.table(\"./TestiSeq-540MB/timeENA.log\", header = F, sep = \"\\t\")\n",
    "options(repr.plot.width = 4.5, repr.plot.height = 5)\n",
    "ggplot(timeENA1, aes(x = V1, y = V2, color = V1)) +\n",
    "  geom_boxplot(alpha = 0.8) +\n",
    "  geom_jitter(position = position_jitter(width = 0.2), alpha = 0.7, size = 3) +\n",
    "  scale_color_manual(values = c(\"Wget\" = \"#fc4e07\", \"Aspera\" = \"#00afbb\", \"AXEL\" = \"#e7b800\")) +\n",
    "  theme_chy() + theme(legend.position = \"\") +\n",
    "  theme(axis.text = element_text(size = 15, colour = \"black\"))+\n",
    "  labs(title = \"FTP from ENA\", x = \"\", y = \"Time (s)\")-> p1\n",
    "p1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 189,
   "metadata": {
    "vscode": {
     "languageId": "r"
    }
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAhwAAAJYCAIAAACmVahRAAAABmJLR0QA/wD/AP+gvaeTAAAgAElEQVR4nOzdd3wUZfoA8Oedme2bTe/0GsAgHRVE7DQLCAoiYsFD7/AEFeVUQOX09FSEOwtFRGk/wEIxcoiIcIggTQQCIRAIJQnpZdvsTnl/fwzOrdtS2Owm8Hw/H/2EmWdmn51M9tmZtwyhlAJCCCEUCkykE0AIIXTlwKKCEEIoZLCoIIQQChksKgghhEIGiwpCCKGQwaKCEEIoZLCoIIQQChku0gkg1BTl5+dnZ2enpaX17Nkz0rk0V3gMr054pRJMaWnp3Llzx40b169fv4SEBLPZ3LFjx1tuuWXu3Lnnz5/3u0l2djYJKjo6ulevXqNHj/7yyy99N3/11VeVsLZt29pstiC5ZWVlqTvMz8/3XJWTk/Pss8/ecccdrVq1slgsvXv3fvDBB7///vvgb7asrOztt9/u27dvfHx8YmLizTff/Oabb/I8H8JNnE7nwoULlcT0en379u2HDx/+j3/8w+l0ekU+8cQTwQ+jqmPHjp4b3nHHHcHjZ86cGfw4AIDdbr/zzjtHjBjxz3/+s9Zgv3JycnQ63RNPPOG7qgEn1Q8//FDHo6HIy8trWNqKcB7D//znP6NGjWrRooXBYGjXrt0TTzxx+PDhemU7dOhQNbFPP/201nhZltPT09VNDhw4oCxfuXKlsiQ7O7teCdTLX/7yF51Od+zYscZ7icijKIB58+YZjcZAx43juDlz5kiS5LXV0aNH637w+/bte+LECc/NBUHo06ePsvYvf/lLoNwqKyvT0tKUsM8//9xz1dy5c1mW9ftyd911V2lpqd8dbtq0KSkpyXeTdu3a/fbbbyHZ5NChQ506dfKbWOvWrTdt2uQZPGnSpDoeww4dOnhu2LZt2+Dxr7zySqCjqlKLwdixY2sN9iXL8o033qjT6c6dO+e1qmEn1datW+t4NBSnTp1qQNqq8BxDQRDGjx/v9yC89957dc92yJAh6ra33357rfH//e9/PV9u//79yvIVK1YoS44ePVr3V6+vwsJCg8EwYMAAWZYb71UiC29/+ffKK6+88cYbys/du3cfPHhw69atZVk+d+7cvn379uzZI4rizJkzjx8/vnLlSr97yMjIGD16tNdCSZJKSkqOHz/+888/A8C+ffuGDh2anZ2t1+uVAI7jli1b1qtXL57nP/roozFjxtx0002+O586dWphYSEA3HfffQ8//LC6fO3atc8++ywAsCx71113DRo0SK/X5+TkLF++vLKy8ptvvhk1atSOHTsIIZ5727Zt2z333CMIglarHT16dN++fa1Wa1ZW1t69e0+fPn3fffcdOHDAYrFcziYFBQVDhw4tKioCgNatW48fP75NmzZ5eXlZWVnZ2dlnz5695557tm7dOmjQICW+b9++wS/UBEH4+uuvKaXdu3f3XHju3DkAyMzM7Natm98NMzMzg+wWADZs2LB48eLgMcF98sknO3funDZtWsuWLT2XX/5J1adPH8/P0EBiY2MbnHzYjuFTTz2lvM20tLSHH344LS3t6NGjK1ascDgczz33XHx8/MSJE+ub/LZt20pKSvx+11GtWbOmvrsNodTU1ClTprzzzjuLFi2aPHlyBDNpRJGuak3R3r17lY9do9G4YcMG34Cff/5Z/TbndaGgXqmMHj06yEv88MMPOp1OiVy0aJHX2nnz5imr2rdvb7fbvdZ+++23ytrU1NSysjJ1uSiKbdq0AQCdTvfjjz96blJSUtK1a1dlq2+//dZzVXV1dWJiIgAkJCQcPHhQXS7L8vTp05VNXnjhhcvcRP37GTt2rNPpVJcLgjBjxgxlVUZGhiiKQQ6ap7feegsAYmNjCwoK1IUnTpxQdrVkyZI67sdLYWFhQkKC+tfRgCsVm80WFxen1WpLSko8l1/OSaVeqUyZMqW++dRXeI7hrl27lLW9evWqqKhQlx86dCgmJgYAEhMTq6qq6vJySpVlWVaj0QDAhx9+GCRYkqSUlBQAUL/GhflKhVJaVlam0+liYmKsVmujvlCkYFHxQ71y/+yzzwLFHD58WDkvvW6/1LGoUEpfe+01JXLy5Mleq2RZvvnmm5W1U6dO9VxVVVWVnp4OAISQ7777znPVoUOHlE1mzJjh+3JbtmxR1nrdu3jllVeU5V988YXXJpIktW/fHgDatWt3OZtUVVWZTCYAaNu2rWdFUd/sLbfcouzQqxYGkpubqxz8ZcuWeS5Xy+1PP/1Ul/34ZnLnnXcCgHr104Ci8tFHHwHAqFGjvJZfzkkVzqISnmN4zz33KGsPHTrkteqDDz5QVr3//vt1eUWlqOj1+qFDhwLAjTfeGCT4xx9/VHY+cuTISBUVSqlyD+ODDz5o7BeKCCwqfvTu3Vv51Pb8DuVr8ODByllYVFSkLqx7UVHv7d5www2+a8+ePavcPmIYZteuXeryRx99VNnq6aef9tpk1apVyqr//ve/vju0Wq3KN+URI0aoC2VZVm7RpKSk+L1KyMrKevXVV1999dWampoGb7J9+3YlsZdfftnvofjss8+UgDfeeMNvgCdZlpVbgnfddZfXqvnz5yv7CdR0FJxygWgwGNTyXN+iIstyRkYGAKxbt85r1eWcVOEsKmE4htXV1cpleteuXX33UFpayjBMoL8LX2pR+fzzz5UjfP78+UDBTz75pFKz58yZ0xhFxW63u1yuWsM2bNgAAJ06dboiW1aw95cfLpcLACiloigGCfvzn/88ZcqUKVOmKH8D9aXcQQqkVatW//rXvwBAluVHH31U6VK1efPmpUuXAkCXLl3efvttr03Onz+fkJCQkJCgXMp4cbvdyg/U42EHBw8eVHocPfTQQ36b94cPHz579uzZs2dHRUU1eJMLFy4oP/To0cPvm1U+iAGgsrLSb4CnRYsW7dixIy4ubtGiRV6rTp06BQCxsbGet1/q6OjRo8qNuHfffVfNp76+//77nJycuLi4YcOGea0Kz0l1+cJwDH/55RflaNx1112+axMSEq6//nolLHjnQy/33nuvTqejlK5du9ZvgCRJX331FQA88MADXs2KXgRBmD9/fv/+/WNjY41GY+fOnadMmXLy5EmvMKXDmHLbbd++fYMGDbJYLDqdzmw2d+vW7fnnnw/UnW/o0KEJCQm5ubmbN2+u+xtsNiJb05qmUaNGKQfnscceq/tdfkXdr1SUbysA8PDDDweKuffee5WY6dOnV1VVtWjRAgA0Gs2BAwfqlRWldN26dcquPC8XlixZoiz86quv6rifBmyyefPmRx555JFHHvHq6qZSe1cHvyFOKb1w4YJyAffRRx/5rlVugFx33XW5ubmPPvpoZmam0WhMSEgYNGjQ+++/73A4Au2W53ml8XnIkCHKP5V86nulonRae+CBB3xXXc5JFc4rlTAcw7lz5yqrNm7c6HdXL7zwghIQqOehJ/VKhf7+99KvXz+/kWqv+sOHD//9739Xfva9Uvnpp5/69evn+1Gp1Wq9zk9lE47jNm3axHF+Oj2ZTKY1a9b4TWbcuHEA8Pjjj9f6BpsdLCp+bNq0ST0tunXr9uGHH164cKGO29axqMiyrN7o8Hu3SqF2ZWFZVm14+Mc//lG/90Ppzz//3Lp1awCIjo72fC9qu/rPP/9cWVk5a9asa6+91mKxmM3mzMzMGTNmeN6EafAmtRoxYoSyz3379gWPVO7+tW3b1u12+67t0KEDAMTGxvr9C2/VqlWgYjx16lQAiI+PLywspJdRVJSW9nnz5vmuupyTKpxFJQzH8C9/+Yt6CvndlXoVXpcvLp5FZfXq1cqGeXl5vpFKs1ZGRgalNEhR6dy5s/JGJkyY8N57702ZMsWzF9yqVavUHSqbEEKUzgWxsbHjx49/9913n3766WuuuUaJZxhmy5Ytvsko9yFat25d6xtsdrCo+Pfiiy96/TllZGQ8+eSTq1evDv6hGbyoiKJ44cKFLVu23HrrrUqY30Z1T+vXr/dMY+DAgb7jGPw6fPjw3XffPXjwYKW7i/KJsHv3bs+YRx55RFm1fv16deCLJ7PZrPTcvZxNglPvYt16663BI48fP67ccPNqn1cIgqB+DrIsO2rUqHfeeeedd96ZMGGCeqcxOjradwzHli1blJshar+DhhUVdcjhnj17/AY0+KRSi0q/fv1erc3q1avrnrOX8BxDtRN8Tk6O3zQ++eQTJSBIpwaVZ1Gx2+1Kl5A333zT963Fx8cDwOzZs2nQogIAffr08WyYEUVR/d3Fx8fbbDbfTXr06JGfn++5yd/+9jdlVZs2bQRB8Mpn7969ytrLHFTUBGFRCWjz5s3Dhw/3+30tIyPj2Wef9dugV/fBj0qrQF0yue+++5RNGIap+ynoNWJOp9N99tlnXjde7r//fjUZAEhNTZ00adLcuXOnT5+uNCwDAMdxnp2yGrBJIC6Xa8aMGUrjQWxsbHZ2dl2OQ5cuXfyWVaUxAACSkpJ++eUXz1XFxcXKXR0AuO222zxXlZWVpaamAsDEiRPVhQ0rKspHoUajCdJU27CTql6DH++999665+wlPMdQvRMYqC+Aequ2Lv2jPIsKpfSBBx4AgO7du3uFqa0Xx44do0GLik6n89vUr3YYW7x4sdcmHMf5vTZSN/nyyy+9Vrndbq1W67m3KwYWlVqUl5evW7du6tSpPXv29G07vf/++9U+Toq6F5Xu3bvv2LGj1gSKioo8m0zffvvtOmZ++vTpV199dfr06WPGjFEvVvr27ev5l3z33Xere37ggQc8RwZIkqSO1OvcubNajRqwiV+bNm1SB9jHxMQEuhOi2rdvX6C/T0VRUdGCBQsWLFigfGp4qampUcfEHTlyRF2u/Nm3bt26urpaXdiwovLyyy8DQFpaWq2R9T2pwlZUwnMM1ZZCz1FWnr7++mslwO+NRC9eRUUtSF5v4bHHHgOAzMxM5Z9BiopvF3/FkSNH1NPeaxPPaup3E79tJ0oT6UsvvVTre2xesKjUQ1VV1TfffDNlyhTlbFD06NHD8/6+WlQyMjJe8fHyyy8/+eSTAwYMUGIYhlm/fn3wF1X7ESmdTLRarW/X/lopo5SV/XhOZaFednTs2NF3BAmlVG3I+f777xu8iZf8/Pzhw4erB/C2224L0gdUpWyiDEGv03v2oYyXBIC5c+cqS5RR3wzDeFX3hhWVxx9/3PNjq47qclKFs00luJAcw4ceekhZdfLkSb+vot7++uSTT2pNyauo8DyvdOWYNWuWGuN2u5VZBv7+978rS4IUFa+Rp56Uq3O1J7S6ycKFC4Nv0rNnT99V1157LQA89thjtb7H5gWLSkPIsrxkyZLo6GjllHrnnXfUVXVsqP/iiy+UsJYtWwYJU0bSAcBNN920fPly5edrrrmG5/kG5KxOgqJ+iVMbSALNtqS2fM6cObPBm3havHix2tW4VatWy5cvr0uROHfunPKN3u8+6+i7775TXlcZ4lNSUqLcf3/xxRe9IhtWVJTuBoMHD25YekFOqqZTVEJyDP/85z8rq7zusKnUOSjXrl1ba0peRYX+3mbTqVMndYk6ojM3N1dZEqSo7Ny5M9BrKb3CkpOTvTYJ9P1J3aRFixa+q5SvX8OGDav1PTYvOE7F24EDB5YsWbJkyZKqqqpAMYSQxx57TBlsBQBZWVn1fZXRo0crnfTPnz8faMrS3Nzc559/HgBMJtOnn3760EMPKeOQjx49+tJLL9X3FQkh6vXB8ePHlR/UlvZAszmpow2UabsatomC5/kRI0Y88cQTVqvVZDK98cYbJ06ceOihh4KPGFAsXbpUlmUA8JzorL6UOWwAwOFwAEBFRYXdbgeAt99+22sWXnUOj9WrVytLvOZC9qumpgYAlA9ZL+E5qcIgJMdQ6WAGAOXl5X5fpaKiQvlBmZ2hvsaOHQsAubm56gBMZeRKz5496/J7DEK5W6D8v16bCILgu8psNgNAkFOimcKi4m337t2TJk2aNGnS/v37g0eOGDFC+cvxHRVVF8oILwBQpob0IoriQw89pPzpvvXWW+3atQOABQsWKFfx77//vjrhhKpt27apqaljxowJ9IpqPVD/aLt06aL8oLyQ3zSUHwwGQ4M3AQBJksaNG6d8YRw4cODhw4dfeukl9XMnOEqpMqX5wIED1c8jX9LvAgWoxzn4sNMGU3brd/xm2E6qyxSeY6ieQmoPKC9K+xnDMErv3vq67bbblI5eykWz2+1WulAqbfi1On36dKBVysRoycnJdd9E+T36HUmqnCrBp79sjnCWYm/qx9a2bdtuu+22IJEXL15UrvHVZvB6UT/i/X4MzZkzR/nTGjRokNqvPyUlZf78+cpgyYkTJx4+fFjpIK+IiorKz8/3mtnbU25urvKD+lcxcOBA5YdDhw6p0zF5Uh9uoX5nbMAmADBz5kzlD/uhhx5aunSp3+5PgWzduvXs2bMAEHza2v79+x84cEAZJ6H0q/Gi3plUeqklJyer00x5EQRh2rRpANCrVy+lgVe9KxWEclT9fvsO20l1mcJzDAcMGKDVat1u97fffjt79myvDa1W686dOwHguuuu83vZVyuNRjNq1KjFixevXr36rbfe+u6776qrqwFAbQ4Mbvfu3X4viE+cOFFWVgYAffv29d3kT3/6k+8mp06dKikpAQCl+cSLcqpE5BfduCJ9/63JsVqtyrcw5Vk6QSLVvwfPKRrrPqJemXAF/PWb3L17tzIgw2g0+vYhVocKjh8/3nO50lAMAFu3bvV9OZfLpUxUzDCMZwcw5S8kMTHRd04qURTVPwbPwfD13cRqtSptp/369avjIBtP6gzHwUcLqiMJli5d6rvW4XAot25MJlNlZWXwV2xYm8rrr78OAAkJCb6rLvOkClubStiOodI7mRDiObZDoU5h59mqFIRvmwql9IcfflB2snv3bqVfgNcw++Bdiv2eaWrPfnWeb3UTjUZz+vRp303UayO/I6uUbyGvvvpqXd5mM4JFxQ915vmkpKR169b5tiTb7fZ3331XaQyIiYlRhhAr6l5U1FkUvaZZtNls6hfb+fPn+25YUFCgXqB4TgKhPKMFADp27OhVihwOhzpL7pgxYzxXffPNN8ry22+/3bPY8Dyvfpp79VKt7yYff/yxsvCbb74Jfkz8Um79tWnTJnhYTk6OcgFkNpu9hh9WVlaq31K95uT3q2FFRZlXKtCUkZdzUl1OUamqqjp69OjRo0fVNuogwnYMd+zYoawdNmyY58DAixcvtmrVCgBiY2M9OygH4beoqFPcT548WekY8u6773oGBB/82L9/f8/jL4qi0l8cALp166b+7jw36dWrl+cz2SRJmj17tvLbTEtL8+1ZU11drfQ98Z3qu7nD219+PP3007/++uvnn39eUlIycuTIlJSUTp06tW/fPiUlpaKioqioaPv27UqrLMdxS5cuVUZ+1Zd6m9WrQfvZZ59VxqANHDhwypQpvhumpaW9//77yoQlSgdlZQbJ66+//oknnli8ePHJkye7dev2wAMPZGRkREVFnTx5cuPGjcojh1NTU9977z3PvY0YMeL+++9fu3bt999/n5mZec8991xzzTVnzpzJyspSbpelpKR8+OGHl7PJTz/9pPywatUqdcYzvx588EF1zn/FmTNnlBvWaj/sQDp37vzyyy+/9tprNpvthhtuGDVqVJ8+ffR6/bFjx7KyspTGgN69eyvXE43h5ptvZhhGluVffvnF91FaITmp9u7dqz4xIYiMjAz1O3JWVpbyVT0jI0PtoBFI2I7hoEGDJkyYsHz58k2bNg0ePPjpp59OTk4+cuTIO++8o0zCOHfuXK/nwtULwzCjR4/+4IMPFi9eLMsyISRIW6OvX375pUePHiNGjLj22mvz8/N/+OEH5aauTqf79NNPfbuWxMbGHjx4sFevXiNGjOjZs+e5c+d++OEHpZsAIWTx4sXqw5NUe/fuVRLzOuGvBJGuak2UJElvvfWW2vnVr3bt2vl2Jaz7lYoamZKSog4hVC8CDAZDoF78Cs/hzepXJ6fTqXb59ZWZmXn8+HHfXTkcDvWWmpcuXbr4/YZbr03ULgm18r0TqE7i8vHHHwc/norXXnvNb2MAAAwZMqTWmzaKBs/9pTwKWpkIxFeDT6r6Pk7Y8zJR/TatzHlVF+E5hk6n0+8sxSzL1mt2O79XKpRS9asM+JtFP9CVSnx8/GeffebZVKmKjY31msVLPbbffPONOtmXJ4PBsHz5cr9pK3Pv9+rVq+7vtLnAohJMcXHxhx9+OGLEiPbt21ssFoPB0Llz5zvvvHPy5Mnr1q3zO6dh3YsKpVSdo37cuHHUY/pIqMMTis6fP6+2fHrdJfvxxx8fe+yxTp06KRNxp6enjxw5cuXKlb4TEHn66quv7rrrrvT0dK1Wm5iYePvtty9evNjve6zvJnVvivQtKuotl8OHDwc/IKrc3NwZM2b06NEjNjZWp9O1bNly7NixmzZtquPm9DKKijLxe/AnpTfgpApzUaFhPIb/93//d/vttycnJ+t0utatW0+YMCHQ4JVAAhUV9cE/vn8gNHBRUZrECgoKpk2b1qVLF5PJpMyU+vLLL3s9ypN6HNv9+/fzPP/OO+/07t1b/Z0+88wzvi1GKuVL4fTp0+v1ZpsFQj2eroEQuhw5OTldu3blOM7rkboR9+KLL27atEmdNQSFxMqVK5Vbi/v371cnvquLysrK1NRUl8t19OhRzymQrww4TgWhkMnIyLj99tsFQVizZk2kc/mD6upq9Ws7iri1a9e6XK7bbrvtyqsogEUFodB65plnAGDZsmWRTuR/XC7X9u3b1QFGKOKUKZeUU+XKg0UFoVAaOnRoZmbm3r17f/3110jnAgCwffv2Ll26aDQavz0JUfgdPXp0165d3bp1833m9JUBiwpCoUQIWbRoEcMw6siGyEpOTn7rrbd++eWXy+mhi0Jo5syZhJCFCxf6PvXgynBlviuEIui666576qmn/vOf/yjTjURWly5d7r//fqPRGOlErkAcx5nNZrPZXPfysHfv3vXr13s+/+LKg72/EAo9q9X66KOP9ujR45VXXol0LqgJ+ec//7lnz56lS5fWZTa5ZgqLCkIIoZDB218IIYRCBosKQgihkMGighBCKGSwqCCEEAoZLCoIIYRCBosKQgihkMGighBCKGTwyY+XOBwOl8vFcVzwZyghhBAKAq9ULnn22Wfj4uLUxykihBBqACwqCCGEQgaLCkIIoZDBooIQQihksKgghBAKGSwqCCGEQgaLCkIIoZDBooIQQihksKgghBAKGSwqCCGEQgaLCkIIoZDBooIQQihkIllUtmzZQgI7e/asV/zq1asHDx4cExMTExMzaNCgFStWBNpz3SMRQgiFUCRnKc7Ly6tjpCzLEydO9KwNO3fu3Llz5+bNm5ctW8YwTAMiEUIIhVwki8qpU6cAYNy4cc8884zv2tTUVPXnefPmKXVizpw548aNI4SsWrVq5syZK1eu7N2797Rp0xoQiVCjopJVqDlMhXJgtKy+BWfqAoSNdFIINT4aOXfffTcAfPjhh8HD7Ha7xWIBgJkzZ3ounzVrFgBER0fb7fb6RvqaPHkyAAwYMKCh7wahSyR3uT3//fJ9t5bu6lm6s2vpT9eU7e5X8ev9fEkWpXKks0OocUXydpBypdKxY8fgYVlZWTU1NRzHeV1nTJs2TaPRVFdXZ2Vl1TcSoUYiOU9XZ//Zfm6B5LpIuChGn87oUghhxJqD1pOzbXlvUCpEOkeEGlHEigql9PTp0wDQqVOn4JEHDhwAgIEDB8bGxnouVxrhAWDHjh31jUSoMVCxypr7ilSzn9WncYZ2DBdNGD1hDESTyJm7AMj8xbXO8wsjnSZCjShiReXChQs8z+t0usLCwnvvvbdVq1YxMTEDBw58/vnny8vLPSMLCgoAoHv37r47yczMBIDs7Oz6RqpqfieKIjbjo8vkLFwp1Bxk9C0Ja/Zdy+pbAFBn0RrRnhP+3BAKj4g11Cv3vgRBuOGGG9SFu3bt2rVr1/Lly5ctW3bnnXcqC5VSERcX57uT+Ph4ACgpKalvpOqOO+4QRVH5uUWLFpf1ltDVjco8X/ItAEO4qEAxrKGlYDvpLtvMmTLCmRtCYROx7+ZKUZFleeDAgVu3bi0vLz937tyKFSvS0tJKSkoefPDB4uJiJVIpFUpV8KIstFqt9Y1EKOQk+wkqlDJaP99pPHCEsO7q/WHKCaGwi9iVSlpa2pQpU5KTk1988UWNRgMAcXFx48ePv+WWW7p06VJRUTFz5sxFixYBgCzLwXdFCFF+qHuk6l//+pfyw/z587Ozs1u2bNmA94IQAEjuciq7CWcJHkYYney6CEABvM9GX3zxOsmRyxo76ZNHhihNhBpXxIrK8OHDhw8f7rs8NTX1r3/965w5c3766Sd1SV5eXkVFhW+wsjA9Pb2+kap+/fopP0RFRfE838A3gxAAwxqAMASk4GGUSoQx1qWiAABftJwvXqdPHolFBTUXTbFpulevXgCQm5vrcrng91GQfkuF0qSflpam/LPukQiFHKNvRVgTFW21xMk8Z66lxyNCzVdTLCparRYATCaT8oNSCXJy/HSYOXHiBHhcf9Q9EqGQY/XpmqhrZbGK0oC3YalYRViTJvbGcCaGUDhFpqgIgtCjR48uXbps377dd+1vv/0GANdee63SBKJ0D9u+fbvN9ofvgA6HY9u2bWpAvSIRagyG9ImMNlnmzwBQ37VUdkl8IWfO1CUMCX9uCIVHZIqKRqNJSkrKycl57bXXJOkP96ArKirmzZsHAMokLgAwZMgQi8XicrmWLl3qGfn555/zPG+xWIYNG1bfSIQagya6nyH9UcIYJftJKv2hiU4WKiRHHmvsGNVxFmF0kcoQocYWsdtfr776KsMw27dvv+eeew4cOMDzfHFx8bp16/r3719SUtKzZ8+pU6cqkRaLZfr06QDw3HPPrVmzxuVy8Ty/evVqZRrKF154QZnvq5q0YJsAACAASURBVF6RCDUSY4vHTW2nM4ZWEn9etB0XHXmi/aRgPUYluyZmoKXrv1gjNqigK1oE5x1bunSp0mripV+/fidPnvSMFEVRvXAxGo063aUveiNHjhRFsWGRXnBCSRRCIl9kv7C0+tjTFb+Orjo03npyNl+6WZbd9d1P5a8jizZD5a8jGyNJhBpDJKe+f+SRRwYMGDB//vwtW7ZcuHAhISHh2muvvfPOO5966imW/cMk4SzLrl+/ftGiRUuWLMnJyWFZtkePHpMmTXr88ce9hp7UPRKhxsPqUozpj0D6I5FOBKFwI5T6aVG8Cj355JMLFy4cMGCAOj4GoYirOjRKGacS0+PrSOeCUJ00xS7FCCGEmiksKgghhEIGiwpCCKGQwaKCEEIoZLCoIIQQChksKgghhEIGiwpCCKGQwaKCEEIoZLCoIIQQChksKgghhEIGiwpCCKGQwaKCEEIoZLCoIIQQChksKgghhEIGiwpCCKGQwaKCEEIoZLCoIIQQChksKgghhEIGiwpCCKGQwaKCEEIoZLCoIIQQChksKgghhEIGiwpCCKGQwaKCEEIoZLCoIIQQChksKgghhEIGiwpCCKGQwaKCEEIoZLhIJ4DQlYqKtmNCzUHZXQqEZfUttNH9GH3LSGeFUOPCooL8c8nykWrbRZcbAFL0umuiTHoWr2vrSnLkOc7+2129RxYqgUoAQBgt0STok4YZWz5FuOhIJ4hQY8Gigrzxkry2sHhtQfFF3s1LMgDoWSZZpxuTnji2RYqewdJSC6HmV9vJlyXHSaKJZQ3tCKMBACrxsrvEceEz0XosKuNdRpsU6TQRahT4AYH+oEoQp2effCf37CmbQ88waXpdmkFnYNk8u/3dk+eeO5Jb4RYinWOTJrtLbCdfFW25rLEdo01RKgoAEFbPGloxuhR31W7bqdeVyxeErjx4pYL+R6L077n5W0rKE7TaeK1GXa5nmFgNV+EWvi+p0DDMe9d0YkkE02zSnIWrRMcJ1tgGiM53LcNZQOtyV/3sKt+qS7gz/Okh1NjwSgX9z9bSih9LKmI0Gs+KoorTauK0mv+WVW4uLgt/bs0ClV3u8i1AWMIaA8Uw2kQq1rjKt4YzMYTCBosK+p+si+XVopik1QYKSNJpa0Qx6yIWFf8kZ74slNfaDk9Yo2j9DUAOT1YIhRMWFXSJTZSO1FijOJYEvbUVrdFkW+1VghiuvJoTKtZQWVTbUQIiGirxVLSFJSmEwgrbVK5264pKcm2OTmZj7xiLS6I6ppbWEi1h3LJc7hZiNHjyeGO4KMJwQGuruFQkjJawprAkhVBY4ZXK1W75uYszsk8tP3dRzzAsAzKtpajIQFlCsGOxX6yhDaOJo2J1LXGSXWPpDoQNS1IIhRV+NKBL4rWaJJ3WKtXyLdsqSvFaTbI+YLvLVY3Ra+JuobKbSnygENldDlyUNu6WcOaFUNhgUUGXsIQMToiVKVUGPPrlkiRRpoMTYrngDS9XMUPaeM7YSXSeBupnQA8V7bJQoo3uq8X+xOgKhUUF/c/9aUntjMYzDqdEqe9aGegZJ9/WpH8gPTn8uTUXrC7N3P5lztBGtJ+kQinApUGOVBZkvkByneeieprazyKktsZ8hJonLCrof1L0uhc6tk4z6E7Y7FbxD/fBrIJ4wupI0eumd2idbvAzrA+pNDHXW7rM18bdTGVRtJ0UbcdF23HJeRpYnSHl/uiuH7L6FpHOEaHGgh140B/cnBirYzu8d+pcrs1+3unSMAQABJnqGSbTYn62Q6uB8TGRzrEZ4MzdorstEGr2CzW/yq6SS7MUx/RnTRmRTg2hxoVFBXm7IS66e6+uW0oq9lbVnHU4qUxbmwx9Yyx3JsdFcXjC1BlhNdH9NdH9I50HQmGFnxHIDzPHjkpLHJWWGOlEEELNDLapIIQQChksKgghhEIGiwpCCKGQwaKCEEIoZLCoIIQQChksKgghhEIGiwpCCKGQwaKCEEIoZLCoIIQQChksKgghhEIGiwpCCKGQwaKCEEIoZLCoIBRKVKyR3cVUdkU6EYQiA2cpRigEqFjDF3/tLvtBdJ0DKhGi1URlahOG6BLvAGAjnR1C4YNFBaHLJVh/s+e9LtpyqCwQLgoIC9TmKv3WVbnTXb7Z1H4mo0mIdI4IhQkWFYQui2jPseW+KNpPsYZWhDV7rpLdJa6S/1DJEZXxvtcqhK5U2KaC0OWQ7GfeEe2nWFMH37LBaJMYfYq7cpez4POIJIdQ+GFRQajh3BU/CTWHGF0SIVq/AYSLAWD4knWyUBnm3BCKCCwqCDWcUL2PSjWMJj5IDKNNlF2lQs2BsGWFUARhUUGo4WRXIZUBgASJIayRyk7ZVRSupBCKJCwqCF0OGrSgAAAAIQAAVG78ZBCKPCwqCDUco00mlALQYEGSkzB6RpcSrqQQiiQsKgg1nCa6N9GYqVAVJEZylxJNnMbSK2xZIRRBWFQQajht3E0aUzfJVQQg+g2gopVKLl3icEabGObcEIoILCoIXQaiNbZ9jtW3FG0nqcx7raRilcRf0ET3MbWcFJHsEAo/HFGP0GXRWHpFdXzdmvem5MwDomE4CxCWym4qVBFWp40daO74GuFiI50mQmGCRQWhy6WJvTEm81Nn0f+5y7fJQjnIbsJoNDF9tAnD9SmjCGOIdIIIhQ8WFYRCgNGlmto8a2w1RXYVUclGNLGsLjX4+BWErkhYVBAKGcJoWUPrSGeBUCQ1rYb6BQsWGAyGadOm+V27evXqwYMHx8TExMTEDBo0aMWKFYH2U/dIhBBCIdSErlRycnKee+45nudF0bt3pizLEydO9KwNO3fu3Llz5+bNm5ctW8YwTAMiEUIIhVxT+ZAVBGH8+PEOh8Pv2nnz5il1Ys6cOadOncrLy5szZw4ArFy5cv78+Q2LRAghFHq0aXjhhRcAgBACAFOmTPFcZbfbLRYLAMycOdNz+axZswAgOjrabrfXN9LX5MmTAWDAgAGhe0/Nw8g9v8G670fu+S3SiSA/Kn8dWbQZKn8dGelEEKqrJnGlsn379nfffbdz585Dhw71XZuVlVVTU8NxnFdby7Rp0zQaTXV1dVZWVn0jEUIINYbIF5WqqqqHH36YYZgVK1YYjUbfgAMHDgDAwIEDY2P/MIJMaYQHgB07dtQ3EiGEUGOIfFF58sknz58/P2vWrD59+vgNKCgoAIDu3bv7rsrMzASA7Ozs+kYihBBqDBHu/bV8+fI1a9b079//pZdeChSjlIq4uDjfVfHx8QBQUlJS30jVRx99JEkSAFy4cCEmJqZh7wIhhJAikkXlzJkzU6ZMMRqNy5cvZ1k2UJhSKpSq4EVZaLVa6xupWrZsmdqDWWnkRwgh1GARKyqSJE2YMKGmpmbBggUdO3YMEinLtTwyT+kzVq9IVVpamnKlUlZW5js+BiGEUL1ErE3lzTff3LVr17Bhw5S+vEGkpqYCQEVFhe8qZWF6enp9I1Vff/31hg0bNmzYkJmZWVhYWO+3gRBCyENkrlSys7Nff/31+Pj4JUuW1BocpFSUl5cDQFpaWn0jEYoQKtpzRdtRKlYDY+CM7TSWnkC0kc4KoZCJTFHJz88XRbG8vFwpA14++OCDDz74AAC2b99+0003KZUgJyfHN/LEiRPgcf1R90iEwk+wHnGe+1iw/iqL1SALQFjCmllDa2OLR3WJw3FKY3RliHyX4lrdcMMNALB9+3abzea53OFwbNu2TQ2oVyRCYeYq21KT8wxftgWoxOpbclEZnLEtYfWS9Yjt1Gu2M+8A1NIiiFCzEJmiMnz4cL/j+0ePHg0e07TcdNNNADBkyBCLxeJyuZYuXeq5k88//5zneYvFMmzYMGVJ3SMRCifBesR+5m3ZeUET1YnRpRBGB5QA0TCaONacQanAF612Fq6MdJoIhUAzuFKxWCzTp08HgOeee27NmjUul4vn+dWrVz/zzDMA8MILL6hdgeseiVAYUeeFBZLzLGfq4PeGM6tvRSWns3CZ5LoY/uQQCq0mNPV9EH/729/27du3cePGsWPHGo1GSZJcLhcAjBw5csaMGQ2LRCg8RPtJofogo40DEvDPjTW0kPgL7oofDanjwpkbQiHXDK5UAIBl2fXr1y9YsKBv374sy2q12v79+y9evPirr77yGjVZ90iEwkO0HZPFGsIFm6+BMAaQBdGG0wihZq9pXal88cUXgVYRQiZPnlzroJZ6RSIUBrJYBVSoQ79hhrrLw5EQQo2peVypINR8MawJgAWQgocRIhMO2/xQs4dFBaFGQ90yf54QjuEMVKgJGilSYFlju3BlhlBjaVq3vxC6Mkj8Wb5otat8O5WqQRYl53mgAkBnRpcE1M8gR9FVxGgTdHE3hT9VhEILiwpCIeYq/dae/77oPMswOsKZgOEYTYzkPC9YDzOuNI25ExCNZzwVKkFy6lJGs6aMSOWMUKhgUUEolFzlW22n35RdZZypPVEb5zUJQHSSI192XRCoW2O59tKdZypIrotUcmpjbzS2+msE00YoVLCoIBQyslBpz58nu0s5cyevBkvW2A4YneQ8LbtLhap9hIsGIgNlGV2CIWWModXTDBcVqbQRCiEsKgiFjKvsP7LzNKNv6bcLDKtPZ7SJku0IsGZd/C2Ei2EN7bRxgzhT5/CnilAjwaKCUMgI1XupLLCsKVAAYbSMoS3ILkOLJzSWXuHMDaHwwC7FCIWM5DxHmFoGORLWQGVedhWHJyWEwgyLCkIhQwhLaw2il0IbOxmEIgKLCkIhw+hbguwKHiPLDsIYGJ2fx9MhdAXAooJQyGii+xNGD5ItWJBQxujTOXPXcCWFUFhhUUEoZPRJw1hTB5E/H2imL9ldCkRvSB1L/jj+EaErBhYVhEKGsFGmNs8z2lTJfpJKvOcqKttE+3HJeZY1tmVNGfjwYHSlwi7FCADgtN35QvapakFM1GqusZhvSYxN0tU6VTvyQxs7MKrjq/bT/xQdZ4AwDGemMi+5iqhoJwSANUr2nJrsP7HGDFOrP2liBkQ6X4RCDIvKVa1KEI/V2AEgz+74ukhmKJUBtEUlS8/pH22V9kCLZOyi1ADauFs4c1e+aK27codoOy7xBUAFwkWz+hasLplSkYrVQtWuGudJQ4s/GdMfiXS+CIUSFpWrV6VbmHrkZAHPA4CJ47qajcpypySfdfLvnDpb7HI/075lRHMMB1fJBtGe0xh7ZrQpVNrPMBzRJAPhQHZIzjPKKsJoRHue7dRsoXInZ+oUaA+iPVf5v/3M242R4eUztnwKHwODPGFRuXq9e+rc7soqHcvYJMnzisTAMp1MxnwHv+rCxS5RxjuS4iOWYlg4C5fzxV810s6pDIQFECr8r3WD48KntQ5ZEW3Z1twZoU8uFPQpY1ksKsgDFpWr1G81tm2lFRaOswr++ym1NupzrPalZ4tuTYxnr4K7YITREU1sCHdIqUCFGsIBAAMBDiABClQmXBRhdCF86XCQ3XKASomuclhUrlL/LassE4ROJmOB0/9gPQKQqNXm2Z1HrbZrLeYwpxd+2vg7YnttDOEOHQWf2U+/yRk7AmEDR1HRnmNq+ZSxzbMhfOkwcFfsqNg3ONJZoKYIuxRfpU7bnZQCG/TOS5SGtUniaZszbFldUcQqABq0ooByrSILlWFKCaHGh0XlKlUjSCyp5bfPEUaiYJf83x9DtWAMQOH3qb4CIwCsMRz5IBQWWFSuUkl6rURrqRZuKmsIidXgPdKGYA1tCWukQadsoTJPiIYztA1bVgg1NiwqV6luUSYNYXgp2LjuSrcQreGuuQoaVBqDNqY/o0uTXEVBYiS+iGiTNLEDw5YVQo0Ni8pV6tbE2HSD9jzPB7o9I8hylSBeHx/T2qgPb2pXCMJFG9IeJIxeDlBXJHcZAVmfPIrVtwhzbgg1HiwqV6lUvW5CyzQ9wzhlPzfBBFk+ZXe2Mxkmt04Lf25XDEPag/rEEVTmRcdpKrv/t4IKMn+OilXauFtMLf8UuQQRCj28XX71mtAy9SLvfutkPgBxy1SglCXglmilIFQKUluj4eVObTqasQ35crCmDrMZXZrz4hrJmQ+yCAwDVAZgGF2SMfVuY+ungcELQXRFwaJy9WIIvNCx9YaLpbsrqmSg+XanRKmWYSwa7q6U2KfapnfCinLZCNEYW/1ZlzTcXf6jaDsuC6WMJoE1dtDGDQ4yOwtCzRcWlasaIZCi0wJAj+iop9qm87Icq9F0izK1MxkindoVhdW3NuDEkejqgEUFAQDEarj705MjnQVCqNnDhnqEEEIhg0UFIYRQyGBRQQghFDJYVBBCCIUMFhWEEEIhg0UFIYRQyGBRQQghFDI4TqU5kSnkO5xlbkHPMi30ujitJtIZIYTQH2BRaR54Wf66sGR9Yel5J++WKUPAxLF9oi0TWqdeDc/6RQg1F1hUmoFil3vW8byfK6pdMo3TcGaOlSmtFsT1F0v3VFVPap02sWVa0OcCI4RQmGBRaerskvTKsbwd5ZVJWq3n/a5Y0EiU5jv5j04XmFhuTHpSBJNECCEFNtQ3dWsuFP9cUZ2i89OCwhLSzmCoEcVF+QUXXW6/myOEUDhhUWnS3DL9uqhEBhoT4EHxhEArg/68k88qKg1zbggh5AuLSpN23GYv5oV4TbBeXnqWkSndV2UNW1YIIRQIFpUmrdTldsmynqnl16RjmAtOPjwpIYRQEFhUmjQWCAGgtYVRAA3BXyVCKPLwk6hJSzfoDCxjl6TgYbwstTPjsxoRQpGHRaVJ62g2tjcZygUxSEyNKBpY9oa46LBlhRBCgWBRadIIwPiWKdEcW8C7/AaIlBY4XRlm07DkhDDnhhBCvrCoNHVDkxPuTk10SfJZBy/9sXXFLkq5NkdLo25GpzZGFn+VCKHIwxH1TR0BmNGxjZllvywsOWGzaRnWwDASULsoaVnmGovppU5te8dERTpNhBACwKLSLGgZ8myHVrcmxm4qLt9dUV0tiAwhfWMtN8bH3JOSGB1gXCRCCIUffh41G9dGR10bHQUADknSEEbD4BSSCKEmB4tK82Nk2UingBBC/mFRQShiZP68YD0ku0uB6Fh9OmfpzXDYPIaaNywqCEWAzJ93nF/oqthOxSoquwAYwhpZXYou5QFD6oOE0UY6QYQaCIsKQuEm2o5Yc18WbMcZLorRpgKjI4TKok105Ev5cyXbYXPHvxPGGOk0EWoILCoIhZXsLrGenCXajmmM7YDRq8sZLprhomV3KV/yH8LFmNvPimCSCDUYjphDKKychctF6zHW0MazoqgYbSJhDa7STUL1/vDnhtDlw6KCUPhQ2eEq+w4YDWED3t1i9Wmyu8xV/n04E0MoVLCoIBQ+ou0EFSpYTWzQKAYYjVBzIEw5IRRSWFQQCh8qVlFZAFJL5y5CdFSoBFrLIw8QaoKwqCAUPoQ1EcJRCPYsAwAAEAljBIKjXFHzg0UFofBhje2AM1PRGjyMSjwX1S08KSEUWlhUEAofRpOgjekPYg0EvliRhXLCRWljbwpnYgiFChYVhMLKkPYI0bcQ7XmUyr5rqeSQXcXa6L66hNvDnxtClw+LCkJhxZm7mlo/w2gTJPsJWaxRlxOQJddF0XlWY7nW3H4mEByYjJolPHERCjd98kjCRTvPfyjaT4r8BSAEKAVCGE2cIfkuY5vnGV1apHNEqIGwqCAUAbr4W7Qx/dwVO4SaQ1QopkTP6ltoY2/QWHoD4JNyUDOGRQWhyCCsWZc4XJc4PNKJIBRK2KaCEEIoZLCoIIQQChksKgghhEIGiwpCCKGQwaKCEEIoZCJcVIqKiv785z/3798/Ojo6PT395ptvfu+999xut9/g1atXDx48OCYmJiYmZtCgQStWrAi027pHIoQQCqFIdinevHnz2LFjq6urAYAQUlNTU1hYuH379o8//njXrl3JyclqpCzLEydO9KwNO3fu3Llz5+bNm5ctW8YwTAMiEUIIhVzEPmStVuukSZOqq6sHDx783XffVVZWVlRUrFixIiEhIS8v79FHH/UMnjdvnlIn5syZc+rUqby8vDlz5gDAypUr58+f37BIhBCKDJeDnjoIv22D4z9DWUGkswk1GiHz5s0DgLZt2zocDs/lX3/9tZJYUVGRssRut1ssFgCYOXOmZ+SsWbMAIDo62m631zfS1+TJkwFgwIABoXl7zcfIPb/Buu9H7vkt0olETOWv9xVthooDd4Vwn7Jkd1X+zBdv4EuyhJpfZckVwp03Ba7y7UWboWgziI78SOfSnMjVpdKGf0mzhknT+ktP95L+2kd64Sbpwyly7r5IpxYyEbtS+e233wBg1KhRBoPBc/nQoUNZlgWAQ4cOKUuysrJqamo4jps2bZpn5LRp0zQaTXV1dVZWVn0jEWokVLI6zn1ceXBkzbG/WHNfsua+WH30iapD9zuL1gCt9dlc6IpWkAsLnqabFkJ5IWgNEJ0I5hgQXPTQVvrJ83TrZ0BppFMMgYgVlRYtWowePfrGG2/0Wm6322VZBgCltADAgQMHAGDgwIGxsX94srfSCA8AO3bsqG8kQo1BchXWHPur/dy/Zf4Cw5oZfRqjTQNGK9qP28/8w3ryZSrZI50jCpGSc3T/Zti9np49Wqf46lJ5+Sw57xBJbAEpbcEcCzojGKIgLpW06Az2KvqfxXTPhkZOOhwi1lD/+uuv+12+cOFCSml0dHT//v2VJQUFBQDQvXt33+DMzMwffvghOzu7vpEIhRyVnfZTs92VPzH6NIaLVpcTVs9o4mV3MV+8kbBGc/tZOGVk8+ZyyOveh51rwWmllIJWD5k3kbGvQEKLIBvRLUvh7BGS1Bp0Ru91DAPJbWnhSfhuCek6AKITGzH5xtckJpTMy8vbsGHD2bNnjx49um3bNp1O99lnnymtI/B7qYiLi/PdMD4+HgBKSkrqG6m67rrrRPHSTYlWrVqF5O2gqxN/8Wt31R5Gl+JZUVSMNhlk0VWySRd/hybm+vCnh0KFrn4DflwJhIApBggBp43+kkUripgZa0Cr97+NrYIe+h60ej8VRUEIJLSkpWfpoa3kpnGNl3wYNImi8tNPPz333HPKzyzLLlq06N5771XXKqVCqQpelIVWq7W+kQiFGuVLNlLJxRpiA0UQXapkz+FLN2FRacZKztE9G4FhISbp0hKNjjh1NP8oPbCZXH+v343omSNgq6SmuCCXqERnoKIAZ34DLCqX7/rrr//4449LS0sPHz68bt26iRMnbtq0admyZVqtFgCUJpYgCLn0m6p7pGrGjBnKVitXrjxx4kTLli0b+B6aCZHSQ1XWI1ZbpVs0sExro95d20FDdSE5z8mu80QTsKIAACEMsAah6hcAOeLjjlHD0HPZ4LJTo8Xzo4QazGCroGezAxUVqCkH0U20uuA7J6wGyotClmuENImi0qlTp06dOik/79+//8Ybb1yzZs111103depUAEhNTc3Ly6uoqPDdUFmYnp6u/LPukSr1kmjLli02my0076ep2l9Z8+HpC0et9mpBkIECECPLFvMuoCBfEd1OIkgWKqjkZrgANzd+R4iOyrwsVDNByw9qumQJKPXTKkaByFLArTQ6IEztnbuoDDpDLTFNXpP7utSnT58JEyYAwFdffaUsSU1Nhd+rgpfy8
Download .txt
gitextract_o5hgf_3g/

├── INSTALL.md
├── LICENSE
├── README.md
├── bin/
│   └── iseq
├── docs/
│   ├── ChineseTutorial.md
│   ├── Examples.md
│   └── benchmark/
│       ├── README.md
│       ├── TestFasterqDump/
│       │   ├── testFasterqDump.log
│       │   └── timefasterqDump.sh
│       ├── TestiSeq-2GB/
│       │   ├── TestiSeq-2GB.bash
│       │   ├── timeENA.log
│       │   ├── timeFQ.log
│       │   ├── timeGSAFTP.log
│       │   ├── timeGSAHW.log
│       │   └── timeSRA.log
│       ├── TestiSeq-540MB/
│       │   ├── TestiSeq-540MB.bash
│       │   ├── timeENA.log
│       │   ├── timeFQ.log
│       │   ├── timeGSAFTP.log
│       │   ├── timeGSAHW.log
│       │   └── timeSRA.log
│       ├── benchmark.ipynb
│       └── iSeq-Table S1.xlsx
└── iSeq.yml
Condensed preview — 24 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,324K chars).
[
  {
    "path": "INSTALL.md",
    "chars": 5729,
    "preview": "## Install the latest version of iSeq\r\n\r\n```bash\r\nversion=\"1.9.8\"\r\nwget \"https://github.com/BioOmics/iSeq/releases/downl"
  },
  {
    "path": "LICENSE",
    "chars": 1064,
    "preview": "MIT License\n\nCopyright (c) 2024 BioOmics\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\no"
  },
  {
    "path": "README.md",
    "chars": 32193,
    "preview": "[![Anaconda-Server Badge](https://anaconda.org/bioconda/iseq/badges/version.svg)](https://anaconda.org/bioconda/iseq)\r\n["
  },
  {
    "path": "bin/iseq",
    "chars": 58365,
    "preview": "#!/bin/bash\n# Author: BioOmics (https://github.com/BioOmics)\n# Last modified: 2025-11-20\n# ============================="
  },
  {
    "path": "docs/ChineseTutorial.md",
    "chars": 10139,
    "preview": "## iSeq使用方法 \r\n- 中文纯手打,英文是由ChatGPT翻译的😀\r\n```{bash}\r\n$ iseq --help\r\n\r\nUsage:\r\n  iseq -i accession [options]\r\n\r\nRequired opt"
  },
  {
    "path": "docs/Examples.md",
    "chars": 3814,
    "preview": "# Examples of using iSeq\r\n\r\n## Basic examples\r\n1. Download all Run sequencing data and metadata associated with a Projec"
  },
  {
    "path": "docs/benchmark/README.md",
    "chars": 817,
    "preview": "## Stability\niSeq demonstrated high stability, successfully downloading and passing integrity checks for a large number "
  },
  {
    "path": "docs/benchmark/TestFasterqDump/testFasterqDump.log",
    "chars": 1873,
    "preview": "2\tConvert SRA to FASTQ\t74\n2\tCompress FASTQ\t803\n3\tConvert SRA to FASTQ\t66\n3\tCompress FASTQ\t528\n4\tConvert SRA to FASTQ\t64\n"
  },
  {
    "path": "docs/benchmark/TestFasterqDump/timefasterqDump.sh",
    "chars": 1,
    "preview": "\n"
  },
  {
    "path": "docs/benchmark/TestiSeq-2GB/TestiSeq-2GB.bash",
    "chars": 4591,
    "preview": "#!/bin/bash\n\nif command -v iseq >/dev/null 2>&1; then\n    sleep 0\nelse\n    echo \"iseq is not installed\"\n    echo \"Please"
  },
  {
    "path": "docs/benchmark/TestiSeq-2GB/timeENA.log",
    "chars": 1115,
    "preview": "Wget\t583\nAspera\t215\nAXEL\t59\nWget\t976\nAspera\t87\nAXEL\t73\nWget\t607\nAspera\t208\nAXEL\t69\nWget\t187\nAspera\t312\nAXEL\t54\nWget\t150\n"
  },
  {
    "path": "docs/benchmark/TestiSeq-2GB/timeFQ.log",
    "chars": 1556,
    "preview": "--fastq\t537\n--fastq+gzip\t316\n--gzip\t42\n--fastq\t116\n--fastq+gzip\t211\n--gzip\t149\n--fastq\t293\n--fastq+gzip\t315\n--gzip\t144\n-"
  },
  {
    "path": "docs/benchmark/TestiSeq-2GB/timeGSAFTP.log",
    "chars": 1153,
    "preview": "Wget\t1085\nAXEL\t148\nAspera\t89\nWget\t1244\nAXEL\t134\nAspera\t87\nWget\t956\nAXEL\t137\nAspera\t92\nWget\t1083\nAXEL\t171\nAspera\t87\nWget\t"
  },
  {
    "path": "docs/benchmark/TestiSeq-2GB/timeGSAHW.log",
    "chars": 627,
    "preview": "AXEL\t21\nWget\t10\nAXEL\t20\nWget\t14\nAXEL\t16\nWget\t16\nAXEL\t17\nWget\t10\nAXEL\t13\nWget\t11\nAXEL\t9\nWget\t15\nAXEL\t22\nWget\t15\nAXEL\t21\nW"
  },
  {
    "path": "docs/benchmark/TestiSeq-2GB/timeSRA.log",
    "chars": 664,
    "preview": "Wget\t125\nAXEL\t75\nWget\t261\nAXEL\t79\nWget\t87\nAXEL\t85\nWget\t95\nAXEL\t64\nWget\t120\nAXEL\t86\nWget\t108\nAXEL\t59\nWget\t76\nAXEL\t63\nWget"
  },
  {
    "path": "docs/benchmark/TestiSeq-540MB/TestiSeq-540MB.bash",
    "chars": 4298,
    "preview": "#!/bin/bash\n\nif command -v iseq >/dev/null 2>&1; then\n    sleep 0\nelse\n    echo \"iseq is not installed\"\n    echo \"Please"
  },
  {
    "path": "docs/benchmark/TestiSeq-540MB/timeENA.log",
    "chars": 558,
    "preview": "Wget\t781\nAspera\t23\nAXEL\t65\nWget\t992\nAspera\t440\nAXEL\t103\nWget\t812\nAspera\t26\nAXEL\t95\nWget\t268\nAspera\t30\nAXEL\t130\nWget\t314\n"
  },
  {
    "path": "docs/benchmark/TestiSeq-540MB/timeFQ.log",
    "chars": 773,
    "preview": "--fastq\t291\n--fastq+gzip\t419\n--gzip\t32\n--fastq\t46\n--fastq+gzip\t250\n--gzip\t250\n--fastq\t341\n--fastq+gzip\t323\n--gzip\t35\n--f"
  },
  {
    "path": "docs/benchmark/TestiSeq-540MB/timeGSAFTP.log",
    "chars": 575,
    "preview": "Wget\t1180\nAXEL\t113\nAspera\t76\nWget\t1237\nAXEL\t139\nAspera\t76\nWget\t787\nAXEL\t131\nAspera\t88\nWget\t929\nAXEL\t151\nAspera\t89\nWget\t8"
  },
  {
    "path": "docs/benchmark/TestiSeq-540MB/timeGSAHW.log",
    "chars": 308,
    "preview": "AXEL\t18\nWget\t9\nAXEL\t20\nWget\t8\nAXEL\t19\nWget\t13\nAXEL\t26\nWget\t9\nAXEL\t20\nWget\t8\nAXEL\t23\nWget\t9\nAXEL\t20\nWget\t9\nAXEL\t20\nWget\t1"
  },
  {
    "path": "docs/benchmark/TestiSeq-540MB/timeSRA.log",
    "chars": 327,
    "preview": "Wget\t102\nAXEL\t51\nWget\t117\nAXEL\t68\nWget\t82\nAXEL\t53\nWget\t91\nAXEL\t54\nWget\t100\nAXEL\t45\nWget\t84\nAXEL\t44\nWget\t98\nAXEL\t36\nWget\t"
  },
  {
    "path": "docs/benchmark/benchmark.ipynb",
    "chars": 1177449,
    "preview": "{\n \"cells\": [\n  {\n   \"cell_type\": \"code\",\n   \"execution_count\": 187,\n   \"metadata\": {\n    \"vscode\": {\n     \"languageId\":"
  },
  {
    "path": "iSeq.yml",
    "chars": 127,
    "preview": "channels:\n  - conda-forge\n  - bioconda\ndependencies:\n  - pigz\n  - wget\n  - axel\n  - aspera-cli ==4.14.0\n  - sra-tools >="
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the BioOmics/iSeq GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 24 files (1.2 MB), approximately 818.5k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!