Skip to content

Writers

superfish.writers

Classes

Functions:

superfish.writers.fish_externalfield_data
fish_externalfield_data(
    t7data,
    eleAnchorPt="beginning",
    fieldScale=1,
    RFphase=0,
    z_offset=0,
    name=None,
    normalize_by_Ez0=False,
)

Convert Fish t7data to openPMD external field data.

.. deprecated:: Use direct parsing with openPMD-beamphysics instead.

Superfish fields oscillate as::

Er, Ez ~ cos(wt)
Hphi   ~ -sin(wt)

For complex fields oscillating as e^-iwt::

Re(Ex*e^-iwt)  ~ cos
Re(-iB*e^-iwt) ~ -sin

and therefore B = -i * mu_0 * H_phi is the complex magnetic field in Tesla.

Parameters:

Name Type Description Default
t7data FishT7Data

Parsed T7 data in the native Superfish units, as returned by :func:superfish.parsers.parse_fish_t7.

required
eleAnchorPt (beginning, center, end)

Element anchor point attribute.

"beginning"
fieldScale float

Unused.

1
RFphase float

RF phase attribute.

0
z_offset float

Offset added to the grid origin in z, in meters.

0
name str

Name attribute.

None
normalize_by_Ez0 bool

Normalize the fields by the maximum on-axis Ez.

False

Returns:

Type Description
ExternalFieldData

Keys attrs and components, ready to be written to an HDF5 file.

Source code in superfish/writers.py
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
def fish_externalfield_data(
    t7data: FishT7Data,
    eleAnchorPt: str = "beginning",
    fieldScale: float = 1,
    RFphase: float = 0,
    z_offset: float = 0,
    name: str | None = None,
    normalize_by_Ez0: bool = False,
) -> ExternalFieldData:
    """
    Convert Fish t7data to openPMD external field data.

    .. deprecated::
        Use direct parsing with openPMD-beamphysics instead.

    Superfish fields oscillate as::

        Er, Ez ~ cos(wt)
        Hphi   ~ -sin(wt)

    For complex fields oscillating as e^-iwt::

        Re(Ex*e^-iwt)  ~ cos
        Re(-iB*e^-iwt) ~ -sin

    and therefore B = -i * mu_0 * H_phi is the complex magnetic field in
    Tesla.

    Parameters
    ----------
    t7data : FishT7Data
        Parsed T7 data in the native Superfish units, as returned by
        :func:`superfish.parsers.parse_fish_t7`.
    eleAnchorPt : {"beginning", "center", "end"}
        Element anchor point attribute.
    fieldScale : float
        Unused.
    RFphase : float
        RF phase attribute.
    z_offset : float
        Offset added to the grid origin in z, in meters.
    name : str, optional
        Name attribute.
    normalize_by_Ez0 : bool
        Normalize the fields by the maximum on-axis Ez.

    Returns
    -------
    ExternalFieldData
        Keys ``attrs`` and ``components``, ready to be written to an HDF5
        file.
    """
    warnings.warn(
        "fish_externalfield_data should be replaced by direct parsing using openPMD-beamphyics",
        DeprecationWarning,
    )

    attrs = {}
    attrs["eleAnchorPt"] = eleAnchorPt

    # Use these to calculate spacing
    zmin = t7data["zmin"] * 0.01
    zmax = t7data["zmax"] * 0.01
    rmin = t7data["rmin"] * 0.01
    rmax = t7data["rmax"] * 0.01

    assert rmin == 0, f"rmin is not zero: {rmin}"

    nr = t7data["nr"]
    nz = t7data["nz"]

    dz = (zmax - zmin) / (nz - 1)
    dr = (rmax) / (nr - 1)

    attrs["gridGeometry"] = "cylindrical"
    attrs["axisLabels"] = ("r", "theta", "z")
    attrs["gridLowerBound"] = (0, 1, 0)
    attrs["gridSize"] = (nr, 1, nz)
    attrs["gridSpacing"] = (dr, 0, dz)

    # Set requested zmin
    attrs["gridOriginOffset"] = (0, 0, zmin + z_offset)

    attrs["fundamentalFrequency"] = t7data["freq"] * 1e6

    # Bmad non-standard
    ## attrs['masterParameter'] = 'VOLTAGE'

    attrs["harmonic"] = 1
    attrs["RFphase"] = RFphase

    if name:
        attrs["name"] = name

    # Normalize on-axis field
    if normalize_by_Ez0:
        Ez0_max = 1e6 * np.abs(t7data["Ez"][0, :]).max()  # V/m
    else:
        Ez0_max = 1

    components = {}
    components["electricField/r"] = (
        t7data["Er"].reshape(nr, 1, nz).astype(complex) * 1e6 / Ez0_max
    )
    components["electricField/z"] = (
        t7data["Ez"].reshape(nr, 1, nz).astype(complex) * 1e6 / Ez0_max
    )
    components["magneticField/theta"] = (
        t7data["Hphi"].reshape(nr, 1, nz) * -1j * mu_0 / Ez0_max
    )  # -i * mu_0

    return dict(attrs=attrs, components=components)
