view combine.xml @ 20:a9a28e46d54a draft default tip

planemo upload for repository https://github.com/galaxyproteomics/tools-galaxyp/tree/master/tools/cardinal commit 91e77c139cb3b7c6d67727dc39140dd79355fa0c
author galaxyp
date Thu, 04 Jul 2024 13:47:49 +0000
parents aad328eb6c0f
children
line wrap: on
line source

<tool id="cardinal_combine" name="MSI combine" version="@TOOL_VERSION@+galaxy@VERSION_SUFFIX@" profile="22.05">
    <description>
        combine several mass spectrometry imaging datasets into one
    </description>
    <macros>
        <import>macros.xml</import>
    </macros>
    <expand macro="requirements"/>
    <command detect_errors="exit_code">
    <![CDATA[
        #for $i, $infile in enumerate($infiles):
            #if $infile.ext == 'imzml'
                cp '${infile.extra_files_path}/imzml' infile_${i}.imzML &&
                cp '${infile.extra_files_path}/ibd' infile_${i}.ibd &&
            #elif $infile.ext == 'analyze75'
                cp '${infile.extra_files_path}/hdr' infile_${i}.hdr &&
                cp '${infile.extra_files_path}/img' infile_${i}.img &&
                cp '${infile.extra_files_path}/t2m' infile_${i}.t2m &&
            #else
                ln -s '$infile' infile_${i}.RData &&
            #end if
        #end for
        #if $annotation_cond.annotation_tabular == 'annotation'
            #for $i, $annotation_file in enumerate($annotation_cond.annotation_files):
                ln -s '$annotation_file' annotation_file_${i}.tabular &&
            #end for
        #end if

        cat '${msi_combine}' &&
        Rscript '${msi_combine}' &&
        mkdir $outfile_imzml.files_path &&
        mv ./out.imzML "${os.path.join($outfile_imzml.files_path, 'imzml')}" | true &&
        mv ./out.ibd "${os.path.join($outfile_imzml.files_path, 'ibd')}" | true &&
        echo "imzML file:" > $outfile_imzml &&
        ls -l "$outfile_imzml.files_path" >> $outfile_imzml

    ]]>
    </command>
    <configfiles>
        <configfile name="msi_combine"><![CDATA[

#import re

################ 1) load libraries and do preparations #################

library(Cardinal)
library(ggplot2)
library(MALDIquantForeign)
library(MALDIquant)


## read tabular file for xy_shift option
#if str( $combine_conditional.combine_method ) == 'xy_shifts':
    input_list = read.delim("$combine_conditional.coordinates_file", header = $combine_conditional.xy_header, 
    stringsAsFactors = FALSE)
#end if

## function to load RData and store with new variable name
loadRData <- function(fileName){
load(fileName)
get(ls()[ls() != "fileName"])
}

## preparations for reading files one by one with for loop
sample_names = numeric()
x_shifts = 0
y_shifts = 0
max_y = numeric()
valid_dataset = logical()
coordinates_combined = data.frame(matrix(,ncol=2, nrow=0))
msidata_combined = list()
#set $msidata = []
#set $pixelcoords = []
#set $num_infiles = len($infiles)
all_files = $num_infiles

###################### 2) reading MSI files ####################################

#for $i, $infile in enumerate($infiles):

    ## read and manipulate MSI data

        #if $infile.ext == 'imzml'
            #if str($processed_cond.processed_file) == "processed":
                msidata_$i <- readImzML('infile_${i}', resolution=$processed_cond.accuracy, units = "$processed_cond.units", attach.only=TRUE)
                msidata_$i = collect(msidata_$i, as.matrix=TRUE) ##coercion to continuous
                centroided(msidata_$i) = $centroids
            #else
                msidata_$i <- readImzML('infile_${i}', attach.only=TRUE)
                centroided(msidata_$i) = $centroids
            #end if
        #elif $infile.ext == 'analyze75'
            msidata_$i = readAnalyze('infile_${i}', attach.only=TRUE)
            centroided(msidata_$i) = $centroids
        #else
            ## function to read RData files independent of filename
            loadRData <- function(fileName){
            load(fileName)
            get(ls()[ls() != "fileName"])
            }
            msidata_$i = loadRData('infile_${i}.RData')
            msidata_$i <- as(msidata_$i, "MSImagingExperiment")

        #end if

    ## remove duplicated coordinates, otherwise combine will fail
    print(paste0(sum(duplicated(coord(msidata_$i))), " duplicated coordinates were removed from input file"))
    msidata_${i} <- msidata_${i}[,!duplicated(coord(msidata_${i}))]

    ## same name for MSI data files necessary to combine data into one single coordinate system
    run(msidata_$i) = "msidata"

    ## remove z dimension and 3D information in pixelData to allow combining datasets with and without z dimension
    coord(msidata_${i})\$z <- NULL
    pData(msidata_${i})\$'3DPositionX' <- NULL
    pData(msidata_${i})\$'3DPositionY' <- NULL

############ 3) Read and process annotation tabular files ######################

    #if str($annotation_cond.annotation_tabular) == 'annotation'

        ## read annotation tabular, set first two columns as x and y, merge with coordinates dataframe and order according to pixelorder in msidata
        input_annotation = read.delim("annotation_file_${i}.tabular", header = $annotation_cond.tabular_header, stringsAsFactors = FALSE)
        colnames(input_annotation)[1:2] = c("x", "y")

        msidata_coordinates = cbind(coord(msidata_$i)[,1:2], 1:ncol(msidata_$i))
        colnames(msidata_coordinates)[3] = "pixel_index"

        annotation_df = merge(msidata_coordinates, input_annotation, by=c("x", "y"), all.x=TRUE)
        annotation_df_sorted = annotation_df[order(annotation_df\$pixel_index),]
        annotation_df_sorted\$pixel_index = NULL

        ## extract columnnames from (last) annotation tabular (for QC plot names)
        annotation_colnames = colnames(input_annotation)

    #end if

############### 4) shift coordinates with xy shifts ############################

    #if str( $combine_conditional.combine_method ) == 'xy_shifts':

        ## optional: set all files to 1/1 and then add shift
        #if $combine_conditional.xy_origin:
            coord(msidata_$i)\$x = as.integer(coord(msidata_$i)\$x - min(coord(msidata_$i)\$x-1))
            coord(msidata_$i)\$y = as.integer(coord(msidata_$i)\$y - min(coord(msidata_$i)\$y-1))
        #end if

        ## shift coordinates according to input tabular file and store file names
        coord(msidata_$i)\$x = as.integer(coord(msidata_$i)\$x + input_list[$i+1,$combine_conditional.column_x]) ## shifts x coordinates according to tabular file
        coord(msidata_$i)\$y = as.integer(coord(msidata_$i)\$y + input_list[$i+1,$combine_conditional.column_y]) ## shifts y coordinates according to tabular file
        sample_name = rep(paste(input_list[$i+1,$combine_conditional.column_names]),times=ncol(msidata_$i)) ## stores file name for each pixel
        sample_names = append(sample_names, sample_name)

        ## store number of file to use later when removing duplicate coordinates
        pixelcoords_$i = cbind(coord(msidata_$i)[,1:2], rep($i+1,ncol(msidata_$i)))
        #silent $pixelcoords.append('pixelcoords_'+str($i))
        colnames(pixelcoords_$i)[3] = "file_number"

##################### 5) shift coordinates automatically #######################

    #elif str( $combine_conditional.combine_method ) == 'automatic_combine':

        ## use name of Galaxy input file as sample annotation
        sample_name = character()
        #set escaped_element_identifier = re.sub('[^\w\-\s\[/]]', '_', str($infile.element_identifier))

        if (ncol(msidata_$i)>0 & nrow(msidata_$i) >0)
        {
            sample_name = append(sample_name, rep(paste("$escaped_element_identifier"),ncol(msidata_$i)))
        }

        ## Number of input files define grid which is row-wise filled with files
        coord(msidata_$i)\$x = as.integer(coord(msidata_$i)\$x - (min(coord(msidata_$i)\$x-1)) + x_shifts)
        coord(msidata_$i)\$y = as.integer(coord(msidata_$i)\$y - (min(coord(msidata_$i)\$y-1)) + y_shifts)

        x_shifts = max(coord(msidata_$i)\$x) + $combine_conditional.shift_value
        max_y = append(max_y, max(coord(msidata_$i)\$y))
        all_files = $num_infiles
        new_row = ($i+1)/ceiling(sqrt(all_files))
        new_row%%1==0
        if (new_row%%1==0)
        {x_shifts = 0 ### when row is filled: x values start again at zero
         y_shifts = max(max_y) + $combine_conditional.shift_value ### when row is filled: y value increases to start a new row
        max_y = numeric()}

    #end if

############################# 6) combination of files ##########################

    ## combine shifted coordinates with sample name and annotations from input file

    #if str($annotation_cond.annotation_tabular) == 'annotation'
        cardinal_coordinates_$i = data.frame(as.matrix(Cardinal::coord(msidata_$i)[,1:2]), sample_name, annotation_df_sorted[,-c(1,2)])
    #else
        cardinal_coordinates_$i = data.frame(as.matrix(Cardinal::coord(msidata_$i)[,1:2]), sample_name)
    #end if

    ## store files to combine them later and for each file check if it is valid
    #silent $msidata.append('msidata_'+str($i)) 
    valid_dataset = append(valid_dataset, ncol(msidata_$i)>0 & nrow(msidata_$i)>0) 


######################### 6a) combination different mz axis ####################

    ## combination for files with different mz axis via MALDIquant during for loop

    #if $processed_true: 
    print("mz axis differ")

        cardinal_mzs_$i = Cardinal::mz(msidata_$i)

        for(number_spectra in 1:ncol(msidata_${i})){

            if (centroided(msidata_$i) == FALSE){
                ## create mass spectrum object
                maldi_data_${i} = list()
                for(number_spectra in 1:ncol(msidata_$i)){
                    maldi_data_${i}[[number_spectra]] = MALDIquant::createMassSpectrum(mass = cardinal_mzs_$i, intensity = Cardinal::iData(msidata_$i)[,number_spectra])}
            }else{
                maldi_data_${i} = list()
                for (spectra in 1:ncol(msidata_$i))
                {
                    single_peaks_${i} = createMassPeaks(cardinal_mzs_$i, Cardinal::spectra(msidata_$i)[,spectra], snr=as.numeric(rep("NA", nrow(msidata_$i))))
                    maldi_data_${i}[[spectra]] = single_peaks_${i}
                }
            }
        }

        msidata_combined = append(msidata_combined, maldi_data_$i)

    #end if

    coordinates_combined = rbind(coordinates_combined, cardinal_coordinates_$i) 

#end for


######################### 6b) combination same mz axis ###################

#if str( $combine_conditional.combine_method ) == 'automatic_combine':
    print("automatic combine")

   #if not $processed_true:
       ## combine only valid datasets

        valid_data =  list(#echo ','.join($msidata)#)[valid_dataset]
        msidata = do.call(cbind, valid_data)
        print("Valid datasets in order of input bottom to top:")
        print(valid_dataset)
        writeImzML(msidata, "out")

    #else

        ## save msidata as imzML file MALDIquant
        MALDIquantForeign::exportImzMl(msidata_combined, file="out.imzML", processed=TRUE, coordinates=as.matrix(coordinates_combined[,1:2]))

    #end if

########################### xy shift combination ###############################
################################################################################

#elif str( $combine_conditional.combine_method ) == 'xy_shifts':
    print("xy_shifts")

    #if not $processed_true:

        duplicated_coordinates= duplicated(coordinates_combined[,1:2])| duplicated(coordinates_combined[,1:2], fromLast=TRUE)
        print(paste0("Number of removed duplicated coordinates after combination: ", sum(duplicated_coordinates)))
        coordinates_combined = coordinates_combined[!duplicated_coordinates,]

        ## remove duplicated coordinates
        datasetlist = list()
        count = 1
        for (usable_dataset in list(#echo ','.join($msidata)#)){
        
            pixelsofinterest = paste(coord(usable_dataset)\$x, coord(usable_dataset)\$y, sep="_") %in% paste(coordinates_combined\$x, coordinates_combined\$y, sep="_")           
            filtered_dataset = usable_dataset[,pixelsofinterest]
            if (ncol(filtered_dataset) > 0 ){
                datasetlist[[count]] = filtered_dataset}
            count = count +1}
        msidata = do.call(cbind, datasetlist)
        writeImzML(msidata, "out")

    #else

        ## in case user made mistake with xy shifts: find duplicated coordinates
        duplicated_coordinates= duplicated(coordinates_combined[,1:2])| duplicated(coordinates_combined[,1:2], fromLast=TRUE)
        print(paste0("Number of removed duplicated coordinates after combination: ", sum(duplicated_coordinates)))
        unique_coordinates = data.frame(coordinates_combined)[!duplicated_coordinates,]

        filtered_dataset = msidata_combined [!duplicated_coordinates]
        coordinates_matrix = as.matrix(unique_coordinates[,1:2])

        ## save msidata as imzML file MALDIquant
        MALDIquantForeign::exportImzMl(filtered_dataset, file="out.imzML", processed=TRUE, coordinates=coordinates_matrix)

        coordinates_combined = unique_coordinates

    #end if

#end if

################################## outputs #####################################
################################################################################

########### QC with pixels and their annotations ################################

pdf("Combined_qc.pdf", width=15, height=15)

## combined plot
combine_plot = ggplot(coordinates_combined[,1:3], aes(x=x, y=y, fill=sample_name))+
       geom_tile() +
       coord_fixed()+
       ggtitle("Spatial orientation of combined data")+
       theme_bw()+
       theme(text=element_text(family="ArialMT", face="bold", size=15))+
       theme(legend.position="bottom",legend.direction="vertical")+
       guides(fill=guide_legend(ncol=4,byrow=TRUE))
coord_labels = aggregate(cbind(x,y)~sample_name, data=coordinates_combined[,1:3], mean)
coord_labels\$file_number = gsub( "_.*$", "", coord_labels\$sample_name)
print(combine_plot)

    #if str($annotation_cond.annotation_tabular) == 'annotation'
        ## annotation plots
        for (inputcolumns in 4:ncol(coordinates_combined)){
                ## plot 1
                column1_df = coordinates_combined[,c(1,2,inputcolumns)]
                colnames(column1_df)[3] = "column1"

                if (sum(is.na(column1_df[3])) < nrow(column1_df)){
                column1_plot = ggplot(column1_df, aes(x=x, y=y, fill=column1))+
                       geom_tile() +
                       coord_fixed()+
                       ggtitle(paste0(annotation_colnames[inputcolumns-1]))+
                       theme_bw()+
                       theme(text=element_text(family="ArialMT", face="bold", size=15))+
                       theme(legend.position="bottom",legend.direction="vertical")+
                       guides(fill=guide_legend(ncol=4,byrow=TRUE, title=annotation_colnames[1]))
                print(column1_plot)}
                ##rename columnname for output tabular file
                colnames(column1_df)[3] = annotation_colnames[inputcolumns-1]

        }

    #end if
    dev.off()

##################### annotation tabular output ################################

            write.table(coordinates_combined, file="$pixel_annotations", quote = FALSE, row.names = FALSE, col.names=TRUE, sep = "\t")

    ]]></configfile>
    </configfiles>
    <inputs>
        <param name="infiles" type="data" multiple="true" format="imzml,rdata,analyze75"
            label="MSI data"
            help="Input file as imzML (composite upload), Analyze7.5 (composite upload) or Cardinal 'MSImageSet'  or 'MSImagingExperiment' saved as RData (regular upload)"/>
        <param name="centroids" type="boolean" label="Centroided input" help="Choose Yes if peak detection has already been done." truevalue="TRUE" falsevalue="FALSE"/>
        <conditional name="processed_cond">
            <param name="processed_file" type="select" label="Processed imzML file" help="Choose no if your input is an Analyze7.5 or continuous imzML file">
                <option value="no_processed" selected="True">no</option>
                <option value="processed">yes</option>
            </param>
            <when value="no_processed"/>
            <when value="processed">
                <param name="accuracy" type="float" value="50" label="Mass accuracy to which the m/z values will be binned" help="This should be set to the native accuracy of the mass spectrometer, if known"/>
                <param name="units" display="radio" type="select" label="Unit of the mass accuracy" help="either m/z or ppm">
                    <option value="mz" >mz</option>
                    <option value="ppm" selected="True" >ppm</option>
                </param>
            </when>
        </conditional>
        <conditional name="annotation_cond">
            <param name="annotation_tabular" type="select" label="Optional annotation of pixels with tabular files">
                <option value="no_annotation" selected="True">no annotation</option>
                <option value="annotation">pixel annotations</option>
            </param>
            <when value="no_annotation"/>
            <when value="annotation">
                <param name="annotation_files" type="data" multiple="true" format="tabular"
                    label="Pixel annotations tabular files"
                    help="Same number and order of files as input files. First column x values, second column y values, further columns with annotations"/>
                <param name="tabular_header" type="boolean" label="Tabular files contain a header line" truevalue="TRUE" falsevalue="FALSE"/>
            </when>
        </conditional>
        <conditional name="combine_conditional">
            <param name="combine_method" type="select" label="Way of combining multiple files">
                <option value="automatic_combine" selected="True" >automatic combination</option>
                <option value="xy_shifts">shift xy coordinates with a tabular file</option>
            </param>
            <when value="automatic_combine">
                <param name="shift_value" type="integer" value="5" label="Number of empty pixels that should separate different datasets in x and y dimension"/>
            </when>
            <when value="xy_shifts">
                <param name="coordinates_file" type="data" format="tabular" label="Datasetnames, x and y values to shift pixel coordinates before combining"
            help="Tabular file with three columns: 1 for the filename, 1 for the x-coordinate shift and 1 for the y-coordinate shift. Pixels with the same coordinates after shifting will be deleted."/>
                <param name="column_x" data_ref="coordinates_file" label="Column with values for shift in x direction" type="data_column"/>
                <param name="column_y" data_ref="coordinates_file" label="Column with values for shift in y direction" type="data_column"/>
                <param name="column_names" data_ref="coordinates_file" label="Column with dataset names" type="data_column"/>
                <param name="xy_header" type="boolean" label="Tabular files contain a header line" truevalue="TRUE" falsevalue="FALSE"/>
                <param name="xy_origin" type="boolean" label="Set all file coordinates to 1/1 as origin" truevalue="TRUE" falsevalue="FALSE" help="Yes: all file coordinates are shifted in order to have at least one pixel with x = 1 and one with y = 1; then coordinates shifts are added. No: the coordinate shifts are added to the current coordinates of the file"/>
            </when>
        </conditional>
        <param name="processed_true" type="boolean" label="Do the files have different m/z axis?" help="If all m/z values of all files are exactly the same choose 'No'. If not sure choose 'Yes'." truevalue="TRUE" falsevalue="FALSE"/>
    </inputs>
    <outputs>
        <data format="imzml" name="outfile_imzml" label="${tool.name} on ${on_string}: imzML"/>
        <data format="pdf" name="QC_overview" from_work_dir="Combined_qc.pdf" label = "${tool.name} on ${on_string}: QC"/>
        <data format="tabular" name="pixel_annotations" label="${tool.name} on ${on_string}: annotations"/>
    </outputs>
    <tests>
        <test>
            <param name="infiles" value="msidata_1.RData,msidata_2.RData,msidata_3.RData" ftype="rdata"/>
            <conditional name="annotation_cond">
                <param name="annotation_tabular" value="annotation"/>
                <param name="annotation_files" value="annotations_file1.tabular,annotations_file2.tabular,annotations_file3.tabular" ftype="tabular"/>
                <param name="tabular_header" value="TRUE"/>
            </conditional>
            <param name="combine_method" value="xy_shifts"/>
            <param name="coordinates_file" ftype="tabular" value="xy_coordinates.tabular"/>
            <param name="column_x" value="1"/>
            <param name="column_y" value="2"/>
            <param name="column_names" value="3"/>
            <param name="processed_true" value="FALSE"/>
            <output name="pixel_annotations" file="123_annotation_output.tabular"/>
            <output name="QC_overview" file="123_combined_QC.pdf" compare="sim_size"/>
            <output name="outfile_imzml" ftype="imzml" file="123_combined.imzml.txt" compare="sim_size">
                <extra_files type="file" file="123_combined.imzml" name="imzml" lines_diff="12"/>
                <extra_files type="file" file="123_combined.ibd" name="ibd" compare="sim_size"/>
            </output>
        </test>
        <test>
            <param name="infiles" value="123_combined_picked.rdata,123_combined_picked2.rdata" ftype="rdata"/>
            <param name="centroids" value="TRUE"/>
            <param name="combine_method" value="xy_shifts"/>
            <param name="coordinates_file" ftype="tabular" value="xy_coordinates2.tabular"/>
            <param name="column_x" value="1"/>
            <param name="column_y" value="2"/>
            <param name="column_names" value="3"/>
            <param name="processed_true" value="TRUE"/>
            <output name="pixel_annotations" file="picked.tabular"/>
            <output name="QC_overview" file="picked_QC.pdf" compare="sim_size"/>
            <output name="outfile_imzml" ftype="imzml" file="picked.imzml.txt" compare="sim_size">
                <extra_files type="file" file="picked.imzml" name="imzml" lines_diff="12"/>
                <extra_files type="file" file="picked.ibd" name="ibd" compare="sim_size"/>
            </output>
        </test>
        <test>
            <param name="infiles" value="msidata_1.RData,msidata_2.RData,msidata_3.RData" ftype="rdata"/>
            <conditional name="annotation_cond">
                <param name="annotation_tabular" value="no_annotation"/>
            </conditional>
            <param name="combine_method" value="automatic_combine"/>
            <param name="processed_true" value="FALSE"/>
            <output name="QC_overview" file="123_combined_auto.pdf" compare="sim_size"/>
            <output name="pixel_annotations" file="123_combined_auto.tabular"/>
            <output name="outfile_imzml" ftype="imzml" file="123_combined_auto.imzml.txt" compare="sim_size">
                <extra_files type="file" file="123_combined_auto.imzml" name="imzml" lines_diff="12"/>
                <extra_files type="file" file="123_combined_auto.ibd" name="ibd" compare="sim_size"/>
            </output>
        </test>
        <test>
            <param name="infiles" value="msidata_1.RData,msidata_2.RData" ftype="rdata"/>
            <conditional name="annotation_cond">
                <param name="annotation_tabular" value="annotation"/>
                <param name="annotation_files" value="annotations_file1.tabular,annotations_file2.tabular" ftype="tabular"/>
                <param name="tabular_header" value="TRUE"/>
            </conditional>
            <param name="combine_method" value="automatic_combine"/>
            <param name="processed_true" value="FALSE"/>
            <output name="pixel_annotations" file="12_annotation_output.tabular"/>
            <output name="QC_overview" file="12_combined_QC.pdf" compare="sim_size"/>
            <output name="outfile_imzml" ftype="imzml" file="12_combined.imzml.txt" compare="sim_size">
                <extra_files type="file" file="12_combined.imzml" name="imzml" lines_diff="12"/>
                <extra_files type="file" file="12_combined.ibd" name="ibd" compare="sim_size"/>
            </output>
        </test>
        <test>
            <param name="infiles" value="msidata_1.RData,123_combined.RData" ftype="rdata"/>
            <conditional name="annotation_cond">
                <param name="annotation_tabular" value="annotation"/>
                <param name="annotation_files" value="annotations_file1.tabular,123_annotation.tabular" ftype="tabular"/>
                <param name="tabular_header" value="TRUE"/>
            </conditional>
            <param name="combine_method" value="automatic_combine"/>
            <param name="processed_true" value="FALSE"/>
            <output name="pixel_annotations" file="112_annotation_output.tabular"/>
            <output name="QC_overview" file="112_auto_combined_QC.pdf" compare="sim_size"/>
            <output name="outfile_imzml" ftype="imzml" file="112_auto_combined.imzml.txt" compare="sim_size">
                <extra_files type="file" file="112_auto_combined.imzml" name="imzml" lines_diff="12"/>
                <extra_files type="file" file="112_auto_combined.ibd" name="ibd" compare="sim_size"/>
            </output>
        </test>
        <test>
            <param name="infiles" value="msidata_2.RData,123_combined.RData" ftype="rdata"/>
            <conditional name="annotation_cond">
                <param name="annotation_tabular" value="no_annotation"/>
            </conditional>
            <param name="combine_method" value="automatic_combine"/>
            <param name="processed_true" value="FALSE"/>
            <output name="pixel_annotations" file="2123_annotation_output.tabular"/>
            <output name="QC_overview" file="2123_auto_combined_QC.pdf" compare="sim_size"/>
            <output name="outfile_imzml" ftype="imzml" file="2123_auto_combined.imzml.txt" compare="sim_size">
                <extra_files type="file" file="2123_auto_combined.imzml" name="imzml" lines_diff="12"/>
                <extra_files type="file" file="2123_auto_combined.ibd" name="ibd" compare="sim_size"/>
            </output>
        </test>
    </tests>
    <help>
<![CDATA[

@CARDINAL_DESCRIPTION@

-----

This tool combines several mass spectrometry imaging data files.

@MSIDATA_INPUT_DESCRIPTION@
- Coordinates stored as decimals rather than integers will be rounded to obtain a regular pixel grid. This might lead to duplicated coordinates which will be automatically removed before the tools analysis starts. 
@SPECTRA_TABULAR_INPUT_DESCRIPTION@

- For xy shifts with tabular file: Tabular file with x and y coordinates shift and file name

    - Each input file is renamed and shifted in x and y direction according to this tabular file. In the example the files have about the same pixel dimensions which is smaller than 510x260.
    - The file can have any column names as header (in this case set "Tabular file contains a header line" to "Yes") or no header at all (set "Tabular file contains a header line" to "No").

        ::
        
            x_shift     y_shift    file name
               0            0       file1
              510           0       file2
               0           260      file3
              510          260      file4
              ...
              ...
        



**Options**

- "automatic combination": files are automatically arranged in a grid, subfiles are named according to the input file name
- "xy shifts": each file can be moved in x and y direction according to the users need (define one tabular file in the order in which the files are loaded in the history (bottom to top) and define for each file the x and y coordinates shifts in separate columns and the file name in a third column as shown above). The xy shift option combines all datasets and removes all duplicated pixels (same x and y coordinates).
- "Set all file coordinates to 1/1 as origin" can be choosen to override current pixel coordinates of the input file and set their minimal x and minimal y values to 1. Then the shifts from the xy shift tabular files are used to move the pixels of each dataset. 
- In case the input files have not exactly the same m/z values set "Do the files have different m/z axis?" to "Yes". Then functionalities of the "MALDIquant" package are used to combine the datasets. 


**Tips**

- The combine tool puts all samples into a common x-y-grid, therefore pixel coordinates will change. In case the pixels are already annotated, the annotations should be provided as tabular files and the tool will return an annotation file with the new pixel coordinates. This annotation file can then be used together with the combined MSI data for tools in which the annotation is required (e.g. 'MSI classification') or useful (e.g. 'MSI spectra plots').


**Output**

- MSI data as imzML file (in continuous format when m/z axis were the same; in processed format when m/z axis were different)
- Pdf with pixel positions and annotations of the combined files
- Tabular file with pixel annotations (x,y,column with input file names and annotation columns)


]]>
    </help>
        <citations>
            <citation type="doi">10.1093/bioinformatics/btv146</citation>
            <citation type="doi">10.1007/978-3-319-45809-0_6</citation>
            <citation type="doi">10.1093/gigascience/giz143</citation>
        </citations>
</tool>