I have csv catalogue(s) of earthquakes occurring in time and xyz space that can be individually represented as cubes or spheres of differing sizes depending on the earthquake magnitude. I have little experience on Blender/Python and am wondering whether I can learn enough of these subjects in a few days to create a nice 3D visualization of my various date,x,y,z,m, and maybe some other attributes. The appearance of the earthquakes might be additionally accompanied by some sound. No physics required. The earthquakes are in local areas so no spherical surfaces required. I have been attempting to do these displays using two different programs as shown following, but Blender would be vastly better. I am stalled here: existing script I have been able to find for csv import appears to be limited to 3 variables
2 Answers
The good thing about comma separated values files is that they are pretty easy to read if they don't contain errors. The amount of Python you need to learn isn't too much.
I made this example file and saved it next to my blendfile:
number,long,lat,mag
1,37.9230,18.1445,3.5
2,47.1948,23.1326,0.1
3,40.9674,16.6782,1.5
4,45.1434,23.3850,4.2
5,39.4629,21.7380,1.4
6,34.7125,16.9653,5.3
7,34.3573,17.9092,3.3
8,40.9570,24.7064,4.4
9,34.9255,17.1371,3.4
10,45.9753,20.9662,0.7
11,31.0126,20.1624,3.4
12,47.6929,20.7224,5.6
My script is not elegant at all. I focused on it being readable. It can be done much shorter and prettier but not everybody is an experienced coder.
The script imports the csv file, separates it into lines and puts the values into a list.
From there it's not hard to let Blender generate circles or spheres with the right diameter and the right location.
Under Linux it's better to start Blender from a terminal. Otherwise you won't see what the script is printing. Under Windows, the System console can be toggled in the Window menu at the top.
import bpy
blendPath = bpy.path.abspath("//") # path to the blendfile because my .csv is in the same directory
fileName = "example.csv" # name of the csv
txt = open(blendPath + fileName, "r") # open the file to read
quakeTxt = txt.read() # read the entire file into a string
txt.close() # close the file
print(quakeTxt)
quakeLines = quakeTxt.split("\n") # split into a list divided by linebreaks
print(quakeLines)
quakeData = [] # this will hold the actual data
flag = 1 # that flag helps omit the first line
for a in quakeLines:
if flag: # if it's the first time
flag = 0
continue # continue with the next iteration of the loop
if len(a) > 0: # ignore empty lines
# this is a good place to turn the strings into numbers
quakeData.append(a.split(",")) # append the data as a list
for a in quakeData: # go through the data
number = a[0]
locX = a[1]
locY = a[2]
mag = a[3]
print("Nr " + number + ": Location: " + locX + " " + locY + " Magnitude: " + mag)
# the print statement only works because all the numbers are still strings. That has to change if you want to use them for blender objects
-
1$\begingroup$ Thanks for all the commenting, the non-coders salute you ;-) $\endgroup$ Mar 5, 2018 at 7:32
-
1$\begingroup$ For test prints consider using
print("Nr ", number, ": Location: ", loxX)
Doesn't matter what type the vars are, and avoids unnecessary string concatenation. $\endgroup$ Mar 5, 2018 at 11:01
This can be done with Animation Nodes. Download and install the linked add-on. The first thing we need to do is to parse our data. In the Node Editor, create a new Animation Nodes NodeTree:
Add a Text Block Reader node (nodes can be added with Shift + A or you can search by name with Ctrl + A). Press the "+" button, then the magnifying glass button and click to create a new Text Editor window.
Now, paste your .csv
file into the Text Editor. Here is mine:
36.0071678,-120.5664978,3.37,1.25
39.361,-120.0015,0.2,1.2
61.0127,-152.3792,109.2,1.9
34.2196667,-117.5191667,4.28,2.01
19.1678333,-155.692337,4.33,1.84
52.5276,160.5151,37.6,5.2
33.5093333,-116.7995,3.67,0.6
63.7417,-149.4625,117.7,1.4
39.3438,-120.0228,5.4,1.2
33.497,-116.7903333,6.16,1.09
33.4935,-116.7871667,6.63,0.39
33.3825,-116.8723333,5.13,1
37.6496658,-118.9426651,5.26,0.74
33.765,-116.9028333,11,0.95
60.9685,-150.2176,25.3,1
The data is ordered x,y,z,mag
. Add a Split Text node, and set it to "Lines." Now we have a list of strings, each containing the data for one earthquake.
Next, we need to extract a location vector and a magnitude from these text lists. We'll use Expression nodes for this. Add an Expression node and create a new input from the Text List output of the Split Text node. Use the gear icon to set the output type to Vector List. Paste the following code into the text box:
[[float(p) for p in e.split(",")[:3]] for e in t]
Duplicate the Expression node, change the output type to Float List and paste this code:
[float(e.split(",")[3]) for e in t]
Current NodeTree:
Next, add a Combine Vector node and a Compose Matrix node:
Last, add an Object Instancer node. Select the mesh that you want to represent the earthquakes (I'm using an Icosphere). Set the number of Instances to the number of earthquakes in your data. Add an Object Matrix Output node, and use it to position the Icospheres:
Result:
(requires Animation Nodes)
(x,y,z)
or(lat,long,depth)
? $\endgroup$