Beispiel #1
0
def detect(trypaths=None):
    """Check if we have calpy and if so, add its path to sys.path."""

    global calpy_path

    calpy = software.checkExternal('calpy')
    if not calpy:
        return

    print("You have calpy version %s" % calpy)
    path = ''
    calpy = calpy.split('-')[0]  # trim the version trailer
    if software.checkVersion('calpy', '0.3.4-rev3', external=True) >= 0:
        P = utils.command('calpy --whereami')
        if not P.sta:
            path = P.out.splitlines()[0]
            pf.debug("I found calpy in %s" % path)
    if not path:
        if trypaths is None:
            trypaths = ['/usr/local/lib', '/usr/local']
        for p in trypaths:
            path = '%s/calpy-%s' % (p, calpy)
            if os.path.exists(path):
                pf.debug('path exists: %s' % path)
                break
            else:
                pf.debug('path does not exist: %s' % path)
                path = ''
    if path:
        #path += '/calpy'
        print("I found calpy in '%s'" % path)
        sys.path.append(path)

    calpy_path = path
Beispiel #2
0
def checkSelfIntersectionsWithTetgen(self,verbose=False):
    """check self intersections using tetgen

    Returns pairs of intersecting triangles
    """
    from pyformex.plugins.tetgen import writeSurface
    cmd = 'tetgen -d '
    tmp = utils.tempName()
    print("Writing temp file %s" % tmp)
    writeSurface(tmp, self.coords, self.elems)
    if verbose:
        cmd += '-V '
    cmd=cmd+ tmp
    print("Checking with command\n %s" % cmd)
    P = utils.command(cmd)
    if P.sta:
        print('Tetgen got an error')
        return P.sta
    try:
        os.remove(tmp+'.node')
        os.remove(tmp+'.smesh')
        os.remove(tmp+'.1.face')
        os.remove(tmp+'.1.node')
    except:
        pass
    if P.sta or verbose:
        print(P.out)
    return asarray( [int(l.split(' ')[0]) for l in out.split('acet #')[1:]]).reshape(-1, 2)-1
Beispiel #3
0
def remoteCommand(host=None,command=None):
    """Execute a remote command.

    host: the hostname where the command is executed
    command: the command line
    """
    if host is None or command is None:
        res = askItems(
            [ _I('host', choices=['bumpfs', 'bumpfs2', '--other--']),
              _I('other', '', text='Other host name'),
              _I('command', 'hostname'),
              ],
            enablers = [('host', '--other--', 'other')],
            )

    if res:
        host = res['host']
        if host == '--other--':
            host = res['other']
        command = res['command']

    if host and command:
        P = utils.command(['ssh', host, command])
        print(P.out)
        return P.sta
Beispiel #4
0
def distance2centerlines(S):
    """Find the distances of the points of TriSurface S with open profiles
    to its centerlines.

    Retuns an array of  scalar distances for all nodes of S.
    """
    tmp = utils.tempFile(suffix='.vtp').name
    tmp1 = utils.tempFile(suffix='.vtp').name
    S.write(tmp, 'vtp')

    cmd = "vmtk vmtksurfacereader -ifile %s --pipe vmtkcenterlines -endpoints 1  -seedselector profileidlist -sourceids 0\
    --pipe vmtkdistancetocenterlines -useradius 1 -ofile %s " % (tmp, tmp1)

    P = utils.command(cmd)

    if P.sta:
        print("An error occurred during the distance calculation.")
        print(P.out)
        return None
    from pyformex.plugins.vtk_itf import readVTKObject
    [coords, cells, polys, lines,
     verts], fielddata, celldata, pointdata = readVTKObject(tmp1)
    cdist = pointdata['DistanceToCenterlines']
    from pyformex.plugins.vtk_itf import checkClean
    if not checkClean(S):
        print('nodes need to be re-matched because surface was not clean')
        reorderindex = Coords(coords).match(S.coords)
        cdist = cdist[reorderindex]
    os.remove(tmp)
    os.remove(tmp1)
    return cdist
Beispiel #5
0
def gtsinside(self,pts,dir=0):
    """_Test whether points are inside the surface.

    pts is a plex-1 Formex.
    dir is the shooting direction.

    Returns a list of point numbers that are inside.
    This is not intended to be used directly. Use inside instead
    """
    import os
    S = self.rollAxes(dir)
    P = pts.rollAxes(dir)
    tmp = utils.tempFile(suffix='.gts').name
    tmp1 = utils.tempFile(suffix='.dta').name
    tmp2 = utils.tempFile(suffix='.out').name
    #print("Writing temp file %s" % tmp)
    S.write(tmp, 'gts')
    #print("Writing temp file %s" % tmp1)
    with open(tmp1, 'w') as f:
        P.coords.tofile(f, sep=' ')
        f.write('\n')

    #print("Performing inside testing")
    cmd = "gtsinside %s %s" % (tmp, tmp1)
    P = utils.command(cmd, stdout=open(tmp2, 'w'))
    os.remove(tmp)
    os.remove(tmp1)
    if P.sta:
        #print("An error occurred during the testing.\nSee file %s for more details." % tmp2)
        print(P.out)
        return None
    #print("Reading results from %s" % tmp2)
    ind = fromfile(tmp2, sep=' ', dtype=Int)
    os.remove(tmp2)
    return ind
