Giter Site home page Giter Site logo

haddocking / pdb-tools Goto Github PK

View Code? Open in Web Editor NEW
355.0 15.0 111.0 973 KB

A dependency-free cross-platform swiss army knife for PDB files.

Home Page: https://haddocking.github.io/pdb-tools/

License: Apache License 2.0

Python 99.83% TeX 0.17%
python protein pdb bioinformatics structural-biology structural-bioinformatics rcsb utrecht-university

pdb-tools's Introduction

pdb-tools

PyPI version PyPi Downloads tests DOI

A swiss army knife for manipulating and editing PDB files.

Looking for the other pdb-tools?

The Harms lab maintains a set of tools also called pdbtools, which perform a slightly different set of functions. You can find them here.

About

Manipulating PDB files is often painful. Extracting a particular chain or set of residues, renumbering residues, splitting or merging models and chains, or just ensuring the file is conforming to the PDB specifications are examples of tasks that can be done using any decent parsing library or graphical interface. These, however, almost always require 1) scripting knowledge, 2) time, and 3) installing one or more programs.

pdb-tools were designed to be a swiss-knife for the PDB format. They have no external dependencies, besides obviously the Python programming language. They are the descendant of a set of old FORTRAN77 programs that had the particular advantage of working with streams, i.e. the output of one script could be piped into another. Since FORTRAN77 is a pain too, I rewrote them in Python and added a few more utilities.

The philosophy of the scripts is simple: one script, one task. If you want to do two things, pipe the scripts together. Requests for new scripts will be taken into consideration - use the Issues button or write them yourself and create a Pull Request.

Installation Instructions

pdb-tools are available on PyPi and can be installed though pip. This is the recommended way as it makes updating/uninstalling rather simple:

pip install pdb-tools

Because we use semantic versioning in the development of pdb-tools, every bugfix or new feature results in a new version of the software that is automatically published on PyPI. As such, there is no difference between the code on github and the latest version you can install with pip. To update your installation to the latest version of the code run:

pip install --upgrade pdb-tools

What can I do with them?

The names of the tools should be self-explanatory. Their command-line interface is also pretty consistent. Therefore, here is a couple of examples to get you started:

  • Downloading a structure

    pdb_fetch 1brs > 1brs.pdb  # 6 chains
    pdb_fetch -biounit 1brs > 1brs.pdb  # 2 chains
  • Renumbering a structure

    pdb_reres -1 1ctf.pdb > 1ctf_renumbered.pdb
  • Selecting chain(s)

    pdb_selchain -A 1brs.pdb > 1brs_A.pdb
    pdb_selchain -A,D 1brs.pdb > 1brs_AD.pdb
  • Deleting hydrogens

    pdb_delelem -H 1brs.pdb > 1brs_noH.pdb
  • Selecting backbone atoms

    pdb_selatom -CA,C,N,O 1brs.pdb > 1brs_bb.pdb
  • Selecting chains, removing HETATM, and producing a valid PDB file

    pdb_selchain -A,D 1brs.pdb | pdb_delhetatm | pdb_tidy > 1brs_AD_noHET.pdb

Note: On Windows the tools will have the .exe extension.

What can't I do with them?

Operations that involve coordinates or numerical calculations are usually not in the scope of pdb-tools. Use a proper library for that, it will be much faster and scalable. Also, although we provide mmCIF<->PDB converters, we do not support large mmCIF files with more than 99999 atoms, or 9999 residues in a single chain. Our tools will complain if you try using them on such a molecule.

Citation

We finally decided to write up a small publication describing the tools. If you used them in a project that is going to be published, please cite us:

