Putting link references to lines of code in a source block

| categories: org-mode | tags:

I keep forgetting about this interesting gem of a feature in org-mode code blocks. You can put references to specific lines of code outside the block! http://orgmode.org/manual/Literal-examples.html#Literal-examples

The following code block has some references in it that we can refer to later:

#+BEGIN_SRC emacs-lisp -n -r
(save-excursion (sc)
  (goto-char (point-min))) (jump)
#+END_SRC
1: (save-excursion
2:   (goto-char (point-min)))

In line

(sc)
we remember the current position.
(jump)
jumps to point-min.

To make this work with python we have to make a slight change to the reference format in the header.

#+BEGIN_SRC python -n -r -l "#(ref:%s)"
for i in range(5):                # (for)
    print i                       # (body)
#+END_SRC
1: for i in range(5):
2:     print i
0
1
2
3
4

In line

(for)
we initialize the loop, and in line
(body)
we run it.

Copyright (C) 2014 by John Kitchin. See the License for information about copying.

org-mode source

Org-mode version = 8.2.5h

Discuss on Twitter

The sqlite variation of ase.db

| categories: ase, vasp | tags:

In a recent post we explored writing VASP calculations to an ase database in json format. Today we explore a similar idea, but writing to sqlite. I have incorporated the code from the previous post into a utils module in jasp.

from jasp.utils import *

print get_jasp_dirs('/home-research/jkitchin/research/rutile-atat')
['/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/0', '/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/1', '/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/10', '/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/11', '/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/12', '/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/13', '/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/14', '/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/15', '/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/16', '/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/17', '/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/2', '/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/3', '/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/4', '/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/5', '/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/59', '/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/6', '/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/66', '/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/7', '/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/73', '/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/74', '/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/78', '/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/8', '/home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/9']

That new function get_jasp_dirs just returns a list of directories that are known finished VASP calculations. We will use a functional style of programming to map a function onto each directory in that list.

from jasp import *
from jasp.utils import *

from ase.db import connect

# I want a sqlite extension, so we have to specify db as the type, which means sqlite
c = connect('vaspdb.sqlite', type='db')

dirs = get_jasp_dirs('/home-research/jkitchin/research/rutile-atat')

def write(directory):
    with jasp(directory) as calc:
        atoms = calc.get_atoms()
        calc.results['energy'] = atoms.get_potential_energy()
        calc.results['forces'] = atoms.get_forces()
    print c.write(atoms), directory

# functional approach to writing
map(write, dirs)
1 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/0
2 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/1
3 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/10
4 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/11
5 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/12
6 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/13
7 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/14
8 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/15
9 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/16
10 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/17
11 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/2
12 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/3
13 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/4
14 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/5
15 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/59
16 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/6
17 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/66
18 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/7
19 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/73
20 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/74
21 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/78
22 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/8
23 /home-research/jkitchin/research/rutile-atat/RuTi_O_rutile/9

Now, we have a sqlite database. Let us explore that a bit before using the python interface again.

1 Exploring the database with sqlite

First we see the tables.

.tables
keywords           species            text_key_values  
number_key_values  systems          

We can see details of the tables like this.

select * from sqlite_master;
table|systems|systems|2|CREATE TABLE systems (
    id integer primary key autoincrement,
    unique_id text unique,
    ctime real,
    mtime real,
    user text,
    numbers blob,
    positions blob,
    cell blob,
    pbc integer,
    initial_magmoms blob,
    initial_charges blob,
    masses blob,
    tags blob,
    momenta blob,
    constraints text,
    calculator text,
    calculator_parameters text,
    energy real,
    free_energy real,
    forces blob,
    stress blob,
    dipole blob,
    magmoms blob,
    magmom blob,
    charges blob,
    data text)
index|sqlite_autoindex_systems_1|systems|3|
table|sqlite_sequence|sqlite_sequence|4|CREATE TABLE sqlite_sequence(name,seq)
table|species|species|5|CREATE TABLE species (
    Z integer,
    n integer,
    id text,
    foreign key (id) references systems(id))
table|keywords|keywords|6|CREATE TABLE keywords (
    keyword text,
    id text,
    foreign key (id) references systems(id))
table|text_key_values|text_key_values|8|CREATE TABLE text_key_values (
    key text,
    value text,
    id text,
    foreign key (id) references systems(id))
