Пример #1
0
    def __init__(self,kind=None,keys=None,set=None,type='FIELD',variable='PRESELECT',extra='',**options):
        """ Create new output request.

        - `type`: 'FIELD' or 'HISTORY'
        - `kind`: None, 'NODE', or 'ELEMENT' (first character suffices)
        - `extra`: an extra string to be added to the command line. This
          allows to add Abaqus options not handled by this constructor.
          The string will be appended to the command line preceded by a comma.

        For kind=='':

          - `variable`: 'ALL', 'PRESELECT' or ''
          
        For kind=='NODE' or 'ELEMENT':

          - `keys`: a list of output identifiers (compatible with kind type)
          - `set`: a single item or a list of items, where each item is either
            a property number or a node/element set name for which the results
            should be written. If no set is specified, the default is 'Nall'
            for kind=='NODE' and 'Eall' for kind='ELEMENT'
        """
        if 'history' in options:
            GD.warning("The `history` argument in an output request is deprecated.\nPlease use `type='history'` instead.")
        if 'numberinterval' in options:
            GD.warning("The `numberinterval` argument in an output request is deprecated.\nPlease use the `extra` argument instead.")

        if kind:
            kind = kind[0].upper()
        if set is None:
            set = "%sall" % kind
        Dict.__init__(self,{'kind':kind})
        if kind is None:
            self.update({'type':type,'variable':variable,'extra':extra})
        else:
            self.update({'keys':keys,'set':set})
Пример #2
0
def createMovieInteractive():
    """Create a movie from a saved sequence of images.

    """
    if not image.multisave:
        pf.warning('You need to start multisave mode first!')
        return

    names = image.multisave[0]
    glob = names.glob()

    res = draw.askItems(
        [ _I('files', glob),
          _I('encoder', choices=['mencoder', 'convert', 'ffmpeg']),
          _G('Mencoder', [
              _I('fps', 10),
              _I('vbirate', 800),
              ]),
          _G('Convert', [
              _I('delay', 1),
              _I('colors', 256),
              ]),
          ],
        enablers = [
            ('encoder', 'mencoder', 'Mencoder'),
            ('encoder', 'convert', 'Convert'),
          ])
    if not res:
        return

    pf.GUI.setBusy()
    image.createMovie(**res)
    pf.GUI.setBusy(False)
Пример #3
0
    def okColor(self, color, colormap=None):
        """Compute a color usable by the shader.

        The shader (currently) only supports 3*float type of colors:

        - None
        - single color (separate for front and back faces)
        - vertex colors
        """
        if isinstance(color, str):
            if color == 'prop' and hasattr(self.object, 'prop'):
                color = self.object.prop
            elif color == 'random':
                # create random colors
                color = np.random.rand(self.object.nelems(), 3)
            elif color.startswith('fld:'):
                # get colors from a named field
                fld = self.object.getField(color[4:])
                if fld and fld.fldtype == 'node':
                    color = fld.data
                    colormap = None
                else:
                    pf.warning("Could not set color from field %s" % color)

        color, colormap = saneColorSet(color, colormap, self.fcoords.shape)

        if color is not None:
            if color.dtype.kind == 'i':
                # We have a color index
                if colormap is None:
                    colormap = np.array(colors.palette)
                color = colormap[color]

        return color
Пример #4
0
def createMovie(encoder='ffmpeg'):
    """Create a movie from a saved sequence of images.

    encoder is one of: 'ffmpeg, mencoder, convert'
    """
    if not multisave:
        pf.warning('You need to start multisave mode first!')
        return

    names,format,quality,window,border,hotkey,autosave,rootcrop = multisave
    glob = names.glob()
    ## if glob.split('.')[-1] != 'jpg':
    ##     pf.warning("Currently you need to save in 'jpg' format to create movies")
    ##     return

    if encoder == 'convert':
        cmd = "convert -delay 1 -colors 256 %s output.gif" % names.glob()
    elif encoder == 'mencoder':
        cmd = "mencoder -ovc lavc -fps 5 -o output.avi %s" % names.glob()
    elif encoder == 'mencoder1':
        cmd = "mencoder \"mf://%s\" -mf fps=10 -o output1.avi -ovc lavc -lavcopts vcodec=msmpeg4v2:vbitrate=800" % names.glob()
    else:
        cmd = "ffmpeg -qscale 1 -r 1 -i %s output.mp4" % names.glob()
    pf.debug(cmd)
    utils.runCommand(cmd)
Пример #5
0
def createMovieInteractive():
    """Create a movie from a saved sequence of images.

    """
    if not image.multisave:
        pf.warning('You need to start multisave mode first!')
        return

    names = image.multisave[0]
    glob = names.glob()

    res = draw.askItems(
        [ _I('files',glob),
          _I('encoder',choices=['mencoder','convert','ffmpeg']),
          _G('Mencoder',[
              _I('fps',10),
              _I('vbirate',800),
              ]),
          _G('Convert',[
              _I('delay',1),
              _I('colors',256),
              ]),
          ],
        enablers = [
            ('encoder','mencoder','Mencoder'),
            ('encoder','convert','Convert'),
          ])
    if not res:
        return

    pf.GUI.setBusy()
    image.createMovie(**res)
    pf.GUI.setBusy(False)
Пример #6
0
def submitJob(srcdir,tgtdir,include=[],delete_old=True):
    """Submit a cluster job in srcdir to the tgtdir.

    This will copy the specified include files from srcdir to the tgtdir,
    making sure that a file '*.request' is only copied after all other files
    have been copied.
    If no includes are given, all files in the srcdir are copied.

    For example, to submit a simple abaqus job from a folder with
    multiple job files, you can do::

      submitJob('myjobdir','bumpfs1:bumper/requests/jobname',include=['*.inp'])

    To submit a job having its own input folder equal to the job name, do::

      submitJob('myjobdir/jobname','bumpfs1:bumper/requests/jobname')

    """
    if delete_old:
        P = rsyncFiles(srcdir,tgtdir,include=[],exclude=['*'],exclude_first=True,opts=' -rv --delete --delete-excluded')
        if P.sta:
            pf.warning("Could not delete old files from request folder!")

    if include:
        P = rsyncFiles(srcdir,tgtdir,include=include,exclude=['*'])
    else:
        P = rsyncFiles(srcdir,tgtdir,exclude=['*.request'],include=include,exclude_first=True)
    if P.sta:
        print(P.out)
    else:
        P = rsyncFiles(srcdir,tgtdir,include=['*.request'],exclude=['*'])
    if P.sta:
        pf.warning("Some error occurred during file transfer!")
Пример #7
0
    def readAttrib(self,attrib=None,**kargs):
        """Read an Attributes dict defined on the last read geometry.

        """
        try:
            self.geometry.attrib(**attrib)
        except:
            # Attributes readback may produce an error with
            # complex data types, e.g. vertex color array
            pf.warning("GeometryFile.read: Error while reading an Attribute block. The current version does not support the readback of some complex attribute data types (like a vertex color array). All attributes in this block will be skipped.")
Пример #8
0
def openProject(fn=None,exist=False,access=['wr','rw','w','r'],default=None):
    """Open a (new or old) Project file.

    A dialog is presented to ask the user for a Project file name and the
    access modalities. The parameters help in setting sensible defaults
    for the user and in delimiting his options.
    Depending on he results of the dialog, either a new project is created or
    an old one is opened, or nothing is done.
    If a project is opened, it is returned, else the return value is None.

    Parameters:

    - `fn`: filename: if specified, the Project file dialog will start with
      the specified file, otherwise it will start in the current directory.
    - `exist`: boolean: if False (default), the user can create new project
      files as well as open existing ones. Use exist=True or
      :func:`openExistingProject` to only accept existing project files.
    - `access`: a list of :class:`Project` access modes to be presented to
      the user.
    - `default`: the access mode that is presented as default to the user.
      If not specified, the first option of `access` will be the default.
    """
    if type(access) == str:
        access = [access]
    cur = fn if fn else '.'
    typ = utils.fileDescription(['pyf','all'])
    res = widgets.ProjectSelection(cur,typ,exist=exist,access=access,default=default,convert=True).getResult()
    if not res:
        return

    fn = res.fn
    if not fn.endswith('.pyf'):
        fn += '.pyf'
    access = res.acc
    compression = res.cpr
    convert = res.cvt
    signature = pf.fullVersion()

    # OK, we have all data, now create/open the project
    pf.message("Opening project %s" % fn)
    pf.GUI.setBusy() # loading  may take a while
    try:
        proj = project.Project(fn,access=access,convert=convert,signature=signature,compression=compression)
        if proj.signature != signature:
            pf.warning("The project was written with %s, while you are now running %s. If the latter is the newer one, this should probably not cause any problems. Saving is always done in the current format of the running version. Save your project and this message will be avoided on the next reopening." % (proj.signature,signature))
    except:
        proj = None
        raise
    finally:
        pf.GUI.setBusy(False)

    proj.hits = 0
    pf.debug("START COUNTING HITS",pf.DEBUG.PROJECT)
    return proj
Пример #9
0
def openProject(fn=None,exist=False,access=['wr', 'rw', 'w', 'r'],default=None):
    """Open a (new or old) Project file.

    A dialog is presented to ask the user for a Project file name and the
    access modalities. The parameters help in setting sensible defaults
    for the user and in delimiting his options.
    Depending on he results of the dialog, either a new project is created or
    an old one is opened, or nothing is done.
    If a project is opened, it is returned, else the return value is None.

    Parameters:

    - `fn`: filename: if specified, the Project file dialog will start with
      the specified file, otherwise it will start in the current directory.
    - `exist`: boolean: if False (default), the user can create new project
      files as well as open existing ones. Use exist=True or
      :func:`openExistingProject` to only accept existing project files.
    - `access`: a list of :class:`Project` access modes to be presented to
      the user.
    - `default`: the access mode that is presented as default to the user.
      If not specified, the first option of `access` will be the default.
    """
    if isinstance(access, str):
        access = [access]
    cur = fn if fn else '.'
    res = widgets.ProjectSelection(cur, ['pyf', 'all'], exist=exist, access=access, default=default, convert=True).getResults()
    if not res:
        return

    fn = res.fn
    if not fn.endswith('.pyf'):
        fn += '.pyf'
    access = res.acc
    compression = res.cpr
    convert = res.cvt
    signature = pf.fullVersion()

    # OK, we have all data, now create/open the project
    print("Opening project %s" % fn)
    pf.GUI.setBusy() # loading  may take a while
    try:
        proj = project.Project(fn, access=access, convert=convert, signature=signature, compression=compression)
        if proj.signature != signature:
            pf.warning("The project was written with %s, while you are now running %s. If the latter is the newer one, this should probably not cause any problems. Saving is always done in the current format of the running version. Save your project and this message will be avoided on the next reopening." % (proj.signature, signature))
    except:
        proj = None
        raise
    finally:
        pf.GUI.setBusy(False)

    proj.hits = 0
    pf.debug("START COUNTING HITS", pf.DEBUG.PROJECT)
    return proj
Пример #10
0
def check(trypaths=None):
    """Warn the user that calpy was not found."""
    if calpy_path is None:
        detect(trypaths)

    try:
        import calpy
    except ImportError:
        pass
    
    if not utils.hasModule('calpy',check=True):
        GD.warning("sys.path=%s\nSorry, I can not run this example, because you do not have calpy installed (at least not in a place where I can find it)." % sys.path)
        exit()
