Пример #1
0
def generate_filename(config, kind=None, name=None, path=None):
    config = xicsrt_config.get_config(config)
    prefix = config['general']['output_prefix']
    suffix = config['general']['output_suffix']
    run_suffix = config['general']['output_run_suffix']
    if path is None:
        path = config['general']['output_path']

    if kind is None:
        ext = ''
    elif kind == 'image':
        ext = config['general']['image_ext']
    elif kind == 'results':
        ext = config['general']['results_ext']
    elif kind == 'config':
        ext = config['general']['config_ext']
    else:
        raise Exception(f'Data kind {kind} unknown.')

    if name is None:
        name = kind

    filename = '_'.join(filter(None, (prefix, name, suffix, run_suffix))) + ext
    filepath = os.path.join(path, filename)

    return filepath
Пример #2
0
def raytrace(config):
    """
    Perform a series of ray tracing runs.

    Each run will rebuild all objects, reset the random seed and then
    perform the requested number of iterations.

    If the option 'save_images' is set, then images will be saved
    at the completion of each run. The saving of these run images
    is one reason to use this routine rather than just increasing
    the number of iterations: periodic outputs during long computations.

    Also see :func:`~xicsrt.xicsrt_multiprocessing.raytrace` for a
    multiprocessing version of this routine.
    """
    profiler.start('raytrace')
    
    # Update the default config with the user config.
    config = xicsrt_config.get_config(config)
    check_config(config)

    # Make local copies of some options.
    num_runs = config['general']['number_of_runs']
    random_seed = config['general']['random_seed']
    
    output_list = []
    
    for ii in range(num_runs):
        m_log.info('Starting run: {} of {}'.format(ii + 1, num_runs))
        config_run = deepcopy(config)
        config_run['general']['output_run_suffix'] = '{:04d}'.format(ii)

        # Make sure each run uses a unique random seed.
        if random_seed is not None:
            random_seed += ii
        config_run['general']['random_seed'] = random_seed
        
        iteration = raytrace_single(config_run, _internal=True)
        output_list.append(iteration)
        
    output = combine_raytrace(output_list)

    # Reset the configuration options that were unique to the individual runs.
    output['config']['general']['output_run_suffix'] = config['general']['output_run_suffix']
    output['config']['general']['random_seed'] = config['general']['random_seed']

    if config['general']['save_config']:
        xicsrt_io.save_config(output['config'])
    if config['general']['save_images']:
        xicsrt_io.save_images(output)
    if config['general']['save_results']:
        xicsrt_io.save_results(output)
    if config['general']['print_results']:
        print_raytrace(output)

    profiler.stop('raytrace')
    return output
Пример #3
0
def get_element(config_user, name, section=None, initialize=True):
    """
    Retrieves an raytracing element (source, optic or filter) object.
    """
    config = xicsrt_config.get_config(config_user)
    if section is None:
        section = _find_element_section(config, name)

    disp = Dispatcher(config, section)
    disp.instantiate(name)
    obj = disp.get_object(name)
    if initialize:
        obj.setup()
        obj.check_param()
        obj.initialize()
    return obj
def add_sources(config):
    # Update the default config with the user config.
    config = xicsrt_config.get_config(config)

    # Combine the user and default object pathlists.
    pathlist = []
    pathlist.extend(config['general']['pathlist_objects'])
    pathlist.extend(config['general']['pathlist_default'])

    sources = Dispatcher(config, 'sources')
    sources.instantiate()
    sources.setup()
    sources.initialize()

    for key in config['sources']:
        obj = sources.get_object(key)

    add_surf(obj)
Пример #5
0
def raytrace_single(config, _internal=False):
    """
    Perform a single raytrace run consisting of multiple iterations.

    If history is enabled, sort the rays into those that are detected and
    those that are lost (found and lost). The found ray history will be
    returned in full. The lost ray history will be truncated to allow
    analysis of lost ray pattern while still limiting memory usage.

    private keywords
    ================
    _internal : bool (False)
      Used when calling this function from `raytrace` as part of the execution
      of multiple runs. Controls how `history_max_lost` is handled along with
      how `save_config` and `save_results` are interpreted.
    """
    profiler.start('raytrace_single')

    # Update the default config with the user config.
    config = xicsrt_config.config_to_numpy(config)
    config = xicsrt_config.get_config(config)
    check_config(config)

    m_log.info('Seeding np.random with {}'.format(config['general']['random_seed']))
    np.random.seed(config['general']['random_seed'])

    num_iter = config['general']['number_of_iter']
    max_lost_iter = int(config['general']['history_max_lost']/num_iter)

    if _internal:
        max_lost_iter = max_lost_iter//config['general']['number_of_runs']

    # Setup the dispatchers.
    if 'filters' in config:
        m_log.debug("Creating filters")
        filters = Dispatcher(config, 'filters')
        filters.instantiate()
        filters.setup()
        filters.initialize()
        config['filters'] = filters.get_config()
    else:
        filters = None

    m_log.debug("Creating sources")
    sources = Dispatcher(config, 'sources')
    sources.instantiate()
    sources.apply_filters(filters)
    sources.setup()
    sources.check_param()
    sources.initialize()
    config['sources'] = sources.get_config()

    m_log.debug("Creating optics")
    optics = Dispatcher(config, 'optics')
    optics.instantiate()
    optics.apply_filters(filters)
    optics.setup()
    optics.check_param()
    optics.initialize()
    config['optics'] = optics.get_config()

    # Do the actual raytracing
    output_list = []
    for ii in range(num_iter):
        m_log.info('Starting iteration: {} of {}'.format(ii + 1, num_iter))

        single = _raytrace_iter(config, sources, optics)
        sorted = _sort_raytrace(single, max_lost=max_lost_iter)
        output_list.append(sorted)

    output = combine_raytrace(output_list)

    if _internal is False:
        if config['general']['print_results']:
            print_raytrace(output)
        if config['general']['save_config']:
            xicsrt_io.save_config(output['config'])
        if config['general']['save_results']:
            xicsrt_io.save_results(output)

    if config['general']['save_images']:
        xicsrt_io.save_images(output)

    profiler.stop('raytrace_single')
    # profiler.report()
    return output
