Example #1
0
def convertToOPMD(input_file):
    """ Take native wpg output and rewrite in openPMD conformant way.
    @param input_file: The hdf5 file to be converted.
    @type: string
    @example: input_file = "prop_out.h5"
    """

    # Check input file.
    if not h5py.is_hdf5(input_file):
        raise IOError("Not a valid hdf5 file: %s. " % (input_file))

    # Open in and out files.
    with h5py.File(input_file, 'r') as h5:
        with h5py.File(input_file.replace(".h5", ".opmd.h5"), 'w') as opmd_h5:

            # Get number of time slices in wpg output, assuming horizontal and vertical polarizations have same dimensions, which is always true for wpg output.
            data_shape = h5['data/arrEhor'].value.shape

            # Branch off if this is a non-time dependent calculation in frequency domain.
            if data_shape[2] == 1 and h5['params/wDomain'].value == "frequency":
                # Time independent calculation in frequency domain.
                _convert_from_frequency_representation(h5, opmd_h5, data_shape)
                return

            number_of_x_meshpoints = data_shape[0]
            number_of_y_meshpoints = data_shape[1]
            number_of_time_steps = data_shape[2]

            time_max = h5['params/Mesh/sliceMax'].value  #s
            time_min = h5['params/Mesh/sliceMin'].value  #s
            time_step = abs(time_max - time_min) / number_of_time_steps  #s

            photon_energy = h5['params/photonEnergy'].value  # eV
            photon_energy = photon_energy * e  # Convert to J

            # Copy misc and params from original wpg output.
            opmd_h5.create_group('history/parent')
            try:
                h5.copy('/params', opmd_h5['history/parent'])
                h5.copy('/misc', opmd_h5['history/parent'])
                h5.copy('/history', opmd_h5['history/parent'])
            # Some keys may not exist, e.g. if the input file comes from a non-simex wpg run.
            except KeyError:
                pass
            except:
                raise

            sum_x = 0.0
            sum_y = 0.0
            for it in range(number_of_time_steps):
                # Write opmd
                # Setup the root attributes for iteration 0
                opmd.setup_root_attr(opmd_h5)

                full_meshes_path = opmd.get_basePath(
                    opmd_h5, it) + opmd_h5.attrs["meshesPath"]
                # Setup basepath.
                time = time_min + it * time_step
                opmd.setup_base_path(opmd_h5,
                                     iteration=it,
                                     time=time,
                                     time_step=time_step)
                opmd_h5.create_group(full_meshes_path)
                meshes = opmd_h5[full_meshes_path]

                # Path to the E field, within the h5 file.
                full_e_path_name = b"E"
                meshes.create_group(full_e_path_name)
                E = meshes[full_e_path_name]

                # Create the dataset (2d cartesian grid)
                E.create_dataset(
                    b"x", (number_of_x_meshpoints, number_of_y_meshpoints),
                    dtype=numpy.complex64,
                    compression='gzip')
                E.create_dataset(
                    b"y", (number_of_x_meshpoints, number_of_y_meshpoints),
                    dtype=numpy.complex64,
                    compression='gzip')

                # Write the common metadata for the group
                E.attrs["geometry"] = numpy.string_("cartesian")
                # Get grid geometry.
                nx = h5['params/Mesh/nx'].value
                xMax = h5['params/Mesh/xMax'].value
                xMin = h5['params/Mesh/xMin'].value
                dx = (xMax - xMin) / nx
                ny = h5['params/Mesh/ny'].value
                yMax = h5['params/Mesh/yMax'].value
                yMin = h5['params/Mesh/yMin'].value
                dy = (yMax - yMin) / ny
                E.attrs["gridSpacing"] = numpy.array([dx, dy],
                                                     dtype=numpy.float64)
                E.attrs["gridGlobalOffset"] = numpy.array(
                    [h5['params/xCentre'].value, h5['params/yCentre'].value],
                    dtype=numpy.float64)
                E.attrs["gridUnitSI"] = numpy.float64(1.0)
                E.attrs["dataOrder"] = numpy.string_("C")
                E.attrs["axisLabels"] = numpy.array([b"x", b"y"])
                E.attrs["unitDimension"] = \
                   numpy.array([1.0, 1.0, -3.0, -1.0, 0.0, 0.0, 0.0 ], dtype=numpy.float64)
                #            L    M     T     I  theta  N    J
                # E is in volts per meters: V / m = kg * m / (A * s^3)
                # -> L * M * T^-3 * I^-1

                # Add time information
                E.attrs[
                    "timeOffset"] = 0.  # Time offset with respect to basePath's time

                # Write attribute that is specific to each dataset:
                # - Staggered position within a cell
                E["x"].attrs["position"] = numpy.array([0.0, 0.5],
                                                       dtype=numpy.float32)
                E["y"].attrs["position"] = numpy.array([0.5, 0.0],
                                                       dtype=numpy.float32)

                # - Conversion factor to SI units
                # WPG writes E fields in units of sqrt(W/mm^2), i.e. it writes E*sqrt(c * eps0 / 2).
                # Unit analysis:
                # [E] = V/m
                # [eps0] = As/Vm
                # [c] = m/s
                # ==> [E^2 * eps0 * c] = V**2/m**2 * As/Vm * m/s = V*A/m**2 = W/m**2 = [Intensity]
                # Converting to SI units by dividing by sqrt(c*eps0/2)*1e3, 1e3 for conversion from mm to m.
                c = 2.998e8  # m/s
                eps0 = 8.854e-12  # As/Vm
                E["x"].attrs["unitSI"] = numpy.float64(
                    1.0 / math.sqrt(0.5 * c * eps0) / 1.0e3)
                E["y"].attrs["unitSI"] = numpy.float64(
                    1.0 / math.sqrt(0.5 * c * eps0) / 1.0e3)

                # Copy the fields.
                Ex = h5['data/arrEhor'][:, :, it,
                                        0] + 1j * h5['data/arrEhor'][:, :, it,
                                                                     1]
                Ey = h5['data/arrEver'][:, :, it,
                                        0] + 1j * h5['data/arrEver'][:, :, it,
                                                                     1]
                E["x"][:, :] = Ex
                E["y"][:, :] = Ey

                # Get area element.
                dA = dx * dy

                ### Number of photon fields.
                # Path to the number of photons.
                full_nph_path_name = b"Nph"
                meshes.create_group(full_nph_path_name)
                Nph = meshes[full_nph_path_name]

                # Create the dataset (2d cartesian grid)
                Nph.create_dataset(
                    b"x", (number_of_x_meshpoints, number_of_y_meshpoints),
                    dtype=numpy.float32,
                    compression='gzip')
                Nph.create_dataset(
                    b"y", (number_of_x_meshpoints, number_of_y_meshpoints),
                    dtype=numpy.float32,
                    compression='gzip')

                # Write the common metadata for the group
                Nph.attrs["geometry"] = numpy.string_("cartesian")
                Nph.attrs["gridSpacing"] = numpy.array([dx, dy],
                                                       dtype=numpy.float64)
                Nph.attrs["gridGlobalOffset"] = numpy.array(
                    [h5['params/xCentre'].value, h5['params/yCentre'].value],
                    dtype=numpy.float64)
                Nph.attrs["gridUnitSI"] = numpy.float64(1.0)
                Nph.attrs["dataOrder"] = numpy.string_("C")
                Nph.attrs["axisLabels"] = numpy.array([b"x", b"y"])
                Nph.attrs["unitDimension"] = \
                   numpy.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], dtype=numpy.float64)

                # Add time information
                Nph.attrs[
                    "timeOffset"] = 0.  # Time offset with respect to basePath's time
                # Nph - Staggered position within a cell
                Nph["x"].attrs["position"] = numpy.array([0.0, 0.5],
                                                         dtype=numpy.float32)
                Nph["y"].attrs["position"] = numpy.array([0.5, 0.0],
                                                         dtype=numpy.float32)
                Nph["x"].attrs["unitSI"] = numpy.float64(1.0)
                Nph["y"].attrs["unitSI"] = numpy.float64(1.0)

                # Calculate number of photons via intensity and photon energy.
                # Since fields are stored as sqrt(W/mm^2), have to convert to W/m^2 (factor 1e6 below).
                number_of_photons_x = numpy.round(
                    abs(Ex)**2 * dA * time_step * 1.0e6 / photon_energy)
                number_of_photons_y = numpy.round(
                    abs(Ey)**2 * dA * time_step * 1.0e6 / photon_energy)
                sum_x += number_of_photons_x.sum(axis=-1).sum(axis=-1)
                sum_y += number_of_photons_y.sum(axis=-1).sum(axis=-1)
                Nph["x"][:, :] = number_of_photons_x
                Nph["y"][:, :] = number_of_photons_y

                ### Phases.
                # Path to phases
                full_phases_path_name = b"phases"
                meshes.create_group(full_phases_path_name)
                phases = meshes[full_phases_path_name]

                # Create the dataset (2d cartesian grid)
                phases.create_dataset(
                    b"x", (number_of_x_meshpoints, number_of_y_meshpoints),
                    dtype=numpy.float32,
                    compression='gzip')
                phases.create_dataset(
                    b"y", (number_of_x_meshpoints, number_of_y_meshpoints),
                    dtype=numpy.float32,
                    compression='gzip')

                # Write the common metadata for the group
                phases.attrs["geometry"] = numpy.string_("cartesian")
                phases.attrs["gridSpacing"] = numpy.array([dx, dy],
                                                          dtype=numpy.float64)
                phases.attrs["gridGlobalOffset"] = numpy.array(
                    [h5['params/xCentre'].value, h5['params/yCentre'].value],
                    dtype=numpy.float64)
                phases.attrs["gridUnitSI"] = numpy.float64(1.0)
                phases.attrs["dataOrder"] = numpy.string_("C")
                phases.attrs["axisLabels"] = numpy.array([b"x", b"y"])
                phases.attrs["unitDimension"] = numpy.array(
                    [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], dtype=numpy.float64)
                phases["x"].attrs["unitSI"] = numpy.float64(1.0)
                phases["y"].attrs["unitSI"] = numpy.float64(1.0)

                # Add time information
                phases.attrs[
                    "timeOffset"] = 0.  # Time offset with respect to basePath's time
                # phases positions. - Staggered position within a cell
                phases["x"].attrs["position"] = numpy.array(
                    [0.0, 0.5], dtype=numpy.float32)
                phases["y"].attrs["position"] = numpy.array(
                    [0.5, 0.0], dtype=numpy.float32)

                phases["x"][:, :] = numpy.angle(Ex)
                phases["y"][:, :] = numpy.angle(Ey)

    print(
        "Found %e and %e photons for horizontal and vertical polarization, respectively."
        % (sum_x, sum_y))
