예제 #1
0
def read_outcar(FileName, InitialStep):
    #read poscar file
    print('Reading outcar file ', FileName, ' from initial step ', InitialStep)
    switch = False
    flagrprimd = -1
    iatom = -1
    istep = 0
    MyCrystal = cr.Lattice()
    TimeStep = 1.0
    newfile = FileName + '.umd.dat'
    nf = open(newfile, 'w')
    nf.close()
    atomictype = 0
    CurrentTime = 0.0
    TimeStep = 0.0
    with open(FileName, 'r') as ff:
        while True:
            line = ff.readline()
            if not line: break
            line = line.strip()
            entry = line.split()
            if (len(entry) > 0):
                if (entry[0] == 'ions'):  #determine how many atoms
                    jatom = 0
                    MyCrystal.natom = 0
                    MyCrystal.ntypat = len(entry) - 4
                    MyCrystal.types = [0 for _ in range(MyCrystal.ntypat)]
                    for ii in range(len(entry) - 4):
                        MyCrystal.natom = MyCrystal.natom + int(entry[4 + ii])
                        MyCrystal.types[ii] = int(entry[4 + ii])

                    MyCrystal.typat = [0 for _ in range(MyCrystal.natom)]
                    for ii in range(len(entry) - 4):
                        atomictype += 1
                        for jj in range(int(entry[4 + ii])):
                            MyCrystal.typat[jatom] = atomictype - 1
                            jatom = jatom + 1
                    MyCrystal.atoms = [
                        cr.Atom() for _ in range(MyCrystal.natom)
                    ]
                    oldpos = [cr.Atom() for _ in range(MyCrystal.natom)]
                    MyCrystal.elements = ['X' for _ in range(MyCrystal.ntypat)]
                    MyCrystal.masses = [0.0 for _ in range(MyCrystal.ntypat)]
                    MyCrystal.zelec = [0.0 for _ in range(MyCrystal.ntypat)]
                    MyCrystal.stress = [0.0 for _ in range(6)]
                    phase = [[0.0, 0.0, 0.0] for _ in range(MyCrystal.natom)]
                    diffcoords = [[0.0, 0.0, 0.0]
                                  for _ in range(MyCrystal.natom)]
                    MyCrystal.magnetization = 0.0
                    print('Total number of atoms = ', len(diffcoords))
                    break
    ff.close()
    flagmass = 0
    flagtitle = 0
    atn = ''
    ats = ''
    atno = ''
    with open(FileName, 'r') as ff:
        while True:
            line = ff.readline()
            if not line: break
            line = line.strip()
            entry = line.split()
            if (len(entry) > 0):
                if (len(entry) > 1):
                    if entry[1] == 'Iteration':
                        break
#                if (entry[0]=='VRHFIN'):
#                    flagtitle += 1
#                    atomicsymbol = entry[1]
#                    MyCrystal.elements[flagtitle-1] = atomicsymbol[1:-1]
#                    print ('element ',flagtitle,' is ',MyCrystal.elements[flagtitle-1])
#                    (atn,ats,atno,MyCrystal.masses[flagtitle-1])=cr.Elements2rest(MyCrystal.elements[flagtitle-1])
#                    print ('just chekcing: ',atn,ats,atno)
                if (entry[0] == 'POTCAR:'):
                    if (flagtitle < MyCrystal.ntypat):
                        MyCrystal.elements[flagtitle] = entry[2].split('_')[0]
                        #                        print ('element ',flagtitle,' is ',MyCrystal.elements[flagtitle])
                        (atn, ats, atno,
                         MyCrystal.masses[flagtitle]) = cr.Elements2rest(
                             MyCrystal.elements[flagtitle])
                        #                        print ('just chekcing: ',atn,ats,atno)
                        print('element ', flagtitle, ' is ',
                              MyCrystal.elements[flagtitle],
                              ' with atomic number ', atno, ' and mass ',
                              MyCrystal.masses[flagtitle])
                        flagtitle += 1
                if (entry[0] == 'POMASS'):
                    if flagmass < MyCrystal.ntypat:
                        #                        print('flagmass is',flagmass,' with the line ',entry)
                        #                        for ii in range(MyCrystal.ntypat):
                        MyCrystal.masses[flagmass] = float(entry[2][:-1])
                        MyCrystal.zelec[flagmass] = float(entry[5])
                        flagmass += 1
#                if (entry[0]=='ZVAL'):
#                    for ii in range(MyCrystal.ntypat):
#                        MyCrystal.zelec[ii]=float(entry[ii+2])
#                if (entry[0]=='Mass'):
#                    flagmass=1
                if (entry[0] == 'NELECT'):
                    MyCrystal.noelectrons = float(entry[2])

    ff.close()
    umd.print_header(FileName, MyCrystal)
    with open(FileName, 'r') as ff:
        while True:
            line = ff.readline()
            if not line: break
            line = line.strip()
            entry = line.split()
            if (len(entry) == 6):
                #                print ('a line of 6 elements: ',entry)
                if (entry[4] == 'magnetization'):
                    #                    print ('the line of 6 elements: ',entry)
                    MyCrystal.magnetization = float(entry[5])
            if (switch == False):
                if (len(entry) > 0 and entry[0] == 'POTIM'):
                    TimeStep = float(entry[2])
                if (len(entry) >= 2 and entry[1] == 'aborting'):
                    switch = True
                else:
                    continue
            if (switch == True and len(entry) > 0):
                #                print 'entry[0] is ',entry[0]
                jatom = 0
                if (
                        entry[0] == 'Total+kin.'
                ):  #reading stress tensor, corrected for the internal kinetic pressure (the term contains it itself0
                    for ii in range(6):
                        MyCrystal.stress[ii] = float(
                            entry[ii +
                                  1]) / 10.0  #transforms from kbars into GPa
                    MyCrystal.pressure = (
                        float(entry[1]) + float(entry[2]) + float(entry[3])
                    ) / 30.0  #transforms also from kbars into GPa
                if entry[0] == 'energy':
                    if entry[
                            2] == 'entropy=':  #reading Kohn-Sham energy, contains all the electronic energy without the electronic entropy
                        MyCrystal.internalenergy = float(
                            entry[3]
                        )  #this leads only part of the internal energy, one should add the kinetic energy of ions
                        #the variance of {this energy + kinetic energy of ions}  yields Cv
                if (entry[0] == '%'):
                    if (
                            entry[1] == 'ion-electron'
                    ):  #the term T*Sel in the formula F = E - T*Sel, with F = Kohn-Sham energy and E = Kohn-Sham energy without the electronic entropy
                        MyCrystal.electronicentropy = MyCrystal.internalenergy - float(
                            entry[4])
                if (entry[0] == 'magnetization'
                    ):  #reading magnetization of individual atoms
                    #print('reading magnetization')
                    line = ff.readline()
                    line = ff.readline()
                    line = ff.readline()
                    for ii in range(MyCrystal.natom):
                        line = ff.readline()
                        line = line.strip()
                        entry = line.split()
                        MyCrystal.atoms[ii].magnet = float(entry[len(entry) -
                                                                 1])
                        #print ('for atom ',iatom,' magnetization is ',MyCrystal.atoms[ii].magnet)


#                if (len(entry) == 6):
#                    print ('a line of 6 elements: ',entry)
#                    if (entry[0] == 'number'):
#                        print ('the line of 6 elements: ',entry)
#                        MyCrystal.magnetization = float(entry[5])
                if line == 'total charge':  #reading the atomi charges
                    #print('reading magnetization')
                    line = ff.readline()
                    line = ff.readline()
                    line = ff.readline()
                    for ii in range(MyCrystal.natom):
                        line = ff.readline()
                        line = line.strip()
                        entry = line.split()
                        MyCrystal.atoms[ii].charge = float(entry[len(entry) -
                                                                 1])
                if (entry[0] == 'kinetic'):  #reading kinetic energy of ions
                    if (len(entry) > 2):
                        if (entry[2] == 'EKIN'):
                            MyCrystal.kineticenergy = float(entry[4])
                if (entry[0] == 'total'):  #reading energy
                    #KS energy + thermostat + ion-kinetic terms
                    #used to check the drift in energy over a simulation
                    if (len(entry) > 2):
                        if (entry[2] == 'ETOTAL'):
                            MyCrystal.energywithdrift = float(entry[4])
                            #ETOTAL is the last value we want to take in the umd, so we can put the switch off and increase the counter of steps
                            #Once istep >= InitialStep, we can compute the velocities, diffcoord etc. and print the umd
                            switch = False
                            istep = istep + 1
                            if istep >= InitialStep:
                                #print (' treating step no. ', istep)
                                for jatom in range(MyCrystal.natom):
                                    for ii in range(3):
                                        jump = MyCrystal.atoms[jatom].xcart[
                                            ii] - oldpos[jatom].xcart[ii]
                                        if jump > MyCrystal.acell[ii] / 2:
                                            #print ('positive jump',jump,jatom,MyCrystal.atoms[jatom].xcart[ii],oldpos[jatom].xcart[ii])
                                            phase[jatom][
                                                ii] = phase[jatom][ii] - (
                                                    MyCrystal.rprimd[ii][0] +
                                                    MyCrystal.rprimd[ii][1] +
                                                    MyCrystal.rprimd[ii][2])
                                            diffcoords[jatom][
                                                ii] = MyCrystal.atoms[
                                                    jatom].xcart[ii] + phase[
                                                        jatom][ii]
                                            jump = jump - (
                                                MyCrystal.rprimd[ii][0] +
                                                MyCrystal.rprimd[ii][1] +
                                                MyCrystal.rprimd[ii][2])
                                        elif jump < -MyCrystal.acell[ii] / 2:
                                            #print ('negatie jump',jump,jatom,MyCrystal.atoms[jatom].xcart[ii],oldpos[jatom].xcart[ii])
                                            phase[jatom][
                                                ii] = phase[jatom][ii] + (
                                                    MyCrystal.rprimd[ii][0] +
                                                    MyCrystal.rprimd[ii][1] +
                                                    MyCrystal.rprimd[ii][2])
                                            jump = jump + (
                                                MyCrystal.rprimd[ii][0] +
                                                MyCrystal.rprimd[ii][1] +
                                                MyCrystal.rprimd[ii][2])
                                            diffcoords[jatom][
                                                ii] = MyCrystal.atoms[
                                                    jatom].xcart[ii] + phase[
                                                        jatom][ii]
                                        else:
                                            diffcoords[jatom][
                                                ii] = MyCrystal.atoms[
                                                    jatom].xcart[ii] + phase[
                                                        jatom][ii]
                                        MyCrystal.atoms[jatom].vels[
                                            ii] = jump / TimeStep
                                        for jj in range(3):
                                            MyCrystal.atoms[jatom].xred[
                                                ii] = MyCrystal.atoms[jatom].xred[
                                                    ii] + MyCrystal.gprimd[ii][
                                                        jj] * MyCrystal.atoms[
                                                            jatom].xcart[ii]
                                            while MyCrystal.atoms[jatom].xred[
                                                    ii] >= 1.0:
                                                MyCrystal.atoms[jatom].xred[
                                                    ii] = MyCrystal.atoms[
                                                        jatom].xred[ii] - 1.0
                                (CurrentTime, TimeStep) = umd.print_snapshots(
                                    FileName, MyCrystal, TimeStep,
                                    (istep - InitialStep) * TimeStep,
                                    diffcoords)
                if (entry[0] == 'kin.'):  #reading the temperature
                    if len(entry) == 7:
                        MyCrystal.temperature = float(entry[5])
                    elif len(entry) == 6:
                        mixedtemp = entry[4]
                        MyCrystal.temperature = float(mixedtemp[-8:])
                    else:
                        print('defect on the temperature line', entry)
                if (flagrprimd > -1):  #reaeding the unit cell
                    #                    print 'entries are ',entry
                    MyCrystal.rprimd[flagrprimd][0] = float(
                        entry[0].split(',')[0])
                    MyCrystal.rprimd[flagrprimd][1] = float(
                        entry[1].split(',')[0])
                    MyCrystal.rprimd[flagrprimd][2] = float(
                        entry[2].split(')')[0])
                    MyCrystal.acell[flagrprimd] = math.sqrt(
                        MyCrystal.rprimd[flagrprimd][0] *
                        MyCrystal.rprimd[flagrprimd][0] +
                        MyCrystal.rprimd[flagrprimd][1] *
                        MyCrystal.rprimd[flagrprimd][1] +
                        MyCrystal.rprimd[flagrprimd][2] *
                        MyCrystal.rprimd[flagrprimd][2])
                    flagrprimd = flagrprimd + 1
                if (flagrprimd == 3):
                    MyCrystal.gprimd = MyCrystal.makegprimd()
                    #MyCrystal.cellvolume = MyCrystal.makevolume()
                    MyCrystal.density = MyCrystal.getdensity()
                    #print('gprimd  ',MyCrystal.gprimd)
                    #print(MyCrystal.cellvolume)
                    flagrprimd = -1
                if (entry[0] == 'direct'):
                    flagrprimd = flagrprimd + 1
                if (iatom > -1):  #reading the atomic positions
                    #print ('current iatom is ',iatom)
                    MyCrystal.atoms[iatom].xred = [0.0, 0.0, 0.0]
                    MyCrystal.atoms[iatom].vels = [0.0, 0.0, 0.0]
                    oldpos[iatom].xcart = MyCrystal.atoms[iatom].xcart
                    MyCrystal.atoms[iatom].xcart = [
                        float(entry[0]),
                        float(entry[1]),
                        float(entry[2])
                    ]
                    MyCrystal.atoms[iatom].forces = [
                        float(entry[3]),
                        float(entry[4]),
                        float(entry[5])
                    ]
                    iatom = iatom + 1
                    if (iatom == MyCrystal.natom):
                        iatom = -1
                if (entry[0] == 'POSITION'):
                    line = ff.readline()
                    iatom = 0
    return (CurrentTime, TimeStep)
def main(argv):
    """     ********* Main program *********     """
    #other dictionnaries and parameters for the figure
    markers = ['o','^','*','P','X','<','>','v','8','s','p','h','+','D'] #************************************Be sure you have enough markers for all the pairs you want to plot
    colors_T = {'T2':'#800080','T3':'#297fff','T4':'#00ff00','T4.5':'#bae200','T5':'#ffcd01','T5.5':'#ff6e00','T6':'#ff0101','T6.5':'#ff00a2','T7':'#ff01de','T7.5':'#ffa6f4','T10':'#ffe86e','T15':'#ffbf90','T20':'#ff7788'}
    plot_parameters = {"size_fonts" : 12,"size_font_ticks":10,"size_figure" : (4,4),"size_markers" : 8,"size_lines" : 1,"shift_labelpad" : 20}
    label = {'xmax':r"1st $g(r)$ peak location ($\AA$)",'xmin':r"Coordination sphere radius ($\AA$)",'bond':r"Bond length ($\AA$)"}
    #initialization of variables
    bondanalysis = 0
    elements = ''
    number = ''
    atoms = []
    legend_labels = {} 
    data = {} #big dictionnary with inside dist dictionnary and rho, all coresponding to different T
    distance_columns = {'xmax':1,'xmin':3,'bond':5}
    #other parameters
    Na=6.022*10**23
    try:
        options,arg = getopt.getopt(argv,"hg:a:d:b:",["gofrsfilename","atom","distance",'bondanalysis'])
    except getopt.GetoptError:
        print("plot_distances+analysis_xmin.py -g <_gofrs.txt> -a <pairs of atoms>(ex: 'Ca-O,Ca-Ca,O2')  -d <distance type to print ('xmax' or 'xmin' or 'bond')> -b <=1 if analysis and update of bondfiles, default =0>")
        sys.exit()
    for opt,arg in options:
        if opt == '-h':
            print('')
            print('plot_distances+analysis_xmin.py program to plot xmin,xmax or bond length as a function of density or acell for each T and all the selected pairs of atoms')
            print("plot_distances+analysis_xmin.py -g <_gofrs.txt> -a <pairs of atoms>(ex: 'Ca-O,Ca-Ca,O2')  -d <distance type to print ('xmax' or 'xmin' or 'bond')> -b <=1 if analysis and update of bondfiles, default =0>")
            print("plot_distances+analysis_xmin.py requires _gofrs.txt file (use analyze_gofrs_semi_automatic.py)")
            print('')
            print('WARNING: this script use the filenames inside the _gofrs.txt file to extract the temperature and cell size for the plot. If you do have both information in your filenames at the same place, then update the function split_name to extract them correctly.')
            sys.exit()
        if opt in ('-g','--gofrsfilename'):
            filename = str(arg)
        elif opt in ('-a','--atoms'):
            atoms = arg.split(',')                      #list of atom pairs we want to analyze here
        elif opt in ('-d','--distance'):
            distance_type = str(arg)
        elif opt in ('-b','--bondanalysis'):
            bondanalysis = int(arg)
    #******* 1st step: read the header and extract all relevant informations
    #creation of elements and number lists and initialization of T
    skip_head = 0
    with open(filename,'r') as f:
        while True:
            line = f.readline()
            if not line: break
            else:
                entry = line.split('\n')[0].split('\t')
                skip_head +=1
                if entry[0] == 'elements':
                    elements = list(filter(None, entry[1:]))
                    print(elements)
                if entry[0] == 'number':
                    number = list(filter(None, entry[1:]))
                    print(number)
                if entry[0] == 'pair':
                    allpairs_ordered = entry[1:]
                if entry[0] == 'file':
                    line = f.readline()
                    entry=line.split()
                    temperature0, acell0 = split_name(entry[0]) 
                    break
    if elements != '' and number != '':
        #calculation of M*N nedded for the calculation of densities
        MN = 0
        for i in range(len(elements)):
            MN = MN + float(number[i]) * cr.Elements2rest(elements[i])[3]
    else:
        MN =0
    #creation of the list containing all the pairs only once and in the same order
    unique_pairs = [allpairs_ordered[0]]
    for i in range(1,len(allpairs_ordered)):
        if allpairs_ordered[i] != allpairs_ordered[i-1]:
            unique_pairs.append(allpairs_ordered[i])
    print('All the pairs availables in the file are:',unique_pairs)
    print('The pairs selected for the plot are:', atoms)
    print('The index for each pair is:')
    #initialization of the dictionnaries containing the data
    #we create sub dictionnaries of the data dictionnary
    data[temperature0] = {'file':[],'rho':[],'dist':{}}
    selected_pairs = [] #pairs to analyze along with their column number
    for i in range(0,len(unique_pairs)):
        for atom_pair in atoms:
            if (unique_pairs[i] == atom_pair): 
                data[temperature0]['dist'][atom_pair] = []
                selected_pairs.append((atom_pair,i*5+distance_columns[distance_type]))
                print(atom_pair, i*5+distance_columns[distance_type])
    #******* 2nd step: extraction of data from the fullgofrs.txt file 
    with open(filename,'r') as f:
        [f.readline() for i in range(skip_head)]
        while True:
            line = f.readline()
            if not line: break
            else:
                entry=line.split('\t')
                temperature, acell = split_name(entry[0]) 
                if temperature != temperature0:     #if we change T:
                    #we create sub dictionnaries of the data dictionnary  and we re-initialize the arrays
                    temperature0 = temperature
                    data[temperature0] = {'file':[],'rho':[],'dist':{}}
                    for i in range(len(selected_pairs)):
                        data[temperature0]['dist'][selected_pairs[i][0]] = []
                if MN ==0:
                    data[temperature0]['rho'].append(float(acell))     #rho is replaced by acell
                else:
                    data[temperature0]['rho'].append(MN/(Na*float(acell)**3*10**(-24)))     #calculation density
                data[temperature0]['file'].append(entry[0].split('/')[-1].split('.gofr.dat')[0])              #extract filename
                #we replace the 0 (no data) by NaN
                for i in range(len(selected_pairs)):
                    if float(entry[selected_pairs[i][1]]) == 0.0:
                        data[temperature0]['dist'][selected_pairs[i][0]].append(float('nan'))
                    else:
                        data[temperature0]['dist'][selected_pairs[i][0]].append(float(entry[selected_pairs[i][1]]))
    #******* 3rd step: bond analysis 
    #Smooth xmin data using fitting and get minrho, maxrho even if we don't want to update/create .bonds.inp
    new_xmin, minrho, maxrho, params, chi2_reduced = smoothing_xmin(data,selected_pairs)
    if bondanalysis == 1:    
        #**** Extract all gofrfiles available
        allgofrfiles = []
        for dirpath, dirnames, filenames in os.walk(os.curdir):
            allgofrfiles.extend(sorted(glob.glob(dirpath+'/*.gofr.dat')))
        print("**** gofrfiles in the current directory are:", allgofrfiles)
        gofrfileslocation = {}
        for gofrfile in allgofrfiles:
            gofrfileslocation[gofrfile.split('/')[-1].split('.gofr.dat')[0]] = gofrfile
        #**** For each line (gofrfile) in the .gofrs.txt file
        for temp in sorted(data):
            for file in  data[temp]['file']:
                #Check if the bondfile already exist: if yes we update it, if not we create it
                bondfile = gofrfileslocation[file].split('.gofr.dat')[0]+'.bonds.inp'
                if (os.path.isfile(bondfile)):
                    update_bonds(bondfile,selected_pairs,atoms,new_xmin,unique_pairs,file)
                else:
                    create_bonds(bondfile,selected_pairs,atoms,new_xmin,unique_pairs,file)           
    else:
        print("Bond analysis not done. If you want it, use option -b 1")
    #******* 4th step: plot of the data and write the deviation from mean in file
    plt.close(1)
    h = 2 * len(atoms) #height of the figure depends on the number of pairs we display
    fig = plt.figure(1,figsize = (4,h))
    plt.subplots_adjust(top = 0.97, bottom = 0.07, right = 0.89, left = 0.07, hspace = 0, wspace = 0)
    #Creation of ticks
    if MN != 0:
        major_ticks = np.arange(0.5, 7, 0.5) 
        minor_ticks = np.arange(0.5, 7, 0.1)
    else:
        major_ticks = AutoLocator()
        minor_ticks = AutoMinorLocator()                                                                 
    #plot & write percentage variation of distance
    ylim_allT = {}
    string = ''
    for atom_pair in atoms:
        string = string+'_'+atom_pair
    newfilename = 'distance_variation_'+distance_type+'_'+filename[:-4]+string+'.txt'
    f=open(newfilename,'w')
    for i in range(len(selected_pairs)):
        atom_pair = selected_pairs[i][0]
        ylim_allT[atom_pair] = [9999,0]
        #print('***************** for atom pair:',atom_pair)
        f.write(atom_pair+'\t'+"\t".join(temp for temp in sorted(data) )+ "\n")
        all_means='mean'
        all_range='range'
        all_percent='%var_from_mean'
        all_percent_rho='%var_from_mean_per_rho'
        all_params_a='fitted_parameter_a'
        all_params_b='fitted_parameter_b'
        all_params_c='fitted_parameter_c'
        all_params_d='fitted_parameter_d'
        all_chi2='chi2_reduced'
        plt.subplot(len(atoms), 1, atoms.index(atom_pair)+1)
        ax = plt.gca()
        #plot and prepare the strings to write in the new log file
        for temp in sorted(data): #loop over temperatures = key in data dictionnary
            #classic analysis (mean, range, %variation)
            #print('******* for temperature:',temp)
            mean_dist=np.nanmean(data[temp]['dist'][atom_pair])
            all_means = all_means+'\t'+str(np.round(mean_dist,2))
            #print('mean dist for',atom_pair,'=',np.round(mean_dist,2))
            range_var=(np.nanmax(data[temp]['dist'][atom_pair])- np.nanmin(data[temp]['dist'][atom_pair]) )
            all_range = all_range+'\t'+str(np.round(range_var,2))
            #print('dist range for', atom_pair, '=', np.round(range_var,2))
            percent_var_mean = (range_var /  mean_dist) * 100
            all_percent=all_percent+'\t'+str(np.round(percent_var_mean,1))
            #print('percent var mean for', atom_pair, '=', np.round(percent_var_mean,1))
            percent_var_mean_per_rho = percent_var_mean / ( np.nanmax(data[temperature0]['rho']) - np.nanmin(data[temperature0]['rho']) )
            all_percent_rho=all_percent_rho+'\t'+str(np.round(percent_var_mean_per_rho,1))
            #print('percent var mean  per rho for', atom_pair, '=', np.round(percent_var_mean_per_rho,1))
            #results from fit
            if bondanalysis == 1:
                newrhoX = np.arange(minrho, maxrho+0.1, 0.1)
                try:
                    all_params_a= all_params_a+'\t'+str(params[temp][atom_pair][0])
                    all_params_b= all_params_b+'\t'+str(params[temp][atom_pair][1])
                    if len(params[temp][atom_pair])==4:
                        all_params_c= all_params_c+'\t'+str(params[temp][atom_pair][2])
                        all_params_d= all_params_d+'\t'+str(params[temp][atom_pair][3])
                        function = poly3
                    else:
                        all_params_c= all_params_c+'\t-'
                        all_params_d= all_params_d+'\t-'
                        function = linear
                    all_chi2 = all_chi2+'\t'+str(chi2_reduced[temp][atom_pair])
                    #print('chi2 for', atom_pair, '=', chi2_reduced[temp][atom_pair])
                    ax.plot(newrhoX,function(newrhoX,*params[temp][atom_pair]), '-',color=colors_T[temp], linewidth = plot_parameters["size_lines"] )
                except KeyError:
                    all_chi2 = all_chi2+'\t-'
                    all_params_a= all_params_a+'\t-'
                    all_params_b= all_params_b+'\t-'
                    all_params_c= all_params_c+'\t-'
                    all_params_d= all_params_d+'\t-'
            #plot
            ax.plot(data[temp]['rho'],data[temp]['dist'][atom_pair], '--',  color=colors_T[temp], linewidth = plot_parameters["size_lines"], marker = markers[atoms.index(atom_pair)], markersize = plot_parameters["size_markers"])
#            ax.text(1.025,0.5, atom_pair ,transform=ax.transAxes, fontsize=plot_parameters["size_fonts"], fontweight='bold')
            ax.text(0.85,0.9, atom_pair, transform=ax.transAxes, fontsize=plot_parameters["size_fonts"], fontweight='bold')
            #define bounds for axis
            if ylim_allT[atom_pair][1] < np.nanmax(data[temp]['dist'][atom_pair]):
                ylim_allT[atom_pair][1] = np.nanmax(data[temp]['dist'][atom_pair])
            if ylim_allT[atom_pair][0] > np.nanmin(data[temp]['dist'][atom_pair]):
                ylim_allT[atom_pair][0] = np.nanmin(data[temp]['dist'][atom_pair])
        f.write(all_means+'\n')
        f.write(all_range+'\n')
        f.write(all_percent+'\n')
        f.write(all_percent_rho+'\n')
        f.write(all_chi2+'\n')
        f.write(all_params_a+'\n')
        f.write(all_params_b+'\n')
        f.write(all_params_c+'\n')
        f.write(all_params_d+'\n')
        f.write('\n')                           
        #Adjustment of ticks and make the graph prettier
        if MN != 0:
            ax.set_xticks(major_ticks)
            ax.set_xticks(minor_ticks, minor=True)
        else:
            ax.xaxis.set_major_locator(major_ticks)
            ax.xaxis.set_minor_locator(minor_ticks)    
        ax.xaxis.set_ticks_position('both')
        ax.yaxis.set_ticks_position('both')
        majorLocator = AutoLocator()
        minorLocator = AutoMinorLocator()
        ax.yaxis.set_major_locator(majorLocator)
        ax.yaxis.set_minor_locator(minorLocator)                
        ax.set_xlim(minrho,maxrho)
        ax.set_ylim(ylim_allT[atom_pair][0],ylim_allT[atom_pair][1])
        if  atoms.index(atom_pair) != len(atoms)-1:
            plt.setp(ax.get_xticklabels(), visible=False)
        ax.tick_params(which = 'both', labelsize = plot_parameters["size_font_ticks"], width = plot_parameters["size_lines"]/2)   
    f.close()
    # Fine-tune figure
    ax0 = fig.add_subplot(111, frameon=False) 
    plt.tick_params(labeltop=False, top=False, labelbottom=False, bottom=False, labelleft=False, left=False, labelright=False, right=False)
    if MN != 0:
        ax0.set_xlabel(r'Density (g.cm$^{-3}$)', fontweight = 'bold', fontsize = plot_parameters["size_fonts"], labelpad = plot_parameters["shift_labelpad"])
    else:
        ax0.set_xlabel(r'Cell size ($\AA$)', fontweight = 'bold', fontsize = plot_parameters["size_fonts"], labelpad = plot_parameters["shift_labelpad"])    
    ax0.set_ylabel(label[distance_type],fontsize=plot_parameters["size_fonts"],fontweight='bold', labelpad = plot_parameters["shift_labelpad"]+plot_parameters["shift_labelpad"]/1.3)
    #Legend 
    for temp in data: 
        legend_labels[str(int(float(temp.strip('T'))*1000))] =  mpatches.Patch(color=colors_T[temp])
    s = [(k, legend_labels[k]) for k in sorted(legend_labels.keys(),reverse = False)]      
    #legend = ax0.legend([v for k,v in s],[k for k,v in s], title = ' $\\bf{Temperature}$ \n           (K)',loc='upper left',bbox_to_anchor=(1.2, 1), fontsize = plot_parameters["size_fonts"], borderaxespad=0.,ncol=1)
    #plt.setp(legend.get_title(),fontsize= plot_parameters["size_fonts"])
    #plt.title(filename.split('.txt')[0], fontsize = plot_parameters["size_fonts"], fontweight='bold')
    #save the figure
    string = ''
    for atom_pair in atoms:
        string = string+'_'+atom_pair
    figurename = 'distance_'+distance_type+'_'+filename[:-4]+string+'.png'
    fig.savefig(figurename, bbox_inches = 'tight', dpi = 150)
    print(figurename, '   created')
예제 #3
0
def main(argv):
    """     ********* Main program *********     """
    #param for the plot
    colors_elem = {
        'Al': 'pink',
        'C': '0.25',
        'Ca': 'c',
        'H': 'w',
        'K': 'm',
        'Na': 'b',
        'O': 'r',
        'Si': 'y'
    }  #other dictionnaries and parameters for the figure for article version
    letter = ''
    statfile2 = ''
    plot_parameters = {
        "size_fonts": 12,
        "size_font_ticks": 10,
        "size_figure": (8, 4),
        "size_markers": 4,
        "size_lines": 1,
        "shift_labelpad": 20
    }
    #plot_parameters = {"size_fonts" : 12,"size_font_ticks":10,"size_figure" : (8,4),"size_markers" : 10,"size_lines" : 2,"shift_labelpad" : 20}
    #other parameters
    Na = 6.022 * 10**23
    try:
        options, arg = getopt.getopt(argv, "hf:g:v:m:d:l:", [
            "file1", "gfile2", "variable", "mineralfile", "density_max",
            "letter"
        ])
    except getopt.GetoptError:
        print(
            "plot_speciation-r1-elements.py  -v <variable (rho,T)> -m <mineralfile with elements> -f <stat-concentrate_r1_abso_filename1> -g <stat-concentrate_r1_abso_filename2> -d <maximum density to plot in g/cm3> -l <letter for article subplot, default = ''>"
        )
        sys.exit()
    for opt, arg in options:
        if opt == '-h':
            print('')
            print(
                'plot_speciation-r1-elements.py program to  Plot abundance of elements as a function of rho or T'
            )
            print(
                "plot_speciation-r1-elements.py -v <variable (rho,T)> -m <mineralfile with elements> -f <stat-concentrate_r1_abso_filename1> -g <stat-concentrate_r1_abso_filename2>  -d <maximum density to plot in g/cm3> -l <letter for article subplot, default = ''>"
            )
            print(
                'requires the file containing elements and number (in order to compute the densities)'
            )
            print('')
            sys.exit()
        elif opt in ("-f", "--file1"):
            statfile1 = str(arg)
        elif opt in ("-g", "--gfile2"):
            statfile2 = str(arg)
        elif opt in ("-v", "--variable"):
            variable = str(arg)
        elif opt in ("-m", "--mineralfile"):
            mineralfile = str(arg)
        elif opt in ("-d", "--density_max"):
            max_den = float(arg)
        elif opt in ("-l", "--letter"):
            letter = str(arg)
    #***** Calculation of the molecular mass
    with open(mineralfile, 'r') as mf:
        entry = mf.readline()
        elements = entry.split()[1:]
        entry = mf.readline()
        number = list(map(int, entry.split()[1:]))
    MN = 0
    for i in range(len(elements)):
        MN = MN + number[i] * cr.Elements2rest(elements[i])[3]
    #**** Calculation of congruent proportions
    congruent = {}
    for ii in range(len(elements)):
        congruent[elements[ii]] = number[ii] / sum(number)
    #***** Creation of the plot
    if statfile2 != '':
        allstatfiles = [statfile1, statfile2]
        with open(statfile1, 'r') as f:
            line = f.readline()
            file1 = line.split()[1]
        with open(statfile2, 'r') as f2:
            line = f2.readline()
            file2 = line.split()[1]
        fig, ax1, ax2 = creation_plot2(variable, file1, file2, MN,
                                       plot_parameters, max_den, letter)
        figurename = statfile1.split('/')[-1].split(
            '.dat')[0] + '+' + statfile2.split('/')[-1].split(
                '.dat')[0] + '_' + variable + '-elements'
    else:
        allstatfiles = [statfile1]
        fig, ax1 = creation_plot(variable, plot_parameters, max_den, letter)
        figurename = statfile1.split('.dat')[0] + '_' + variable + '-elements'

    for ii in range(len(allstatfiles)):
        statfile = allstatfiles[ii]
        #selection of the plot
        if ii == 1:
            ax = ax2
        else:
            ax = ax1
        #initialisation
        atomsnumbers = {
        }  #create dictionnary which will contain the number of atom for each element in each species
        filescolumns = {
        }  #create dictionnary containing the column number for the different files
        xdata = {'T': [], 'rho': []}  #dictionnary containing the x data
        lifetime = {
        }  #dictionnary containing lifetime data for each element and file
        perc = {}  #idem for percentages
        selected_files = [
        ]  #list containing the files we use for the plot (depends on the density limit)
        #***** Extraction of all files and cluster and count of their atoms
        with open(statfile, 'r') as f:
            line = f.readline()
            entry = line.split('\n')[0].split('\t')[1:-1]
            for file in entry:
                filescolumns[file] = entry.index(file)
            while True:
                line = f.readline()
                if not line: break
                else:
                    entry = line.split('\n')[0].split('\t')
                    if len(entry) > 1:
                        atomsnumbers[entry[0]] = {
                        }  #create dictionnary which will contain the number of atom for each element in each species
        for elem in elements:
            #print("for elem",elem)
            for species in atomsnumbers:
                #print("for species",species)
                m = re.search(elem, species)
                if m:  #if there is the current element in the species
                    ii = m.end(
                    )  #then we use the index of the end of the matching pattern m
                    try:  #to try to see if there is several iteration of this element using '_'
                        if species[ii] == '_':
                            num = ''
                            try:
                                while re.match('[0-9]', species[ii + 1]):
                                    num = num + species[ii + 1]
                                    ii += 1
                            except IndexError:  #index error when we arrive at the end of the cluster name
                                pass
                                #print('end of the cluster')
                            #print("num after '_':", num)
                            atomsnumbers[species][elem] = int(num)
                        else:  #if there is no '_' after the matching pattern it means there is only one atom of this element
                            atomsnumbers[species][elem] = 1
                    except IndexError:  #if the matching pattern is actually at the end of the string we raise an indexerror --> there is only one instance of this element
                        atomsnumbers[species][elem] = 1
                else:
                    atomsnumbers[species][elem] = 0
        #print(atomsnumbers)
        #**** Extraction of selected files
        for file in filescolumns:
            temperature, acell = split_name(file)
            density = MN / (Na * float(acell)**3 * 10**(-24))
            if density <= max_den:
                xdata['rho'].append(density)  #calculation density
                xdata['T'].append(int(temperature))
                selected_files.append(file)
        print("selected files are", selected_files)
        #**** Initialization of perc and lifetime dictionnary for each element and file
        for elem in elements:
            perc[elem] = {}
            lifetime[elem] = {}
            for file in selected_files:
                perc[elem][file] = []
                lifetime[elem][file] = []
        #*****************************
        #*******************
        #*******
        #**** Extract the lifetimes
        with open(statfile, 'r') as f:
            f.readline()
            while True:
                line = f.readline(
                )  #for each line of the file we extract the data
                if not line: break
                else:
                    entry = line.split('\n')[0].split('\t')[:-1]
                    #print("entry is",entry)
                    for elem in atomsnumbers[entry[
                            0]]:  #we skip the analysis for element that are not present in the species
                        if atomsnumbers[entry[0]][elem] == 0:
                            continue
                        else:  #and we store the lifetime for each element and file
                            for file in selected_files:
                                try:
                                    lifetime[elem][file].append(
                                        float(entry[filescolumns[file] + 1]) *
                                        atomsnumbers[entry[0]][elem])
                                except ValueError:  #if there is '' instead of a numerical value
                                    lifetime[elem][file].append(0)
        #**** Compute percentages
        #1st: sum lifetime per element
        for elem in elements:
            perc[elem] = []
            for file in selected_files:
                perc[elem].append(sum(lifetime[elem][file]))
        #2nd: sum all tot lifetime
        totlifetime = []
        for ii in range(len(selected_files)):
            sumlifetime = 0
            for elem in perc:
                sumlifetime = sumlifetime + perc[elem][ii]
            totlifetime.append(sumlifetime)
        #3rd: compute percentages
        for elem in perc:
            for ii in range(len(selected_files)):
                perc[elem][ii] = perc[elem][ii] / totlifetime[ii]
        #*****************************
        #*******************
        #*******
        #**** Plot the percentages and write file with percentages
        newfilename = statfile.split(
            '.dat')[0] + '_' + variable + '-elements' + '.txt'
        nf = open(newfilename, 'w')
        if variable == 'rho':
            nf.write('Density(g/cm3)\t' + '\t'.join(
                str(round(density, 2)) for density in xdata[variable]) + '\n')
        else:
            nf.write('Temperature(K)\t' +
                     '\t'.join(str(temp) for temp in xdata[variable]) + '\n')
        ydata = []
        ycolors = []
        labels = []
        for elem in perc:
            #sort the data by the x value
            x, y = zip(*sorted(zip(xdata[variable], perc[elem])))
            #plot lines
            line, = ax.plot(x,
                            y,
                            '.--',
                            color=colors_elem[elem],
                            markersize=plot_parameters["size_markers"],
                            linewidth=plot_parameters["size_lines"],
                            label=elem)
            label_line(ax, line, elem, halign='center')
            #write data in file
            nf.write(elem + '\t' +
                     '\t'.join(str(round(data, 4))
                               for data in perc[elem]) + '\n')
            #for stackplot only
            ydata.append(y)
            ycolors.append(colors_elem[elem])
            labels.append(elem)
        #plot stacked area
        #plt.stackplot(x,ydata[0],ydata[1],ydata[2],ydata[3], colors = ycolors, labels = labels )

        #plot lines of congruent gas
        for elem in congruent:
            ax.axhline(y=congruent[elem],
                       color=colors_elem[elem],
                       linewidth=plot_parameters["size_lines"] / 1.5,
                       linestyle=':')

        #legend = plt.legend(bbox_to_anchor=(1.01, 1), loc='upper left', fontsize = plot_parameters["size_fonts"], title = '$\\bf{Elements}$', borderaxespad=0., ncol = 1)
        #plt.setp(legend.get_title(),fontsize= plot_parameters["size_fonts"])
        print(newfilename, 'is created')

    figurename = figurename + '.pdf'
    plt.savefig(figurename, bbox_inches='tight', dpi=300)
    print(figurename, 'is created')
