Skip to content

Commit

Permalink
* When running differential expression, RNAlysis session reports will…
Browse files Browse the repository at this point in the history
… automatically include the auto-generated R script, as well as the sanitized design matrix used.

* Added optional parameters to all differential expression samples, allowing users to return a path to the auto-generated R script and data sanitized design matrix used.
  • Loading branch information
GuyTeichman committed May 8, 2024
1 parent bad763b commit 6b4e265
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 3 deletions.
2 changes: 2 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ Changed
* RNAlysis now offers default values for differential expression tables' column names.
* Functions that average replicates now display clearer group names by default.
* The RNAlysis interface to ShortStack now uses the most recent API (replace 'knownRNAs' with 'known_miRNAs').
* When running differential expression, RNAlysis session reports will automatically include the auto-generated R script, as well as the sanitized design matrix used.
* Added optional parameters to all differential expression samples, allowing users to return a path to the auto-generated R script and data sanitized design matrix used.

Fixed
*******
Expand Down
18 changes: 15 additions & 3 deletions rnalysis/gui/gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,8 @@ def __init__(self, parent=None):


class DiffExpWindow(gui_windows.FuncExternalWindow):
EXCLUDED_PARAMS = {'self', 'comparisons', 'covariates', 'lrt_factors', 'model_factors'}
EXCLUDED_PARAMS = {'self', 'comparisons', 'covariates', 'lrt_factors', 'model_factors', 'return_design_matrix',
'return_code'}
IGNORED_WIDGETS = gui_windows.FuncExternalWindow.IGNORED_WIDGETS | {'load_design'}

__slots__ = {'comparisons': 'list of comparisons to make',
Expand Down Expand Up @@ -438,6 +439,9 @@ def init_lrt_ui(self):

def get_analysis_kwargs(self):
kwargs = super().get_analysis_kwargs()
kwargs['return_design_matrix'] = True
kwargs['return_code'] = True

kwargs['comparisons'] = self.comparisons_widgets['picker'].get_comparison_values()
if not self.simplified:
kwargs['covariates'] = self.covariates_widgets['picker'].get_comparison_values()
Expand Down Expand Up @@ -1610,6 +1614,9 @@ def process_outputs(self, outputs, job_id: int, source_name: str = ''):
tab_name = self.get_tab_name()
for this_src_name, output in outputs.items():
self.process_outputs(output, job_id, f"{this_src_name} {tab_name}")
elif isinstance(outputs, Path):
new_id = JOB_COUNTER.get_id()
self.itemSpawned.emit(f"'{source_name}'\noutput", new_id, job_id, outputs)

def _multi_keep_window_accepted(self, dialog: 'MultiKeepWindow', source_name: str):
kept_outputs = dialog.result()
Expand Down Expand Up @@ -3492,7 +3499,7 @@ def update_report_spawn(self, name: str, spawn_id: int, predecessor_id: int,
def is_valid_spawn(spawn: object):
if validation.isinstanceinh(spawn, filtering.Filter) \
or validation.isinstanceinh(spawn, enrichment.FeatureSet) \
or isinstance(spawn, (pd.Series, pd.DataFrame, plt.Figure)) \
or isinstance(spawn, (pd.Series, pd.DataFrame, plt.Figure, Path)) \
or validation.isinstanceinh(spawn, generic.GenericPipeline):
return True
return False
Expand All @@ -3503,7 +3510,7 @@ def _get_spawn_type(spawn: Union[filtering.Filter, enrichment.FeatureSet, pd.Dat
spawn_type = FILTER_OBJ_TYPES_INV.get(type(spawn).__name__, 'Other table')
elif validation.isinstanceinh(spawn, enrichment.FeatureSet):
spawn_type = 'Gene set'
elif isinstance(spawn, (pd.Series, pd.DataFrame, plt.Figure)):
elif isinstance(spawn, (pd.Series, pd.DataFrame, plt.Figure, Path)):
spawn_type = 'Other output'
elif validation.isinstanceinh(spawn, generic.GenericPipeline):
spawn_type = 'Pipeline'
Expand All @@ -3526,6 +3533,8 @@ def _cache_spawn(spawn: Union[filtering.Filter, enrichment.FeatureSet, pd.DataFr
elif validation.isinstanceinh(spawn, generic.GenericPipeline):
filename = parsing.slugify(suffix) + '.yaml'
obj = spawn.export_pipeline(None)
elif isinstance(spawn, Path):
filename = parsing.slugify(suffix) + spawn.suffix
else:
raise TypeError(f"Invalid spawn type '{type(spawn)}' for spawn '{spawn}'!")
io.cache_gui_file(obj, filename)
Expand Down Expand Up @@ -3554,6 +3563,9 @@ def _format_report_desc(obj: Union[filtering.Filter, enrichment.FeatureSet, pd.D
desc = f'<img src="data/{filename}" alt="Figure" height="400">'
elif validation.isinstanceinh(obj, generic.GenericPipeline):
desc = str(obj).replace('\n', '<br>')
elif isinstance(obj, Path):
data = io.load_cached_gui_file(obj)
desc = f'<pre><code>{data}</code></pre>'.replace('\n', '<br>')
else:
raise TypeError(f"Invalid object type '{type(obj)}' of object '{obj}'.")

Expand Down
6 changes: 6 additions & 0 deletions rnalysis/utils/io.py
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,9 @@ def load_cached_gui_file(filename: Union[str, Path], load_as_obj: bool = True) -
with open(file_path) as f:
return {item.strip() for item in f.readlines()}

elif file_path.suffix in {'.R'} and load_as_obj:
with open(file_path) as f:
return f.read()
else:
with open(file_path, 'rb') as f:
return f.read()
Expand All @@ -156,6 +159,9 @@ def cache_gui_file(item: Union[pd.DataFrame, set, str], filename: str):
save_table(item, file_path, index=True)
elif isinstance(item, set):
save_gene_set(item, file_path)
elif isinstance(item, Path) and item.suffix == '.R':
assert item.exists(), f"File '{item}' flagged for caching does not exist!"
shutil.copy(item, file_path)
elif isinstance(item, str):
with open(file_path, 'w') as f:
f.write(item)
Expand Down

0 comments on commit 6b4e265

Please sign in to comment.