def convertToOPMD(input_file):
    """ Take native wpg output and rewrite in openPMD conformant way.
    @param input_file: The hdf5 file to be converted.
    @type: string
    @example: input_file = "prop_out.h5"
    """

    # Check input file.
    if not h5py.is_hdf5(input_file):
        raise IOError("Not a valid hdf5 file: %s. " % (input_file))

    # Open in and out files.
    h5 = h5py.File( input_file, 'r')
    opmd_h5 = h5py.File(input_file.replace(".h5", ".opmd.h5"), 'w')

    # Get number of time slices in wpg output, assuming horizontal and vertical polarizations have same dimensions, which is always true for wpg output.
    data_shape = h5['data/arrEhor'].value.shape
    number_of_x_meshpoints = data_shape[0]
    number_of_y_meshpoints = data_shape[1]
    number_of_time_steps = data_shape[2]

    time_max = h5['params/Mesh/sliceMax'].value #s
    time_min = h5['params/Mesh/sliceMin'].value #s

    time_step = abs(time_max - time_min) / number_of_time_steps #s


    photon_energy = h5['params/photonEnergy'].value # eV
    photon_energy = photon_energy * e # Convert to J

    # Copy misc and params from original wpg output.
    opmd_h5.create_group('history/parent')
    h5.copy('/params', opmd_h5['history/parent'])
    h5.copy('/misc', opmd_h5['history/parent'])
    h5.copy('/history', opmd_h5['history/parent'])

    sum_x = 0.0
    sum_y = 0.0

    for it in range(number_of_time_steps):
        # Write opmd
        # Setup the root attributes for iteration 0
        opmd.setup_root_attr( opmd_h5 )

        full_meshes_path = opmd.get_basePath(opmd_h5, it) + opmd_h5.attrs["meshesPath"]
        # Setup basepath.
        time=time_min+it*time_step
        opmd.setup_base_path( opmd_h5, iteration=it, time=time, time_step=time_step)
        opmd_h5.create_group(full_meshes_path)
        meshes = opmd_h5[full_meshes_path]

        # Path to the E field, within the h5 file.
        full_e_path_name = b"E"
        meshes.create_group(full_e_path_name)
        E = meshes[full_e_path_name]

        # Create the dataset (2d cartesian grid)
        E.create_dataset(b"x", (number_of_x_meshpoints, number_of_y_meshpoints), dtype=numpy.complex64, compression='gzip')
        E.create_dataset(b"y", (number_of_x_meshpoints, number_of_y_meshpoints), dtype=numpy.complex64, compression='gzip')

        # Write the common metadata for the group
        E.attrs["geometry"] = numpy.string_("cartesian")
        # Get grid geometry.
        nx = h5['params/Mesh/nx'].value
        xMax = h5['params/Mesh/xMax'].value
        xMin = h5['params/Mesh/xMin'].value
        dx = (xMax - xMin) / nx
        ny = h5['params/Mesh/ny'].value
        yMax = h5['params/Mesh/yMax'].value
        yMin = h5['params/Mesh/yMin'].value
        dy = (yMax - yMin) / ny
        E.attrs["gridSpacing"] = numpy.array( [dx,dy], dtype=numpy.float64)
        E.attrs["gridGlobalOffset"] = numpy.array([h5['params/xCentre'].value, h5['params/yCentre'].value], dtype=numpy.float64)
        E.attrs["gridUnitSI"] = numpy.float64(1.0)
        E.attrs["dataOrder"] = numpy.string_("C")
        E.attrs["axisLabels"] = numpy.array([b"x",b"y"])
        E.attrs["unitDimension"] = \
           numpy.array([1.0, 1.0, -3.0, -1.0, 0.0, 0.0, 0.0 ], dtype=numpy.float64)
           #            L    M     T     I  theta  N    J
           # E is in volts per meters: V / m = kg * m / (A * s^3)
           # -> L * M * T^-3 * I^-1

        # Add time information
        E.attrs["timeOffset"] = 0.  # Time offset with respect to basePath's time

        # Write attribute that is specific to each dataset:
        # - Staggered position within a cell
        E["x"].attrs["position"] = numpy.array([0.0, 0.5], dtype=numpy.float32)
        E["y"].attrs["position"] = numpy.array([0.5, 0.0], dtype=numpy.float32)

        # - Conversion factor to SI units
        # WPG writes E fields in units of sqrt(W/mm^2), i.e. it writes E*sqrt(c * eps0 / 2).
        # Unit analysis:
        # [E] = V/m
        # [eps0] = As/Vm
        # [c] = m/s
        # ==> [E^2 * eps0 * c] = V**2/m**2 * As/Vm * m/s = V*A/m**2 = W/m**2 = [Intensity]
        # Converting to SI units by dividing by sqrt(c*eps0/2)*1e3, 1e3 for conversion from mm to m.
        c    = 2.998e8   # m/s
        eps0 = 8.854e-12 # As/Vm
        E["x"].attrs["unitSI"] = numpy.float64(1.0  / math.sqrt(0.5 * c * eps0) / 1.0e3 )
        E["y"].attrs["unitSI"] = numpy.float64(1.0  / math.sqrt(0.5 * c * eps0) / 1.0e3 )

        # Copy the fields.
        Ex = h5['data/arrEhor'][:,:,it,0] + 1j * h5['data/arrEhor'][:,:,it,1]
        Ey = h5['data/arrEver'][:,:,it,0] + 1j * h5['data/arrEver'][:,:,it,1]
        E["x"][:,:] = Ex
        E["y"][:,:] = Ey

        # Get area element.
        dA = dx*dy

        ### Number of photon fields.
        # Path to the number of photons.
        full_nph_path_name = b"Nph"
        meshes.create_group(full_nph_path_name)
        Nph = meshes[full_nph_path_name]

        # Create the dataset (2d cartesian grid)
        Nph.create_dataset(b"x", (number_of_x_meshpoints, number_of_y_meshpoints), dtype=numpy.float32, compression='gzip')
        Nph.create_dataset(b"y", (number_of_x_meshpoints, number_of_y_meshpoints), dtype=numpy.float32, compression='gzip')

        # Write the common metadata for the group
        Nph.attrs["geometry"] = numpy.string_("cartesian")
        Nph.attrs["gridSpacing"] = numpy.array( [dx,dy], dtype=numpy.float64)
        Nph.attrs["gridGlobalOffset"] = numpy.array([h5['params/xCentre'].value, h5['params/yCentre'].value], dtype=numpy.float64)
        Nph.attrs["gridUnitSI"] = numpy.float64(1.0)
        Nph.attrs["dataOrder"] = numpy.string_("C")
        Nph.attrs["axisLabels"] = numpy.array([b"x",b"y"])
        Nph.attrs["unitDimension"] = \
           numpy.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], dtype=numpy.float64)

        # Add time information
        Nph.attrs["timeOffset"] = 0.  # Time offset with respect to basePath's time
        # Nph - Staggered position within a cell
        Nph["x"].attrs["position"] = numpy.array([0.0, 0.5], dtype=numpy.float32)
        Nph["y"].attrs["position"] = numpy.array([0.5, 0.0], dtype=numpy.float32)
        Nph["x"].attrs["unitSI"] = numpy.float64(1.0 )
        Nph["y"].attrs["unitSI"] = numpy.float64(1.0 )

        # Calculate number of photons via intensity and photon energy.
        # Since fields are stored as sqrt(W/mm^2), have to convert to W/m^2 (factor 1e6 below).
        number_of_photons_x = numpy.round(abs(Ex)**2 * dA * time_step *1.0e6 / photon_energy)
        number_of_photons_y = numpy.round(abs(Ey)**2 * dA * time_step *1.0e6 / photon_energy)
        sum_x += number_of_photons_x.sum(axis=-1).sum(axis=-1)
        sum_y += number_of_photons_y.sum(axis=-1).sum(axis=-1)
        Nph["x"][:,:] = number_of_photons_x
        Nph["y"][:,:] = number_of_photons_y

        ### Phases.
        # Path to phases
        full_phases_path_name = b"phases"
        meshes.create_group(full_phases_path_name)
        phases = meshes[full_phases_path_name]

        # Create the dataset (2d cartesian grid)
        phases.create_dataset(b"x", (number_of_x_meshpoints, number_of_y_meshpoints), dtype=numpy.float32, compression='gzip')
        phases.create_dataset(b"y", (number_of_x_meshpoints, number_of_y_meshpoints), dtype=numpy.float32, compression='gzip')

        # Write the common metadata for the group
        phases.attrs["geometry"] = numpy.string_("cartesian")
        phases.attrs["gridSpacing"] = numpy.array( [dx,dy], dtype=numpy.float64)
        phases.attrs["gridGlobalOffset"] = numpy.array([h5['params/xCentre'].value, h5['params/yCentre'].value], dtype=numpy.float64)
        phases.attrs["gridUnitSI"] = numpy.float64(1.0)
        phases.attrs["dataOrder"] = numpy.string_("C")
        phases.attrs["axisLabels"] = numpy.array([b"x",b"y"])
        phases.attrs["unitDimension"] = numpy.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], dtype=numpy.float64)
        phases["x"].attrs["unitSI"] = numpy.float64(1.0 )
        phases["y"].attrs["unitSI"] = numpy.float64(1.0 )

        # Add time information
        phases.attrs["timeOffset"] = 0.  # Time offset with respect to basePath's time
        # phases positions. - Staggered position within a cell
        phases["x"].attrs["position"] = numpy.array([0.0, 0.5], dtype=numpy.float32)
        phases["y"].attrs["position"] = numpy.array([0.5, 0.0], dtype=numpy.float32)

        phases["x"][:,:] = numpy.angle(Ex)
        phases["y"][:,:] = numpy.angle(Ey)

    print "Found %e and %e photons for horizontal and vertical polarization, respectively." % (sum_x, sum_y)

    opmd_h5.close()
    h5.close()
