Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions ms2/src/org/labkey/ms2/MS2Controller.java
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@
import org.labkey.ms2.compare.RunColumn;
import org.labkey.ms2.compare.SpectraCountQueryView;
import org.labkey.ms2.peptideview.AbstractMS2RunView;
import org.labkey.ms2.peptideview.AbstractQueryMS2RunView;
import org.labkey.ms2.peptideview.MS2RunViewType;
import org.labkey.ms2.peptideview.QueryPeptideMS2RunView;
import org.labkey.ms2.pipeline.AbstractMS2SearchTask;
Expand Down Expand Up @@ -257,7 +256,7 @@ private NavTree appendProteinAdminNavTrail(NavTree root, String title, PageConfi
}


private AbstractMS2RunView<? extends WebPartView> getPeptideView(String grouping, MS2Run... runs)
private AbstractMS2RunView getPeptideView(String grouping, MS2Run... runs)
{
return MS2RunViewType.getViewType(grouping).createView(getViewContext(), runs);
}
Expand Down Expand Up @@ -1081,9 +1080,9 @@ public ModelAndView getView(ChartForm form, BindException errors) throws Excepti
throw new NotFoundException("Unsupported GO chart type: " + form.getChartType());
}

AbstractMS2RunView<? extends WebPartView> peptideView = getPeptideView(queryURL.getParameter("grouping"), _run);
AbstractMS2RunView peptideView = getPeptideView(queryURL.getParameter("grouping"), _run);

Map<String, SimpleFilter> filters = peptideView.getFilter(queryURL, _run);
Map<String, SimpleFilter> filters = peptideView.getFilter(queryURL);

String chartTitle = "GO " + _goChartType + " Classifications";
SQLFragment fragment = peptideView.getProteins(queryURL, _run, form);
Expand Down Expand Up @@ -3828,7 +3827,7 @@ public ModelAndView getView(DetailsForm form, BindException errors) throws Excep
run = form.validateRun();
QueryPeptideMS2RunView peptideQueryView = new QueryPeptideMS2RunView(getViewContext(), run);
SimpleFilter filter = getAllPeptidesFilter(getViewContext(), getViewContext().getActionURL().clone(), run);
AbstractQueryMS2RunView.AbstractMS2QueryView gridView = peptideQueryView.createGridView(filter);
AbstractMS2RunView.AbstractMS2QueryView gridView = peptideQueryView.createGridView(filter);
protein.setPeptides(new TableSelector(gridView.getTable(), PageFlowUtil.set("Peptide"), filter, new Sort("Peptide")).getArray(String.class));
}

Expand Down
245 changes: 230 additions & 15 deletions ms2/src/org/labkey/ms2/peptideview/AbstractMS2RunView.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,40 @@
package org.labkey.ms2.peptideview;

import org.apache.log4j.Logger;
import org.jetbrains.annotations.Nullable;
import org.labkey.api.data.ButtonBar;
import org.labkey.api.data.ColumnHeaderType;
import org.labkey.api.data.ColumnInfo;
import org.labkey.api.data.Container;
import org.labkey.api.data.DataRegion;
import org.labkey.api.data.DisplayColumn;
import org.labkey.api.data.ExcelWriter;
import org.labkey.api.data.MenuButton;
import org.labkey.api.data.NestableQueryView;
import org.labkey.api.data.NestedRenderContext;
import org.labkey.api.data.RenderContext;
import org.labkey.api.data.SQLFragment;
import org.labkey.api.data.SimpleFilter;
import org.labkey.api.data.Sort;
import org.labkey.api.data.TSVGridWriter;
import org.labkey.api.data.Table;
import org.labkey.api.data.TableInfo;
import org.labkey.api.data.TableSelector;
import org.labkey.api.query.DetailsURL;
import org.labkey.api.query.FieldKey;
import org.labkey.api.query.QueryNestingOption;
import org.labkey.api.query.QueryService;
import org.labkey.api.query.QuerySettings;
import org.labkey.api.query.UserSchema;
import org.labkey.api.security.User;
import org.labkey.api.util.Pair;
import org.labkey.api.view.ActionURL;
import org.labkey.api.view.DataView;
import org.labkey.api.view.DisplayElement;
import org.labkey.api.view.GridView;
import org.labkey.api.view.NavTree;
import org.labkey.api.view.NotFoundException;
import org.labkey.api.view.ViewContext;
import org.labkey.api.view.WebPartView;
import org.labkey.ms2.HydrophobicityColumn;
import org.labkey.ms2.MS2Controller;
import org.labkey.ms2.MS2ExportType;
Expand All @@ -44,27 +59,27 @@
import org.labkey.ms2.MS2Run;
import org.labkey.ms2.MassType;
import org.labkey.ms2.RunListException;
import org.labkey.ms2.SpectrumIterator;
import org.labkey.ms2.SpectrumRenderer;
import org.labkey.ms2.protein.ProteinManager;
import org.labkey.ms2.protein.tools.GoLoader;
import org.labkey.ms2.protein.tools.ProteinDictionaryHelpers;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.Controller;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

