def trackster(self, trans, **kwargs): """ Display browser for the visualization denoted by id and add the datasets listed in `dataset_ids`. """ # define app configuration app = { 'jscript' : "viz/trackster" } # get dataset to add id = kwargs.get( "id", None ) # get dataset to add new_dataset_id = kwargs.get( "dataset_id", None ) # set up new browser if no id provided if not id: # use dbkey from dataset to be added or from incoming parameter dbkey = None if new_dataset_id: decoded_id = self.decode_id( new_dataset_id ) hda = self.hda_manager.get_owned( decoded_id, trans.user, current_history=trans.user ) dbkey = hda.dbkey if dbkey == '?': dbkey = kwargs.get( "dbkey", None ) # save database key app['default_dbkey'] = dbkey else: # load saved visualization vis = self.get_visualization( trans, id, check_ownership=False, check_accessible=True ) app['viz_config'] = self.get_visualization_config( trans, vis ) # backup id app['id'] = id; # add dataset id app['add_dataset'] = new_dataset_id # check for gene region gene_region = GenomeRegion.from_str(kwargs.get("gene_region", "")) # update gene region of saved visualization if user parses a new gene region in the url if gene_region.chrom is not None: app['gene_region'] = { 'chrom' : gene_region.chrom, 'start' : gene_region.start, 'end' : gene_region.end } # fill template return trans.fill_template('galaxy.panels.mako', config = {'right_panel' : True, 'app' : app})
def trackster(self, trans, **kwargs): """ Display browser for the visualization denoted by id and add the datasets listed in `dataset_ids`. """ # define app configuration app = {'jscript' : "viz/trackster"} # get dataset to add id = kwargs.get("id", None) # get dataset to add new_dataset_id = kwargs.get("dataset_id", None) # set up new browser if no id provided if not id: # use dbkey from dataset to be added or from incoming parameter dbkey = None if new_dataset_id: decoded_id = self.decode_id(new_dataset_id) hda = self.hda_manager.get_owned(decoded_id, trans.user, current_history=trans.user) dbkey = hda.dbkey if dbkey == '?': dbkey = kwargs.get("dbkey", None) # save database key app['default_dbkey'] = dbkey else: # load saved visualization vis = self.get_visualization(trans, id, check_ownership=False, check_accessible=True) app['viz_config'] = self.get_visualization_config(trans, vis) # backup id app['id'] = id # add dataset id app['add_dataset'] = new_dataset_id # check for gene region gene_region = GenomeRegion.from_str(kwargs.get("gene_region", "")) # update gene region of saved visualization if user parses a new gene region in the url if gene_region.chrom is not None: app['gene_region'] = { 'chrom' : gene_region.chrom, 'start' : gene_region.start, 'end' : gene_region.end } # fill template return trans.fill_template('galaxy.panels.mako', config={'right_panel': True, 'app': app})
def trackster(self, trans, id=None, **kwargs): """ Display browser for the visualization denoted by id and add the datasets listed in `dataset_ids`. """ # Get dataset to add. new_dataset_id = kwargs.get( "dataset_id", None ) # Check for gene region gene_region = GenomeRegion.from_str(kwargs.get("gene_region", "")) # Set up new browser if no id provided. if not id: # Use dbkey from dataset to be added or from incoming parameter. dbkey = None if new_dataset_id: dbkey = self.get_dataset( trans, new_dataset_id ).dbkey if dbkey == '?': dbkey = kwargs.get( "dbkey", None ) # fill template return trans.fill_template( "tracks/browser.mako", viewport_config=gene_region.__dict__, add_dataset=new_dataset_id, default_dbkey=dbkey ) # Display saved visualization. vis = self.get_visualization( trans, id, check_ownership=False, check_accessible=True ) viz_config = self.get_visualization_config( trans, vis ) # Update gene region of saved visualization if user parses a new gene region in the url if gene_region.chrom is not None: viz_config['viewport']['chrom'] = gene_region.chrom viz_config['viewport']['start'] = gene_region.start viz_config['viewport']['end'] = gene_region.end ''' FIXME: if new_dataset is not None: if trans.security.decode_id(new_dataset) in [ d["dataset_id"] for d in viz_config.get("tracks") ]: new_dataset = None # Already in browser, so don't add ''' # fill template return trans.fill_template( 'tracks/browser.mako', config=viz_config, add_dataset=new_dataset_id )
def _rerun_tool(self, trans, payload, **kwargs): """ Rerun a tool to produce a new output dataset that corresponds to a dataset that a user is currently viewing. """ # # TODO: refactor to use same code as run_tool. # # Run tool on region if region is specificied. run_on_regions = False regions = payload.get('regions', None) if regions: if isinstance(regions, dict): # Regions is a single region. regions = [GenomeRegion.from_dict(regions)] elif isinstance(regions, list): # There is a list of regions. regions = [GenomeRegion.from_dict(r) for r in regions] if len(regions) > 1: # Sort by chrom name, start so that data is not fetched out of order. regions = sorted(regions, key=lambda r: (r.chrom.lower(), r.start)) # Merge overlapping regions so that regions do not overlap # and hence data is not included multiple times. prev = regions[0] cur = regions[1] index = 1 while True: if cur.chrom == prev.chrom and cur.start <= prev.end: # Found overlapping regions, so join them into prev. prev.end = cur.end del regions[index] else: # No overlap, move to next region. prev = cur index += 1 # Get next region or exit. if index == len(regions): # Done. break else: cur = regions[index] run_on_regions = True # Dataset check. decoded_dataset_id = self.decode_id(payload.get('target_dataset_id')) original_dataset = self.hda_manager.get_accessible(decoded_dataset_id, user=trans.user) original_dataset = self.hda_manager.error_if_uploading( original_dataset) msg = self.hda_manager.data_conversion_status(original_dataset) if msg: return msg # Set tool parameters--except non-hidden dataset parameters--using combination of # job's previous parameters and incoming parameters. Incoming parameters # have priority. # original_job = self.hda_manager.creating_job(original_dataset) tool = trans.app.toolbox.get_tool(original_job.tool_id) if not tool or not tool.allow_user_access(trans.user): return trans.app.model.Dataset.conversion_messages.NO_TOOL tool_params = dict([(p.name, p.value) for p in original_job.parameters]) # TODO: rather than set new inputs using dict of json'ed value, unpack parameters and set using set_param_value below. # TODO: need to handle updates to conditional parameters; conditional # params are stored in dicts (and dicts within dicts). new_inputs = payload['inputs'] tool_params.update( dict([(key, dumps(value)) for key, value in new_inputs.items() if key in tool.inputs and value is not None])) tool_params = tool.params_from_strings(tool_params, self.app) # # If running tool on region, convert input datasets (create indices) so # that can regions of data can be quickly extracted. # data_provider_registry = trans.app.data_provider_registry messages_list = [] if run_on_regions: for jida in original_job.input_datasets: input_dataset = jida.dataset data_provider = data_provider_registry.get_data_provider( trans, original_dataset=input_dataset, source='data') if data_provider and (not data_provider.converted_dataset or data_provider.converted_dataset.state != trans.app.model.Dataset.states.OK): # Can convert but no converted dataset yet, so return message about why. data_sources = input_dataset.datatype.data_sources msg = input_dataset.convert_dataset( trans, data_sources['data']) if msg is not None: messages_list.append(msg) # Return any messages generated during conversions. return_message = self._get_highest_priority_msg(messages_list) if return_message: return return_message # # Set target history (the history that tool will use for inputs/outputs). # If user owns dataset, put new data in original dataset's history; if # user does not own dataset (and hence is accessing dataset via sharing), # put new data in user's current history. # if original_dataset.history.user == trans.user: target_history = original_dataset.history else: target_history = trans.get_history(create=True) hda_permissions = trans.app.security_agent.history_get_default_permissions( target_history) def set_param_value(param_dict, param_name, param_value): """ Set new parameter value in a tool's parameter dictionary. """ # Recursive function to set param value. def set_value(param_dict, group_name, group_index, param_name, param_value): if group_name in param_dict: param_dict[group_name][group_index][ param_name] = param_value return True elif param_name in param_dict: param_dict[param_name] = param_value return True else: # Recursive search. return_val = False for value in param_dict.values(): if isinstance(value, dict): return_val = set_value(value, group_name, group_index, param_name, param_value) if return_val: return return_val return False # Parse parameter name if necessary. if param_name.find("|") == -1: # Non-grouping parameter. group_name = group_index = None else: # Grouping parameter. group, param_name = param_name.split("|") index = group.rfind("_") group_name = group[:index] group_index = int(group[index + 1:]) return set_value(param_dict, group_name, group_index, param_name, param_value) # Set parameters based tool's trackster config. params_set = {} for action in tool.trackster_conf.actions: success = False for joda in original_job.output_datasets: if joda.name == action.output_name: set_param_value(tool_params, action.name, joda.dataset) params_set[action.name] = True success = True break if not success: return trans.app.model.Dataset.conversion_messages.ERROR # # Set input datasets for tool. If running on regions, extract and use subset # when possible. # if run_on_regions: regions_str = ",".join([str(r) for r in regions]) for jida in original_job.input_datasets: # If param set previously by config actions, do nothing. if jida.name in params_set: continue input_dataset = jida.dataset if input_dataset is None: # optional dataset and dataset wasn't selected tool_params[jida.name] = None elif run_on_regions and 'data' in input_dataset.datatype.data_sources: # Dataset is indexed and hence a subset can be extracted and used # as input. # Look for subset. subset_dataset_association = trans.sa_session.query(trans.app.model.HistoryDatasetAssociationSubset) \ .filter_by(hda=input_dataset, location=regions_str) \ .first() if subset_dataset_association: # Data subset exists. subset_dataset = subset_dataset_association.subset else: # Need to create subset. data_source = input_dataset.datatype.data_sources['data'] input_dataset.get_converted_dataset(trans, data_source) input_dataset.get_converted_dataset_deps( trans, data_source) # Create new HDA for input dataset's subset. new_dataset = trans.app.model.HistoryDatasetAssociation( extension=input_dataset.ext, dbkey=input_dataset.dbkey, create_dataset=True, sa_session=trans.sa_session, name="Subset [%s] of data %i" % (regions_str, input_dataset.hid), visible=False) target_history.add_dataset(new_dataset) trans.sa_session.add(new_dataset) trans.app.security_agent.set_all_dataset_permissions( new_dataset.dataset, hda_permissions) # Write subset of data to new dataset data_provider = data_provider_registry.get_data_provider( trans, original_dataset=input_dataset, source='data') trans.app.object_store.create(new_dataset.dataset) data_provider.write_data_to_file(regions, new_dataset.file_name) # TODO: (a) size not working; (b) need to set peek. new_dataset.set_size() new_dataset.info = "Data subset for trackster" new_dataset.set_dataset_state( trans.app.model.Dataset.states.OK) # Set metadata. # TODO: set meta internally if dataset is small enough? trans.app.datatypes_registry.set_external_metadata_tool.tool_action.execute( trans.app.datatypes_registry. set_external_metadata_tool, trans, incoming={'input1': new_dataset}, overwrite=False, job_params={"source": "trackster"}) # Add HDA subset association. subset_association = trans.app.model.HistoryDatasetAssociationSubset( hda=input_dataset, subset=new_dataset, location=regions_str) trans.sa_session.add(subset_association) subset_dataset = new_dataset trans.sa_session.flush() # Add dataset to tool's parameters. if not set_param_value(tool_params, jida.name, subset_dataset): return { "error": True, "message": "error setting parameter %s" % jida.name } # # Execute tool and handle outputs. # try: subset_job, subset_job_outputs = tool.execute( trans, incoming=tool_params, history=target_history, job_params={"source": "trackster"}) except Exception as e: # Lots of things can go wrong when trying to execute tool. return { "error": True, "message": e.__class__.__name__ + ": " + str(e) } if run_on_regions: for output in subset_job_outputs.values(): output.visible = False trans.sa_session.flush() # # Return new track that corresponds to the original dataset. # output_name = None for joda in original_job.output_datasets: if joda.dataset == original_dataset: output_name = joda.name break for joda in subset_job.output_datasets: if joda.name == output_name: output_dataset = joda.dataset dataset_dict = output_dataset.to_dict() dataset_dict['id'] = trans.security.encode_id(dataset_dict['id']) dataset_dict['track_config'] = self.get_new_track_config( trans, output_dataset) return dataset_dict
def _rerun_tool( self, trans, payload, **kwargs ): """ Rerun a tool to produce a new output dataset that corresponds to a dataset that a user is currently viewing. """ # # TODO: refactor to use same code as run_tool. # # Run tool on region if region is specificied. run_on_regions = False regions = payload.get( 'regions', None ) if regions: if isinstance( regions, dict ): # Regions is a single region. regions = [ GenomeRegion.from_dict( regions ) ] elif isinstance( regions, list ): # There is a list of regions. regions = [ GenomeRegion.from_dict( r ) for r in regions ] if len( regions ) > 1: # Sort by chrom name, start so that data is not fetched out of order. regions = sorted(regions, key=lambda r: (r.chrom.lower(), r.start)) # Merge overlapping regions so that regions do not overlap # and hence data is not included multiple times. prev = regions[0] cur = regions[1] index = 1 while True: if cur.chrom == prev.chrom and cur.start <= prev.end: # Found overlapping regions, so join them into prev. prev.end = cur.end del regions[ index ] else: # No overlap, move to next region. prev = cur index += 1 # Get next region or exit. if index == len( regions ): # Done. break else: cur = regions[ index ] run_on_regions = True # Dataset check. original_dataset = self.get_dataset( trans, payload[ 'target_dataset_id' ], check_ownership=False, check_accessible=True ) msg = self.check_dataset_state( trans, original_dataset ) if msg: return msg # # Set tool parameters--except non-hidden dataset parameters--using combination of # job's previous parameters and incoming parameters. Incoming parameters # have priority. # original_job = self.get_hda_job( original_dataset ) tool = trans.app.toolbox.get_tool( original_job.tool_id ) if not tool: return trans.app.model.Dataset.conversion_messages.NO_TOOL tool_params = dict( [ ( p.name, p.value ) for p in original_job.parameters ] ) # TODO: rather than set new inputs using dict of json'ed value, unpack parameters and set using set_param_value below. # TODO: need to handle updates to conditional parameters; conditional # params are stored in dicts (and dicts within dicts). new_inputs = payload[ 'inputs' ] tool_params.update( dict( [ ( key, to_json_string( value ) ) for key, value in new_inputs.items() if key in tool.inputs and new_inputs[ key ] is not None ] ) ) tool_params = tool.params_from_strings( tool_params, self.app ) # # If running tool on region, convert input datasets (create indices) so # that can regions of data can be quickly extracted. # data_provider_registry = trans.app.data_provider_registry messages_list = [] if run_on_regions: for jida in original_job.input_datasets: input_dataset = jida.dataset data_provider = data_provider_registry.get_data_provider( trans, original_dataset=input_dataset, source='data' ) if data_provider and ( not data_provider.converted_dataset or data_provider.converted_dataset.state != trans.app.model.Dataset.states.OK ): # Can convert but no converted dataset yet, so return message about why. data_sources = input_dataset.datatype.data_sources msg = input_dataset.convert_dataset( trans, data_sources[ 'data' ] ) if msg is not None: messages_list.append( msg ) # Return any messages generated during conversions. return_message = self._get_highest_priority_msg( messages_list ) if return_message: return return_message # # Set target history (the history that tool will use for inputs/outputs). # If user owns dataset, put new data in original dataset's history; if # user does not own dataset (and hence is accessing dataset via sharing), # put new data in user's current history. # if original_dataset.history.user == trans.user: target_history = original_dataset.history else: target_history = trans.get_history( create=True ) hda_permissions = trans.app.security_agent.history_get_default_permissions( target_history ) def set_param_value( param_dict, param_name, param_value ): """ Set new parameter value in a tool's parameter dictionary. """ # Recursive function to set param value. def set_value( param_dict, group_name, group_index, param_name, param_value ): if group_name in param_dict: param_dict[ group_name ][ group_index ][ param_name ] = param_value return True elif param_name in param_dict: param_dict[ param_name ] = param_value return True else: # Recursive search. return_val = False for value in param_dict.values(): if isinstance( value, dict ): return_val = set_value( value, group_name, group_index, param_name, param_value) if return_val: return return_val return False # Parse parameter name if necessary. if param_name.find( "|" ) == -1: # Non-grouping parameter. group_name = group_index = None else: # Grouping parameter. group, param_name = param_name.split( "|" ) index = group.rfind( "_" ) group_name = group[ :index ] group_index = int( group[ index + 1: ] ) return set_value( param_dict, group_name, group_index, param_name, param_value ) # Set parameters based tool's trackster config. params_set = {} for action in tool.trackster_conf.actions: success = False for joda in original_job.output_datasets: if joda.name == action.output_name: set_param_value( tool_params, action.name, joda.dataset ) params_set[ action.name ] = True success = True break if not success: return trans.app.model.Dataset.conversion_messages.ERROR # # Set input datasets for tool. If running on regions, extract and use subset # when possible. # if run_on_regions: regions_str = ",".join( [ str( r ) for r in regions ] ) for jida in original_job.input_datasets: # If param set previously by config actions, do nothing. if jida.name in params_set: continue input_dataset = jida.dataset if input_dataset is None: # optional dataset and dataset wasn't selected tool_params[ jida.name ] = None elif run_on_regions and 'data' in input_dataset.datatype.data_sources: # Dataset is indexed and hence a subset can be extracted and used # as input. # Look for subset. subset_dataset_association = trans.sa_session.query( trans.app.model.HistoryDatasetAssociationSubset ) \ .filter_by( hda=input_dataset, location=regions_str ) \ .first() if subset_dataset_association: # Data subset exists. subset_dataset = subset_dataset_association.subset else: # Need to create subset. data_source = input_dataset.datatype.data_sources[ 'data' ] converted_dataset = input_dataset.get_converted_dataset( trans, data_source ) deps = input_dataset.get_converted_dataset_deps( trans, data_source ) # Create new HDA for input dataset's subset. new_dataset = trans.app.model.HistoryDatasetAssociation( extension=input_dataset.ext, \ dbkey=input_dataset.dbkey, \ create_dataset=True, \ sa_session=trans.sa_session, name="Subset [%s] of data %i" % \ ( regions_str, input_dataset.hid ), visible=False ) target_history.add_dataset( new_dataset ) trans.sa_session.add( new_dataset ) trans.app.security_agent.set_all_dataset_permissions( new_dataset.dataset, hda_permissions ) # Write subset of data to new dataset data_provider = data_provider_registry.get_data_provider( trans, original_dataset=input_dataset, source='data' ) trans.app.object_store.create( new_dataset.dataset ) data_provider.write_data_to_file( regions, new_dataset.file_name ) # TODO: (a) size not working; (b) need to set peek. new_dataset.set_size() new_dataset.info = "Data subset for trackster" new_dataset.set_dataset_state( trans.app.model.Dataset.states.OK ) # Set metadata. # TODO: set meta internally if dataset is small enough? trans.app.datatypes_registry.set_external_metadata_tool.tool_action.execute( trans.app.datatypes_registry.set_external_metadata_tool, trans, incoming={ 'input1': new_dataset }, overwrite=False, job_params={ "source" : "trackster" } ) # Add HDA subset association. subset_association = trans.app.model.HistoryDatasetAssociationSubset( hda=input_dataset, subset=new_dataset, location=regions_str ) trans.sa_session.add( subset_association ) subset_dataset = new_dataset trans.sa_session.flush() # Add dataset to tool's parameters. if not set_param_value( tool_params, jida.name, subset_dataset ): return { "error" : True, "message" : "error setting parameter %s" % jida.name } # # Execute tool and handle outputs. # try: subset_job, subset_job_outputs = tool.execute( trans, incoming=tool_params, history=target_history, job_params={ "source" : "trackster" } ) except Exception, e: # Lots of things can go wrong when trying to execute tool. return { "error" : True, "message" : e.__class__.__name__ + ": " + str(e) }