def displayCylinder(self, name): # If it is already there, remove it self.undisplayCylinder(name) self.displayed[name] = None t = self.cylinders[name]['type'] p = self.cylinders[name]['position'] v = self.cylinders[name]['vector'] r = self.cylinders[name]['diameter'] / 2.0 pEnd = p[0] + v[0] * self.cylinders[name]['length'], p[ 1] + v[1] * self.cylinders[name]['length'], p[ 2] + v[2] * self.cylinders[name]['length'] #print "New cylinder mesh at %.2f, %.2f, %.2f, radius=%.2f" % (p[0], p[1], p[2], r) newCyl = self.a.toAObject( aims.SurfaceGenerator.cylinder(aims.Point3df(p[0], p[1], p[2]), aims.Point3df(pEnd), r, r, 24, True, True)) # Couleur automatique par catégorie if t not in self.typeColors: self.currentColorHue = (self.currentColorHue + 40) % 256 self.typeColors[t] = QtGui.QColor.fromHsv(self.currentColorHue, 245, 220, 255) color = self.typeColors[t] self.a.setMaterial(newCyl, diffuse=[ color.redF(), color.greenF(), color.blueF(), color.alphaF() ]) self.a.addObjects(newCyl, self.wins) self.displayed[name] = {'mesh': newCyl, 'type': t}
def peaks_as_spheres(path_peaks_volume, path_spheres, radius=2): """ Represent peaks as spheres centered on peaks location and of radius radius :param path_peaks_volume: path of the boolean volume with peaks :param path_spheres: path of the mesh (spheres) representing the peaks :param radius: radius (in mm) of the spheres used for display :return: """ volume = aims.read(path_peaks_volume) data = np.array(volume)[..., 0] voxel_size = volume.header()['voxel_size'] + [1] scaling = aims.AffineTransformation3d() scaling.fromMatrix(np.diag(voxel_size)) peaks_vol_coord = np.transpose(np.vstack(np.where(data != 0))) centers = [aims.Point3df(p) for p in peaks_vol_coord] print(len(centers)) for i, center in enumerate(centers): center = scaling.transform(center) sphere = aims.SurfaceGenerator.sphere(center, radius,300) if i == 0: spheres = sphere else: aims.SurfaceManip.meshMerge(spheres, sphere) aims.write(spheres, path_spheres)
def vertices_and_faces_to_mesh(vertices, faces, header=None): ''' Create an aims 2D or 3D mesh using precomputed vertices and faces. Vertices and faces are assumed to be compatible :param vertices: ndarray (N,d) :param faces: ndarray (N1,d1) :param header: a dictionnary like structure :return: AimsTimeSurface ''' # determine the mesh type based on polygon type (does not work for quads polygon !) poly_type = faces.shape[-1] mesh = aims.TimeSurface(dim=poly_type) v = mesh.vertex() p = mesh.polygon() v.assign([aims.Point3df(x) for x in vertices]) p.assign([aims.AimsVector(x, dtype='U32', dim=poly_type) for x in faces]) # recompute normals, not mandatory but to have coherent mesh #rem does not work for 2D meshes normals need to be added manually (works like a texture) mesh.updateNormals() if header is not None: #fill the mesh empty header of the mesh with values in header h = mesh.header() for k in header.keys(): h[k] = header[k] return mesh
def mesh_from_arrays(coord, triangles, path=None): """ Create a mesh object from two arrays fixme: intent should be set ! """ carray = gifti.GiftiDataArray().from_array(coord.astype(np.float32), "NIFTI_INTENT_POINTSET", encoding='B64BIN') #endian="LittleEndian") tarray = gifti.GiftiDataArray().from_array(triangles.astype(np.int32), "NIFTI_INTENT_TRIANGLE", encoding='B64BIN') #endian="LittleEndian") img = gifti.GiftiImage(darrays=[carray, tarray]) if path is not None: try: from soma import aims mesh = aims.AimsTimeSurface(3) mesh.vertex().assign([aims.Point3df(x) for x in coord]) mesh.polygon().assign( [aims.AimsVector_U32_3(x) for x in triangles]) aims.write(mesh, path) except: print("soma writing failed") gifti.write(img, path) return img
def activateVirtualLed(self, x, y, globx, globy): print 'coucou', x, y w = self.view().aWindow() obj = w.objectAtCursorPosition(x, y) if obj is not None: print 'object:', obj, obj.name() poly = w.polygonAtCursorPosition(x, y, obj) mesh = anatomistControl.cpp.AObjectConverter.aims(obj) if poly == 0xffffff or poly < 0 or poly >= len(mesh.polygon()): return #print 'polygon:', poly #print 'mesh:', mesh ppoly = mesh.polygon()[poly] vert = mesh.vertex() #print 'poly:', poly, ppoly pos = aims.Point3df() pos = w.positionFromCursor(x, y) #print 'pos:', pos v = ppoly[np.argmin([(vert[p] - pos).norm() for p in ppoly])] print 'vertex:', v, vert[v]
def clickHandler(self, eventName, params): # pdb.set_trace() coords = params['position'][:3] #coords = self.a.linkCursorLastClickedPosition().items() if self.mesh is not None: #self.updateMeshTexture(coords) win = params['window'] pos2d = aims.Point3df() win.view().cursorFromPosition(coords, pos2d) x, y = pos2d[:2] obj = win.objectAtCursorPosition(x, y) MeshObj = [iterobj for iterobj in obj if iterobj == self.mesh] if len(MeshObj) > 0: #obj == self.currentObj: if self.aimsMesh is None: self.aimsMesh = self.a.toAimsObject(self.mesh) poly = win.polygonAtCursorPosition(x, y, self.currentObj) if poly != 0xffffff and poly >= 0 and poly < len( self.aimsMesh.polygon()): ppoly = self.aimsMesh.polygon()[poly] vert = self.aimsMesh.vertex() v = ppoly[np.argmin([(vert[p] - coords).norm() for p in ppoly])] self.updateMeshTexture(v, self.aimsMesh) self.dispCoords(coords) self.coords[self.currentElec] = coords #j'en suis la intermediaire = self.texture2[0].arraydata() intermediaire[np.where(intermediaire >= 15)] = 0 self.VertexLed.append()
def index_to_sphere(mesh, index, radius=R, nb_vertices=V): """ Create a sphere of center the index th vertices of a mesh and of radius radius :param mesh: :param index: :param radius: :param nb_vertices: :return: """ vertices = np.array(mesh.vertex()) center = vertices[index] sphere = aims.SurfaceGenerator.sphere(aims.Point3df(center), radius, int(nb_vertices)) return sphere
def vertices_and_faces_to_mesh(vertices, faces): ''' Create an aims 3D mesh using precomputed vertices and faces. Vertices and faces are assumed to be compatible :param vertices: ndarray :param faces: ndarray :return: aims mesh ''' #determine the mesh type based on polygon type (does not work for quads polygon !) poly_type = faces.shape[-1] mesh = aims.TimeSurface(dim=poly_type) v = mesh.vertex() p = mesh.polygon() v.assign([aims.Point3df(x) for x in vertices]) p.assign([aims.AimsVector(x, dtype='U32', dim=poly_type) for x in faces]) #recompute normals, not mandatory but to have coherent mesh mesh.updateNormals() return mesh
def vertices_and_faces_to_mesh(vertices, faces): """ Create an aims 2D or 3D mesh using precomputed vertices and faces. Vertices and faces are assumed to be compatible Note this should note be used as default aims.TimeSurface() function does exactly the same things but I did not know it at the time :param vertices: ndarray :param faces: ndarray :return: AimsTimeSurface """ # determine the mesh type based on polygon type (does not work for quads polygon !) poly_type = faces.shape[-1] mesh = aims.TimeSurface(dim=poly_type) v = mesh.vertex() p = mesh.polygon() v.assign([aims.Point3df(x) for x in vertices]) p.assign([aims.AimsVector(x, dtype="U32", dim=poly_type) for x in faces]) # recompute normals, not mandatory but to have coherent mesh # rem does not work for 2D meshes normals need to be added manually (works like a texture) mesh.updateNormals() return mesh
def printElec(self): diameter = 1 listPlots = [] for eleckeys, elec in self.approxElec.items(): name = eleckeys for plot in elec.keys(): #tu parcours approxElec pour générer les maillage mesh = self.a.toAObject( aims.SurfaceGenerator.sphere( aims.Point3df(elec[plot][0], elec[plot][1], elec[plot][2]), diameter, 64)) mesh.setName(name + str(plot + 1)) listPlots.append(mesh) self.a.setMaterial( mesh, diffuse=(0.0, 0.9, 0.1, 1.0) ) #[color.redF(), color.greenF(), color.blueF(), color.alphaF()] self.a.assignReferential(self.locaData.preReferential(), mesh) self.a.addObjects(mesh, self.locaData.wins[0]) #self.locaData.DeetoEstimated = approxElec meshes = {name: listPlots} self.dicMeshes.update(meshes)
def displayCylinder(self, name): # If it is already there, remove it self.undisplayCylinder(name) self.displayed[name] = None t = self.cylinders[name]['type'] p = self.cylinders[name]['position'] v = self.cylinders[name]['vector'] r = self.cylinders[name]['diameter'] / 2.0 newCyl = None if self.dispMode == 'off': self.displayed[name] = {'mesh': None, 'type': t} return if self.dispMode not in ['real', 'sphere', 'bipole']: print "Unknown dispMode %s for electrode ! Using 'real'..." % repr( self.dispMode) self.dispMode = 'real' if self.dispMode == 'real': pEnd = p[0] + v[0] * self.cylinders[name]['length'], p[ 1] + v[1] * self.cylinders[name]['length'], p[ 2] + v[2] * self.cylinders[name]['length'] newCyl = self.a.toAObject( aims.SurfaceGenerator.cylinder(aims.Point3df(p[0], p[1], p[2]), aims.Point3df(pEnd), r, r, 24, True, True)) self.a.releaseObject(newCyl) elif self.dispMode == 'sphere': diam = 2.0 if self.dispParams.has_key('diameter'): diam = float(self.dispParams['diameter']) if t == 'Plot': # Ignore the other parts pCenter = (p[0] + v[0] * self.cylinders[name]['length'] / 2.0, p[1] + v[1] * self.cylinders[name]['length'] / 2.0, p[2] + v[2] * self.cylinders[name]['length'] / 2.0) newCyl = self.a.toAObject( aims.SurfaceGenerator.sphere( aims.Point3df(pCenter[0], pCenter[1], pCenter[2]), diam, 32)) self.a.releaseObject(newCyl) #newCyl = self.a.toAObject(aims.SurfaceGenerator.cube(aims.Point3df(pCenter[0], pCenter[1], pCenter[2]), 2.0)) elif self.dispMode == 'bipole': #pCenter = (p[0] + v[0]*self.cylinders[name]['length']/2.0, p[1] + v[1]*self.cylinders[name]['length']/2.0, p[2] + v[2]*self.cylinders[name]['length']/2.0) #to change one day newCyl = self.a.toAObject( aims.SurfaceGenerator.ellipse(aims.Point3df(p[0], p[1], p[2]), 2.5, 1.5, 50)) self.a.releaseObject(newCyl) #aims.SurfaceGenerator.ellipse() # Automatic color for an unknown type if t not in self.typeColors: self.currentColorHue = (self.currentColorHue + 40) % 256 self.typeColors[t] = QtGui.QColor.fromHsv(self.currentColorHue, 245, 220, 255) color = self.typeColors[t] if newCyl is not None: self.a.setMaterial(newCyl, diffuse=[ color.redF(), color.greenF(), color.blueF(), color.alphaF() ]) self.displayed[name] = {'mesh': newCyl, 'type': t}
import os from soma import aims import numpy PRD = os.environ['PRD'] os.chdir(os.path.join(PRD, 'surface')) mesh = aims.AimsTimeSurface(3) # a mesh has a header mesh.header()['cortex_high'] = 'cortex_high' vert = mesh.vertex() poly = mesh.polygon() c = numpy.loadtxt('lh_vertices_high.txt') vert.assign([aims.Point3df(x) for x in c]) pol = numpy.loadtxt('lh_triangles_high.txt') poly.assign([aims.AimsVector(x, dtype='U32', dim=3) for x in pol]) # write result aims.write(mesh, 'lh_mesh_high.mesh')
def execution( self, context ): if loadmat is None: return self.matlabExecution( context ) # scipy / numpy / pyaims execution aim = self.source_volume amat = self.read bim = self.registered_volume if self.registered_volume is not None: bmatname = self.registered_volume.fullName() + '.mat' bmat = self.central_to_registered if bmat is None: context.write( 'No destination transformation - ' \ 'taking its origin translation' ) # bim = None else: bmat = None context.write( 'No destination volume - going only to central ref' ) aattrs = aimsGlobals.aimsVolumeAttributes( aim ) # context.write( 'aatrs: ', aattrs ) if bim: battrs = aimsGlobals.aimsVolumeAttributes( bim ) # context.write( 'battrs: ', battrs ) dim1 = aattrs[ 'volume_dimension' ][:3] vox1 = aattrs[ 'voxel_size' ][:3] t1 = aims.Motion( aattrs[ 'transformations' ][0] ) s2m = aims.Motion( aattrs[ 'storage_to_memory' ] ) mvox1 = aims.Motion() mvox1.rotation().setValue( vox1[0], 0, 0 ) mvox1.rotation().setValue( vox1[1], 1, 1 ) mvox1.rotation().setValue( vox1[2], 2, 2 ) tn = t1 * s2m * mvox1 origin1 = tn.inverse().transform( aims.Point3df( 0, 0, 0 ) ) origin1 += aims.Point3df( 1, 1, 1 ) # add 1 to matlab coords if bim: dim2 = battrs[ 'volume_dimension' ][:3] vox2 = battrs[ 'voxel_size' ][:3] t2 = aims.Motion( battrs[ 'transformations' ][0] ) s2m2 = aims.Motion( battrs[ 'storage_to_memory' ] ) mvox2 = aims.Motion() mvox2.rotation().setValue( vox2[0], 0, 0 ) mvox2.rotation().setValue( vox2[1], 1, 1 ) mvox2.rotation().setValue( vox2[2], 2, 2 ) tn = t2 * s2m2 * mvox2 origin2 = tn.inverse().transform( aims.Point3df( 0, 0, 0 ) ) origin2 += aims.Point3df( 1, 1, 1 ) # add 1 to matlab coords else: dim2 = [ 0, 0, 0 ] vox2 = [ 1, 1, 1 ] origin2 = [ 0, 0, 0 ] # context.write( 'dim1:', str( dim1 ) ) # context.write( 'vox1:', str( vox1 ) ) # context.write( 'origin1:', str( origin1 ) ) # context.write( 'dim2', str( dim2 ) ) # context.write( 'vox2:', str( vox2 ) ) # context.write( 'origin2:', str( origin2 ) ) # create matlab script DIM1 = numpy.transpose( numpy.mat( dim1 ) ) VOX1 = numpy.transpose( numpy.mat( vox1 ) ) ORIGIN1 = numpy.transpose( numpy.mat( origin1 ) ) DIM2 = numpy.transpose( numpy.mat( dim2 ) ) VOX2 = numpy.transpose( numpy.mat( vox2 ) ) ORIGIN2 = numpy.transpose( numpy.mat( origin2 ) ) trans1 = self.write.fullPath() if os.path.exists( amat.fullPath() ): a = loadmat( amat.fullPath() ) aM = numpy.mat( a[ 'M' ] ).astype( numpy.double ) aM = aM * numpy.mat( numpy.diag( [ 1./vox1[0], 1./vox1[1], 1./vox1[2], 1. ] ) ) else: aM = numpy.mat( numpy.diag( [ 1., 1., 1., 1., ] ) ) aM[ 0:3, 3 ] = - numpy.multiply( ORIGIN1, VOX1 ) ainv = numpy.linalg.inv( aM ) o1 = ainv[:, 3 ] # Y and Z axis are flipped o1[ 1:3 ] = -o1[ 1:3 ] + numpy.multiply( ( DIM1[1:3] - 1 ), VOX1[1:3] ) if bmat: if os.path.exists( bmat.fullPath() ): b = loadmat( bmat.fullPath() ); bM = numpy.mat( b[ 'M' ] ).astype( numpy.double ) bM = bM * numpy.mat( numpy.diag( [ 1./vox2[0], 1./vox2[1], 1./vox2[2], 1. ] ) ) else: bM = numpy.mat( numpy.diag( [ 1., 1., 1., 1. ] ) ) bM[ 0:3, 3 ] = - numpy.multiply( ORIGIN2, VOX2 ) else: bM = numpy.mat( numpy.diag( [ 1., 1., 1., 1. ] ) ) bM[ 0:3, 3 ] = - numpy.multiply( ORIGIN2, VOX2 ) binv = numpy.linalg.inv( bM ) o2 = binv[:, 3 ] # Y and Z axis are flipped o2[ 1:3 ] = -o2[ 1:3, 0 ] + numpy.multiply( ( DIM2[1:3] - 1 ), VOX2[1:3] ) # flip Y and Z axis to go to Aims/Anatomist world aflip = numpy.mat( numpy.diag( [ 1., -1., -1., 1. ] ) ) aflip[ 1:3, 3 ] = numpy.multiply( ( DIM1[1:3] - 1 ), VOX1[1:3] ) aM = aM * aflip # verify origin still transforms to 0 # aM * o1 bflip = numpy.mat( numpy.diag( [ 1., -1., -1., 1. ] ) ) bflip[ 1:3, 3 ] = numpy.multiply( ( DIM2[1:3] - 1 ), VOX2[1:3] ) bM = bM * bflip # verify origin still transforms to 0 # bM * o2 M = numpy.linalg.inv(bM) * aM # M * o1 - o2 T = numpy.array( numpy.transpose( M[ 0:3, 3 ] ) )[ 0,: ] context.write( 'writing ', trans1 ) fid = open( trans1, 'w' ) Mt = numpy.array( numpy.transpose( M[0:3, 0:3] ) ) print('%f %f %f' % tuple( T ), file=fid) print('%f %f %f' % tuple( Mt[ 0,: ] ), file=fid) print('%f %f %f' % tuple( Mt[ 1,: ] ), file=fid) print('%f %f %f' % tuple( Mt[ 2,: ] ), file=fid) fid.close()
def applyMatrix(self, x, y, z, matrix): return matrix.transform( aims.Point3df(x,y,z) ).items()