Skip to content

Commit

Permalink
Misc clean up
Browse files Browse the repository at this point in the history
  • Loading branch information
bovee committed May 21, 2022
1 parent f669279 commit 2ed9cd5
Show file tree
Hide file tree
Showing 28 changed files with 314 additions and 173 deletions.
2 changes: 1 addition & 1 deletion LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2014-2020 Roderick Bovee, 2020- Google
Copyright (c) 2014- Roderick Bovee

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,17 @@ Entab supports reading a variety of bioinformatics, chemoinformatics, and
other formats.

- Agilent Chemstation CH, FID, MS, MWD, and UV formats
- Agilent Masshunter DAD format[^1]
- FASTA and FASTQ sequence formats
- FCS flow cytometry format
- Inficon Hapsite mass specotrometry format
- PNG image format
- SAM and BAM alignment formats
- Thermo continuous flow isotope mass spectrometry formats
- TSV
- Thermo RAW files
- CSV & TSV files

[^1]: This format uses multiple files so it's not supported in streaming mode or in e.g. the JS bindings.

## CLI

Expand Down
7 changes: 5 additions & 2 deletions entab-cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ use entab::EtError;

use crate::tsv_params::TsvParams;

/// Parse the provided `stdin` using `args` and write results to `stdout`.
///
/// # Errors
/// If there are any issues, an `EtError` will be returned.
pub fn run<I, T, R, W>(args: I, stdin: R, stdout: W) -> Result<(), EtError>
where
I: IntoIterator<Item = T>,
Expand Down Expand Up @@ -60,9 +64,8 @@ where
if e.kind() == ErrorKind::DisplayHelp || e.kind() == ErrorKind::DisplayVersion {
e.print()?;
return Ok(());
} else {
return Err(e.to_string().into());
}
return Err(e.to_string().into());
}
};