Beispiel #6
0
def transferFiles(host, userdir, files, targetdir):
    """Copy files from userdir on host to targetdir.

    files is a list of file names.
    """
    files = [ '%s:%s/%s' % (host, userdir.rstrip('/'), f) for f in files ]
    cmd = "scp %s %s" % (' '.join(files), targetdir)
    P = utils.command(cmd)
    return P.sta
Beispiel #7
0
def killClusterJob(jobname=None):
    """Kill a job to the cluster."""
    res = askItems([('jobname', '')])
    if res:
        jobname = res['jobname']
        host = pf.cfg.get('jobs/host', 'mecaflix')
        reqdir = pf.cfg.get('jobs/inputdir', 'bumper/requests')
        cmd = "touch %s/%s.kill" % (reqdir, jobname)
        print(host)
        print(cmd)
        P = utils.command(['ssh', host, "%s" % cmd])
        print(P.out)
Beispiel #8
0
def getRemoteDirs(host, userdir):
    """Get a list of all subdirs in userdir on host.

    The host should be a machine where the user has ssh access.
    The userdir is relative to the user's home dir.
    """
    cmd = "ssh %s 'cd %s;ls -F|egrep \".*/\"'" % (host, userdir)
    P = utils.command(cmd, shell=True)
    if P.sta:
        dirs = []
    else:
        dirs = [ j.strip('/') for j in P.out.split('\n') ]
    return dirs
Beispiel #9
0
def vmtkDistanceOfSurface(self, S, tryfixsign=True):
    """Find the distances of TriSurface S to the TriSurface self.

    Retuns a tuple of vector and signed scalar distances for all nodes of S.
    It is advisable to use a surface S which is clean (fused, compacted and renumbered).
    If not vmtk cleans the mesh and the nodes of S are re-matched.
    The signed distance is positive if the distance vector and the surface
    normal have negative dot product, i.e. if node of S is outer with respect to self.
    NB: the sign of sdist computed by vmtk can be wrong! This is a known bug of vmtk:
    If the endpoint of the distancevector is located on an edge of self,
    the normal is wrongly computed and the sign of sdist is wrong.
    The option tryfixsign has been added to solve this bug by letting pyFormex re-computing the dot product.
    However, some wrong sign may still be wrong.
    """
    tmp = utils.tempFile(suffix='.vtp').name
    tmp1 = utils.tempFile(suffix='.vtp').name
    tmp2 = utils.tempFile(suffix='.vtp').name
    S.write(tmp, 'vtp')
    self.write(tmp1, 'vtp')
    cmd = 'vmtk vmtksurfacedistance -ifile %s -rfile %s -distancevectorsarray vdist -signeddistancearray sdist -ofile %s' % (
        tmp, tmp1, tmp2)
    P = utils.command(cmd)
    os.remove(tmp)
    os.remove(tmp1)
    if P.sta:
        print("An error occurred during the distance calculation.")
        print(P.out)
        return None
    from pyformex.plugins.vtk_itf import readVTKObject
    [coords, cells, polys, lines,
     verts], fielddata, celldata, pointdata = readVTKObject(tmp2)
    vdist, sdist = pointdata['vdist'], pointdata['sdist']
    os.remove(tmp2)
    from pyformex.plugins.vtk_itf import checkClean
    if not checkClean(S):
        print('nodes need to be re-matched because surface was not clean')
        reorderindex = Coords(coords).match(S.coords)
        vdist = vdist[reorderindex]
        sdist = sdist[reorderindex]
    if tryfixsign:
        from pyformex.plugins.vtk_itf import findElemContainingPoint
        cellids = findElemContainingPoint(self, S.coords + vdist)
        notFound = cellids == -1
        if sum(notFound) > 0:
            print(
                "%d (of %d) points have not been found inside any cell. Check tolerance of findElemContainingPoint"
                % (sum(notFound), S.ncoords()))
        nc = self.areaNormals()[1][cellids]  #normals of cellids
        sdist1 = sign(dotpr(nc, vdist)) * abs(sdist)
        sdist[~notFound] = sdist1[~notFound]
    return vdist, sdist
Beispiel #10
0
def rsyncFiles(srcdir, tgtdir, include=['*'], exclude=[], exclude_first=False, rsh='ssh -q', chmod='ug+rwX,o-rwx', opts='-rv'):
    """Transfer files remotely using rsync

    Parameters:

    - `srcdir`: string: path from where to copy files. The path may be relative
      or absolute, and it can containing a leading 'host:' part to specify a
      remote directory (if `tgtdir` does not contain one).
    - `tgtdir`: string: path where to copy files to. The path may be relative
      or absolute, and it can containing a leading 'host:' part to specify a
      If tgtdir does not exist, it is created (thought the parent should exist).
      remote directory (if `srcdir` does not contain one).
    - `include`: list of strings: files to include in the copying process.
    - `exclude`: list of strings: files to exclude from the copying process.
    - `rsh`: string: the remote shell command to be used.
    - `chmod`: string: the permissions settings on the target system.
    - `opts`: string: the

    The includes are applied before the excludes. The first match will decide
    the outcome. The default is to recursively copy all files from `srcdir` to
    `tgtdir`. Other typical uses:

    - Copy some files from srcdir to tgtdir::

        rsyncFiles(src,tgt,include=['*.png','*.jpg'],exclude=['*'])

    - Copy all but some files from srcdir to tgtdir::

        rsyncFiles(src,tgt,exclude=['*.png','*.jpg'],exclude_first=True)

    Returns the Process used to execute the command. If the -v option
    is included in `opts`, then the Process.out atribute will contain
    the list of files transfered.

    Remarks:

    - You need to have no-password ssh access to the remote systems
    - You need to have rsync installed on source and target systems.

    """
    include = ' '.join(["--include '%s'" % i for i in include])
    exclude = ' '.join(["--exclude '%s'" % i for i in exclude])
    if exclude_first:
        include,exclude = exclude,include
    cmd = "rsync -e '%s' --chmod=%s %s %s %s/ %s %s" % (rsh, chmod, include, exclude, srcdir, tgtdir, opts)
    P = utils.command(cmd,shell=True)
    return P