Пример #11
0
    def write(self, geom, name=None, sep=None):
        """Write any geometry object to the geometry file.

        `geom` is one of the Geometry data types of pyFormex or a list
        or dict of such objects.
        It can also be a WebGL objdict.
        Currently exported geometry objects are
        :class:`Coords`, :class:`Formex`, :class:`Mesh`,
        :class:`PolyLine`, :class:`BezierSpline`.
        The geometry object is written to the file using the specified
        separator, or the default.
        """
        self.checkWritable()
        if isinstance(geom, dict):
            for name in geom:
                self.write(geom[name], name, sep)
        elif isinstance(geom, list):
            if name is None:
                for obj in geom:
                    if hasattr(obj, 'obj'):
                        #This must be a WebGL object dict
                        self.writeDict(obj, sep=sep)
                    else:
                        if hasattr(obj, 'name'):
                            objname = obj.name
                        else:
                            objname = None
                        self.write(obj, objname, sep)
            else:
                name = utils.NameSequence(name)
                for obj in geom:
                    self.write(obj, name.next(), sep)

        elif hasattr(geom, 'write_geom'):
            geom.write_geom(self, name, sep)
        else:
            try:
                writefunc = getattr(self, 'write' + geom.__class__.__name__)
            except:
                warning(
                    "Can not (yet) write objects of type %s to geometry file: skipping"
                    % type(geom))
                return
            try:
                writefunc(geom, name, sep)
            except:
                warning(
                    "Error while writing objects of type %s to geometry file: skipping"
                    % type(geom))
                raise
Пример #12
0
    def addScene(self,name=None,camera=True):
        """Add the current OpenGL scene to the WebGL model.

        This method adds all the geometry in the current viewport to
        the WebGL model. By default it will also add the current camera
        and export the scene as a completed WebGL model with the given
        name.

        Parameters:

        - `name`: a string with the name of the model for the current
          scene. When multiple scenes are exported, they will be identified
          by this name. This name is also used as the basename for the
          exported geometry files. For a single scene export, the name may
          be omitted, and will then be set equal to the name of the WebGL
          exporter. If no name is specified, the model is not exported.
          This allows the user to add more scenes to the same model, and
          then to explicitely export it with :func:`exportScene`.
        - `camera`: bool or dict : if True, sets the current viewport camera as the
          camera in the WebGL model. If False the default camera values of WebGL
          will be used. If dict the camera values will be taken from the dictionary.
        """
        self._actors = List()
        self._gui = []

        self.bgcolor = pf.canvas.settings.bgcolor
        print("Exporting %s actors from current scene" % len(pf.canvas.actors))
        sorted_actors = [ a for a in pf.canvas.actors if a.opak ] + [ a for a in pf.canvas.actors if not a.opak ]
        for i, a in enumerate(sorted_actors):
            o = a.object
            atype = type(a).__name__
            otype = type(o).__name__
            pf.debug("Actor %s: %s %s Shape=(%s,%s) Color=%s"% (i, atype, otype, o.nelems(), o.nplex(), a.color), pf.DEBUG.WEBGL)
            self.addActor(a)

        if camera is True:
            ca = pf.canvas.camera
            print(ca.report())
            if not np.allclose(ca.area,((0.,0.),(1.,1.))):
                pf.warning("You current display uses soft zooming. The exported WebGL model currently does not have that feature, so the displayed area may be different from the pyFormex view.\nTo create a pyFormex display without soft zooming, use Camera->ZoomAll and the zoom in or out using only the Camera->DollyIn and/or Camera->Dolly/Out.")
            self.setCamera(focus=ca.focus, position=ca.eye, up=ca.upvector)
        elif camera is False:
            self._camera = None
        else:
            self.setCamera(**camera)

        if name:
            self.exportScene(name)
Пример #13
0
def checkImageFormat(fmt,verbose=False):
    """Checks image format; if verbose, warn if it is not.

    Returns the image format, or None if it is not OK.
    """
    GD.debug("Format requested: %s" % fmt)
    GD.debug("Formats available: %s" % imageFormats())
    if fmt in imageFormats():
        if fmt == 'tex' and verbose:
            GD.warning("This will only write a LaTeX fragment to include the 'eps' image\nYou have to create the .eps image file separately.\n")
        return fmt
    else:
        if verbose:
            error("Sorry, can not save in %s format!\n"
                  "I suggest you use 'png' format ;)"%fmt)
        return None
Пример #14
0
def createMovie():
    """Create a movie from a saved sequence of images."""
    if not multisave:
        GD.warning('You need to start multisave mode first!')
        return

    names,format,window,border,hotkey,autosave,rootcrop = multisave
    glob = names.glob()
    if glob.split('.')[-1] != 'jpg':
        GD.warning("Currently you need to save in 'jpg' format to create movies")
        return
    
    #cmd = "mencoder -ovc lavc -fps 5 -o output.avi %s" % names.glob()
    cmd = "ffmpeg -r 1 -i %s output.mp4" % names.glob()
    GD.debug(cmd)
    utils.runCommand(cmd)
Пример #15
0
def check(trypaths=None):
    """Warn the user that calpy was not found."""
    if calpy_path is None:
        detect(trypaths)

    try:
        import calpy
    except ImportError:
        pass

    if utils.hasModule('calpy', check=True):
        return True
    else:
        pf.warning(
            "sys.path=%s\nSorry, I can not run this example, because you do not have calpy installed (at least not in a place where I can find it)."
            % sys.path)
        return False
Пример #16
0
    def write(self,geom,name=None,sep=None):
        """Write any geometry object to the geometry file.

        `geom` is one of the Geometry data types of pyFormex or a list
        or dict of such objects.
        It can also be a WebGL objdict.
        Currently exported geometry objects are
        :class:`Coords`, :class:`Formex`, :class:`Mesh`,
        :class:`PolyLine`, :class:`BezierSpline`.
        The geometry object is written to the file using the specified
        separator, or the default.
        """
        self.checkWritable()
        if isinstance(geom,dict):
            for name in geom:
                self.write(geom[name],name,sep)
        elif isinstance(geom,list):
            if name is None:
                for obj in geom:
                    if hasattr(obj,'obj'):
                        #This must be a WebGL object dict
                        self.writeDict(obj,sep=sep)
                    else:
                        if hasattr(obj,'name'):
                            objname = obj.name
                        else:
                            objname = None
                        self.write(obj,objname,sep)
            else:
                name = utils.NameSequence(name)
                for obj in geom:
                    self.write(obj,name.next(),sep)

        elif hasattr(geom,'write_geom'):
            geom.write_geom(self,name,sep)
        else:
            try:
                writefunc = getattr(self,'write'+geom.__class__.__name__)
            except:
                warning("Can not (yet) write objects of type %s to geometry file: skipping" % type(geom))
                return
            try:
                writefunc(geom,name,sep)
            except:
                warning("Error while writing objects of type %s to geometry file: skipping" % type(geom))
                raise
Пример #17
0
    def addMaterial(self, material):
        """Create or replace the material properties of the element.

        If the argument is a dict, it will be added to the global MaterialDB.
        If the argument is a string, this string will be used as a key to
        search in the global MaterialDB.
        """
        if isinstance(material, str) :
            if material in _matDB:
                self.material = _matDB[material] 
            else:
                pf.warning("Material '%s'  is not in the database" % material)
        elif isinstance(material, dict):
            _matDB[material['name']] = CDict(material)
            self.material = _matDB[material['name']]
        elif material==None:
            self.material=material
        else:
            raise ValueError,"Expected a string or a dict"
Пример #18
0
def checkImageFormat(fmt, verbose=True):
    """Checks image format; if verbose, warn if it is not.

    Returns the image format, or None if it is not OK.
    """
    pf.debug("Format requested: %s" % fmt, pf.DEBUG.IMAGE)
    pf.debug("Formats available: %s" % imageFormats(), pf.DEBUG.IMAGE)
    if fmt in imageFormats():
        if fmt == 'tex' and verbose:
            pf.warning(
                "This will only write a LaTeX fragment to include the 'eps' image\nYou have to create the .eps image file separately.\n"
            )
        return fmt
    else:
        if verbose:
            import draw
            draw.error("Sorry, can not save in %s format!\n"
                       "I suggest you use 'png' format ;)" % fmt)
        return None
Пример #19
0
    def addMaterial(self, material):
        """Create or replace the material properties of the element.

        If the argument is a dict, it will be added to the global MaterialDB.
        If the argument is a string, this string will be used as a key to
        search in the global MaterialDB.
        """
        if isinstance(material, str) :
            if material in _matDB:
                self.material = _matDB[material]
            else:
                pf.warning("Material '%s'  is not in the database" % material)
        elif isinstance(material, dict):
            _matDB[material['name']] = CDict(material)
            self.material = _matDB[material['name']]
        elif material is None:
            self.material=material
        else:
            raise ValueError("Expected a string or a dict")
Пример #20
0
def checkPrintSyntax(filename):
    """Check whether the script in the given files uses print function syntax.

    Returns the compiled object if no error was found during compiling.
    Returns the filename if an error was found and correction has been
    attempted.
    Raises an exception if an error is found and no correction attempted.
    """
    with open(filename, 'r') as f:
        try:
            script = f.read()
            scr = compile(script, filename, 'exec')
            return scr
        except SyntaxError as err:
            if re.compile('.*print +[^ (]').match(err.text):
                ans = pf.warning(
                    """..

Syntax error in line %s of %s::

  %s

It looks like your are using a print statement instead of the print function.
In order to prepare you for the future (Python3), pyFormex already enforces
the use of the print function.
This means that you have to change any print statement from::

    print something

into a print function call::

    print(something)

You can try an automatic conversion with the command::

    2to3 -f print -%s

If you want, I can run this command for you now. Beware though!
This will overwrite the contents of file %s.

Also, the automatic conversion is not guaranteed to work, because
there may be other errors.
""" % (err.lineno, err.filename, err.text, filename, filename),
                    actions=['Not this time', 'Convert now'],
                )
                if ans == 'Convert now':
                    print(ans)
                    if convertPrintSyntax(filename):
                        print(
                            "Script properly converted, now running the converted script"
                        )
                        return filename
                raise
Пример #21
0
def toggleAppScript():
    import apps
    appname = pf.cfg['curfile']
    if utils.is_script(appname):
        appdir = apps.findAppDir(os.path.dirname(appname))
        if appdir:
            appname = os.path.basename(appname)
            if appname.endswith('.py'):
                appname = appname[:-3]
            pkgname = appdir.pkg
            appname = "%s.%s" % (pkgname,appname)
            pf.GUI.setcurfile(appname)
        else:
            pf.warning("This script is not in an application directory.\n\nYou should add the directory path '%s' to the application paths before you can run this file as an application.")

    else:
        fn = apps.findAppSource(appname)
        if os.path.exists(fn):
            pf.GUI.setcurfile(fn)
        else:
            pf.warning("I can not find the source file for this application.")
Пример #22
0
def editPreferences():
    """Edit the preferences file

    This allows the user to edit all his stored preferences through his
    normal editor. The current preferences are saved to the user preferences
    file before it is loaded in the editor. When the user saves the
    preferences file, the stored preferences will be reloaded into
    pyFormex. This will remain active until the user selects the
    'File->Save Preferences Now' option from the GUI.
    """
    from ..main import savePreferences
    if pf.preffile is None:
        pf.warning("You have no writable preferences file")
        return

    if not savePreferences():
        if pf.warning("Could not save to preferences file %s\nEdit the file anyway?" % pf.preffile) == 'Cancel':
            return

    pf.GUI.filewatch.addWatch(pf.preffile, reloadPreferences)
    P = draw.editFile(pf.preffile)
Пример #23
0
    def addSection(self, section):
        """Create or replace the section properties of the element.

        If 'section' is a dict, it will be added to the global SectionDB.
        If 'section' is a string, this string will be used as a key to
        search in the global SectionDB.
        """
        if isinstance(section, str):
            if section in _secDB:
                self.section = _secDB[section]
            else:
                pf.warning("Section '%s' is not in the database" % section)
        elif isinstance(section, dict):
            # WE COULD ADD AUTOMATIC CALCULATION OF SECTION PROPERTIES
            #self.computeSection(section)
            #print(section)
            _secDB[section['name']] = CDict(section)
            self.section = _secDB[section['name']]
        elif section is None:
            self.section = section
        else:
            raise ValueError("Expected a string or a dict")
