Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Formats for the ELDICO ED-1 #682

Merged
merged 16 commits into from
Jan 26, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions newsfragments/682.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add Bruker and miniCBF format readers for the ELDICO ED-1 electron diffractometer with DECTRIS QUADRO detector.
289 changes: 289 additions & 0 deletions src/dxtbx/format/FormatBrukerED1.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,289 @@
from __future__ import annotations

Check warning on line 1 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L1

Added line #L1 was not covered by tests

from boost_adaptbx.boost.python import streambuf
from scitbx import matrix
from scitbx.array_family import flex

Check warning on line 5 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L3-L5

Added lines #L3 - L5 were not covered by tests

from dxtbx import IncorrectFormatError
from dxtbx.ext import (

Check warning on line 8 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L7-L8

Added lines #L7 - L8 were not covered by tests
is_big_endian,
read_uint8,
read_uint16,
read_uint16_bs,
read_uint32,
read_uint32_bs,
)
from dxtbx.format.FormatBruker import FormatBruker
from dxtbx.model import SimplePxMmStrategy
from dxtbx.model.beam import Probe

Check warning on line 18 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L16-L18

Added lines #L16 - L18 were not covered by tests


class FormatBrukerED1(FormatBruker):
@staticmethod
def understand(image_file):

Check warning on line 23 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L21-L23

Added lines #L21 - L23 were not covered by tests

try:
header_lines = FormatBruker.read_header_lines(image_file)
except OSError:
return False

Check warning on line 28 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L25-L28

Added lines #L25 - L28 were not covered by tests

header_dic = FormatBruker.parse_header(header_lines)

Check warning on line 30 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L30

Added line #L30 was not covered by tests

dettype = header_dic.get("DETTYPE").upper()

Check warning on line 32 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L32

Added line #L32 was not covered by tests
if dettype is None:
return False

Check warning on line 34 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L34

Added line #L34 was not covered by tests

# ED-1 has a QUADRO detector (which is an EIGER)
if not ("EIGER" in dettype or "QUADRO" in dettype):
return False

Check warning on line 38 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L38

Added line #L38 was not covered by tests

# ED-1 energy is fixed at 160 keV
wavelength = float(header_dic["WAVELEN"].split()[0])

Check warning on line 41 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L41

Added line #L41 was not covered by tests
if round(wavelength, 3) != 0.029:
return False

Check warning on line 43 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L43

Added line #L43 was not covered by tests

return True

Check warning on line 45 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L45

Added line #L45 was not covered by tests

def _start(self):

Check warning on line 47 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L47

Added line #L47 was not covered by tests

try:
header_lines = FormatBruker.read_header_lines(self._image_file)
except OSError:
return False

Check warning on line 52 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L49-L52

Added lines #L49 - L52 were not covered by tests

self.header_dict = FormatBrukerED1.parse_header(header_lines)

Check warning on line 54 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L54

Added line #L54 was not covered by tests

# The ED-1 format can't currently use BrukerImage, for the same reason
# as for the Photon-II/III (hardcoded image size is one factor)
# https://github.com/cctbx/cctbx_project/issues/65
# from iotbx.detectors.bruker import BrukerImage
# self.detectorbase = BrukerImage(self._image_file)

def _goniometer(self):

Check warning on line 62 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L62

Added line #L62 was not covered by tests
# goniometer angles in ANGLES are 2-theta, omega, phi, chi (FIXED)
# AXIS indexes into this list to define the scan axis (in FORTRAN counting)
# START and RANGE define the start and step size for each image

_, omega, phi, chi = map(float, self.header_dict["ANGLES"].split())
scan_axis = ["NONE", "2THETA", "OMEGA", "PHI", "CHI", "X", "Y", "Z"]
scan_axis = scan_axis[int(self.header_dict["AXIS"])]
names = flex.std_string(("PHI", "CHI", "OMEGA"))
scan_axis = flex.first_index(names, scan_axis)

Check warning on line 71 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L67-L71

Added lines #L67 - L71 were not covered by tests
if scan_axis is None:
scan_axis = 2 # "OMEGA" default

Check warning on line 73 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L73

Added line #L73 was not covered by tests

# Axes here determined by trial and error to give the correct rotation
# axis for the ED-1 prototype, in which the CHI angle is 267°
axes = flex.vec3_double(((1, 0, 0), (0, 0, -1), (0, 1, 0)))
omega -= 180
angles = flex.double((phi, chi, omega))

Check warning on line 79 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L77-L79

Added lines #L77 - L79 were not covered by tests

# The ED-1 has a single-axis goniometer, but go through the multi-axis
# goniometer model to compose the axis.
g = self._goniometer_factory.make_multi_axis_goniometer(

Check warning on line 83 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L83

Added line #L83 was not covered by tests
axes, angles, names, scan_axis
)

# It is preferable to return a single axis goniometer, as this can be
# further optimised by dials.find_rotation_axis
return self._goniometer_factory.known_axis(g.get_rotation_axis())

Check warning on line 89 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L89

Added line #L89 was not covered by tests

def _calculate_gain(self, wavelength):

Check warning on line 91 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L91

