Skip to content
This repository has been archived by the owner on Oct 28, 2024. It is now read-only.

Commit

Permalink
Integrate Representation to Parser (#14)
Browse files Browse the repository at this point in the history
* parse booleans directly 

* update bitmask
  • Loading branch information
zachcp authored Jul 25, 2024
1 parent 2f82306 commit edaa7fd
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 41 deletions.
1 change: 1 addition & 0 deletions src/pymolparsing/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
pub mod colors;
pub mod parsing;
pub mod psedata;
pub mod representation;
63 changes: 39 additions & 24 deletions src/pymolparsing/parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
//! m_tmpids[m_iter.getAtm()] = m_id;
use crate::molviewspec::nodes::{ComponentExpression, ComponentSelector};
use crate::pymolparsing::colors::{Color, COLOR_SET};
use crate::pymolparsing::representation::RepType;

use itertools::Itertools;
use pdbtbx::{self, Residue, PDB};
Expand Down Expand Up @@ -134,7 +135,8 @@ pub struct AtomInfo {
pub vdw: f64,
pub partial_charge: f64,
pub formal_charge: i32,
pub hetatm: i8,
#[serde(deserialize_with = "int_to_bool")]
pub is_hetatm: bool,
pub vis_rep: i32,
pub color: i32,
pub id: i32,
Expand All @@ -150,19 +152,24 @@ pub struct AtomInfo {
// Should be equivalent to RDKit::Atom::getTotalDegree() and
// OBAtom::GetTotalDegree().
pub valence: i32, //
pub is_masked: i8,
pub is_protected: i8,
#[serde(deserialize_with = "int_to_bool")]
pub is_masked: bool,
#[serde(deserialize_with = "int_to_bool")]
pub is_protected: bool,
pub protons: i32, // atomic number
pub unique_id: i64,
pub stereo: i8,
pub discrete_state: i32,
pub elec_radius: f64,
pub rank: i32,
pub hb_donor: i8,
pub hb_acceptor: i8,
#[serde(deserialize_with = "int_to_bool")]
pub hb_donor: bool,
#[serde(deserialize_with = "int_to_bool")]
pub hb_acceptor: bool,
// color and secondary structure
pub atomic_color: i32,
pub has_setting: i8,
#[serde(deserialize_with = "int_to_bool")]
pub has_setting: bool,
pub anisou_1: f32,
pub anisou_2: f32,
pub anisou_3: f32,
Expand All @@ -173,13 +180,6 @@ pub struct AtomInfo {
}

impl AtomInfo {
pub fn is_hetero(&self) -> bool {
match self.hetatm {
1 => true,
0 => false,
_ => false,
}
}
// https://github.com/schrodinger/pymol-open-source/blob/03d7a7fcf0bd95cd93d710a1268dbace2ed77765/layer2/AtomInfo.h#L319
pub fn is_metal() {
unimplemented!()
Expand All @@ -196,16 +196,16 @@ impl AtomInfo {
pub fn to_pdbtbx_atom(&self) -> pdbtbx::Atom {
let formal_charge = self.formal_charge as isize;
let atom = pdbtbx::Atom::new(
self.is_hetero(), // hetero
0, // serial_number
&self.name, // atom_name
0.0, // x Todo
0.0, // y Todo
0.0, // z Todo
0.0, // occupancy? Todo
self.b, // b-factor
&self.elem, // element
formal_charge, // charge: todo: is this the right charge?
self.is_hetatm, // hetero
0, // serial_number
&self.name, // atom_name
0.0, // x Todo
0.0, // y Todo
0.0, // z Todo
0.0, // occupancy? Todo
self.b, // b-factor
&self.elem, // element
formal_charge, // charge: todo: is this the right charge?
);
atom.unwrap()
}
Expand Down Expand Up @@ -296,6 +296,9 @@ pub enum ObjectType {
}

/// Named colors.
///
/// See also [`crate::pymolparsing::colors::COLOR_SET`].
///
#[derive(Debug, Serialize_repr, Deserialize_repr, PartialEq, Clone)]
#[repr(i32)]
pub enum AutoColor {
Expand Down Expand Up @@ -459,7 +462,7 @@ impl PyObjectMolecule {
let serial_number = atom_info.id as usize;

let atom = pdbtbx::Atom::new(
atom_info.is_hetero(), // hetero
atom_info.is_hetatm, // hetero
serial_number, // serial_number: Note: I am not sure this is correct just yet.
atom_info.name.clone(), // atom_name
x_coord.into(), // x
Expand Down Expand Up @@ -1627,6 +1630,18 @@ pub struct Settings {
pub value: CustomValue,
}

fn int_to_bool<'de, D>(deserializer: D) -> Result<bool, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::de::Error;
match u8::deserialize(deserializer)? {
0 => Ok(false),
1 => Ok(true),
other => Err(Error::custom(format!("Invalid boolean value: {}", other))),
}
}

// Todo:
//
// struct PyObjectGadget {}
Expand Down
1 change: 0 additions & 1 deletion src/pymolparsing/psedata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ pub struct PSEData {
unique_settings: Vec<i32>,
selector_secrets: Vec<i32>,
editor: Vec<i32>,
// pub view: [f32; 25],
pub view: SceneView,
view_dict: HashMap<String, String>,
#[serde(with = "serde_bytes")]
Expand Down
52 changes: 36 additions & 16 deletions src/pymolparsing/representation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
//! # Examples
//!
//! ```
//! use crate::RepBitmask;
//! use pseutils::pymolparsing::representation::RepBitmask;
//!
//! let mut reps = RepBitmask::new();
//! reps.insert(RepBitmask::CYL | RepBitmask::SPHERE);
Expand All @@ -18,10 +18,11 @@
//! assert!(reps.contains(RepBitmask::SPHERE));
//! ```
use bitflags::bitflags;
use serde::{Deserialize, Serialize};

// First, define an enum for all representation types
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum RepType {
pub enum RepType {
Cyl,
Sphere,
Surface,
Expand All @@ -46,7 +47,7 @@ enum RepType {
}

bitflags! {
struct RepBitmask: u32 {
pub struct RepBitmask: u32 {
const CYL = 1 << 0;
const SPHERE = 1 << 1;
const SURFACE = 1 << 2;
Expand All @@ -69,13 +70,13 @@ bitflags! {
const ELLIPSOID = 1 << 19;
const VOLUME = 1 << 20;

const REPS_ATOM_MASK = Self::CYL.bits | Self::SPHERE.bits | Self::SURFACE.bits |
Self::LABEL.bits | Self::NONBONDED_SPHERE.bits | Self::CARTOON.bits | Self::RIBBON.bits |
Self::LINE.bits | Self::MESH.bits | Self::DOT.bits | Self::NONBONDED.bits | Self::ELLIPSOID.bits;
const REPS_ATOM_MASK = Self::CYL.bits() | Self::SPHERE.bits() | Self::SURFACE.bits() |
Self::LABEL.bits() | Self::NONBONDED_SPHERE.bits() | Self::CARTOON.bits() | Self::RIBBON.bits() |
Self::LINE.bits() | Self::MESH.bits() | Self::DOT.bits() | Self::NONBONDED.bits() | Self::ELLIPSOID.bits();

const REPS_OBJECT_MASK = Self::SURFACE.bits | Self::MESH.bits | Self::DOT.bits |
Self::CELL.bits | Self::CGO.bits | Self::CALLBACK.bits | Self::EXTENT.bits | Self::SLICE.bits |
Self::ANGLE.bits | Self::DIHEDRAL.bits | Self::VOLUME.bits | Self::DASH.bits;
const REPS_OBJECT_MASK = Self::SURFACE.bits() | Self::MESH.bits() | Self::DOT.bits() |
Self::CELL.bits() | Self::CGO.bits() | Self::CALLBACK.bits() | Self::EXTENT.bits() | Self::SLICE.bits() |
Self::ANGLE.bits() | Self::DIHEDRAL.bits() | Self::VOLUME.bits() | Self::DASH.bits();
}
}

Expand All @@ -90,6 +91,27 @@ impl RepBitmask {
}
}

// Custom Serde deserialization
impl<'de> Deserialize<'de> for RepBitmask {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let bits = u32::deserialize(deserializer)?;
Ok(RepBitmask::from_bits_truncate(bits))
}
}

// Custom Serde serialization
impl Serialize for RepBitmask {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
serializer.serialize_u32(self.bits())
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -120,7 +142,10 @@ mod tests {
// Check that the correct flags are set
assert!(bitmask.contains(RepBitmask::CYL));
assert!(bitmask.contains(RepBitmask::SURFACE));
}

#[test]
fn test_bitmask_from_int_02() {
// I see this value in the example.pse
// Binary: 111110110001111111
let int_value = 2060287;
Expand All @@ -130,7 +155,6 @@ mod tests {
assert!(bitmask.contains(RepBitmask::CYL));
assert!(bitmask.contains(RepBitmask::SURFACE));

assert!(bitmask.contains(RepBitmask::CYL));
assert!(bitmask.contains(RepBitmask::SPHERE));
assert!(bitmask.contains(RepBitmask::SURFACE));
assert!(bitmask.contains(RepBitmask::LABEL));
Expand All @@ -142,19 +166,15 @@ mod tests {
assert!(bitmask.contains(RepBitmask::DOT));
assert!(bitmask.contains(RepBitmask::DASH));
assert!(bitmask.contains(RepBitmask::NONBONDED));
assert!(bitmask.contains(RepBitmask::CELL));
assert!(bitmask.contains(RepBitmask::CGO));
assert!(bitmask.contains(RepBitmask::CALLBACK));
assert!(bitmask.contains(RepBitmask::EXTENT));
assert!(bitmask.contains(RepBitmask::SLICE));
assert!(bitmask.contains(RepBitmask::ANGLE));
assert!(bitmask.contains(RepBitmask::DIHEDRAL));
assert!(bitmask.contains(RepBitmask::ELLIPSOID));
assert!(bitmask.contains(RepBitmask::VOLUME));

// Check that the flag that should not be set is indeed not set
assert!(!bitmask.contains(RepBitmask::VOLUME));

// Verify the raw bits
assert!(!bitmask.contains(RepBitmask::EXTENT));
assert_eq!(bitmask.bits(), 2060287);
}
}

0 comments on commit edaa7fd

Please sign in to comment.