superfish.writers.poisson_externalfield_data
poisson_externalfield_data(
    t7data,
    eleAnchorPt="beginning",
    fieldScale=1,
    type="electric",
    z_offset=0,
    name=None,
    normalize_by_fz0=False,
)

Convert Poisson t7data to openPMD external field data.

Parameters:

Name Type Description Default
t7data PoissonT7Data

Parsed T7 data in the native Superfish units, as returned by :func:superfish.parsers.parse_poisson_t7.

required
eleAnchorPt (beginning, center, end)

Element anchor point attribute.

"beginning"
fieldScale float

Unused.

1
type (electric, magnetic)

Type of field data in t7data.

"electric"
z_offset float

Offset added to the grid origin in z, in meters.

0
name str

Name attribute.

None
normalize_by_fz0 bool

Normalize the fields by the maximum on-axis z field.

False

Returns:

Type Description
ExternalFieldData

Keys attrs and components, ready to be written to an HDF5 file.

Source code in superfish/writers.py
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
def poisson_externalfield_data(
    t7data: PoissonT7Data,
    eleAnchorPt: str = "beginning",
    fieldScale: float = 1,
    type: str = "electric",
    z_offset: float = 0,
    name: str | None = None,
    normalize_by_fz0: bool = False,
) -> ExternalFieldData:
    """
    Convert Poisson t7data to openPMD external field data.

    Parameters
    ----------
    t7data : PoissonT7Data
        Parsed T7 data in the native Superfish units, as returned by
        :func:`superfish.parsers.parse_poisson_t7`.
    eleAnchorPt : {"beginning", "center", "end"}
        Element anchor point attribute.
    fieldScale : float
        Unused.
    type : {"electric", "magnetic"}
        Type of field data in ``t7data``.
    z_offset : float
        Offset added to the grid origin in z, in meters.
    name : str, optional
        Name attribute.
    normalize_by_fz0 : bool
        Normalize the fields by the maximum on-axis z field.

    Returns
    -------
    ExternalFieldData
        Keys ``attrs`` and ``components``, ready to be written to an HDF5
        file.
    """

    attrs = {}

    assert eleAnchorPt in ["beginning", "center", "end"], (
        f"Unallowed eleAnchorPt point: {eleAnchorPt}"
    )

    attrs["eleAnchorPt"] = eleAnchorPt

    # Use these to calculate spacing
    zmin = t7data["zmin"] * 0.01
    zmax = t7data["zmax"] * 0.01
    rmin = t7data["rmin"] * 0.01
    rmax = t7data["rmax"] * 0.01

    assert rmin == 0, f"rmin is not zero: {rmin}"

    nr = t7data["nr"]
    nz = t7data["nz"]

    dz = (zmax - zmin) / (nz - 1)
    dr = (rmax) / (nr - 1)

    attrs["gridGeometry"] = "cylindrical"
    attrs["axisLabels"] = ("r", "theta", "z")
    attrs["gridLowerBound"] = (0, 1, 0)
    attrs["gridSize"] = (nr, 1, nz)
    attrs["gridSpacing"] = (dr, 0, dz)

    # Set requested zmin
    attrs["gridOriginOffset"] = (0, 0, zmin + z_offset)

    attrs["fundamentalFrequency"] = 0
    attrs["harmonic"] = 0
    attrs["RFphase"] = 0

    if name:
        attrs["name"] = name

    if type == "electric":
        fr = "Er"
        fz = "Ez"
        ofr = "electricField/r"  # Ouptut names
        ofz = "electricField/z"
        factor = 1  # V/m
        # Bmad non-standard
        # attrs['masterParameter'] = 'VOLTAGE'
    elif type == "magnetic":
        fr = "Br"
        fz = "Bz"
        ofr = "magneticField/r"
        ofz = "magneticField/z"
        factor = 1e-4  # G -> T
        # Bmad non-standard
        # attrs['masterParameter'] = 'BS_FIELD'
    else:
        raise ValueError(f"Unknown type: {type}. Allowed: 'electric' or 'magnetic'")

    # Normalize on-axis field
    if normalize_by_fz0:
        fz0_max = np.abs(t7data[fz][0, :] * factor).max()
    else:
        fz0_max = 1

    components = {}
    components[ofr] = t7data[fr].reshape(nr, 1, nz) * factor / fz0_max
    components[ofz] = t7data[fz].reshape(nr, 1, nz) * factor / fz0_max

    return dict(attrs=attrs, components=components)
