LoginSignup
0

More than 5 years have passed since last update.

ADDA > tool > make_pov_png_180121.py > v0.1-v0.7 > to make [Povray file] and [png files] of the particle shape from the [IntField-Y] in terms of (slant, top, front, and side) views

Last updated at Posted at 2018-01-27
Tested_Environment
GeForce GTX 1070 (8GB)
ASRock Z170M Pro4S [Intel Z170chipset]
Ubuntu 16.04 LTS desktop amd64
TensorFlow v1.2.1
cuDNN v5.1 for Linux
CUDA v8.0
Python 3.5.2
Numpy v1.13.1
IPython 6.0.0 -- An enhanced Interactive Python.
gcc (Ubuntu 5.4.0-6ubuntu1~16.04.4) 5.4.0 20160609
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
scipy v0.19.1
geopandas v0.3.0
MATLAB R2017b (Home Edition)
ADDA v.1.3b6
POV-Ray 3.7.0.unofficial

This article is related to ADDA (light scattering simulator based on the discrete dipole approximation).

About

In this article, a tool to make Povray file and png files of the particle shape is introduced.

By using the Matplotlib, it took 43 minutes to show the Chebyshev particle with N=206,800.
(see. this article for the detail).
Instead of using the Matplotlib, Povray is used to render the images.

The tool processes as follows:

  1. read (x,y,z) positions in the [LN-IntField-Y]
    • [LN-IntField-Y] is the symbolic link of [IntField-Y]
  2. created Povray file based on the coordinates
    • for 4 views (slant, top, front, and side)
  3. render the image by executing the Povray

IntField-Y: Input file

The following is the example command to create [IntField-Y] using ADDA.

./adda -shape cylinder 1.5 -store_int_field -grid 26 -maxiter 10 

Where, the -maxiter is used because the calculation do not need to be finished with the high accuracy. Only the position information in the 'IntField-Y' is used.

In another case, the users can use [IntField-Y] for the calculation where the iterative solver converges with the desired accuracy where the -maxiter is not specified.

code

Requirements

Following tools are required.

  • Python 3 (e.g. Python 3.5.2)
  • Numpy (e.g. Numpy v1.13.1)
  • Povray (e.g. POV-Ray 3.7.0.unofficial)

Python script (make_pov_png_180121.py v0.1-v0.7)

Following is the Python script named make_pov_png_180121.py used to create Povray file and png files.

make_pov_png_180121.py
import numpy as np
import sys
import subprocess as sb

'''
v0.7 Jan. 27, 2018
  - ** rename [make_pov_180121.py] to [make_pov_png_180121.py]
  - create also (top, front, side) images
  - refactor > reposition constants definitions
  - execute povray command
  - add make_pov_file()
  - read [IntField-Y] file instead of (x,y,z) file
v0.6 Jan. 27, 2018
  - refactor
    + from [IN_FILE] to [IN_FILE_XYZ]
v0.5 Jan. 23, 2018
  - convert [right-handed] to [left-handed] coordinate
    + interchange y and z
v0.4 Jan. 23, 2018 viewing geometry
  - [light_source] takes [LOCX], [LOCY], [LOCZ]
  - change [camera.location]
    + main() change [CONFIG_FORMAT]
    + add calc_xyz()
    + [CONFIG_FORMAT] takes [LOCX], [LOCY], [LOCZ]
    + add [VIEW_RADIUS]
    + add [ELEVATION_DEG], [AZIMUTH_DEG]
v0.3 Jan., 21, 2018
  - each particle is colored
  - [SHAPE_FORMAT] has color value template
    + [RED], [GREEN], [BLUE]
v0.2 Jan., 21, 2018
  - tweak [MONOMER_RADIUS] from 0.5 to 0.25
v0.1 Jan., 21, 2018
  - output [.pov] file
    + add main()
  - add [SHAPE_FORMAT]
  - add [CONFIG_FORMAT]
'''

# tested on Python 3.5.2
# coding rule: PEP8

CONFIG_FORMAT = """
camera {
  location <LOCX, LOCY, LOCZ>
  look_at <0, 0, 0>
}
light_source { <LOCX, LOCY, LOCZ>
  color rgb <1.0, 1.0, 1.0>
}

background{color rgb <1.0,1.0,1.0>}
"""