table|number_key_values|number_key_values|10|CREATE TABLE number_key_values (
    key text,
    value real,
    id text,
    foreign key (id) references systems (id))
index|unique_id_index|systems|11|CREATE INDEX unique_id_index on systems(unique_id)
index|ctime_index|systems|12|CREATE INDEX ctime_index on systems(ctime)
index|user_index|systems|13|CREATE INDEX user_index on systems(user)
index|calculator_index|systems|14|CREATE INDEX calculator_index on systems(calculator)
index|species_index|species|15|CREATE INDEX species_index on species(Z)
index|keyword_index|keywords|16|CREATE INDEX keyword_index on keywords(keyword)
index|text_index|text_key_values|17|CREATE INDEX text_index on text_key_values(key)
index|number_index|number_key_values|18|CREATE INDEX number_index on number_key_values(key)

Let us see one entry from the systems table.

select * from systems where id=1;
id|unique_id|ctime|mtime|user|numbers|positions|cell|pbc|initial_magmoms|initial_charges|masses|tags|momenta|constraints|calculator|calculator_parameters|energy|free_energy|forces|stress|dipole|magmoms|magmom|charges|data
1|3ed58bb16897177be0ed56400c90b6f4|14.2361260035084|14.2361260035084|jkitchin|@|7|||||||vasp|{"incar": {"doc": "INCAR parameters", "nbands": 43, "sigma": 0.1, "prec": "high", "encut": 350.0}, "doc": "JSON representation of a VASP calculation.\n\nenergy is in eV\nforces are in eV/\\AA\nstress is in GPa (sxx, syy, szz,  syz, sxz, sxy)\nmagnetic moments are in Bohr-magneton\nThe density of states is reported with E_f at 0 eV.\nVolume is reported in \\AA^3\nCoordinates and cell parameters are reported in \\AA\n\nIf atom-projected dos are included they are in the form:\n{ados:{energy:data, {atom index: {orbital : dos}}}\n", "potcar": [["Ru", "potpaw_PBE/Ru/POTCAR", "dee616f2a1e7a5430bb588f1710bfea3001d54ea"], ["O", "potpaw_PBE/O/POTCAR", "9a0489b46120b0cad515d935f44b5fbe3a3b1dfa"]], "input": {"kpts": [6, 6, 10], "kpts_nintersections": null, "reciprocal": false, "setups": {}, "xc": "PBE", "txt": "-", "gamma": true}, "atoms": {"cell": [[4.526933343669885, 0.0, 0.0], [0.0, 4.526933343669885, 0.0], [0.0, 0.0, 3.095292162609941]], "symbols": ["O", "O", "O", "O", "Ru", "Ru"], "tags": [0, 0, 0, 0, 0, 0], "pbc": [true, true, true], "positions": [[1.3820537023391204, 1.3820537023391204, 0.0], [3.1448796413307645, 3.1448796413307645, 0.0], [3.645520374174063, 0.8814129694958222, 1.5476460813049704], [0.8814129694958222, 3.645520374174063, 1.5476460813049704], [0.0, 0.0, 0.0], [2.2634666718349425, 2.2634666718349425, 1.5476460813049704]]}, "data": {"stress": [0.0884313161515024, 0.0884313161515024, 0.06042693164307849, -0.0, -0.0, -0.0], "doc": "Data from the output of the calculation", "volume": 63.432210741434858, "total_energy": -44.251496, "forces": [[-0.023609, -0.023609, 0.0], [0.023609, 0.023609, 0.0], [-0.023609, 0.023609, 0.0], [0.023609, -0.023609, 0.0], [0.0, 0.0, 0.0], [0.0, 0.0, 0.0]], "fermi_level": 5.0374}, "metadata": {"date.created": 1395241327.477995, "uuid": "7081ee4a-af77-11e3-a6e6-003048f5e49e", "date.created.ascii": "Wed Mar 19 11:02:07 2014", "user.username": "jkitchin", "atoms.resort": [2, 3, 4, 5, 0, 1], "user.email": "jkitchin@andrew.cmu.edu", "user.fullname": "John Kitchin", "O.potential.git_hash": "9a0489b46120b0cad515d935f44b5fbe3a3b1dfa", "atoms.tags": [0, 0, 0, 0, 0, 0], "O.potential.path": "potpaw_PBE/O/POTCAR", "Ru.potential.path": "potpaw_PBE/Ru/POTCAR", "Ru.potential.git_hash": "dee616f2a1e7a5430bb588f1710bfea3001d54ea"}}|-44.251496||+|||||{"keywords": [], "data": {}, "key_value_pairs": {}}

