# -*- coding: utf-8 -*- # This software and supporting documentation are distributed by # bioPICSEL # CEA/DSV/I²BM/MIRCen/LMN, Batiment 61, # 18, route du Panorama # 92265 Fontenay-aux-Roses # France # # This software is governed by the CeCILL license version 2 under # French law and abiding by the rules of distribution of free software. # You can use, modify and/or redistribute the software under the # terms of the CeCILL license version 2 as circulated by CEA, CNRS # and INRIA at the following URL "http://www.cecill.info". # # As a counterpart to the access to the source code and rights to copy, # modify and redistribute granted by the license, users are provided only # with a limited warranty and the software's author, the holder of the # economic rights, and the successive licensors have only limited # liability. # # In this respect, the user's attention is drawn to the risks associated # with loading, using, modifying and/or developing or reproducing the # software by the user in light of its specific status of free software, # that may mean that it is complicated to manipulate, and that also # therefore means that it is reserved for developers and experienced # professionals having in-depth computer knowledge. Users are therefore # encouraged to load and test the software's suitability as regards their # requirements in conditions enabling the security of their systems and/or # data to be ensured and, more generally, to use and operate it in the # same conditions as regards security. # # The fact that you are presently reading this means that you have had # knowledge of the CeCILL license version 2 and that you accept its terms. # Ligne obligatoire from brainvisa.processes import * import os, math, copy, csv, os.path import soma.aims # Pour les formats de fichier Aims import shfjGlobals # Import brainrat libraries import brainrat.uicheck as uicheck name = 'VolumeROIAnalysis' userLevel = 0 signature = Signature( 'ListOf_Input_3dImage', ListOf( ReadDiskItem( '3D Volume', 'Biology 3D volume formats' ) ), 'ListOf_Input_3dImage_ROI', ListOf( ReadDiskItem( 'ROI', ( 'Graph', 'GIS Image', ) ) ), 'ListOf_Input_Motion_3dImage_TO_ROI', ListOf( ReadDiskItem( 'Transformation matrix', 'Transformation matrix' ) ), 'Hierarchy', ReadDiskItem( 'Hierarchy', 'Hierarchy' ), 'Hierarchy_Use_Path', Boolean(), 'ListOf_Output_Text_Results', ListOf( WriteDiskItem( 'Text file', 'Text file' ) ), 'Synthesis_Result', WriteDiskItem( 'Text file', 'Text file' ), ) def ListOf_Input_3dImageChanged( self, ListOf_Input_3dImage ): def getOutputStatPathes( inputpathes ): v = list() for a in inputpathes : if a : p, e = os.path.splitext( a.fullPath() ) v.append( p + '_stat.txt' ) return v if self.ListOf_Input_3dImage \ and self.isDefault('ListOf_Output_Text_Results'): # Store the new default value for ListOf_Output_Text_Results field statpathes = getOutputStatPathes(self.ListOf_Input_3dImage) self.setValue('ListOf_Output_Text_Results', statpathes, True) # Get the item corresponding to an index # also when index is greater than size of values # it allows to manage optional multiple values def matchingItem(self, values, index = 0, defaultindex = 0) : if index < len(values) : return values[index] else : return values[defaultindex] def initialization( self ): self.Hierarchy_Use_Path = False # Sets optional parameters self.setOptional( 'ListOf_Input_Motion_3dImage_TO_ROI', 'Hierarchy', 'Hierarchy_Use_Path', 'ListOf_Output_Text_Results', 'Synthesis_Result' ) # Sets default parameters value self.Input_3dImage_ROI = '' # Add links self.addLink( None, 'ListOf_Input_3dImage', self.ListOf_Input_3dImageChanged ) def execution( self, context ): #try : # Check parameters for i in self.ListOf_Input_3dImage : if ( len( i.fullPath() ) == 0 ) or ( not os.path.exists( i.fullPath() ) ) : context.error( '\'ListOf_Input_3dImage\' field contains invalid file path [ %s ].' \ ' Please select valid volume files.' % i.fullPath() ) return for i in self.ListOf_Input_3dImage_ROI : if ( len( i.fullPath() ) == 0 ) or ( not os.path.exists( i.fullPath() ) ) : context.error( '\'ListOf_Input_3dImage_ROI\' field contains invalid file path [ %s ].' \ ' Please select valid volume files.' % i.fullPath() ) return if ( len(self.ListOf_Input_3dImage_ROI) != len(self.ListOf_Input_3dImage) ) and (len(self.ListOf_Input_3dImage_ROI) > 1) : context.error( '\'ListOf_Input_3dImage_ROI\' field contains %d files.' \ ' It must contain 1 file or %d files as ListOf_Input_3dImage field.' % (len(self.ListOf_Input_3dImage_ROI), len(self.ListOf_Input_3dImage) ) ) return # Make a translation dictionary translation = {} if self.Hierarchy : # Hierarchie (fichier ".hie") hie = soma.aims.read( unicode(self.Hierarchy) ) # Make a children queue ch = list( hie.children() ) pt = [ item[ 'name' ] for item in hie.children() ] while ch: # get one child and remove it from the queue item = ch.pop() path = pt.pop() # Look for 'label' and 'name' properties if item.has_key( 'label' ) and item.has_key( 'name' ): # Leaf case label = long(item[ 'label' ]) name = item[ 'name' ] if self.Hierarchy_Use_Path: translation[ label ] = path else: translation[ label ] = name # add item children to the queue ch += item.children() for p in item.children() : if p.has_key( 'name' ) and len(p[ 'name' ]) > 0 : pt.append( path + '/' + p[ 'name' ] ) else : pt.append( path ) outputfiles = [] for i in xrange(len(self.ListOf_Input_3dImage)) : roiimage = self.matchingItem(self.ListOf_Input_3dImage_ROI, i) context.write( _t_( 'Processing %s volume statistics' % os.path.basename(self.ListOf_Input_3dImage[i].fullPath() ) ), ' ...' ) if ( len(self.ListOf_Output_Text_Results) > i ) and ( len( self.ListOf_Output_Text_Results[i].fullPath() ) > 0 ) : outputfile = self.ListOf_Output_Text_Results[i] else : outputfile = context.temporary( 'Text file' ) if os.path.exists( outputfile.fullPath() ): os.remove( outputfile.fullPath() ) # Append the output file to a list that will be used to generate synthesis outputfiles.append(outputfile) command = [ 'AimsRoiFeatures', '-s', self.ListOf_Input_3dImage[i].fullPath(), '-i', roiimage.fullPath(), '-f', 'csv', '-o', outputfile.fullPath() ] if ( len(self.ListOf_Input_Motion_3dImage_TO_ROI) > i ) and ( len( self.ListOf_Input_Motion_3dImage_TO_ROI[i].fullPath() ) > 0 ) : # Invert motion in temporary file motion = self.matchingItem(self.ListOf_Input_Motion_3dImage_TO_ROI, i) invmotion = context.temporary( 'Transformation matrix' ) m = soma.aims.read(motion.fullPath()) m = m.inverse() soma.aims.write(m, invmotion.fullPath()) command += [ '-t', invmotion.fullPath() ] context.system( *command ) if self.Hierarchy : # Apply hierarchy to labels r = csv.reader( open(outputfile.fullPath(), 'rb'), delimiter = '\t', quoting = csv.QUOTE_MINIMAL ) tr = [] for l in r: if len(l) > 0 : try : l[0] = translation.get(long(l[0]), l[0]) except ValueError: pass tr.append(l) r = None w = csv.writer( open(outputfile.fullPath(), 'wb'), delimiter = '\t', quoting = csv.QUOTE_MINIMAL ) w.writerows(tr) w = None voistatfile = open( outputfile.fullPath(), "rb" ) voistat = voistatfile.readlines() context.write( uicheck.formatAsHTMLTable( voistat, columnsep = '\t', quoting = csv.QUOTE_MINIMAL ) ) if self.Synthesis_Result : # Generate synthesis synthesis = [] headline1 = [ '' ] for i in xrange(len(outputfiles)) : roi = self.matchingItem(self.ListOf_Input_3dImage_ROI, i) o = outputfiles[i] p, e = os.path.splitext(self.ListOf_Input_3dImage[i].fullPath()) headline1.append(os.path.basename(p)) p, e = os.path.splitext(roi.fullPath()) headline1.append(os.path.basename(p)) headline1 += [ '' ] * 5 headline2 = [ 'ROI_label x Files x Measures' ] + [ 'point_count', 'volume', 'mean', 'stddev', 'min', 'max', 'median' ] * len(outputfiles) synthesis.append(headline1) synthesis.append(headline2) synthesisrows = {} # First pass to extract headers for o in outputfiles : r = csv.reader( open(o.fullPath(), 'rb'), delimiter = '\t', quoting = csv.QUOTE_MINIMAL ) for l in r : if len(l) > 0 : if not synthesisrows.get(l[0]) and l[0] != 'ROI_label' : synthesisrows[l[0]] = [] # Second pass to fill synthesis for o in outputfiles : for k, v in synthesisrows.items() : r = csv.reader( open(o.fullPath(), 'rb'), delimiter = '\t', quoting = csv.QUOTE_MINIMAL ) keyfound = False for l in r : if l[0] == k : v += l[1:] keyfound = True break r = None if not keyfound : v += [0] * 7 # Add generated lines to synthesis for k, v in synthesisrows.items() : synthesis.append( [k] + v ) w = csv.writer( open(self.Synthesis_Result.fullPath(), 'wb'), delimiter = '\t', quoting = csv.QUOTE_MINIMAL ) w.writerows(synthesis) w = None #except Exception, error : #context.error( _t_( uicheck.messages[ 'processingerrormessage' ] ) )