/**
* User: jeckels
* Date: Feb 22, 2006
*/
public abstract class AbstractMS2RunView<WebPartType extends WebPartView>
public abstract class AbstractMS2RunView
{
private static Logger _log = Logger.getLogger(AbstractMS2RunView.class);

Expand All @@ -83,21 +98,19 @@ public AbstractMS2RunView(ViewContext viewContext, MS2Run... runs)
_runs = runs;
}

public WebPartType createGridView(MS2Controller.RunForm form)
public AbstractMS2QueryView createGridView(MS2Controller.RunForm form)
{
return createGridView(form.getExpanded(), false);
}

public abstract WebPartType createGridView(boolean expanded, boolean forExport);
public abstract AbstractMS2QueryView createGridView(boolean expanded, boolean forExport);

public abstract GridView getPeptideViewForProteinGrouping(String proteinGroupingId, String columns) throws SQLException;

public abstract void addSQLSummaries(SimpleFilter peptideFilter, List<Pair<String, String>> sqlSummaries);

public abstract SQLFragment getProteins(ActionURL queryUrl, MS2Run run, MS2Controller.ChartForm form);

public abstract Map<String, SimpleFilter> getFilter(ActionURL queryUrl, MS2Run run);

public Container getContainer()
{
return _container;
Expand All @@ -112,14 +125,14 @@ protected String getAJAXNestedGridURL()
return groupURL.toString() + "&proteinGroupingId=";
}