Example #3
0
def _convert_from_frequency_representation(h5,
                                           opmd_h5,
                                           data_shape,
                                           pulse_energy=1.0e-3,
                                           pulse_duration=23.0e-15):
    """ Converter for non-time dependent wavefronts in frequency representation.
    Requires knowledge of pulse energy and pulse duration to allow photon number calculation.
    """

    number_of_x_meshpoints = data_shape[0]
    number_of_y_meshpoints = data_shape[1]

    photon_energy = h5['params/photonEnergy'].value  # eV
    photon_energy = photon_energy * e  # Convert to J

    # Copy misc and params from original wpg output.
    opmd_h5.create_group('history/parent')
    try:
        h5.copy('/params', opmd_h5['history/parent'])
        h5.copy('/misc', opmd_h5['history/parent'])
        h5.copy('/history', opmd_h5['history/parent'])
    # Some keys may not exist, e.g. if the input file comes from a non-simex wpg run.
    except KeyError:
        pass
    except:
        raise

    sum_x = 0.0
    sum_y = 0.0

    # Write opmd
    # Setup the root attributes.
    it = 0
    opmd.setup_root_attr(opmd_h5)

    full_meshes_path = opmd.get_basePath(opmd_h5,
                                         it) + opmd_h5.attrs["meshesPath"]
    # Setup basepath.
    time = 0.0
    time_step = pulse_duration
    opmd.setup_base_path(opmd_h5, iteration=it, time=time, time_step=time_step)
    opmd_h5.create_group(full_meshes_path)
    meshes = opmd_h5[full_meshes_path]

    ## Path to the E field, within the h5 file.
    #full_e_path_name = b"E"
    #meshes.create_group(full_e_path_name)
    #E = meshes[full_e_path_name]

    ## Create the dataset (2d cartesian grid)
    #E.create_dataset(b"x", (number_of_x_meshpoints, number_of_y_meshpoints), dtype=numpy.complex64, compression='gzip')
    #E.create_dataset(b"y", (number_of_x_meshpoints, number_of_y_meshpoints), dtype=numpy.complex64, compression='gzip')

    ## Write the common metadata for the group
    #E.attrs["geometry"] = numpy.string_("cartesian")
    ## Get grid geometry.
    nx = h5['params/Mesh/nx'].value
    xMax = h5['params/Mesh/xMax'].value
    xMin = h5['params/Mesh/xMin'].value
    dx = (xMax - xMin) / nx
    ny = h5['params/Mesh/ny'].value
    yMax = h5['params/Mesh/yMax'].value
    yMin = h5['params/Mesh/yMin'].value
    dy = (yMax - yMin) / ny
    #E.attrs["gridSpacing"] = numpy.array( [dx,dy], dtype=numpy.float64)
    #E.attrs["gridGlobalOffset"] = numpy.array([h5['params/xCentre'].value, h5['params/yCentre'].value], dtype=numpy.float64)
    #E.attrs["gridUnitSI"] = numpy.float64(1.0)
    #E.attrs["dataOrder"] = numpy.string_("C")
    #E.attrs["axisLabels"] = numpy.array([b"x",b"y"])
    #E.attrs["unitDimension"] = \
    #numpy.array([1.0, 1.0, -3.0, -1.0, 0.0, 0.0, 0.0 ], dtype=numpy.float64)
    ##            L    M     T     I  theta  N    J
    ## E is in volts per meters: V / m = kg * m / (A * s^3)
    ## -> L * M * T^-3 * I^-1

    ## Add time information
    #E.attrs["timeOffset"] = 0.  # Time offset with respect to basePath's time

    ## Write attribute that is specific to each dataset:
    ## - Staggered position within a cell
    #E["x"].attrs["position"] = numpy.array([0.0, 0.5], dtype=numpy.float32)
    #E["y"].attrs["position"] = numpy.array([0.5, 0.0], dtype=numpy.float32)

    ## - Conversion factor to SI units
    ## WPG writes E fields in units of sqrt(W/mm^2), i.e. it writes E*sqrt(c * eps0 / 2).
    ## Unit analysis:
    ## [E] = V/m
    ## [eps0] = As/Vm
    ## [c] = m/s
    ## ==> [E^2 * eps0 * c] = V**2/m**2 * As/Vm * m/s = V*A/m**2 = W/m**2 = [Intensity]
    ## Converting to SI units by dividing by sqrt(c*eps0/2)*1e3, 1e3 for conversion from mm to m.
    #c    = 2.998e8   # m/s
    #eps0 = 8.854e-12 # As/Vm
    #E["x"].attrs["unitSI"] = numpy.float64(1.0  / math.sqrt(0.5 * c * eps0) / 1.0e3 )
    #E["y"].attrs["unitSI"] = numpy.float64(1.0  / math.sqrt(0.5 * c * eps0) / 1.0e3 )

    # Get E fields.
    Ex = h5['data/arrEhor'][:, :, it, 0] + 1j * h5['data/arrEhor'][:, :, it, 1]
    Ey = h5['data/arrEver'][:, :, it, 0] + 1j * h5['data/arrEver'][:, :, it, 1]
    #E["x"][:,:] = Ex
    #E["y"][:,:] = Ey

    ### Number of photon fields.
    # Path to the number of photons.
    full_nph_path_name = b"Nph"
    meshes.create_group(full_nph_path_name)
    Nph = meshes[full_nph_path_name]

    # Create the dataset (2d cartesian grid)
    Nph.create_dataset(b"x", (number_of_x_meshpoints, number_of_y_meshpoints),
                       dtype=numpy.float32,
                       compression='gzip')
    Nph.create_dataset(b"y", (number_of_x_meshpoints, number_of_y_meshpoints),
                       dtype=numpy.float32,
                       compression='gzip')

    # Write the common metadata for the group
    Nph.attrs["geometry"] = numpy.string_("cartesian")
    Nph.attrs["gridSpacing"] = numpy.array([dx, dy], dtype=numpy.float64)
    Nph.attrs["gridGlobalOffset"] = numpy.array(
        [h5['params/xCentre'].value, h5['params/yCentre'].value],
        dtype=numpy.float64)
    Nph.attrs["gridUnitSI"] = numpy.float64(1.0)
    Nph.attrs["dataOrder"] = numpy.string_("C")
    Nph.attrs["axisLabels"] = numpy.array([b"x", b"y"])
    Nph.attrs["unitDimension"] = \
       numpy.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], dtype=numpy.float64)

    # Add time information
    Nph.attrs["timeOffset"] = 0.  # Time offset with respect to basePath's time
    # Nph - Staggered position within a cell
    Nph["x"].attrs["position"] = numpy.array([0.0, 0.5], dtype=numpy.float32)
    Nph["y"].attrs["position"] = numpy.array([0.5, 0.0], dtype=numpy.float32)
    Nph["x"].attrs["unitSI"] = numpy.float64(1.0)
    Nph["y"].attrs["unitSI"] = numpy.float64(1.0)

    # Calculate number of photons via intensity and photon energy.
    # Since fields are stored as sqrt(W/mm^2), have to convert to W/m^2 (factor 1e6 below).
    number_of_photons_x = numpy.round(abs(Ex)**2)
    number_of_photons_y = numpy.round(abs(Ey)**2)
    sum_x = number_of_photons_x.sum(axis=-1).sum(axis=-1)
    sum_y = number_of_photons_y.sum(axis=-1).sum(axis=-1)

    # Conversion from Nph/s/0.1%bandwidth/mm to Nph. Sum * photon_energy must be equal to pulse energy.
    # Normalization factor.
    c_factor = pulse_energy / photon_energy
    # Normalize
    number_of_photons_x *= c_factor
    number_of_photons_y *= c_factor
    # Normalize to sum over all pixels (if != 0 ).
    if sum_x != 0.0:
        number_of_photons_x /= sum_x
    if sum_y != 0.0:
        number_of_photons_y /= sum_y

    # Write to h5 dataset.
    Nph["x"][:, :] = number_of_photons_x
    Nph["y"][:, :] = number_of_photons_y

    ### Phases.
    # Path to phases
    full_phases_path_name = b"phases"
    meshes.create_group(full_phases_path_name)
    phases = meshes[full_phases_path_name]

    # Create the dataset (2d cartesian grid)
    phases.create_dataset(b"x",
                          (number_of_x_meshpoints, number_of_y_meshpoints),
                          dtype=numpy.float32,
                          compression='gzip')
    phases.create_dataset(b"y",
                          (number_of_x_meshpoints, number_of_y_meshpoints),
                          dtype=numpy.float32,
                          compression='gzip')

    # Write the common metadata for the group
    phases.attrs["geometry"] = numpy.string_("cartesian")
    phases.attrs["gridSpacing"] = numpy.array([dx, dy], dtype=numpy.float64)
    phases.attrs["gridGlobalOffset"] = numpy.array(
        [h5['params/xCentre'].value, h5['params/yCentre'].value],
        dtype=numpy.float64)
    phases.attrs["gridUnitSI"] = numpy.float64(1.0)
    phases.attrs["dataOrder"] = numpy.string_("C")
    phases.attrs["axisLabels"] = numpy.array([b"x", b"y"])
    phases.attrs["unitDimension"] = numpy.array(
        [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], dtype=numpy.float64)
    phases["x"].attrs["unitSI"] = numpy.float64(1.0)
    phases["y"].attrs["unitSI"] = numpy.float64(1.0)

    # Add time information
    phases.attrs[
        "timeOffset"] = 0.  # Time offset with respect to basePath's time
    # phases positions. - Staggered position within a cell
    phases["x"].attrs["position"] = numpy.array([0.0, 0.5],
                                                dtype=numpy.float32)
    phases["y"].attrs["position"] = numpy.array([0.5, 0.0],
                                                dtype=numpy.float32)

    phases["x"][:, :] = numpy.angle(Ex)
    phases["y"][:, :] = numpy.angle(Ey)

    print(
        "Found %e and %e photons for horizontal and vertical polarization, respectively."
        % (sum_x, sum_y))

    opmd_h5.close()
    h5.close()