Пример #24
0
    def addSection(self, section):
        """Create or replace the section properties of the element.

        If 'section' is a dict, it will be added to the global SectionDB.
        If 'section' is a string, this string will be used as a key to
        search in the global SectionDB.
        """
        if isinstance(section, str):
            if section in _secDB:
                self.section = _secDB[section]
            else:
                pf.warning("Section '%s' is not in the database" % section)
        elif isinstance(section,dict):
            # WE COULD ADD AUTOMATIC CALCULATION OF SECTION PROPERTIES
            #self.computeSection(section)
            #print(section)
            _secDB[section['name']] = CDict(section)
            self.section = _secDB[section['name']]
        elif section==None:
            self.section = section
        else: 
            raise ValueError,"Expected a string or a dict"
Пример #25
0
    def writeGeometry(self,geom,name=None,sep=None):
        """Write a single Geometry object to the Geometry File.

        Writes a single Geometry object to the Geometry File, using the
        specified name and separator.

        Parameters:

        - `geom`: a supported Geometry type object.
          Currently supported Geometry objects are
          :class:`Coords`,
          :class:`Formex`,
          :class:`Mesh`,
          :class:`PolyLine`,
          :class:`BezierSpline`.
          Other types are skipped, and a message is written, but processing
          continues.
        - `name`: string: the name of the object to be stored in the file.
          If not specified, and the object has an `attrib` dict containing
          a name, that value is used. Else an object name is generated
          from the file name.
          On readback, the object names are used as keys to store the objects
          in a dict.
        - `sep`: string: defines the separator to be used for writing this
          object. If not specified, the value given in the constructor will
          be used. This argument allows to override it on a per object base.

        Returns 1 if the object has been written, 0 otherwise.
        """
        self.checkWritable()

        try:
            writefunc = getattr(self, 'write'+geom.__class__.__name__)
        except:
            pf.warning("Can not (yet) write objects of type %s to geometry file: skipping" % type(geom))
            return 1

        if name is None:
            name = geom.attrib.name
        if name is None:
            name = next(self.autoname)

        try:
            writefunc(geom, name, sep)
        except:
            pf.warning("Error while writing objects of type %s to geometry file: skipping" % type(geom))
            raise

        if geom.attrib and Version(self.version) >= Version('2.0'):
            try:
                self.writeAttrib(geom.attrib)
            except:
                pf.warning("Error while writing objects of type %s to geometry file: skipping" % type(geom))
                raise

        return 0
Пример #26
0
def checkPrintSyntax(filename):
    """Check whether the script in the given files uses print function syntax.

    Returns the compiled object if no error was found during compiling.
    Returns the filename if an error was found and correction has been
    attempted.
    Raises an exception if an error is found and no correction attempted.
    """
    with open(filename,'r') as f:
        try:
            script = f.read()
            scr = compile(script,filename,'exec')
            return scr
        except SyntaxError as err:
            if re.compile('.*print +[^ (]').match(err.text):
                ans = pf.warning("""..

Syntax error in line %s of %s::

  %s

It looks like your are using a print statement instead of the print function.
In order to prepare you for the future (Python3), pyFormex already enforces
the use of the print function.
This means that you have to change any print statement from::

    print something

into a print function call::

    print(something)

You can try an automatic conversion with the command::

    2to3 -f print -%s

If you want, I can run this command for you now. Beware though!
This will overwrite the contents of file %s.

Also, the automatic conversion is not guaranteed to work, because
there may be other errors.
""" % (err.lineno,err.filename,err.text,filename,filename),actions=['Not this time','Convert now'],)
                if ans == 'Convert now':
                    print(ans)
                    if convertPrintSyntax(filename):
                        message("Script properly converted, now running the converted script")
                        return filename
                raise
Пример #27
0
def multitask(tasks, nproc=-1):
    """Perform tasks in parallel.

    Runs a number of tasks in parallel over a number of subprocesses.

    Parameters:

    - `tasks` : a list of (function,args) tuples, where function is a
      callable and args is a tuple with the arguments to be passed to the
      function.
    - ` nproc`: the number of subprocesses to be started. This may be
      different from the number of tasks to run: processes finishing a
      task will pick up a next one. There is no benefit in starting more
      processes than the number of tasks or the number of processing units
      available. The default will set `nproc` to the minimum of these two
      values.
    """
    if nproc < 0:
        nproc = min(len(tasks), cpu_count())

    pf.debug("Multiprocessing using %s processors" % nproc, pf.DEBUG.MULTI)
    #    if pf.scriptMode == 'script':
    if __name__ == '__draw__':
        if pf.warning("""..

Multiprocessing in 'script' mode
================================

You are trying to use multiprocessing while running in 'script' mode.
Multiprocessing in 'script' mode may cause pyFormex to hang indefinitely.
We strongly advice you to cancel the operation now and to run your
application in 'app' mode. Multiprocessing runs fine in 'app' mode.
""",
                      actions=[
                          'Cancel', 'I know the risks and insist on continuing'
                      ]) == 'Cancel':
            return

    pool = Pool(nproc)
    res = pool.map(dofunc, tasks)
    pool.close()
    return res
Пример #28
0
def run(argv=[]):
    """This is a fairly generic main() function.

    It is responsible for reading the configuration file(s),
    processing the command line options and starting the application.
    The basic configuration file is 'pyformexrc' located in the pyformex
    directory. It should always be present and be left unchanged.
    You can copy this file to another location if you want to make changes.
    By default, pyformex will try to read the following extra configuration
    files (in this order:
        default settings:     <pyformexdir>/pyformexrc
        system-wide settings: /etc/pyformexrc
        user settings:        $HOME/.pyformex/pyformexrc
        local settings        $PWD/.pyformexrc
    Also, an extra config file can be specified in the command line.
    Config file settings always override previous ones.
    On exit, the preferences that were changed are written to the last
    read config file. Changed settings are those that differ from the settings
    in all but the last one.
    """
    # Create a config instance
    pyformex.cfg = Config()
    # Fill in the pyformexdir and homedir variables
    # (use a read, not an update)
    if os.name == 'posix':
        homedir = os.environ['HOME']
    elif os.name == 'nt':
        homedir = os.environ['HOMEDRIVE']+os.environ['HOMEPATH']
    pyformex.cfg.read("pyformexdir = '%s'\n" % pyformexdir)
    pyformex.cfg.read("homedir = '%s'\n" % homedir)

    # Read the defaults (before the options)
    defaults = os.path.join(pyformexdir,"pyformexrc")
    pyformex.cfg.read(defaults)
    
    # Process options
    import optparse
    from optparse import make_option as MO
    parser = optparse.OptionParser(
        # THE Qapp options are removed, because it does not seem to work !!!
        # SEE the comments in the gui.startGUI function  
        usage = "usage: %prog [<options>] [ [ scriptname [scriptargs] ] ...]",
        version = utils.FullVersion(),
        description = pyformex.Description,
        formatter = optparse.TitledHelpFormatter(),
        option_list=[
        MO("--gui",
           action="store_true", dest="gui", default=None,
           help="start the GUI (default if no scriptfile argument is given)",
           ),
        MO("--nogui",
           action="store_false", dest="gui", default=None,
           help="do not load the GUI (default if a scriptfile argument is given)",
           ),
        MO("--interactive",'-i',
           action="store_true", dest="interactive", default=False,
           help="Go into interactive mode after processing the command line parameters. This is implied by the --gui option.",
           ),
        MO("--force-dri",
           action="store_true", dest="dri", default=None,
           help="Force use of Direct Rendering",
           ),
        MO("--force-nodri",
           action="store_false", dest="dri", default=None,
           help="Disables the Direct Rendering",
           ),
        MO("--uselib",
           action="store_true", dest="uselib", default=None,
           help="Use the pyFormex C lib if available. This is the default.",
           ),
        MO("--nouselib",
           action="store_false", dest="uselib", default=None,
           help="Do not use the pyFormex C-lib.",
           ),
        MO("--fastencode",
           action="store_true", dest="fastencode", default=False,
           help="Use a fast algorithm to encode edges.",
           ),
        MO("--norst2html",
           action="store_false", dest="rst2html", default=True,
           help="Do not try to convert rst messages to html before displaying.",
           ),
        MO("--config",
           action="store", dest="config", default=None,
           help="Use file CONFIG for settings",
           ),
        MO("--nodefaultconfig",
           action="store_true", dest="nodefaultconfig", default=False,
           help="Skip the default site and user config files. This option can only be used in conjunction with the --config option.",
           ),
        MO("--redirect",
           action="store_true", dest="redirect", default=False,
           help="Redirect standard output to the message board (ignored with --nogui)",
           ),
        MO("--debug",
           action="store_const", dest="debug", const=-1,
           help="display debugging info to sys.stdout",
           ),
        MO("--debuglevel",
           action="store", dest="debug", type="int", default=0,
           help="display debugging info to sys.stdout",
           ),
        ## MO("--classify",
        ##    action="store_true", dest="classify", default=False,
        ##    help="classify the examples in categories",
        ##    ),
        MO("--newviewports",
           action="store_true", dest="newviewports", default=False,
           help="Use the new multiple viewport canvas implementation. This is an experimental feature only intended for developers.",
           ),
        MO("--testmodule",
           action="store", dest="testmodule", default=None,
           help="Run the docstring tests for module TESTMODULE. TESTMODULE is the name of the module, using . as path separator.",
           ),
        MO("--test",
           action="store_true", dest="test", default=False,
           help="testing mode: only for developers!",
           ),
        MO("--testexecutor",
           action="store_true", dest="executor", default=False,
           help="test alternate executor: only for developers!",
           ),
        MO("--remove",
           action="store_true", dest="remove", default=False,
           help="remove the pyformex installation and exit",
           ),
        MO("--whereami",
           action="store_true", dest="whereami", default=False,
           help="show where the pyformex package is installed and exit",
           ),
        MO("--detect",
           action="store_true", dest="detect", default=False,
           help="show detected helper software and exit",
           ),
        ])
    pyformex.options, args = parser.parse_args(argv)
    pyformex.print_help = parser.print_help


    # process options
    if pyformex.options.nodefaultconfig and not pyformex.options.config:
        print("\nInvalid options: --nodefaultconfig but no --config option\nDo pyformex --help for help on options.\n")
        sys.exit()

    pyformex.debug("Options: %s" % pyformex.options)


    ########## Process special options which will not start pyFormex #######

    if pyformex.options.remove or \
       pyformex.options.whereami or \
       pyformex.options.detect or \
       pyformex.options.testmodule:

        if pyformex.options.remove:
            remove_pyFormex(pyformexdir,pyformex.scriptdir)

        if pyformex.options.whereami or pyformex.options.debug :
            print("Script started from %s" % pyformex.scriptdir)
            print("I found pyFormex in %s " %  pyformexdir)
            print("Current Python sys.path: %s" % sys.path)

        if pyformex.options.detect or pyformex.options.debug :
            print("Detecting all installed helper software")
            utils.checkExternal()
            print(utils.reportDetected())

        if pyformex.options.testmodule:
            for a in pyformex.options.testmodule.split(','):
                test_module(a)

        sys.exit()

    ########### Read the config files  ####################

    # These values  should not be changed
    pyformex.cfg.userprefs = os.path.join(pyformex.cfg.userconfdir,'pyformexrc')
    pyformex.cfg.autorun = os.path.join(pyformex.cfg.userconfdir,'startup.py')
    
    # Set the config files
    if pyformex.options.nodefaultconfig:
        sysprefs = []
        userprefs = []
    else:
        sysprefs = [ pyformex.cfg.siteprefs ]
        userprefs = [ pyformex.cfg.userprefs ]
        if os.path.exists(pyformex.cfg.localprefs):
            userprefs.append(pyformex.cfg.localprefs)

    if pyformex.options.config:
        userprefs.append(pyformex.options.config)

    if len(userprefs) == 0:
        # We should always have a place to store the user preferences
        userprefs = [ pyformex.cfg.userprefs ]

    pyformex.preffile = os.path.abspath(userprefs[-1]) # Settings will be saved here
   
    # Read all but the last as reference
    for f in filter(os.path.exists,sysprefs + userprefs[:-1]):
        pyformex.debug("Reading config file %s" % f)
        pyformex.cfg.read(f)
    pyformex.refcfg = pyformex.cfg
    pyformex.debug("="*60)
    pyformex.debug("RefConfig: %s" % pyformex.refcfg)

    # Use the last as place to save preferences
    pyformex.prefcfg = Config(default=refLookup)
    if os.path.exists(pyformex.preffile):
        pyformex.debug("Reading config file %s" % pyformex.preffile)
        pyformex.prefcfg.read(pyformex.preffile)
    pyformex.debug("="*60)
    pyformex.debug("Config: %s" % pyformex.prefcfg)

    # Fix incompatible changes in configuration
    apply_config_changes(pyformex.prefcfg)

    # Create an empty one for the session settings
    pyformex.cfg = Config(default=prefLookup)

    # This should probably be changed to options overriding config
    # Set option from config if it was not explicitely given
    if pyformex.options.uselib is None:
        pyformex.options.uselib = pyformex.cfg['uselib']


    # Set default --nogui if first remaining argument is a pyformex script.
    if pyformex.options.gui is None:
        pyformex.options.gui = not (len(args) > 0 and utils.is_pyFormex(args[0]))

    if pyformex.options.gui:
        pyformex.options.interactive = True

    # Set Revision and run svnclean if we run from an SVN version
    if svnversion:
        setRevision()
        svnclean = os.path.join(pyformexdir,'svnclean')
        if os.path.exists(svnclean):
            try:
                utils.runCommand(svnclean)
            except:
                print("Error while executing %s, we ignore it and continue" % svnclean)

        def getSVNURL():
            sta,out = utils.runCommand("cd %s;svn info | grep -F 'URL:'"%pyformexdir)
            if sta == 0:
                return out
            else:
                return ''


        ## s = getSVNURL()
        ## print s
        ## import re
        ## m = re.match(".*//(?P<user>[^@]*)@svn\.berlios\.de.*",s)
        ## pyformex.svnuser = m.group('user')
        ## print pyformex.svnuser
    


    ###### We have the config and options all set up ############
    filterWarnings()



    def _format_warning(message,category,filename,lineno,line=None):
        """Replace the default warnings.formatwarning

        This allows the warnings being called using a simple mnemonic
        string. The full message is then found from the message module.
        """
        import messages
        message = messages.getMessage(message)
        message = """..

pyFormex Warning
================
%s

`Called from:` %s `line:` %s
""" % (message,filename,lineno)
        if line:
            message += "%s\n" % line
        return message


    if pyformex.cfg['warnings/nice']:
        import warnings
        warnings.formatwarning = _format_warning
    


    # Start the GUI if needed
    # Importing the gui should be done after the config is set !!
    if pyformex.options.gui:
        from gui import guimain
        pyformex.debug("GUI version")
        res = guimain.startGUI(args)
        if res != 0:
            print("Could not start the pyFormex GUI: %s" % res)
            return res # EXIT

    # Display the startup warnings and messages
    if startup_warnings:
        if pyformex.cfg['startup_warnings']:
            pyformex.warning(startup_warnings)
        else:
            print(startup_warnings)
    if startup_messages:
        print(startup_messages)

    pyformex.debug(utils.reportDetected())
 
    #print(pyformex.cfg.keys())
    #print(pyformex.refcfg.keys())
      
    #
    # Qt4 may have changed the locale.
    # Since a LC_NUMERIC setting other than C may cause lots of troubles
    # with reading and writing files (formats become incompatible!)
    # we put it back to a sane setting
    #
    utils.setSaneLocale()

    # Initialize the libraries
    #print("NOW LOAIDNG LIBS")
    #import lib
    #lib.init_libs(pyformex.options.uselib,pyformex.options.gui)


    # Prepend the autorun scripts
    ar = pyformex.cfg.get('autorun','')
    if ar :
        if type(ar) is str:
            ar = [ ar ]
        # expand tilde, as would bash
        ar = map(utils.tildeExpand,ar)
        args[0:0] = [ fn for fn in ar if os.path.exists(fn) ]

    # remaining args are interpreted as scripts and their parameters
    res = 0
    if args:
        pyformex.debug("Remaining args: %s" % args)
        from script import processArgs
        res = processArgs(args)
        
        if res:
            if pyformex.options.gui:
                pyformex.message("There was an error while executing a script")
            else:
                return res # EXIT
                
    else:
        pyformex.debug("stdin is a tty: %s" % sys.stdin.isatty())
        # Play script from stdin
        # Can we check for interactive session: stdin connected to terminal?
        #from script import playScript
        #playScript(sys.stdin)
        

    # after processing all args, go into interactive mode
    if pyformex.options.gui and pyformex.app:
        res = guimain.runGUI()

    ## elif pyformex.options.interactive:
    ##     print("Enter your script and end with CTRL-D")
    ##     from script import playScript
    ##     playScript(sys.stdin)
        
    #Save the preferences that have changed
    savePreferences()

    # Exit
    return res