Beispiel #11
0
def createMovie(files, encoder='convert', outfn='output', **kargs):
    """Create a movie from a saved sequence of images.

    Parameters:

    - `files`: a list of filenames, or a string with one or more filenames
      separated by whitespace. The filenames can also contain wildcards
      interpreted by the shell.
    - `encoder`: string: the external program to be used to create the movie.
      This will also define the type of output file, and the extra parameters
      that can be passed. The external program has to be installed on the
      computer. The default is `convert`, which will create animated gif.
      Other possible values are 'mencoder' and 'ffmeg', creating meg4
      encode movies from jpeg input files.
    - `outfn`: string: output file name (not including the extension).
      Default is output.

    Other parameters may be passed and may be needed, depending on the
    converter program used. Thus, for the default 'convert' program,
    each extra keyword parameter will be translated to an option
    '-keyword value' for the command.

    Example::

      createMovie('images*.png',delay=1,colors=256)

    will create an animated gif 'output.gif'.
    """
    print("Encoding %s" % files)
    if isinstance(files, list):
        files = ' '.join(files)

    if encoder == 'convert':
        outfile = outfn + '.gif'
        cmd = "convert " + " ".join(["-%s %s" % k for k in kargs.items()
                                     ]) + " %s %s" % (files, outfile)
    elif encoder == 'mencoder':
        outfile = outfn + '.avi'
        cmd = "mencoder \"mf://%s\" -o %s -mf fps=%s -ovc lavc -lavcopts vcodec=msmpeg4v2:vbitrate=%s" % (
            files, outfile, kargs['fps'], kargs['vbirate'])
    else:
        outfile = outfn + '.mp4'
        cmd = "ffmpeg -qscale 1 -r 1 -i %s output.mp4" % files
    pf.debug(cmd, pf.DEBUG.IMAGE)
    P = utils.command(cmd)
    print("Created file %s" % os.path.abspath(outfile))
    return P.sta
Beispiel #12
0
def saveMovie(filename, format, windowname=None):
    """Create a movie from the pyFormex window."""
    if windowname is None:
        windowname = pf.GUI.windowTitle()
    pf.GUI.raise_()
    pf.GUI.repaint()
    pf.GUI.toolbar.repaint()
    pf.GUI.update()
    pf.canvas.makeCurrent()
    pf.canvas.raise_()
    pf.canvas.update()
    pf.app.processEvents()
    windowid = windowname
    cmd = "xvidcap --fps 5 --window %s --file %s" % (windowid, filename)
    pf.debug(cmd, pf.DEBUG.IMAGE)
    P = utils.command(cmd)
    return P.sta
Beispiel #13
0
def runTetgen(fn,options=''):
    """Run tetgen mesher on the specified file.

    The input file is a closed triangulated surface.
    tetgen will generate a volume tetraeder mesh inside the surface,
    and create a new approximation of the surface as a by-product.
    """
    if not utils.hasExternal('tetgen'):
        pf.warning("""..

I could not find the 'tetgen' command.

tetgen is a quality tetrahedral mesh generator and a 3D Delaunay triangulator. See http://tetgen.org. It is available from the Debian non-free section.
""")
        return

    if os.path.exists(fn) and utils.hasExternal('tetgen'):
        P = utils.command('tetgen -z%s %s' % (options, fn))
        return P.sta
Beispiel #14
0
def save_window_rect(filename, format, quality=-1, window='root', crop=None):
    """Save a rectangular part of the screen to a an image file.

    crop: (x,y,w,h)
    """
    options = ''
    if crop:
        x, y, w, h = crop
        options += ' -crop "%sx%s+%s+%s"' % (w, h, x, y)
    cmd = 'import -window "%s" %s %s:%s' % (window, options, format, filename)
    # We need to use shell=True because window name might contain spaces
    # thus we need to add quotes, but these are not stripped off when
    # splitting the command line.
    # TODO: utils should probably be changed to strip quotes after splitting
    P = utils.command(cmd, shell=True)
    if P.sta:  # He, isn't this standard with utils.command?
        print(P.sta)
        print(P.err)
        print(P.out)
    return P.sta