Example #4
0
def convertTxtToOPMD(esther_dirname=None):
    """
    Converts the esther .txt output files to opmd conform hdf5.
    @param esther_dirname: Path (absolute or relative) of the directory containing esther output.
    @type : str
    """
    # Check input.
    if not os.path.isdir(esther_dirname):
        raise IOError("%s is not a directory or link to a directory." %
                      (esther_dirname))

    # Get files in directory.
    dir_listing = os.listdir(esther_dirname)

    # We need these files.
    expected_files = [
        'densite_massique.txt', 'temperature_du_milieu.txt',
        'pression_hydrostatique.txt', 'vitesse_moyenne.txt',
        'position_externe_relative.txt'
    ]

    if not all([f in dir_listing for f in expected_files]):
        raise IOError(
            "%s does not contain all relevant information (density, temperature, pressure, velocity and position. Will abort now."
        )

    # Ok let's start reading header information.
    with open(esther_dirname + "/densite_massique.txt") as f:

        tmp = f.readline()  # Save header line as temp.
        tmp = tmp.split()  # Split header line to obtain timesteps and zones.
        number_of_timesteps = int(tmp[0])
        number_of_zones = int(tmp[1])

        # Close.
        f.close()

        # Load data via numpy.
        rho_array = numpy.loadtxt(str(esther_dirname) +
                                  "/densite_massique.txt",
                                  skiprows=3,
                                  unpack=True)
        pres_array = numpy.loadtxt(str(esther_dirname) +
                                   "/pression_hydrostatique.txt",
                                   skiprows=3,
                                   unpack=True)
        temp_array = numpy.loadtxt(str(esther_dirname) +
                                   "/temperature_du_milieu.txt",
                                   skiprows=3,
                                   unpack=True)
        vel_array = numpy.loadtxt(str(esther_dirname) + "/vitesse_moyenne.txt",
                                  skiprows=3,
                                  unpack=True)
        pos_array = numpy.loadtxt(str(esther_dirname) +
                                  "/position_externe_relative.txt",
                                  skiprows=3,
                                  unpack=True)

        # Slice out the timestamps.
        time_array = rho_array[0]
    time_array = time_array
    time_step = time_array[1] - time_array[0]

    # Create opmd.h5 output file
    h5_path = str(esther_dirname) + "/output.opmd.h5"
    with h5py.File(h5_path, 'w') as opmd_h5:

        # Setup the root attributes.
        opmd.setup_root_attr(opmd_h5, extension="HYDRO1D")

        # Loop over all timestamps.
        for it in range(number_of_timesteps):
            # Write opmd
            full_meshes_path = opmd.get_basePath(
                opmd_h5, it) + opmd_h5.attrs["meshesPath"]

            # Setup basepath
            opmd.setup_base_path(opmd_h5,
                                 iteration=it,
                                 time=rho_array[0, it],
                                 time_step=time_step)
            opmd_h5.create_group(full_meshes_path)
            meshes = opmd_h5[full_meshes_path]

            # Create and save datasets
            meshes.create_dataset('rho', data=rho_array[1:, it])
            meshes.create_dataset('pres', data=pres_array[1:, it])
            meshes.create_dataset('temp', data=temp_array[1:, it])
            meshes.create_dataset('vel', data=vel_array[1:, it])
            meshes.create_dataset('pos', data=pos_array[1:, it])

            # Assign documentation.
            meshes['rho'].attrs[
                "info"] = "Mass density (mass per unit volume) stored on a 1D Lagrangian grid (zones)."
            meshes['pres'].attrs[
                "info"] = "Hydrostatic pressure stored on a 1D Lagrangian grid (zones)."
            meshes['temp'].attrs[
                "info"] = "Temperature stored on a 1D Lagrangian grid (zones)."
            meshes['vel'].attrs[
                "info"] = "Average velocity stored on a 1D Lagrangian grid (zones)."
            meshes['pos'].attrs[
                "info"] = "External position stored on a 1D Lagrangian grid (zones)."

            # Assign SI units
            #                L      M     t     I     T     N     Lum
            meshes['rho'].attrs["unitDimension"] = \
                numpy.array([-3.0,  1.0,  0.0,  0.0,  0.0,  0.0,  0.0], dtype=numpy.float64) # kg m^-3
            meshes['pres'].attrs["unitDimension"] = \
                numpy.array([ 1.0, -1.0, -2.0,  0.0,  0.0,  0.0,  0.0], dtype=numpy.float64) # N m^-2 = kg m s^-2 m^-2 = kg m^-1 s^-2
            meshes['temp'].attrs["unitDimension"] = \
                numpy.array([ 0.0,  0.0,  0.0,  0.0,  1.0,  0.0,  0.0], dtype=numpy.float64) # K
            meshes['vel'].attrs["unitDimension"] = \
                numpy.array([ 1.0,  0.0, -1.0,  0.0,  0.0,  0.0,  0.0], dtype=numpy.float64) # m s^-1
            meshes['pos'].attrs["unitDimension"] = \
                numpy.array([ 1.0,  0.0, 0.0,  0.0,  0.0,  0.0,  0.0], dtype=numpy.float64) # m

            # Write common attributes.
            axis_label = ["Zones"]
            geometry = numpy.string_("other")
            grid_spacing = [numpy.float64(1.0)]
            grid_global_offset = [numpy.float64(0.0)]
            grid_unit_si = numpy.float64(1.0)
            time_offset = 0.0
            data_order = numpy.string_("C")

            # Write the common metadata to pass test
            for key in meshes.keys():
                meshes[key].attrs["unitSI"] = 1.0
                meshes[key].attrs["axisLabels"] = axis_label
                meshes[key].attrs["geometry"] = geometry
                meshes[key].attrs["gridSpacing"] = grid_spacing
                meshes[key].attrs["gridGlobalOffset"] = grid_global_offset
                meshes[key].attrs["gridUnitSI"] = grid_unit_si
                meshes[key].attrs["timeOffset"] = time_offset
                meshes[key].attrs["dataOrder"] = data_order
                meshes[key].attrs["position"] = numpy.array(
                    [0.5, 0.5], dtype=numpy.float32)

        opmd_h5.close()

        return os.path.abspath(h5_path)
