Skip to content
Commits on Source (3)
......@@ -5,8 +5,6 @@ option(BUILD_STATIC "BUILD_STATIC" OFF)
option(EXTRA "EXTRA" OFF)
option(STATIC_LIBGCC "STATIC_LIBGCC" OFF)
option(STATIC_LIBSTDC++ "STATIC_LIBSTDC++" OFF)
option(SSSE3 "SSSE3" OFF)
option(POPCNT "POPCNT" OFF)
IF(STATIC_LIBSTDC++)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static-libstdc++")
......@@ -29,19 +27,8 @@ else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
endif()
if(SSSE3)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mssse3")
if(POPCNT)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mpopcnt")
endif()
elseif(CMAKE_BUILD_MARCH)
if(CMAKE_BUILD_MARCH)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=${CMAKE_BUILD_MARCH}")
else()
include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCHNATIVE)
if(COMPILER_SUPPORTS_MARCHNATIVE)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
endif()
endif()
find_package(ZLIB REQUIRED)
......@@ -52,7 +39,7 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
endif()
if(WIN32)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
add_definitions(-D_CRT_SECURE_NO_WARNINGS -D_ITERATOR_DEBUG_LEVEL=0)
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wno-uninitialized -Wno-ignored-attributes -Wno-unused-variable")
endif()
......@@ -61,7 +48,25 @@ include_directories(
"${CMAKE_SOURCE_DIR}/src"
"${ZLIB_INCLUDE_DIR}")
add_executable(diamond src/run/main.cpp
set(DISPATCH_OBJECTS
"src/dp/swipe/banded_3frame_swipe.cpp"
"src/dp/swipe/swipe.cpp"
"src/dp/swipe/banded_swipe.cpp"
"src/search/collision.cpp"
"src/search/stage1.cpp"
"src/search/stage2.cpp"
"src/tools/benchmark.cpp"
"src/dp/swipe/swipe_wrapper.cpp"
)
add_library(arch_generic OBJECT ${DISPATCH_OBJECTS})
target_compile_options(arch_generic PUBLIC -DDISPATCH_ARCH=ARCH_GENERIC)
add_library(arch_sse4_1 OBJECT ${DISPATCH_OBJECTS})
target_compile_options(arch_sse4_1 PUBLIC -DDISPATCH_ARCH=ARCH_SSE4_1 -mssse3 -mpopcnt -msse4.1)
add_executable(diamond $<TARGET_OBJECTS:arch_generic>
$<TARGET_OBJECTS:arch_sse4_1>
src/run/main.cpp
src/basic/config.cpp
src/basic/score_matrix.cpp
src/blast/blast_filter.cpp
......@@ -78,7 +83,6 @@ add_executable(diamond src/run/main.cpp
src/data/reference.cpp
src/data/seed_histogram.cpp
src/output/daa_record.cpp
src/search/search.cpp
src/util/command_line_parser.cpp
src/util/seq_file_format.cpp
src/util/util.cpp
......@@ -88,7 +92,6 @@ add_executable(diamond src/run/main.cpp
src/dp/ungapped_align.cpp
src/run/tools.cpp
src/dp/greedy_align.cpp
src/search/stage2.cpp
src/output/output_format.cpp
src/output/join_blocks.cpp
src/data/frequent_seeds.cpp
......@@ -99,7 +102,6 @@ add_executable(diamond src/run/main.cpp
src/output/blast_pairwise_format.cpp
src/dp/comp_based_stats.cpp
src/run/double_indexed.cpp
src/search/collision.cpp
src/output/sam_format.cpp
src/align/align.cpp
src/search/setup.cpp
......@@ -107,9 +109,7 @@ add_executable(diamond src/run/main.cpp
src/data/taxonomy.cpp
src/lib/tantan/tantan.cc
src/basic/masking.cpp
src/dp/swipe/swipe.cpp
src/dp/banded_sw.cpp
src/data/sorted_list.cpp
src/data/seed_set.cpp
src/util/simd.cpp
src/output/taxon_format.cpp
......@@ -118,8 +118,6 @@ add_executable(diamond src/run/main.cpp
src/output/target_culling.cpp
src/align/greedy_pipeline.cpp
src/align/swipe_pipeline.cpp
src/dp/swipe/banded_3frame_swipe.cpp
src/dp/swipe/banded_swipe.cpp
src/align/banded_swipe_pipeline.cpp
src/data/ref_dictionary.cpp
src/util/io/compressed_stream.cpp
......@@ -137,7 +135,6 @@ add_executable(diamond src/run/main.cpp
src/data/taxonomy_nodes.cpp
src/util/algo/MurmurHash3.cpp
src/search/stage0.cpp
src/util/memory/memory_pool.cpp
src/data/seed_array.cpp
src/output/paf_format.cpp
src/util/system/system.cpp
......@@ -150,6 +147,7 @@ add_executable(diamond src/run/main.cpp
src/util/system/getRSS.cpp
src/util/math/sparse_matrix.cpp
src/lib/tantan/LambdaCalculator.cc
src/data/taxonomy_filter.cpp
)
if(EXTRA)
......
......@@ -18,7 +18,6 @@ Keep posted about new developments by following me on
[![Build Status](https://travis-ci.org/bbuchfink/diamond.svg?branch=master)](https://travis-ci.org/bbuchfink/diamond)
[![image](https://anaconda.org/bioconda/diamond/badges/version.svg)](https://anaconda.org/bioconda/diamond)
![image](https://anaconda.org/bioconda/diamond/badges/platforms.svg)
[![image](https://anaconda.org/bioconda/diamond/badges/downloads.svg)](https://anaconda.org/bioconda/diamond)
Quick start guide
......@@ -32,7 +31,7 @@ quick example for setting up and using the program on Linux.
Installing the software on your system may be done by downloading it in
binary format for immediate use:
wget http://github.com/bbuchfink/diamond/releases/download/v0.9.26/diamond-linux64.tar.gz
wget http://github.com/bbuchfink/diamond/releases/download/v0.9.28/diamond-linux64.tar.gz
tar xzf diamond-linux64.tar.gz
The extracted `diamond` binary file should be moved to a directory
......
......@@ -82,4 +82,5 @@ g++ -std=gnu++11 -DNDEBUG -O3 -Wno-deprecated-declarations $1 $2 $3 \
src/util/system/getRSS.cpp \
src/util/math/sparse_matrix.cpp \
src/lib/tantan/LambdaCalculator.cc \
src/data/taxonomy_filter.cpp \
-lz -lpthread -o diamond
diamond-aligner (0.9.28+dfsg-1) unstable; urgency=medium
* Team upload.
* New upstream version
* One patch against upstream could go (-mnative no longer set)
-- Steffen Moeller <moeller@debian.org> Fri, 08 Nov 2019 19:28:00 +0100
diamond-aligner (0.9.26+dfsg-1) unstable; urgency=medium
* Team upload.
......
......@@ -6,7 +6,7 @@ Priority: optional
Build-Depends: debhelper-compat (= 12),
cmake,
zlib1g-dev
Standards-Version: 4.4.0
Standards-Version: 4.4.1
Vcs-Browser: https://salsa.debian.org/med-team/diamond-aligner
Vcs-Git: https://salsa.debian.org/med-team/diamond-aligner.git
Homepage: https://github.com/bbuchfink/diamond
......
Description: Do not use march=native flag
Bug-Debian: https://bugs.debian.org/906615
Author: Andreas Tille <tille@debian.org>
Last-Update: Sun, 19 Aug 2018 06:38:58 +0200
Index: diamond-aligner/CMakeLists.txt
===================================================================
--- diamond-aligner.orig/CMakeLists.txt
+++ diamond-aligner/CMakeLists.txt
@@ -38,10 +38,10 @@ elseif(CMAKE_BUILD_MARCH)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=${CMAKE_BUILD_MARCH}")
else()
include(CheckCXXCompilerFlag)
- CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCHNATIVE)
- if(COMPILER_SUPPORTS_MARCHNATIVE)
- set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
- endif()
+ #CHECK_CXX_COMPILER_FLAG("-march=native" COMPILER_SUPPORTS_MARCHNATIVE)
+ #if(COMPILER_SUPPORTS_MARCHNATIVE)
+ # set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native")
+ #endif()
endif()
find_package(ZLIB REQUIRED)
avoid_unwanted_optimisation.patch
no_march_native.patch
82feea2aee5c82e283704b9317cb5e8abc625f90.patch
[0.9.28]
- Fixed a bug that could cause alignment score overflows for scores > 65535 in frameshift alignment mode.
- Fixed a clang compiler error.
[0.9.27]
- Improved performance of the seed matching stage.
- Seed frequency counts are computed based on hit seeds.
- Added option `--taxon-exclude` to exclude list of taxon ids from search.
- Compiling from source will no longer perform a native build. Instead, a portable binary that contains code paths
for multiple architectures will be produced, with dispatch logic that is invoked at runtime.
[0.9.26]
- Fixed a bug that could cause undefined behaviour when using a database file of format version < 2.
- Fixed a compiler error when compiled as generic C++.
......
......@@ -91,7 +91,7 @@ void align_worker(size_t thread_id, const Parameters *params, const Metadata *me
QueryMapper *mapper;
if (config.ext == Config::swipe)
mapper = new ExtensionPipeline::Swipe::Pipeline(*params, hits.query, hits.begin, hits.end);
else if (config.frame_shift != 0)
else if (config.frame_shift != 0 || config.ext == Config::banded_swipe)
mapper = new ExtensionPipeline::BandedSwipe::Pipeline(*params, hits.query, hits.begin, hits.end, dp_stat, hits.target_parallel);
else
mapper = new ExtensionPipeline::Greedy::Pipeline(*params, hits.query, hits.begin, hits.end);
......@@ -142,7 +142,6 @@ void align_queries(Trace_pt_buffer &trace_pts, Consumer* output_file, const Para
threads.emplace_back(heartbeat_worker, query_range.second);
size_t n_threads = config.load_balancing == Config::query_parallel ? (config.threads_align == 0 ? config.threads_ : config.threads_align) : 1;
for (size_t i = 0; i < n_threads; ++i)
//threads.push_back(launch_thread(static_cast<void(*)(size_t)>(&align_worker), i));
threads.emplace_back(align_worker, i, &params, &metadata);
for (auto &t : threads)
t.join();
......
/****
DIAMOND protein aligner
Copyright (C) 2013-2017 Benjamin Buchfink <buchfink@gmail.com>
Copyright (C) 2013-2019 Benjamin Buchfink <buchfink@gmail.com>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
......@@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "align.h"
#include "../dp/dp.h"
#include "../util/interval_partition.h"
#include "../util/simd.h"
using namespace std;
......@@ -46,7 +47,7 @@ struct Target : public ::Target
return TranslatedPosition::absolute_interval(TranslatedPosition(i0, f), TranslatedPosition(i1, f), query_dna_len);
}
void add_strand(QueryMapper &mapper, vector<DpTarget> &v, vector<Seed_hit>::iterator begin, vector<Seed_hit>::iterator end)
void add_strand(QueryMapper &mapper, vector<DpTarget> &v, vector<Seed_hit>::iterator begin, vector<Seed_hit>::iterator end, int target_idx)
{
if (end == begin) return;
const int band = config.padding, d_min = -int(subject.length() - 1), d_max = int(mapper.query_seq(0).length() - 1);
......@@ -58,15 +59,15 @@ struct Target : public ::Target
d1 = std::min(i->diagonal() + band, d_max);
}
else {
v.emplace_back(subject, d0, d1, &hsps, subject_id);
v.emplace_back(subject, d0, d1, target_idx);
d0 = std::max(i->diagonal() - band, d_min);
d1 = std::min(i->diagonal() + band, d_max);
}
}
v.emplace_back(subject, d0, d1, &hsps, subject_id);
v.emplace_back(subject, d0, d1, target_idx);
}
void add(QueryMapper &mapper, vector<DpTarget> &vf, vector<DpTarget> &vr)
void add(QueryMapper &mapper, vector<DpTarget> &vf, vector<DpTarget> &vr, int target_idx)
{
vector<Seed_hit>::iterator hits = mapper.seed_hits.begin() + begin, hits_end = mapper.seed_hits.begin() + end;
Strand strand = top_hit.strand();
......@@ -77,9 +78,9 @@ struct Target : public ::Target
const auto it = find_if(hits, hits_end, [](const Seed_hit &x) { return x.strand() == REVERSE; });
if(strand == FORWARD || mapper.target_parallel)
add_strand(mapper, vf, hits, it);
add_strand(mapper, vf, hits, it, target_idx);
if (strand == REVERSE || mapper.target_parallel)
add_strand(mapper, vr, it, hits_end);
add_strand(mapper, vr, it, hits_end, target_idx);
//const int d = hits[0].diagonal();
//const DpTarget t(subject, std::max(d - 32, -int(subject.length() - 1)), std::min(d + 32, int(mapper.query_seq(0).length() - 1)), &hsps, subject_id);
......@@ -100,6 +101,10 @@ struct Target : public ::Target
void finish(QueryMapper &mapper)
{
inner_culling(mapper.raw_score_cutoff());
if (config.frame_shift)
return;
for (list<Hsp>::iterator i = hsps.begin(); i != hsps.end(); ++i)
i->query_source_range = TranslatedPosition::absolute_interval(TranslatedPosition(i->query_range.begin_, Frame(i->frame)), TranslatedPosition(i->query_range.end_, Frame(i->frame)), mapper.source_query_len);
}
bool is_outranked(const IntervalPartition &ip, int source_query_len, double rr) const
......@@ -148,9 +153,18 @@ void Pipeline::run_swipe(bool score_only)
{
vector<DpTarget> vf, vr;
for (size_t i = 0; i < n_targets(); ++i)
target(i).add(*this, vf, vr);
banded_3frame_swipe(translated_query, FORWARD, vf.begin(), vf.end(), this->dp_stat, score_only, target_parallel);
banded_3frame_swipe(translated_query, REVERSE, vr.begin(), vr.end(), this->dp_stat, score_only, target_parallel);
target(i).add(*this, vf, vr, (int)i);
if (score_matrix.frame_shift()) {
list<Hsp> hsp = banded_3frame_swipe(translated_query, FORWARD, vf.begin(), vf.end(), this->dp_stat, score_only, target_parallel);
hsp.splice(hsp.end(), banded_3frame_swipe(translated_query, REVERSE, vr.begin(), vr.end(), this->dp_stat, score_only, target_parallel));
while (!hsp.empty()) {
list<Hsp> &l = target(hsp.begin()->swipe_target).hsps;
l.splice(l.end(), hsp, hsp.begin());
}
}
else {
DP::BandedSwipe::swipe(query_seq(0), vf.begin(), vf.end(), Frame(0), score_only ? 0 : DP::TRACEBACK);
}
}
void build_ranking_worker(PtrVector<::Target>::iterator begin, PtrVector<::Target>::iterator end, Atomic<size_t> *next, vector<unsigned> *intervals) {
......
......@@ -25,14 +25,15 @@ namespace ExtensionPipeline { namespace Swipe {
void Pipeline::run(Statistics &stat)
{
const size_t n = targets.size();
vector<DpTarget> seqs(n);
vector<sequence> seqs(n);
for (size_t i = 0; i < n; ++i) {
seqs[i].seq = ref_seqs::get()[targets[i].subject_id];
seqs[i] = ref_seqs::get()[targets[i].subject_id];
}
vector<int> scores(n);
swipe(query_seq(0), seqs.begin(), seqs.end(), scores.begin());
for (size_t i = 0; i < n; ++i)
vector<int> scores = DP::Swipe::swipe(query_seq(0), seqs.data(), seqs.data() + seqs.size());
for (size_t i = 0; i < n; ++i) {
targets[i].hsps.push_back(Hsp(scores[i]));
targets[i].hsps.back().frame = 0;
}
}
}}
\ No newline at end of file
......@@ -24,7 +24,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "sequence.h"
#include "masking.h"
const char* Const::version_string = "0.9.26";
const char* Const::version_string = "0.9.28";
const char* Const::program_name = "diamond";
const char* Const::id_delimiters = " \a\b\f\n\r\t\v\1";
......
......@@ -28,11 +28,11 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "shape_config.h"
#include "../util/io/temp_file.h"
#include "../basic/match.h"
#include "../data/sorted_list.h"
#include "../basic/translate.h"
#include "../dp/dp.h"
#include "masking.h"
#include "../util/system/system.h"
#include "../util/simd.h"
using namespace std;
......@@ -72,7 +72,9 @@ Config::Config(int argc, const char **argv)
.add_command("cluster", "")
.add_command("translate", "")
.add_command("filter-blasttab", "")
.add_command("show-cbs", "");
.add_command("show-cbs", "")
.add_command("simulate-seqs", "")
.add_command("split", "");
Options_group general("General options");
general.add()
......@@ -171,7 +173,8 @@ Config::Config(int argc, const char **argv)
("taxonmap", 0, "protein accession to taxid mapping file", prot_accession2taxid)
("taxonnodes", 0, "taxonomy nodes.dmp from NCBI", nodesdmp)
("taxonnames", 0, "taxonomy names.dmp from NCBI", namesdmp)
("taxonlist", 0, "restrict search to list of taxon ids (comma-separated)", taxonlist);
("taxonlist", 0, "restrict search to list of taxon ids (comma-separated)", taxonlist)
("taxon-exclude", 0, "exclude list of taxon ids (comma-separated)", taxon_exclude);
Options_group advanced("Advanced options");
advanced.add()
......@@ -266,7 +269,6 @@ Config::Config(int argc, const char **argv)
("join-split-key-len", 0, "", join_split_key_len, 17u)
("radix-bits", 0, "", radix_bits, 8u)
("join-ht-factor", 0, "", join_ht_factor, 1.3)
("hash-join", 0, "", hash_join)
("sort-join", 0, "", sort_join)
("simple-freq", 0, "", simple_freq)
("freq-treshold", 0, "", freq_treshold)
......@@ -428,7 +430,7 @@ Config::Config(int argc, const char **argv)
init_cbs();
raw_ungapped_xdrop = score_matrix.rawscore(ungapped_xdrop);
simd_messages();
verbose_stream << "CPU features detected: " << SIMD::features() << endl;
}
Translator::init(query_gencode);
......
......@@ -155,7 +155,6 @@ struct Config
unsigned join_split_key_len;
unsigned radix_bits;
double join_ht_factor;
bool hash_join;
bool sort_join;
bool simple_freq;
double freq_treshold;
......@@ -181,11 +180,12 @@ struct Config
int stop_match_score;
int tantan_maxRepeatOffset;
bool tantan_ungapped;
string taxon_exclude;
enum {
makedb = 0, blastp = 1, blastx = 2, view = 3, help = 4, version = 5, getseq = 6, benchmark = 7, random_seqs = 8, compare = 9, sort = 10, roc = 11, db_stat = 12, model_sim = 13,
match_file_stat = 14, model_seqs = 15, opt = 16, mask = 17, fastq2fasta = 18, dbinfo = 19, test_extra = 20, test_io = 21, db_annot_stats = 22, read_sim = 23, info = 24, seed_stat = 25,
smith_waterman = 26, protein_snps = 27, cluster = 28, translate = 29, filter_blasttab = 30, show_cbs = 31
smith_waterman = 26, protein_snps = 27, cluster = 28, translate = 29, filter_blasttab = 30, show_cbs = 31, simulate_seqs = 32, split = 33
};
unsigned command;
......
......@@ -23,7 +23,7 @@ struct Const
{
enum {
build_version = 127,
build_version = 129,
seedp_bits = 10,
seedp = 1<<seedp_bits,
max_seed_weight = 32,
......
......@@ -206,7 +206,7 @@ struct Hsp
bool is_weakly_enveloped(const Hsp &j) const;
std::pair<int, int> diagonal_bounds() const;
unsigned score, frame, length, identities, mismatches, positives, gap_openings, gaps, sw_score;
unsigned score, frame, length, identities, mismatches, positives, gap_openings, gaps, sw_score, swipe_target;
float time;
interval query_source_range, query_range, subject_range;
Packed_transcript transcript;
......
......@@ -41,7 +41,8 @@ struct Reduction
map_[(long)Translator::STOP] = value_traits.mask_char;
const vector<string> tokens(tokenize(definition_string, " "));
size_ = (unsigned)tokens.size();
bit_size_ = (uint64_t)ceil(log(size_) / log(2));
bit_size_exact_ = log(size_) / log(2);
bit_size_ = (uint64_t)ceil(bit_size_exact_);
for (unsigned i = 0; i<size_; ++i)
for (unsigned j = 0; j<tokens[i].length(); ++j) {
const char ch = tokens[i][j];
......@@ -61,6 +62,10 @@ struct Reduction
return bit_size_;
}
double bit_size_exact() const {
return bit_size_exact_;
}
unsigned operator()(Letter a) const
{
return map_[(long)a];
......@@ -108,6 +113,7 @@ private:
#endif
unsigned size_;
uint64_t bit_size_;
double bit_size_exact_;
};
......
......@@ -36,7 +36,7 @@ typedef double array_of_8[BLAST_NUM_STAT_VALUES];
const double INT2_MAX = std::numeric_limits<double>::max();
const char DNA_scores[5 * 5] = {
const signed char DNA_scores[5 * 5] = {
2, -3, -3, -3, -3,
-3,2,-3,-3,-3,
-3,-3,2,-3,-3,
......
......@@ -134,7 +134,6 @@ struct Shape
for (unsigned i = 0; i < weight_; ++i) {
Letter l = seq[positions_[i]];
if (l == value_traits.mask_char || l == sequence::DELIMITER || l == Translator::STOP)
//if (l == value_traits.mask_char || l == sequence::DELIMITER)
return false;
unsigned r = Reduction::reduction(l);
#ifdef FREQUENCY_MASKING
......@@ -156,7 +155,6 @@ struct Shape
for (unsigned i = 0; i < weight_; ++i) {
Letter l = seq[positions_[i]];
if (l == value_traits.mask_char || l == sequence::DELIMITER || l == Translator::STOP)
//if (l == value_traits.mask_char || l == sequence::DELIMITER)
return false;
unsigned r = Reduction::reduction(l);
s <<= b;
......
......@@ -24,7 +24,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <string.h>
#include <mutex>
#include "../util/log_stream.h"
#include "../util/memory/memory_pool.h"
typedef uint64_t stat_type;
......@@ -94,7 +93,6 @@ struct Statistics
log_stream << "MSE = " << (double)data_[SQUARED_ERROR] / (double)data_[OUT_HITS] << endl;
//log_stream << "Cells = " << data_[CELLS] << endl;
verbose_stream << "Temporary disk space used: " << (double)data_[TEMP_SPACE] / (1 << 30) << " GB" << endl;
log_stream << "Memory pool maximum allocation size: " << (double)MemoryPool::global().max_alloc_size() / (1 << 30) << " GB" << endl;
log_stream << "Outranked hits = " << data_[OUTRANKED_HITS] << " (" << data_[OUTRANKED_HITS]*100.0/ data_[PAIRWISE] << "%)" << endl;
message_stream << "Reported " << data_[PAIRWISE] << " pairwise alignments, " << data_[MATCHES] << " HSPs." << endl;
message_stream << data_[ALIGNED] << " queries aligned." << endl;
......