Opened 9 years ago

Closed 8 years ago

#599 closed defect (not a bug)

"Transplanting" a model loses track of children

Reported by: Tristan Croll Owned by: Tom Goddard
Priority: major Milestone: Alpha2
Component: Infrastructure Version:
Keywords: Cc:
Blocked By: Blocking:
Notify when closed: Platform: all
Project: ChimeraX

Description

Hi all,

I'm trying to do some rearrangements of my data handling for the Clipper plugin, to make it all work more neatly with the ChimeraX framework. What I'm aiming for is something like the following:

class CrystalStructure(Model):
  '''
  Master container class for a crystal structure, designed to act as the
  head node of a Model tree with the following general format:
  
  CrystalStructure
    |
    -- master model (AtomicStructure)
    |
    -- symmetry copies (SymModels)
    |    |
    |    -- AtomicStructure
    |    |
    |    -- AtomicStructure
    |    |
    |    -- ...
    |
    -- reciprocal space data (MTZData)
    |    |
    |    -- clippper.HKL_info
    |    |
    |    -- clipper.HKL_data_Flag
    |    |
    |    -- clipper.HKL_data_F_Phi
    |    |
    |    -- ...
    |
    -- real-space maps (XMapSet)
         |
         -- 2mFo-Fc (Volume)
         |
         -- ...
  '''

... so that everything associated with the model remains together in the one neat tree in the Models panel etc. I'd like to be able to initiate it from an already-loaded AtomicStructure, which would necessitate removing the AtomicStructure from the existing tree and adding it to the CrystalStructure model. This works to an extent. When I've loaded a single Atomic model:

from chimerax.core.models import Model
m = session.models.list()[0]
newm = Model('test', session)
session.models.remove([m])
newm.add([m])
session.models.add([newm])

... gives me m subordinate to newm as I wanted - BUT any children of m (e.g. the 'missing structure' PseudobondGroup) disappear. That's not the behaviour I expected - I think the sensible thing would be to have copying/moving behave just like directories in the filesystem - everything below the chosen node comes along with it.

Change History (3)

comment:1 by Tristan Croll, 9 years ago

The following addition to chimerax.core.models appears to behave itself:

    def move_model(self, model, new_parent):
        '''
        Move a model (and all its children) from its current position 
        in the tree and add it as a child of new_parent.
        '''
        session = self._session()
        mlist = model.all_models()
        model_id = model.id            
        if new_parent in mlist:
            raise RuntimeError('Target model cannot be one of the models being moved!')
        for m in mlist:
            m.removed_from_session(session)
            mid = m.id
            if mid is not None:
                del self._models[mid]
                m.id = None
        session.triggers.activate_trigger(REMOVE_MODELS, mlist)
        if len(model_id) == 1:
            parent = self.drawing
        else:
            parent = self._models[model_id[:-1]]
        parent.remove_drawing(model, delete=False)
        parent._next_unused_id = None
        new_parent.add([model])

Testing:

# m is model 1
m = session.models.list()[0]
from chimerax.core.models import Model
newm1 = Model('target1', session)
newm2 = Model('target2', session)
session.models.add([newm1, newm2])
session.models.move_model(m, newm1)
# m is now model 2.1 under target1
session.models.move_model(m, newm2)
# m is now model 3.1 under target2

I've done some minimal stability testing (trying all the different visualisation buttons), and everything appears to be fine.

comment:2 by Tom Goddard, 8 years ago

Owner: set to Tom Goddard
Status: newassigned

The way to do this is to not do the models.remove() call, simply add the existing model to the new model.

m = session.models.list()[0]
newm = Model('test', session)
newm.add([m])
session.models.add([newm])

The remove() call removes the model and detaches all its children and is typically used only when deleting a model.

The long wait for a reply to this ticket is because you added it without assigning an owner, so no one ever saw it.

comment:3 by Tom Goddard, 8 years ago

Resolution: not a bug
Status: assignedclosed
Note: See TracTickets for help on using tickets.