From 42701f57d77c329870ef1a5190358a0c4cb66020 Mon Sep 17 00:00:00 2001 From: Alessandragr <alessandra-ribeiro@live.com> Date: Sun, 9 Feb 2025 12:09:18 -0300 Subject: [PATCH] Correcting fonctions --- .gitignore | 2 + README.md | 1 + src/Model/GeneticMaterial.cpp | 549 +++++++++++++++++++++------------- 3 files changed, 348 insertions(+), 204 deletions(-) diff --git a/.gitignore b/.gitignore index 9f3bdd9..0d514de 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ Docs/ .vscode/ *.json + +vcpkg/ \ No newline at end of file diff --git a/README.md b/README.md index 2bed8a1..6e75443 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ # bioAPI +## Description Development of an API using C++ for advanced biological data analysis using FASTQ and FASTA files. diff --git a/src/Model/GeneticMaterial.cpp b/src/Model/GeneticMaterial.cpp index 9a707eb..151195d 100644 --- a/src/Model/GeneticMaterial.cpp +++ b/src/Model/GeneticMaterial.cpp @@ -1,3 +1,4 @@ +#include <zlib.h> #include <iostream> #include <fstream> #include <string> @@ -6,11 +7,27 @@ #include <stdexcept> #include <optional> #include <zlib.h> -#include <tar.h> #include <archive.h> #include <archive_entry.h> #include <vector> #include <unzip.h> +#include <stdio.h> +#include <cctype> +#include <variant> + + +bool startsWith(const std::string& str, const std::string& prefix) { + if (prefix.size() > str.size()) return false; + return str.compare(0, prefix.size(), prefix) == 0; +} + + +bool endsWith(const std::string& str, const std::string& suffix) { + if (suffix.size() > str.size()) return false; + return std::equal(suffix.rbegin(), suffix.rend(), str.rbegin()); +} + + class GeneticMaterial { @@ -19,110 +36,22 @@ class GeneticMaterial { std::optional<std::string> fileType; // Pode ser "FASTA", "FASTQ" ou std::nullopt std::optional<std::string> content; // Conteúdo do arquivo, ou std::nullopt se não carregado - fileData.content = (decompressedContent.str().empty()) ? std::nullopt : std::make_optional(decompressedContent.str()); + - }; + }; protected: std::string filePath; std::string fileContent; std::string fileExtension; + FileContent fileData; public: GeneticMaterial(const std::string& path) : filePath(path) {} + - - std::pair<std::vector<FileContent>, std::vector<FileContent>> verifyAndLoadFile(const std::string& filePath) { - std::pair<std::vector<FileContent>, std::vector<FileContent>> fileData; - - size_t position = filePath.find_last_of('.'); - if(position==std::string::npos) { - throw std::runtime_error("Arquivo sem extensão, insira um arquivo com uma extensão válida: FASTA, FASTQ, ZIP or TAR."); - } - - std::string fileExtension = filePath.substr(position + 1); - std::transform(fileExtension.begin(), fileExtension.end(), fileExtension.begin(), ::tolower); - try { - if(fileExtension=="gz") { - fileData = descompressGzipFile(filePath); - } else if(fileExtension=="tar") { - fileData = descompressTarFile(filePath); - } else if(fileExtension=="zip") { - fileData = decompressZipFile(filePath); - } else if (fileExtension=="fasta" || fileExtension=="fastq") { - fileData = loadFileContent(filePath); - } else { - throw std::runtime_error("Extensão não suportada: " + fileExtension + - "\n" + "Please insert files of type: FASTA, FASTQ, ZIP or TAR"); - } - } catch (const std::exception& e) { - throw std::runtime_error("Erro ao processar o arquivo: " + std::string(e.what())); - } - - return fileData; - } - - - - - void loadFileContent(const std::variant<std::string, std::vector<std::string>>& input, - std::vector<FileContent>& fastaFiles, - std::vector<FileContent>& fastqFiles) { - - std::vector<std::string> filePaths; - - if (std::holds_alternative<std::string>(input)) { - filePaths.push_back(std::get<std::string>(input)); // Adiciona o único caminho à lista - } else { - filePaths = std::get<std::vector<std::string>>(input); // Converte diretamente para a lista - } - - // Processa cada arquivo na lista - for (const auto& filePath : filePaths) { - std::ifstream file(filePath, std::ios::binary); - - if(!file.is_open()) { - throw std::runtime_error("Não foi possÃvel abrir o arquivo: " + filePath); - } - - // Processar o arquivo em blocos - constexpr size_t bufferSize = 4096; // 4 KB - char buffer[bufferSize]; - std::stringstream fileContent; - - while (file.read(buffer, bufferSize)) { - fileContent.append(buffer, file.gcount()); - } - - // Verifica se há bytes restantes no final do arquivo - if (file.gcount() > 0) { - fileContent.append(buffer, file.gcount()); - } - - file.close(); - - - FileContent fileData; - fileData.fileName = filePath; - fileData.content = fileContent.str(); - - if (filePath.ends_with(".fasta")) { - fileData.fileType = "FASTA"; - fastaFiles.push_back(fileData); - } else if (filePath.ends_with(".fastq")) { - fileData.fileType = "FASTQ"; - fastqFiles.push_back(fileData); - } else { - throw std::runtime_error("Tipo de arquivo não suportado: " + filePath); - } - } - } - - - - - std::vector<FileContent> decompressGzipFile(const std::string& filePath) { + std::pair<std::vector<FileContent>, std::vector<FileContent>> decompressGzipFile(const std::string& filePath) { gzFile gzFile = gzopen(filePath.c_str(), "rb"); if (!gzFile) { throw std::runtime_error("Não foi possÃvel abrir o arquivo GZIP: " + filePath); @@ -151,188 +80,400 @@ class GeneticMaterial { } // Processa o conteúdo para dividir em FASTA/FASTQ - std::vector<FileContent> fileContents; - std::string content = decompressedContent.str(); + std::vector<FileContent> fastaFiles; + std::vector<FileContent> fastqFiles; - std::istringstream contentStream(content); + std::istringstream contentStream(decompressedContent.str()); std::string line; FileContent currentFile; while (std::getline(contentStream, line)) { - if (line.starts_with(">")) { // InÃcio de um arquivo FASTA - if (!currentFile.fileName.empty()) { - fileContents.push_back(currentFile); - currentFile = FileContent(); // Reinicia o arquivo atual + if (line.empty()) continue; + if (startsWith(line, ">")) { // InÃcio de um arquivo FASTA + if (!currentFile.content.has_value()) { + if (currentFile.fileType == "FASTA") { + fastaFiles.push_back(currentFile); + } else if (currentFile.fileType == "FASTQ") { + fastqFiles.push_back(currentFile); + } } + currentFile = FileContent(); currentFile.fileType = "FASTA"; - currentFile.content += line + "\n"; - } else if (line.starts_with("@")) { // InÃcio de um arquivo FASTQ - if (!currentFile.fileName.empty()) { - fileContents.push_back(currentFile); - currentFile = FileContent(); // Reinicia o arquivo atual + *currentFile.content += line + "\n"; // Acessa o valor do optional + } else if (startsWith(line, "@")) { // InÃcio de um arquivo FASTQ + if (currentFile.fileType == "FASTA") { + fastaFiles.push_back(currentFile); + } else if (currentFile.fileType == "FASTQ") { + fastqFiles.push_back(currentFile); } + currentFile = FileContent(); currentFile.fileType = "FASTQ"; - currentFile.content += line + "\n"; + *currentFile.content += line + "\n"; // Acessa o valor do optional } else { - currentFile.content += line + "\n"; + *currentFile.content += line + "\n"; // Acessa o valor do optional } } // Adiciona o último arquivo processado - if (!currentFile.content.empty()) { - fileContents.push_back(currentFile); + if (!currentFile.content.has_value()) { + if (currentFile.fileType == "FASTA") { + fastaFiles.push_back(currentFile); + } else if (currentFile.fileType == "FASTQ") { + fastqFiles.push_back(currentFile); + } } - return fileContents; + return {fastaFiles, fastqFiles}; } + std::pair<std::vector<FileContent>, std::vector<FileContent>> descompressTarFile(const std::string& filePath) { + struct archive* tarFile = archive_read_new(); + if (!tarFile) { + throw std::runtime_error("Falha ao alocar memória para o manipulador de TAR."); + } - std::pair<std::vector<FileContent>, std::vector<FileContent>> descompressTarFile(const std::string& filePath) { - struct archive* tarFile = archive_read_new(); - struct archive_entry* entry; - std::vector<FileContent> fastaFiles; - std::vector<FileContent> fastqFiles; + struct archive_entry* entry; + std::vector<FileContent> fastaFiles; + std::vector<FileContent> fastqFiles; - // Configurando o libarchive para lidar com arquivos TAR - archive_read_support_filter_all(tarFile); - archive_read_support_format_all(tarFile); + // Configurando o libarchive para lidar com arquivos TAR + archive_read_support_filter_all(tarFile); + archive_read_support_format_all(tarFile); - if (archive_read_open_filename(tarFile, filePath.c_str(), 10240) != ARCHIVE_OK) { - throw std::runtime_error("Não foi possÃvel abrir o arquivo TAR: " + filePath); + if (archive_read_open_filename(tarFile, filePath.c_str(), 10240) != ARCHIVE_OK) { + archive_read_free(tarFile); // Libera a memória antes de lançar a exceção e evita o vazamento de dados + throw std::runtime_error("Não foi possÃvel abrir o arquivo TAR: " + filePath); + } + + while (archive_read_next_header(tarFile, &entry) == ARCHIVE_OK) { + std::string currentFileName = archive_entry_pathname(entry); + + // Converte o nome do arquivo para lowercase para evitar problemas de case + std::transform(currentFileName.begin(), currentFileName.end(), currentFileName.begin(), ::tolower); + + // Filtra apenas arquivos .fasta ou .fastq + if (endsWith(currentFileName, ".fasta") || endsWith(currentFileName, ".fastq")) { + std::cout << "Arquivo encontrado: " << currentFileName << std::endl; + + std::string fileType = (endsWith(currentFileName, ".fasta")) ? "FASTA" : "FASTQ"; + + // Lê o conteúdo do arquivo + std::ostringstream fileContent; + const void* buffer; + size_t size; + int64_t offset; + + while (true) { + int readBytes = archive_read_data_block(tarFile, &buffer, &size, &offset); + if (readBytes == ARCHIVE_EOF) break; + if (readBytes < ARCHIVE_OK) { + archive_read_free(tarFile); + throw std::runtime_error("Erro ao ler o arquivo: " + currentFileName); + } + + if (buffer) { // Verifica se buffer não é nullptr (caso extremo) + fileContent.write(static_cast<const char*>(buffer), size); // Adiciona o conteúdo ao stream + } + } + + // Cria o objeto FileContent + FileContent fileData; + fileData.fileName = currentFileName; + fileData.fileType = std::make_optional(fileType); + fileData.content = fileContent.str(); + + if (fileType == "FASTA") { + fastaFiles.push_back(std::move(fileData)); // Adiciona à lista de FASTA + } else { + fastqFiles.push_back(std::move(fileData)); // Adiciona à lista de FASTQ + } + + } else { + std::cout << "Arquivo ignorado: " << currentFileName << std::endl; + } + // Avança para o próximo arquivo no TAR + archive_read_data_skip(tarFile); + } + + archive_read_free(tarFile); // Libera o recurso do arquivo TAR + return {std::move(fastaFiles), std::move(fastqFiles)}; // Retorna as listas separadas de FASTA e FASTQ } - while (archive_read_next_header(tarFile, &entry) == ARCHIVE_OK) { - std::string currentFileName = archive_entry_pathname(entry); - // Converte o nome do arquivo para lowercase para evitar problemas de case + + + std::pair<std::vector<FileContent>, std::vector<FileContent>> decompressZipFile(const std::string& filePath) { + unzFile zipFile = unzOpen(filePath.c_str()); + + if (!zipFile) { + throw std::runtime_error("Não foi possÃvel abrir o arquivo ZIP: " + filePath); + } + + if (unzGoToFirstFile(zipFile) != UNZ_OK) { + unzClose(zipFile); + throw std::runtime_error("Erro ao acessar o primeiro arquivo no ZIP: " + filePath); + } + + // Vetores para armazenar os arquivos FASTA e FASTQ + std::vector<FileContent> fastaFiles; + std::vector<FileContent> fastqFiles; + + do { + // Obtém o nome do arquivo atual no ZIP + char fileName[256]; + unz_file_info fileInfo; + + if (unzGetCurrentFileInfo(zipFile, &fileInfo, fileName, sizeof(fileName), nullptr, 0, nullptr, 0) != UNZ_OK) { + unzClose(zipFile); + throw std::runtime_error("Erro ao obter informações do arquivo no ZIP."); + } + + std::string currentFileName(fileName); std::transform(currentFileName.begin(), currentFileName.end(), currentFileName.begin(), ::tolower); // Filtra apenas arquivos .fasta ou .fastq - if (currentFileName.ends_with(".fasta") || currentFileName.ends_with(".fastq")) { + if (endsWith(currentFileName, ".fasta") || endsWith(currentFileName, ".fastq")) { std::cout << "Arquivo encontrado: " << currentFileName << std::endl; - - std::string fileType = (currentFileName.ends_with(".fasta")) ? "FASTA" : "FASTQ"; + // Abre o arquivo atual dentro do ZIP + if (unzOpenCurrentFile(zipFile) != UNZ_OK) { + unzClose(zipFile); + throw std::runtime_error("Erro ao abrir arquivo dentro do ZIP: " + currentFileName); + } // Lê o conteúdo do arquivo - std::stringstream fileContent; - const void* buffer; - size_t size; - int64_t offset; - - while (true) { - int readBytes = archive_read_data_block(tarFile, &buffer, &size, &offset); - if (readBytes == ARCHIVE_EOF) break; - if (readBytes < ARCHIVE_OK) { - throw std::runtime_error("Erro ao ler o arquivo: " + currentFileName); - } + std::string fileContent; + char buffer[4096]; + int bytesRead; - // Adiciona o conteúdo ao stream - fileContent.write(static_cast<const char*>(buffer), size); + while ((bytesRead = unzReadCurrentFile(zipFile, buffer, sizeof(buffer))) > 0) { + fileContent.append(buffer, bytesRead); } - // Cria o objeto FileContent + if (bytesRead < 0) { + unzCloseCurrentFile(zipFile); + unzClose(zipFile); + throw std::runtime_error("Erro ao ler o arquivo dentro do ZIP: " + currentFileName); + } + + unzCloseCurrentFile(zipFile); + + // Cria o objeto FileContent FileContent fileData; fileData.fileName = currentFileName; - ffileData.fileType = std::make_optional(fileType); - fileData.content = fileContent.str(); + fileData.fileType = std::make_optional(endsWith(currentFileName, ".fasta") ? "FASTA" : "FASTQ"); + fileData.content = std::move(fileContent); + + // Armazena o conteúdo no vetor apropriado + if (endsWith(currentFileName, ".fasta")) { + fastaFiles.push_back(std::move(fileData)); + } else if (endsWith(currentFileName, ".fastq")) { + fastqFiles.push_back(std::move(fileData)); + } + } else { + std::cout << "Arquivo ignorado: " << currentFileName << std::endl; + } + } while (unzGoToNextFile(zipFile) == UNZ_OK); + unzClose(zipFile); + return {std::move(fastaFiles), std::move(fastqFiles)}; + } - if (fileType == "FASTA") { - fastaFiles.push_back(fileData); // Adiciona à lista de FASTA - } else { - fastqFiles.push_back(fileData); // Adiciona à lista de FASTQ - } + + + std::pair<std::vector<FileContent>, std::vector<FileContent>> verifyAndLoadFile(const std::string& filePath) { + std::pair<std::vector<FileContent>, std::vector<FileContent>> fileData; + + size_t position = filePath.find_last_of('.'); + if (position == std::string::npos) { + throw std::runtime_error("Arquivo sem extensão, insira um arquivo com uma extensão válida: FASTA, FASTQ, ZIP ou TAR."); + } + + std::string fileExtension = filePath.substr(position + 1); + std::transform(fileExtension.begin(), fileExtension.end(), fileExtension.begin(), ::tolower); + + try { + if (fileExtension == "gz") { + fileData = decompressGzipFile(filePath); + } else if (fileExtension == "tar") { + fileData = descompressTarFile(filePath); + } else if (fileExtension == "zip") { + fileData = decompressZipFile(filePath); + } else if (fileExtension == "fasta" || fileExtension == "fastq") { + // Chama a função loadFileContent e verifica se o retorno é válido + auto result = loadFileContent(filePath); + if (result) { + const auto& [fastaFiles, fastqFiles] = *result; + // Verifica se as listas não são nullopt e atribui à s listas de fileData + if (fastaFiles) { + fileData.first = *fastaFiles; + } + if (fastqFiles) { + fileData.second = *fastqFiles; + } } else { - std::cout << "Arquivo ignorado: " << currentFileName << std::endl; + throw std::runtime_error("Falha ao carregar conteúdo do arquivo: " + filePath); + } + } else { + throw std::runtime_error("Extensão não suportada: " + fileExtension + + "\nPor favor, insira arquivos do tipo: FASTA, FASTQ, ZIP ou TAR."); } - // Avança para o próximo arquivo no TAR - archive_read_data_skip(tarFile); + } catch (const std::exception& e) { + throw std::runtime_error("Erro ao processar o arquivo: " + std::string(e.what())); } - archive_read_free(tarFile); // Libera o recurso do arquivo TAR - return {fastaFiles, fastqFiles}; // Retorna as listas separadas de FASTA e FASTQ + return fileData; } - std::pair<std::vector<FileContent>, std::vector<FileContent>> decompressZipFile(const std::string& filePath) { - unzFile zipFile = unzOpen(filePath.c_str()); - if (!zipFile) { - throw std::runtime_error("Não foi possÃvel abrir o arquivo ZIP: " + filePath); + std::optional<std::pair<std::optional<std::vector<FileContent>>, std::optional<std::vector<FileContent>>>> loadFileContent(const std::variant<std::string, + std::vector<std::string>>& input) { + + std::vector<std::string> filePaths; + + // Verifica se o input é uma string ou um vetor de strings + if (std::holds_alternative<std::string>(input)) { + filePaths.push_back(std::get<std::string>(input)); // Adiciona o único caminho à lista + } else { + filePaths = std::get<std::vector<std::string>>(input); // Converte diretamente para a lista + } + + // Vetores de arquivos FASTA e FASTQ + std::optional<std::vector<FileContent>> fastaFiles; + std::optional<std::vector<FileContent>> fastqFiles; + + // Processa cada arquivo na lista + for (const auto& filePath : filePaths) { + std::ifstream file(filePath, std::ios::binary); + + if (!file.is_open()) { + throw std::runtime_error("Não foi possÃvel abrir o arquivo: " + filePath); } + // Processar o arquivo em blocos + constexpr size_t bufferSize = 4096; // 4 KB + char buffer[bufferSize]; + std::stringstream fileContent; - if (unzGoToFirstFile(zipFile) != UNZ_OK) { - unzClose(zipFile); - throw std::runtime_error("Erro ao acessar o primeiro arquivo no ZIP: " + filePath); + while (file.read(buffer, bufferSize)) { + fileContent.write(buffer, file.gcount()); // Usa write em vez de append + } + + // Verifica se há bytes restantes no final do arquivo + if (file.gcount() > 0) { + fileContent.write(buffer, file.gcount()); // Usa write em vez de append } - std::vector<std::string> fastaFiles; - std::vector<std::string> fastqFiles; + file.close(); + + // Cria o objeto FileContent + FileContent fileData; + fileData.fileName = filePath; + fileData.content = fileContent.str(); - do { - // Obtém o nome do arquivo atual no ZIP - char fileName[256]; - unz_file_info fileInfo; - - if (unzGetCurrentFileInfo(zipFile, &fileInfo, fileName, sizeof(fileName), nullptr, 0, nullptr, 0) != UNZ_OK) { - throw std::runtime_error("Erro ao obter informações do arquivo no ZIP."); + // Verifica o tipo de arquivo e adiciona ao vetor apropriado + if (endsWith(filePath, ".fasta")) { + if (!fastaFiles) { + fastaFiles = std::vector<FileContent>(); // Inicializa o vetor se necessário + } + fileData.fileType = "FASTA"; + fastaFiles->push_back(fileData); + } else if (endsWith(filePath, ".fastq")) { + if (!fastqFiles) { + fastqFiles = std::vector<FileContent>(); // Inicializa o vetor se necessário } + fileData.fileType = "FASTQ"; + fastqFiles->push_back(fileData); + } else { + throw std::runtime_error("Tipo de arquivo não suportado: " + filePath); + } + } + // Retorna a lista de arquivos FASTA e FASTQ como opcional + return std::make_optional(std::make_pair(std::move(fastaFiles), std::move(fastqFiles))); + } + - std::string currentFileName(fileName); - std::transform(currentFileName.begin(), currentFileName.end(), currentFileName.begin(), ::tolower); - if (currentFileName.ends_with(".fasta") || currentFileName.ends_with(".fastq")) { - std::cout << "Arquivo encontrado: " << currentFileName << std::endl; - // Abre o arquivo atual dentro do ZIP - if (unzOpenCurrentFile(zipFile) != UNZ_OK) { - throw std::runtime_error("Erro ao abrir arquivo dentro do ZIP: " + currentFileName); - } - // Lê o conteúdo do arquivo - std::string fileContent; - char buffer[4096]; - int bytesRead; - while ((bytesRead = unzReadCurrentFile(zipFile, buffer, sizeof(buffer))) > 0) { - fileContent.append(buffer, bytesRead); - } + bool verifySequence(const std::string& fastaContent) { + bool erroEncontrado = false; + std::string line; + bool isHeader = true; - if (bytesRead < 0) { - unzCloseCurrentFile(zipFile); - throw std::runtime_error("Erro ao ler o arquivo dentro do ZIP: " + currentFileName); - } + // Percorre cada caractere da string + for (size_t i = 0; i < fastaContent.size(); ++i) { + char c = fastaContent[i]; - unzCloseCurrentFile(zipFile); - - // Armazena o conteúdo no vetor apropriado - FileContent fileData = {currentFileName, fileContent}; - if (currentFileName.ends_with(".fasta")) { - fastaFiles.push_back(fileData); - } else if (currentFileName.ends_with(".fastq")) { - fastqFiles.push_back(fileData); + // Verifica se é uma nova linha (fim de sequência ou cabeçalho) + if (c == '\n' || c == '\r') { + // Se a linha estava com cabeçalho (iniciada por ">", ignorar) + if (line.empty() || line[0] == '>') { + // Linha de cabeçalho encontrada, ignora e reinicia + line.clear(); + isHeader = true; + } else { + // Verifica os caracteres da sequência + for (char seqChar : line) { + if (!isalpha(seqChar) && seqChar != 'N' && seqChar != 'n') { + std::cerr << "Caractere inválido encontrado na sequência: " << seqChar << std::endl; + erroEncontrado = true; + } } + line.clear(); + isHeader = false; + } + } else { + // Acumula os caracteres da sequência ou cabeçalho + if (isHeader || c == '>') { + line.push_back(c); } else { - std::cout << "Arquivo ignorado: " << currentFileName << std::endl; + line.push_back(c); // Acumula caracteres da sequência } - } while (unzGoToNextFile(zipFile) != UNZ_END_OF_LIST_OF_FILE); - - unzClose(zipFile); - return {fastaFiles, fastqFiles}; } + } + + return !erroEncontrado; // Retorna true se não houver caracteres inválidos + } + + + + + // Lê a sequência e me retorna quantos alinhamentos é possÃvel fazer com ela + // Função para calcular o coeficiente binomial: C(n, k) = n! / (k! * (n-k)!) + uint64_t binomialCoefficient(int n, int k) { + if (k > n) return 0; + if (k == 0 || k == n) return 1; + + uint64_t result = 1; + for (int i = 1; i <= k; ++i) { + result = result * (n - i + 1) / i; + } + return result; + } + + // Função para calcular o número de alinhamentos globais possÃveis + uint64_t calculateGlobalAlignments(int length1, int length2) { + int totalLength = length1 + length2; + return binomialCoefficient(totalLength, length1); + } + + // Função para calcular o número de alinhamentos locais possÃveis + uint64_t calculateLocalAlignments(int length1, int length2) { + return static_cast<uint64_t>((length1 + 1) * (length2 + 1) * (length1 + length2) / 2); + } - virtual ~GeneticMaterial() {} + virtual ~GeneticMaterial() {} }; - // Verificações para saber se os arquivos fasta e fastq são válidos - // Falta acerta essa questão dos arquivos passados como fasta ou fastq. Quantos arquivos podem ser passado de uma só vez? + // Verificações para saber se os arquivos fasta e fastq são válidos. -- GitLab