How about the species table:

select * from species where id=1;
Z|n|id
8|4|1
44|2|1

Now we can find a calculation with two Ru and 4 oxygen atoms, but it takes some sqlite knowledge.

select sp1.id,sys.id 
from species as sp1 
inner join
species as sp2
on sp1.id = sp2.id
inner join systems as sys
on sp1.id=sys.id
where (sp1.Z=44 and sp1.n=2) and (sp2.Z=8 and sp2.n=4);
id|id
1|1

That is an expected result. Let us get back to the python interface.

2 The python interface to the ase-db

Let us search for entries containing 2 Ru atoms and 4 O atoms again. We know this should be the first entry from before. Note how much simpler this syntax is.

from ase.db import connect

# I want a sqlite extension, so we have to specify db as the type, which means sqlite
c = connect('vaspdb.sqlite', type='db')

for row in c.select('Ru=2,O=4'): print row
{'ctime': 14.236126003508412, 'energy': -44.251496, 'tags': array([0, 0, 0, 0, 0, 0], dtype=int32), 'positions': array([[ 1.3820537 ,  1.3820537 ,  0.        ],
       [ 3.14487964,  3.14487964,  0.        ],
       [ 3.64552037,  0.88141297,  1.54764608],
       [ 0.88141297,  3.64552037,  1.54764608],
       [ 0.        ,  0.        ,  0.        ],
       [ 2.26346667,  2.26346667,  1.54764608]]), 'calculator': u'vasp', 'calculator_parameters': {u'incar': {u'doc': u'INCAR parameters', u'prec': u'high', u'nbands': 43, u'sigma': 0.1, u'encut': 350.0}, u'doc': u'JSON representation of a VASP calculation.\n\nenergy is in eV\nforces are in eV/\\AA\nstress is in GPa (sxx, syy, szz,  syz, sxz, sxy)\nmagnetic moments are in Bohr-magneton\nThe density of states is reported with E_f at 0 eV.\nVolume is reported in \\AA^3\nCoordinates and cell parameters are reported in \\AA\n\nIf atom-projected dos are included they are in the form:\n{ados:{energy:data, {atom index: {orbital : dos}}}\n', u'potcar': [[u'Ru', u'potpaw_PBE/Ru/POTCAR', u'dee616f2a1e7a5430bb588f1710bfea3001d54ea'], [u'O', u'potpaw_PBE/O/POTCAR', u'9a0489b46120b0cad515d935f44b5fbe3a3b1dfa']], u'input': {u'kpts': array([ 6,  6, 10]), u'reciprocal': False, u'xc': u'PBE', u'kpts_nintersections': None, u'setups': {}, u'txt': u'-', u'gamma': True}, u'atoms': {u'cell': array([[ 4.52693334,  0.        ,  0.        ],
       [ 0.        ,  4.52693334,  0.        ],
       [ 0.        ,  0.        ,  3.09529216]]), u'symbols': [u'O', u'O', u'O', u'O', u'Ru', u'Ru'], u'tags': array([0, 0, 0, 0, 0, 0]), u'pbc': array([ True,  True,  True], dtype=bool), u'positions': array([[ 1.3820537 ,  1.3820537 ,  0.        ],
       [ 3.14487964,  3.14487964,  0.        ],
       [ 3.64552037,  0.88141297,  1.54764608],
       [ 0.88141297,  3.64552037,  1.54764608],
       [ 0.        ,  0.        ,  0.        ],
       [ 2.26346667,  2.26346667,  1.54764608]])}, u'data': {u'stress': array([ 0.08843132,  0.08843132,  0.06042693, -0.        , -0.        , -0.        ]), u'doc': u'Data from the output of the calculation', u'volume': 63.43221074143486, u'total_energy': -44.251496, u'forces': array([[-0.023609, -0.023609,  0.      ],
       [ 0.023609,  0.023609,  0.      ],
       [-0.023609,  0.023609,  0.      ],
       [ 0.023609, -0.023609,  0.      ],
       [ 0.      ,  0.      ,  0.      ],
       [ 0.      ,  0.      ,  0.      ]]), u'fermi_level': 5.0374}, u'metadata': {u'date.created': 1395241327.477995, u'uuid': u'7081ee4a-af77-11e3-a6e6-003048f5e49e', u'date.created.ascii': u'Wed Mar 19 11:02:07 2014', u'user.username': u'jkitchin', u'atoms.resort': array([2, 3, 4, 5, 0, 1]), u'user.email': u'jkitchin@andrew.cmu.edu', u'user.fullname': u'John Kitchin', u'O.potential.git_hash': u'9a0489b46120b0cad515d935f44b5fbe3a3b1dfa', u'atoms.tags': array([0, 0, 0, 0, 0, 0]), u'O.potential.path': u'potpaw_PBE/O/POTCAR', u'Ru.potential.path': u'potpaw_PBE/Ru/POTCAR', u'Ru.potential.git_hash': u'dee616f2a1e7a5430bb588f1710bfea3001d54ea'}}, 'cell': array([[ 4.52693334,  0.        ,  0.        ],
       [ 0.        ,  4.52693334,  0.        ],
       [ 0.        ,  0.        ,  3.09529216]]), 'numbers': array([ 8,  8,  8,  8, 44, 44], dtype=int32), 'forces': array([[-0.023609, -0.023609,  0.      ],
       [ 0.023609,  0.023609,  0.      ],
       [-0.023609,  0.023609,  0.      ],
       [ 0.023609, -0.023609,  0.      ],
       [ 0.      ,  0.      ,  0.      ],
       [ 0.      ,  0.      ,  0.      ]]), 'mtime': 14.236126003508412, 'pbc': array([ True,  True,  True], dtype=bool), 'id': 1, 'unique_id': u'3ed58bb16897177be0ed56400c90b6f4', 'user': u'jkitchin'}

