Ejemplo n.º 1
0
def get_img_data(data_type, file_info, img_info, **kwargs):
    """
    Get data from an image or FITS file
    """
    if file_info['ext'] == 'fits':
        hdulist = get_file(file_info)
        data = hdulist[int(img_info['frame'])].data
    else:
        try:
            from PIL import Image
        except ImportError:
            raise ToyzJobError(
                "You must have PIL (Python Imaging Library) installed to "
                "open files of this type")
        img = get_file(file_info)
        data = np.array(img)

    if data_type == 'data':
        if 'scale' in kwargs:
            width = int(kwargs['width'] / 2 / img_info['viewer']['scale'])
            height = int(kwargs['height'] / 2 / img_info['viewer']['scale'])
        else:
            width = int(kwargs['width'] / 2)
            height = int(kwargs['height'] / 2)
        x0 = max(0, kwargs['x'] - width)
        y0 = max(0, kwargs['y'] - height)
        xf = min(data.shape[1], kwargs['x'] + width)
        yf = min(data.shape[0], kwargs['y'] + height)
        if 'scale' in kwargs:
            tile_data = {
                'x0_idx': x0,
                'y0_idx': y0,
                'xf_idx': xf,
                'yf_idx': yf
            }
            data = scale_data(file_info, img_info, tile_data, data)
        else:
            data = data[y0:yf, x0:xf]
        response = {
            'id': 'data',
            'min': float(data.min()),
            'max': float(data.max()),
            'mean': float(data.mean()),
            'median': float(np.median(data)),
            'std_dev': float(np.std(data)),
            'data': data.tolist()
        }
    elif data_type == 'datapoint':
        if (kwargs['x'] < data.shape[1] and kwargs['y'] < data.shape[0]
                and kwargs['x'] >= 0 and kwargs['y'] >= 0):
            response = {
                'id': 'datapoint',
                'px_value': float(data[kwargs['y'], kwargs['x']])
            }
        else:
            response = {'id': 'datapoint', 'px_value': 0}
    else:
        raise ToyzJobError(
            "Loading that data type has not been implemented yet")
    return response
Ejemplo n.º 2
0
Archivo: tasks.py Proyecto: fred3m/toyz
def load_workspace(toyz_settings, tid, params):
    """
    Load a workspace
    """
    core.check4keys(params, ['work_id'])
    user_id = tid['user_id']
    if 'user_id' in params and params['user_id'] != tid['user_id']:
        permissions = core.get_workspace_permissions(toyz_settings, tid,
                                                     params)
        print('permissions', permissions)
        if permissions['view']:
            user_id = params['user_id']
        else:
            raise ToyzJobError("You do not have permission to load {0}".format(
                params['work_id']))

    workspaces = db_utils.get_param(toyz_settings.db,
                                    'workspaces',
                                    user_id=user_id)
    if params['work_id'] not in workspaces:
        raise ToyzJobError("{0} not found in your workspaces".format(
            params['work_id']))
    response = {
        'id': 'workspace',
        'work_id': params['work_id'],
        'settings': workspaces[params['work_id']]
    }
    return response
