Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I am trying to populate the rows and columns of a table by using a rule replacment.

To generate a table that looks like this enter image description here

For example Sc would be row 1, column 1.

An example of a record looks like this

 rawData = Import["H:\\allresults.json"]


record = {19, 60, "Ag", "Ag", "19Ag@60Ag_npo: -186.503305 by solar<br> \
19Ag@60Ag_bnp: -180.812004 by solar<br> O_sng:-8.032213 by \
marco<br>", "-1.675194475", "Binding Energy", "solar"}

Then I extract the relevant entries with some functions (there is probably a more elegant way to to do this)

getRow[resultVector_] := resultVector[[3]];
getColumn[resultVector_] := resultVector[[4]];
getResult[resultVector_] := resultVector[[5]];
getResultType[resultVector_] := resultVector[[7]];

For example

getRow[record]

gives

Out[41] = Ag

I have a list of replacemnt rules

elementList = {"Sc" -> 1, "Ti" -> 2, "V" -> 3, "Cr" -> 4, "Mn" -> 5, 
  "Fe" -> 6, "Co" -> 7, "Ni" -> 8, "Cu" -> 9, "Zn" -> 10, "Y" -> 11, 
  "Zr" -> 12, "Nb" -> 13, "Mo" -> 14, "Tc" -> 15, "Ru" -> 16, 
  "Rh" -> 17, "Pd" -> 18, "Ag" -> 19, "Cd" -> 20, "Lu" -> 21, 
  "Hf" -> 22, "Ta" -> 23, "W" -> 24, "Re" -> 25, "Os" -> 26, 
  "Ir" -> 27, "Pt" -> 28, "Au" -> 29, "Hg" -> 30}

I would like to build a table where the location in the table gets identified, and the corresponding result gets put into that location of the table.

For example Ag, Ag (row, column) should put "-1.675194475" in location (19,19) (row, column) of a table.

Is there a better way to do this than with replacement rules?


Update:

Here is my current implementation to see all my data:

elementList = {"Sc" -> 1, "Ti" -> 2, "V" -> 3, "Cr" -> 4, "Mn" -> 5, 
 "Fe" -> 6, "Co" -> 7, "Ni" -> 8, "Cu" -> 9, "Zn" -> 10, "Y" -> 11, 
  "Zr" -> 12, "Nb" -> 13, "Mo" -> 14, "Tc" -> 15, "Ru" -> 16, 
  "Rh" -> 17, "Pd" -> 18, "Ag" -> 19, "Cd" -> 20, "Lu" -> 21, 
  "Hf" -> 22, "Ta" -> 23, "W" -> 24, "Re" -> 25, "Os" -> 26, 
  "Ir" -> 27, "Pt" -> 28, "Au" -> 29, "Hg" -> 30};

I create lists of data for different particle sizes and energy types

