Skip to content

add a recipe module to modify the origin when needed#1483

Open
Yujin-Bao wants to merge 2 commits into
python-microscopy:masterfrom
Yujin-Bao:add_recipe_module_offset_origin
Open

add a recipe module to modify the origin when needed#1483
Yujin-Bao wants to merge 2 commits into
python-microscopy:masterfrom
Yujin-Bao:add_recipe_module_offset_origin

Conversation

@Yujin-Bao
Copy link
Copy Markdown
Contributor

Is this a bugfix or an enhancement?
Enchancement

Proposed changes:
With this module we could modify the xy origin in PYMEImage. This could serve as the initial coarse offset before calculating the shiftmap of two cameras/modalities. I did not try do to it in PYMEAcquire because practically there would be some drift and the shiftmap should be calibrated regularly (once every 2 to 3 weeks). Every time the initial offset is a little bit different.

Checklist:
The below is a list of things what will be considered when reviewing PRs. It is not prescriptive, and does not
imply that PRs which touch any of these will be rejected but gives a rough indication of where there is a potential
for hangups (i.e. factors which could turn a 5 min review into a half hour or longer and shunt it to the bottom
of the TODO list).

  • [√] Does the PR avoid variable renaming in existing code, whitespace changes, and other forms of tidying? [There is a place for code tidying, but it makes reviewing
    much simpler if this is kept separate from functional changes. The auto-formatting performed by some editors is particulaly egregious and can lead to files with thousands
    of non-functional changes with a few functional changes scattered amoungst them]

If an enhancement (or non-trivial bugfix):

  • Has this been discussed in advance (feature request, PR proposal, email, or direct conversation)?
  • Does this change how users interact with the software? How will these changes be communicated?
  • [√] Does this maintain backwards compatibility with old data?
  • Does this change the required dependencies?
  • Are there any other side effects of the change?

@David-Baddeley
Copy link
Copy Markdown
Contributor

David-Baddeley commented Mar 7, 2024

A number of thoughts / considerations here:

  • This feels very special case for the general PYME repo, and almost certainly doesn't belong in processing. Maybe this should be in a plugin, or we should write a more generic metadata modification recipe, or potentially add a metadata module to group different metadata modifications together.

  • This is also the wrong way to do it - applyFilter() is deprecated and should not be used. More importantly, the code as written modifies the metadata of the input. It is a pretty important convention that the input is not modified, moreover, it is currently only by accident that modifications to the input data propagate to the output - there is no guarantee that the output metadata is not created and before the call to applyFilter. The correct way of doing it would be to implement completeMetadata(im) (which takes a copy of the output image as a parameter and, by convention executes at the end of module exeution) and make the changes there.

  • While using Filter as a base, and implementing completeMetadata() (along with a dummy apply_filter() which simply returns the data un-modified) would work, it would not be ideal from a performance stand-point, as it will force a copy of the data in memory. A more efficient implementation would be something along the lines of the following:

class SetOriginMetadata(ModuleBase):
    inputImage = Input('input')
    outputImage = Output('output')

    def run(self, inputImage):
        # create a new image, using the data from the old image
        # this re-uses the reference to the unmodified image data so we don't need to allocate more memory
        # but creates a new, empty, metadata
        im = ImageStack(inputImage.data, titleStub=self.outputImage)
        
        # copy the metadata entries from the original image
        im.mdh.copyEntriesFrom(inputImage.mdh)
        
        # add any module-specific metadata to the output image
        self.completeMetadata(im)

        # return the new image
        return im

    def completeMetadata(self, im):
        '''Do any required modifications to the output metadata"
        # Set origin etc ...

@David-Baddeley
Copy link
Copy Markdown
Contributor

David-Baddeley commented Mar 7, 2024

Actually, on second thoughts, don't implement completeMetadata - just make the changes in run() method on the new image metadata. ie ...

class SetOriginMetadata(ModuleBase):
    inputImage = Input('input')
    outputImage = Output('output')

    def run(self, inputImage):
        # create a new image, using the data from the old image
        # this re-uses the reference to the unmodified image data so we don't need to allocate more memory
        # but creates a new, empty, metadata
        im = ImageStack(inputImage.data, titleStub=self.outputImage)
        
        # copy the metadata entries from the original image (note, this is not technically required, as the .execute()
        # method will automatically copy (merge) the input metadata to the output, but it doesn't hurt to be explicit)
        im.mdh.copyEntriesFrom(inputImage.mdh)
        
        # add any module-specific metadata to the output image
        im.mdh['Origin.x'] = #New origin value
        ....

        # return the new image.
        return im

The rationale here is the completeMetadata() is a bit of a relic whose function has mostly been moved to ModuleBase.execute() and should be retired.

@David-Baddeley
Copy link
Copy Markdown
Contributor

Also note that "Origin.x" etc are in units of nm, not pixels, and would need to be Float()s rather than Int()

@Yujin-Bao
Copy link
Copy Markdown
Contributor Author

Thanks, David! I am also not sure either if this is a long-term solution, but making the origin changable does make it easier to overlay two imaging modalities on different cameras, although the origin is actually an 'effective origin' based on users and instrument instead of 'real metadata origin'. Previously I used im.mdh.Camera.ROIOriginX because Origin.x metadata in OI-DIC images are missing (have not looked into why). But I made the suggested changes and adding Origin.x metadata also did work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants