-
Notifications
You must be signed in to change notification settings - Fork 68
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
Bug fixes and input checks for make_trapezoid
#212
Conversation
…pplied. Better warnings for incorrect inputs.
Hey. Thanks for taking care of it @btasdelen I think it would be the right moment to think about and implement all possible input arg combinations and add tests for all of them. I won't find the time before thursday afternoon / friday, but would be happy to contribute. |
@btasdelen Can you explain the computation for the second case? Shouldn't it consider a flat time as well? By setting |
@FrankZijlstra Oh shoot, you are right. Do we go back to setting |
I think that is the most reasonable assumption. As for the structure of the function, maybe it would be a little clearer if all parameters are set to if amplitude is not None and duration is not None:
...
elif flat_area is not None and flat_time is not None:
...
elif area is not None:
...
elif ...: There would be more repeated code though, and each case would still need some nested if's for checking that no other ambiguous parameters are set and variations of the same case (e.g. |
As for all the possible combinations, I wrote a little script using sympy to enumerate all that are non-ambiguous:
Of course, not all of these make sense to implement... E.g. only specifying |
@FrankZijlstra I think a good portion of these options at the end just calculates the missing information, and at the end, there are actually only a couple of way to design the gradient. To avoid too much code repetition, what I have in mind is each condition may fill the missing information, and sets a variable that determines which way will be used (i.e. by area, or by amplitude). That is way too many combinations. I suggest only implement the ways that are actually useful, but also warn the user for any other case. If someone somewhere has an edge case that needs a specific combination of input, they can let us know and we can add it. Higher the complication, worse the bugs. I will have time to do these in 2-3 days. In the meantime, please let me know if there are ideas. |
Looking at the possible combinations, I think the main cases are (where the ones marked with (x) is what the current code more or less covers):
I don't think that is too many per se. Within these cases, the timing would have to be figured out, depending on which timing parameters are specified. The main question then is whether the timing is fully specified, or whether something will need to be inferred. It's possible there is some common code related to the timing that can be put before checking which case we are using. And if you consider Splitting the case explicitly would also be easier to test. Knowing which of |
Thanks for rewriting the function @btasdelen. I will definitely have a look at it and go through evertything in detail, but not sure when I find the time. But I guess it's not super urgent anyway, is it? |
@schuenke I don't think it is urgent, there are a couple of bug fixes regarding the input checks, but nothing critical. Overall calculation and the logic is the same as before. A short summary of the rework:
There are small things left to do:
|
Currently, if we provide def calculate_shortest_params_for_area(area: float, max_slew: float, max_grad: float, grad_raster_time: float):
"""Calculate the shortest possible rise_time, flat_time, and fall_time for a given area."""
if area == 0: # typical case in phase encoding loops
# If the area is 0, return all times and amplitude as 0
return 0.0, 0.0, 0.0, 0.0
... |
How about we check in |
Does the interpreter on the scanner accept zero duration gradients? I don't think I ever tried this. And perhaps there are slew rate checks that would fail in our code? But even if it is accepted, it should only be returned if the user did not specify any other timing. |
I was wondering the same. I know that rf pulses with amp = 0 were and probably still are a problem. And blocks with only labels and no duration can also cause problems, no? So maybe it's safer to keep it the way it is, but I will still try out the 0 duration gradients on the scanner next week. Hopefully... |
This PR contains bug fixes, too. I suggest we merge this, and create a new PR for future discussion, if you agree @schuenke? |
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.
lgtm
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 to me for now, though it could use some more tests. I think combined with the sequence examples tests in #220 we should have a better idea whether anything broke.
Tries to address #211.
Instead of throwing an error, I printed a
UserWarning
for whenarea
andrise_time
is supplied. I am not sure if there is a good case for solving an optimization to find the shortest trapezoid for a fixedrise_time
andarea
, let me know if it is of interest.For the second case, I believe there is a bug with setting
fall_time
whenduration
andrise_time
is supplied. I also added a sanity check that covers the case in #211.If this is a good time to overhaul input sanity checks for this function, let me know, we can brainstorm it. I find the current structure too nested and convoluted.