3 Summary

It is not yet obvious what the advantage of the sqlite format over the json format is. One is that you can use SQL to create queries, which is probably more powerful than the ase-db format. It is a little mysterious how the ase-db searches the json format to me.

Copyright (C) 2014 by John Kitchin. See the License for information about copying.

org-mode source

Org-mode version = 8.2.5h

Discuss on Twitter

Finding the maximum power of a photovoltaic device.

| categories: optimization, python | tags:

A photovoltaic device is characterized by a current-voltage relationship. Let us say, for argument's sake, that the relationship is known and defined by

\(i = 0.5 - 0.5 * V^2\)

The voltage is highest when the current is equal to zero, but of course then you get no power. The current is highest when the voltage is zero, i.e. short-circuited, but there is again no power. We seek the highest power condition, which is to find the maximum of \(i V\). This is a constrained optimization. We solve it by creating an objective function that returns the negative of (\i V\), and then find the minimum.

First, let us examine the i-V relationship.

import matplotlib.pyplot as plt
import numpy as np

V = np.linspace(0, 1)

def i(V):
    return 0.5 - 0.5 * V**2

plt.figure()
plt.plot(V, i(V))
plt.savefig('images/iV.png')
<matplotlib.figure.Figure object at 0x11193ec18>
[<matplotlib.lines.Line2D object at 0x111d43668>]

Now, let us be sure there is a maximum in power.

import matplotlib.pyplot as plt
import numpy as np

V = np.linspace(0, 1)

def i(V):
    return 0.5 - 0.5 * V**2

plt.plot(V, i(V) * V)
plt.savefig('images/P1.png')
[<matplotlib.lines.Line2D object at 0x111d437f0>]

You can see in fact there is a maximum, near V=0.6. We could solve this problem analytically by taking the appropriate derivative and solving it for zero. That still might require solving a nonlinear problem though. We will directly setup and solve the constrained optimization.

from scipy.optimize import fmin_slsqp
import numpy as np
import matplotlib.pyplot as plt

def objective(X):
    i, V = X
    return - i * V

def eqc(X):
    'equality constraint'
    i, V = X
    return (0.5 - 0.5 * V**2) - i

X0 = [0.2, 0.6]
X = fmin_slsqp(objective, X0, eqcons=[eqc])

imax, Vmax = X


V = np.linspace(0, 1)

def i(V):
    return 0.5 - 0.5 * V**2

plt.plot(V, i(V), Vmax, imax, 'ro')
plt.savefig('images/P2.png')
Optimization terminated successfully.    (Exit mode 0)
            Current function value: -0.192450127337
            Iterations: 5
            Function evaluations: 20
            Gradient evaluations: 5
[<matplotlib.lines.Line2D object at 0x111946470>, <matplotlib.lines.Line2D object at 0x11192c518>]

You can see the maximum power is approximately 0.2 (unspecified units), at the conditions indicated by the red dot in the figure above.

Copyright (C) 2016 by John Kitchin. See the License for information about copying.

org-mode source

Org-mode version = 8.2.10

Discuss on Twitter

Popup tips on bibtex links in org-mode

| categories: uncategorized | tags:

I want to explore using popup tips to display richer information about org-mode links. The idea is to have something like a tooltip that displays the bibtex entry when you hover over it, or click on it.

https://github.com/auto-complete/popup-el/blob/master/popup.el

Here is a canonical example of a popup.

(popup-tip "Hello, World!")
t

All I need to do is figure out a simple way to get the bibtex entry as a string, and pop it up when a link is clicked on.

(org-add-link-type
 "test"
 ;; this function is run when you click
 (lambda (link-string) 
   (popup-tip link-string))
 ;; formatting
(lambda (keyword desc format)
   (cond
    ((eq format 'html) (format "<pre>%s:%s</pre>" keyword desc)))))
lambda (link-string) (popup-tip link-string)
lambda (keyword desc format) (cond ((eq format (quote html)) (format <pre>%s:%s</pre> keyword desc)))

Now we give it a try.

test:show-me-the-popup

That looks good.

Ok, the penultimate step will be to lookup a bibtex entry, and show the entry in a popup. We will hardcode the path to the bibtex file.

(org-add-link-type
 "test"
 ;; this function is run when you click
 (lambda (bibtex-key)
   (let ((entry (with-temp-buffer
                  (insert-file-contents "~/Dropbox/bibliography/references.bib")
                  (goto-char (point-min))
                  (re-search-forward bibtex-key)
                  (bibtex-narrow-to-entry)
                  (buffer-string))))
     (popup-tip entry))))
lambda (bibtex-key) (let ((cb (current-buffer)) (entry (with-temp-buffer (insert-file-contents ~/Dropbox/bibliography/references.bib) (goto-char (point-min)) (re-search-forward bibtex-key) (bibtex-narrow-to-entry) (buffer-string)))) (popup-tip entry))

test:mehta-2014-ident-poten

And here is what appears for me:

The final step is to connect this to an idle timer . We want a popup to occur when our mouse is idle. I am setting this up to run one time, after 5 seconds of idleness.

(run-with-idle-timer 5 nil (lambda () (popup-tip "You are being idle")))
[nil 0 5 0 nil (lambda nil (popup-tip "You are being idle")) nil idle 0]

So, we need to setup an idle timer that runs on some interval. When the cursor is on the right kind of link, we want to get a popup. I adapted the following code from http://www.emacswiki.org/emacs/IdleTimers .

;; variable for the timer object
(defvar idle-timer-bibtex-timer nil)

;; callback function 
(defun idle-timer-bibtex-callback ()
  "displays a popup of the bibtex entry in a test link"
  (interactive)
  (let ((object (org-element-context)))    
    (when (and (equal (org-element-type object) 'link) 
               (equal (org-element-property :type object) "test"))
      (let* ((bibtex-key (org-element-property :path object))
             (entry (with-temp-buffer
                      (insert-file-contents "~/Dropbox/bibliography/references.bib")
                      (goto-char (point-min))
                      (re-search-forward bibtex-key)
                      (bibtex-narrow-to-entry)
                      (buffer-string))))
        (popup-tip entry)))))

;; start functions
(defun idle-timer-bibtex-start ()
  (interactive)
  (when (timerp idle-timer-bibtex-timer)
    (cancel-timer idle-timer-bibtex-timer))
  (setq idle-timer-bibtex-timer
          (run-with-timer 1 1 #'idle-timer-bibtex-callback)))

;; stop function
(defun idle-timer-bibtex-stop ()
  (interactive)
  (when (timerp idle-timer-bibtex-timer)
    (cancel-timer idle-timer-bibtex-timer))
  (setq idle-timer-bibtex-timer nil))

(idle-timer-bibtex-start)
idle-timer-bibtex-stop

test:kitchin-2008-alloy

Now, whenever the cursor is on the link, and there is an idle of about a sec, I get a popup window of the bibtex entry. It looks like this:

There are still some limitations to this code. It does not handle multiple citations in a link (like the cite links I normally use do). That will take a little work to fixup. I cannot figure out how to get mouse-over tooltips; this only works when the cursor is on the link. I do not know what the optimal timer setting is. This one runs every second. I do not see any issues in performance with that. Another issue might be making the timer a file local variable. It would be nice if the timer quit running when the file was closed. I do not know how easy that would be to implement, or if there should be one timer running for org-mode. Finally, this code is hard-coded to use my reference file. For a real module, we would probably provide some customization to choose other bibtex files. Overall though, this might be a handy way to quickly peruse the citations in an org-file.

Copyright (C) 2014 by John Kitchin. See the License for information about copying.

org-mode source

Org-mode version = 8.2.5h

Discuss on Twitter

Multiple search criteria to find bibtex entries

| categories: bibtex | tags:

I have been thinking about ways to search my bibtex file with multiple criteria. Eventually, I want a decent natural language search like "au=kitchin and alloy" to find papers authored by me about alloys. For now, I am going to settle with a way to find these. This strategy will create a search function that prints the entries that are found. Here is the prototype idea:

(defun my-search (key start end)
  (when (and (re-search-forward "kitchin" end t)
           (re-search-forward "alloy" end t))
      (princ (format "%s\n" (buffer-substring start end)))))

(with-temp-buffer
  (insert-file-contents "../../bibliography/references.bib")
  (bibtex-map-entries  'my-search))
@ARTICLE{inoglu-2011-ident-sulfur,
  pdf =		 {[[file:bibtex-pdfs/inoglu-2011-ident-sulfur.pdf]]},
  org-notes =
                  {[[file:~/Dropbox/bibliography/notes.org::inoglu-2011-ident-sulfur]]},
  author =	 {Inoglu, Nilay and Kitchin, John R.},
  title =	 {Identification of Sulfur-Tolerant Bimetallic
                  Surfaces Using {DFT} Parametrized Models and
                  Atomistic Thermodynamics},
  journal =	 {ACS Catalysis},
  year =	 2011,
  pages =	 {399--407},
  abstract =	 {The identification of sulfur-tolerant alloys for
                  catalytic applications is difficult due to the
                  combinatorially large number of alloy compositions
                  and surface structures that may be
                  considered. Density functional theory calculations
                  (DFT) are not fast enough to enumerate all the
                  possible structures and their sulfur tolerance. In
                  this work, a DFT parametrized algebraic model that
                  accounts for structure and composition was used to
                  estimate the d-band properties and sulfur adsorption
                  energies of 370 transition metal-based bimetallic
                  alloy surfaces.  The estimated properties were
                  validated by DFT calculations for 110 of the surface
                  structures. We then utilized an atomistic
                  thermodynamic framework that includes surface
                  segregation, the presence of adsorbates, and effects
                  of environmental conditions to identify alloy
                  compositions and structures with enhanced sulfur
                  tolerance that are likely to be stable under the
                  environmental conditions. As a case study, we show
                  how this database can be used to identify
                  sulfur-tolerant Cu-based catalysts and compare the
                  results with what is known about these catalysts
                  experimentally.},
  doi =		 {10.1021/cs200039t},
  issn =	 {null},
  type =	 {Journal Article}
}
@ARTICLE{kitchin-2008-alloy,
  pdf =		 {[[file:bibtex-pdfs/kitchin-2008-alloy.pdf]]},
  org-notes =
                  {[[file:~/Dropbox/bibliography/notes.org::kitchin-2008-alloy]]},
  author =	 {Kitchin, J. R. and Reuter, K. and Scheffler, M.},
  title =	 {Alloy surface segregation in reactive environments:
                  First-principles atomistic thermodynamics study of
                  \ce{Ag_3Pd}(111) in oxygen atmospheres},
  journal =	 {Physical Review B},
  year =	 2008,
  volume =	 77,
  number =	 7,
  abstract =	 {We present a first-principles atomistic
                  thermodynamics framework to describe the structure,
                  composition, and segregation profile of an alloy
                  surface in contact with a (reactive)
                  environment. The method is illustrated with the
                  application to a Ag3Pd(111) surface in an oxygen
                  atmosphere, and we analyze trends in segregation,
                  adsorption, and surface free energies. We observe a
                  wide range of oxygen adsorption energies on the
                  various alloy surface configurations, including
                  binding that is stronger than on a Pd(111) surface
                  and weaker than that on a Ag(111) surface. This and
                  the consideration of even small amounts of
                  nonstoichiometries in the ordered bulk alloy are
                  found to be crucial to accurately model the Pd
                  surface segregation occurring in increasingly O-rich
                  gas phases.},
  doi =		 {https://doi.org/10.1103/PhysRevB.77.075437},
  pages =	 075437,
  issn =	 {1098-0121},
  type =	 {Journal Article}
}
@ARTICLE{tierney-2009-hydrog-dissoc,
  pdf =		 {[[file:bibtex-pdfs/tierney-2009-hydrog-dissoc.pdf]]},
  org-notes =
                  {[[file:~/Dropbox/bibliography/notes.org::tierney-2009-hydrog-dissoc]]},
  author =	 {Tierney, H. L. and Baber, A. E. and Kitchin,
                  J. R. and Sykes, E.  C. H.},
  title =	 {Hydrogen Dissociation and Spillover on Individual
                  Isolated Palladium Atoms},
  journal =	 {Physical Review Letters},
  year =	 2009,
  volume =	 103,
  number =	 24,
  abstract =	 {Using a combination of low-temperature scanning
                  tunneling microscopy and density functional theory
                  it is demonstrated how the nature of an inert host
                  metal of an alloy can affect the thermodynamics and
                  kinetics of a reaction pathway in a much more
                  profound way than simply a dilution, electronic, or
                  geometric effect. This study reveals that
                  individual, isolated Pd atoms can promote H-2
                  dissociation and spillover onto a Cu(111) surface,
                  but that the same mechanism is not observed for an
                  identical array of Pd atoms in Au(111).},
  pages =	 246102,
  doi =		 {10.1103/PhysRevLett.103.246102},
  issn =	 {0031-9007},
  url =		 {http://prl.aps.org/abstract/PRL/v103/i24/e246102},
  type =	 {Journal Article}
}

That is not too bad. If I had a parser like this one , I could do some reasonable searches. I could try integrating it with reftex or something similar for selecting citations. I would like that a lot.

What if I wanted to find articles with Kitchin as an author, and alloy in the title? This is my best effort at doing that, where I explicitly match the fields in the bibtex entries.

(find-file "~/Dropbox/bibliography/references.bib")
(bibtex-map-entries (lambda (bibtex-key start end)
                      (let* ((entry (bibtex-parse-entry))
                             (title (cdr (assoc "title" entry)))
                             (authors (cdr (assoc "author" entry))))
                        (when (and title (string-match "alloy" title)
                                   authors (string-match "kitchin" authors))
                          (princ (buffer-substring start end)))))))
@ARTICLE{kitchin-2008-alloy,
  pdf =		 {[[file:bibtex-pdfs/kitchin-2008-alloy.pdf]]},
  org-notes =
                  {[[file:~/Dropbox/bibliography/notes.org::kitchin-2008-alloy]]},
  author =	 {Kitchin, J. R. and Reuter, K. and Scheffler, M.},
  title =	 {Alloy surface segregation in reactive environments:
                  First-principles atomistic thermodynamics study of
                  \ce{Ag_3Pd}(111) in oxygen atmospheres},
  journal =	 {Physical Review B},
  year =	 2008,
  volume =	 77,
  number =	 7,
  abstract =	 {We present a first-principles atomistic
                  thermodynamics framework to describe the structure,
                  composition, and segregation profile of an alloy
                  surface in contact with a (reactive)
                  environment. The method is illustrated with the
                  application to a Ag3Pd(111) surface in an oxygen
                  atmosphere, and we analyze trends in segregation,
                  adsorption, and surface free energies. We observe a
                  wide range of oxygen adsorption energies on the
                  various alloy surface configurations, including
                  binding that is stronger than on a Pd(111) surface
                  and weaker than that on a Ag(111) surface. This and
                  the consideration of even small amounts of
                  nonstoichiometries in the ordered bulk alloy are
                  found to be crucial to accurately model the Pd
                  surface segregation occurring in increasingly O-rich
                  gas phases.},
  doi =		 {https://doi.org/10.1103/PhysRevB.77.075437},
  pages =	 075437,
  issn =	 {1098-0121},
  type =	 {Journal Article}
}

This is a more precise search, which yields only one entry. That is not exactly nimble searching, but it does provide precision. I need to think about this some more.

Copyright (C) 2014 by John Kitchin. See the License for information about copying.

org-mode source

Org-mode version = 8.2.5h

Discuss on Twitter
« Previous Page -- Next Page »