Rodrigues JPGLM, Teixeira JMC, Trellet M and Bonvin AMJJ.
pdb-tools: a swiss army knife for molecular structures. 
F1000Research 2018, 7:1961 (https://doi.org/10.12688/f1000research.17456.1) 

If you use a reference manager that supports BibTex, use this record:

@Article{ 10.12688/f1000research.17456.1,
AUTHOR = { Rodrigues, JPGLM and Teixeira, JMC and Trellet, M and Bonvin, AMJJ},
TITLE = {pdb-tools: a swiss army knife for molecular structures [version 1; peer review: 2 approved]
},
JOURNAL = {F1000Research},
VOLUME = {7},
YEAR = {2018},
NUMBER = {1961},
DOI = {10.12688/f1000research.17456.1}
}

Requirements

pdb-tools should run on Python 2.7+ and Python 3.x. We test on Python 2.7, 3.6, and 3.7. There are no dependencies.

Installing from Source

Download the zip archive or clone the repository with git. We recommend the git approach since it makes updating the tools extremely simple.

# To download
git clone https://github.com/haddocking/pdb-tools
cd pdb-tools

# To update
git pull origin master

# To install
python setup.py install

Contributing

If you want to contribute to the development of pdb-tools, provide a bug fix, or a new tools, read our CONTRIBUTING instructions here.

License

pdb-tools are open-source and licensed under the Apache License, version 2.0. For details, see the LICENSE file.

pdb-tools's People

Contributors

amjjbonvin avatar cunlianggeng avatar joaomcteixeira avatar joaorodrigues avatar mtrellet avatar rvanasa avatar rvhonorato avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pdb-tools's Issues

input PDB file

Hi! I am new using this tool. I just wanna know if a list of PDB IDs can be used as input file or I should use just one at time.

Thanks!!

pdb_deinsert

Insertions in the residue sequence with a numbering such as 100A, 100B, ... can be nasty for some programs. It would be nice to have a tool that will detect those and renumber sequentially the PDB file. pdb_reres will preserve the insertions.

pdb_selres should allow for selecting a unique residue

Describe the bug
When using the same residue ID as an argument, pdb_selres script returns the following error:
ERROR!! Start (11) cannot be larger than end (11)

To Reproduce

pdb_fetch.py 4G6K | pdb_selres -11:11
ERROR!! Start (11) cannot be larger than end (11)

Expected behavior
Residue(s) with ID 11 should be selected and returned

Desktop (please complete the following information):

  • OS: MacOSX Mojave 10.14.3
  • Python Version: all

Chain selection should be case-sensitive

Describe the bug
pdb_selchain (and maybe others, did not check) use str.upper when validating input and as such cannot be used to operate on lowercase chain names. Should be a simple fix.

To Reproduce

pdb_fetch.py 6zoj | pdb_selchain -e > model.pdb
cat result  # result is empty!

Update PyPI version

A user just reported #41 which is a duplicate from #39, meaning that updates in the master branch are not getting reflected directly in the PyPI package.

Please update the PyPI package with the new version. Because it is a fix without breaking backwards compatibility nor new feature addition, I propose next version number to be 2.0.1 to account for the PR #40 . As far as I can see this is the only PR accepted since 2.0.0 release.

pdb_delinsertion - naming is confusing

The naming of this tool is confusing (experience from users) because it implies that insertions are deleted. But this is not case since those are by default removed and the numbering adapted.

So a better naming could be: pdb_renuminsertion

pip install does not install LICENSE file

Describe the bug
After doing the recommended pip install, the LICENSE file is not installed

To Reproduce
pip install --target /tmp/example pdf-tools

Expected behavior
LICENSE should be found somewhere in /tmp/example

Desktop (please complete the following information):

  • Ubuntu 18.04
  • Python 2.7

pdb_validate.py output might not be to stderr

Describe the bug
This is not a bug itself, but the output of the validation, when it's not correct at all, writes to stderr the result of the warnings instead of the stdout. As long as the expected output of the tool is always valid, I will expect to output to stdout and not stderr.

To Reproduce

pdb_fetch.py 2oob | pdb_validate.py

Expected behavior
Any output should be to stdout.

Desktop (please complete the following information):

  • OS: Mac OS
  • Python Version 3.7

Keeping REMARKS field when generating ensembles

It would be nice to have an option to keep the pdb-specific REMARKS fields when generating an ensemble from single files with pdb_mkensemble. And also restore those when splitting such an ensemble.

Would be a handy feature to reduce for example the number of files in HADDOCK directories without loosing the information in the REMARKS fields.

New tools for protein, nucleic, carbo, ligands

Talking with @brianjimenez

We thought there could be four new tools to directly select for protein, nucleic, and carbohydrates, regardless of the chain where they sit. We could use the residue name identified for HADDOCK to perform the selection. For ligands, we could use the information in the PDB data bank; I already have files for that, and we could also do by negation.

These new tools could be named:

  • pdb_selprotein
  • pdb_selnucleic
  • pdb_selcarbo
  • pdb_selligands

Likewise, we could have the del version.

I am very mindful to the one-script-one-job philosophy, yet I think these scripts could enhance user experience without breaking the original philosophy.

What are your thoughts?

Behaviour in `selaltloc`

While working for haddocking/haddock3#144 I found that pdb_selaltloc is likely doing more than what it should. (Or maybe I am wrong).

pdb_selaltloc properly corrects for altLoc, but it also:

  • removes residues when residue numbers are repeated
  • removes insertions

I would like selaltloc to do just alternative locations. It would be easier if all altLocs had a letter in its right position for the PDB line. But, as we can see from the pdbtools test example, that is not the case:

ATOM 357 N ILE A 25 -9.702 -5.727 -16.084 0.61 4.36 N
ANISOU 357 N ILE A 25 520 465 672 33 -18 2 N
ATOM 358 CA ILE A 25 -9.340 -5.286 -17.428 0.61 4.45 C
ANISOU 358 CA ILE A 25 533 529 630 -6 -50 -5 C
ATOM 359 C ILE A 25 -8.471 -4.014 -17.377 0.61 4.39 C
ANISOU 359 C ILE A 25 478 580 609 -1 -12 -14 C
ATOM 360 O ILE A 25 -7.519 -3.868 -18.141 0.61 5.13 O
ANISOU 360 O ILE A 25 566 725 660 -65 86 -77 O
ATOM 376 N ALEU A 25 -9.706 -5.722 -16.071 0.99 4.68 N
ANISOU 376 N ALEU A 25 553 548 676 10 -26 -1 N
ATOM 377 CA ALEU A 25 -9.351 -5.281 -17.410 0.99 4.87 C
ANISOU 377 CA ALEU A 25 554 645 651 -35 -48 -28 C
ATOM 378 C ALEU A 25 -8.459 -4.039 -17.346 0.99 4.69 C
ANISOU 378 C ALEU A 25 518 645 621 -13 -18 -33 C
ATOM 379 O ALEU A 25 -7.460 -3.953 -18.055 0.99 5.25 O
ANISOU 379 O ALEU A 25 583 759 652 -28 45 -75 O

@JoaoRodrigues Can't we really rewrite selaltloc to rely only on altLoc and occupancy? Are there any edge cases that hinder this?

I wrote a mini-pdb-example demonstrating my point. You can run pdb_selaltloc on it. I would expect only residue 1 is corrected and nothing more.

Download it here -> wget https://pastebin.com/raw/KU3FxXF9 -O selaltloc_example.pdb

molprobity.py gives a TypeError

The bug
When I use the molprobity.py script to predict the His protonation states, it gives a TypeError (Python 3.9.4 on MacOS Catalina, 10.15.7):

## Executing Reduce to assign histidine protonation states
## Input PDB: e2aP2_1f3g-clean.pdb
Traceback (most recent call last):
File "/Users/jbibbe/software/haddock-tools/molprobity.py", line 143, in <module> fout.write(line+'\n')
TypeError: can't concat str to bytes

This same error also happens in Python 3.7.10.

When I use Python 2.7.13, I get the following error:

Traceback (most recent call last):
File "/Users/jbibbe/software/haddock-tools/molprobity.py", line 137, in <module> hadded, process_error = run_molprobity(open_fhandle)
File "/Users/jbibbe/software/haddock-tools/molprobity.py", line 69, in run_molprobity tmp_file.write(cmd_stdin)
TypeError: expected a string or other character buffer object

Quick fix
I fixed this for Python 3 by adding a line at line 138:
hadded = hadded.decode()
I haven’t tried to fix it for Python 2.7.13.

To Reproduce
molprobity.py file.pdb

Expected behavior
The script should return a list of the histidines in the protein structure, with their protonation states. Example:

## Executing Reduce to assign histidine protonation states
## Input PDB: 2J8S-renumbered-clean.pdb 
HIS ( 526 )	-->	HISD
HIS ( 1042 )	-->	HISD
HIS ( 2525 )	-->	HISD
HIS ( 4526 )	-->	HISD
HIS ( 338 )	-->	HISE
HIS ( 505 )	-->	HISE
HIS ( 525 )	-->	HISE

Desktop:

  • OS: MacOS Catalina (10.15.7)
  • Python Version: 3.9.4, 3.7.10 and 2.7.13.

pdb_delinsertion

Describe the bug
I found an example where pdb_delinsert fails to renumber residues properly.

To Reproduce

pdb_fetch.py 1FIW > 1FIW.pdb
pdb_delinsertion 1FIW.pdb > 1FIWdi.pdb

Now if you look for this particular region of the PDB results side by side (parsed|original):

   4 ATOM    192  N   ASN A  42      27.347  48.999  55.631  1.00 48.07  | 804 ATOM    192  N   ASN A  37E     27.347  48.999  55.631  1.00 48.07
   5 ATOM    193  CA  ASN A  42      27.379  47.849  56.520  1.00 47.93  | 805 ATOM    193  CA  ASN A  37E     27.379  47.849  56.520  1.00 47.93
   6 ATOM    194  C   ASN A  42      28.507  47.861  57.542  1.00 47.95  | 806 ATOM    194  C   ASN A  37E     28.507  47.861  57.542  1.00 47.95
   7 ATOM    195  O   ASN A  42      28.776  46.838  58.158  1.00 47.97  | 807 ATOM    195  O   ASN A  37E     28.776  46.838  58.158  1.00 47.97
   8 ATOM    196  CB  ASN A  42      27.457  46.565  55.699  1.00 48.23  | 808 ATOM    196  CB  ASN A  37E     27.457  46.565  55.699  1.00 48.23
   9 ATOM    197  CG  ASN A  42      28.679  46.532  54.799  1.00 49.30  | 809 ATOM    197  CG  ASN A  37E     28.679  46.532  54.799  1.00 49.30
  10 ATOM    198  OD1 ASN A  42      28.735  45.785  53.819  1.00 49.23  | 810 ATOM    198  OD1 ASN A  37E     28.735  45.785  53.819  1.00 49.23
  11 ATOM    199  ND2 ASN A  42      29.652  47.383  55.105  1.00 46.68  | 811 ATOM    199  ND2 ASN A  37E     29.652  47.383  55.105  1.00 46.68
  12 ATOM    200  N   ASN A  42      29.131  49.027  57.731  1.00 47.02  | 812 ATOM    200  N   ASN A  37F     29.131  49.027  57.731  1.00 47.02
  13 ATOM    201  CA  ASN A  42      30.270  49.222  58.620  1.00 45.87  | 813 ATOM    201  CA  ASN A  37F     30.270  49.222  58.620  1.00 45.87
  14 ATOM    202  C   ASN A  42      31.421  48.278  58.483  1.00 42.93  | 814 ATOM    202  C   ASN A  37F     31.421  48.278  58.483  1.00 42.93
  15 ATOM    203  O   ASN A  42      32.113  48.092  59.431  1.00 40.20  | 815 ATOM    203  O   ASN A  37F     32.113  48.092  59.431  1.00 40.20
  16 ATOM    204  CB  ASN A  42      29.920  49.170  60.087  1.00 48.11  | 816 ATOM    204  CB  ASN A  37F     29.920  49.170  60.087  1.00 48.11
  17 ATOM    205  CG  ASN A  42      28.801  50.098  60.452  1.00 52.88  | 817 ATOM    205  CG  ASN A  37F     28.801  50.098  60.452  1.00 52.88
  18 ATOM    206  OD1 ASN A  42      28.709  51.223  59.955  1.00 55.93  | 818 ATOM    206  OD1 ASN A  37F     28.709  51.223  59.955  1.00 55.93
  19 ATOM    207  ND2 ASN A  42      27.927  49.637  61.337  1.00 57.46  | 819 ATOM    207  ND2 ASN A  37F     27.927  49.637  61.337  1.00 57.46

You will see that it fails to separate those two asparagines. I haven't scan the whole 1FIW but other residues seem working.

Desktop (please complete the following information):

  • OS: Linux (always)
  • Python Version 3.7
  • pdb-tools version: 2.0.4 23fd473

`pdb_fixinsert` and its impact on numbering

Hello

I came across pdb_fixinsert and just wanted to confirm that my understanding of its operation is correct before I start using it more systematically.

The tool's help mentions that it "works by deleting an insertion code and shifting the residue numbering of downstream residues". Although "delete" appears here, the tool does not actually delete anything. Rather, it seems to be renaming the insertion code residue so that it disappears. So, in the case of 1,2,3,4,5,5A,6,7,8,9,10,.... it would turn it to 1,2,3,4,5,6,7,8,9,10,11,.... With 6 now being the 5A, 7 being the 6 and so on.

The number of residues does not change. The total number of lines (between the original and processed through pdb_fixinsert) does not change.

Is there a specific use case that pdb_fixinsert addresses and is the interpretation of the insertion codes context specific? My understanding from looking up more about the interpretation of insertion codes was that they encode more than one pieces of information: The position of the residue (and which residue it is) but also what else might appear in that index on the same molecule but a different species. I was therefore looking for a way to decouple these two pieces of information. Therefore, coming across pdb_fixinsert's description, I thought that it was going to remove those residues with insertion codes in a better way (than just deleting them).....but it only seems to renumber them.

Any help with this would be greatly appreciated.

Migrate to GitHub Actions

Talking to @JoaoRodrigues, we decided it is about time to migrate the CI to GitHub actions.

I have recently updated my python-skeleton-template to the latest GitHub Actions dev/deploy. Actually, some of my workflows are updates from the workflows of pdb-tools, especially the FEATURE and SKIP tags on commit, which are really cool 🕶️

@JoaoRodrigues and I will PR on this in the next few days.

Comments/suggestions?

pdb_reatom misaligning with TER lines

Describe the bug
I'm using pdb_reatom and in PDBs which don't have anything on TER lines except the TER statement. The reatoming prints the atom number on the line below the TER line.

ATOM   1761  C2   DG C  54      -4.483   5.846  44.656  1.00 19.29           C
ATOM   1762  N2   DG C  54      -5.602   6.488  44.306  1.00 19.87           N
ATOM   1763  N3   DG C  54      -3.587   5.523  43.715  1.00 19.53           N
ATOM   1764  C4   DG C  54      -2.495   4.892  44.221  1.00 19.98           C
TER
 1765ATOM   1766  P    DC C  55       0.470   6.191  38.221  1.00 32.28           P
ATOM   1767  OP1  DC C  55       0.309   5.296  37.053  1.00 35.01           O

I just read the PDB guidelines on what the TER line should look like and I now know that it's supposed to have the res name and info preceding it in the line. But I'm also using software to modify the PDBs and after checking the PDBs produced by two of them (PYMOL and RING2.0), both are producing PDBs with TER and nothing else in TER lines.

I changed the script to be below and it fixed the problem for me.

elif line.startswith('TER'):
            yield line[:6]
            serial += 1

Now I know the empty TER lines aren't proper PDB format I don't know if you want to change your script or not but thought I'd report the behaviour anyway.

Desktop (please complete the following information):

  • OS: Mac OS
  • Python Version 3.7

Distances reported in pdb_gap are squared

The distances reported in pdb_gap are actually squared distances. I wrote the code to evaluate the square euclidean distance to avoid calculating the sqrt all the time but forgot to do it once it actually finds a gap. As a result, the numbers reported might be a bit mind-boggling for users ... (e.g. 30A become 900A).

Not critical, but I should take care of this sometime soon, also correct the unit test.

Implement `pdb_selmodel`

Is your tool request related to a problem? Please describe.
When we have a multi-model ensemble we need to use pdb_splitmodel and then (in disk) find the appropriate model we want.

Describe the solution you'd like
pdb_selmodel would select a given MODEL in a ensemble or a range of models:

$ pdb_selmodel -1 1ccm.pdb
$ pdb_selmodel -1:5 1ccm.pdb

In case the input is not an ensemble it could instead just return the same pdb instead of an error, then it would not break any pipelines.

Does any of the existing tools or a combination of them do what you want?
No, but pdb_splitmodel + scripting does the trick.

Remove REMARK and general info lines

I found myself today removing the REMARK and info lines manually from a series of PDB files.

Should there be a pdb_delinfo.py tool that keeps only lines from coordinates and connectivity ? If you agree, assign me for the task.

Add option to pdb_tidy to only add TER between different chains

By default pdb_tidy adds TER statement for every break, within or between chains.

This might not always be desirable. Between chains is in principle always OK, but within the same chain not.
E.g. missing density in X-ray structures result in missing residues, but the gaps do not contain TER statements.

Those additional TER statement might cause third party software to handle those are real termini and add for example charges...

Execution of setup.py fails after any execution of "python setup.py test" with python2.7

Describe the bug
With python2.7, when using python setup.py test to run the unit tests, *.pyc files are created in the pdbtools/ directory. Any new execution of python setup.py option fails with the following error:

→ python setup.py test
error in pdb-tools setup command: ('Invalid module name', 'pdbtools.pdb_keepcoord.')

This only happens with python2.7 because python3.2+ is now storing those compiled files into a __pycache__ directory.

To Reproduce
Steps to reproduce the behavior. Preferrably, a code snippet.

→ python setup.py test
running test
running egg_info
writing pdb_tools.egg-info/PKG-INFO
writing top-level names to pdb_tools.egg-info/top_level.txt
writing dependency_links to pdb_tools.egg-info/dependency_links.txt
writing entry points to pdb_tools.egg-info/entry_points.txt
reading manifest file 'pdb_tools.egg-info/SOURCES.txt'
writing manifest file 'pdb_tools.egg-info/SOURCES.txt'
running build_ext
test_file_not_found (test_pdb_tocif.TestTool)
$ pdb_tocif not_existing.pdb ... ok
test_helptext (test_pdb_tocif.TestTool)
$ pdb_tocif ... ok
...
→ python setup.py test
error in pdb-tools setup command: ('Invalid module name', 'pdbtools.pdb_keepcoord.')

Expected behavior
Any new call to setup.py should be successful and build, install or test again successfully.

Desktop (please complete the following information):

  • OS: * MacOSX Mojave 10.14.3
  • Python Version: 2.7 only

Behaviour of `pdb_selres`

Describe the bug

pdb_selres does not seem to handle TER records correctly, as it tries to read a residue ID from that line, which usually does not exist.

To Reproduce

Here's a simple PDB file with 3 residues (generated by pdb_splitmodel):

ATOM      1  N   MET     1      88.820 110.610  35.000  1.00  0.00           N
ATOM      2  H1  MET     1      89.440 110.390  34.230  1.00  0.00           H
ATOM      3  H2  MET     1      88.400 109.720  35.230  1.00  0.00           H
ATOM      4  H3  MET     1      88.080 111.180  34.620  1.00  0.00           H
ATOM      5  CA  MET     1      89.410 111.440  36.040  1.00  0.00           C
ATOM      6  HA  MET     1      90.140 110.860  36.600  1.00  0.00           H
ATOM      7  CB  MET     1      90.100 112.650  35.480  1.00  0.00           C
ATOM      8  HB1 MET     1      90.510 113.180  36.340  1.00  0.00           H
ATOM      9  HB2 MET     1      89.370 113.290  34.970  1.00  0.00           H
ATOM     10  CG  MET     1      91.360 112.190  34.580  1.00  0.00           C
ATOM     11  HG1 MET     1      90.960 111.610  33.750  1.00  0.00           H
ATOM     12  HG2 MET     1      92.050 111.550  35.130  1.00  0.00           H
ATOM     13  SD  MET     1      92.140 113.680  33.900  1.00  0.00           S
ATOM     14  CE  MET     1      90.970 114.080  32.520  1.00  0.00           C
ATOM     15  HE1 MET     1      91.180 113.430  31.670  1.00  0.00           H
ATOM     16  HE2 MET     1      89.950 113.980  32.920  1.00  0.00           H
ATOM     17  HE3 MET     1      91.180 115.130  32.320  1.00  0.00           H
ATOM     18  C   MET     1      88.240 111.850  36.910  1.00  0.00           C
ATOM     19  O   MET     1      87.340 112.580  36.460  1.00  0.00           O
ATOM     20  N   SER     2      88.210 111.490  38.240  1.00  0.00           N
ATOM     21  H   SER     2      89.070 111.170  38.660  1.00  0.00           H
ATOM     22  CA  SER     2      87.080 111.510  39.150  1.00  0.00           C
ATOM     23  HA  SER     2      86.440 112.270  38.690  1.00  0.00           H
ATOM     24  CB  SER     2      86.330 110.190  39.160  1.00  0.00           C
ATOM     25  HB1 SER     2      86.200 109.900  38.110  1.00  0.00           H
ATOM     26  HB2 SER     2      85.400 110.380  39.690  1.00  0.00           H
ATOM     27  OG  SER     2      87.050 109.250  39.940  1.00  0.00           O
ATOM     28  HG  SER     2      86.460 108.980  40.660  1.00  0.00           H
ATOM     29  C   SER     2      87.350 112.030  40.610  1.00  0.00           C
ATOM     30  O   SER     2      86.340 112.090  41.310  1.00  0.00           O
ATOM     31  N   VAL     3      88.520 112.490  41.030  1.00  0.00           N
ATOM     32  H   VAL     3      89.340 112.490  40.440  1.00  0.00           H
ATOM     33  CA  VAL     3      88.810 112.900  42.440  1.00  0.00           C
ATOM     34  HA  VAL     3      88.050 112.530  43.120  1.00  0.00           H
ATOM     35  CB  VAL     3      90.170 112.290  42.880  1.00  0.00           C
ATOM     36  HB  VAL     3      90.240 112.470  43.950  1.00  0.00           H
ATOM     37  CG1 VAL     3      90.300 110.780  42.690  1.00  0.00           C
ATOM     38 1HG1 VAL     3      89.930 110.380  41.750  1.00  0.00           H
ATOM     39 2HG1 VAL     3      91.330 110.460  42.830  1.00  0.00           H
ATOM     40 3HG1 VAL     3      89.790 110.330  43.550  1.00  0.00           H
ATOM     41  CG2 VAL     3      91.310 112.920  42.070  1.00  0.00           C
ATOM     42 1HG2 VAL     3      92.300 112.640  42.410  1.00  0.00           H
ATOM     43 2HG2 VAL     3      91.250 112.810  40.990  1.00  0.00           H
ATOM     44 3HG2 VAL     3      91.280 114.000  42.250  1.00  0.00           H
ATOM     45  C   VAL     3      88.770 114.420  42.520  1.00  0.00           C
ATOM     46  O   VAL     3      88.910 115.210  41.610  1.00  0.00           O
TER
pdb_selres -1:2 foo.pdb

gives:

Traceback (most recent call last):
  File "/home/tianyi/miniconda3/bin/pdb_selres", line 8, in <module>
    sys.exit(main())
  File "/home/tianyi/miniconda3/lib/python3.9/site-packages/pdbtools/pdb_selres.py", line 249, in main
    pdbfh, resrange = check_input(sys.argv[1:])
  File "/home/tianyi/miniconda3/lib/python3.9/site-packages/pdbtools/pdb_selres.py", line 188, in check_input
    resid_list.append(int(line[22:26]))
ValueError: invalid literal for int() with base 10: ''

Expected behavior

Should select residues 1 and 2.

Desktop (please complete the following information):

  • OS: Ubuntu 20.04.3 LTS
  • Python Version: 3.9.5

Doesn't work if a chain ID is lowercase when you remove HETATM

Hello, thanks for your tools to the community. However, it doesn't really work if a chain ID is written in lowercase when you remove HETATM, like 'a', not 'A'. However, this pdb-tools will try to find the letter 'A'., and delete everything about 'a' and finally return you an empty file.

Improve documentation updates

Currently we have to manually update the documentation (web page) to reflect the tools. It would be nice to automate this with a github action. Any volunteers? :) @mtrellet

