Specify color ramp for volume state

Fixes #289
This commit is contained in:
Jarrett Johnson
2023-07-20 12:07:03 -04:00
parent b034d5c3e6
commit 9333da43b2
7 changed files with 62 additions and 38 deletions

View File

@@ -64,6 +64,11 @@ static ObjectVolumeState* ObjectVolumeGetActiveState(ObjectVolume* I)
return nullptr;
}
CObjectState* ObjectVolume::_getObjectState(int state)
{
return &State[state];
}
static ObjectMapState * ObjectVolumeStateGetMapState(ObjectVolumeState * vs) {
ObjectMap *map = NULL;
@@ -1262,30 +1267,34 @@ void ObjectVolumeRecomputeExtent(ObjectVolume * I)
/*==============================================================================*/
PyObject * ObjectVolumeGetRamp(ObjectVolume * I)
PyObject* ObjectVolumeGetRamp(ObjectVolume* I, int state)
{
/* TODO: Allow for multi-state maps? */
PyObject * result = NULL;
ObjectVolumeState *ovs;
if(I && (ovs = ObjectVolumeGetActiveState(I))) {
if (!I) {
return (PConvAutoNone(nullptr));
}
if (auto ovs = static_cast<ObjectVolumeState*>(I->getObjectState(state))) {
if(!ovs->isUpdated)
I->update();
result = PConvFloatArrayToPyList(ovs->Ramp.data(), ovs->Ramp.size());
return PConvFloatArrayToPyList(ovs->Ramp.data(), ovs->Ramp.size());
}
return (PConvAutoNone(result));
return (PConvAutoNone(nullptr));
}
/*==============================================================================*/
pymol::Result<> ObjectVolumeSetRamp(ObjectVolume * I, std::vector<float>&& ramp_list)
pymol::Result<> ObjectVolumeSetRamp(ObjectVolume* I, std::vector<float>&& ramp_list, int state)
{
/* TODO: Allow for multi-state maps? */
ObjectVolumeState *ovs = ObjectVolumeGetActiveState(I);
if(!ovs || ramp_list.empty()) {
return pymol::make_error("ObjectVolumeSetRamp failed.");
if (!I) {
return pymol::make_error("Invalid volume.");
}
if (ramp_list.empty()) {
return pymol::make_error("Empty ramp.");
}
auto ovs = static_cast<ObjectVolumeState*>(I->getObjectState(state));
if (!ovs) {
return pymol::make_error("Invalid volume state.");
}
ovs->Ramp = std::move(ramp_list);

View File

@@ -64,6 +64,9 @@ struct ObjectVolume : public pymol::CObject {
void invalidate(cRep_t rep, cRepInv_t level, int state) override;
int getNFrame() const override;
pymol::CObject* clone() const override;
protected:
CObjectState* _getObjectState(int state) override;
};
ObjectVolume *ObjectVolumeFromBox(PyMOLGlobals * G, ObjectVolume * obj, ObjectMap * map,
@@ -84,8 +87,8 @@ int ObjectVolumeNewFromPyList(PyMOLGlobals * G, PyObject * list, ObjectVolume **
int ObjectVolumeInvalidateMapName(ObjectVolume * I, const char *name, const char * new_name);
CField * ObjectVolumeGetField(ObjectVolume* I);
PyObject * ObjectVolumeGetRamp(ObjectVolume* I);
pymol::Result<> ObjectVolumeSetRamp(ObjectVolume* I, std::vector<float>&& ramp_list);
PyObject* ObjectVolumeGetRamp(ObjectVolume* I, int state);
pymol::Result<> ObjectVolumeSetRamp(ObjectVolume* I, std::vector<float>&& ramp_list, int state);
ObjectMapState * ObjectVolumeGetMapState(ObjectVolume * I);

View File

@@ -4580,18 +4580,16 @@ ExecutiveGetHistogram(PyMOLGlobals * G, const char * objName, int n_points, floa
return pymol::make_error("failed to get map state");
}
PyObject* ExecutiveGetVolumeRamp(PyMOLGlobals * G, const char * objName) {
PyObject* ExecutiveGetVolumeRamp(PyMOLGlobals* G, const char* objName, int state) {
#ifdef _PYMOL_NOPY
return NULL;
return nullptr;
#else
pymol::CObject *obj;
PyObject* result = NULL;
PyObject* result = nullptr;
PRINTFD(G, FB_Executive) "Executive-GetVolumeRamp Entered.\n" ENDFD;
obj = ExecutiveFindObjectByName(G, objName);
if(obj && obj->type==cObjectVolume) {
result = ObjectVolumeGetRamp((ObjectVolume *) obj);
if (auto obj = ExecutiveFindObject<ObjectVolume>(G, objName)) {
result = ObjectVolumeGetRamp(obj, state);
}
PRINTFD(G, FB_Executive) "Executive-GetVolumeRamp Exited.\n" ENDFD;
@@ -4601,11 +4599,11 @@ PyObject* ExecutiveGetVolumeRamp(PyMOLGlobals * G, const char * objName) {
#endif
}
pymol::Result<> ExecutiveSetVolumeRamp(PyMOLGlobals * G, const char * objName, std::vector<float> ramp_list) {
pymol::Result<> ExecutiveSetVolumeRamp(PyMOLGlobals* G, const char* objName, std::vector<float> ramp_list, int state)
{
auto obj = ExecutiveFindObject<ObjectVolume>(G, objName);
if(obj) {
return ObjectVolumeSetRamp(obj, std::move(ramp_list));
if (obj) {
return ObjectVolumeSetRamp(obj, std::move(ramp_list), state);
}
return pymol::make_error("Object ", objName, " not found");

View File

@@ -649,8 +649,8 @@ const char *ExecutiveFindBestNameMatch(PyMOLGlobals * G, const char *name);
int ExecutiveSetVisFromPyDict(PyMOLGlobals * G, PyObject * dict);
PyObject *ExecutiveGetVisAsPyDict(PyMOLGlobals * G);
CField *ExecutiveGetVolumeField(PyMOLGlobals * G, const char * objName, int state);
pymol::Result<> ExecutiveSetVolumeRamp(PyMOLGlobals * G, const char * objName, std::vector<float> ramp_list);
PyObject *ExecutiveGetVolumeRamp(PyMOLGlobals * G, const char * objName);
pymol::Result<> ExecutiveSetVolumeRamp(PyMOLGlobals* G, const char* objName, std::vector<float> ramp_list, int state);
PyObject* ExecutiveGetVolumeRamp(PyMOLGlobals* G, const char* objName, int state);
pymol::Result<std::vector<float>>
ExecutiveGetHistogram(PyMOLGlobals * G, const char * objName, int n_points,

View File

@@ -818,7 +818,8 @@ static PyObject * CmdGetVolumeRamp(PyObject * self, PyObject * args)
PyObject *result = NULL;
int ok = false;
char* objName;
ok = PyArg_ParseTuple(args, "Os", &self, &objName);
int state;
ok = PyArg_ParseTuple(args, "Osi", &self, &objName, &state);
if(ok) {
API_SETUP_PYMOL_GLOBALS;
@@ -827,7 +828,7 @@ static PyObject * CmdGetVolumeRamp(PyObject * self, PyObject * args)
API_HANDLE_ERROR;
}
if(ok && (ok = APIEnterBlockedNotModal(G))) {
result = ExecutiveGetVolumeRamp(G,objName);
result = ExecutiveGetVolumeRamp(G, objName, state);
APIExitBlocked(G);
}
@@ -843,8 +844,9 @@ static PyObject * CmdSetVolumeRamp(PyObject * self, PyObject * args)
char* objName;
PyObject *ramp_list;
std::vector<float> float_array;
int state;
API_SETUP_ARGS(G, self, args, "OsO", &self, &objName, &ramp_list);
API_SETUP_ARGS(G, self, args, "OsOi", &self, &objName, &ramp_list, &state);
if (!PyList_Check(ramp_list) ||
!PConvFromPyObject(G, ramp_list, float_array)) {
@@ -853,7 +855,7 @@ static PyObject * CmdSetVolumeRamp(PyObject * self, PyObject * args)
API_ASSERT(APIEnterBlockedNotModal(G));
auto result =
ExecutiveSetVolumeRamp(G, objName, std::move(float_array));
ExecutiveSetVolumeRamp(G, objName, std::move(float_array), state);
APIExitBlocked(G);
return APIResult(G, result);
}

View File

@@ -3,6 +3,8 @@ Volume color ramp utilities
'''
import sys
from pymol.constants import CURRENT_STATE
cmd = sys.modules["pymol.cmd"]
_volume_windows = {}
@@ -82,17 +84,23 @@ SEE ALSO
namedramps[name] = ramp
def get_volume_color(name, quiet=1, _self=cmd):
def get_volume_color(name, state=CURRENT_STATE, quiet=1, _self=cmd):
'''
DESCRIPTION
Get the volume color ramp of a volume object.
ARGUMENTS
name = str: volume object name
state = int: state of volume
'''
quiet = int(quiet)
r = _self.DEFAULT_ERROR
with _self.lockcm:
r = _self._cmd.get_volume_ramp(_self._COb, name)
r = _self._cmd.get_volume_ramp(_self._COb, name, int(state)-1)
if isinstance(r, list):
if not quiet:
@@ -112,7 +120,7 @@ DESCRIPTION
return r
def volume_color(name, ramp='', quiet=1, _guiupdate=True, _self=cmd):
def volume_color(name, ramp='', state=CURRENT_STATE, quiet=1, _guiupdate=True, _self=cmd):
'''
DESCRIPTION
@@ -126,6 +134,8 @@ ARGUMENTS
with (x, color, alpha, ...) or (x, r, g, b, alpha, ...) values. If empty, get
the current volume colors.
state = int: state of volume to color
EXAMPLE
fetch 1a00, map, type=2fofc
@@ -135,7 +145,7 @@ EXAMPLE
quiet = int(quiet)
if not ramp:
return get_volume_color(name, quiet, _self)
return get_volume_color(name, state, quiet, _self)
if isinstance(ramp, str) and ramp in namedramps:
ramp = namedramps[ramp]
@@ -143,7 +153,7 @@ EXAMPLE
ramplist = ramp_expand(ramp)
with _self.lockcm:
r = cmd._cmd.set_volume_ramp(_self._COb, name, ramplist)
r = cmd._cmd.set_volume_ramp(_self._COb, name, ramplist, int(state)-1)
if _guiupdate and name in _volume_windows:
from pymol import gui

View File

@@ -593,6 +593,8 @@ ARGUMENTS
selection = an atom selection about which to display the mesh with
an additional "buffer" (if provided).
state = specifies which state to create.
carve = a radius about each atom in the selection for which to
include density. If "carve" is not provided, then the whole
brick is displayed.
@@ -635,7 +637,7 @@ SEE ALSO
int(source_state)-1,int(quiet))
if ramp:
_self.volume_color(name, ramp)
_self.volume_color(name, ramp, state)
return r