SHAPE_FORMAT = """
sphere { <XXX, YYY, ZZZ>, RRR
  texture {
    pigment { color rgb <RED,GREEN,BLUE> }
    finish {      ambient 0.4    }
  }
}
"""

# IN_FILE_XYZ = 'LN-SHAPE'
IN_FILE_INTFIELD_Y = 'LN-IntField-Y'  # LN: symbolic link file
OUT_FILE = "shape_180121.pov"
MONOMER_RADIUS = 0.25

RGBSET = [
    [0.40000000000000002, 0.76078431372549016, 0.6470588235294118],
    [0.40000000000000002, 0.76078431372549016, 0.6470588235294118],
    [0.9882352941176471, 0.55294117647058827, 0.3843137254901961],
    [0.55294117647058827, 0.62745098039215685, 0.79607843137254897],
    [0.90588235294117647, 0.54117647058823526, 0.76470588235294112],
    [0.65098039215686276, 0.84705882352941175, 0.32941176470588235],
    [0.65098039215686276, 0.84705882352941175, 0.32941176470588235],
    [1.0, 0.85098039215686272, 0.18431372549019609],
    [0.89803921568627454, 0.7686274509803922, 0.58039215686274515],
    [0.70196078431372544, 0.70196078431372544, 0.70196078431372544],
    [0.70196078431372544, 0.70196078431372544, 0.70196078431372544],
]

X_MAX = 10  # used to set colors based on the x position


def calc_xyz(theta_deg, phi_deg, radius):
    ath = np.deg2rad(theta_deg)
    aph = np.deg2rad(phi_deg)
    x = radius * np.cos(aph) * np.sin(ath)
    y = radius * np.sin(aph) * np.sin(ath)
    z = radius * np.cos(ath)
    return x, y, z


def read_IntFieldY(filepath):
    # skip 1st row (title)
    dat = np.genfromtxt(filepath, skip_header=1)
    # extract only first 3 columns (x,y,z)
    wrk = dat[:, :3]
    return wrk


def make_pov_file(filepath, azenith, aazimuth):
    # dat = np.genfromtxt(IN_FILE_XYZ)
    dat = read_IntFieldY(filepath)
    with open(OUT_FILE, 'wb+') as fd:
        # camera position and lightsource position
        cax, cay, caz = calc_xyz(azenith, aazimuth, VIEW_RADIUS)
        wrk = CONFIG_FORMAT.replace('LOCX', '%s' % cax)
        wrk = wrk.replace('LOCY', '%s' % caz)  # left-handed coord.
        wrk = wrk.replace('LOCZ', '%s' % cay)  # left-handed coord.
        wrk = np.array(wrk).reshape(1,)
        np.savetxt(fd, wrk, fmt='%s')
        # each monomer
        for elem in dat:
            wrk = SHAPE_FORMAT.replace('XXX', '%s' % elem[0])
            # position (left-handed coordinate)
            wrk = wrk.replace('YYY', '%s' % elem[2])
            wrk = wrk.replace('ZZZ', '%s' % elem[1])
            #
            wrk = wrk.replace('RRR', '%s' % MONOMER_RADIUS)
            # color
            #    clidx = (elem[0] - (-50)) / (50 - (-50))
            clidx = (elem[0] - (-X_MAX)) / (X_MAX - (-X_MAX))
            clidx = clidx * len(RGBSET)
            if clidx < 0.0:
                clidx = 0.0
            if clidx > X_MAX:
                clidx = X_MAX
            acol = RGBSET[int(clidx)]
            wrk = wrk.replace('RED', '%s' % acol[0])
            wrk = wrk.replace('GREEN', '%s' % acol[1])
            wrk = wrk.replace('BLUE', '%s' % acol[2])
            #
            wrk = np.array(wrk).reshape(1,)
            np.savetxt(fd, wrk, fmt='%s')
    print('[%s] is created' % OUT_FILE)


def make_png_file(infile, azenith, aazimuth, suffix):
    make_pov_file(infile, azenith, aazimuth)
    outfile = OUT_FILE.replace('.', suffix + '.')
    cmd = 'mv %s %s' % (OUT_FILE, outfile)
    sb.call(cmd.split())
    cmd = 'povray ' + outfile
    sb.call(cmd.split())
    #
    msg = ''
    msg += '[%s] is created\n' % outfile
    msg += '[%s] is created\n' % outfile.replace('pov', 'png')
    return msg

