Visualizzazione post con etichetta xyz-hate. Mostra tutti i post
Visualizzazione post con etichetta xyz-hate. Mostra tutti i post

lunedì 29 agosto 2016

MethPlot Lib

Another fast line of code, so that I know where to look when I need it.
This time is MatplotLib, with LateX in the labels ;-)


import numpy as np
import pylab as pl
data = np.loadtxt('dijmsd5nm')
pl.rc('text', usetex=True)
pl.rc('font', family='serif')
pl.plot(data[:,0], data[:,1], 'ro')
pl.xlabel (r"$\displaystyle\sum_{n=1}^\infty 1$", fontsize= 12, color= 'black')
pl.ylabel(r'\textbf{time}(s)')

pl.show()




A little bit of explanation: in the folder where I use the Python script there are several data files, named something like "dijmsd5nm, dijmsd7_5nm, dijmsd10nm, dijmsd12_5nm, etc", where the underscore stands for the decimal point, since if I want to take these files in windows I am not allowed to have a point otherwise it can be seen as the beginning of the file extension.
If I don't do all the "re.sub" (the substituiting string characters in the file name) matplotlib plots the graphs as they come, i.e not in the good order 5nm->7.5nm->10nm->etc.
So I have to sort them first and then in the for loop that plots they are in order.

And here the refined super confusing version:


import numpy as np
import pylab as pl
import os
import itertools
import re

plotnum= 0
data=[]
dataname=[]
path= '.'
for i in os.listdir(path):
    if os.path.isfile and 'dij' in i:
        dataname.append(i)
        plotnum+=1
#sortthem!
for i in range(0,plotnum):
    for j in range(i,plotnum):
        nameI=re.sub("dijmsd","", dataname[i])
        nameI=re.sub("_", ".", nameI)
        nameI=float(re.sub("nm","",nameI))
        nameJ=re.sub("dijmsd","", dataname[j])
        nameJ=re.sub("_", ".", nameJ)
        nameJ=float(re.sub("nm","",nameJ))
        supp=dataname[i]
        if(nameJ<nameI):
            dataname[i]=dataname[j]
            dataname[j]=supp

for i in range(0,plotnum):
    data.append(np.loadtxt(dataname[i]))
marker = itertools.cycle(('o', '*', 'v', '^', '>', '<', 's', 'D'))

pl.figure(figsize=(8,6), dpi=180)

pl.rc('text', usetex=True)
pl.rc('font', family='serif')
for i in range(0,plotnum):
    name=re.sub("dijmsd","", dataname[i])
    name=re.sub("_", ".", name)
    pl.scatter(data[i][:,0], data[i][:,1],s=30, c=np.random.rand(3,), marker=next(marker), label=name)
pl.title(r"$\delta_{ij}^2$ per shell")
pl.xlabel (r"Shell")
pl.ylabel(r"$\delta_{ij}^2$ $\left[\r{A} ^2\right]$")
pl.xlim(0.,20.)
pl.ylim(0.02, 0.041)
pl.legend(loc="lower right")

pl.savefig("pictures/exercice_2.png", dpi=180)

pl.show()


lunedì 8 febbraio 2016

Skullbasher and Scriptbasher

Then comes the time when you need to use a program (PowDog) that takes as input only file with format .qpow and you only have the .xyz files.
Moreover this program wants as inline command the atom element. So you script something with bash that transforms .xyz into .qpow and then starts the program N times with different inline command each time.

Mission accomplished.


#!/bin/bash 


for f in *.xyz; do 

   awk '{t=$1; $1=$2; $2=$3; $3=$4; $4=t; print }' $f > $f.qpowd 
done 
for f in *.qpowd; do 
#the "${f%%-*}" only takes the first 2 characters of the file's name 
   ./powdog -i $f -F form.factor -e "${f%%-*}" 
done



martedì 2 febbraio 2016

I sing the parsing song

One simple format to store your atomic positions is .xyz format.
The file starts with a number (N) that tells how many atoms (and how many rows) will follow.
The remaining file is made of 4 columns with type of atom and 3 cordinates. An example is the following:

4

Pd 1 1 2.
Pd 3 1.4 1.
Pd 1 4.3 11
Pd 4 1.2 3.

Now, for every simulation or elaboration, i need to read these kind of files and, preferably, create 4 arrays one of strings and the other 3 of float.
The best thing would be to have a separate function outside the main, in order to call it when needed.
So the values must be passed by reference and not by value, using C pointers. 
The problems arise because of the clumsy way C handles strings, which basically are arrays of char.
Moreover, I do not expect the atom type to be a string of more than 5 characters, so what I need to do when passing by reference my array of strings (which is a Nx6 matrix of char) is to send a triple pointer to the function that is, actually, a double pointer to a string and everything blows up without a careful use of & and *.
Here's the result.
That's it.  It took time to get it so simply and now I am happy and I wanted to share this in order to avoid a lot of complications to those interested.



  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>


  4. void  parserxyz(char *fileneeded, double **atomx, double **atomy, double **atomz, char (**atomtype)[5], unsigned int *N)
  5. {
  6. FILE * fp;
  7. unsigned int i;
  8. fp = fopen(fileneeded, "r");
  9. if (fp == NULL) {
  10.  exit(EXIT_FAILURE);
  11. }
  12. fscanf(fp,"%u", N);
  13. *atomx = (double*) malloc(sizeof(double)*(*N));
  14. *atomy = (double*) malloc(sizeof(double)*(*N));
  15. *atomz = (double*) malloc(sizeof(double)*(*N));
  16. *atomtype= malloc(5*sizeof(char) * (*N));
  17. for (i=0; i<(*N); ++i)
  18. {
  19. fscanf(fp,"%s %lf %lf %lf", (*atomtype)[i],  &(*atomx)[i], &(*atomy)[i], &(*atomz)[i] ); 
  20. }

  21. fclose(fp);

  22. }