예제 #4
0
def main(argv):
    """     ********* Main program *********     """
    files = []
    all_lifetimes = {} #dictionnary containing lifetimes for each cluster 
    all_length = {}#dictionnary containing length of cluster for each cluster 
    all_clusters_sizes = [] #list with all the cluster sizes accross all files
    all_species = [] #list with all the species accross all files
    nsubfig = np.zeros(13,dtype=int) #list of number of subfig per natoms cluster
    order_species={}  #dictionnary to order all the species in each column
    for ii in range(1,14):
        order_species[ii]=[]
    #parameters for the figures depending on the output format (presentation or article)
    plot_parameters = {"size_fonts" : 12,"size_font_ticks":10,"size_figure" : (8,4),"size_markers" : 4,"size_lines" : 1,"shift_labelpad" : 20}
    colors_T = {'2000':'#800080','3000':'#297fff','4000':'#00ff00','4500':'#bae200','5000':'#ffcd01','6000':'#ff0101','6500':'#ff00a2','7000':'#ff01de'}
    letters = ['a','b','c','d','e','f','g','h','i']
    #other parameters
    Na=6.022*10**23
    try:
        options,arg = getopt.getopt(argv,"hm:f:",["mineralfile","filename"])
    except getopt.GetoptError:
        print("plot_speciation-lifetime-r1.py  -m <mineralfile with elements> -f <one filename of the same format name than all we want to plot>  ")
        sys.exit()
    for opt,arg in options:
        if opt == '-h':
            print('')
            print('plot_speciation-lifetime-r1.py program to  Plot lifetime barchart for all clusters smaller then 13 atoms,  one subfigure per cluster,  one figure per speciation_r1.popul.dat file created by the script speciation_lifetime.py')
            print("plot_speciation-lifetime-r1.py  -m <mineralfile with elements> -f <one filename of the same format name than all we want to plot>  ")
            print("")
            print('requires the file containing elements and number (in order to compute the densities)')
            print('')
            sys.exit()
        elif opt in ("-m","--mineralfile"):
            mineralfile = str(arg)
        elif opt in ("-f","--filename"):
            firstfilename = str(arg)
    #***** Calculation of the molecular mass
    with open(mineralfile,'r') as mf:
        entry = mf.readline()
        elements = entry.split()[1:]
        entry = mf.readline()
        number = entry.split()[1:]
    MN = 0
    for i in range(len(elements)):
        MN = MN + float(number[i]) * cr.Elements2rest(elements[i])[3]
    #***** 1st step : List of all the files concerned by the  T and acell
    cell = firstfilename.split('.outcar.umd.dat')[0].split('_')[3].strip('a')
    speciation = firstfilename.split('.outcar.umd.dat.r')[-1].split('.popul.dat')[0]
    length = firstfilename.split('.popul.dat_L')[-1].split('.txt')[0]
    filename = '*_a'+cell+'*outcar.umd.dat.r'+speciation+'.popul.dat_L'+length+'*.txt'
    print('I search for files of type', filename)
    allfiles = sorted(glob.glob(filename))                             #I list every population file created by plot_speciation-lifetime.py in alphabetic order
    #print('all files are:',allfiles)
    #we remove the empty files (the ones created by hand) from the file list
    for file in allfiles:
        if os.stat(file).st_size != 0:
            files.append(file)
    #print('selected files are:',files)
    #***** 2nd step : Extraction of all cluster type from all files  in order to have max number of rows per columns
    for file in files:
        print('************* for file',file)
        with open(file,'r') as f:
            #**** Extract species and lengths
            line = f.readline() #we read the first line with cluster sizes
            clusters_sizes = line.split('\n')[0].split('\t')
            line = f.readline() #we read the second line with cluster names
            clusters=line.split('\n')[0].split('\t')
            #print('clusters in file:',clusters)
            for ii in range(len(clusters)):
                all_length[clusters[ii]] = int(clusters_sizes[ii])
        #***** Count the number of subfigure per natoms cluster and Create dictionnary to order all the species in each column
        #update of the list containing each cluster size
        for species in clusters:
            if species not in all_species:
                all_clusters_sizes.append(clusters_sizes[clusters.index(species)])
        #update of the newcount based on all the cluster that have been seen up to now
        for ii in range(1,14):
            newcount = all_clusters_sizes.count(str(ii))
            if nsubfig[ii-1] < newcount:
                nsubfig[ii-1] = newcount
        for species in clusters:
            if species in order_species[all_length[species]]: continue
            else:
                order_species[all_length[species]].append(species)
            all_species.append(species)
    #creation of the list containing each species ONCE
    all_species = []
    for ii in range(1,14):
        for species in order_species[ii]:
            all_species.append(species)
    #print('total number of subfig:',nsubfig)
    print('order of species',order_species)
    #print('all the species are',all_species)
    #**** 3rd step : Core of the script = extraction of data and plot     
    for file in files:
        print('************* for file',file)
        letter = letters[allfiles.index(file)]
        #**** 3.1) Extraction of T and acell
        temperature, acell = split_name(file)
        #**** 3.2) Extract all data
        with open(file,'r') as f:
            #**** Extract species and lengths
            line = f.readline() #we read the first line with cluster sizes
            clusters_sizes = line.split('\n')[0].split('\t')
            line = f.readline() #we read the second line with cluster names
            clusters=line.split('\n')[0].split('\t')
            for ii in range(len(clusters)):
                all_length[clusters[ii]] = int(clusters_sizes[ii])
                all_lifetimes[clusters[ii]] = []
            #**** Extract lifetimes
            while True:
                line = f.readline() #we read all the other lines with lifetime for each apparition
                if not line: break
                else:
                    entry=line.split('\n')[0].split('\t')
                    for ii in range(0,len(clusters)): #we store the correct lifetime in the dictionnary for the corresponding key
                        if entry[ii] != '':
                            all_lifetimes[clusters[ii]].append(float(entry[ii]))
                        else: continue
        #**** 3.3) plot
        #fig 1 has the clusters up to 7 atoms
        print("creation of plot 1 with",max(nsubfig[0:7]),'subplots in rows')
        fig1 = plt.figure(figsize=(7*2,max(nsubfig[0:7])*1.9), constrained_layout=False)
        gs1 = fig1.add_gridspec(nrows=max(nsubfig[0:7]), ncols=7, width_ratios =np.ones(7), height_ratios =np.ones(max(nsubfig[0:7])), wspace = 0.5, hspace = 0.5, figure=fig1)
        #fig 2 has the clusters from 8 to 13 atoms
        print("creation of plot 2 with",max(nsubfig[7:]),'subplots in rows')
        fig2 = plt.figure(figsize=(7*2,max(nsubfig[7:])*1.9), constrained_layout=False)
        gs2 = fig2.add_gridspec(nrows=max(nsubfig[7:]), ncols=7,  width_ratios =np.ones(7), height_ratios =np.ones(max(nsubfig[7:])), wspace = 0.5, hspace = 0.5,  figure=fig2)
        for species in all_species:
            if all_length[species] < 8:                
                #print(species, order_species[all_length[species]].index(species), all_length[species]-1 )
                #plot only if there is something to draw
                if species in clusters:
                    #creation subplot
                    ax = fig1.add_subplot(gs1[order_species[all_length[species]].index(species), all_length[species]-1])
                    #text
                    ax.text(0.85,0.85, format_1label(species) , transform=ax.transAxes, horizontalalignment = 'right', fontsize = plot_parameters["size_fonts"])
                    if order_species[all_length[species]].index(species) ==  0:
                        ax.text(0.5,1.1, str(all_length[species]) , transform=ax.transAxes, horizontalalignment = 'center', fontsize = plot_parameters["size_fonts"], fontweight = 'bold')            
                    #plot
                    ax.bar(np.arange(len(all_lifetimes[species])),all_lifetimes[species],  width = 1, align = 'edge', color = colors_T[temperature])
                    #axis limits (pretty, rounded up)
                    maxnumberx = max_axis(len(all_lifetimes[species]))
                    ax.set_xticks([0, maxnumberx])
                    ax.set_xlim([0, maxnumberx])
                    maxnumbery = max_axis(max(all_lifetimes[species]))
                    ax.set_yticks([0,maxnumbery]) 
                    ax.set_ylim([0,maxnumbery])          
                    ax.tick_params(which = 'both', labelsize = plot_parameters["size_font_ticks"], width = plot_parameters["size_lines"]/2)               
                #empty subplot otherwise
                else:
                    ax = fig1.add_subplot(gs1[order_species[all_length[species]].index(species), all_length[species]-1], frameon=False)                    
                    ax.tick_params(labeltop=False, top=False, labelbottom=False, bottom=False, labelleft=False, left=False, labelright = False, right=False)     
            else:
                #plot only if there is something to draw
                if species in clusters:
                    #creation subplot
                    ax = fig2.add_subplot(gs2[order_species[all_length[species]].index(species), all_length[species]-8])
                    #text
                    ax.text(0.85,0.85, format_1label(species) , transform=ax.transAxes, horizontalalignment = 'right', fontsize = plot_parameters["size_fonts"])
                    if order_species[all_length[species]].index(species) ==  0:
                        ax.text(0.5,1.1, str(all_length[species]) , transform=ax.transAxes, horizontalalignment = 'center', fontsize = plot_parameters["size_fonts"], fontweight = 'bold')
                    #plot
                    ax.bar(np.arange(len(all_lifetimes[species])),all_lifetimes[species],  width = 1, align = 'edge', color = colors_T[temperature])
                    #axis limits (pretty, rounded up)
                    maxnumberx = max_axis(len(all_lifetimes[species]))
                    ax.set_xticks([0, maxnumberx])
                    ax.set_xlim([0, maxnumberx])
                    maxnumbery = max_axis(max(all_lifetimes[species]))
                    ax.set_yticks([0,maxnumbery]) 
                    ax.set_ylim([0,maxnumbery])          
                    ax.tick_params(which = 'both', labelsize = plot_parameters["size_font_ticks"], width = plot_parameters["size_lines"]/2) 
                else:
                    ax = fig2.add_subplot(gs2[order_species[all_length[species]].index(species), all_length[species]-8], frameon=False)
                    ax.tick_params(labeltop=False, top=False, labelbottom=False, bottom=False, labelleft=False, left=False, labelright = False, right=False) 
        #**** 4th step : Add a big invisible subplot in order to center x and y labels (since the ticklabels are turned off we have to move the x and y labels with labelpad)
        ax0 = fig1.add_subplot(gs1[:,:], frameon=False)
        ax0bis = fig2.add_subplot(gs2[:,:], frameon=False)
        for ax in [ax0,ax0bis]:
            ax.tick_params(labeltop=False, top=False, labelbottom=False, bottom=False, labelleft=False, left=False, labelright = False, right=False)
            ax.set_xlabel(r'Number of species occurence', fontweight = 'bold', fontsize = plot_parameters["size_fonts"], labelpad = plot_parameters["shift_labelpad"]*1.2)
            ax.set_ylabel(r'Lifetime (fs)', fontweight = 'bold', fontsize = plot_parameters["size_fonts"], labelpad = plot_parameters["shift_labelpad"]*2.5)
            ax.text(-0.1,1, letter , transform=ax.transAxes, horizontalalignment = 'left', fontweight = 'bold', fontsize = 12, bbox=dict(facecolor='none', edgecolor='k', pad=3.0))  
        #**** 5th step: Save plot
        figurename1 = file.split('/')[-1].split('.txt')[0]+'_matrix1.pdf'
        fig1.savefig(figurename1, dpi=300, bbox_inches='tight') #remove 'tight' to take into account options of subplots_adjust
        figurename2 = file.split('/')[-1].split('.txt')[0]+'_matrix2.pdf'
        fig2.savefig(figurename2, dpi=300, bbox_inches='tight') #remove 'tight' to take into account options of subplots_adjust
        print(figurename1, 'is created')
        print(figurename2, 'is created')
        #plt.show()  
    #**** 6th step: For files that does not exist and for which we created a corresponding empty file, we create an empty figure and remove them of the list of files
    for file in allfiles:
        if os.stat(file).st_size == 0:
            temperature, acell = split_name(file)
            letter = letters[allfiles.index(file)]
            #fig 1 has the clusters up to 7 atoms
            fig1 = plt.figure(figsize=(7*2,max(nsubfig[0:7])*1.9), constrained_layout=False)
            gs1 = fig1.add_gridspec(nrows=max(nsubfig[0:7]), ncols=7, width_ratios =np.ones(7), height_ratios =np.ones(max(nsubfig[0:7])), wspace = 0.5, hspace = 0.5, figure=fig1)
            #fig 2 has the clusters from 8 to 13 atoms
            fig2 = plt.figure(figsize=(7*2,max(nsubfig[7:])*1.9), constrained_layout=False)
            gs2 = fig2.add_gridspec(nrows=max(nsubfig[7:]), ncols=7,  width_ratios =np.ones(7), height_ratios =np.ones(max(nsubfig[7:])), wspace = 0.5, hspace = 0.5,  figure=fig2)
            #**** 3rd step : Add a big invisible subplot in order to center x and y labels (since the ticklabels are turned off we have to move the x and y labels with labelpad)
            ax0 = fig1.add_subplot(gs1[:,:], frameon=False)
            ax0bis = fig2.add_subplot(gs2[:,:], frameon=False)
            for ax in [ax0,ax0bis]:
                ax.tick_params(labeltop=False, top=False, labelbottom=False, bottom=False, labelleft=False, left=False, labelright = False, right=False)
                ax.set_xlabel(r'Number of species occurence', fontweight = 'bold', fontsize = plot_parameters["size_fonts"], labelpad = plot_parameters["shift_labelpad"]*1.2)
                ax.set_ylabel(r'Lifetime (fs)', fontweight = 'bold', fontsize = plot_parameters["size_fonts"], labelpad = plot_parameters["shift_labelpad"]*2.5)
                ax.text(-0.1,1, letter , transform=ax.transAxes, horizontalalignment = 'left', fontweight = 'bold', fontsize = 12, bbox=dict(facecolor='none', edgecolor='k', pad=3.0))  
def main(argv):
    """     ********* Main program *********     """
    #other dictionnaries and parameters for the figure
    colors_densities = {}
    lines = {
    }  #dictionnary for the lines for legend (the keys are acell or densities, and values are the color of lines)
    limits = {}  #dictionnary for y limits
    AllTrho = []  #list for storing the temperature in order to sort them
    files = []
    #other parameters
    Na = 6.022 * 10**23  #avogadro constant
    try:
        options, arg = getopt.getopt(argv, "hm:", ["mineralfile"])
    except getopt.GetoptError:
        print("plot_msd_allrhoT.py  -m <mineralfile with elements>")
        sys.exit()
    for opt, arg in options:
        if opt == '-h':
            print(
                "plot_msd_allrhoT.py script to plot all the msd at every acell and T (matrix with atom in columns and T in lines)"
            )
            print("plot_msd_allrhoT.py  -m <mineralfile with elements> ")
            print(
                'requires the file containing elements and number (in order to compute the densities)'
            )
            sys.exit()
        elif opt in ("-m", "--mineralfile"):
            mineralfile = str(arg)
    size_fonts = 12
    size_fonts_ticks = 10
    size_figure = (14, 14)
    size_lines = 2
    shift_label = 20
    #***** Calculation of the molecular mass
    with open(mineralfile, 'r') as mf:
        entry = mf.readline()
        elements = entry.split()[1:]
        entry = mf.readline()
        number = entry.split()[1:]
    MN = 0
    for i in range(len(elements)):
        MN = MN + float(number[i]) * cr.Elements2rest(elements[i])[3]
    #***** List the files in alphabetical order regarding to temperature (need to extract T and compute it because of the T4.5 listed before T4)
    initfiles = sorted(glob.glob(
        '*outcar.msd.dat'))  #I list every msd files in alphabetic order
    for file in initfiles:
        temperature, acell = split_name(file)
        temperature = int(float(temperature.strip('T')) * 1000)
        AllTrho.append((temperature, acell))
    AllTrho = sorted(AllTrho)  #first I sort everything in alphabetical order
    AllTrho = sorted(AllTrho, key=lambda tup: tup[0],
                     reverse=True)  #then I reverse the order of the T only
    for Trho in AllTrho:
        T = Trho[0] / 1000
        rem = Trho[0] % 1000
        if rem == 0:
            T = int(T)
        pattern = '_T' + str(T) + '_nvt_a' + Trho[1]
        for file in initfiles:
            if re.search(pattern, file):
                files.append(file)
    #print(files)
    #***** Calculation of the number of figures (T * ntypat)
    firstfile = files[0]  #I take the first file
    temperature0, acell0 = split_name(firstfile)
    with open(firstfile, 'r') as f:
        atoms = f.readline()
        atoms = atoms.strip('time_(fs)').split()  #I extract the atoms
    T_numsubplot = [temperature0
                    ]  #list for the correspondance T / subplot number
    for file in files:
        temperature, acell = split_name(file)
        if temperature != temperature0:
            T_numsubplot.append(temperature)
            temperature0 = temperature
    temperature0, acell0 = split_name(firstfile)
    #***** Count of the number of densities (needed for the automatic color change)
    #first store every density into the dictionary
    for file in files:
        #calculation of densities in g/cm3
        temperature, acell = split_name(file)
        Volume = float(acell)**3
        Density = MN / (Na * Volume * 10**(-24))
        #we store the densities into the dictionnary
        colors_densities[round(Density, 1)] = []
    #now the dictionary has every possible densities of our mineral, we attribute the colors to each density
    name = 'devon'
    cm_data = np.loadtxt(
        "/Users/akobsch/Dropbox/Recherche/PhD-MD-silicates/simulations/scripts/Analysis/ScientificColourMaps6/"
        + name + "/" + name + ".txt")
    #cm_data = cm_data[::-1] #for reverse colors (hawaii,lajolla)
    new_map = LinearSegmentedColormap.from_list(
        'new', cm_data[:-20])  #cm_data[:-20] for devon, davos, oslo
    color = iter(new_map(np.linspace(
        0, 1, len(colors_densities))))  #Creation of the color list
    allrho = []
    for key in natsort.natsorted(colors_densities):
        c = next(color)
        colors_densities[key] = c
        allrho.append(key)
    #*****************************
    #*******************
    #*******
    #Read & plot
    plt.close(1)
    fig = plt.figure(1, figsize=size_figure)
    plt.subplots_adjust(top=0.97,
                        bottom=0.07,
                        right=0.89,
                        left=0.07,
                        hspace=0,
                        wspace=0)
    plt.subplot(len(T_numsubplot), len(atoms), 1)
    ax = plt.gca()
    for atom in atoms:
        for file in files:
            #calculation of densities in g/cm3
            temperature, acell = split_name(file)
            Volume = float(acell)**3
            Density = MN / (Na * Volume * 10**(-24))
            #change of subplot
            if temperature != temperature0:
                plt.subplot(
                    len(T_numsubplot), len(atoms),
                    T_numsubplot.index(temperature) * 4 + 1 +
                    atoms.index(atom))
                ax = plt.gca()
                temperature0 = temperature
            #importation of data
            Temps, DataAtom = np.loadtxt(file,
                                         skiprows=1,
                                         usecols=(0, atoms.index(atom) + 1),
                                         unpack=True)
            #plot
            lines[str(round(Density,
                            1))], = ax.plot(Temps,
                                            DataAtom,
                                            '-',
                                            color=colors_densities[round(
                                                Density, 1)],
                                            linewidth=size_lines)
            #we add x and y labels outside the plot on the right columns and lines
            if T_numsubplot.index(temperature) == 0:
                ax.set_xlabel(atoms[atoms.index(atom)],
                              fontweight='bold',
                              fontsize=size_fonts)
                ax.xaxis.set_label_position('top')
            if atoms.index(atom) == len(atoms) - 1:
                ax.set_ylabel(str(int(float(temperature.strip('T')) * 1000)) +
                              ' K',
                              fontweight='bold',
                              fontsize=size_fonts)
                ax.yaxis.set_label_position('right')
            #limitation of data along x and ticks (linear only)
            Xlimit = 9999
            #major_ticks = np.arange(0, Xlimit, 2000)
            #minor_ticks = np.arange(0, Xlimit, 500)
            #ax.set_xticks(major_ticks)
            #ax.set_xticks(minor_ticks, minor=True)
            ax.set_xscale('log')
            ax.set_xlim(10, Xlimit)
            #limitation of data along y
            ax.set_yscale('log')
            if atoms.index(atom) == 0:
                ax.autoscale(axis='y', tight=True)
                limits[temperature] = (0.100001, ax.get_ylim()[1])
            ax.set_ylim(limits[temperature])
            #we make the graph prettier
            if atoms.index(atom) != 0:
                plt.setp(ax.get_yticklabels(), visible=False)
            if T_numsubplot.index(temperature) != len(T_numsubplot) - 1:
                plt.setp(ax.get_xticklabels(), visible=False)
            ax.xaxis.set_ticks_position('both')
            ax.yaxis.set_ticks_position('both')
            ax.yaxis.set_tick_params(which='both', direction='inout')
            ax.xaxis.set_tick_params(which='both', direction='inout')
            ax.grid(axis='y',
                    which='major',
                    linestyle='--',
                    linewidth=size_lines / 2,
                    alpha=0.5)
            ax.set_facecolor((1, 1, 1, 0))
            #ax.get_xaxis().set_tick_params(direction='inout')
            #ax.get_yaxis().set_tick_params(direction='inout')
            #plt.setp(ax.get_xticklabels()[-2], visible=False)
            #plt.setp(ax.get_yticklabels()[-1], visible=False)
            ax.tick_params(which='both',
                           labelsize=size_fonts_ticks,
                           width=size_lines / 2)

    #************ Fine tune figure
    ax0 = fig.add_subplot(111, frameon=False)
    plt.tick_params(labeltop=False,
                    top=False,
                    labelbottom=False,
                    bottom=False,
                    labelleft=False,
                    left=False,
                    labelright=False,
                    right=False)
    ax0.set_xlabel(r'Time (fs)',
                   fontweight='bold',
                   fontsize=size_fonts,
                   labelpad=shift_label)
    ax0.set_ylabel(r"Mean square displacement ($\mathregular{\AA^2}$)",
                   fontsize=size_fonts,
                   fontweight='bold',
                   labelpad=shift_label + shift_label / 2)

    #************ legend
    ncols = 12
    custom_lines = [
        Line2D([0], [0],
               color=colors_densities[key],
               ls='-',
               marker='',
               linewidth=size_lines) for key in allrho[:ncols]
    ]
    legend = ax0.legend([col for col in custom_lines],
                        [label for label in allrho[:ncols]],
                        title='$\\bf{Density}$ (g.cm$^{-3}$)',
                        bbox_to_anchor=(0.5, 1.05),
                        loc="lower center",
                        fontsize=size_fonts,
                        borderaxespad=0.,
                        ncol=ncols)
    custom_lines = [
        Line2D([0], [0],
               color=colors_densities[key],
               ls='-',
               marker='',
               linewidth=size_lines) for key in allrho[ncols:]
    ]
    legend2 = ax0.legend([col for col in custom_lines],
                         [label for label in allrho[ncols:]],
                         bbox_to_anchor=(0.5, 1.05),
                         loc="upper center",
                         fontsize=size_fonts,
                         borderaxespad=0.,
                         ncol=ncols)
    ax0.add_artist(legend)
    plt.setp(legend.get_title(), fontsize=size_fonts)

    figurename = 'msd_' + file.split('_')[0] + '.pdf'
    plt.savefig(figurename, bbox_inches='tight', dpi=300)
    print(figurename, 'is created')