pdb_selatlloc fails on single locs

When using pdb_selatlloc to select a loc that is unique, for example, select A where there is nothing else than A, pdb_selaltloc fails.

to reproduce:

pdb_fetch 3u7t | pdb_keepcoord | pdb_selatom -CA,C,N,O | pdb_delresname -HOH | pdb_selaltloc -A | pdb_delinsertion | pdb_reatom -1 | pdb_tidy > 3u7tBB.pdb

On the other hand, this works:

pdb_fetch 3u7t | pdb_keepcoord | pdb_selatom -CA,C,N,O | pdb_delresname -HOH | pdb_selaltloc | pdb_delinsertion | pdb_reatom -1 | pdb_tidy > 3u7tBB.pdb

The problem is in these lines:

   ATOM     85  N  ASER A  22     -14.282  -3.023 -15.571  0.53  4.57           N·· 
   ATOM     86  CA ASER A  22     -13.829  -3.816 -14.436  0.53  5.30           C·· 
   ATOM     87  C  ASER A  22     -12.365  -3.540 -14.113  0.53  4.77           C·· 
   ATOM     88  O  ASER A  22     -11.531  -3.326 -15.003  0.53  5.44           O·· 
   ATOM     89  N  BPRO A  23     -14.305  -3.040 -15.563  0.47  5.18           N·· 
   ATOM     90  CA BPRO A  23     -13.801  -3.851 -14.452  0.47  5.29           C·· 
   ATOM     91  C  BPRO A  23     -12.344  -3.583 -14.119  0.47  4.84           C·· 
   ATOM     92  O  BPRO A  23     -11.499  -3.414 -15.007  0.47  5.37           O·· 

