Skip to content

Commit

Permalink
polymer.protein polymer.nucleic multifilesave ...
Browse files Browse the repository at this point in the history
* new selection keywords: polymer.protein polymer.nucleic
* new command: multifilesave
* MMTF export (requires simplemmtf python module)
* select: present, state -1 -> current object state
* create: source_state = -1 -> current
  (was: source_state = -1/0 -> all)
* cif: support quoted '?' and '.' as values
  cif_get_array -> None instead of empty string for ? and .
* fix copy discrete object w/o coords
* fix loading pdbqr AutoDock 4 atom types
* fix get_model('none') and get_str('mol', 'none')
* h_add refactored: 5x faster, support discrete objects
  • Loading branch information
speleo3 committed Feb 7, 2018
1 parent 5acb6c4 commit e2df29a
Show file tree
Hide file tree
Showing 42 changed files with 1,015 additions and 196 deletions.
24 changes: 24 additions & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,30 @@
CHANGE LOG
=========================================================================

2018-02-07 Thomas Holder <[email protected]>

* new selection keywords: polymer.protein polymer.nucleic

* new command: multifilesave

* MMTF export (requires simplemmtf python module)

* select: present, state -1 -> current object state

* create: source_state = -1 -> current
(was: source_state = -1/0 -> all)

* cif: support quoted '?' and '.' as values
cif_get_array -> None instead of empty string for ? and .

* fix copy discrete object w/o coords

* fix loading pdbqr AutoDock 4 atom types

* fix get_model('none') and get_str('mol', 'none')

* h_add refactored: 5x faster, support discrete objects

2017-12-21 Thomas Holder, Piotr Rotkiewicz