def main(argv):
    """     ********* Main program *********     """
    #other dictionnaries and parameters for the figure
    markers = [
        'o', '^', '*', 'P', 'X', '<', '>', 'v', '8', 's', 'p', 'h', '+', 'D'
    ]  #************************************Be sure you have enough markers for all the pairs you want to plot
    colors_T = {
        'T2': '#800080',
        'T3': '#297fff',
        'T4': '#00ff00',
        'T4.5': '#bae200',
        'T5': '#ffcd01',
        'T5.5': '#ff6e00',
        'T6': '#ff0101',
        'T6.5': '#ff00a2',
        'T7': '#ff01de',
        'T7.5': '#ffa6f4',
        'T10': '#ffe86e',
        'T15': '#ffbf90',
        'T20': '#ff7788'
    }
    plot_parameters = {
        "size_fonts": 12,
        "size_font_ticks": 10,
        "size_figure": (4, 4),
        "size_markers": 8,
        "size_lines": 1,
        "shift_labelpad": 20
    }
    label = {
        'xmax': r"1st $g(r)$ peak location ($\AA$)",
        'xmin': r"Coordination sphere radius ($\AA$)",
        'bond': r"Bond length ($\AA$)"
    }
    #initialization of variables
    elements = ''
    number = ''
    atoms = []
    legend_labels = {}
    data = {
    }  #big dictionnary with inside dist dictionnary and rho, all coresponding to different T
    distance_columns = {'xmax': 1, 'xmin': 3, 'bond': 5}
    xvariable = 'rho'
    TP = {}  #dictionnary with P and T in each simufile
    #dictionnary for fullaverages file in full version
    column_number = {
        'rho': 2,
        'P': 5,
        'stdev_P': 6,
        'err_P': 7,
        'T': 8,
        'stdev_T': 9,
        'err_T': 10,
        'E': 14,
        'stdev_E': 15,
        'err_E': 16,
        'Cvm_Nkb': 23,
        'stdev_Cvm_Nkb': 24,
        'Cvm': 25,
        'stdev_Cvm': 26,
        'testCv': 31,
        'stdev_testCv': 32
    }
    #other parameters
    Na = 6.022 * 10**23
    try:
        options, arg = getopt.getopt(argv, "hf:g:j:a:d:x:", [
            "fgofrsfilename1", "gofrsfilename2", "jgofrsfilename3", "atom",
            "distance", 'xvariable'
        ])
    except getopt.GetoptError:
        print(
            "plot_distances_5x3.py -f <_gofrs.txt 1> -g <_gofrs.txt 2> -j <_gofrs.txt 3> -a <pairs of atoms>(ex: 'Ca-O,Ca-Ca,O2')  -d <distance type to print ('xmax' or 'xmin' or 'bond')> -x <xvariable (P or rho)>"
        )
        sys.exit()
    for opt, arg in options:
        if opt == '-h':
            print('')
            print(
                'plot_distances_5x3.py program to plot xmin,xmax or bond length as a function of density or acell for each T and 5  selected pairs of atoms'
            )
            print(
                "plot_distances_5x3.py -f <_gofrs.txt 1> -g <_gofrs.txt 2> -j <_gofrs.txt 3> -a <pairs of atoms>(ex: 'Ca-O,Ca-Ca,O2')  -d <distance type to print ('xmax' or 'xmin' or 'bond')> -x <xvariable (P or rho)> "
            )
            print(
                "plot_distances_5x3.py requires _gofrs.txt file (use analyze_gofrs_semi_automatic.py)"
            )
            print('')
            print(
                'For plots as function of P, make sure the files from fullaverages.py are in the current folder'
            )
            print(
                'WARNING: this script use the filenames inside the _gofrs.txt file to extract the temperature and cell size for the plot. If you do have both information in your filenames at the same place, then update the function split_name to extract them correctly.'
            )
            sys.exit()
        if opt in ('-f', '--gofrsfilename'):
            filename1 = str(arg)
        elif opt in ('-g', '--gofrsfilename'):
            filename2 = str(arg)
        elif opt in ('-j', '--gofrsfilename'):
            filename3 = str(arg)
        elif opt in ('-a', '--atoms'):
            atoms = arg.split(',')  #list of atom pairs we want to analyze here
        elif opt in ('-d', '--distance'):
            distance_type = str(arg)
        elif opt in ('-x', '--xvariable'):
            xvariable = str(arg)
    files = [filename1, filename2, filename3]
    #******* write data analysis and find ymax, ymin for every atoms
    ylim_allT = {
        'Ca-O': [9999, 0],
        'K-O': [9999, 0],
        'Na-O': [9999, 0],
        'Al-O': [9999, 0],
        'Si-O': [9999, 0],
        'O-O': [9999, 0],
        'O2': [9999, 0],
        'Ca-Ca': [9999, 0],
        'K-K': [9999, 0],
        'Na-Na': [9999, 0],
        'Ca-Al': [9999, 0],
        'K-Al': [9999, 0],
        'Na-Al': [9999, 0],
        'Al-Al': [9999, 0],
        'Al-Si': [9999, 0],
        'Si-Si': [9999, 0]
    }
    for filename in files:
        print('********Analysis', filename)
        #******* 1st step: read the header and extract all relevant informations
        #creation of elements and number lists and initialization of T
        skip_head = 0
        with open(filename, 'r') as f:
            while True:
                line = f.readline()
                if not line: break
                else:
                    entry = line.split('\n')[0].split('\t')
                    skip_head += 1
                    if entry[0] == 'elements':
                        elements = list(filter(None, entry[1:]))
                        print(elements)
                    if entry[0] == 'number':
                        number = list(filter(None, entry[1:]))
                        print(number)
                    if entry[0] == 'pair':
                        allpairs_ordered = entry[1:]
                    if entry[0] == 'file':
                        line = f.readline()
                        entry = line.split()
                        temperature0, acell0 = split_name(entry[0])
                        break
        if elements != '' and number != '':
            #calculation of M*N nedded for the calculation of densities
            MN = 0
            for i in range(len(elements)):
                MN = MN + float(number[i]) * cr.Elements2rest(elements[i])[3]
        else:
            MN = 0
        #creation of the list containing all the pairs only once and in the same order
        unique_pairs = [allpairs_ordered[0]]
        for i in range(1, len(allpairs_ordered)):
            if allpairs_ordered[i] != allpairs_ordered[i - 1]:
                unique_pairs.append(allpairs_ordered[i])
        print('The index for each pair is:')
        #initialization of the dictionnaries containing the data
        #we create sub dictionnaries of the data dictionnary
        data = {}
        data[temperature0] = {'file': [], 'rho': [], 'dist': {}}
        selected_pairs = []  #pairs to analyze along with their column number
        for atom_pair in atoms:
            for i in range(0, len(unique_pairs)):
                if (unique_pairs[i] == atom_pair):
                    data[temperature0]['dist'][atom_pair] = []
                    selected_pairs.append(
                        (atom_pair, i * 5 + distance_columns[distance_type]))
                    print(atom_pair, i * 5 + distance_columns[distance_type])
        print('All the pairs availables in the file are:', unique_pairs)
        print('The pairs selected for the plot are:', selected_pairs)
        #******* 2nd step: extraction of data from the fullgofrs.txt file
        with open(filename, 'r') as f:
            [f.readline() for i in range(skip_head)]
            while True:
                line = f.readline()
                if not line: break
                else:
                    entry = line.split('\t')
                    temperature, acell = split_name(entry[0])
                    if temperature != temperature0:  #if we change T:
                        #we create sub dictionnaries of the data dictionnary  and we re-initialize the arrays
                        temperature0 = temperature
                        data[temperature0] = {
                            'file': [],
                            'rho': [],
                            'dist': {}
                        }
                        for i in range(len(selected_pairs)):
                            data[temperature0]['dist'][selected_pairs[i]
                                                       [0]] = []
                    if MN == 0:
                        data[temperature0]['rho'].append(
                            float(acell))  #rho is replaced by acell
                    else:
                        data[temperature0]['rho'].append(
                            MN / (Na * float(acell)**3 *
                                  10**(-24)))  #calculation density
                    data[temperature0]['file'].append(entry[0].split(
                        '/')[-1].split('.gofr.dat')[0])  #extract filename
                    #we replace the 0 (no data) by NaN
                    for i in range(len(selected_pairs)):
                        print(selected_pairs[i])
                        if float(entry[selected_pairs[i][1]]) == 0.0:
                            data[temperature0]['dist'][
                                selected_pairs[i][0]].append(float('nan'))
                        else:
                            data[temperature0]['dist'][
                                selected_pairs[i][0]].append(
                                    float(entry[selected_pairs[i][1]]))
        #******* 3rd step:  analysis
        #Smooth xmin data using fitting and get minrho, maxrho even if we don't want to update/create .bonds.inp
        new_xmin, minrho, maxrho, params, chi2_reduced = smoothing_xmin(
            data, selected_pairs)
        #******* 4th step: write the deviation from mean in file and update the ymax and ymin
        # write percentage variation of distance
        string = ''
        for sp_tuple in selected_pairs:
            atom_pair = sp_tuple[0]
            string = string + '_' + atom_pair
        newfilename = 'distance_variation_' + distance_type + '_' + filename[:
                                                                             -4] + string + '.txt'
        nf = open(newfilename, 'w')
        for i in range(len(selected_pairs)):
            atom_pair = selected_pairs[i][0]
            #print('***************** for atom pair:',atom_pair)
            nf.write(atom_pair + '\t' +
                     "\t".join(temp for temp in sorted(data)) + "\n")
            all_means = 'mean'
            all_range = 'range'
            all_percent = '%var_from_mean'
            all_percent_rho = '%var_from_mean_per_rho'
            all_params_a = 'fitted_parameter_a'
            all_params_b = 'fitted_parameter_b'
            all_params_c = 'fitted_parameter_c'
            all_params_d = 'fitted_parameter_d'
            all_chi2 = 'chi2_reduced'
            #plot and prepare the strings to write in the new log file
            for temp in sorted(
                    data):  #loop over temperatures = key in data dictionnary
                #classic analysis (mean, range, %variation)
                #print('******* for temperature:',temp)
                mean_dist = np.nanmean(data[temp]['dist'][atom_pair])
                all_means = all_means + '\t' + str(np.round(mean_dist, 2))
                #print('mean dist for',atom_pair,'=',np.round(mean_dist,2))
                range_var = (np.nanmax(data[temp]['dist'][atom_pair]) -
                             np.nanmin(data[temp]['dist'][atom_pair]))
                all_range = all_range + '\t' + str(np.round(range_var, 2))
                #print('dist range for', atom_pair, '=', np.round(range_var,2))
                percent_var_mean = (range_var / mean_dist) * 100
                all_percent = all_percent + '\t' + str(
                    np.round(percent_var_mean, 1))
                #print('percent var mean for', atom_pair, '=', np.round(percent_var_mean,1))
                percent_var_mean_per_rho = percent_var_mean / (
                    np.nanmax(data[temperature0]['rho']) -
                    np.nanmin(data[temperature0]['rho']))
                all_percent_rho = all_percent_rho + '\t' + str(
                    np.round(percent_var_mean_per_rho, 1))
                #print('percent var mean  per rho for', atom_pair, '=', np.round(percent_var_mean_per_rho,1))
                #define bounds for axis
                if ylim_allT[atom_pair][1] < np.nanmax(
                        data[temp]['dist'][atom_pair]):
                    ylim_allT[atom_pair][1] = np.nanmax(
                        data[temp]['dist'][atom_pair])
                if ylim_allT[atom_pair][0] > np.nanmin(
                        data[temp]['dist'][atom_pair]):
                    ylim_allT[atom_pair][0] = np.nanmin(
                        data[temp]['dist'][atom_pair])
            nf.write(all_means + '\n')
            nf.write(all_range + '\n')
            nf.write(all_percent + '\n')
            nf.write(all_percent_rho + '\n')
            nf.write(all_chi2 + '\n')
            nf.write(all_params_a + '\n')
            nf.write(all_params_b + '\n')
            nf.write(all_params_c + '\n')
            nf.write(all_params_d + '\n')
            nf.write('\n')
    nf.close()
    #update the ylim_allT to have the same vertical scale
    ylim_allT = update_ylim(ylim_allT, ['Ca-O', 'Na-O', 'K-O'])
    ylim_allT = update_ylim(ylim_allT, ['Ca-Ca', 'Na-Na', 'K-K'])
    ylim_allT = update_ylim(ylim_allT, ['Ca-Al', 'Na-Al', 'K-Al'])

    #************ Plot data
    print('*******************************')
    print('******************')
    print('********')
    print('Plot')
    plt.close(1)
    fig, axes = plt.subplots(nrows=5, ncols=3, figsize=(10, 14))
    plt.subplots_adjust(top=0.97,
                        bottom=0.07,
                        right=0.89,
                        left=0.07,
                        hspace=0,
                        wspace=0)
    for filename in files:
        #******* 0th step: extract P and T for each thermo file
        if xvariable == 'P':
            TP = {}
            mineralname = filename.split('_')[1]
            thermofiles = sorted(glob.glob('thermo_' + mineralname + '*.txt'))
            for file in thermofiles:
                TP = extract_TP(file, column_number, TP, '')
            #print(TP)
        #******* 1st step: read the header and extract all relevant informations
        #creation of elements and number lists and initialization of T
        skip_head = 0
        with open(filename, 'r') as f:
            while True:
                line = f.readline()
                if not line: break
                else:
                    entry = line.split('\n')[0].split('\t')
                    skip_head += 1
                    if entry[0] == 'elements':
                        elements = list(filter(None, entry[1:]))
                        print(elements)
                    if entry[0] == 'number':
                        number = list(filter(None, entry[1:]))
                        print(number)
                    if entry[0] == 'pair':
                        allpairs_ordered = entry[1:]
                    if entry[0] == 'file':
                        line = f.readline()
                        entry = line.split()
                        temperature0, acell0 = split_name(entry[0])
                        break
        if elements != '' and number != '':
            #calculation of M*N nedded for the calculation of densities
            MN = 0
            for i in range(len(elements)):
                MN = MN + float(number[i]) * cr.Elements2rest(elements[i])[3]
        else:
            MN = 0
        #creation of the list containing all the pairs only once and in the same order
        unique_pairs = [allpairs_ordered[0]]
        for i in range(1, len(allpairs_ordered)):
            if allpairs_ordered[i] != allpairs_ordered[i - 1]:
                unique_pairs.append(allpairs_ordered[i])
        #initialization of the dictionnaries containing the data
        #we create sub dictionnaries of the data dictionnary
        data = {}
        data[temperature0] = {'file': [], 'rho': [], 'dist': {}, 'P': []}
        selected_pairs = []  #pairs to analyze along with their column number
        for atom_pair in atoms:
            for i in range(0, len(unique_pairs)):
                if (unique_pairs[i] == atom_pair):
                    data[temperature0]['dist'][atom_pair] = []
                    selected_pairs.append(
                        (atom_pair, i * 5 + distance_columns[distance_type]))
        unique_pairs = []
        for sp_tuple in selected_pairs:
            unique_pairs.append(sp_tuple[0])
        print('The pairs selected for the plot are:', unique_pairs)
        #******* 2nd step: extraction of data from the fullgofrs.txt file
        with open(filename, 'r') as f:
            [f.readline() for i in range(skip_head)]
            while True:
                line = f.readline()
                if not line: break
                else:
                    entry = line.split('\t')
                    temperature, acell = split_name(entry[0])
                    if temperature != temperature0:  #if we change T:
                        #we create sub dictionnaries of the data dictionnary  and we re-initialize the arrays
                        temperature0 = temperature
                        data[temperature0] = {
                            'file': [],
                            'rho': [],
                            'dist': {},
                            'P': []
                        }
                        for i in range(len(selected_pairs)):
                            data[temperature0]['dist'][selected_pairs[i]
                                                       [0]] = []
                    if MN == 0:
                        data[temperature0]['rho'].append(
                            float(acell))  #rho is replaced by acell
                    else:
                        data[temperature0]['rho'].append(
                            MN / (Na * float(acell)**3 *
                                  10**(-24)))  #calculation density
                    data[temperature0]['file'].append(entry[0].split(
                        '/')[-1].split('.gofr.dat')[0])  #extract filename
                    if xvariable == 'P':
                        data[temperature0]['P'].append(TP[entry[0].split(
                            'outcar.gofr.dat')[0].split('/')[-1]][1])
                    #we replace the 0 (no data) by NaN
                    for i in range(len(selected_pairs)):
                        if float(entry[selected_pairs[i][1]]) == 0.0:
                            data[temperature0]['dist'][
                                selected_pairs[i][0]].append(float('nan'))
                        else:
                            data[temperature0]['dist'][
                                selected_pairs[i][0]].append(
                                    float(entry[selected_pairs[i][1]]))
        #******* 3rd step:  analysis
        #Smooth xmin data using fitting and get minrho, maxrho even if we don't want to update/create .bonds.inp
        new_xmin, minrho, maxrho, params, chi2_reduced = smoothing_xmin(
            data, selected_pairs)
        #******* 4th step: plot of the data
        #Creation of ticks
        if MN != 0:
            major_ticks = np.arange(0.5, 7, 1)
            minor_ticks = np.arange(0.5, 7, 0.5)
        else:
            major_ticks = AutoLocator()
            minor_ticks = AutoMinorLocator()
        #plot
        for i in range(len(selected_pairs)):
            atom_pair = selected_pairs[i][0]
            ax = axes[unique_pairs.index(atom_pair),
                      files.index(filename)]  #line,col = atom,feldspar
            #plot and prepare the strings to write in the new log file
            for temp in sorted(
                    data):  #loop over temperatures = key in data dictionnary
                #print('******* for temperature:',temp)
                #plot
                ax.plot(data[temp][xvariable],
                        data[temp]['dist'][atom_pair],
                        '--',
                        color=colors_T[temp],
                        linewidth=plot_parameters["size_lines"],
                        marker=markers[unique_pairs.index(atom_pair)],
                        markersize=plot_parameters["size_markers"])
                #            ax.text(1.025,0.5, atom_pair ,transform=ax.transAxes, fontsize=plot_parameters["size_fonts"], fontweight='bold')
                ax.text(0.97,
                        0.9,
                        atom_pair,
                        transform=ax.transAxes,
                        horizontalalignment='right',
                        fontsize=plot_parameters["size_fonts"],
                        fontweight='bold')
            #Adjustment of ticks and make the graph prettier
            if xvariable == 'P':
                ax.set_xlim(1, 275)
                ax.set_xscale('log')
            elif MN != 0:
                ax.set_xticks(major_ticks)
                ax.set_xticks(minor_ticks, minor=True)
                ax.set_xlim(minrho, maxrho)
            else:
                ax.xaxis.set_major_locator(major_ticks)
                ax.xaxis.set_minor_locator(minor_ticks)
                ax.set_xlim(minrho, maxrho)
            ax.set_facecolor((1, 1, 1, 0))
            ax.xaxis.set_ticks_position('both')
            ax.yaxis.set_ticks_position('both')
            majorLocator = AutoLocator()
            minorLocator = AutoMinorLocator()
            ax.yaxis.set_major_locator(majorLocator)
            ax.yaxis.set_minor_locator(minorLocator)
            ax.set_ylim(ylim_allT[atom_pair][0], ylim_allT[atom_pair][1])
            if unique_pairs.index(atom_pair) != len(unique_pairs) - 1:
                plt.setp(ax.get_xticklabels(), visible=False)
            if files.index(filename) != 0:
                plt.setp(ax.get_yticklabels(), visible=False)
            ax.tick_params(which='both',
                           labelsize=plot_parameters["size_font_ticks"],
                           width=plot_parameters["size_lines"] / 2)
    # Fine-tune figure
    ax0 = fig.add_subplot(111, frameon=False)
    plt.tick_params(labeltop=False,
                    top=False,
                    labelbottom=False,
                    bottom=False,
                    labelleft=False,
                    left=False,
                    labelright=False,
                    right=False)
    if xvariable == 'P':
        ax0.set_xlabel(r'Pressure (GPa)',
                       fontweight='bold',
                       fontsize=plot_parameters["size_fonts"],
                       labelpad=plot_parameters["shift_labelpad"])
    elif MN != 0:
        ax0.set_xlabel(r'Density (g.cm$^{-3}$)',
                       fontweight='bold',
                       fontsize=plot_parameters["size_fonts"],
                       labelpad=plot_parameters["shift_labelpad"])
    else:
        xvariable = 'acell'
        ax0.set_xlabel(r'Cell size ($\AA$)',
                       fontweight='bold',
                       fontsize=plot_parameters["size_fonts"],
                       labelpad=plot_parameters["shift_labelpad"])
    ax0.set_ylabel(label[distance_type],
                   fontsize=plot_parameters["size_fonts"],
                   fontweight='bold',
                   labelpad=plot_parameters["shift_labelpad"] +
                   plot_parameters["shift_labelpad"] / 1.3)
    #Legend
    for temp in data:
        legend_labels[str(int(float(temp.strip('T')) *
                              1000))] = mpatches.Patch(color=colors_T[temp])
    s = [(k, legend_labels[k])
         for k in sorted(legend_labels.keys(), reverse=False)]
    #legend = ax0.legend([v for k,v in s],[k for k,v in s], title = ' $\\bf{Temperature}$ \n           (K)',loc='upper left',bbox_to_anchor=(1.2, 1), fontsize = plot_parameters["size_fonts"], borderaxespad=0.,ncol=1)
    #plt.setp(legend.get_title(),fontsize= plot_parameters["size_fonts"])
    #plt.title(filename.split('.txt')[0], fontsize = plot_parameters["size_fonts"], fontweight='bold')
    #save the figure
    string = ''
    for atom_pair in atoms:
        string = string + '_' + atom_pair
    figurename = 'distance_' + distance_type + '_all' + string + '_' + xvariable + '.pdf'
    fig.savefig(figurename, bbox_inches='tight', dpi=150)
    print(figurename, '   created')
예제 #7
0
def main(argv):
    """     ********* Main program *********     """
    nmeltatoms = 100  #limit of natoms to consider a species being part of the melt
    #other dictionnaries and parameters for the figure for article version
    letter = ''
    statfile2 = ''
    plot_parameters = {
        "size_fonts": 12,
        "size_font_ticks": 10,
        "size_figure": (8, 4),
        "size_markers": 4,
        "size_lines": 1,
        "shift_labelpad": 20
    }
    #plot_parameters = {"size_fonts" : 12,"size_font_ticks":10,"size_figure" : (8,4),"size_markers" : 10,"size_lines" : 2,"shift_labelpad" : 20}
    #other parameters
    Na = 6.022 * 10**23
    try:
        options, arg = getopt.getopt(argv, "hf:g:v:m:d:l:", [
            "file1", "gfile2", "variable", "mineralfile", "density_max",
            "letter"
        ])
    except getopt.GetoptError:
        print(
            "plot_speciation-r1-species.py  -v <variable (rho,T)> -m <mineralfile with elements> -f <stat-concentrate_r1_abso_filename>  -g <stat-concentrate_r1_abso_filename2>  -d <maximum density to plot in g/cm3> -l <letter for article subplot, default = ''>"
        )
        sys.exit()
    for opt, arg in options:
        if opt == '-h':
            print('')
            print(
                'plot_speciation-r1-species.py program to  Plot abundance of chemical species for selected cation as a function of rho or T'
            )
            print(
                "plot_speciation-r1-species.py -v <variable (rho,T)> -m <mineralfile with elements> -f <stat-concentrate_r1_abso_filename>  -g <stat-concentrate_r1_abso_filename2>  -d <maximum density to plot in g/cm3> -l <letter for article subplot, default = ''>"
            )
            print(
                'requires the file containing elements and number (in order to compute the densities)'
            )
            print('')
            sys.exit()
        elif opt in ("-f", "--file1"):
            statfile1 = str(arg)
        elif opt in ("-g", "--gfile2"):
            statfile2 = str(arg)
        elif opt in ("-v", "--variable"):
            variable = str(arg)
        elif opt in ("-m", "--mineralfile"):
            mineralfile = str(arg)
        elif opt in ("-d", "--density_max"):
            max_den = float(arg)
        elif opt in ("-l", "--letter"):
            letter = str(arg)
    #***** Calculation of the molecular mass
    with open(mineralfile, 'r') as mf:
        entry = mf.readline()
        elements = entry.split()[1:]
        entry = mf.readline()
        number = entry.split()[1:]
    MN = 0
    for i in range(len(elements)):
        MN = MN + float(number[i]) * cr.Elements2rest(elements[i])[3]
    #***** Creation of the plot
    if statfile2 != '':
        allstatfiles = [statfile1, statfile2]
        with open(statfile1, 'r') as f:
            line = f.readline()
            file1 = line.split()[1]
        with open(statfile2, 'r') as f2:
            line = f2.readline()
            file2 = line.split()[1]
        fig, ax1, ax2 = creation_plot2(variable, file1, file2, MN,
                                       plot_parameters, max_den, letter)
        figurename = statfile1.split('/')[-1].split(
            '.dat')[0] + '+' + statfile2.split('/')[-1].split(
                '.dat')[0] + '_' + variable + '-species'
    else:
        allstatfiles = [statfile1]
        fig, ax1 = creation_plot(variable, plot_parameters, max_den, letter)
        figurename = statfile1.split('.dat')[0] + '_' + variable + '-species'

    for ii in range(len(allstatfiles)):
        statfile = allstatfiles[ii]
        #selection of the plot
        if ii == 1:
            ax = ax2
        else:
            ax = ax1

        #initialisation
        xdata = {'T': [], 'rho': []}  #dictionnary containing the x data
        data = []  #list containing y data
        melt = []  #list containing y data for species with 100 atoms or more
        selected_files = [
        ]  #list containing the files we use for the plot (depends on the density limit)
        species1 = []
        list_colored_species = []
        list_colored_red = []
        list_colored_blue = []
        list_colored_purple = []
        list_colored_green = []
        list_grey_species = []
        list_black_species = ["melt-like"]
        colors_species = {}

        #***** Count of the number of clusters for the selected atom type (needed for the automatic color change)
        #first store every cluster type into the dictionary
        if re.search("L208", statfile):
            #print("we group all the species of more than nmeltatoms atoms under the denomination 'melt-like'")
            with open(statfile, 'r') as f:
                line = f.readline()
                while True:
                    line = f.readline()
                    if not line: break
                    else:
                        entry = line.split('\n')[0].split('\t')
                        if len(entry) > 1:
                            natoms = count_natom(entry[0])
                            if natoms < nmeltatoms:
                                species1.append(entry[0])
                                colors_species[entry[0]] = []
                species1.append("melt-like")
                colors_species["melt-like"] = []
        else:
            #print("we use the standard script")
            with open(statfile, 'r') as f:
                line = f.readline()
                while True:
                    line = f.readline()
                    if not line: break
                    else:
                        entry = line.split('\n')[0].split('\t')
                        if len(entry) > 1:
                            species1.append(entry[0])
                            colors_species[entry[0]] = []
        #*****************************
        #*******************
        #*******
        #Read and compute percentages
        #in case of speciation r1 L208, we group all the species of more than 100 atoms under the denomination "melt-like"
        with open(statfile, 'r') as f:
            line = f.readline()
            entry = line.split()
            files = entry[1:]
            #creation of the x data list
            for file in files:
                temperature, acell = split_name(file)
                density = MN / (Na * float(acell)**3 * 10**(-24))
                if density <= max_den:
                    xdata['rho'].append(density)  #calculation density
                    xdata['T'].append(int(temperature))
                    selected_files.append(file)
            if re.search("L208", statfile):
                print("we group all the species of more than", nmeltatoms,
                      "atoms under the denomination 'melt-like'")
                #creation of the y data matrix
                while True:
                    line = f.readline()
                    if not line: break
                    else:
                        entry = line.split('\n')[0].split('\t')[:-1]
                        linedata = []  #we initialize the list of data per line
                        if len(entry) > 1:
                            for i in range(1, len(entry)):
                                if files[
                                        i -
                                        1] in selected_files:  #if the column which corresponding file is in the selected files, then we use the data
                                    if entry[i] == '':
                                        entry[i] = 0
                                    else:
                                        entry[i] = float(entry[i])
                                    linedata.append(
                                        entry[i]
                                    )  #we create a list of the data for this line (cluster)
                            natoms = count_natom(entry[0])
                            if natoms < nmeltatoms:
                                data.append(
                                    linedata[:]
                                )  #we add this list to the big list of data in order to have nested lists
                            else:
                                melt.append(linedata[:])
                print('for files', selected_files)
                print('all species are', species1, len(species1))
                print('and density', xdata['rho'])
                #calculation of the percentages per density
                totalsmelt = np.ndarray.tolist(np.sum(
                    melt, 0))  #we sum all the melt species together
                data.append(
                    totalsmelt[:])  #and we add this total to the data matrix
                print('initial data of len', np.size(data, 0),
                      np.size(data, 1))
                totals = np.sum(data, 0)
                #print('totals', totals)
                for i in range(np.size(data, 0)):
                    for j in range(np.size(data, 1)):
                        if totals[j] == 0:
                            data[i][j] = 0
                        else:
                            data[i][j] = data[i][j] / totals[j]
                #print('calculated percentages',data)
                newtotals = np.sum(data, 0)
                print('total should be 1', newtotals)
            else:
                print("we use the standard script")
                #creation of the y data matrix
                while True:
                    line = f.readline()
                    if not line: break
                    else:
                        entry = line.split('\n')[0].split('\t')[:-1]
                        linedata = []  #we initialize the list of data per line
                        if len(entry) > 1:
                            for i in range(1, len(entry)):
                                if files[
                                        i -
                                        1] in selected_files:  #if the column which corresponding file is in the selected files, then we use the data
                                    if entry[i] == '':
                                        entry[i] = 0
                                    else:
                                        entry[i] = float(entry[i])
                                    linedata.append(
                                        entry[i]
                                    )  #we create a list of the data for this line (cluster)
                            data.append(
                                linedata[:]
                            )  #we add this list to the big list of data in order to have nested lists
                print('for files', selected_files)
                print('all species are', species1)
                #print('initial data',data)
                #print('and density', xdata['rho'])
                #calculation of the percentages per density
                totals = np.sum(data, 0)
                #print('totals', totals)
                for i in range(np.size(data, 0)):
                    for j in range(np.size(data, 1)):
                        if totals[j] == 0:
                            data[i][j] = 0
                        else:
                            data[i][j] = data[i][j] / totals[j]
                #print('calculated percentages',data)
                newtotals = np.sum(data, 0)
                print('total should be 1', newtotals)
        #*****************************
        #*******************
        #*******
    #    #now the dictionary has every possible cluster, we attribute the colors to each cluster
    #    list_species = []
    #    color = iter(plt.cm.jet(np.linspace(0,1,len(colors_species)))) #Creation of the color list
    #    for key in natsort.natsorted(colors_species):
    #        c = next(color)
    #        colors_species[key] = c
    #        list_species.append(key)
    #    print(list_species, len(list_species))
    #*** check the abundance to put in grey the species less abundant than 1% and put a label only for species more abundante than 5% at least one time
        for i in range(np.size(data, axis=0)):  #loop on each cluster
            if max(data[i]) < 0.01:
                colors_species[species1[i]] = '0.5'
                list_grey_species.append(species1[i])
            else:
                #this is for basic automatic color change
                list_colored_species.append(species1[i])
                #this is for custom color change relative to the feldspars
                if (species1[i][0] == 'N' or species1[i][0] == 'K'
                        or species1[i][0] == 'C') and re.search(
                            'Si_1O', species1[i]):
                    list_colored_blue.append(species1[i])
                elif re.match('Si_1O', species1[i]):
                    list_colored_red.append(species1[i])
                elif (species1[i][0] == 'N' or species1[i][0] == 'K' or
                      species1[i][0] == 'C') and re.search('O', species1[i]):
                    list_colored_purple.append(species1[i])
                elif species1[i][0:5] == 'Al_1O':
                    list_colored_green.append(species1[i])
                #We add the label
                if max(data[i]) > 0.05:
                    x_max = xdata[variable][data[i].index(max(data[i]))]
                    y_max = max(data[i])
                    label = species1[i]
                    #formatage of label
                    label = format1label(label)
                    ax.text(x_max, y_max, label, color='0.35')
        print('list red', list_colored_red)
        print('list blue', list_colored_blue)
        print('list purple', list_colored_purple)
        print('list green', list_colored_green)
        #**** we attribute the colors to each cluster with abundance > 0.01
        #this is for basic automatic color change
        #color = iter(plt.cm.jet(np.linspace(0,1,len(list_colored_species)))) #Creation of the color list
        #for key in natsort.natsorted(list_colored_species):
        #    c = next(color)
        #    colors_species[key] = c
        #and this is for custom color change relative to the feldspars
        dict_r = {
            'red': (
                (
                    0.0, 1.0, 1.0
                ),  # <- at 0.0 (first value), the red component is 1 (second value) (the third value may be alpha)
                (1.0, 0.3, 1.0)),  # <- at 1.0, the red component is 0.3
            'green': ((0.0, 0.0, 0.0), (1.0, 0.0, 0.0)),
            'blue': ((0.0, 0.0, 0.0), (1.0, 0.0, 0.0))
        }
        cmreds = LinearSegmentedColormap('reds', dict_r)
        color_r = iter(cmreds(np.linspace(
            0, 1,
            len(list_colored_red))))  #Creation of the color list for reds
        dict_b = {
            'red': ((0.0, 0.0, 0.0), (1.0, 0.4, 1.0)),
            'green': ((0.0, 0.0, 0.0), (1.0, 1.0, 1.0)),
            'blue': (
                (
                    0.0, 1.0, 1.0
                ),  # <- at 0.0 (first value), the blue component is 1 (second value) (the third value may be alpha)
                (1.0, 1.0, 1.0))  # <- at 1.0, the blue component is 0.3
        }
        cmblues = LinearSegmentedColormap('blues', dict_b)
        color_b = iter(cmblues(np.linspace(
            0, 1,
            len(list_colored_blue))))  #Creation of the color list for blues
        dict_p = {
            'red': (
                (
                    0.0, 0.6, 1.0
                ),  # <- at 0.0 (first value), the red component is 0.6 (second value) (the third value may be alpha)
                (1.0, 0.3, 1.0)),  # <- at 1.0, the red component is 0.3
            'green': ((0.0, 0.0, 0.0), (1.0, 0.0, 0.0)),
            'blue': (
                (
                    0.0, 0.6, 1.0
                ),  # <- at 0.0 (first value), the blue component is 0.6 (second value) (the third value may be alpha)
                (1.0, 0.3, 1.0))  # <- at 1.0, the blue component is 0.3
        }
        cmpurples = LinearSegmentedColormap('purples', dict_p)
        color_p = iter(cmpurples(np.linspace(0, 1, len(
            list_colored_purple))))  #Creation of the color list for purples
        dict_g = {
            'red': ((0.0, 0.0, 0.0), (1.0, 0.0, 0.0)),
            'green': (
                (
                    0.0, 1.0, 1.0
                ),  # <- at 0.0 (first value), the green component is 0.7 (second value) (the third value may be alpha)
                (1.0, 0.3, 1.0)),  # <- at 1.0, the green component is 0.3
            'blue': ((0.0, 0.0, 0.0), (1.0, 0.0, 0.0))
        }
        cmgreens = LinearSegmentedColormap('greens', dict_g)
        color_g = iter(cmgreens(np.linspace(
            0, 1,
            len(list_colored_green))))  #Creation of the color list for greens
        for key in natsort.natsorted(list_colored_species):
            if key == 'O_1':
                colors_species[key] = 'gold'
            elif key == 'O_2':
                colors_species[key] = 'darkorange'
            elif key == 'O_3':
                colors_species[key] = 'tomato'
            elif key == 'Na_1' or key == 'K_1' or key == 'Ca_1':
                colors_species[key] = (0.5, 0, 1.0)
            elif key == "melt-like":
                colors_species[key] = '0'
            else:
                colors_species[key] = '0.5'
        colors_species = color_change(color_r, list_colored_red,
                                      colors_species)
        colors_species = color_change(color_b, list_colored_blue,
                                      colors_species)
        colors_species = color_change(color_p, list_colored_purple,
                                      colors_species)
        colors_species = color_change(color_g, list_colored_green,
                                      colors_species)
        #*****************************
        #*******************
        #*******
        #***plot for each cluster and write file with percentages
        newfilename = statfile.split(
            '.dat')[0] + '_' + variable + '-species' + '.txt'
        nf = open(newfilename, 'w')
        if variable == 'rho':
            nf.write('Density(g/cm3)\t' + '\t'.join(
                str(round(density, 2)) for density in xdata[variable]) + '\n')
        else:
            nf.write('Temperature(K)\t' +
                     '\t'.join(str(temp) for temp in xdata[variable]) + '\n')
        #plot stacked area
        #    plt.stackplot(xdata[variable],data)
        #plot lines
        if re.search("L208", statfile):
            #print("we group all the species of more than nmeltatoms atoms under the denomination 'melt-like'")
            i = -1
            with open(statfile, 'r') as f:
                line = f.readline()
                while True:
                    line = f.readline()
                    if not line: break
                    else:
                        entry = line.split('\n')[0].split('\t')[:-1]
                        if len(entry) > 1:
                            natoms = count_natom(entry[0])
                            if natoms < nmeltatoms:
                                i += 1
                                x, y = zip(
                                    *sorted(zip(xdata[variable], data[i])))
                                if entry[
                                        0] in list_colored_species:  #we plot only the colored lines. delete this line to plot also the grey species
                                    line, = ax.plot(
                                        x,
                                        y,
                                        '.--',
                                        color=colors_species[entry[0]],
                                        markersize=plot_parameters[
                                            "size_markers"],
                                        linewidth=plot_parameters["size_lines"]
                                    )
                                nf.write(
                                    format1label(entry[0]) + '\t' + '\t'.join(
                                        str(round(perc, 4))
                                        for perc in data[i]) + '\n')
                #we plot the last line, for the melt-like
                i += 1
                x, y = zip(*sorted(zip(xdata[variable], data[i])))
                line, = ax.plot(x,
                                y,
                                '.--',
                                color=colors_species['melt-like'],
                                markersize=plot_parameters["size_markers"],
                                linewidth=plot_parameters["size_lines"])
                nf.write(
                    format1label('melt-like') + '\t' +
                    '\t'.join(str(round(perc, 4)) for perc in data[i]) + '\n')
        else:
            i = -1
            with open(statfile, 'r') as f:
                line = f.readline()
                while True:
                    line = f.readline()
                    if not line: break
                    else:
                        entry = line.split('\n')[0].split('\t')[:-1]
                        if len(entry) > 1:
                            i += 1
                            x, y = zip(*sorted(zip(xdata[variable], data[i])))
                            if entry[
                                    0] in list_colored_species:  #we plot only the colored lines. delete this line to plot also the grey species
                                line, = ax.plot(
                                    x,
                                    y,
                                    '.--',
                                    color=colors_species[entry[0]],
                                    markersize=plot_parameters["size_markers"],
                                    linewidth=plot_parameters["size_lines"])
                            nf.write(
                                format1label(entry[0]) + '\t' + '\t'.join(
                                    str(round(perc, 4))
                                    for perc in data[i]) + '\n')
        #                    if variable == 'T':
        #                        label_line(ax, line, entry[0], halign='right')
        #                    elif list_species.index(entry[0]) < int(len(list_species)/2):
        #                        label_line(ax, line, entry[0], halign='left')
        #                    else:
        #                        label_line(ax, line, entry[0], halign='right')
    #    ax.hlines(y=0.05, xmin = 1, xmax=2.1, color = 'r')
    #    ax.hlines(y=0.01, xmin = 1, xmax=2.1, color = 'm')
    #*****************************
    #*******************
    #*******
    #legend
    #custom_lines_grey = [Line2D([0],[0],color = colors_species[key], ls = '--', marker = '.', markersize = plot_parameters["size_markers"], linewidth = plot_parameters["size_lines"]) for key in natsort.natsorted(list_grey_species)]
        list_grey_species = format_label(natsort.natsorted(list_grey_species))
        #legend_grey = plt.legend([line for line in custom_lines_grey],[label for label in list_grey_species],title = '$\\bf{Clusters <1\%}$', bbox_to_anchor=(1.25, 1), loc='upper left', fontsize = plot_parameters["size_fonts"],  borderaxespad=0.)
        #plt.gca().add_artist(legend_grey)
        #plt.setp(legend_grey.get_title(),fontsize= plot_parameters["size_fonts"])

        custom_lines = [
            Line2D([0], [0],
                   color=colors_species[key],
                   ls='--',
                   marker='.',
                   markersize=plot_parameters["size_markers"],
                   linewidth=plot_parameters["size_lines"])
            for key in natsort.natsorted(list_colored_species)
        ]
        list_colored_species = format_label(
            natsort.natsorted(list_colored_species))
        if statfile2 != '':
            legend = ax.legend([line for line in custom_lines],
                               [label for label in list_colored_species],
                               bbox_to_anchor=(0.5, 0.99),
                               loc='upper center',
                               fontsize=plot_parameters["size_font_ticks"],
                               borderaxespad=0.,
                               ncol=3)
        #if len(list_colored_species) > 16:
    #        legend = plt.legend([line for line in custom_lines],[label for label in list_colored_species],title = '$\\bf{Species}$', bbox_to_anchor=(1.01, 1), loc='upper left', fontsize = plot_parameters["size_fonts"],  borderaxespad=0., ncol = 2)
    #   legend = plt.legend([line for line in custom_lines],[label for label in list_colored_species],title = '$\\bf{Species}$', bbox_to_anchor=(0.5, 0.99), loc='upper center', fontsize = plot_parameters["size_fonts"],  borderaxespad=0.,ncol = 8)
        else:
            #        legend = plt.legend([line for line in custom_lines],[label for label in list_colored_species],title = '$\\bf{Species}$', bbox_to_anchor=(1.01, 1), loc='upper left', fontsize = plot_parameters["size_fonts"],  borderaxespad=0.)
            legend = ax.legend([line for line in custom_lines],
                               [label for label in list_colored_species],
                               title='$\\bf{Species}$',
                               bbox_to_anchor=(0.5, 0.99),
                               loc='upper center',
                               fontsize=plot_parameters["size_fonts"],
                               borderaxespad=0.,
                               ncol=8)
            plt.setp(legend.get_title(),
                     fontsize=plot_parameters["size_fonts"])

        nf.write('\n')
        nf.write('Species<1%\t' +
                 '\t'.join(str(species)
                           for species in list_grey_species) + '\n')
        print(newfilename, 'is created')

    figurename = figurename + '.pdf'
    plt.savefig(figurename, bbox_inches='tight', dpi=300)
    print(figurename, 'is created')
def main(argv):
    """     ********* Main program *********     """
    #parameters for the figures depending on the output format (presentation or article)
    plot_parameters = {
        "size_fonts": 12,
        "size_font_ticks": 10,
        "size_figure": (8, 4),
        "size_markers": 4,
        "size_lines": 1,
        "shift_labelpad": 20
    }
    #other dictionnaries and parameters for the figure
    colors_T = {
        'T2': '#800080',
        'T3': '#297fff',
        'T4': '#00ff00',
        'T4.5': '#bae200',
        'T5': '#ffcd01',
        'T5.5': '#ff6e00',
        'T6': '#ff0101',
        'T6.5': '#ff00a2',
        'T7': '#ff01de',
        'T10': '#ffa6f4',
        'T15': '#ffe86e',
        'T20': '#ffbf90'
    }
    #colors_T = create_colors()
    allT = {}
    #initialization of parameters
    filename2 = ''
    xvariable = 'rho'
    #dictionnary for fullaverages file in full version
    column_number = {
        'rho': 2,
        'P': 5,
        'stdev_P': 6,
        'err_P': 7,
        'T': 8,
        'stdev_T': 9,
        'err_T': 10,
        'E': 14,
        'stdev_E': 15,
        'err_E': 16,
        'Cvm_Nkb': 23,
        'stdev_Cvm_Nkb': 24,
        'Cvm': 25,
        'stdev_Cvm': 26,
        'testCv': 31,
        'stdev_testCv': 32
    }
    #other parameters
    Na = 6.022 * 10**23
    try:
        options, arg = getopt.getopt(
            argv, "hf:g:a:x:",
            ["filename1", "gfilename2", "atoms", 'xvariable'])
    except getopt.GetoptError:
        print(
            "plot_coordinence_separated.py -f <gofr_compound.txt> -g <gofr_compound.txt 2> -a <atomic pair list:'Ca-O,K-O,Al-O,Si-O'> -x <xvariable (P or rho)>"
        )
        sys.exit()
    for opt, arg in options:
        if opt == '-h':
            print('')
            print(
                'plot_coordinence_separated.py program to plot coordinence as a function of density for each T and all cations with O'
            )
            print(
                "plot_coordinence_separated.py -f <gofr_compound.txt> -g <gofr_compound.txt 2> -a <atomic pair list:'Ca-O,K-O,Al-O,Si-O'> -x <xvariable (P or rho)>"
            )
            print(
                "plot_coordinence_separated.py requires gofr txt file containing every bond distance and coordination of one compound for every acell and T with the number of elements in header (use analyze_gofrs script etc.)"
            )
            print('')
            print(
                'For plots as function of P, make sure the files from fullaverages.py are in the current folder'
            )
            sys.exit()
        if opt in ('-f', '--filename'):
            filename = str(arg)
        elif opt in ('-g', '--gfilename'):
            filename2 = str(arg)
        elif opt in ('-a', '--atoms'):
            atoms = arg.split(',')
        elif opt in ('-x', '--xvariable'):
            xvariable = str(arg)
    #************ creation of the figure to plot (with correct number of lines)
    if filename2 != '':
        files = [filename, filename2]
        figurename = 'coordinence_' + filename.split('.txt')[0].split(
            '_')[1] + '-' + filename2.split('.txt')[0].split(
                '_')[1] + '_' + xvariable
        typeline = {filename: '--', filename2: '-'}
        typemarker = {filename: 'x', filename2: ''}
        compo = {
            filename2: format1label(filename2.split('_')[1]),
            filename: format1label(filename.split('_')[1])
        }
    else:
        files = [filename]
        figurename = 'coordinence_' + filename.split(
            '.txt')[0] + '_' + xvariable
        typeline = {filename: '-'}
        typemarker = {filename: '*'}
        compo = {filename: format1label(filename.split('_')[1])}

    if xvariable == 'P':
        fig, ax1, ax2, ax3, ax11, ax22, ax33, ax0 = creation_plot_P(
            plot_parameters)
        axis1 = [ax1, ax11]
        axis2 = [ax2, ax22]
        axis3 = [ax3, ax33]
    else:
        fig, ax1, ax2, ax3, ax0 = creation_plot(plot_parameters)
        axis1 = [ax1]
        axis2 = [ax2]
        axis3 = [ax3]
    offset = 0  #offset for printing text on Na-O K-O subplot
    #************** for each file we extract and plot data for each atom on the correct subplot
    for file in files:
        #***** Initialization of data dictionnaries
        pair_columns = {}
        data = {
        }  #big dictionnary with inside coord  all coresponding to different T and atom pairs
        X = {}  #idem for rho or P
        #******* Extract P and T for each thermo file
        if xvariable == 'P':
            TP = {}
            mineralname = file.split('_')[1]
            thermofiles = sorted(glob.glob('thermo_' + mineralname + '*.txt'))
            for thermofile in thermofiles:
                TP = extract_TP(thermofile, column_number, TP, '')
        #***** Calculation of the molecular mass
        with open(file, 'r') as f:
            line = f.readline()
            entry = line.split()
            elements = entry[1:]
            line = f.readline()
            entry = line.split()
            number = entry[1:]
            line = f.readline()
            entry = line.split()
            pair = entry[1:]
        MN = 0
        for i in range(len(elements)):
            MN = MN + float(number[i]) * cr.Elements2rest(elements[i])[3]
        #******** extraction of data
        pair_columns[pair[0]] = 4
        for i in range(1, len(pair)):
            if pair[i] != pair[i - 1]:
                pair_columns[pair[i]] = i + 4
        print('All the pair availables in the file with their index are:',
              pair_columns)
        for atom_pair in pair_columns:
            for atom in atoms:
                if atom_pair == atom:
                    data[atom] = {}
                    X[atom] = {}
        with open(file, 'r') as f:
            [f.readline() for i in range(4)]
            while True:
                line = f.readline()
                if not line: break
                else:
                    entry = line.split('\n')[0].split('\t')
                    temperature, acell = split_name(entry[0])
                    for atom_pair in pair_columns:
                        for atom in atoms:
                            if atom_pair == atom:
                                try:
                                    data[atom][temperature].append(
                                        float(entry[pair_columns[atom]]))
                                    if xvariable == 'P':
                                        X[atom][temperature].append(TP[
                                            entry[0].split('outcar.gofr.dat')
                                            [0].split('/')[-1]][1])
                                    else:
                                        X[atom][temperature].append(
                                            MN /
                                            (Na * float(acell)**3 *
                                             10**(-24)))  #calculation density
                                except KeyError:
                                    data[atom][temperature] = [
                                        float(entry[pair_columns[atom]])
                                    ]
                                    if xvariable == 'P':
                                        X[atom][temperature] = [
                                            TP[entry[0].split(
                                                'outcar.gofr.dat')[0].split(
                                                    '/')[-1]][1]
                                        ]
                                    else:
                                        X[atom][temperature] = [
                                            MN /
                                            (Na * float(acell)**3 * 10**(-24))
                                        ]  #calculation density
        #***** Plot each atom pair on the correct subplot --> ax1 for Na/K-O, ax2 for Al-O, ax3 for Si-O
        for temperature in data['Si-O']:
            allT[temperature] = ''
            for atom in data:
                if atom == 'Na-O' or atom == 'K-O' or atom == 'Ca-O':
                    for ax in axis1:
                        ax.plot(X[atom][temperature],
                                data[atom][temperature],
                                marker=typemarker[file],
                                linestyle=typeline[file],
                                color=colors_T[temperature],
                                markersize=plot_parameters["size_markers"],
                                linewidth=plot_parameters["size_lines"])
                    ax1.text(0.02,
                             0.91 - offset,
                             atom,
                             transform=ax1.transAxes,
                             fontsize=plot_parameters['size_fonts'],
                             fontweight='bold')