Expand Down
2 changes: 1 addition & 1 deletion entab-js/LICENSE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2014-2020 Roderick Bovee, 2020- Google
Copyright (c) 2014- Roderick Bovee

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
3 changes: 3 additions & 0 deletions entab-js/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ for (const record of reader) {
}
```

Note that this will require paging the entire file into memory so files that
take >10 Mb may be slow and files >100 Mb may not work at all.

## Development

Build with `wasm-pack build`.
Expand Down
31 changes: 26 additions & 5 deletions entab-js/example/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ function translate(text, key = "") {
"Pick a file": "Escoge un archivo",
"See a sample file": "Ver un archivo de ejemplo",
"Close file": "Cerrar el archivo",
"Close error": "Cerrar diálogo de error",
"Open settings panel": "Abra el panel de configuración",
"Close settings panel": "Cerrar el panel de configuración",
"error-msg": "Hubo un problema al analizar el archivo.",
Expand All @@ -55,6 +56,7 @@ function translate(text, key = "") {
"Pick a file": "Choisir un fichier",
"See a sample file": "Voir un exemple de fichier",
"Close file": "Fermez le fichier",
"Close error": "Fermer l'erreur",
"Open settings panel": "Ouvrir le panneau paramètres",
"Close settings panel": "Fermer le panneau paramètres",
"error-msg": "Un problème est survenu lors de l'analyse du fichier.",
Expand All @@ -76,6 +78,7 @@ function translate(text, key = "") {
"Pick a file": "选择文件",
"See a sample file": "看例子",
"Close file": "关文件",
"Close error": "关错误框",
"Open settings panel": "开设置面板",
"Close settings panel": "关设置面板",
"error-msg": "解析文件出现问题。",
Expand All @@ -97,6 +100,7 @@ function translate(text, key = "") {
"Pick a file": "選擇文件",
"See a sample file": "看例子",
"Close file": "關文件",
"Close error": "關錯誤框",
"Open settings panel": "開設置面板",
"Close settings panel": "關設置面板",
"error-msg": "解析文件出現問題。",
Expand All @@ -122,11 +126,11 @@ const app = PetiteVue.createApp({
const url = new URL(window.location);
url.search = "";
url.searchParams.set("u", this.url);
url.searchParams.set("p", this.graph.parser);
url.searchParams.set("x", this.graph.xaxis);
if (this.graph.parser) url.searchParams.set("p", this.graph.parser);
if (this.graph.xaxis) url.searchParams.set("x", this.graph.xaxis);
if (this.graph.yaxis) url.searchParams.set("y", this.graph.yaxis);
if (this.graph.caxis) url.searchParams.set("c", this.graph.caxis);
url.searchParams.set("m", this.graph.cmap);
if (this.graph.cmap) url.searchParams.set("m", this.graph.cmap);
window.history.replaceState(null, "entab: plot scientific data", url);
}
},
Expand Down Expand Up @@ -171,13 +175,26 @@ const app = PetiteVue.createApp({
this.statusType = "";
this.statusMessage = translate("Loading file…");
return fetch(url).then(response => {
if (!response.ok) {
throw { statusCode: response.status, statusText: response.statusText, };
}
response.name = url.split("/").slice(-1)[0];
return this.processFile(response);
}).catch(e => {
console.error(e);
this.statusType = "error";
this.statusType = "network-error";
// TODO: translate
this.statusMessage = "A network error occured.";
if (!e.statusCode) {
this.statusMessage = "A network error occured. That server probably blocks remote requests.";
} else if (e.statusCode === 404) {
this.statusMessage = "No file exists at that URL.";
} else if (e.statusCode === 401 || e.statusCode === 403) {
this.statusMessage = "Permissions are required to access that URL.";
} else if (e.statusCode >= 500 && e.statusCode < 600) {
this.statusMessage = "A server error occured.";
} else {
this.statusMessage = "A network error occured.";
}
});
},
closeFile() {
Expand Down Expand Up @@ -530,6 +547,10 @@ const FUNCTIONS = {

async function calculateBounds(reader) {
const datum = reader.next().value;
if (!datum) {
// TODO: translate
return new Promise((resolve, reject) => { reject("File had no records") });
}
const bounds = {};
const columns = [];
let nPoints = 0;
Expand Down
53 changes: 43 additions & 10 deletions entab-js/example/index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<!--
[WIP]
Build the JS assets with `wasm-pack build --target web --out-dir examples/pkg`, move them into
Build the JS assets with `wasm-pack build --target web --out-dir example/pkg`, move them into
this folder and serve with e.g. `python3 -m http.server 8000`.
-->
<html lang="en-us">
Expand Down Expand Up @@ -38,13 +38,19 @@
#overlay { height: 98%; left: 0px; top: 0px; position: absolute; padding: 5px; display: flex; flex-direction: column; align-items: flex-start; justify-content: space-between; }
.overlayButton { position: absolute; left: 0px; top: 0px; padding: 15px; font-size: 18pt; line-height: 24pt; }
#overlay .overlayButton { font-size: 30pt; }
/* .closeFileButton { position: absolute; right: 0px; top: 0px; padding: 15px; font-size: 30pt; line-height: 24pt; } */
.progress { position: absolute; right: 0px; top: 0px; padding: 15px; line-height: 24pt; display: flex; align-items: center; }
.closeFileButton { padding-left: 20px; font-size: 30pt; }
.closeErrorButton { position: absolute; right: 0px; top: 0px; padding: 10px; font-size: 30pt; line-height: 24pt; } */
.row { display: flex; align-items: center; }
.row label, .row .label-spacer { display: inline-block; width: 80px; text-align: right; }
#chart { height: 95%; width: 95%; top: 2.5%; left: 2.5%; position: absolute; }
.status, noscript { position: absolute; width: 20%; left: 30%; top: 10%; padding: 2em; text-align: center; }
.status, noscript { position: absolute; width: 35%; left: 25%; top: 10%; padding: 2em; text-align: center; }
@media only screen and (min-width: 768px) {
.status, noscript { width: 28%; left: 28%; }
}
@media only screen and (min-width: 992px) {
.status, noscript { width: 20%; left: 30%; }
}
.button { margin: 0.2em; padding: 0.5em; border-radius: 5px; };
.button:active {
box-shadow: 0 0 0 5px rgba(0,0,0,0.2) inset; border-color: black;
Expand Down Expand Up @@ -93,9 +99,9 @@
></svg>
<div class="buttonBar">
<a class="overlayButton"
role="button"
role="button"
:aria-label="translate('Open settings panel')"
tabindex="0"
tabindex="0"
@keydown.enter="toggleOverlay(true)"
@click="toggleOverlay(true)"
>
Expand All @@ -106,9 +112,9 @@
{{ statusMessage }}
</span>
<a class="closeFileButton"
role="button"
role="button"
:aria-label="translate('Close file')"
tabindex="0"
tabindex="0"
v-if="graph.buffer || filename"
@keydown.enter="closeFile"
@click="closeFile"
Expand Down Expand Up @@ -150,16 +156,43 @@
v-if="statusType === 'error'"
style="background-color: #F09090"
>
&#9888; {{ translate("There was a problem parsing the file.", "error-msg") }} &#9888;
<a class="closeErrorButton"
role="button"
:aria-label="translate('Close error')"
tabindex="0"
@keydown.enter="closeFile"
@click="closeFile"
>
&#xd7;
</a>
&#9888; {{ translate("There was a problem parsing the file.", "error-msg") }}
<div style="text-align: left; font-family: monospace; font-size: 1em; white-space: pre;">
{{ statusMessage }}
</div>
</div>
<div class="status"
@drop.prevent="fileDropped"
@dragover.prevent
v-if="statusType === 'network-error'"
style="background-color: #F09090"
>
<a class="closeErrorButton"
role="button"
:aria-label="translate('Close error')"
tabindex="0"
@keydown.enter="closeFile"
@click="closeFile"
>
&#xd7;
</a>
<br />
&#9888; {{ statusMessage }}
</div>
<div id="overlay" v-if="showOverlay">
<a class="overlayButton"
role="button"
role="button"
:aria-label="translate('Close settings panel')"
tabindex="0"
tabindex="0"
@keydown.enter="toggleOverlay(false)"
@click="toggleOverlay(false)"
>
Expand Down
6 changes: 5 additions & 1 deletion entab-js/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,11 @@ pub struct Reader {
}

fn to_js(err: EtError) -> JsValue {
err.to_string().into()
let res = err.to_string().into();
// technically we could just take a &EtError, but to have a nice function signature we consume
// the err so we should also drop it in here to make clippy happy
drop(err);
res
}

#[wasm_bindgen]
Expand Down
8 changes: 6 additions & 2 deletions entab-py/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![allow(clippy::needless_option_as_deref)]
#![allow(clippy::needless_option_as_deref, clippy::used_underscore_binding)]
mod raw_io_wrapper;

use std::collections::BTreeMap;
Expand All @@ -18,8 +18,12 @@ use crate::raw_io_wrapper::RawIoWrapper;
create_exception!(entab, EntabError, exceptions::PyException);

fn to_py(err: EtError) -> PyErr {
EntabError::new_err(err.to_string())
// TODO: somehow bind err.byte and err.record in here too?
let res = EntabError::new_err(err.to_string());
// we could technically just take an `&EtError` here, but the function signature is nicer with
// a `EtError` so we have to drop it here to make clippy happy
drop(err);
res
}

/// Map a Value into a `PyObject`
Expand Down
2 changes: 1 addition & 1 deletion entab-r/LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2014-2020 Roderick Bovee, 2020- Google
Copyright (c) 2014- Roderick Bovee

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
3 changes: 2 additions & 1 deletion entab/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ categories = ["parsing", "science"]

[dependencies]
# parsing
bytecount = "0.6.2"
chrono = { version = "0.4", default-features=false, features = ["alloc", "serde"] }
encoding = "0.2.33"
memchr = "2.3"
Expand All @@ -28,7 +29,7 @@ rayon = "1.5.1"
[features]
default = ["compression", "std"]
compression = ["bzip2", "xz2", "zstd"]
std = ["chrono/std", "serde/std"]
std = ["bytecount/runtime-dispatch-simd", "chrono/std", "serde/std"]

[[bench]]
name = "benchmarks"
Expand Down
3 changes: 2 additions & 1 deletion entab/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ To parse the IDs out of a FASTA file:
//! use entab::readers::fasta::{FastaReader, FastaRecord};
//!
//! let file = File::open("./tests/data/sequence.fasta")?;
//! let mut reader = FastaReader::new(file, ())?;
//! let mut reader = FastaReader::new(file, None)?;
//! while let Some(FastaRecord { id, .. }) = reader.next()? {
//! println!("{}", id);
//! }
Expand All @@ -21,5 +21,6 @@ To parse the IDs out of a FASTA file:
[Chromatography Toolbox](https://github.com/chemplexity/chromatography) - Matlab - Agilent/Thermo/NetCDF/mzXML
[Isoreader](https://github.com/isoverse/isoreader) - R - Isodat
[Unfinnigan](https://github.com/prvst/unfinnigan) - Perl/Python - Thermo RAW
[seqio](https://github.com/markschl/seq_io) - Rust - FASTX

_Please let me know if there are others that you find useful that should be added to this list._
9 changes: 8 additions & 1 deletion entab/fuzz/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions entab/src/filetype.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,9 @@ impl FileType {
}

/// Returns the "parser name" associated with this file type
///
/// # Errors
/// If a file is unsupported, an error will be returned.
pub fn to_parser_name<'a>(&self, hint: Option<&'a str>) -> Result<&'a str, EtError> {
Ok(match (self, hint) {
(FileType::AgilentChemstationFid, None) => "chemstation_fid",
Expand Down
5 changes: 3 additions & 2 deletions entab/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@
//! Alternatively, you may not know the type of file when writing your code so
//! you may want to abstract over as many types as possible. This is where the
//! slower, generic parser framework is used (for example, in the bindings
//! libraries also). This framework can optionally take a `parser_name` to force
//! it to use that specific parser and optional params to control parser options.
//! for different languages). This framework can optionally take a `parser_name`
//! to force it to use that specific parser and optional params to control
//! parser options.
//! ```
//! # #[cfg(feature = "std")] {
//! use std::fs::File;
Expand Down
Loading

0 comments on commit 2ed9cd5

Please sign in to comment.