Skip to content

Commit c142343

Browse files
author
milescsmith
committed
add readme
1 parent 1f4d345 commit c142343

7 files changed

Lines changed: 94 additions & 80 deletions

File tree

CHANGELOG.md

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,43 @@
11
# Changelog
2+
23
All notable changes to this project will be documented in this file.
34

45
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
56
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
67

8+
## [0.2.0] - 2021-02-02
9+
10+
### Added
11+
12+
- A real README.md
13+
14+
### Changed
15+
16+
- Removed conditional requirement of `import_metadata` as a version of Python >=3.8 is required
17+
18+
## [0.1.11] - 2021-02-02
19+
20+
### Changed
21+
22+
- updated dependency versions
723

824
## [0.1.10] - 2021-12-20
925

1026
### Changed
27+
1128
- updated dependency versions
1229

1330

1431
## [0.1.9] - 2021-04-20
1532

1633
### Changed
34+
1735
- updated dependency versions
1836

1937
## [0.1.8] - 2021
2038

2139
### Changed
40+
2241
- renamed `logging.py` to `logger.py` to avoid colliding with the standard module name
2342
- alter how the PED file is written to: for whatever reason, `Path().write_text()` was not working
2443
but using a open file context manager with `writelines()` does.
@@ -27,19 +46,24 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2746
## [0.1.7] - 2021-02-22
2847

2948
### Added
49+
3050
- CHANGELOG.md
3151
- more logging info
3252

3353
### Fixed
54+
3455
- add missing import of liftPed to plinkliftover.__main__ from plinkliftover.liftover
3556
- if the liftOver executable cannot be found, raise an error
3657

3758
## [0.1.6] - 2021-02-22
3859

3960
### Fixed
40-
- replace `set` and `tuple` in type hints with their `typing.Set` and `typing.Tuple` counterparts
4161

62+
- replace `set` and `tuple` in type hints with their `typing.Set` and `typing.Tuple` counterparts
4263

64+
[0.2.0]: https://github.com/olivierlacan/keep-a-changelog/compare/0.1.11...0.2.0
65+
[0.1.11]: https://github.com/olivierlacan/keep-a-changelog/compare/0.1.10...0.1.11
66+
[0.1.10]: https://github.com/olivierlacan/keep-a-changelog/compare/0.1.9...0.1.10
4367
[0.1.9]: https://github.com/olivierlacan/keep-a-changelog/compare/0.1.8...0.1.9
4468
[0.1.8]: https://github.com/olivierlacan/keep-a-changelog/compare/0.1.7...0.1.8
4569
[0.1.7]: https://github.com/olivierlacan/keep-a-changelog/compare/0.1.6...0.1.7

README.md

Lines changed: 46 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,84 @@
1-
# plinkliftover
1+
# PLINKLiftOver
22

3-
<div align="center">
3+
<div align="justified">
44