Beispiel #15
0
def runLocalProcessor(filename='',processor='abaqus'):
    """Run a black box job locally.

    The black box job is a command run on an input file.
    If a filename is specified and is not an absolute path name,
    it is relative to the current directory.
    """
    if not filename:
        filename = askFilename(pf.cfg['workdir'], filter="Abaqus input files (*.inp)", exist=True)
    cpus = '4'
    if filename:
        jobname = os.path.basename(filename)[:-4]
        dirname = os.path.dirname(filename)
        if dirname == '':
            dirname = '.'
        cmd = pf.cfg['jobs/cmd_%s' % processor]
        cmd = cmd.replace('$F', jobname)
        cmd = cmd.replace('$C', cpus)
        cmd = "cd %s;%s" % (dirname, cmd)
        P = utils.command(cmd, shell=True)
        print(P.out)
Beispiel #16
0
def voronoi(fn):
    """Determine the voronoi diagram corresponding with a triangulated surface.

    fn is the file name of a surface, including the extension (.off, .stl, .gts, .neu or .smesh)
    The voronoi diagram is determined by Tetgen.
    The output are the voronoi nodes and the corresponding radii of the voronoi spheres.
    """
    S = TriSurface.read(fn)
    fn, ftype = os.path.splitext(fn)
    ftype = ftype.strip('.').lower()
    if ftype != 'smesh':
        S.write('%s.smesh' % fn)
    P = utils.command('tetgen -zpv %s.smesh' % fn)
    #information tetrahedra
    elems = tetgen.readElems('%s.1.ele' % fn)[0]
    nodes = tetgen.readNodes('%s.1.node' % fn)[0]
    #voronoi information
    nodesVor = tetgen.readNodes('%s.1.v.node' % fn)[0]
    #calculate the radii of the voronoi spheres
    vec = nodesVor[:] - nodes[elems[:, 0]]
    radii = sqrt((vec * vec).sum(axis=-1))
    return nodesVor, radii
Beispiel #17
0
def tetgenConvexHull(pts):
    """_Tetralize the convex hull of some points.

    Finds the convex hull some points and returns
    a tet mesh of the convex hull and the convex hull (tri3 mesh).

    If all points are on the same plane there is no convex hull.

    """
    tmp = utils.tempName()
    writeNodes(fn=tmp+'.node', coords=pts, offset=0)
    P = utils.command('tetgen %s'%(tmp+'.node'))
    if P.sta:
        print(P.out)
    tetconvhull = readTetgen(tmp+'.1.ele').values()[0]
    try:
        os.remove(tmp+'.node')
        os.remove(tmp+'.1.face')
        os.remove(tmp+'.1.node')
        os.remove(tmp+'.1.ele')
    except:
        pass
    return tetconvhull, tetconvhull.getBorderMesh()
Beispiel #18
0
def voronoiInner(fn):
    """Determine the inner voronoi diagram corresponding with a triangulated surface.

    fn is the file name of a surface, including the extension (.off, .stl, .gts, .neu or .smesh)
    The output are the voronoi nodes and the corresponding radii of the voronoi spheres.
    """
    S = TriSurface.read(fn)
    fn, ftype = os.path.splitext(fn)
    ftype = ftype.strip('.').lower()
    if ftype != 'smesh':
        S.write('%s.smesh' % fn)
    P = utils.command('tetgen -zp %s.smesh' % fn)
    #information tetrahedra
    elems = tetgen.readElems('%s.1.ele' % fn)[0]
    nodes = tetgen.readNodes('%s.1.node' % fn)[0].astype(float64)
    #calculate surface normal for each point
    elemsS = array(S.elems)
    NT = S.areaNormals()[1]
    NP = zeros([nodes.shape[0], 3])
    for i in [0, 1, 2]:
        NP[elemsS[:, i]] = NT
    #calculate centrum circumsphere of each tetrahedron
    centers = circumcenter(nodes, elems)[0]
    #check if circumcenter falls within the geomety described by the surface
    ie = column_stack([
        ((nodes[elems[:, j]] - centers[:]) * NP[elems[:, j]]).sum(axis=-1)
        for j in [0, 1, 2, 3]
    ])
    ie = ie[:, :] >= 0
    w = where(ie.all(1))[0]
    elemsInner = elems[w]
    nodesVorInner = centers[w]
    #calculate the radii of the voronoi spheres
    vec = nodesVorInner[:] - nodes[elemsInner[:, 0]]
    radii = sqrt((vec * vec).sum(axis=-1))
    return nodesVorInner, radii
Beispiel #19
0
def readDXF(filename):
    """Read a DXF file and extract the recognized entities.

    `filename`: name of a .DXF file.

    Returns a multiline string with one line for each recognized entity,
    in a format that can directly be used by :func:`convertDXF`.

    This function requires the external program `dxfparser` which comes
    with the pyFormex distribution. It currently recognizes entities of
    type 'Arc', 'Line', 'Polyline', 'Vertex'.
    """
    print(filename)
    if utils.hasExternal('dxfparser'):
        cmd = 'pyformex-dxfparser %s 2>/dev/null' % filename
        print(cmd)
        P = utils.command(cmd, shell=True)
        if P.sta == 0:
            return P.out
        else:
            return ''
    else:
        utils.warn('warn_dxf_noparser')
        return ''