Ejemplo n.º 3
0
def create_tile(file_info, img_info, tile_info):
    try:
        from PIL import Image
    except ImportError:
        raise ToyzJobError(
            "You must have PIL (Python Imaging Library) installed to "
            "open files of this type")

    if file_info['ext'] == 'fits':
        try:
            from matplotlib import cm as cmap
            from matplotlib.colors import Normalize, LinearSegmentedColormap
        except ImportError:
            raise ToyzJobError(
                "You must have matplotlib installed to load FITS images")

        hdulist = get_file(file_info)
        data = hdulist[int(img_info['frame'])].data
        # If no advanced resampling algorithm is used, scale the data as quickly as possible.
        # Otherwise crop the data.
        if file_info['resampling'] == 'NEAREST':
            data = scale_data(file_info, img_info, tile_info, data)
        else:
            data = data[tile_info['y0_idx']:tile_info['yf_idx'],
                        tile_info['x0_idx']:tile_info['xf_idx']]
        # FITS images have a flipped y-axis from what browsers and other image formats expect
        if img_info['invert_y']:
            data = np.flipud(data)
        if img_info['invert_x']:
            data = np.fliplr(data)

        norm = Normalize(img_info['colormap']['px_min'],
                         img_info['colormap']['px_max'], True)
        colormap_name = img_info['colormap']['name']
        if img_info['colormap']['invert_color']:
            colormap_name = colormap_name + '_r'
        colormap = getattr(cmap, colormap_name)
        cm = cmap.ScalarMappable(norm, colormap)
        img = np.uint8(cm.to_rgba(data) * 255)
        img = Image.fromarray(img)
        if file_info['resampling'] != 'NEAREST':
            img = img.resize((tile_info['width'], tile_info['height']),
                             getattr(Image, file_info['resampling']))
    else:
        img = get_file(file_info)
        img = img.crop((tile_info['x0_idx'], tile_info['y0_idx'],
                        tile_info['xf_idx'], tile_info['yf_idx']))
        img = img.resize((tile_info['width'], tile_info['height']),
                         getattr(Image, file_info['resampling']))
    width, height = img.size
    if width > 0 and height > 0:
        path = os.path.dirname(tile_info['new_filepath'])
        core.create_paths([path])
        img.save(tile_info['new_filepath'],
                 format=img_formats[file_info['tile_format']])
    else:
        return False, ''
    return True, tile_info
Ejemplo n.º 4
0
Archivo: tasks.py Proyecto: fred3m/toyz
def create_paths(toyz_settings, tid, params):
    """
    Creates a new path on the server (if it does not already exist).
    
    Parameters
        - toyz_settings ( :py:class:`toyz.utils.core.ToyzSettings`): Settings for the toyz 
          application
        - tid (*string* ): Task ID of the client user running the task
        - params (*dict* ): Any parameters sent by the client (see *params* below)
    
    Params
        - path (*string* ): path to create on the server
    
    Response
        id: 'create_folder',
        status (*string* ): 'success',
        path (*string* ): path created on the server
    """
    core.check4keys(params, ['path', 'new_folder'])
    path = os.path.join(params['path'], params['new_folder'])
    permissions = file_access.get_parent_permissions(toyz_settings.db,
                                                     path,
                                                     user_id=tid['user_id'])
    if 'w' not in permissions and 'x' not in permissions:
        raise ToyzJobError(
            "You do not have permission to create path {0}".format(path))
    core.create_paths(path)
    response = {
        'id': 'notification',
        'msg': 'Created path'.format(path),
        'func': 'create_dir'
    }
    return response
Ejemplo n.º 5
0
Archivo: core.py Proyecto: fred3m/toyz
def get_toyz_module(toyz_settings, user_id, module):
    """
    Get a toyz module from either installed modules or one in a users toyz paths.
    An uninstalled toy will take precedence if it is in the toy paths as opposed to installed
    modules.
    
    Parameters
        toyz_settings ( :py:class:`toyz.utils.core.ToyzSettings` ):
            - Settings for the application runnning the job (may be needed to load user info 
              or check permissions)
        user_id ( *string* ): id of the current user
        module ( *string* ): name of the module to search for
    
    Returns
        toyz_module ( *module* ): python module if it exists, otherwise ``None``.
    
    Raises
        Raises a :py:class:`toyz.utils.errors.ToyzJobError` if the module is not found
        in the users approved modules
    """
    toyz_module = get_user_toyz(toyz_settings, user_id, module)
    if toyz_module is not None:
        return toyz_module
    if toyz_module is None and check_user_modules(toyz_settings, user_id,
                                                  module):
        return importlib.import_module(module)
    else:
        raise ToyzJobError(module + " not found in " + user_id +
                           "'s approved modules")
Ejemplo n.º 6
0
Archivo: tasks.py Proyecto: fred3m/toyz
def get_file_info(toyz_settings, tid, params):
    """
    Get information about an image file
    """
    import toyz.web.viewer as viewer
    core.check4keys(params, ['file_info', 'img_info'])
    if tid['user_id'] != 'admin':
        permissions = file_access.get_parent_permissions(
            toyz_settings.db,
            params['file_info']['filepath'],
            user_id=tid['user_id'])
        if permissions is None or 'r' not in permissions:
            raise ToyzJobError(
                'You do not have permission to view the requested file.'
                'Please contact your network administrator if you believe this is an error.'
            )
    file_info = viewer.get_file_info(params['file_info'])
    img_info = file_info['images'][file_info['frame']]
    img_info.update(params['img_info'])
    # Get the tile map for the first image
    result = get_img_info(toyz_settings, tid, {
        'file_info': file_info,
        'img_info': img_info
    })

    file_info['images'][file_info['frame']] = result['img_info']
    response = {
        'id': 'file info',
        'file_info': file_info,
        'new_tiles': result['new_tiles']
    }
    return response
Ejemplo n.º 7
0
Archivo: tasks.py Proyecto: fred3m/toyz
def get_tile_info(toyz_settings, tid, params):
    """
    Get new tiles that need to be loaded
    """
    import toyz.web.viewer as viewer

    core.check4keys(params, ['img_info', 'file_info'])
    if tid['user_id'] != 'admin':
        permissions = file_access.get_parent_permissions(
            toyz_settings.db,
            params['file_info']['filepath'],
            user_id=tid['user_id'])
        if 'r' not in permissions:
            raise ToyzJobError(
                'You do not have permission to view the requested file.'
                'Please contact your network administrator if you believe this is an error.'
            )

    all_tiles, new_tiles = viewer.get_tile_info(params['file_info'],
                                                params['img_info'])

    #print('all tile:', all_tiles)

    response = {
        'id': 'tile info',
        'all_tiles': all_tiles,
        'new_tiles': new_tiles
    }
    return response
Ejemplo n.º 8
0
Archivo: tasks.py Proyecto: fred3m/toyz
def save_workspace(toyz_settings, tid, params):
    """
    Save a workspace for later use
    """
    core.check4keys(params, ['workspaces', 'overwrite'])
    workspaces = db_utils.get_param(toyz_settings.db,
                                    'workspaces',
                                    user_id=tid['user_id'])
    work_id = params['workspaces'].keys()[0]
    if work_id in workspaces and params['overwrite'] is False:
        response = {'id': 'verify', 'func': 'save_workspace'}
    else:
        user_id = tid['user_id']
        if 'user_id' in params and params['user_id'] != tid['user_id']:
            params['work_id'] = work_id
            permissions = core.get_workspace_permissions(
                toyz_settings, tid, params)
            if permissions['modify']:
                user_id = params['user_id']
            else:
                raise ToyzJobError(
                    "You do not have permission to save {0}".format(
                        params['work_id']))

        db_utils.update_param(toyz_settings.db,
                              'workspaces',
                              workspaces=params['workspaces'],
                              user_id=user_id)
        response = {
            'id': 'notification',
            'msg': 'Workspace saved successfully',
            'func': 'save_workspace'
        }

    return response
Ejemplo n.º 9
0
Archivo: tasks.py Proyecto: fred3m/toyz
def get_img_tile(toyz_settings, tid, params):
    """
    Load a tile from a larger image and notify the client it has been created
    """
    import toyz.web.viewer as viewer

    core.check4keys(params, ['img_info', 'file_info', 'tile_info'])
    if tid['user_id'] != 'admin':
        permissions = file_access.get_parent_permissions(
            toyz_settings.db,
            params['file_info']['filepath'],
            user_id=tid['user_id'])
        if 'r' not in permissions:
            raise ToyzJobError(
                'You do not have permission to view the requested file.'
                'Please contact your network administrator if you believe this is an error.'
            )

    created, tile_info = viewer.create_tile(params['file_info'],
                                            params['img_info'],
                                            params['tile_info'])

    response = {
        'id': 'tile created',
        'success': created,
        'tile_info': tile_info
    }

    return response
Ejemplo n.º 10
0
Archivo: tasks.py Proyecto: fred3m/toyz
def change_pwd(toyz_settings, tid, params):
    """
    Change a users password.
    
    Parameters
        - toyz_settings ( :py:class:`toyz.utils.core.ToyzSettings`): Settings for the toyz 
          application
        - tid (*string* ): Task ID of the client user running the task
        - params (*dict* ): Any parameters sent by the client (see *params* below)
    
    Params
        - current_pwd (*string* ):  Users current password. Must match the password on 
          file or an exception is raised
        - new_pwd (*string* ): New password
        - confirm_pwd (*string* ): Confirmation of the the new password. If new_pwd and 
          confirm_pwd do not match, an exception is raised
    
    Response
        - id: 'notification'
        - func: 'change_pwd'
        - msg: 'Password changed successfully'
    """
    core.check4keys(params, ['current_pwd', 'new_pwd', 'confirm_pwd'])
    if core.check_pwd(toyz_settings, tid['user_id'], params['current_pwd']):
        if params['new_pwd'] == params['confirm_pwd']:
            pwd_hash = core.encrypt_pwd(toyz_settings, params['new_pwd'])
        else:
            raise ToyzJobError("New passwords did not match")
    else:
        raise ToyzJobError("Invalid user_id or password")

    db_utils.update_param(toyz_settings.db,
                          'pwd',
                          user_id=tid['user_id'],
                          pwd=pwd_hash)

    response = {
        'id': 'notification',
        'func': 'change_pwd',
        'msg': 'Password changed successfully',
    }
    return response
Ejemplo n.º 11
0
def get_file_info(file_info):
    file_split = file_info['filepath'].split('.')
    file_info['filename'] = os.path.basename(file_split[0])
    if 'fits' in file_split[1:]:
        file_info['ext'] = 'fits'
    else:
        file_info['ext'] = file_split[-1]

    if 'tile_width' not in file_info:
        file_info['tile_width'] = 400
    if 'tile_height' not in file_info:
        file_info['tile_height'] = 200
    if 'img_type' not in file_info:
        file_info['img_type'] == 'image'

    if file_info['ext'] == 'fits':
        file_info['file_type'] = 'img_array'
        hdulist = get_file(file_info)
        file_info['hdulist'] = [hdu.__class__.__name__ for hdu in hdulist]
        if 'images' not in file_info:
            if len(hdulist) > 1:
                file_info['images'] = OrderedDict(
                    [[str(n), {
                        'frame': str(n)
                    }] for n, hdu in enumerate(hdulist)
                     if 'imagehdu' in hdu.__class__.__name__.lower()])
            else:
                file_info['images'] = {'0': {'frame': '0'}}
        if len(file_info['images']) == 0:
            raise ToyzJobError(
                "FITS file does not contain any recognized image hdu's")
    else:
        file_info['file_type'] = 'img'
        file_info['images'] = {'0': {'frame': '0'}}

    file_defaults = {
        'frame': next(iter(file_info['images'])),
        'resampling': 'NEAREST',
        'invert_x': False,
        'invert_y': False,
        'tile_format': 'png',
        'colormap': {
            'name': 'Spectral',
            'color_scale': 'linear',
            'invert_color': False,
            'set_bounds': False
        }
    }

    for default in file_defaults:
        if default not in file_info:
            file_info[default] = file_defaults[default]

    return file_info
Ejemplo n.º 12
0
def import_fits():
    try:
        import astropy.io.fits as pyfits
    except ImportError:
        try:
            import pyfits
        except ImportError:
            raise ToyzJobError(
                "You must have astropy or pyfits installed to view FITS images"
            )
    return pyfits
Ejemplo n.º 13
0
Archivo: tasks.py Proyecto: fred3m/toyz
def reset_pwd(toyz_settings, tid, params):
    """
    Reset a users password
    """
    user = core.get_user_type(params)
    if 'user_id' in params:
        user_id = params['user_id']
    elif 'group_id' in params:
        user_id = group_id
    else:
        raise ToyzJobError(
            "Must specify a user_id or group_id to reset password")
    pwd_hash = core.encrypt_pwd(toyz_settings, user_id)
    db_utils.update_param(toyz_settings.db, 'pwd', pwd=pwd_hash, **user)

    response = {
        'id': 'notification',
        'func': 'reset_pwd',
        'msg': 'Password reset successfully',
    }
    return response
Ejemplo n.º 14
0
def scale_data(file_info, img_info, tile_info, data):
    if img_info['scale'] == 1:
        data = data[tile_info['y0_idx']:tile_info['yf_idx'],
                    tile_info['x0_idx']:tile_info['xf_idx']]
    else:
        try:
            import scipy.ndimage
            data = data[tile_info['y0_idx']:tile_info['yf_idx'],
                        tile_info['x0_idx']:tile_info['xf_idx']]
            data = scipy.ndimage.zoom(data, img_info['scale'], order=0)
        except ImportError:
            if img_info['scale'] > 1:
                data = data[tile_info['y0_idx']:tile_info['yf_idx'],
                            tile_info['x0_idx']:tile_info['xf_idx']]
                data = np.kron(data,
                               np.ones((img_info['scale'], img_info['scale'])))
                #data = zoom(data, img_info['scale'], order=0)
            elif img_info['scale'] < 1 and img_info['scale'] > 0:
                tile_width = min(
                    file_info['tile_width'],
                    int((img_info['width'] - tile_info['x0_idx']) *
                        img_info['scale']) - 1)
                tile_height = min(
                    file_info['tile_height'],
                    int((img_info['height'] - tile_info['y0_idx']) *
                        img_info['scale']) - 1)

                xmax = min(img_info['width'] - 1, tile_info['xf_idx'])
                ymax = min(img_info['height'] - 1, tile_info['yf_idx'])

                xIdx = np.linspace(tile_info['x0_idx'], xmax, tile_width)
                yIdx = np.linspace(tile_info['y0_idx'], ymax, tile_height)
                xIdx = np.array(xIdx, np.int)
                yIdx = np.reshape(np.array(yIdx, np.int), (yIdx.size, 1))
                data = data[yIdx, xIdx]
            else:
                raise ToyzJobError('Scale must be a positive number')
    return data
Ejemplo n.º 15
0
def get_file(file_info):
    """
    If the image has already been loaded into memory, access it here.
    Otherwise, store the image for later use
    """
    if session_vars.filepath == file_info['filepath']:
        img_file = session_vars.img_file
    else:
        print('loading', file_info['filepath'])
        if file_info['ext'] == 'fits':
            print('Detected fits image type')
            pyfits = import_fits()
            img_file = pyfits.open(file_info['filepath'])
        else:
            try:
                from PIL import Image
            except ImportError:
                raise ToyzJobError(
                    "You must have PIL (Python Imaging Library) installed to "
                    "open files of this type")
            img_file = Image.open(file_info['filepath'])
        session_vars.filepath = file_info['filepath']
        session_vars.img_file = img_file
    return img_file
Ejemplo n.º 16
0
Archivo: tasks.py Proyecto: fred3m/toyz
def get_img_info(toyz_settings, tid, params):
    """
    Map a large image into a set of tiles that make up the larger image
    """
    import toyz.web.viewer as viewer
    print('************************************************')
    core.check4keys(params, ['img_info', 'file_info'])
    if tid['user_id'] != 'admin':
        permissions = file_access.get_parent_permissions(
            toyz_settings.db,
            params['file_info']['filepath'],
            user_id=tid['user_id'])
        if 'r' not in permissions:
            raise ToyzJobError(
                'You do not have permission to view the requested file.'
                'Please contact your network administrator if you believe this is an error.'
            )
    shortcuts = db_utils.get_param(toyz_settings.db,
                                   'shortcuts',
                                   user_id=tid['user_id'])
    save_path = os.path.join(shortcuts['temp'], tid['session_id'], 'images')
    params['img_info']['save_path'] = save_path
    img_info = viewer.get_img_info(params['file_info'], params['img_info'])

    result = get_tile_info(toyz_settings, tid, {
        'file_info': params['file_info'],
        'img_info': img_info
    })
    img_info['tiles'] = result['new_tiles']
    response = {
        'id': 'img info',
        'img_info': img_info,
        'new_tiles': result['new_tiles']
    }
    print('************************************************')
    return response
Ejemplo n.º 17
0
Archivo: tasks.py Proyecto: fred3m/toyz
def load_directory(toyz_settings, tid, params):
    """
    Used by the file browser to load the folders and files in a given path.
    
    Parameters
        - toyz_settings ( :py:class:`toyz.utils.core.ToyzSettings`): Settings for the toyz 
          application
        - tid (*string* ): Task ID of the client user running the task
        - params (*dict* ): Any parameters sent by the client (see *params* below)
    
    Params
        - path (*string* ): Path to search
    
    Response
        - id: 'directory'
        - path (*string* ): path passed to the function
        - shortcuts (*dict* ): Dictionary of ``shortcut_name: shortcut_path`` 's for the user
        - folders (*list* of strings): folders contained in the path
        - files (*list* of strings): files contained in the path
        - parent (*string* ): parent directory of current path
    """
    core.check4keys(params, ['path'])
    show_hidden = False
    # If the path is contained in a set of dollar signs (for example `$images$`) then
    # search in the users shortcuts for the given path
    shortcuts = db_utils.get_param(toyz_settings.db,
                                   'shortcuts',
                                   user_id=tid['user_id'])
    if params['path'][0] == '$' and params['path'][-1] == '$':
        shortcut = params['path'][1:-1]
        if shortcut not in shortcuts:
            raise ToyzJobError("Shortcut '{0}' not found for user {1}".format(
                shortcut, tid['user_id']))
        params['path'] = shortcuts[shortcut]

    if not os.path.isdir(params['path']):
        parent = os.path.dirname(params['path'])
        if not os.path.isdir(parent):
            raise ToyzJobError("Path '{0}' not found".format(params['path']))
        params['path'] = parent
    if 'show_hidden' in params and params['show_hidden']:
        show_hidden = True

    # Keep separate lists of the files and directories for the current path.
    # Only include the files and directories the user has permissions to view
    files = []
    folders = []
    groups = db_utils.get_param(toyz_settings.db,
                                'groups',
                                user_id=tid['user_id'])
    if 'admin' in groups or tid['user_id'] == 'admin':
        admin = True
    else:
        admin = False
    for f in os.listdir(params['path']):
        if (f[0] != '.' or show_hidden):
            f_path = os.path.join(params['path'], f)
            if admin:
                permission = True
            else:
                permissions = file_access.get_parent_permissions(
                    toyz_settings.db, f_path, user_id=tid['user_id'])
                if permissions is None:
                    permissions = ''
                permission = 'f' in permissions
            if permission:
                if os.path.isfile(f_path):
                    files.append(str(f))
                elif os.path.isdir(f_path):
                    folders.append(str(f))
            else:
                print("no access to", f)
    files.sort(key=lambda v: v.lower())
    folders.sort(key=lambda v: v.lower())
    response = {
        'id': 'directory',
        'path': os.path.join(params['path'], ''),
        'shortcuts': shortcuts.keys(),
        'folders': folders,
        'files': files,
        'parent': os.path.abspath(os.path.join(params['path'], os.pardir))
    }

    #print('path info:', response)
    return response
Ejemplo n.º 18
0
Archivo: tasks.py Proyecto: fred3m/toyz
def save_user_info(toyz_settings, tid, params):
    """
    Save a users info. If any admin settings are being changed, ensures that the user
    is in the admin group.
    
    Parameters
        - toyz_settings ( :py:class:`toyz.utils.core.ToyzSettings`): Settings for the toyz 
          application
        - tid (*string* ): Task ID of the client user running the task
        - params (*dict* ): Any parameters sent by the client (see *params* below)
    
    Params can be any settings the user has permission to set on the server.
    
    Response
        - id: 'notification'
        - func: 'save_user_info'
        - msg: 'Settings saved for <user_id>'
    """
    groups = db_utils.get_param(toyz_settings.db,
                                'groups',
                                user_id=tid['user_id'])
    # check that user is in the admin group
    if 'paths' in params and tid[
            'user_id'] != 'admin' and 'admin' not in groups:
        raise ToyzJobError(
            "You must be in the admin group to modify path permissions")

    if (('modules' in params or 'toyz' in params or 'third_party' in params)
            and tid['user_id'] != 'admin' and 'admin' not in groups
            and 'modify_toyz' not in groups):
        raise ToyzJobError(
            "You must be an administrator or belong to the 'modify_toyz' "
            "group to modify a users toyz or module access")

    # Conditions is a dict that contains any conditional parameters from a gui
    # parameter list. We don't use any of those for this function, so we remove them
    if 'conditions' in params:
        del params['conditions']

    user = core.get_user_type(params)
    #update_fields = dict(params)
    #if 'user_id' in params:
    #    del update_fields['user_id']
    #elif 'group_id' in params:
    #   del update_fields['group_id']
    for field in params:
        if field in db_utils.param_formats:
            field_dict = {field: params[field]}
            field_dict.update(user)
            db_utils.update_all_params(toyz_settings.db, field, **field_dict)

    if 'user_id' in user:
        msg = params['user_id']
    else:
        msg = params['group_id']

    response = {
        'id': 'notification',
        'func': 'save_user_info',
        'msg': 'Settings saved for ' + msg
    }

    return response
Ejemplo n.º 19
0
Archivo: core.py Proyecto: fred3m/toyz
def run_job(toyz_settings, pipe, job):
    """
    Loads modules and runs a job (function) sent from a client. Any errors will be trapped 
    and flagged as a :py:class:`toyz.utils.errors.ToyzError` and sent back to the client who 
    initiated the job. 
    
    All job functions will take exactly 3 parameters: **toyz_settings**, **tid**, **params**. 
    The **tid** is the task id (*user*, *session*, and *request_id* ) information (see below), 
    and **params** is a dictionary of parameters sent by the client. 
    
    Each job is run as a new process, so any modules imported should be removed from memory 
    when the job has completed.
    
    Parameters
        toyz_settings ( :py:class:`toyz.utils.core.ToyzSettings` ):
            - Settings for the application runnning the job (may be needed to load user info 
              or check permissions)
        pipe: *multiprocessing.Pipe*
            - Communication with the parent process.
            - It may be useful to pass progress notifications to a client as a job
              is run. To send a notifaction the pipe requires a dictionary that is of the
              same form as the result (see Returns below), but usually with 
              ``id='notification'``.
        job: *dict*
            - The job received from the user. Each job will contain the following keys:
            - ``id`` (*dict*): Unique values for the given job. These are the
              **user_id**, the id of the user loaded from a secure cookie; the
              **session_id**, a unique identifier for the websocket; and the
              **request_id**, a unique identifier for the current request, sent from the client
            - ``module`` (*str*): Name of the Python module that contains the function called 
              by the client. In order for a module to work for a user, he/she must either have
              permissions set to view the module or belong to a group with permissions set
              to view the module (including *all_users*).
            - ``task`` (*str*): Name of the function called by the client
            - ``parameters`` (*dict*): Required and optional parameters passed to the function.
    
    Returns
        result: *dict*
            - The result is returned to the application running the job and is composed
              of two keys: an ``id``: the job id for the completed job, and a ``response``
              that is sent to the client.
            - The response is either an empty dictionary or one that contains (at a minimum) 
              the key **id**, which is used by the client to identify the type of response it is 
              receiving. Including the key **request_completed** with a *True* value tells the
              client that the current request has finished and may be removed from the queue.
    
    Example
    
        A client might send the following job to the server:
        
        .. code-block:: javascript
        
            job = {
                id : {
                    user_id : 'Iggy',
                    session_id : '12',
                    request_id : 305
                },
                module : 'toyz.web.tasks',
                task : 'load_directory',
                parameters : {
                    path: '~/images'
                }
            }
        
        In this case, after receiving the job, this function will import 
        the :py:mod:`toyz.web.tasks` module 
        (if it has not been imported already) and run the function 
        ``load_directory(toyz_settings, job['id'],job['parameters'])``. 
        If there are any errors in loading the directory, a response of the form
    
        .. code-block:: python
        
            response = {
                'id' : 'ERROR',
                'error' : 'Error message here for unable to lead directory',
                'traceback' : traceback.format_exec()
            }
        
        is sent. If the directory is loaded correctly a response of the form
        
        .. code-block:: python
    
                response={
                    'id': 'directory',
                    'path': '~/images/proj1',
                    'shortcuts': ['user', 'temp', 'home'],
                    'folders': ['proj1', 'proj2'],
                    'files': [],
                    'parent': '~/images'
                }
    
        is sent to the client.
    """
    # TODO: Eventually a job should be added to the jobs dictionary and removed after the response has been sent
    import traceback
    session_vars.toyz_settings = toyz_settings
    session_vars.pipe = pipe
    response = {}
    try:
        try:
            if job['module'].split('.')[-1] == 'tasks':
                toyz_module = get_toyz_module(toyz_settings,
                                              job['id']['user_id'],
                                              job['module'])
            else:
                raise ImportError()
        except ImportError:
            ToyzJobError(job['module'] + " not found in " +
                         job['id']['user_id'] + "'s approved modules")
        task = getattr(toyz_module, job["task"])
        response = task(toyz_settings, job['id'], job['parameters'])
    except ToyzJobError as error:
        response = {
            'id': "ERROR",
            'error': error.msg,
            'traceback': traceback.format_exc()
        }
    except Exception as error:
        response = {
            'id': "ERROR",
            'error': "PYTHON ERROR:" + type(error).__name__ + str(error.args),
            'traceback': traceback.format_exc()
        }
        print(traceback.format_exc())
    if response != {}:
        response['request_id'] = job['id']['request_id']
        #self.write_message(response)

    result = {
        'id': job['id'],
        'response': response,
    }

    #logging.info("sent message:%r",response['id'])
    return result
