Ticket #778: changes_take_3.diff

File changes_take_3.diff, 45.9 KB (added by Tristan Croll, 8 years ago)

Updated to make better use of the ChangeManager framework, further speed improvements.

  • src/core/atomic/atomstruct_cpp/Atom.cpp

    diff --git a/src/core/atomic/atomstruct_cpp/Atom.cpp b/src/core/atomic/atomstruct_cpp/Atom.cpp
    index 1903479..dcdf0b8 100644
    a b Atom::get_idatm_info_map()  
    846846    return _idatm_map;
    847847}
    848848
     849void
     850Atom::bonds_track_change(const std::string& reason) {
     851    for(std::vector<Bond*>::iterator b = _bonds.begin(); b != _bonds.end(); ++b) {
     852        (*b)->track_change(reason);
     853    }
     854}
     855
     856
    849857bool
    850858Atom::has_missing_structure_pseudobond() const
    851859{
    Atom::set_alt_loc(char alt_loc, bool create, bool _from_residue)  
    11121120    if (alt_loc == _alt_loc || alt_loc == ' ')
    11131121        return;
    11141122    graphics_container()->set_gc_shape();
    1115     structure()->change_tracker()->add_modified(this, ChangeTracker::REASON_ALT_LOC);
     1123    track_change(ChangeTracker::REASON_ALT_LOC);
    11161124    if (create) {
    11171125        if (_alt_loc_map.find(alt_loc) != _alt_loc_map.end()) {
    11181126            set_alt_loc(alt_loc, create=false);
    Atom::set_alt_loc(char alt_loc, bool create, bool _from_residue)  
    11351143        _Alt_loc_info &info = (*i).second;
    11361144        _serial_number = info.serial_number;
    11371145        _alt_loc = alt_loc;
    1138         structure()->change_tracker()->add_modified(this, ChangeTracker::REASON_COORD);
     1146        track_change(ChangeTracker::REASON_COORD);
    11391147    } else {
    11401148        residue()->set_alt_loc(alt_loc);
    11411149    }
    Atom::set_aniso_u(float u11, float u12, float u13, float u22, float u23, float u  
    11601168    (*a)[3] = u22;
    11611169    (*a)[4] = u23;
    11621170    (*a)[5] = u33;
    1163     structure()->change_tracker()->add_modified(this, ChangeTracker::REASON_ANISO_U);
     1171    track_change(ChangeTracker::REASON_ANISO_U);
    11641172}
    11651173
    11661174void
    Atom::set_bfactor(float bfactor)  
    11711179        (*i).second.bfactor = bfactor;
    11721180    } else
    11731181        structure()->active_coord_set()->set_bfactor(this, bfactor);
    1174     structure()->change_tracker()->add_modified(this, ChangeTracker::REASON_BFACTOR);
     1182    track_change(ChangeTracker::REASON_BFACTOR);
    11751183}
    11761184
    11771185void
    Atom::set_color(const Rgba& rgba)  
    11801188    if (rgba == _rgba)
    11811189        return;
    11821190    graphics_container()->set_gc_color();
    1183     change_tracker()->add_modified(this, ChangeTracker::REASON_COLOR);
     1191    track_change(ChangeTracker::REASON_COLOR);
     1192    bonds_track_change(ChangeTracker::REASON_COLOR);
    11841193    _rgba = rgba;
    11851194}
    11861195
    11871196void
    11881197Atom::set_coord(const Coord& coord, CoordSet* cs)
    1189 {
    1190     structure()->change_tracker()->add_modified(this, ChangeTracker::REASON_COORD);
     1198{   
     1199    track_change(ChangeTracker::REASON_COORD);
     1200    bonds_track_change(ChangeTracker::REASON_COORD);
    11911201    if (cs == nullptr) {
    11921202        cs = structure()->active_coord_set();
    11931203        if (cs == nullptr) {
    Atom::set_display(bool d)  
    12141224    if (d == _display)
    12151225        return;
    12161226    graphics_container()->set_gc_shape();
    1217     change_tracker()->add_modified(this, ChangeTracker::REASON_DISPLAY);
     1227    graphics_container()->set_gc_atom_vis();
     1228    graphics_container()->set_gc_bond_vis();
     1229    track_change(ChangeTracker::REASON_DISPLAY);
    12181230    _display = d;
    12191231}
    12201232
    Atom::set_draw_mode(DrawMode dm)  
    12231235{
    12241236    if (dm == _draw_mode)
    12251237        return;
     1238    if ( _draw_mode == DrawMode::Sphere || dm == DrawMode::Sphere )
     1239        graphics_container()->set_gc_bond_vis();
    12261240    graphics_container()->set_gc_shape();
    1227     change_tracker()->add_modified(this, ChangeTracker::REASON_DRAW_MODE);
     1241    track_change(ChangeTracker::REASON_DRAW_MODE);
    12281242    _draw_mode = dm;
    12291243}
    12301244
    Atom::set_hide(int h)  
    12341248    if (h == _hide)
    12351249        return;
    12361250    graphics_container()->set_gc_shape();
    1237     change_tracker()->add_modified(this, ChangeTracker::REASON_HIDE);
     1251    graphics_container()->set_gc_atom_vis();
     1252    graphics_container()->set_gc_bond_vis();
     1253    track_change(ChangeTracker::REASON_HIDE);
    12381254    _hide = h;
    12391255}
    12401256
    12411257void
    12421258Atom::set_occupancy(float occupancy)
    12431259{
    1244     structure()->change_tracker()->add_modified(this, ChangeTracker::REASON_OCCUPANCY);
     1260    track_change(ChangeTracker::REASON_OCCUPANCY);
    12451261    if (_alt_loc != ' ') {
    12461262        _Alt_loc_map::iterator i = _alt_loc_map.find(_alt_loc);
    12471263        (*i).second.occupancy = occupancy;
    Atom::set_radius(float r)  
    12591275        return;
    12601276
    12611277    graphics_container()->set_gc_shape();
    1262     change_tracker()->add_modified(this, ChangeTracker::REASON_RADIUS);
     1278    track_change(ChangeTracker::REASON_RADIUS);
    12631279    _radius = r;
    12641280}
    12651281
    Atom::set_selected(bool s)  
    12691285    if (s == _selected)
    12701286        return;
    12711287    graphics_container()->set_gc_select();
    1272     change_tracker()->add_modified(this, ChangeTracker::REASON_SELECTED);
     1288    track_change(ChangeTracker::REASON_SELECTED);
     1289    bonds_track_change(ChangeTracker::REASON_SELECTED);
    12731290    _selected = s;
    12741291}
    12751292
    Atom::set_serial_number(int sn)  
    12811298        _Alt_loc_map::iterator i = _alt_loc_map.find(_alt_loc);
    12821299        (*i).second.serial_number = sn;
    12831300    }
    1284     structure()->change_tracker()->add_modified(this, ChangeTracker::REASON_SERIAL_NUMBER);
     1301    track_change(ChangeTracker::REASON_SERIAL_NUMBER);
    12851302}
    12861303
    12871304std::string
  • src/core/atomic/atomstruct_cpp/Atom.h

    diff --git a/src/core/atomic/atomstruct_cpp/Atom.h b/src/core/atomic/atomstruct_cpp/Atom.h
    index eb8c7ed..a2c4c62 100644
    a b private:  
    109109    typedef std::map<unsigned char, _Alt_loc_info>  _Alt_loc_map;
    110110    _Alt_loc_map  _alt_loc_map;
    111111    std::vector<float>*  _aniso_u;
     112    bool _changed_since_last_drawn = false;
    112113    Bonds  _bonds; // _bonds/_neighbors in same order
    113114    mutable AtomType  _computed_idatm_type;
    114115    unsigned int  _coord_index;
    private:  
    128129    mutable Rings  _rings;
    129130    bool  _selected = false;
    130131    int  _serial_number;
    131     void  _set_structure_category(Atom::StructCat sc) const;
     132    void  _set_structure_category(Atom::StructCat sc);
    132133    Structure*  _structure;
    133134    mutable StructCat  _structure_category;
    134135public:
    public:  
    137138    void  _switch_initial_element(const Element& e) { _element = &e; }
    138139
    139140public:
     141    bool changed_since_last_drawn() const { return _changed_since_last_drawn; }
     142    void set_changed_since_last_drawn(bool flag) { _changed_since_last_drawn = flag; }
    140143    void  add_bond(Bond *b);
    141144    char  alt_loc() const { return _alt_loc; }
    142145    std::set<char>  alt_locs() const;
    public:  
    208211
    209212    // change tracking
    210213    ChangeTracker*  change_tracker() const;
     214    void track_change(const std::string& reason) {
     215        change_tracker()->add_modified(this, reason);
     216        this->set_changed_since_last_drawn(true);
     217    }
     218   
     219    void bonds_track_change(const std::string& reason);
     220   
    211221
    212222    // graphics related
    213223    const Rgba&  color() const { return _rgba; }
    Atom::idatm_type() const {  
    243253}
    244254
    245255inline void
    246 Atom::_set_structure_category(Atom::StructCat sc) const
     256Atom::_set_structure_category(Atom::StructCat sc)
    247257{
    248258    if (sc == _structure_category)
    249259        return;
    250     change_tracker()->add_modified(const_cast<Atom*>(this),
    251         ChangeTracker::REASON_STRUCTURE_CATEGORY);
     260    track_change(ChangeTracker::REASON_STRUCTURE_CATEGORY);
    252261    _structure_category = sc;
    253262}
    254263
    255264inline void
    256265Atom::set_computed_idatm_type(const char* it) {
    257266    if (!idatm_is_explicit() && _computed_idatm_type != it) {
     267        track_change(ChangeTracker::REASON_IDATM_TYPE);
    258268        change_tracker()->add_modified(this, ChangeTracker::REASON_IDATM_TYPE);
    259269    }
    260270    _computed_idatm_type =  it;
    Atom::set_idatm_type(const char* it) {  
    267277    if (!(_explicit_idatm_type.empty() && _computed_idatm_type == it)
    268278    && !(*it == '\0' && _explicit_idatm_type == _computed_idatm_type)
    269279    && !(!_explicit_idatm_type.empty() && it == _explicit_idatm_type)) {
    270         change_tracker()->add_modified(this, ChangeTracker::REASON_IDATM_TYPE);
     280        track_change(ChangeTracker::REASON_IDATM_TYPE);
    271281    }
    272282    _explicit_idatm_type = it;
    273283}
    inline void  
    276286Atom::set_name(const AtomName& name) {
    277287    if (name == _name)
    278288        return;
    279     change_tracker()->add_modified(this, ChangeTracker::REASON_NAME);
     289    track_change(ChangeTracker::REASON_NAME);
    280290    _name = name;
     291    _changed_since_last_drawn = true;
    281292}
    282293
    283294inline Atom::StructCat
  • src/core/atomic/atomstruct_cpp/Bond.cpp

    diff --git a/src/core/atomic/atomstruct_cpp/Bond.cpp b/src/core/atomic/atomstruct_cpp/Bond.cpp
    index 268e3f8..4454684 100644
    a b Bond::polymeric_start_atom() const  
    174174    return psa;
    175175}
    176176
     177void
     178Bond::set_hide(int h) {
     179    if (h == _hide)
     180        return;
     181    graphics_container()->set_gc_bond_vis();
     182    Connection::set_hide(h);
     183}
     184
     185void
     186Bond::set_display(bool d) {
     187    if (d == _display)
     188        return;
     189    graphics_container()->set_gc_bond_vis();
     190    Connection::set_display(d);
     191}
     192
    177193}  // namespace atomstruct
  • src/core/atomic/atomstruct_cpp/Bond.h

    diff --git a/src/core/atomic/atomstruct_cpp/Bond.h b/src/core/atomic/atomstruct_cpp/Bond.h
    index 43b2fcd..ab236af 100644
    a b private:  
    4646    const char*  err_msg_loop() const
    4747        { return "Can't bond an atom to itself"; }
    4848    mutable Rings  _rings;
    49 
     49    bool _changed_since_last_drawn = false;
     50   
    5051    static int  session_base_version(int /*version*/) { return 1; }
    5152    static int  SESSION_NUM_INTS(int /*version*/=CURRENT_SESSION_VERSION) { return 0; }
    5253    static int  SESSION_NUM_FLOATS(int /*version*/=CURRENT_SESSION_VERSION) { return 0; }
    5354public:
     55    void set_hide(int h);
     56    void set_display(bool d);
    5457    virtual ~Bond() {}
    5558    virtual bool shown() const;
    5659    const Rings&  all_rings(bool cross_residues = false, int size_threshold = 0,
    public:  
    6265        return rings(cross_residues, 0, ignore);
    6366    }
    6467    static bool  polymer_bond_atoms(Atom* first, Atom* second);
     68    bool changed_since_last_drawn() const { return _changed_since_last_drawn; }
     69    void set_changed_since_last_drawn(bool flag) { _changed_since_last_drawn = flag; }
    6570    Atom*  polymeric_start_atom() const;
    6671    const Rings&  rings(bool cross_residues = false, int all_size_threshold = 0,
    6772        std::set<const Residue*>* ignore = nullptr) const;
    public:  
    8085
    8186    // change tracking
    8287    ChangeTracker*  change_tracker() const;
    83     void track_change(const std::string& reason) const {
     88    void track_change(const std::string& reason) {
    8489        change_tracker()->add_modified(this, reason);
     90        this->set_changed_since_last_drawn(true);
    8591    }
    8692
    8793    // graphics related
  • src/core/atomic/atomstruct_cpp/Connection.h

    diff --git a/src/core/atomic/atomstruct_cpp/Connection.h b/src/core/atomic/atomstruct_cpp/Connection.h
    index d0ba00e..443d9cc 100644
    a b public:  
    106106    }
    107107
    108108    // change tracking
    109     virtual void  track_change(const std::string& reason) const = 0;
     109    virtual void  track_change(const std::string& reason) = 0;
    110110
    111111    // graphics related
    112112    const Rgba&  color() const { return _rgba; }
  • src/core/atomic/atomstruct_cpp/CoordSet.cpp

    diff --git a/src/core/atomic/atomstruct_cpp/CoordSet.cpp b/src/core/atomic/atomstruct_cpp/CoordSet.cpp
    index 69eac6b..94399c5 100644
    a b CoordSet::session_save(int** ints, float** floats) const  
    130130void
    131131CoordSet::set_bfactor(const Atom *a, float val)
    132132{
    133     _bfactor_map.insert(std::pair<const Atom *, float>(a, val));
     133    //_bfactor_map.insert(std::pair<const Atom *, float>(a, val));
     134    _bfactor_map[a] = val;
    134135}
    135136
    136137void
    137138CoordSet::set_occupancy(const Atom *a, float val)
    138139{
    139     _occupancy_map.insert(std::pair<const Atom *, float>(a, val));
     140    //_occupancy_map.insert_or_assign(std::pair<const Atom *, float>(a, val));
     141    _occupancy_map[a] = val;
    140142}
    141143
    142144}  // namespace atomstruct
  • src/core/atomic/atomstruct_cpp/PBGroup.h

    diff --git a/src/core/atomic/atomstruct_cpp/PBGroup.h b/src/core/atomic/atomstruct_cpp/PBGroup.h
    index f8e0eb9..cb5dc9b 100644
    a b protected:  
    7676
    7777    void _check_destroyed_atoms(PBGroup::Pseudobonds& pbonds, const std::set<void*>& destroyed);
    7878    void delete_pbs_check(const std::set<Pseudobond*>& pbs) const;
     79    bool _changed = false;
    7980public:
     81    bool changed() const { return _changed; }
     82    void set_changed(bool flag) { _changed = flag; }
    8083    virtual void  clear() = 0;
    8184    virtual const Rgba&  color() const { return _color; }
    8285    virtual const std::string&  category() const { return _category; }
  • src/core/atomic/atomstruct_cpp/Pseudobond.h

    diff --git a/src/core/atomic/atomstruct_cpp/Pseudobond.h b/src/core/atomic/atomstruct_cpp/Pseudobond.h
    index 52cc7ae..de7d1d9 100644
    a b protected:  
    6060        { return "Can't form pseudobond to itself"; }
    6161    const char*  err_msg_not_end() const
    6262        { return "Atom given to other_end() not in pseudobond!"; }
     63    bool _changed = false;
    6364public:
     65    bool changed() const { return _changed; }
     66    void set_changed(bool flag) { _changed = flag; }
    6467    ChangeTracker*  change_tracker() const;
    6568    GraphicsContainer*  graphics_container() const;
    6669    PBGroup*  group() const { return _group; }
    public:  
    7679    }
    7780    void  session_restore(int version, int** ints, float** floats);
    7881    void  session_save(int** ints, float** floats) const;
    79     void  track_change(const std::string& reason) const {
     82    void  track_change(const std::string& reason) {
    8083        change_tracker()->add_modified(this, reason);
     84        this->set_changed(true);
    8185    }
    8286};
    8387
  • src/core/atomic/atomstruct_cpp/Structure.h

    diff --git a/src/core/atomic/atomstruct_cpp/Structure.h b/src/core/atomic/atomstruct_cpp/Structure.h
    index 60ce973..e8a4cf6 100644
    a b public:  
    6565      COLOR_CHANGE = (1 << 1),
    6666      SELECT_CHANGE = (1 << 2),
    6767      RIBBON_CHANGE = (1 << 3),
     68      ATOM_VIS_CHANGE = (1 << 4),
     69      BOND_VIS_CHANGE = (1 << 5)
    6870    };
    6971
    7072    GraphicsContainer(): _gc_changes(0) {}
    public:  
    7476    virtual bool  get_gc_select() const { return _gc_changes & SELECT_CHANGE; }
    7577    virtual bool  get_gc_shape() const { return _gc_changes & SHAPE_CHANGE; }
    7678    virtual bool  get_gc_ribbon() const { return _gc_changes & RIBBON_CHANGE; }
     79    virtual bool  get_gc_atom_vis() const { return _gc_changes & ATOM_VIS_CHANGE; }
     80    virtual bool  get_gc_bond_vis() const {return _gc_changes & BOND_VIS_CHANGE; }
    7781    virtual int   get_graphics_changes() const { return _gc_changes; }
    7882    virtual void  set_gc_color() { set_graphics_change(COLOR_CHANGE); }
    7983    virtual void  set_gc_select() { set_graphics_change(SELECT_CHANGE); }
    8084    virtual void  set_gc_shape() { set_graphics_change(SHAPE_CHANGE); }
    8185    virtual void  set_gc_ribbon() { set_graphics_change(RIBBON_CHANGE); }
     86    virtual void  set_gc_atom_vis() { set_graphics_change(ATOM_VIS_CHANGE); }
     87    virtual void  set_gc_bond_vis() { set_graphics_change(BOND_VIS_CHANGE); }
    8288    virtual void  set_graphics_changes(int change) { _gc_changes = change; }
    8389    virtual void  set_graphics_change(ChangeType type) { _gc_changes |= type; }
    8490    virtual void  clear_graphics_change(ChangeType type) { _gc_changes &= ~type; }
    protected:  
    184190    static int  SESSION_NUM_MISC(int version=CURRENT_SESSION_VERSION) {
    185191        return version > 7 ? 3 : 4;
    186192    }
    187 
    188193public:
     194   
    189195    Structure(PyObject* logger = nullptr);
    190196    virtual  ~Structure();
    191197
  • src/core/atomic/molarray.py

    diff --git a/src/core/atomic/molarray.py b/src/core/atomic/molarray.py
    index ac0a869..a149860 100644
    a b class Atoms(Collection):  
    342342        "Return list of 2-tuples of (structure, Atoms for that structure)."
    343343        astruct = self.structures._pointers
    344344        return [(us, self.filter(astruct==us._c_pointer.value)) for us in self.unique_structures]
     345   
     346    _changed = cvec_property('atom_changed', bool, doc='Changed since last redraw')
    345347    chain_ids = cvec_property('atom_chain_id', string, read_only = True)
    346348    colors = cvec_property('atom_color', uint8, 4,
    347349        doc="Returns a :mod:`numpy` Nx4 array of uint8 RGBA values. Can be set "
    class Bonds(Collection):  
    611613    def __init__(self, bond_pointers = None):
    612614        Collection.__init__(self, bond_pointers, molobject.Bond, Bonds)
    613615
     616
     617    _changed = cvec_property('bond_changed', bool, doc='Changed since last redraw')
     618    '''
     619    True if the bond or the position(s) of its atoms have been changed
     620    since the last time they were drawn.
     621    Returns a :mod:`numpy` array of bool. Can be set with such an array
     622    (or equivalent sequence), or with a single value.
     623    '''
     624
    614625    atoms = cvec_property('bond_atoms', cptr, 2, astype = _atoms_pair, read_only = True)
    615626    '''
    616627    Returns a two-tuple of :class:`Atoms` objects.
  • src/core/atomic/molc.cpp

    diff --git a/src/core/atomic/molc.cpp b/src/core/atomic/molc.cpp
    index 4e7e24c..adadb2a 100755
    a b inline bool normalize(float *v)  
    248248// -------------------------------------------------------------------------
    249249// atom functions
    250250//
     251
     252
     253extern "C" EXPORT void atom_changed(void *atoms, size_t n, npy_bool *flags)
     254{
     255    Atom **a = static_cast<Atom **>(atoms);
     256    error_wrap_array_get(a, n, &Atom::changed_since_last_drawn, flags);
     257}
     258
     259extern "C" EXPORT void set_atom_changed (void *atoms, size_t n, npy_bool *flags)
     260{
     261    Atom **a = static_cast<Atom **>(atoms);
     262    error_wrap_array_set(a, n, &Atom::set_changed_since_last_drawn, flags);
     263}
     264   
     265
    251266extern "C" EXPORT void atom_bfactor(void *atoms, size_t n, float32_t *bfactors)
    252267{
    253268    Atom **a = static_cast<Atom **>(atoms);
    extern "C" EXPORT PyObject *atom_intra_bonds(void *atoms, size_t n)  
    10241039// -------------------------------------------------------------------------
    10251040// bond functions
    10261041//
     1042
     1043extern "C" EXPORT void bond_changed(void *bonds, size_t n, npy_bool *flags)
     1044{
     1045    Bond **b = static_cast<Bond **>(bonds);
     1046    error_wrap_array_get(b, n, &Bond::changed_since_last_drawn, flags);
     1047}
     1048
     1049extern "C" EXPORT void set_bond_changed (void *bonds, size_t n, npy_bool *flags)
     1050{
     1051    Bond **b = static_cast<Bond **>(bonds);
     1052    error_wrap_array_set(b, n, &Bond::set_changed_since_last_drawn, flags);
     1053}
     1054
     1055
    10271056extern "C" EXPORT void bond_atoms(void *bonds, size_t n, pyobject_t *atoms)
    10281057{
    10291058    Bond **b = static_cast<Bond **>(bonds);
    extern "C" EXPORT void *bond_other_atom(void *bond, void *atom)  
    12241253// -------------------------------------------------------------------------
    12251254// pseudobond functions
    12261255//
     1256
     1257extern "C" EXPORT void pseudobond_changed(void *pbonds, size_t n, npy_bool *flags)
     1258{
     1259    Pseudobond **b = static_cast<Pseudobond **>(pbonds);
     1260    error_wrap_array_get(b, n, &Pseudobond::changed, flags);
     1261}
     1262
     1263extern "C" EXPORT void set_pseudobond_changed (void *pbonds, size_t n, npy_bool *flags)
     1264{
     1265    Pseudobond **b = static_cast<Pseudobond **>(pbonds);
     1266    error_wrap_array_set(b, n, &Pseudobond::set_changed, flags);
     1267}
     1268
     1269
     1270
    12271271extern "C" EXPORT void pseudobond_atoms(void *pbonds, size_t n, pyobject_t *atoms)
    12281272{
    12291273    Pseudobond **b = static_cast<Pseudobond **>(pbonds);
    extern "C" EXPORT void pseudobond_global_manager_session_save_teardown(void *man  
    17341778// -------------------------------------------------------------------------
    17351779// residue functions
    17361780//
     1781
     1782//~ extern "C" EXPORT void residue_changed(void *residues, size_t n, npy_bool *flags)
     1783//~ {
     1784    //~ Residue **r = static_cast<Residue **>(residues);
     1785    //~ error_wrap_array_get(r, n, &Residue::changed, flags);
     1786//~ }
     1787
     1788//~ extern "C" EXPORT void set_residue_changed (void *residues, size_t n, npy_bool *flags)
     1789//~ {
     1790    //~ Residue **r = static_cast<Residue **>(residues);
     1791    //~ error_wrap_array_set(r, n, &Residue::set_changed, flags);
     1792//~ }
     1793
     1794
    17371795extern "C" EXPORT void residue_atoms(void *residues, size_t n, pyobject_t *atoms)
    17381796{
    17391797    Residue **r = static_cast<Residue **>(residues);
    extern "C" EXPORT int sequence_ungapped_to_gapped(void *seq, int32_t index)  
    32113269// -------------------------------------------------------------------------
    32123270// structure functions
    32133271//
     3272
     3273
    32143274extern "C" EXPORT void set_structure_color(void *mol, uint8_t *rgba)
    32153275{
    32163276    Structure *m = static_cast<Structure *>(mol);
    extern "C" EXPORT void structure_atoms(void *mols, size_t n, pyobject_t *atoms)  
    33033363    }
    33043364}
    33053365
     3366//~ extern "C" EXPORT void structure_visible_atoms_changed(void *mols, size_t n, npy_bool *changed)
     3367//~ {
     3368    //~ Structure **m = static_cast<Structure **>(mols);
     3369    //~ try {
     3370        //~ for (size_t i = 0; i != n; ++i) {
     3371            //~ *changed++ = m[i]->get_gc_atom_vis();
     3372        //~ }
     3373    //~ } catch (...) {
     3374        //~ molc_error();
     3375    //~ }
     3376//~ }
     3377
     3378//~ extern "C" EXPORT void set_structure_visible_atoms_changed(void *mols, size_t n, npy_bool *changed)
     3379//~ {
     3380    //~ Structure **m = static_cast<Structure **>(mols);
     3381    //~ try {
     3382        //~ for (size_t i = 0; i != n; ++i) {
     3383            //~ if (*changed++) {
     3384                //~ m[i]->set_gc_atom_vis();
     3385            //~ } else {
     3386                //~ m[i]->clear_graphics_change(Structure::ChangeType::ATOM_VIS_CHANGE);
     3387            //~ }
     3388        //~ }
     3389    //~ } catch (...) {
     3390        //~ molc_error();
     3391    //~ }
     3392//~ }
     3393
     3394extern "C" EXPORT void structure_visible_atoms(void *mols, size_t n, pyobject_t *atoms)
     3395{
     3396    Structure **m = static_cast<Structure **>(mols);
     3397    try {
     3398        for (size_t i = 0; i != n; ++i) {
     3399            const Structure::Atoms &a = m[i]->atoms();
     3400            for (size_t j = 0; j != a.size(); ++j) {
     3401                if ( a[j]->visible() )
     3402                    *atoms++ = a[j];
     3403            }
     3404        }
     3405    } catch (...) {
     3406        molc_error();
     3407    }
     3408}
     3409
     3410
    33063411extern "C" EXPORT void structure_ball_scale(void *mols, size_t n, float32_t *bscales)
    33073412{
    33083413    Structure **m = static_cast<Structure **>(mols);
    extern "C" EXPORT void structure_bonds(void *mols, size_t n, pyobject_t *bonds)  
    33343439    }
    33353440}
    33363441
     3442extern "C" EXPORT void structure_num_bonds_visible(void *mols, size_t n, size_t *nbonds)
     3443{
     3444    Structure **m = static_cast<Structure **>(mols);
     3445    try {
     3446        for (size_t i = 0; i != n; ++i)
     3447          {
     3448            const Structure::Bonds &bonds = m[i]->bonds();
     3449            int c = 0;
     3450            for (auto b: bonds)
     3451              if (b->shown())
     3452                c++;
     3453            nbonds[i] = c;
     3454          }
     3455    } catch (...) {
     3456        molc_error();
     3457    }
     3458}
     3459
     3460extern "C" EXPORT void structure_visible_bonds(void *mols, size_t n, pyobject_t *bonds)
     3461{
     3462    Structure **m = static_cast<Structure **>(mols);
     3463    try {
     3464        for (size_t i = 0; i != n; ++i) {
     3465            const Structure::Bonds &b = m[i]->bonds();
     3466            for (size_t j = 0; j != b.size(); ++j) {
     3467                if ( b[j]->shown() )
     3468                    *bonds++ = b[j];
     3469            }
     3470        }
     3471    } catch (...) {
     3472        molc_error();
     3473    }
     3474}
     3475
     3476//~ extern "C" EXPORT void structure_visible_bonds_changed(void *mols, size_t n, npy_bool *changed)
     3477//~ {
     3478    //~ Structure **m = static_cast<Structure **>(mols);
     3479    //~ try {
     3480        //~ for (size_t i = 0; i != n; ++i) {
     3481            //~ *changed++ = m[i]->get_gc_bond_vis();
     3482        //~ }
     3483    //~ } catch (...) {
     3484        //~ molc_error();
     3485    //~ }
     3486//~ }
     3487
     3488//~ extern "C" EXPORT void set_structure_visible_bonds_changed(void *mols, size_t n, npy_bool *changed)
     3489//~ {
     3490    //~ Structure **m = static_cast<Structure **>(mols);
     3491    //~ try {
     3492        //~ for (size_t i = 0; i != n; ++i) {
     3493            //~ if (*changed++) {
     3494                //~ m[i]->set_gc_bond_vis();
     3495            //~ } else {
     3496                //~ m[i]->clear_graphics_change(Structure::ChangeType::BOND_VIS_CHANGE);
     3497            //~ }
     3498        //~ }
     3499    //~ } catch (...) {
     3500        //~ molc_error();
     3501    //~ }
     3502//~ }
     3503
     3504
     3505
     3506
     3507
    33373508extern "C" EXPORT void structure_num_residues(void *mols, size_t n, size_t *nres)
    33383509{
    33393510    Structure **m = static_cast<Structure **>(mols);
  • src/core/atomic/molobject.py

    diff --git a/src/core/atomic/molobject.py b/src/core/atomic/molobject.py
    index a4937f2..2089978 100644
    a b class Atom(State):  
    125125
    126126    def atomspec(self):
    127127        return self.residue.atomspec() + '@' + self.name
    128 
     128   
     129    _changed = c_property('atom_changed', bool, doc='Changed since last redraw')
    129130    alt_loc = c_property('atom_alt_loc', byte, doc='Alternate location indicator')
    130131    bfactor = c_property('atom_bfactor', float32, doc = "B-factor, floating point value.")
    131132    bonds = c_property('atom_bonds', cptr, "num_bonds", astype=_bonds, read_only=True,
    class Bond(State):  
    378379    def atomspec(self):
    379380        return a1.atomspec() + a2.atomspec()
    380381
     382
     383    _changed = c_property('bond_changed', bool, doc='Changed since last redraw')
     384
    381385    atoms = c_property('bond_atoms', cptr, 2, astype = _atom_pair, read_only = True)
    382386    '''Two-tuple of :py:class:`Atom` objects that are the bond end points.'''
    383387    color = c_property('bond_color', uint8, 4)
    class PseudobondGroupData:  
    612616    _COLOR_CHANGE = 0x2
    613617    _SELECT_CHANGE = 0x4
    614618    _RIBBON_CHANGE = 0x8
    615     _ALL_CHANGE = 0xf
     619    _VISIBLE_ATOMS_CHANGE = 0x10
     620    _VISIBLE_BONDS_CHANGE = 0x20
     621    _ALL_CHANGE = 0xff
    616622    _graphics_changed = c_property('pseudobond_group_graphics_change', int32)
    617623
    618624
    class StructureData:  
    14631469    '''Index of the active coordinate set.'''
    14641470    atoms = c_property('structure_atoms', cptr, 'num_atoms', astype = _atoms, read_only = True)
    14651471    ''':class:`.Atoms` collection containing all atoms of the structure.'''
     1472    _visible_atoms = c_property('structure_visible_atoms', cptr, 'num_atoms_visible', astype = _atoms,
     1473                          read_only = True)
     1474    ''':class:`.Atoms` containing only the visible atoms of the structure. Read only.'''
    14661475    ball_scale = c_property('structure_ball_scale', float32,
    14671476        doc = "Scales sphere radius in ball-and-stick style.")
    14681477    bonds = c_property('structure_bonds', cptr, 'num_bonds', astype = _bonds, read_only = True)
    14691478    ''':class:`.Bonds` collection containing all bonds of the structure.'''
     1479    _visible_bonds = c_property('structure_visible_bonds', cptr, 'num_bonds_visible', astype = _bonds,
     1480                          read_only = True)
     1481    ''':class:`.Bonds` containing only the visible bonds of the structure. Read only.'''
    14701482    chains = c_property('structure_chains', cptr, 'num_chains', astype = _chains, read_only = True)
    14711483    ''':class:`.Chains` collection containing all chains of the structure.'''
    14721484    coordset_ids = c_property('structure_coordset_ids', int32, 'num_coordsets', read_only = True)
    class StructureData:  
    14771489    '''Structure has lower case chain ids. Boolean'''
    14781490    num_atoms = c_property('structure_num_atoms', size_t, read_only = True)
    14791491    '''Number of atoms in structure. Read only.'''
    1480     num_atoms_visible = c_property('structure_num_atoms_visible', size_t, read_only = True)
     1492    _num_atoms_visible = c_property('structure_num_atoms_visible', size_t, read_only = True)
    14811493    '''Number of visible atoms in structure. Read only.'''
    14821494    num_bonds = c_property('structure_num_bonds', size_t, read_only = True)
    14831495    '''Number of bonds in structure. Read only.'''
     1496    _num_bonds_visible = c_property('structure_num_bonds_visible', size_t, read_only = True)
     1497    '''Number of visible atoms in structure. Read only.'''
    14841498    num_coordsets = c_property('structure_num_coordsets', size_t, read_only = True)
    14851499    '''Number of coordinate sets in structure. Read only.'''
    14861500    num_chains = c_property('structure_num_chains', size_t, read_only = True)
    class StructureData:  
    17861800    _COLOR_CHANGE = 0x2
    17871801    _SELECT_CHANGE = 0x4
    17881802    _RIBBON_CHANGE = 0x8
    1789     _ALL_CHANGE = 0xf
     1803    _VISIBLE_ATOMS_CHANGE = 0x10
     1804    _VISIBLE_BONDS_CHANGE = 0x20
     1805    _ALL_CHANGE = 0xff
    17901806    _graphics_changed = c_property('structure_graphics_change', int32)
    17911807
    17921808class ChangeTracker:
  • src/core/atomic/structure.py

    diff --git a/src/core/atomic/structure.py b/src/core/atomic/structure.py
    index fb07010..98ddfbe 100644
    a b class Structure(Model, StructureData):  
    5454        self._ribbon_t2r = {}         # ribbon triangles-to-residue map
    5555        self._ribbon_r2t = {}         # ribbon residue-to-triangles map
    5656        self._ribbon_tether = []      # ribbon tethers from ribbon to floating atoms
    57 
     57        self.atoms.radii = self.atoms.default_radii 
     58       
     59        # Cache objects corresponding to currently visible entities, to
     60        # avoid expensive look-ups on redraws.
     61        self._cached_num_atoms_visible = self._num_atoms_visible
     62        self._cached_visible_atoms = self._visible_atoms
     63        self._cached_num_bonds_visible = self._num_bonds_visible
     64        self._cached_visible_bonds = self._visible_bonds   
     65        self._cached_visible_bond_atoms = self.visible_bonds.atoms
     66     
    5867        from . import molobject
    5968        molobject.add_to_object_map(self)
    6069
    class Structure(Model, StructureData):  
    6473                ("save_teardown", "end save session")]:
    6574            self._ses_handlers.append(t.add_handler(trig_name,
    6675                    lambda *args, qual=ses_func: self._ses_call(qual)))
    67 
     76       
    6877        self._make_drawing()
    6978
    7079    def __str__(self):
    class Structure(Model, StructureData):  
    257266        from ..colors import most_common_color
    258267        if ribbon_displays.any():
    259268            return most_common_color(residues.filter(ribbon_displays).ribbon_colors)
    260         atoms = self.atoms
    261         shown = atoms.filter(atoms.displays)
     269        shown = self.visible_atoms
     270        #shown = atoms.filter(atoms.displays)
    262271        if shown:
    263272            return most_common_color(shown.colors)
    264         return most_common_color(atoms.colors)
     273        return most_common_color(self.atoms.colors)
    265274    def _set_single_color(self, color):
    266275        self.atoms.colors = color
    267276        self.residues.ribbon_colors = color
    class Structure(Model, StructureData):  
    269278
    270279    def _make_drawing(self):
    271280        # Create graphics
    272         self._update_atom_graphics()
    273         self._update_bond_graphics()
    274         for pbg in self.pbg_map.values():
    275             pbg._update_graphics()
    276         self._create_ribbon_graphics()
     281        self._update_graphics_if_needed(force_recalc = True)
     282        #~ self._update_atom_graphics()
     283        #~ self._update_bond_graphics()
     284        #~ for pbg in self.pbg_map.values():
     285            #~ pbg._update_graphics()
     286        #~ self._create_ribbon_graphics()
    277287
    278288    @property
    279289    def _level_of_detail(self):
    280290        gu = structure_graphics_updater(self.session)
    281291        return gu.level_of_detail
     292       
     293    @property
     294    def num_atoms_visible(self):
     295        '''
     296        Number of atoms currently visible in this structure. Cached for
     297        performance.
     298        '''
     299        if self._graphics_changed & self._VISIBLE_ATOMS_CHANGE:
     300            self._cached_num_atoms_visible = self._num_atoms_visible
     301        return self._cached_num_atoms_visible
     302   
     303    @property
     304    def visible_atoms(self):
     305        '''
     306        All currently visible atoms in this structure. Cached
     307        for performance.
     308        '''
     309        if self._graphics_changed & self._VISIBLE_ATOMS_CHANGE:
     310            self._cached_visible_atoms = self._visible_atoms
     311        return self._cached_visible_atoms
     312   
     313    @property
     314    def num_bonds_visible(self):
     315        '''
     316        Number of bonds currently visible in this structure. Cached
     317        for performance.
     318        '''
     319        if self._graphics_changed & self._VISIBLE_BONDS_CHANGE:
     320            self._cached_num_bonds_visible = self._num_bonds_visible
     321        return self._cached_num_bonds_visible
    282322
     323    @property
     324    def visible_bonds(self):
     325        '''
     326        All currently visible bonds in this structure. Cached for
     327        performance.
     328        '''
     329        if self._graphics_changed & self._VISIBLE_BONDS_CHANGE:
     330            self._cached_visible_bonds = self._visible_bonds
     331        return self._cached_visible_bonds
     332   
     333    @property
     334    def visible_bond_atoms(self):
     335        '''
     336        A tuple of :class:`Atoms` giving all atoms involved in
     337        currently visible bonds. Equivalent to self.visible_bonds.atoms,
     338        but cached for performance.
     339        '''
     340        if self._graphics_changed & self._VISIBLE_BONDS_CHANGE:
     341            self._cached_visible_bond_atoms = self.visible_bonds.atoms
     342        return self._cached_visible_bond_atoms
     343       
    283344    def new_atoms(self):
    284345        # TODO: Handle instead with a C++ notification that atoms added or deleted
    285346        self._atom_bounds_needs_update = True
    286347
    287     def _update_graphics_if_needed(self, *_):
     348    def _update_graphics_if_needed(self, *_, force_recalc = False):
    288349        gc = self._graphics_changed
    289         if gc == 0:
     350        if gc == 0 and not force_recalc:
    290351            return
    291 
     352       
     353       
    292354        if gc & self._RIBBON_CHANGE:
    293355            self._create_ribbon_graphics()
    294356            # Displaying ribbon can set backbone atom hide bits producing shape change.
    295357            gc |= self._graphics_changed
    296358
    297359        # Update graphics
    298         self._graphics_changed = 0
    299360        s = (gc & self._SHAPE_CHANGE)
    300361        if gc & (self._COLOR_CHANGE | self._RIBBON_CHANGE) or s:
    301362            self._update_ribbon_tethers()
    302         self._update_graphics(gc)
     363        self._update_graphics(gc, force_recalc = force_recalc)
     364        self._graphics_changed = 0
    303365        self.redraw_needed(shape_changed = s,
    304366                           selection_changed = (gc & self._SELECT_CHANGE))
    305367        if s:
    class Structure(Model, StructureData):  
    313375                if isinstance(surf, MolecularSurface):
    314376                    surf.update_selection()
    315377
    316     def _update_graphics(self, changes = StructureData._ALL_CHANGE):
    317         self._update_atom_graphics(changes)
    318         self._update_bond_graphics(changes)
     378    def _update_graphics(self, changes = StructureData._ALL_CHANGE, force_recalc = False):
     379        import numpy
     380        atoms = self.visible_atoms
     381        bonds = self.visible_bonds
     382        bond_atoms = self.visible_bond_atoms
     383       
     384        force_atom_recalc = False
     385        force_bond_recalc = False
     386       
     387        if force_recalc:
     388            force_atom_recalc = True
     389            force_bond_recalc = True
     390       
     391        else:
     392            if changes & self._VISIBLE_ATOMS_CHANGE:
     393                force_atom_recalc = True
     394                self._graphics_changed ^= self._VISIBLE_ATOMS_CHANGE
     395           
     396            if changes & self._VISIBLE_BONDS_CHANGE:
     397                force_bond_recalc = True
     398                self._graphics_changed ^= self._VISIBLE_BONDS_CHANGE
     399       
     400       
     401        if force_atom_recalc:
     402            achanged = numpy.array([True]*len(atoms))
     403            ch_atoms = atoms
     404        else:
     405            achanged = atoms._changed
     406            ch_atoms = atoms[achanged]
     407       
     408        if force_bond_recalc:
     409            bchanged = numpy.array([True]*len(bonds))
     410            ch_bonds = bonds
     411            ch_bond_atoms = bond_atoms
     412        else:
     413            bchanged = bonds._changed
     414            ch_bonds = bonds[bchanged]
     415            ch_bond_atoms = (ba[bchanged] for ba in bond_atoms)
     416           
     417       
     418        half_bond_change_filter = numpy.concatenate((bchanged,bchanged))
     419       
     420        self._update_atom_graphics( ch_atoms, achanged, changes = changes,
     421                                    force_recalc = force_atom_recalc)
     422        self._update_bond_graphics(ch_bonds, ch_bond_atoms,
     423                                    half_bond_change_filter,
     424                                    changes = changes,
     425                                    force_recalc = force_bond_recalc)
    319426        for pbg in self.pbg_map.values():
    320427            pbg._update_graphics(changes)
    321428        self._update_ribbon_graphics()
     429        self.redraw_needed()
    322430
    323     def _update_atom_graphics(self, changes = StructureData._ALL_CHANGE):
    324         atoms = self.atoms  # optimzation, avoid making new numpy array from C++
    325         avis = atoms.visibles
     431    def _update_atom_graphics(self, atoms, ch_filter, changes = StructureData._ALL_CHANGE, force_recalc = False):
     432        import numpy
    326433        p = self._atoms_drawing
     434        from numpy import empty, float32, multiply
     435        #ch_indices = numpy.where(ch_filter)[0]
     436       
    327437        if p is None:
    328             if avis.sum() == 0:
    329                 return
     438            #avis = atoms.visibles
     439            #if avis.sum() == 0:
     440            #    return
    330441            self._atoms_drawing = p = self.new_drawing('atoms')
    331442            self._atoms_drawing.custom_x3d = self._custom_atom_x3d
    332443            # Update level of detail of spheres
    333444            self._level_of_detail.set_atom_sphere_geometry(p)
     445   
     446        if force_recalc:
     447            n = len(atoms)
     448            xyzr = empty((n, 4), float32)
     449            xyzr[:, :3] = atoms.coords
     450            xyzr[:, 3] = self._atom_display_radii(atoms)
    334451
     452            from ..geometry import Places
     453            p.colors = atoms.colors
     454            p.positions = Places(shift_and_scale=xyzr)
     455            p.display_positions = numpy.array([True]*len(atoms))
     456            p.selected_positions = atoms.selected if atoms.num_selected > 0 else None
     457            atoms._changed = False
     458            return
     459       
     460       
    335461        if changes & self._SHAPE_CHANGE:
    336462            # Set instanced sphere center position and radius
    337463            n = len(atoms)
    338             from numpy import empty, float32, multiply
    339464            xyzr = empty((n, 4), float32)
    340465            xyzr[:, :3] = atoms.coords
    341466            xyzr[:, 3] = self._atom_display_radii(atoms)
    342 
     467           
    343468            from ..geometry import Places
    344             p.positions = Places(shift_and_scale=xyzr)
    345             p.display_positions = avis
     469            p.positions.set_shift_and_scale(ch_filter, xyzr)
     470            # So the drawing knows it needs to redraw positions
     471            p.positions_changed()
     472            #p.display_positions = avis
     473           
    346474
    347         if changes & (self._COLOR_CHANGE | self._SHAPE_CHANGE):
     475        if changes & (self._COLOR_CHANGE): # | self._SHAPE_CHANGE):
    348476            # Set atom colors
    349             p.colors = atoms.colors
     477            p.set_colors(atoms.colors, ch_filter)
    350478
    351         if changes & (self._SELECT_CHANGE | self._SHAPE_CHANGE):
     479        if changes & (self._SELECT_CHANGE ): #| self._SHAPE_CHANGE):
    352480            # Set selected
    353             p.selected_positions = atoms.selected if atoms.num_selected > 0 else None
     481            vatoms = self.visible_atoms
     482            p.selected_positions = vatoms.selected if vatoms.num_selected > 0 else None
     483        atoms._changed = False
    354484
    355485    def _custom_atom_x3d(self, stream, x3d_scene, indent, place):
    356486        from numpy import empty, float32
    357487        p = self._atoms_drawing
    358         atoms = self.atoms
     488        atoms = self.visible_atoms
    359489        radii = self._atom_display_radii(atoms)
    360490        tab = ' ' * indent
    361491        for v, xyz, r, c in zip(p.display_positions, atoms.coords, radii, p.colors):
    class Structure(Model, StructureData):  
    371501    def _atom_display_radii(self, atoms):
    372502        return atoms.display_radii(self.ball_scale, self.bond_radius)
    373503   
    374     def _update_bond_graphics(self, changes = StructureData._ALL_CHANGE):
    375         bonds = self.bonds  # optimzation, avoid making new numpy array from C++
     504    def _update_bond_graphics(self, bonds, bond_atoms,
     505                                ch_filter, changes = StructureData._ALL_CHANGE,
     506                                force_recalc = False):
     507        import numpy
     508        #ch_indices = numpy.where(ch_filter)[0]
    376509        p = self._bonds_drawing
    377510        if p is None:
    378             if bonds.num_shown == 0:
    379                 return
     511            #if bonds.num_shown == 0:
     512            #    return
    380513            self._bonds_drawing = p = self.new_drawing('bonds')
    381514            self._bonds_drawing.custom_x3d = self._custom_bond_x3d
    382515            # Update level of detail of cylinders
    383516            self._level_of_detail.set_bond_cylinder_geometry(p)
    384 
    385         if changes & (self._SHAPE_CHANGE | self._SELECT_CHANGE):
    386             bond_atoms = bonds.atoms
    387         if changes & self._SHAPE_CHANGE:
     517       
     518        if force_recalc:
     519            #bond_atoms = bonds.atoms
    388520            ba1, ba2 = bond_atoms
     521            p.colors = bonds.half_colors
    389522            p.positions = _halfbond_cylinder_placements(ba1.coords, ba2.coords, bonds.radii)
    390523            p.display_positions = _shown_bond_cylinders(bonds)
    391         if changes & (self._COLOR_CHANGE | self._SHAPE_CHANGE):
    392             p.colors = c = bonds.half_colors
    393         if changes & (self._SELECT_CHANGE | self._SHAPE_CHANGE):
    394524            p.selected_positions = _selected_bond_cylinders(bond_atoms)
     525            bonds._changed = False
     526            return
     527       
     528        if changes & self._SHAPE_CHANGE:
     529            ba1, ba2 = bond_atoms
     530            p.positions.set_opengl_matrices(ch_filter,
     531                _halfbond_cylinder_placements(ba1.coords, ba2.coords, bonds.radii)._opengl_array)
     532            p.positions_changed()
     533            #p.display_positions = ch_filter #_shown_bond_cylinders(bonds)
     534        if changes & (self._COLOR_CHANGE): # | self._SHAPE_CHANGE):
     535            p.set_colors(bonds.half_colors, ch_filter)
     536        if changes & (self._SELECT_CHANGE):# | self._SHAPE_CHANGE):
     537            vbonds = self.visible_bonds
     538            p.selected_positions = _selected_bond_cylinders(vbonds.atoms)
     539        bonds._changed = False
    395540
    396541    def _custom_bond_x3d(self, stream, x3d_scene, indent, place):
    397542        from numpy import empty, float32
    398543        p = self._bonds_drawing
    399         bonds = self.bonds
     544        bonds = self.visible_bonds
    400545        ba1, ba2 = bonds.atoms
    401546        cyl_info = _halfbond_cylinder_x3d(ba1.coords, ba2.coords, bonds.radii)
    402547        tab = ' ' * indent
    class Structure(Model, StructureData):  
    13751520
    13761521    def _update_ribbon_graphics(self):
    13771522        # Set selected ribbons in graphics
     1523        if not self.ribbon_display_count:
     1524            return
    13781525        from .molarray import Residues
    1379         atoms = self.atoms
     1526        atoms = self.visible_atoms
    13801527        if atoms.num_selected > 0:
    13811528            residues = atoms.filter(atoms.selected).unique_residues
    13821529            from numpy import array
    class Structure(Model, StructureData):  
    14231570                p.selected_triangles_mask = m
    14241571
    14251572    def _update_ribbon_tethers(self):
     1573        if not self.ribbon_display_count:
     1574            return
    14261575        from numpy import around
    14271576        for all_atoms, tp, xyz1, tether_atoms, shape, scale in self._ribbon_tether:
    14281577            all_atoms.update_ribbon_visibility()
    class Structure(Model, StructureData):  
    14501599    def _atom_bounds(self):
    14511600        if not self._atom_bounds_needs_update:
    14521601            return self._cached_atom_bounds
    1453         a = self.atoms
    1454         adisp = a[a.displays]
    1455         xyz = adisp.coords
    1456         radii = adisp.radii
     1602        a = self.visible_atoms
     1603        xyz = a.coords
     1604        radii = a.display_radii(self.ball_scale, self.bond_radius)
    14571605        # TODO: Currently 40% of time is taken in getting atom radii because
    14581606        #       they are recomputed from element and bonds every time. Ticket #789.
    14591607        #       If that was fixed by using a precomputed radius, then it would make
    class Structure(Model, StructureData):  
    15311679
    15321680        if not dp is None:
    15331681            anum = dp.nonzero()[0][anum]    # Remap index to include undisplayed positions
    1534         atom = self.atoms[anum]
     1682        atom = self.visible_atoms[anum]
    15351683
    15361684        # Create pick object
    15371685        s = PickedAtom(atom, fmin)
    class Structure(Model, StructureData):  
    15411689    def _bond_first_intercept(self, mxyz1, mxyz2):
    15421690        d = self._bonds_drawing
    15431691        if d and d.display:
    1544             b,f = _bond_intercept(self.bonds, mxyz1, mxyz2)
     1692            b,f = _bond_intercept(self.visible_bonds, mxyz1, mxyz2)
    15451693            if b:
    15461694                return PickedBond(b, f)
    15471695        return None
    class Structure(Model, StructureData):  
    16031751        if pmask.sum() == 0:
    16041752            return []
    16051753
    1606         a = self.atoms
     1754        a = self.visible_atoms
    16071755        if not dp is None:
    16081756            anum = dp.nonzero()[0][pmask]    # Remap index to include undisplayed positions
    16091757            atoms = a.filter(anum)
  • src/core/geometry/place.py

    diff --git a/src/core/geometry/place.py b/src/core/geometry/place.py
    index f5e8bc1..b509ed2 100644
    a b class Places:  
    423423    '''
    424424    def __init__(self, places=None, place_array=None, shift_and_scale=None,
    425425                 opengl_array=None):
     426        import numpy
    426427        if (place_array is not None or shift_and_scale is not None
    427428                or opengl_array is not None):
    428429            pl = None
    class Places:  
    508509    def __setitem__(self, i, p):
    509510        self._place_list[i] = p
    510511
     512    def set_shift_and_scale(self, indices_or_mask, shift_and_scale_array):
     513        self._shift_and_scale[indices_or_mask] = shift_and_scale_array
     514   
     515    def set_opengl_matrices(self, indices_or_mask, opengl_array):
     516        self._opengl_array[indices_or_mask] = opengl_array
     517   
    511518    def __len__(self):
    512519        if self._place_list is not None:
    513520            n = len(self._place_list)
  • src/core/graphics/drawing.py

    diff --git a/src/core/graphics/drawing.py b/src/core/graphics/drawing.py
    index b11585f..3766fbe 100644
    a b class Drawing:  
    466466    def get_colors(self):
    467467        return self._colors
    468468
    469     def set_colors(self, rgba):
     469    def set_colors(self, rgba, indices_or_mask = None):
    470470        from numpy import ndarray, array, uint8
    471471        c = rgba if isinstance(rgba, ndarray) else array(rgba, uint8)
    472         self._colors = c
     472        if indices_or_mask is None:
     473            self._colors = c
     474        else:
     475            self._colors[indices_or_mask] = c
     476            self._attribute_changes.add('_colors')
    473477        self._opaque_color_count = opaque_count(c)
    474         self.redraw_needed()
    475478
    476479    colors = property(get_colors, set_colors)
    477480    '''Color for each position used when per-vertex coloring is not