# viewing geometry
ELEVATION_DEG = 30.0  # elevation angle [degree]
AZIMUTH_DEG = -60.0  # azimuth angle [degree]
VIEW_RADIUS = 30.0  # radius of the viewing geometry
#
zenith_deg = 90.0 - ELEVATION_DEG  # zenith angle [degree]


def main():
    infile = IN_FILE_INTFIELD_Y
    msg = ''
    msg += make_png_file(infile, zenith_deg, AZIMUTH_DEG, '_slant')
    msg += make_png_file(infile, 0, 0, '_top')
    msg += make_png_file(infile, 90, 0, '_front')
    msg += make_png_file(infile, 90, -90, '_side')
    print(msg)
    msg = 'To view images at once, open [view_180128.html]\n'
    msg += 'on your web browser\n'
    msg += 'e.g. google-chrome view_180128.html'
    print(msg)

if __name__ == '__main__':
    main()

html to view outputs (view_180128.html v0.1)

The following is a html file to view the output files on the Web browser.

view_180128.html
<!--
v0.1 Jan. 28, 2018
  - show 4 images
-->
<html>
<table>

<tr>
<td>slant (Theta=60deg, Phi=-60deg)</td><td>top</td>
</tr>
<tr>
<td><img src=shape_180121_slant.png></td>
<td><img src=shape_180121_top.png></td>
</tr>

<tr>
<td>front</td><td>side</td>
</tr>
<tr>
<td><img src=shape_180121_front.png></td>
<td><img src=shape_180121_side.png></td>
</tr>

</table>
</html>

How to use

1. prepare [LN-IntField-Y]

Following is the example of the symbolic linkage of the ADDA output.

$ln -fs ../CALC_180117_MUELLER/gHN_N0500_THETA_1p0/run44242_chebyshev_g104_m1.5/IntField-Y LN-IntField-Y

Also, instead of the symbolic link, the user can copy the ADDA output in the name of [LN-IntField-Y].

2. run the script

$python3 make_pov_png_180121.py 
...
...
...
...
...
...
Render Time:
  Photon Time:      No photons
  Radiosity Time:   No radiosity
  Trace Time:       0 hours  0 minutes  0 seconds (0.122 seconds)
              using 8 thread(s) with 0.523 CPU-seconds total
POV-Ray finished

[shape_180121_slant.pov] is created
[shape_180121_slant.png] is created
[shape_180121_top.pov] is created
[shape_180121_top.png] is created
[shape_180121_front.pov] is created
[shape_180121_front.png] is created
[shape_180121_side.pov] is created
[shape_180121_side.png] is created

To view images at once, open [view_180128.html]
on your web browser
e.g. google-chrome view_180128.html

3. view the images

As shown in the Step2, output files can be viewed by reading [view_180128.html].
For example, with the Google Chrome, following command can be used (depending on the OS).
(Or, drag and drop the [view_180182.html] file onto the web browser).

$google-chrome view_180128.html

Then, in the web browser, the user can see the following images.

qiita.png

Output example

bisphere

command: './adda -shape bisphere 1.0 -store_int_field -grid 26 -maxiter 10 '

N=18,656
Processing time: 8.287sec

qiita.png

Capsule

command: './adda -shape capsule 1.5 -store_int_field -grid 26 -maxiter 10 '

N=30,280
Processing time: 9.986sec

qiita.png

Cylinder

command: './adda -shape cylinder 1.5 -store_int_field -grid 26 -maxiter 10 '

N=21,600
Processing time: 8.524sec

qiita.png

Egg

command: './adda -shape egg 0.7 0.5 -store_int_field -grid 26 -maxiter 10 '

N=13,748
Processing time: 7.740sec

qiita.png

Sphere

command: './adda -shape sphere -store_int_field -grid 26 -maxiter 10 '

N=9,328
Processing time: 6.968sec

qiita.png

Chebyshev

command: './adda -shape chebyshev 0.7 12 -grid 104 -store_int_field -maxiter 10 -eq_rad 6.299605 '

N=206,800
Processing time: 32.261sec

qiita.png

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0