Skip to content

September 2025 new azimuthal average changes - #549

Closed
Heidy-Elkhaligy wants to merge 3 commits into
masterfrom
new_azimuthal_average
Closed

September 2025 new azimuthal average changes#549
Heidy-Elkhaligy wants to merge 3 commits into
masterfrom
new_azimuthal_average

Conversation

@Heidy-Elkhaligy

Copy link
Copy Markdown
Collaborator

image.cpp added AverageRotationally and ApplyRampFilter( ) functions azimuthal_average.cpp now contains diameTR, RASTR and SPOT-RASTR options

Description

Old version: Alignment was performed via iterative real-space cross-correlation with angle scanning until convergence.
New version: Alignment now supports an initial alignment step using autocorrelation and Fourier Transform (FT), which generates a reference image for a second round of alignment using cross-correlation, providing more robust and faster convergence
New additions in the new version:

  1. Diameter determination (diameTR): Automatic detection of tube boundaries and support for binning by tube diameter.
  2. Added RASTR (Reconstruction of Average Subtracted Tubular Regions) option, which isolates small areas of tubular architecture by subtracting a masked azimuthal average.
  3. Added SPOT-RASTR (Specimen Preparation On a Tube – RASTR) to subtract the signal of the lipid nano-tubes

Fixes # (issue)

I have rebased my feature branch to be current with the master branch using to minimize conflicts and headaches

  • yes
  • no

Which compilers were tested

  • g++
  • icpc
  • clang
  • other (please specify)

These changes are isolated to the

  • gui
  • core library
  • gpu core library
  • program it modifies

How has the functionality been tested?

Please describe the tests that you ran to verify your changes. Please also note any relevant details for your test configuration.

  • Tested manually from GUI
  • Tested manually from CLI
  • Passed console tests
  • Passed samples functional testing
  • other (please specify)

Checklist:

  • I have not changed anything that did not need to be changed
  • I have performed a self-review of my own code
  • I have commented my code, (w.r.t. why), particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation {Ok to pass for now}
  • My changes generate no new warnings
  • Any dependent changes have been merged and published in downstream modules

@bHimes bHimes left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume these methods do what they should. My comments are mostly to clean up some easy performance issues with memory allocations (calls to new) and narrowing the scope of local variables which is safer and allows the compiler to better optimize register usage.

Comment thread src/core/image.cpp Outdated

