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

add pystxm operations #1

Open
wants to merge 38 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
60f24e0
Merge branch 'master' into operations_pystxm
JulReinhardt Aug 19, 2020
35ee06f
fixing error messages
JulReinhardt Aug 19, 2020
2bd543d
Merge branch 'ingestor_pystxm' into operations_pystxm
JulReinhardt Aug 19, 2020
4ea26a1
Merge branch 'master' into operations_pystxm
JulReinhardt Aug 19, 2020
b3eb0ba
testing
JulReinhardt Aug 19, 2020
ee6a74a
back to working state
JulReinhardt Aug 19, 2020
5fa3dd8
add operations
JulReinhardt Aug 19, 2020
ee2a3a5
change to pystxmtools package for import of operations
JulReinhardt Aug 27, 2020
4d04629
add entry points for pystxm operations
JulReinhardt Aug 31, 2020
b296a7c
remove ingestor parts --> see different PR
JulReinhardt Aug 31, 2020
f9698d9
test example
JulReinhardt Sep 4, 2020
ae411b4
use apply signature and new imports of operation
JulReinhardt Sep 11, 2020
b11de62
adapt new decorator written pystxm operations
JulReinhardt Sep 13, 2020
6b88e3c
modify imports for register_operation
JulReinhardt Sep 14, 2020
a2bb9c7
messing with the test
JulReinhardt Sep 16, 2020
73f37db
messing with the test
JulReinhardt Sep 16, 2020
9d22cd9
Merge remote-tracking branch 'origin/master' into operations_pystxm
JulReinhardt Oct 22, 2020
d651fb9
add vanessa's operations to entrypoints
JulReinhardt Oct 22, 2020
45f423f
execute iterative false
JulReinhardt Oct 26, 2020
ade00d1
Merge branch 'master' into operations_pystxm
JulReinhardt Oct 26, 2020
d2752cd
get array data from image intent if projector return list
JulReinhardt Oct 28, 2020
64a2367
Ron's suggestions
JulReinhardt Oct 30, 2020
1af93be
get array data from Image Intent for workflow operation
JulReinhardt Oct 30, 2020
48eb441
Merge branch 'master' into operations_pystxm
JulReinhardt Nov 12, 2020
d2b4891
Merge branch 'master' into operations_pystxm
JulReinhardt Dec 3, 2020
aa9065e
add decomposition pca to entry points
JulReinhardt Dec 10, 2020
bfcbbdb
add switch for energy axis being last or first axis
JulReinhardt Dec 10, 2020
69e521d
formatting
JulReinhardt Dec 10, 2020
d668476
some fixes in projector and adding entry points for more operations
JulReinhardt Jan 25, 2021
bb8ab02
Merge branch 'master' into operations_pystxm
JulReinhardt Feb 2, 2021
4ed29ef
add multiple intent display names for splitview
JulReinhardt Feb 2, 2021
be18c84
change decomposition to energy axis = first
JulReinhardt Feb 2, 2021
ffeb104
minors
JulReinhardt Feb 5, 2021
d979e23
Trim comments
ronpandolfi Feb 5, 2021
6d521e6
remove entry points and more to pystxm-tools
JulReinhardt Feb 6, 2021
744f969
Merge branch 'operations_pystxm' of https://github.com/Xi-CAM/Xi-cam.…
JulReinhardt Feb 6, 2021
24d9963
remove extra logic, keep only energy stack data in projector
JulReinhardt Feb 6, 2021
bdb432d
list to project all
JulReinhardt Mar 2, 2021
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 .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ build/
dist/
*.egg-info/
venv/
.vscode
1 change: 1 addition & 0 deletions xicam/spectral/ingestors/NXcxi_ptycho.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ def ingest_cxi(paths):
sorted_entry_list = sorted(h5_entry_dict.items(), key=lambda item: item[1])
# TODO check if energies are "continuous" or have interruptions
# the removal of last for entries is only temporary due to the example dataset
# FIXME what to do if some energies are 'out of range'?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

refer to nx tycho to see if we can put these reference energies in a different field (may have to extend the spec)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

heuristics, or acquisition-side definition of the reference energies
(just writing these comments for later notes - fine to keep this in for now)

del sorted_entry_list[-4:]