Пример #29
0
def writeSection(fil,prop):
    """Write an element section.

    prop is a an element property record with a section and eltype attribute
    """
    out = ""
    setname = esetName(prop)
    el = prop.section
    eltype = prop.eltype.upper()

    mat = el.material
    if mat is not None:
        fil.write(fmtMaterial(mat))
            
    if eltype in connector_elems:
        fil.write(fmtConnectorSection(el,setname))

    elif eltype in frame_elems:
        fil.write(fmtFrameSection(el,setname))
            
    elif eltype in truss_elems:
        if el.sectiontype.upper() == 'GENERAL':
            fil.write("""*SOLID SECTION, ELSET=%s, MATERIAL=%s
%s
""" %(setname,el.material.name, float(el.cross_section)))
        elif el.sectiontype.upper() == 'CIRC':
            fil.write("""*SOLID SECTION, ELSET=%s, MATERIAL=%s
%s
""" %(setname,el.material.name, float(el.radius)**2*pi))

    ############
    ##BEAM elements
    ##########################
    elif eltype in beam_elems:
        if el.integrate:
            fil.write(fmtBeamSection(el,setname))
        else:
            fil.write(fmtGeneralBeamSection(el,setname))

    ############
    ## SHELL elements
    ##########################
    elif eltype in shell_elems:
        fil.write(fmtShellSection(el,setname,mat.name))
    
    ############
    ## SURFACE elements
    ##########################
    elif eltype in surface_elems:
        if el.sectiontype.upper() == 'SURFACE':
            fil.write("""*SURFACE SECTION, ELSET=%s \n""" % setname)
    
    ############
    ## MEMBRANE elements
    ##########################
    elif eltype in membrane_elems:
        if el.sectiontype.upper() == 'MEMBRANE':
            if mat is not None:
                fil.write("""*MEMBRANE SECTION, ELSET=%s, MATERIAL=%s
%s \n""" % (setname,mat.name,float(el.thickness)))


    ############
    ## 3DSOLID elements
    ##########################
    elif eltype in solid3d_elems:
        if el.sectiontype.upper() == '3DSOLID':
            if mat is not None:
                fil.write("""*SOLID SECTION, ELSET=%s, MATERIAL=%s
%s \n""" % (setname,mat.name,1.))

    ############
    ## 2D SOLID elements
    ##########################
    elif eltype in solid2d_elems:
        if el.sectiontype.upper() == 'SOLID':
            if mat is not None:
                fil.write("""*SOLID SECTION, ELSET=%s, MATERIAL=%s
%s \n""" % (setname,mat.name,float(el.thickness)))
            
    ############
    ## RIGID elements
    ##########################
    elif eltype in ['R2D2','RB2D2','RB3D2','RAX2','R3D3','R3D4']:
        if el.sectiontype.upper() == 'RIGID':
            fil.write("""*RIGID BODY,REFNODE=%s,density=%s, ELSET=%s\n""" % (el.nodeset,el.density,setname))



    ############
    ## UNSUPPORTED elements
    ##########################
    else:
        GD.warning('Sorry, elementtype %s is not yet supported' % eltype)
Пример #30
0
def save(filename=None,window=False,multi=False,hotkey=True,autosave=False,border=False,rootcrop=False,format=None,verbose=False):
    """Saves an image to file or Starts/stops multisave maode.

    With a filename and multi==False (default), the current viewport rendering
    is saved to the named file.

    With a filename and multi==True, multisave mode is started.
    Without a filename, multisave mode is turned off.
    Two subsequent calls starting multisave mode without an intermediate call
    to turn it off, do not cause an error. The first multisave mode will
    implicitely be ended before starting the second.

    In multisave mode, each call to saveNext() will save an image to the
    next generated file name.
    Filenames are generated by incrementing a numeric part of the name.
    If the supplied filename (after removing the extension) has a trailing
    numeric part, subsequent images will be numbered continuing from this
    number. Otherwise a numeric part '-000' will be added to the filename.
    
    If window is True, the full pyFormex window is saved.
    If window and border are True, the window decorations will be included.
    If window is False, only the current canvas viewport is saved.

    If hotkey is True, a new image will be saved by hitting the 'S' key.
    If autosave is True, a new image will be saved on each execution of
    the 'draw' function.
    If neither hotkey nor autosave are True, images can only be saved by
    executing the saveNext() function from a script.

    If no format is specified, it is derived from the filename extension.
    fmt should be one of the valid formats as returned by imageFormats()
  
    If verbose=True, error/warnings are activated. This is usually done when
    this function is called from the GUI.
    
    """
    global multisave

    # Leave multisave mode if no filename or starting new multisave mode
    if multisave and (filename is None or multi):
        GD.message("Leave multisave mode")
        QtCore.QObject.disconnect(GD.gui,QtCore.SIGNAL("Save"),saveNext)
        multisave = None

    if filename is None:
        return

    #chdir(filename)
    name,ext = os.path.splitext(filename)
    # Get/Check format
    if not format: # is None:
        format = checkImageFormat(imageFormatFromExt(ext))
    if not format:
        return

    if multi: # Start multisave mode
        names = utils.NameSequence(name,ext)
        if os.path.exists(names.peek()):
            next = names.next()
        GD.message("Start multisave mode to files: %s (%s)" % (names.name,format))
        #print hotkey
        if hotkey:
             QtCore.QObject.connect(GD.gui,QtCore.SIGNAL("Save"),saveNext)
             if verbose:
                 GD.warning("Each time you hit the '%s' key,\nthe image will be saved to the next number." % GD.cfg['keys/save'])
        multisave = (names,format,window,border,hotkey,autosave,rootcrop)
        print "MULTISAVE %s "% str(multisave)
        return multisave is None

    else: # Save the image
        if window:
            if rootcrop:
                sta = save_main_window(filename,format,border=border)
            else:
                sta = save_window(filename,format)
        else:
            sta = save_canvas(GD.canvas,filename,format)
        if sta:
            GD.debug("Error while saving image %s" % filename)
        else:
            GD.message("Image file %s written" % filename)
        return
