From 80dc23dec3e49713d8434714c23e8275749e3c72 Mon Sep 17 00:00:00 2001 From: Saurabh Mogre Date: Fri, 23 Jun 2023 10:49:09 -0700 Subject: [PATCH] Export packing outputs as a tiff file (#166) * refactor loops over ingredients and compartments in ImageWriter * linting * formatting with black * remove duplicated image export --- cellpack/autopack/Analysis.py | 1 - cellpack/autopack/Environment.py | 79 +++++++++++++++++-- cellpack/autopack/writers/ImageWriter.py | 46 +---------- .../packing-configs/test_image_config.json | 30 +++++++ 4 files changed, 106 insertions(+), 50 deletions(-) create mode 100644 cellpack/tests/packing-configs/test_image_config.json diff --git a/cellpack/autopack/Analysis.py b/cellpack/autopack/Analysis.py index fdccebb34..49d757b96 100644 --- a/cellpack/autopack/Analysis.py +++ b/cellpack/autopack/Analysis.py @@ -35,7 +35,6 @@ from cellpack.autopack.upy.colors import map_colors from cellpack.autopack.utils import check_paired_key, get_paired_key from cellpack.autopack.writers.ImageWriter import ImageWriter - import concurrent.futures import multiprocessing diff --git a/cellpack/autopack/Environment.py b/cellpack/autopack/Environment.py index fd83101dd..3c1d45f65 100644 --- a/cellpack/autopack/Environment.py +++ b/cellpack/autopack/Environment.py @@ -585,7 +585,8 @@ def save_result( self.log.info("time to save result file %d", time() - t0) if vAnalysis == 1: - # START Analysis Tools: Graham added back this big chunk of code for analysis tools and graphic on 5/16/12 + # START Analysis Tools: Graham added back this big chunk of code + # for analysis tools and graphic on 5/16/12 # Needs to be cleaned up into a function and proper uPy code # totalVolume = self.grid.gridVolume*unitVol unitVol = self.grid.gridSpacing**3 @@ -754,8 +755,9 @@ def save_result( self.log.info("self.gridVolume = %d", self.grid.gridVolume) self.log.info("histoVol.timeUpDistLoopTotal = %d", self.timeUpDistLoopTotal) - # END Analysis Tools: Graham added back this big chunk of code for analysis tools and graphic on 5/16/12 - # Needs to be cleaned up into a function and proper uPy code + # END Analysis Tools: Graham added back this big chunk of code + # for analysis tools and graphic on 5/16/12 + # Needs to be cleaned up into a function and proper uPy code self.log.info("time to save end %d", time() - t0) def loadResult( @@ -1392,7 +1394,6 @@ def buildGrid(self, rebuild=True): if self.previous_grid_file is not None: distance = self.grid.distToClosestSurf # [:] nbFreePoints = nbPoints # -1 - # Graham turned this off on 5/16/12 to match August Repair for May Hybrid for i, mingrs in enumerate( self.molecules ): # ( jtrans, rotMatj, self, ptInd ) @@ -1724,8 +1725,9 @@ def pickIngredient(self, vThreshStart, verbose=0): ingr = self.activeIngr[0] else: # prob = uniform(vRangeStart,1.0) - # Graham 9/21/11 This is wrong...vRangeStart is the point index, - # need active list i.e. thresholdPriority to be limited + # #Graham 9/21/11 This is wrong... + # vRangeStart is the point index, need active list + # i.e. thresholdPriority to be limited prob = uniform(0, 1.0) ingrInd = 0 for threshProb in self.thresholdPriorities: @@ -3350,3 +3352,68 @@ def applyStep(self, step): # if self.traj.traj_type=="dcd" or self.traj.traj_type=="xyz": self.traj.applyState_primitive_name(self, step) # ho can we apply to parent instance the rotatiotn? + + def create_voxelization(self, image_data, image_size, voxel_size, hollow=False): + """ + Update the image data for all molecules in the recipe by creating voxelized + representations. + + Parameters + ---------- + image_data: numpy.ndarray + The image data to update. + image_size: list + The size of the image data. + voxel_size: float + The size of a voxel in the image data. + hollow: bool + If True, the voxelization will be hollow. + + Returns + ---------- + image_data: numpy.ndarray + The updated image data. + """ + channel_colors = [] + for pos, rot, ingr, _ in self.molecules: + if ingr.name not in image_data: + image_data[ingr.name] = numpy.zeros(image_size, dtype=numpy.uint8) + if ingr.color is not None: + color = ingr.color + if all([x <= 1 for x in ingr.color]): + color = [int(col * 255) for col in ingr.color] + channel_colors.append(color) + + image_data[ingr.name] = ingr.create_voxelization( + image_data=image_data[ingr.name], + bounding_box=self.boundingBox, + voxel_size=voxel_size, + image_size=image_size, + position=pos, + rotation=rot, + ) + + for compartment in self.compartments: + if compartment.name not in image_data: + image_data[compartment.name] = numpy.zeros( + image_size, dtype=numpy.uint8 + ) + if hasattr(compartment, "color") and compartment.color is not None: + color = compartment.color + if all([x <= 1 for x in compartment.color]): + color = [int(col * 255) for col in compartment.color] + channel_colors.append(color) + else: + channel_colors.append([0, 255, 0]) + + image_data[compartment.name] = compartment.create_voxelization( + image_data=image_data[compartment.name], + bounding_box=self.boundingBox, + voxel_size=voxel_size, + image_size=image_size, + position=compartment.position, + mesh_store=self.mesh_store, + hollow=hollow, + ) + + return image_data, channel_colors diff --git a/cellpack/autopack/writers/ImageWriter.py b/cellpack/autopack/writers/ImageWriter.py index bd7dfc619..911553f74 100644 --- a/cellpack/autopack/writers/ImageWriter.py +++ b/cellpack/autopack/writers/ImageWriter.py @@ -178,50 +178,10 @@ def create_voxelization(self): """ Creates a voxelized representation of the current scene """ - channel_colors = [] - - for pos, rot, ingr, _ in self.env.molecules: - if ingr.name not in self.image_data: - self.image_data[ingr.name] = numpy.zeros( - self.image_size, dtype=numpy.uint8 - ) - if ingr.color is not None: - color = ingr.color - if all([x <= 1 for x in ingr.color]): - color = [int(col * 255) for col in ingr.color] - channel_colors.append(color) - - self.image_data[ingr.name] = ingr.create_voxelization( - image_data=self.image_data[ingr.name], - bounding_box=self.env.boundingBox, - voxel_size=self.voxel_size, - image_size=self.image_size, - position=pos, - rotation=rot, - ) - for compartment in self.env.compartments: - if compartment.name not in self.image_data: - self.image_data[compartment.name] = numpy.zeros( - self.image_size, dtype=numpy.uint8 - ) - if hasattr(compartment, "color") and compartment.color is not None: - color = compartment.color - if all([x <= 1 for x in compartment.color]): - color = [int(col * 255) for col in compartment.color] - channel_colors.append(color) - else: - channel_colors.append([0, 255, 0]) - - self.image_data[compartment.name] = compartment.create_voxelization( - image_data=self.image_data[compartment.name], - bounding_box=self.env.boundingBox, - voxel_size=self.voxel_size, - image_size=self.image_size, - position=compartment.position, - mesh_store=self.env.mesh_store, - hollow=self.hollow, - ) + self.image_data, channel_colors = self.env.create_voxelization( + self.image_data, self.image_size, self.voxel_size, self.hollow + ) concatenated_image = numpy.zeros( (len(self.image_data), *self.image_size), dtype=numpy.uint8 diff --git a/cellpack/tests/packing-configs/test_image_config.json b/cellpack/tests/packing-configs/test_image_config.json new file mode 100644 index 000000000..d4537d440 --- /dev/null +++ b/cellpack/tests/packing-configs/test_image_config.json @@ -0,0 +1,30 @@ +{ + "name": "test_image_config_convolved", + "format": "simularium", + "inner_grid_method": "trimesh", + "live_packing": false, + "ordered_packing": false, + "out": "out/", + "overwrite_place_method": true, + "place_method": "spheresSST", + "save_analyze_result": true, + "show_grid_plot": true, + "number_of_packings": 1, + "spacing": null, + "use_periodicity": false, + "show_sphere_trees": false, + "load_from_grid_file": true, + "save_converted_recipe": true, + "image_export_options": { + "hollow": false, + "voxel_size": [1,1,1], + "projection_axis": "z", + "convolution_options": { + "psf": "gaussian", + "psf_parameters":{ + "sigma": 2, + "size": [5,5,5] + } + } + } +} \ No newline at end of file