Example #5
0
def convertToOPMD(input_file):
    """ Take native wpg output and rewrite in openPMD conformant way.
    :param input_file: The hdf5 file to be converted.
    :type  input_file: string

    :example: convertToOPMD(input_file="prop_out.h5")
    """
    # Check input file.
    if not h5py.is_hdf5(input_file):
        raise IOError("Not a valid hdf5 file: %s. " % (input_file))

    # Read the data into memory.
    with h5py.File(input_file, 'r') as h5:

        ## Branch off if this is a non-time dependent calculation in frequency domain.
        #if data_shape[2] == 1 and h5['params/wDomain'][()] == "frequency":
        ## Time independent calculation in frequency domain.
        #_convert_from_frequency_representation(h5, opmd_h5, data_shape)
        #return

        number_of_x_meshpoints = h5['params/Mesh/nx'][()]
        number_of_y_meshpoints = h5['params/Mesh/ny'][()]
        number_of_time_steps = h5['params/Mesh/nSlices'][()]

        time_max = h5['params/Mesh/sliceMax'][()]
        time_min = h5['params/Mesh/sliceMin'][()]
        time_step = abs(time_max - time_min) / number_of_time_steps  #s

        photon_energy = h5['params/photonEnergy'][()]
        photon_energy = photon_energy * e  # Convert to J

        # matrix dataset to write with values 0...size*size-1
        print("Read geometry: ({0}x{1}x{2}).".format(number_of_x_meshpoints,
                                                     number_of_y_meshpoints,
                                                     number_of_time_steps))

        # open file for writing
        opmd_fname = input_file.replace(".h5", ".opmd.h5")

        series = opmd.Series(opmd_fname, opmd.Access_Type.create)

        # Add metadata
        series.set_author("SIMEX")

        ### FIXME: For some obscure reason, have to local import time module here, othewise
        ### FIXME: get runtime error about "time" not being assigned.
        import time
        localtime = time.localtime()
        date_string = "{}-{}-{} {}:{}:{} {}".format(
            localtime.tm_year,
            localtime.tm_mon,
            localtime.tm_mday,
            localtime.tm_hour,
            localtime.tm_min,
            localtime.tm_sec,
            localtime.tm_zone,
        )
        # Base standard attributes.
        series.set_date(date_string)
        series.set_software("WavePropaGator (WPG)")
        series.set_software_version(h5["info/package_version"][()])

        # WAVEFRONT extension attributes.
        series.set_attribute("beamline",
                             str(h5['params/beamline/printout'][()]))
        series.set_attribute("temporal domain", str(h5["params/wDomain"][()]))
        series.set_attribute("spatial domain", str(h5["params/wSpace"][()]))

        # Further comments.
        series.set_comment(
            "This series is based on output from a WPG run converted to \
                           openPMD format using the utility %s, part of the SimEx library. "
            % (__file__))

        # Loop over time slices.
        print("Converting {0:s} to openpmd compliant {1:s}.".format(
            input_file, opmd_fname))

        # Add constant data here.
        series.set_attribute("radius of curvature in x", h5["params/Rx"][()])
        series.set_attribute("z coordinate", h5["params/Mesh/zCoord"][()])
        series.set_attribute("Rx_Unit_Dimension", [1, 0, 0, 0, 0, 0, 0])
        series.set_attribute("Rx_UnitSI", 1.0)
        series.set_attribute("radius of curvature in y", h5["params/Ry"][()])
        series.set_attribute("Ry_Unit_Dimension", [1, 0, 0, 0, 0, 0, 0])
        series.set_attribute("Ry_UnitSI", 1.0)
        series.set_attribute("Delta radius of curvature in x",
                             h5["params/dRx"][()])
        series.set_attribute("DRx_Unit_Dimension", [1, 0, 0, 0, 0, 0, 0])
        series.set_attribute("DRx_UnitSI", 1.0)
        series.set_attribute("Delta radius of curvature in y",
                             h5["params/dRy"][()])
        series.set_attribute("DRy_Unit_Dimension", [1, 0, 0, 0, 0, 0, 0])
        series.set_attribute("DRy_UnitSI", 1.0)
        series.set_attribute("photon energy", h5['params/photonEnergy'][()])
        series.set_attribute("photon energy unit dimension",
                             [2, 1, -2, 0, 0, 0, 0])
        series.set_attribute("photon energy UnitSI", e)

        for time_step in range(number_of_time_steps):

            E_hor_real = series.iterations[time_step + 1].meshes["E_real"]["x"]
            E_hor_imag = series.iterations[time_step + 1].meshes["E_imag"]["x"]
            E_ver_real = series.iterations[time_step + 1].meshes["E_real"]["y"]
            E_ver_imag = series.iterations[time_step + 1].meshes["E_imag"]["y"]

            ehor_re = h5['data/arrEhor'][:, :, time_step,
                                         0].astype(numpy.float64)
            ehor_im = h5['data/arrEhor'][:, :, time_step,
                                         1].astype(numpy.float64)
            ever_re = h5['data/arrEver'][:, :, time_step,
                                         0].astype(numpy.float64)
            ever_im = h5['data/arrEver'][:, :, time_step,
                                         1].astype(numpy.float64)

            ehor_re_dataset = opmd.Dataset(
                ehor_re.dtype,
                [number_of_x_meshpoints, number_of_y_meshpoints])
            ehor_im_dataset = opmd.Dataset(
                ehor_im.dtype,
                [number_of_x_meshpoints, number_of_y_meshpoints])
            ever_re_dataset = opmd.Dataset(
                ever_re.dtype,
                [number_of_x_meshpoints, number_of_y_meshpoints])
            ever_im_dataset = opmd.Dataset(
                ever_im.dtype,
                [number_of_x_meshpoints, number_of_y_meshpoints])

            E_hor_real.reset_dataset(ehor_re_dataset)
            E_hor_imag.reset_dataset(ehor_im_dataset)
            E_ver_real.reset_dataset(ever_re_dataset)
            E_ver_imag.reset_dataset(ever_im_dataset)

            E_hor_real[()] = ehor_re
            E_hor_imag[()] = ehor_im
            E_ver_real[()] = ehor_re
            E_ver_imag[()] = ehor_im

            # Write the common metadata for the group
            E_real = series.iterations[time_step + 1].meshes["E_real"]
            E_imag = series.iterations[time_step + 1].meshes["E_imag"]

            # Get grid geometry.
            E_real.set_geometry(opmd.Geometry.cartesian)
            E_imag.set_geometry(opmd.Geometry.cartesian)

            # Get grid properties.
            nx = h5['params/Mesh/nx'][()]
            xMax = h5['params/Mesh/xMax'][()]
            xMin = h5['params/Mesh/xMin'][()]
            dx = (xMax - xMin) / nx

            ny = h5['params/Mesh/ny'][()]
            yMax = h5['params/Mesh/yMax'][()]
            yMin = h5['params/Mesh/yMin'][()]
            dy = (yMax - yMin) / ny

            tMax = h5['params/Mesh/sliceMax'][()]
            tMin = h5['params/Mesh/sliceMin'][()]
            dt = (tMax - tMin) / number_of_time_steps

            E_real.set_grid_spacing(numpy.array([dx, dy], dtype=numpy.float64))
            E_imag.set_grid_spacing(numpy.array([dx, dy], dtype=numpy.float64))

            E_real.set_grid_global_offset(
                numpy.array(
                    [h5['params/xCentre'][()], h5['params/yCentre'][()]],
                    dtype=numpy.float64))
            E_imag.set_grid_global_offset(
                numpy.array(
                    [h5['params/xCentre'][()], h5['params/yCentre'][()]],
                    dtype=numpy.float64))

            E_real.set_grid_unit_SI(numpy.float64(1.0))
            E_imag.set_grid_unit_SI(numpy.float64(1.0))

            E_real.set_data_order(opmd.Data_Order.C)
            E_imag.set_data_order(opmd.Data_Order.C)

            E_real.set_axis_labels([b"x", b"y"])
            E_imag.set_axis_labels([b"x", b"y"])

            unit_dimension = {
                opmd.Unit_Dimension.L: 1.0,
                opmd.Unit_Dimension.M: 1.0,
                opmd.Unit_Dimension.T: -3.0,
                opmd.Unit_Dimension.I: -1.0,
                opmd.Unit_Dimension.theta: 0.0,
                opmd.Unit_Dimension.N: 0.0,
                opmd.Unit_Dimension.J: 0.0
            }
            E_real.set_unit_dimension(unit_dimension)
            E_imag.set_unit_dimension(unit_dimension)

            # Write attribute that is specific to each dataset:
            # - Staggered position within a cell

            # - Conversion factor to SI units
            # WPG writes E fields in units of sqrt(W/mm^2), i.e. it writes E*sqrt(c * eps0 / 2).
            # Unit analysis:
            # [E] = V/m
            # [eps0] = As/Vm
            # [c] = m/s
            # ==> [E^2 * eps0 * c] = V**2/m**2 * As/Vm * m/s = V*A/m**2 = W/m**2 = [Intensity]
            # Converting to SI units by dividing by sqrt(c*eps0/2)*1e3, 1e3 for conversion from mm to m.
            c = 2.998e8  # m/s
            eps0 = 8.854e-12  # As/Vm
            E_real.set_grid_unit_SI(
                numpy.float64(1.0 / math.sqrt(0.5 * c * eps0) / 1.0e3))
            E_imag.set_grid_unit_SI(
                numpy.float64(1.0 / math.sqrt(0.5 * c * eps0) / 1.0e3))

            # Add particles.

            series.flush()

    # The files in 'series' are still open until the object is destroyed, on
    # which it cleanly flushes and closes all open file handles.
    # One can delete the object explicitly (or let it run out of scope) to
    # trigger this.
    del series

    return

    # Open in and out files.
    if (False):
        # Get number of time slices in wpg output, assuming horizontal and vertical polarizations have same dimensions, which is always true for wpg output.
        data_shape = h5['data/arrEhor'][()].shape

        # Branch off if this is a non-time dependent calculation in frequency domain.
        if data_shape[2] == 1 and h5['params/wDomain'][()] == "frequency":
            # Time independent calculation in frequency domain.
            _convert_from_frequency_representation(h5, opmd_h5, data_shape)
            return

        number_of_x_meshpoints = data_shape[0]
        number_of_y_meshpoints = data_shape[1]
        number_of_time_steps = data_shape[2]

        time_max = h5['params/Mesh/sliceMax'][()]  #s
        time_min = h5['params/Mesh/sliceMin'][()]  #s
        time_step = abs(time_max - time_min) / number_of_time_steps  #s

        photon_energy = h5['params/photonEnergy'][()]  # eV
        photon_energy = photon_energy * e  # Convert to J

        # Copy misc and params from original wpg output.
        opmd_h5.create_group('history/parent')
        try:
            h5.copy('/params', opmd_h5['history/parent'])
            h5.copy('/misc', opmd_h5['history/parent'])
            h5.copy('/history', opmd_h5['history/parent'])

        # Some keys may not exist, e.g. if the input file comes from a non-simex wpg run.
        except KeyError:
            pass
        except:
            raise

        sum_x = 0.0
        sum_y = 0.0
        for it in range(number_of_time_steps):
            # Write opmd
            # Setup the root attributes for iteration 0
            opmd_legacy.setup_root_attr(opmd_h5)

            full_meshes_path = opmd_legacy.get_basePath(
                opmd_h5, it) + opmd_h5.attrs["meshesPath"]
            # Setup basepath.
            time = time_min + it * time_step
            opmd_legacy.setup_base_path(opmd_h5,
                                        iteration=it,
                                        time=time,
                                        time_step=time_step)
            opmd_h5.create_group(full_meshes_path)
            meshes = opmd_h5[full_meshes_path]

            # Path to the E field, within the h5 file.
            full_e_path_name = b"E"
            meshes.create_group(full_e_path_name)
            E = meshes[full_e_path_name]

            # Create the dataset (2d cartesian grid)
            E.create_dataset(b"x",
                             (number_of_x_meshpoints, number_of_y_meshpoints),
                             dtype=numpy.complex64,
                             compression='gzip')
            E.create_dataset(b"y",
                             (number_of_x_meshpoints, number_of_y_meshpoints),
                             dtype=numpy.complex64,
                             compression='gzip')

            # Write the common metadata for the group
            E.attrs["geometry"] = numpy.string_("cartesian")
            # Get grid geometry.
            nx = h5['params/Mesh/nx'][()]
            xMax = h5['params/Mesh/xMax'][()]
            xMin = h5['params/Mesh/xMin'][()]
            dx = (xMax - xMin) / nx
            ny = h5['params/Mesh/ny'][()]
            yMax = h5['params/Mesh/yMax'][()]
            yMin = h5['params/Mesh/yMin'][()]
            dy = (yMax - yMin) / ny
            E.attrs["gridSpacing"] = numpy.array([dx, dy], dtype=numpy.float64)
            E.attrs["gridGlobalOffset"] = numpy.array(
                [h5['params/xCentre'][()], h5['params/yCentre'][()]],
                dtype=numpy.float64)
            E.attrs["gridUnitSI"] = numpy.float64(1.0)
            E.attrs["dataOrder"] = numpy.string_("C")
            E.attrs["axisLabels"] = numpy.array([b"x", b"y"])
            E.attrs["unitDimension"] = \
               numpy.array([1.0, 1.0, -3.0, -1.0, 0.0, 0.0, 0.0 ], dtype=numpy.float64)
            #            L    M     T     I  theta  N    J
            # E is in volts per meters: V / m = kg * m / (A * s^3)
            # -> L * M * T^-3 * I^-1

            # Add time information
            E.attrs[
                "timeOffset"] = 0.  # Time offset with respect to basePath's time

            # Write attribute that is specific to each dataset:
            # - Staggered position within a cell
            E["x"].attrs["position"] = numpy.array([0.0, 0.5],
                                                   dtype=numpy.float32)
            E["y"].attrs["position"] = numpy.array([0.5, 0.0],
                                                   dtype=numpy.float32)

            # - Conversion factor to SI units
            # WPG writes E fields in units of sqrt(W/mm^2), i.e. it writes E*sqrt(c * eps0 / 2).
            # Unit analysis:
            # [E] = V/m
            # [eps0] = As/Vm
            # [c] = m/s
            # ==> [E^2 * eps0 * c] = V**2/m**2 * As/Vm * m/s = V*A/m**2 = W/m**2 = [Intensity]
            # Converting to SI units by dividing by sqrt(c*eps0/2)*1e3, 1e3 for conversion from mm to m.
            c = 2.998e8  # m/s
            eps0 = 8.854e-12  # As/Vm
            E["x"].attrs["unitSI"] = numpy.float64(
                1.0 / math.sqrt(0.5 * c * eps0) / 1.0e3)
            E["y"].attrs["unitSI"] = numpy.float64(
                1.0 / math.sqrt(0.5 * c * eps0) / 1.0e3)

            # Copy the fields.
            Ex = h5['data/arrEhor'][:, :, it,
                                    0] + 1j * h5['data/arrEhor'][:, :, it, 1]
            Ey = h5['data/arrEver'][:, :, it,
                                    0] + 1j * h5['data/arrEver'][:, :, it, 1]
            E["x"][:, :] = Ex
            E["y"][:, :] = Ey

            # Get area element.
            dA = dx * dy

            ### Number of photon fields.
            # Path to the number of photons.
            full_nph_path_name = b"Nph"
            meshes.create_group(full_nph_path_name)
            Nph = meshes[full_nph_path_name]

            # Create the dataset (2d cartesian grid)
            Nph.create_dataset(
                b"x", (number_of_x_meshpoints, number_of_y_meshpoints),
                dtype=numpy.float32,
                compression='gzip')
            Nph.create_dataset(
                b"y", (number_of_x_meshpoints, number_of_y_meshpoints),
                dtype=numpy.float32,
                compression='gzip')

            # Write the common metadata for the group
            Nph.attrs["geometry"] = numpy.string_("cartesian")
            Nph.attrs["gridSpacing"] = numpy.array([dx, dy],
                                                   dtype=numpy.float64)
            Nph.attrs["gridGlobalOffset"] = numpy.array(
                [h5['params/xCentre'][()], h5['params/yCentre'][()]],
                dtype=numpy.float64)
            Nph.attrs["gridUnitSI"] = numpy.float64(1.0)
            Nph.attrs["dataOrder"] = numpy.string_("C")
            Nph.attrs["axisLabels"] = numpy.array([b"x", b"y"])
            Nph.attrs["unitDimension"] = \
               numpy.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], dtype=numpy.float64)

            # Add time information
            Nph.attrs[
                "timeOffset"] = 0.  # Time offset with respect to basePath's time
            # Nph - Staggered position within a cell
            Nph["x"].attrs["position"] = numpy.array([0.0, 0.5],
                                                     dtype=numpy.float32)
            Nph["y"].attrs["position"] = numpy.array([0.5, 0.0],
                                                     dtype=numpy.float32)
            Nph["x"].attrs["unitSI"] = numpy.float64(1.0)
            Nph["y"].attrs["unitSI"] = numpy.float64(1.0)

            # Calculate number of photons via intensity and photon energy.
            # Since fields are stored as sqrt(W/mm^2), have to convert to W/m^2 (factor 1e6 below).
            number_of_photons_x = numpy.round(
                abs(Ex)**2 * dA * time_step * 1.0e6 / photon_energy)
            number_of_photons_y = numpy.round(
                abs(Ey)**2 * dA * time_step * 1.0e6 / photon_energy)
            sum_x += number_of_photons_x.sum(axis=-1).sum(axis=-1)
            sum_y += number_of_photons_y.sum(axis=-1).sum(axis=-1)
            Nph["x"][:, :] = number_of_photons_x
            Nph["y"][:, :] = number_of_photons_y

            ### Phases.
            # Path to phases
            full_phases_path_name = b"phases"
            meshes.create_group(full_phases_path_name)
            phases = meshes[full_phases_path_name]

            # Create the dataset (2d cartesian grid)
            phases.create_dataset(
                b"x", (number_of_x_meshpoints, number_of_y_meshpoints),
                dtype=numpy.float32,
                compression='gzip')
            phases.create_dataset(
                b"y", (number_of_x_meshpoints, number_of_y_meshpoints),
                dtype=numpy.float32,
                compression='gzip')

            # Write the common metadata for the group
            phases.attrs["geometry"] = numpy.string_("cartesian")
            phases.attrs["gridSpacing"] = numpy.array([dx, dy],
                                                      dtype=numpy.float64)
            phases.attrs["gridGlobalOffset"] = numpy.array(
                [h5['params/xCentre'][()], h5['params/yCentre'][()]],
                dtype=numpy.float64)
            phases.attrs["gridUnitSI"] = numpy.float64(1.0)
            phases.attrs["dataOrder"] = numpy.string_("C")
            phases.attrs["axisLabels"] = numpy.array([b"x", b"y"])
            phases.attrs["unitDimension"] = numpy.array(
                [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], dtype=numpy.float64)
            phases["x"].attrs["unitSI"] = numpy.float64(1.0)
            phases["y"].attrs["unitSI"] = numpy.float64(1.0)

            # Add time information
            phases.attrs[
                "timeOffset"] = 0.  # Time offset with respect to basePath's time
            # phases positions. - Staggered position within a cell
            phases["x"].attrs["position"] = numpy.array([0.0, 0.5],
                                                        dtype=numpy.float32)
            phases["y"].attrs["position"] = numpy.array([0.5, 0.0],
                                                        dtype=numpy.float32)

            phases["x"][:, :] = numpy.angle(Ex)
            phases["y"][:, :] = numpy.angle(Ey)

    print(
        "Found %e and %e photons for horizontal and vertical polarization, respectively."
        % (sum_x, sum_y))