Added line #L91 was not covered by tests
"""The CCDPARM header item contains 5 items. For an X-ray detector
are described by:
1. readnoise
2. e/ADU
3. e/photon
4. bias
5. full scale
and the gain in ADU/X-ray is given by (e/photon) / (e/ADU).
For the ED-1 QUADRO, this should be 3.0 exactly, but some old files have
this inverted. In the case of exactly 1/3 gain, invert it back.
"""
ccdparm = self.header_dict["CCDPARM"].split()
e_ADU = float(ccdparm[1])
e_photon = float(ccdparm[2])

Check warning on line 105 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L103-L105

Added lines #L103 - L105 were not covered by tests
if e_ADU == 0:
return 1.0
gain = e_photon / e_ADU

Check warning on line 108 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L107-L108

Added lines #L107 - L108 were not covered by tests
if gain == 1.0 / 3.0:
gain = 3.0
return gain

Check warning on line 111 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L110-L111

Added lines #L110 - L111 were not covered by tests

def _detector(self):

Check warning on line 113 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L113

Added line #L113 was not covered by tests
# goniometer angles in ANGLES are 2-theta, omega, phi, chi (FIXED)
two_theta = float(self.header_dict["ANGLES"].split()[0])

Check warning on line 115 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L115

Added line #L115 was not covered by tests

# Assume Bruker full_scale value means saturation
full_scale = float(self.header_dict["CCDPARM"].split()[-1])
min_trusted_value = 0

Check warning on line 119 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L118-L119

Added lines #L118 - L119 were not covered by tests

fast = matrix.col((1, 0, 0))
slow = matrix.col((0, -1, 0))
beam = matrix.col((0, 0, 1))
pixel_mm = 0.075

Check warning on line 124 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L121-L124

Added lines #L121 - L124 were not covered by tests
beam_pixel = [float(bp) for bp in self.header_dict["CENTER"].split()[:-3:-1]]
distance_mm = 10.0 * float(self.header_dict["DISTANC"].split()[1])
origin = (

Check warning on line 127 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L126-L127

Added lines #L126 - L127 were not covered by tests
-distance_mm * beam
- fast * pixel_mm * beam_pixel[1]
- slow * pixel_mm * beam_pixel[0]
)
# 2theta rotation appears to be around the slow axis
origin = origin.rotate_around_origin(slow, two_theta, deg=True)
fast = fast.rotate_around_origin(slow, two_theta, deg=True)
pixel_size = pixel_mm, pixel_mm

Check warning on line 135 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L133-L135

Added lines #L133 - L135 were not covered by tests
# ncols is nfast, nrows is nslow
image_size = (

Check warning on line 137 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L137

Added line #L137 was not covered by tests
int(self.header_dict["NCOLS"].split()[0]),
int(self.header_dict["NROWS"].split()[0]),
)

gain = self._calculate_gain(float(self.header_dict["WAVELEN"].split()[0]))
detector = self._detector_factory.complex(

Check warning on line 143 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L142-L143

Added lines #L142 - L143 were not covered by tests
"PAD",
origin.elems,
fast.elems,
slow.elems,
pixel_size,
image_size,
(min_trusted_value, full_scale),
)

# Here we set specifics, notably parallax correction and
# QE correction are effectively disabled by setting the simple
# pixel-to-millimetre strategy and a very high mu value.
for panel in detector:
panel.set_gain(gain)
panel.set_thickness(0.450)
panel.set_material("Si")
panel.set_px_mm_strategy(SimplePxMmStrategy())
panel.set_mu(1e10)

Check warning on line 161 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L157-L161

Added lines #L157 - L161 were not covered by tests

return detector

Check warning on line 163 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L163

Added line #L163 was not covered by tests

def _beam(self):

Check warning on line 165 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L165

Added line #L165 was not covered by tests
"""Make unpolarized beam"""
wavelength = float(self.header_dict["WAVELEN"].split()[0])

Check warning on line 167 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L167

Added line #L167 was not covered by tests

return self._beam_factory.make_polarized_beam(

Check warning on line 169 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L169

Added line #L169 was not covered by tests
sample_to_source=(0.0, 0.0, 1.0),
wavelength=wavelength,
polarization=(0, 1, 0),
polarization_fraction=0.5,
probe=Probe.electron,
)

def _scan(self):

Check warning on line 177 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L177

Added line #L177 was not covered by tests

start = float(self.header_dict["START"].split()[0])
incr = float(self.header_dict["INCREME"].split()[0])

Check warning on line 180 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L179-L180

Added lines #L179 - L180 were not covered by tests
if incr < 0:
start *= -1
incr *= -1

Check warning on line 183 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L182-L183

Added lines #L182 - L183 were not covered by tests

return self._scan_factory.single_file(

Check warning on line 185 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L185

Added line #L185 was not covered by tests
filename=self._image_file,
exposure_times=1,
osc_start=start,
osc_width=incr,
epoch=None,
)

def get_raw_data(self):

Check warning on line 193 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L193

Added line #L193 was not covered by tests
"""Get the pixel intensities (i.e. read the image and return as a
flex array of integers.)"""

# It is better to catch FORMAT 86 here and fail with a sensible error msg
# as soon as something is attempted with the image data rather than in
# the understand method. Otherwise the user gets FormatBruker reading the
# image improperly but without failing
if self.header_dict["FORMAT"] != "100":
raise NotImplementedError(

Check warning on line 202 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L202

Added line #L202 was not covered by tests
"Only FORMAT 100 images from the ED-1 are currently supported"
)

f = self.open_file(self._image_file, "rb")
header_size = int(self.header_dict["HDRBLKS"]) * 512
f.read(header_size)

Check warning on line 208 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L206-L208

Added lines #L206 - L208 were not covered by tests

if is_big_endian():
read_2b = read_uint16_bs
read_4b = read_uint32_bs

Check warning on line 212 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L211-L212

Added lines #L211 - L212 were not covered by tests
else:
read_2b = read_uint16
read_4b = read_uint32

Check warning on line 215 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L214-L215

Added lines #L214 - L215 were not covered by tests

# NPIXELB stores the number of bytes/pixel for the data and the underflow
# table. We expect 1 byte for underflows and either 2 or 1 byte per pixel
# for the data
npixelb = [int(e) for e in self.header_dict["NPIXELB"].split()]
assert npixelb[1] == 1

Check warning on line 221 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L221

Added line #L221 was not covered by tests

if npixelb[0] == 1:
read_data = read_uint8

Check warning on line 224 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L224

Added line #L224 was not covered by tests
elif npixelb[0] == 2:
read_data = read_2b

Check warning on line 226 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L226

Added line #L226 was not covered by tests
else:
raise IncorrectFormatError(

Check warning on line 228 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L228

Added line #L228 was not covered by tests
"{} bytes per pixel is not supported".format(npixelb[0])
)

nrows = int(self.header_dict["NROWS"].split()[0])
ncols = int(self.header_dict["NCOLS"].split()[0])

Check warning on line 233 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L232-L233

Added lines #L232 - L233 were not covered by tests

raw_data = read_data(streambuf(f), nrows * ncols)

Check warning on line 235 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L235

Added line #L235 was not covered by tests

image_size = (nrows, ncols)
raw_data.reshape(flex.grid(*image_size))

Check warning on line 238 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L237-L238

Added lines #L237 - L238 were not covered by tests

(num_underflows, num_2b_overflows, num_4b_overflows) = [
int(e) for e in self.header_dict["NOVERFL"].split()
]

# read underflows
if num_underflows > 0:
# stored values are padded to a multiple of 16 bytes
nbytes = num_underflows + 15 & ~(15)
underflow_vals = read_uint8(streambuf(f), nbytes)[:num_underflows]

Check warning on line 248 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L247-L248

Added lines #L247 - L248 were not covered by tests
else:
underflow_vals = None

Check warning on line 250 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L250

Added line #L250 was not covered by tests

# handle 2 byte overflows
if num_2b_overflows > 0:
# stored values are padded to a multiple of 16 bytes
nbytes = num_2b_overflows * 2 + 15 & ~(15)
overflow_vals = read_2b(streambuf(f), nbytes // 2)[:num_2b_overflows]
overflow = flex.int(nrows * ncols, 0)
sel = (raw_data == 255).as_1d()
overflow.set_selected(sel, overflow_vals - 255)
overflow.reshape(flex.grid(*image_size))
raw_data += overflow

Check warning on line 261 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L255-L261

Added lines #L255 - L261 were not covered by tests

# handle 4 byte overflows
if num_4b_overflows > 0:
# stored values are padded to a multiple of 16 bytes
nbytes = num_4b_overflows * 4 + 15 & ~(15)
overflow_vals = read_4b(streambuf(f), nbytes // 4)[:num_4b_overflows]
overflow = flex.int(nrows * ncols, 0)
sel = (raw_data == 65535).as_1d()
overflow.set_selected(sel, overflow_vals - 65535)
overflow.reshape(flex.grid(*image_size))
raw_data += overflow

Check warning on line 272 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L266-L272

Added lines #L266 - L272 were not covered by tests

# handle underflows
if underflow_vals is not None:
sel = (raw_data == 0).as_1d()
underflow = flex.int(nrows * ncols, 0)
underflow.set_selected(sel, underflow_vals)
underflow.reshape(flex.grid(*image_size))
raw_data += underflow

Check warning on line 280 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L276-L280

Added lines #L276 - L280 were not covered by tests

# handle baseline. num_underflows == -1 means no baseline subtraction. See
# https://github.com/cctbx/cctbx_project/files/1262952/BISFrameFileFormats.zip
if num_underflows != -1:
num_exposures = [int(e) for e in self.header_dict["NEXP"].split()]
baseline = num_exposures[2]
raw_data += baseline

Check warning on line 287 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L286-L287

Added lines #L286 - L287 were not covered by tests

return raw_data

Check warning on line 289 in src/dxtbx/format/FormatBrukerED1.py

View check run for this annotation

Codecov / codecov/patch

src/dxtbx/format/FormatBrukerED1.py#L289

Added line #L289 was not covered by tests
Loading
Loading