From 39bb27150dcb1b146b1792e9dbb9fee5a35b7596 Mon Sep 17 00:00:00 2001 From: Thomas Holder Date: Wed, 25 Jun 2025 07:12:12 +0200 Subject: [PATCH 1/5] Test for flatten_obj --- scripts/flatten_obj.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/scripts/flatten_obj.py b/scripts/flatten_obj.py index bbc6247e..cd2906b0 100644 --- a/scripts/flatten_obj.py +++ b/scripts/flatten_obj.py @@ -334,3 +334,25 @@ def flatten_obj(name="",selection="",state=0,rename=0,quiet=1,chain_map=""): # tab-completion of arguments cmd.auto_arg[0]['flatten_obj'] = [ cmd.object_sc, 'name or selection', ''] cmd.auto_arg[1]['flatten_obj'] = [ cmd.object_sc, 'selection', ''] + + +def test_flatten_obj__rename0(): + cmd.reinitialize() + cmd.fab("ACD", "m1", chain="C") + cmd.fab("DEF", "m2", chain="C") + flatten_obj("m3", "m1 | m2", rename=0) + assert cmd.count_atoms("m3") == 80 + assert cmd.count_atoms("m3 & resi 2") == 26 + assert cmd.get_chains("m3") == ["A", "C"] + + +def test_flatten_obj__rename1(): + cmd.reinitialize() + cmd.fab("ACD", "m1", chain="C") + cmd.fab("DEF", "m2", chain="C") + flatten_obj("m3", "m1 | m2", rename=1, chain_map="foo") + assert cmd.get_chains("m3") == ["A", "B"] + assert dict(stored.foo) == { + "A": ("m1", 1, "C"), + "B": ("m2", 1, "C"), + } \ No newline at end of file From a32580964c7039d88f35daaf2307be38604d35da Mon Sep 17 00:00:00 2001 From: Thomas Holder Date: Wed, 25 Jun 2025 07:12:24 +0200 Subject: [PATCH 2/5] Test for ccp4_contact.py --- scripts/ccp4_contact.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/scripts/ccp4_contact.py b/scripts/ccp4_contact.py index 764fff11..568473a9 100644 --- a/scripts/ccp4_contact.py +++ b/scripts/ccp4_contact.py @@ -23,6 +23,7 @@ AUTHOR Gerhard Reitmayr and Dalia Daujotyte, 2011. ''' +from pathlib import Path from pymol import cmd import re @@ -73,3 +74,14 @@ def ccp4_contact(contactsfile, selName1="source", selName2="target"): cmd.select(selName2 + "_atom", atomSel) cmd.extend("ccp4_contact", ccp4_contact) + + +def test_ccp4_contact(): + datadir = Path(__file__).parents[1] / "files_for_examples" + cmd.reinitialize() + cmd.fab("PCQAFSISGKQKGFEDSRGTL", chain="A", resi=80) + ccp4_contact(f"{datadir}/2c7r.contact", selName1="sel1", selName2="sel2") + assert cmd.count_atoms("sel1_res") == 128 + assert cmd.count_atoms("sel1_atom") == 20 + assert cmd.count_atoms("sel2_res") == 128 + assert cmd.count_atoms("sel2_atom") == 20 \ No newline at end of file From f64e0329ed38eb9dd87e504588c52b9dc83742e1 Mon Sep 17 00:00:00 2001 From: Thomas Holder Date: Wed, 25 Jun 2025 07:35:12 +0200 Subject: [PATCH 3/5] Test for ccp4_ncont --- scripts/ccp4_ncont.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/scripts/ccp4_ncont.py b/scripts/ccp4_ncont.py index 65e8eeef..c6458834 100644 --- a/scripts/ccp4_ncont.py +++ b/scripts/ccp4_ncont.py @@ -23,7 +23,7 @@ AUTHOR Gerhard Reitmayr and Dalia Daujotyte, 2009. ''' -from __future__ import print_function +from pathlib import Path from pymol import cmd import re @@ -83,3 +83,21 @@ def ccp4_ncont(contactsfile, selName1="source", selName2="target"): cmd.select(selName2 + "_atom", atomSel) cmd.extend("ccp4_ncont", ccp4_ncont) + + +def test_ccp4_ncont(): + datadir = Path(__file__).parents[1] / "files_for_examples" + cmd.reinitialize() + cmd.fab("PCQAFSISGKQKGFEDSRGTL", "m1", chain="A", resi=80) + cmd.fnab("GCTGAC", "m2", dbl_helix=False) + cmd.remove("hydro") + cmd.alter("m2", "chain = 'C'") + cmd.alter("m2", "resv += 407") + cmd.alter("m2 & name O1P", "name = 'OP1'") + cmd.alter("m2 & name O2P", "name = 'OP2'") + cmd.alter("m2 & name O3P", "name = 'OP3'") + ccp4_ncont(f"{datadir}/2c7r.ncont", selName1="sel1", selName2="sel2") + assert cmd.count_atoms("sel1_res") == 23 + assert cmd.count_atoms("sel1_atom") == 5 + assert cmd.count_atoms("sel2_res") == 104 + assert cmd.count_atoms("sel2_atom") == 16 \ No newline at end of file From c8d8bb570ed78b85d9f926d89fb7a67934528e82 Mon Sep 17 00:00:00 2001 From: Thomas Holder Date: Tue, 24 Jun 2025 07:02:08 +0200 Subject: [PATCH 4/5] Fix invalid escape sequences (W605) Related to https://github.com/Pymol-Scripts/Pymol-script-repo/issues/147 --- scripts/ccp4_contact.py | 2 +- scripts/ccp4_ncont.py | 2 +- scripts/flatten_obj.py | 2 +- scripts/plot_noe.py | 14 +++++++------- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/scripts/ccp4_contact.py b/scripts/ccp4_contact.py index 568473a9..1e8812b6 100644 --- a/scripts/ccp4_contact.py +++ b/scripts/ccp4_contact.py @@ -30,7 +30,7 @@ def parseCONTACTContacts(f): # Lys 24A ca Asp 263D CG ... 4.94 [ -1B ] 3: -X, Y+1/2, -Z+1/2 - conParser = re.compile("(\S*)\s*(\d+)([A-Z])\s*(\w+)") + conParser = re.compile(r"(\S*)\s*(\d+)([A-Z])\s*(\w+)") s1 = [] s2 = [] for line in f: diff --git a/scripts/ccp4_ncont.py b/scripts/ccp4_ncont.py index c6458834..84dfbab5 100644 --- a/scripts/ccp4_ncont.py +++ b/scripts/ccp4_ncont.py @@ -31,7 +31,7 @@ def parseNCONTContacts(f): # /1/B/ 282(PHE). / CE1[ C]: /1/E/ 706(GLN). / O [ O]: 3.32 # * in the second group is needed when chain code is blank - conParser = re.compile("\s*/(\d+)/([a-zA-Z0-9]*)/\s*(\d+).*?/\s*([a-zA-Z0-9]*).*?:") + conParser = re.compile(r"\s*/(\d+)/([a-zA-Z0-9]*)/\s*(\d+).*?/\s*([a-zA-Z0-9]*).*?:") mode = 0 s1 = [] s2 = [] diff --git a/scripts/flatten_obj.py b/scripts/flatten_obj.py index cd2906b0..fc416367 100644 --- a/scripts/flatten_obj.py +++ b/scripts/flatten_obj.py @@ -277,7 +277,7 @@ def flatten_obj(name="",selection="",state=0,rename=0,quiet=1,chain_map=""): cmd.create(prefix, obj, state, 1) # renumber all states - statere = re.compile("^%s_(.*)_(\d+)$" % metaprefix) # matches split object names + statere = re.compile(r"^%s_(.*)_(\d+)$" % metaprefix) # matches split object names warn_lowercase = False diff --git a/scripts/plot_noe.py b/scripts/plot_noe.py index ed517e38..deaff45d 100644 --- a/scripts/plot_noe.py +++ b/scripts/plot_noe.py @@ -56,10 +56,10 @@ def plot_noe(filename, line_color=None, line_width='1.0', advanced_coloring=0, s if advanced_coloring == 1: cmd.set("group_auto_mode", 2) - rgx_assi = re.compile("\s*[asignASIGN]+\s+.*") - rgx_or = re.compile("\s*[orOR]+\s+.*") - rgx_bracket = re.compile("(\(|\))") - rgx_tick = re.compile("(\w)\'") + rgx_assi = re.compile(r"\s*[asignASIGN]+\s+.*") + rgx_or = re.compile(r"\s*[orOR]+\s+.*") + rgx_bracket = re.compile(r"(\(|\))") + rgx_tick = re.compile(r"(\w)'") restraint_line = None restraint_block = [] @@ -68,17 +68,17 @@ def plot_noe(filename, line_color=None, line_width='1.0', advanced_coloring=0, s for line in open(filename): if rgx_assi.match(line): if restraint_line: - restraint_block.append(rgx_tick.sub("\g<1>^", rgx_bracket.sub(" ", restraint_line))) + restraint_block.append(rgx_tick.sub(r"\g<1>^", rgx_bracket.sub(" ", restraint_line))) restraints_blocks.append(restraint_block) restraint_block = [] restraint_line = line elif rgx_or.match(line): - restraint_block.append(rgx_tick.sub("\g<1>^", rgx_bracket.sub(" ", restraint_line))) + restraint_block.append(rgx_tick.sub(r"\g<1>^", rgx_bracket.sub(" ", restraint_line))) restraint_line = line else: restraint_line += line - restraint_block.append(rgx_tick.sub("\g<1>^", rgx_bracket.sub(" ", restraint_line))) + restraint_block.append(rgx_tick.sub(r"\g<1>^", rgx_bracket.sub(" ", restraint_line))) restraints_blocks.append(restraint_block) for restraint_block in restraints_blocks: From d867d29d7a893a203b5bc0d1a9480c0c87bd0749 Mon Sep 17 00:00:00 2001 From: Thomas Holder Date: Sun, 29 Jun 2025 18:32:42 +0200 Subject: [PATCH 5/5] Fix invalid escape sequences (W605) Part 2 Semi-automated with: ruff check --fix --select W605 scripts --- scripts/forster_distance_calculator.py | 4 ++-- scripts/propka.py | 6 +++--- scripts/transformations.py | 6 +++--- scripts/wfmesh.py | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/scripts/forster_distance_calculator.py b/scripts/forster_distance_calculator.py index 5ca81895..0c9dd46c 100644 --- a/scripts/forster_distance_calculator.py +++ b/scripts/forster_distance_calculator.py @@ -1,4 +1,4 @@ -''' +r''' Described at PyMOL wiki: http://www.pymolwiki.org/index.php/forster_distance_calculator @@ -77,7 +77,7 @@ def forster(D_Exi="ATTO488Exi.txt", D_Emi="ATTO488Emi.txt", A_Exi="ATTO590Exi.tx print("The .plt should be opened with gnuplot to make the graphs.") print("The created graphs are .eps files.") print("They can be converted to pdf with the program: epstopdf or eps2pdf") - print('Part of LaTeX: C:\Program Files (x86)\MiKTeX 2.9\miktex' + "\\" + "bin") + print(r'Part of LaTeX: C:\Program Files (x86)\MiKTeX 2.9\miktex' + "\\" + "bin") print("Or download here: http://tinyurl.com/eps2pdf") DonorEmi = open(D_Emi, "r") diff --git a/scripts/propka.py b/scripts/propka.py index a8c4d0b8..181506dd 100644 --- a/scripts/propka.py +++ b/scripts/propka.py @@ -1,4 +1,4 @@ -''' +r''' Described at PyMOL wiki: http://www.pymolwiki.org/index.php/propka @@ -222,7 +222,7 @@ def getpropka(PDB="NIL", chain="*", resi="0", resn="NIL", source="upload", PDBID assert version in ['v2.0', 'v3.0', 'v3.1'], "'version' has to be either: 'v2.0', 'v3.0', 'v3.1'" assert source in ['ID', 'upload', 'addr', 'input_file'], "'source' has to be either: 'ID', 'upload', 'addr', 'input_file'" if source == "upload": - assert PDB not in ['NIL'], "You always have to provide PDB path. Example: PDB=.\Results_propka\4ins2011.pdb" + assert PDB not in ['NIL'], r"You always have to provide PDB path. Example: PDB=.\Results_propka\4ins2011.pdb" if source == "ID": assert len(PDBID) == 4, "PDBID has to be 4 characters" # To print out to screen for selected residues. Can be separated with "." or make ranges with "-". Example: resi="4-8.10" @@ -517,7 +517,7 @@ def importpropkabonds(result_pka_pkafile): def createdirs(): if platform.system() == 'Windows': - Newdir = os.getcwd() + "\Results_propka\\" + Newdir = os.getcwd() + "\\Results_propka\\" if platform.system() == 'Linux': Newdir = os.getcwd() + "/Results_propka/" if not os.path.exists(Newdir): diff --git a/scripts/transformations.py b/scripts/transformations.py index 12a7f850..b69c082f 100644 --- a/scripts/transformations.py +++ b/scripts/transformations.py @@ -30,7 +30,7 @@ # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE # POSSIBILITY OF SUCH DAMAGE. -"""Homogeneous Transformation Matrices and Quaternions. +r"""Homogeneous Transformation Matrices and Quaternions. A library for calculating 4x4 matrices for translating, rotating, reflecting, scaling, shearing, projecting, orthogonalizing, and superimposing arrays of @@ -883,7 +883,7 @@ def orthogonalization_matrix(lengths, angles): def affine_matrix_from_points(v0, v1, shear=True, scale=True, usesvd=True): - """Return affine transform matrix to register two point sets. + r"""Return affine transform matrix to register two point sets. v0 and v1 are shape (ndims, \*) arrays of at least ndims non-homogeneous coordinates, where ndims is the dimensionality of the coordinate space. @@ -992,7 +992,7 @@ def affine_matrix_from_points(v0, v1, shear=True, scale=True, usesvd=True): def superimposition_matrix(v0, v1, scale=False, usesvd=True): - """Return matrix to transform given 3D point set into second point set. + r"""Return matrix to transform given 3D point set into second point set. v0 and v1 are shape (3, \*) or (4, \*) arrays of at least 3 points. diff --git a/scripts/wfmesh.py b/scripts/wfmesh.py index 56a76647..b04b2754 100644 --- a/scripts/wfmesh.py +++ b/scripts/wfmesh.py @@ -42,7 +42,7 @@ def readOBJ(self, file): if os.path.exists(file): input = open(file, 'r') for line in input: - dat = re.split("\s+", line) + dat = re.split(r"\s+", line) # Find vertex line if line[0] == 'v' and line[1] != 't' and line[1] != 'n':