Beispiel #20
0
def centerline(self,
               seedselector='pickpoint',
               sourcepoints=[],
               targetpoints=[],
               endpoints=False,
               groupcl=False,
               capping=False):
    """Compute the centerline of a surface.

    The centerline is computed using VMTK. This is very well suited for
    computing the centerlines in vascular models.

    Parameters:

    - `seedselector`: str: seed point selection method, one of
      [`pickpoint`,`openprofiles`,`carotidprofiles`,`pointlist`,`idlist`,`profileidlist`].
      Note the `pointlist` option will not use the points defined in `sourcepoints`
      and `targetpoints` as end points of the centerline, but it will look
      for the closest surface point of the open profiles. To avoid this problem with
      this option the vmtksurfacecapper is activated with option centerpoint to
      select the correct point.
    - `sourcepoints`: list: source point coordinates (flattened array-like or Coords-like array)
      for `pointlist` method or a list of point ids for `idlist` method.
    - `targetpoints`: list: flattened target point coordinates for `pointlist` method
      or a list of point ids for `idlist` method
    - `endpoints`: boolean: append source- and targetpoints to centerlines
    - `capping`: boolean: closes open profile
    - `groupcl`: boolean: if True the points of the centerlines are merged and
      grouped to avoid repeated points and separate different branches

      Note that when seedselector is `idlist`, the surface must be clenead converting
      it to a vtkPolyData using the function convert2VPD with flag clean=True and then
      converted back using convertFromVPD implemented in the vtk_itf plugin to avoid
      wrong point selection of the vmtk function.

    Returns a tuple containing a list of centerlines returned as PolyLines and a dictionary
    of additional centerlines attributes (such as maximum inscribed sphere
    used for the centerline computation, local coordinate system
    and various integers values to group the centerline points according to
    the branching). Every key contains a list of the attributes arrays grouped per centerline.
    """
    from pyformex.plugins.curve import PolyLine
    from pyformex.plugins.vtk_itf import readVTKObject, writeVTP

    tmp1 = utils.tempFile(suffix='.vtp').name
    tmp2 = utils.tempFile(suffix='.vtp').name

    print("Writing temp files %s" % tmp1)
    writeVTP(tmp1, self)

    print("Computing centerline using VMTK")
    cmds = []

    if capping or seedselector == 'pointlist':
        cmds.append(
            'vmtk vmtksurfacecapper -method centerpoint -interactive 0 -ifile %s -ofile %s'
            % (tmp1, tmp1))

    cmd = 'vmtk vmtkcenterlines -seedselector %s -ifile %s -ofile %s' % (
        seedselector, tmp1, tmp2)

    if seedselector in ['pointlist', 'idlist', 'profileidlist']:
        if not (len(sourcepoints)):
            raise ValueError(
                'sourcepoints cannot be an empty list when using seedselector= \'%s\''
                % seedselector)
        if not (len(targetpoints)) and seedselector not in ['profileidlist']:
            raise ValueError(
                'targetpoints cannot be an empty list when using seedselector= \'%s\''
                % seedselector)
        if seedselector in ['pointlist']:
            fmt = ' %f'
            sourcepoints = asarray(sourcepoints).ravel()
            targetpoints = asarray(targetpoints).ravel()
        if seedselector in ['idlist', 'profileidlist']:
            fmt = ' %i'

        if seedselector in ['pointlist']:
            seedtype = 'points'
        if seedselector in ['idlist', 'profileidlist']:
            seedtype = 'ids'

        cmd += ' -source%s' % seedtype
        cmd += fmt * len(sourcepoints) % tuple(sourcepoints)
        if len(targetpoints):
            cmd += ' -target%s' % seedtype
            cmd += fmt * len(targetpoints) % tuple(targetpoints)

    cmd += ' -endpoints %i' % endpoints

    cmds.append(cmd)

    cmds.append('vmtk vmtkcenterlineattributes -ifile %s -ofile %s\n' %
                (tmp2, tmp2))
    if groupcl:
        cmds.append(
            'vmtk vmtkbranchextractor -ifile %s -radiusarray@ MaximumInscribedSphereRadius -ofile %s\n'
            % (tmp2, tmp2))
        cmds.append(
            'vmtk vmtkcenterlinemerge -ifile %s -ofile %s -radiusarray@ MaximumInscribedSphereRadius \
        -groupidsarray@ GroupIds -centerlineidsarray@ CenterlineIds -tractidsarray@ TractIds \
        -blankingarray@ Blanking -mergeblanked 1' % (tmp2, tmp2))
    cmds.append('vmtk vmtksurfacecelldatatopointdata -ifile %s -ofile %s' %
                (tmp2, tmp2))

    for c in cmds:
        P = utils.command(c)
        if P.sta:
            print("An error occurred during the centerline computing\n %s" %
                  P.out)
            return None

    datatmp = readVTKObject(tmp2, samePlex=0)

    os.remove(tmp1)
    os.remove(tmp2)

    cls = []
    data = {}
    for icl, clids in enumerate(datatmp[0][3]):
        cls.append(PolyLine(datatmp[0][0][clids]))
        for k in datatmp[3]:
            if not (icl):  #initialize the array per every attribute
                data[k] = []
            data[k].append(datatmp[3][k][clids])

    return cls, data
