Mercurial > repos > rv43 > tomo
changeset 71:1cf15b61cd83 draft
planemo upload for repository https://github.com/rolfverberg/galaxytools commit 366e516aef0735af2998c6ff3af037181c8d5213
author | rv43 |
---|---|
date | Mon, 20 Mar 2023 13:56:57 +0000 |
parents | 97c4e2cbbad9 |
children | d5329ca0210d |
files | fit.py read_image.py read_image.xml run_link_to_galaxy run_tomo_all run_tomo_combine run_tomo_find_center run_tomo_reconstruct run_tomo_reduce sobhani-3249-A.yaml tomo_combine.py tomo_find_center.py tomo_macros.xml tomo_reconstruct.py tomo_reduce.py tomopy_galaxy.yml tomopy_galaxy_tool_dev.yml workflow/__main__.py workflow/link_to_galaxy.py workflow/models.py workflow/run_tomo.py |
diffstat | 21 files changed, 294 insertions(+), 308 deletions(-) [+] |
line wrap: on
line diff
--- 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):
--- 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__() -
--- 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 @@ -<tool id="read_image" name="Read and Plot a Tomography Image" version="0.2.0" python_template_version="3.9"> - <description>Read and plot a raw, reduced or reconstructed tomography image</description> - <macros> - <import>tomo_macros.xml</import> - </macros> - <command detect_errors="exit_code"><![CDATA[ - $__tool_directory__/read_image.py - --input_file '$input_file' - --image_index $image_index - -l '$log' - ]]></command> - <inputs> - <param name="input_file" type="data" optional="false" label="Input file"/> - <param name="image_index" type='integer' value="-1" label="Image index"/> - </inputs> - <outputs> - <expand macro="common_outputs"/> - </outputs> - <help><![CDATA[ - Read and plot a raw, reduced or reconstructed tomography image. - ]]></help> - <expand macro="citations"/> -</tool>
--- 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'
--- 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'
--- 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
--- 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
--- 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
--- 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
--- 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
--- 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()}')
--- 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)
--- 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 @@ <xml name="requirements"> <requirements> <requirement type="package" version="1.0.3">lmfit</requirement> + <requirement type="package" version="3.5.2">matplotlib</requirement> <requirement type="package" version="1.0.0">nexusformat</requirement> - <requirement type="package" version="1.11.0">tomopy</requirement> + <requirement type="package" version="1.12.2">tomopy</requirement> </requirements> </xml> <xml name="citations">
--- 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.''')
--- 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',
--- /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
--- /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
--- 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.''')
--- 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']]
--- 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)]
--- 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}')