Ejemplo n.º 20
0
def get_img_info(file_info, img_info):
    if file_info['ext'] == 'fits':
        hdulist = get_file(file_info)
        data = hdulist[int(img_info['frame'])].data
        height, width = data.shape

        if ('colormap' not in img_info):
            if (file_info['colormap']['set_bounds']):
                px_min = file_info['px_min']
                px_max = file_info['px_max']
            else:
                px_min = float(data.min())
                px_max = float(data.max())
            img_info['colormap'] = file_info['colormap']
            if not file_info['colormap']['set_bounds']:
                img_info['colormap']['px_min'] = float(data.min())
                img_info['colormap']['px_max'] = float(data.max())
    else:
        # For non-FITS formats, only a single large image is loaded, which
        try:
            from PIL import Image
        except ImportError:
            raise ToyzJobError(
                "You must have PIL (Python Imaging Library) installed to "
                "open files of this type")
        img = get_file(file_info)
        img_info['colormap'] = {
            'name': 'none',
            'px_min': 0,
            'px_max': 255,
            'invert_color': False
        }
        width, height = img.size
    img_info['width'] = width
    img_info['height'] = height

    if 'scale' not in img_info:
        if 'viewer' not in img_info or 'scale' not in img_info['viewer']:
            raise ToyzJobError(
                "You must either supply a scale or image viewer parameters")
        if img_info['viewer']['scale'] < 0:
            img_info['viewer'] = get_best_fit(width, height,
                                              img_info['viewer'])
        else:
            img_info['viewer'] = get_window(img_info['viewer'])
    else:
        img_info['viewer'] = get_window(img_info['viewer'])
    img_info['scale'] = img_info['viewer']['scale']
    img_info['scaled_width'] = int(math.ceil(width * img_info['scale']))
    img_info['scaled_height'] = int(math.ceil(height * img_info['scale']))
    img_info['columns'] = int(
        math.ceil(img_info['scaled_width'] / file_info['tile_width']))
    img_info['rows'] = int(
        math.ceil(img_info['scaled_height'] / file_info['tile_height']))

    img_defaults = {'invert_x': False, 'invert_y': False, 'tiles': {}}
    for default in img_defaults:
        if default not in img_info:
            if default in file_info:
                img_info[default] = file_info[default]
            else:
                img_info[default] = img_defaults[default]

    #print('img_info:', img_info)
    return img_info