Changeset 5288


Ignore:
Timestamp:
May 25, 2022 6:12:19 PM (4 months ago)
Author:
toby
Message:

add routines to install gsl and/or diffpy.pdffit2, possibly in a separate environment; add more binaries to the libraries

Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/GSASIIpath.py

    r5285 r5288  
    4848   
    4949    :param str key: a value to be found in the configuration (config.py) file
    50     :param default: a value to be supplied is none is in the config file or
     50    :param default: a value to be supplied if none is in the config file or
    5151      the config file is not found. Defaults to None
    5252    :returns: the value found or the default.
     
    13271327        sys.exit()
    13281328       
    1329 def condaTest():
     1329def condaTest(requireAPI=False):
    13301330    '''Returns True if it appears that Python is being run under Anaconda
    13311331    Python with conda present. Tests for conda environment vars and that
     
    13351335    '''   
    13361336    if not all([(i in os.environ) for i in ('CONDA_DEFAULT_ENV','CONDA_EXE', 'CONDA_PREFIX', 'CONDA_PYTHON_EXE')]): return False
    1337     # is the conda package available?
    1338     try:
    1339         import conda.cli.python_api
    1340     except:
    1341         print('You do not have the conda package installed in this environment',
     1337    if requireAPI:
     1338        # is the conda package available?
     1339        try:
     1340            import conda.cli.python_api
     1341        except:
     1342            print('You do not have the conda package installed in this environment',
    13421343                  '\nConsider using the "conda install conda" command')
    1343         return False
     1344            return False
    13441345
    13451346    # There is no foolproof way to check if someone activates conda
     
    13571358    # python we are running in shares the beginning part of its path with
    13581359    # the one in the base installation:
    1359     return commonPath(os.environ['CONDA_PYTHON_EXE'],sys.executable)
     1360    dir1 = os.path.dirname(os.environ['CONDA_PYTHON_EXE'])
     1361    dir2 = os.path.dirname(sys.executable)
     1362    if sys.platform != "win32": # python in .../bin/..
     1363        dir1 = os.path.dirname(dir1)
     1364        dir2 = os.path.dirname(dir2)   
     1365    return commonPath(dir1,dir2)
    13601366
    13611367def condaInstall(packageList):
     
    13751381      if it did not.
    13761382    '''
    1377     import conda.cli.python_api
     1383    try:
     1384        import conda.cli.python_api
     1385    except:
     1386        print('You do not have the conda package installed in this environment',
     1387                  '\nConsider using the "conda install conda" command')
     1388        return None
    13781389    try:
    13791390        (out, err, rc) = conda.cli.python_api.run_command(
     
    14051416    return out
    14061417
    1407 def commonPath(file1,file2):
    1408     '''Check if two files share the same path. Note that paths
    1409     are considered the same if either file is in a subdirectory
     1418def commonPath(dir1,dir2):
     1419    '''Check if two directories share a path. Note that paths
     1420    are considered the same if either directory is a subdirectory
    14101421    of the other, but not if they are in different subdirectories
    1411     /a/b/c/x.x and  /a/b/c/y.y share a path, as does  /a/b/c/d/y.y
    1412     but  /a/b/c/d/x.x and  /a/b/c/e/x.x do not.
     1422    /a/b/c shares a path with /a/b/c/d but /a/b/c/d and /a/b/c/e do not.
    14131423
    14141424    :returns: True if the paths are common
    14151425    '''
    14161426
    1417     for i,j in zip(fullsplit(os.environ['CONDA_PYTHON_EXE']),
    1418                fullsplit(sys.executable)):
     1427    for i,j in zip(fullsplit(dir1),fullsplit(dir2)):
    14191428        if i != j: return False
    14201429    return True
     
    14431452    return None
    14441453   
     1454def condaEnvCreate(envname, packageList, force=False):
     1455    '''Create a Python interpreter in a new conda environment. Use this
     1456    when there is a potential conflict between packages and it would
     1457    be better to keep the packages separate (which is one of the reasons
     1458    conda supports environments). Note that conda should be run from the
     1459    case environment; this attempts to deal with issues if it is not.
     1460
     1461    :param str envname: the name of the environment to be created.
     1462      If the environment exists, it will be overwritten only if force is True.
     1463    :param list packageList: a list of conda install create command
     1464      options, such as::
     1465
     1466            ['python=3.7', 'conda', 'gsl', 'diffpy.pdffit2',
     1467                '-c', 'conda-forge', '-c', 'diffpy']
     1468
     1469    :param bool force: if False (default) an error will be generated
     1470      if an environment exists
     1471
     1472    :returns: (status,msg) where status is True if an error occurs and
     1473      msg is a string with error information if status is True or the
     1474      location of the newly-created Python interpreter.
     1475    '''
     1476    if not all([(i in os.environ) for i in ('CONDA_DEFAULT_ENV',
     1477                            'CONDA_EXE', 'CONDA_PREFIX', 'CONDA_PYTHON_EXE')]):
     1478        return True,'not running under conda?'
     1479    try:
     1480        import conda.cli.python_api
     1481    except:
     1482        return True,'conda package not available (in environment)'
     1483    # workaround for bug that avoids nesting packages if running from an
     1484    # environment (see https://github.com/conda/conda/issues/11493)
     1485    p = os.path.dirname(os.path.dirname(os.environ['CONDA_EXE']))
     1486    if not os.path.exists(os.path.join(p,'envs')):
     1487        msg = ('Error derived installation path not found: '+
     1488                  os.path.join(p,'envs'))
     1489        print(msg)
     1490        return True,msg
     1491    newenv = os.path.join(p,'envs',envname)
     1492    if os.path.exists(newenv) and not force:
     1493        msg = 'path '+newenv+' already exists and force is not set, aborting'
     1494        print(msg)
     1495        return True,msg
     1496    pathList = ['-p',newenv]
     1497    try:
     1498        (out, err, rc) = conda.cli.python_api.run_command(
     1499            conda.cli.python_api.Commands.CREATE,
     1500            packageList + pathList,
     1501    use_exception_handler=True, stdout=sys.stdout, stderr=sys.stderr
     1502            )
     1503        #print('rc=',rc)
     1504        #print('out=',out)
     1505        #print('err=',err)
     1506        if rc != 0: return True,str(out)
     1507        if sys.platform == "win32":
     1508            newpython = os.path.join(newenv,'python.exe')
     1509        else:
     1510            newpython = os.path.join(newenv,'bin','python')
     1511        if os.path.exists(newpython):
     1512            return False,newpython
     1513        return True,'Unexpected, '+newpython+' not found'
     1514    except Exception as msg:
     1515        print("Error occurred, see below\n",msg)
     1516        return True,'Error: '+str(msg)
     1517   
     1518def addCondaPkg():
     1519    '''Install the conda API into the current conda environment using the
     1520    command line, so that the API can be used in the current Python interpreter
     1521
     1522    Attempts to do this without a shell failed on the Mac because it seems that
     1523    the environment was inherited; seems to work w/o shell on Windows.
     1524    '''
     1525    if not all([(i in os.environ) for i in ('CONDA_DEFAULT_ENV','CONDA_EXE',
     1526                        'CONDA_PREFIX', 'CONDA_PYTHON_EXE')]):
     1527        return None
     1528    condaexe = os.environ['CONDA_EXE']
     1529    currenv = os.environ['CONDA_DEFAULT_ENV']
     1530    if sys.platform == "win32":
     1531        cmd = [os.environ['CONDA_EXE'],'install','conda','-n',currenv,'-y']
     1532        p = subprocess.Popen(cmd,
     1533                         #stdout=subprocess.PIPE,
     1534                         stderr=subprocess.PIPE)
     1535    else:
     1536        script = 'source ' + os.path.join(
     1537            os.path.dirname(os.environ['CONDA_PYTHON_EXE']),
     1538            'activate') + ' base; '
     1539        script += 'conda install conda -n '+currenv+' -y'
     1540        p = subprocess.Popen(script,shell=True,env={},
     1541                         #stdout=subprocess.PIPE,
     1542                         stderr=subprocess.PIPE)
     1543    out,err = MakeByte2str(p.communicate())
     1544    #print('Output from adding conda:\n',out)
     1545    if err:
     1546        print('Note error/warning:')
     1547        print(err)
     1548    if currenv == "base":
     1549        print('\nUnexpected action: adding conda to base environment???')
     1550
    14451551if __name__ == '__main__':
    14461552    '''What follows is called to update (or downdate) GSAS-II in a separate process.
  • trunk/GSASIIphsGUI.py

    r5285 r5288  
    9191acosd = lambda x: 180.*np.arccos(x)/np.pi
    9292atan2d = lambda x,y: 180.*np.arctan2(y,x)/np.pi
     93is_exe = lambda fpath: os.path.isfile(fpath) and os.access(fpath, os.X_OK)
    9394
    9495# previous rigid body selections
     
    1459914600    # See if if we can import the GSAS-II supplied PDFfit
    1460014601    pdffitloc = os.path.join(GSASIIpath.path2GSAS2,'PDFfit2')
     14602    print(pdffitloc,'\n',GSASIIpath.binaryPath)
    1460114603    if pdffitloc not in sys.path: sys.path.append(pdffitloc)
    1460214604    try:
     
    1460614608    except Exception as err:
    1460714609        pass
    14608         #print('Failed to import PDFfit2 with error\n:'+str(err))
     14610        #print('Failed to import PDFfit2 with error:\n'+str(err))
    1460914611   
    1461014612    if not os.path.exists(pdffitloc):
    1461114613        print('PDFfit2 not found in GSAS-II \n\t(expected in '+pdffitloc+')')
    1461214614        return False
     14615
    1461314616    import glob
    14614     if not glob.glob(os.path.join(GSASIIpath.binaryPath,'pdffit*')):
    14615         msg = 'GSAS-II does not supply PDFfit2 for the version of Python that you are using'
    14616         G2G.G2MessageBox(G2frame,msg,'Need PDFfit2')
     14617    # see if we can fix things so the GSAS-II version can be used
     14618    if not GSASIIpath.condaTest() and glob.glob(os.path.join(GSASIIpath.binaryPath,'pdffit*')):
     14619        msg = ('GSAS-II supplies a version of PDFfit2 that should be compatible with '+
     14620        'this Python installation. Since Python was not installed under conda you need '+
     14621        'to correct this for yourself. You likely need to '+
     14622        'install GSL (GNU Software Library).')
     14623        G2G.G2MessageBox(G2frame,msg,'PDFfit2 will not load; No conda')
    1461714624        return False
    14618 
    14619     # see if we can fix things so the GSAS-II version can be used
    14620     if not GSASIIpath.condaTest():
    14621         msg = ('PDFfit2 is not running with this Python installation. '+
    14622         'Since Python was not installed under conda you need to install this yourself. '+
    14623         'pip install diffpy.pdffit2" may do this for you. You will likely need to '+
    14624         'install the GSL (GNU Software Library).')
    14625         G2G.G2MessageBox(G2frame,msg,'No conda')
     14625    elif not GSASIIpath.condaTest():
     14626        msg = ('GSAS-II does not supply a version of PDFfit2 compatible with '+
     14627        'this Python installation. Since Python was not installed under conda you need '+
     14628        'to correct this for yourself. You likely need to '+
     14629        'install the GSL (GNU Software Library) and use "pip install diffpy.pdffit2".')
     14630        G2G.G2MessageBox(G2frame,msg,'PDFfit2 not provided; No conda')
    1462614631        return False
    14627     # can we access conda?
    14628     try:
     14632
     14633    try:     # have conda. Can we access it programmatically?
    1462914634        import conda.cli.python_api
    1463014635    except:
    14631         msg = ('You do not have the conda package installed in this '+
    14632                 'environment so nothing can be installed.',
    14633                 '\n\nConsider using the "conda install conda" command')
    14634         G2G.G2MessageBox(G2frame,msg,'conda import error')
    14635         return False
    14636    
     14636        if not glob.glob(os.path.join(GSASIIpath.binaryPath,'pdffit*')):
     14637            msg = 'GSAS-II does not supply PDFfit2 for the version of Python that you are using'
     14638        else:
     14639            msg = 'GSAS-II supplies PDFfit2 that should be compatible with the version of Python that you are using. The problem is likely that the GSL package needs to be installed.'
     14640        msg += ('\n\nYou do not have the conda package installed in this '+
     14641                    'environment. This is needed for GSAS-II to install software.'+
     14642                    '\n\nDo you want to have conda installed for you?')
     14643        dlg = wx.MessageDialog(G2frame,msg,caption='Install?',
     14644                                   style=wx.YES_NO|wx.ICON_QUESTION)
     14645        if dlg.ShowModal() != wx.ID_YES:
     14646            dlg.Destroy()
     14647            return False
     14648        dlg.Destroy()
     14649        try:
     14650            wx.BeginBusyCursor()
     14651            print('Preparing to install conda. This may take a few minutes...')
     14652            GSASIIpath.addCondaPkg()
     14653        finally:
     14654            wx.EndBusyCursor()
     14655        try:     # have conda. Can we access it programmatically?
     14656            import conda.cli.python_api
     14657        except:
     14658            print('command line conda install did not provide package. Unexpected!')
     14659            return False
     14660       
    1463714661    if 'gsl' not in conda.cli.python_api.run_command(conda.cli.python_api.Commands.LIST,'gsl')[0].lower():
    1463814662        msg = ('The gsl (GNU Software Library), needed by PDFfit2, '+
     
    1464414668            return False
    1464514669        dlg.Destroy()
    14646         wx.BeginBusyCursor()
    14647         print('Preparing to install gsl. This may take a few minutes...')
    14648         res = GSASIIpath.condaInstall(['gsl'])
    14649         wx.EndBusyCursor()
     14670
     14671        try:
     14672            wx.BeginBusyCursor()
     14673            print('Preparing to install gsl. This may take a few minutes...')
     14674            res = GSASIIpath.condaInstall(['gsl','-c','conda-forge'])
     14675        finally:
     14676            wx.EndBusyCursor()
    1465014677        if res:
    1465114678            msg = 'Installation of the GSL package failed with error:\n' + str(res)
     
    1465714684        from diffpy.pdffit2 import PdfFit
    1465814685        #pf = PdfFit()
     14686        return True
    1465914687    except Exception as err:
    14660         msg = 'Failed to import PDFfit2 with error\n:'+str(err)
     14688        msg = 'Failed to import PDFfit2 with error:\n'+str(err)
    1466114689        G2G.G2MessageBox(G2frame,msg,'PDFfit2 import error')
     14690
     14691    # can we install pdffit2 into our current environment?
     14692    msg = ('Do you want to try using conda to install PDFfit2 into the '+
     14693                'current Python (conda) environment, freezing the current '+
     14694               'configuration? (There is a low chance for success with this.)'+
     14695               ' The alternative is to install PDFfit2 in a separate environment.'+
     14696               ' This will be offered next')
     14697    dlg = wx.MessageDialog(G2frame,msg,caption='Install?',
     14698                                   style=wx.YES_NO|wx.ICON_QUESTION)
     14699    if dlg.ShowModal() == wx.ID_YES:
     14700        try:
     14701            wx.BeginBusyCursor()
     14702            print('Preparing to install diffpy.pdffit. This may take a few minutes...')
     14703            res = GSASIIpath.condaInstall(['diffpy.pdffit2','gsl',
     14704                                        '-c','diffpy','-c','conda-forge',
     14705                                           '--freeze-installed'])
     14706        finally:
     14707            wx.EndBusyCursor()
     14708        try: # PDFfit now runs?
     14709            from diffpy.pdffit2 import PdfFit
     14710            #pf = PdfFit()
     14711            return True
     14712        except Exception as err:
     14713            msg = 'Failed to import PDFfit2 with error:\n'+str(err)
     14714            print(msg)
     14715
     14716    # Last effort: With conda we should be able to create a separate Python in a separate
     14717    # environment
     14718    msg = ('Do you want to try using conda to install PDFfit2 into a separate environment? '+
     14719               '\n\nIf successful, the pdffit2_exec configuration option will be set to the '+
     14720               'this new Python environment.')
     14721    dlg = wx.MessageDialog(G2frame,msg,caption='Install?',
     14722                                   style=wx.YES_NO|wx.ICON_QUESTION)
     14723    if dlg.ShowModal() != wx.ID_YES:
    1466214724        return False
    14663     return True
     14725    try:
     14726        wx.BeginBusyCursor()
     14727        print('Preparing to create a conda environment. This may take a few minutes...')
     14728        res,PDFpython = GSASIIpath.condaEnvCreate('pdffit2',
     14729                    ['python=3.7', 'conda', 'gsl', 'diffpy.pdffit2',
     14730                         '-c', 'conda-forge', '-c', 'diffpy'])
     14731    finally:
     14732        wx.EndBusyCursor()
     14733    if os.path.exists(PDFpython):
     14734        vars = G2G.GetConfigValsDocs()
     14735        vars['pdffit2_exec'][1] = PDFpython
     14736        GSASIIpath.SetConfigValue(vars)
     14737        G2G.SaveConfigVars(vars)
     14738        print('config',GSASIIpath.GetConfigValue('pdffit2_exec'))
     14739        return True
     14740    else:
     14741        msg = 'Failed to install PDFfit2 with error:\n'+str(PDFpython)
     14742        print(msg)
     14743        G2G.G2MessageBox(G2frame,
     14744            'Install failed. See console for error message\n\n'+
     14745            'All attempts to install PDFfit2 have failed. '+
     14746            'Do you have write access to where GSAS-II is installed?',
     14747            'PDFfit2 install error')
     14748        return False
  • trunk/GSASIIpwd.py

    r5285 r5288  
    33303330    PDFfit_exe,PDFfit_path = findPDFfit()  # returns python loc and path(s) for pdffit
    33313331    if not PDFfit_exe:
    3332         GSASIIpath.IPyBreak()
    3333         return None
    3334     for p in PDFfit_path:
    3335         rundata += "sys.path.append(r'{:}')\n".format(p)
     3332        print('PDFfit2 is not found. Creating .sh file without paths.')
     3333    if PDFfit_path:
     3334        for p in PDFfit_path:
     3335            rundata += "sys.path.append(r'{:}')\n".format(p)
    33363336    rundata += 'from diffpy.pdffit2 import PdfFit\n'
    33373337    rundata += 'pf = PdfFit()\n'
  • trunk/docs/source/packages.rst

    r5285 r5288  
    6161  GSAS-II to download updates to our code. This can be skipped if svn
    6262  is installed directly (easy Linux, but a bit harder on MacOS and
    63   Windows).
     63  Windows). In conda-forge this package is called subversion, but at
     64  present is only available for Linux.
     65* pywin32 (windows only): this provides the win32com module that is
     66  used to install GSAS-II on windows machines. GSAS-II can be used on
     67  Windows without this, but the installation will offer less
     68  integration into Windows.
    6469* conda: the conda package allows access to conda features from
    6570  inside Python. It will be used inceasingly by GSAS-II to
     
    7378  Python interpreter::
    7479
    75     conda install wxpython numpy scipy matplotlib pyopengl pillow h5py imageio svn -c conda-forge
    76    
    77   or to use a separate environment (here named ``g2python``), use::
    78 
    79     conda install -n g2python wxpython numpy scipy matplotlib pyopengl pillow h5py imageio svn conda -c conda-forge
    80 
     80    conda install python=3.9 wxpython numpy scipy matplotlib pyopengl pillow h5py imageio subversion -c conda-forge
     81   
     82  or to put a Python configured for GSAS-II into a separate conda
     83  environment (here named ``g2python``, but any name can be used), use
     84  command::
     85
     86    conda create -n g2python python=3.9 wxpython numpy scipy matplotlib pyopengl  pillow h5py imageio conda subversion -c conda-forge
     87
     88Note that at present the subversion is only available for Linux, so
     89that should be removed from the commands above. For windows add pywin32
     90Also, while there is no
     91reason why GSAS-II should not run with Python 3.10, we are not yet
     92providing binaries for this.
     93   
    8194Remember to activate using: ``<path>\Scripts\activate``  (windows);
    8295``source <path>/bin/activate`` (Mac/Linux). Note that one should add
Note: See TracChangeset for help on using the changeset viewer.