Beispiel #21
0
def remesh(self,
           elementsizemode='edgelength',
           edgelength=None,
           area=None,
           areaarray=None,
           aspectratio=None,
           excludeprop=None,
           includeprop=None,
           preserveboundary=False,
           conformal='border',
           options=''):
    """Remesh a TriSurface.

    Returns the remeshed TriSurface. If the TriSurface has property numbers
    the property numbers will be inherited by the remeshed surface.

    Parameters:

    - `elementsizemode`: str: metric that is used for remeshing.
      `edgelength`, `area` and `areaarray` allow to specify a global
      target edgelength, area and areaarray (area at each node), respectively.
    - `edgelength`: float: global target triangle edgelength
    - `area`: float: global target triangle area
    - `areaarray`: array of float: nodal target triangle area
    - `aspectratio`: float: upper threshold for aspect ratio (default=1.2)
    - `includeprop`: either a single integer, or a list/array of integers.
      Only the regions with these property number(s) will be remeshed.
      This option is not compatible with `exludeprop`.
    - `excludeprop`: either a single integer, or a list/array of integers.
      The regions with these property number(s) will not be remeshed.
      This option is not compatible with `includeprop`.
    - `preserveboundary`: if True vmtk tries to keep the shape of the border.
    - `conformal`: None, `border` or `regionsborder`.
      If there is a border (ie. the surface is open) conformal=`border`
      preserves the border line (both points and connectivity); conformal=`regionsborder`
      preserves both border line and lines between regions with different property numbers.
    
    Detected BUGS:
    
    - preserveboundary = True
    
        With VMTK 1.3 and VTK6 there is a bug: if surface has a boundary (is not closed) and you want preserveboundary=False you can an error:
        python: /build/vtk6-E5SYwm/vtk6-6.3.0+dfsg1/Common/Core/vtkDataArrayTemplate.h:191: T vtkDataArrayTemplate<T>::GetValue(vtkIdType) [with T = int; vtkIdType = long long int]: Assertion `id >= 0 && id < this->Size' failed.
        Aborted
    
        As a workaround, you can
        - either close the surface (so there is no boundary, and preserveboundary will be ignored) 
        - or add some extensions (with different property number) to the borders and use preserveboundary=True
        After remeshing you can clip the added parts using their property number.
    """
    if includeprop is not None:
        if excludeprop is not None:
            raise ValueError('you cannot use both excludeprop and includeprop')
        else:
            ps = self.propSet()
            mask = in1d(ar1=ps, ar2=checkArray1D(includeprop))
            if sum(mask) == 0:
                utils.warn("warn_vmtk_includeprop", data=(includeprop, ps))
                return self
            excludeprop = ps[~mask]
    if conformal == 'border' or conformal == 'regionsborder':
        if elementsizemode == 'areaarray':
            raise ValueError(
                'conformal (regions)border and areaarray cannot be used together (yet)!'
            )  #conformalBorder alters the node list. Afterwards, the nodes do not correspond with pointdata.
        if self.isClosedManifold() == False:
            if conformal == 'regionsborder':
                if self.propSet() is not None:
                    if len(self.propSet()) > 1:
                        return TriSurface.concatenate([
                            remesh(s2,
                                   elementsizemode=elementsizemode,
                                   edgelength=edgelength,
                                   area=area,
                                   areaarray=None,
                                   aspectratio=aspectratio,
                                   excludeprop=excludeprop,
                                   preserveboundary=preserveboundary,
                                   conformal='border')
                            for s2 in self.splitProp()
                        ])
            added = TriSurface(
                self.getBorderMesh().convert('line3').setType('tri3'))
            s1 = self + added.setProp(-1) + added.setProp(
                -2)  #add triangles on the border
            s1 = s1.fuse().compact().renumber(
            )  #this would mix up the areaarray!!
            excludeprop1 = array([-1, -2])
            if excludeprop is not None:
                excludeprop1 = append(excludeprop1,
                                      asarray(excludeprop).reshape(-1))
            return remesh(s1,
                          elementsizemode=elementsizemode,
                          edgelength=edgelength,
                          area=area,
                          areaarray=None,
                          aspectratio=aspectratio,
                          excludeprop=excludeprop1,
                          preserveboundary=preserveboundary,
                          conformal=None).cselectProp([-1, -2]).compact()
    else:
        if conformal is not None:
            raise ValueError(
                'conformal should be either None, border or regionsborder')

    from pyformex.plugins.vtk_itf import writeVTP, checkClean, readVTKObject
    tmp = utils.tempFile(suffix='.vtp').name
    tmp1 = utils.tempFile(suffix='.vtp').name
    fielddata, celldata, pointdata = {}, {}, {}
    cmd = 'vmtk vmtksurfaceremeshing -ifile %s -ofile %s' % (tmp, tmp1)
    if elementsizemode == 'edgelength':
        if edgelength is None:
            self.getElemEdges()
            E = Mesh(self.coords, self.edges, eltype='line2')
            edgelength = E.lengths().mean()
        cmd += ' -elementsizemode edgelength -edgelength %f' % edgelength
    elif elementsizemode == 'area':
        if area is None:
            area = self.areas().mean()
        cmd += ' -elementsizemode area -area %f' % area
    elif elementsizemode == 'areaarray':
        if not checkClean(self):
            raise ValueError(
                "Mesh is not clean: vtk will alter the node numbering and the areaarray will not correspond to the node numbering. To clean: mesh.fuse().compact().renumber()"
            )
        cmd += ' -elementsizemode areaarray -areaarray nodalareas '
        pointdata['nodalareas'] = areaarray
    if aspectratio is not None:
        cmd += ' -aspectratio %f' % aspectratio
    if excludeprop is not None:
        cmd += ' -exclude ' + ' '.join([
            '%d' % i for i in checkArray1D(excludeprop, kind='i', allow=None)
        ])
    if preserveboundary:
        cmd += ' -preserveboundary 1'
    if self.prop is not None:
        cmd += ' -entityidsarray prop'
    print("Writing temp file %s" % tmp)
    cmd += ' %s' % options

    writeVTP(mesh=self, fn=tmp, pointdata=pointdata)
    print("Remeshing with command\n %s" % cmd)
    P = utils.command(cmd)
    os.remove(tmp)
    if P.sta:
        print("An error occurred during the remeshing.")
        print(P.out)
        return None
    [coords, cells, polys, lines,
     verts], fielddata, celldata, pointdata = readVTKObject(tmp1)
    S = TriSurface(coords, polys)
    if self.prop is not None:
        S = S.setProp(celldata['prop'])
    os.remove(tmp1)
    return S
