-
Notifications
You must be signed in to change notification settings - Fork 56
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Made Adapters Sliceable #285
base: dev
Are you sure you want to change the base?
Conversation
…ed to define set item, might be nice to list indecies of transforms in the default print
… transform was not added to the list for things to imported in the adapter file so added that
Thank you! I will take a look soon! |
A few short questions:
|
Essentially what i meant with my last comment is that you can add a transform to the end of the adapter by slicing. |
Ah, I see. Could you show a code example? Let me know once you have added everything you wanted to add to this PR. |
Appending via slicing is fine, imo. We should have checks in place and error if slices are assigned non-Adapter objects (thus making the adapter self-recursive, each slice is an Adapter itself). That said, best practice should be to use add_transform (could just call this append as well). We could add an insert method to mimic list behavior, too. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good overall, see individual comments for potential changes and discussion.
bayesflow/adapters/adapter.py
Outdated
@@ -76,7 +76,68 @@ def __call__(self, data: dict[str, any], *, inverse: bool = False, **kwargs) -> | |||
return self.forward(data, **kwargs) | |||
|
|||
def __repr__(self): | |||
return f"Adapter([{' -> '.join(map(repr, self.transforms))}])" | |||
str_transf = '' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use double quotes for strings to conform to our style guide.
bayesflow/adapters/adapter.py
Outdated
def __getitem__(self, index): | ||
if isinstance(index, slice): | ||
if index.start > index.stop: | ||
raise IndexError("Index slice must be positive integers such that a < b for adapter[a:b]") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should just return an empty adapter.
bayesflow/adapters/adapter.py
Outdated
if isinstance(index, slice): | ||
if index.start > index.stop: | ||
raise IndexError("Index slice must be positive integers such that a < b for adapter[a:b]") | ||
if index.stop < len(self.transforms): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this works for index.stop = None, which happens when you call adapter[start:]
Best would be to just mimic list behavior via returning Adapter(self.transforms[index])
bayesflow/adapters/adapter.py
Outdated
new_adapter = Adapter(transforms=sliced_transforms) | ||
return new_adapter | ||
else: | ||
raise IndexError("Index slice out of range") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can let the internal list handle this
bayesflow/adapters/adapter.py
Outdated
raise IndexError("Adapter index out of range.") | ||
sliced_transforms = self.transforms[index] | ||
new_adapter = Adapter(transforms=sliced_transforms) | ||
return new_adapter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same idea here, let the internal list handle edge cases
else: | ||
raise TypeError("Invalid index type. Must be int or slice.") | ||
|
||
def __setitem__(self, index, new_value): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems a bit verbose, does the following snippet not work?
self.transforms[index] = new_value.transforms[:]
Or for an integer index:
self.transforms[index:index + 1] = new_value.transforms[:]
…ts that I had previously written
I made the adapters sliceable but one concern I have is that when I ask for
generic_adapter[0:2]
this will return an entirely new adapter instance. Depending on the use case this one matter but could cause problems. I also made a test file but it's not tracked by github, please let me know if I should also upload that.I also noticed that ElementwiseTransform wasn't being imported so added that as well.
I thought it might also be nice to add the indices of the transforms to the default adapter print, but didn't add that particular feature. I also thought it might be nice to add the feature of appending a new transform via slice assignment so if
index == len(adapter.transforms)
then simply use theadd_transform
method.Resolves #274