def add_optics(config):

    for key_opt in config['optics']:
        config_opt = config['optics'][key_opt]
        config_opt = xicsrt_config.config_to_numpy(config_opt)

        if True:
            w = config_opt['width'] / 2.0
            h = config_opt['height'] / 2.0
            cx = config_opt['xaxis']
            cy = np.cross(config_opt['xaxis'], config_opt['zaxis'])

            point0 = w * cx + h * cy + config_opt['origin']
            point1 = h * cy + config_opt['origin']
            point2 = -1 * w * cx + h * cy + config_opt['origin']

            point3 = w * cx + config_opt['origin']
            point4 = config_opt['origin']
            point5 = -1 * w * cx + config_opt['origin']

            point6 = w * cx - h * cy + config_opt['origin']
            point7 = -1 * h * cy + config_opt['origin']
            point8 = -1 * w * cx - h * cy + config_opt['origin']

            points = np.array([
                point0, point1, point2, point3, point4, point5, point6, point7,
                point8
            ])

            x = points[:, 0]
            y = points[:, 1]
            z = points[:, 2]

            # I am sure there is a way to automate this using a meshgrid,
            # but at the moment this is faster.
            triangles = ((4, 0, 2), (4, 2, 8), (4, 6, 8), (4, 6, 0))

            obj = ipv.plot_trisurf(x,
                                   y,
                                   z,
                                   triangles=triangles,
                                   color=[0.5, 0.5, 0.5, 0.5])
            obj.material.transparent = True

        if 'crystal' in str.lower(key_opt) and 'radius' in config_opt:

            # Initialize the configuration.
            # This merges the user config that we created
            # with the default config
            config = xicsrt_config.get_config(config)

            # The easiest way to do coordinate transformations is
            # to use the raytrace objects, since they already have
            # everything built in.  Of course we could do this
            # by just using some simple matrix multiplications,
            # but this way we can use existing code.
            #
            # We could just instantiate the objects directly as needed,
            # but since a dispatcher is already available in xicsrt that
            # does this for us, we might as well use it.  This is copied
            # from xicsrt_raytrace.raytrace_single.
            name = 'crystal'
            section = 'optics'
            optics = Dispatcher(config, section)
            optics.instantiate()
            optics.setup()
            optics.initialize()

            # Get the crystal object from the dispatcher.
            optic_obj = optics.get_object(name)

            crystal_center_ext = config_opt[
                'origin'] + config_opt['zaxis'] * config_opt['radius']
            crystal_center_loc = optic_obj.point_to_local(crystal_center_ext)

            x = np.array([crystal_center_ext[0]])
            y = np.array([crystal_center_ext[1]])
            z = np.array([crystal_center_ext[2]])
            ipv.scatter(x, y, z, color='black', marker="sphere")

            # Plot the crystal circle.
            num = 1000
            crystal_radius = config_opt['radius']
            coord_loc = np.zeros((num, 3))
            coord_loc[:, 0] = np.sin(np.linspace(
                0.0, np.pi * 2,
                num)) * config_opt['radius'] + crystal_center_loc[0]
            coord_loc[:, 1] = crystal_center_loc[1]
            coord_loc[:, 2] = np.cos(np.linspace(
                0.0, np.pi * 2,
                num)) * config_opt['radius'] + crystal_center_loc[2]
            coord_ext = optic_obj.point_to_external(coord_loc)
            x = coord_ext[:, 0]
            y = coord_ext[:, 1]
            z = coord_ext[:, 2]
            lines = np.zeros((num, 2), dtype=int)
            lines[:, 0] = np.arange(num)
            lines[:, 1] = np.roll(lines[:, 0], 1)
            obj = ipv.plot_trisurf(x,
                                   y,
                                   z,
                                   lines=lines,
                                   color=[0.0, 0.0, 0.0, 0.5])

            rowland_center_ext = config_opt[
                'origin'] + config_opt['zaxis'] * config_opt['radius'] / 2
            rowland_center_loc = optic_obj.point_to_local(rowland_center_ext)
            rowland_radius = crystal_radius / 2
            coord_loc = np.zeros((num, 3))
            coord_loc[:, 0] = np.sin(np.linspace(
                0.0, np.pi * 2, num)) * rowland_radius + rowland_center_loc[0]
            coord_loc[:, 1] = rowland_center_loc[1]
            coord_loc[:, 2] = np.cos(np.linspace(
                0.0, np.pi * 2, num)) * rowland_radius + rowland_center_loc[2]
            coord_ext = optic_obj.point_to_external(coord_loc)
            x = coord_ext[:, 0]
            y = coord_ext[:, 1]
            z = coord_ext[:, 2]
            lines = np.zeros((num, 2), dtype=int)
            lines[:, 0] = np.arange(num)
            lines[:, 1] = np.roll(lines[:, 0], 1)
            obj = ipv.plot_trisurf(x,
                                   y,
                                   z,
                                   lines=lines,
                                   color=[0.0, 0.0, 0.0, 0.5])