From 4d73e9af131327476e8d41d3e811b1d5dc6eb623 Mon Sep 17 00:00:00 2001 From: nicwade Date: Tue, 30 Jun 2020 14:03:28 +0100 Subject: [PATCH] adds iterative plugin templates --- .../iterative/testing_iterative_plugin.py | 97 +++++++++++++++++++ .../iterative/testing_iterative_plugin2.py | 76 +++++++++++++++ .../iterative/testing_iterative_plugin3.py | 87 +++++++++++++++++ .../iterative/testing_iterative_plugin4.py | 94 ++++++++++++++++++ 4 files changed, 354 insertions(+) create mode 100644 plugin_examples/plugin_templates/iterative/testing_iterative_plugin.py create mode 100644 plugin_examples/plugin_templates/iterative/testing_iterative_plugin2.py create mode 100644 plugin_examples/plugin_templates/iterative/testing_iterative_plugin3.py create mode 100644 plugin_examples/plugin_templates/iterative/testing_iterative_plugin4.py diff --git a/plugin_examples/plugin_templates/iterative/testing_iterative_plugin.py b/plugin_examples/plugin_templates/iterative/testing_iterative_plugin.py new file mode 100644 index 000000000..e57d7a221 --- /dev/null +++ b/plugin_examples/plugin_templates/iterative/testing_iterative_plugin.py @@ -0,0 +1,97 @@ +# Copyright 2014 Diamond Light Source Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +.. module:: iterative_plugin + :platform: Unix + :synopsis: Iterative plugin example +.. moduleauthor:: Nicola Wadeson +""" + +import numpy as np + +from savu.plugins.utils import register_plugin +from savu.plugins.filters.base_filter import BaseFilter +from savu.plugins.driver.iterative_plugin import IterativePlugin + + +@register_plugin +class TestingIterativePlugin(BaseFilter, IterativePlugin): + """ + A plugin to test the iterative plugin driver + + :u*param nIterations: Number of iterations. Default: 10. + + """ + + def __init__(self): + super(TestingIterativePlugin, self).__init__("TestingIterativePlugin") + + def pre_process(self): + self.set_iterations(self.parameters['nIterations']) + + def process_frames(self, data): + # A random example function + if self.get_iteration() == 0: + return np.zeros(data[0].shape, dtype=np.float32) + return data[1] + np.ones(data[0].shape, dtype=np.float32)*10 + + def post_process(self): + # option here to break out of the iterations + #self.set_processing_complete() + pass + + def setup(self): + # set up the output dataset that is created by the plugin + in_dataset, out_dataset = self.get_datasets() + + in_pData, out_pData = self.get_plugin_datasets() + in_pData[0].plugin_data_setup('SINOGRAM', 'single') + + # Cloned datasets are at the end of the out_dataset list + out_dataset[0].create_dataset(in_dataset[0]) + + # What is a cloned dataset? + # Since each dataset in Savu has its own backing hdf5 file, a dataset + # cannot be used for input and output at the same time. So, in the + # case of iterative plugins, if a dataset is used as output and then + # as input on the next iteration, the subsequent output must be a + # different file. + # A cloned dataset is a copy of another dataset but with a different + # backing file. It doesn't have a name, is not accessible as a dataset + # in the framework and is only used in alternation with another + # dataset to allow it to be used as both input and output + # simultaneously. + + # This is a cloned dataset (of out_dataset[0]) + self.create_clone(out_dataset[1], out_dataset[0]) + + out_pData[0].plugin_data_setup('SINOGRAM', 'single') + out_pData[1].plugin_data_setup('SINOGRAM', 'single') + + # input and output datasets for the first iteration + self.set_iteration_datasets(0, [in_dataset[0]], [out_dataset[0]]) + # input and output datasets for subsequent iterations + self.set_iteration_datasets(1, [in_dataset[0], out_dataset[0]], + [out_dataset[1]]) + # out_dataset[0] and out_dataset[1] will continue to alternate for + # all remaining iterations i.e. output becomes input and input becomes + # output. + + # total number of output datasets + def nOutput_datasets(self): + return 2 + + # total number of output datasets that are clones + def nClone_datasets(self): + return 1 diff --git a/plugin_examples/plugin_templates/iterative/testing_iterative_plugin2.py b/plugin_examples/plugin_templates/iterative/testing_iterative_plugin2.py new file mode 100644 index 000000000..ebb7b2f8c --- /dev/null +++ b/plugin_examples/plugin_templates/iterative/testing_iterative_plugin2.py @@ -0,0 +1,76 @@ +# Copyright 2014 Diamond Light Source Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +.. module:: testing_iterative_plugin2 + :platform: Unix + :synopsis: Iterative plugin example +.. moduleauthor:: Nicola Wadeson +""" + +import numpy as np + +from savu.plugins.utils import register_plugin +from savu.plugins.filters.base_filter import BaseFilter +from savu.plugins.driver.iterative_plugin import IterativePlugin + + +@register_plugin +class TestingIterativePlugin2(BaseFilter, IterativePlugin): + """ + A plugin to test the iterative plugin driver + """ + + def __init__(self): + super(TestingIterativePlugin2, self).\ + __init__("TestingIterativePlugin2") + + def pre_process(self): + self.set_iterations(3) + + def process_frames(self, data): + if self.get_iteration() == 0: + return data[0] + return data[0] + + def post_process(self): + # option here to break out of the iterations + # self.set_processing_complete() + pass + + def setup(self): + self.exp.log(self.name + " Start") + + # set up the output dataset that is created by the plugin + in_dataset, out_dataset = self.get_datasets() + + in_pData, out_pData = self.get_plugin_datasets() + in_pData[0].plugin_data_setup('SINOGRAM', 'single') + + out_dataset[0].create_dataset(in_dataset[0]) + self.clone_dataset(out_dataset[1], out_dataset[0]) + + out_pData[0].plugin_data_setup('SINOGRAM', 'single') + out_pData[1].plugin_data_setup('SINOGRAM', 'single') + + # try replacing input dataset with the output dataset + self.set_iteration_datasets(0, [in_dataset[0]], [out_dataset[0]]) + self.set_iteration_datasets(1, [out_dataset[0]], [out_dataset[1]]) + + self.exp.log(self.name + " End") + + def nOutput_datasets(self): + return 2 + + def nClone_datasets(self): + return 1 diff --git a/plugin_examples/plugin_templates/iterative/testing_iterative_plugin3.py b/plugin_examples/plugin_templates/iterative/testing_iterative_plugin3.py new file mode 100644 index 000000000..6ec0f905d --- /dev/null +++ b/plugin_examples/plugin_templates/iterative/testing_iterative_plugin3.py @@ -0,0 +1,87 @@ +# Copyright 2014 Diamond Light Source Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +.. module:: testing_iterative_plugin3 + :platform: Unix + :synopsis: Iterative plugin example +.. moduleauthor:: Nicola Wadeson +""" + +from savu.plugins.utils import register_plugin +from savu.plugins.filters.base_filter import BaseFilter +from savu.plugins.driver.iterative_plugin import IterativePlugin + + +@register_plugin +class TestingIterativePlugin3(BaseFilter, IterativePlugin): + """ + A plugin to test the iterative plugin driver + """ + + def __init__(self): + super(TestingIterativePlugin3, self).\ + __init__("TestingIterativePlugin3") + + def pre_process(self): + self.set_iterations(3) + + def process_frames(self, data): + return [data[0], data[0]] + + def post_process(self): + # option here to break out of the iterations + # self.set_processing_complete() + pass + + def setup(self): + self.exp.log(self.name + " Start") + + # set up the output dataset that is created by the plugin + in_dataset, out_dataset = self.get_datasets() + + in_pData, out_pData = self.get_plugin_datasets() + in_pData[0].plugin_data_setup('SINOGRAM', self.get_max_frames()) + + # these are the datasets with names + out_dataset[0].create_dataset(in_dataset[0]) + out_dataset[1].create_dataset(in_dataset[0]) + # these are the clones + out_dataset[2].create_dataset(out_dataset[0]) + out_dataset[3].create_dataset(out_dataset[1]) + + out_pData[0].plugin_data_setup('SINOGRAM', 'single') + out_pData[1].plugin_data_setup('SINOGRAM', 'single') + out_pData[2].plugin_data_setup('SINOGRAM', 'single') + out_pData[3].plugin_data_setup('SINOGRAM', 'single') + + # try replacing input dataset with the output dataset + dIn = [in_dataset[0]] + dOut = [out_dataset[0], out_dataset[1]] + self.set_iteration_datasets(0, dIn, dOut) + + dIn = [out_dataset[0], out_dataset[0], out_dataset[1]] + dOut = [out_dataset[2], out_dataset[3]] + self.set_iteration_datasets(1, dIn, dOut) + + # cloned datasets used as alternating datasets? + self.set_alternating_datasets(out_dataset[0], out_dataset[2]) + self.set_alternating_datasets(out_dataset[1], out_dataset[3]) + + self.exp.log(self.name + " End") + + def nOutput_datasets(self): + return 4 + + def nClone_datasets(self): + return 2 diff --git a/plugin_examples/plugin_templates/iterative/testing_iterative_plugin4.py b/plugin_examples/plugin_templates/iterative/testing_iterative_plugin4.py new file mode 100644 index 000000000..ccd03f508 --- /dev/null +++ b/plugin_examples/plugin_templates/iterative/testing_iterative_plugin4.py @@ -0,0 +1,94 @@ +# Copyright 2014 Diamond Light Source Ltd. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +""" +.. module:: testing_iterative_plugin4 + :platform: Unix + :synopsis: Iterative plugin example +.. moduleauthor:: Nicola Wadeson +""" + +from savu.plugins.utils import register_plugin +from savu.plugins.filters.base_filter import BaseFilter +from savu.plugins.driver.iterative_plugin import IterativePlugin + + +@register_plugin +class TestingIterativePlugin4(BaseFilter, IterativePlugin): + """ + A plugin to test the iterative plugin driver - switching between sinograms + and projections on each iteration. + """ + + def __init__(self): + super(TestingIterativePlugin4, self).\ + __init__("TestingIterativePlugin4") + + def pre_process(self): + self.set_iterations(3) + + def process_frames(self, data): + return data[0] + + def post_process(self): + # option here to break out of the iterations + # self.set_processing_complete() + pass + + def setup(self): + # set up the output dataset that is created by the plugin + in_dataset, out_dataset = self.get_datasets() + + in_pData, out_pData = self.get_plugin_datasets() + in_pData[0].plugin_data_setup('SINOGRAM', 'single') + + out_dataset[0].create_dataset(in_dataset[0]) + # Clone and set as alternating dataset - should I actually do this here? + self.clone_dataset(out_dataset[1], out_dataset[0]) + + # HOw to set more than one pattern associated with a plugin + out_pData[0].plugin_data_setup('SINOGRAM', 'single') # set first pattern + out_pData[1].plugin_data_setup('PROJECTION', 'single') # set first pattern + + # Do I need two plugin data objects? When should I set this? + + # try replacing input dataset with the output dataset *****option to change the pattern on each iteration? + # option to set any number of patterns one after another + self.set_iteration_datasets(0, [in_dataset[0]], [out_dataset[0]], pattern='SINOGRAM') # Add option for pattern to be a dictionary with different pattern for each dataset + self.set_iteration_datasets(1, [out_dataset[0]], [out_dataset[1]], pattern='PROJECTION') # PROJECTION + # out_dataset[0] and out_dataset[1] will continue to alternate for the + # remaining iterations + self.set_alternating_patterns(['SINOGRAM', 'PROJECTION']) # or explicitly add it as above or a combination of both + # it could be that the first two iterations have the same pattern and the remainder alternate + + # alternatively to above you could just have +# self.set_iteration_datasets(0, [in_dataset[0]], [out_dataset[0]]) +# self.set_iteration_datasets(1, [out_dataset[0]], [out_dataset[1]]) +# self.set_alternating_patterns(['SINOGRAM', 'PROJECTION']) # what if there is more than on pattern - this should also be a dictionary + + # So, to set different patterns there are two ways + # first way is to add 'pattern' key word to set_iteration_datasets function call + # second way is to pass a list of patterns to set_alternating_patterns function call + # in either case, each entry can be a list of a dictionary + # if a list apply to all datasets + # if a dictionary, they should be {dataset: pattern} key value pairs + + # Now I just have to make this work - can I just create an extra pluginData object for each dataset and alternate between those? + # Or will I have to calculate mfp/mft every time? + # Don't forget to call "finalise_datasets" or whatever the function is (usually called after the setup method) + + def nOutput_datasets(self): + return 2 + + def nClone_datasets(self): + return 1