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

Commit

Permalink
Small Fixes (#15)
Browse files Browse the repository at this point in the history
* fix some clippy issues and add the repBitMask

* more field tests

* add preude
  • Loading branch information
zachcp authored Jul 26, 2024
1 parent edaa7fd commit fdea0c4
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 100 deletions.
7 changes: 6 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,9 @@
pub mod molviewspec;
pub mod pymolparsing;

pub use crate::pymolparsing::psedata::PSEData;
pub use self::pymolparsing::psedata::PSEData;

/// Prelude module for commonly used items
pub mod prelude {
pub use crate::pymolparsing::psedata::PSEData;
}
2 changes: 1 addition & 1 deletion src/molviewspec/nodes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ impl Node {
println!("In the parse node!");
println!("{:?}", self.kind);
if self.kind == KindT::Download {
let mut parse_node = Node::new(KindT::Parse, Some(NodeParams::ParseParams(params)));
let parse_node = Node::new(KindT::Parse, Some(NodeParams::ParseParams(params)));
self.children.get_or_insert_with(Vec::new).push(parse_node);
self.children.as_mut().unwrap().last_mut()
} else {
Expand Down
61 changes: 56 additions & 5 deletions src/pymolparsing/colors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,63 @@
/// ```
use once_cell::sync::Lazy;

#[derive(Clone)]
use serde_repr::{Deserialize_repr, Serialize_repr};

/// Named colors.
///
/// See also [`crate::pymolparsing::colors::COLOR_SET`].
///
#[derive(Debug, Serialize_repr, Deserialize_repr, PartialEq, Clone)]
#[repr(i32)]
pub enum AutoColor {
Aquamarine = 5257,
Bluewhite = 5278,
Brown = 51,
Carbon = 26,
Cyan = 5,
Darksalmon = 5280,
Deepblue = 23,
Deepsalmon = 5258,
Deepteal = 5262,
Dirtyviolet = 5272,
Forest = 22,
Greencyan = 5275,
Grey50 = 104,
Grey70 = 124,
Hotpink = 12,
Hydrogen = 29,
Lightmagenta = 154,
Lightpink = 5274,
Lightteal = 5266,
Lime = 10,
Limegreen = 15,
Limon = 5276,
Marine = 17,
Olive = 18,
Orange = 13,
Paleyellow = 5256,
Raspberry = 5268,
Salmon = 9,
Sand = 5269,
Skyblue = 5277,
Slate = 11,
Smudge = 5270,
Splitpea = 5267,
Teal = 20,
Violet = 53,
Violetpurple = 5271,
Warmpink = 5279,
Wheat = 52,
Yellow = 6,
Yelloworange = 36,
}

#[derive(Clone, Debug, PartialEq)]
pub struct Color {
name: &'static str, // Changed from String to &'static str,
r: f32,
g: f32,
b: f32,
pub name: &'static str, // Changed from String to &'static str,
pub r: f32,
pub g: f32,
pub b: f32,
}

/// Colors from Pymol
Expand Down
95 changes: 17 additions & 78 deletions src/pymolparsing/parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +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 crate::pymolparsing::representation::{RepBitmask, RepType};

use itertools::Itertools;
use pdbtbx::{self, Residue, PDB};
Expand Down Expand Up @@ -126,8 +126,10 @@ pub struct AtomInfo {
pub elem: String,
pub text_type: String,
pub label: String,
// todo: make enum
pub ss_type: String,
pub is_hydrogen: i8,
#[serde(deserialize_with = "int_to_bool")]
pub is_hydrogen: bool,
pub custom_type: i32,
pub priority: i32,
pub b: f64,
Expand All @@ -137,13 +139,16 @@ pub struct AtomInfo {
pub formal_charge: i32,
#[serde(deserialize_with = "int_to_bool")]
pub is_hetatm: bool,
pub vis_rep: i32,
pub vis_rep: RepBitmask,
// color is an index into the color vec
pub color: i32,
pub id: i32,
// https://github.com/schrodinger/pymol-open-source/blob/03d7a7fcf0bd95cd93d710a1268dbace2ed77765/layer2/AtomInfo.h#L292C33-L292C77
pub cartoon: i32, // /* 0 = default which is auto (use ssType) */
pub flags: i64,
pub is_bonded: i8,
#[serde(deserialize_with = "int_to_bool")]
pub is_bonded: bool,
// not sure what this is
pub chem_flag: i32,
// https://github.com/schrodinger/pymol-open-source/blob/03d7a7fcf0bd95cd93d710a1268dbace2ed77765/layer2/AtomInfo.cpp#L44
pub geom: i32, // cAtomInfo*
Expand Down Expand Up @@ -187,7 +192,7 @@ impl AtomInfo {
pub fn is_visible() {
unimplemented!()
}
pub fn atomInfoBrackResidue() {
pub fn atom_info_brack_residue() {
// https://github.com/schrodinger/pymol-open-source/blob/03d7a7fcf0bd95cd93d710a1268dbace2ed77765/layer2/AtomInfo.cpp#L1256C6-L1256C28
//inefficient but reliable way to find where residue atoms are located in an object
// for purpose of residue-based operations
Expand Down Expand Up @@ -228,10 +233,11 @@ impl AtomInfo {
pub struct Bond {
pub index_1: i32,
pub index_2: i32,
// todo: make enum
pub order: i32,
pub id: i32,
pub stereo: i32,
pub unique_id: i32,
pub unique_id: i8,
pub has_setting: i32,
// todo handle arity 7 or arity 8 with specific symmetry info
// Symmetry operation of the second atom.
Expand Down Expand Up @@ -295,55 +301,6 @@ pub enum ObjectType {
CObjectCurve = 14,
}

/// Named colors.
///
/// See also [`crate::pymolparsing::colors::COLOR_SET`].
///
#[derive(Debug, Serialize_repr, Deserialize_repr, PartialEq, Clone)]
#[repr(i32)]
pub enum AutoColor {
Aquamarine = 5257,
Bluewhite = 5278,
Brown = 51,
Carbon = 26,
Cyan = 5,
Darksalmon = 5280,
Deepblue = 23,
Deepsalmon = 5258,
Deepteal = 5262,
Dirtyviolet = 5272,
Forest = 22,
Greencyan = 5275,
Grey50 = 104,
Grey70 = 124,
Hotpink = 12,
Hydrogen = 29,
Lightmagenta = 154,
Lightpink = 5274,
Lightteal = 5266,
Lime = 10,
Limegreen = 15,
Limon = 5276,
Marine = 17,
Olive = 18,
Orange = 13,
Paleyellow = 5256,
Raspberry = 5268,
Salmon = 9,
Sand = 5269,
Skyblue = 5277,
Slate = 11,
Smudge = 5270,
Splitpea = 5267,
Teal = 20,
Violet = 53,
Violetpurple = 5271,
Warmpink = 5279,
Wheat = 52,
Yellow = 6,
Yelloworange = 36,
}

/// PyObject
///
/// General Object-Level settings object
Expand All @@ -356,12 +313,10 @@ pub struct PyObject {
pub object_type: ObjectType, // cObject_t
pub name: String,
pub color: i32, // represents a pointer into an array of colors.
//
// https://github.com/schrodinger/pymol-open-source/blob/03d7a7fcf0bd95cd93d710a1268dbace2ed77765/layer1/Rep.h
// https://github.com/schrodinger/pymol-open-source/blob/03d7a7fcf0bd95cd93d710a1268dbace2ed77765/modules/pymol/constants.py#L155-L177
// https://github.com/schrodinger/pymol-open-source/blob/03d7a7fcf0bd95cd93d710a1268dbace2ed77765/modules/pymol/viewing.py#L51C1-L53C71
pub vis_rep: i32, //

pub vis_rep: RepBitmask, //
pub extent_min: [f32; 3],
pub extent_max: [f32; 3],
pub extent_flag: i32,
Expand All @@ -376,7 +331,7 @@ pub struct PyObject {
impl PyObject {
/// get_color - note this currently works if there are
/// no custom colors.
pub fn get_color(self) -> Color {
pub fn get_color(&self) -> Color {
COLOR_SET
.get(self.color as usize)
.expect("Index within bounds")
Expand Down Expand Up @@ -612,30 +567,14 @@ impl<'de> Deserialize<'de> for PymolSessionObjectData {
D: Deserializer<'de>,
{
let value = Value::deserialize(deserializer)?;

// Debug print
// println!("Deserialized value: {:?}", value);

// Try to deserialize as PyObjectMolecule
match from_value::<PyObjectMolecule>(value.clone()) {
Ok(molecule) => return Ok(PymolSessionObjectData::PyObjectMolecule(molecule)),
Err(_) => {} // If it fails, we'll try the next option
}

// println!(
// "Did not serialize as a molecule. Not trying as a session: {:?}",
// value
// );

// If that fails, try to deserialize as SessionSelector
match from_value::<SessionSelectorList>(value.clone()) {
Ok(selection) => return Ok(PymolSessionObjectData::SessionSelectorList(selection)),
Err(_) => {} // If it fails, we'll return an error
if let Ok(selection) = from_value::<SessionSelectorList>(value.clone()) {
return Ok(PymolSessionObjectData::SessionSelectorList(selection));
}

// If both fail, return a generic error
// Err(String::from("We are unable to serialize this Value"));
Err(panic!("Problem opening the file"))
Err(serde::de::Error::custom("Failed to deserialize value"))
}
}

Expand Down
1 change: 1 addition & 0 deletions src/pymolparsing/representation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub enum RepType {
}

bitflags! {
#[derive(Debug)]
pub struct RepBitmask: u32 {
const CYL = 1 << 0;
const SPHERE = 1 << 1;
Expand Down
2 changes: 1 addition & 1 deletion tests/test_molview_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ fn test_moviewspec_01_common_actions_selectors() {
};
// State is the base model
let mut state = State::new();
let mut structure = state
let structure = state
.download("https://files.wwpdb.org/download/1cbs.cif")
.expect("Create a Download node with a URL")
.parse(structfile)
Expand Down
38 changes: 24 additions & 14 deletions tests/test_pse_parsing.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use pseutils::pymolparsing::colors::Color;
use pseutils::pymolparsing::colors::{Color, COLOR_SET};
use pseutils::pymolparsing::parsing::{CustomValue, SettingsEnum};
use pseutils::pymolparsing::representation::RepBitmask;
use pseutils::PSEData;
const TEST_OUTPUT_DIR: &str = "./test_temporary";

Expand Down Expand Up @@ -30,32 +31,43 @@ fn test_load_pse_data_molecule_selection() {
#[test]
fn test_pdb_00() {
let psedata: PSEData = PSEData::load("tests/data/example.pse").unwrap();
let names = psedata.get_session_names();
print!("{:?}", names);
// this has a Molecule and a selection
let names = psedata.get_session_names();
assert_eq!(names.len(), 2);

let mols = psedata.get_molecule_data();
assert_eq!(mols.len(), 1);

let atom01 = mols[0].get_atom(0);
assert!(atom01.x() == 50.87300109863281);
assert!(atom01.y() == 32.97800064086914);
assert!(atom01.z() == 2.38700008392334);

let chains = mols[0].get_chains();
println!("Chains: {:?}", chains);
let residues = mols[0].get_residues_by_chain(chains[0].clone());
println!("Residues: {:?}", residues);

let residue = mols[0].create_residue(chains[0].clone(), residues[0]);
println!("Residue: {:?}", residue);

let chain = mols[0].create_chain(chains[0].clone());
println!("Chain: {:?}", chain);

// Check symmetry code
let (unit, sym) = mols[0].get_unit_cell_symmetry();
println!("{:?},{:?}", unit, sym);

// Check the pymol object fields
let pyobj = &mols[0].object;
let color = &pyobj.get_color();
assert_eq!(
*color,
Color {
name: "carbon",
r: 0.2,
g: 1.0,
b: 0.2
}
);

let vis_rep = &pyobj.vis_rep;
assert!(vis_rep.contains(RepBitmask::CYL));
// check the name
assert_eq!(&pyobj.name, "1pdb");

// Move on to PDB, baby!
let pdb = mols[0].to_pdb();
Expand Down Expand Up @@ -158,11 +170,10 @@ fn test_colors() {
[0.0, 1.0, 1.0], // cyan - 999
];

let mut name = String::from("c000");
for a in 0..1000 {
let set1 = (a as f32 / A_DIV) as usize;
// sprintf(color->Name,"c%03d",a);
name = format!("c{:03}", a);
let name = format!("c{:03}", a);
let f = 1.0 - (a as f32 - (set1 as f32 * A_DIV)) / A_DIV;
let r = f * spectrum_c[set1][0] + (1.0 - f) * spectrum_c[set1 + 1][0];
let g = f * spectrum_c[set1][1] + (1.0 - f) * spectrum_c[set1 + 1][1];
Expand Down Expand Up @@ -205,10 +216,9 @@ fn test_colors() {

// complementary spectra separated by white (w000-w999)

let mut name = String::from("w000");
for a in 0..1000 {
let set1 = (a as f32 / W_DIV) as usize;
name = format!("w{:03}", a);
let name = format!("w{:03}", a);
let f = 1.0 - (a as f32 - (set1 as f32 * W_DIV)) / W_DIV;
let r = f * spectrum_w[set1][0] + (1.0 - f) * spectrum_w[set1 + 1][0];
let g = f * spectrum_w[set1][1] + (1.0 - f) * spectrum_w[set1 + 1][1];
Expand Down

0 comments on commit fdea0c4

Please sign in to comment.