Skip to content
83 changes: 36 additions & 47 deletions DuSC_explorer/rotatable.py → DuSC_explorer/DuSC_dectris.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
"""
Load TitanX data and show real and reciprocal space.
Load Dectris Arina data and show real and reciprocal space.

The real space ROI can be rotated
Based on DuSC_explorer, but uses dense operations.

author: Peter Ercius
date: 2023/11/02

"""

Expand All @@ -13,15 +12,16 @@
import pyqtgraph as pg
from pyqtgraph.graphicsItems.ROI import Handle
import numpy as np
from scipy import ndimage
import ncempy
from tifffile import imwrite
import h5py
import hdf5plugin

from qtpy.QtWidgets import *
from qtpy.QtCore import QRectF
from qtpy import QtGui

class fourD(QWidget):
class DuSC(QWidget):

def __init__(self, *args, **kwargs):

Expand All @@ -39,18 +39,13 @@ def __init__(self, *args, **kwargs):
self.log_diffraction = True
self.handle_size = 10

self.available_colormaps = ['thermal', 'flame', 'yellowy', 'bipolar', 'spectrum', 'cyclic', 'greyclip', 'grey',
'viridis', 'inferno', 'plasma', 'magma']
self.colormap = pg.colormap.getFromMatplotlib('grey')
self.available_colormaps = ['viridis', 'inferno', 'plasma', 'magma','cividis','CET-C5','CET-C5s']
self.colormap = 'cividis' # default colormap

super(fourD, self).__init__(*args, *kwargs)
self.setWindowTitle("NCEM: TitanX 4D Data Explorer")
super(DuSC, self).__init__(*args, *kwargs)
self.setWindowTitle("NCEM: Dectris Arina 4D Data Explorer")
self.setWindowIcon(QtGui.QIcon('MF_logo_only_small.ico'))

# Set the update strategy to the JIT version
#self.update_real = self.update_real_stempy
#self.update_diffr = self.update_diffr_stempy

# Add a graphics/view/image
# Need to set invertY = True and row-major
self.graphics = pg.GraphicsLayoutWidget()
Expand Down Expand Up @@ -129,8 +124,6 @@ def __init__(self, *args, **kwargs):

self.open_file()

self.real_space_roi.addRotateHandle((0, 0), (0.5, 0.5))

self.real_space_roi.sigRegionChanged.connect(self.update_diffr)
self.diffraction_space_roi.sigRegionChanged.connect(self.update_real)
self.real_space_roi.sigRegionChanged.connect(self._update_position_message)
Expand All @@ -149,7 +142,7 @@ def open_file(self):
"""

fd = pg.FileDialog()
fd.setNameFilter("Sparse Stempy (*.dm3 *.dm4)")
fd.setNameFilter("Dectris (*_master.h5)")
fd.setDirectory(str(self.current_dir))
fd.setFileMode(pg.FileDialog.ExistingFile)

Expand All @@ -160,25 +153,22 @@ def open_file(self):
self.setData(Path(file_names[0]))

def setData(self, fPath):
""" Load the data from the DM file.
""" Load the data from the file.

Parameters
----------
fPath : pathlib.Path
The path of to the file to load.
"""
self.statusBar.showMessage("Loading the data...")

# Load data as a SparseArray class
with ncempy.io.dm.fileDM(fPath) as f0:
dm0 = f0.getDataset(0)

scanI = int(f0.allTags['.ImageList.2.ImageTags.Series.nimagesx'])
scanJ = int(f0.allTags['.ImageList.2.ImageTags.Series.nimagesy'])
numkI = dm0['data'].shape[2]
numkJ = dm0['data'].shape[1]

self.sa = dm0['data'].reshape([scanJ,scanI,numkJ,numkI])

# Load Dectris data
with ncempy.io.dectris.fileDECTRIS(fPath) as dectris:
self.sa = dectris.get_dataset(remove_bad_pixels=True)
scanI = self.sa.shape[0]
scanJ = self.sa.shape[1]
numkI = self.sa.shape[2]
numkJ = self.sa.shape[3]

print('Data shape is {}'.format(self.sa.shape))

Expand Down Expand Up @@ -207,31 +197,22 @@ def setData(self, fPath):

self.statusBar.showMessage('loaded {}'.format(fPath.name))


def update_diffr(self):
""" Update the diffraction space image by summing in real space
"""
# Get the region of the real space ROI
out = self.real_space_roi.getArrayRegion(self.dp, self.real_space_image_item,returnMappedCoords=True,order=0)
# Setup a mask with the correct dimensions
mask = np.zeros(self.scan_dimensions, dtype=bool)
mask[np.round(out[1][0].astype(np.uint16)), np.round(out[1][1]).astype(np.uint16)] = 1
ndimage.binary_closing(mask, output=mask)

out2 = self.real_space_roi.getArraySlice(self.dp, self.real_space_image_item)

temp = self.sa[out2[0][0],out2[0][1],:,:]
mask = mask[out2[0][0],out2[0][1]]
self.dp = temp.sum(axis=(0,1),where=mask[:,:,None,None], dtype=np.uint16)

self.dp = self.sa[int(self.real_space_roi.pos().y()) - 0:int(self.real_space_roi.pos().y() + self.real_space_roi.size().y()) + 1,
int(self.real_space_roi.pos().x()) - 0:int(self.real_space_roi.pos().x() + self.real_space_roi.size().x()) + 1,
:, :]
self.dp = self.dp.sum(axis=(0,1))
self.diffraction_pattern_image_item.setImage(np.log(self.dp + 1))

def update_real(self):
""" Update the real space image by summing in diffraction space
"""
self.rs = self.sa[:, :,
int(self.diffraction_space_roi.pos().y()) - 1:int(self.diffraction_space_roi.pos().y() + self.diffraction_space_roi.size().y()) + 0,
int(self.diffraction_space_roi.pos().x()) - 1:int(self.diffraction_space_roi.pos().x() + self.diffraction_space_roi.size().x()) + 0]
int(self.diffraction_space_roi.pos().y()) - 0:int(self.diffraction_space_roi.pos().y() + self.diffraction_space_roi.size().y()) + 1,
int(self.diffraction_space_roi.pos().x()) - 0:int(self.diffraction_space_roi.pos().x() + self.diffraction_space_roi.size().x()) + 1]
self.rs = self.rs.sum(axis=(2, 3))
self.real_space_image_item.setImage(self.rs, autoRange=True)

Expand Down Expand Up @@ -326,10 +307,18 @@ def _write_smv(self, out_path):
with open(out_path, 'rb+') as f0:
f0.seek(512, 0)
f0.write(im)
if __name__ == '__main__':

def open_file():
"""Start the graphical user interface by opening a file. This is used from a python interpreter."""
main()

def main():
"""Main function used to start the GUI."""

qapp = QApplication([])
fourD_view = fourD()
fourD_view.show()
DuSC_view = DuSC()
DuSC_view.show()
qapp.exec_()

if __name__ == '__main__':
main()