<jupyter_start><jupyter_text>iCAT world--- OverviewNotebook to create stacks of tile specifications in "real-world" or "physical" coordinate space (aka microns). This is to facilitate `5_iCAT-correlate.ipynb` as there is otherwise no way of knowing _a priori_ which high-mag EM tiles overlap with each low-mag EM tile.  Packages<jupyter_code>from pathlib import Path
from tqdm.notebook import tqdm

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt<jupyter_output><empty_output><jupyter_text>Settings<jupyter_code># pandas display settings
pd.set_option('display.max_rows', 20)
pd.set_option('display.width', None)
pd.set_option('display.max_colwidth', 15)

# Indirectly enable autocomplete
%config Completer.use_jedi = False<jupyter_output><empty_output><jupyter_text>Set up environment---<jupyter_code>import renderapi
from icatapi.render_pandas import create_stacks_DataFrame
# `render` project parameters
# ---------------------------
owner = 'rlane'
project = 'pancreas'

# Create a renderapi.connect.Render object
# ----------------------------------------
render_connect_params = {
    'host': 'sonic.tnw.tudelft.nl',
    'port': 8080,
    'owner': owner,
    'project': project,
    'client_scripts': '/home/catmaid/render/render-ws-java-client/src/main/scripts',
    'memGB': '2G'
}
render = renderapi.connect(**render_connect_params)
render.make_kwargs()
# Infer stack and section info
# ----------------------------
stacks = renderapi.render.get_stacks_by_owner_project(render=render)
stacks_EM = [stack for stack in stacks if 'EM' in stack]
stacks_FM = [stack for stack in stacks if 'EM' not in stack]

# Output
# ------
out = f"""\
all stacks.......... {stacks}
EM stacks........... {stacks_EM}
FM stacks........... {stacks_FM}
...
"""
print(out)

# Create stacks DataFrame
# ------------------------
stacks = ['EM_lomag', 'EM_himag']
df_project = create_stacks_DataFrame(stacks=stacks,
                                     render=render)
df_project.groupby('stack')\
          .apply(lambda x: x.sample(3))<jupyter_output>all stacks.......... ['EM_lomag_overlaid', 'AF594_overlaid', 'Hoechst_overlaid', 'EM_himag_stitched', 'EM_himag_montaged', 'Hoechst', 'EM_lomag', 'EM_himag', 'AF594']
EM stacks........... ['EM_lomag_overlaid', 'EM_himag_stitched', 'EM_himag_montaged', 'EM_lomag', 'EM_himag']
FM stacks........... ['AF594_overlaid', 'Hoechst_overlaid', 'Hoechst', 'AF594']
...<jupyter_text>Create world stacks---<jupyter_code>from matplotlib.transforms import Affine2D as AffineMPL
from renderapi.transform import AffineModel as AffineRender

from icatapi.overlay import get_transform_metadata
from icatapi.render_pandas import create_stack_from_DataFrame
channel_map = {
    'EM_lomag': 'Secondary electrons',
    'EM_himag': 'Secondary electrons'
}

# Loop through stacks
for stack, df_stack in tqdm(df_project.groupby('stack')):

    # Loop through tiles
    for i, tile in df_stack.iterrows():

        # Get transform metadata
        fp = Path(tile['imageUrl'].split('.nl')[1])
        tform_md = get_transform_metadata(fp)
        channel_name = channel_map[fp.parents[1].name]
        pixelsize, rotation, shear, translation = tform_md[channel_name]

        # Convert from metres to microns
        pixelsize = [1e6*ps for ps in pixelsize]      # m --> um
        translation = [1e6*tr for tr in translation]  # m --> um

        # Create transform
        w = tile['width']
        h = tile['height']
        T = AffineMPL().translate(-w/2, -h/2)\
                       .scale(*pixelsize)\
                       .rotate(rotation)\
                       .skew(shear, 0)\
                       .translate( translation[0],
                                  -translation[1])
        A = AffineRender()
        A.M = T.get_matrix()

        # Replace transform in DataFrame
        df_stack.at[i, 'tforms'] = [A]

    # Create world stack
    stack_world = f"{stack}_world"
    create_stack_from_DataFrame(df=df_stack,
                                name=stack_world,
                                render=render)<jupyter_output><empty_output><jupyter_text>Inspect stacks---<jupyter_code>from icatapi.plotting import plot_tile_map, plot_stacks<jupyter_output><empty_output><jupyter_text>Project DataFrame<jupyter_code># Project DataFrame
stacks = renderapi.render.get_stacks_by_owner_project(render=render)
stacks_world = [stack for stack in stacks if 'world' in stack]
df_world = create_stacks_DataFrame(stacks=stacks_world,
                                   render=render)

df_world.groupby('stack')\
        .apply(lambda x: x.sample(3))<jupyter_output><empty_output><jupyter_text>Map out tiles in `render` space<jupyter_code># Set stacks to plot
stacks_2_plot = stacks_world

# Plot tile map
plot_tile_map(stacks_2_plot, render=render)<jupyter_output><empty_output><jupyter_text>Plot stacks<jupyter_code>stacks_2_plot = stacks_world

plot_stacks(stacks=stacks_2_plot,
            maxTileSpecsToRender=30,
            render=render)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.14251544747857287, 'fraction_numerical': 0.008371536774965119, 'mean_word_length': 3.153973509933775, 'pattern_counts': {'":': 0, '<': 32, '<?xml version=': 0, '>': 34, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '276141', 'license': 'CC-BY-4.0', 'n_tokens_mistral': 1694, 'n_tokens_neox': 1606, 'n_words': 351, 'path': 'notebooks/4_iCAT-world.ipynb', 'repo_name': 'hoogenboom-group/iCAT-workflow', 'size': '5017'}