Beispiel #22
0
def createCalixInput():
    """Write the Calix input file."""

    checkWorkdir()
    if not checkModel():
        return

    # ask job name from user
    res = askItems([
        _I('jobname', feresult_name.next(), text='Job Name'),
        _I('header', 'A Calix example', text='Header Text'),
        _I(
            'zem',
            '3',
            text='ZEM control',
            itemtype='radio',
            choices=['0', '3', '6'],
        ),
    ])
    if not res:
        return

    jobname = res['jobname']
    header = res['header']
    nzem = int(res['zem'])
    if not jobname:
        print("No Job Name: writing to sys.stdout")
        jobname = None

    filnam = jobname + '.dta'
    print("Writing calix data file %s in %s" % (filnam, os.getcwd()))
    fil = open(filnam, 'w')

    nnodes = model.coords.shape[0]
    nelems = model.celems[-1]
    nplex = [e.shape[1] for e in model.elems]
    if min(nplex) != max(nplex):
        print([e.shape for e in model.elems])
        warning("All parts should have same element type")
        return
    nodel = nplex[0]

    # Get materials
    secprops = PDB.getProp(kind='e', attr=['section'])
    print(secprops)
    # need E, nu, thickness, rho
    mats = array([[
        sec.young_modulus,
        sec.poisson_ratio,
        sec.thickness,
        sec.density,
    ] for sec in secprops])
    matnr = zeros(nelems, dtype=int32)
    for i, mat in enumerate(secprops):  # proces in same order as above!
        matnr[mat.set] = i + 1
    print(matnr)
    nmats = mats.shape[0]

    # Header
    fil.write("""; calix data file generated by %s
; jobname=%s
start: %s
;use cmdlog 'calix.log'
;use for messages cmdlog
file open 'femodel.tmp' write da 1
yes cmdlog
;yes debug
use for cmdlog output
femodel elast stress 2
use for cmdlog cmdlog
;-----------------------------------------
; Aantal knopen:   %s
; Aantal elementen:   %s
; Aantal materialen:     %s
; Aantal belastingsgevallen: %s
""" % (pf.Version(), jobname, header, nnodes, nelems, nmats, nsteps))
    # Nodal coordinates
    fil.write(""";-----------------------------------------
; Knopen
;--------
nodes coord %s 1
""" % nnodes)
    fil.write('\n'.join([
        "%5i%10.2f%10.2f" % (i, x[0], x[1])
        for i, x in zip(arange(nnodes) + 1, model.coords)
    ]))
    fil.write('\n\n')
    # Boundary conditions
    fil.write(""";-----------------------------------------
; Verhinderde verplaatsingen
;-------------------------
bound bcon
plane
""")
    for p in PDB.getProp(kind='n', attr=['bound']):
        bnd = "%5i" + "%5i" * 2 % (p.bound[0], p.bound[1])
        if p.set is None:
            nod = arange(model.nnodes)
        else:
            nod = array(p.set)
        fil.write('\n'.join([bnd % i for i in nod + 1]))
        fil.write('\n')
    fil.write('\n')
    fil.write("""print bcon 3
                           $$$$$$$$$$$$$$$$$$$$$$$
                           $$      D O F S      $$
                           $$$$$$$$$$$$$$$$$$$$$$$
""")

    # Materials
    fil.write(""";-----------------------------------------
; Materialen
;-----------
array mat    %s 4
""" % len(mats))
    print(mats)
    fil.write('\n'.join(["%.4e " * 4 % tuple(m) for m in mats]))
    fil.write('\n\n')
    fil.write("""print mat 3
                           $$$$$$$$$$$$$$$$$$$$$$$
                           $$ M A T E R I A L S $$
                           $$$$$$$$$$$$$$$$$$$$$$$
""")

    # Elements
    for igrp, grp in enumerate(model.elems):
        nelems, nplex = grp.shape
        fil.write(""";-----------------------------------------
; Elementen
;----------
elements elems-%s matnr-%s  %s %s 1
""" % (igrp, igrp, nplex, nelems))
        fil.write('\n'.join([
            "%5i" * (nplex + 2) % tuple([i, 1] + e.tolist())
            for i, e in zip(arange(nelems) + 1, grp + 1)
        ]))
        fil.write('\n\n')
        fil.write("""plane plane-%s coord bcon elems-%s matnr-%s 2 2
""" % (igrp, igrp, igrp))

    #########################
    # Nodal Loads
    cloads = [p for p in PDB.getProp('n', attr=['cload'])]
    fil.write("""text 3 1
                           $$$$$$$$$$$$$$$$$$$$
                           $$  NODAL  LOADS  $$
                           $$$$$$$$$$$$$$$$$$$$
loads f bcon 1
""")
    if len(cloads) > 0:
        for p in cloads:
            loadcase = loadcaseFromTag(p)
            if p.set is None:
                nodeset = arange(calpyModel.nnodes)
            else:
                nodeset = p.set
            F = [0.0, 0.0]
            for i, v in p.cload:
                if i in [0, 1]:
                    F[i] = v
            fil.write(''.join([
                "%5i%5i%10.2f%10.2f\n" % (n + 1, loadcase, F[0], F[1])
                for n in nodeset
            ]))
    fil.write('\n')

    #########################
    # Distributed loads
    eloads = [p for p in PDB.getProp('e', attr=['eload'])]
    if len(eloads) > 0:
        fil.write("""text 4 1
                           $$$$$$$$$$$$$$$$$$$$$$$$$$
                           $$  BOUNDARY  ELEMENTS  $$
                           $$$$$$$$$$$$$$$$$$$$$$$$$$
   elem  loadnr  localnodes
""")
        # get the data from database, group by group
        for igrp in range(len(model.elems)):
            geloads = [p for p in eloads if p.group == igrp]
            neloads = len(geloads)
            loaddata = []
            fil.write("array randen integer   %s 4 0 1\n" % neloads)
            i = 1
            for p in geloads:
                loadcase = loadcaseFromTag(p)
                xload = yload = 0.
                if p.label == 'x':
                    xload = p.value
                elif p.label == 'y':
                    yload = p.value
                # Save the load data for later
                loaddata.append((i, loadcase, xload, yload))
                # Because of the way we constructed the database, the set will
                # contain only one element, but let's loop over it anyway in
                # case one day we make the storage more effective
                for e in p.set:
                    fil.write(("%5s" * 4 + "\n") % (e + 1, i, p.edge + 1,
                                                    (p.edge + 1) % 4 + 1))
                i += 1
            fil.write("""print randen
tran randen tranden
boundary  rand-%s coord bcon elems-%s matnr-%s tranden 1
""" % ((igrp, ) * 3))
            fil.write("""text 3 1
                           $$$$$$$$$$$$$$$$$$$$$$$
                           $$  BOUNDARY  LOADS  $$
                           $$$$$$$$$$$$$$$$$$$$$$$
loadvec boundary rand-%s f 1
""" % igrp)
            for eload in loaddata:
                fil.write("%5s%5s%10s%10s\n" % eload)
            fil.write('\n')

    #########################
    # Print total load vector
    fil.write("""
print f 3
                           $$$$$$$$$$$$$$$$$$$$
                           $$  LOAD  VECTOR  $$
                           $$$$$$$$$$$$$$$$$$$$
;
""")
    # Assemble
    for igrp in range(len(model.elems)):
        fil.write("assemble plane-%s mat s 0 0 0 %s\n" % (igrp, nzem))

    # Solve and output
    fil.write(""";------------------------------------------------solve+output
flavia mesh '%s.flavia.msh' %s
flavia nodes coord
""" % (jobname, nplex))
    for igrp in range(len(model.elems)):
        fil.write("flavia elems elems-%s matnr-%s %s\n" % (igrp, igrp, nplex))
    fil.write("flavia results '%s.flavia.res'\n" % jobname)
    fil.write("""
solbnd s f
delete s
text named 1
"Displacement" "Elastic Analysis"
text typed 1
Vector OnNodes
text names 1
"Stress" "Elastic Analysis"
text types 1
Matrix OnNodes
intvar set 1 1
loop 1
  displ f bcon displ $1 1
  tran displ disp
  flavia result named typed disp $1
""")
    for igrp in range(len(model.elems)):
        fil.write("""
  stress plane-%s mat f stresg $1 1
  gp2nod plane-%s stresg strese 0 1
  nodavg plane-%s elems-%s strese stren nval 1
  tran stren stre
  flavia result names types stre $1
""" % ((igrp, ) * 4))
    fil.write("""
  intvar add 1 1
next
stop
""")

    # Done: Close data file
    fil.close()
    showFile(filnam, mono=True)

    if ack("Shall I run the Calix analysis?"):
        # Run the analysis
        outfile = utils.changeExt(filnam, 'res')
        cmd = "calix %s %s" % (filnam, outfile)
        utils.command(cmd)
        showFile(outfile, mono=True)

        if ack("Shall I read the results for postprocessing?"):
            from pyformex.plugins import flavia
            meshfile = utils.changeExt(filnam, 'flavia.msh')
            resfile = utils.changeExt(filnam, 'flavia.res')
            DB = flavia.readFlavia(meshfile, resfile)
            postproc_menu.setDB(DB)
            export({name: DB})
            if showInfo(
                    "The results have been exported as %s\nYou can now use the postproc menu to display results"
                    % name,
                    actions=['Cancel', 'OK']) == 'OK':
                postproc_menu.selection.set(name)
                postproc_menu.selectDB(DB)
                postproc_menu.open_dialog()