diff --git a/CHAP/common/reader.py b/CHAP/common/reader.py index 2bf457b..4445b90 100755 --- a/CHAP/common/reader.py +++ b/CHAP/common/reader.py @@ -561,7 +561,7 @@ def read(self, filename, method='read_csv', comment='#', **kwargs): :param comment: Character to identify comment lines in the input file, defaults to `'#'`. :type comment: str, optional - :param \*\*kwargs: Additional keyword arguments to supply to the + :param **kwargs: Additional keyword arguments to supply to the `pandas` reader. :rtype: `pandas.DataFrame` """ diff --git a/CHAP/models.py b/CHAP/models.py index 435c2b5..e18b1a5 100755 --- a/CHAP/models.py +++ b/CHAP/models.py @@ -33,7 +33,7 @@ class CHAPBaseModel(BaseModel): def dict(self, *args, **kwargs): """Dump the class implemention to a dictionary. - :param \*\*kwargs: Optional keyword arguments, including: + :param **kwargs: Optional keyword arguments, including: :keyword exclude: Class variable(s) to omit from the output dictionary. :type exclude: dict or set, optional @@ -48,7 +48,7 @@ class variables that have an alias., defaults to `True`. def model_dump(self, *args, **kwargs): """Dump the class implemention to a dictionary. - :param \*\*kwargs: Optional keyword arguments, including: + :param **kwargs: Optional keyword arguments, including: :keyword exclude: Class variable(s) to omit from the output dictionary. :type exclude: dict or set, optional @@ -68,7 +68,7 @@ class variables that have an alias., defaults to `True`. def model_dump_json(self, *args, **kwargs): """Dump the class implemention to a JSON string. - :param \*\*kwargs: Optional keyword arguments, including: + :param **kwargs: Optional keyword arguments, including: :keyword exclude: Class variable(s) to omit from the output dictionary. :type exclude: dict or set, optional diff --git a/CHAP/pipeline.py b/CHAP/pipeline.py index e7c3715..3ea0e11 100755 --- a/CHAP/pipeline.py +++ b/CHAP/pipeline.py @@ -481,7 +481,7 @@ def run(cls, **kwargs): pipeline file config dictionary (see: :class:`~CHAP.models.RunConfig)`. - :param \*\*kwargs: Optional keyword arguments, including: + :param **kwargs: Optional keyword arguments, including: :keyword config: Initialization parameters for an instance of the pipeline item this method is called from (often used by Readers and Processors). diff --git a/CHAP/utils/fit.py b/CHAP/utils/fit.py index 02ef7d6..16da1cd 100755 --- a/CHAP/utils/fit.py +++ b/CHAP/utils/fit.py @@ -1262,7 +1262,7 @@ def fit(self, config=None, **kwargs): :param config: Fit configuration. :type config: CHAP.utils.models.FitConfig, optional - :param \*\*kwargs: Additional key, value pairs to pass on + :param **kwargs: Additional key, value pairs to pass on directly to the core fit routine. """ # Check input parameters @@ -1357,7 +1357,7 @@ class attribute. :type plot_residual: bool, optional :param plot_masked_data: :type plot_masked_data: bool, optional - :param \*\*kwargs: Additional key, value pairs to pass on + :param **kwargs: Additional key, value pairs to pass on directly to the Matplotlib plot function. """ if result is None: @@ -2740,7 +2740,7 @@ def plot( :type plot_residual: bool, optional :param plot_masked_data: :type plot_masked_data: bool, optional - :param \*\*kwargs: Additional key, value pairs to pass on + :param **kwargs: Additional key, value pairs to pass on directly to the Matplotlib plot function. """ # Third party modules @@ -2817,7 +2817,7 @@ def fit(self, config=None, **kwargs): :param config: Fit configuration. :type config: CHAP.utils.models.FitConfig, optional - :param \*\*kwargs: Additional key, value pairs to pass on + :param **kwargs: Additional key, value pairs to pass on directly to the core fit routine. """ # Check input parameters diff --git a/CHAP/utils/general.py b/CHAP/utils/general.py index 758dbe5..550fb35 100755 --- a/CHAP/utils/general.py +++ b/CHAP/utils/general.py @@ -2736,7 +2736,7 @@ def quick_imshow( :type grid_linewidth: int, optional :param colorbar: Include a colorbar, defaults to `False`. :type colorbar: bool, optional - :param \*\*kwargs: Any additional keyword parameters to pass on to + :param **kwargs: Any additional keyword parameters to pass on to `matplotlib.pyplot.imshow `__. :raise: ValueError for invalid input data or parameters. :return: In-memory object as a byte stream represention if @@ -2853,7 +2853,7 @@ def quick_plot( :type save_only: bool, optional :param block: Wait for the image to be closed before returning. :type block: bool, optional - :param \*\*kwargs: Any additional keyword parameters to pass on to + :param **kwargs: Any additional keyword parameters to pass on to `matplotlib.pyplot.plot `__ :raise: ValueError for invalid input data or parameters. """ diff --git a/tests/tomo/detector_cube.yaml b/tests/tomo/input/detector_cube.yaml similarity index 100% rename from tests/tomo/detector_cube.yaml rename to tests/tomo/input/detector_cube.yaml diff --git a/tests/tomo/input/find_center_id3b.yaml b/tests/tomo/input/find_center_id3b.yaml new file mode 100644 index 0000000..ebbbe00 --- /dev/null +++ b/tests/tomo/input/find_center_id3b.yaml @@ -0,0 +1,3 @@ +center_rows: [11, 28] +gaussian_sigma: 0.05 +ring_width: 1 diff --git a/tests/tomo/input/map_id3b.yaml b/tests/tomo/input/map_id3b.yaml new file mode 100644 index 0000000..551d952 --- /dev/null +++ b/tests/tomo/input/map_id3b.yaml @@ -0,0 +1,22 @@ +title: hollow_cube +station: id3b +experiment_type: TOMO +sample: + name: hollow_cube +spec_scans: +- spec_file: ../raw/hollow_cube/hollow_cube + scan_numbers: + - 3 +independent_dimensions: +- label: rotation_angles + units: degrees + data_type: scan_column + name: theta +- label: x_translation + units: mm + data_type: spec_motor + name: GI_samx +- label: z_translation + units: mm + data_type: spec_motor + name: GI_samz diff --git a/tests/tomo/input/reconstruct_data.yaml b/tests/tomo/input/reconstruct_data.yaml new file mode 100644 index 0000000..dd5173a --- /dev/null +++ b/tests/tomo/input/reconstruct_data.yaml @@ -0,0 +1,4 @@ +x_bounds: [15, 390] +y_bounds: [25, 380] +secondary_iters: 10 +ring_width: 1 diff --git a/tests/tomo/input/reduce_data_id3b.yaml b/tests/tomo/input/reduce_data_id3b.yaml new file mode 100644 index 0000000..45a10ac --- /dev/null +++ b/tests/tomo/input/reduce_data_id3b.yaml @@ -0,0 +1 @@ +img_row_bounds: [3, 35] diff --git a/tests/tomo/input/tomo_sim_id3b.yaml b/tests/tomo/input/tomo_sim_id3b.yaml new file mode 100644 index 0000000..5a2e85f --- /dev/null +++ b/tests/tomo/input/tomo_sim_id3b.yaml @@ -0,0 +1,7 @@ +station: id3b +sample_type: hollow_cube +sample_size: +- 1.0 +wall_thickness: 0.2 +theta_step: 1.0 +slit_size: 2.0 diff --git a/tests/tomo/test_tomo.py b/tests/tomo/test_tomo.py index 8b37e04..ab84779 100644 --- a/tests/tomo/test_tomo.py +++ b/tests/tomo/test_tomo.py @@ -23,80 +23,51 @@ from CHAP.tomo.processor import * -map_config = { - 'title': 'hollow_cube', - 'station': 'id3b', - 'experiment_type': 'TOMO', - 'sample': {'name': 'hollow_cube'}, - 'spec_scans': [{ - 'spec_file': 'raw/hollow_cube/hollow_cube', - 'scan_numbers': 3}], - 'independent_dimensions': [ - {'label': 'rotation_angles', - 'units': 'degrees', - 'data_type': 'scan_column', - 'name': 'theta'}, - {'label': 'x_translation', - 'units': 'mm', - 'data_type': 'spec_motor', - 'name': 'GI_samx'}, - {'label': 'z_translation', - 'units': 'mm', - 'data_type': 'spec_motor', - 'name': 'GI_samz'}], -} - -def load_detector_config(): - return YAMLReader.run(filename='detector_cube.yaml', log_level='WARNING') - -class TestEdd: +class TestTomo: def test_id3b(self): - detector_config = load_detector_config() + run_config = { + 'root': 'tests/tomo', + 'inputdir': 'input', + 'interactive': False, + 'log_level': 'WARNING'} + map_config = YAMLReader.run( + filename='map_id3b.yaml', **run_config) + sim_config = YAMLReader.run( + filename='tomo_sim_id3b.yaml', **run_config) + assert map_config['station'] == sim_config['station'] + detector_config = YAMLReader.run( + filename='detector_cube.yaml', **run_config) simfield = TomoSimFieldProcessor.run( - data=[PipelineData( - name='YAMLReader', - data=detector_config, - schema='common.models.map.DetectorConfig')], - config={ - 'station': map_config['station'], - 'sample_type': map_config['title'], - 'sample_size': [1.0], - 'wall_thickness': 0.2, - 'theta_step': 1.0, - 'slit_size': 2.0, - }, - log_level='WARNING') + config=sim_config, detector_config=detector_config, **run_config) data = [PipelineData( name='TomoSimFieldProcessor', data=simfield, schema='tomo.models.TomoSimField')] - darkfield = TomoDarkFieldProcessor.run(data=data, log_level='WARNING') + darkfield = TomoDarkFieldProcessor.run(data=data, **run_config) data.append(PipelineData( name='TomoDarkFieldProcessor', data=darkfield, schema='tomo.models.TomoDarkField')) brightfield = TomoBrightFieldProcessor.run( - data=data, num_image=10, log_level='WARNING') + data=data, num_image=10, **run_config) data.append(PipelineData( name='TomoBrightFieldProcessor', data=brightfield, schema='tomo.models.TomoBrightField')) - tomospec = TomoSpecProcessor.run(data=data, log_level='WARNING') + tomospec = TomoSpecProcessor.run(data=data, **run_config) FileTreeWriter.run( data=[PipelineData(data=tomospec)], force_overwrite=True, outputdir='raw/hollow_cube', - log_level='WARNING') + **run_config) map_hollow_cube = MapProcessor.run( - config=map_config, - detector_config=detector_config, - log_level='WARNING') + config=map_config, detector_config=detector_config, **run_config) data = [PipelineData( name='MapProcessor', data=map_hollow_cube, schema='tomofields')] @@ -110,7 +81,7 @@ def test_id3b(self): 'scan_numbers': 1}], }, detector_config=detector_config, - log_level='WARNING') + **run_config) data.append(PipelineData( name='SpecReader', data=darkfield, schema='darkfield')) @@ -124,80 +95,60 @@ def test_id3b(self): 'scan_numbers': 2}], }, detector_config=detector_config, - log_level='WARNING') + **run_config) data.append(PipelineData( name='SpecReader', data=brightfield, schema='brightfield')) - data = list(TomoCHESSMapConverter.run(data=data, log_level='WARNING')) + data = list(TomoCHESSMapConverter.run(data=data, **run_config)) + reduce_config = YAMLReader.run( + filename='reduce_data_id3b.yaml', **run_config) data += list(TomoReduceProcessor.run( - data=data, - config={'img_row_bounds': [3, 35]}, - save_figures=False, - interactive=False, - log_level='WARNING')) + data=data, config=reduce_config, save_figures=False, **run_config)) + center_config = YAMLReader.run( + filename='find_center_id3b.yaml', **run_config) data += TomoFindCenterProcessor.run( - data=data, - config={ - 'center_rows': [11, 28], - 'gaussian_sigma': 0.05, - 'ring_width': 1, - }, - save_figures=False, - interactive=False, - log_level='WARNING') + data=data, config=center_config, save_figures=False, **run_config) + recon_config = YAMLReader.run( + filename='reconstruct_data.yaml', **run_config) data += TomoReconstructProcessor.run( - data=data, - config={ - 'x_bounds': [15, 390], - 'y_bounds': [25, 380], - 'secondary_iters': 10, - 'ring_width': 1, - }, - save_figures=False, - interactive=False, - log_level='WARNING') + data=data, config=recon_config, save_figures=False, **run_config) tomodata = PipelineItem.get_data(data, schema='tomodata') nxentry = tomodata[tomodata.default] nxdata = nxentry[nxentry.default] reconstructed_data = nxdata.nxsignal - assert reconstructed_data.shape == (32, 355, 375) + assert reconstructed_data.shape == ( + reduce_config['img_row_bounds'][1] - + reduce_config['img_row_bounds'][0], + recon_config['y_bounds'][1] - + recon_config['y_bounds'][0], + recon_config['x_bounds'][1] - + recon_config['x_bounds'][0]) assert pytest.approx(reconstructed_data.sum()) == 164.28904724121094 metadata = PipelineItem.get_data( data, schema='foxden.reader.FoxdenMetadataReader') + user_metadata = { + 'findcenter': TomoFindCenterConfig( + center_offsets=[-0.5, -0.5], center_stack_index=0, + **center_config).model_dump(), + 'reconstructed_data': TomoReconstructConfig( + z_bounds=[ + 0, + reduce_config['img_row_bounds'][1] - + reduce_config['img_row_bounds'][0]], + **recon_config).model_dump(), + 'reduced_data': TomoReduceConfig(**reduce_config).model_dump(), + } assert metadata == { 'btr': 'unknown', 'did': '/workflow=tomo_reconstruct', 'parent_did': None, 'schema': 'user', - 'user_metadata': { - 'findcenter': { - 'center_offset_max': None, - 'center_offset_min': None, - 'center_offsets': [-0.5, -0.5], - 'center_rows': [11, 28], - 'center_search_range': None, - 'center_stack_index': 0, - 'gaussian_sigma': 0.05, - 'ring_width': 1.0}, - 'reconstructed_data': { - 'gaussian_sigma': None, - 'remove_stripe_sigma': None, - 'ring_width': 1.0, - 'secondary_iters': 10, - 'x_bounds': [15, 390], - 'y_bounds': [25, 380], - 'z_bounds': [0, 32]}, - 'reduced_data': { - 'delta_theta': None, - 'img_row_bounds': [3, 35], - 'remove_stripe': {}}, - }, - } + 'user_metadata': user_metadata} provenance = PipelineItem.get_data( data, schema='foxden.reader.FoxdenProvenanceReader')