Пример #31
0
def save(filename=None,
         window=False,
         multi=False,
         hotkey=True,
         autosave=False,
         border=False,
         rootcrop=False,
         format=None,
         quality=-1,
         size=None,
         verbose=False):
    """Saves an image to file or Starts/stops multisave mode.

    With a filename and multi==False (default), the current viewport rendering
    is saved to the named file.

    With a filename and multi==True, multisave mode is started.
    Without a filename, multisave mode is turned off.
    Two subsequent calls starting multisave mode without an intermediate call
    to turn it off, do not cause an error. The first multisave mode will
    implicitely be ended before starting the second.

    In multisave mode, each call to saveNext() will save an image to the
    next generated file name.
    Filenames are generated by incrementing a numeric part of the name.
    If the supplied filename (after removing the extension) has a trailing
    numeric part, subsequent images will be numbered continuing from this
    number. Otherwise a numeric part '-000' will be added to the filename.

    If window is True, the full pyFormex window is saved.
    If window and border are True, the window decorations will be included.
    If window is False, only the current canvas viewport is saved.

    If hotkey is True, a new image will be saved by hitting the 'S' key.
    If autosave is True, a new image will be saved on each execution of
    the 'draw' function.
    If neither hotkey nor autosave are True, images can only be saved by
    executing the saveNext() function from a script.

    If no format is specified, it is derived from the filename extension.
    fmt should be one of the valid formats as returned by imageFormats()

    If verbose=True, error/warnings are activated. This is usually done when
    this function is called from the GUI.

    """
    #print "SAVE: quality=%s" % quality
    global multisave

    # Leave multisave mode if no filename or starting new multisave mode
    if multisave and (filename is None or multi):
        pf.message("Leave multisave mode")
        pf.GUI.signals.SAVE.disconnect(saveNext)
        multisave = None

    if filename is None:
        return

    #chdir(filename)
    name, ext = os.path.splitext(filename)
    # Get/Check format
    if not format:  # is None:
        format = checkImageFormat(imageFormatFromExt(ext))
    if not format:
        return

    if multi:  # Start multisave mode
        names = utils.NameSequence(name, ext)
        if os.path.exists(names.peek()):
            next = names.next()
        pf.message("Start multisave mode to files: %s (%s)" %
                   (names.name, format))
        if hotkey:
            pf.GUI.signals.SAVE.connect(saveNext)
            if verbose:
                pf.warning(
                    "Each time you hit the '%s' key,\nthe image will be saved to the next number."
                    % pf.cfg['keys/save'])
        multisave = (names, format, quality, size, window, border, hotkey,
                     autosave, rootcrop)
        print("MULTISAVE %s " % str(multisave))
        return multisave is None

    else:  # Save the image
        if window:
            if rootcrop:
                sta = save_main_window(filename,
                                       format,
                                       quality,
                                       border=border)
            else:
                sta = save_window(filename, format, quality)
        else:
            if size == pf.canvas.getSize():
                size = None
            sta = save_canvas(pf.canvas, filename, format, quality, size)
        if sta:
            pf.debug("Error while saving image %s" % filename, pf.DEBUG.IMAGE)
        else:
            pf.message("Image file %s written" % filename)
        return
Пример #32
0
def updateQt4Bindings():
    pf.warning("You changed the Python Qt4 bindings setting to '%s'.\nThis setting will only become active after you restart pyFormex." % pf.cfg['gui/bindings'])
Пример #33
0
def run(argv=[]):
    """This is a fairly generic main() function.

    It is responsible for reading the configuration file(s),
    processing the command line options and starting the application.
    The basic configuration file is 'pyformexrc' located in the pyformex
    directory. It should always be present and be left unchanged.
    You can copy this file to another location if you want to make changes.
    By default, pyformex will try to read the following extra configuration
    files (in this order:
        default settings:     <pyformexdir>/pyformexrc
        system-wide settings: /etc/pyformexrc
        user settings:        $HOME/.pyformex/pyformexrc
        local settings        $PWD/.pyformexrc
    Also, an extra config file can be specified in the command line.
    Config file settings always override previous ones.
    On exit, the preferences that were changed are written to the last
    read config file. Changed settings are those that differ from the settings
    in all but the last one.
    """
    # Create a config instance
    pf.cfg = Config()
    # Fill in the pyformexdir and homedir variables
    # (use a read, not an update)
    if os.name == 'posix':
        homedir = os.environ['HOME']
    elif os.name == 'nt':
        homedir = os.environ['HOMEDRIVE'] + os.environ['HOMEPATH']
    pf.cfg.read("pyformexdir = '%s'\n" % pyformexdir)
    pf.cfg.read("homedir = '%s'\n" % homedir)

    # Read the defaults (before the options)
    defaults = os.path.join(pyformexdir, "pyformexrc")
    pf.cfg.read(defaults)

    # Process options
    import optparse
    from optparse import make_option as MO
    parser = optparse.OptionParser(
        # THE Qapp options are removed, because it does not seem to work !!!
        # SEE the comments in the gui.startGUI function
        usage="usage: %prog [<options>] [ [ scriptname [scriptargs] ] ...]",
        version=pf.fullVersion(),
        description=pf.Description,
        formatter=optparse.TitledHelpFormatter(),
        option_list=[
            MO(
                "--gui",
                action="store_true",
                dest="gui",
                default=None,
                help=
                "Start the GUI (this is the default when no scriptname argument is given)",
            ),
            MO(
                "--nogui",
                action="store_false",
                dest="gui",
                default=None,
                help=
                "Do not start the GUI (this is the default when a scriptname argument is given)",
            ),
            MO(
                "--interactive",
                action="store_true",
                dest="interactive",
                default=False,
                help=
                "Go into interactive mode after processing the command line parameters. This is implied by the --gui option.",
            ),
            MO(
                "--dri",
                action="store_true",
                dest="dri",
                default=None,
                help=
                "Use Direct Rendering Infrastructure. By default, direct rendering will be used if available.",
            ),
            MO(
                "--nodri",
                action="store_false",
                dest="dri",
                default=None,
                help=
                "Do not use the Direct Rendering Infrastructure. This may be used to turn off the direc rendering, e.g. to allow better capturing of images and movies.",
            ),
            MO(
                "--uselib",
                action="store_true",
                dest="uselib",
                default=None,
                help=
                "Use the pyFormex C lib if available. This is the default.",
            ),
            MO(
                "--nouselib",
                action="store_false",
                dest="uselib",
                default=None,
                help="Do not use the pyFormex C-lib.",
            ),
            MO(
                "--commands",
                action="store_true",
                dest="commands",
                default=False,
                help=
                "Use the commands module to execute external commands. Default is to use the subprocess module.",
            ),
            MO(
                "--config",
                action="store",
                dest="config",
                default=None,
                help="Use file CONFIG for settings",
            ),
            MO(
                "--nodefaultconfig",
                action="store_true",
                dest="nodefaultconfig",
                default=False,
                help=
                "Skip the default site and user config files. This option can only be used in conjunction with the --config option.",
            ),
            MO(
                "--redirect",
                action="store_true",
                dest="redirect",
                default=None,
                help=
                "Redirect standard output to the message board (ignored with --nogui)",
            ),
            MO(
                "--noredirect",
                action="store_false",
                dest="redirect",
                help="Do not redirect standard output to the message board.",
            ),
            MO(
                "--debug",
                action="store",
                dest="debug",
                default='',
                help=
                "Display debugging information to sys.stdout. The value is a comma-separated list of (case-insensitive) strings corresponding with the attributes of the DebugLevels class. The individual values are OR-ed together to produce a final debug value. The special value 'all' can be used to switch on all debug info.",
            ),
            MO(
                "--debuglevel",
                action="store",
                dest="debuglevel",
                type="int",
                default=0,
                help=
                "Display debugging info to sys.stdout. The value is an int with the bits of the requested debug levels set. A value of -1 switches on all debug info. If this option is used, it overrides the --debug option.",
            ),
            MO(
                "--newviewports",
                action="store_true",
                dest="newviewports",
                default=False,
                help=
                "Use the new multiple viewport canvas implementation. This is an experimental feature only intended for developers.",
            ),
            MO(
                "--testmodule",
                action="store",
                dest="testmodule",
                default=None,
                help=
                "Run the docstring tests for module TESTMODULE. TESTMODULE is the name of the module, using . as path separator.",
            ),
            MO(
                "--testcamera",
                action="store_true",
                dest="testcamera",
                default=False,
                help="Print camera settings whenever they change.",
            ),
            MO(
                "--testexecutor",
                action="store_true",
                dest="executor",
                default=False,
                help="Test alternate executor: only for developers!",
            ),
            MO(
                "--memtrack",
                action="store_true",
                dest="memtrack",
                default=False,
                help="Track memory for leaks. This is only for developers.",
            ),
            MO(
                "--fastnurbs",
                action="store_true",
                dest="fastnurbs",
                default=False,
                help="Test C library nurbs drawing: only for developers!",
            ),
            MO(
                "--pyside",
                action="store_true",
                dest="pyside",
                default=None,
                help="Use the PySide bindings for QT4 libraries",
            ),
            MO(
                "--pyqt4",
                action="store_false",
                dest="pyside",
                default=None,
                help="Use the PyQt4 bindings for QT4 libraries",
            ),
            MO(
                "--opengl2",
                action="store_true",
                dest="opengl2",
                default=False,
                help=
                "Use the new OpenGL rendering engine. This is an experimental feature only intended for developers.",
            ),
            MO(
                "--listfiles",
                action="store_true",
                dest="listfiles",
                default=False,
                help="List the pyformex Python source files.",
            ),
            MO(
                "--search",
                action="store_true",
                dest="search",
                default=False,
                help=
                "Search the pyformex source for a specified pattern and exit. This can optionally be followed by -- followed by options for the grep command and/or '-a' to search all files in the extended search path. The final argument is the pattern to search. '-e' before the pattern will interprete this as an extended regular expression. '-l' option only lists the names of the matching files.",
            ),
            MO(
                "--remove",
                action="store_true",
                dest="remove",
                default=False,
                help=
                "Remove the pyFormex installation and exit. This option only works when pyFormex was installed from a tarball release using the supplied install procedure. If you install from a distribution package (e.g. Debian), you should use your distribution's package tools to remove pyFormex. If you run pyFormex directly from SVN sources, you should just remove the whole checked out source tree.",
            ),
            MO(
                "--whereami",
                action="store_true",
                dest="whereami",
                default=False,
                help="Show where the pyformex package is installed and exit",
            ),
            MO(
                "--detect",
                action="store_true",
                dest="detect",
                default=False,
                help="Show detected helper software and exit",
            ),
        ])
    pf.options, args = parser.parse_args(argv)
    pf.print_help = parser.print_help

    # Set debug level
    if pf.options.debug and not pf.options.debuglevel:
        pf.options.debuglevel = pf.debugLevel(pf.options.debug.split(','))

    # process options
    if pf.options.nodefaultconfig and not pf.options.config:
        print(
            "\nInvalid options: --nodefaultconfig but no --config option\nDo pyformex --help for help on options.\n"
        )
        sys.exit()

    pf.debug("Options: %s" % pf.options, pf.DEBUG.ALL)

    ########## Process special options which will not start pyFormex #######

    if pf.options.testmodule:
        for a in pf.options.testmodule.split(','):
            test_module(a)
        return

    if pf.options.remove:
        remove_pyFormex(pyformexdir, pf.bindir)
        return

    if pf.options.whereami:  # or pf.options.detect :
        pf.options.debuglevel |= pf.DEBUG.INFO

    pf.debug("pyformex script started from %s" % pf.bindir, pf.DEBUG.INFO)
    pf.debug("I found pyFormex installed in %s " % pyformexdir, pf.DEBUG.INFO)
    pf.debug("Current Python sys.path: %s" % sys.path, pf.DEBUG.INFO)

    if pf.options.detect:
        print("Detecting installed helper software")
        utils.checkExternal()
        print(utils.reportDetected())

    if pf.options.whereami or pf.options.detect:
        return

    ########### Read the config files  ####################

    # These values should not be changed
    pf.cfg.userprefs = os.path.join(pf.cfg.userconfdir, 'pyformexrc')

    # Set the config files
    if pf.options.nodefaultconfig:
        sysprefs = []
        userprefs = []
    else:
        sysprefs = [pf.cfg.siteprefs]
        userprefs = [pf.cfg.userprefs]
        if os.path.exists(pf.cfg.localprefs):
            userprefs.append(pf.cfg.localprefs)

    if pf.options.config:
        userprefs.append(pf.options.config)

    if len(userprefs) == 0:
        # We should always have a place to store the user preferences
        userprefs = [pf.cfg.userprefs]

    pf.preffile = os.path.abspath(userprefs[-1])  # Settings will be saved here

    # Read all but the last as reference
    for f in filter(os.path.exists, sysprefs + userprefs[:-1]):
        pf.debug("Reading config file %s" % f, pf.DEBUG.CONFIG)
        pf.cfg.read(f)

    pf.refcfg = pf.cfg
    pf.debug("=" * 60, pf.DEBUG.CONFIG)
    pf.debug("RefConfig: %s" % pf.refcfg, pf.DEBUG.CONFIG)

    # Use the last as place to save preferences
    pf.prefcfg = Config(default=refLookup)
    if os.path.exists(pf.preffile):
        pf.debug("Reading config file %s" % pf.preffile, pf.DEBUG.CONFIG)
        pf.prefcfg.read(pf.preffile)
    pf.debug("=" * 60, pf.DEBUG.CONFIG)
    pf.debug("Config: %s" % pf.prefcfg, pf.DEBUG.CONFIG)

    # Fix incompatible changes in configuration
    apply_config_changes(pf.prefcfg)

    # Create an empty one for the session settings
    pf.cfg = Config(default=prefLookup)

    ####################################################################
    ## Post config initialization ##

    # process non-starting options dependent on config

    if pf.options.search or pf.options.listfiles:
        if len(args) > 0:
            opts = [a for a in args if a.startswith('-')]
            args = [a for a in args if not a in opts]
            if '-a' in opts:
                opts.remove('-a')
                extended = True
            else:
                extended = False
            if len(args) > 1:
                files = args[1:]
            else:
                files = utils.sourceFiles(relative=True, extended=extended)
            if pf.options.listfiles:
                print('\n'.join(files))
            else:
                cmd = "grep %s '%s' %s" % (' '.join(opts), args[0], ''.join(
                    [" '%s'" % f for f in files]))
                #print(cmd)
                os.system(cmd)
        return

    # process other options dependent on config
    if pf.options.pyside is None:
        pf.options.pyside = pf.cfg['gui/bindings'].lower() == 'pyside'

    # process options that override the config
    if pf.options.redirect is not None:
        pf.cfg['gui/redirect'] = pf.options.redirect
    delattr(pf.options, 'redirect')  # avoid abuse
    #print "REDIRECT",pf.cfg['gui/redirect']

    ###################################################################

    # This should probably be changed to options overriding config
    # Set option from config if it was not explicitely given
    if pf.options.uselib is None:
        pf.options.uselib = pf.cfg['uselib']

    # Set default --nogui if first remaining argument is a pyformex script.
    if pf.options.gui is None:
        pf.options.gui = not (len(args) > 0 and utils.is_pyFormex(args[0]))

    if pf.options.gui:
        pf.options.interactive = True

    #  If we run from an source version, we should set the proper revision
    #  number and run the svnclean procedure.

    if pf.installtype in 'SG':
        svnclean = os.path.join(pyformexdir, 'svnclean')
        if os.path.exists(svnclean):
            try:
                utils.system(svnclean)
            except:
                print("Error while executing %s, we ignore it and continue" %
                      svnclean)

    ###### We have the config and options all set up ############
    filterWarnings()

    def _format_warning(message, category, filename, lineno, line=None):
        """Replace the default warnings.formatwarning

        This allows the warnings being called using a simple mnemonic
        string. The full message is then found from the message module.
        """
        import messages
        message = messages.getMessage(message)
        message = """..

pyFormex Warning
================
%s

`Called from:` %s `line:` %s
""" % (message, filename, lineno)
        if line:
            message += "%s\n" % line
        return message

    if pf.cfg['warnings/nice']:
        import warnings
        warnings.formatwarning = _format_warning

    utils.checkModule('numpy', fatal=True)

    # Make sure pf.PF is a Project
    from project import Project
    pf.PF = Project()

    utils.setSaneLocale()

    # Set application paths
    pf.debug("Loading AppDirs", pf.DEBUG.INFO)
    import apps
    apps.setAppDirs()

    # Start the GUI if needed
    # Importing the gui should be done after the config is set !!
    if pf.options.gui:
        from gui import guimain
        pf.debug("GUI version", pf.DEBUG.INFO)
        res = guimain.startGUI(args)
        if res != 0:
            print("Could not start the pyFormex GUI: %s" % res)
            return res  # EXIT

    # Display the startup warnings and messages
    if startup_warnings:
        if pf.cfg['startup_warnings']:
            pf.warning(startup_warnings)
        else:
            print(startup_warnings)
    if startup_messages:
        print(startup_messages)

    if pf.options.debuglevel & pf.DEBUG.INFO:
        # NOTE: inside an if to avoid computing the report when not printed
        pf.debug(utils.reportDetected(), pf.DEBUG.INFO)

    #
    # Qt4 may have changed the locale.
    # Since a LC_NUMERIC setting other than C may cause lots of troubles
    # with reading and writing files (formats become incompatible!)
    # we put it back to a sane setting
    #
    utils.setSaneLocale()

    # Initialize the libraries
    #import lib
    #lib.init_libs(pf.options.uselib,pf.options.gui)

    # Prepend the autorun script
    ar = pf.cfg.get('autorun', '')
    if ar and os.path.exists(ar):
        args[0:0] = [ar]

    # remaining args are interpreted as scripts and their parameters
    res = 0
    if args:
        pf.debug("Remaining args: %s" % args, pf.DEBUG.INFO)
        from script import processArgs
        res = processArgs(args)

        if res:
            if pf.options.gui:
                pf.message("There was an error while executing a script")
            else:
                return res  # EXIT

    else:
        pf.debug("stdin is a tty: %s" % sys.stdin.isatty(), pf.DEBUG.INFO)
        # Play script from stdin
        # Can we check for interactive session: stdin connected to terminal?
        #from script import playScript
        #playScript(sys.stdin)

    # after processing all args, go into interactive mode
    if pf.options.gui and pf.app:
        res = guimain.runGUI()

    ## elif pf.options.interactive:
    ##     print("Enter your script and end with CTRL-D")
    ##     from script import playScript
    ##     playScript(sys.stdin)

    #Save the preferences that have changed
    savePreferences()

    # Exit
    return res
