Example #1
0
    def execute(self, context):
        first_atom = context.scene.objects.get(self.first_atom_name)

        if first_atom and first_atom.mb.type != 'ATOM':
            self.first_atom_name = " "
            first_atom = None
        
        if self.first_atom_name.strip() and not first_atom:
            logger.debug('Object "{}" not found.'.format(self.first_atom_name))
            return {'CANCELLED'}
        
        if first_atom:
            molecule = first_atom.mb.get_molecule()
        else:
            molecule = context.scene.mb.new_molecule()
        
        # create a new atom object with the molecule's properties
        
        new_atom = mb_utils.add_atom(context, self.coord_3d, self.element,
                                     self.element, molecule.atom_index+1,
                                     molecule)
        self.new_atom_name = new_atom.name
        
        # add a bond if atom is added to existing molecule
        if first_atom:
            new_bond = mb_utils.add_bond(context, first_atom, new_atom)
            self.new_bond_name = new_bond.name
            new_bond.select = True
        
        context.scene.objects.active = new_atom
        new_atom.select = True
        return {'FINISHED'}
Example #2
0
def import_molecule(context,
                    report,
                    filepath,
                    molecule,
                    refine_atoms,
                    refine_bonds,
                    bond_material,
                    bond_type,
                    auto_unit,
                    scale_distances,
                    bond_guess,
                    put_origin,
                    parent_center,
                    mask_planes,
                    mask_flip,
                    draw_uc,
                    supercell,
                    ):
    
    try:
        
        all_obs = []
        all_obs.append(molecule.objects.parent)
        
        structure = mb_io_files.MB_Structure.from_file(
            filepath,
            auto_unit=auto_unit,
            unit_fac=scale_distances,
            )
        
        # some sanity checks
        if not structure.all_atoms:
            msg = "No atoms found in {}. ".format(filepath)
            msg += "Please check file format and/or MolBlend code."
            logger.error(msg)
            report({'ERROR'}, msg)
            return False
        
        logger.debug("Found {} frames in {}".format(structure.nframes,
                                                    filepath))

        molecule["unit_cells"] = structure.axes
        
        if draw_uc and molecule["unit_cells"]:
            # read unit cell and create cube
            unit_cell_obs = mb_utils.draw_unit_cell(molecule, context)
            all_obs.extend(unit_cell_obs)
        elif draw_uc and not molecule["unit_cells"]:
            msg = "No unit cell vectors read."
            logger.warning(msg)
            report({'WARNING'}, msg)
        
        if sum(supercell) > 3:
            structure.create_supercell(supercell)
        
        if mask_planes:
            structure.apply_mask(mask_planes, mask_flip)
        
        if bond_guess:
            structure.guess_bonds(tol=0.2)
        
        if parent_center:
            center_of_mass = structure.get_center_of_mass()
        else:
            center_of_mass = Vector(structure.origin)
        
        molecule.objects.parent.location = center_of_mass
        
        # add all atoms to scene
        atom_obs = {}
        warning = set()
        for index, atom in sorted(structure.all_atoms.items()):
            new_atom = mb_utils.add_atom(context,
                                         atom["coords"][0]-center_of_mass,
                                         atom["element"],
                                         atom["name"],
                                         index, #atom["id"],
                                         molecule)
            new_atom.mb.supercell = atom.get("supercell", (0,0,0))
            all_obs.append(new_atom)
            new_atom.mb.index = index
            atom_obs[index] = new_atom
            
            if structure.nframes > 1:
                anim_data = new_atom.animation_data_create()
                atom_id = '{}.{}'.format(new_atom.mb.get_molecule().name,
                                         new_atom.mb.index)
                action = bpy.data.actions.new(name="frames_{}".format(atom_id))
                anim_data.action = action
                ag = action.groups.new("Location")
                
                for dim in range(3):
                    fcu = action.fcurves.new(data_path="location", index=dim)
                    fcu.group = ag
                    for nf in range(structure.nframes):
                        coord = structure.all_atoms[index]["coords"][nf]
                        loc = (coord-center_of_mass)[dim]
                        fcu.keyframe_points.add(1)
                        fcu.keyframe_points[-1].co = nf + 1, loc
                        fcu.keyframe_points[-1].interpolation = 'LINEAR'
        molecule.atom_index = index
        # add bonds to scene
        for index1, other in structure.bonds.items():
            for index2 in other:
                try:
                    new_bond = mb_utils.add_bond(context, atom_obs[index1],
                                                atom_obs[index2],
                                                bond_type=bond_type)
                except KeyError as err:
                    if not err.args:
                        err.args=('',)
                    msg = "Atom index {} was found in CONECT"
                    msg += " but not in the list of atoms"
                    msg = msg.format(err.args[0])
                    err.args = (msg, )
                    report({'ERROR'}, msg)
                    raise
                all_obs.append(new_bond)
        molecule.bond_material = bond_material
        
        if warning:
            logger.warning('\n'.join(warning))
        
        if put_origin:
            molecule.objects.parent.location -= center_of_mass
        
        # select all objects and make parent active
        bpy.ops.object.select_all(action="DESELECT")
        context.scene.objects.active = molecule.objects.parent
        #for ob in all_obs:
            #ob.select = True
        
        return True

    except:
        # if something bad happend, delete all objects and re-raise
        logger.debug("Trying to delete all newly imported objects.")
        report({'ERROR'}, "Something went wrong in import. Check console.")
        for ob in all_obs:
            context.scene.objects.unlink(ob)
            bpy.data.objects.remove(ob)
        logger.exception('')
        return False
Example #3
0
 def modal(self, context, event):
     mouse_2d = event.mouse_x, event.mouse_y
     self.coord_3d = mb_utils.mouse_2d_to_location_3d(
         context, mouse_2d, region=self.region, 
         rv3d=self.rv3d, depth=self.depth_location)
     
     if event.type == 'MOUSEMOVE':
         new_atom = context.scene.objects.get(self.new_atom_name)
         context.scene.objects.active = new_atom
         new_atom.select = True
         new_bond = context.scene.objects.get(self.new_bond_name)
         first_atom = context.scene.objects.get(self.first_atom_name)
         
         hover_ob = mb_utils.return_cursor_object(
             context, event, exclude=[new_atom], mb_type='ATOM')
         if hover_ob:
             new_atom.draw_bounds_type = 'SPHERE'
             new_atom.draw_type = 'BOUNDS'
             if new_bond:
                 new_bond.constraints["mb.stretch"].target = hover_ob
         else:
             new_atom.draw_type = 'SOLID'
             if new_bond:
                 new_bond.constraints["mb.stretch"].target = new_atom
                 if not event.alt:
                     self.coord_3d = mb_geometry.get_fixed_geometry(
                         context, first_atom, new_atom, self.coord_3d,
                         self.geometry)
                 
                 if event.ctrl:
                      # constrain length
                     self.coord_3d = mb_geometry.get_fixed_length(
                         context, first_atom, new_atom, self.coord_3d,
                         length=-1)
         
         new_atom.location = self.coord_3d - self.parent_coord_3d
         # sometimes, when bond is exactly along axis, the dimension goes
         # to zero due to the stretch constraint
         # check for this case and fix it
         if new_bond:
             mb_utils.check_ob_dimensions(new_bond)
     
     elif event.type == 'LEFTMOUSE' and event.value == 'RELEASE':
         # check if new atom is above already existing atom
         new_atom = context.object
         first_atom = context.scene.objects.get(self.first_atom_name)
         hover_ob = mb_utils.return_cursor_object(
             context, event, exclude=[new_atom], mb_type='ATOM')
         if hover_ob:
             mol = new_atom.mb.get_molecule()
             mol.remove_object(new_atom)
             mol.atom_index -= 1
             context.scene.objects.unlink(new_atom)
             bpy.data.objects.remove(new_atom)
             new_bond = context.scene.objects.get(self.new_bond_name)
             if new_bond:
                 mol.remove_object(new_bond)
                 context.scene.objects.unlink(new_bond)
                 bpy.data.objects.remove(new_bond)
                 mb_utils.add_bond(context, first_atom, hover_ob)
         return {'FINISHED'}
     
     return {'RUNNING_MODAL'}
def import_molecule(
    context,
    report,
    filepath,
    molecule,
    refine_atoms,
    refine_bonds,
    bond_material,
    bond_type,
    auto_unit,
    scale_distances,
    bond_guess,
    put_origin,
    parent_center,
    mask_planes,
    mask_flip,
    draw_uc,
    supercell,
):

    try:

        all_obs = []
        all_obs.append(molecule.objects.parent)

        structure = mb_io_files.MB_Structure.from_file(
            filepath,
            auto_unit=auto_unit,
            unit_fac=scale_distances,
        )

        # some sanity checks
        if not structure.all_atoms:
            msg = "No atoms found in {}. ".format(filepath)
            msg += "Please check file format and/or MolBlend code."
            logger.error(msg)
            report({'ERROR'}, msg)
            return False

        logger.debug("Found {} frames in {}".format(structure.nframes,
                                                    filepath))

        molecule["unit_cells"] = structure.axes

        if draw_uc and molecule["unit_cells"]:
            # read unit cell and create cube
            unit_cell_obs = mb_utils.draw_unit_cell(molecule, context)
            all_obs.extend(unit_cell_obs)
        elif draw_uc and not molecule["unit_cells"]:
            msg = "No unit cell vectors read."
            logger.warning(msg)
            report({'WARNING'}, msg)

        if sum(supercell) > 3:
            structure.create_supercell(supercell)

        if mask_planes:
            structure.apply_mask(mask_planes, mask_flip)

        if bond_guess:
            structure.guess_bonds(tol=0.2)

        if parent_center:
            center_of_mass = structure.get_center_of_mass()
        else:
            center_of_mass = Vector(structure.origin)

        molecule.objects.parent.location = center_of_mass

        # add all atoms to scene
        atom_obs = {}
        warning = set()
        for index, atom in sorted(structure.all_atoms.items()):
            new_atom = mb_utils.add_atom(
                context,
                atom["coords"][0] - center_of_mass,
                atom["element"],
                atom["name"],
                index,  #atom["id"],
                molecule)
            new_atom.mb.supercell = atom.get("supercell", (0, 0, 0))
            all_obs.append(new_atom)
            new_atom.mb.index = index
            atom_obs[index] = new_atom

            if structure.nframes > 1:
                anim_data = new_atom.animation_data_create()
                atom_id = '{}.{}'.format(new_atom.mb.get_molecule().name,
                                         new_atom.mb.index)
                action = bpy.data.actions.new(name="frames_{}".format(atom_id))
                anim_data.action = action
                ag = action.groups.new("Location")

                for dim in range(3):
                    fcu = action.fcurves.new(data_path="location", index=dim)
                    fcu.group = ag
                    for nf in range(structure.nframes):
                        coord = structure.all_atoms[index]["coords"][nf]
                        loc = (coord - center_of_mass)[dim]
                        fcu.keyframe_points.add(1)
                        fcu.keyframe_points[-1].co = nf + 1, loc
                        fcu.keyframe_points[-1].interpolation = 'LINEAR'
        molecule.atom_index = index
        # add bonds to scene
        for index1, other in structure.bonds.items():
            for index2 in other:
                try:
                    new_bond = mb_utils.add_bond(context,
                                                 atom_obs[index1],
                                                 atom_obs[index2],
                                                 bond_type=bond_type)
                except KeyError as err:
                    if not err.args:
                        err.args = ('', )
                    msg = "Atom index {} was found in CONECT"
                    msg += " but not in the list of atoms"
                    msg = msg.format(err.args[0])
                    err.args = (msg, )
                    report({'ERROR'}, msg)
                    raise
                all_obs.append(new_bond)
        molecule.bond_material = bond_material

        if warning:
            logger.warning('\n'.join(warning))

        if put_origin:
            molecule.objects.parent.location -= center_of_mass

        # select all objects and make parent active
        bpy.ops.object.select_all(action="DESELECT")
        context.scene.objects.active = molecule.objects.parent
        #for ob in all_obs:
        #ob.select = True

        return True

    except:
        # if something bad happend, delete all objects and re-raise
        logger.debug("Trying to delete all newly imported objects.")
        report({'ERROR'}, "Something went wrong in import. Check console.")
        for ob in all_obs:
            context.scene.objects.unlink(ob)
            bpy.data.objects.remove(ob)
        logger.exception('')
        return False