frames_stack = []
Expand Down
7 changes: 3 additions & 4 deletions xicam/spectral/operations/decomposition.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class svd_solver(enum.Enum):
# *[f'component{i}' for i in range(3)],
'energy', 'component_indices')
@visible('data', False)
# @input_names('data', 'Number of components', 'Copy', 'Whiten', 'SVD Solver', 'Tolerance', 'Iterated Power', 'Random State')
# @input_names('data', 'energy axis is last', 'Number of components', 'Copy', 'Whiten', 'SVD Solver', 'Tolerance', 'Iterated Power', 'Random State')
@intent(PairPlotIntent, "Pair Plot", output_map={"transform_data": "transform_data"})
@intent(ImageIntent, "PCA Transform", output_map={"image": "transform_data", 'xvals': 'component_indices'}, mixins=['SliceSelector'], axes={'t': 2, 'x': 1, 'y': 0, 'c': None})
@intent(ImageIntent, "False-color PCA Transform", output_map={"image": "transform_data", 'xvals': 'component_indices'}, axes={'t': None, 'x': 1, 'y': 0, 'c': 2})
Expand All @@ -37,9 +37,8 @@ class svd_solver(enum.Enum):
def pca(data:np.ndarray, n_components:Union[int, float, str]=3, copy:bool=True, whiten:bool=False, svd_solver:svd_solver='auto', tol:float=0.0, iterated_power:Union[str, int]='auto', random_state:int=None):
pca = PCA(n_components, copy=copy, whiten=whiten, svd_solver=svd_solver, tol=tol, iterated_power=iterated_power, random_state=random_state)

pca.fit(np.asarray(data).reshape(-1, data.shape[2]))
images = pca.transform(np.asarray(data).reshape(-1, data.shape[2])).reshape(data.shape[0],data.shape[1], n_components)

pca.fit(np.asarray(data).reshape(-1, data.shape[0]))
images = pca.transform(np.asarray(data).reshape(-1, data.shape[0])).reshape(data.shape[1], data.shape[2], 3)
return images, pca.explained_variance_ratio_, pca.components_, data.coords['E (eV)'], np.arange(images.shape[-1])


Expand Down
15 changes: 8 additions & 7 deletions xicam/spectral/projectors/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@ def project_nxSTXM(run_catalog: BlueskyRun):
energy = projection['irmap/DATA/energy']['value']

xdata = getattr(run_catalog, stream).to_dask()[field] # type: xr.DataArray

xdata = np.squeeze(xdata)

xdata = xdata.assign_coords({xdata.dims[0]: energy, xdata.dims[2]: sample_x, xdata.dims[1]: sample_y})

return xdata.transpose('y (μm)', 'x (μm)', ...)
return [ImageIntent(item_name='IR maps', image=xdata),]


def project_nxCXI_ptycho(run_catalog: BlueskyRun):
Expand All @@ -40,10 +38,13 @@ def project_nxCXI_ptycho(run_catalog: BlueskyRun):
rec_data_phase = getattr(run_catalog, phase_rec_stream).to_dask()[phase_rec_field]
rec_data_phase = np.squeeze(rec_data_phase)

rec_data_trans = rec_data_trans.assign_coords(
{rec_data_trans.dims[0]: energy, rec_data_trans.dims[1]: coords_y, rec_data_trans.dims[2]: coords_x})

return [ImageIntent(item_name='Transmission Reconstruction', image=rec_data_trans),
rec_data_trans = rec_data_trans.assign_coords({rec_data_trans.dims[0]: energy,
rec_data_trans.dims[1]: coords_y,
rec_data_trans.dims[2]: coords_x})

#TODO add imagemixins to display complex
return [ImageIntent(item_name='ptychography data', image=rec_data_trans),
# ImageIntent(image=rec_data_phase, item_name='phase reconstruction')
]

Expand Down Expand Up @@ -71,4 +72,4 @@ def project_all(run_catalog: BlueskyRun):
for projection in run_catalog.metadata['start']['projections']:
projector = projection_mapping.get(projection['name'])
if projector:
return projector(run_catalog)
return projector(run_catalog)
14 changes: 11 additions & 3 deletions xicam/spectral/stages/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import numpy as np
import xarray as xr

from databroker.in_memory import BlueskyInMemoryCatalog
from qtpy.QtWidgets import QLabel, QComboBox, QHBoxLayout, QWidget, QSpacerItem, QSizePolicy

Expand All @@ -16,9 +17,10 @@
from xicam.gui.widgets.linearworkfloweditor import WorkflowEditor
from databroker.core import BlueskyRun
from xicam.core.execution import Workflow
from xicam.core.intents import Intent
from xicam.plugins import GUIPlugin
from ..widgets.image_viewers import CatalogViewerBlend
from ..projectors import project_nxSTXM, project_all
from ..projectors import project_all


class SpectralBase(GUIPlugin):
Expand All @@ -42,10 +44,16 @@ def __init__(self):
super(SpectralBase, self).__init__()

def treatment_kwargs(self, workflow):
intent_name = ['hyperspectral_data', 'ptychography data', 'IR maps']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ronpandolfi what's the best way to attribute scientific meaning through intents?


# FIXME: Putting this here for now...
self.current_data = None
return {'data': project_all(self.current_catalog)}
projected_data = project_all(self.current_catalog)
if isinstance(projected_data, list):
data_intent = next(filter(lambda intent: intent.item_name in intent_name, iter(projected_data)))
return {'data': data_intent.image}
else:
return {'data': projected_data}

def append_treatment(self, result_set):
if self.current_data is None:
Expand All @@ -60,7 +68,7 @@ def appendCatalog(self, run_catalog: BlueskyRun, **kwargs):
# catalog.metadata.update(self.schema())
ensemble = Ensemble()
ensemble.append_catalog(run_catalog)
self.ensemble_model.add_ensemble(ensemble, project_all)
self.ensemble_model.add_ensemble(ensemble, [project_all])

try:
# Apply nxSTXM projection
Expand Down
21 changes: 16 additions & 5 deletions xicam/spectral/workflows/workflows.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@

from shop.correction.register import RegisterOperation
from shop.correction.filter import MedianFilterOperation, WienerFilterOperation
from pystxmtools.corrections.register import register_operation
from pystxmtools.corrections.filter import median_filter_operation, wiener_filter_operation, denoise_operation, despike_operation
from pystxmtools.corrections.optical_density import calc_opt_density_operation
from pystxmtools.corrections.fitting import lsq_fit_operation

# from ..operations.register import RegisterOperation
# from shop.correction.filter import median_filter, wiener_filter
Expand All @@ -13,13 +15,22 @@ def __init__(self):
super(StxmWorkflow, self).__init__(name="STXM Workflow")

# Create instances of operations
register = RegisterOperation()
wiener = MedianFilterOperation()
median = WienerFilterOperation()
register = register_operation()
wiener = median_filter_operation()
median = wiener_filter_operation()
denoise = denoise_operation()
#TODO: how can calcOD receive IO map in workflow editor
calc_OD = calc_opt_density_operation()
lstsq_fit = lsq_fit_operation()

# Add operation to the workflow
self.add_operations(register)
self.add_operations(wiener)
self.add_operations(median)
self.add_operation(denoise)
self.add_operation(calc_OD)
self.add_operation(lstsq_fit)
# self.auto_connect_all()
#connect one operation's output with another operation's input
# self.add_link()

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add connections, move to Xi-CAM.STXM

40 changes: 29 additions & 11 deletions xicam/tests/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,42 @@
from skimage import data
from scipy.ndimage.interpolation import shift

from shop.correction.register import register_frames_stack
from pystxmtools.corrections.register import register_frames_stack

@fixture
# @fixture
def test_stack():
image = data.camera()
n_frames = 10
shifts = [(round(random.uniform(1, 50), 2), round(random.uniform(1, 50), 2)) for i in range(n_frames)]
stack = []
# shifts = (round(random.uniform(1, 50), 2), round(random.uniform(1, 50), 2))
im_shift_stack = []
for n in range(n_frames):
stack.append(shift(image, shifts[n]))
return np.asarray(stack)
shifts = (round(random.uniform(1, 50), 2), round(random.uniform(1, 50), 2))
el = [shift(image, shifts), shifts]
im_shift_stack.append(el)
return np.asarray(im_shift_stack)

def test_register_frame_stack(test_stack):

def test_register_frame_stack():
"Test something in register_frame_stack "
aligned_frames = register_frames_stack(test_stack)
print(aligned_frames.shape)
print(test_stack.shape)
image = data.camera()
n_frames = 10
# shifts = (round(random.uniform(1, 50), 2), round(random.uniform(1, 50), 2))
im_stack = []
shift_stack = []
for n in range(n_frames-1):
shifts = [round(random.uniform(1, 50), 2), round(random.uniform(1, 50), 2)]
shift_stack.append(shifts)

shifted_frames = shift(image, shifts)
im_stack.append(shifted_frames)
# aligned_frames, calc_shifts = register_frames_stack(frames=test_stack[:,0])
aligned_frames, calc_shifts = register_frames_stack(np.asarray(im_stack))

return aligned_frames, calc_shifts, shift_stack, shifts, np.asarray(im_stack)

assert aligned_frames.shape[0] == test_stack.shape[0]
# assert calc_shifts == shift_stack
# assert calc_shifts == test_stack[:,1]


if __name__ == "__main__":
test_stack()