-
Notifications
You must be signed in to change notification settings - Fork 11
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
Incorporating height profile into GrainStats #871
Conversation
40156ae
to
aa8d5e6
Compare
Saves height profiles across the maximum feret of cropped grains to JSON (`height_profiles.json`). Controlled by the `extract_height_profile` option under `grainstats` in `default_config.yaml`. Regression tests are updated to include this new output and new tests introduced where required.
One of the tests was deliberately skipped and looked weird as only three points were interpolated. On starting to incorporate into the main workflow tests revealed why this is. The feret coordinates were being sorted independently which was a mistake, it decoupled and often flipped over the points between which interpolation was occurring. Further we were always taking the x-axis and interpolating along that but when the y-axis was the longer distance this resulted in sparse interpolation. Instead we now perform linear interpolation on the axis with longest difference first and then interpolate the points on the other axis to determine the points at which we want to interpolate heights.
aa8d5e6
to
3c11103
Compare
Ready for review as I figured out how to update the HDF5 (see #873 for details and future reference). In fixing this I found there was a precision error in the heights on OSX compared to Linux (where the tests were developed) to which end I split the regression test of heights out to their own functions and skip them if the reported I also noticed a missing f-string in one of the |
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.
This works for me, and I am able to extract the height profiles from the HDF5 file and plot them.
Thank you very much for your work on this 🎉
It should be possible to iterate over the dictionary directly using from pathlib import Path
from loguru import logger
import numpy as np
import h5py
import matplotlib.pyplot as plt
FILE_PATH = Path("./minicircle.topostats")
with h5py.File(FILE_PATH, "r") as f:
# print keys
logger.info(f.keys())
height_profiles = f["height_profiles"]["above"]
fig, ax = plt.subplots(figsize=(10,5))
for key, profile in height_profiles.items()
ax.plot(profile, label=key)
ax.set_xlabel("Pixel")
ax.set_ylabel("Height (nm)")
ax.set_title("Height Profiles")
plt.legend()
plt.show() |
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.
🎉
Closes #748
After the protracted wrestling I had of how to get minimum feret distances out (see #755) I've decided to finish this work off now as I'm unlikely to look at it again until September and had been tinkering with it over the last week and it is more efficient to finish it off now than struggle to remember where I was in two months time.
This PR includes two commits, importantly one fixes a problem with the
topostats.measure.height_profiles.interpolate_height_profiles()
which was introduced in #859 (details on that below).Height Profiles
The option
extract_height_profile
has been introduced to thegrainstats
section ofdefault_config.yaml
, whentrue
this will trigger extraction of height profiles along the maximum feret. These are aggregated across all "grains" and images and written to a JSON file (height_profiles.json
) adjacent toall_statistics.csv
in the specified output directory.JSON is used because CSV is not particularly conducive to this data structure as profiles are taken across cropped images which differ in size.
This necessitated adding a dependency for
numpyencoder
which correctly and safely converts Numpydtypes
to a format thatjson.dump()
can write.I have a suspicion that at some point it will be desirable to generate line plots of these which is possible but for now users will have to extract the data align and plot these themselves (if anyone does this and wants to share or contribute their solution to TopoStats that would be very much appreciated).
Fixing
interpolate_height_profiles()
#859In #859 I had mistakenly used
np.sort()
on the feret co-ordinates. Two of tests developed there passed, one I opted to skip (The maximum feret was almost horizontal and this should have raised flags as it was indicative of another problem, namely that we should interpolate in such a manner as to get as many points as possible along the line of the maximum feret)When it came to developing tests to incorporate height profile extraction into the work flow of
GrainStats()
it revealed that things were not as they should be as whilst the feret coordinates were correct point interpolation resulted in...Clearly not what we wanted! This arose because
np.interp()
expects "monotonically increasing sample points" and in some of the above the feret coordinates were returned with the highest value first and were therefore decreasing.Solution
In order to get the interpolation correct after identifying these problems two changes were made.
The points are now correctly interpolated regardless of the order in which the feret coordinates are returned and we get the greatest detail by doing so along the longest x/y axis first.
As a bonus the test that was previously skipped is now looking as expected and has been reinstated.