#                    plt.setp(ax.get_xticklabels(), visible=False)
                elif atom == 'Si-O':
                    for ax in axis3:
                        ax.plot(X[atom][temperature],
                                data[atom][temperature],
                                marker=typemarker[file],
                                linestyle=typeline[file],
                                color=colors_T[temperature],
                                markersize=plot_parameters["size_markers"],
                                linewidth=plot_parameters["size_lines"])
                    ax3.text(0.02,
                             0.91,
                             atom,
                             transform=ax3.transAxes,
                             fontsize=plot_parameters['size_fonts'],
                             fontweight='bold')
                elif atom == 'Al-O':
                    for ax in axis2:
                        ax.plot(X[atom][temperature],
                                data[atom][temperature],
                                marker=typemarker[file],
                                linestyle=typeline[file],
                                color=colors_T[temperature],
                                markersize=plot_parameters["size_markers"],
                                linewidth=plot_parameters["size_lines"])
                    ax2.text(0.02,
                             0.91,
                             atom,
                             transform=ax2.transAxes,
                             fontsize=plot_parameters['size_fonts'],
                             fontweight='bold')
        offset = offset + 0.10  #we update the offset for printing text on Na-O K-O subplot after finishing the first file

    #************ legend
    Tlist = [label for label in natsort.natsorted(allT)]
    custom_patch = [mpatches.Patch(color=colors_T[key]) for key in Tlist]
    legend = ax0.legend(
        [col for col in custom_patch],
        [str(int(float(label.strip('T')) * 1000)) for label in Tlist],
        title='$\\bf{Temperature~(K)}$',
        bbox_to_anchor=(0.5, 1.07),
        loc="lower center",
        fontsize=plot_parameters["size_font_ticks"],
        borderaxespad=0.,
        ncol=len(Tlist))
    plt.setp(legend.get_title(), fontsize=plot_parameters["size_font_ticks"])

    legend_labels = {}
    for file in files:
        legend_labels[compo[file]] = plt.Line2D(
            (0, 1), (0, 0),
            color='k',
            linestyle=typeline[file],
            markersize=plot_parameters["size_markers"] + 2,
            marker=typemarker[file])
    s = [(k, legend_labels[k])
         for k in sorted(legend_labels.keys(), reverse=False)]
    legend1 = ax0.legend([v for k, v in s], [k for k, v in s],
                         loc='lower center',
                         bbox_to_anchor=(0.5, 1.02),
                         ncol=len(files),
                         fontsize=plot_parameters["size_font_ticks"],
                         borderaxespad=0.)

    ax0.add_artist(legend)

    #save the figure
    figurename = figurename + '.pdf'
    fig.savefig(figurename, bbox_inches='tight', dpi=300)

    print(figurename, '   created')
예제 #9
0
def main(argv):
    """     ********* Main program *********     """
    atoms = 'all'
    max_den = 6
    size = {}
    lifetime = {}
    datadic = {}
    xdata = {'T':[],'rho':[]} #dictionnary containing the x data
    selected_clusters = []
    selected_files = [] #list containing the files we use for the plot (depends on the density limit)
    #other dictionnaries and parameters for the figure for article version
    list_colored_species = []
    list_colored_red = []
    list_colored_green = []
    list_colored_blue = []
    list_colored_purple = []
    list_minor_species = []
    colors_species = {"melt-like":'0'}
    letter = '' 
    plot_parameters = {"size_fonts" : 12,"size_font_ticks":10,"size_figure" : (6,4),"size_markers" : 4,"size_lines" : 1,"shift_labelpad" : 20}
    #other parameters
    Na=6.022*10**23
    sizelimit = 13
    try:
        options,arg = getopt.getopt(argv,"hf:v:m:l:a:t:d:",["filenameoutput","variable","mineralfile","letter","atoms",'type',"density_max"])
    except getopt.GetoptError:
        print("plot_speciation-analyzed-lifetime-r0.py  -f <output filename> -v <variable (rho,T)> -m <mineralfile with elements> -l <letter for article subplot, default = ''> -t <type (max or median)> -d <maximum density to plot in g/cm3> -a <list of first atoms determining the type of cluster to plot (e.g. 'Si_1O,Al_1O,melt,O')>")
        sys.exit()
    for opt,arg in options:
        if opt == '-h':
            print('')
            print('plot_speciation-analyzed-lifetime-r0.py program to  Plot the average and median lifetime of selected species as a function of T or rho')
            print("plot_speciation-analyzed-lifetime-r0.py -f <output filename> -v <variable (rho,T)> -m <mineralfile with elements> -l <letter for article subplot, default = ''> -t <type (max or median)>  -d <maximum density to plot in g/cm3> -a <list of first atoms determining the type of cluster to plot (e.g. 'Si_1O,Al_1O,melt,O')>")
            print('')
            print("all the species with more than 13 atoms are grouped together under the name 'melt-like'. To display the corresponding lifetime, indicate melt in the list of atoms")
            print('')
            print('requires to be launched from subfolder T or acell containing the requires the files popul.dat ')
            print('requires also the file containing elements and number (in order to compute the densities)')
            print('')
            sys.exit()
        elif opt in ('-f','--filename'):
            outputfilename = str(arg)
        elif opt in ("-v", "--variable"):
            xvariable = str(arg)
        elif opt in ("-m","--mineralfile"):
            mineralfile = str(arg)
        elif opt in ("-l","--letter"):
            letter = str(arg)
        elif opt in ("-a","--atoms"):
            atoms = arg.split(',')
        elif opt in ("-t","--type"):
            yvariable = str(arg)
        elif opt in ("-d","--density_max"):
            max_den = float(arg)
    #*****************************
    #*******************
    #*******
    #***** Calculation of the molecular mass
    with open(mineralfile,'r') as mf:
        entry = mf.readline()
        elements = entry.split()[1:]
        entry = mf.readline()
        number = entry.split()[1:]
    MN = 0
    for i in range(len(elements)):
        MN = MN + float(number[i]) * cr.Elements2rest(elements[i])[3]
    #*****************************
    #*******************
    #*******
    #***** Extraction of the lifetimes and creation of the xdata lists
    files = sorted(glob.glob('*r0.popul.dat')) #I list every popul.dat files in alphabetic order
    for file in files:
        #creation of the x data list
        temperature, acell = split_name(file)
        density = MN/(Na*float(acell)**3*10**(-24))
        if density <= max_den:    
            xdata['rho'].append(density )    #calculation density
            xdata['T'].append(int(temperature))   
            selected_files.append(file)
            lifetime[file] = {} #dictionnary with the lifetime of all the cluster in each file
            with open(file,'r') as f:     
                f.readline()
                f.readline()
                while True:
                    line = f.readline()
                    if not line: break
                    else:
                        entry=line.split('\t')
                        natoms = len(entry[4].split(','))
                        if natoms > sizelimit:
                            #print('for ',entry[0], 'natoms = ',natoms, '>', sizelimit)
                            try:
                                lifetime[file]['melt-like'].append(float(entry[3]))
                            except KeyError :
                                lifetime[file]['melt-like'] = [float(entry[3])]
                                size['melt-like'] = '>'+str(sizelimit)
                        else:
                            try:
                                lifetime[file][entry[0]].append(float(entry[3]))
                            except KeyError :
                                lifetime[file][entry[0]] = [float(entry[3])]
                                size[entry[0]] = natoms
                #print('lifetimes melt-like',lifetime[file]['melt-like'])
    print('for files', selected_files, len(selected_files))
    #print('we have xdata',xdata['rho'], len(xdata['rho']))
    #print('we have xdata',xdata['T'], len(xdata['T']))
    #**** Creation of the dictionnaries and lists of max or median lifetime for each cluster
    #initialisation of the dictionnary containing a list for each cluster selected
    if atoms == ['all']:
        print("we use all clusters")
        for file in selected_files:
            for cluster in lifetime[file]:
                datadic[cluster] = []
    else:
        print("we use the selected clusters")
        for file in selected_files:
            for cluster in lifetime[file]:
                for atom in atoms:
                    if cluster[:len(atom)] == atom:
                        datadic[cluster] = []                    
    #choice of the function to use
    if yvariable == 'median':
        function = np.median
    else:
        function = np.max
    for cluster in datadic:
        selected_clusters.append(cluster)
        for file in selected_files:
            try:
                datadic[cluster].append(function(lifetime[file][cluster]))
            except KeyError:
                datadic[cluster].append(0)
    #print('medianlife is',medianlife)
    #print('averagelife is',averagelife)
    print("The selected clusters are",selected_clusters)
    #*****************************
    #*******************
    #*******
    #***** Color attribution
    #**** Now the dictionary has every possible cluster, we attribute the colors to each cluster
    #check the lifetime not display the species with an average lifetime smaller than 50 fs and we add name of the species  
    for cluster in datadic : #loop on each cluster
        if max(datadic[cluster]) < 0:
            list_minor_species.append(cluster)
        elif cluster == 'melt-like':
            continue
        else:
            #this is for basic automatic color change
            list_colored_species.append(cluster)
    #**** we attribute the colors to each cluster 
    #this is for basic automatic color change
    color = iter(plt.cm.jet(np.linspace(0,1,11))) #Creation of the color list for 11 coordination #
    for i in range(1,12,1):
        c = next(color)
        colors_species[i] = c
    #*****************************
    #*******************
    #*******
    #*** Creation of the plots
    #one subplot per type without interstitial --> 2 subplots
    fig, ax1, ax2, ax0 = creation_plot(max_den,xvariable,yvariable,plot_parameters,letter)
    #plot for each cluster and write file with median and average lifetime
    figurename = outputfilename+'_'+xvariable+'_r0_'+yvariable
    newfilename = figurename + '.txt'
    nf = open(newfilename,'w')
    if xvariable == 'rho':
        nf.write('Density(g/cm3)\t' + '\t'.join(str(round(density,2)) for density in xdata[xvariable]) + '\n')
    else:
        nf.write('Temperature(K)\t' + '\t'.join(str(temp) for temp in xdata[xvariable]) + '\n')
    #plot lines
    for cluster in list_colored_species:
        print("for cluster",cluster)
        if cluster[:5] == 'Al_1O' :
            #print('plot on ax1 for cluster', cluster)
            plot_and_write(xdata, xvariable,  datadic, cluster, colors_species, plot_parameters, nf, ax1)
        elif cluster[:5] == 'Si_1O' :
            #print('plot on ax2 for cluster', cluster)
            plot_and_write(xdata, xvariable,  datadic, cluster, colors_species, plot_parameters, nf, ax2)
    #*****************************
    #*******************
    #*******
    #legend           
    list_minor_species = format_label(natsort.natsorted(list_minor_species))       
    custom_lines = [Line2D([0],[0],color = colors_species[CN], ls = '--', marker = '.', markersize = plot_parameters["size_markers"], linewidth = plot_parameters["size_lines"]) for CN in range(1,12,1)]
    list_colored_species = [str(CN) for CN in range(1,12,1)]
    print(list_colored_species)
    legend = ax0.legend([line for line in custom_lines],[label for label in list_colored_species],title = '$\\bf{x}$', bbox_to_anchor=(0.5, 1.04), loc='lower center', fontsize = plot_parameters["size_fonts"],  borderaxespad=0., ncol = 11)
    plt.setp(legend.get_title(),fontsize= plot_parameters["size_fonts"])
    ax1.text(0.99,0.99, r'AlO$_{x}$' , transform=ax1.transAxes, horizontalalignment = 'right', verticalalignment = 'top', fontweight = 'bold', fontsize = plot_parameters["size_fonts"])
    ax2.text(0.99,0.99, r'SiO$_{x}$' , transform=ax2.transAxes, horizontalalignment = 'right', verticalalignment = 'top', fontweight = 'bold', fontsize = plot_parameters["size_fonts"])
    #*****************************
    #*******************
    #*******
    #save plots
    extension = '.svg'
    figurename = figurename+ extension
    fig.savefig(figurename, bbox_inches='tight', dpi=300)
    print(figurename, 'is created')    
    nf.write('\n')
    nf.write('Species_with_medianlife<50fs\t'+ '\t'.join(str(species) for species in list_minor_species) + '\n')
    nf.close()
    print(newfilename, 'is created')
def main(argv):
    """     ********* Main program *********     """
    #parameters for the figure for article
    plot_parameters = {"size_fonts" : 12,"size_font_ticks":10,"size_figure" : (4,4),"size_markers" : 4,"size_lines" : 1,"shift_labelpad" : 10}
    thermofile = 'all'
    thermofile2 = ''
    filetype = 'all'
    init_letter = ''
    letters = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z']
    #figure dictionnary
    colors_T = {'T2':'#800080','T3':'#297fff','T4':'#00ff00','T4.5':'#bae200','T5':'#ffcd01','T5.5':'#ff6e00','T6':'#ff0101','T6.5':'#ff00a2','T7':'#ff01de','T10':'#ffa6f4','T15':'#ffe86e','T20':'#ffbf90'}
    #other parameters
    Na=6.022*10**23
    eVtoJ = 1.6e-19        #1eV = 1.6e-19 J
    kb = 1.38064852e-23    #boltzmann constant
    try:
        options,arg = getopt.getopt(argv,"hf:g:t:l:",["filename","gfilename","type",'letter'])
    except getopt.GetoptError:
        print("plot_thermo-rho.py -f <thermo_filename (default = 'all')>  -g <thermo_filename 2 (if we want to plot 2 files)>  -t <type of the file: 'short' or 'all'> -l <letter of first plot, default = ''> ")
        sys.exit()
    for opt,arg in options:
        if opt == '-h':
            print('')
            print('plot_thermo-rho.py program to fit and plot BM3 as a function of density')
            print("plot_thermo-rho.py -f <thermo_filename (default = 'all' -> 3plot)> -g <thermo_filename 2 (if we want to plot 2 files)>  -t <type of the file: 'short' or 'all'>  -l <letter of first plot, default = ''>")
            print('')
            sys.exit()
        elif opt in ('-f','--filename'):
            thermofile = str(arg)
        elif opt in ('-g','--gfilename'):
            thermofile2 = str(arg)
        elif opt in ('-t','--type'):
            filetype = str(arg)
        elif opt in ('-l','--letter'):
            init_letter = str(arg)
    #selection of the column depending on the type of the thermo file
    if filetype == 'all':
        column_number = {'rho':2,'P':5,'stdev_P':6,'err_P':7,'T':8,'stdev_T':9,'err_T':10,'E':14,'stdev_E':15,'err_E':16,'Cvm_Nkb':23,'stdev_Cvm_Nkb':24,'Cvm':25,'stdev_Cvm':26}
    else:
        column_number = {'rho':2,'P':5,'stdev_P':6,'err_P':7,'T':8,'stdev_T':9,'err_T':10,'E':11,'stdev_E':12,'err_E':13,'Cvm_Nkb':14,'stdev_Cvm_Nkb':15}
    #************ initialization of the plot
    if thermofile == 'all':
        fig,ax1,ax2,ax3, ax0 = creation_plot_3(plot_parameters)
        print("axis are ax1",ax1,"ax2",ax2,"ax3",ax3,"ax0",ax0)
        files = sorted(glob.glob('thermo_*O8_'+filetype+'.txt'),reverse=True) #I list every thermo files
        figurename = 'Fit_BM3_thermo_all'
    elif thermofile2 != '':
        fig,ax1,ax2, ax0  = creation_plot_2(plot_parameters)
        print("axis are ax1",ax1,"ax2",ax2,"ax0",ax0)
        files = [thermofile, thermofile2] #we will plot 2 files
        figurename = 'Fit_BM3_'+thermofile.split('.txt')[0]+'_'+thermofile2.split('.txt')[0].split('_')[1]
    else:
        fig, ax = creation_plot(plot_parameters)
        files = [thermofile] #I take only the file we want
        figurename = 'Fit_BM3_'+thermofile.split('.txt')[0]
    #************ creation of arrays and plot at the same time
    for file in files:
        print("****** For file",file)
        #********initialisations
        #**change of subplot
        if thermofile == 'all' or thermofile2 !='':
            if files.index(file) == 0:
                ax=ax1
                letter = init_letter                    
            if files.index(file) == 1:
                ax=ax2
                try:
                    letter = letters[letters.index(init_letter)+1]
                except ValueError:
                    print("You haven't indicated any letter")
                    letter = ''
            if files.index(file) == 2:
                ax=ax3 
                try:
                    letter = letters[letters.index(init_letter)+2]
                except ValueError:
                    print("You haven't indicated any letter")
            #print("I plot on axis",ax)
        #**initialisation of data dictionnaries
        rho = {}
        V = {}
        P = {}
        stdev_P = {}
        data = {}
        #********* creation of the BM3 txt file
        bm = fileBM3(file)
        #********* fill the dictionnaries with data
        with open(file,'r') as f:
            line = f.readline()
            entry=line.split()
            elements = entry[1:]
            line = f.readline()
            entry=line.split()
            number = entry[1:]
            f.readline()
            #calculation of M*N nedded for the calculation of volumes
            MN = 0
            for i in range(len(elements)):
                MN = MN + float(number[i]) * cr.Elements2rest(elements[i])[3]   
            #extract data
            while True:
                line = f.readline()
                if not line: break
                else:    
                    entry=line.split('\n')[0].split('\t')
                    temperature, acell = split_name(entry[0])
                    try:
                        data[temperature].append([  float(entry[column_number['rho']]) , float(entry[column_number['P']]) , float(entry[column_number['stdev_P']])   ])
                    except KeyError:                      
                        data[temperature] = []
                        data[temperature].append([  float(entry[column_number['rho']]) , float(entry[column_number['P']]) , float(entry[column_number['stdev_P']])   ])
        #********* remove the data we do not want to use
        for temperature in data:
            #first we sort the data by density from biggest to smallest
            data[temperature] = sorted(data[temperature], key=lambda x: x[0], reverse=True) #sort by the first column: rho
            #second we create rho,P,stdev_P dictionnaries with only the data with positive P starting below 100 GPa
            for ii in range(len(data[temperature])):
                if data[temperature][ii][1] < 100:
                    if data[temperature][ii][1] < 1 or  data[temperature][ii][0] < 1.6   :
                        #if the pressure is below 1GPa or below the limit density, then we take this value and STOP the loop to not take the others
                        try:
                            rho[temperature].append(data[temperature][ii][0] )
                            V[temperature].append( MN / (Na * data[temperature][ii][0]*1E-24))
                            P[temperature].append(data[temperature][ii][1]  )
                            stdev_P[temperature].append(data[temperature][ii][2] )
                        except KeyError:
                            rho[temperature] = []
                            rho[temperature].append(data[temperature][ii][0] )
                            V[temperature] = [ MN / (Na * data[temperature][ii][0]*1E-24)]
                            P[temperature] = [data[temperature][ii][1]  ]
                            stdev_P[temperature] = [data[temperature][ii][2] ]
                        break
                    else:
                        try:
                            rho[temperature].append(data[temperature][ii][0] )
                            V[temperature].append( MN / (Na * data[temperature][ii][0]*1E-24))
                            P[temperature].append(data[temperature][ii][1]  )
                            stdev_P[temperature].append(data[temperature][ii][2] )
                        except KeyError:
                            rho[temperature] = []
                            rho[temperature].append(data[temperature][ii][0] )
                            V[temperature] = []
                            V[temperature].append(MN / (Na * data[temperature][ii][0]*1E-24))
                            P[temperature] = []
                            P[temperature].append(data[temperature][ii][1]  )
                            stdev_P[temperature] = []
                            stdev_P[temperature].append(data[temperature][ii][2] )     
        #******** Fit data and plot
        #This is the theoretical model (initial guesses), based on common values 
        m0 = {'T2':[2.6,15,4],'T3':[2.6,15,4],'T4':[2.6,15,4],'T5':[2.6,15,4],'T6':[2.6,15,4],'T10':[2.6,15,4],'T15':[2.6,15,4],'T20':[2.6,15,4]} #rho0 in g/cm3, K0 in GPa, Kp0
        #m0 = {'T3':[3000,19,4],'T4':[3000,19,4],'T5':[3000,15,4],'T6':[3000,15,6]} #V0 in angstrom3, K0 in GPa, Kp0
        drho = 0.1
        for temperature in sorted(rho):
            if len(rho[temperature]) > 4:
                #***************** fit using P=f(rho)
               # try:  #Least square fit
               #     m, pcov = curve_fit(fonction_BM3, rho[temperature], P[temperature], p0=m0[temperature], sigma=stdev_P[temperature], absolute_sigma=False )
               #     chi2 = chi2red(m,rho[temperature],P[temperature],stdev_P[temperature])
               #     DensityX=np.arange(rho[temperature][-1]-drho,rho[temperature][0]+drho,drho) 
               #     ax.plot(DensityX,fonction_BM3(DensityX,m[0],m[1],m[2]),'-', color=colors_T[temperature], label= temperature + ' BM3 fit')
               #     print(temperature, "Least-square fit of BM3")
               #     perr = np.sqrt(np.diag(pcov)) #stdev on the parameters
               #     bm.write(str(temperature) + '\t' + str('{:1.2e}'.format(chi2)) + '\t' + str('{:1.2e}'.format(m[0])) + '\t' + str('{:1.2e}'.format(m[1])) + '\t' + str('{:1.2e}'.format(m[2])) + '\t' + str('{:1.2e}'.format(perr[0])) + '\t' + str('{:1.2e}'.format(perr[1])) + '\t' + str('{:1.2e}'.format(perr[2])) +'\n')
                #try:   #fmin fit    
                #    m=simplex(fonction, m0[temperature], args=(rho[temperature], P[temperature], stdev_P[temperature]), maxiter = 1000000, full_output=0)
                #    chi2=chi2red(m,rho[temperature],P[temperature],stdev_P[temperature])
                #    DensityX=np.arange(rho[temperature][-1]-drho,rho[temperature][0]+drho,drho) 
                #    ax.plot(DensityX,fonction_BM3(DensityX,m[0],m[1],m[2]),'-', color=colors_T[temperature], label= temperature + ' BM3 fit')
                #    print(temperature, "Least-square fit of BM3")
                #    bm.write(str(temperature) + '\t' + str('{:1.2e}'.format(chi2)) + '\t' + str('{:1.2e}'.format(m[0])) + '\t' + str('{:1.2e}'.format(m[1])) + '\t' + str('{:1.2e}'.format(m[2])) + '\n')
                try: #odr fit
                    eos_model_BM3 = odr.Model(BM3_P_rho)  # model for fitting
                    stdev_rho = [i/1000 for i in rho[temperature]] #creation of stdev for rho
                    data_for_ODR = odr.RealData(rho[temperature], P[temperature], stdev_rho, stdev_P[temperature]) # RealData object using our data
                    odr_process = odr.ODR(data_for_ODR, eos_model_BM3, beta0=m0[temperature], maxit = 10000) # Set up orth-dist-reg with the model and data
                    odr_results = odr_process.run() # run the regression
                    print('***************',temperature, "Fit of BM3")
                    odr_results.pprint() # use the pprint method to display results
                    DensityX=np.arange(rho[temperature][-1]-drho,rho[temperature][0]+drho,drho) 
                    ax.plot(DensityX,BM3_P_rho(odr_results.beta,DensityX),'-', color=colors_T[temperature], label= temperature + ' BM3 fit')
                    bm.write(str(temperature) + '\t' + str('{:1.2e}'.format(odr_results.res_var)) + '\t' + str('{:1.2e}'.format(odr_results.beta[0])) + '\t' + str('{:1.2e}'.format(odr_results.beta[1])) + '\t' + str('{:1.2e}'.format(odr_results.beta[2])) + '\t' + str('{:1.2e}'.format(odr_results.sd_beta[0])) + '\t' + str('{:1.2e}'.format(odr_results.sd_beta[1])) + '\t' + str('{:1.2e}'.format(odr_results.sd_beta[2]))  + '\n')
                    #print('chi2red', chi2red(odr_results.beta,rho[temperature],P[temperature],stdev_P[temperature]))
                    #print('residual variance',odr_results.res_var)
                #***************** fit using P=f(V)
                #try: #odr fit
                #    eos_model_BM3 = odr.Model(BM3_P_V)  # model for fitting
                #    stdev_V = [i/1000 for i in V[temperature]] #creation of stdev for rho
                #    data_for_ODR = odr.RealData(V[temperature], P[temperature], stdev_V, stdev_P[temperature]) # RealData object using our data
                #    odr_process = odr.ODR(data_for_ODR, eos_model_BM3, beta0=m0[temperature], maxit = 10000) # Set up orth-dist-reg with the model and data
                #    odr_results = odr_process.run() # run the regression
                #    print('***************',temperature, "Fit of BM3")
                #    odr_results.pprint() # use the pprint method to display results
                #    DensityX=np.arange(rho[temperature][-1]-drho,rho[temperature][0]+drho,drho) 
                #    VolumeX = [MN/(Na*DensityX[ii]*1E-24) for ii in range(len(DensityX))]
                #    ax.plot(DensityX,BM3_P_V(odr_results.beta,VolumeX),'-', color=colors_T[temperature], label= temperature + ' BM3 fit')
                #    bm.write(str(temperature) + '\t' + str('{:1.2e}'.format(odr_results.sum_square)) + '\t' + str('{:1.2e}'.format(MN/(Na*odr_results.beta[0]*1E-24))) + '\t' + str('{:1.2e}'.format(odr_results.beta[1])) + '\t' + str('{:1.2e}'.format(odr_results.beta[2])) + '\n')
                except RuntimeError:
                    print(temperature, "FAIL of fit of BM3")
                    bm.write(str(temperature) + '\t-\t-\t-\t-\n')
                ax.plot(rho[temperature],P[temperature],'o', color=colors_T[temperature], markersize = plot_parameters['size_markers'], label= temperature + ' data')
    #Create legend from custom artist/label lists  
#    legend_labels['not started'] = plt.Line2D((0,1),(0,0),  markersize = plot_parameters["size_markers"], marker='o', facecolor = 'r', edgecolor='r', linestyle='')
#    s = [(k, legend_labels[k]) for k in sorted(legend_labels.keys(),reverse = False)]
#    if filename == 'all':
#        ax=ax0
#    plt.legend([v for k,v in s],[k for k,v in s],loc='upper center', bbox_to_anchor=(0.46, 1.14),fancybox=True, fontsize = plot_parameters["size_fonts"], ncol=len(style_lines))
    figurename = figurename+'.png'
    print("figure saved with name ",figurename)
    fig.savefig(figurename, bbox_inches = 'tight', dpi = 300)
def main(argv):
    """     ********* Main program *********     """
    #parameters for the figures depending on the output format (presentation or article)
    plot_parameters = {"size_fonts" : 12,"size_font_ticks":10,"size_figure" : (8,4),
                       "size_markers" : 8,"size_lines" : 1,"shift_labelpad" : 20}
    colors_T = {'2000':'#800080','3000':'#297fff','4000':'#00ff00','4500':'#bae200',
                '5000':'#ffcd01','5500':'#ff6e00','6000':'#ff0101','6500':'#ff00a2','7000':'#ff01de'}
    #initialization of parameters
    yvariable = 4 #for coord #
    #yvariable = 5 #for bond length
    #yvariable = 1 #for xmax
    filename4 = ''
    filename3 = ''
    xvariable = 'rho'
    #dictionnary for fullaverages file in full version
    column_number = {'rho':2,'P':5,'stdev_P':6,'err_P':7,'T':8,'stdev_T':9,'err_T':10,
                     'E':14,'stdev_E':15,'err_E':16,'Cvm_Nkb':23,'stdev_Cvm_Nkb':24,
                     'Cvm':25,'stdev_Cvm':26,'testCv':31,'stdev_testCv':32}
    #other parameters
    Na=6.022*10**23
    try:
        options,arg = getopt.getopt(argv,"hf:g:j:i:x:",["filename2","gfilename","jfilename","ifilename",'xvariable'])
    except getopt.GetoptError:
        print("plot_coordinence+comparison.py -f <gofr_compound.txt> -g <gofr_comparison1.txt> -j <gofr_comparison2.txt> -i <gofr_comparison3.txt> -x <xvariable (P or rho)>")
        sys.exit()
    for opt,arg in options:
        if opt == '-h':
            print('')
            print('plot_coordinence+comparison.py same program as plot_coordinence_separated but to compare one of our data file with other (literrature) data files')
            print("plot_coordinence+comparison.py-f <gofr_compound.txt> -g <gofr_comparison1.txt> -j <gofr_comparison2.txt> -i <gofr_comparison3.txt> -x <xvariable (P or rho)>")
            print("plot_coordinence+comparison.py requires gofr txt file containing every bond distance and coordination of one compound for every acell and T with the number of elements in header (use analyze_gofrs script etc.)")
            print('')
            print('For plots as function of P, make sure the files from fullaverages.py are in the current folder')
            sys.exit()
        if opt in ('-f','--filename'):
            filename = str(arg)
        elif opt in ('-g','--gfilename'):
            filename2 = str(arg) 
        elif opt in ('-j','--jfilename'):
            filename3 = str(arg)
        elif opt in ('-i','--ifilename'):
            filename4 = str(arg)
        elif opt in ('-x','--xvariable'):
            xvariable = str(arg)
    #************ creation of the figure to plot (with correct number of lines)
    string = filename.split('_')[1]
    files = [filename]
    for file in [filename2,filename3,filename4]:
        if file != '':
            files.append(file)
            string += '-'+file.split('.txt')[0].split('_')[-1]
    string +='_'+xvariable    
    typeline = {filename : '-', filename2: '*', filename3: '+',filename4: 'd'}
    atoms = ['Na-O','Ca-O','Al-O','Si-O']
    
    if xvariable == 'P':
        fig, ax1,ax2,ax3,ax11,ax22,ax33, ax0 = creation_plot_P(plot_parameters)
        axis1 = [ax1,ax11]
        axis2 = [ax2,ax22]
        axis3 = [ax3,ax33]
    else:
        fig, ax1,ax2,ax3,ax0 = creation_plot(plot_parameters)
        axis1 = [ax1]
        axis2 = [ax2]        
        axis3 = [ax3]
    offset = 0 #offset for printing text on Na-O K-O subplot
    if yvariable == 4:
        ax0.set_ylabel(r'Coordination number', fontweight = 'bold', fontsize = plot_parameters["size_fonts"],
                       labelpad = plot_parameters["shift_labelpad"])
        figurename = 'coordinence_'+ string
    elif yvariable == 5: 
        ax0.set_ylabel(r'Bond length ($\AA$)', fontweight = 'bold', fontsize = plot_parameters["size_fonts"], 
                       labelpad = plot_parameters["shift_labelpad"]*2)
        figurename = 'bondlength_'+ string
    else:
        ax0.set_ylabel(r'????', fontweight = 'bold', fontsize = plot_parameters["size_fonts"], 
                       labelpad = plot_parameters["shift_labelpad"])
        figurename = 'unknown_'+ string
    
    #************** Extract our data and plot 
    #*** Initialization of data dictionnaries
    pair_columns = {}
    data = {} #big dictionnary with inside coord  all coresponding to different T and atom pairs
    X = {}  #idem for rho or P
    #******* Extract P and T for each thermo file
    if xvariable == 'P':
        TP = {}
        mineralname = filename.split('_')[1]
        thermofiles = sorted(glob.glob('thermo_'+mineralname+'*.txt'))
        for thermofile in thermofiles:
            TP = extract_TP(thermofile, column_number, TP,'')
    #*** Calculation of the molecular mass
    with open(filename, 'r') as f:
        line = f.readline()
        entry=line.split()
        elements = entry[1:]
        line = f.readline()
        entry=line.split()
        number = entry[1:]
        line = f.readline()
        entry=line.split()
        pair = entry[1:]
    MN = 0
    for i in range(len(elements)):
        MN = MN + float(number[i]) * cr.Elements2rest(elements[i])[3]
    #******** extraction of data        
    pair_columns[pair[0]] =yvariable
    for i in range(1,len(pair)):
        if pair[i] != pair[i-1]:
            pair_columns[pair[i]] = i+yvariable
    print('All the pairs available in the file with their index are:', pair_columns)
    for atom_pair in pair_columns:
        for atom in atoms:
            if atom_pair == atom:
                data[atom] = {}
                X[atom] = {}
    with open(filename,'r') as f:
        [f.readline() for i in range(4)]
        while True:
            line = f.readline()
            if not line: break
            else:
                entry=line.split('\n')[0].split('\t')
                temperature, acell = split_name(entry[0]) 
                for atom_pair in pair_columns:
                    for atom in atoms:
                        if atom_pair == atom:
                            try:
                                data[atom][temperature].append( float(entry[pair_columns[atom]]) )
                                if xvariable == 'P':
                                    X[atom][temperature].append(TP[entry[0].split('outcar.gofr.dat')[0].split('/')[-1]][1])
                                else:
                                    X[atom][temperature].append( MN/(Na*float(acell)**3*10**(-24)) )    #calculation density
                            except KeyError:
                                data[atom][temperature] = [ float(entry[pair_columns[atom]]) ]
                                if xvariable == 'P':
                                    X[atom][temperature] = [TP[entry[0].split('outcar.gofr.dat')[0].split('/')[-1]][1]]
                                else:
                                    X[atom][temperature] = [ MN/(Na*float(acell)**3*10**(-24)) ]    #calculation density
    #***** Plot each atom pair on the correct subplot --> ax1 for Na/Ca-O, ax2 for Al-O, ax3 for Si-O
    for temperature in data['Si-O']:
        for atom in data:
            if atom == 'Ca-O' or atom == 'Na-O':
                for ax in axis1:
                    ax.plot(X[atom][temperature],data[atom][temperature], linestyle = typeline[filename][:], color=colors_T[temperature], markersize = plot_parameters["size_markers"], linewidth=plot_parameters["size_lines"] )
            elif atom == 'Si-O':
                for ax in axis2:
                    ax.plot(X[atom][temperature],data[atom][temperature], linestyle = typeline[filename][:], color=colors_T[temperature], markersize = plot_parameters["size_markers"], linewidth=plot_parameters["size_lines"] )
                ax2.text( 0.02,0.91, atom ,transform=ax2.transAxes, fontsize=plot_parameters['size_fonts'], fontweight='bold'  ) #for coord
                #ax2.text( 0.87,0.91, atom ,transform=ax2.transAxes, fontsize=plot_parameters['size_fonts'], fontweight='bold'  ) #for bond
            elif atom == 'Al-O':
                for ax in axis3:
                    ax.plot(X[atom][temperature],data[atom][temperature],linestyle = typeline[filename][:], color=colors_T[temperature], markersize = plot_parameters["size_markers"], linewidth=plot_parameters["size_lines"] )
                ax3.text(0.02,0.91, atom ,transform=ax3.transAxes, fontsize=plot_parameters['size_fonts'], fontweight='bold'  ) #for coord
                #ax3.text(0.87,0.91, atom ,transform=ax3.transAxes, fontsize=plot_parameters['size_fonts'], fontweight='bold'  ) #for bond
    #************** Extract the collected data and plot
    pair_sources = {'gofrs-coordinence_Neilson2016.txt':'Na-O','gofrs-coordinence_Spera2009.txt':'Ca-O','gofrs-coordinence_deKoker2010.txt':'Ca-O'}
    sources = {'gofrs-coordinence_Neilson2016.txt':'Neilson $et~al.$ (2016)','gofrs-coordinence_Spera2009.txt':'Spera $et~al.$ (2009)','gofrs-coordinence_deKoker2010.txt':'de Koker (2010)','gofrs-bond_deKoker2010.txt':'de Koker (2010)'}
    for file in files[1:]:
        print('For file ',file)
        #***** Initialization of data dictionnaries
        pair_columns={'Na-O':2,'Ca-O':2,'Al-O':3,'Si-O':4}
        data = {} #big dictionnary with inside coord  all coresponding to different T and atom pairs
        X = {}  #idem for rho or P
        with open(file, 'r') as f:
            line = f.readline()
            entry=line.split()
            pairs = entry[2:9]
        print('All the pairs available in the file are:', pairs)
        #******** extraction of data        
        for atom_pair in pairs:
            for atom in atoms:
                if atom_pair == atom:
                    data[atom] = {}
                    X[atom] = {}
        with open(file,'r') as f:
            f.readline()
            while True:
                line = f.readline()
                if not line: break
                else:
                    entry=line.split('\n')[0].split('\t')
                    temperature = str(int(float( entry[9])))
                    for atom_pair in pairs:
                        for atom in atoms:
                            if atom_pair == atom:
                                try:
                                    data[atom][temperature].append( float(entry[pair_columns[atom]]) )
                                    if xvariable == 'P':
                                        X[atom][temperature].append( float(entry[1])) 
                                    else:
                                        X[atom][temperature].append( float(entry[0])/1000) 
                                except KeyError:
                                    data[atom][temperature] = [ float(entry[pair_columns[atom]]) ]
                                    if xvariable == 'P':
                                        X[atom][temperature] = [ float(entry[1])]
                                    else:
                                        X[atom][temperature] = [ float(entry[0])/1000]   
        #***** Plot each atom pair on the correct subplot --> ax1 for Na/Ca-O, ax2 for Al-O, ax3 for Si-O
        for temperature in data['Si-O']:
            #**** select the color of symbols
            typefill = {filename : None, filename2: colors_T[temperature], filename3: 'w',filename4: 'w'}
            for atom in data:
                if atom == 'Ca-O' or atom == 'Na-O':
                    #print('plot M-O for ', temperature)
                    for ax in axis1:
                        ax.plot(X[atom][temperature],data[atom][temperature], marker = typeline[file][0], markeredgewidth = 0.5, linestyle = 'None', markerfacecolor=typefill[file], markeredgecolor=colors_T[temperature], markersize = plot_parameters["size_markers"] )
                elif atom == 'Si-O':
                    #print('plot Si-O for ', temperature)
                    for ax in axis2:
                        ax.plot(X[atom][temperature],data[atom][temperature], marker = typeline[file][0], markeredgewidth = 0.5, linestyle = 'None', markerfacecolor=typefill[file], markeredgecolor=colors_T[temperature], markersize = plot_parameters["size_markers"] )
                elif atom == 'Al-O':
                    #print('plot Al-O for ', temperature)
                    for ax in axis3:
                        ax.plot(X[atom][temperature],data[atom][temperature], marker = typeline[file][0], markeredgewidth = 0.5, linestyle = 'None', markerfacecolor=typefill[file], markeredgecolor=colors_T[temperature], markersize = plot_parameters["size_markers"] )
    for atom in ['Ca-O','Na-O']:
        ax1.text( 0.02,0.91-offset, atom,transform=ax1.transAxes, fontsize=plot_parameters['size_fonts'], fontweight='bold'  ) #for coord
        #ax1.text( 0.87,0.91-offset, atom,transform=ax1.transAxes, fontsize=plot_parameters['size_fonts'], fontweight='bold'  ) #for bond
        offset = offset + 0.10        #we update the offset for printing text on Na-O K-O subplot after finishing the first file              
    #Legend 
    typefill = {filename : None, filename2: 'k', filename3: 'w',filename4: 'w'}
    legend_labels = {}
    for file in files[1:]: 
        legend_labels[sources[file]] =  plt.Line2D((0,1),(0,0), markeredgecolor='k',
                     markerfacecolor = typefill[file], linestyle = 'None', 
                     markersize = plot_parameters["size_markers"], marker=typeline[file][0])
    legend_labels['this study'] =  plt.Line2D((0,1),(0,0), color='k', linestyle=typeline[filename][:], 
                 linewidth = plot_parameters["size_lines"])
    s = [(k, legend_labels[k]) for k in sorted(legend_labels.keys(),reverse = False)]      
    ax1.legend([v for k,v in s],[k for k,v in s], loc='lower right', bbox_to_anchor=(0.99, 0.01),
               ncol=1, fontsize = plot_parameters["size_font_ticks"], borderaxespad=0.) #for coord
    #ax1.legend([v for k,v in s],[k for k,v in s], loc='lower left', bbox_to_anchor=(0.01, 0.01), ncol=1, fontsize = plot_parameters["size_font_ticks"], borderaxespad=0.) #for bond

    
    #save the figure
    figurename = figurename + '.pdf'
    fig.savefig(figurename, bbox_inches = 'tight', dpi = 300)
    
    print(figurename, '   created')