Пример #34
0
def runApp(appname, argv=[], refresh=False, lock=True, check=True):
    """Run a pyFormex application.

    A pyFormex application is a Python module that can be loaded in
    pyFormex and that contains a function 'run()'. Running the application
    is equivalent to executing this function.

    Parameters:

    - `appname`: name of the module in Python dot notation. The module should
    live in a path included the the a file holding a pyFormex script.

    - `argv`: list of arguments. This variable can be changed by the app
    and the resulting argv will be returned to the caller.

    Returns the exit value of the run function. A zero value is supposed
    to mean a normal exit.
    """
    global exitrequested
    if check and len(pf.scriptlock) > 0:
        print("!!Not executing because a script lock has been set: %s" %
              pf.scriptlock)
        return

    from pyformex import apps
    from pyformex.timer import Timer
    t = Timer()
    print("Loading application %s with refresh=%s" % (appname, refresh))
    app = apps.load(appname, refresh=refresh)
    if app is None:
        errmsg = "An  error occurred while loading application %s" % appname
        if pf.GUI:
            if apps._traceback and pf.cfg['showapploaderrors']:
                print(apps._traceback)

            from pyformex.gui import draw
            fn = apps.findAppSource(appname)
            if os.path.exists(fn):
                errmsg += "\n\nYou may try executing the application as a script,\n  or you can load the source file in the editor."
                res = draw.ask(errmsg,
                               choices=[
                                   'Run as script', 'Load in editor',
                                   "Don't bother"
                               ])
                if res[0] in 'RL':
                    if res[0] == 'L':
                        draw.editFile(fn)
                    elif res[0] == 'R':
                        pf.GUI.setcurfile(fn)
                        draw.runScript(fn)
            else:
                errmsg += "and I can not find the application source file."
                draw.error(errmsg)
        else:
            error(errmsg)

        return

    if hasattr(app, '_opengl2') and not app._opengl2:
        pf.warning(
            "This Example can not yet be run under the pyFormex opengl2 engine.\n"
        )
        return

    if hasattr(app, '_status') and app._status == 'unchecked':
        pf.warning(
            "This looks like an Example script that has been automatically converted to the pyFormex Application model, but has not been checked yet as to whether it is working correctly in App mode.\nYou can help here by running and rerunning the example, checking that it works correctly, and where needed fixing it (or reporting the failure to us). If the example runs well, you can change its status to 'checked'"
        )

    if lock:
        scriptLock('__auto/app__')
    msg = "Running application '%s' from %s" % (appname, app.__file__)
    pf.scriptName = appname
    if pf.GUI:
        pf.GUI.startRun()
        pf.GUI.apphistory.add(appname)
        pf.GUI.board.write(msg, color='green')
    else:
        print(msg)
    pf.debug("  Passing arguments: %s" % argv, pf.DEBUG.SCRIPT)
    app._args_ = argv
    try:
        try:
            res = app.run()
        except SystemExit:
            print("EXIT FROM APP")
            pass
        except:
            raise
    finally:
        if hasattr(app, 'atExit'):
            app.atExit()
        if pf.cfg['autoglobals']:
            g = app.__dict__
            autoExport(g)
        if lock:
            scriptRelease('__auto/app__')  # release the lock
        if pf.GUI:
            pf.GUI.stopRun()

    pf.debug("  Arguments left after execution: %s" % argv, pf.DEBUG.SCRIPT)
    msg = "Finished %s in %s seconds" % (appname, t.seconds())
    if pf.GUI:
        pf.GUI.board.write(msg, color='green')
    else:
        print(msg)
    pf.debug("Memory: %s" % vmSize(), pf.DEBUG.MEM)
    return res
Пример #35
0
def createCylinder():
    pf.warning("This function has been moved to the Geometry menu")
Пример #36
0
def runApp(appname,argv=[],refresh=False):
    global exitrequested
    if len(pf.scriptlock) > 0:
        pf.message("!!Not executing because a script lock has been set: %s" % pf.scriptlock)
        #print(pf.scriptlock)
        return

    import apps
    from timer import Timer
    t = Timer()
    pf.message("Loading application %s with refresh=%s" % (appname,refresh))
    app = apps.load(appname,refresh=refresh)
    if app is None:
        errmsg = "An  error occurred while loading application %s" % appname
        if pf.GUI:
            if apps._traceback and pf.cfg['showapploaderrors']:
                print(apps._traceback)

            from gui import draw
            fn = apps.findAppSource(appname)
            if os.path.exists(fn):
                errmsg += "\n\nYou may try executing the application as a script,\n  or you can load the source file in the editor."
                res = draw.ask(errmsg,choices=['Run as script', 'Load in editor', "Don't bother"])
                if res[0] in 'RL':
                    if res[0] == 'L':
                        draw.editFile(fn)
                    elif res[0] == 'R':
                        pf.GUI.setcurfile(fn)
                        draw.runScript(fn)
            else:
                errmsg += "and I can not find the application source file."
                draw.error(errmsg)
        else:
            error(errmsg)

        return

    if hasattr(app,'_status') and app._status == 'unchecked':
        pf.warning("This looks like an Example script that has been automatically converted to the pyFormex Application model, but has not been checked yet as to whether it is working correctly in App mode.\nYou can help here by running and rerunning the example, checking that it works correctly, and where needed fixing it (or reporting the failure to us). If the example runs well, you can change its status to 'checked'")

    scriptLock('__auto__')
    msg = "Running application '%s' from %s" % (appname,app.__file__)
    pf.scriptName = appname
    if pf.GUI:
        pf.GUI.startRun()
        pf.GUI.apphistory.add(appname)
        pf.board.write(msg,color='green')
    else:
        message(msg)
    pf.debug("  Passing arguments: %s" % argv,pf.DEBUG.SCRIPT)
    app._args_ = argv
    try:
        try:
            res = app.run()
        except _Exit:
            pass
        except _ExitSeq:
            exitrequested = True
        except:
            raise
    finally:
        if hasattr(app,'atExit'):
            app.atExit()
        if pf.cfg['autoglobals']:
            g = app.__dict__
            exportNames = listAll(clas=Geometry,dic=g)
            pf.PF.update([(k,g[k]) for k in exportNames])
        scriptRelease('__auto__') # release the lock
        if pf.GUI:
            pf.GUI.stopRun()

    pf.debug("  Arguments left after execution: %s" % argv,pf.DEBUG.SCRIPT)
    msg = "Finished %s in %s seconds" % (appname,t.seconds())
    if pf.GUI:
        pf.board.write(msg,color='green')
    else:
        message(msg)
    pf.debug("Memory: %s" % vmSize(),pf.DEBUG.MEM)
