RNApolis 0.8.2__tar.gz → 0.8.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. {rnapolis-0.8.2/src/RNApolis.egg-info → rnapolis-0.8.3}/PKG-INFO +1 -1
  2. {rnapolis-0.8.2 → rnapolis-0.8.3}/setup.py +1 -1
  3. {rnapolis-0.8.2 → rnapolis-0.8.3/src/RNApolis.egg-info}/PKG-INFO +1 -1
  4. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/rnapolis/tertiary_v2.py +34 -1
  5. {rnapolis-0.8.2 → rnapolis-0.8.3}/tests/test_v2.py +39 -7
  6. {rnapolis-0.8.2 → rnapolis-0.8.3}/LICENSE +0 -0
  7. {rnapolis-0.8.2 → rnapolis-0.8.3}/README.md +0 -0
  8. {rnapolis-0.8.2 → rnapolis-0.8.3}/pyproject.toml +0 -0
  9. {rnapolis-0.8.2 → rnapolis-0.8.3}/setup.cfg +0 -0
  10. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/RNApolis.egg-info/SOURCES.txt +0 -0
  11. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/RNApolis.egg-info/dependency_links.txt +0 -0
  12. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/RNApolis.egg-info/entry_points.txt +0 -0
  13. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/RNApolis.egg-info/requires.txt +0 -0
  14. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/RNApolis.egg-info/top_level.txt +0 -0
  15. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/rnapolis/adapter.py +0 -0
  16. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/rnapolis/aligner.py +0 -0
  17. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/rnapolis/annotator.py +0 -0
  18. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/rnapolis/clashfinder.py +0 -0
  19. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/rnapolis/common.py +0 -0
  20. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/rnapolis/component_A.csv +0 -0
  21. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/rnapolis/component_C.csv +0 -0
  22. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/rnapolis/component_G.csv +0 -0
  23. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/rnapolis/component_U.csv +0 -0
  24. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/rnapolis/metareader.py +0 -0
  25. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/rnapolis/mmcif_pdbx_v50.dic +0 -0
  26. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/rnapolis/molecule_filter.py +0 -0
  27. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/rnapolis/motif_extractor.py +0 -0
  28. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/rnapolis/parser.py +0 -0
  29. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/rnapolis/parser_v2.py +0 -0
  30. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/rnapolis/rfam_folder.py +0 -0
  31. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/rnapolis/splitter.py +0 -0
  32. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/rnapolis/tertiary.py +0 -0
  33. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/rnapolis/transformer.py +0 -0
  34. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/rnapolis/unifier.py +0 -0
  35. {rnapolis-0.8.2 → rnapolis-0.8.3}/src/rnapolis/util.py +0 -0
  36. {rnapolis-0.8.2 → rnapolis-0.8.3}/tests/test_adapter.py +0 -0
  37. {rnapolis-0.8.2 → rnapolis-0.8.3}/tests/test_annotator.py +0 -0
  38. {rnapolis-0.8.2 → rnapolis-0.8.3}/tests/test_bugfixes.py +0 -0
  39. {rnapolis-0.8.2 → rnapolis-0.8.3}/tests/test_common.py +0 -0
  40. {rnapolis-0.8.2 → rnapolis-0.8.3}/tests/test_metareader.py +0 -0
  41. {rnapolis-0.8.2 → rnapolis-0.8.3}/tests/test_molecule_filter.py +0 -0
  42. {rnapolis-0.8.2 → rnapolis-0.8.3}/tests/test_parser.py +0 -0
  43. {rnapolis-0.8.2 → rnapolis-0.8.3}/tests/test_quadruplexes.py +0 -0
  44. {rnapolis-0.8.2 → rnapolis-0.8.3}/tests/test_rfam_folder.py +0 -0
  45. {rnapolis-0.8.2 → rnapolis-0.8.3}/tests/test_tertiary.py +0 -0
  46. {rnapolis-0.8.2 → rnapolis-0.8.3}/tests/test_transformer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: RNApolis
3
- Version: 0.8.2
3
+ Version: 0.8.3
4
4
  Summary: A Python library containing RNA-related bioinformatics functions and classes
5
5
  Home-page: https://github.com/tzok/rnapolis-py
6
6
  Author: Tomasz Zok
@@ -5,7 +5,7 @@ with open("README.md") as f:
5
5
 