예제 #12
0
def main(argv):
    """     ********* Main program *********     """
    #parameters for the figure for article
    plot_parameters = {
        "size_fonts": 12,
        "size_font_ticks": 10,
        "size_figure": (10, 4),
        "size_markers": 4,
        "size_lines": 1,
        "shift_labelpad": 5
    }
    #other dictionnaries and parameters for the figure
    lines = {}  #dictionnary for the lines for legend
    Na = 6.022 * 10**23  #avogadro constant
    #other dictionnaries and parameters for the figure
    colors_densities = {}
    colors_T = {
        'T2': '#800080',
        'T3': '#297fff',
        'T4': '#00ff00',
        'T4.5': '#bae200',
        'T5': '#ffcd01',
        'T6': '#ff0101',
        'T6.5': '#ff00a2',
        'T7': '#ff01de'
    }
    #colors_T = create_colors()
    allT = {}  #dictionnary for the legend
    letters = ['a', 'b']
    try:
        options, arg = getopt.getopt(argv, "hm:a:v:f:g:l:", [
            "mineralfile", "atoms", "variable", "folder1", "gfolder2",
            "letters"
        ])
    except getopt.GetoptError:
        print(
            "plot_allgofrs_2subplots.py  -m <mineralfile>  -a <1 couple of atoms>(ex: 'O-O') -v <variable for colors (rho,T)> -f <folder 1> -g <folder 2> -l <two letters>"
        )
        sys.exit()
    for opt, arg in options:
        if opt == '-h':
            print(
                "plot_allgofrs_2subplots.py script to plot all the gofrs of the selected couple of atoms at every acell for 2 T or at every T for 2 acell"
            )
            print(
                "plot_allgofrs_2subplots.py for O-O, an insert is added  to zoom in the 0-2$\AA$ region"
            )
            print("WARNING!!!!!")
            print(
                "plot_allgofrs_2subplots.py requires to have separated folders of T and acell in order to plot all the files from the 2 T folders or from the 2 acell folders"
            )
            print("")
            print(
                "plot_allgofrs_2subplots.py -m <mineralfile>  -a <1 couple of atoms>(ex: 'O-O') -v <variable for colors (rho,T)>  -f <folder 1> -g <folder 2> -l <two letters>"
            )
            print("")
            sys.exit()
        elif opt in ("-a", "--atoms"):
            atom_couple = str(
                arg)  #list of atom couples we want to analyze here
        elif opt in ("-m", "--mineralfile"):
            mineralfile = str(arg)
        elif opt in ("-v", "--variable"):
            variable = str(arg)
        elif opt in ("-f", "--folder1"):
            folder1 = str(arg).split('/')[0]
        elif opt in ("-g", "--gfolder2"):
            folder2 = str(arg).split('/')[0]
        elif opt in ("-l", "--letters"):
            letters = arg.split(',')
    #***** Calculation of the molecular mass
    with open(mineralfile, 'r') as mf:
        entry = mf.readline()
        elements = entry.split()[1:]
        entry = mf.readline()
        number = entry.split()[1:]
    MN = 0
    for i in range(len(elements)):
        MN = MN + float(number[i]) * cr.Elements2rest(
            elements[i])[3]  #I compute the molecular mass
    #***** Count of the number of densities or temperatures (needed for the automatic color change)
    #loop throught all files of the selected folder
    files1 = sorted(
        glob.glob(folder1 + '/*outcar.gofr.dat'
                  ))  #I list every gofr files from folder1 in alphabetic order
    files2 = sorted(
        glob.glob(folder2 + '/*outcar.gofr.dat'
                  ))  #I list every gofr files from folder1 in alphabetic order
    files = files1[:]
    files.extend(files2)
    print(files)
    files.reverse()
    if variable == 'rho':
        #we store every density into the dictionary colors_densities
        for file in files:
            #calculation of densities in g/cm3
            temperature, acell = split_name(file)
            Volume = float(acell)**3
            Density = MN / (Na * Volume * 10**(-24))
            #we store the densities into the dictionnary
            colors_densities[round(Density, 1)] = []
    #now the dictionary has every possible densities or temperatures of our mineral, we attribute the colors to each density/temperature
    list_densities = []
    if variable == 'rho':
        color = iter(plt.cm.rainbow(np.linspace(
            0, 1, len(colors_densities))))  #Creation of the color list
        for key in natsort.natsorted(colors_densities):
            c = next(color)
            colors_densities[key] = c
            list_densities.append(
                key
            )  #list usefull if we want to plot the value of densities near to the lines, see plot_speciation_r0
        print(
            list_densities,
            "densities list for color bar. If you don't want densities but temperatures, please change the variable option to T"
        )
    else:
        print([
            key for key in colors_T
        ], "temperature list for color bar. If you don't want temperatures but densities, please change the variable option to rho"
              )
    #*****************************
    #*******************
    #*******
    #Read & plot
    firstfile = files[0]  #I take the first file
    temperature0, acell0 = split_name(firstfile)
    with open(firstfile, 'r') as f:
        couples = f.readline()
        couples = couples.strip('dist')
        couples = re.sub('(Int\([A-Za-z-]*\))', ' ', couples).split(
        )  #I substitute all Int(...)  by a blankspace and split using spaces
    col = 0
    for couple in couples:
        if (couple == atom_couple):
            if atom_couple == 'O-O':
                fig, ax1, ax2, ax11, ax22 = creation_plot_insert(
                    plot_parameters, atom_couple)
                indexcol = couples.index(couple) + col + 1
                if variable == 'rho':
                    for file in files1:
                        #extraction of data
                        distance, gofr = extraction(file, indexcol)
                        #extraction of key for color legend
                        temperature, acell = split_name(file)
                        Volume = float(acell)**3
                        Density = MN / (Na * Volume * 10**(-24)
                                        )  #calculation of densities in g/cm3
                        #plot
                        lines[str(round(Density, 1))], = ax1.plot(
                            distance,
                            gofr,
                            color=colors_densities[round(Density, 1)],
                            linewidth=plot_parameters['size_lines'])
                        ax11.plot(distance,
                                  gofr,
                                  color=colors_densities[round(Density, 1)],
                                  linewidth=plot_parameters['size_lines'])
                    for file in files2:
                        #extraction of data
                        distance, gofr = extraction(file, indexcol)
                        #extraction of key for color legend
                        temperature, acell = split_name(file)
                        Volume = float(acell)**3
                        Density = MN / (Na * Volume * 10**(-24)
                                        )  #calculation of densities in g/cm3
                        #plot
                        lines[str(round(Density, 1))], = ax2.plot(
                            distance,
                            gofr,
                            color=colors_densities[round(Density, 1)],
                            linewidth=plot_parameters['size_lines'])
                        ax22.plot(distance,
                                  gofr,
                                  color=colors_densities[round(Density, 1)],
                                  linewidth=plot_parameters['size_lines'])
                else:  #variable == T
                    for file in files1:
                        #extraction of data
                        distance, gofr = extraction(file, indexcol)
                        #extraction of key for color legend
                        temperature, acell = split_name(file)
                        #plot
                        lines[format_T(temperature)], = ax1.plot(
                            distance,
                            gofr,
                            color=colors_T[temperature],
                            linewidth=plot_parameters['size_lines'])
                        ax11.plot(distance,
                                  gofr,
                                  color=colors_T[temperature],
                                  linewidth=plot_parameters['size_lines'])
                    for file in files2:
                        #extraction of data
                        distance, gofr = extraction(file, indexcol)
                        #extraction of key for color legend
                        temperature, acell = split_name(file)
                        #plot
                        lines[format_T(temperature)], = ax2.plot(
                            distance,
                            gofr,
                            color=colors_T[temperature],
                            linewidth=plot_parameters['size_lines'])
                        ax22.plot(distance,
                                  gofr,
                                  color=colors_T[temperature],
                                  linewidth=plot_parameters['size_lines'])
            else:  #atom_couple != O-O
                fig, ax1, ax2 = creation_plot(plot_parameters, atom_couple)
                indexcol = couples.index(couple) + col + 1
                if variable == 'rho':
                    for file in files1:
                        #extraction of data
                        distance, gofr = extraction(file, indexcol)
                        #extraction of key for color legend
                        temperature, acell = split_name(file)
                        Volume = float(acell)**3
                        Density = MN / (Na * Volume * 10**(-24)
                                        )  #calculation of densities in g/cm3
                        #plot
                        lines[str(round(Density, 1))], = ax1.plot(
                            distance,
                            gofr,
                            color=colors_densities[round(Density, 1)],
                            linewidth=plot_parameters['size_lines'])
                    for file in files2:
                        #extraction of data
                        distance, gofr = extraction(file, indexcol)
                        #extraction of key for color legend
                        temperature, acell = split_name(file)
                        Volume = float(acell)**3
                        Density = MN / (Na * Volume * 10**(-24)
                                        )  #calculation of densities in g/cm3
                        #plot
                        lines[str(round(Density, 1))], = ax2.plot(
                            distance,
                            gofr,
                            color=colors_densities[round(Density, 1)],
                            linewidth=plot_parameters['size_lines'])
                else:  #variable == T
                    for file in files1:
                        #extraction of data
                        distance, gofr = extraction(file, indexcol)
                        #extraction of key for color legend
                        temperature, acell = split_name(file)
                        #plot
                        lines[format_T(temperature)], = ax1.plot(
                            distance,
                            gofr,
                            color=colors_T[temperature],
                            linewidth=plot_parameters['size_lines'])
                    for file in files2:
                        #extraction of data
                        distance, gofr = extraction(file, indexcol)
                        #extraction of key for color legend
                        temperature, acell = split_name(file)
                        #plot
                        lines[format_T(temperature)], = ax2.plot(
                            distance,
                            gofr,
                            color=colors_T[temperature],
                            linewidth=plot_parameters['size_lines'])
        col += 1
    #article letter
    ax1.text(0.012,
             0.985,
             letters[0],
             transform=ax1.transAxes,
             verticalalignment='top',
             horizontalalignment='left',
             fontweight='bold',
             fontsize=plot_parameters["size_fonts"],
             bbox=dict(facecolor='none', edgecolor='k', pad=3.0))
    ax2.text(0.012,
             0.985,
             letters[1],
             transform=ax2.transAxes,
             verticalalignment='top',
             horizontalalignment='left',
             fontweight='bold',
             fontsize=plot_parameters["size_fonts"],
             bbox=dict(facecolor='none', edgecolor='k', pad=3.0))
    # Legend
    ax0 = fig.add_subplot(111, frameon=False)
    plt.tick_params(labeltop=False,
                    top=False,
                    labelbottom=False,
                    bottom=False,
                    labelleft=False,
                    left=False,
                    labelright=False,
                    right=False)
    s = [(k, lines[k]) for k in sorted(lines.keys())]  #sort the dictionnary
    if variable == 'rho':
        title_legend = ' $\\bf{Density}$ \n (g.cm$^{-3}$)'
    else:
        title_legend = ' $\\bf{Temperature}$ (K)'
        #title_legend=' $\\bf{Temperature}$ \n           (K)'
    ncol = 8
    legend = ax0.legend([v for k, v in s[:ncol]], [k for k, v in s[:ncol]],
                        title=title_legend,
                        bbox_to_anchor=(0.5, 1.05),
                        loc="lower center",
                        borderaxespad=0.,
                        fontsize=plot_parameters['size_font_ticks'],
                        ncol=ncol)
    #legendbis = ax0.legend([v for k,v in s[ncol:]],[k for k,v in s[ncol:]], bbox_to_anchor=(0.5, 1.05),  loc="upper center", borderaxespad=0., fontsize = plot_parameters['size_font_ticks'], ncol = ncol)
    #legend = ax0.legend([v for k,v in s],[k for k,v in s], title = title_legend, bbox_to_anchor=(1.05, 1), loc='upper left", borderaxespad=0., fontsize = plot_parameters['size_font_ticks'])
    plt.setp(legend.get_title(), fontsize=plot_parameters['size_fonts'])
    ax0.add_artist(legend)
    #Save fig
    filename = 'gofrs_' + files[0].split('/')[-1].split(
        '_')[0] + '_' + folder1 + '_' + folder2 + '_' + atom_couple + '.pdf'
    plt.savefig(filename, bbox_inches="tight", dpi=300)
    print(filename, ' is created')
예제 #13
0
def main(argv):
    """     ********* Main program *********     """
    SkipSteps = 0
    units = 0
    #parameters
    Na = 6.022e23  #Avogadro constant
    eVtoJ = 1.6e-19  #1eV = 1.6e-19 J
    KtoeV = 0.000086173324  #1K = 8.62E-5 eV
    kb = 1.38064852e-23  #boltzmann constant
    umd.headerumd()
    try:
        options, arg = getopt.getopt(argv, "hs:u:", ["sSkipSteps", "units"])
    except getopt.GetoptError:
        print(
            'fullaverages.py -s <SkipSteps> -u <units version: 0 = minimal (default), 1 = full units>'
        )
        sys.exit()
    for opt, arg in options:
        if opt == '-h':
            print(
                'fullaverages.py -s <SkipSteps> -u <units version: 0 = minimal (default), 1 = full units>'
            )
            print(
                'Program to extract and average thermodynamic data from all the umd files in the current folder'
            )
            print(
                'As ouptut it produces a fullthermo.dat file. On each line there are specified in order: '
            )
            print('    - the umd filename, the number of snapshots')
            print('    - 3 columns per variable (rho,P,T,E)')
            print('        - average')
            print('        - stdev of data to the mean')
            print('        - statistical error on the mean')
            print(
                '    - 2 columns for the Cv(Nkb) with the calculated value and statistical error'
            )
            print(
                'WARNING: please note that the Cv formulation is valdid *only* for NVT simulations'
            )
            print(' ')
            sys.exit()
        elif opt in ("-s", "--sSkipSteps"):
            SkipSteps = int(arg)
        elif opt in ("-u", "--units"):
            units = int(arg)
    #Initialization
    files = sorted(
        glob.glob('*.umd.dat'))  #list every umd files in alphabetic order
    f, natom = headerfile(files[0],
                          units)  #I create the first newfile for averages
    #Calculation for each file and writing of the newfile
    for file in files:
        results = [
        ]  #initialization of the final result array, used to print each line of result in the new file
        is_E = 0  #initialization of the indicator of energy (in order to compute the Cv)
        is_KE = 0
        print('Averaging in file', file)
        results.append(file)
        #********** Extraction of the Data for the Density, Pressure, Temperature and Energy
        # In each case we try to:
        #     1) extract the data from the umd, create the array and compute the average and stendard deviation
        #     2) compute the sequence of values obtained from (c0/(n-1))**(1/2) (see blocking method in Flyvbjerg1989)
        #     3) select the values to write in the file
        #
        #**** Density
        try:
            nsteps_rho, Density, Average_rho, Variance_rho, stdev_rho = grep_pattern(
                file, "Density", SkipSteps)
            list_sigma_rho, list_err_rho = blocking_method(
                Density, Variance_rho)
            final_sigma_rho, final_err_rho = selection_value(
                list_sigma_rho, list_err_rho)
        except subprocess.CalledProcessError:
            print('    WARNING !!! Density is not defined in the UMD file')
            nsteps_rho, Density, Average_rho, Variance_rho, stdev_rho = (0.0,
                                                                         0.0,
                                                                         0.0,
                                                                         0.0,
                                                                         0.0)
            list_sigma_rho, list_err_rho = (np.zeros(3), np.zeros(3))
            final_sigma_rho, final_err_rho = ('0.0', '0.0')
        #**** Pressure
        try:
            nsteps_P, Pressure, Average_P, Variance_P, stdev_P = grep_pattern(
                file, "Pressure", SkipSteps)
            list_sigma_P, list_err_P = blocking_method(Pressure, Variance_P)
            final_sigma_P, final_err_P = selection_value(
                list_sigma_P, list_err_P)
        except subprocess.CalledProcessError:
            print('    WARNING !!! Pressure is not defined in the UMD file')
            nsteps_P, Pressure, Average_P, Variance_P, stdev_P = (0.0, 0.0,
                                                                  0.0, 0.0,
                                                                  0.0)
            list_sigma_P, list_err_P = (np.zeros(3), np.zeros(3))
            final_sigma_P, final_err_P = ('0.0', '0.0')
        #**** Temperature
        try:
            nsteps_T, Temperature, Average_T, Variance_T, stdev_T = grep_pattern(
                file, "Temperature", SkipSteps)
            list_sigma_T, list_err_T = blocking_method(Temperature, Variance_T)
            final_sigma_T, final_err_T = selection_value(
                list_sigma_T, list_err_T)
        except subprocess.CalledProcessError:
            print('    WARNING !!! Temperature is not defined in the UMD file')
            nsteps_T, Temperature, Average_T, Variance_T, stdev_T = (0.0, 0.0,
                                                                     0.0, 0.0,
                                                                     0.0)
            list_sigma_T, list_err_T = (np.zeros(3), np.zeros(3))
            final_sigma_T, final_err_T = ('0.0', '0.0')
        #**** Energies
        try:
            #this energy does not include the kinetic energy of ions, it is the energy without entropy of VASP
            nsteps_EWE, EnergyWithoutEntropy, Average_EWE, Variance_EWE, stdev_EWE = grep_pattern(
                file, "InternalEnergy", SkipSteps)
            list_sigma_EWE, list_err_EWE = blocking_method(
                EnergyWithoutEntropy, Variance_EWE)
            final_sigma_EWE, final_err_EWE = selection_value(
                list_sigma_EWE, list_err_EWE)
            is_E = 1
        except subprocess.CalledProcessError:
            print(
                '    WARNING !!! InternalEnergy is not defined in the UMD file'
            )
            nsteps_EWE, EnergyWithoutEntropy, Average_EWE, Variance_EWE, stdev_EWE = (
                0.0, 0.0, 0.0, 0.0, 0.0)
            list_sigma_EWE, list_err_EWE = (np.zeros(3), np.zeros(3))
            final_sigma_EWE, final_err_EWE = ('0.0', '0.0')
        try:
            nsteps_K, KineticEnergy, Average_K, Variance_K, stdev_K = grep_pattern(
                file, "KineticEnergyIons", SkipSteps)
            is_KE = 1
        except subprocess.CalledProcessError:
            print(
                '    WARNING !!! KineticEnergy is not defined in the UMD file')
            nsteps_K, KineticEnergy, Average_K, Variance_K, stdev_K = (0.0,
                                                                       0.0,
                                                                       0.0,
                                                                       0.0,
                                                                       0.0)
        #the internal energy as used in the Hugoniot calculation is the internal energy which includes the kinetic energy of ions
        if is_E == 1 and is_KE == 1:
            Energy = [
                KineticEnergy[ii] + EnergyWithoutEntropy[ii]
                for ii in range(len(KineticEnergy))
            ]
            nsteps_E = len(Energy)
            Average_E = sum(Energy) / nsteps_E
            Variance_E = 0
            for ii in range(nsteps_E):
                Variance_E = Variance_E + (Energy[ii] - Average_E)**2
            Variance_E = Variance_E / nsteps_E
            stdev_E = np.sqrt(Variance_E)
            list_sigma_E, list_err_E = blocking_method(Energy, Variance_E)
            final_sigma_E, final_err_E = selection_value(
                list_sigma_E, list_err_E)
        else:
            print(
                '    WARNING !!! InternalEnergy does not include the kinetic energy of ions!!'
            )
            nsteps_E, Energy, Average_E, Variance_E, stdev_E = nsteps_EWE, EnergyWithoutEntropy, Average_EWE, Variance_EWE, stdev_EWE
            list_sigma_E, list_err_E = list_sigma_EWE, list_err_EWE
            final_sigma_E, final_err_E = final_sigma_EWE, final_err_EWE

        #**** For the calculation of Cv and conversions we need the mass of the cell and natoms
        #--> we read the header of the umd file using umd_process store the elements information in the class MyCrystal
        (MyCrystal, TimeStep) = umd.read_bigheader_umd(file)
        natom = MyCrystal.natom
        #***** Calculation of Cv and statistical error using the bootstrap method
        #*** The calculation of Cv depends on the data we have (E, KE)
        # If we have E but not KE, then we take the ideal gas kinetic part to compute the Cv
        if is_E == 1 and is_KE == 0:
            print(
                '    For information: Cv is computed using the ideal gas kinetic part'
            )
            Cv_bootstrap = []
            for n in range(1000):
                #print('*****Bootstrap N°',n)
                Energy_rand = np.random.choice(Energy, nsteps_E, replace=True)
                variance_Erand = 0
                variance_Erand = np.mean(Energy_rand**
                                         2) - np.mean(Energy_rand)**2
                Cv = variance_Erand * (eVtoJ)**2 / (
                    kb * Average_T**2) + 3 / 2 * natom * kb  #in J/unitcell/K
                Cv_bootstrap.append(Cv)
            Cv_bootstrap = np.asarray(Cv_bootstrap)
            Cv = np.mean(
                Cv_bootstrap)  #an estimator of the mean of Cv, in J/unitcell/K
            Cv_stdev = np.sqrt(
                np.mean(Cv_bootstrap**2) - np.mean(Cv_bootstrap)**
                2)  #the error on the previous mean, in J/unitcell/K
        # If we have E and KE, then we take both variances to compute the Cv
        elif is_E == 1 and is_KE == 1:
            print(
                '    For information: Cv is computed using both internal and kinetic energy variances'
            )
            Cv_bootstrap = []
            for n in range(1000):
                #print('*****Bootstrap N°',n)
                Energy_rand = np.random.choice(Energy, nsteps_E, replace=True)
                variance_Erand = 0
                variance_Erand = np.mean(Energy_rand**
                                         2) - np.mean(Energy_rand)**2
                Cv = variance_Erand * (eVtoJ)**2 / (kb * Average_T**2
                                                    )  #in J/unitcell/K
                Cv_bootstrap.append(Cv)
            Cv_bootstrap = np.asarray(Cv_bootstrap)
            Cv = np.mean(
                Cv_bootstrap)  #an estimator of the mean of Cv, in J/unitcell/K
            Cv_stdev = np.sqrt(
                np.mean(Cv_bootstrap**2) - np.mean(Cv_bootstrap)**
                2)  #the error on the previous mean, in J/unitcell/K
        #if we do not have the energy, then we do not compute the Cv
        else:
            print('    WARNING !!! Cv is not computed')
            Cv, Cv_stdev = (0, 0)
        Cvm = Cv * Na / natom  #in J/K/mol
        Cvm_stdev = Cv_stdev * Na / natom  #in J/K/mol
        Cvm_Nkb = Cv / (kb * natom)  #in Nakb
        Cvm_Nkb_stdev = Cv_stdev / (kb * natom)  #in Nakb

        #****** Write result line
        #**** For the conversions we need the mass of the cell
        #--> we read the header of the umd file using umd_process store the elements information in the class MyCrystal
        (MyCrystal, TimeStep) = umd.read_bigheader_umd(file)
        mass = 0
        for itypat in range(MyCrystal.ntypat):
            (atomicname, atomicsymbol, atomicnumber,
             MyCrystal.masses[itypat]) = cr.Elements2rest(
                 MyCrystal.elements[itypat])
            mass = mass + MyCrystal.masses[itypat] * MyCrystal.types[itypat]
        mass = mass / Na
        #convert eV/unitcell to eV/atom or to J/g
        if final_sigma_E[0] == '>':
            final_sigma_E_conv = '>' + '{:1.1e}'.format(
                float(final_sigma_E[1:]) / natom)
            final_sigma_E_mass = '>' + '{:1.1e}'.format(
                float(final_sigma_E[1:]) * eVtoJ / mass)
        else:
            final_sigma_E_conv = '{:1.1e}'.format(
                float(final_sigma_E[:]) / natom)
            final_sigma_E_mass = '{:1.1e}'.format(
                float(final_sigma_E[:]) * eVtoJ / mass)
        if units == 0:
            results.extend([
                str(nsteps_P), '{:1.2f}'.format(Average_rho),
                '{:1.1e}'.format(stdev_rho),
                str(final_sigma_rho), '{:1.2e}'.format(Average_P),
                '{:1.1e}'.format(stdev_P),
                str(final_sigma_P), '{:1.0f}'.format(Average_T),
                '{:1.0f}'.format(stdev_T),
                str(final_sigma_T), '{:1.2e}'.format(Average_E / natom),
                '{:1.1e}'.format(stdev_E / natom),
                str(final_sigma_E_conv), '{:1.2f}'.format(Cvm_Nkb),
                '{:1.1e}'.format(Cvm_Nkb_stdev)
            ])
        else:  #additional conversion of units
            #conversion of eV/unitcell to J/g
            Average_E_mass = Average_E * eVtoJ / mass
            stdev_E_mass = stdev_E * eVtoJ / mass
            #conversion of J/K to J/K/g
            Cvm_mass = Cv / mass
            Cvm_mass_stdev = Cv_stdev / mass
            #conversion K to eV
            if final_sigma_T[0] == '>':
                final_sigma_T_conv = '>' + '{:1.1e}'.format(
                    float(final_sigma_T[1:]) * KtoeV)
            else:
                final_sigma_T_conv = '{:1.1e}'.format(
                    float(final_sigma_T[:]) * KtoeV)
            results.extend([
                str(nsteps_P), '{:1.2f}'.format(Average_rho),
                '{:1.1e}'.format(stdev_rho),
                str(final_sigma_rho), '{:1.2e}'.format(Average_P),
                '{:1.1e}'.format(stdev_P),
                str(final_sigma_P), '{:1.0f}'.format(Average_T),
                '{:1.0f}'.format(stdev_T),
                str(final_sigma_T), '{:1.2e}'.format(Average_T * KtoeV),
                '{:1.1e}'.format(stdev_T * KtoeV),
                str(final_sigma_T_conv), '{:1.2e}'.format(Average_E / natom),
                '{:1.1e}'.format(stdev_E / natom),
                str(final_sigma_E_conv), '{:1.3e}'.format(Average_E),
                '{:1.1e}'.format(stdev_E),
                str(final_sigma_E), '{:1.3e}'.format(Average_E_mass),
                '{:1.1e}'.format(stdev_E_mass),
                str(final_sigma_E_mass), '{:1.2f}'.format(Cvm_Nkb),
                '{:1.1e}'.format(Cvm_Nkb_stdev), '{:1.2e}'.format(Cvm),
                '{:1.1e}'.format(Cvm_stdev), '{:1.2e}'.format(Cvm_mass),
                '{:1.1e}'.format(Cvm_mass_stdev), '{:1.2e}'.format(Cv),
                '{:1.1e}'.format(Cv_stdev)
            ])
        f.write("\t".join(x for x in results) + "\n")
    f.close()
