├── .gitignore ├── Dockerfile ├── Cargo.toml ├── .travis.yml ├── README.md ├── src └── main.rs └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | target/ 2 | **/*.rs.bk 3 | *.f[aq] 4 | *.out 5 | tasks.json -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ekidd/rust-musl-builder 2 | 3 | # We need to add the source code to the image because `rust-musl-builder` 4 | # assumes a UID of 1000, but TravisCI has switched to 2000. 5 | ADD . ./ 6 | RUN sudo chown -R rust:rust . 7 | 8 | CMD cargo build --release -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "komplexity" 3 | version = "0.3.5" 4 | authors = ["Erik Clarke "] 5 | 6 | [dependencies] 7 | bio = "~0.14" 8 | clap = "~2.24" 9 | fnv = "~1.0" 10 | 11 | [[bin]] 12 | name = "kz" 13 | path = "src/main.rs" 14 | 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | sudo: required 3 | os: 4 | - linux 5 | services: 6 | - docker 7 | rust: 8 | - stable 9 | 10 | jobs: 11 | include: 12 | - stage: GitHub Release 13 | script: echo "Deploying to GitHub release..." 14 | before_deploy: "./build-release kz ${TRAVIS_TAG}-${TRAVIS_OS_NAME}\n" 15 | deploy: 16 | provider: releases 17 | api_key: 18 | secure: FMfnWWeX/BfktyD2W9kNosKTU8hXHC2zyuDryq5VOMZZZ6WipBQQsTZXo8ddNb5GBrIkKhcpc/duxz4nac3ZCaeSVQ63hv5+4kP1qahxY7851xHdLoo+TrcCRZGIzxOhoPgkK+B0ZlMvSh3EhbFnrbdqpXmOpY8pfeyFouraOiU1yFdTroFAPij4AYSVDuAvj8ZG8MKACvDlIzMh0ODcHz4FzZAAPZvjNiKV+fdb9fqH59kDAS+O2324tLhMk3kRRmPSrgCS5u12HuHA6nihQsO46dm1IdIIxR0goDe8XLJ0bq0gXjWlrvEDt704ZRtmohfa+/V4Wb10AtkVMJvPyc6KCq+7Imd3kVY/QAz8brEIGogjowA9LUN7OqgvU/2q0gJuc76bQTYJp7fv2JfB5q6vxQnpvVQofJhyfUrQNo7s07QbSTHAifWXxtKlsb5XYRmY9k+ILZuSpbWKmY2wCWIozqVCNhTaIr/QJQ5A3RRVwL3kZDpntchyYt1LdvJsbxs9Przr2OJhXjaiOiqboIq+b5nUpKI/WSdwpLzeXgm9RdT7nY5zvRiiG0ZFUqB8azAnm2N8lfD3fw9U5RHpgtYIIVaxHY0Dh+xFKuNZTME57RoSXFW3W41+rXp5KgiTENtC+HC5WcWio1VChG6gQMiEmsD73YI/rf7P2TlbNho= 19 | file: "kz-${TRAVIS_TAG}-${TRAVIS_OS_NAME}.zip" 20 | skip_cleanup: true 21 | on: 22 | tags: true 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # komplexity 2 | 3 | [![Build Status](https://travis-ci.org/eclarke/komplexity.svg?branch=master)](https://travis-ci.org/eclarke/komplexity) 4 | 5 | A command-line tool built in Rust to quickly calculate and/or mask low-complexity sequences from a FAST[A/Q] file. This uses the number of unique _k_-mers over a sequence divided by the length to assess complexity. 6 | 7 | We've noticed that, for _k_=4, a normalized complexity score of < 0.55 suggests across a 64-120bp region strongly that the sequence is a low-complexity repeat sequence. 8 | 9 | ## Installation 10 | 11 | Assuming you have Rust and Cargo installed: 12 | 13 | ```sh 14 | git clone https://github.com/eclarke/komplexity 15 | cd komplexity 16 | cargo install 17 | ``` 18 | 19 | Or, using Conda: 20 | ```sh 21 | conda install -c eclarke komplexity 22 | ``` 23 | 24 | If Cargo's default bin directory is in your path (usually `$HOME/.cargo/bin`), you can run this by just typing `kz`. 25 | 26 | ## Usage 27 | 28 | This tool has two modes: measuring (default) and masking. Both modes read from standard in and write to standard out. 29 | 30 | ### Measuring 31 | 32 | Measuring mode reports the length of a sequence, the number of unique kmers in that sequence, and the normalized complexity (unique kmers / length). As this looks across the entire sequence, it is most appropriate for short reads (e.g. Illumina), since longer sequences will have low normalized complexity simply due to greater length. 33 | 34 | ```sh 35 | # For fastq files: 36 | kz < seqs.fq 37 | # For fasta files: 38 | kz --fasta < seqs.fa 39 | # Vary length of k: 40 | kz -k5 < seqs.fq 41 | ``` 42 | 43 | The output is a list of sequence IDs from the fastq file with the length of the sequence, the number of unique _k_-mers in the sequence, and the number of unique _k_-mers/length (normalized complexity) in a tab-delimited format to stout. 44 | 45 | ### Masking 46 | 47 | Masking mode (`--mask`) outputs the input sequences with low-complexity regions masked by Ns. The low-complexity regions are found using a sliding window (of size `--window_size`) over the sequence; the complexity of the subsequence is assessed as in the "measuring" mode. The threshold below which the sequence is masked is configurable through the `--threshold` parameter and should be a value between 0-1 (least to most masking). 48 | 49 | ```sh 50 | # For fastq files: 51 | kz --mask < seqs.fq 52 | # For fasta files: 53 | kz --mask --fasta < seqs.fa 54 | # Vary threshold: 55 | kz --mask --threshold 0.7 < seqs.fq 56 | # Vary window size: 57 | kz --mask --window_size 64 < seqs.fq 58 | ``` 59 | ### Filtering 60 | 61 | Filtering mode (`--filter`) outputs the input sequences with low-complexity sequences omitted. The threshold below which the sequence is masked is configurable through the `--threshold` parameter and should be a value between 0-1 (least to most masking). Note that this is most useful for Illumina reads or other short sequences, as scores will approach 1 for longer sequences. 62 | 63 | ```sh 64 | # For fastq files: 65 | kz --filter < seqs.fq 66 | # For fasta files: 67 | kz --filter --fasta < seqs.fa 68 | # Vary threshold: 69 | kz --filter --threshold 0.7 < seqs.fq 70 | ``` 71 | Note that you cannot filter and mask at the same time. 72 | 73 | ### Parallelization 74 | 75 | I didn't write any parallelization code into this as it's mostly I/O bound. Instead I suggest using [GNU Parallel](https://www.gnu.org/software/parallel/) as follows: 76 | 77 | #### FASTQ files 78 | Use `-L4` to define a record as being four lines. The `-j` parameter defines the number of cores to use, and `--round-robin` passes records to each of the spawned jobs. Any options to `kz` can be specified as normal. _The input order is not maintained using this method._ 79 | 80 | ```sh 81 | cat | parallel --round_robin -L4 -j --pipe kz 82 | ``` 83 | 84 | #### FASTA files 85 | As above, but the record is now defined using `--recstart '>'`. 86 | ```sh 87 | cat | parallel --round_robin --recstart '>' -j --pipe kz --fasta 88 | ``` 89 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | extern crate bio; 2 | extern crate clap; 3 | extern crate fnv; 4 | 5 | use std::vec::Vec; 6 | use std::io; 7 | use std::iter; 8 | use std::collections::VecDeque; 9 | 10 | use bio::alphabets; 11 | use bio::alphabets::RankTransform; 12 | use bio::io::{fastq, fasta}; 13 | 14 | use fnv::{FnvHashSet, FnvHashMap}; 15 | 16 | use clap::{App, Arg}; 17 | 18 | const VERSION: &'static str = env!("CARGO_PKG_VERSION"); 19 | 20 | fn main() { 21 | 22 | let args = App::new("kz") 23 | .about("Calculate the overall complexity of a sequence. Reads from stdin and writes to stdout.") 24 | .arg(Arg::with_name("k") 25 | .short("k") 26 | .takes_value(true) 27 | .help("length of k-mer to use") 28 | .default_value("4")) 29 | .arg(Arg::with_name("fasta") 30 | .long("fasta") 31 | .short("f") 32 | .takes_value(false) 33 | .help("input is in fasta format")) 34 | .arg(Arg::with_name("window_size") 35 | .long("window_size") 36 | .short("w") 37 | .takes_value(true) 38 | .default_value("32") 39 | .help("window size for masking")) 40 | .arg(Arg::with_name("threshold") 41 | .long("threshold") 42 | .short("t") 43 | .takes_value(true) 44 | .default_value("0.55") 45 | .help("complexity threshold ([0:1], 0 = most stringent, 1 = least)")) 46 | .arg(Arg::with_name("mask") 47 | .long("mask") 48 | .short("m") 49 | .takes_value(false) 50 | .help("use sliding window to mask low-complexity regions")) 51 | .arg(Arg::with_name("lower_case") 52 | .long("lower_case") 53 | .short("l") 54 | .takes_value(false) 55 | .help("mask using lower-case symbols rather than Ns")) 56 | .arg(Arg::with_name("filter") 57 | .long("filter") 58 | .short("F") 59 | .takes_value(false) 60 | .help("filter sequences falling below a threshold")) 61 | .arg(Arg::with_name("version") 62 | .long("version") 63 | .short("V") 64 | .takes_value(false) 65 | .help("print version info")) 66 | .get_matches(); 67 | 68 | if args.is_present("version") { 69 | println!("komplexity v{}", VERSION); 70 | std::process::exit(0) 71 | }; 72 | 73 | let record_type = match args.is_present("fasta") { 74 | true => RecordType::Fasta, 75 | false => RecordType::Fastq, 76 | }; 77 | 78 | let filter_or_mask = (args.is_present("mask") as bool, args.is_present("filter") as bool); 79 | 80 | if filter_or_mask.0 && filter_or_mask.1 { 81 | error_exit("cannot filter and mask") 82 | } 83 | 84 | let task = match filter_or_mask { 85 | (true, false) => Task::Mask, 86 | (false, true) => Task::Filter, 87 | _ => Task::Measure 88 | }; 89 | 90 | let mask_type = match args.is_present("lower_case") { 91 | true => MaskType::LowerCase, 92 | false => MaskType::N 93 | }; 94 | 95 | let k: u32 = args 96 | .value_of("k") 97 | .unwrap() 98 | .trim() 99 | .parse() 100 | .expect("k must be an integer"); 101 | 102 | if k > 12 { 103 | // Because we use the extended IUPAC alphabet, we're restricted to 104 | // smaller ks (though this doesn't matter for our purposes) 105 | error_exit("-k must be less than or equal to 12") 106 | } 107 | 108 | let threshold: f64 = args 109 | .value_of("threshold") 110 | .unwrap() 111 | .trim() 112 | .parse() 113 | .expect("'--threshold' must be a number between 0-1"); 114 | 115 | if threshold < 0.0 || threshold > 1.0 { 116 | error_exit("'--threshold' must be a number between 0-1"); 117 | } 118 | 119 | let window_size: usize = args 120 | .value_of("window_size") 121 | .unwrap() 122 | .trim() 123 | .parse() 124 | .expect("'--window_size' must be an integer greater than 0"); 125 | 126 | complexity(record_type, task, k, threshold, window_size, mask_type); 127 | } 128 | 129 | #[derive(Debug)] 130 | struct Interval { 131 | start: usize, 132 | end: usize 133 | } 134 | 135 | enum RecordType { 136 | Fasta, 137 | Fastq 138 | } 139 | 140 | enum Task { 141 | Mask, 142 | Measure, 143 | Filter 144 | } 145 | 146 | enum MaskType { 147 | N, 148 | LowerCase 149 | } 150 | 151 | fn complexity(record_type: RecordType, task: Task, k: u32, threshold: f64, window_size: usize, mask_type: MaskType) { 152 | let alphabet = alphabets::dna::iupac_alphabet(); 153 | let rank = RankTransform::new(&alphabet); 154 | 155 | match record_type { 156 | RecordType::Fasta => { 157 | let mut writer = fasta::Writer::new(io::stdout()); 158 | let records = fasta::Reader::new(io::stdin()).records(); 159 | records 160 | .map(|r| r.expect("Error reading FASTA record")) 161 | .map(|r| { 162 | let id = r.id(); 163 | let seq = r.seq(); 164 | match task { 165 | Task::Mask => { 166 | let seq = mask_sequence(seq, &rank, k, threshold, window_size, &mask_type); 167 | writer.write(id, r.desc(), &seq).unwrap(); 168 | }, 169 | Task::Measure => { 170 | let length = seq.len(); 171 | let kmers = unique_kmers(seq, k, &rank); 172 | println!("{}\t{}\t{}\t{}", id, length, kmers, kmers as f64 / length as f64); 173 | }, 174 | Task::Filter => { 175 | let length = seq.len(); 176 | let kmers = unique_kmers(seq, k, &rank); 177 | let sequence_complexity = kmers as f64 / length as f64; 178 | if sequence_complexity > threshold { 179 | writer.write(id, r.desc(), &seq).unwrap(); 180 | } 181 | } 182 | } 183 | 184 | }) 185 | .collect::>(); 186 | }, 187 | RecordType::Fastq => { 188 | let mut writer = fastq::Writer::new(io::stdout()); 189 | let records = fastq::Reader::new(io::stdin()).records(); 190 | records 191 | .map(|r| r.expect("Error reading FASTQ record")) 192 | .map(|r| { 193 | let id = r.id(); 194 | let seq = r.seq(); 195 | match task { 196 | Task::Mask => { 197 | let seq = mask_sequence(seq, &rank, k, threshold, window_size, &mask_type); 198 | writer.write(id, r.desc(), &seq, r.qual()).unwrap(); 199 | }, 200 | Task::Measure => { 201 | let length = seq.len(); 202 | let kmers = unique_kmers(seq, k, &rank); 203 | println!("{}\t{}\t{}\t{}", id, length, kmers, kmers as f64 / length as f64); 204 | } 205 | Task::Filter => { 206 | let length = seq.len(); 207 | let kmers = unique_kmers(seq, k, &rank); 208 | let sequence_complexity = kmers as f64 / length as f64; 209 | if sequence_complexity > threshold { 210 | writer.write(id, r.desc(), &seq, r.qual()).unwrap(); 211 | } 212 | } 213 | } 214 | }) 215 | .collect::>(); 216 | } 217 | } 218 | } 219 | 220 | fn mask_sequence(seq: &[u8], rank: &RankTransform, k: u32, threshold: f64, window_size: usize, mask_type: &MaskType) -> Vec { 221 | let intervals = lc_intervals(seq, k, rank, threshold, window_size); 222 | mask_intervals(seq, intervals, mask_type) 223 | } 224 | 225 | fn unique_kmers(text: &[u8], k: u32, rank: &RankTransform) -> usize { 226 | rank.qgrams(k, text) 227 | .collect::>() 228 | .len() 229 | } 230 | 231 | fn lc_intervals(text: &[u8], q: u32, rank: &RankTransform, threshold: f64, window_size: usize) -> Vec { 232 | let mut intervals: Vec = Vec::new(); 233 | let mut window: VecDeque = VecDeque::with_capacity(window_size); 234 | let mut kmer_iterator = rank.qgrams(q, text).into_iter(); 235 | let mut kmers: FnvHashMap = FnvHashMap::default(); 236 | 237 | // Init: fill window buffer 238 | for _ in 0..window_size { 239 | match kmer_iterator.next() { 240 | Some(kmer) => window.push_back(kmer), 241 | None => break 242 | } 243 | } 244 | // Count kmers in window 245 | for kmer in window.iter() { 246 | let n = kmers.entry(*kmer).or_insert(0); 247 | *n += 1; 248 | } 249 | 250 | let mut idx = 0; 251 | loop { 252 | let window_complexity = kmers.len() as f64 / window.len() as f64; 253 | if window_complexity < threshold { 254 | let start = idx; 255 | let end = idx + (window.len() - 1 + q as usize); 256 | intervals.push(Interval{ start, end }); 257 | } 258 | match kmer_iterator.next() { 259 | Some(kmer) => { 260 | let prev = window.pop_front().unwrap(); 261 | window.push_back(kmer); 262 | // Update kmer counts: remove 1 from leaving kmer 263 | let prev_n = *kmers.get(&prev).unwrap(); 264 | if prev_n == 1 { 265 | kmers.remove(&prev); 266 | } else { 267 | kmers.insert(prev, prev_n-1); 268 | } 269 | // Update kmer counts: add 1 for entering kmer 270 | let next_n = kmers.entry(kmer).or_insert(0); 271 | *next_n += 1; 272 | // Update index 273 | idx += 1; 274 | }, 275 | None => break, 276 | } 277 | } 278 | return collapse_intervals(intervals); 279 | } 280 | 281 | fn collapse_intervals(intervals: Vec) -> Vec { 282 | let mut collapsed: Vec = Vec::new(); 283 | let mut intervals = intervals.into_iter(); 284 | if let Some(mut current) = intervals.next() { 285 | for interval in intervals { 286 | if interval.start < current.end { 287 | current.end = interval.end; 288 | } else { 289 | collapsed.push(current); 290 | current = interval; 291 | } 292 | } 293 | collapsed.push(current); 294 | } 295 | return collapsed; 296 | } 297 | 298 | fn mask_intervals(seq: &[u8], intervals: Vec, mask_type: &MaskType) -> Vec { 299 | let mut new_seq: Vec = Vec::with_capacity(seq.len()); 300 | let mut last = Interval{start: 0, end: 0}; 301 | for interval in intervals { 302 | let intervening = &seq[last.end .. interval.start]; 303 | new_seq.extend_from_slice(intervening); 304 | match *mask_type { 305 | MaskType::LowerCase => new_seq.append(&mut lowercase(&seq[interval.start..interval.end])), 306 | MaskType::N => new_seq.extend(iter::repeat(b'N').take(interval.end-interval.start)), 307 | }; 308 | // for _ in interval.start..interval.end { 309 | // new_seq.push(b'N'); 310 | // } 311 | last = interval; 312 | } 313 | let end = &seq[last.end..]; 314 | new_seq.extend_from_slice(end); 315 | return new_seq; 316 | } 317 | 318 | fn error_exit(msg: &str) { 319 | eprintln!("{}", msg); 320 | std::process::exit(1); 321 | } 322 | 323 | fn lowercase(seq: &[u8]) -> Vec { 324 | // ACGTRYSWKMBDHVNZ 325 | let mut new = Vec::with_capacity(seq.len()); 326 | for b in seq { 327 | let b = match *b { 328 | b'A' => b'a', 329 | b'C' => b'c', 330 | b'G' => b'g', 331 | b'T' => b't', 332 | b'R' => b'r', 333 | b'Y' => b'y', 334 | b'S' => b's', 335 | b'W' => b'w', 336 | b'K' => b'k', 337 | b'M' => b'm', 338 | b'B' => b'b', 339 | b'D' => b'd', 340 | b'H' => b'h', 341 | b'V' => b'v', 342 | b'N' => b'n', 343 | b'Z' => b'z', 344 | _ => *b, 345 | }; 346 | new.push(b); 347 | } 348 | return new; 349 | } 350 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | [[package]] 2 | name = "aho-corasick" 3 | version = "0.6.3" 4 | source = "registry+https://github.com/rust-lang/crates.io-index" 5 | dependencies = [ 6 | "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 7 | ] 8 | 9 | [[package]] 10 | name = "ansi_term" 11 | version = "0.9.0" 12 | source = "registry+https://github.com/rust-lang/crates.io-index" 13 | 14 | [[package]] 15 | name = "approx" 16 | version = "0.1.1" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | 19 | [[package]] 20 | name = "atty" 21 | version = "0.2.2" 22 | source = "registry+https://github.com/rust-lang/crates.io-index" 23 | dependencies = [ 24 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 25 | "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", 26 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 27 | ] 28 | 29 | [[package]] 30 | name = "bio" 31 | version = "0.14.2" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | dependencies = [ 34 | "approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 35 | "bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 36 | "bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", 37 | "bytecount 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 38 | "csv 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)", 39 | "custom_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 40 | "itertools 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", 41 | "itertools-num 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 42 | "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 43 | "multimap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 44 | "ndarray 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", 45 | "newtype_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 46 | "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", 47 | "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 48 | "ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", 49 | "quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 50 | "regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 51 | "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", 52 | "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", 53 | "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", 54 | "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 55 | ] 56 | 57 | [[package]] 58 | name = "bit-set" 59 | version = "0.4.0" 60 | source = "registry+https://github.com/rust-lang/crates.io-index" 61 | dependencies = [ 62 | "bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", 63 | ] 64 | 65 | [[package]] 66 | name = "bit-vec" 67 | version = "0.4.4" 68 | source = "registry+https://github.com/rust-lang/crates.io-index" 69 | 70 | [[package]] 71 | name = "bitflags" 72 | version = "0.8.2" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | 75 | [[package]] 76 | name = "bytecount" 77 | version = "0.1.7" 78 | source = "registry+https://github.com/rust-lang/crates.io-index" 79 | 80 | [[package]] 81 | name = "byteorder" 82 | version = "1.1.0" 83 | source = "registry+https://github.com/rust-lang/crates.io-index" 84 | 85 | [[package]] 86 | name = "clap" 87 | version = "2.24.2" 88 | source = "registry+https://github.com/rust-lang/crates.io-index" 89 | dependencies = [ 90 | "ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", 91 | "atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 92 | "bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", 93 | "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", 94 | "term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", 95 | "unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 96 | "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", 97 | "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 98 | ] 99 | 100 | [[package]] 101 | name = "csv" 102 | version = "0.15.0" 103 | source = "registry+https://github.com/rust-lang/crates.io-index" 104 | dependencies = [ 105 | "byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 106 | "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 107 | "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", 108 | ] 109 | 110 | [[package]] 111 | name = "custom_derive" 112 | version = "0.1.7" 113 | source = "registry+https://github.com/rust-lang/crates.io-index" 114 | 115 | [[package]] 116 | name = "either" 117 | version = "1.1.0" 118 | source = "registry+https://github.com/rust-lang/crates.io-index" 119 | 120 | [[package]] 121 | name = "fnv" 122 | version = "1.0.5" 123 | source = "registry+https://github.com/rust-lang/crates.io-index" 124 | 125 | [[package]] 126 | name = "itertools" 127 | version = "0.6.2" 128 | source = "registry+https://github.com/rust-lang/crates.io-index" 129 | dependencies = [ 130 | "either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 131 | ] 132 | 133 | [[package]] 134 | name = "itertools-num" 135 | version = "0.1.1" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | dependencies = [ 138 | "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 139 | ] 140 | 141 | [[package]] 142 | name = "kernel32-sys" 143 | version = "0.2.2" 144 | source = "registry+https://github.com/rust-lang/crates.io-index" 145 | dependencies = [ 146 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 147 | "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 148 | ] 149 | 150 | [[package]] 151 | name = "komplexity" 152 | version = "0.3.1" 153 | dependencies = [ 154 | "bio 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)", 155 | "clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)", 156 | "fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", 157 | ] 158 | 159 | [[package]] 160 | name = "lazy_static" 161 | version = "0.2.8" 162 | source = "registry+https://github.com/rust-lang/crates.io-index" 163 | 164 | [[package]] 165 | name = "libc" 166 | version = "0.2.30" 167 | source = "registry+https://github.com/rust-lang/crates.io-index" 168 | 169 | [[package]] 170 | name = "matrixmultiply" 171 | version = "0.1.13" 172 | source = "registry+https://github.com/rust-lang/crates.io-index" 173 | dependencies = [ 174 | "rawpointer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", 175 | ] 176 | 177 | [[package]] 178 | name = "memchr" 179 | version = "1.0.1" 180 | source = "registry+https://github.com/rust-lang/crates.io-index" 181 | dependencies = [ 182 | "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", 183 | ] 184 | 185 | [[package]] 186 | name = "multimap" 187 | version = "0.4.0" 188 | source = "registry+https://github.com/rust-lang/crates.io-index" 189 | dependencies = [ 190 | "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", 191 | ] 192 | 193 | [[package]] 194 | name = "ndarray" 195 | version = "0.9.1" 196 | source = "registry+https://github.com/rust-lang/crates.io-index" 197 | dependencies = [ 198 | "itertools 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", 199 | "matrixmultiply 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", 200 | "num-complex 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 201 | "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 202 | ] 203 | 204 | [[package]] 205 | name = "newtype_derive" 206 | version = "0.1.6" 207 | source = "registry+https://github.com/rust-lang/crates.io-index" 208 | dependencies = [ 209 | "rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", 210 | ] 211 | 212 | [[package]] 213 | name = "num-complex" 214 | version = "0.1.40" 215 | source = "registry+https://github.com/rust-lang/crates.io-index" 216 | dependencies = [ 217 | "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 218 | ] 219 | 220 | [[package]] 221 | name = "num-integer" 222 | version = "0.1.35" 223 | source = "registry+https://github.com/rust-lang/crates.io-index" 224 | dependencies = [ 225 | "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 226 | ] 227 | 228 | [[package]] 229 | name = "num-traits" 230 | version = "0.1.40" 231 | source = "registry+https://github.com/rust-lang/crates.io-index" 232 | 233 | [[package]] 234 | name = "ordered-float" 235 | version = "0.5.0" 236 | source = "registry+https://github.com/rust-lang/crates.io-index" 237 | dependencies = [ 238 | "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", 239 | "unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", 240 | ] 241 | 242 | [[package]] 243 | name = "quick-error" 244 | version = "1.2.0" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | 247 | [[package]] 248 | name = "quote" 249 | version = "0.3.15" 250 | source = "registry+https://github.com/rust-lang/crates.io-index" 251 | 252 | [[package]] 253 | name = "rawpointer" 254 | version = "0.1.0" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | 257 | [[package]] 258 | name = "regex" 259 | version = "0.2.2" 260 | source = "registry+https://github.com/rust-lang/crates.io-index" 261 | dependencies = [ 262 | "aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", 263 | "memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 264 | "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", 265 | "thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", 266 | "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 267 | ] 268 | 269 | [[package]] 270 | name = "regex-syntax" 271 | version = "0.4.1" 272 | source = "registry+https://github.com/rust-lang/crates.io-index" 273 | 274 | [[package]] 275 | name = "rustc-serialize" 276 | version = "0.3.24" 277 | source = "registry+https://github.com/rust-lang/crates.io-index" 278 | 279 | [[package]] 280 | name = "rustc_version" 281 | version = "0.1.7" 282 | source = "registry+https://github.com/rust-lang/crates.io-index" 283 | dependencies = [ 284 | "semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", 285 | ] 286 | 287 | [[package]] 288 | name = "semver" 289 | version = "0.1.20" 290 | source = "registry+https://github.com/rust-lang/crates.io-index" 291 | 292 | [[package]] 293 | name = "serde" 294 | version = "1.0.11" 295 | source = "registry+https://github.com/rust-lang/crates.io-index" 296 | 297 | [[package]] 298 | name = "serde_derive" 299 | version = "1.0.11" 300 | source = "registry+https://github.com/rust-lang/crates.io-index" 301 | dependencies = [ 302 | "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", 303 | "serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)", 304 | "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", 305 | ] 306 | 307 | [[package]] 308 | name = "serde_derive_internals" 309 | version = "0.15.1" 310 | source = "registry+https://github.com/rust-lang/crates.io-index" 311 | dependencies = [ 312 | "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", 313 | "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", 314 | ] 315 | 316 | [[package]] 317 | name = "strsim" 318 | version = "0.6.0" 319 | source = "registry+https://github.com/rust-lang/crates.io-index" 320 | 321 | [[package]] 322 | name = "syn" 323 | version = "0.11.11" 324 | source = "registry+https://github.com/rust-lang/crates.io-index" 325 | dependencies = [ 326 | "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", 327 | "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", 328 | "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 329 | ] 330 | 331 | [[package]] 332 | name = "synom" 333 | version = "0.11.3" 334 | source = "registry+https://github.com/rust-lang/crates.io-index" 335 | dependencies = [ 336 | "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", 337 | ] 338 | 339 | [[package]] 340 | name = "term_size" 341 | version = "0.3.0" 342 | source = "registry+https://github.com/rust-lang/crates.io-index" 343 | dependencies = [ 344 | "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", 345 | "libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)", 346 | "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 347 | ] 348 | 349 | [[package]] 350 | name = "thread_local" 351 | version = "0.3.4" 352 | source = "registry+https://github.com/rust-lang/crates.io-index" 353 | dependencies = [ 354 | "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", 355 | "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", 356 | ] 357 | 358 | [[package]] 359 | name = "unicode-segmentation" 360 | version = "1.2.0" 361 | source = "registry+https://github.com/rust-lang/crates.io-index" 362 | 363 | [[package]] 364 | name = "unicode-width" 365 | version = "0.1.4" 366 | source = "registry+https://github.com/rust-lang/crates.io-index" 367 | 368 | [[package]] 369 | name = "unicode-xid" 370 | version = "0.0.4" 371 | source = "registry+https://github.com/rust-lang/crates.io-index" 372 | 373 | [[package]] 374 | name = "unreachable" 375 | version = "0.1.1" 376 | source = "registry+https://github.com/rust-lang/crates.io-index" 377 | dependencies = [ 378 | "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 379 | ] 380 | 381 | [[package]] 382 | name = "unreachable" 383 | version = "1.0.0" 384 | source = "registry+https://github.com/rust-lang/crates.io-index" 385 | dependencies = [ 386 | "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 387 | ] 388 | 389 | [[package]] 390 | name = "utf8-ranges" 391 | version = "1.0.0" 392 | source = "registry+https://github.com/rust-lang/crates.io-index" 393 | 394 | [[package]] 395 | name = "vec_map" 396 | version = "0.8.0" 397 | source = "registry+https://github.com/rust-lang/crates.io-index" 398 | dependencies = [ 399 | "serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", 400 | "serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", 401 | ] 402 | 403 | [[package]] 404 | name = "void" 405 | version = "1.0.2" 406 | source = "registry+https://github.com/rust-lang/crates.io-index" 407 | 408 | [[package]] 409 | name = "winapi" 410 | version = "0.2.8" 411 | source = "registry+https://github.com/rust-lang/crates.io-index" 412 | 413 | [[package]] 414 | name = "winapi-build" 415 | version = "0.1.1" 416 | source = "registry+https://github.com/rust-lang/crates.io-index" 417 | 418 | [metadata] 419 | "checksum aho-corasick 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "500909c4f87a9e52355b26626d890833e9e1d53ac566db76c36faa984b889699" 420 | "checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6" 421 | "checksum approx 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08abcc3b4e9339e33a3d0a5ed15d84a687350c05689d825e0f6655eef9e76a94" 422 | "checksum atty 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d912da0db7fa85514874458ca3651fe2cddace8d0b0505571dbdcd41ab490159" 423 | "checksum bio 0.14.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b289c40c8d5055cc6ef73d66e5c1e90a4e5e675d78c6c56c6a31e17da870c52a" 424 | "checksum bit-set 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9bf6104718e80d7b26a68fdbacff3481cfc05df670821affc7e9cbc1884400c" 425 | "checksum bit-vec 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "02b4ff8b16e6076c3e14220b39fbc1fabb6737522281a388998046859400895f" 426 | "checksum bitflags 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1370e9fc2a6ae53aea8b7a5110edbd08836ed87c88736dfabccade1c2b44bff4" 427 | "checksum bytecount 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "4bbeb7c30341fce29f6078b4bdf876ea4779600866e98f5b2d203a534f195050" 428 | "checksum byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff81738b726f5d099632ceaffe7fb65b90212e8dce59d518729e7e8634032d3d" 429 | "checksum clap 2.24.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b8f69e518f967224e628896b54e41ff6acfb4dcfefc5076325c36525dac900f" 430 | "checksum csv 0.15.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ef22b37c7a51c564a365892c012dc0271221fdcc64c69b19ba4d6fa8bd96d9c" 431 | "checksum custom_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9" 432 | "checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a" 433 | "checksum fnv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc484842f1e2884faf56f529f960cc12ad8c71ce96cc7abba0a067c98fee344" 434 | "checksum itertools 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "22c285d60139cf413244894189ca52debcfd70b57966feed060da76802e415a0" 435 | "checksum itertools-num 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d78fa608383e6e608ba36f962ac991d5d6878d7203eb93b4711b14fa6717813" 436 | "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" 437 | "checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf" 438 | "checksum libc 0.2.30 (registry+https://github.com/rust-lang/crates.io-index)" = "2370ca07ec338939e356443dac2296f581453c35fe1e3a3ed06023c49435f915" 439 | "checksum matrixmultiply 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "7ce012d2c43046267a74283eaa7e9a51941479901e2b86702be10f27e2779158" 440 | "checksum memchr 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1dbccc0e46f1ea47b9f17e6d67c5a96bd27030519c519c9c91327e31275a47b4" 441 | "checksum multimap 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2eb04b9f127583ed176e163fb9ec6f3e793b87e21deedd5734a69386a18a0151" 442 | "checksum ndarray 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9d0603e041601804a61a33ebecbea220b43a86437b9ee20680a1f9fdaaa922a8" 443 | "checksum newtype_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ac8cd24d9f185bb7223958d8c1ff7a961b74b1953fd05dba7cc568a63b3861ec" 444 | "checksum num-complex 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "503e668405c5492d67cf662a81e05be40efe2e6bcf10f7794a07bd9865e704e6" 445 | "checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba" 446 | "checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0" 447 | "checksum ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58d25b6c0e47b20d05226d288ff434940296e7e2f8b877975da32f862152241f" 448 | "checksum quick-error 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c36987d4978eb1be2e422b1e0423a557923a5c3e7e6f31d5699e9aafaefa469" 449 | "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" 450 | "checksum rawpointer 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebac11a9d2e11f2af219b8b8d833b76b1ea0e054aa0e8d8e9e4cbde353bdf019" 451 | "checksum regex 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1731164734096285ec2a5ec7fea5248ae2f5485b3feeb0115af4fda2183b2d1b" 452 | "checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" 453 | "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" 454 | "checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084" 455 | "checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac" 456 | "checksum serde 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f7726f29ddf9731b17ff113c461e362c381d9d69433f79de4f3dd572488823e9" 457 | "checksum serde_derive 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cf823e706be268e73e7747b147aa31c8f633ab4ba31f115efb57e5047c3a76dd" 458 | "checksum serde_derive_internals 0.15.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37aee4e0da52d801acfbc0cc219eb1eda7142112339726e427926a6f6ee65d3a" 459 | "checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" 460 | "checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" 461 | "checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" 462 | "checksum term_size 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2b6b55df3198cc93372e85dd2ed817f0e38ce8cc0f22eb32391bfad9c4bf209" 463 | "checksum thread_local 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1697c4b57aeeb7a536b647165a2825faddffb1d3bad386d507709bd51a90bb14" 464 | "checksum unicode-segmentation 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a8083c594e02b8ae1654ae26f0ade5158b119bd88ad0e8227a5d8fcd72407946" 465 | "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" 466 | "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" 467 | "checksum unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" 468 | "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" 469 | "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" 470 | "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" 471 | "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" 472 | "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" 473 | "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" 474 | --------------------------------------------------------------------------------