Source code for schrodinger.application.livedesign.upload_utils

import enum
import os

from schrodinger.application.livedesign import login

from requests.exceptions import HTTPError

# Constants used in the LiveDesign API
KEY_ID = 'id'
READ_ONLY = 'READ_ONLY'
FILE = 'FILE'
DEFAULT = 'DEFAULT'
ATTACHMENT = 'ATTACHMENT'
IMAGE = 'IMAGE'
THREE_D = 'THREE_D'
LD_FILE_TYPES = {ATTACHMENT, IMAGE, THREE_D}


# LiveDesign model command types
[docs]class CommandType(enum.Enum): normal = 'NORMAL' realtime = 'REALTIME' click_to_run = 'CLICK_TO_RUN' clustering = 'CLUSTERING' def __str__(self): return self.value
[docs]def upload_ld_attachment(file_path, project_id, ld_client, remote_file_name=None, file_type=ATTACHMENT): """ Upload a file to LiveDesign as an attachment and return the corresponding attachment ID. :param file_path: the path to the file to be uploaded :type file_path: str :param project_id: the ID of the LiveDesign project that the file should be uploaded to :type project_id: int :param ld_client: an instance of the LD client to use for the upload :type ld_client: ldclient.client.LDClient :param remote_file_name: the name of the attachment once uploaded; `None`, use the (base) name of the file path :type remote_file_name: str or NoneType :param file_type: Type of file being uploaded. Param should be an image, attachment, or 3D structure in LD_FILE_TYPES. :type file_type: str :return: the attachment ID :rtype: str """ if remote_file_name is None: remote_file_name = os.path.basename(file_path) assert file_type in LD_FILE_TYPES attach_map = ld_client.get_or_create_attachment( file_path, file_type=file_type, project_ids=[project_id], remote_file_name=remote_file_name) return attach_map[KEY_ID]
[docs]def get_template_vars(template_data, template_class): """ Provided a list containing LiveDesign attachment IDs and names, generate and return a list of template variables. :param template_data: a list of 2-`tuple` containing LD attachment IDs and corresponding names :type template_data: `list` of 2-`tuple` of (`int`, `str`) :param template_class: the template class to initialize, from the downloaded ldclient.models module. :type template_class: class :return: a list of template variables :rtype: `list` of `ldclient.models.ModelTemplateVar` """ template_vars = [] for attachment_id, name in template_data: template_var = template_class(tag=READ_ONLY, type=FILE, name=name, data=attachment_id) template_vars.append(template_var) return template_vars
[docs]def get_model_by_name(ld_client, model_name, include_archived=True): """ Retrieves a single model. Used in KNIME. :param ld_client: an instance of the LD client to get models :type ld_client: `ldclient.client.LDClient` :param model_name: Name of the model to retrieve :type model_name: str :param include_archived: Whether to include archived models or not. If False, ignore archived models :type include_archived: bool :return: Matched model object :rtype: `models.Model` """ def is_model_valid(model): ''' Checks if the given model's name matches model_name If the name matches, but if include_archived is False and if the matched model is archived, then return False ''' if model.name == model_name: return True if include_archived else not model.archived return False matching_models = list(filter(is_model_valid, ld_client.models())) if len(matching_models) == 0: raise RuntimeError("No models found with name: {0}".format(model_name)) if len(matching_models) > 1: raise RuntimeError( "Multiple models found with name: {0}".format(model_name)) return matching_models[0]
[docs]def upload_ld_model(name, user_name, folder, project_id, template_vars, description, protocol_id, ld_client, model_class, model_recursive_class, command_type=CommandType.normal, predictions=None, model_id=None, overwrite=False): """ Create a LiveDesign model and upload it to a LiveDesign server. :param name: the name of the model :type name: `str` :param user_name: the name of the user uploading this model :type user_name: `str` :param folder: the directory path in which the model should be created on the LiveDesign server :type folder: `str` :param project_id: the ID of the LiveDesign project that the file should be uploaded to :type project_id: `str` :param template_vars: a list of template variables containing attachment data :rtype: `list` of `ldclient.models.ModelTemplateVar` :param description: a description of the model :type description: `str` :param protocol_id: the ID of the parent protocol for this model :type protocol_id: `str` :param ld_client: an instance of the LD client to use for the upload :type ld_client: `ldclient.client.LDClient` :param model_class: the model class, from the downloaded ldclient.models module :type model_class: class :param model_recursive_class: the "model recursive class" that is necessary to build the model instance :type: model_recursive_class: :class: `ModelRecursive` :param command_type: Command type of the model to be uploaded :type command_type: CommandType :param predictions: the predictions to be added to the model :type predictions: `list` of `ldclient.models.ModelReturn` :param model_id: Id of the model to be updated. If model_id is specified, 'overwrite' option will be ignored. :type model_id: int :param overwrite: If true and if exactly one model with 'name' already exists, then instead of creating a new one, update the model. If no model or more than one model exist with same name, then create a new model. If 'model_id' is specified, this option will be ignored and always the given model_id is updated. :type overwrite: bool :return: a tuple containing the model instance uploaded to the LiveDesign server (if available) and a message about the status of the upload :rtype: tuple[ldclient.models.Model or None, str] """ default_command_type = model_recursive_class(DEFAULT, str(command_type)) command_queue = model_recursive_class(DEFAULT, 'SYNC') if not predictions: predictions = [] model = model_class(name=name, archived=False, published=True, command_type=default_command_type, command_queue=command_queue, user=user_name, folder=folder, returns=predictions, project_ids=[project_id], template_vars=template_vars, description=description, parent=protocol_id) try: if model_id: model.id = model_id model = ld_client.update_model(model_id, model) elif overwrite: model = ld_client.create_or_update_model(model) else: model = ld_client.create_model(model) return model, '' except HTTPError as exc: code = exc.response.status_code msg = f'Export resulted in HTTP error {code}.' if 'Permission denied' in str(exc): msg += (' Please make sure your account has the necessary' ' permissions to perform this operation.') return None, msg
[docs]def get_uploaded_model_url(host, model_id, ld_version, use_lig_designer_config: bool = False): """ Gets the URL for a model the user has uploaded :param host: host name for model :type host: str :param model_id: model's ID number :type model_id: str :param ld_version: Version of LD used :type ld_version: login.Version :param use_lig_designer_config: if the ligand designer config url should be used :return: URL for the user's uploaded model :rtype: str """ if use_lig_designer_config: return f'{host}/admin/liganddesignerconfigurations/liganddesignerconfiguration/{str(model_id)}/change/' if ld_version >= login.LD_VERSION_NEW_GLIDE_MODEL_URL: path = 'models' else: path = 'extprops' return f'{host}/admin/{path}/ldmodel/{str(model_id)}/change/'