Handling CONECT entries

A user suggested:

Remove obviously incorrect CONECT records.

We have discussed the possibility to remove all CONECT lines directly because assessing this requires knowing the chemical structure of the molecule, as you have said in our discussions. But also we can keep the CONECT related to S-S bonds easily in case of ATOM entries, on the other hand.

For HETATM entries, there are to main problems identified, from https://www.wwpdb.org/documentation/file-format-content/format33/sect10.html:

Known Problems

CONECT records involving atoms for which the coordinates are not present in the entry (e.g., symmetry-generated) are not given.

CONECT records involving atoms for which the coordinates are missing due to disorder, are also not provided.

Some questions

@JoaoRodrigues @amjjbonvin @brianjimenez @mtrellet

  1. Should we remove all CONECT entries?
  2. Should we remove only those belonging to absent atom serials?
  3. Should we keep at least the S-S bonds for ATOM entries?
  4. should pdb_tidy handle this or a new tool instead?

RFE: enhance pdb_selres to allow selection of random residue list

Is your tool request related to a problem? Please describe.
I would like to select any list of residue from a pdb file.

Describe the solution you'd like

pdb_selres 1,10,43,8 my.pdb would ouput the 1,8,10 and 43rd residues from the pdb file.

Does any of the existing tools or a combination of them do what you want?
I can iterate with pdb_selres and extract each number in loop and concatenate the resulting output files