superfish.writers.write_fish_t7
write_fish_t7(filename, t7data, fmt='%10.8e')

Write a T7 file from a FISH t7data dict.

Parameters:

Name Type Description Default
filename str

Path of the T7 file to write.

required
t7data FishT7Data

Parsed T7 data, as returned by :func:superfish.parsers.parse_fish_t7.

required
fmt str

Number format for the data columns.

'%10.8e'

Returns:

Type Description
str

The filename written to.

See Also

superfish.parsers.parse_fish_t7

Source code in superfish/writers.py
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
def write_fish_t7(
    filename: str,
    t7data: FishT7Data,
    fmt: str = "%10.8e",
) -> str:
    """
    Write a T7 file from a FISH t7data dict.

    Parameters
    ----------
    filename : str
        Path of the T7 file to write.
    t7data : FishT7Data
        Parsed T7 data, as returned by
        :func:`superfish.parsers.parse_fish_t7`.
    fmt : str
        Number format for the data columns.

    Returns
    -------
    str
        The filename written to.

    See Also
    --------
    superfish.parsers.parse_fish_t7
    """

    # Collect these
    xmin = t7data["zmin"]
    xmax = t7data["zmax"]
    nx = t7data["nz"]
    ymin = t7data["rmin"]
    ymax = t7data["rmax"]
    ny = t7data["nr"]
    freq = t7data["freq"]

    header = f"""{xmin} {xmax} {nx - 1}
{freq}
{ymin} {ymax} {ny - 1}"""

    # Unroll the arrays
    dat = np.array([t7data[f].reshape(nx * ny).T for f in ["Ez", "Er", "E", "Hphi"]]).T

    np.savetxt(filename, dat, header=header, comments="", fmt=fmt)

    return filename
superfish.writers.write_poisson_t7
write_poisson_t7(filename, t7data, fmt='%10.8e')

Write a T7 file from a POISSON t7data dict.

Parameters:

Name Type Description Default
filename str

Path of the T7 file to write.

required
t7data PoissonT7Data

Parsed T7 data, as returned by :func:superfish.parsers.parse_poisson_t7.

required
fmt str

Number format for the data columns.

'%10.8e'

Returns:

Type Description
str

The filename written to.

See Also

superfish.parsers.parse_poisson_t7

Source code in superfish/writers.py
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
def write_poisson_t7(
    filename: str,
    t7data: PoissonT7Data,
    fmt: str = "%10.8e",
) -> str:
    """
    Write a T7 file from a POISSON t7data dict.

    Parameters
    ----------
    filename : str
        Path of the T7 file to write.
    t7data : PoissonT7Data
        Parsed T7 data, as returned by
        :func:`superfish.parsers.parse_poisson_t7`.
    fmt : str
        Number format for the data columns.

    Returns
    -------
    str
        The filename written to.

    See Also
    --------
    superfish.parsers.parse_poisson_t7
    """

    # Collect these
    ymin = t7data["zmin"]
    ymax = t7data["zmax"]
    ny = t7data["nz"]
    xmin = t7data["rmin"]
    xmax = t7data["rmax"]
    nx = t7data["nr"]
    # freq = t7data['freq']

    header = f"""{xmin} {xmax} {nx - 1}
{ymin} {ymax} {ny - 1}"""

    if "Ez" in t7data:
        arrays = [t7data["Er"], t7data["Ez"]]
    else:
        arrays = [t7data["Br"], t7data["Bz"]]

    # Unroll the arrays
    dat = np.array([a.reshape(nx * ny, order="F").T for a in arrays]).T

    np.savetxt(filename, dat, header=header, comments="", fmt=fmt)

    return filename