# HG changeset patch
# User rv43
# Date 1679320617 0
# Node ID 1cf15b61cd8331f1be25d6b8b965b9d9bd7a5b0c
# Parent 97c4e2cbbad97e64ce52ef667881f13241755c75
planemo upload for repository https://github.com/rolfverberg/galaxytools commit 366e516aef0735af2998c6ff3af037181c8d5213
diff -r 97c4e2cbbad9 -r 1cf15b61cd83 fit.py
--- a/fit.py Fri Mar 10 16:39:22 2023 +0000
+++ b/fit.py Mon Mar 20 13:56:57 2023 +0000
@@ -20,7 +20,10 @@
from os import cpu_count, getpid, listdir, mkdir, path
from re import compile, sub
from shutil import rmtree
-from sympy import diff, simplify
+try:
+ from sympy import diff, simplify
+except:
+ pass
try:
from joblib import Parallel, delayed
have_joblib = True
@@ -32,12 +35,20 @@
except:
have_xarray = False
-from .general import illegal_value, is_int, is_dict_series, is_index, index_nearest, \
+#try:
+# from .general import illegal_value, is_int, is_dict_series, is_index, index_nearest, \
+# almost_equal, quick_plot #, eval_expr
+#except:
+# try:
+# from sys import path as syspath
+# syspath.append(f'/nfs/chess/user/rv43/msnctools/msnctools')
+# from general import illegal_value, is_int, is_dict_series, is_index, index_nearest, \
+# almost_equal, quick_plot #, eval_expr
+# except:
+# from general import illegal_value, is_int, is_dict_series, is_index, index_nearest, \
+# almost_equal, quick_plot #, eval_expr
+from general import illegal_value, is_int, is_dict_series, is_index, index_nearest, \
almost_equal, quick_plot #, eval_expr
-#from sys import path as syspath
-#syspath.append(f'/nfs/chess/user/rv43/msnctools/msnctools')
-#from general import illegal_value, is_int, is_dict_series, is_index, index_nearest, \
-# almost_equal, quick_plot #, eval_expr
from sys import float_info
float_min = float_info.min
@@ -1810,8 +1821,8 @@
self.fit(**kwargs)
@classmethod
- def fit_map(cls, x, ymap, models, normalize=True, **kwargs):
- return(cls(x, ymap, models, normalize=normalize, **kwargs))
+ def fit_map(cls, ymap, models, x=None, normalize=True, **kwargs):
+ return(cls(ymap, x=x, models=models, normalize=normalize, **kwargs))
@property
def best_errors(self):
diff -r 97c4e2cbbad9 -r 1cf15b61cd83 read_image.py
--- a/read_image.py Fri Mar 10 16:39:22 2023 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-#!/usr/bin/env python3
-
-import logging
-
-import argparse
-import pathlib
-import sys
-
-def __main__():
-
- # Parse command line arguments
- parser = argparse.ArgumentParser(
- description='Read a raw or reconstructed image')
- parser.add_argument('-i', '--input_file',
- required=True,
- type=pathlib.Path,
- help='''Full or relative path to the input file (in yaml or nxs format).''')
- parser.add_argument('--image_type',
- required=False,
- help='Image type (dark, bright, tomo_raw, tomo_reduced, or reconstructed')
- parser.add_argument('--image_index',
- required=False,
- type=int,
- help='Image index (only for raw or reduced images')
- parser.add_argument('-l', '--log',
-# type=argparse.FileType('w'),
- default=sys.stdout,
- help='Logging stream or filename')
- parser.add_argument('--log_level',
- choices=logging._nameToLevel.keys(),
- default='INFO',
- help='''Specify a preferred logging level.''')
- args = parser.parse_args()
-
- # Set log configuration
- # When logging to file, the stdout log level defaults to WARNING
- logging_format = '%(asctime)s : %(levelname)s - %(module)s : %(funcName)s - %(message)s'
- level = logging.getLevelName(args.log_level)
- if args.log is sys.stdout:
- logging.basicConfig(format=logging_format, level=level, force=True,
- handlers=[logging.StreamHandler()])
- else:
- if isinstance(args.log, str):
- logging.basicConfig(filename=f'{args.log}', filemode='w',
- format=logging_format, level=level, force=True)
- elif isinstance(args.log, io.TextIOWrapper):
- logging.basicConfig(filemode='w', format=logging_format, level=level,
- stream=args.log, force=True)
- else:
- raise(ValueError(f'Invalid argument --log: {args.log}'))
- stream_handler = logging.StreamHandler()
- logging.getLogger().addHandler(stream_handler)
- stream_handler.setLevel(logging.WARNING)
- stream_handler.setFormatter(logging.Formatter(logging_format))
-
- # Log command line arguments
- logging.info(f'input_file = {args.input_file}')
- logging.info(f'image_type = {args.image_type}')
- logging.info(f'image_index = {args.image_index}')
- logging.debug(f'log = {args.log}')
- logging.debug(f'is log stdout? {args.log is sys.stdout}')
-
- # Instantiate Tomo object
- tomo = Tomo(galaxy_flag=args.galaxy_flag)
-
- # Read input file
- data = tomo.read(args.input_file)
- print(f'data:\n{data}')
-
-if __name__ == "__main__":
- __main__()
-
diff -r 97c4e2cbbad9 -r 1cf15b61cd83 read_image.xml
--- a/read_image.xml Fri Mar 10 16:39:22 2023 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-
- Read and plot a raw, reduced or reconstructed tomography image
-
- tomo_macros.xml
-
-
-
-
-
-
-
-
-
-
-
-
diff -r 97c4e2cbbad9 -r 1cf15b61cd83 run_link_to_galaxy
--- a/run_link_to_galaxy Fri Mar 10 16:39:22 2023 +0000
+++ b/run_link_to_galaxy Mon Mar 20 13:56:57 2023 +0000
@@ -1,6 +1,5 @@
#!/bin/bash
-#python -m workflow link_to_galaxy -i tenstom_1304r-1.nxs -g 'https://galaxy.classe.cornell.edu' -a 'fbea44f58986b87b40bb9315c496e687'
-#python -m workflow link_to_galaxy -i tenstom_1304r-1.nxs -g 'https://galaxy-dev.classe.cornell.edu' -a 'bd404baf78eef76657277f33021d408f'
-
-python -m workflow link_to_galaxy -i sobhani-3249-A.yaml -g 'https://galaxy-dev.classe.cornell.edu' -a 'bd404baf78eef76657277f33021d408f'
+python -m workflow link_to_galaxy -i sobhani-3249-A_start.nxs -g 'https://galaxy-dev.classe.cornell.edu' -a 'bd404baf78eef76657277f33021d408f'
+python -m workflow link_to_galaxy -i tenstom_1304r-1_start.nxs -g 'https://galaxy-dev.classe.cornell.edu' -a 'bd404baf78eef76657277f33021d408f'
+python -m workflow link_to_galaxy -i tenstom_1304r-1_one_stack_start.nxs -g 'https://galaxy-dev.classe.cornell.edu' -a 'bd404baf78eef76657277f33021d408f'
diff -r 97c4e2cbbad9 -r 1cf15b61cd83 run_tomo_all
--- a/run_tomo_all Fri Mar 10 16:39:22 2023 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,6 +0,0 @@
-#!/bin/bash
-
-# From workflow
-#python -m workflow run_tomo -i sobhani-3249-A.yaml -o sobhani-3249-A.nxs -n 48 -s 'no'
-#python -m workflow run_tomo -i tenstom_1304r-1_one_stack.yaml -o tenstom_1304r-1_one_stack.nxs -n 48 -s 'no'
-python -m workflow run_tomo -i tenstom_1304r-1.yaml -o tenstom_1304r-1.nxs -n 48 -s 'no'
diff -r 97c4e2cbbad9 -r 1cf15b61cd83 run_tomo_combine
--- a/run_tomo_combine Fri Mar 10 16:39:22 2023 +0000
+++ b/run_tomo_combine Mon Mar 20 13:56:57 2023 +0000
@@ -1,4 +1,9 @@
#!/bin/bash
+# From workflow
+#python -m workflow run_tomo -i sobhani-3249-A_recon.nxs -o sobhani-3249-A_recon_combined.nxs -n 48 -s 'only' --combine_data
+#python -m workflow run_tomo -i tenstom_1304r-1_one_stack_recon.nxs -o tenstom_1304r-1_one_stack_recon_combined.nxs -n 48 -s 'only' --combine_data
+#python -m workflow run_tomo -i tenstom_1304r-1_recon.nxs -o tenstom_1304r-1_recon_combined.nxs -n 48 -s 'only' --combine_data
+
# As Galaxy tool:
-python tomo_combine.py -i tenstom_1304r-1_recon.nxs -o tenstom_1304r-1_recon_combined.nxs --log_level INFO
+python tomo_combine.py -i tenstom_1304r-1_recon.nxs -o tenstom_1304r-1_recon_combined.nxs --log_level INFO -l tomo.log --galaxy_flag
diff -r 97c4e2cbbad9 -r 1cf15b61cd83 run_tomo_find_center
--- a/run_tomo_find_center Fri Mar 10 16:39:22 2023 +0000
+++ b/run_tomo_find_center Mon Mar 20 13:56:57 2023 +0000
@@ -1,9 +1,11 @@
#!/bin/bash
# From workflow
-python -m workflow run_tomo -i sobhani-3249-A_reduce.nxs -o sobhani-3249-A_centers.yaml -n 48 -s 'only' --find_center
+#python -m workflow run_tomo -i sobhani-3249-A_reduce.nxs -o sobhani-3249-A_centers.yaml -n 48 -s 'only' --find_center
+#python -m workflow run_tomo -i tenstom_1304r-1_one_stack_reduce.nxs -o tenstom_1304r-1_one_stack_centers.yaml -n 48 -s 'only' --find_center
+#python -m workflow run_tomo -i tenstom_1304r-1_reduce.nxs -o tenstom_1304r-1_centers.yaml -n 48 -s 'only' --find_center
# As Galaxy tool:
-#python tomo_find_center.py -i sobhani-3249-A_reduce.nxs -o sobhani-3249-A_centers.yaml --log_level INFO -l tomo.log --galaxy_flag --center_rows 50 270
-#python tomo_find_center.py -i tenstom_1304r-1_one_stack_reduce.nxs -o tenstom_1304r-1_one_stack_centers.yaml --log_level INFO
-#python tomo_find_center.py -i tenstom_1304r-1_reduce.nxs -o tenstom_1304r-1_centers.yaml --log_level INFO
+python tomo_find_center.py -i sobhani-3249-A_reduce.nxs -o sobhani-3249-A_centers.yaml --log_level INFO -l tomo.log --galaxy_flag --center_rows 50 270
+python tomo_find_center.py -i tenstom_1304r-1_one_stack_reduce.nxs -o tenstom_1304r-1_one_stack_centers.yaml --log_level INFO -l tomo.log --galaxy_flag --center_rows 75 850
+python tomo_find_center.py -i tenstom_1304r-1_reduce.nxs -o tenstom_1304r-1_centers.yaml --log_level INFO -l tomo.log --galaxy_flag
diff -r 97c4e2cbbad9 -r 1cf15b61cd83 run_tomo_reconstruct
--- a/run_tomo_reconstruct Fri Mar 10 16:39:22 2023 +0000
+++ b/run_tomo_reconstruct Mon Mar 20 13:56:57 2023 +0000
@@ -1,9 +1,11 @@
#!/bin/bash
# From workflow
-python -m workflow run_tomo -i sobhani-3249-A_reduce.nxs -c sobhani-3249-A_centers.yaml -o sobhani-3249-A_recon.nxs -n 48 -s 'only' --reconstruct_data
+#python -m workflow run_tomo -i sobhani-3249-A_reduce.nxs -c sobhani-3249-A_centers.yaml -o sobhani-3249-A_recon.nxs -n 48 -s 'only' --reconstruct_data
+#python -m workflow run_tomo -i tenstom_1304r-1_one_stack_reduce.nxs -c tenstom_1304r-1_one_stack_centers.yaml -o tenstom_1304r-1_one_stack_recon.nxs -n 48 -s 'only' --reconstruct_data
+#python -m workflow run_tomo -i tenstom_1304r-1_reduce.nxs -c tenstom_1304r-1_centers.yaml -o tenstom_1304r-1_recon.nxs -n 48 -s 'only' --reconstruct_data
# As Galaxy tool:
-#python tomo_reconstruct.py -i sobhani-3249-A_reduce.nxs -c sobhani-3249-A_centers.yaml -o sobhani-3249-A_recon.nxs --log_level INFO -l tomo.log --galaxy_flag --x_bounds 650 1050 --y_bounds 270 1430
-#python tomo_reconstruct.py -i tenstom_1304r-1_one_stack_reduce.nxs -c tenstom_1304r-1_one_stack_centers.yaml -o tenstom_1304r-1_one_stack_recon.nxs --log_level INFO
-#python tomo_reconstruct.py -i tenstom_1304r-1_reduce.nxs -c tenstom_1304r-1_centers.yaml -o tenstom_1304r-1_recon.nxs --log_level INFO
+python tomo_reconstruct.py -i sobhani-3249-A_reduce.nxs -c sobhani-3249-A_centers.yaml -o sobhani-3249-A_recon.nxs --log_level INFO -l tomo.log --galaxy_flag --x_bounds 650 1050 --y_bounds 270 1430
+python tomo_reconstruct.py -i tenstom_1304r-1_one_stack_reduce.nxs -c tenstom_1304r-1_one_stack_centers.yaml -o tenstom_1304r-1_one_stack_recon.nxs --log_level INFO -l tomo.log --galaxy_flag --x_bounds 629 1450 --y_bounds 606 1468
+python tomo_reconstruct.py -i tenstom_1304r-1_reduce.nxs -c tenstom_1304r-1_centers.yaml -o tenstom_1304r-1_recon.nxs --log_level INFO -l tomo.log --galaxy_flag --x_bounds 629 1450 --y_bounds 606 1468
diff -r 97c4e2cbbad9 -r 1cf15b61cd83 run_tomo_reduce
--- a/run_tomo_reduce Fri Mar 10 16:39:22 2023 +0000
+++ b/run_tomo_reduce Mon Mar 20 13:56:57 2023 +0000
@@ -1,9 +1,11 @@
#!/bin/bash
# From workflow
-python -m workflow run_tomo -i sobhani-3249-A.yaml -o sobhani-3249-A_reduce.nxs -n 48 -s 'only' --reduce_data
+#python -m workflow run_tomo -i sobhani-3249-A.yaml -o sobhani-3249-A_reduce.nxs -n 48 -s 'only' --reduce_data
+#python -m workflow run_tomo -i tenstom_1304r-1_one_stack.yaml -o tenstom_1304r-1_one_stack_reduce.nxs -n 48 -s 'only' --reduce_data
+#python -m workflow run_tomo -i tenstom_1304r-1.yaml -o tenstom_1304r-1_reduce.nxs -n 48 -s 'only' --reduce_data
# As Galaxy tool:
-#python tomo_reduce.py -i sobhani-3249-A.yaml -o sobhani-3249-A_reduce.nxs --log_level INFO -l tomo.log --galaxy_flag --img_x_bounds 620 950
-#python tomo_reduce.py -i tenstom_1304r-1_one_stack.yaml -o tenstom_1304r-1_one_stack_reduce.nxs --log_level INFO -l tomo.log --galaxy_flag
-#python tomo_reduce.py -i tenstom_1304r-1.yaml -o tenstom_1304r-1_reduce.nxs --log_level INFO -l tomo.log --galaxy_flag #--img_x_bounds 713 1388
+python tomo_reduce.py -i sobhani-3249-A_start.nxs -o sobhani-3249-A_reduce.nxs --log_level INFO -l tomo.log --galaxy_flag --img_x_bounds 620 950
+python tomo_reduce.py -i tenstom_1304r-1_one_stack_start.nxs -o tenstom_1304r-1_one_stack_reduce.nxs --log_level INFO -l tomo.log --galaxy_flag #--img_x_bounds 582 1509
+python tomo_reduce.py -i tenstom_1304r-1_start.nxs -o tenstom_1304r-1_reduce.nxs --log_level INFO -l tomo.log --galaxy_flag #--img_x_bounds 713 1388
diff -r 97c4e2cbbad9 -r 1cf15b61cd83 sobhani-3249-A.yaml
--- a/sobhani-3249-A.yaml Fri Mar 10 16:39:22 2023 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,40 +0,0 @@
-sample_maps:
-- cycle: 2022-1
- btr: sobhani-3249-A
- title: sobhani-3249-A
- station: id3b
- sample:
- name: tomo7C
- detector:
- prefix: andor2
- rows: 1436
- columns: 1700
- pixel_size:
- - 0.0065
- - 0.0065
- lens_magnification: 5.0
- tomo_fields:
- spec_file: /nfs/chess/scratch/user/rv43/2022-1/id3b/sobhani-3249-A/tomo7C/tomo7C
- scan_numbers:
- - 1
- stack_info:
- - scan_number: 1
- starting_image_offset: 5
- num_image: 360
- ref_x: 0.0
- ref_z: 6.1845
- theta_range:
- start: 0.0
- end: 180.0
- num: 360
- start_index: 4
- bright_field:
- spec_file: /nfs/chess/scratch/user/rv43/2022-1/id3b/sobhani-3249-A/tomo7C/tomo7C_flat
- scan_numbers:
- - 1
- stack_info:
- - scan_number: 1
- starting_image_offset: 1
- num_image: 20
- ref_x: 0.0
- ref_z: 6.1845
diff -r 97c4e2cbbad9 -r 1cf15b61cd83 tomo_combine.py
--- a/tomo_combine.py Fri Mar 10 16:39:22 2023 +0000
+++ b/tomo_combine.py Mon Mar 20 13:56:57 2023 +0000
@@ -23,6 +23,9 @@
required=False,
type=pathlib.Path,
help='''Full or relative path to the output file (in yaml format).''')
+ parser.add_argument('--galaxy_flag',
+ action='store_true',
+ help='''Use this flag to run the scripts as a galaxy tool.''')
parser.add_argument('-l', '--log',
# type=argparse.FileType('w'),
default=sys.stdout,
@@ -31,6 +34,16 @@
choices=logging._nameToLevel.keys(),
default='INFO',
help='''Specify a preferred logging level.''')
+ parser.add_argument('--x_bounds',
+ required=False,
+ nargs=2,
+ type=int,
+ help='''Boundaries of reconstructed images in x-direction.''')
+ parser.add_argument('--y_bounds',
+ required=False,
+ nargs=2,
+ type=int,
+ help='''Boundaries of reconstructed images in y-direction.''')
args = parser.parse_args()
# Set log configuration
@@ -63,18 +76,21 @@
logging.debug(f'log = {args.log}')
logging.debug(f'is log stdout? {args.log is sys.stdout}')
logging.debug(f'log_level = {args.log_level}')
+ logging.info(f'x_bounds = {args.x_bounds}')
+ logging.info(f'y_bounds = {args.y_bounds}')
# Instantiate Tomo object
- tomo = Tomo()
+ tomo = Tomo(galaxy_flag=args.galaxy_flag)
# Read input file
data = tomo.read(args.input_file)
# Combine the reconstructed tomography stacks
- data = tomo.combine_data(data)
+ data = tomo.combine_data(data, x_bounds=args.x_bounds, y_bounds=args.y_bounds)
# Write output file
- data = tomo.write(data, args.output_file)
+ if data is not None:
+ data = tomo.write(data, args.output_file)
# Displaying memory usage
# logging.info(f'Memory usage: {tracemalloc.get_traced_memory()}')
diff -r 97c4e2cbbad9 -r 1cf15b61cd83 tomo_find_center.py
--- a/tomo_find_center.py Fri Mar 10 16:39:22 2023 +0000
+++ b/tomo_find_center.py Mon Mar 20 13:56:57 2023 +0000
@@ -24,7 +24,6 @@
type=pathlib.Path,
help='''Full or relative path to the output file (in yaml format).''')
parser.add_argument('--center_rows',
- required=True,
nargs=2,
type=int,
help='''Center finding rows.''')
@@ -81,7 +80,7 @@
data = tomo.read(args.input_file)
# Find the calibrated center axis info
- data = tomo.find_centers(data, center_rows=tuple(args.center_rows))
+ data = tomo.find_centers(data, center_rows=args.center_rows)
# Write output file
data = tomo.write(data, args.output_file)
diff -r 97c4e2cbbad9 -r 1cf15b61cd83 tomo_macros.xml
--- a/tomo_macros.xml Fri Mar 10 16:39:22 2023 +0000
+++ b/tomo_macros.xml Mon Mar 20 13:56:57 2023 +0000
@@ -2,8 +2,9 @@
lmfit
+ matplotlib
nexusformat
- tomopy
+ tomopy
diff -r 97c4e2cbbad9 -r 1cf15b61cd83 tomo_reconstruct.py
--- a/tomo_reconstruct.py Fri Mar 10 16:39:22 2023 +0000
+++ b/tomo_reconstruct.py Mon Mar 20 13:56:57 2023 +0000
@@ -22,11 +22,11 @@
parser.add_argument('-c', '--center_file',
required=True,
type=pathlib.Path,
- help='''Full or relative path to the center info file (in Nexus format).''')
+ help='''Full or relative path to the center info file (in yaml format).''')
parser.add_argument('-o', '--output_file',
required=False,
type=pathlib.Path,
- help='''Full or relative path to the output file (in yaml format).''')
+ help='''Full or relative path to the output file (in Nexus format).''')
parser.add_argument('--galaxy_flag',
action='store_true',
help='''Use this flag to run the scripts as a galaxy tool.''')
diff -r 97c4e2cbbad9 -r 1cf15b61cd83 tomo_reduce.py
--- a/tomo_reduce.py Fri Mar 10 16:39:22 2023 +0000
+++ b/tomo_reduce.py Mon Mar 20 13:56:57 2023 +0000
@@ -20,7 +20,7 @@
type=pathlib.Path,
help='''Full or relative path to the input file (in yaml or nxs format).''')
parser.add_argument('-o', '--output_file',
- required=False,
+ required=True,
type=pathlib.Path,
help='''Full or relative path to the output file (in Nexus format).''')
parser.add_argument('--galaxy_flag',
diff -r 97c4e2cbbad9 -r 1cf15b61cd83 tomopy_galaxy.yml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tomopy_galaxy.yml Mon Mar 20 13:56:57 2023 +0000
@@ -0,0 +1,11 @@
+name: tomopy_galaxy
+channels:
+ - conda-forge
+ - defaults
+dependencies:
+ - lmfit==1.0.3
+ - matplotlib==3.5.2
+ - nexusformat==1.0.0
+ - pip==22.3.1
+ - python==3.9.13
+ - tomopy==1.12.2
diff -r 97c4e2cbbad9 -r 1cf15b61cd83 tomopy_galaxy_tool_dev.yml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tomopy_galaxy_tool_dev.yml Mon Mar 20 13:56:57 2023 +0000
@@ -0,0 +1,16 @@
+name: tomopy_galaxy_tool_dev
+channels:
+ - conda-forge
+ - defaults
+dependencies:
+# - ephemeris
+ - lmfit==1.1.0
+ - matplotlib==3.7.1
+ - nexusformat==1.0.0
+ - pip==23.0.1
+ - pydantic==1.10.6
+ - python==3.9.13
+ - tomopy==1.12.2
+ - pip:
+ - bioblend==1.1.1
+ - planemo==0.75.7
diff -r 97c4e2cbbad9 -r 1cf15b61cd83 workflow/__main__.py
--- a/workflow/__main__.py Fri Mar 10 16:39:22 2023 +0000
+++ b/workflow/__main__.py Mon Mar 20 13:56:57 2023 +0000
@@ -202,9 +202,9 @@
const='reconstruct_data',
action='append_const',
help='''Use this flag to create and add reconstructed data data to the input file.''')
-tomo_parser.add_argument('--combine_datas',
+tomo_parser.add_argument('--combine_data',
dest='modes',
- const='combine_datas',
+ const='combine_data',
action='append_const',
help='''Use this flag to combine reconstructed data data and add to the input file.''')
diff -r 97c4e2cbbad9 -r 1cf15b61cd83 workflow/link_to_galaxy.py
--- a/workflow/link_to_galaxy.py Fri Mar 10 16:39:22 2023 +0000
+++ b/workflow/link_to_galaxy.py Mon Mar 20 13:56:57 2023 +0000
@@ -37,10 +37,12 @@
def link_to_galaxy(filename:str, galaxy=None, user=None, password=None, api_key=None) -> None:
# Read input file
extension = path.splitext(filename)[1]
- if extension == '.yml' or extension == '.yaml':
- with open(filename, 'r') as f:
- data = safe_load(f)
- elif extension == '.nxs':
+# RV yaml input not incorporated yet, since Galaxy can't use pyspec right now
+# if extension == '.yml' or extension == '.yaml':
+# with open(filename, 'r') as f:
+# data = safe_load(f)
+# elif extension == '.nxs':
+ if extension == '.nxs':
with NXFile(filename, mode='r') as nxfile:
data = nxfile.readfile()
else:
@@ -53,7 +55,9 @@
nxroot = NXroot()
for sample_map in wf.sample_maps:
import_scanparser(sample_map.station)
- sample_map.construct_nxentry(nxroot, include_raw_data=False)
+# RV raw data must be included, since Galaxy can't use pyspec right now
+# sample_map.construct_nxentry(nxroot, include_raw_data=False)
+ sample_map.construct_nxentry(nxroot, include_raw_data=True)
nxentry = nxroot[nxroot.attrs['default']]
elif isinstance(data, NXroot):
nxentry = data[data.attrs['default']]
diff -r 97c4e2cbbad9 -r 1cf15b61cd83 workflow/models.py
--- a/workflow/models.py Fri Mar 10 16:39:22 2023 +0000
+++ b/workflow/models.py Mon Mar 20 13:56:57 2023 +0000
@@ -11,9 +11,9 @@
from functools import cache
from pathlib import PosixPath
-from pydantic import validator, ValidationError, conint, confloat, constr, \
- conlist, FilePath, PrivateAttr
from pydantic import BaseModel as PydanticBaseModel
+from pydantic import validator, ValidationError, conint, confloat, constr, conlist, FilePath, \
+ PrivateAttr
from nexusformat.nexus import *
from time import time
from typing import Optional, Literal
@@ -23,17 +23,35 @@
except:
pass
-from msnctools.general import is_int, is_num, input_int, input_int_list, input_num, input_yesno, \
- input_menu, index_nearest, string_to_list, file_exists_and_readable
+try:
+ from msnctools.general import is_int, is_num, input_int, input_int_list, input_num, \
+ input_yesno, input_menu, index_nearest, string_to_list, file_exists_and_readable
+except:
+ from general import is_int, is_num, input_int, input_int_list, input_num, \
+ input_yesno, input_menu, index_nearest, string_to_list, file_exists_and_readable
def import_scanparser(station):
if station in ('id1a3', 'id3a'):
- from msnctools.scanparsers import SMBRotationScanParser
- globals()['ScanParser'] = SMBRotationScanParser
+ try:
+ from msnctools.scanparsers import SMBRotationScanParser
+ globals()['ScanParser'] = SMBRotationScanParser
+ except:
+ try:
+ from scanparsers import SMBRotationScanParser
+ globals()['ScanParser'] = SMBRotationScanParser
+ except:
+ pass
elif station in ('id3b'):
- from msnctools.scanparsers import FMBRotationScanParser
- globals()['ScanParser'] = FMBRotationScanParser
+ try:
+ from msnctools.scanparsers import FMBRotationScanParser
+ globals()['ScanParser'] = FMBRotationScanParser
+ except:
+ try:
+ from scanparsers import FMBRotationScanParser
+ globals()['ScanParser'] = FMBRotationScanParser
+ except:
+ pass
else:
raise RuntimeError(f'Invalid station: {station}')
@@ -45,10 +63,9 @@
try:
parser = ScanParser(spec_file, scan_number)
try:
- scan_type = parser.get_scan_type()
+ scan_type = parser.scan_type
except:
scan_type = None
- pass
except:
scan_numbers.remove(scan_number)
return(scan_numbers)
@@ -434,15 +451,6 @@
def get_scanparser(self, scan_number):
return(get_scanparser(self.spec_file, scan_number))
-# def get_detector_data(self, detector_prefix, scan_number=None, scan_step_index=None):
-# if scan_number is None:
-# scan_number = self.scan_numbers[0]
-# if scan_step_index is None:
-# scan_info = self.stack_info[self.get_scan_index(scan_number)]
-# scan_step_index = scan_info['starting_image_offset']
-# parser = self.get_scanparser(scan_number)
-# return(parser.get_detector_data(detector_prefix, scan_step_index))
-
def get_detector_data(self, detector_prefix, scan_number=None, scan_step_index=None):
image_stacks = []
if scan_number is None:
@@ -460,10 +468,13 @@
else:
image_stacks.append(parser.get_detector_data(detector_prefix,
image_offset+scan_step_index))
- if len(image_stacks) == 1:
+ if scan_number is not None and scan_step_index is not None:
+ # Return a single image for a specific scan_number and scan_step_index request
return(image_stacks[0])
else:
+ # Return a list otherwise
return(image_stacks)
+ return(image_stacks)
def scan_numbers_cli(self, attr_desc, **kwargs):
available_scan_numbers = self.available_scan_numbers
@@ -475,8 +486,11 @@
available_scan_numbers = []
for scan_number in self.available_scan_numbers:
parser = self.get_scanparser(scan_number)
- if parser.scan_type == scan_type:
- available_scan_numbers.append(scan_number)
+ try:
+ if parser.scan_type == scan_type:
+ available_scan_numbers.append(scan_number)
+ except:
+ pass
elif scan_type == 'df1':
tomo_scan_numbers = kwargs['tomo_scan_numbers']
available_scan_numbers = []
@@ -587,8 +601,8 @@
scan_index = self.get_scan_index(scan_number)
# Select the image set
- last_image_index = image_offset+num_image-1
- print(f'Available good image set index range: [{image_offset}, {last_image_index}]')
+ last_image_index = image_offset+num_image
+ print(f'Available good image set index range: [{image_offset}, {last_image_index})')
image_set_approved = False
if scan_index is not None:
scan_info = stack_info[scan_index]
@@ -597,16 +611,16 @@
image_set_approved = input_yesno(f'Accept these values (y/n)?', 'y')
if not image_set_approved:
print(f'Default starting image offset and number of images: '+
- f'{image_offset} and {last_image_index-image_offset}')
+ f'{image_offset} and {num_image}')
image_set_approved = input_yesno(f'Accept these values (y/n)?', 'y')
if image_set_approved:
offset = image_offset
num = last_image_index-offset
while not image_set_approved:
offset = input_int(f'Enter the starting image offset', ge=image_offset,
- le=last_image_index-1)#, default=image_offset)
+ lt=last_image_index)#, default=image_offset)
num = input_int(f'Enter the number of images', ge=1,
- le=last_image_index-offset+1)#, default=last_image_index-offset+1)
+ le=last_image_index-offset)#, default=last_image_index-offset)
print(f'Current starting image offset and number of images: {offset} and {num}')
image_set_approved = input_yesno(f'Accept these values (y/n)?', 'y')
if scan_index is not None:
@@ -688,7 +702,7 @@
scan_numbers = [scan_number]
for scan_number in scan_numbers:
parser = self.get_scanparser(scan_number)
- horizontal_shifts.append(parser.get_horizontal_shift())
+ horizontal_shifts.append(parser.horizontal_shift)
if len(horizontal_shifts) == 1:
return(horizontal_shifts[0])
else:
@@ -702,7 +716,7 @@
scan_numbers = [scan_number]
for scan_number in scan_numbers:
parser = self.get_scanparser(scan_number)
- vertical_shifts.append(parser.get_vertical_shift())
+ vertical_shifts.append(parser.vertical_shift)
if len(vertical_shifts) == 1:
return(vertical_shifts[0])
else:
@@ -728,22 +742,20 @@
return
# Select the theta range for the tomo reconstruction from the first scan
+ theta_range_approved = False
thetas = np.linspace(spec_theta_start, spec_theta_end, spec_num_theta)
delta_theta = thetas[1]-thetas[0]
- theta_range_approved = False
- print(f'Theta range obtained from SPEC data: [{spec_theta_start}, {spec_theta_end})')
+ print(f'Theta range obtained from SPEC data: [{spec_theta_start}, {spec_theta_end}]')
print(f'Theta step size = {delta_theta}')
print(f'Number of theta values: {spec_num_theta}')
- exit('Done')
default_start = None
default_end = None
if station in ('id1a3', 'id3a'):
theta_range_approved = input_yesno(f'Accept this theta range (y/n)?', 'y')
if theta_range_approved:
- theta_start = spec_theta_start
- theta_end = spec_theta_end
- num_theta = spec_num_theta
- theta_index_start = 0
+ self.theta_range = {'start': float(spec_theta_start), 'end': float(spec_theta_end),
+ 'num': int(spec_num_theta), 'start_index': 0}
+ return
elif station in ('id3b'):
if spec_theta_start <= 0.0 and spec_theta_end >= 180.0:
default_start = 0
@@ -765,7 +777,8 @@
f'{theta_end})')
print(f'Number of theta values: {num_theta}')
theta_range_approved = input_yesno(f'Accept this theta range (y/n)?', 'y')
- self.thetas = np.linspace(theta_start, theta_end, num_theta)
+ self.theta_range = {'start': float(theta_start), 'end': float(theta_end),
+ 'num': int(num_theta), 'start_index': int(theta_index_start)}
def image_range_cli(self, attr_desc, detector_prefix):
stack_info = self.stack_info
@@ -805,13 +818,17 @@
btr = cli_kwargs.get('btr')
station = cli_kwargs.get('station')
detector = cli_kwargs.get('detector')
+ sample_name = cli_kwargs.get('sample_name')
print(f'\n -- Configure the location of the {attr_desc}scan data -- ')
if station in ('id1a3', 'id3a'):
basedir = f'/nfs/chess/{station}/{cycle}/{btr}'
runs = [d for d in os.listdir(basedir) if os.path.isdir(os.path.join(basedir, d))]
#RV index = 15-1
#RV index = 7-1
- index = input_menu(runs, header='Choose a sample directory')
+ if sample_name is not None and sample_name in runs:
+ index = runs.index(sample_name)
+ else:
+ index = input_menu(runs, header='Choose a sample directory')
self.spec_file = f'{basedir}/{runs[index]}/spec.log'
self.scan_numbers_cli(attr_desc, station=station, scan_type='ts1')
else:
@@ -845,8 +862,8 @@
def cli(self):
print('\n -- Configure the sample metadata -- ')
-#RV self.name = 'test'
#RV self.name = 'sobhani-3249-A'
+#RV self.name = 'tenstom_1304r-1'
self.set_single_attr_cli('name', 'the sample name')
#RV self.description = 'test sample'
self.set_single_attr_cli('description', 'a description of the sample (optional)')
@@ -917,17 +934,19 @@
use_detector_config = input_yesno(f'Current detector settings:\n{self.detector}\n'+
f'Keep these settings? (y/n)')
if not use_detector_config:
-#RV have_detector_config = True
- have_detector_config = input_yesno(f'Is a detector configuration file available? (y/n)')
- if have_detector_config:
-#RV detector_config_file = 'retiga.yaml'
-#RV detector_config_file = 'andor2.yaml'
- detector_config_file = input(f'Enter detector configuration file name: ')
+ menu_options = ['not listed', 'andor2', 'manta', 'retiga']
+ input_mode = input_menu(menu_options, header='Choose one of the following detector '+
+ 'configuration options')
+ if input_mode:
+ detector_config_file = f'{menu_options[input_mode]}.yaml'
have_detector_config = self.detector.construct_from_yaml(detector_config_file)
+ else:
+ have_detector_config = False
if not have_detector_config:
self.set_single_attr_cli('detector', 'detector')
self.set_single_attr_cli('tomo_fields', 'Tomo field', chain_attr_desc=True,
- cycle=self.cycle, btr=self.btr, station=self.station, detector=self.detector)
+ cycle=self.cycle, btr=self.btr, station=self.station, detector=self.detector,
+ sample_name=self.sample.name)
if self.station in ('id1a3', 'id3a'):
have_dark_field = True
tomo_spec_file = self.tomo_fields.spec_file
@@ -1001,7 +1020,7 @@
nxspec_scans[field_name] = field.construct_nxcollection(image_key, thetas,
self.detector)
if include_raw_data:
- image_stacks.append(field.get_detector_data(self.detector.prefix))
+ image_stacks += field.get_detector_data(self.detector.prefix)
for scan_number in field.scan_numbers:
parser = field.get_scanparser(scan_number)
scan_info = field.stack_info[field.get_scan_index(scan_number)]
diff -r 97c4e2cbbad9 -r 1cf15b61cd83 workflow/run_tomo.py
--- a/workflow/run_tomo.py Fri Mar 10 16:39:22 2023 +0000
+++ b/workflow/run_tomo.py Mon Mar 20 13:56:57 2023 +0000
@@ -32,13 +32,24 @@
pass
from yaml import safe_load, safe_dump
-from msnctools.fit import Fit
-from msnctools.general import illegal_value, is_int, is_int_pair, is_num, is_index_range, \
- input_int, input_num, input_yesno, input_menu, draw_mask_1d, select_image_bounds, \
- select_one_image_bound, clear_imshow, quick_imshow, clear_plot, quick_plot
+try:
+ from msnctools.fit import Fit
+except:
+ from fit import Fit
+try:
+ from msnctools.general import illegal_value, is_int, is_int_pair, is_num, is_index_range, \
+ input_int, input_num, input_yesno, input_menu, draw_mask_1d, select_image_bounds, \
+ select_one_image_bound, clear_imshow, quick_imshow, clear_plot, quick_plot
+except:
+ from general import illegal_value, is_int, is_int_pair, is_num, is_index_range, \
+ input_int, input_num, input_yesno, input_menu, draw_mask_1d, select_image_bounds, \
+ select_one_image_bound, clear_imshow, quick_imshow, clear_plot, quick_plot
-from workflow.models import import_scanparser, FlatField, TomoField, TomoWorkflow
-from workflow.__version__ import __version__
+try:
+ from workflow.models import import_scanparser, FlatField, TomoField, TomoWorkflow
+ from workflow.__version__ import __version__
+except:
+ pass
num_core_tomopy_limit = 24
@@ -266,7 +277,7 @@
return(nxroot)
- def find_centers(self, nxroot, center_rows=None):
+ def find_centers(self, nxroot, center_rows=None, center_stack_index=None):
"""Find the calibrated center axis info
"""
logger.info('Find the calibrated center axis info')
@@ -277,13 +288,19 @@
if not isinstance(nxentry, NXentry):
raise ValueError(f'Invalid nxentry ({nxentry})')
if self.galaxy_flag:
- if center_rows is None:
- raise ValueError(f'Missing parameter center_rows ({center_rows})')
- if not is_int_pair(center_rows):
- raise ValueError(f'Invalid parameter center_rows ({center_rows})')
+ if center_rows is not None:
+ center_rows = tuple(center_rows)
+ if not is_int_pair(center_rows):
+ raise ValueError(f'Invalid parameter center_rows ({center_rows})')
elif center_rows is not None:
- logging.warning(f'Ignoring parameter center_rows ({center_rows})')
+ logger.warning(f'Ignoring parameter center_rows ({center_rows})')
center_rows = None
+ if self.galaxy_flag:
+ if center_stack_index is not None and not is_int(center_stack_index, ge=0):
+ raise ValueError(f'Invalid parameter center_stack_index ({center_stack_index})')
+ elif center_stack_index is not None:
+ logger.warning(f'Ignoring parameter center_stack_index ({center_stack_index})')
+ center_stack_index = None
# Create plot galaxy path directory and path if needed
if self.galaxy_flag:
@@ -298,26 +315,28 @@
raise KeyError(f'Unable to find valid reduced data in {nxentry}.')
# Select the image stack to calibrate the center axis
- # reduced data axes order: stack,row,theta,column
+ # reduced data axes order: stack,theta,row,column
# Note: Nexus cannot follow a link if the data it points to is too big,
# so get the data from the actual place, not from nxentry.data
- num_tomo_stacks = nxentry.reduced_data.data.tomo_fields.shape[0]
+ tomo_fields_shape = nxentry.reduced_data.data.tomo_fields.shape
+ if len(tomo_fields_shape) != 4 or any(True for dim in tomo_fields_shape if not dim):
+ raise KeyError('Unable to load the required reduced tomography stack')
+ num_tomo_stacks = tomo_fields_shape[0]
if num_tomo_stacks == 1:
center_stack_index = 0
- center_stack = np.asarray(nxentry.reduced_data.data.tomo_fields[0])
- if not center_stack.size:
- raise KeyError('Unable to load the required reduced tomography stack')
default = 'n'
else:
if self.test_mode:
center_stack_index = self.test_config['center_stack_index']-1 # make offset 0
+ elif self.galaxy_flag:
+ if center_stack_index is None:
+ center_stack_index = int(num_tomo_stacks/2)
+ if center_stack_index >= num_tomo_stacks:
+ raise ValueError(f'Invalid parameter center_stack_index ({center_stack_index})')
else:
center_stack_index = input_int('\nEnter tomography stack index to calibrate the '
- 'center axis', ge=0, le=num_tomo_stacks-1, default=int(num_tomo_stacks/2))
- center_stack = \
- np.asarray(nxentry.reduced_data.data.tomo_fields[center_stack_index])
- if not center_stack.size:
- raise KeyError('Unable to load the required reduced tomography stack')
+ 'center axis', ge=1, le=num_tomo_stacks, default=int(1+num_tomo_stacks/2))
+ center_stack_index -= 1
default = 'y'
# Get thetas (in degrees)
@@ -331,26 +350,35 @@
eff_pixel_size = nxentry.instrument.detector.x_pixel_size
# Get cross sectional diameter
- cross_sectional_dim = center_stack.shape[2]*eff_pixel_size
+ cross_sectional_dim = tomo_fields_shape[3]*eff_pixel_size
logger.debug(f'cross_sectional_dim = {cross_sectional_dim}')
# Determine center offset at sample row boundaries
logger.info('Determine center offset at sample row boundaries')
# Lower row center
- # center_stack order: row,theta,column
if self.test_mode:
lower_row = self.test_config['lower_row']
elif self.galaxy_flag:
- lower_row = min(center_rows)
- if not 0 <= lower_row < center_stack.shape[0]-1:
- raise ValueError(f'Invalid parameter center_rows ({center_rows})')
+ if center_rows is None:
+ lower_row = 0
+ else:
+ lower_row = min(center_rows)
+ if not 0 <= lower_row < tomo_fields_shape[2]-1:
+ raise ValueError(f'Invalid parameter center_rows ({center_rows})')
else:
- lower_row = select_one_image_bound(center_stack[:,0,:], 0, bound=0,
+ lower_row = select_one_image_bound(
+ nxentry.reduced_data.data.tomo_fields[center_stack_index,0,:,:], 0, bound=0,
title=f'theta={round(thetas[0], 2)+0}',
- bound_name='row index to find lower center', default=default)
- lower_center_offset = self._find_center_one_plane(center_stack[lower_row,:,:], lower_row,
- thetas, eff_pixel_size, cross_sectional_dim, path=path, num_core=self.num_core)
+ bound_name='row index to find lower center', default=default, raise_error=True)
+ logger.debug('Finding center...')
+ t0 = time()
+ lower_center_offset = self._find_center_one_plane(
+ #np.asarray(nxentry.reduced_data.data.tomo_fields[center_stack_index,:,lower_row,:]),
+ nxentry.reduced_data.data.tomo_fields[center_stack_index,:,lower_row,:],
+ lower_row, thetas, eff_pixel_size, cross_sectional_dim, path=path,
+ num_core=self.num_core)
+ logger.debug(f'... done in {time()-t0:.2f} seconds')
logger.debug(f'lower_row = {lower_row:.2f}')
logger.debug(f'lower_center_offset = {lower_center_offset:.2f}')
@@ -358,18 +386,27 @@
if self.test_mode:
upper_row = self.test_config['upper_row']
elif self.galaxy_flag:
- upper_row = max(center_rows)
- if not lower_row < upper_row < center_stack.shape[0]:
- raise ValueError(f'Invalid parameter center_rows ({center_rows})')
+ if center_rows is None:
+ upper_row = tomo_fields_shape[2]-1
+ else:
+ upper_row = max(center_rows)
+ if not lower_row < upper_row < tomo_fields_shape[2]:
+ raise ValueError(f'Invalid parameter center_rows ({center_rows})')
else:
- upper_row = select_one_image_bound(center_stack[:,0,:], 0,
- bound=center_stack.shape[0]-1, title=f'theta={round(thetas[0], 2)+0}',
- bound_name='row index to find upper center', default=default)
- upper_center_offset = self._find_center_one_plane(center_stack[upper_row,:,:], upper_row,
- thetas, eff_pixel_size, cross_sectional_dim, path=path, num_core=self.num_core)
+ upper_row = select_one_image_bound(
+ nxentry.reduced_data.data.tomo_fields[center_stack_index,0,:,:], 0,
+ bound=tomo_fields_shape[2]-1, title=f'theta={round(thetas[0], 2)+0}',
+ bound_name='row index to find upper center', default=default, raise_error=True)
+ logger.debug('Finding center...')
+ t0 = time()
+ upper_center_offset = self._find_center_one_plane(
+ #np.asarray(nxentry.reduced_data.data.tomo_fields[center_stack_index,:,upper_row,:]),
+ nxentry.reduced_data.data.tomo_fields[center_stack_index,:,upper_row,:],
+ upper_row, thetas, eff_pixel_size, cross_sectional_dim, path=path,
+ num_core=self.num_core)
+ logger.debug(f'... done in {time()-t0:.2f} seconds')
logger.debug(f'upper_row = {upper_row:.2f}')
logger.debug(f'upper_center_offset = {upper_center_offset:.2f}')
- del center_stack
center_config = {'lower_row': lower_row, 'lower_center_offset': lower_center_offset,
'upper_row': upper_row, 'upper_center_offset': upper_center_offset}
@@ -409,11 +446,6 @@
raise KeyError(f'Unable to find valid reduced data in {nxentry}.')
# Create an NXprocess to store image reconstruction (meta)data
-# if 'reconstructed_data' in nxentry:
-# logger.warning(f'Existing reconstructed data in {nxentry} will be overwritten.')
-# del nxentry['reconstructed_data']
-# if 'data' in nxentry and 'reconstructed_data' in nxentry.data:
-# del nxentry.data['reconstructed_data']
nxprocess = NXprocess()
# Get rotation axis rows and centers
@@ -430,7 +462,7 @@
thetas = np.asarray(nxentry.reduced_data.rotation_angle)
# Reconstruct tomography data
- # reduced data axes order: stack,row,theta,column
+ # reduced data axes order: stack,theta,row,column
# reconstructed data order in each stack: row/z,x,y
# Note: Nexus cannot follow a link if the data it points to is too big,
# so get the data from the actual place, not from nxentry.data
@@ -442,9 +474,15 @@
num_tomo_stacks = nxentry.reduced_data.data.tomo_fields.shape[0]
tomo_recon_stacks = num_tomo_stacks*[np.array([])]
for i in range(num_tomo_stacks):
+ # Convert reduced data stack from theta,row,column to row,theta,column
+ logger.debug(f'Reading reduced data stack {i+1}...')
+ t0 = time()
tomo_stack = np.asarray(nxentry.reduced_data.data.tomo_fields[i])
- if not tomo_stack.size:
- raise KeyError(f'Unable to load tomography stack {i} for reconstruction')
+ logger.debug(f'... done in {time()-t0:.2f} seconds')
+ if len(tomo_stack.shape) != 3 or any(True for dim in tomo_stack.shape if not dim):
+ raise ValueError(f'Unable to load tomography stack {i+1} for reconstruction')
+ tomo_stack = np.swapaxes(tomo_stack, 0, 1)
+ assert(len(thetas) == tomo_stack.shape[1])
assert(0 <= lower_row < upper_row < tomo_stack.shape[0])
center_offsets = [lower_center_offset-lower_row*center_slope,
upper_center_offset+(tomo_stack.shape[0]-1-upper_row)*center_slope]
@@ -453,7 +491,7 @@
tomo_recon_stack = self._reconstruct_one_tomo_stack(tomo_stack, thetas,
center_offsets=center_offsets, num_core=self.num_core, algorithm='gridrec')
logger.debug(f'... done in {time()-t0:.2f} seconds')
- logger.info(f'Reconstruction of stack {i} took {time()-t0:.2f} seconds')
+ logger.info(f'Reconstruction of stack {i+1} took {time()-t0:.2f} seconds')
# Combine stacks
tomo_recon_stacks[i] = tomo_recon_stack
@@ -497,7 +535,7 @@
if num_tomo_stacks == 1:
basetitle = 'recon'
else:
- basetitle = f'recon stack {i}'
+ basetitle = f'recon stack {i+1}'
for i, stack in enumerate(tomo_recon_stacks):
title = f'{basetitle} {res_title} xslice{x_slice}'
quick_imshow(stack[z_range[0]:z_range[1],x_slice,y_range[0]:y_range[1]],
@@ -550,7 +588,7 @@
return(nxroot_copy)
- def combine_data(self, nxroot):
+ def combine_data(self, nxroot, x_bounds=None, y_bounds=None):
"""Combine the reconstructed tomography stacks.
"""
logger.info('Combine the reconstructed tomography stacks')
@@ -574,41 +612,39 @@
raise KeyError(f'Unable to find valid reconstructed image data in {nxentry}.')
# Create an NXprocess to store combined image reconstruction (meta)data
-# if 'combined_data' in nxentry:
-# logger.warning(f'Existing combined data in {nxentry} will be overwritten.')
-# del nxentry['combined_data']
-# if 'data' in nxentry 'combined_data' in nxentry.data:
-# del nxentry.data['combined_data']
nxprocess = NXprocess()
# Get the reconstructed data
# reconstructed data order: stack,row(z),x,y
# Note: Nexus cannot follow a link if the data it points to is too big,
# so get the data from the actual place, not from nxentry.data
- tomo_recon_stacks = np.asarray(nxentry.reconstructed_data.data.reconstructed_data)
- num_tomo_stacks = tomo_recon_stacks.shape[0]
+ num_tomo_stacks = nxentry.reconstructed_data.data.reconstructed_data.shape[0]
if num_tomo_stacks == 1:
- return(nxroot)
+ logger.info('Only one stack available: leaving combine_data')
+ return(None)
+
+ # Combine the reconstructed stacks
+ # (load one stack at a time to reduce risk of hitting Nexus data access limit)
t0 = time()
logger.debug(f'Combining the reconstructed stacks ...')
- tomo_recon_combined = tomo_recon_stacks[0,:,:,:]
+ tomo_recon_combined = np.asarray(nxentry.reconstructed_data.data.reconstructed_data[0])
if num_tomo_stacks > 2:
tomo_recon_combined = np.concatenate([tomo_recon_combined]+
- [tomo_recon_stacks[i,:,:,:] for i in range(1, num_tomo_stacks-1)])
+ [nxentry.reconstructed_data.data.reconstructed_data[i]
+ for i in range(1, num_tomo_stacks-1)])
if num_tomo_stacks > 1:
tomo_recon_combined = np.concatenate([tomo_recon_combined]+
- [tomo_recon_stacks[num_tomo_stacks-1,:,:,:]])
+ [nxentry.reconstructed_data.data.reconstructed_data[num_tomo_stacks-1]])
logger.debug(f'... done in {time()-t0:.2f} seconds')
logger.info(f'Combining the reconstructed stacks took {time()-t0:.2f} seconds')
- # Resize the combined tomography data set
+ # Resize the combined tomography data stacks
# combined data order: row/z,x,y
if self.test_mode:
x_bounds = None
y_bounds = None
z_bounds = self.test_config.get('z_bounds')
elif self.galaxy_flag:
- exit('TODO')
if x_bounds is not None and not is_int_pair(x_bounds, ge=0,
lt=tomo_recon_stacks[0].shape[1]):
raise ValueError(f'Invalid parameter x_bounds ({x_bounds})')
@@ -699,7 +735,8 @@
prefix = str(nxentry.instrument.detector.local_name)
tdf_stack = dark_field.get_detector_data(prefix)
if isinstance(tdf_stack, list):
- exit('TODO')
+ assert(len(tdf_stack) == 1) # TODO
+ tdf_stack = tdf_stack[0]
# Take median
if tdf_stack.ndim == 2:
@@ -757,7 +794,8 @@
prefix = str(nxentry.instrument.detector.local_name)
tbf_stack = bright_field.get_detector_data(prefix)
if isinstance(tbf_stack, list):
- exit('TODO')
+ assert(len(tbf_stack) == 1) # TODO
+ tbf_stack = tbf_stack[0]
# Take median if more than one image
"""Median or mean: It may be best to try the median because of some image
@@ -818,8 +856,8 @@
first_image = np.asarray(nxentry.instrument.detector.data[field_indices[0],:,:])
theta = float(nxentry.sample.rotation_angle[field_indices[0]])
z_translation_all = nxentry.sample.z_translation[field_indices]
- z_translation_levels = sorted(list(set(z_translation_all)))
- num_tomo_stacks = len(z_translation_levels)
+ vertical_shifts = sorted(list(set(z_translation_all)))
+ num_tomo_stacks = len(vertical_shifts)
else:
tomo_field_scans = nxentry.spec_scans.tomo_fields
tomo_fields = TomoField.construct_from_nxcollection(tomo_field_scans)
@@ -1112,7 +1150,7 @@
if len(tomo_stacks) == 1:
title = f'red fullres theta {round(thetas[0], 2)+0}'
else:
- title = f'red stack {i} fullres theta {round(thetas[0], 2)+0}'
+ title = f'red stack {i+1} fullres theta {round(thetas[0], 2)+0}'
quick_imshow(tomo_stack[0,:,:], title=title, path=path, save_fig=self.save_figs,
save_only=self.save_only, block=self.block)
# if not self.block:
@@ -1135,15 +1173,13 @@
# if not self.block:
# clear_imshow(title)
- # Convert tomography stack from theta,row,column to row,theta,column
- t0 = time()
- tomo_stack = np.swapaxes(tomo_stack, 0, 1)
- logger.debug(f'Converting coordinate order took {time()-t0:.2f} seconds')
-
# Save test data to file
if self.test_mode:
- row_index = int(tomo_stack.shape[0]/2)
- np.savetxt(f'{self.output_folder}/red_stack_{i+1}.txt', tomo_stack[row_index,:,:],
+# row_index = int(tomo_stack.shape[0]/2)
+# np.savetxt(f'{self.output_folder}/red_stack_{i+1}.txt', tomo_stack[row_index,:,:],
+# fmt='%.6e')
+ row_index = int(tomo_stack.shape[1]/2)
+ np.savetxt(f'{self.output_folder}/red_stack_{i+1}.txt', tomo_stack[:,row_index,:],
fmt='%.6e')
# Combine resized stacks
@@ -1168,6 +1204,7 @@
# Try automatic center finding routines for initial value
# sinogram index order: theta,column
# need column,theta for iradon, so take transpose
+ sinogram = np.asarray(sinogram)
sinogram_T = sinogram.T
center = sinogram.shape[1]/2
@@ -1499,7 +1536,7 @@
accept = True
logger.debug(f'y_bounds = {y_bounds}')
- # Selecting z bounds (in xy-plane) (only valid for a single image set)
+ # Selecting z bounds (in xy-plane) (only valid for a single image stack)
if num_tomo_stacks != 1:
z_bounds = None
else:
@@ -1548,9 +1585,11 @@
logger.info(f'test_mode = {test_mode}')
# Check for correction modes
+ legal_modes = ['reduce_data', 'find_center', 'reconstruct_data', 'combine_data', 'all']
if modes is None:
modes = ['all']
- logger.debug(f'modes {type(modes)} = {modes}')
+ if not all(True if mode in legal_modes else False for mode in modes):
+ raise ValueError(f'Invalid parameter modes ({modes})')
# Instantiate Tomo object
tomo = Tomo(num_core=num_core, output_folder=output_folder, save_figs=save_figs,
@@ -1581,9 +1620,10 @@
data = tomo.combine_data(data)
# Write output file
- if not test_mode:
+ if data is not None and not test_mode:
if center_data is None:
data = tomo.write(data, output_file)
else:
data = tomo.write(center_data, output_file)
+ logger.info(f'Completed modes: {modes}')