Remember
Each pdb-tools should do one and one job only. If you have to describe what you want using an and, probably it is the job for at least two tools. We want simple tools that can be combined, for flexibility.

pdb_canonical: converting modified aminoacids to their standard counterparts

Is your tool request related to a problem? Please describe.
PDB files often have modified/nonstandard residues (e.g. MSE) that are labeled as HETATM in the middle of the sequence. These are not accepted by many modeling tools.

Describe the solution you'd like
It would be interesting to have a tool to replace them by the canonical versions (e.g. MSE -> MET) and remove the extra atoms.

Does any of the existing tools or a combination of them do what you want?
No.

sub commands?

This is a great set of tools but have you considered doing sub commands i.e. pdb_tools seg instead of pdb_seg. I understand the idea of what you are trying to do but I have other PDB related tools and this package pollutes the env a lot

image

Issue with doctools.py

Describe the bug
Was finished working on a new tool proposal. Went to run doctools.py to update documentation. The script does not run and I get different error messages for python and python3. I checked that this is not a package import issue in either version.

To Reproduce
Steps to reproduce the behavior. Preferrably, a code snippet.

$ python doctools.py

  File "doctools.py", line 13
    print(template.read(), file=handle)
                               ^
SyntaxError: invalid syntax

----------------------------------------------------------------