예제 #14
0
def main(argv):
    """     ********* Main program *********     """
    #parameters for the figures depending on the output format (presentation or article)
    plot_parameters = {"size_fonts" : 12,"size_font_ticks":10,"size_figure" : (8,4),"size_markers" : 8,"size_lines" : 1,"shift_labelpad" : 20}
    colors_T = {'0':'k','2000':'#800080','3000':'#297fff','4000':'#00ff00','4500':'#bae200','5000':'#ffcd01','5500':'#ff6e00','6000':'#ff0101','6500':'#ff00a2','7000':'#ff01de'}
    plot_area = 1 #0 to only plot lines of each colors for our data, 1 to plot instead area (enveloppe) of our data
    #initialization of parameters
    filename4 = ''
    filename3 = ''
    #other parameters
    Na=6.022*10**23
    try:
        options,arg = getopt.getopt(argv,"hf:g:j:i:",["filename2","gfilename","jfilename","ifilename"])
    except getopt.GetoptError:
        print("plot_coordinence_separated.py -f <bonds_compound.txt> -g <gofr_comparison1.txt> -j <gofr_comparison2.txt> -i <gofr_comparison3.txt> ")
        sys.exit()
    for opt,arg in options:
        if opt == '-h':
            print('')
            print('plot_coordinence_separated.py program to plot coordinence as a function of density for each T and all cations with O')
            print("plot_coordinence_separated.py-f <bonds_compound.txt> -g <gofr_comparison1.txt> -j <gofr_comparison2.txt> -i <gofr_comparison3.txt> ")
            print("plot_coordinence_separated.py requires bonds.txt file containing every bond distance of one compound for every acell (use bond_analysis.py script)")
            print('')
            sys.exit()
        if opt in ('-f','--filename'):
            filename = str(arg) #plot bond length --> column 5 and xmax --> column 1
        elif opt in ('-g','--gfilename'):
            filename2 = str(arg) # plot from deKoker 2010 
        elif opt in ('-j','--jfilename'):
            filename3 = str(arg) 
        elif opt in ('-i','--ifilename'):
            filename4 = str(arg)
    #************ creation of the figure to plot (with correct number of lines)
    if filename3 == '':    
        if filename4 == '':
            files = [filename,filename2]
            string = filename.split('_')[1]+'-'+filename2.split('.txt')[0].split('_')[-1]
        else:
            files = [filename,filename2, filename3]
            string = filename.split('_')[1]+'-'+filename2.split('.txt')[0].split('_')[-1]+'-'+filename3.split('.txt')[0].split('_')[-1]
    else:
        if filename4 == '':
            files = [filename,filename2, filename3]
            string = filename.split('_')[1]+'-'+filename2.split('.txt')[0].split('_')[-1]+'-'+filename3.split('.txt')[0].split('_')[-1]
        else:
            files = [filename,filename2,filename3,filename4]
            string = filename.split('_')[1]+'-'+filename2.split('.txt')[0].split('_')[-1]+'-'+filename3.split('.txt')[0].split('_')[-1]+'-'+filename4.split('.txt')[0].split('_')[-1]
    typeline = {filename : '-', filename2: '+', filename3: '*',filename4: 'x'}
    atoms = ['Na-O','Ca-O','Al-O','Si-O']
    nlines = 3
    size_figure = (6,2.3*nlines) #height of the figure depends on the number of pair we display
    offset = 0 #offset for printing text on Na-O K-O subplot
    plt.close(1)
    fig, (ax1,ax2,ax3) = plt.subplots(nrows = nlines, ncols = 1, sharex = True, sharey = False, figsize=size_figure)
    major_xticks = np.arange(0, 8, 0.5) 
    minor_xticks = np.arange(0, 8, 0.1)
    for ax in [ax1,ax2,ax3]:
        ax.set_xticks(major_xticks)
        ax.set_xticks(minor_xticks, minor=True)                                           
        ax.xaxis.set_ticks_position('both')
        majorLocator = AutoLocator()
        minorLocator = AutoMinorLocator()                                                        
        ax.yaxis.set_ticks_position('both')
        ax.yaxis.set_major_locator(majorLocator)
        ax.yaxis.set_minor_locator(minorLocator)
        ax.set_xlim(0.9,4.4)
        plt.autoscale(axis='y')
        ax.tick_params(which = 'both', labelsize = plot_parameters["size_font_ticks"], width = plot_parameters["size_lines"]/2)   
    # Fine-tune figure : 1) make subplots close to each other (+ less whitespace around), 2) hide x ticks for all but bottom plot, 3) add a big invisible subplot in order to center x and y labels (since the ticklabels are turned off we have to move the x and y labels with labelpad)
    fig.subplots_adjust(top = 0.95, bottom = 0.1, right = 0.95, left = 0.1, hspace = 0.03, wspace = 0.02)
    ax0 = fig.add_subplot(111, frameon=False)
    plt.tick_params(labeltop=False, top=False, labelbottom=False, bottom=False, labelleft=False, left=False, labelright = False, right=False)
    ax0.set_xlabel(r'Density (g.cm$^{-3}$)', fontweight = 'bold', fontsize = plot_parameters["size_fonts"], labelpad = plot_parameters["shift_labelpad"])
    ax0.set_ylabel(r'Bond length ($\AA$)', fontweight = 'bold', fontsize = plot_parameters["size_fonts"], labelpad = plot_parameters["shift_labelpad"]*1.5)
    figurename = 'bondlength_'+ string
    #************** Extract our data and plot 
    #*** Initialization of data dictionnaries
    pair_columns = {}
    data = {} #big dictionnary with inside coord  all coresponding to different T and atom pairs
    rho = {}  #idem for rho
    enveloppe = {}
    rhoenveloppe = {}
    yvariable = 1 #first file --> xmax
    linestyle = '-'
    colorline = '#368400ff'
    colorfill = '#3684007f'
    for iteration in range(3):
        #*** Calculation of the molecular mass
        with open(filename, 'r') as f:
            line = f.readline()
            entry=line.split()
            elements = entry[1:]
            line = f.readline()
            entry=line.split()
            number = entry[1:]
            line = f.readline()
            entry=line.split()
            pair = entry[1:]
        MN = 0
        for i in range(len(elements)):
            MN = MN + float(number[i]) * cr.Elements2rest(elements[i])[3]
        #******** extraction of data        
        pair_columns[pair[0]] =yvariable
        for i in range(1,len(pair)):
            if pair[i] != pair[i-1]:
                pair_columns[pair[i]] = i+yvariable
        print('All the pairs available in the file with their index are:', pair_columns)
        for atom_pair in pair_columns:
            for atom in atoms:
                if atom_pair == atom:
                    data[atom] = {}
                    rho[atom] = {}
                    enveloppe[atom] = {}
                    rhoenveloppe[atom]= {}
        with open(filename,'r') as f:
            [f.readline() for i in range(4)]
            while True:
                line = f.readline()
                if not line: break
                else:
                    entry=line.split('\n')[0].split('\t')
                    temperature, acell = split_name(entry[0]) 
                    for atom_pair in pair_columns:
                        for atom in atoms:
                            if atom_pair == atom:
                                try:
                                    data[atom][temperature].append( float(entry[pair_columns[atom]]) )
                                    rho[atom][temperature].append( MN/(Na*float(acell)**3*10**(-24)) )    #calculation density
                                except KeyError:
                                    data[atom][temperature] = [ float(entry[pair_columns[atom]]) ]
                                    rho[atom][temperature] = [ MN/(Na*float(acell)**3*10**(-24)) ]    #calculation density
        #***** Compute the enveloppe of our data
        if plot_area == 1:
            for atom in data:
                #take all the data together
                alldata = []
                allrho = []
                for temp in data[atom]:
                    alldata.extend(data[atom][temp])
                    allrho.extend(rho[atom][temp])
                allrho, alldata = zip(*sorted(zip(allrho, alldata)))
                #extract enveloppe
                enveloppe[atom]['up'] = [alldata[0]]
                enveloppe[atom]['down'] = [alldata[0]]
                rhoenveloppe[atom] = [allrho[0]]
                j = 0
                for i in range(1,len(allrho)):
                    if allrho[i] == allrho[i-1]:
                        if alldata[i] > enveloppe[atom]['up'][j]:
                            enveloppe[atom]['up'][j] = alldata[i]
                        if alldata[i] < enveloppe[atom]['down'][j]:
                            enveloppe[atom]['down'][j] = alldata[i]
                    else:
                        j+=1
                        rhoenveloppe[atom].append(allrho[i])
                        enveloppe[atom]['up'].append(alldata[i])
                        enveloppe[atom]['down'].append(alldata[i])
                #print('len enveloppe',len(enveloppe[atom]['up']),len(enveloppe[atom]['down']), len(rhoenveloppe[atom]))
        #***** Plot each atom pair on the correct subplot --> ax1 for Na/Ca-O, ax2 for Al-O, ax3 for Si-O
        for temperature in data['Si-O']:
            for atom in data:
                if atom == 'Ca-O' or atom == 'Na-O':
                    if plot_area == 1:
                        ax1.fill_between(rhoenveloppe[atom],enveloppe[atom]['up'],enveloppe[atom]['down'], facecolor = colorfill, linewidth=plot_parameters['size_lines'], alpha = 0.1)
                        ax1.plot(rhoenveloppe[atom],enveloppe[atom]['down'], linestyle = linestyle, color=colorline, linewidth=plot_parameters["size_lines"] )
                        ax1.plot(rhoenveloppe[atom],enveloppe[atom]['up'], linestyle = linestyle, color=colorline, linewidth=plot_parameters["size_lines"] )
                    else:
                        ax1.plot(rho[atom][temperature],data[atom][temperature], linestyle = linestyle, color=colors_T[temperature], markersize = plot_parameters["size_markers"], linewidth=plot_parameters["size_lines"] )
                elif atom == 'Si-O':
                    if plot_area == 1:
                        ax3.fill_between(rhoenveloppe[atom],enveloppe[atom]['up'],enveloppe[atom]['down'], facecolor = colorfill, linewidth=plot_parameters['size_lines'], alpha = 0.1)
                        ax3.plot(rhoenveloppe[atom],enveloppe[atom]['down'], linestyle = linestyle, color=colorline, linewidth=plot_parameters["size_lines"] )
                        ax3.plot(rhoenveloppe[atom],enveloppe[atom]['up'], linestyle = linestyle, color=colorline, linewidth=plot_parameters["size_lines"] )    
                    else:
                        ax3.plot(rho[atom][temperature],data[atom][temperature], linestyle = linestyle, color=colors_T[temperature], markersize = plot_parameters["size_markers"], linewidth=plot_parameters["size_lines"] )
                    #ax3.text( 0.02,0.91, atom ,transform=ax3.transAxes, fontsize=plot_parameters['size_fonts'], fontweight='bold'  ) #for coord
                    ax3.text( 0.89,0.91, atom ,transform=ax3.transAxes, fontsize=plot_parameters['size_fonts'], fontweight='bold'  ) #for bond
                elif atom == 'Al-O':
                    if plot_area == 1:                    
                        ax2.fill_between(rhoenveloppe[atom],enveloppe[atom]['up'],enveloppe[atom]['down'], facecolor = colorfill, linewidth=plot_parameters['size_lines'], alpha = 0.1)
                        ax2.plot(rhoenveloppe[atom],enveloppe[atom]['down'], linestyle = linestyle, color=colorline, linewidth=plot_parameters["size_lines"] )
                        ax2.plot(rhoenveloppe[atom],enveloppe[atom]['up'], linestyle = linestyle, color=colorline, linewidth=plot_parameters["size_lines"] )    
                    else:
                        ax2.plot(rho[atom][temperature],data[atom][temperature],linestyle = linestyle, color=colors_T[temperature], markersize = plot_parameters["size_markers"], linewidth=plot_parameters["size_lines"] )
                    #ax2.text(0.02,0.91, atom ,transform=ax2.transAxes, fontsize=plot_parameters['size_fonts'], fontweight='bold'  ) #for coord
                    ax2.text(0.89,0.91, atom ,transform=ax2.transAxes, fontsize=plot_parameters['size_fonts'], fontweight='bold'  ) #for bond
        if iteration == 0:
            linestyle = '--'
            colorline = '#368400ff'
            colorfill = '#3684007f'
            yvariable = 2 #second run --> average
        elif iteration == 1:
            linestyle = '-.'
            colorline = '#6fc933ff'
            colorfill = '#6fc9337f'
            yvariable = 3 #third run --> median
        elif iteration == 2:
            linestyle = ':'
            colorline = 'k'
            colorfill = 'gray'
            yvariable = 4 #fourth run --> bondr3
    #************** Extract the collected data and plot
    sources = {'gofrs-bond_deKoker2010.txt':'de Koker (2010)','gofrs-bond_Angel1990.txt':'Angel $et~al.$ (1990)','gofrs-bond_Taylor1979.txt':'Taylor and Brown (1979)'}
    print('files from other sources',files[1:])
    for file in files[1:]:
        print('For file ',file)
        #***** Initialization of data dictionnaries
        pair_columns={'Na-O':2,'Ca-O':2,'Al-O':3,'Si-O':4}
        data = {} #big dictionnary with inside coord  all coresponding to different T and atom pairs
        rho = {}  #idem for rho
        with open(file, 'r') as f:
            line = f.readline()
            entry=line.split()
            pairs = entry[2:9]
        print('All the pairs available in the file are:', pairs)
        #******** extraction of data        
        for atom_pair in pairs:
            for atom in atoms:
                if atom_pair == atom:
                    data[atom] = {}
                    rho[atom] = {}
        with open(file,'r') as f:
            f.readline()
            while True:
                line = f.readline()
                if not line: break
                else:
                    entry=line.split('\n')[0].split('\t')
                    temperature = str(int(float( entry[9])))
                    for atom_pair in pairs:
                        for atom in atoms:
                            if atom_pair == atom:
                                datapoint = float(entry[pair_columns[atom]])
                                #replace 0 by nan
                                if datapoint == 0.0:
                                    datapoint = float(np.nan)
                                #add datapoint to data dic
                                try:
                                    data[atom][temperature].append( datapoint )
                                    rho[atom][temperature].append( float(entry[0])/1000) 
                                except KeyError:
                                    data[atom][temperature] = [ datapoint ]
                                    rho[atom][temperature] = [ float(entry[0])/1000]   
        #***** Plot each atom pair on the correct subplot --> ax1 for Na/Ca-O, ax2 for Al-O, ax3 for Si-O
        for temperature in data['Si-O']:
            for atom in data:
                if atom == 'Ca-O' or atom == 'Na-O':
                    #print('plot M-O for ', temperature)
                    ax1.plot(rho[atom][temperature],data[atom][temperature], marker = typeline[file][0], linestyle = 'None', color=colors_T[temperature], markersize = plot_parameters["size_markers"] )
                elif atom == 'Si-O':
                    #print('plot Si-O for ', temperature)
                    ax3.plot(rho[atom][temperature],data[atom][temperature], marker = typeline[file][0], linestyle = 'None', color=colors_T[temperature], markersize = plot_parameters["size_markers"])
                elif atom == 'Al-O':
                    #print('plot Al-O for ', temperature)
                    ax2.plot(rho[atom][temperature],data[atom][temperature], marker = typeline[file][0], linestyle = 'None',  color=colors_T[temperature], markersize = plot_parameters["size_markers"])
    for atom in ['Ca-O']:#,'Na-O']:
        #ax1.text( 0.02,0.91-offset, atom,transform=ax1.transAxes, fontsize=plot_parameters['size_fonts'], fontweight='bold'  ) #for coord
        ax1.text( 0.89,0.91-offset, atom,transform=ax1.transAxes, fontsize=plot_parameters['size_fonts'], fontweight='bold'  ) #for bond
        offset = offset + 0.10        #we update the offset for printing text on Na-O K-O subplot after finishing the first file              
    #Legend 
    legend_labels = {}
    legend_labels2 = {}
    for file in files[1:]: 
        legend_labels[sources[file]] =  plt.Line2D((0,1),(0,0), color='k', linestyle = 'None', markersize = plot_parameters["size_markers"]-2, marker=typeline[file][0])
    if plot_area == 1:
        legend_labels2['xmax'] =  mpatches.Patch(facecolor='#3684007f',  linestyle = '-',edgecolor='#368400ff')
        legend_labels2['average'] = mpatches.Patch(facecolor='#3684007f', linestyle = '--',edgecolor='#368400ff')
        legend_labels2['median'] = mpatches.Patch(facecolor='#6fc9337f', linestyle = '-.',edgecolor='#6fc933ff')
    else:        
        legend_labels2['xmax'] =  plt.Line2D((0,1),(0,0), color='k', linestyle='-', linewidth = plot_parameters["size_lines"])
        legend_labels2['average'] =  plt.Line2D((0,1),(0,0), color='k', linestyle='--', linewidth = plot_parameters["size_lines"])
        legend_labels2['median'] =  plt.Line2D((0,1),(0,0), color='k', linestyle='-.', linewidth = plot_parameters["size_lines"])
    s = [(k, legend_labels[k]) for k in sorted(legend_labels.keys(),reverse = False)]      
    s2 = [(k, legend_labels2[k]) for k in sorted(legend_labels2.keys(),reverse = False)]      
    #legend1 = ax1.legend([v for k,v in s],[k for k,v in s], loc='lower left', bbox_to_anchor=(0.3, 1.02), ncol=1, fontsize = plot_parameters["size_font_ticks"], borderaxespad=0.)
    #legend2 = ax1.legend([v for k,v in s2],[k for k,v in s2], loc='lower left', bbox_to_anchor=(0.01, 1.02), ncol=1, fontsize = plot_parameters["size_font_ticks"], borderaxespad=0., title='This study')
    #plt.setp(legend2.get_title(),fontsize= plot_parameters["size_font_ticks"], fontweight = 'bold')
    legend1 = ax1.legend([v for k,v in s],[k for k,v in s], loc='lower left', bbox_to_anchor=(0.3, 0.02), ncol=1, fontsize = plot_parameters["size_font_ticks"]-2, borderaxespad=0.)
    legend2 = ax1.legend([v for k,v in s2],[k for k,v in s2], loc='lower left', bbox_to_anchor=(0.01, 0.02), ncol=1, fontsize = plot_parameters["size_font_ticks"]-2, borderaxespad=0.)
    
    ax1.add_artist(legend1)
    
    #save the figure
    figurename = figurename + '.pdf'
    fig.savefig(figurename, bbox_inches = 'tight', dpi = 300)
    
    print(figurename, '   created')
def main(argv):
    """     ********* Main program *********     """
    #parameters for the figures depending on the output format (presentation or article)
    plot_parameters = {"size_fonts" : 12,"size_font_ticks":10,"size_figure" : (8,8),
                       "size_markers" : 5,"size_lines" : 1,"shift_labelpad" : 10}
    #other dictionnaries and parameters for the figure
    style_markers = {'CaAl2Si2O8':'d','KAlSi3O8':'s','NaAlSi3O8':'o'}
    style_lines = {'CaAl2Si2O8':':','KAlSi3O8':'--','NaAlSi3O8':'-'}
    colors_T = {'T2':'#800080','T3':'#297fff','T4':'#00ff00','T4.5':'#bae200',
                'T5':'#ffcd01','T6':'#ff0101','T6.5':'#ff00a2','T7':'#ff01de'}
    #colors_T = create_colors()
    #variables nedded fot the plot
    filename = 'all'
    filename2 = ''
    ions = []
    compounds = []
    Temperatures = []
    data = {} #dictionnary containing the data for each element, initialized for each T
    stdev = {} #same for stdev
    #other parameters
    Na=6.022*10**23
    #dictionnary for fullaverages file in full version
    column_number = {'rho':2,'P':5,'stdev_P':6,'err_P':7,'T':8,'stdev_T':9,'err_T':10,
                     'E':14,'stdev_E':15,'err_E':16,'Cvm_Nkb':23,'stdev_Cvm_Nkb':24,
                     'Cvm':25,'stdev_Cvm':26,'testCv':31,'stdev_testCv':32}
    try:
        options,arg = getopt.getopt(argv,"hf:g:p:v:",["filename","gfilename2",'property','variable'])
    except getopt.GetoptError:
        print("plot_diffusion_2x2.py -f <filename>(default = all) -g <filename2(option)> -p <property to plot (D or t)> -v <variable x axis (rho or P)> ")
        sys.exit()
    for opt,arg in options:
        if opt == '-h':
            print('')
            print('plot_diffusion_2x2.py program to plot diffusion coefficient (or time of ballistic to diffusive regime change) as a function of density or pressure for each T and the selected minerals containing 4 elements')
            print("plot_diffusion_2x2.py -f <filename>(default = all files of every compound) -g <filename2(option)>  -p <property to plot (D or t)> -v <variable x axis (rho or P)>")
            print("plot_diffusion_2x2.py requires to be lauched from the folder containing every diffusivities file created by the script analyze_msd")
            print('')
            print('For plots as function of P, make sure the files from fullaverages.py are in the current folder')
            sys.exit()
        if opt in ('-f','--filename'):
            filename = str(arg)
        elif opt in ('-g','--gfilename2'):
            filename2 = str(arg)
        elif opt in ('-p','--property'):
            prop = str(arg)
        elif opt in ('-v','--variable'):
            xvariable = str(arg)
    #** Figure creation 
    fig,ax1,ax2,ax3,ax4, ax0 = creation_plot_2x2(plot_parameters, prop, xvariable)
    if prop == 'D':
        name = 'diffusivities'
        index = 1
    else:
        name = 'regimechange'
        index = 6
    if filename == 'all':
        files = sorted(glob.glob('diffusivities_*.txt'),reverse=True) #I list every diffusivities files
        figurename = name + '_2x2_all_'+xvariable
    elif filename2 != '':
        files = [filename,filename2] #I list every diffusivities files
        figurename = name + '_2x2_'+filename.split('.txt')[0].split('_')[1]+'_'+filename2.split('.txt')[0].split('_')[1]+'_'+xvariable    
    else:
        files = [filename] #I take only the file we want
        figurename = name + '_2x2_'+filename.split('.txt')[0].split('_')[1]+'_'+xvariable
    #** Plot expe data  
    handles, legendlabels =  [] ,[]
    if prop == 'D':
        handles, legendlabels = plot_deKoker2010(ax1,ax2,ax3,ax4, handles, legendlabels, xvariable)
        handles, legendlabels = plot_Neilson2016(ax1,ax2,ax3,ax4, handles, legendlabels, xvariable)
        #handles, legendlabels = plot_Spera2009(ax1,ax2,ax3,ax4, handles, legendlabels, xvariable)
    #** Plot our data
    for file in files:
        #print("************************ for diffusivity file named",file)
        #**extraction compound        
        compounds.append(file.split('_')[1].split('.txt')[0]) #we need the compound for the legend
        #******* Extract P and T for each thermo file
        if xvariable == 'P':
            TP = {}
            mineralname = file.split('_')[1].split('.txt')[0]
            thermofiles = sorted(glob.glob('thermo_'+mineralname+'*.txt'))
            for thermofile in thermofiles:
                TP = extract_TP(thermofile, column_number, TP,'')
            if TP == {}:
                print('ERROR!!!! TP dictionnary empty')
        #**creation of elements and number lists and initialization of T
        with open(file,'r') as f:
            skiplines = 0
            while True:
                line = f.readline()
                skiplines += 1
                entry=line.split()
                if entry[0] == 'elements':
                    elements = entry[1:]
                    ions.append(elements[0])
                elif entry[0] == 'number':
                    number = entry[1:]
                elif entry[0] == 'file':
                    line = f.readline()
                    entry=line.split()
                    mineral, temperature0, acell0 = split_name(entry[0])
                    break
        #**calculation of M*N nedded for the calculation of densities
        MN = 0
        for i in range(len(elements)):
            MN = MN + float(number[i]) * cr.Elements2rest(elements[i])[3]
        #**initialisation of data
        data = {} #big dictionnary with inside self diffusion coefficient or time of regime change, all coresponding to different T and atom pairs
        stdev = {} #idem for stdev
        X = {}  #idem for rho or P
        for elem in elements:
            stdev[elem] = {}
            data[elem] = {}
            X[elem] = {}
        #****** Extraction of data
        with open(file,'r') as f:
            [f.readline() for i in range(skiplines)]
            while True:
                line = f.readline()
                if not line: break
                else:
                    entry=line.split('\n')[0].split('\t')
                    mineral, temperature, acell = split_name(entry[0]) 
                    #print(entry[0])
                    for i in range(len(elements)): 
                        elem = elements[i]
                        try:
                            data[elem][temperature].append(float(entry[i*6+index]))
                            stdev[elem][temperature].append(float(entry[i*6+2]))    
                            if xvariable == 'P':
                                X[elem][temperature].append(TP[entry[0].split('outcar.msd.dat')[0].split('/')[-1]][1])
                            else:
                                X[elem][temperature].append( MN/(Na*float(acell)**3*10**(-24)) )    #calculation density
                        except KeyError:
                            data[elem][temperature] = [ float(entry[i*6+index])]
                            stdev[elem][temperature] = [ float(entry[i*6+2]) ]
                            if xvariable == 'P':
                                X[elem][temperature] = [TP[entry[0].split('outcar.msd.dat')[0].split('/')[-1]][1]]
                            else:
                                X[elem][temperature] = [ MN/(Na*float(acell)**3*10**(-24)) ]    #calculation density
        #***** Plot each element on the correct subplot 
        for elem in elements:
            #choice of axis
            if elem == 'O':
                ax = ax4
            elif elem == 'Si':
                ax = ax3
            elif elem == 'Al':
                ax = ax2
            else:
                ax = ax1
            for temperature in data[elem]:
                #print("******** ", temperature)
                #print(data[elem][temperature])
                Temperatures.append(temperature)
                #attribution of fill color
                if mineral == 'NaAlSi3O8':
                    fillcolor = colors_T[temperature]+'ff'#with custom dict    #np.array([colors_T[temperature][0],colors_T[temperature][1],colors_T[temperature][2],1])   #with dic from create_colors() function
                elif mineral == 'CaAl2Si2O8':
                    fillcolor = 'w'
                elif mineral == 'KAlSi3O8':
                    fillcolor =  colors_T[temperature]+'7f'#with custom dict    #np.array([colors_T[temperature][0],colors_T[temperature][1],colors_T[temperature][2],0.5])  #with dic from create_colors() function
                #remove data with nan 
                ThisData = np.array(data[elem][temperature])
                ThisX= np.array(X[elem][temperature])
                data_mask = np.isfinite(ThisData)                
                ax.plot(ThisX[data_mask],ThisData[data_mask], style_markers[mineral]+style_lines[mineral],
                        markersize = plot_parameters["size_markers"], markeredgewidth = 0.5, 
                        color = colors_T[temperature], markerfacecolor = fillcolor, 
                        markeredgecolor = colors_T[temperature], linewidth = plot_parameters["size_lines"])
                #if prop == 'D':
                    #ax.errorbar(X[elem][temperature],data[elem][temperature], yerr=stdev[elem][temperature], fmt=style_markers[mineral], markersize = plot_parameters[size_markers], markeredgewidth = 0.5, edgecolor colors_T[temperature], facecolor = fillcolor, linestyle = style_lines[mineral],  linewidth = plot_parameters["size_lines"] )
    #********* Legend               
    #Create legend from custom artist/label lists
    Temperatures = list(set(Temperatures)) #get elements only once in the list
    custom_patch = [mpatches.Patch(color=colors_T[key]) for key in natsort.natsorted(Temperatures)]
    legend = ax0.legend([col for col in custom_patch],[str(int(float(label.strip('T'))*1000)) for label in natsort.natsorted(Temperatures)],title = '$\\bf{Temperature~(K)}$', bbox_to_anchor=(0.5, 1.07), loc="lower center", fontsize = plot_parameters["size_font_ticks"],  borderaxespad=0., ncol=len(Temperatures))
    plt.setp(legend.get_title(),fontsize= plot_parameters["size_font_ticks"])
    #definition of line and marker style
    fillcolor = {}
    for mineral in style_markers:
        if mineral == 'CaAl2Si2O8':
            fillcolor[mineral] = 'w'
        elif mineral == 'KAlSi3O8':
            fillcolor[mineral] = '#0000007f'
        else:
            fillcolor[mineral] = '#000000ff' 
    custom_lines = [plt.Line2D([0],[0], marker = style_markers[key], linestyle = style_lines[key],
                               markeredgecolor = 'k', markerfacecolor = fillcolor[key],  
                               color = 'k', markersize = plot_parameters["size_markers"], 
                               markeredgewidth = 0.5, linewidth = plot_parameters["size_lines"]) for key in sorted(compounds)]
    ax0.legend([line for line in custom_lines],[format1label(label) for label in sorted(compounds)],
               bbox_to_anchor=(0.5, 1.02), loc='lower center', fontsize = plot_parameters["size_fonts"], 
               borderaxespad=0., ncol =3)
    
    ax0.add_artist(legend)
    #Add elements on subplots
    if filename == 'all' or filename2 != '':
        string = ions[0]
        for i in range(1,len(ions)):
            string = string + ' ' + ions[i]
        ax1.text(0.95,0.9, string, transform=ax1.transAxes, horizontalalignment = 'right',
                 fontweight = 'bold', fontsize = plot_parameters['size_fonts'])
    else:
        ax1.text(0.95,0.9, elements[0], transform=ax1.transAxes, horizontalalignment = 'right', 
                 fontweight = 'bold', fontsize = plot_parameters['size_fonts'])
    ax2.text(0.95,0.9, elements[1], transform=ax2.transAxes, horizontalalignment = 'right', 
             fontweight = 'bold', fontsize = plot_parameters['size_fonts'])
    ax3.text(0.95,0.9, elements[2], transform=ax3.transAxes, horizontalalignment = 'right', 
             fontweight = 'bold', fontsize = plot_parameters['size_fonts'])
    ax4.text(0.95,0.9, elements[3], transform=ax4.transAxes, horizontalalignment = 'right', 
             fontweight = 'bold', fontsize = plot_parameters['size_fonts'])
    figurename = figurename + '.pdf'
    fig.savefig(figurename, bbox_inches = 'tight', dpi = 150)
    print(figurename,' created')
def main(argv):
    """     ********* Main program *********     """
    #parameters for the figure for article
    plot_parameters = {"size_fonts" : 12,"size_font_ticks":10,"size_figure" : (10,10),
                       "size_markers" : 4,"size_lines" : 1,"shift_labelpad" : 10}
    #other dictionnaries and parameters for the figure
    colors_T = {'T2':'#800080','T3':'#297fff','T4':'#00ff00','T4.5':'#bae200',
                'T5':'#ffcd01','T5.5':'#ff6e00','T6':'#ff0101','T6.5':'#ff00a2','T7':'#ff01de'}
    xvariable = 'rho'
    #variables nedded fot the plot
    #other dictionnaries and parameters for the figure
    Temperatures = []
    #other parameters
    Na=6.022*10**23
    #dictionnary for fullaverages file in full version
    column_number = {'rho':2,'P':5,'stdev_P':6,'err_P':7,'T':8,'stdev_T':9,'err_T':10,
                     'E':14,'stdev_E':15,'err_E':16,'Cvm_Nkb':23,'stdev_Cvm_Nkb':24,
                     'Cvm':25,'stdev_Cvm':26,'testCv':31,'stdev_testCv':32}
    try:
        options,arg = getopt.getopt(argv,"hv:",['variable'])
    except getopt.GetoptError:
        print("plot_diffusion_all_compvibr.py -v <variable x axis (rho or P)> ")
        sys.exit()
    for opt,arg in options:
        if opt == '-h':
            print('')
            print('plot_diffusion_all_compvibr.py program to plot diffusion coefficient as a function of density for each T and the selected minerals containing 4 elements')
            print("plot_diffusion_all_compvibr.py -v <variable x axis (rho or P)> ")
            print("plot_diffusion_all_compvibr.py requires to be lauched from the folder containing every diffusivities file created by the script analyze_msd and vibr2diffusion")
            print('')
            print('For plots as function of P, make sure the files from fullaverages.py are in the current folder')
            sys.exit()
        if opt in ('-v','--variable'):
            xvariable = str(arg)
    figurename = 'diffusivities_all_compvibr_'+xvariable
    if xvariable == 'rho':
        major_xticks = np.arange(0, 4.5, 0.5) 
        minor_xticks = np.arange(0, 4.1, 0.1) 
        label = r'Density (g.cm$^{-3}$)'
    else:
        label = r'Pressure (GPa)' 
                
    minerals = ['NaAlSi3O8','KAlSi3O8','CaAl2Si2O8']
    

    plt.close(1)
    fig = plt.figure(1,figsize=plot_parameters['size_figure'])
    plt.subplots_adjust(top = 0.97, bottom = 0.07, right = 0.89, left = 0.07, hspace = 0, wspace = 0)
    plt.subplot(4,3,1) #4 inles 3 columns
    ax = plt.gca()
    for mineral in minerals:
        #************ Extract Data
        diffusion_msd_file = 'diffusivities_'+mineral+'.txt'
        diffusion_vibr_file = 'diffusivities-vibr_'+mineral+'.txt'
        #** creation of elements and number lists
        with open(diffusion_vibr_file,'r') as f:
            skiplines = 0
            while True:
                line = f.readline()
                skiplines += 1
                entry=line.split()
                if entry[0] == 'elements':
                    elements = entry[1:]
                elif entry[0] == 'number':
                    number = entry[1:]
                elif entry[0] == 'file':
                    break
        #** calculation of M*N nedded for the calculation of densities
        MN = 0
        for i in range(len(elements)):
            MN = MN + float(number[i]) * cr.Elements2rest(elements[i])[3]
        #** Extraction of data in diffusivities-vibr_mineral.txt file
        datavibr = {}
        Xvibr = {}
        #initialisation of data
        datavibr = {} #big dictionnary with inside self diffusion coefficient or time of regime change, all coresponding to different T and atom pairs
        Xvibr = {}  #idem for rho or P
        for i in range(len(elements)):
            elem = elements[i]
            datavibr[elem] = {}
            Xvibr[elem] = {}
        #fill dictionnaries
        with open(diffusion_vibr_file,'r') as f:
            [f.readline() for i in range(skiplines)]
            while True:
                line = f.readline()
                if not line: break
                else:
                    entry=line.split('\n')[0].split('\t')
                    temp, acell = split_name(entry[0]) 
                    for i in range(len(elements)): 
                        elem = elements[i]
                        try:
                            datavibr[elem][temp].append(float(entry[i+2]))
                            if xvariable == 'P':
                                Xvibr[elem][temp].append(float(entry[1]))
                            else:
                                Xvibr[elem][temp].append( MN/(Na*float(acell)**3*10**(-24)) )    #calculation density
                        except KeyError:
                            datavibr[elem][temp] = [ float(entry[i+2])]
                            if xvariable == 'P':
                                Xvibr[elem][temp] = [float(entry[1])]
                            else:
                                Xvibr[elem][temp] = [ MN/(Na*float(acell)**3*10**(-24)) ]    #calculation density         
        #** Extract P and T from thermofile
        if xvariable == 'P':
            TP = {}
            thermofile = 'thermo_'+mineral+'_all.txt'
            TP = extract_TP(thermofile, column_number, TP,'')
            if TP == {}:
                print('ERROR!!!! TP dictionnary empty')
        #** Extraction of data in diffusivities_mineral.txt file
        dataMSD = {}
        XMSD = {}
        #count number lines in header
        with open(diffusion_msd_file,'r') as f:
            skiplines = 0
            while True:
                line = f.readline()
                skiplines += 1
                entry=line.split()
                if entry[0] == 'file':
                    break
        #initialisation of data
        dataMSD = {} #big dictionnary with inside self diffusion coefficient or time of regime change, all coresponding to different T and atom pairs
        XMSD = {}  #idem for rho or P
        for i in range(len(elements)):
            elem = elements[i]
            dataMSD[elem] = {}
            XMSD[elem] = {}
        #fill dictionnaries
        with open(diffusion_msd_file,'r') as f:
            [f.readline() for i in range(skiplines)]
            while True:
                line = f.readline()
                if not line: break
                else:
                    entry=line.split('\n')[0].split('\t')
                    temp, acell = split_name(entry[0]) 
                    for i in range(len(elements)): 
                        elem = elements[i]
                        try:
                            dataMSD[elem][temp].append(float(entry[i*6+1]))
                            if xvariable == 'P':
                                XMSD[elem][temp].append(TP[entry[0].split('outcar.msd.dat')[0].split('/')[-1]][1])
                            else:
                                XMSD[elem][temp].append( MN/(Na*float(acell)**3*10**(-24)) )    #calculation density
                        except KeyError:
                            dataMSD[elem][temp] = [ float(entry[i*6+1])]
                            if xvariable == 'P':
                                XMSD[elem][temp] = [TP[entry[0].split('outcar.msd.dat')[0].split('/')[-1]][1]]
                            else:
                                XMSD[elem][temp] = [ MN/(Na*float(acell)**3*10**(-24)) ]    #calculation density 
        #************ Plot Data
        for elem in elements:
            #print("******** ", elem)
            #change of subplot
            plt.subplot(4,3,elements.index(elem)*3+1+minerals.index(mineral))
            ax = plt.gca()
            #plot
            for temp in datavibr[elem]:
                #print("******** ", temp)
                #put only the T you want in colors_T (no T10, 15) 
                try:
                    ax.plot(Xvibr[elem][temp],datavibr[elem][temp], ls = ':', 
                        marker = 'x', markersize = plot_parameters["size_markers"],
                        color = colors_T[temp], linewidth = plot_parameters["size_lines"])
                    ax.plot(XMSD[elem][temp],dataMSD[elem][temp], ls = '-', 
                        marker = '*', markersize = plot_parameters["size_markers"],
                        color = colors_T[temp], linewidth = plot_parameters["size_lines"])
                    Temperatures.append(temp)
                except KeyError:
                    pass
            #we add x and y labels outside the plot on the right columns and lines
            if elements.index(elem) == 0:
                ax.set_xlabel(format1label(mineral), fontweight = 'bold', fontsize = plot_parameters["size_fonts"])
                ax.xaxis.set_label_position('top')
            if minerals.index(mineral) == len(minerals)-1:
                if elements.index(elem) == 0:
                    ax.set_ylabel('Na, K, Ca', fontweight = 'bold', fontsize = plot_parameters["size_fonts"])
                else:
                    ax.set_ylabel(elem, fontweight = 'bold', fontsize = plot_parameters["size_fonts"])
                ax.yaxis.set_label_position('right')
            #limitation of data along x
            if xvariable == 'rho':
                ax.set_xticks(major_xticks)
                ax.set_xticks(minor_xticks, minor=True)
                ax.set_xlim(1.0,4.1)
                if minerals.index(mineral) != len(minerals)-1:
                    plt.setp(ax.get_xticklabels()[-1], visible=False)                
            else:
                ax.set_xscale('log')
                ax.set_xlim(1,275)               
            #limitation of data along y            
            ax.set_yscale('log')
            ax.set_ylim(4e-10,3e-7)
            #we remove unwanted axis tick labels
            if  minerals.index(mineral) != 0:
                plt.setp(ax.get_yticklabels(), visible=False)
            if elements.index(elem) != len(elements)-1:
                plt.setp(ax.get_xticklabels(), visible=False)
            #we make the graph prettier
            ax.xaxis.set_ticks_position('both')
            ax.yaxis.set_ticks_position('both')
            ax.yaxis.set_tick_params(which = 'both', direction='inout')
            ax.xaxis.set_tick_params(which = 'both', direction='inout')            
            ax.grid(axis = 'y', which = 'major', linestyle = '--', 
                    linewidth = plot_parameters["size_lines"]/2, alpha = 0.5)
            ax.tick_params(which = 'both', labelsize = plot_parameters["size_font_ticks"],
                           width = plot_parameters["size_lines"]/2)
            ax.set_facecolor((1,1,1,0))

            #plt.setp(ax.get_yticklabels()[-1], visible=False)
    
    #************ Fine tune figure
    ax0 = fig.add_subplot(111, frameon=False)
    plt.tick_params(labeltop=False, top=False, labelbottom=False, bottom=False, 
                    labelleft=False, left=False, labelright = False, right=False)
    ax0.set_xlabel(label, fontweight = 'bold', fontsize = plot_parameters["size_fonts"],
                   labelpad = plot_parameters["shift_labelpad"]*2)
    ax0.set_ylabel(r'Diffusion coefficient (m$^2$.s$^{-1}$)', fontweight = 'bold', 
                   fontsize = plot_parameters["size_fonts"], 
                   labelpad = plot_parameters["shift_labelpad"]*3+plot_parameters["shift_labelpad"]/2)
    
    #************ Create legend from custom artist/label lists
    Temperatures = list(set(Temperatures)) #get elements only once in the list
    custom_patch = [mpatches.Patch(color=colors_T[key]) for key in natsort.natsorted(Temperatures)]
    
    legend_labels = {'D from MSD': plt.Line2D((0,1),(0,0), color='k', markersize = plot_parameters["size_markers"],
                                    marker='*', linestyle='-', linewidth = plot_parameters["size_lines"]),
                     'D from vibrational spectrum': plt.Line2D((0,1),(0,0), color='k', markersize = plot_parameters["size_markers"],
                                    marker='x', linestyle='--', linewidth = plot_parameters["size_lines"])}
    s = [(k, legend_labels[k]) for k in sorted(legend_labels.keys(),reverse = False)]
    
    legend = ax0.legend([col for col in custom_patch],[str(int(float(label.strip('T'))*1000)) for label in natsort.natsorted(Temperatures)],title = '$\\bf{Temperature~(K)}$', bbox_to_anchor=(0.5, 1.08), loc="lower center", fontsize = plot_parameters["size_font_ticks"],  borderaxespad=0., ncol=len(Temperatures))    
    plt.setp(legend.get_title(),fontsize= plot_parameters["size_font_ticks"])
    plt.legend([v for k,v in s],[k for k,v in s], bbox_to_anchor=(0.5, 1.03), loc='lower center',fancybox=True, fontsize = plot_parameters["size_fonts"], ncol=len(legend_labels))
    ax0.add_artist(legend)
    
    
    figurename = figurename + '.pdf'
    print("figure saved with name ",figurename)
    fig.savefig(figurename, bbox_inches = 'tight', dpi = 300)
