rust-sasa-python 0.2.2__tar.gz → 0.2.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.
@@ -659,7 +659,7 @@ dependencies = [
659
659
 
660
660
  [[package]]
661
661
  name = "rust-sasa-python"
662
- version = "0.2.2"
662
+ version = "0.2.3"
663
663
  dependencies = [
664
664
  "nalgebra",
665
665
  "pdbtbx",
@@ -1,6 +1,6 @@
1
1
  [package]
2
2
  name = "rust-sasa-python"
3
- version = "0.2.2"
3
+ version = "0.2.3"
4
4
  edition = "2024"
5
5
 
6
6
  # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -119,6 +119,43 @@ sasa_values = sasa.calculate_sasa_internal(atoms, probe_radius=1.4, n_points=100
119
119
  print(f"SASA values: {sasa_values}")
120
120
  ```
121
121
 
122
+ **`calculate_sasa_internal_at_residue_level(atoms_in: list[tuple[tuple[float, float, float], float, int]], probe_radius: float, n_points: int) -> list[ResidueResult]`**
123
+
124
+ Calculate SASA at the residue level for a set of atoms directly without PDB file parsing. This function groups atoms by residue ID and calculates the average SASA per atom within each residue.
125
+
126
+ **Parameters:**
127
+ - `atoms_in`: List of tuples, each containing:
128
+ - Atom coordinates as `(x, y, z)` tuple of floats
129
+ - Atom radius as float
130
+ - Residue ID as int (used to group atoms into residues)
131
+ - `probe_radius`: Probe sphere radius in Ångströms
132
+ - `n_points`: Number of points for surface sampling
133
+
134
+ **Returns:**
135
+ - List of `ResidueResult` objects with:
136
+ - `chain_id`: Always "UNK" (unknown)
137
+ - `residue_name`: Always "UNK" (unknown)
138
+ - `residue_number`: The residue ID from input
139
+ - `sasa`: Average SASA per atom in the residue
140
+
141
+ **Example:**
142
+ ```python
143
+ import rust_sasa_python as sasa
144
+
145
+ # Define atoms with residue grouping
146
+ # Residue 1: two atoms, Residue 2: one atom
147
+ atoms = [
148
+ ((0.0, 0.0, 0.0), 1.7, 1), # Carbon in residue 1
149
+ ((1.5, 0.0, 0.0), 1.2, 1), # Hydrogen in residue 1
150
+ ((0.0, 3.0, 0.0), 1.55, 2), # Nitrogen in residue 2
151
+ ]
152
+
153
+ # Calculate residue-level SASA
154
+ residues = sasa.calculate_sasa_internal_at_residue_level(atoms, probe_radius=1.4, n_points=100)
155
+ for residue in residues:
156
+ print(f"Residue {residue.residue_number}: {residue.sasa:.2f} Ų (avg per atom)")
157
+ ```
158
+
122
159
  ## Usage Examples
123
160
 
124
161
  ### Basic Usage
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rust-sasa-python
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Classifier: Programming Language :: Rust
5
5
  Classifier: Programming Language :: Python :: Implementation :: CPython
6
6
  Classifier: Programming Language :: Python :: Implementation :: PyPy
@@ -51,7 +51,7 @@ print(f"Polar SASA: {result.polar:.2f}")
51
51
  print(f"Non-polar SASA: {result.non_polar:.2f}")
52
52
  ```
53
53
 
54
- See [DOCS](DOCS.md) for more information and API reference.
54
+ See [DOCS](https://github.com/maxall41/rust-sasa-python/blob/main/DOCS.md) for more information and API reference.
55
55
 
56
56
  ## Contributing
57
57
 
@@ -35,7 +35,7 @@ print(f"Polar SASA: {result.polar:.2f}")
35
35
  print(f"Non-polar SASA: {result.non_polar:.2f}")
36
36
  ```
37
37
 
38
- See [DOCS](DOCS.md) for more information and API reference.
38
+ See [DOCS](https://github.com/maxall41/rust-sasa-python/blob/main/DOCS.md) for more information and API reference.
39
39
 
40
40
  ## Contributing
41
41
 
@@ -3,8 +3,9 @@ use pdbtbx;
3
3
  use pyo3::exceptions::PyRuntimeError;
4
4
  use pyo3::prelude::*;
5
5
  use rust_sasa::options::SASAOptions;
6
- use rust_sasa::{Atom, calculate_sasa_internal as calculate_sasa_internal_internal};
6
+ use rust_sasa::{Atom, SASAProcessor, calculate_sasa_internal as calculate_sasa_internal_internal};
7
7
  use rust_sasa::{AtomLevel, ChainLevel, ProteinLevel, ResidueLevel}; // As in long long
8
+ use std::collections::HashMap;
8
9
 
9
10
  #[pyclass]
10
11
  #[derive(Clone)]
@@ -35,7 +36,7 @@ pub struct Residue {
35
36
  #[pyo3(get)]
36
37
  pub residue_name: String,
37
38
  #[pyo3(get)]
38
- pub residue_number: i32,
39
+ pub residue_number: u32,
39
40
  #[pyo3(get)]
40
41
  pub sasa: f32,
41
42
  }
@@ -195,7 +196,7 @@ impl SASACalculator {
195
196
  residue_results.push(Residue {
196
197
  chain_id: result.chain_id,
197
198
  residue_name: result.name,
198
- residue_number: result.serial_number as i32,
199
+ residue_number: result.serial_number as u32,
199
200
  sasa: result.value,
200
201
  });
201
202
  }
@@ -316,6 +317,39 @@ pub fn calculate_sasa_internal(
316
317
  ))
317
318
  }
318
319
 
320
+ #[pyfunction]
321
+ fn calculate_sasa_internal_at_residue_level(
322
+ atoms_in: Vec<((f32, f32, f32), f32, usize)>,
323
+ probe_radius: f32,
324
+ n_points: usize,
325
+ ) -> PyResult<Vec<Residue>> {
326
+ let atom_sasa = calculate_sasa_internal(atoms_in.clone(), probe_radius, n_points).unwrap();
327
+
328
+ let mut residue_groups: HashMap<usize, Vec<f32>> = HashMap::new();
329
+
330
+ for (i, atom) in atoms_in.iter().enumerate() {
331
+ let parent_id = atom.2;
332
+ residue_groups
333
+ .entry(parent_id)
334
+ .or_insert_with(Vec::new)
335
+ .push(atom_sasa[i]);
336
+ }
337
+
338
+ let mut residue_sasa = Vec::new();
339
+ for (parent_id, sasa_values) in residue_groups {
340
+ let local_sum = sasa_values.iter().sum::<f32>();
341
+
342
+ residue_sasa.push(Residue {
343
+ chain_id: "UNK".to_string(),
344
+ residue_name: "UNK".to_string(),
345
+ residue_number: parent_id as u32,
346
+ sasa: local_sum / sasa_values.len() as f32,
347
+ });
348
+ }
349
+
350
+ Ok(residue_sasa)
351
+ }
352
+
319
353
  #[pymodule]
320
354
  fn rust_sasa_python(m: &Bound<'_, PyModule>) -> PyResult<()> {
321
355
  m.add_class::<SASACalculator>()?;
@@ -329,6 +363,10 @@ fn rust_sasa_python(m: &Bound<'_, PyModule>) -> PyResult<()> {
329
363
  m.add_function(wrap_pyfunction!(calculate_atom_sasa, m)?)?;
330
364
  m.add_function(wrap_pyfunction!(calculate_chain_sasa, m)?)?;
331
365
  m.add_function(wrap_pyfunction!(calculate_sasa_internal, m)?)?;
366
+ m.add_function(wrap_pyfunction!(
367
+ calculate_sasa_internal_at_residue_level,
368
+ m
369
+ )?)?;
332
370
 
333
371
  Ok(())
334
372
  }