<tool id="proteomics_moff" name="moFF" version="@VERSION@.0">
    <description>extracts MS1 intensities from spectrum files</description>
    <macros>
        <token name="@VERSION@">2.0.3</token>
        <!-- xml macros, used for shared Galaxy parameter inputs -->
        <xml name="ident_input_macro" token_allow_multiple="true" token_input_type="data">
        <!-- this is exactly the same across all three, except for allowing multiple in MBR and all but not in moff -->
            <conditional name="ident_input">
                    <param name="input_type_selector" type="select" label="Choose the format for the identification file:">
                        <option value="ps">Peptide Shaker PSM report (standard, not extended)</option>
                        <option value="generic">Another tabular identification file</option>
                    </param>
                    <when value="ps">
                        <param name="ident_input_file" type="@INPUT_TYPE@" format="tabular" label="Peptide Shaker PSM report" multiple="@ALLOW_MULTIPLE@"/>
                    </when>
                    <when value="generic">
                        <param name="ident_input_file" type="@INPUT_TYPE@" format="tabular" label="A general tabular format" multiple="@ALLOW_MULTIPLE@"
                            help="Must have specific columns; see below to select these columns from your file. The file should have at most one header line. "/>
                        <param name="remove_header" type="boolean" value="false" label="Remove the header line?" help="This is necessary if the file has a line with column headers"/>
                        <param name="peptide"
                            type="data_column"
                            data_ref="ident_input_file"
                            label="Column with peptide-spectrum-match sequence"/>
                        <param name="prot"
                            type="data_column"
                            data_ref="ident_input_file"
                            label="Column with protein ID"/>
                        <param name="mod_peptide"
                            type="data_column"
                            data_ref="ident_input_file"
                            label="Column with peptide-spectrum-match sequence that contains possible modifications"/>
                        <param name="rt"
                            type="data_column"
                            data_ref="ident_input_file"
                            label="Column with PSM retention time (in second)"/>
                        <param name="mz"
                            type="data_column"
                            data_ref="ident_input_file"
                            label="Column with m/z (mass over charge)"/>
                        <param name="mass"
                            type="data_column"
                            data_ref="ident_input_file"
                            label="Column with mass of the peptide"/>
                        <param name="charge"
                            type="data_column"
                            data_ref="ident_input_file"
                            label="Column with charge of ionized peptide"/>
                    </when>
            </conditional>
        </xml>
	<xml name="filt_matched_peptide">
        <conditional name="match_filter">
            <param name="filter_flags" type="select" label="Activate filtering of matched peptides">
                <option selected="True" value="nofilter">Do not activate</option>
                <option value="filter">Filter by flags to exclude or require</option>
            </param>
            <when value="filter">
                <param argument="--sample_size" label="sample_size"  type="float" value="0.20" help="percentage of MS2 peptide used to estimated the threshold. Default value: 0.20" />
                <param argument="--quantile_thr_filtering" label="-quantile_thr_filtering" type="float" value="0.75" help="quantile value used to compute the filtering threshold for the matched peak"/>
                <param argument="--ptm_file" type="data" format="tabular" label="ptm_file"  optional= "True"  help="load your ptm file in order to overwrite internal method"/>
            </when>
            <when value="nofilter"/>
        </conditional>
	</xml>
        <!-- tokens (code snippets used in <command>) -->
        <token name="@FORMAT@"><![CDATA[
            #if $task.task_selector != 'mbr'
                #if $task.msms_input.input_type_selector == "raw":
                    #set $format = '.raw'
                #else
                    #set $format = '.mzml'
                #end if
            #else:
                #set $format = '.tabular'
            #end if
        ]]></token>
        <token name="@IDENT_INPUT_ARG_MULTIPLE@"><![CDATA[
            ## this is where the ident input gets passed to moff/moff_all/moff_mbr
            --tsv_list
            #for $value in $task.ident_input.ident_input_file:
                './ident_inputs/$value.element_identifier$format'
            #end for
        ]]></token>
        <token name="@IDENT_INPUT_ARG_SINGLE@"><![CDATA[
            ## this is where the ident input gets passed to moff/moff_all/moff_mbr
            --tsv_list './ident_inputs/${task.ident_input.ident_input_file.element_identifier}$format'
        ]]></token>
        <token name="@WRANGLE_IDENT_INPUT_SINGLE@"><![CDATA[
            mkdir ./ident_inputs &&
            #if $task.ident_input.input_type_selector == "ps":
                cp '$task.ident_input.ident_input_file' './ident_inputs/$task.ident_input.ident_input_file.element_identifier$format' &&
            #else
                cp '$task.ident_input.ident_input_file' ./tempfile1.tab &&
                ## optionally remove first line
                #if $task.ident_input.remove_header:
                    sed -i '1d' ./tempfile1.tab &&
                #end if
                ## header row with correct names: "peptide", "prot", "mod_peptide", "rt", "mz", "mass", and "charge"
                echo -e "peptide\tprot\tmod_peptide\trt\tmz\tmass\tcharge" > ./tempfile2.tab &&
                awk 'BEGIN{OFS="\t"; FS="\t"}{print \$pep,\$prot,\$mod,\$rt,\$mz,\$mass,\$charge}' pep="${task.ident_input.peptide}" prot="$task.ident_input.prot" mod="$task.ident_input.mod_peptide" rt="$task.ident_input.rt" mz="$task.ident_input.mz" mass="$task.ident_input.mass" charge="$task.ident_input.charge" ./tempfile1.tab >> ./tempfile2.tab &&
                mv ./tempfile2.tab './ident_inputs/$task.ident_input.ident_input_file.element_identifier$format' &&
            #end if
        ]]></token>
        <token name="@WRANGLE_IDENT_INPUT_MULTIPLE@"><![CDATA[
            mkdir ./ident_inputs &&
            #if $task.ident_input.input_type_selector == "ps":
                #for $value in $task.ident_input.ident_input_file:
                    cp '${value}' './ident_inputs/${value.element_identifier}$format' &&
                #end for
            #else
                #for $i, $value in enumerate($task.ident_input.ident_input_file):
                    cp '${value}' './tempfile${i}_1.tab' &&
                    ## optionally remove first line
                    #if $task.ident_input.remove_header:
                        sed -i '1d' './tempfile${i}_1.tab' &&
                    #end if
                    ## header row with correct names: "peptide", "prot", "mod_peptide", "rt", "mz", "mass", and "charge"
                    echo -e "peptide\tprot\tmod_peptide\trt\tmz\tmass\tcharge" > './tempfile${i}_2.tab' &&
                    awk 'BEGIN{OFS="\t"; FS="\t"}{print \$pep,\$prot,\$mod,\$rt,\$mz,\$mass,\$charge}' pep="${task.ident_input.peptide}" prot="$task.ident_input.prot" mod="$task.ident_input.mod_peptide" rt="$task.ident_input.rt" mz="$task.ident_input.mz" mass="$task.ident_input.mass" charge="$task.ident_input.charge" './tempfile${i}_1.tab' >> './tempfile${i}_2.tab' &&
                    mv './tempfile${i}_2.tab' './ident_inputs/${value.element_identifier}$format' &&
                #end for
            #end if
        ]]></token>
        <token name="@RAW_INPUT_ARG_SINGLE@"><![CDATA[
            --raw_list './raws/$task.msms_input.raw_list.element_identifier$format'
        ]]></token>
        <token name="@RAW_INPUT_ARG_MULTIPLE@"><![CDATA[
            --raw_list
            #for $value in $task.msms_input.raw_list:
                './raws/$value.element_identifier$format'
            #end for
        ]]></token>
        <token name="@WRANGLE_RAW_INPUT_SINGLE@"><![CDATA[
            mkdir ./raws &&
            ## for files, need to softlink the name to the history item
            ln -s '$task.msms_input.raw_list' './raws/$task.msms_input.raw_list.element_identifier$format' &&
        ]]></token>
        <token name="@WRANGLE_RAW_INPUT_MULTIPLE@"><![CDATA[
            mkdir ./raws &&
            ## for files, need to softlink the name to the history item
            #for $value in $task.msms_input.raw_list:
                ln -s '$value' './raws/$value.element_identifier$format' &&
            #end for
        ]]></token>
    </macros>
    <requirements>
        <requirement type="package" version="@VERSION@">moff</requirement>
    </requirements>
    <version_command>echo @VERSION@</version_command>
    <command detect_errors="aggressive"><![CDATA[
        @FORMAT@
        mkdir ./out &&
        #if $task.task_selector == "moff":
            @WRANGLE_IDENT_INPUT_SINGLE@
            @WRANGLE_RAW_INPUT_SINGLE@
            moff_all.py
                @IDENT_INPUT_ARG_SINGLE@
                @RAW_INPUT_ARG_SINGLE@
                --tol $task.tol
                --mbr $task.mbr
                --xic_length $task.xic_length
                --rt_peak_win $task.rt_peak_win
                --rt_peak_win_match $task.rt_peak_win_match
	            --loc_out ./out
                    #if str( $task.match_filter.filter_flags ) == "filter":
                        --match_filter
                        --sample_size $task.match_filter.sample_size
                        --quantile_thr_filtering $task.match_filter.quantile_thr_filtering
                        #if ($task.match_filter.ptm_file):
                            --ptm_file '$task.match_filter.ptm_file'
                        #else:
                            --ptm_file '$__tool_directory__/tool-data/ptm_setting_ps.json'
                        #end if
                    #end if
          #if ($task.peptide_summary):
              --peptide_summary
          #end if
          #if $task.peptide_summary:
              && mv ./out/peptide_summary_intensity_moFF_run.tab '$output_peptide_summary'
          #end if
          &&
          mv ./out/*moff_result.txt '$output_table'
          &&
          mv ./out/*.log '$output_logs'
        #else if $task.task_selector == "mbr":
           @WRANGLE_IDENT_INPUT_MULTIPLE@
           moff_all.py
                @IDENT_INPUT_ARG_MULTIPLE@
                --mbr $task.mbr
				--raw_list
           &&
           mv ./mbr_output/* ./out
        #else:
           ## moff_all (mbr followed by apex)
           @WRANGLE_IDENT_INPUT_SINGLE@
           @WRANGLE_RAW_INPUT_MULTIPLE@
           moff_all.py
               @IDENT_INPUT_ARG_SINGLE@
               @RAW_INPUT_ARG_MULTIPLE@
               --tol $task.tol
               --mbr $task.mbr
               --xic_length $task.xic_length
               --rt_peak_win $task.rt_peak_win
               --rt_peak_win_match $task.rt_peak_win_match
               --loc_out ./out
               #if ($task.peptide_summary):
                   --peptide_summary
               #end if
               #if str( $task.match_filter.filter_flags ) == "filter":
                    --match_filter
                    --sample_size $task.match_filter.sample_size
                    --quantile_thr_filtering $task.match_filter.quantile_thr_filtering
                    #if ($task.match_filter.ptm_file):
                        --ptm_file '$task.match_filter.ptm_file'
                    #else:
                        --ptm_file '$__tool_directory__/tool-data/ptm_setting_ps.json'
                    #end if
               #end if

           #if $task.peptide_summary:
               && mv ./out/peptide_summary_intensity_moFF_run.tab '$output_peptide_summary'
		   #end if
	   #end if
    ]]></command>
    <inputs>
        <conditional name="task">
            <param name="task_selector" type="select" label="Choose which module to run">
                <option value="moff">Apex intensity</option>
                <option value="mbr">Match between runs</option>
                <option value="all">All (match-between-runs followed by quantitation)</option>
            </param>
            <when value = "moff">
                <expand macro="ident_input_macro" allow_multiple="false"/>
                <conditional name="msms_input">
                    <param name="input_type_selector" type="select" label="Choose the format for the MS/MS file">
                        <option value="raw">Thermo RAW file</option>
                        <option value="mzml">mzML</option>
                    </param>
                    <when value="raw">
                        <param argument="--raw_list" type="data" multiple="false" format="thermo.raw" label="RAW file(s)"/>
                    </when>
                    <when value="mzml">
                        <param argument="--raw_list" type="data" multiple="false" format="mzml" label="mzML file(s)"/>
                    </when>
                </conditional>


                <param argument="--tol" type="float" value="10" label="Tolerance parameter"
                    help="Specify the tolerance parameter in ppm." />
                <param argument="--mbr" type="text" value="off" label="moFF workflow"
                    help="select the moFF workflow" />
                <param argument="--xic_length" type="float" value="3.0" label="retention time windows for XiC"
                    help="Specify rt window for xic in minutes." />
                <param argument="--rt_peak_win" type="float" value="1" label="retention time window for apex detection"
					help="Specify rt window for the peak in minutes." />
				<param argument="--rt_peak_win_match" type="float" value="1.2" label="retention time window for the matched peak"
                    help="Specify the retention time window for the matched peak in minutes." />
                <expand macro="filt_matched_peptide"/>
                <param argument="--peptide_summary" type="boolean" value="true" label="Output the peptide summary?"/>
            </when>
            <when value="mbr">
                <expand macro="ident_input_macro" allow_multiple="false" input_type="data_collection"/>
                <param argument="--mbr" type="text" value="only" label="moFF workflow"
					help="select the moFF workflow" />
            </when>
            <when value="all">
                <expand macro="ident_input_macro" allow_multiple="false" input_type="data"/>
                <conditional name="msms_input">
                    <param name="input_type_selector" type="select" label="Choose the format for the MS/MS file">
                        <option value="raw">Thermo RAW file</option>
                        <option value="mzml">mzML</option>
                    </param>
                    <when value="raw">
                        <param argument="--raw_list" type="data" multiple="true" min="2" format="thermo.raw" label="RAW file(s)"/>
                    </when>
                    <when value="mzml">
                        <param argument="--raw_list" type="data" multiple="true" min="2" format="mzml" label="mzML file(s)"/>
                    </when>
                </conditional>

                <param argument="--tol" type="float" value="10" label="Tolerance parameter"
                    help="Specify the tolerance parameter in ppm." />
                <param argument="--mbr" type="text" value="on" label="moFF workflow"
                    help="select the moFF workflow" />
                <param argument="--xic_length" type="float" value="3.0" label="retention time windows for XiC"
                    help="Specify rt window for xic in minutes." />
                <param argument="--rt_peak_win" type="float" value="1" label="retention time window for apex detection"
                    help="Specify the retention time window for the peak in minutes." />
                <param argument="--rt_peak_win_match" type="float" value="1.2" label="retention time window for the matched peak"
					help="Specify the retention time window for the matched peak in minutes." />
                <expand macro="filt_matched_peptide"/>
                <param argument="--peptide_summary" type="boolean" value="true" label="Output the peptide summary?"/>
            </when>
     </conditional>
    </inputs>
    <outputs>
        <data format="tabular" name="output_table" label="${tool.name} on ${on_string}: quantification">
            <filter>task['task_selector']=='moff'</filter>
        </data>
        <data format="txt" name="output_logs" label="${tool.name} ${on_string}: log">
            <filter>task['task_selector']=='moff'</filter>
        </data>
        <collection name="ident_output" type="list" label="${tool.name} on ${on_string}: quantification">
            <filter>task['task_selector']=='all'</filter>
            <discover_datasets pattern="(?P&lt;designation&gt;.*)\.txt" directory="out" format="tabular"/>
        </collection>
        <collection name="ident_output_mbr" type="list" label="${tool.name} on ${on_string}: matched">
            <filter>task['task_selector']=='mbr'</filter>
            <discover_datasets pattern="(?P&lt;designation&gt;.*)\.txt" directory="out" format="tabular"/>
        </collection>
        <collection name="log_output" type="list" label="${tool.name} on ${on_string}: logs">
            <filter>task['task_selector']=='all' or task['task_selector']=='mbr'</filter>
            <discover_datasets pattern="(?P&lt;designation&gt;.*)\.log" directory="out" format="txt"/>
        </collection>
        <data format="tabular" name="output_peptide_summary" label="${tool.name} on ${on_string}: peptide summary">
            <filter>(task['task_selector']=='all' or task['task_selector']=='moff') and task['peptide_summary'] </filter>
        </data>
    </outputs>
    <tests>
        <!-- test mbr -->
        <test>
            <param name="task|task_selector" value="mbr"/>
            <param name="ident_input|input_type_selector" value="ps"/>
            <param name="ident_input_file">
                <collection type="list">
                    <element name="mbr_test1" value="input/mbr_test1.tabular"/>
                    <element name="mbr_test2" value="input/mbr_test2.tabular"/>
                </collection>
            </param>
            <param name="ext" value="tabular"/>
            <output_collection name="ident_output_mbr" type="list" count="2">
                <element name="mbr_test1_match">
                    <assert_contents>
                        <has_text text="NH2-QVEEAVQSDDK-COOH"/>
                        <has_text text="NH2-RDVGINNTVK-COOH"/>
                    </assert_contents>
                </element>
            </output_collection>
        </test>
    </tests>
    <help>
    <![CDATA[

**Description**

moFF (a Modest Feature Finder) is an OS independent tool designed to extract
apex MS1 intensity using a set of identified MS2 peptides.
It currently uses a Go library to directly extract data from Thermo Raw spectrum files,
eliminating the need for conversions from other formats.
Moreover, moFF also allows one to work directly with mzML files.

**Usage**

*Modules:*

1. Apex Intensity: this is used for a single pair of files, one identification and one spectrum file.
2. Match between runs (MBR): for multiple identification files, share MS2 identified peptides between runs and predict the retention time.
3. All (match between runs followed by apex intensity): this is used for more than one pair of identification and spectrum files.

If both match between runs and apex intensity are desired, it is best to run them both at once (i.e., run the 'All' module).
The MBR module is mainly useful for observing the intermediate steps of the algorithm - its outputs are not able to be used as inputs in moFF or in other tools.
If quantification of multiple files without MBR is desired, the apex intensity module may be run with multiple files or a dataset collection in batch mode.
In either case, moFF must be given the paired files at the same time - thus the best method is to construct a dataset collection in which the raw and identification files are in the same order.

*Inputs:*

- Identification file: this can either be a generic tabular file or the standard PSM report from PeptideShaker.
  If it is a generic tabular file, please select the columns corresponding to the required information.
- MS/MS file: this can either be a Thermo raw file or an mzML file.

A given pair of files must have the *exact* same display name, not including the extension;
e.g. ``example1.tabular`` and ``example1.mzml``.
If the display names are different, simply change them in the history menu.
For multiple files (the MBR or All modules), the identification and spectrum files must be provided as dataset collections.
This allows for usage of the output dataset collections in workflows.

*Parameters:*

All the parameters related to the the time windows (``rt_w``, ``rt_p``, ``rt_p_match``) are basically the
half of the entire time windows where the apex peak is searched or the XIC is retrieved.
For correct rt windows, we suggest you set the ``rt_p`` value equal to or slighly greater than the
dynamic exclusion duration set in your machine. We suggest also to set the
``rt_p_match`` always slightly bigger than tha values used for ``rt_p``.
*Outputs:*
When used in the single file mode ("Apex intensity" module), the outputs are 2 (or 3) files: a log file, a quantitation file,
and (optionally) a peptide summary, with intensities aggregated across peptides. When used in the multiple file mode ("All"),
the outputs are a dataset collection of log files (one per identification file), a dataset collection of quantification files, and (optionally) a peptide summary.
If used with a generic tabular format, the only columns in the output file are the 7 columns selected while using moFF plus the columns that moFF adds. Other columns are discarded.

**More Information**

See the moFF Github site at https://github.com/compomics/moFF,
and the publication at https://dx.doi.org/10.1038/nmeth.4075
    ]]>
    </help>
    <citations>
        <citation type="doi">10.1038/nmeth.4075</citation>
    </citations>
</tool>
