Skip to content

Commit

Permalink
Simulate square, circle and star shapes
Browse files Browse the repository at this point in the history
  • Loading branch information
Kristina Ulicna committed Aug 21, 2023
1 parent 3b2b3b3 commit 1f9a828
Show file tree
Hide file tree
Showing 5 changed files with 93 additions and 121 deletions.
15 changes: 8 additions & 7 deletions examples/show_cbox.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,20 @@
from grace.base import GraphAttrs
from pathlib import Path

DATA_PATH = Path("/Users/arl/Documents/Turing/Data/Bea/")
FILE_STEM = Path(
"FoilHole_24680421_Data_24671727_24671728_20181024_2216-78563_noDW"
)
IMAGE_PATH = DATA_PATH / FILE_STEM.with_suffix(".mrc")
CBOX_PATH = DATA_PATH / FILE_STEM.with_suffix(".cbox")

# Expects the image data & H5 node positions in the same folder.
# Use identical naming convention for files & specify whole path to mrc file:
# e.g. /Users/kulicna/Desktop/dataset/shape_squares/MRC_Synthetic_File_000.mrc

IMAGE_PATH = Path(input("Enter absolute path to your file: "))
C_BOX_PATH = Path(str(IMAGE_PATH).replace(".mrc", ".cbox"))


with mrcfile.open(IMAGE_PATH, "r") as mrc:
image_data = mrc.data.astype(int)


cbox_df = starfile.read(CBOX_PATH)["cryolo"]
cbox_df = starfile.read(C_BOX_PATH)["cryolo"]