Example #6
0
def convertToOPMD(input_path):
    """ Convert xmdyn output stored on disk into an openPMD compatible hdf5.

    :param input_path: The directory containing xmdyn output.
    :type input_path: str

    """

    # Check input path.
    if not os.path.isdir(input_path):
        raise IOError("Directory %s not found." % (input_path))

    # Check all required data is present.
    snapshot_dir = os.path.join(input_path, 'snp')
    if not os.path.isdir(snapshot_dir):
        raise IOError("%s does not contain a snapshot directory snp/." %
                      (input_path))

    # Get all snapshot directories.
    snapshots = os.listdir(snapshot_dir)

    # Get number of snapshots.
    number_of_snapshots = len(snapshots)
    if len(number_of_snapshots) == 0:
        raise RuntimeError("%s does not contain any snapshots." %
                           (snapshot_dir))

    # Sort dirs.
    snapshots.sort()

    # Check and parse xmdyn input file to extract time steps and photon numbers.
    input_file_path = os.path.join(
        input_path, 'xparams.txt'
    )  # We use the file written at xmdyn runtime which reflects the actual state of affairs.
    if not os.path.isfile(input_file_path):
        raise IOError("XMDYN input file %s was not found." % (input_file_path))

    xmdyn_parameters = _parse_xmdyn_xparams(input_file_path)

    # Setup a pmi demo object to facilitate loading of data.
    pmi = PMIDemo()

    # Open in and out files.
    with h5py.File("xmdy_out.opmd.h5", 'w') as opmd_h5:

        time_max = xmdyn_parameters['stop_time'].m_as(second)
        time_min = xmdyn_parameters['start_time'].m_as(second)
        time_step = xmdyn_parameters['time_step'].m_as(second)

        photon_energy = xmdyn_parameters['photon_energy'].m_as(joule)

        sum_x = 0.0
        sum_y = 0.0

        for it, snp in enumerate(snapshots):

            # Load snapshot data as a dict
            snapshot_dict = pmi.f_load_snp_from_dir(snp)

            # Write opmd
            # Setup the root attributes for iteration 0
            opmd.setup_root_attr(opmd_h5)

            full_meshes_path = opmd.get_basePath(
                opmd_h5, it) + opmd_h5.attrs["meshesPath"]
            # Setup basepath.
            time = time_min + it * time_step
            opmd.setup_base_path(opmd_h5,
                                 iteration=it,
                                 time=time,
                                 time_step=time_step)
            opmd_h5.create_group(full_meshes_path)
            meshes = opmd_h5[full_meshes_path]

            # Form factors
            ff_path = b"form factor"
            meshes.create_group(ff_path)
            ff = meshes[ff_path]

            # Create the dataset (1d grid)
            f0 = ff.create_dataset(b"f0",
                                   snapshot_dict['f0'].shape,
                                   dtype=numpy.float64,
                                   compression='gzip')
            q = ff.create_dataset(b"q",
                                  snapshot_dict['Q'].shape,
                                  dtype=numpy.float64,
                                  compression='gzip')

            f0.attrs["gridUnitSI"] = numpy.float64(1.0)
            f0.attrs["dataOrder"] = numpy.string_("C")
            f0.attrs["axisLabels"] = numpy.array([b"f0"])
            f0.attrs["unitDimension"] = numpy.array(
                [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], dtype=numpy.float64)
            #                                           L    M    T    I  th     N    J
            q.attrs["gridUnitSI"] = numpy.float64(1.0)
            q.attrs["dataOrder"] = numpy.string_("C")
            q.attrs["axisLabels"] = numpy.array([b"q"])
            q.attrs["unitDimension"] = numpy.array(
                [-1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], dtype=numpy.float64)
            #                                          L    M    T    I   th    N    J

            # Copy the fields.
            ff["q"][:] = snapshot_dict['Q']
            ff["f0"][:] = snapshot_dict['f0']

            # Particles.
            full_particles_path = opmd.get_basePath(
                opmd_h5, it) + opmd_h5.attrs["particlesPath"]
            opmd.setup_base_path(opmd_h5,
                                 iteration=it,
                                 time=time,
                                 time_step=time_step)
            particles = opmd_h5.create_group(full_particles_path)

            # Atoms and ions.
            ions_path = b"Ions"
            ions = particles.create_group(ions_path)

            # Loop over elements
            #unique_atom_numbers = snapshot_dict['Z'].unique()
            #for uatm_idx, uatm in enumerate(unique_atom_numbers):
            #symbol = elements[uatm].symbol
            #species = ions.create_group(symbol)

            # Loop over atom types and create a group for each.
            for idx, econf in snapshot_dict['econf']:
                econf_group = ions.create_group(econf)

                indices = numpy.where(snapshot_dict['T'] == idx)
                position = econf_group.create_group('position')
                x = snapshot_dict['r'][indices, 0]
                y = snapshot_dict['r'][indices, 1]
                z = snapshot_dict['r'][indices, 2]
                position.create_dataset('x', data=x)
                position.create_dataset('y', data=y)
                position.create_dataset('z', data=z)

                velocity = econf_group.create_group('velocity')
                vx = snapshot_dict['v'][indices, 0]
                vy = snapshot_dict['v'][indices, 1]
                vz = snapshot_dict['v'][indices, 2]
                velocity.create_dataset('x', data=vx)
                velocity.create_dataset('y', data=vy)
                velocity.create_dataset('z', data=vz)

                charge = econf_group.create_dataset(
                    'charge', data=snapshot_dict['q'][indices])
                mass = econf_group.create_dataset(
                    'mass', data=snapshot_dict['m'][indices])
                uid = econf_group.create_dataset(
                    'id', data=snapshot_dict['uid'][indices])
                Z = econf_group.create_dataset(
                    'Z', data=snapshot_dict['q'][indices])