def main(argv):
    """     ********* Main program *********     """
    data1 = {}  #dictionnary containing lifetimes for each cluster (file 1)
    data2 = {}  #dictionnary containing lifetimes for each cluster (file 2)
    data3 = {}  #dictionnary containing lifetimes for each cluster (file 3)
    cluster_lengths = {
    }  #dictionnary containing length of cluster for each cluster of all files
    filename3 = ''
    atoms = 'all'
    letter = ''
    #other dictionnaries and parameters for the figure
    colors_T = {
        '2000': '#800080',
        '3000': '#297fff',
        '4000': '#00ff00',
        '5000': '#ffcd01',
        '6000': '#ff0101',
        '7000': '#ff01de'
    }
    plot_parameters = {
        "size_fonts": 12,
        "size_font_ticks": 10,
        "size_figure": (8, 4),
        "size_markers": 4,
        "size_lines": 1,
        "shift_labelpad": 20
    }
    #other parameters
    Na = 6.022 * 10**23
    try:
        options, arg = getopt.getopt(argv, "hf:g:j:a:v:m:l:", [
            "file1", "gfile2", "jfile3", "atom", "variable", "mineralfile",
            'letter'
        ])
    except getopt.GetoptError:
        print(
            "plot_speciation-lifetime-comp.py -m <mineralfile with elements>  -a <list of first atoms determining the type of cluster to plot (default = 'all')> -v <variable (rho,T)> -l <letter, default = ''> -f <small_popul.txt filename> -g <small_popul.txt filename n°2> -j <small_popul.txt filename n°3 (option)>"
        )
        sys.exit()
    for opt, arg in options:
        if opt == '-h':
            print('')
            print(
                'plot_speciation-lifetime-comp.py program to  Plot lifetime barchart for 3 files (.txt files obtained from plot_speciation-lifetime.py) for selected clusters'
            )
            print(
                "plot_speciation-lifetime-comp.py -m <mineralfile with elements>  -a <list of first atoms determining the type of cluster to plot (default = 'all')> -v <variable (rho,T)> -l <letter, default = ''> -f <small_popul.txt filename> -g <small_popul.txt filename n°2> -j <small_popul.txt filename n°3 (option)> "
            )
            print('')
            print(
                'requires the file containing elements and number (in order to compute the densities)'
            )
            print(
                'requires the files .txt created with the plot_speciation_lifetime.py script'
            )
            print('')
            sys.exit()
        elif opt in ("-f", "--file1"):
            filename1 = str(arg)
        elif opt in ("-g", "--gfile2"):
            filename2 = str(arg)
        elif opt in ("-j", "--jfile3"):
            filename3 = str(arg)
        elif opt in ("-a", "--atom"):
            atoms = arg.split(',')
        elif opt in ("-v", "--variable"):
            variable = str(arg)
        elif opt in ("-m", "--mineralfile"):
            mineralfile = str(arg)
        elif opt in ('-l', 'letter'):
            letter = str(arg)
    #***** Calculation of the molecular mass
    with open(mineralfile, 'r') as mf:
        entry = mf.readline()
        elements = entry.split()[1:]
        entry = mf.readline()
        number = entry.split()[1:]
    MN = 0
    for i in range(len(elements)):
        MN = MN + float(number[i]) * cr.Elements2rest(elements[i])[3]
    #***** Extraction of all cluster type from all files along with max size of data per cluster
    print("*********************** 1st step: extraction of data separately")
    with open(filename1, 'r') as f:
        print('********** for file', filename1)
        line = f.readline()  #we read the first line with cluster sizes
        all_length = line.split('\n')[0].split('\t')
        line = f.readline()  #we read the second line with cluster names
        clusters = line.split('\n')[0].split('\t')
        #print('clusters in file:',clusters)
        #we take all the clusters
        if atoms == 'all':
            print("I use all atomic clusters")
            for i in range(len(clusters)):
                data1[clusters[i]] = []  #initialization of data
                cluster_lengths[clusters[i]] = int(all_length[i])
        else:  #or we select only the cluster names we want
            print('I use only clusters starting by ', atoms)
            for atom in atoms:
                for i in range(len(clusters)):
                    if clusters[i][:len(atom)] == atom:
                        data1[clusters[i]] = []  #initialization of data
                        cluster_lengths[clusters[i]] = int(all_length[i])
        #print(data1)
        while True:
            line = f.readline(
            )  #we read all the other lines with lifetime for each apparition
            if not line: break
            else:
                entry = line.split('\n')[0].split('\t')
                for i in range(
                        0, len(clusters)
                ):  #we store the correct lifetime in the dictionnary for the corresponding key
                    if entry[i] != '':
                        try:
                            data1[clusters[i]].append(float(entry[i]))
                        except KeyError:
                            continue
                    else:
                        continue
    with open(filename2, 'r') as f:
        print('********** for file', filename2)
        line = f.readline()  #we read the first line with cluster sizes
        all_length = line.split('\n')[0].split('\t')
        line = f.readline()  #we read the second line with cluster names
        clusters = line.split('\n')[0].split('\t')
        #print('clusters in file:',clusters)
        #we take all the clusters
        if atoms == 'all':
            print("I use all atomic clusters")
            for i in range(len(clusters)):
                data2[clusters[i]] = []  #initialization of data
                cluster_lengths[clusters[i]] = int(all_length[i])
        else:  #or we select only the cluster names we want
            print('I use only clusters starting by ', atoms)
            for atom in atoms:
                for i in range(len(clusters)):
                    if clusters[i][:len(atom)] == atom:
                        data2[clusters[i]] = []  #initialization of data
                        cluster_lengths[clusters[i]] = int(all_length[i])
        #print(data1)
        while True:
            line = f.readline(
            )  #we read all the other lines with lifetime for each apparition
            if not line: break
            else:
                entry = line.split('\n')[0].split('\t')
                for i in range(
                        0, len(clusters)
                ):  #we store the correct lifetime in the dictionnary for the corresponding key
                    if entry[i] != '':
                        try:
                            data2[clusters[i]].append(float(entry[i]))
                        except KeyError:
                            continue
                    else:
                        continue
    if filename3 != '':
        with open(filename3, 'r') as f:
            print('********** for file', filename3)
            line = f.readline()  #we read the first line with cluster sizes
            all_length = line.split('\n')[0].split('\t')
            line = f.readline()  #we read the second line with cluster names
            clusters = line.split('\n')[0].split('\t')
            #print('clusters in file:',clusters)
            #we take all the clusters
            if atoms == 'all':
                print("I use all atomic clusters")
                for i in range(len(clusters)):
                    data3[clusters[i]] = []  #initialization of data
                    cluster_lengths[clusters[i]] = int(all_length[i])
            else:  #or we select only the cluster names we want
                print('I use only clusters starting by ', atoms)
                for atom in atoms:
                    for i in range(len(clusters)):
                        if clusters[i][:len(atom)] == atom:
                            data3[clusters[i]] = []  #initialization of data
                            cluster_lengths[clusters[i]] = int(all_length[i])
            #print(data1)
            while True:
                line = f.readline(
                )  #we read all the other lines with lifetime for each apparition
                if not line: break
                else:
                    entry = line.split('\n')[0].split('\t')
                    for i in range(
                            0, len(clusters)
                    ):  #we store the correct lifetime in the dictionnary for the corresponding key
                        if entry[i] != '':
                            try:
                                data3[clusters[i]].append(float(entry[i]))
                            except KeyError:
                                continue
                        else:
                            continue
    #creation of the list containing all the cluster once and only once
    clusters = []
    [clusters.append(key) for key in data1]
    for key in data2:
        if key not in clusters:
            clusters.append(key)
    if filename3 != '':
        for key in data3:
            if key not in clusters:
                clusters.append(key)
    clusters.sort()
    print(clusters)
    print(
        "*********************** 2nd step: Addition of '0' data in order to have the same x axis "
    )
    #*********creation of the dictionnaries containing:
    #-sizes of the data
    #-lists of labels (with the cluster name and then voids)
    #-data completed by voids
    labels = {}
    sizes = {}
    size3 = 0
    for cluster in clusters:
        #***test to obtain the size of data list for current cluster
        try:
            size1 = len(data1[cluster])
            #print("#1:",cluster,size1)
        except KeyError:
            size1 = 0
            #print("#1:",cluster,size1)
        try:
            size2 = len(data2[cluster])
            #print("#2:",cluster,size2)
        except KeyError:
            size2 = 0
            #print("#2:",cluster,size2)
        if filename3 != '':
            try:
                size3 = len(data3[cluster])
                #print("#2:",cluster,size2)
            except KeyError:
                size3 = 0
        #the number we keep is the max of the three previous values
        sizes[cluster] = max(size1, size2, size3)
        #***now we can create the labels
        #either with simple method of 'label'+ voids
        labels[cluster] = [cluster]
        for i in range(sizes[cluster] - 1):
            labels[cluster].append('')
        #or by putting the label in the middle of the arrays
        #labels[cluster]=[]
        #if sizes[cluster] > 1:
        #    if sizes[cluster] > 2:
        #        for i in range(round(sizes[cluster]/2)-1):
        #            labels[cluster].append('')
        #        labels[cluster].append(cluster)
        #        for i in range(round(sizes[cluster]/2)-1):
        #            labels[cluster].append('')
        #    else:
        #        labels[cluster].extend([cluster,''])
        #else:
        #    labels[cluster]=[cluster]
        #***Now we add 'nan' to data array in order to have the same x axis
        try:
            if size1 < sizes[cluster]:
                for i in range(sizes[cluster] - size1 - 1):
                    data1[cluster].append(float('nan'))
                data1[cluster].append(0)
        except KeyError:
            data1[cluster] = []
            for i in range(sizes[cluster] - 1):
                data1[cluster].append(float('nan'))
            data1[cluster].append(0)
        try:
            if size2 < sizes[cluster]:
                for i in range(sizes[cluster] - size2 - 1):
                    data2[cluster].append(float('nan'))
                data2[cluster].append(0)
        except KeyError:
            data2[cluster] = []
            for i in range(sizes[cluster] - 1):
                data2[cluster].append(float('nan'))
            data2[cluster].append(0)
        if filename3 != '':
            try:
                if size3 < sizes[cluster]:
                    for i in range(sizes[cluster] - size3 - 1):
                        data3[cluster].append(float('nan'))
                    data3[cluster].append(0)
            except KeyError:
                data3[cluster] = []
                for i in range(sizes[cluster] - 1):
                    data3[cluster].append(float('nan'))
                data3[cluster].append(0)
    #print(labels)
    #print("sizes of lists",sizes)
    print(
        "*********************** 3rd step: Creation of labels and arrays to plot"
    )
    #creation of the big list of data (concatenation) and labels
    totdata1 = []
    totdata2 = []
    totdata3 = []
    totlabels = []
    #if we want to sort clusters by size and name
    sorted_cluster_lengths = [
        (v[0], v[1]) for v in natsort.natsorted(cluster_lengths.items(),
                                                key=lambda kv: (kv[1], kv[0]))
    ]  #[v[0] for v in sorted(d.items(), key=lambda kv: (-kv[1], kv[0]))] #  natsort.natsorted(cluster_lengths.items(), key=lambda kv: kv[1])
    print(sorted_cluster_lengths)
    for i in range(len(sorted_cluster_lengths)):
        cluster = sorted_cluster_lengths[i][0]
        totdata1.extend(data1[cluster])
        totdata2.extend(data2[cluster])
        if filename3 != '':
            totdata3.extend(data3[cluster])
        totlabels.extend(labels[cluster])
        #print(cluster, sizes[cluster])
    #formatage of labels
    for j in range(len(totlabels)):
        if totlabels[j] != '':
            totlabels[j] = format1label(totlabels[j])
    #print(totlabels)
    if (len(totdata1) == 0) and (len(totdata2) == 0) and (len(totdata3) == 0):
        print("There is nothing to plot for clusters of type ", atoms)
        sys.exit()
    #creation of x vector
    totsize = 0
    for key in sizes:
        totsize = totsize + sizes[key]
    x = np.arange(totsize)
    #creation of custom labels
    temp1, acell1 = split_name(filename1)
    temp2, acell2 = split_name(filename2)
    if filename3 != '':
        temp3, acell3 = split_name(filename3)
    if variable == 'rho':
        var1 = 'a' + acell1
        label1 = str(round(MN / (Na * float(acell1)**3 * 10**(-24)),
                           2)) + ' g.cm$^{-3}$'
        print(label1)
        var2 = 'a' + acell2
        label2 = str(round(MN / (Na * float(acell2)**3 * 10**(-24)),
                           2)) + ' g.cm$^{-3}$'
        print(label2)
        if filename3 != '':
            var3 = 'a' + acell3
            label3 = str(round(MN / (Na * float(acell3)**3 * 10**(-24)),
                               2)) + ' g.cm$^{-3}$'
            print(label3)
        fixedvar = temp1
        title = filename1.split('_')[0]
        #formatage of the mineral name
        i = 0
        while True:
            if i <= len(title) - 1:
                if re.match('[0-9]', title[i]):
                    title = title[:i] + '$_{' + title[i] + '}$' + title[i + 1:]
                    i = i + 5
                i = i + 1
            else:
                break
        title = title + ' at ' + fixedvar + ' K'
    else:
        var1 = temp1 + 'K'
        label1 = str(temp1) + ' K'
        var2 = temp2 + 'K'
        label2 = str(temp2) + ' K'
        if filename3 != '':
            var3 = temp3 + 'K'
            label3 = str(temp3) + ' K'
        fixedvar = str(round(MN / (Na * float(acell2)**3 * 10**(-24)), 2))
        title = filename1.split('_')[0]
        #formatage of the mineral name
        i = 0
        while True:
            if i <= len(title) - 1:
                if re.match('[0-9]', title[i]):
                    num = 0
                    try:
                        while re.match('[0-9]', title[i + num]):
                            num += 1
                    except IndexError:  #index error when we arrive at the end of the cluster name
                        pass
                        #print('end of the cluster')
                    title = title[:i] + '$_{' + title[i:i +
                                                      num] + '}$' + title[i +
                                                                          num:]
                    i = i + 5
                i = i + 1
            else:
                break
        title = title + ' at ' + fixedvar + ' g.cm$^{-3}$'
    print(
        "*********************** 4th step: Plot everything on the same figure")
    #*********** Plot
    #Creation of the plot
    speciation_type = filename1.split('umd.dat.')[1].split('.popul.dat')[0]
    if speciation_type == 'r1':
        xlabel = 'Chemical species'
    else:
        xlabel = 'Coordinating polyhedra'
    fig, ax = creation_plot(xlabel)
    #if speciation_type == 'r0': #because of resolution problems (too many bars so they are too thin to appear) we should use a line plot filled for r0
    #    print("speciation 0")
    #    plt.fill_between(x,totdata1, y2 =0, color=colors_T[temp1], alpha = 1, label=label1)
    #    plt.fill_between(x,totdata2, y2 =0, color=colors_T[temp2], alpha = 0.5, label=label2)
    #    if filename3 != '':
    #        plt.fill_between(x,totdata3, y2=0, color=colors_T[temp3], alpha = 0.35, label=label3)
    #else: #but for r1 we keep the standard bar plot (less bars to plot)
    #    print("speciation 1")
    #    plt.bar(x,totdata1, width = 1, color=colors_T[temp1], alpha = 1, label=label1)
    #    plt.bar(x,totdata2, width = 1, color=colors_T[temp2], alpha = 0.5, label=label2)
    #    if filename3 != '':
    #        plt.bar(x,totdata3, width = 1, color=colors_T[temp3], alpha = 0.35, label=label3)
    plt.plot(x, totdata1, '-', color=colors_T[temp1], label=label1)
    plt.plot(x, totdata2, '-', color=colors_T[temp2], label=label2)
    if filename3 != '':
        plt.plot(x, totdata3, '-', color=colors_T[temp3], label=label3)
    plt.xticks(x, totlabels, rotation=45, fontsize=10)
    ax.yaxis.set_ticks_position('both')
    if letter != '':
        ax.text(0.007,
                0.94,
                letter,
                transform=ax.transAxes,
                horizontalalignment='left',
                fontweight='bold',
                fontsize=plot_parameters["size_fonts"],
                bbox=dict(facecolor='none', edgecolor='k', pad=3.0))
    #plt.title(title, fontsize = 12, fontweight = 'bold')
    #plt.legend(loc='upper right', fontsize = 12)
    #save plot
    if filename3 != '':
        figurename = 'comparison_lifetime_' + filename1.split('/')[-1].split(
            '_'
        )[0] + '_' + speciation_type + '_' + fixedvar + '_' + var1 + '-' + var2 + '-' + var3
    else:
        figurename = 'comparison_lifetime_' + filename1.split('/')[-1].split(
            '_'
        )[0] + '_' + speciation_type + '_' + fixedvar + '_' + var1 + '-' + var2
    figurename = figurename + '.svg'
    plt.savefig(figurename, bbox_inches='tight', dpi=300)
    print(figurename, 'is created')
예제 #18
0
def main(argv):
    """     ********* Main program *********     """
    files = []
    data = {} #dictionnary containing lifetimes for each cluster 
    cluster_lengths = {}#dictionnary containing length of cluster for each cluster 
    sizes = {}
    labels = {}
    note = {} #dictionnary to add a note on the figure in case of max lifetime = simulation time
    #other dictionnaries and parameters for the figure
    colors_T = {'2000':'#800080','3000':'#297fff','4000':'#00ff00','4500':'#bae200','5000':'#ffcd01','6000':'#ff0101','6500':'#ff00a2','7000':'#ff01de'}
    atoms = 'all'
    atomslist = 'all'
    letters = ['a','b','c','d','e','f','g','h','i']
    #other parameters
    Na=6.022*10**23
    try:
        options,arg = getopt.getopt(argv,"hm:a:f:l:",["mineralfile","atom","filename","lifetime"])
#        options,arg = getopt.getopt(argv,"hc:m:a:r:l:",["cell","mineralfile",'atoms','rspeciation',"length"])
    except getopt.GetoptError:
        print("plot_speciation-lifetime-comp-allT.py  -m <mineralfile with elements> -a <list of first atom determining the type of cluster to plot  (default = 'all')>  -f <one filename of the same format name than all we want to plot> -l <list of max lifetime of all the simu>  ")
#        print("plot_speciation-lifetime-comp-allT.py  -m <mineralfile with elements> -a <list of first atom determining the type of cluster to plot  (default = 'all')>  -c <cell we want to plot>  -r <speciation type (0 or 1)> -l <max length of clusters>  ")
        sys.exit()
    for opt,arg in options:
        if opt == '-h':
            print('')
            print('plot_speciation-lifetime-comp-allT.py program to  Plot lifetime barchart for all temperatures at a selected acell for some cluster,  one figure per file')
            print("plot_speciation-lifetime-comp-allT.py  -m <mineralfile with elements> -a <list of first atom determining the type of cluster to plot  (default = 'all')>  -f <one filename of the same format name than all we want to plot> -l <list of max lifetime of all the simu>  ")
#            print("plot_speciation-lifetime-comp-allT.py  -m <mineralfile with elements> -a <list of first atom determining the type of cluster to plot (default = 'all')>  -c <cell we want to plot>  -r <speciation type (0 or 1)> -l <max length of clusters> ")
            print("")
            print('requires the file containing elements and number (in order to compute the densities)')
            print('requires to launch the script from the directory containing all the files .txt created with the plot_speciation_lifetime.py script')
            print('')
            sys.exit()
#        elif opt in ("-c", "--cell"):
#            cell = str(arg)
        elif opt in ("-m","--mineralfile"):
            mineralfile = str(arg)
        elif opt in ("-a","--atoms"):
            atomslist = str(arg)
            atoms = arg.split(',')                      #list of atom couples we want to analyze here
        elif opt in ("-f","--filename"):
            firstfilename = str(arg)
        elif opt in ("-l","--lifetime"):
            max_lifetimes = list(map(int,arg.split(',')))
#        elif opt in ("-r","--rspeciation"):
#            speciation = str(arg)
#        elif opt in ("-l","--length"):
#            length = str(arg)
    #***** Calculation of the molecular mass
    with open(mineralfile,'r') as mf:
        entry = mf.readline()
        elements = entry.split()[1:]
        entry = mf.readline()
        number = entry.split()[1:]
    MN = 0
    for i in range(len(elements)):
        MN = MN + float(number[i]) * cr.Elements2rest(elements[i])[3]
    #***** List of all the files concerned by the  T and acell
    cell = firstfilename.split('.outcar.umd.dat')[0].split('_')[3].strip('a')
    speciation = firstfilename.split('.outcar.umd.dat.r')[-1].split('.popul.dat')[0]
    length = firstfilename.split('.popul.dat_L')[-1].split('.txt')[0]
    filename = '*_a'+cell+'*outcar.umd.dat.r'+speciation+'.popul.dat_L'+length+'*.txt'
    print('I search for files of type', filename)
    allfiles = sorted(glob.glob(filename))                             #I list every population file created by plot_speciation-lifetime.py in alphabetic order
    #print(files)
    print('I use the corresponding limit lifetimes', max_lifetimes)
    #we remove the empty files (the ones created by hand) from the file list
    for file in allfiles:
        if os.stat(file).st_size != 0:
            files.append(file)
    #***** Extraction of all cluster type from all files along with max size of data per cluster
    print("*********************** 1st step: calculation of total number of bars in order to have the same x axis")
    for file in files:
        print('********** for file',file)
        with open(file,'r') as f:
            line = f.readline() #we read the first line with cluster sizes
            all_length = line.split('\n')[0].split('\t')
            print(all_length)
            line = f.readline() #we read the second line with cluster names
            clusters=line.split('\n')[0].split('\t')
            print('clusters in file:',clusters)
            #we take all the clusters
            if atoms == 'all':
                print("I use all atomic clusters")
                for i in range(len(clusters)):
                    data[clusters[i]] = [] #initialization of data 
                    cluster_lengths[clusters[i]] = all_length[i]
            else: #or we select only the cluster names we want 
                print('I use only clusters starting by ', atoms)
                for atom in atoms:
                    for i in range(len(clusters)):
                        if clusters[i][:len(atom)] == atom:
                            print(clusters[i])
                            data[clusters[i]] = [] #initialization of data 
                            cluster_lengths[clusters[i]] = all_length[i]
            #extraction of data, all in the same data dictionnary in order to know the total (cumulative) number of bars in the bar plot
            while True:
                line = f.readline() #we read all the other lines with lifetime for each apparition
                if not line: break
                else:
                    entry=line.split('\n')[0].split('\t')
                    for i in range(0,len(clusters)): #we store the correct lifetime in the dictionnary for the corresponding key
                        if entry[i] != '':
                            try:
                                data[clusters[i]].append(float(entry[i]))
                            except KeyError:
                                continue
                        else: continue
        #print('data',data) 
        #test to find the maximum value for data sizes (for each cluster)
        if atoms == 'all':
            for cluster in clusters:
                try:
                    if len(data[cluster]) > sizes[cluster]:
                        sizes[cluster] = len(data[cluster])
                except KeyError:
                    sizes[cluster] = len(data[cluster])
        else:
            for atom in atoms:
                for cluster in clusters:
                    if cluster[:len(atom)] == atom:
                        try:
                            if len(data[cluster]) > sizes[cluster]:
                                sizes[cluster] = len(data[cluster])
                        except KeyError:
                            sizes[cluster] = len(data[cluster])
        #print("sizes",sizes)
    #************ Extraction of the data and determination of the max of all figures (to keep the y axis identical)
    print("*********************** 2nd step: Extraction of data per file and deterination of ymax for all fig")
    ymax = 0
    for file in files: 
        print('********** for file',file)
        letter = letters[allfiles.index(file)]
        print('letter is', letter)
        data = {} #initialization of data
        with open(file,'r') as f:
            line = f.readline() #we read the first line with cluster sizes
            line = f.readline() #we read the second line with cluster names
            clusters=line.split('\n')[0].split('\t')
            #print('clusters in file:',clusters)
            #we take all the clusters
            if atoms == 'all':
                for i in range(len(clusters)):
                    data[clusters[i]] = [] #initialization of data 
            else: #or we select only the cluster names we want    
                for atom in atoms:
                    for i in range(len(clusters)):
                        if clusters[i][:len(atom)] == atom:
                            data[clusters[i]] = [] #initialization of data 
            #extraction of data
            while True:
                line = f.readline() #we read all the other lines with lifetime for each apparition
                if not line: break
                else:
                    entry=line.split('\n')[0].split('\t')
                    for i in range(0,len(clusters)): #we store the correct lifetime in the dictionnary for the corresponding key
                        if entry[i] != '':
                            try:
                                data[clusters[i]].append(float(entry[i]))
                            except KeyError:
                                continue
                        else: continue
        #we complete the data lists with nan in  order to have the same x axis
        for cluster in sizes:
            try:
                if len(data[cluster]) < sizes[cluster]:
                    for i in range(sizes[cluster]-len(data[cluster])):
                        data[cluster].append(float('nan'))
            except KeyError:
                data[cluster] = []
                for i in range(sizes[cluster]):
                    data[cluster].append(float('nan'))
        #********* Creation of the dictionnary containing the lists of labels (with the cluster name and then voids)   
        for cluster in sizes: 
            print('cluster',cluster)
            print(data[cluster])
            if str(data[cluster][0]) != 'nan': #we replace labels by voids when the specie is not there
                labels[cluster]=[cluster]
                for i in range(sizes[cluster]-1):
                    labels[cluster].append('') 
            else:
                labels[cluster]=['']
                for i in range(sizes[cluster]-1):
                    labels[cluster].append('') 
        #********* Creation of the big list of data (concatenation) and labels sorted by length of clusters
        totdata = [] 
        totlabels = []
        sorted_cluster_lengths = natsort.natsorted(cluster_lengths.items(), key=lambda kv: kv[1])
        print(sorted_cluster_lengths)
        for i in range(len(sorted_cluster_lengths)):
            cluster = sorted_cluster_lengths[i][0]
            totdata.extend(data[cluster])
            totlabels.extend(labels[cluster])
        print('maximum of data',np.nanmax(totdata))
        if np.nanmax(totdata) < max_lifetimes[files.index(file)] :
            if np.nanmax(totdata) > ymax:
                ymax = np.nanmax(totdata)
            note[file] = ''
        else:
            note[file] = 'maximum lifetime \n = simulation time' 
    print("*********************************** ymax =",ymax)   
    #************ Same as before with plot, each on a different figure (one fig per T)
    print("*********************** 3rd step: Extraction of data per file and plot each graph on a different figure")    
    for file in files: 
        print('********** for file',file)
        letter = letters[allfiles.index(file)]
        print('letter is', letter)
        data = {} #initialization of data
        with open(file,'r') as f:
            line = f.readline() #we read the first line with cluster sizes
            line = f.readline() #we read the second line with cluster names
            clusters=line.split('\n')[0].split('\t')
            #print('clusters in file:',clusters)
            #we take all the clusters
            if atoms == 'all':
                for i in range(len(clusters)):
                    data[clusters[i]] = [] #initialization of data 
            else: #or we select only the cluster names we want    
                for atom in atoms:
                    for i in range(len(clusters)):
                        if clusters[i][:len(atom)] == atom:
                            data[clusters[i]] = [] #initialization of data 
            #extraction of data
            while True:
                line = f.readline() #we read all the other lines with lifetime for each apparition
                if not line: break
                else:
                    entry=line.split('\n')[0].split('\t')
                    for i in range(0,len(clusters)): #we store the correct lifetime in the dictionnary for the corresponding key
                        if entry[i] != '':
                            try:
                                data[clusters[i]].append(float(entry[i]))
                            except KeyError:
                                continue
                        else: continue
        #we complete the data lists with nan in  order to have the same x axis
        for cluster in sizes:
            try:
                if len(data[cluster]) < sizes[cluster]:
                    for i in range(sizes[cluster]-len(data[cluster])):
                        data[cluster].append(float('nan'))
            except KeyError:
                data[cluster] = []
                for i in range(sizes[cluster]):
                    data[cluster].append(float('nan'))
        #********* Creation of the dictionnary containing the lists of labels (with the cluster name and then voids)   
        for cluster in sizes: 
            if str(data[cluster][0]) != 'nan': #we replace labels by voids when the specie is not there
                labels[cluster]=[cluster]
                for i in range(sizes[cluster]-1):
                    labels[cluster].append('') 
            else:
                labels[cluster]=['']
                for i in range(sizes[cluster]-1):
                    labels[cluster].append('') 
        #********* Creation of the big list of data (concatenation) and labels sorted by length of clusters
        totdata = [] 
        totlabels = []
        sorted_cluster_lengths = natsort.natsorted(cluster_lengths.items(), key=lambda kv: kv[1])
        print(sorted_cluster_lengths)
        for i in range(len(sorted_cluster_lengths)):
            cluster = sorted_cluster_lengths[i][0]
            totdata.extend(data[cluster])
            totlabels.extend(labels[cluster])     
        #formatage of labels
        for j in range(len(totlabels)):
            if totlabels[j] != '':
                i=0
                while True:
                    #print('i=',i, 'len totlabels -1 = ',len(totlabels[j])-1 )
                    if i <= len(totlabels[j])-1:
                        #print('totlabels j i = ', totlabels[j][i])
                        if re.match('_',totlabels[j][i]):
                            num=0
                            try:
                                while re.match('[0-9]',totlabels[j][i+1+num]):
                                    num +=1
                            except IndexError: #index error when we arrive at the end of the cluster name
                                pass
                                #print('end of the cluster')
                            totlabels[j] = totlabels[j][:i]+'$_{'+totlabels[j][i+1:i+1+num]+'}$' + totlabels[j][i+1+num:]
                            #print('new totlabels j =',totlabels[j])
                            i = i+5
                        i = i+1
                    else:break
        #print(totlabels)
        #*********** Plot
        #Creation of the plot
        fig, ax = creation_plot(speciation)
        if (len(totdata) == 0) :
            print("There is nothing to plot for clusters of type ",atoms, 'in file ', file )
            #save empty plot
            empty_plot(fig, ax, file, ymax, letter, colors_T, speciation, length, atomslist)
            continue
        #creation of x vector
        totsize = 0
        for key in sizes:
            totsize = totsize + sizes[key]
        x = np.arange(totsize)
        print('len of x= ', len(x))
        #creation of custom labels
        temp, acell = split_name(file)
        label= str(temp)+' K'
        fixedvar = str(round(MN/(Na*float(acell)**3*10**(-24)),2))
        title = file.split('_')[0]
        #formatage of the mineral name
        i=0
        while True:
            if i <= len(title)-1:
                if re.match('[0-9]',title[i]):
                    num=0
                    try:
                        while re.match('[0-9]',title[i+num]):
                            num +=1
                    except IndexError: #index error when we arrive at the end of the cluster name
                        pass
                        #print('end of the cluster')
                    title = title[:i]+'$_{'+title[i:i+num]+'}$' + title[i+num:]
                    i = i+5
                i = i+1
            else:break
        title = title+' at '+fixedvar+' g.cm$^{-3}$'
        if speciation == '0' or len(x)>1000: #because of resolution problems (too many bars so they are too thin to appear) we should use a line plot filled for r0
            plt.fill_between(x,totdata, y2 =0, color=colors_T[temp], alpha = 1, label=label)  
        else: #but for r1 we keep the standard bar plot (less bars to plot)
            plt.bar(x,totdata, width = 1, color=colors_T[temp], alpha = 1, label=label)  
        plt.xticks(x, totlabels, rotation = 45, fontsize = 10)
        width=20
        ax.set_xlim(-width,len(x)+width)
        ax.set_ylim(0,ymax)
        ax.yaxis.set_ticks_position('both')
        #plt.title(title, fontsize = 12, fontweight = 'bold')
        plt.text(0.01,0.95, letter , transform=ax.transAxes, horizontalalignment = 'left', fontweight = 'bold', fontsize = 12, bbox=dict(facecolor='none', edgecolor='k', pad=3.0))  
        plt.legend(loc='upper right', fontsize = 12)
        plt.subplots_adjust(top = 0.97, bottom = 0.26, right = 0.94, left = 0.12, hspace = 0, wspace = 0)
        #addition of the note if it exists
        if note[file] != '':
            plt.text(0.7,0.7, note[file] , transform=ax.transAxes, horizontalalignment = 'left', fontsize = 12)  
        #save plot
        figurename = 'lifetime_allT_'+file.split('.outcar.umd.dat')[0]+'_r'+speciation+'_L'+length+'_'+atomslist+'.png'
        plt.savefig(figurename, dpi=150)#, bbox_inches='tight') #remove 'tight' to take into account options of subplots_adjust
        print(figurename, 'is created')
        #plt.show()    

    #For files that does not exist and for which we created a corresponding empty file, we create an empty figure and remove them of the list of files
    for file in allfiles:
        if os.stat(file).st_size == 0:
            letter = letters[allfiles.index(file)]
            fig, ax = creation_plot(speciation)
            empty_plot(fig, ax, file, ymax, letter, colors_T, speciation, length, atomslist)
