Commit b82ff6c2 authored by Penom Nom's avatar Penom Nom
Browse files

No commit message

No commit message
parent 21811f95
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?eclipse-pydev version="1.0"?>
<pydev_project>
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
<path>/nG6-current/core</path>
</pydev_pathproperty>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.6</pydev_property>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
</pydev_project>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?eclipse-pydev version="1.0"?>
<pydev_project>
<pydev_pathproperty name="org.python.pydev.PROJECT_SOURCE_PATH">
<path>/nG6-meta2/core</path>
</pydev_pathproperty>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python 2.6</pydev_property>
<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
</pydev_project>
#
# Copyright (C) 2009 INRA
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
__author__ = 'Plateforme genomique Midi Pyrenees'
__copyright__ = 'Copyright (C) 2009 INRA'
__license__ = 'GNU General Public License'
__version__ = '1.0'
__email__ = 'support.genopole@toulouse.inra.fr'
__status__ = 'beta'
import os, re, glob, sys
from optparse import *
from time import localtime, strftime
# Add a file to input_elements.
# @usage : add_element( elem, input_elements, casava_regexp )
# @param : elem string File path.
# @param : input_elements dictionary File list.
# @param : casava_regex string Regex describing the structure used for the path of output files of CASAVA usable by the casava option of FASTQC.
def add_element ( elem, input_elements, casava_regex ):
is_casava_file = re.search(casava_regex, elem)
# Set the key
if( is_casava_file ):
key = is_casava_file.group(1)
else:
key = os.path.basename(elem)
# If an other file for this read already exists
if( key in input_elements ):
input_elements[key]['files_path'] += " " + elem
input_elements[key]['fastqc_opt'] = "--casava"
# Otherwise
else:
input_elements[key] = {}
input_elements[key]['files_path'] = elem
input_elements[key]['fastqc_opt'] = ""
# Check mandatory parameters.
# @usage : check_parameters()
def check_parameters ():
# handle required arguments
if( not options.output_iter_list ):
sys.stderr.write( "No output defined.\n" )
sys.exit(1)
# at least one input type is required
if( not (options.input_file_list or options.input_file or options.input_directory) ):
sys.stderr.write( "No input defined.\n" )
sys.exit(1)
if( options.input_directory and not options.input_directory.endswith('/') ):
options.input_directory = options.input_directory + "/"
# Loads the informations of iteration on input_elements.
# @usage : gather_input_elements ( iterable_file_list, regexp )
# @param : iterable_file_list dictionary File list.
# @param : regexp string Regex describing the structure used for the path of output files of CASAVA usable by the casava option of FASTQC.
# @return : element_count int The file number.
def gather_input_elements ( iterable_file_list, regexp ):
element_count = 0
###
# All three input options can be used in tandem, so we check every one.
###
# Handle any input file lists
if ( options.input_file_list ):
#For each containing list file
for input_file_list in ( options.input_file_list.rsplit(',') ):
#If file list is compressed
if ( input_file_list.endswith( '.gz' ) or input_file_list.endswith( '.gzip' ) ):
sys.stderr.write( "Support unavailable for processing gzipped file lists.\n" )
sys.exit(1)
FH_InFileList = open(input_file_list, "r" )
#For each file lists in file
for line in FH_InFileList:
empty_line = re.search('^\s*$', line)
if ( not empty_line ):
line = line.rstrip()
add_element( line, input_elements, regexp )
element_count = element_count + 1
# Handle any directories
if ( options.input_directory ):
#For each directory
for input_directory in ( options.input_directory.rsplit(',') ):
dir_files = glob.glob( input_directory + '*' )
#For each element in directory
for one_file in dir_files:
# Only consider files
if( os.path.isfile(one_file) ):
# If the extension is defined, the file must match it
if ( (not options.input_directory_extension) or one_file.endswith( '.' + options.input_directory_extension ) ):
add_element( one_file, input_elements, regexp )
element_count = element_count + 1
# Handle any individual files
if ( options.input_file ):
#For each file
for input_file in ( options.input_file.rsplit(',') ):
add_element( input_file, input_elements, regexp )
element_count = element_count + 1
return element_count
if __name__ == '__main__':
##
# Manage options
##
parser = OptionParser(usage="%prog -o OUTPUT_FILE [-f INPUT_FILE] [-l INPUT_FILE_LIST] [-d INPUT_DIRECTORY [-e INPUT EXTENSION]] [-t]", description="Generates list file from various input sources of filenames. This script is used to accept a selection of inputs from either an input list, directory, file, or any combination thereof. Each of these options can also be specified using comma-separated lists.")
igroup = OptionGroup(parser, "options","")
igroup.add_option("-o", "--output_iter_list", help="Desired path to output iterator file.", dest="output_iter_list")
igroup.add_option("-f", "--input_file", help="The full path to an input file. this can also be a comma-separated list of input files.", dest="input_file")
igroup.add_option("-l", "--input_file_list", help="Plain text file containing the full paths to any number of files, one per line. This can also be a comma-separated list of input file lists.", dest="input_file_list")
igroup.add_option("-d", "--input_directory", help="The full path to an input directory. This can also be a comma-separated list of input directories.", dest="input_directory")
igroup.add_option("-e", "--input_directory_extension", help="To be used in conjuction with the input_directory option, this can be used to filter files by extension within any passed input directories.", dest="input_directory_extension")
igroup.add_option("-t", "--timestamp", help="Add timestamp to each output line.", dest="timestamp", action="store_true")
parser.add_option_group(igroup)
(options, args) = parser.parse_args()
check_parameters()
##
# Set variables
##
# Regex to identify the output files of CASAVA 1.8 (for 'casava' option in FASTQC)
casava_output_regexp = '.+\/([^\/]+_[^\/]+_[^\/]+_[^\/]+)_[^\/]+\.fastq\.gz'
# Play nicely
os.umask(0000)
# Structure like input_elements{file_id:{'files_path':files_path, 'fastqc_opt':fastqc_opt}}. It store output informations.
input_elements = {}
##
# Load informations on input_elements
##
input_element_count = gather_input_elements( input_elements, casava_output_regexp )
##
# Create output file
##
FH_output = open( options.output_iter_list, "w" )
# Header line
FH_output.write( '$;I_FILE_BASE$;' + "\t" + '$;FASTQC_OPT$;' + "\t" '$;I_FASTQC_FILES$;' )
# Timestamp
timestamp = ""
if( options.timestamp ):
FH_output.write( "\t" + '$;I_TIMESTAMP$;' )
timestamp = strftime("%b %d %Y %I:%H%p", localtime())
FH_output.write( "\n" )
# For each future iteration
for file_name in input_elements.keys():
FH_output.write( file_name + "\t" + input_elements[file_name]['fastqc_opt'] + "\t" + input_elements[file_name]['files_path'] )
if( options.timestamp ):
FH_output.write( "\t" + timestamp )
FH_output.write( "\n" )
FH_output.close
#
# Copyright (C) 2009 INRA
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
__author__ = 'Plateforme genomique Midi Pyrenees'
__copyright__ = 'Copyright (C) 2009 INRA'
__license__ = 'GNU General Public License'
__version__ = '1.0'
__email__ = 'support.genopole@toulouse.inra.fr'
__status__ = 'beta'
import os, re, glob, sys
from optparse import *
from time import localtime, strftime
# Add a file to input_elements.
# @usage : add_element( elem, input_elements, casava_regexp )
# @param : elem string File path.
# @param : input_elements dictionary File list.
# @param : casava_regex string Regex describing the structure used for the path of output files of CASAVA usable by the casava option of FASTQC.
def add_element ( elem, input_elements, casava_regex ):
is_casava_file = re.search(casava_regex, elem)
# Set the key
if( is_casava_file ):
key = is_casava_file.group(1)
else:
key = os.path.basename(elem)
# If an other file for this read already exists
if( key in input_elements ):
input_elements[key]['files_path'] += " " + elem
input_elements[key]['fastqc_opt'] = "--casava"
# Otherwise
else:
input_elements[key] = {}
input_elements[key]['files_path'] = elem
input_elements[key]['fastqc_opt'] = ""
# Check mandatory parameters.
# @usage : check_parameters()
def check_parameters ():
# handle required arguments
if( not options.output_iter_list ):
sys.stderr.write( "No output defined.\n" )
sys.exit(1)
# at least one input type is required
if( not (options.input_file_list or options.input_file or options.input_directory) ):
sys.stderr.write( "No input defined.\n" )
sys.exit(1)
if( options.input_directory and not options.input_directory.endswith('/') ):
options.input_directory = options.input_directory + "/"
# Loads the informations of iteration on input_elements.
# @usage : gather_input_elements ( iterable_file_list, regexp )
# @param : iterable_file_list dictionary File list.
# @param : regexp string Regex describing the structure used for the path of output files of CASAVA usable by the casava option of FASTQC.
# @return : element_count int The file number.
def gather_input_elements ( iterable_file_list, regexp ):
element_count = 0
###
# All three input options can be used in tandem, so we check every one.
###
# Handle any input file lists
if ( options.input_file_list ):
#For each containing list file
for input_file_list in ( options.input_file_list.rsplit(',') ):
#If file list is compressed
if ( input_file_list.endswith( '.gz' ) or input_file_list.endswith( '.gzip' ) ):
sys.stderr.write( "Support unavailable for processing gzipped file lists.\n" )
sys.exit(1)
FH_InFileList = open(input_file_list, "r" )
#For each file lists in file
for line in FH_InFileList:
empty_line = re.search('^\s*$', line)
if ( not empty_line ):
line = line.rstrip()
add_element( line, input_elements, regexp )
element_count = element_count + 1
FH_InFileList.close
# Handle any directories
if ( options.input_directory ):
#For each directory
for input_directory in ( options.input_directory.rsplit(',') ):
dir_files = glob.glob( input_directory + '*' )
#For each element in directory
for one_file in dir_files:
# Only consider files
if( os.path.isfile(one_file) ):
# If the extension is defined, the file must match it
if ( (not options.input_directory_extension) or one_file.endswith( '.' + options.input_directory_extension ) ):
add_element( one_file, input_elements, regexp )
element_count = element_count + 1
# Handle any individual files
if ( options.input_file ):
#For each file
for input_file in ( options.input_file.rsplit(',') ):
add_element( input_file, input_elements, regexp )
element_count = element_count + 1
return element_count
if __name__ == '__main__':
##
# Manage options
##
parser = OptionParser(usage="%prog -o OUTPUT_FILE [-f INPUT_FILE] [-l INPUT_FILE_LIST] [-d INPUT_DIRECTORY [-e INPUT EXTENSION]] [-t]", description="Generates list file from various input sources of filenames. This script is used to accept a selection of inputs from either an input list, directory, file, or any combination thereof. Each of these options can also be specified using comma-separated lists.")
igroup = OptionGroup(parser, "options","")
igroup.add_option("-o", "--output_iter_list", help="Desired path to output iterator file.", dest="output_iter_list")
igroup.add_option("-f", "--input_file", help="The full path to an input file. this can also be a comma-separated list of input files.", dest="input_file")
igroup.add_option("-l", "--input_file_list", help="Plain text file containing the full paths to any number of files, one per line. This can also be a comma-separated list of input file lists.", dest="input_file_list")
igroup.add_option("-d", "--input_directory", help="The full path to an input directory. This can also be a comma-separated list of input directories.", dest="input_directory")
igroup.add_option("-e", "--input_directory_extension", help="To be used in conjuction with the input_directory option, this can be used to filter files by extension within any passed input directories.", dest="input_directory_extension")
igroup.add_option("-t", "--timestamp", help="Add timestamp to each output line.", dest="timestamp", action="store_true")
parser.add_option_group(igroup)
(options, args) = parser.parse_args()
check_parameters()
##
# Set variables
##
# Regex to identify the output files of CASAVA 1.8 (for 'casava' option in FASTQC)
casava_output_regexp = '.+\/([^\/]+_[^\/]+_[^\/]+_[^\/]+)_[^\/]+\.fastq\.gz'
# Play nicely
os.umask(0000)
# Structure like input_elements{file_id:{'files_path':files_path, 'fastqc_opt':fastqc_opt}}. It store output informations.
input_elements = {}
##
# Load informations on input_elements
##
input_element_count = gather_input_elements( input_elements, casava_output_regexp )
##
# Create output file
##
FH_output = open( options.output_iter_list, "w" )
# Header line
FH_output.write( '$;I_FILE_BASE$;' + "\t" + '$;FASTQC_OPT$;' + "\t" '$;I_FASTQC_FILES$;' )
# Timestamp
timestamp = ""
if( options.timestamp ):
FH_output.write( "\t" + '$;I_TIMESTAMP$;' )
timestamp = strftime("%b %d %Y %I:%H%p", localtime())
FH_output.write( "\n" )
# For each future iteration
for file_name in input_elements.keys():
FH_output.write( file_name + "\t" + input_elements[file_name]['fastqc_opt'] + "\t" + input_elements[file_name]['files_path'] )
if( options.timestamp ):
FH_output.write( "\t" + timestamp )
FH_output.write( "\n" )
FH_output.close
sys.exit(0)
\ No newline at end of file
This diff is collapsed.
......@@ -31,7 +31,29 @@ require_once(t3lib_extMgm::extPath('nG6').'/lib/class.tx_nG6_utils.php');
* @author PF bioinformatique de Toulouse <>
*/
class tx_nG6_db {
/*
* Global functions
*------------------------------------------------------------*/
/**
* Update the specified field of the table
*
* @param string $entity the entity to change
* @param string $id the element id to update
* @param string $field the field to change
* @param string $value the new value
*/
function update_field($entity, $id, $field, $value) {
if( $field == 'uid' )
{
throw new Exception ("The function 'update_field' cannot change an id.") ;
}
$GLOBALS['TYPO3_DB']-> exec_UPDATEquery ("tx_nG6_$entity", 'uid='.$id, array($field => $value));
}
/*
* Project functions
*------------------------------------------------------------*/
......
......@@ -81,10 +81,13 @@ class tx_nG6_pi1 extends tslib_pibase {
<script type="text/javascript" src="'.t3lib_extMgm::siteRelPath($this->extKey).'res/js/jsphylosvg-min.js"></script>
<script type="text/javascript" src="'.t3lib_extMgm::siteRelPath($this->extKey).'res/js/raphael-min.js"></script>
<script type="text/javascript" src="'.t3lib_extMgm::siteRelPath($this->extKey).'res/js/unitip.js"></script>
<script type="text/javascript" src="'.t3lib_extMgm::siteRelPath($this->extKey).'res/js/jquery.datePicker.min.js"></script>
<script type="text/javascript" src="'.t3lib_extMgm::siteRelPath($this->extKey).'res/js/jquery.jeditable.min.js"></script>
<script type="text/javascript" src="'.t3lib_extMgm::siteRelPath($this->extKey).'res/js/krona-1.1.js"></script>
<link type="text/css" rel="stylesheet" media="screen" href="'.t3lib_extMgm::siteRelPath($this->extKey).'res/css/unitip.css"/>
<link type="text/css" rel="stylesheet" media="screen" href="'.t3lib_extMgm::siteRelPath($this->extKey).'res/css/jquery.venny.css"/>
<link type="text/css" rel="stylesheet" media="screen" href="'.t3lib_extMgm::siteRelPath($this->extKey).'res/css/jquery.dataTables.css"/>
<link type="text/css" rel="stylesheet" media="screen" href="'.t3lib_extMgm::siteRelPath($this->extKey).'res/css/jquery.datePicker.css"/>
<link type="text/css" rel="stylesheet" media="screen" href="'.t3lib_extMgm::siteRelPath($this->extKey).'res/css/tx_nG6.css"/>
<link type="text/css" rel="stylesheet" media="screen" href="'.t3lib_extMgm::siteRelPath($this->extKey).'res/css/jquery.ui.core.css"/>
<link type="text/css" rel="stylesheet" media="screen" href="'.t3lib_extMgm::siteRelPath($this->extKey).'res/css/jquery.ui.theme.css"/>
......
......@@ -91,6 +91,19 @@
<label index="unpublish_dialog_title">Unpublish</label>
<label index="unpublish_confirmation_msg">Are you sure you want to unpublish the selected project(s) ? When done analysis and data related to the project(s) will be no longer visible by all users.</label>
<label index="Jeditable_dblClickTitle">Double click to edit</label>
<label index="Datepicker_closeText">Done</label>
<label index="Datepicker_prevText">&#x3c;Prev</label>
<label index="Datepicker_nextText">Next&#x3e;</label>
<label index="Datepicker_currentText">Today</label>
<label index="Datepicker_monthNames">January, February, March, April, May, June, July, August, September, October, November, December</label>
<label index="Datepicker_monthNamesShort">Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec</label>
<label index="Datepicker_dayNames">Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday</label>
<label index="Datepicker_dayNamesShort">Sun, Mon, Tue, Wed, Thu, Fri, Sat</label>
<label index="Datepicker_dayNamesMin">Su, Mo, Tu, We, Th, Fr, Sa</label>
<label index="Datepicker_weekHeader">Wk</label>
<label index="Analyse_sample">Samples</label>
<label index="Analyse_archives_title">Result file(s)</label>
<label index="Analyse_total">Total</label>
......@@ -445,6 +458,19 @@
<label index="analyse_desc">L'ensemble des résultats de cette analyse occupent ###ANALYSE_SIZE### d'espace disque.</label>
<label index="list_project_size_desc">L'ensemble des données brutes et des résultats d'analyses occupent ###PROJECT_SIZE### d'espace disque pour l'ensemble des projets.</label>
<label index="Datepicker_closeText">Fermer</label>
<label index="Datepicker_prevText">&#x3c;Préc</label>
<label index="Datepicker_nextText">Suiv&#x3e;</label>
<label index="Datepicker_currentText">Courant</label>
<label index="Datepicker_monthNames">Janvier, Février, Mars, Avril, Mai, Juin, Juillet, Août, Septembre, Octobre, Novembre, Décembre</label>
<label index="Datepicker_monthNamesShort">Jan, Fév, Mar, Avr, Mai, Jun, Jul, Aoû, Sep, Oct, Nov, Déc</label>
<label index="Datepicker_dayNames">Dimanche, Lundi, Mardi, Mercredi, Jeudi, Vendredi, Samedi</label>
<label index="Datepicker_dayNamesShort">Dim, Lun, Mar, Mer, Jeu, Ven, Sam</label>
<label index="Datepicker_dayNamesMin">Di, Lu, Ma, Me, Je, Ve, Sa</label>
<label index="Datepicker_weekHeader">Sm</label>
<label index="Jeditable_dblClickTitle">Double clic pour éditer</label>
<label index="Analyse_sample">Echantillons</label>
<label index="Analyse_archives_title">Fichier(s) résultat</label>
<label index="Analyse_total">Total</label>
......@@ -551,7 +577,7 @@
<label index="S16CleanerAnalyse_homopolymer_param">Supprime les séquences avec des homopolymères de taille supérieur à ###HOMO_SIZE###pb.</label>
<label index="S16CleanerAnalyse_fwd_param">Primer forward = ###FWD### trouvé avec un minimum de ###MIN_FWD### matches.</label>
<label index="S16CleanerAnalyse_rvrs_param">Primer reverse = ###RVRS### trouvé avec un minimum de ###MIN_RVRS### matches.</label>
<label index="S16CleanerAnalyse_full_size_param">Supprime les séquences complètes dont la taille est infèrieur à ###FULL_MIN_SIZE###pb.</label>
<label index="S16CleanerAnalyse_full_size_param">Supprime les séquences complètes dont la taille est inférieur à ###FULL_MIN_SIZE###pb.</label>
<label index="S16CleanerAnalyse_result_title">Résultats du nettoyage</label>
<label index="S16CleanerAnalyse_before_cleaning">Avant nettoyage</label>
<label index="S16CleanerAnalyse_after_cleaning">Après nettoyage</label>
......
This diff is collapsed.
{*
Copyright (C) 2009 INRA
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*}
{* Recursive function to display an analysis hierarchy *}
{foreach from=$element item=new_element}
<tr>
{assign var="hidden_class" value="class='tx-nG6-pi1-hidden'"}
{if $new_element.data.hidden == 0}
{assign var="hidden_class" value=""}
{/if}
{if $new_element.data.superuser}
<td><center><input type="checkbox" id="chk_analysis_{$new_element.data.id}" value="analysis_{$new_element.data.id}"></center></td>
{/if}
<td {$hidden_class} nowrap>
{section name=customer loop=$prof*3}
&nbsp;
{/section}
{if $prof != 0}
|--
{/if}
{$new_element.data.href}
</td>
<td {$hidden_class}>{$new_element.data.description}</td>
<td {$hidden_class}>{$new_element.data.software}</td>
<td {$hidden_class}>{$new_element.data.version}</td>
</tr>
{* recall *}
{if $new_element.child}
{$new_prof = $prof + 1}
{include file="recursive_list_analysis_display.tpl" element=$new_element.child prof=$new_prof}
{/if}
{*
Copyright (C) 2009 INRA
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*}
{* Recursive function to display an analysis hierarchy *}
{foreach from=$element item=new_element}
<tr id="tr_analysis_{$new_element.data.id}">
{assign var="hidden_attribute" value="tx-nG6-pi1-hidden"}
{assign var="hidden_class" value="class='$hidden_attribute'"}
{if $new_element.data.hidden == 0}
{assign var="hidden_class" value=""}
{assign var="hidden_attribute" value=""}
{/if}
{assign var="editable" value=""}
{if $new_element.data.superuser}
<td><center><input type="checkbox" id="chk_analysis_{$new_element.data.id}" value="analysis_{$new_element.data.id}"></center></td>
{assign var="editable" value="editable"}
{/if}
<td class="{$editable} field=analyze=name {$hidden_attribute}" nowrap>
{assign var="analyze_tree" value=""}
{section name=customer loop=$prof*3}
{assign var="analyze_tree" value="$analyze_tree &nbsp;"}
{/section}
{if $prof != 0}
{assign var="analyze_tree" value="$analyze_tree |-- "}
{/if}
{$analyze_tree}{$new_element.data.href}
</td>
<td class="{$editable} field=analyze=description {$hidden_attribute}">{$new_element.data.description}</td>
<td {$hidden_class}>{$new_element.data.software}</td>
<td {$hidden_class}>{$new_element.data.version}</td>
</tr>
{* recall *}
{if $new_element.child}
{$new_prof = $prof + 1}
{include file="recursive_list_analysis_display.tpl" element=$new_element.child prof=$new_prof}
{/if}