Пример #37
0
def save(filename=None,
         window=False,
         multi=False,
         hotkey=True,
         autosave=False,
         border=False,
         grab=False,
         format=None,
         quality=-1,
         size=None,
         verbose=False,
         alpha=True,
         rootcrop=None):
    """Saves an image to file or Starts/stops multisave mode.

    With a filename and multi==False (default), the current viewport rendering
    is saved to the named file.

    With a filename and multi==True, multisave mode is started.
    Without a filename, multisave mode is turned off.
    Two subsequent calls starting multisave mode without an intermediate call
    to turn it off, do not cause an error. The first multisave mode will
    implicitely be ended before starting the second.

    In multisave mode, each call to saveNext() will save an image to the
    next generated file name.
    Filenames are generated by incrementing a numeric part of the name.
    If the supplied filename (after removing the extension) has a trailing
    numeric part, subsequent images will be numbered continuing from this
    number. Otherwise a numeric part '-000' will be added to the filename.

    If window is True, the full pyFormex window is saved.
    If window and border are True, the window decorations will be included.
    If window is False, only the current canvas viewport is saved.

    If grab is True, the external 'import' program is used to grab the
    window from the screen buffers. This is required by the border and
    window options.

    If hotkey is True, a new image will be saved by hitting the 'S' key.
    If autosave is True, a new image will be saved on each execution of
    the 'draw' function.
    If neither hotkey nor autosave are True, images can only be saved by
    executing the saveNext() function from a script.

    If no format is specified, it is derived from the filename extension.
    fmt should be one of the valid formats as returned by imageFormats()

    If verbose=True, error/warnings are activated. This is usually done when
    this function is called from the GUI.

    """
    #print "SAVE: quality=%s" % quality
    global multisave

    if rootcrop is not None:
        pf.warning("image.save does no longer support the 'rootcrop' option")

    # Leave multisave mode if no filename or starting new multisave mode
    if multisave and (filename is None or multi):
        print("Leave multisave mode")
        if multisave[6]:
            pf.GUI.signals.SAVE.disconnect(saveNext)
        multisave = None

    if filename is None:
        return

    #chdir(filename)
    name, ext = os.path.splitext(filename)
    # Get/Check format
    if not format:  # is None:
        format = checkImageFormat(imageFormatFromExt(ext))
    if not format:
        return

    if multi:  # Start multisave mode
        names = utils.NameSequence(name, ext)
        if os.path.exists(names.peek()):
            next = names.next()
        print("Start multisave mode to files: %s (%s)" % (names.name, format))
        if hotkey:
            pf.GUI.signals.SAVE.connect(saveNext)
            if verbose:
                pf.warning(
                    "Each time you hit the '%s' key,\nthe image will be saved to the next number."
                    % pf.cfg['keys/save'])
        multisave = (names, format, quality, size, window, border, hotkey,
                     autosave, grab)
        print("MULTISAVE %s " % str(multisave))
        return multisave is None

    else:
        # Save the image
        if grab:
            # Grab from X server buffers (needs external)
            #
            # TODO: configure command to grab screen rectangle
            #
            if window:
                if border:
                    windowname = 'root'
                    crop = pf.GUI.frameGeometry().getRect()
                else:
                    windowname = None
                    crop = None
            else:
                windowname = None
                crop = 'canvas'

            sta = save_window(filename,
                              format,
                              quality,
                              windowname=windowname,
                              crop=crop)
        else:
            # Get from OpenGL rendering
            if size == pf.canvas.getSize():
                # TODO:
                # We could grab from the OpenGL buffers here!!
                size = None
            # Render in an off-screen buffer and grab from there
            #
            # TODO: the offscreen buffer should be properly initialized
            # according to the current canvas
            #
            sta = save_canvas(pf.canvas, filename, format, quality, size,
                              alpha)

        if sta:
            pf.debug("Error while saving image %s" % filename, pf.DEBUG.IMAGE)
        else:
            print("Image file %s written" % filename)
        return
Пример #38
0
    def read(self,count=-1,warn_version=True):
        """Read objects from a pyFormex Geometry File.

        This function reads objects from a Geometry File until the file
        ends, or until `count` objects have been read.
        The File should have been opened for reading.

        A count may be specified to limit the number of objects read.

        Returns a dict with the objects read. The keys of the dict are the
        object names found in the file. If the file does not contain
        object names, they will be autogenerated from the file name.

        Note that PGF files of version 1.0 are no longer supported.
        The use of formats 1.1 to 1.5 is deprecated, and users are
        urged to upgrade these files to a newer format. Support for
        these formats may be removed in future.
        """
        if self.writing:
            print("File is opened for writing, not reading.")
            return {}

        self.results = OrderedDict()
        self.geometry = None # used to make sure fields follow geom block

        if Version(self.version) < Version('1.6'):
            if warn_version:
                pf.warning("This is an old PGF format (%s). We recommend you to convert it to a newer format. The geometry import menu contains an item to upgrade a PGF file to the latest format (%s)." % (self.version,GeometryFile._version_))
            return self.readLegacy(count)


        while True:
            s = self.fil.readline()

            if len(s) == 0:   # end of file
                break

            if s.startswith('#'):

                # Remove the leading '#' and space
                s = s[1:].strip()

                if s.startswith('objtype'):
                    if count > 0 and len(self.results) >= count:
                        break
                    self.readGeometry(**self.decode(s))

                elif s.startswith('field'):
                    self.readField(**self.decode(s))

                elif s.startswith('attrib'):
                    self.readAttrib(**self.decode(s))

                elif s.startswith('pyFormex Geometry File'):
                    # we have a new header line
                    self.readHeader(s)

            # Unrecognized lines are silently ignored, whether starting
            # with a '#' or not.
            # We recommend to start all comments lines with a '#' though.

        self.file.close()

        return self.results
Пример #39
0
def image2numpy(image,resize=(0,0),order='RGBA',flip=True,indexed=None,expand=None):
    """Transform an image to a Numpy array.

    Parameters:

    - `image`: a QImage or any data that can be converted to a QImage,
      e.g. the name of an image file, in any of the formats supported by Qt.
      The image can be a full color image or an indexed type. Only 32bit
      and 8bit images are currently supported.
    - `resize`: a tuple of two integers (width,height). Positive value will
      force the image to be resized to this value.
    - `order`: string with a permutation of the characters 'RGBA', defining
      the order in which the colors are returned. Default is RGBA, so that
      result[...,0] gives the red component. Note however that QImage stores
      in ARGB order. You may also specify a subset of the 'RGBA' characters,
      in which case you will only get some of the color components. An often
      used value is 'RGB' to get the colors without the alpha value.
    - `flip`: boolean: if True, the image scanlines are flipped upside down.
      This is practical because image files are usually stored in top down
      order, while OpenGL uses an upwards positive direction, requiring a
      flip to show the image upright.
    - `indexed`: True, False or None.

      - If True, the result will be an indexed image where each pixel color
        is an index into a color table. Non-indexed image data will be
        converted.

      - If False, the result will be a full color array specifying the color
        of each pixel. Indexed images will be converted.

      - If None (default), no conversion is done and the resulting data are
        dependent on the image format. In all cases both a color and a
        colortable will be returned, but the latter will be None for
        non-indexed images.

    - `expand`: deprecated, retained for compatibility

    Returns:

    - if `indexed` is False: an int8 array with shape (height,width,4), holding
      the 4 components of the color of each pixel. Order of the components
      is as specified by the `order` argument. Indexed image formats will
      be expanded to a full color array.

    - if `indexed` is True: a tuple (colors,colortable) where colors is an
      (height,width) shaped int array of indices into the colortable,
      which is an int8 array with shape (ncolors,4).

    - if `indexed` is None (default), a tuple (colors,colortable) is returned,
      the type of which depend on the original image format:

      - for indexed formats, colors is an int (height,width) array of indices
        into the colortable, which is an int8 array with shape (ncolors,4).

      - for non-indexed formats, colors is a full (height,width,4) array
        and colortable is None.
    """
    if expand is not None:
        utils.warn("depr_image2numpy_arg")
        indexed = not expand


    image = resizeImage(image,*resize)

    if indexed:
        image = image.convertToFormat(QImage.Format_Indexed8)

    h,w = image.height(),image.width()

    if image.format() in (QImage.Format_ARGB32_Premultiplied,
                          QImage.Format_ARGB32,
                          QImage.Format_RGB32):
        buf = image.bits()
        if not pf.options.pyside:
            buf = buf.asstring(image.numBytes())
        ar = np.frombuffer(buf,dtype='ubyte',count=image.numBytes()).reshape(h,w,4)
        idx = [ 'BGRA'.index(c) for c in order ]
        ar = ar[...,idx]
        ct = None

    elif image.format() == QImage.Format_Indexed8:
        ct = np.array(image.colorTable(),dtype=np.uint32)
        #print("IMAGE FORMAT is INDEXED with %s colors" % ct.shape[0])
        ct = ct.view(np.uint8).reshape(-1,4)
        idx = [ 'BGRA'.index(c) for c in order ]
        ct = ct[...,idx]
        buf = image.bits()
        if not pf.options.pyside:
            buf = buf.asstring(image.numBytes())
        ar = np.frombuffer(buf,dtype=np.uint8)
        if ar.size != w*h:
            pf.warning("Size of image data (%s) does not match the reported dimensions: %s x %s = %s" % (ar.size,w,h,w*h))
            #ar = ar[:w*h]
        ar = ar.reshape(h,-1)
        #print "IMAGE SHAPE IS %s" % str(ar.shape)

    else:
        raise ValueError("image2numpy only supports 32bit and 8bit images")

    # Put upright as expected
    if flip:
        ar = np.flipud(ar)

    # Convert indexed to nonindexed if requested
    if indexed is False and ct is not None:
            ar = ct[ar]
            ct = None

    # Return only full colors if requested
    if indexed is False:
        return ar
    else:
        return ar,ct
Пример #40
0
def updateQt4Bindings():
    pf.warning("You changed the Python Qt4 bindings setting to '%s'.\nThis setting will only become active after you restart pyFormex." % pf.cfg['gui/bindings'])
