Skip to content

Latest commit

 

History

History
322 lines (219 loc) · 5.94 KB

firstread.rst

File metadata and controls

322 lines (219 loc) · 5.94 KB

First Read

Step-by-step: how to read openPMD data? We are using the examples files from openPMD-example-datasets.

@media screen and (min-width: 60em) { /* C++11 and Python code samples side-by-side */ #first-read > .section > .section:nth-of-type(2n+1) { float: left; width: 48%; margin-right: 4%; } #first-read > .section > .section:nth-of-type(2n+0):after { content: ""; display: table; clear: both; } /* only show first C++11 and Python Headline */ #first-read > .section > .section:not(#c-11):not(#python) > h3 { display: none; } } /* align language headline */ #first-read > .section > .section > h3 { text-align: center; padding-left: 1em; } /* avoid jumping of headline when hovering to get anchor */ #first-read > .section > .section > h3 > a.headerlink { display: inline-block; } #first-read > .section > .section > h3 > .headerlink:after { visibility: hidden; } #first-read > .section > .section > h3:hover > .headerlink:after { visibility: visible; }

Include / Import

After successfull installation <install>, you can start using openPMD-api as follows:

C++11

#include <openPMD/openPMD.hpp>

// example: data handling & print
#include <vector>   // std::vector
#include <iostream> // std::cout
#include <memory>   // std::shared_ptr

namespace api = openPMD;

Python

import openpmd_api as api

# example: data handling
import numpy as np

Open

Open an existing openPMD series in data<N>.h5. Further file formats than .h5 (HDF5) are supported: .bp (ADIOS1) or .json (JSON).

C++11

auto series = api::Series(
    "data%T.h5",
    AccessType::READ_ONLY);

Python

series = api.Series(
    "data%T.h5",
    api.Access_Type.read_only)

Iteration

Grouping by an arbitrary, positive integer number <N> in a series. Let's take the iteration 100:

C++11

auto i = series.iterations[100];

Python

i = series.iterations[100]

Attributes

openPMD defines a kernel of meta attributes and can always be extended with more. Let's see what we've got:

C++11

std::cout
    << "Author: "
    << s.author() << "\n"
    << "openPMD version: "
    << s.openPMD() << "\n";

Python

print(
    "Author: {0}"
    "openPMD version: {1}"
    .format(
        s.author,
        s.openPMD))

Record

An openPMD record can be either structured (mesh) or unstructured (particles). Let's read an electric field:

C++11

// record
auto E = i.meshes["E"];

// record components
auto E_x = E["x"];

Python

# record
E = i.meshes["E"]

# record components
E_x = E["x"]

Units

On read, units are automatically converted to SI unless otherwise specified (not yet implemented). Even without the name "E" we can check the dimensionality of a record to understand its purpose.

C++11

// unit system agnostic dimension
auto E_unitDim = E.getUnitDimension();

// ...
// api::UnitDimension::M

Python

# unit system agnostic dimension
E_unitDim = E.unit_dimension

# ...
# api.Unit_Dimension.M

Note

This example is not yet written :-)

Register Chunk

We can load record components partially and in parallel or at once. Reading small data one by one is is a performance killer for I/O. Therefore, we register the data to be loaded first and then flush it in collectively.

C++11

// alternatively, pass pre-allocated
std::shared_ptr< double > x_data =
    E_x.loadChunk< double >();

Python

# returns an allocated but
# undefined numpy array
x_data = E_x.load_chunk()

Attention

After registering a data chunk such as x_data for loading, it MUST NOT be modified or deleted until the flush() step is performed! You must not yet access x_data !

Flush Chunk

We now flush the registered data chunks and fill them with actual data from the I/O backend. Flushing several chunks at once allows to increase I/O performance significantly. Only after that, the variable x_data can be read, manipulated and/or deleted.

C++11

series.flush();

Python

series.flush()

Data

We can not work with the newly loaded data in x_data:

C++11

auto extent = E_x.getExtent();

cout << "First values in E_x "
        "of shape: ";
for( auto const& dim : extent )
    cout << dim << ', ';
cout << "\n"

for( size_t col = 0;
     col < extent[1] && col < 5;
     ++col )
    cout << x_data.get()[col]
         << ", ";
cout << "\n";

Python

extent = E_x.shape

print(
    "First values in E_x "
    "of shape: ",
    extent)


print(x_data[0, 0, :5])

Close

Finally, the Series is closed when its destructor is called. Make sure to have flush() ed all data loads at this point, otherwise it will be called once more implicitly.

C++11

// destruct series object,
// e.g. when out-of-scope

Python

del series