protected ButtonBar createButtonBar(Class<? extends Controller> exportAllAction, Class<? extends Controller> exportSelectedAction, String whatWeAreSelecting, DataRegion dataRegion)
protected ButtonBar createButtonBar(String whatWeAreSelecting, DataRegion dataRegion)
{
ButtonBar result = new ButtonBar();

List<MS2ExportType> exportFormats = getExportTypes();

ActionURL exportUrl = _url.clone();
exportUrl.setAction(exportAllAction);
exportUrl.setAction(MS2Controller.ExportAllPeptidesAction.class);
MenuButton exportAll = new MenuButton("Export All");
for (MS2ExportType exportFormat : exportFormats)
{
Expand All @@ -133,7 +146,7 @@ protected ButtonBar createButtonBar(Class<? extends Controller> exportAllAction,
result.add(exportAll);

MenuButton exportSelected = new MenuButton("Export Selected");
exportUrl.setAction(exportSelectedAction);
exportUrl.setAction(MS2Controller.ExportSelectedPeptidesAction.class);
exportSelected.setRequiresSelection(true);
for (MS2ExportType exportFormat : exportFormats)
{
Expand Down Expand Up @@ -332,13 +345,139 @@ protected MS2Run getSingleRun()
return _runs[0];
}

public abstract ModelAndView exportToTSV(MS2Controller.ExportForm form, HttpServletResponse response, List<String> selectedRows, List<String> headers) throws IOException;
public Map<String, SimpleFilter> getFilter(ActionURL queryUrl)
{
NestableQueryView queryView = createGridView(false, false);
RenderContext context = queryView.createDataView().getRenderContext();
TableInfo tinfo = queryView.createTable();

Sort sort = new Sort();
return Collections.singletonMap("Filter", context.buildFilter(tinfo, Collections.emptyList(), queryUrl, queryView.getDataRegionName(), Table.ALL_ROWS, Table.NO_OFFSET, sort));
}

public void exportToExcel(MS2Controller.ExportForm form, HttpServletResponse response, List<String> selectedRows) throws IOException
{
createGridView(form.getExpanded(), true).exportToExcel(response, selectedRows);
}


public void exportToTSV(MS2Controller.ExportForm form, HttpServletResponse response, List<String> selectedRows, List<String> headers) throws IOException
{
AbstractMS2QueryView gridView = createGridView(form.getExpanded(), true);
gridView.createRowIdFragment(selectedRows);
gridView.exportToTSV(response, headers);
}

public void exportToAMT(MS2Controller.ExportForm form, HttpServletResponse response, List<String> selectedRows) throws IOException
{
AbstractMS2QueryView ms2QueryView = createGridView(form.getExpanded(), true);
ms2QueryView.createRowIdFragment(selectedRows);

List<FieldKey> keys = new ArrayList<>();
keys.add(FieldKey.fromParts("Fraction", "Run", "Run"));
keys.add(FieldKey.fromParts("Fraction", "Fraction"));
keys.add(FieldKey.fromParts("Mass"));
keys.add(FieldKey.fromParts("Scan"));
keys.add(FieldKey.fromParts("RetentionTime"));
keys.add(FieldKey.fromParts("H"));
keys.add(FieldKey.fromParts("PeptideProphet"));
keys.add(FieldKey.fromParts("Peptide"));
ms2QueryView.setOverrideColumns(keys);

ms2QueryView.exportToTSV(response, getAMTFileHeader());
}

public void exportSpectra(MS2Controller.ExportForm form, ActionURL currentURL, SpectrumRenderer spectrumRenderer, List<String> exportRows) throws IOException, RunListException
{
List<MS2Run> runs = form.validateRuns();

// Choose a different iterator based on whether this is a nested view that may include protein group criteria
NestableQueryView queryView = createGridView(form);
SQLFragment sql = generateSubSelect(queryView, currentURL, exportRows, FieldKey.fromParts("RowId")).second;
try (SpectrumIterator iter = new QueryResultSetSpectrumIterator(runs, sql))
{
spectrumRenderer.render(iter);
spectrumRenderer.close();
}
}

/** Generate the SELECT SQL to get a particular FieldKey, respecting the filters and other config on the URL */
protected Pair<ColumnInfo, SQLFragment> generateSubSelect(NestableQueryView queryView, ActionURL currentURL, @Nullable List<String> selectedIds, FieldKey desiredFK)
{
RenderContext context = queryView.createDataView().getRenderContext();
TableInfo tinfo = queryView.createTable();

Sort sort = new Sort();
SimpleFilter filter;
if (context instanceof NestedRenderContext)
{
filter = ((NestedRenderContext)context).buildFilter(tinfo, Collections.emptyList(), currentURL, queryView.getDataRegionName(), Table.ALL_ROWS, Table.NO_OFFSET, sort, true);
}
else
{
filter = context.buildFilter(tinfo, Collections.emptyList(), currentURL, queryView.getDataRegionName(), Table.ALL_ROWS, Table.NO_OFFSET, sort);
}
addSelectionFilter(selectedIds, queryView, filter);

public abstract ModelAndView exportToAMT(MS2Controller.ExportForm form, HttpServletResponse response, List<String> selectedRows) throws IOException;
ColumnInfo desiredCol = QueryService.get().getColumns(tinfo, Collections.singletonList(desiredFK)).get(desiredFK);
if (desiredCol == null)
{
throw new IllegalArgumentException("Couldn't find column " + desiredFK + " in table " + tinfo);
}

List<ColumnInfo> columns = new ArrayList<>();
columns.add(desiredCol);

QueryService.get().ensureRequiredColumns(tinfo, columns, filter, sort, new HashSet<>());

SQLFragment sql = QueryService.get().getSelectSQL(tinfo, columns, filter, sort, Table.ALL_ROWS, Table.NO_OFFSET, false);
return new Pair<>(desiredCol, sql);
}

/** Add a filter for any selection the user might have made. The type of selection depends on the type of view (peptides/protein groups/search engine protein) */
private void addSelectionFilter(@Nullable List<String> exportRows, NestableQueryView queryView, SimpleFilter filter)
{
if (exportRows != null)
{
List<Integer> rowIds = parseIds(exportRows);
FieldKey selectionFK;
QueryNestingOption nestingOption = queryView.getSelectedNestingOption();
if (nestingOption != null)
{
// We're nested, so the selection key is going to be at the protein or protein group level
selectionFK = nestingOption.getAggregateRowIdFieldKey();
}
else
{
// No nesting, so the selection key will just be the peptide's RowId
selectionFK = FieldKey.fromParts("RowId");
}
filter.addClause(new SimpleFilter.InClause(selectionFK, rowIds));
}
}

/**
* Convert from Strings to Integers
* @throws NotFoundException if there's an unparseable value
*/
private List<Integer> parseIds(List<String> exportRows)
{
List<Integer> rowIds = new ArrayList<>(exportRows.size());
for (String exportRow : exportRows)
{
try
{
rowIds.add(Integer.parseInt(exportRow));
}
catch (NumberFormatException e)
{
throw new NotFoundException("Invalid selection: " + exportRow);
}
}
return rowIds;
}

public abstract ModelAndView exportToExcel(MS2Controller.ExportForm form, HttpServletResponse response, List<String> selectedRows) throws IOException;

public abstract void exportSpectra(MS2Controller.ExportForm form, ActionURL currentURL, SpectrumRenderer spectrumRenderer, List<String> exportRows) throws IOException, RunListException;

protected List<String> getAMTFileHeader()
{
Expand Down Expand Up @@ -371,4 +510,80 @@ protected List<String> getAMTFileHeader()

return fileHeader;
}

public abstract class AbstractMS2QueryView extends NestableQueryView
{
protected SimpleFilter.FilterClause _selectedRowsClause;

public AbstractMS2QueryView(UserSchema schema, QuerySettings settings, boolean expanded, boolean forExport, QueryNestingOption... queryNestingOptions)
{
super(schema, settings, expanded, forExport, queryNestingOptions);

setViewItemFilter((type, label) -> SingleMS2RunRReport.TYPE.equals(type));
}

@Override
protected void populateButtonBar(DataView view, ButtonBar bar)
{
super.populateButtonBar(view, bar);
ButtonBar bb = createButtonBar("peptides", view.getDataRegion());
for (DisplayElement element : bb.getList())
{
bar.add(element);
}
}

public void exportToTSV(HttpServletResponse response, List<String> headers) throws IOException
{
getSettings().setMaxRows(Table.ALL_ROWS);

try (TSVGridWriter tsvWriter = getTsvWriter())
{
tsvWriter.setColumnHeaderType(ColumnHeaderType.Caption);
tsvWriter.setFileHeader(headers);
tsvWriter.write(response);
}
}

public void exportToExcel(HttpServletResponse response, List<String> selectedRows) throws IOException
{
createRowIdFragment(selectedRows);
getSettings().setMaxRows(ExcelWriter.MAX_ROWS_EXCEL_97);
exportToExcel(response);
}

protected void createRowIdFragment(List<String> selectedRows)
{
if (selectedRows != null)
{
List<Integer> parsedSelection = new ArrayList<>();
for (String selectedRow : selectedRows)
{
Integer row = Integer.valueOf(selectedRow);
parsedSelection.add(row);
}

// Don't used _selectedNestingOption one because we want to export as if we're a simple flat view
QueryNestingOption nesting = determineNestingOption();
FieldKey column = nesting == null ? FieldKey.fromParts("RowId") : nesting.getRowIdFieldKey();
_selectedRowsClause = new SimpleFilter.InClause(column, parsedSelection);
}
}

@Override
public DataView createDataView()
{
DataView result = super.createDataView();
SimpleFilter filter = new SimpleFilter(result.getRenderContext().getBaseFilter());

if (_selectedRowsClause != null)
{
filter.addClause(_selectedRowsClause);
}

filter.addAllClauses(ProteinManager.getPeptideFilter(_url, ProteinManager.EXTRA_FILTER | ProteinManager.PROTEIN_FILTER, getUser(), _runs));
result.getRenderContext().setBaseFilter(filter);
return result;
}
}
}
Loading