55
[![Build status](https://github.com/milescsmith/plinkliftover/workflows/build/badge.svg?branch=master&event=push)](https://github.com/milescsmith/plinkliftover/actions?query=workflow%3Abuild)
66
[![Python Version](https://img.shields.io/pypi/pyversions/plinkliftover.svg)](https://pypi.org/project/plinkliftover/)
77
[![Dependencies Status](https://img.shields.io/badge/dependencies-up%20to%20date-brightgreen.svg)](https://github.com/milescsmith/plinkliftover/pulls?utf8=%E2%9C%93&q=is%3Apr%20author%3Aapp%2Fdependabot)
88

99
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
1010
[![Security: bandit](https://img.shields.io/badge/security-bandit-green.svg)](https://github.com/PyCQA/bandit)
11-
[![Pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/milescsmith/plinkliftover/blob/master/.pre-commit-config.yaml)
1211
[![Semantic Versions](https://img.shields.io/badge/%F0%9F%9A%80-semantic%20versions-informational.svg)](https://github.com/milescsmith/plinkliftover/releases)
1312
[![License](https://img.shields.io/github/license/milescsmith/plinkliftover)](https://github.com/milescsmith/plinkliftover/blob/master/LICENSE)
13+
![Alt](https://repobeats.axiom.co/api/embed/8d9c682229fb45f45eef3f300367eb33a44bd347.svg "Repobeats analytics image")
1414

15-
Awesome `plinkliftover` is a Python cli/package created with https://github.com/TezRomacH/python-package-template
15+
**PLINKLiftOver** is a utility enabling [liftOver](http://genome.ucsc.edu/cgi-bin/hgLiftOver)
16+
to work on genomics files from [PLINK](https://www.cog-genomics.org/plink/),
17+
allowing one to update the coordinates from one genome reference version to
18+
another.
1619

1720
</div>
18-
1921
## Installation
2022

23+
PLINKLiftOver requires
24+
* Python 3.8
25+
* The command line version of [liftOver](http://genome.ucsc.edu/cgi-bin/hgLiftOver),
26+
installed and on the system path
27+
* An appropriate [chain file](http://hgdownload.soe.ucsc.edu/downloads.html#liftover)
28+
* The [MAP file](https://zzz.bwh.harvard.edu/plink/data.shtml) from a PLINK
29+
dataset
30+
2131
```bash
2232
pip install -U plinkliftover
2333
```
2434

25-
or install with `Poetry`
35+
or install with the development version with
2636

2737
```bash
28-
poetry add plinkliftover
38+
pip install -U git+https://github.com/milescsmith/plinkliftover.git
2939
```
3040

31-
Then you can run
41+
## Usage
3242

3343
```bash
34-
plinkliftover --help
44+
Usage: plinkliftover [OPTIONS] MAPFILE CHAINFILE
45+
46+
Converts genotype data stored in plink's PED+MAP format from one genome
47+
build to another, using liftOver.
48+
49+
Arguments:
50+
MAPFILE The plink MAP file to `liftOver`. [required]
51+
CHAINFILE The location of the chain files to provide to `liftOver`.
52+
[required]
53+
54+
Options:
55+
--pedfile TEXT Optionally remove "unlifted SNPs" from the plink
56+
PED file after running `liftOver`.
57+
--datfile TEXT Optionally remove 'unlifted SNPs' from a data
58+
file containing a list of SNPs (e.g. for
59+
--exclude or --include in `plink`)
60+
--prefix TEXT The prefix to give to the output files.
61+
--liftoverexecutable TEXT The location of the `liftOver` executable.
62+
-v, --version Prints the version of the plinkliftover package.
63+
--help Show this message and exit.
3564
```
3665
66+
For example
67+
3768
```bash
38-
plinkliftover --name Roman
69+
plinkliftover updating.map hg19ToHg38.over.chain.gz
3970
```
4071
41-
or if installed with `Poetry`:
72+
### Note!
4273
43-
```bash
44-
poetry run plinkliftover --help
45-
```
74+
By default, [PLINK 2.0](https://www.cog-genomics.org/plink/2.0/) does not
75+
use/create the required MAP file. It can be generated using PLINK 1.9 by
4676
4777
```bash
48-
poetry run plinkliftover --name Roman
78+
plink --bfile original --recode --out to_update
4979
```
5080
51-
## 📈 Releases
52-
53-
You can see the list of available releases on the [GitHub Releases](https://github.com/milescsmith/plinkliftover/releases) page.
54-
55-
We follow [Semantic Versions](https://semver.org/) specification.
56-
57-
We use [`Release Drafter`](https://github.com/marketplace/actions/release-drafter). As pull requests are merged, a draft release is kept up-to-date listing the changes, ready to publish when you’re ready. With the categories option, you can categorize pull requests in release notes using labels.
58-
59-
For Pull Request this labels are configured, by default:
60-
61-
| **Label** | **Title in Releases** |
62-
| :-----------------------------------: | :---------------------: |
63-
| `enhancement`, `feature` | 🚀 Features |
64-
| `bug`, `refactoring`, `bugfix`, `fix` | 🔧 Fixes & Refactoring |
65-
| `build`, `ci`, `testing` | 📦 Build System & CI/CD |
66-
| `breaking` | 💥 Breaking Changes |
67-
| `documentation` | 📝 Documentation |
68-
| `dependencies` | ⬆️ Dependencies updates |
69-
70-
You can update it in [`release-drafter.yml`](https://github.com/milescsmith/plinkliftover/blob/master/.github/release-drafter.yml).
71-
72-
GitHub creates the `bug`, `enhancement`, and `documentation` labels for you. Dependabot creates the `dependencies` label. Create the remaining labels on the Issues tab of your GitHub repository, when you need them.
81+
where `original` is the prefix for the bed/bim/fam files and `to_update` is the prefix to give the new files.
7382
7483
## 🛡 License
7584

poetry.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ build-backend = "poetry.masonry.api"
66

77
[tool.poetry]
88
name = "plinkliftover"
9-
version = "0.1.11"
9+
version = "0.2.0"
1010
description = "Converts genotype data stored in plink's PED+MAP format from one genome build to another, using liftOver"
1111
readme = "README.md"
1212
authors = [
@@ -32,8 +32,7 @@ classifiers = [ # Update me
3232
"plinkliftover" = "plinkliftover.__main__:app"
3333

3434
[tool.poetry.dependencies]
35-
python = "^3.8"
36-
importlib_metadata = {version = "^3.4.0", python = "<3.8"}
35+
python = ">=3.8.3,<4.0"
3736
typer = "^0.4.0"
3837
rich = "^10.2.1"
3938
psutil = "^5.8.0"

src/plinkliftover/__init__.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
# type: ignore[attr-defined]
22
"""`plinkliftover` Converts genotype data stored in plink's PED+MAP format from one genome build to another, using liftOver"""
3-
try:
4-
from importlib.metadata import PackageNotFoundError, version
5-
except ImportError: # pragma: no cover
6-
from importlib_metadata import PackageNotFoundError, version
7-
3+
from importlib.metadata import PackageNotFoundError, version
84

95
try:
106
__version__ = version(__name__)

src/plinkliftover/__main__.py

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
from pathlib import Path
66

77
import typer
8-
from plinkliftover import __version__
9-
from plinkliftover.liftover import bed2map, liftBed, liftDat, liftPed, map2bed
10-
from plinkliftover.logger import plo_logger as logger
8+
from . import __version__
9+
from .liftover import bed2map, liftBed, liftDat, liftPed, map2bed
10+
from .logger import plo_logger as logger
1111
from rich.console import Console
1212

1313
app = typer.Typer(
@@ -66,9 +66,6 @@ def main(
6666
# Show usage message if user hasn't provided any arguments, rather
6767
# than giving a non-descript error message with the usage()
6868

69-
lifted_set = set()
70-
unlifted_set = set()
71-
7269
mapfile = Path(mapfile)
7370
oldbed = mapfile.with_suffix(".bed")
7471
map2bed(mapfile, oldbed)
@@ -94,14 +91,11 @@ def main(
9491
)
9592

9693
newbed = Path(f"{mapfile}.bed")
97-
# unlifted = Path(f"{prefix}.unlifted")
9894
lifted_set, unlifted_set, lb_status = liftBed(
9995
fin=oldbed,
10096
fout=newbed,
10197
chainfile=chainfile,
10298
liftOverPath=liftOverPath,
103-
unlifted_set=unlifted_set,
104-
lifted_set=lifted_set,
10599
)
106100

107101
if lb_status:

src/plinkliftover/liftover.py

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
from pathlib import Path
2424
from subprocess import check_output
2525

26-
from plinkliftover.logger import plo_logger as logger
26+
from .logger import plo_logger as logger
2727
from rich.console import Console
2828
from typer import progressbar
2929

@@ -36,10 +36,10 @@ def map2bed(fin: Path, fout: Path) -> bool:
3636
f"Converting [green]MAP[/] file [yellow]{fin.name}[/] file to [green]UCSC BED[/] file [blue]{fout.name}[/]..."
3737
)
3838
lines = fin.read_text().split("\n")
39-
output = []
39+
output = list()
4040
with progressbar(lines) as map_lines:
41-
for ln in map_lines:
42-
if len(x := ln.split()) == 4:
41+
for line in map_lines:
42+
if len(x := line.split()) == 4:
4343
chrom, rs, _, pos = x
4444
output.append(f"chr{chrom}\t{int(pos)-1}\t{int(pos)}\t{rs}")
4545
else:
@@ -53,8 +53,6 @@ def liftBed(
5353
fout: Path,
5454
chainfile: Path,
5555
liftOverPath: Path,
56-
unlifted_set: Set[str],
57-
lifted_set: Set[str],
5856
) -> Tuple[Set[str]]:
5957
console.print(f"Lifting [green]BED[/] file [blue]{fin.name}[/]...")
6058
params = {
@@ -70,18 +68,14 @@ def liftBed(
7068
unlifted_lines = Path(params["UNLIFTED"]).read_text().split("\n")
7169
console.print(f"Processing [red]unlifted[/] {fout.name}.unlifted")
7270
with progressbar(unlifted_lines) as unlifted:
73-
for ln in unlifted:
74-
if len(ln) == 0 or ln[0] == "#":
75-
continue
76-
unlifted_set.add(ln.strip().split()[-1])
71+
print("Using new set comprehension for 'unlifted_set'")
72+
unlifted_set = {ln.strip().split()[-1] for ln in unlifted if len(ln) > 0 and ln[0] != "#"}
7773

7874
console.print(f"Processing [red]new[/] {fout.name}")
7975
new_bed_lines = Path(params["NEW"]).read_text().split("\n")
8076
with progressbar(new_bed_lines) as new_bed:
81-
for ln in new_bed:
82-
if len(ln) == 0 or ln[0] == "#":
83-
continue
84-
lifted_set.add(ln.strip().split()[-1])
77+
print("Using new set comprehension for 'lifted_set'")
78+
lifted_set = {ln.strip().split()[-1] for ln in new_bed if len(ln) != 0 and ln[0] != "#"}
8579

8680
return lifted_set, unlifted_set, True
8781

@@ -91,7 +85,7 @@ def bed2map(fin: Path, fout: Path) -> bool:
9185
f"Converting lifted [green]BED[/] [blue]{fin.name}[/] file back to [green]MAP[/] [yellow]{fout.name}[/]..."
9286
)
9387
bed_lines = fin.read_text().split("\n")
94-
output = []
88+
output = list()
9589
with progressbar(bed_lines) as lines:
9690
for ln in lines:
9791
if len(x := ln.split()) == 4:
@@ -105,7 +99,7 @@ def bed2map(fin: Path, fout: Path) -> bool:
10599
def liftDat(fin: Path, fout: Path, lifted_set: Set[str]) -> bool:
106100
console.print(f"Updating [green]DAT[/] file [pink]{fin.name}[/]...")
107101
lines = fin.read_text().split("\n")
108-
output = []
102+
output = list()
109103
with progressbar(lines) as dat_lines:
110104
for ln in dat_lines:
111105
if len(ln) == 0 or ln[0] != "M":
@@ -133,12 +127,11 @@ def liftPed(
133127

134128
console.print(f"Updating [green]PED[/] file [orange]{fin.resolve()}[/]...")
135129
lines = fin.read_text().split("\n")
136-
output = []
130+
output = list()
137131
with progressbar(lines) as liftped_lines:
138132
for ln in liftped_lines:
139133
if ln.strip() != "":
140134
f = ln.strip().split()
141-
# l = len(f)
142135
f = f[:6] + [
143136
f[i * 2] + " " + f[i * 2 + 1] for i in range(3, len(f) // 2)
144137
]
@@ -151,7 +144,6 @@ def liftPed(
151144
a = "\t".join(f[:6])
152145
b = "\t".join(newmarker)
153146
output.append(f"{a}\t{b}\n")
154-
# print marker[:10]
155147
console.print(
156148
f"Writing new [green]PED[/] data to [light_slate_blue]{fout.resolve()}[/]"
157149
)

0 commit comments

Comments
 (0)