Skip to content

Commit

Permalink
Merge pull request #677 from DiamondLightSource/nics_working_branch
Browse files Browse the repository at this point in the history
adds iterative plugin templates
  • Loading branch information
dkazanc authored Jul 6, 2020
2 parents 9d0f148 + 4d73e9a commit 0c3d52d
Show file tree
Hide file tree
Showing 4 changed files with 354 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -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 <scientificsoftware@diamond.ac.uk>
"""

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
Original file line number Diff line number Diff line change
@@ -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 <scientificsoftware@diamond.ac.uk>
"""

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
Original file line number Diff line number Diff line change
@@ -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 <scientificsoftware@diamond.ac.uk>
"""

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
Original file line number Diff line number Diff line change
@@ -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 <scientificsoftware@diamond.ac.uk>
"""

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

0 comments on commit 0c3d52d

Please sign in to comment.