6
6
  setup(
7
7
  name="RNApolis",
8
- version="0.8.2",
8
+ version="0.8.3",
9
9
  packages=["rnapolis"],
10
10
  package_dir={"": "src"},
11
11
  author="Tomasz Zok",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: RNApolis
3
- Version: 0.8.2
3
+ Version: 0.8.3
4
4
  Summary: A Python library containing RNA-related bioinformatics functions and classes
5
5
  Home-page: https://github.com/tzok/rnapolis-py
6
6
  Author: Tomasz Zok
@@ -121,7 +121,9 @@ class Structure:
121
121
  groupby_cols.append("pdbx_PDB_ins_code")
122
122
 
123
123
  # Group atoms by residue
124
- grouped = self.atoms.groupby(groupby_cols, dropna=False, observed=False)
124
+ grouped = self.atoms.groupby(
125
+ groupby_cols, dropna=False, observed=False, sort=False
126
+ )
125
127
 
126
128
  else:
127
129
  # For unknown formats, return an empty list
@@ -495,6 +497,37 @@ class Residue:
495
497
  return Atom(atoms_df.iloc[0], self.format)
496
498
  return None
497
499
 
500
+ @cached_property
501
+ def is_nucleotide(self) -> bool:
502
+ """
503
+ Check if this residue is a nucleotide.
504
+
505
+ A nucleotide is identified by the presence of specific atoms:
506
+ - Sugar atoms: C1', C2', C3', C4', O4'
507
+ - Base atoms: N1, C2, N3, C4, C5, C6
508
+
509
+ Returns:
510
+ --------
511
+ bool
512
+ True if the residue is a nucleotide, False otherwise
513
+ """
514
+ # Early check: if less than 11 atoms, can't be a nucleotide
515
+ if len(self.atoms) < 11:
516
+ return False
517
+
518
+ # Required sugar atoms
519
+ sugar_atoms = ["C1'", "C2'", "C3'", "C4'", "O4'"]
520
+
521
+ # Required base atoms
522
+ base_atoms = ["N1", "C2", "N3", "C4", "C5", "C6"]
523
+
524
+ # Check for all required atoms
525
+ for atom_name in sugar_atoms + base_atoms:
526
+ if self.find_atom(atom_name) is None:
527
+ return False
528
+
529
+ return True
530
+
498
531
  def is_connected(self, next_residue_candidate: "Residue") -> bool:
499
532
  """
500
533
  Check if this residue is connected to the next residue candidate.
@@ -12,7 +12,7 @@ from rnapolis.parser_v2 import (
12
12
  write_cif,
13
13
  write_pdb,
14
14
  )
15
- from rnapolis.tertiary_v2 import Atom, Residue, Structure, calculate_torsion_angle
15
+ from rnapolis.tertiary_v2 import Structure, calculate_torsion_angle
16
16
 
17
17
 
18
18
  def compare_structures(df1: pd.DataFrame, df2: pd.DataFrame, rtol=1e-5, atol=1e-8):
@@ -42,11 +42,13 @@ def compare_structures(df1: pd.DataFrame, df2: pd.DataFrame, rtol=1e-5, atol=1e-
42
42
  )
43
43
 
44
44
  # Sort residues for consistent comparison order
45
- key_func = lambda r: (
46
- r.chain_id,
47
- r.residue_number,
48
- r.insertion_code or "",
49
- )
45
+ def key_func(r):
46
+ return (
47
+ r.chain_id,
48
+ r.residue_number,
49
+ r.insertion_code or "",
50
+ )
51
+
50
52
  residues1.sort(key=key_func)
51
53
  residues2.sort(key=key_func)
52
54
 
@@ -265,7 +267,6 @@ def test_torsion_angle_calculation():
265
267
  a4 = np.array([0.0, 1.0, 1.0])
266
268
 
267
269
  # Calculate the torsion angle
268
- from rnapolis.tertiary_v2 import calculate_torsion_angle
269
270
 
270
271
  angle = calculate_torsion_angle(a1, a2, a3, a4)
271
272
 
@@ -414,3 +415,34 @@ def test_cif_pdb_cif_roundtrip(data_dir):
414
415
  # is preserved through the PDB intermediate representation, assuming
415
416
  # the PDB format could represent the original structure or its fitted version.
416
417
  compare_structures(df_to_write_pdb, df_final_cif)
418
+
419
+
420
+ def test_groupby_order(data_dir):
421
+ cif_path = os.path.join(data_dir, "1ehz-assembly-1.cif")
422
+ if not os.path.exists(cif_path):
423
+ pytest.skip(f"Test file not found: {cif_path}")
424
+
425
+ # 1. Parse Original CIF
426
+ with open(cif_path, "r") as f:
427
+ df_atoms = parse_cif_atoms(f)
428
+ assert not df_atoms.empty, "Original CIF parsing failed"
429
+
430
+ # 2. Group by chain_id and residue_number
431
+ structure = Structure(df_atoms) # Ensure Structure can be created
432
+ residues = structure.residues # Access residues to trigger any necessary processing
433
+ assert str(residues[0]) == "A.G1"
434
+ assert str(residues[1]) == "A.C2"
435
+
436
+
437
+ def test_is_nucleotide(data_dir):
438
+ cif_path = os.path.join(data_dir, "1ehz-assembly-1.cif")
439
+ if not os.path.exists(cif_path):
440
+ pytest.skip(f"Test file not found: {cif_path}")
441
+
442
+ with open(cif_path, "r") as f:
443
+ df_atoms = parse_cif_atoms(f)
444
+ assert not df_atoms.empty, "Original CIF parsing failed"
445
+
446
+ structure = Structure(df_atoms)
447
+ residues = [residue for residue in structure.residues if residue.is_nucleotide]
448
+ assert len(residues) == 76
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes