Example #1
0
def open_mode(ascii_file, mode_index, supercell=[2,2,2], animate=True, n_frames=30, vectors=False, bbox=True, bbox_offset=(0,0,0), scale_factor=1.0, vib_magnitude=1.0, arrow_magnitude=1.0):
    """
    Open v_sim ascii file in Blender

    Arguments:
        ascii_file: Path to file
        mode_index: integer id of mode; 0 corresponds to first mode in ascii file
        supercell: 3-tuple or list of integer supercell dimensions
        animate: Boolean: if True, add animation keyframes
        n_frames: Animation length in frames
        vectors: Boolean; if True, show arrows
        bbox: Boolean; if True, show bounding box
        bbox_loc: Vector or 3-tuple in lattice vector coordinates; position of bbox. Default (0,0,0) (Left front bottom)

    """

    vsim_cell, positions, symbols, vibs = import_vsim(ascii_file)
    lattice_vectors = cell_vsim_to_vectors(vsim_cell)
    
    # Switch to a new empty scene
    bpy.ops.scene.new(type='EMPTY')
    
    # Draw bounding box #
    if bbox:
        bbox_offset = Vector(bbox_offset)
        draw_bounding_box(lattice_vectors, offset=bbox_offset)

    # Draw atoms
    for cell_id_tuple in itertools.product(range(supercell[0]),range(supercell[1]),range(supercell[2])):
        cell_id = Vector(cell_id_tuple)
        for atom_index, (position, symbol) in enumerate(zip(positions, symbols)):
            atom = add_atom(position,lattice_vectors,symbol,cell_id=cell_id, name = '{0}_{1}_{2}{3}{4}'.format(atom_index,symbol,*cell_id_tuple), scale_factor=scale_factor)
            displacement_vector = vibs[mode_index].vectors[atom_index]
            qpt = vibs[mode_index].qpt
            B = 2 * math.pi * Matrix(lattice_vectors).inverted().transposed()
            qpt_cartesian = Vector(qpt) * B
            
            if animate:
                animate_atom_vibs(atom, qpt_cartesian, displacement_vector,
                                  n_frames=n_frames, magnitude=vib_magnitude)
            if vectors:
                arrow_vector=vector_with_phase(atom, qpt_cartesian, displacement_vector)

                add_arrow(loc=absolute_position(position, lattice_vectors=lattice_vectors,
                                                cell_id=cell_id),
                          rot_euler=vector_to_euler(arrow_vector),
                          scale=arrow_vector.length*arrow_magnitude)
            
    # Position camera and colour world
    # Note that cameras as objects and cameras as 'cameras' have different attributes,
    # so need to look up camera in bpy.data.cameras to set field of view.

    field_of_view = 0.5 # Camera field of view in radians

    camera_x = (lattice_vectors[0][0]/2. + lattice_vectors[2][0]/2.) * supercell[0]
    camera_y = max(((abs(lattice_vectors[0][0]) + abs(lattice_vectors[2][0]) + 2) * supercell[0],
                    abs(lattice_vectors[2][2]) * supercell[2] + 2)) / (-2. * math.tan(field_of_view/2.))
    camera_z = lattice_vectors[2][2]/2. * supercell[2]
    camera_loc=( camera_x,
                 1.05 * camera_y,
                camera_z)
    bpy.ops.object.camera_add(location=camera_loc,rotation=(math.pi/2,0,0))
    camera = bpy.context.object
    bpy.context.scene.camera = camera
    bpy.data.cameras[camera.name].angle = field_of_view

    bpy.context.scene.world = bpy.data.worlds['World']
    bpy.data.worlds['World'].horizon_color = [0.5, 0.5, 0.5]
Example #2
0
def open_mode(**options):
    """
    Open v_sim ascii file in Blender

    :param input_file: Path to file
    :type input_file: str
    :param camera_rot: Camera tilt adjustment in degrees
    :type camera_rot: float
    :param config: Settings from configuration files
    :type config: configparser.ConfigParser
    :param mass_weighting: Weight eigenvectors by mass.
        This has usually already been done when generating the .ascii file,
        in which case the default value of 0 is acceptable.
        A value of 1 corresponds to the formally correct mass scaling of m^-0.5
        for non-weighted eigenvectors.
        A value of -1 will REMOVE existing mass-weighting.
        In-between values may be useful for re-scaling to see the range of
        movements in a system, but are not physically meaningful.
    :type mass_weighting: float
    :param end_frame: The ending frame number of the rendered Animation
        (default=start_frame+n_frames-1)
    :type end_frame: int or None
    :param miller: Miller indices of view
    :type miller: 3-tuple of floats
    :param mode_index: id of mode; 0 corresponds to first mode in ascii file
    :type mode_index: int
    :param n_frames: Animation length of a single oscillation
        cycle in frames (default=30)
    :type n_frames: Positive int
    :param normalise_vectors: Re-scale vectors so largest arrow is fixed length
    :type normalise_vectors: bool
    :param offset_box: Position of bbox in lattice vector coordinates.
        Default (0,0,0) (Left front bottom)
    :type offset_box: Vector or 3-tuple
    :param preview: Enable preview mode - single frame, smaller render
    :type preview: bool
    :param scale_arrow: Scale factor for arrows
    :type scale_arrow: float
    :param scale_atom: Scale of atoms, relative to covalent radius
    :type scale_atom: float
    :param scale_vib: Scale factor for oscillations
        (angstroms / normalised eigenvector).
    :type scale_vib: float
    :param show_box: If True, show bounding box
    :type show_box: bool
    :param start_frame: The starting frame number of the rendered
        animation (default=0)
    :type start_frame: int or None
    :param static: if True, ignore frame range and use single frame.
        Otherwise, add animation keyframes.
    :type static: bool
    :param supercell: supercell dimensions
    :type supercell: 3-tuple or 3-list of ints
    :param vectors: If True, show arrows
    :type vectors: bool
    :param zoom: Camera zoom adjustment
    :type zoom: float

    """

    # Initialise Opts object, accessing options and user config
    opts = vsim2blender.Opts(options)

    # Work out actual frame range.
    # Priority goes 1. static/preview 2. end_frame 3. n_frames
    start_frame = opts.get('start_frame', 0)
    n_frames = opts.get('n_frames', 30)

    # Preview images default to static, others default to animated
    preview = opts.get('preview', False)
    if preview:
        static = opts.get('static', True)
    else:
        static = opts.get('static', False)

    if static:
        end_frame = start_frame
    else:
        end_frame = opts.get('end_frame', start_frame + n_frames - 1)

    input_file = opts.get('input_file', False)
    if input_file:
        (vsim_cell, positions, symbols, vibs) = import_vsim(input_file)
        lattice_vectors = cell_vsim_to_vectors(vsim_cell)
    else:
        raise Exception('No .ascii file provided')

    if opts.get('mass_weighting', 0):
        f = opts.get('mass_weighting', 1)
        masses = [
            float(opts.config['masses'][symbol])**f for symbol in symbols
        ]
    else:
        masses = [1 for symbol in symbols]

    # Switch to a new empty scene
    bpy.ops.scene.new(type='EMPTY')

    # Draw bounding box
    if (opts.get('show_box', True)):
        bbox_offset = opts.get('offset_box', (0, 0, 0))
        bbox_offset = Vector(bbox_offset)
        draw_bounding_box(lattice_vectors, offset=bbox_offset)

    # Draw atoms after checking config
    mode_index = opts.get('mode_index', 0)
    supercell = (opts.get('supercell', (2, 2, 2)))
    vectors = opts.get('vectors', False)

    normalise_vectors = opts.get('normalise_vectors', False)
    # Variable for tracking largest arrow
    max_vector = 0
    arrow_objects = []

    mass_weighting = opts.get('mass_weighting', 0.)
    assert type(mass_weighting) == float

    for cell_id_tuple in itertools.product(range(supercell[0]),
                                           range(supercell[1]),
                                           range(supercell[2])):
        cell_id = Vector(cell_id_tuple)
        for (atom_index, (position, symbol,
                          mass)) in enumerate(zip(positions, symbols, masses)):
            atom = add_atom(position,
                            lattice_vectors,
                            symbol,
                            cell_id=cell_id,
                            scale_factor=opts.get('scale_atom', 1.),
                            name='{0}_{1}_{2}{3}{4}'.format(
                                atom_index, symbol, *cell_id_tuple),
                            config=opts.config)
            if vectors or not static:
                displacement_vector = vibs[mode_index].vectors[atom_index]
                qpt = vibs[mode_index].qpt
                B = (2 * math.pi *
                     Matrix(lattice_vectors).inverted().transposed())
                qpt_cartesian = Vector(qpt) * B

            if not static:
                animate_atom_vibs(atom,
                                  qpt_cartesian,
                                  displacement_vector,
                                  start_frame=start_frame,
                                  end_frame=end_frame,
                                  n_frames=n_frames,
                                  magnitude=opts.get('scale_vib', 1.),
                                  mass=mass)
            if vectors:
                arrow_vector = vector_with_phase(atom, qpt_cartesian,
                                                 displacement_vector)
                scale = arrow_vector.length
                loc = absolute_position(position,
                                        lattice_vectors=lattice_vectors,
                                        cell_id=cell_id)
                # Arrows are scaled by eigenvector magnitude
                arrow_objects.append(
                    add_arrow(loc=loc,
                              mass=mass,
                              rot_euler=vector_to_euler(arrow_vector),
                              scale=scale))

    if vectors:
        col = str2list(opts.config.get('colours', 'arrow',
                                       fallback='0. 0. 0.'))
        bpy.data.materials['Arrow'].diffuse_color = col

    # Rescaling; either by clamping max or accounting for cell size
    if vectors and normalise_vectors:
        master_scale = opts.get('scale_arrow', 1.)
        # Compare first element of object scales; they should be isotropic!
        max_length = max((arrow.scale[0] for arrow in arrow_objects))
        for arrow in arrow_objects:
            arrow.scale *= master_scale / max_length

    elif vectors:
        master_scale = opts.get('scale_arrow', 1.) * len(positions)
        for arrow in arrow_objects:
            arrow.scale *= master_scale

    # Position camera and colour world. Note that cameras as objects and
    # cameras as 'cameras' have different attributes, so need to look up
    # camera in bpy.data.cameras to set field of view.

    camera.setup_camera(lattice_vectors, field_of_view=0.2, opts=opts)

    bpy.context.scene.world = bpy.data.worlds['World']
    bpy.data.worlds['World'].horizon_color = str2list(
        opts.config.get('colours', 'background', fallback='0.5 0.5 0.5'))
Example #3
0
def open_mode(**options):
    """
    Open v_sim ascii file in Blender

    :param input_file: Path to file
    :type input_file: str
    :param camera_rot: Camera tilt adjustment in degrees
    :type camera_rot: float
    :param config: Settings from configuration files
    :type config: configparser.ConfigParser
    :param do_mass_weighting: Weight eigenvectors by mass.
        This is not usually required.
    :type do_mass_weighting: bool
    :param end_frame: The ending frame number of the rendered Animation
        (default=start_frame+n_frames-1)
    :type end_frame: int or None
    :param miller: Miller indices of view
    :type miller: 3-tuple of floats
    :param mode_index: id of mode; 0 corresponds to first mode in ascii file
    :type mode_index: int
    :param n_frames: Animation length of a single oscillation
        cycle in frames (default=30)
    :type n_frames: Positive int
    :param normalise_vectors: Re-scale vectors so largest arrow is fixed length
    :type normalise_vectors: bool
    :param offset_box: Position of bbox in lattice vector coordinates.
        Default (0,0,0) (Left front bottom)
    :type offset_box: Vector or 3-tuple
    :param preview: Enable preview mode - single frame, smaller render
    :type preview: bool
    :param scale_arrow: Scale factor for arrows
    :type scale_arrow: float
    :param scale_atom: Scale of atoms, relative to covalent radius
    :type scale_atom: float
    :param scale_vib: Scale factor for oscillations
        (angstroms / normalised eigenvector).
    :type scale_vib: float
    :param show_box: If True, show bounding box
    :type show_box: bool
    :param start_frame: The starting frame number of the rendered
        animation (default=0)
    :type start_frame: int or None
    :param static: if True, ignore frame range and use single frame.
        Otherwise, add animation keyframes.
    :type static: bool
    :param supercell: supercell dimensions
    :type supercell: 3-tuple or 3-list of ints
    :param vectors: If True, show arrows
    :type vectors: bool
    :param zoom: Camera zoom adjustment
    :type zoom: float

    """

    # Initialise Opts object, accessing options and user config
    opts = vsim2blender.Opts(options)

    # Work out actual frame range.
    # Priority goes 1. static/preview 2. end_frame 3. n_frames
    start_frame = opts.get('start_frame', 0)
    n_frames = opts.get('n_frames', 30)

    # Preview images default to static, others default to animated
    preview = opts.get('preview', False)
    if preview:
        static = opts.get('static', True)
    else:
        static = opts.get('static', False)

    if static:
        end_frame = start_frame
    else:
        end_frame = opts.get('end_frame', start_frame + n_frames - 1)

    input_file = opts.get('input_file', False)
    if input_file:
        (vsim_cell, positions, symbols, vibs) = import_vsim(input_file)
        lattice_vectors = cell_vsim_to_vectors(vsim_cell)
    else:
        raise Exception('No .ascii file provided')

    if opts.get('do_mass_weighting', False):
        masses = [float(opts.config['masses'][symbol]) for symbol in symbols]
    else:
        masses = [1 for symbol in symbols]

    # Switch to a new empty scene
    bpy.ops.scene.new(type='EMPTY')

    # Draw bounding box
    if (opts.get('show_box', True)):
        bbox_offset = opts.get('offset_box', (0, 0, 0))
        bbox_offset = Vector(bbox_offset)
        draw_bounding_box(lattice_vectors, offset=bbox_offset)

    # Draw atoms after checking config
    mode_index = opts.get('mode_index', 0)
    supercell = (opts.get('supercell', (2, 2, 2)))
    vectors = opts.get('vectors', False)

    normalise_vectors = opts.get('normalise_vectors', False)
    # Variable for tracking largest arrow
    max_vector = 0
    arrow_objects = []

    for cell_id_tuple in itertools.product(range(supercell[0]),
                                           range(supercell[1]),
                                           range(supercell[2])):
        cell_id = Vector(cell_id_tuple)
        for (atom_index,
             (position, symbol, mass)) in enumerate(zip(positions,
                                                        symbols,
                                                        masses)):
            atom = add_atom(position, lattice_vectors, symbol,
                            cell_id=cell_id,
                            name='{0}_{1}_{2}{3}{4}'.format(
                                atom_index, symbol, *cell_id_tuple),
                            config=opts.config)
            if vectors or not static:
                displacement_vector = vibs[mode_index].vectors[atom_index]
                qpt = vibs[mode_index].qpt
                B = (2 * math.pi *
                     Matrix(lattice_vectors).inverted().transposed())
                qpt_cartesian = Vector(qpt) * B

            if not static:
                animate_atom_vibs(atom, qpt_cartesian,
                                  displacement_vector,
                                  start_frame=start_frame,
                                  end_frame=end_frame,
                                  n_frames=n_frames,
                                  magnitude=opts.get('scale_vib', 1.),
                                  mass=mass)
            if vectors:
                arrow_vector = vector_with_phase(atom, qpt_cartesian,
                                                 displacement_vector)
                max_vector = max(max_vector, arrow_vector.length)
                loc = absolute_position(position,
                                        lattice_vectors=lattice_vectors,
                                        cell_id=cell_id)
                # Arrows are scaled by eigenvector magnitude
                arrow_objects.append(
                    add_arrow(loc=loc,
                              mass=mass,
                              rot_euler=vector_to_euler(arrow_vector),
                              scale=arrow_vector.length))
    if vectors:
        col = str2list(opts.config.get('colours', 'arrow',
                       fallback='0. 0. 0.'))
        bpy.data.materials['Arrow'].diffuse_color = col

    # Rescaling; either by clamping max or accounting for cell size
    if vectors and normalise_vectors:
        scale = opts.get('scale_arrow', 1.) / max_vector
        for arrow in arrow_objects:
            arrow.scale *= scale
    elif vectors:
        scale = opts.get('scale_arrow', 1.) * len(positions)
        for arrow in arrow_objects:
            arrow.scale *= scale

    # Position camera and colour world. Note that cameras as objects and
    # cameras as 'cameras' have different attributes, so need to look up
    # camera in bpy.data.cameras to set field of view.

    camera.setup_camera(lattice_vectors, field_of_view=0.2, opts=opts)

    bpy.context.scene.world = bpy.data.worlds['World']
    bpy.data.worlds['World'].horizon_color = str2list(opts.config.get(
        'colours', 'background', fallback='0.5 0.5 0.5'))