Пример #41
0
def run(args=[]):
    """The pyFormex main function.

    After pyFormex launcher script has correctly set up the Python import
    paths, this function is executed. It is responsible for reading the
    configuration file(s), processing the command line options and starting
    the application.

    The basic configuration file is 'pyformexrc' located in the pyFormex
    main directory. It should always be present and be left unchanged.
    If you want to make changes, copy (parts of) this file to another location
    where you can change them. Then make sure pyFormex reads you modifications
    file. By default, pyFormex will try to read the following
    configuration files if they are present (and in this order)::

        default settings:     <pyformexdir>/pyformexrc   (always loaded)
        system-wide settings: /etc/pyformex.conf
        user settings:        <configdir>/pyformex/pyformex.conf
        local settings        $PWD/.pyformexrc

    Also, an extra config file can be specified in the command line, using
    the --config option. The system-wide and user settings can be skipped
    by using the --nodefaultconfig option.

    Config files are loaded in the above order. Settings always override
    those loaded from a previous file.

    When pyFormex exits, the preferences that were changed are written to the
    last read config file. Changed settings are those that differ from the
    settings obtained after loading all but the last config file.
    If none of the optional config files exists, a new user settings file
    will be created, and an error will occur if the <configdir> path is
    not writable.

    """
    if pf.isString(args):
        args = args.split()

    ## Parse the arguments ##
    parseArguments(args)

    ## Process special options which do not start pyFormex ##
    if processReportOptions():
        return

    ## Migrate the user configuration files ##
    migrateUserConfig()

    ## Load the user configuration ##
    loadUserConfig()

    ## Process special options which do not start pyFormex ##
    if processReportOptions2():
        return

    ## Process options that override the config ##

    if pf.options.pyside is not None:
        pf.cfg['gui/bindings'] = 'PySide' if pf.options.pyside else 'PyQt4'

    if pf.options.redirect is not None:
        pf.cfg['gui/redirect'] = pf.options.redirect
    delattr(pf.options, 'redirect')  # avoid abuse

    utils.setSaneLocale()

    ## Check required modules ##
    software.checkModule('numpy', fatal=True)

    # Initialize the libraries
    if pf.options.uselib is None:
        pf.options.uselib = pf.cfg['uselib']
    from pyformex import lib

    # TODO:
    # without this, we get a crash. Maybe config related?
    pf.cfg['gui/startup_warning'] = None

    ## Activate the warning filters
    activateWarningFilters()

    # Make sure pf.PF is a Project
    from pyformex.project import Project
    pf.PF = Project()

    # Set application paths
    pf.debug("Loading AppDirs", pf.DEBUG.INFO)
    from pyformex import apps
    apps.setAppDirs()

    # Start the GUI if needed
    # Importing the gui should be done after the config is set !!
    # Set default --nogui if first remaining argument is a pyformex script.
    args = pf.options.args
    if pf.options.gui is None:
        pf.options.gui = not (len(args) > 0 and utils.is_pyFormex(args[0]))
    if pf.options.gui:
        if pf.options.mesa:
            os.environ['LIBGL_ALWAYS_SOFTWARE'] = '1'
        from pyformex.gui import guimain
        pf.debug("GUI version", pf.DEBUG.INFO)
        res = guimain.startGUI(args)
        if res != 0:
            print("Could not start the pyFormex GUI: %s" % res)
            return res  # EXIT

    # Display the startup warnings and messages
    if pf.startup_warnings:
        if pf.cfg['startup_warnings']:
            pf.warning(pf.startup_warnings)
        else:
            print("*** WARNING ***\n" + pf.startup_warnings +
                  "****************\n")
    if pf.startup_messages:
        print(pf.startup_messages)

    if pf.options.debuglevel & pf.DEBUG.INFO:
        # NOTE: inside an if to avoid computing the report when not printed
        pf.debug(software.reportSoftware(), pf.DEBUG.INFO)

    #
    # Qt4 may have changed the locale.
    # Since a LC_NUMERIC setting other than C may cause lots of troubles
    # with reading and writing files (formats become incompatible!)
    # we put it back to a sane setting
    #
    utils.setSaneLocale()

    # Startup done
    pf.started = True
    print("pyFormex started from %s" % pf.executable)

    # Prepend the inline script
    if pf.options.script:
        args[0:0] = ['-c', pf.options.script]

    # Prepend the autorun script
    ar = pf.cfg.get('autorun', '')
    if ar and os.path.exists(ar):
        args[0:0] = [ar]

    # remaining args are interpreted as scripts/apps and their parameters
    res = 0
    if args:
        pf.debug("Remaining args: %s" % args, pf.DEBUG.INFO)
        from pyformex.script import processArgs
        res = processArgs(args)

        if res:
            if pf.options.gui:
                print("There was an error while executing a script")
            else:
                return res  # EXIT

    else:
        pf.debug("stdin is a tty: %s" % sys.stdin.isatty(), pf.DEBUG.INFO)
        # Play script from stdin
        # Can we check for interactive session: stdin connected to terminal?
        #from script import playScript
        #playScript(sys.stdin)

    # after processing all args, and we have a gui, go into interactive mode
    if pf.options.gui and pf.app:
        res = guimain.runGUI()

        #Save the preferences that have changed
        savePreferences()

    # Exit
    return res
Пример #42
0
def image2numpy(image,
                resize=(0, 0),
                order='RGBA',
                flip=True,
                indexed=None,
                expand=None):
    """Transform an image to a Numpy array.

    Parameters:

    - `image`: a QImage or any data that can be converted to a QImage,
      e.g. the name of an image file, in any of the formats supported by Qt.
      The image can be a full color image or an indexed type. Only 32bit
      and 8bit images are currently supported.
    - `resize`: a tuple of two integers (width,height). Positive value will
      force the image to be resized to this value.
    - `order`: string with a permutation of the characters 'RGBA', defining
      the order in which the colors are returned. Default is RGBA, so that
      result[...,0] gives the red component. Note however that QImage stores
      in ARGB order. You may also specify a subset of the 'RGBA' characters,
      in which case you will only get some of the color components. An often
      used value is 'RGB' to get the colors without the alpha value.
    - `flip`: boolean: if True, the image scanlines are flipped upside down.
      This is practical because image files are usually stored in top down
      order, while OpenGL uses an upwards positive direction, requiring a
      flip to show the image upright.
    - `indexed`: True, False or None.

      - If True, the result will be an indexed image where each pixel color
        is an index into a color table. Non-indexed image data will be
        converted.

      - If False, the result will be a full color array specifying the color
        of each pixel. Indexed images will be converted.

      - If None (default), no conversion is done and the resulting data are
        dependent on the image format. In all cases both a color and a
        colortable will be returned, but the latter will be None for
        non-indexed images.

    - `expand`: deprecated, retained for compatibility

    Returns:

    - if `indexed` is False: an int8 array with shape (height,width,4), holding
      the 4 components of the color of each pixel. Order of the components
      is as specified by the `order` argument. Indexed image formats will
      be expanded to a full color array.

    - if `indexed` is True: a tuple (colors,colortable) where colors is an
      (height,width) shaped int array of indices into the colortable,
      which is an int8 array with shape (ncolors,4).

    - if `indexed` is None (default), a tuple (colors,colortable) is returned,
      the type of which depend on the original image format:

      - for indexed formats, colors is an int (height,width) array of indices
        into the colortable, which is an int8 array with shape (ncolors,4).

      - for non-indexed formats, colors is a full (height,width,4) array
        and colortable is None.
    """
    if expand is not None:
        utils.warn("depr_image2numpy_arg")
        indexed = not expand

    image = resizeImage(image, *resize)

    if indexed:
        image = image.convertToFormat(QImage.Format_Indexed8)

    h, w = image.height(), image.width()

    if image.format() in (QImage.Format_ARGB32_Premultiplied,
                          QImage.Format_ARGB32, QImage.Format_RGB32):
        buf = image.bits()
        if not pf.options.pyside:
            buf = buf.asstring(image.numBytes())
        ar = np.frombuffer(buf, dtype='ubyte',
                           count=image.numBytes()).reshape(h, w, 4)
        idx = ['BGRA'.index(c) for c in order]
        ar = ar[..., idx]
        ct = None

    elif image.format() == QImage.Format_Indexed8:
        ct = np.array(image.colorTable(), dtype=np.uint32)
        #print("IMAGE FORMAT is INDEXED with %s colors" % ct.shape[0])
        ct = ct.view(np.uint8).reshape(-1, 4)
        idx = ['BGRA'.index(c) for c in order]
        ct = ct[..., idx]
        buf = image.bits()
        if not pf.options.pyside:
            buf = buf.asstring(image.numBytes())
        ar = np.frombuffer(buf, dtype=np.uint8)
        if ar.size != w * h:
            pf.warning(
                "Size of image data (%s) does not match the reported dimensions: %s x %s = %s"
                % (ar.size, w, h, w * h))
            #ar = ar[:w*h]
        ar = ar.reshape(h, -1)
        #print "IMAGE SHAPE IS %s" % str(ar.shape)

    else:
        raise ValueError("image2numpy only supports 32bit and 8bit images")

    # Put upright as expected
    if flip:
        ar = np.flipud(ar)

    # Convert indexed to nonindexed if requested
    if indexed is False and ct is not None:
        ar = ct[ar]
        ct = None

    # Return only full colors if requested
    if indexed is False:
        return ar
    else:
        return ar, ct
Пример #43
0
def runApp(appname, argv=[], refresh=False):
    global exitrequested
    if len(pf.scriptlock) > 0:
        pf.message("!!Not executing because a script lock has been set: %s" %
                   pf.scriptlock)
        #print(pf.scriptlock)
        return

    import apps
    from timer import Timer
    t = Timer()
    pf.message("Loading application %s with refresh=%s" % (appname, refresh))
    app = apps.load(appname, refresh=refresh)
    if app is None:
        errmsg = "An  error occurred while loading application %s" % appname
        if pf.GUI:
            if apps._traceback and pf.cfg['showapploaderrors']:
                print(apps._traceback)

            from gui import draw
            fn = apps.findAppSource(appname)
            if os.path.exists(fn):
                errmsg += "\n\nYou may try executing the application as a script,\n  or you can load the source file in the editor."
                res = draw.ask(errmsg,
                               choices=[
                                   'Run as script', 'Load in editor',
                                   "Don't bother"
                               ])
                if res[0] in 'RL':
                    if res[0] == 'L':
                        draw.editFile(fn)
                    elif res[0] == 'R':
                        pf.GUI.setcurfile(fn)
                        draw.runScript(fn)
            else:
                errmsg += "and I can not find the application source file."
                draw.error(errmsg)
        else:
            error(errmsg)

        return

    if hasattr(app, '_status') and app._status == 'unchecked':
        pf.warning(
            "This looks like an Example script that has been automatically converted to the pyFormex Application model, but has not been checked yet as to whether it is working correctly in App mode.\nYou can help here by running and rerunning the example, checking that it works correctly, and where needed fixing it (or reporting the failure to us). If the example runs well, you can change its status to 'checked'"
        )

    scriptLock('__auto__')
    msg = "Running application '%s' from %s" % (appname, app.__file__)
    pf.scriptName = appname
    if pf.GUI:
        pf.GUI.startRun()
        pf.GUI.apphistory.add(appname)
        pf.board.write(msg, color='green')
    else:
        message(msg)
    pf.debug("  Passing arguments: %s" % argv, pf.DEBUG.SCRIPT)
    app._args_ = argv
    try:
        try:
            res = app.run()
        except _Exit:
            pass
        except _ExitSeq:
            exitrequested = True
        except:
            raise
    finally:
        if hasattr(app, 'atExit'):
            app.atExit()
        if pf.cfg['autoglobals']:
            g = app.__dict__
            exportNames = listAll(clas=Geometry, dic=g)
            pf.PF.update([(k, g[k]) for k in exportNames])
        scriptRelease('__auto__')  # release the lock
        if pf.GUI:
            pf.GUI.stopRun()

    pf.debug("  Arguments left after execution: %s" % argv, pf.DEBUG.SCRIPT)
    msg = "Finished %s in %s seconds" % (appname, t.seconds())
    if pf.GUI:
        pf.board.write(msg, color='green')
    else:
        message(msg)
    pf.debug("Memory: %s" % vmSize(), pf.DEBUG.MEM)