points = np.stack(
[
Expand Down
23 changes: 10 additions & 13 deletions examples/show_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,12 @@
from pathlib import Path


DATA_PATH = Path(
# "/Users/csoelistyo/Documents/grace_files/notebook_test/image_files"
# "/Users/kulicna/Desktop/classifier/data_fake/infer/padded"
"/Users/kulicna/Desktop/dataset/data_squares_simple"
)
IMAGE_FILE = (
# "FoilHole_24680421_Data_24671727_24671728_20181024_2216-78563_noDW"
"MRC_Synthetic_File_000"
)
IMAGE_PATH = DATA_PATH / f"{IMAGE_FILE}.mrc"
NODES_PATH = DATA_PATH / f"{IMAGE_FILE}.h5"
# Expects the image data & H5 node positions in the same folder.
# Use identical naming convention for files & specify whole path to mrc file:
# e.g. /Users/kulicna/Desktop/dataset/shape_squares/MRC_Synthetic_File_000.mrc

IMAGE_PATH = Path(input("Enter absolute path to your file: "))
NODES_PATH = Path(str(IMAGE_PATH).replace(".mrc", ".h5"))


with mrcfile.open(IMAGE_PATH, "r") as mrc:
Expand All @@ -32,12 +27,14 @@
# [np.squeeze(f.numpy()) for f in nodes_data.loc[:, "features"]]
# }
features = None

mn, mx = np.min(image_data), np.max(image_data)

data_name = f"{IMAGE_PATH.stem}"

viewer = napari.Viewer()
img_layer = viewer.add_image(image_data, name=data_name)
img_layer = viewer.add_image(
image_data, name=data_name, contrast_limits=(mn, mx)
)
pts_layer = viewer.add_points(
points, features=features, size=32, name=f"nodes_{data_name}"
)
Expand Down
20 changes: 13 additions & 7 deletions grace/simulator/simulate_dataset.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
def synthetic_image_dataset(
folder_path: str,
num_images: int = 10,
square_type: str = "simple",
drawing_type: str = "square",
object_motif: str = "lines",
image_padding: tuple[int, int] = None,
) -> None:
"""TODO: Fill in."""

Expand All @@ -26,10 +27,11 @@ def synthetic_image_dataset(
# Synthesize a corresponding image:
image, G = synthesize_image_from_graph(
G,
square_type=square_type,
drawing_type=drawing_type,
background_pixel_value=VALUE,
image_shape=(SCALE, SCALE),
patch_shape=(PATCH_SIZE, PATCH_SIZE),
image_padding=image_padding,
)

# Save the image & node coordinates:
Expand All @@ -40,13 +42,17 @@ def synthetic_image_dataset(
if __name__ == "__main__":
VALUE = 0.5
SCALE = 3500
NUM_IMAGES = 10
PATCH_SIZE = 224
SQUARE = "fading"
MOTIF = "lines"
DRAWING = "stars"
PADDING = (112, 112)

# Create a dataset:
synthetic_image_dataset(
folder_path=f"/Users/kulicna/Desktop/dataset/data_squares_{SQUARE}",
num_images=10,
square_type=SQUARE,
object_motif="lines",
folder_path=f"/Users/kulicna/Desktop/dataset/shape_{DRAWING}",
num_images=NUM_IMAGES,
drawing_type=DRAWING,
object_motif=MOTIF,
image_padding=PADDING,
)
154 changes: 61 additions & 93 deletions grace/simulator/simulate_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,36 +47,13 @@ def create_canvas_image(
return image


def _insert_simple_square_into_patch(
original_patch: npt.NDArray,
square_pixel_value: int | float,
) -> npt.NDArray:
"""TODO: Fill in."""

# Get image dimensions
height, width = original_patch.shape

# Calculate the size of the square
square_size = min(height, width) // 2

# Calculate the coordinates of the square's top-left corner
top_left_x = (width - square_size) // 2
top_left_y = (height - square_size) // 2

# Insert a black square in the center
original_patch[
top_left_y : top_left_y + square_size,
top_left_x : top_left_x + square_size,
] = square_pixel_value

return original_patch


def _insert_fading_square_into_patch(
original_patch: npt.NDArray,
square_pixel_value: int | float,
central_pixel_value: int | float,
background_pixel_value: int | float,
) -> npt.NDArray:
"""TODO: Fill in."""

patch_size = original_patch.shape[0]
square_size = patch_size // 2

Expand All @@ -92,44 +69,18 @@ def _insert_fading_square_into_patch(

# Calculate the pixel values with fading squares
faded_patch = (
square_pixel_value - background_pixel_value
central_pixel_value - background_pixel_value
) * fading_factor + background_pixel_value

return faded_patch


# def _insert_circle_into_patch(
# original_patch: npt.NDArray,
# circle_pixel_value: int | float,
# ) -> npt.NDArray:
# """TODO: Fill in."""

# # Get image dimensions
# height, width = original_patch.shape

# # Insert a chosen pixel value at the center
# center_x, center_y = height // 2, width // 2
# # print (height, width, center_x, center_y, circle_pixel_value)
# original_patch[center_y, center_x] = circle_pixel_value

# # Create a Gaussian kernel for blurring
# blur_radius = min(height, width) // 2
# gaussian_kernel = np.outer(
# np.exp(-np.linspace(-1, 1, blur_radius * 2 + 1)**2),
# np.exp(-np.linspace(-1, 1, blur_radius * 2 + 1)**2)
# )
# # Normalize the Gaussian kernel
# gaussian_kernel /= np.sum(gaussian_kernel)
# Average values with the original patch
average_image = (original_patch + faded_patch) / 2

# # Apply radial blur from the center towards the edges
# blurred_patch = gaussian_filter(original_patch, sigma=blur_radius/2)
return average_image

# return blurred_patch


def _insert_circle_into_patch(
def _insert_fading_circle_into_patch(
original_patch: npt.NDArray,
circle_pixel_value: int | float,
central_pixel_value: int | float,
background_pixel_value: int | float,
) -> npt.NDArray:
"""TODO: Fill in."""
Expand All @@ -146,21 +97,24 @@ def _insert_circle_into_patch(
normalized_distances = distances / (patch_size // 2)
transition = (
1 - normalized_distances
) * circle_pixel_value + normalized_distances * background_pixel_value
) * central_pixel_value + normalized_distances * background_pixel_value

# Ensure values are within the specified range
smooth_patch = np.clip(
transition,
min(circle_pixel_value, background_pixel_value),
max(circle_pixel_value, background_pixel_value),
min(central_pixel_value, background_pixel_value),
max(central_pixel_value, background_pixel_value),
)

return smooth_patch
# Average values with the original patch
average_image = (original_patch + smooth_patch) / 2

return average_image


def synthesize_image_from_graph(
G: nx.Graph,
square_type: str,
drawing_type: str,
background_pixel_value: int | float,
image_shape: tuple[int, int],
patch_shape: tuple[int, int],
Expand Down Expand Up @@ -190,58 +144,69 @@ def synthesize_image_from_graph(
image : npt.NDArray
Simulated image.
"""
# Make the shape a plural form:
drawing_type = (
f"{drawing_type}s" if not drawing_type.endswith("s") else drawing_type
)

# Create a fake blank image:
canvas_image = create_canvas_image(background_pixel_value, image_shape)
canvas_image = create_canvas_image(
background_pixel_value, image_shape, image_padding
)

# Iterate through the node positions:
for _, node in G.nodes.data():
coords_max = [image_shape[-1], image_shape[-2]]

if image_padding is not None:
node[GraphAttrs.NODE_X] += image_padding[-1]
node[GraphAttrs.NODE_Y] += image_padding[-2]
coords_max[0] += 2 * image_padding[-1]
coords_max[1] += 2 * image_padding[-2]

x, y = int(node[GraphAttrs.NODE_X]), int(node[GraphAttrs.NODE_Y])

# Randomly choose the value of the pixel:
random_value = np.random.random() * 0.5
intensity_value = (
1 - random_value if node["label"] > 0 else random_value
)

# Define the square type:
if square_type == "simple":
sq_st_x = max(
[int(node[GraphAttrs.NODE_X]) - patch_shape[-1] // 4, 0]
)
sq_en_x = min(
[
int(node[GraphAttrs.NODE_X]) + patch_shape[-1] // 4,
image_shape[-1],
]
)
sq_st_y = max(
[int(node[GraphAttrs.NODE_Y]) - patch_shape[-2] // 4, 0]
)
sq_en_y = min(
[
int(node[GraphAttrs.NODE_Y]) + patch_shape[-2] // 4,
image_shape[-2],
]
)
if drawing_type == "squares":
sq_st_x = max([x - patch_shape[-1] // 4, 0])
sq_en_x = min([x + patch_shape[-1] // 4, coords_max[0]])
sq_st_y = max([y - patch_shape[-2] // 4, 0])
sq_en_y = min([y + patch_shape[-2] // 4, coords_max[1]])
canvas_image[sq_st_x:sq_en_x, sq_st_y:sq_en_y] = intensity_value

elif square_type == "fading":
sq_st_x = int(node[GraphAttrs.NODE_X]) - patch_shape[-1] // 2
sq_en_x = int(node[GraphAttrs.NODE_X]) + patch_shape[-1] // 2
sq_st_y = int(node[GraphAttrs.NODE_Y]) - patch_shape[-2] // 2
sq_en_y = int(node[GraphAttrs.NODE_Y]) + patch_shape[-2] // 2
else:
# Choose an object shape:
if drawing_type == "circles":
drawing_function = _insert_fading_circle_into_patch
elif drawing_type == "stars":
drawing_function = _insert_fading_square_into_patch
else:
pass

# List the coords:
sq_st_x = x - patch_shape[-1] // 2
sq_en_x = x + patch_shape[-1] // 2
sq_st_y = y - patch_shape[-2] // 2
sq_en_y = y + patch_shape[-2] // 2
coords = [sq_st_x, sq_en_x, sq_st_y, sq_en_y]
if min(coords) < 0 or max(coords) > max(image_shape):

# Shortlist (ignore, TODO: fix) boundary nodes:
if min(coords) < 0 or max(coords) > max(coords_max):
continue

# Draw the object into the patch:
patch_to_modify = canvas_image[sq_st_x:sq_en_x, sq_st_y:sq_en_y]
modified_patch = _insert_fading_square_into_patch(
modified_patch = drawing_function(
patch_to_modify, intensity_value, background_pixel_value
)
canvas_image[sq_st_x:sq_en_x, sq_st_y:sq_en_y] = modified_patch

else:
pass

return canvas_image, G


Expand Down Expand Up @@ -300,6 +265,9 @@ def montage_from_image(
def save_image_and_graph_combo(
G: nx.Graph, image: np.ndarray, folder_path: str, file_name: str
) -> None:
# Create the path:
Path(folder_path).mkdir(parents=True, exist_ok=True)

# Save the image:
SAVE_IMAGE = Path(folder_path) / file_name
with mrcfile.new(SAVE_IMAGE, overwrite=True) as mrc:
Expand Down
2 changes: 1 addition & 1 deletion notebooks/read_grace.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"# dataset = read_graph(Path(\"/Users/arl/Desktop/annotations.grace\"))\n",
"\n",
"# path = \"/Users/kulicna/Desktop/dataset/data_fake/train/corner/MRC_File_001.grace\"\n",
"path = \"/Users/kulicna/Desktop/dataset/data_circles/MRC_Synthetic_File_000.grace\"\n",
"path = \"/Users/kulicna/Desktop/dataset/data_squares_circles/MRC_Synthetic_File_000.grace\"\n",
"dataset = read_graph(Path(path))"
]
},
Expand Down

0 comments on commit 1f9a828

Please sign in to comment.