void Image::AverageRotationally( ) {
// image must be in real space
bool switchBackToComplex = false;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a minor one, but even though cisTEM was built assuming only real-valued inputs, we use real-space complex valued images now in some cases, so let's not introduce a variable named like this. Perhaps input_image_in_fourier_space. The logic would all stay the same.

Comment thread src/core/image.cpp Outdated
long number_of_rings = this->logical_x_dimension;
//float edge_value = current_image->ReturnAverageOfRealValues(std::min(current_image->physical_address_of_box_center_x - 2, current_image->physical_address_of_box_center_y - 2), true);
float edge_value;
double* ring_axis = new double[number_of_rings];

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two problems here:

1 - Calling "new" is very slow.
2 - We should prefer to not add more raw pointers to the project if possible. It's okay to ignore this here i guess.

// Only make one system call
double* ring_buffer = new double[number_of_rings * 3];
// Zero the array (currently done in a later loope)
ZeroArray(ring_buffer, int(number_of_rings * 3))
// Get (non-owning) pointers to slices in that memory buffer. Only the buffer needs to be deallocated.
double* ring_axis = &ring_buffer[number_of_rings*0];
double* ring_values = &ring_buffer[number_of_rings*1];
double* ring_weight = &ring_buffer[number_of_rings*2]
//
// existing code is unchanged
//
// cleanup
// delete[] ring_buffer;

Comment thread src/core/image.cpp Outdated
for ( counter = 0; counter < number_of_rings; counter++ ) {
ring_axis[counter] = 0.0 + counter * (this->ReturnMaximumDiagonalRadius( ) - 0.0) / float(number_of_rings - 1); // Diagonal because we're using the physical address (0 is the upper left corner)
// = counter * (sqrt(pow(physical_address_of_box_center_x, 2) + pow(physical_address_of_box_center_y, 2) + pow(physical_address_of_box_center_z, 2)));
ring_values[counter] = 0; // What is this?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the answer to "what is this?" is probably that the buffer arrays are being forced to zero in this loop. This is added above following initialization so can be removed here for these two lines.

Comment thread src/core/image.cpp
}

// edge radius in real space is 0.5*logical_dimension
long edge_bin = long((0.5 * this->logical_x_dimension - ring_axis[0]) / (ring_axis[1] - ring_axis[0]));

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this method, it is clear we only operate on self, so using "this->" is probably overkill. Up to you, but I would remove them here as it is a bit of clutter.

Comment thread src/core/image.cpp Outdated

// z-dim first; that's each image in the volume (looking "through" the image rather than at the side)
// Nested loops mean move across the image starting at the first image (z), the first row of pixels, going column by column (left to right across the image, going from top to bottom)
for ( z = 0; z < this->logical_z_dimension; z++ ) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the loop values used outside the loop? If not, prefer for (int z = 0 ... ) to restrict "z" scope to the loop it is used in. I realize there is lots of code in the project that intializes everything up top, but that is outdated practice and shouldn't be built on. It is actually LESS performant, which is the original reason for declaring everything up top.

Comment thread src/core/image.cpp Outdated
counter = 0;

for ( z = 0; z < this->logical_z_dimension; z++ ) {
for ( y = 0; y < this->logical_y_dimension; y++ ) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Contrary to what I mentioned above about not initializing a variable before we need to (loop counters) In this case, powf is a somewhat expensive operation, and is the same for every y value in the loop. Also, the "f" means it is for a float, but you are casting the input to a double (which must either be ignored or cast back to a float.) If you want it to be double, you should use "pow". Same for sqrt/sqrtf

   for ( z = 0; z < this->logical_z_dimension; z++ ) {
        float z_radius_squared = powf(float(central_z_pixel - z), 2));
        // or
        double z_radius_squared = pow(double(central_z_pixel - z), 2));
        for ( y = 0; y < this->logical_y_dimension; y++ ) {
            float/double y_radius_squared = ...; // same
            for ( x = 0; x < this->logical_x_dimension; x++ ) {
                radius       = sqrtf(powf(double(central_x_pixel - x), 2) + y_radius_squared + z_radius_squared);

Comment thread src/core/image.cpp Outdated

if ( is_in_real_space ) {
this->ForwardFFT( );
do_reverse_FFT = true;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

see note on the next method, this is a better name than "switchBackToComplex" however it should be do_inverse_FFT if you prefer to match nomenclature with the rest of the world or do_backward_FFT if you prefer to match existing cisTEM nomenclature.

Comment thread src/core/image.cpp Outdated
}

void Image::ApplyRampFilter( ) {
float x;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some notes on this in the other method. Prefer to declare this in the narrowest scope possible (float z just inside the z-loop, float y just inside the y-loop, etc.) This is safer and more performant.

@bHimes

bHimes commented Sep 13, 2025

Copy link
Copy Markdown
Collaborator

Hi @Heidy-Elkhaligy -

I saw a force pushed commit and several conversations marked resolved that were not resolved. I hope this is just an issue with using git/github (which can be a pain in the butt at first.)

If you have any questions about the code review process or the mechanics of how to respond to/push up changes to code review requests, please let me know. I'm happy to also set aside 10-15 min for a quick Zoom to discuss.

If on the other hand, you did mean to mark my comments as resolved without addressing the code or addressing the comments either, please let me know. If you aren't planning on future contributions and just want to "get this done" I'm happy to just accept your PR and then fix the code myself, which is much easier than going through code review.

I only made comments on changes to the Image class as this might affect the project more broadly. If you would like a review of src/programs/azimuthal_average/azimuthal_average.cpp I can do that as well, but am perfectly happy to let that exist in whatever state you find acceptable as it only affects itself.

@twagner9

twagner9 commented Sep 15, 2025

Copy link
Copy Markdown
Collaborator

Hi @Heidy-Elkhaligy -

I saw a force pushed commit and several conversations marked resolved that were not resolved. I hope this is just an issue with using git/github (which can be a pain in the butt at first.)

If you have any questions about the code review process or the mechanics of how to respond to/push up changes to code review requests, please let me know. I'm happy to also set aside 10-15 min for a quick Zoom to discuss.

If on the other hand, you did mean to mark my comments as resolved without addressing the code or addressing the comments either, please let me know. If you aren't planning on future contributions and just want to "get this done" I'm happy to just accept your PR and then fix the code myself, which is much easier than going through code review.

I only made comments on changes to the Image class as this might affect the project more broadly. If you would like a review of src/programs/azimuthal_average/azimuthal_average.cpp I can do that as well, but am perfectly happy to let that exist in whatever state you find acceptable as it only affects itself.

Sorry @bHimes, I am working with @Heidy-Elkhaligy on this PR in-office -- we have been going through the comments you've suggested and implementing them, @Heidy-Elkhaligy is also just going through some of her azimuthal_average.cpp code as well to check if there's anything else she wants to correct there before pushing. In the future I will be sure to drop a comment sooner to let you know.

But, apologies for not letting you know sooner, and the changes will probably be pushed sometime this week!

@Heidy-Elkhaligy

Heidy-Elkhaligy commented Sep 15, 2025

Copy link
Copy Markdown
Collaborator Author

@bHimes Thanks for pointing this out! I thought that resolving comments locally wouldn’t mark them as resolved until after I push the changes, that was my mistake 😊. It’s my first time working on a pull request, so Tim @twagner9 was helping me on Friday.
I will push the current changes so you can see them now. I really appreciate your patience and the offer to help walk me through the process.

@bHimes

bHimes commented Sep 15, 2025 via email

Copy link
Copy Markdown
Collaborator

image.cpp added AverageRotationally and ApplyRampFilter( ) functions
azimuthal_average.cpp  now contains RASTR and SPOT-RASTR  options
1. Renamed variables for clarity:
   - switchBackToComplex → input_image_in_fourier_space
   - do_reverse_FFT → do_backward_FFT
2. Replaced raw pointers with smart pointers and removed delete[] calls
3. Restricted loop variables to local scope
4. Optimized powf/sqrtf usage by removing redundant powf calls
1. Renamed variables for clarity
2. Replaced some raw pointers with smart pointers and removed delete[] calls
3. Restricted loop variables to local scope
@Heidy-Elkhaligy

Copy link
Copy Markdown
Collaborator Author

@bHimes, I implemented some of the changes you suggested in image.cpp within azimuthal_average.cpp. Sorry for the force push; it was necessary because we had to rebase. I’d appreciate your help reviewing those updates.

@Heidy-Elkhaligy

Copy link
Copy Markdown
Collaborator Author

@bHimes I'm also going on a month-long vacation starting this week. Therefore, there's no rush to review the code, as I won't be able to make any changes during that time. Thank you again for your help and support.

@bHimes

bHimes commented Oct 6, 2025

Copy link
Copy Markdown
Collaborator

Awesome! My kinda traveler. Happy to wait if you'd like to learn more about the process. If you like, i'm also happy to pull in your changes and make any adjustments for you

@Heidy-Elkhaligy

Copy link
Copy Markdown
Collaborator Author

Awesome, thank you! I’d love to learn more about the process and the logic behind the changes so I can avoid making the same mistakes in the future. I’m not a programmer or computer scientist, and my coding skills are pretty basic, so understanding the reasoning would really help me improve. If you decide to go ahead and finish the pull request, I’d really appreciate it if you could point out what I missed or did incorrectly, that would be super helpful for me to learn from!
Thank you for your patience and support!

@timothygrant80

Copy link
Copy Markdown
Owner

@bHimes - are you happy with the state of this now?

@bHimes

bHimes commented Nov 11, 2025

Copy link
Copy Markdown
Collaborator

i'll look it over again tomorrow

@bHimes bHimes mentioned this pull request Nov 12, 2025
21 tasks
@bHimes

bHimes commented Nov 12, 2025

Copy link
Copy Markdown
Collaborator

Included in PR #572, only modified RampFilter method in the Image class, otherwise, the other changes @Heidy-Elkhaligy made looked fine.

@bHimes bHimes closed this Nov 12, 2025
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.

4 participants