data = Import["H:\\allresults.json"];
atoms32 = Select[data, StringCases[#[[1]], "32"] != {} &];
atoms79 = Select[data, StringCases[#[[1]], "60"] != {} &];
atoms32Binding = 
  Select[atoms32, StringCases[#[[1]], "Binding"] != {} &];
atoms32Cohesive = 
  Select[atoms32, StringCases[#[[1]], "Cohesive"] != {} &] ;
atoms79Binding = 
  Select[atoms79, StringCases[#[[1]], "Binding"] != {} &];
atoms79Cohesive = 
  Select[atoms79, StringCases[#[[1]], "Cohesive"] != {} &];
mat = Outer[List, elements, elements];

Is there a more elegant way to do this? I intend to do more energy calculations of different types in the future (vacancy formation energy etc). Is it possible to write it such that the data is automatically partitioned out into lists for each size and type?

rules79Binding = 
  Cases[atoms79Binding, {__, "M1" -> e1_, "M2" -> e2_, __, 
     "result" -> val_, __} :> {e1, e2} -> 
     ToExpression@val, \[Infinity]];
rules79Cohesive = 
  Cases[atoms79Cohesive, {__, "M1" -> e1_, "M2" -> e2_, __, 
     "result" -> val_, __} :> {e1, e2} -> 
     ToExpression@val, \[Infinity]];
rules32Binding = 
  Cases[atoms32Binding, {__, "M1" -> e1_, "M2" -> e2_, __, 
     "result" -> val_, __} :> {e1, e2} -> 
     ToExpression@val, \[Infinity]];
rules32Cohesive = 
  Cases[atoms32Cohesive, {__, "M1" -> e1_, "M2" -> e2_, __, 
     "result" -> val_, __} :> {e1, e2} -> 
     ToExpression@val, \[Infinity]]; 

This also suffers from exactly the same repetitive line with the only thing that changes between the lines is the list.

Finally I plot all the data

ArrayPlot[mat /. rules79Binding /. {_, _} -> 0, 
 ColorFunction -> (Blend[{Blue, Red}, #] &), 
 ColorRules -> {0 -> White}, Mesh -> True, Frame -> True, 
 FrameTicks -> ({#, #} &@Transpose@{Range@Length@elements, elements}),
  PlotRangePadding -> None, ImageSize -> 500, 
 PlotLabel -> "19M1@60M2 Binding Energy"]
ArrayPlot[mat /. rules79Cohesive /. {_, _} -> 0, 
 ColorFunction -> (Blend[{Blue, Red}, #] &), 
 ColorRules -> {0 -> White}, Mesh -> True, Frame -> True, 
 FrameTicks -> ({#, #} &@Transpose@{Range@Length@elements, elements}),
  PlotRangePadding -> None, ImageSize -> 500, 
 PlotLabel -> "19M1@60M2 Cohesive Energy"]
ArrayPlot[mat /. rules32Binding /. {_, _} -> 0, 
 ColorFunction -> (Blend[{Blue, Red}, #] &), 
 ColorRules -> {0 -> White}, Mesh -> True, Frame -> True, 
 FrameTicks -> ({#, #} &@Transpose@{Range@Length@elements, elements}),
  PlotRangePadding -> None, ImageSize -> 500, 
 PlotLabel -> "6M1@32M2 Binding Energy"]
ArrayPlot[mat /. rules32Cohesive /. {_, _} -> 0, 
 ColorFunction -> (Blend[{Blue, Red}, #] &), 
 ColorRules -> {0 -> White}, Mesh -> True, Frame -> True, 
 FrameTicks -> ({#, #} &@Transpose@{Range@Length@elements, elements}),
  PlotRangePadding -> None, ImageSize -> 500, 
 PlotLabel -> "6M1@32M2 Cohesive Energy"]

I have not put pictures up of each plot so that I do not make the post too long.

Also, How can I map specific numerical values over color gradients. For example, for the binding energies, {-1,-2} blends through green. {-2,-3} blends through yellow {-3,-5}, blends through orange, {-5, -10} blends through red, and {-10, infinity} is black.

share|improve this question
    
Your record needs an extra {. I couldn't add it as I can only edit with a minimum of 6 characters. –  Jonathan Shock May 3 '13 at 5:40
    
Your problem might be more tractable if you do a proper Import[] of your source data. Can you maybe give at least an example file we can pull data from? –  J. M. May 3 '13 at 5:41
    
Can you also explain what the problem with using the replacement is? Is it taking too long this way or is it not doing something that you would otherwise like it to do? –  Jonathan Shock May 3 '13 at 5:42
    
Here is a link to the data. It is in JSON format. docs.google.com/file/d/0B5gGZ4-SD7-Zb1Q2ZUtUUmJXNHc/… –  olliepower May 3 '13 at 5:46
    
@JonathanShock I don't know how to do the rule replacement. The table shown is on the web. and my link has the data that generated it. I want to load the data into a table to both reproduce the chart, and to be able to perform calculations on the data. Like make plots of the values across a row for example. –  olliepower May 3 '13 at 5:50

2 Answers 2

up vote 5 down vote accepted

The following will take all of the data that you want from the json file and give you a Table that you can use as you wish. Is this what was wanted?

elementList = {"Sc" -> 1, "Ti" -> 2, "V" -> 3, "Cr" -> 4, "Mn" -> 5, 
"Fe" -> 6, "Co" -> 7, "Ni" -> 8, "Cu" -> 9, "Zn" -> 10, "Y" -> 11, 
"Zr" -> 12, "Nb" -> 13, "Mo" -> 14, "Tc" -> 15, "Ru" -> 16, 
"Rh" -> 17, "Pd" -> 18, "Ag" -> 19, "Cd" -> 20, "Lu" -> 21, 
"Hf" -> 22, "Ta" -> 23, "W" -> 24, "Re" -> 25, "Os" -> 26, 
"Ir" -> 27, "Pt" -> 28, "Au" -> 29, "Hg" -> 30};

Import the data

data = Import["directory/allresults.json"];

Take only the data which includes the binding energy results.

binding = Select[data, StringCases[#[[1]], "Binding"] != {} &];

Take this data and take the elements which correspond to the x and y axes in the figure (ie. the two elements) along with the result (which has to be converted to an Expression rather than a String

dataall = {#[[1]], #[[2]], 
  ToExpression[#[[3]]]} & /@ ({"M1", "M2", "result"} /. #[[2]] & /@
    binding) /. elementList;

This should be the table you are looking for (or at least a list of the data you want).

Edit:

In response to the comment, you can populate a table in the way that you want with:

tab=Table[Cases[dataall,{m,n,_}][[;; , 3]],{m,1,30},{n,1,30}] // MatrixForm

However, you should note that there are sometimes two entries for a single combination of elements.

If you want the elements only at the end of the file (as requested in the comment) you can call:

Table[
  With[{x = Cases[dataall, {m, n, _}][[;; , 3]]}, 
    If[x === {}, 0, x[[-1]]]], 
  {m, 1, 30}, {n, 1, 30}] // MatrixForm
share|improve this answer
    
If it is possible, can the data be ordered such that dataall[[19]][[19]] would give -172.687486 ? –  olliepower May 3 '13 at 6:27
    
@olliepower, there are two problems. One is that that appears to be the cohesive energy, the other is that there are two entries for binding energy (and also two for cohesive energy) for (for instance) Ag, Ag. I have however added this as an edit to the answer. –  Jonathan Shock May 3 '13 at 6:33
    
I see. I just noticed you edited your answer. If there are two entries it should take the entry closest to the end of the data file. . I am editing my above comment to read for the binding energy. –  olliepower May 3 '13 at 6:37
    
That is now implemented as well. –  Jonathan Shock May 3 '13 at 6:39

I prefer a slightly different approach to Jonathan's, and I believe it is simpler and more in line with the spirit of using rule replacements for getting things done. First, note that since you're dealing with elements in the periodic table, which are finite and small in number (and pairs of those), you can easily generate your matrix of pairs of elements and apply rules to those. So, taking the list of elements and the data (where elementList is from the question),

elements = List @@@ elementList // Transpose // First;
mat = Outer[List, elements, elements];

you can construct the replacement rules from the JSON structure as

data = Import["~/Downloads/Chrome/allresults.json"];
rules = Cases[data, {__, "M1" -> e1_, "M2" -> e2_, __, "result" -> val_, __} :> 
    {e1, e2} -> ToExpression@val, ∞];

and simply use rules to replace the matrix entries and display the result:

ArrayPlot[
    mat /. rules /. {_, _} -> 0,
    ColorFunction -> (Blend[{Blue, Red}, #] &), 
    ColorRules -> {0 -> White}, Mesh -> True, Frame -> True,
    FrameTicks -> ({#, #} &@Transpose@{Range@Length@elements, elements}),
    PlotRangePadding -> None, ImageSize -> 500
]

enter image description here

share|improve this answer
    
I get errors when i tried to use your code. `Outer::normal: Nonatomic expression expected at position 2 in Outer[List,element,element]. >>' Outer::normal: Nonatomic expression expected at position 2 in Outer[List,element,element]. >> Outer::normal: Nonatomic expression expected at position 2 in Outer[List,element,element]. >> –  olliepower May 3 '13 at 7:03
    
I will trouble shoot in the morning. I must go to sleep. –  olliepower May 3 '13 at 7:11
    
@olliepower I don't get that error. You must not have defined element as I've done it. –  rm -rf May 5 '13 at 4:12
    
where you define element I defined elementList exactly as I did above, and I have copy pasted your code. I really like the fancy table it made! –  olliepower May 5 '13 at 5:33
    
@olliepower So does it work now or do you still get an error? –  rm -rf May 5 '13 at 8:40

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.