def convertTxtToOPMD(esther_dirname=None):
    """
    Converts the esther .txt output files to opmd conform hdf5.
    @param esther_dirname: Path (absolute or relative) of the directory containing esther output.
    @type : str
    """
    # Check input.
    if not os.path.isdir( esther_dirname):
        raise IOError( "%s is not a directory or link to a directory.")

    # Get files in directory.
    dir_listing = os.listdir( esther_dirname)

    # We need these files.
    expected_files = ['densite_massique.txt', 'temperature_du_milieu.txt', 'pression_hydrostatique.txt', 'vitesse_moyenne.txt', 'position_externe_relative.txt']

    if not all([f in dir_listing for f in expected_files]):
        raise IOError( "%s does not contain all relevant information (density, temperature, pressure, velocity and position. Will abort now." )

    # Ok let's start reading header information.
    with open(esther_dirname+"/densite_massique.txt") as f:

        tmp = f.readline() # Save header line as temp.
        tmp = tmp.split() # Split header line to obtain timesteps and zones.
        number_of_timesteps = int(tmp[0])
        number_of_zones = int(tmp[1])

        # Close.
        f.close()

	# Load data via numpy.
	rho_array = numpy.loadtxt(str(esther_dirname)+"/densite_massique.txt",skiprows=3,unpack=True)
	pres_array = numpy.loadtxt(str(esther_dirname)+"/pression_hydrostatique.txt",skiprows=3,unpack=True)
	temp_array = numpy.loadtxt(str(esther_dirname)+"/temperature_du_milieu.txt",skiprows=3,unpack=True)
	vel_array = numpy.loadtxt(str(esther_dirname)+"/vitesse_moyenne.txt",skiprows=3,unpack=True)
	pos_array = numpy.loadtxt(str(esther_dirname)+"/position_externe_relative.txt",skiprows=3,unpack=True)

    # Slice out the timestamps.
	time_array = rho_array[0]
    time_array = time_array
    time_step = time_array[1] - time_array[0]

    # Create opmd.h5 output file
    with h5py.File(str(esther_dirname)+".opmd.h5", 'w') as opmd_h5:

        # Setup the root attributes.
        opmd.setup_root_attr( opmd_h5, extension="HYDRO1D" )

        # Loop over all timestamps.
        for it in range(number_of_timesteps):
            # Write opmd
            full_meshes_path = opmd.get_basePath(opmd_h5, it) + opmd_h5.attrs["meshesPath"]

            # Setup basepath
            opmd.setup_base_path( opmd_h5, iteration=it, time=rho_array[0,it], time_step=time_step)
            opmd_h5.create_group(full_meshes_path)
            meshes = opmd_h5[full_meshes_path]


            # Create and save datasets
            meshes.create_dataset('rho',  data=rho_array[1:,it])
            meshes.create_dataset('pres', data=pres_array[1:,it])
            meshes.create_dataset('temp', data=temp_array[1:,it])
            meshes.create_dataset('vel',  data=vel_array[1:,it])
            meshes.create_dataset('pos',  data=pos_array[1:,it])

            # Assign documentation.
            meshes['rho'].attrs["info"] = "Mass density (mass per unit volume) stored on a 1D Lagrangian grid (zones)."
            meshes['pres'].attrs["info"] = "Hydrostatic pressure stored on a 1D Lagrangian grid (zones)."
            meshes['temp'].attrs["info"] = "Temperature stored on a 1D Lagrangian grid (zones)."
            meshes['vel'].attrs["info"] = "Average velocity stored on a 1D Lagrangian grid (zones)."
            meshes['pos'].attrs["info"] = "External position stored on a 1D Lagrangian grid (zones)."

            # Assign SI units
            #                L      M     t     I     T     N     Lum
            meshes['rho'].attrs["unitDimension"] = \
                numpy.array([-3.0,  1.0,  0.0,  0.0,  0.0,  0.0,  0.0], dtype=numpy.float64) # kg m^-3
            meshes['pres'].attrs["unitDimension"] = \
                numpy.array([ 1.0, -1.0, -2.0,  0.0,  0.0,  0.0,  0.0], dtype=numpy.float64) # N m^-2 = kg m s^-2 m^-2 = kg m^-1 s^-2
            meshes['temp'].attrs["unitDimension"] = \
                numpy.array([ 0.0,  0.0,  0.0,  0.0,  1.0,  0.0,  0.0], dtype=numpy.float64) # K
            meshes['vel'].attrs["unitDimension"] = \
                numpy.array([ 1.0,  0.0, -1.0,  0.0,  0.0,  0.0,  0.0], dtype=numpy.float64) # m s^-1
            meshes['pos'].attrs["unitDimension"] = \
                numpy.array([ 1.0,  0.0, 0.0,  0.0,  0.0,  0.0,  0.0], dtype=numpy.float64) # m

            # Write common attributes.
            axis_label = ["Zones"]
            geometry = numpy.string_("other")
            grid_spacing = [numpy.float64(1.0)]
            grid_global_offset = [numpy.float64(0.0)]
            grid_unit_si = numpy.float64(1.0)
            time_offset = 0.0
            data_order = numpy.string_("C")

            # Write the common metadata to pass test
            for key in meshes.keys():
                meshes[key].attrs["unitSI"] = 1.0
                meshes[key].attrs["axisLabels"] = axis_label
                meshes[key].attrs["geometry"] = geometry
                meshes[key].attrs["gridSpacing"] = grid_spacing
                meshes[key].attrs["gridGlobalOffset"] = grid_global_offset
                meshes[key].attrs["gridUnitSI"] = grid_unit_si
                meshes[key].attrs["timeOffset"] = time_offset
                meshes[key].attrs["dataOrder"] = data_order
                meshes[key].attrs["position"] = numpy.array([0.5, 0.5], dtype=numpy.float32)

        opmd_h5.close()