diff --git a/PyNutil/coordinate_extraction.py b/PyNutil/coordinate_extraction.py index 232d4f3c698f12f4c3a41fba360a675e1d7c12d3..607d5da05f1bf8f65aae6a88cb0df7a434466784 100644 --- a/PyNutil/coordinate_extraction.py +++ b/PyNutil/coordinate_extraction.py @@ -28,7 +28,7 @@ def getCentroidsAndArea(Segmentation, pixelCutOff=0): # get the area of the objects area = np.array([label.area for label in labelsInfo]) # get the coordinates for all the pixels in each object - coords = np.array([label.coords for label in labelsInfo]) + coords = np.array([label.coords for label in labelsInfo], dtype=object) return centroids, area, coords @@ -79,19 +79,17 @@ def transformToAtlasSpace(anchoring, Y, X, RegHeight, RegWidth): return (O + XYZU + XYZV).T - - - - # points.append would make list of lists, keeping sections separate. # related to coordinate extraction # this function returns an array of points def FolderToAtlasSpace( - folder, QUINT_alignment, pixelID=[0, 0, 0], nonLinear=True + folder, QUINT_alignment, pixelID=[0, 0, 0], nonLinear=True, method="all" ): "apply Segmentation to atlas space to all segmentations in a folder" + + # this should be loaded above and passed as an argument slices = loadVisuAlignJson(QUINT_alignment) segmentationFileTypes = [".png", ".tif", ".tiff", ".jpg", ".jpeg"] @@ -100,7 +98,6 @@ def FolderToAtlasSpace( for file in glob(folder + "/*") if any([file.endswith(type) for type in segmentationFileTypes]) ] - SectionNumbers = number_sections(Segmentations) # order segmentations and sectionNumbers # Segmentations = [x for _,x in sorted(zip(SectionNumbers,Segmentations))] # SectionNumbers.sort() @@ -119,6 +116,7 @@ def FolderToAtlasSpace( nonLinear, pointsList, index, + method, ), ) threads.append(x) @@ -135,12 +133,22 @@ def FolderToAtlasSpace( # related to coordinate extraction # this function returns an array of points def SegmentationToAtlasSpace( - slice, SegmentationPath, pixelID="auto", nonLinear=True, pointsList=None, index=None + slice, + SegmentationPath, + pixelID="auto", + nonLinear=True, + pointsList=None, + index=None, + method="per_pixel", ): """combines many functions to convert a segmentation to atlas space. It takes care of deformations""" Segmentation = cv2.imread(SegmentationPath) - + if method in ["per_object", "all"]: + # this function returns the centroids, area and coordinates of all the objects in the segmentation + # right now we only use centroids + centroids, area, coords = getCentroidsAndArea(Segmentation, pixelCutOff=0) + print("number of objects: ", len(centroids)) if pixelID == "auto": # remove the background from the segmentation SegmentationNoBackGround = Segmentation[~np.all(Segmentation == 255, axis=2)] @@ -166,7 +174,9 @@ def SegmentationToAtlasSpace( triangulation = triangulate(RegWidth, RegHeight, slice["markers"]) newX, newY = transform_vec(triangulation, scaledX, scaledY) else: - print(f"no markers found for {slice['filename']}, result for section will be linear") + print( + f"no markers found for {slice['filename']}, result for section will be linear" + ) newX, newY = scaledX, scaledY else: newX, newY = scaledX, scaledY diff --git a/PyNutil/folder_of_segmentations_to_meshview_multithreaded.py b/PyNutil/folder_of_segmentations_to_meshview_multithreaded.py index ea6f0e3d9a1b8aec00fd5368c8e53dbc04fba8ef..4face1fc061d66275cac8f8a1e06549a1efb4229 100644 --- a/PyNutil/folder_of_segmentations_to_meshview_multithreaded.py +++ b/PyNutil/folder_of_segmentations_to_meshview_multithreaded.py @@ -15,14 +15,14 @@ with open("../test/test5_NOP_s037.json", "r") as f: # print(input) # import our function for converting a folder of segmentations to points -from coordinate_extraction import FolderToAtlasSpace, FolderToAtlasSpaceMultiThreaded +from coordinate_extraction import FolderToAtlasSpace, FolderToAtlasSpace from read_and_write import SaveDataframeasCSV, WritePointsToMeshview, FilesinDirectory from counting_and_load import PixelCountPerRegion, labelPoints startTime = datetime.now() # now we can use our function to convert the folder of segmentations to points -points = FolderToAtlasSpaceMultiThreaded( +points = FolderToAtlasSpace( input["segmentation_folder"], input["alignment_json"], pixelID=input["colour"], diff --git a/PyNutil/main.py b/PyNutil/main.py index 4de8f3e1e657d07776d5f8f8149b42178fdf1bf1..6334ab2db7a9db035e514ee45cf4a045f34fe83f 100644 --- a/PyNutil/main.py +++ b/PyNutil/main.py @@ -6,6 +6,7 @@ import json import pandas as pd from datetime import datetime + class PyNutil: def __init__( self, @@ -37,7 +38,7 @@ class PyNutil: raise ValueError( f"Atlas {volume_path} not found in config file, valid atlases are: \n{' , '.join(list(self.config['annotation_volumes'].keys()))}" ) - + self.segmentation_folder = segmentation_folder self.alignment_json = alignment_json self.colour = colour @@ -45,7 +46,7 @@ class PyNutil: # load the metadata json as well as the path to stored data files def build_quantifier(self): - # do all the expensive computations + # this could potentially be moved into init atlas_root_path = self.config["annotation_volume_directory"] current_atlas_path = self.config["annotation_volumes"][self.atlas]["volume"] print("loading atlas volume") @@ -57,48 +58,59 @@ class PyNutil: print("loading atlas labels") self.atlas_labels = pd.read_csv(atlas_root_path + atlas_label_path) print("atlas labels loaded") - def get_coordinates(self, nonLinear=True, method="all"): if not hasattr(self, "atlas_volume"): - raise ValueError("Please run build_quantifier before running get_coordinates") + raise ValueError( + "Please run build_quantifier before running get_coordinates" + ) if method not in ["per_pixel", "per_object", "all"]: - raise ValueError(f"method {method} not recognised, valid methods are: per_pixel, per_object, or all") + raise ValueError( + f"method {method} not recognised, valid methods are: per_pixel, per_object, or all" + ) print("extracting coordinates") - points = FolderToAtlasSpace( + pixel_points = FolderToAtlasSpace( self.segmentation_folder, self.alignment_json, pixelID=self.colour, - nonLinear=nonLinear + nonLinear=nonLinear, + method=method, ) - self.points = points - + self.pixel_points = pixel_points def quantify_coordinates(self): - if not hasattr(self, "points"): - raise ValueError("Please run get_coordinates before running quantify_coordinates") + if not hasattr(self, "pixel_points"): + raise ValueError( + "Please run get_coordinates before running quantify_coordinates" + ) print("quantifying coordinates") - labeled_points = labelPoints(self.points, self.atlas_volume, scale_factor=2.5) + labeled_points = labelPoints( + self.pixel_points, self.atlas_volume, scale_factor=2.5 + ) self.label_df = PixelCountPerRegion(labeled_points, self.atlas_labels) self.labeled_points = labeled_points print("quantification complete") def save_analysis(self, output_folder): - if not hasattr(self, "points"): + if not hasattr(self, "pixel_points"): raise ValueError("Please run get_coordinates before running save_analysis") + + self.label_df.to_csv( + output_folder + "/counts.csv", sep=";", na_rep="", index=False + ) + if not hasattr(self, "label_df"): print("no quantification found so we will only save the coordinates") - print("if you want to save the quantification please run quantify_coordinates") - self.label_df.to_csv(output_folder + '/counts.csv', sep=";", na_rep="", index=False) + print( + "if you want to save the quantification please run quantify_coordinates" + ) else: - self.label_df.to_csv(output_folder + '/counts.csv', sep=";", na_rep="", index=False) WritePointsToMeshview( - self.points, + self.pixel_points, self.labeled_points, - output_folder + '/pixels_meshview.json', - self.atlas_labels + output_folder + "/pixels_meshview.json", + self.atlas_labels, ) - - + print("analysis saved") diff --git a/PyNutil/read_and_write.py b/PyNutil/read_and_write.py index bbb67301ee23c759395ad04dca302fa25bec979c..9e1849061cf376fdc8130c6547acef6a0812ffb7 100644 --- a/PyNutil/read_and_write.py +++ b/PyNutil/read_and_write.py @@ -53,7 +53,8 @@ def WritePointsToMeshview(points, pointNames, filename, infoFile): regionDict = createRegionDict(points, pointNames) WritePoints(regionDict, filename, infoFile) -# I think this might not need to be its own function :) + +# I think this might not need to be its own function :) def SaveDataframeasCSV(df_to_save, output_csv): """Function for saving a df as a CSV file""" df_to_save.to_csv(output_csv, sep=";", na_rep="", index=False) diff --git a/testOOP.py b/testOOP.py index 9c19e0055f031685e8d599cf5af8c4dd5b32d6d0..7f415c7c8f36162d765b7da0af29036dbe272b43 100644 --- a/testOOP.py +++ b/testOOP.py @@ -1,12 +1,10 @@ from PyNutil import PyNutil -pnt = PyNutil( - settings_file=r"test/test4_2017.json" - ) +pnt = PyNutil(settings_file=r"test/test4_2017.json") pnt.build_quantifier() pnt.get_coordinates() pnt.quantify_coordinates() -pnt.save_analysis('outputs/test4_2017') \ No newline at end of file +pnt.save_analysis("outputs/test4_2017")