$ python3 doctools.py

  File "doctools.py", line 25
    tool = importlib.import_module(f'pdbtools.{name}')
                                                    ^
SyntaxError: invalid syntax

Expected behavior
This file should execute and update documentation.

Desktop (please complete the following information):

  • OS: Ubuntu 16.04 LTS
  • Python Version: 2.7.12, 3.5.2

A rare case for pdb_delinsertion

Today I found another curious case for pdb_delinsertion. I don't call it a bug but, instead, a case not considered yet.

PDB ID: 1MH1

In this pdb there are two residues at the beginning that belong to the purification tag and are assigned are insertions. The chain is continuous, there are no backbone breaks.

ATOM      1  N   GLY A   1A     25.689  14.213  13.354  1.00 30.45           N··  
ATOM      2  CA  GLY A   1A     25.987  15.432  12.550  1.00 26.96           C··  
ATOM      3  C   GLY A   1A     25.765  16.621  13.483  1.00 25.19           C··  
ATOM      4  O   GLY A   1A     25.854  16.429  14.700  1.00 26.24           O··  
ATOM      5  N   SER A   2A     25.502  17.796  12.939  1.00 23.20           N··  
ATOM      6  CA  SER A   2A     25.239  18.997  13.759  1.00 18.18           C··  
ATOM      7  C   SER A   2A     23.808  19.423  13.540  1.00 16.47           C··  
ATOM      8  O   SER A   2A     23.127  19.047  12.551  1.00 16.08           O··  
ATOM      9  CB  SER A   2A     26.204  20.107  13.368  1.00 20.97           C··  
ATOM     10  OG  SER A   2A     27.450  19.508  13.038  1.00 25.16           O··  
ATOM     11  N   PRO A   1      23.223  20.197  14.441  1.00 12.21           N··  
ATOM     12  CA  PRO A   1      21.881  20.749  14.227  1.00 11.37           C··  
ATOM     13  C   PRO A   1      21.929  21.556  12.903  1.00 10.73           C··  
ATOM     14  O   PRO A   1      22.872  22.308  12.668  1.00 12.80           O··  
ATOM     15  CB  PRO A   1      21.641  21.649  15.437  1.00 10.87           C··  
ATOM     16  CG  PRO A   1      22.595  21.065  16.473  1.00 11.96           C··  
ATOM     17  CD  PRO A   1      23.844  20.738  15.680  1.00 12.56           C··  
ATOM     18  N   GLN A   2      20.920  21.358  12.090  1.00 10.01           N··  
ATOM     19  CA  GLN A   2      20.848  22.096  10.790  1.00 10.36           C··  
ATOM     20  C   GLN A   2      20.523  23.577  11.104  1.00  9.48           C··  
ATOM     21  O   GLN A   2      19.483  23.784  11.751  1.00  9.88           O··  
ATOM     22  CB  GLN A   2      19.839  21.439   9.860  1.00  9.46           C··  
ATOM     23  CG  GLN A   2      19.997  22.014   8.451  1.00 10.39           C··  
ATOM     24  CD  GLN A   2      19.124  21.359   7.433  1.00 11.31           C··  
ATOM     25  OE1 GLN A   2      18.853  20.153   7.480  1.00 11.96           O··  
ATOM     26  NE2 GLN A   2      18.609  22.130   6.468  1.00 10.45           N··  

applying the latest (v.2.0.5) for pdb_delinsertion, yields:

ATOM      1  N   GLY A   1      25.689  14.213  13.354  1.00 30.45           N··  
ATOM      2  CA  GLY A   1      25.987  15.432  12.550  1.00 26.96           C··  
ATOM      3  C   GLY A   1      25.765  16.621  13.483  1.00 25.19           C··  
ATOM      4  O   GLY A   1      25.854  16.429  14.700  1.00 26.24           O··  
ATOM      5  N   SER A   2      25.502  17.796  12.939  1.00 23.20           N··  
ATOM      6  CA  SER A   2      25.239  18.997  13.759  1.00 18.18           C··  
ATOM      7  C   SER A   2      23.808  19.423  13.540  1.00 16.47           C··  
ATOM      8  O   SER A   2      23.127  19.047  12.551  1.00 16.08           O··  
ATOM      9  CB  SER A   2      26.204  20.107  13.368  1.00 20.97           C··  
ATOM     10  OG  SER A   2      27.450  19.508  13.038  1.00 25.16           O··  
ATOM     11  N   PRO A   2      23.223  20.197  14.441  1.00 12.21           N··  
ATOM     12  CA  PRO A   2      21.881  20.749  14.227  1.00 11.37           C··  
ATOM     13  C   PRO A   2      21.929  21.556  12.903  1.00 10.73           C··  
ATOM     14  O   PRO A   2      22.872  22.308  12.668  1.00 12.80           O··  
ATOM     15  CB  PRO A   2      21.641  21.649  15.437  1.00 10.87           C··  
ATOM     16  CG  PRO A   2      22.595  21.065  16.473  1.00 11.96           C··  
ATOM     17  CD  PRO A   2      23.844  20.738  15.680  1.00 12.56           C··  
ATOM     18  N   GLN A   4      20.920  21.358  12.090  1.00 10.01           N··  
ATOM     19  CA  GLN A   4      20.848  22.096  10.790  1.00 10.36           C··  
ATOM     20  C   GLN A   4      20.523  23.577  11.104  1.00  9.48           C··  
ATOM     21  O   GLN A   4      19.483  23.784  11.751  1.00  9.88           O··  
ATOM     22  CB  GLN A   4      19.839  21.439   9.860  1.00  9.46           C··  
ATOM     23  CG  GLN A   4      19.997  22.014   8.451  1.00 10.39           C··  
ATOM     24  CD  GLN A   4      19.124  21.359   7.433  1.00 11.31           C··  
ATOM     25  OE1 GLN A   4      18.853  20.153   7.480  1.00 11.96           O··  
ATOM     26  NE2 GLN A   4      18.609  22.130   6.468  1.00 10.45           N··  

pdb_reres removes the MODEL tag from multi-model PDB files

Describe the bug
When working on an NMR structure with pdb-tools, the usage of pdb_reres causes an error in pdb_splitmodel afterwards. Looking at the PDB files, it seems that pdb_reres removes the MODEL tag during the renumbering, thereby causing the error in pdb_splitmodel.

To Reproduce
This causes an error in pdb_splitmodels

pdb_fetch.py 2MSE | pdb_tidy.py | pdb_selchain.py -D | pdb_reres.py -1 > 2MSE_reres.pdb
pdb_splitmodel.py 2MSE_reres.pdb 
Traceback (most recent call last):
  File "/usr/local/bin/pdb_splitmodel", line 8, in <module>
    sys.exit(main())
  File "/usr/local/lib/python3.6/dist-packages/pdbtools/pdb_splitmodel.py", line 103, in main
    split_model(pdbfh)
  File "/usr/local/lib/python3.6/dist-packages/pdbtools/pdb_splitmodel.py", line 91, in split_model
    fh.write(''.join(model_lines))
UnboundLocalError: local variable 'fh' referenced before assignment

Not using pdb_reres does not cause an error:

pdb_fetch.py 2MSE | pdb_tidy.py | pdb_selchain.py -D > 2MSE_orgres.pdb
pdb_splitmodel.py 2MSE_orgres.pdb 

Looking at the pdb files, it seems that pdb_reres removes the MODEL tag in the pdb file.
Without renumbering:

grep "MODEL" 2MSE_orgres.pdb
TITLE     NMR DATA-DRIVEN MODEL OF GTPASE KRAS-GNP:ARAFRBD COMPLEX TETHERED TO A
REMARK 210  SPECTROMETER MODEL             : AVANCE                             
REMARK 465   MODELS 1-10                                                        
REMARK 500 (M=MODEL NUMBER; RES=RESIDUE NAME; C=CHAIN IDENTIFIER;               
MODEL        1                                                                  
MODEL        2                                                                  
MODEL        3                                                                  
MODEL        4                                                                  
MODEL        5                                                                  
MODEL        6                                                                  
MODEL        7                                                                  
MODEL        8                                                                  
MODEL        9                                                                  
MODEL       10                                                                  

With renumbering, the MODEL tags are gone.

grep "MODEL" 2MSE_reres.pdb
TITLE     NMR DATA-DRIVEN MODEL OF GTPASE KRAS-GNP:ARAFRBD COMPLEX TETHERED TO A
REMARK 210  SPECTROMETER MODEL             : AVANCE                             
REMARK 465   MODELS 1-10                                                        
REMARK 500 (M=MODEL NUMBER; RES=RESIDUE NAME; C=CHAIN IDENTIFIER;               

This behaviour could be reproduced with different PDB files containing multiple models.

Expected behavior
pdb_reres is not expected to remove the model tags.

Desktop (please complete the following information):

  • OS: Linux (Ubuntu 18.04)
  • Python Version 3.6
  • pdb-tools: 2.0.5

pdb_selchain is not able to extract a chain with lowercase chain ID when the uppercase is present

Description
When running pdb_selchain on a PDB file containing both uppercase chain IDs and lowercase chain IDs and trying to exctract only a chain with a lowercase ID, pdb_selchain will instead extract the chain with the uppercase ID character.

To Reproduce
Sample pdb: 4L29.pdb
Output: 4L29_m.pdb will have only chain 'M'

pdb_selchain -m 4L29.pdb > 4L29_m.pdb

Expected behavior
The output file should have only chain 'm' (lowercase), not chain 'M' (uppercase).

Desktop:

  • OS: Mac OS
  • Python Version: 2.7

Add chain IDs on missing chains with TER

Dear developers,

A user has requested that sequential chain IDs are added on PDBs that have TER statements delimiting chains but lack chain IDs. My question is on which tool should this be implemented. Initially, I thought about pdb_tidy but now I think that would grant too much power to tidy. Should a new one be created, pdb_completechains?

@JoaoRodrigues @brianjimenez @amjjbonvin @mtrellet

`pdb_tidy` does not correct `MODEL` records

Describe the bug
When running pdb_tidy on a PDB in which the MODEL record is incorrectly formatted (wrong position of the model identifier) it is not corrected. We identified this on haddocking/haddock3#221

To Reproduce
Using this PDB

$ less incorrect_model.pdb
MODEL 1
ATOM      1  N   ASP     1      -0.610  -1.825  -0.630  1.00 15.00      B
ATOM      2  HN  ASP     1      -0.690  -2.310  -1.478  1.00 15.00      B
ATOM      3  CA  ASP     1      -0.051  -0.476  -0.630  1.00 15.00      B
ATOM      4  CB  ASP     1      -0.586   0.337   0.582  1.00 15.00      B
ATOM      5  CG  ASP     1      -0.126   1.802   0.652  1.00 15.00      B
ATOM      6  OD1 ASP     1      -0.007   2.453  -0.406  1.00 15.00      B
ATOM      7  OD2 ASP     1       0.165   2.283   1.767  1.00 15.00      B
ATOM      8  C   ASP     1       1.360  -0.472  -0.590  1.00 15.00      B
ATOM      9  O   ASP     1       2.096  -1.275  -1.374  1.00 15.00      B
$ pdb_tidy incorrect_model.pdb 
MODEL 1                                                                         
ATOM      1  N   ASP     1      -0.610  -1.825  -0.630  1.00 15.00      B       
ATOM      2  HN  ASP     1      -0.690  -2.310  -1.478  1.00 15.00      B       
ATOM      3  CA  ASP     1      -0.051  -0.476  -0.630  1.00 15.00      B       
ATOM      4  CB  ASP     1      -0.586   0.337   0.582  1.00 15.00      B       
ATOM      5  CG  ASP     1      -0.126   1.802   0.652  1.00 15.00      B       
ATOM      6  OD1 ASP     1      -0.007   2.453  -0.406  1.00 15.00      B       
ATOM      7  OD2 ASP     1       0.165   2.283   1.767  1.00 15.00      B       
ATOM      8  C   ASP     1       1.360  -0.472  -0.590  1.00 15.00      B       
ATOM      9  O   ASP     1       2.096  -1.275  -1.374  1.00 15.00      B

Expected behavior

MODEL 1

be changed to

MODEL        1

Desktop (please complete the following information):

$ pip show pdb-tools
Name: pdb-tools
Version: 2.4.1
(...)

Coot can't open the output file of pdb_merge

pdb_merge a.pdb b.pdb ... > output.pdb
pdb_merge a.pdb b.pdb ... | pdb_tidy > output.pdb

I generated the output.pdb file like above(url of file: https://drive.google.com/file/d/1INUdZfA8dEoe40k0v4IA32iFHwI_JRno/view?usp=sharing)
When I tried to open output.pdb using coot, it only showed the content of a.pdb file above. Howerver when I used Chimera, it showed the content of output.pdb. Next I saved the output.pdb file in chimera to another file (url of file: https://drive.google.com/file/d/1lpY40CnG3mXGZiXwQ96IBeNWYMN3Rkhd/view?usp=sharing). When opening it by coot, the content of output.pdb was shown.

I want to know how to generate file that can be used in coot by using this tool directly.
Thanks in advance.

Coot version: 0.9.3

enhancement of pdb_wc

After #51, we can consider increasing the detail of the pdb_wc report to enhance the user experience of both the command-line user as well as the pdb-tools web interface @brianjimenez is developing.

If I recall properly, we discussed altogether in the emails that pdb_wc could also report, for example, on the chain IDs, residue number ranges and atom ranges. This would facilitate the interaction of the user with the other tools such as pdb_chain.

I take no full credit for this idea, I am just registering an idea discussed by all which I found really interesting.

@brianjimenez how could this be integrated in the web interface? Do you find it useful for pdb_wc to do this? Or should it be another tool to do it?

I can take this if you all agree with the implementation.

What happened to the old `pdb_delocc` tool?

In the previous version we had the pdb_delocc tool that was removing double occupancies, keeping only the first instance. Did we lost it?

We have been advertising in the HADDOCK forum as a solution for double occupancies that raise an error on the server.

pdb-deinsertion renumbers chains without insertion codes

The pdb-deinsert tool works nicely but it seems that it affects chains beyond the one with the insertion code. I have an antibody antigen complex where I'm trying to remove the insertion codes for the antibody. The antibody chains are A and B. The antigen sequence numbering starts at C 1391. After removing insertion codes the antigen now starts at C 1396. The antigen should be unaffected by this operation. Thanks for a very handy tool....

Ligand selection command

I am currently attempting to implement pdb-tools into protocol at my institution so that there is less need for text editors. The issue I am having is that there is currently no way to extract a ligand from a PDB file without knowing the residue number. A possible solution to this would be a pdb_sellig command that extracted all hetatm lines associated with the ligand. As of now, the only interaction one can have with Hetatm is to delete them all. Another possible solution would be to give the option of a selhetatm. The selhetatm tool could be used in combination with the delelem to give me my ligand and delete the extraneous water molecules.

Using pdb-tools as a lib (also)

Hi @haddocking/pdb-tools

I have encounter already three to four cases where independent projects wanted to import pdb-tools as library. Despite pdb-tools was not initially designed to be imported and used, it is actually not hard to modify the code to have a reasonably nice lib interface. The most important change is not standardize the names of the functions within each tool. Namely, the functions that perform the logic should have all the same name. run or exec are good names for that. When using pdb-tools as lib, the functions main and check_input will likely not be used.

I will propose a PR with those changes. I will not break any backwards compatibility, I will keep a reference to the old names.

Let me know your thoughts,
Cheers,

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.