* Python 3.7 support (https://sf.net/p/pymol/bugs/197/)
Expand Down
9 changes: 9 additions & 0 deletions contrib/mmtf-c/mmtf_parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,10 @@ void MMTF_container_destroy(MMTF_container* thing) {
free(thing->sequenceIndexList);
free(thing->groupsPerChain);
free(thing->chainsPerModel);

// PyMOL
free(thing->pymolRepsList);
free(thing->pymolColorList);
}
void MMTF_BioAssembly_destroy(MMTF_BioAssembly* bio_assembly) {
IF_NULL_PTRERROR_RETURN(bio_assembly, );
Expand Down Expand Up @@ -962,6 +966,11 @@ bool MMTF_unpack_from_msgpack_object(const msgpack_object* object, MMTF_containe
FETCH_AND_ASSIGN_DUMMYCOUNT(thing, int32_array, groupsPerChain);
FETCH_AND_ASSIGN_WITHCOUNT(thing, string_array, experimentalMethods);
FETCH_AND_ASSIGN_ARRAY(thing, float, unitCell);

// PyMOL
FETCH_AND_ASSIGN_DUMMYCOUNT(thing, int32_array, pymolRepsList);
FETCH_AND_ASSIGN_DUMMYCOUNT(thing, int32_array, pymolColorList);

MAP_ITERATE_END();

return true;
Expand Down
4 changes: 4 additions & 0 deletions contrib/mmtf-c/mmtf_parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,10 @@ typedef struct {
char** WITHCOUNT(chainNameList);
int32_t* groupsPerChain;
int32_t* chainsPerModel;

// PyMOL
int32_t* pymolRepsList;
int32_t* pymolColorList;
} MMTF_container;

/*
Expand Down
13 changes: 13 additions & 0 deletions layer0/strcasecmp.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
/*
* strcasecmp, strncasecmp
*/

#pragma once

#ifdef _WIN32
#include <string.h>
#define strcasecmp(s1, s2) _stricmp(s1, s2)
#define strncasecmp(s1, s2, n) _strnicmp(s1, s2, n)
#else
#include <strings.h>
#endif
5 changes: 5 additions & 0 deletions layer1/PConv.h
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,11 @@ inline PyObject * PConvToPyObject(const std::string &v) {
}

inline PyObject * PConvToPyObject(const char * v) {
#ifndef _PYMOL_NOPY
if (!v) {
Py_RETURN_NONE;
}
#endif
return PyString_FromString(v);
}

Expand Down
9 changes: 9 additions & 0 deletions layer1/PyMOLObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -671,7 +671,16 @@ void ObjectMakeValidName(PyMOLGlobals * G, char *name)
ObjectMakeValidName(name);

if (SelectorNameIsKeyword(G, name)) {
PRINTFB(G, FB_Executive, FB_Warnings)
" Warning: '%s' is a reserved keyword, appending underscore\n", name
ENDFB(G);
strcat(name, "_");
} else if (strcmp(name, "protein") == 0 || strcmp(name, "nucleic") == 0) {
// Warn the user if "protein" or "nucleic" are used as names, but
// don't modify the name (yet).
PRINTFB(G, FB_Executive, FB_Warnings)
" Warning: '%s' may become a reserved selection keyword in the future\n", name
ENDFB(G);
}
}

Expand Down
4 changes: 2 additions & 2 deletions layer1/Scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1245,10 +1245,10 @@ void SceneSetStereo(PyMOLGlobals * G, int flag)
I->StereoMode = 0;
}

if((cur_stereo != I->StereoMode) && ((cur_stereo == 4) || (I->StereoMode == 4))) {
if((cur_stereo != I->StereoMode) && (cur_stereo == cStereo_geowall || I->StereoMode == cStereo_geowall)) {
OrthoReshape(G, G->Option->winX, G->Option->winY, true);
#ifndef _PYMOL_NOPY
if((cur_stereo == 4) && I->StereoMode) {
if(cur_stereo == cStereo_geowall) {
PParse(G, "viewport");
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion layer1/Setting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2891,7 +2891,7 @@ void SettingInitGlobal(PyMOLGlobals * G, int alloc, int reset_gui, int use_defau
if(G->Option->stereo_mode) {
set_i(I, cSetting_stereo_mode, G->Option->stereo_mode);
} else if(G->StereoCapable || G->Option->blue_line) {
set_i(I, cSetting_stereo_mode, 1); /* quadbuffer if we can */
set_i(I, cSetting_stereo_mode, cStereo_quadbuffer); /* quadbuffer if we can */
}

/* In order to get electrostatic potentials in kT from the Coulomb equation...
Expand Down
1 change: 0 additions & 1 deletion layer2/AtomInfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1260,7 +1260,6 @@ int AtomInfoUniquefyNames(PyMOLGlobals * G, const AtomInfoType * atInfo0, int n0
} else {
sprintf(name, "%1d%1s%02d", c / 100, ai1->elem, c % 100);
}
name[4] = 0; /* just is case we go over */
LexAssign(G, ai1->name, name);
result++;
c = c + 1;
Expand Down
72 changes: 52 additions & 20 deletions layer2/CifFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@

#include <vector>
#include <iostream>
#include <stdexcept>

#include "CifFile.h"
#include "File.h"
#include "MemoryDebug.h"
#include "strcasecmp.h"

// basic IO and string handling

Expand Down Expand Up @@ -90,24 +90,38 @@ static void tolowerinplace(char *p) {
static const char * EMPTY_STRING = "";
static cif_array EMPTY_ARRAY(NULL);

/*
* Class to store CIF loops. Only for parsing, do not use in any higher level
* reading functions.
*/
class cif_loop {
public:
int ncols;
int nrows;
const char **values;

// methods
const char * get_value_raw(int row, int col) const;
};

// get table value, return NULL if indices out of bounds
const char * cif_loop::get_value_raw(int row, int col) const {
if (row >= nrows)
return NULL;
return values[row * ncols + col];
}

// get the number of elements in this array
int cif_array::get_nrows() const {
return (col < 0) ? 1 : pointer.loop->nrows;
}

// get array value, return NULL if row-index out of bounds
const char * cif_array::get_value_raw(int row) const {
// or value in ['.', '?']
const char * cif_array::get_value(int row) const {
if (col < 0)
return (row > 0) ? NULL : pointer.value;
return pointer.loop->get_value_raw(row, col);
};

// get array value, return NULL if value in ['.', '?']
const char * cif_array::get_value(int row) const {
const char * s = get_value_raw(row);
return (s && (s[0] == '?' || s[0] == '.') && !s[1]) ? NULL : s;
}

// get array value, return an empty string if missing
Expand Down Expand Up @@ -141,7 +155,7 @@ bool cif_array::is_missing_all() const {
}

// templated getters
template <> const char* cif_array::as<const char* >(int row) const { return as_s(row); }
template <> const char* cif_array::as<const char* >(int row) const { return get_value(row); }
template <> std::string cif_array::as<std::string >(int row) const { return as_s(row); }
template <> int cif_array::as<int >(int row) const { return as_i(row); }
template <> double cif_array::as<double >(int row) const { return as_d(row); }
Expand Down Expand Up @@ -228,7 +242,7 @@ bool cif_file::parse() {
char quote;
char prev = '\0';

std::vector<char> codes;
std::vector<bool> keypossible;

// tokenize
while (true) {
Expand All @@ -243,14 +257,14 @@ bool cif_file::parse() {
prev = *p;
} else if (isquote(*p)) { // will NULL the closing quote
quote = *p;
codes.push_back('Q');
keypossible.push_back(false);
tokens.push_back(p + 1);
while (*++p && !(*p == quote && iswhitespace0(p[1])));
if (*p)
*(p++) = 0;
prev = *p;
} else if (*p == ';' && islinefeed(prev)) { // will NULL the line feed before the closing semicolon
codes.push_back('Q');
keypossible.push_back(false);
tokens.push_back(p + 1);
while (*++p && !(islinefeed(*p) && p[1] == ';'));
if (*p) {
Expand All @@ -259,23 +273,35 @@ bool cif_file::parse() {
}
prev = ';';
} else { // will null the whitespace
codes.push_back('R');
tokens.push_back(p);
char * q = p++;
while (!iswhitespace0(*p)) ++p;
prev = *p;
if (*p)
*(p++) = 0;
if (p - q == 1 && (*q == '?' || *q == '.')) {
// store values '.' (inapplicable) and '?' (unknown) as null-pointers
q = NULL;
keypossible.push_back(false);
} else {
if (*p)
*(p++) = 0;
keypossible.push_back(true);
}
tokens.push_back(q);
}
}

cif_data *current_data = NULL, *current_frame = NULL, *global_block = NULL;

// parse into dictionary
for (unsigned int i = 0, n = tokens.size(); i < n; i++) {
if (codes[i] == 'Q') {
if (!keypossible[i]) {
std::cout << "ERROR" << std::endl;
break;
} else if (tokens[i][0] == '_') {
if (i + 1 == n) {
std::cout << "ERROR truncated" << std::endl;
break;
}

if (current_frame) {
tolowerinplace(tokens[i]);
current_frame->dict[tokens[i]].set_value(tokens[i + 1]);
Expand All @@ -296,7 +322,7 @@ bool cif_file::parse() {
}

// columns
while (++i < n && codes[i] != 'Q' && tokens[i][0] == '_') {
while (++i < n && keypossible[i] && tokens[i][0] == '_') {
tolowerinplace(tokens[i]);

if (current_frame) {
Expand All @@ -313,8 +339,14 @@ bool cif_file::parse() {
}

// rows
while (i < n && (codes[i] == 'Q' || !isspecial(tokens[i]))) {
while (i < n && !(keypossible[i] && isspecial(tokens[i]))) {
i += ncols;

if (i > n) {
std::cout << "ERROR truncated loop" << std::endl;
break;
}

nrows++;
}

Expand All @@ -334,7 +366,7 @@ bool cif_file::parse() {
global_block = current_data = current_frame = new cif_data;

} else if (strncasecmp("save_", tokens[i], 5) == 0) {
if (tokens[i][5]) {
if (tokens[i][5] && current_data) {
// begin
const char * key(tokens[i] + 5);
current_data->saveframes[key] = current_frame = new cif_data;
Expand Down
29 changes: 4 additions & 25 deletions layer2/CifFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,9 @@

#include <vector>
#include <map>
#include <stdexcept>

#include <string.h>

#ifdef WIN32
#define strcasecmp(s1, s2) _stricmp(s1, s2)
#define strncasecmp(s1, s2, n) _strnicmp(s1, s2, n)
#endif

/*
* C string comparison class
*/
Expand Down Expand Up @@ -59,24 +53,12 @@ class cif_file {
bool parse();
};

/*
* Class to store CIF loops. Only for parsing, do not use in any higher level
* reading functions.
*/
class cif_loop {
public:
int ncols;
int nrows;
const char **values;

// methods
const char * get_value_raw(int row, int col) const;
};

/*
* High-level access to CIF arrays
*/
class cif_array {
friend class cif_file;

private:
// column index, -1 if not in loop
short col;
Expand All @@ -88,10 +70,8 @@ class cif_array {
} pointer;

// methods
const char * get_value_raw(int row = 0) const;
const char * get_value(int row = 0) const;

public:
// point this array to a loop (only for parsing)
void set_loop(const cif_loop * loop, short col_) {
col = col_;
Expand All @@ -104,6 +84,7 @@ class cif_array {
pointer.value = value;
};

public:
// constructor
cif_array() {
};
Expand All @@ -114,9 +95,7 @@ class cif_array {
};

// get the number of elements in this array
int get_nrows() const {
return (col < 0) ? 1 : pointer.loop->nrows;
};
int get_nrows() const;

// get element as string, integer or double. If index is out of bounds,
// then return a default value.
Expand Down
Loading

0 comments on commit e2df29a

Please sign in to comment.