def main(argv):
    """     ********* Main program *********     """
    xdata = {'T': [], 'rho': [], 'P': []}  #dictionnary containing the x data
    data = []  #list containing y data
    xdata2 = {'T': [], 'rho': [], 'P': []}  #dictionnary containing the x data
    data2 = []  #list containing y data
    TP = {}  #dictionnary with P and T in each simufile
    colors_species = {}
    #other dictionnaries and parameters for the figure for article version
    #plot_parameters = {"size_fonts" : 12,"size_font_ticks":10,"size_figure" : (8,4),"size_markers" : 4,"size_lines" : 1,"shift_labelpad" : 20}
    plot_parameters = {
        "size_fonts": 16,
        "size_font_ticks": 14,
        "size_figure": (12, 7),
        "size_markers": 10,
        "size_lines": 2,
        "shift_labelpad": 10
    }
    #dictionnary for fullaverages file in full version
    column_number = {
        'rho': 2,
        'P': 5,
        'stdev_P': 6,
        'err_P': 7,
        'T': 8,
        'stdev_T': 9,
        'err_T': 10,
        'E': 14,
        'stdev_E': 15,
        'err_E': 16,
        'Cvm_Nkb': 23,
        'stdev_Cvm_Nkb': 24,
        'Cvm': 25,
        'stdev_Cvm': 26,
        'testCv': 31,
        'stdev_testCv': 32
    }
    #other parameters
    Na = 6.022 * 10**23
    statfile2 = ''
    try:
        options, arg = getopt.getopt(
            argv, "hf:g:a:v:m:",
            ["file1", "gfile2", "atom", "variable", "mineralfile"])
    except getopt.GetoptError:
        print(
            "plot_speciation-r0.py -a <first atom determining the type of cluster to plot> -v <variable (rho,P,T)> -m <mineralfile with elements> -f <stat-concentrate_r0_perc_filename> -g <stat-concentrate_perc_filename n°2 (option)>  "
        )
        sys.exit()
    for opt, arg in options:
        if opt == '-h':
            print('')
            print(
                'plot_speciation-r0.py program to  Plot abundance of coordinations for selected cation as a function of rho,P  or T'
            )
            print(
                "plot_speciation-r0.py -a <first atom determining the type of cluster to plot> -v <variable (rho,P,T)> -m <mineralfile with elements> -f <stat-concentrate_r0_perc_filename> -g <stat-concentrate_perc_filename n°2 (option)> "
            )
            print(
                'requires the file containing elements and number (in order to compute the densities)'
            )
            print('')
            print(
                'For plots as function of P, make sure the files from fullaverages.py are in the current folder'
            )
            sys.exit()
        elif opt in ("-f", "--file1"):
            statfile = str(arg)
        elif opt in ("-g", "--gfile2"):
            statfile2 = str(arg)
        elif opt in ("-a", "--atom"):
            atom = str(arg)
        elif opt in ("-v", "--variable"):
            variable = str(arg)
        elif opt in ("-m", "--mineralfile"):
            mineralfile = str(arg)
    #***** Calculation of the molecular mass
    with open(mineralfile, 'r') as mf:
        entry = mf.readline()
        elements = entry.split()[1:]
        entry = mf.readline()
        number = entry.split()[1:]
    MN = 0
    for i in range(len(elements)):
        MN = MN + float(number[i]) * cr.Elements2rest(elements[i])[3]
    #***** Creation of the plot
    if statfile2 != '':
        with open(statfile, 'r') as f:
            line = f.readline()
            file1 = line.split()[1]
        with open(statfile2, 'r') as f2:
            line = f2.readline()
            file2 = line.split()[1]
        fig, ax, ax2 = creation_plot2(variable, file1, file2, MN,
                                      plot_parameters)
        axrange = ax.get_xlim()
        ax2range = ax2.get_xlim()
    else:
        fig, ax = creation_plot(variable, plot_parameters)
        axrange = ax.get_xlim()
    #***** Count of the number of clusters for the selected atom type (needed for the automatic color change)
    #first store every cluster type into the dictionary
    with open(statfile, 'r') as f:
        while True:
            line = f.readline()
            if not line: break
            else:
                entry = line.split('\n')[0].split('\t')
                if len(entry) > 1:
                    if entry[0][:len(atom)] == atom:
                        colors_species[entry[0]] = []
    mineralname = statfile.split('/')[-1].split('_')[0]
    #then, in case of a second file, we check if there is additional cluster and add them to the dictionary if applicable
    if statfile2 != '':
        with open(statfile2, 'r') as f2:
            while True:
                line = f2.readline()
                if not line: break
                else:
                    entry = line.split('\n')[0].split('\t')
                    if len(entry) > 1:
                        if entry[0][:len(atom)] == atom:
                            if not entry[0] in colors_species:
                                colors_species[entry[0]] = []
    name = 'batlow'  #'lajolla' #'imola'
    if 'Al_1O' in atom or 'Si_1O' in atom:
        #Creation of the color list for 11 coordination
        list_species = []
        cm_data = np.loadtxt(
            "/Users/akobsch/Dropbox/Recherche/PhD-MD-silicates/simulations/scripts/Analysis/ScientificColourMaps6/"
            + name + "/" + name + ".txt")
        #cm_data = cm_data[::-1] #for reverse colors (lajolla)
        new_map = LinearSegmentedColormap.from_list(
            'new', cm_data)  #[:-20]) #no cut for imola
        color = iter(new_map(np.linspace(0, 1,
                                         11)))  #Creation of the color list
        #color = iter(plt.cm.jet(np.linspace(0,1,11)))
        for i in range(1, 12, 1):
            c = next(color)
            curr_species = atom + '_' + str(i)
            if curr_species in colors_species:
                colors_species[curr_species] = c
                list_species.append(curr_species)
        print(list_species, len(list_species))
    else:
        #Creation of the color list for 19 coordination
        list_species = []
        cm_data = np.loadtxt(
            "/Users/akobsch/Dropbox/Recherche/PhD-MD-silicates/simulations/scripts/Analysis/ScientificColourMaps6/"
            + name + "/" + name + ".txt")
        #cm_data = cm_data[::-1] #for reverse colors
        new_map = LinearSegmentedColormap.from_list('new', cm_data)
        color = iter(new_map(np.linspace(0, 1,
                                         19)))  #Creation of the color list
        #color = iter(plt.cm.jet(np.linspace(0,1,19)))
        for i in range(1, 20, 1):
            c = next(color)
            curr_species = atom + '_' + str(i)
            if curr_species in colors_species:
                colors_species[curr_species] = c
                list_species.append(curr_species)
        print(list_species, len(list_species))
    #*****************************
    #*******************
    #*******
    # Extraction of  P and T for each simufile of each thermo file
    thermofiles = sorted(glob.glob('thermo_' + mineralname + '*.txt'))
    for file in thermofiles:
        TP = extract_TP(file, column_number, TP, '')
    #*****************************
    #*******************
    #*******
    #Read & plot for the first file
    #read the file1
    with open(statfile, 'r') as f:
        line = f.readline()
        entry = line.split()
        files = entry[1:]
        #creation of the x data list
        for file in files:
            temperature, acell = split_name(file)
            xdata['rho'].append(
                MN / (Na * float(acell)**3 * 10**(-24)))  #calculation density
            xdata['T'].append(int(temperature))
            xdata['P'].append(TP[file.split('/')[-1]][1])
            #print(file.split('/')[-1],MN/(Na*float(acell)**3*10**(-24)),int(temperature),TP[file.split('/')[-1]][1])
    with open(statfile, 'r') as f:
        #creation of the y data list and plot for each cluster
        while True:
            line = f.readline()
            if not line: break
            else:
                entry = line.split('\n')[0].split('\t')
                if len(entry) > 1:
                    if entry[0][:len(atom)] == atom:
                        for i in range(
                                1, len(entry)):  #we loop over all the files
                            if entry[i] == '':
                                entry[i] = 0
                            data.append(float(entry[i]))
                        #now the data array is filled, we plot the line for this species
                        x, y = zip(*sorted(zip(xdata[variable], data)))
                        line, = ax.plot(
                            x,
                            y,
                            '.--',
                            color=colors_species[entry[0]],
                            markersize=plot_parameters["size_markers"],
                            linewidth=plot_parameters["size_lines"])
                        #if variable == 'T':
                        #    label_line(ax, line, entry[0], halign='right')
                        #elif list_species.index(entry[0]) < int(len(list_species)/2):
                        #    label_line(ax, line, entry[0], halign='left')
                        #else:
                        #    label_line(ax, line, entry[0], halign='right')
                        #and we plot the name of the species near the max of the curve
                        if max(data) > 0.05:
                            x_max = xdata[variable][data.index(max(data))]
                            if x_max > axrange[0] and x_max < axrange[1]:
                                y_max = max(data)
                                label = entry[0]
                                #**** formatage of label with removing _1
                                label = format1label(label)
                                ax.text(x_max,
                                        y_max,
                                        label,
                                        color='0.35',
                                        fontsize=plot_parameters['size_fonts'])

                        data = [
                        ]  #reinitialization of data array for the next species
    figurename = statfile.split(
        '.dat')[0] + '_' + atom + '-clusters_' + variable
    #*****************************
    #*******************
    #*******
    #Same as before but for the second file if it exists
    if statfile2 != '':
        with open(statfile2, 'r') as f2:
            line = f2.readline()
            entry = line.split()
            files = entry[1:]
            #creation of the x data list
            for file in files:
                temperature, acell = split_name(file)
                xdata2['rho'].append(
                    MN /
                    (Na * float(acell)**3 * 10**(-24)))  #calculation density
                xdata2['T'].append(int(temperature))
                xdata2['P'].append(TP[file.split('/')[-1]][1])
        with open(statfile2, 'r') as f2:
            #creation of the y data list and plot for each cluster
            while True:
                line = f2.readline()
                if not line: break
                else:
                    entry = line.split('\n')[0].split('\t')
                    if len(entry) > 1:
                        if entry[0][:len(atom)] == atom:
                            for i in range(
                                    1,
                                    len(entry)):  #we loop over all the files
                                if entry[i] == '':
                                    entry[i] = 0
                                data2.append(float(entry[i]))
                            #now the data array is filled, we plot the line for this species
                            x2, y2 = zip(*sorted(zip(xdata2[variable], data2)))
                            line, = ax2.plot(
                                x2,
                                y2,
                                '.--',
                                color=colors_species[entry[0]],
                                markersize=plot_parameters["size_markers"],
                                linewidth=plot_parameters["size_lines"])
                            #if variable == 'T':
                            #    label_line(ax2, line, entry[0], halign='right')
                            #elif list_species.index(entry[0]) < int(len(list_species)/2):
                            #    label_line(ax2, line, entry[0], halign='left')
                            #else:
                            #    label_line(ax2, line, entry[0], halign='right')
                            #and we plot the name of the species near the max of the curve
                            if max(data2) > 0.05:
                                x2_max = xdata2[variable][data2.index(
                                    max(data2))]
                                if x2_max > ax2range[0] and x2_max < ax2range[
                                        1]:
                                    y2_max = max(data2)
                                    label2 = entry[0]
                                    #**** formatage of label with removing _1
                                    label2 = format1label(label2)
                                    ax2.text(
                                        x2_max,
                                        y2_max,
                                        label2,
                                        color='0.35',
                                        fontsize=plot_parameters['size_fonts'])

                            data2 = [
                            ]  #reinitialization of data array for the next species

        figurename = statfile.split('/')[-1].split(
            '.dat')[0] + '+' + statfile2.split('/')[-1].split(
                '.dat')[0] + '_' + atom + '-clusters_' + variable
    #********* Legend
    #* formatage of label with removing _1
    for j in range(len(list_species)):
        if list_species[j] != '':
            list_species[j] = format1label(list_species[j])
    custom_lines = [
        Line2D([0], [0],
               color=colors_species[key],
               ls='--',
               marker='.',
               markersize=plot_parameters["size_markers"],
               linewidth=plot_parameters["size_lines"])
        for key in natsort.natsorted(colors_species)
    ]
    legend = plt.legend([line for line in custom_lines],
                        [label for label in natsort.natsorted(list_species)],
                        title='$\\bf{Polyhedra}$',
                        bbox_to_anchor=(1.05, 1),
                        loc=2,
                        fontsize=plot_parameters["size_fonts"],
                        borderaxespad=0.)
    plt.setp(legend.get_title(), fontsize=plot_parameters["size_fonts"])

    figurename = figurename + '.pdf'
    print(figurename, 'is created')
    plt.savefig(figurename, bbox_inches='tight', dpi=150)
def main(argv):
    """     ********* Main program *********     """
    thermofile = ''  #file for thermo values
    ground_state_file = ''  #file for ground_state
    #extracted and created data dictionnaries
    rho = {}
    E = {}
    P = {}
    stdev_P = {}
    ground_state = {}
    hugoniot = {}
    #impact values
    impactor_velocities = [12.9, 15.2, 18.1, 8.3, 11.5,
                           15.2]  #in km/s, see bibliography excel file
    impactor_density = 3000  #kg/m3
    #figure dictionnary
    colors_T = {
        'T2': '#800080',
        'T3': '#297fff',
        'T4': '#00ff00',
        'T4.5': '#bae200',
        'T5': '#ffcd01',
        'T5.5': '#ff6e00',
        'T6': '#ff0101',
        'T6.5': '#ff00a2',
        'T7': '#ff01de',
        'T7.5': '#ffa6f4',
        'T10': '#ffe86e',
        'T15': '#ffbf90',
        'T20': '#ff7788'
    }
    #other parameters
    Na = 6.022 * 10**23
    eVtoJ = 1.6e-19  #1eV = 1.6e-19 J
    kb = 1.38064852e-23  #boltzmann constant
    try:
        options, arg = getopt.getopt(argv, "hf:g:t:",
                                     ["filename", "groundstate"])
    except getopt.GetoptError:
        print(
            "analyze_Hugoniot.py -f <thermo_filename (from analyze fullaverage)> -t <type of the file: 'short' or 'all'> -g <ground-state_filename>"
        )
        sys.exit()
    for opt, arg in options:
        if opt == '-h':
            print('')
            print(
                'analyze_Hugoniot.py program to find the Hugoniot point from a thermo file and the ground state file associated'
            )
            print(
                "analyze_Hugoniot.py -f <thermo_filename (from analyze fullaverage)> -t <type of the file: 'short' or 'all'> -g <ground-state_filename>"
            )
            print('')
            print(
                'requires the .txt file with ground states condition: two lines of header,  a first column containing the density in kg/m3, a second column with the specific energy in J/kg, a third column with the pressure in Pa and a last column with the temperature in K'
            )
            print('')
            sys.exit()
        elif opt in ("-g", "--groundstate"):
            ground_state_file = str(arg)
        elif opt in ('-f', '--filename'):
            thermofile = str(arg)
        elif opt in ('-t', '--type'):
            filetype = str(arg)
    #selection of the column depending on the type of the thermo file
    if filetype == 'all':
        column_number = {'rho': 2, 'P': 5, 'T': 8, 'E': 14}
    else:
        column_number = {'rho': 2, 'P': 5, 'T': 8, 'E': 11}
    #************ Extraction of elements info and ground state data
    #**creation of elements and number lists and initialization of T
    with open(thermofile, 'r') as f:
        line = f.readline()
        print(line)
        entry = line.split()
        elements = entry[1:]
        line = f.readline()
        entry = line.split()
        number = entry[1:]
        f.readline()
        line = f.readline()
        entry = line.split()
        temperature0, acell0 = split_name(entry[0])
    #**calculation of M*N (in kg.part/mol) nedded for the calculation of densities and mass
    MN = 0
    ntot = 0
    for i in range(len(elements)):
        ntot = ntot + float(number[i])
        MN = MN + float(number[i]) * cr.Elements2rest(elements[i])[3] * 1E-3
    #extraction of ground-state data into a dictionnary
    with open(ground_state_file, 'r') as g:
        line = g.readline()
        line = g.readline()
        while True:
            line = g.readline()
            if not line: break
            else:
                entry = line.split()
                ground_state[int(entry[0])] = (
                    float(entry[1]), float(entry[2]), round(float(entry[3]))
                )  #key = density value in kg/m3, value = (energy/mass of the cell,pressure, temperature)
                hugoniot[int(entry[0])] = {
                }  #nested dictionnary of hugoniot equation for each T and each value of rho for ground state
    #************ Extraction of P-rho-E data
    with open(thermofile, 'r') as f:
        [f.readline() for i in range(3)]
        while True:
            line = f.readline()
            if not line: break
            else:
                entry = line.split()
                temperature, acell = split_name(entry[0])
                if acell <= '15.0':
                    try:
                        rho[temperature].append(
                            float(entry[column_number['rho']]) *
                            1000)  #calculation density in kg/m3
                        E[temperature].append(float(
                            entry[column_number['E']]))  #in eV/atom
                        P[temperature].append(float(
                            entry[column_number['P']]))  #in GPa
                        stdev_P[temperature].append(
                            convert_to_float(entry[column_number['P'] +
                                                   2]))  #in GPa
                    except KeyError:
                        rho[temperature] = [
                            float(entry[column_number['rho']]) * 1000
                        ]  #calculation density in kg/m3
                        E[temperature] = [float(entry[column_number['E']])
                                          ]  #in eV/atom
                        P[temperature] = [float(entry[column_number['P']])
                                          ]  #in GPa
                        stdev_P[temperature] = [
                            convert_to_float(entry[column_number['P'] + 2])
                        ]  #in GPa

    print("******")
    print("*********")
    print("************")
    print("****************")
    #*********** For each ground state we create the file with Hugoniot point and we fill it with data
    for density_gs in sorted(ground_state):
        print("******************************* For reference density",
              density_gs, 'kg/m3 and reference temperature',
              ground_state[density_gs][2], ' K')
        #creation of the file with hugoniot values and BM3 fit parameters
        nf = Hugoniot(thermofile, ground_state, density_gs,
                      impactor_velocities, impactor_density)
        #creation of the figure to see the  BM3 fit
        fig, ax = creation_plot(thermofile)
        #for each T,  calculation of Hugoniot values
        for temperature in natsort.natsorted(rho):
            print("************** For ", temperature)
            if temperature == 'T1.932' or temperature == 'T4.5' or temperature == 'T5.5' or temperature == 'T6.5' or temperature == 'T2' or temperature == 'T7':
                print("we skip this T")
                continue
            else:
                #calculation of Hugoniot density
                string = str(int(float(temperature.strip('T')) * 1000))
                hugoniot[temperature] = []
                previous_len = len(string)
                #we fill this array with data of the hugoniot equation
                for i in range(len(rho[temperature])):
                    Hg = E[temperature][
                        i] * eVtoJ * Na * ntot / MN - ground_state[density_gs][
                            0] + 0.5 * (P[temperature][i] * 1E9 +
                                        ground_state[density_gs][1]) * (
                                            1 / rho[temperature][i] -
                                            1 / density_gs)
                    hugoniot[temperature].append(Hg)
                    print(i, int(round(rho[temperature][i], 0)), Hg, i - 1,
                          int(round(rho[temperature][i - 1], 0)),
                          hugoniot[temperature][i - 1])
                    #and we compute the value of the rho for which Hg = 0
                    if np.sign(Hg) != np.sign(hugoniot[temperature][i - 1]):
                        #print('change of sign --> we use the straight line between these 2 points to find the rho for which Hg = 0')
                        #print('the equation of such a line is Hg = (Hg[i]-Hg[i-1])/(rho[i]-rho[i-1]) * rho + Hg[i] - (Hg[i]-Hg[i-1])/(rho[i]-rho[i-1]) * rho[i]')
                        #print('Hg = 0 for rho = rho[i] - Hg[i]/( (Hg[i]-Hg[i-1])/(rho[i]-rho[i-1]) ) ')
                        rho0 = rho[temperature][i] - hugoniot[temperature][i] / (
                            (hugoniot[temperature][i] -
                             hugoniot[temperature][i - 1]) /
                            (rho[temperature][i] - rho[temperature][i - 1]))
                        print('change of sign --> rho0 =', rho0)
                        #******We fit a BM3 to this isotherm in order to find the correct pressure corresponding to the Hugoniot density
                        if len(rho[temperature]) >= 4:
                            #Fit of the equation and calculation of the corresponding chi2
                            m0 = {
                                'T3': [2600, 15, 4],
                                'T4': [2600, 15, 4],
                                'T5': [2600, 15, 4],
                                'T6': [2600, 15, 4],
                                'T10': [2600, 15, 4],
                                'T15': [2600, 15, 4],
                                'T20': [2600, 15, 4]
                            }  #rho0 in kg/m3, K0 in GPa, Kp0
                            drho = 0.1
                            try:  #odr fit
                                eos_model_BM3 = odr.Model(
                                    BM3_P_rho)  # model for fitting
                                stdev_rho = [
                                    i / 1000 for i in rho[temperature]
                                ]  #creation of stdev for rho
                                data_for_ODR = odr.RealData(
                                    rho[temperature], P[temperature],
                                    stdev_rho, stdev_P[temperature]
                                )  # RealData object using our data
                                odr_process = odr.ODR(
                                    data_for_ODR,
                                    eos_model_BM3,
                                    beta0=m0[temperature],
                                    maxit=10000
                                )  # Set up orth-dist-reg with the model and data
                                odr_results = odr_process.run(
                                )  # run the regression
                                print('***************', temperature,
                                      "Fit of BM3")
                                odr_results.pprint(
                                )  # use the pprint method to display results
                                DensityX = np.arange(
                                    rho[temperature][-1] - drho,
                                    rho[temperature][0] + drho, drho)
                                ax.plot(DensityX,
                                        BM3_P_rho(odr_results.beta, DensityX),
                                        '-',
                                        color=colors_T[temperature],
                                        label=temperature + ' BM3 fit')
                                ax.plot(rho[temperature],
                                        P[temperature],
                                        'o',
                                        color=colors_T[temperature],
                                        label=temperature + ' data')
                                #print(str(temperature) + '\t' + str('{:1.2e}'.format(odr_results.res_var)) + '\t' + str('{:1.2e}'.format(odr_results.beta[0])) + '\t' + str('{:1.2e}'.format(odr_results.beta[1])) + '\t' + str('{:1.2e}'.format(odr_results.beta[2])) + '\t' + str('{:1.2e}'.format(odr_results.sd_beta[0])) + '\t' + str('{:1.2e}'.format(odr_results.sd_beta[1])) + '\t' + str('{:1.2e}'.format(odr_results.sd_beta[2]))  + '\n')
                                chi2 = chi2red(odr_results.beta,
                                               rho[temperature],
                                               P[temperature],
                                               stdev_P[temperature])
                                #print('residual variance',odr_results.res_var)
                                P0 = fonction_BM3(rho0, odr_results.beta[0],
                                                  odr_results.beta[1],
                                                  odr_results.beta[2])
                                string = string + '\t' + str(
                                    round(rho0)
                                ) + '\t' + str(round(P0, 2)) + '\t' + str(
                                    round(odr_results.beta[0])) + '\t' + str(
                                        round(odr_results.beta[1], 2)
                                    ) + '\t' + str(
                                        round(odr_results.beta[2],
                                              2)) + '\t' + str(round(chi2, 2))
                            #This is the theoretical model (initial guesses), based on common values
#                            m0=np.array([2600, 19, 6]) #rho0 in kg/m3, K0 in GPa, Kp0
#                            try:
#                                m, pcov = curve_fit(fonction_BM3, rho[temperature], P[temperature], p0=m0, sigma=stdev_P[temperature], absolute_sigma=False )
#                                chi2 = chi2red(m,rho[temperature],P[temperature],stdev_P[temperature])
#                                DensityX=np.arange(3200,6300,10)
#                                ax.plot(DensityX,fonction_BM3(DensityX,m[0],m[1],m[2]),'-', color=colors_T[temperature], label= temperature + ' BM3 fit')
#                                ax.plot(rho[temperature],P[temperature],'o', color=colors_T[temperature], label= temperature + ' data')
#                                print("Least-square fit of BM3")
#print('T, Chi2red, rho0(kg/m3), K0(GPa), Kp0(no-units)')
#print(temperature,chi2,m[0],m[1],m[2])
#                                P0 = fonction_BM3(rho0,m[0],m[1],m[2])
#                                string = string + '\t' + str(round(rho0)) + '\t' + str(round(P0,2)) + '\t' + str(round(m[0])) + '\t' + str(round(m[1],2)) + '\t' + str(round(m[2],2)) + '\t' + str(round(chi2,2))
#if least-square minimization fails
                            except RuntimeError:
                                try:
                                    popt, pcov = curve_fit(
                                        poly3,
                                        rho[temperature],
                                        P[temperature],
                                        p0=None,
                                        sigma=stdev_P[temperature],
                                        absolute_sigma=False)
                                    chi2 = chi2red_3(rho[temperature],
                                                     P[temperature],
                                                     stdev_P[temperature],
                                                     popt)
                                    DensityX = np.arange(3200, 6300, 10)
                                    ax.plot(DensityX,
                                            poly3(DensityX, *popt),
                                            '--',
                                            color=colors_T[temperature],
                                            label=temperature + ' poly3 fit')
                                    ax.plot(rho[temperature],
                                            P[temperature],
                                            'o',
                                            color=colors_T[temperature],
                                            label=temperature + ' data')
                                    print("Least-square fit of poly3")
                                    P0 = poly3(rho0, *popt)
                                    string = string + '\t' + str(
                                        round(rho0)) + '\t' + str(round(
                                            P0, 2)) + '\t-\t-\t-\t' + str(
                                                round(chi2, 2))
                                except RuntimeError:
                                    print("Fail of both BM3 a,nd poly3 fit")
                                    P0 = P[temperature][
                                        i] - hugoniot[temperature][i] / (
                                            (hugoniot[temperature][i] -
                                             hugoniot[temperature][i - 1]) /
                                            (P[temperature][i] -
                                             P[temperature][i - 1]))
                                    string = string + '\t' + str(
                                        round(rho0)) + '\t' + str(round(
                                            P0, 2)) + '\t-\t-\t-\t-'
                                    ax.plot(rho[temperature],
                                            P[temperature],
                                            'o',
                                            color=colors_T[temperature],
                                            label=temperature + ' data')
                        #if we don't have enough data, we find P using same method as for finding rho
                        else:
                            print("Not enough data for BM3 fit")
                            ax.plot(rho[temperature],
                                    P[temperature],
                                    'o',
                                    color=colors_T[temperature],
                                    label=temperature + ' data')
                            P0 = P[temperature][i] - hugoniot[temperature][i] / (
                                (hugoniot[temperature][i] -
                                 hugoniot[temperature][i - 1]) /
                                (P[temperature][i] - P[temperature][i - 1]))
                            string = string + '\t' + str(
                                round(rho0)) + '\t' + str(round(
                                    P0, 2)) + '\t-\t-\t-\t-'
                        #Calculation of E0 in J/kg (E hugoniot) using Hugoniot equation and rho,P Hugoniot
                        E0 = ground_state[density_gs][0] - 0.5 * (
                            P0 * 1E9 + ground_state[density_gs][1]) * (
                                1 / rho0 - 1 / density_gs)
                        string = string + '\t' + str(round(E0, 2))
                        #****** Calculation of particle velocities
                        Up = np.sqrt(
                            (P0 * 1E9 - ground_state[density_gs][1]) *
                            (rho0 - density_gs) / (rho0 * density_gs)) * 1E-3
                        string = string + '\t' + str(round(Up, 2))
                        for Uimp in impactor_velocities:
                            Up = -np.sqrt(
                                (rho0 - impactor_density) * P0 * 1E9 /
                                (rho0 * impactor_density)) * 1E-3 + Uimp
                            string = string + '\t' + str(round(Up, 2))
                        break
                if len(string) == previous_len:
                    print('Hg = 0 not found')
                    string = string + '\t-\t-\t-\t-\t-\t-\t-\t-\t-\t-\t-\t-\t-'

                nf.write(string + '\n')
        print('the file ', nf.name, ' is created')
        plt.legend(loc='best')
        figurename = 'BM3_fit_' + thermofile.split('/')[-1].split(
            '_')[1].split('.txt')[0] + '_rho' + str(density_gs) + 'T' + str(
                ground_state[density_gs][2]) + '.png'
        fig.savefig(figurename, bbox_inches='tight', dpi=150)
        print(figurename, ' is created')
예제 #21
0
def main(argv):
    """     ********* Main program *********     """
    #parameters for the figure for article
    plot_parameters = {"size_fonts" : 12,"size_font_ticks":10,"size_figure" : (4,4),
                       "size_markers" : 4,"size_lines" : 1,"shift_labelpad" : 10}
    #other dictionnaries and parameters for the figure
    style_markers = {'Ca':'','K':'','Na':'','Al':'x','Si':'*','O':''}
    style_lines = {'Ca':'--','K':'--','Na':'--','Al':'--','Si':'-','O':'-'}
    legend_labels = {}
    colors_T = {'T2':'#800080','T3':'#297fff','T4':'#00ff00','T4.5':'#bae200',
                'T5':'#ffcd01','T6':'#ff0101','T6.5':'#ff00a2','T7':'#ff01de'}
    filename = 'all'
    filename2 = ''
    atoms = 'all'
    xvariable = 'rho'
    #variables nedded fot the plot
    data = {} #dictionnary containing the data for each element, initialized for each T
    stdev = {} #same for stdev
    #other dictionnaries and parameters for the figure
    ions = []
    compounds = []
    Temperatures = []
    #other parameters
    Na=6.022*10**23
    #dictionnary for fullaverages file in full version
    column_number = {'rho':2,'P':5,'stdev_P':6,'err_P':7,'T':8,'stdev_T':9,'err_T':10,
                     'E':14,'stdev_E':15,'err_E':16,'Cvm_Nkb':23,'stdev_Cvm_Nkb':24,
                     'Cvm':25,'stdev_Cvm':26,'testCv':31,'stdev_testCv':32}
    try:
        options,arg = getopt.getopt(argv,"hf:g:a:v:",["filename","gfilename",'atoms','variable'])
    except getopt.GetoptError:
        print("plot_diffusion_allin1.py -f <filename>(default = all) -g <filename 2 (if we want to plot 2 files)> -a <atoms list, default = 'all'> -v <variable x axis (rho or P)> ")
        sys.exit()
    for opt,arg in options:
        if opt == '-h':
            print('')
            print('plot_diffusion_allin1.py program to plot diffusion coefficient as a function of density for each T and the selected minerals containing 4 elements')
            print("plot_diffusion_allin1.py -f <filename>(default = all files of every compound) -g <filename 2 (if we want to plot 2 files)>  -a <atoms list, default = 'all'> -v <variable x axis (rho or P)> ")
            print("plot_diffusion_allin1.py requires to be lauched from the folder containing every diffusivities file created by the script analyze_msd")
            print('')
            print('For plots as function of P, make sure the files from fullaverages.py are in the current folder')
            sys.exit()
        if opt in ('-f','--filename'):
            filename = str(arg)
        elif opt in ('-g','--gfilename'):
            filename2 = str(arg)
        elif opt in ('-a','--atoms'):
            atoms = str(arg)
        elif opt in ('-v','--variable'):
            xvariable = str(arg)
    if filename == 'all':
        fig,ax1,ax2,ax3, ax0 = creation_plot_3(plot_parameters,xvariable)
        print("axis are ax1",ax1,"ax2",ax2,"ax3",ax3,"ax0",ax0)
        files = sorted(glob.glob('diffusivities_*.txt'),reverse=True) #I list every diffusivities files
        figurename = 'diffusivities_all_'+atoms
    elif filename2 != '':
        fig,ax1,ax2, ax0 = creation_plot_2(plot_parameters,xvariable)
        print("axis are ax1",ax1,"ax2",ax2,"ax0",ax0)
        files = [filename, filename2] #we will plot 2 files
        figurename = filename.split('.txt')[0] +'_'+ filename2.split('.txt')[0].split('_')[1]+'_'+atoms
    else:
        fig, ax = creation_plot(plot_parameters,xvariable)
        files = [filename] #I take only the file we want
        figurename = filename.split('.txt')[0]+'_'+atoms
    #************ creation of arrays and plot at the same time
    for file in files:
        #********initialisations
        #**change of subplot
        if filename == 'all' or filename2 !='':
            if files.index(file) == 0:
                ax=ax1
                letter = 'a'
            if files.index(file) == 1:
                ax=ax2
                letter = 'b'
            if files.index(file) == 2:
                ax=ax3 
                letter = 'c'
            print("I plot on axis",ax)
        #**extraction compound
        compound = file.split('_')[1].split('.txt')[0]  
        compounds.append(format1label(compound))
        #******* Extract P and T for each thermo file
        if xvariable == 'P':
            TP = {}
            mineralname = file.split('_')[1].split('.txt')[0]
            thermofiles = sorted(glob.glob('thermo_'+mineralname+'*.txt'))
            for thermofile in thermofiles:
                TP = extract_TP(thermofile, column_number, TP,'')
            if TP == {}:
                print('ERROR!!!! TP dictionnary empty')
        #**creation of elements and number lists and initialization of T
        with open(file,'r') as f:
            skiplines = 0
            while True:
                line = f.readline()
                skiplines += 1
                entry=line.split()
                if entry[0] == 'elements':
                    elements = entry[1:]
                    ions.append(elements[0])
                elif entry[0] == 'number':
                    number = entry[1:]
                elif entry[0] == 'file':
                    line = f.readline()
                    entry=line.split()
                    temperature0, acell0 = split_name(entry[0])
                    break
        #**calculation of M*N nedded for the calculation of densities
        MN = 0
        for i in range(len(elements)):
            MN = MN + float(number[i]) * cr.Elements2rest(elements[i])[3]
        #**initialisation of data
        data = {} #big dictionnary with inside self diffusion coefficient or time of regime change, all coresponding to different T and atom pairs
        stdev = {} #idem for stdev
        X = {}  #idem for rho or P
        for i in range(len(elements)):
            elem = elements[i]
            stdev[elem] = {}
            data[elem] = {}
            X[elem] = {}
            #we store all the ions only once in ions list
            indicator = 0
            for j in range(len(ions)):
                if elements[i] == ions[j]:
                    indicator = 1
            if indicator == 0:
                ions.append(elements[i])
        #****** Extraction of data
        with open(file,'r') as f:
            [f.readline() for i in range(skiplines)]
            while True:
                line = f.readline()
                if not line: break
                else:
                    entry=line.split('\n')[0].split('\t')
                    temp, acell = split_name(entry[0]) 
                    for i in range(len(elements)): 
                        elem = elements[i]
                        try:
                            data[elem][temp].append(float(entry[i*6+1]))
                            stdev[elem][temp].append(float(entry[i*6+2]))    
                            if xvariable == 'P':
                                X[elem][temp].append(TP[entry[0].split('outcar.msd.dat')[0].split('/')[-1]][1])
                            else:
                                X[elem][temp].append( MN/(Na*float(acell)**3*10**(-24)) )    #calculation density
                        except KeyError:
                            data[elem][temp] = [ float(entry[i*6+1])]
                            stdev[elem][temp] = [ float(entry[i*6+2]) ]
                            if xvariable == 'P':
                                X[elem][temp] = [TP[entry[0].split('outcar.msd.dat')[0].split('/')[-1]][1]]
                            else:
                                X[elem][temp] = [ MN/(Na*float(acell)**3*10**(-24)) ]    #calculation density 
        #****** Selection of elements we plot
        if atoms != 'all':
            elements = atoms.split(',')
            print('now elements list is',elements)
        #****** Plot
        for elem in elements:
            for temperature in data[elem]:
                print("******** ", temperature)
                print(data[elem][temperature])
                Temperatures.append(temperature)
                ax.plot(X[elem][temperature],data[elem][temperature], 
                        style_markers[elem]+style_lines[elem], markersize = plot_parameters["size_markers"], 
                        color = colors_T[temperature], linewidth = plot_parameters["size_lines"])
        #ax.text(0.95,0.85, compound , transform=ax.transAxes, horizontalalignment = 'right', fontweight = 'bold', fontsize = plot_parameters["size_fonts"])
        if filename == 'all':
            ax.text(0.985,0.95, letter , transform=ax.transAxes, horizontalalignment = 'right',
                    fontweight = 'bold', fontsize = plot_parameters["size_fonts"], 
                    bbox=dict(facecolor='none', edgecolor='k', pad=3.0))
        elif filename2 != '':
            ax.text(0.985,0.95, letter , transform=ax.transAxes, horizontalalignment = 'right', 
                    fontweight = 'bold', fontsize = plot_parameters["size_fonts"], 
                    bbox=dict(facecolor='none', edgecolor='k', pad=3.0))      
    #****** Create legend from custom artist/label lists
    #********* Legend               
    #Create legend from custom artist/label lists
    Temperatures = list(set(Temperatures)) #get elements only once in the list
    custom_patch = [mpatches.Patch(color=colors_T[key]) for key in natsort.natsorted(Temperatures)]
    
    if atoms != 'all':
        ions = elements
    print(ions) 
    for ion in ions:
        legend_labels[ion] = plt.Line2D((0,1),(0,0), color='k', markersize = plot_parameters["size_markers"], 
                     marker=style_markers[ion], linestyle=style_lines[ion], linewidth = plot_parameters["size_lines"])
    s = [(k, legend_labels[k]) for k in sorted(legend_labels.keys(),reverse = False)]
    
    if filename == 'all':
        ax=ax0
        legend = ax0.legend([col for col in custom_patch],[str(int(float(label.strip('T'))*1000)) for label in natsort.natsorted(Temperatures)],title = '$\\bf{Temperature~(K)}$', bbox_to_anchor=(0.5, 1.12), loc="lower center", fontsize = plot_parameters["size_font_ticks"],  borderaxespad=0., ncol=len(Temperatures))    
        plt.setp(legend.get_title(),fontsize= plot_parameters["size_font_ticks"])
        plt.legend([v for k,v in s],[k for k,v in s], bbox_to_anchor=(0.5, 1), 
                   loc='lower center',fancybox=True, fontsize = plot_parameters["size_fonts"], ncol=len(style_lines))
        ax0.add_artist(legend)
    elif filename2 != '':
        ax=ax0
        legend = ax0.legend([col for col in custom_patch],[str(int(float(label.strip('T'))*1000)) for label in natsort.natsorted(Temperatures)],title = '$\\bf{Temperature~(K)}$', bbox_to_anchor=(0.5, 1.12), loc="lower center", fontsize = plot_parameters["size_font_ticks"],  borderaxespad=0., ncol=len(Temperatures))    
        plt.setp(legend.get_title(),fontsize= plot_parameters["size_font_ticks"])
        plt.legend([v for k,v in s],[k for k,v in s], bbox_to_anchor=(0.5, 1), 
                   loc='lower center',fancybox=True, fontsize = plot_parameters["size_fonts"], ncol=len(style_lines))
        ax0.add_artist(legend)
    figurename = figurename + '.pdf'
    print("figure saved with name ",figurename)
    fig.savefig(figurename, bbox_inches = 'tight', dpi = 300)