class ImCanvas(HBox, HasTraits): image_path = Unicode() _image_scale = Float() def __init__(self, width=150, height=150): self._canvas = Canvas(width=width, height=height) super().__init__([self._canvas]) @observe('image_path') def _draw_image(self, change): self._image_scale = draw_img(self._canvas, self.image_path, clear=True) # Add value as a read-only property @property def image_scale(self): return self._image_scale def _clear_image(self): self._canvas.clear() # needed to support voila # https://ipycanvas.readthedocs.io/en/latest/advanced.html#ipycanvas-in-voila def observe_client_ready(self, cb=None): self._canvas.on_client_ready(cb)
def __init__(self, img): f = open('app/config.json') cfg = json.load(f) self.img = img self.width = 1080 self.height = 770 self.canvas = Canvas( width=self.width, height=self.height, ) self.output = Output( layout=Layout( #border='1px solid cyan', width='1170px', height='770px', min_height='90vh', overflow='hidden hidden'), ) with self.output: display(self.canvas) def put_image(): resized = cv2.resize(img, (self.width, self.height), interpolation=cv2.INTER_AREA) self.canvas.put_image_data(resized, 0, 0) self.canvas.on_client_ready(put_image)
def load_sprites(self): ' load the sprite sheet and when loaded callback to split it into individual sprites ' sprites = Image.from_file('images/BabyRobot64_Sprites.png') self.sprite_canvas = Canvas(width=132, height=328, sync_image_data=True) self.sprite_canvas.draw_image(sprites, 0, 0) self.sprite_canvas.observe(self.get_array, 'image_data')
def __init__(self, stage, cell_size=10, live_color='white', dead_color='black', background_color='gray', border_width=1.0): self.stage = stage self.cell_size = cell_size self.live_color = live_color self.dead_color = dead_color self.background_color = background_color self.border_width = border_width self.canvas = Canvas(width=self.stage.shape[0] * self.cell_size, height=self.stage.shape[1] * self.cell_size) display(self.canvas)
def all_rooms(self,canvas=None): if canvas == None: canvas = Canvas(width=self.max_x, height=self.max_y) k=0 for i in range(0,self.n_grid): for j in range(0,self.n_grid): if k < self.number_of_rooms: canvas2 = self.Single_Room(self.Rooms[k]) canvas.draw_image(canvas2, self.x[i], self.y[j]) k += 1 return canvas
def __init__(self, image, scale=1, interpolation=transform.interpolation.nearest): self.__scale = scale self.__interpolation = interpolation self.__image = self.transform(image) self.__canvas = Canvas(width=self.__image.shape[1], height=self.__image.shape[0], scale=1) self.__canvas.put_image_data(self.__image, 0, 0)
def __init__(self, globals_dict): self.status_text = display(Code(""), display_id=True) self._globals_dict = globals_dict self._methods = {} self.stop_button = Button(description="Stop") self.stop_button.on_click(self.on_stop_button_clicked) self.canvas = Canvas() self.output_text = "" self.width, self.height = DEFAULT_CANVAS_SIZE self.mouse_x = 0 self.mouse_y = 0 self.mouse_is_pressed = False
def helper_image(self: Core, *args): filename: str = args[0] x: int = int(args[1]) y: int = int(args[2]) w: int = int(args[3]) h: int = int(args[4]) key = (filename, abs(w), abs(h)) if key not in _loaded_images: _loaded_images[key] = Canvas(width=abs(w), height=abs(h)) _loaded_images[key].draw_image( Image.from_file(filename, width=abs(w), height=abs(h)), 0, 0, abs(w), abs(h)) self.canvas.translate(x, y) if w < 0: self.canvas.scale(-1, 1) if h < 0: self.canvas.scale(1, -1) self.canvas.draw_image(_loaded_images[key], 0, 0) if h < 0: self.canvas.scale(1, -1) if w < 0: self.canvas.scale(-1, 1) self.canvas.translate(-x, -y)
def __init__(self, parser: Parser, width: int = 500, height: int = 400, colorMap = defaultColorMap, filterFunction = None, backgroundColorRGB = "black", environmentRenderer = defaultRender2DEnvironment): """ Visualize a 2D PhysiCell simulation parser - a simulation output parser width: int = 500 - the width of the canvas to draw to height: int = 400 - the height of the canvas to draw to colorMap: (cells: numpyArray, variables: Map<string, indicies>, selectedCellID: ?string) => Array<Tuple<fillColor: string, strokeColor: string, cellIndicies: numpyArray>> = defaultColorMap - a function resulting in the cell colors filterFunction: (cells: numpyArray, variables: Map<string, indicies>) => numpyArray (boolean/indicies) = None - a function resulting in an array of the indicies of the cells to draw backgroundColorRGB: string = "black" - the color to paint the background environmentRenderer: (attribute: string, environment: Parser.Environment) => numpyArray<x, y, 1/2/3/4> = defaultRender2DEnvironment - given an environment and the attribute to render, create an image (numpy array) to render (will span the bounds of the attribute) """ super().__init__(parser, width, height, colorMap, filterFunction, (constants.MOVE_ACTION, constants.ZOOM_ACTION, constants.SELECT_ACTION)) frame = parser.getFrame(self._currentFrame) mesh = frame.environment.mesh self._zoom = max((mesh.boundsX[1] - mesh.boundsX[0]) / width, (mesh.boundsY[1] - mesh.boundsY[0]) / height) self._xOffset = mesh.boundsX[0] self._yOffset = mesh.boundsY[0] self._environmentRenderer = environmentRenderer self._buffer = Canvas(width=width, height=height) self._backgroundColor = backgroundColorRGB self.update()
class Image: def __init__(self, image, scale=1): self.scale = scale self.image = self.format(image) self.canvas = Canvas(width=self.image.shape[1], height=self.image.shape[0], scale=1) self.canvas.put_image_data(self.image, 0, 0) @utils.as_numpy def format(self, image): # convert the image to HWC [0-255] format if len(image.shape) == 2: image = image[np.newaxis,...] assert len(image.shape) == 3 if image.shape[0] in [3,1] and not image.shape[-1] in [3,1]: # in CHW format, otherwise we might be in HWC format... image = T.transpose(image, "CHW", "HWC") assert image.shape[-1] in [1,3] # TODO alpha blend if 4? if T.is_float(image): # convert to [0-255], ipycanvas has a weird image format image = image * 255. # assume image = image.astype(np.float32) if self.scale != 1: # match image scale shape = list(image.shape) shape[0] *= self.scale shape[1] *= self.scale image = skimage.transform.resize(image, shape, order=0, preserve_range=True) if image.shape[-1] == 1: # convert to 3 channel image image = np.repeat(image, 3, axis=-1) return image def update(self, image): image = self.format(image) self.canvas.put_image_data(image, 0, 0) def display(self): # TODO update box_layout = ipywidgets.Layout(display='flex',flex_flow='row',align_items='center',width='100%') display(ipywidgets.HBox([self.canvas], layout=box_layout))
def __init__(self, image: str=None, size=(600, 300), **kwargs): """Create a Turtle drawing canvas. Arguments: image: Load the image into the canvas. size: Set the size of the canvas. """ self._size = Turtle.DimPoint(size[0], size[1]) turtle = numpy.array(PIL.Image.open(pathlib.Path(__file__).parent / "turtle.png")) self._turtle = Canvas(width=turtle.shape[0], height=turtle.shape[1]) self._turtle.put_image_data(turtle) self._canvas = MultiCanvas(n_canvases=3, width=self._size.x, height=self._size.y, **kwargs) self._reset() if image is not None: self.background(image) self.clear()
def __init__(self, width=500, height=500, **kwargs): # Examples : # Drawing(border=None) # omit border # Drawing(background='white') # white rather than default # Drawing(800, 200) # 800 pixels wide, 200 pixels high for key in Drawing.defaults.keys(): if kwargs.get(key, None) == None: kwargs[key] = Drawing.defaults[key] kwargs['caching'] = kwargs.get('caching', Drawing.defaults['cache_default']) Canvas.__init__(self, width=width, height=height, **kwargs) for key in Drawing.defaults.keys(): self.__dict__[key] = kwargs[key] self.width = width self.height = height self.caching = kwargs['caching'] self.components = [] # (self.xll, self.yll) = (0.0, 1.0 * height) (self.xur, self.yur) = (1.0 * width, 0.0)
class ImCanvas(HBox): def __init__(self, width=150, height=150, has_border=False): self.has_border = has_border self._canvas = Canvas(width=width, height=height) super().__init__([self._canvas]) def _draw_image(self, image_path: str): self._image_scale = draw_img( self._canvas, image_path, clear=True, has_border=self.has_border ) def _clear_image(self): self._canvas.clear() # needed to support voila # https://ipycanvas.readthedocs.io/en/latest/advanced.html#ipycanvas-in-voila def observe_client_ready(self, cb=None): self._canvas.on_client_ready(cb)
def __init__(self, subj_num): self.subject_num = subj_num self.output_file = 'sdt-' + str(subj_num) + '.csv' # create two buttons with these names, randomize the position if npr.random() < 0.5: self.labels = [[ 'Present', widgets.ButtonStyle(button_color='darkseagreen') ], ['Absent', widgets.ButtonStyle(button_color='salmon')]] self.position = 'left' else: self.labels = [[ 'Absent', widgets.ButtonStyle(button_color='salmon') ], ['Present', widgets.ButtonStyle(button_color='darkseagreen')]] self.position = 'right' self.buttons = [ widgets.Button(description=desc[0], layout=widgets.Layout(width='auto', grid_area=f'button{idx}'), value=idx, style=desc[1]) # create button for idx, desc in enumerate(self.labels) ] # puts buttons into a list self.canvas = Canvas(width=425, height=425, layout=widgets.Layout(justify_self='center', grid_area='canvas')) # create output widget for displaying feedback/reward self.out = widgets.Output(layout=widgets.Layout( width='auto', object_position='center', grid_area='output')) # output widgets wrapped in VBoxes np.random.seed(24) self.create_trials(25, [10, 15, 25, 60]) self.done = False
def __init__(self, cell_size, colors, croppers, border_ratio=0.05): self.croppers = sorted(croppers, key=lambda x: x.rows, reverse=True) width = ((sum(cropper.cols for cropper in croppers) + len(croppers) - 1) * cell_size) height = max(cropper.rows for cropper in croppers) * cell_size self.canvas = Canvas(height=height, width=width) self.border_ratio = border_ratio self.colors = defaultdict(lambda: self.DEFAULT_COLOR) for key, value in colors.items(): self.colors[ord(key)] = value self.cell_size = cell_size
def Single_Zone(self, Zone, fig=None, offset=np.array([0, 0])): w = self.margin wall_width = self.wall_th * self.scale Zone_w = (Zone.x_delta + 2 * w) * self.scale Zone_h = (Zone.y_delta + 2 * w) * self.scale canvas_w = Zone_w + 2 * wall_width canvas_h = Zone_h + 2 * wall_width w = w * self.scale if fig == None: canvas = MultiCanvas(4, width=canvas_w, height=canvas_h) else: canvas = fig # background canvas[0].translate(offset[0], offset[1]) Mars_img = Image.from_file('Images/Mars_surface.jpg') canvas3 = Canvas(width=1000, height=1000) canvas3.draw_image(Mars_img, 0, 0) canvas3.scale(3 * self.scale / 50) canvas[0].draw_image(canvas3, 0, 0) canvas[0].translate(-offset[0], -offset[1]) # Draw Zone canvas[1].translate(offset[0], offset[1]) canvas[1].fill_rect(0, 0, canvas_w, height=canvas_h) canvas[1].clear_rect(wall_width, wall_width, Zone_w, height=Zone_h) # Name of thr Zone canvas[1].font = '16px serif' canvas[1].fill_text(Zone.name, Zone_w / 2, 4 * wall_width) canvas[1].translate(-offset[0], -offset[1]) # Draw object insised the Zone canvas[2].translate(offset[0], offset[1]) if Zone.type == 'Landing_zone': charging = self.problem_2_canvas(Zone.charger) trash_bin = self.problem_2_canvas(Zone.deposit) canvas[2].fill_style = 'green' canvas[2].fill_rect(charging[0] - w / 2, charging[1] - w / 2, w) canvas[2].fill_style = 'blue' canvas[2].fill_rect(trash_bin[0] - w / 2, trash_bin[1] - w / 2, w) else: canvas[2].fill_style = 'brown' p_r = 0.1 x, y, radius = [], [], [] for i in range(0, Zone.max_sample): sam_coord = self.problem_2_canvas(Zone.samples_loc[i, :]) x.append(sam_coord[0]) y.append(sam_coord[1]) radius.append(p_r * self.scale) canvas[2].fill_circles(x, y, radius) for i in Zone.connections['Location']: canvas[2].fill_style = 'red' c_coord = self.problem_2_canvas(Zone.Location_2_coordinate[i]) x = c_coord[0] y = c_coord[1] canvas[2].fill_rect(x - w / 2, y - w / 2, w) canvas[2].translate(-offset[0], -offset[1]) return canvas
def get_array(self, *args, **kwargs): ' callback to split the sprite sheet into individual sprites ' # check that the sprites haven't already been created if self.get_number_of_sprites() == 0: for row in range(5): for col in range(2): x = col * (self.robot_size + 1) y = row * (self.robot_size + 1) # copy the sprite from the sprite sheet image_data = self.sprite_canvas.get_image_data( x, y, self.robot_size) # put the sprite onto its own canvas canvas = Canvas(width=self.robot_size, height=self.robot_size) canvas.put_image_data(image_data, 0, 0) self.canvas_sprites.append(canvas) # add a sprite to the display self.canvas.clear() self.draw()
class GameOfLifePy: def __init__(self, stage, cell_size=10, live_color='white', dead_color='black', background_color='gray', border_width=1.0): self.stage = stage self.cell_size = cell_size self.live_color = live_color self.dead_color = dead_color self.background_color = background_color self.border_width = border_width self.canvas = Canvas(width=self.stage.shape[0] * self.cell_size, height=self.stage.shape[1] * self.cell_size) display(self.canvas) def draw_stage(self): with hold_canvas(self.canvas): # draw live cells cells_index = np.where(self.stage) cells_x = cells_index[0] * self.cell_size cells_y = cells_index[1] * self.cell_size size_array = np.full(cells_x.shape, self.cell_size) self.canvas.fill_style = self.live_color self.canvas.fill_rects(cells_x, cells_y, size_array) # draw "border" of live cells if self.border_width != 0.0: self.canvas.line_width = self.border_width self.canvas.stroke_style = self.background_color self.canvas.stroke_rects(cells_x, cells_y, size_array) # draw dead cells cells_index = np.where(self.stage == False) cells_x = cells_index[0] * self.cell_size cells_y = cells_index[1] * self.cell_size size_array = np.full(cells_x.shape, self.cell_size) self.canvas.fill_style = self.dead_color self.canvas.fill_rects(cells_x, cells_y, size_array) # draw "border" of dead cells if self.border_width != 0.0: self.canvas.line_width = self.border_width self.canvas.stroke_style = self.background_color self.canvas.stroke_rects(cells_x, cells_y, size_array) def next_stage(self): self.stage = get_next_stage(self.stage)
def __init__(self, globals_dict): self.status_text = display(Code(""), display_id=True) self._globals_dict = globals_dict self._methods = {} self.stop_button = Button(description="Stop") self.stop_button.on_click(self.on_stop_button_clicked) self._globals_dict["canvas"] = Canvas() self.kb_mon = Event(source=self.canvas, watched_events=['keydown', 'keyup'], wait=1000 // FRAME_RATE, prevent_default_actions=True) self.output_text = "" self.color_strings = {"default": "#888888"} match_255 = r"(?:(?:2(?:(?:5[0-5])|(?:[0-4][0-9])))|(?:[01]?[0-9]{1,2}))" match_alpha = r"(?:(?:1(?:\.0*)?)|(?:0(?:\.[0-9]*)?))" match_360 = r"(?:(?:3[0-5][0-9])|(?:[0-2]?[0-9]{1,2}))" match_100 = r"(?:100|[0-9]{1,2})" self.regexes = [ re.compile(r"#[0-9A-Fa-f]{6}"), re.compile(r"rgb\({},{},{}\)".format(match_255, match_255, match_255)), re.compile(r"rgba\({},{},{},{}\)".format(match_255, match_255, match_255, match_alpha)), re.compile(r"hsl\({},{}%,{}%\)".format(match_360, match_100, match_100)), re.compile(r"hsla\({},{}%,{}%,{}\)".format(match_360, match_100, match_100, match_alpha)) ] self.width, self.height = DEFAULT_CANVAS_SIZE self.mouse_x = 0 self.mouse_y = 0 self.mouse_is_pressed = False self.key = "" self._keys_held = {} # Settings for drawing text (https://ipycanvas.readthedocs.io/en/latest/drawing_text.html). self.font_settings = { 'size': 12.0, 'font': 'sans-serif', 'baseline': 'top', 'align': 'left' }
def robot(self, canvas, x, y, room): rbt_img = Image.from_file('Images/robot.jpg') x = x * self.scale y = y * self.scale x += self.offset[room][0] + self.wall_th * self.scale y += self.offset[room][1] + self.wall_th * self.scale canvas3 = Canvas(width=1000, height=1000) canvas3.draw_image(rbt_img, 0, 0) canvas3.scale(0.1*self.scale/50) canvas.clear_rect(x, y, self.wall_th) canvas.draw_image(canvas3, x, y) return canvas
def rover(self, canvas, coord, Zone): rvr_img = Image.from_file('Images/rover.jpg') canvas3 = Canvas(width=1000, height=1000) canvas3.draw_image(rvr_img, 0, 0) canvas3.scale(0.025 * self.scale / 50) coord_rvr = self.problem_2_canvas(coord) x = coord_rvr[0] - 0.25 * self.scale y = coord_rvr[1] - 0.25 * self.scale offset = Zone.coordinates * self.scale canvas[3].translate(offset[0], offset[1]) canvas[3].clear_rect(x, y, self.wall_th) canvas[3].draw_image(canvas3, x, y) canvas[3].translate(-offset[0], -offset[1]) return canvas
def displayGraph(graph, coef=1): """Affiche le graph en plt et en canvas""" x, y = calcXY(graph) canvas = Canvas(width=200, height=200) canvas = printCircles(x, y, canvas) canvas = printText(x, y, canvas) canvas = printBones(x, y, canvas) handGraph = [[1, 5, 9, 13, 17], [0, 2], [1, 3], [2, 4], [3], [0, 6], [5, 7], [6, 8], [7], [0, 10], [9, 11], [10, 12], [11], [0, 14], [13, 15], [14, 16], [15], [0, 18], [17, 19], [18, 20], [19]] plt.scatter(x, y) for index in range(len(x)): for link in handGraph[index]: if index <= link: plt.plot([x[index], x[link]], [y[index], y[link]]) plt.axis('equal') plt.show() return canvas
"""Helper functions for array sorting.""" from ipycanvas import Canvas, hold_canvas from random import shuffle import time CANVAS_WIDTH = 400 CANVAS_HEIGHT = 400 canvas = Canvas(width=CANVAS_WIDTH, height=CANVAS_HEIGHT) def color(col): canvas.fill_style = col def make_canvas(): global canvas canvas = Canvas(width=CANVAS_WIDTH, height=CANVAS_HEIGHT) display(canvas) def display_list(li, index=-2): pos = 0 min_elem = min(li) max_elem = max(li) + 1 elem_diff = max_elem - min_elem elem_height = CANVAS_HEIGHT / elem_diff width = CANVAS_WIDTH / len(li) with hold_canvas(canvas): canvas.clear() for elem in li: before_color = canvas.fill_style
def draw_splash(self, canvas, x, y, scale): if scale > 0.: splash_canvas = Canvas(width=self.cell_pixels, height=self.cell_pixels) sprite = Image.from_file('images/splash_2.png') with hold_canvas(splash_canvas): splash_canvas.save() pos_x = self.cell_pixels // 2 pos_y = self.cell_pixels // 2 # Choose a random rotation angle # (but first set the rotation center with `translate`) splash_canvas.translate(pos_x, pos_y) splash_canvas.rotate(uniform(0., pi)) # scale the image splash_canvas.scale(scale) # Restore the canvas center splash_canvas.translate(-pos_x, -pos_y) # Draw the sprite splash_canvas.draw_image(sprite, 0, 0) splash_canvas.restore() x_px = x * self.cell_pixels + self.padding y_px = y * self.cell_pixels + self.padding canvas.draw_image(splash_canvas, x_px, y_px, width=self.cell_pixels, height=self.cell_pixels)
class Turtle: DimPoint = namedtuple('DimPoint', ['x', 'y']) def __init__(self, image: str=None, size=(600, 300), **kwargs): """Create a Turtle drawing canvas. Arguments: image: Load the image into the canvas. size: Set the size of the canvas. """ self._size = Turtle.DimPoint(size[0], size[1]) turtle = numpy.array(PIL.Image.open(pathlib.Path(__file__).parent / "turtle.png")) self._turtle = Canvas(width=turtle.shape[0], height=turtle.shape[1]) self._turtle.put_image_data(turtle) self._canvas = MultiCanvas(n_canvases=3, width=self._size.x, height=self._size.y, **kwargs) self._reset() if image is not None: self.background(image) self.clear() def _reset(self): self._current = self._to_native(Turtle.DimPoint(0,0)) self._cur_heading = (3 * math.pi) / 2 # in Canvas Y is negative. self._pendown = True self._show = True def clear(self): """Clear the canvas and start over.""" with self._do_draw(): self._canvas[1].clear() self._reset() def draw(self, distance: float): """Move the pen by distance.""" with self._do_draw(): start = self._current self._current = Turtle.DimPoint(x = self._current.x + math.cos(self._cur_heading) * distance, y = self._current.y + math.sin(self._cur_heading) * distance) if self._pendown: self._canvas[1].begin_path() self._canvas[1].move_to(*start) self._canvas[1].line_to(*self._current) self._canvas[1].stroke() def turn(self, degrees: float): """Turn the pen by degrees.""" with self._do_draw(): self._cur_heading = (self._cur_heading - math.radians(degrees)) % (math.pi * 2) def goto(self, *place: Union[Tuple[int,int], Sequence[int], DimPoint]): """Goto a point in the coordinate space.""" if len(place) == 0: raise ValueError("Goto where?") elif isinstance(place[0], Turtle.DimPoint): p = place[0] elif isinstance(place[0], tuple): p = Turtle.DimPoint._make(*place) else: p = Turtle.DimPoint._make(place) with self._do_draw(): start = self._current self._current = self._to_native(p) if self._pendown: self._canvas[1].begin_path() self._canvas[1].move_to(*start) self._canvas[1].line_to(*self._current) self._canvas[1].stroke() def heading(self, heading: float): """Set the pen to face heading in degrees.""" with self._do_draw(): self._cur_heading = -math.radians(heading) def up(self): """Pick the pen up. Movements won't make lines.""" self._pendown = False def down(self): """Put the pen down. Movements will make lines.""" self._pendown = True def color(self, color: str): """Set the pen color using HTML color notation.""" self._canvas[1].stroke_style = color self._canvas[1].fill_style = color def width(self, width: int): """Set the line thickness.""" self._canvas[1].line_width = width def show(self): """Show the turtle in the scene.""" with self._do_draw(): self._show = True def hide(self): """Hide the turtle in the scene.""" with self._do_draw(): self._show = False def background(self, filename: str): """Set the background image""" self._reset() self._image = numpy.array(PIL.Image.open(filename)) self.size = (self._image.shape[1], self._image.shape[0]) self._canvas[0].put_image_data(self._image) def find_faces(self) -> List[Dict[str, Union[Tuple[int, int], Sequence[Tuple[int, int]]]]]: """ Find the faces in the background image. Returns list of dictionaries, one for each face that's found. Face dictionaries have landmark names as keys and points as values. The face dictionary has two types of values. Single-point values and path values. The single point values are: "top_right", "top_left", "bottom_right", "bottom_left" The points in these keys are the box where the face was found. The other values are paths that form the contour of a facial feature. They are: "bottom_lip", "top_lip", "left_eye", "right_eye", "left_eyebrow", "right_eyebrow", "nose_tip", "nose_bridge", "chin" Returns: A list of face dictionaries. """ faces = face_recognition.face_locations(self._image, model='hog') features = face_recognition.face_landmarks(self._image, face_locations=faces) rval = [] for i in range(len(faces)): face = {} face.update({ 'top_right': self._to_turtle(Turtle.DimPoint(x=faces[i][1], y=faces[i][0])), 'top_left': self._to_turtle(Turtle.DimPoint(x=faces[i][3], y=faces[i][0])), 'bottom_left': self._to_turtle(Turtle.DimPoint(x=faces[i][3], y=faces[i][2])), 'bottom_right': self._to_turtle(Turtle.DimPoint(x=faces[i][1], y=faces[i][2])), }) for feature in features[i]: face[feature] = list(map(self._to_turtle, features[i][feature])) rval.append(face) return rval def polygon(self, points: Sequence[Tuple[int, int]]): """Draw a filled polygon. Arguments: points: A list of 2D tuples of (x,y) """ with self._do_draw(): self._canvas[1].begin_path() self._canvas[1].move_to(*self._to_native(points[0])) for point in points[1:]: self._canvas[1].line_to(*self._to_native(point)) self._canvas[1].fill() def write(self, text: str, font: str="24px sans-serif", text_align: str="center", line_color: str=None, fill_color: str=None): """Write text. Arguments: text: The text to write font: The HTML font specification text_align: The alignment of the text relative to the turtle line_color: The color of the outline of the text (defaults to the pen color) fill_color: The color of the fill of the text (defaults to the pen color) """ with self._do_draw(): old_stroke = self._canvas[1].stroke_style old_fill = self._canvas[1].fill_style if line_color is not None: self._canvas[1].stroke_style = line_color if fill_color is not None: self._canvas[1].fill_style = fill_color self._canvas[1].translate(self._current.x, self._current.y) self._canvas[1].rotate(self._cur_heading + math.pi/2) self._canvas[1].font = font self._canvas[1].text_align = text_align self._canvas[1].fill_text(text, 0, 0) self._canvas[1].stroke_text(text, 0, 0) self._canvas[1].reset_transform() self._canvas[1].stroke_style = old_stroke self._canvas[1].fill_style = old_fill @contextlib.contextmanager def _do_draw(self): """Context manager that combines all drawing operations and re-renders the turtle.""" with hold_canvas(self._canvas): yield self._canvas[2].clear() if self._show: self._canvas[2].save() self._canvas[2].translate(self._current.x, self._current.y) self._canvas[2].rotate(self._cur_heading + math.pi / 2) self._canvas[2].draw_image(self._turtle, x=-15, y=-15, width=30, height=30) self._canvas[2].restore() def _to_native(self, point: Tuple[int, int]) -> DimPoint: """Convert Turtle coordinates to native ones.""" return Turtle.DimPoint(x=self._size.x//2 + point[0], y=self._size.y//2 - point[1]) def _to_turtle(self, point: DimPoint) -> Tuple[int, int]: """Convert Turtle coordinates to native ones.""" return (point[0] - self._size.x//2, self._size.y//2 - point[1]) def _ipython_display_(self): display(self._canvas) @property def size(self) -> Tuple[int,int]: """Get the size of the canvas' color buffer (not layout size).""" return (self._size.x, self._size.y) @size.setter def size(self, newsize: Tuple[int,int]): """Resize the canvas element and adjust they layout size.""" self._size = Turtle.DimPoint(x=newsize[0], y=newsize[1]) with self._do_draw(): self._canvas.width = self._size.x self._canvas.height = self._size.y if self._size.x >= 800: self._canvas.layout.width = "90%" self._canvas.layout.max_width = f"{self._size.x}px" self._canvas.layout.min_width = "800px" else: self._canvas.layout.width = "auto" self._canvas.layout.max_width = "auto" self._canvas.layout.min_width = "auto"
def __init__(self, parser: Parser, width: int, height: int, colorMap, filterFunction, availableActions): """ Setup the interactor variables, should be called first in a sub class. parser - a simulation output parser width - the width of the canvas to draw to height - the height of the canvas to draw to colorMap - a function resulting in the cell colors (distinct results based on subclass, see subclass documentation for necessary return values) filterFunction - a function resulting in an array of the indicies of the cells to draw availableActions - a list of all the actions that can be performed on the canvas """ self._currentFrame = parser.getFrameRange()[0] self._canvas = Canvas(width=width, height=height) self._parser = parser self._colorMap = colorMap self._height = height self._width = width self._filterFunction = filterFunction self._cellFigure = None self._generalGraph = GeneralPlot(parser) frame = parser.getFrame(self._currentFrame) mesh = frame.environment.mesh self._availableEnvironments = [*frame.environment.current.attributes] self._canvas.on_mouse_down(self._onMouseDown) self._canvas.on_mouse_move(self._onMouseMove) self._canvas.on_mouse_up(self._onMouseUp) self._canvas.on_mouse_out(self._onMouseOut) self.action = availableActions[0] self._buttons = widgets.RadioButtons( options=availableActions, value=self.action, description='Mouse Action:', disabled=False, ) self._buttons.observe(self.onToolChange, names='value') self._visible = (constants.VISIBLE_CELL, ) self._environmentButtons = widgets.SelectMultiple( options=[constants.VISIBLE_CELL, *self._availableEnvironments], description='Visible:', disabled=False, value=[constants.VISIBLE_CELL], ) self._environmentButtons.observe(self.onVisibilityChange, names='value') self._availableAttributes = [*frame.cells.variables.keys()] self._selectedAttribute = self._availableAttributes[0] self._previousSelectedAttribute = None self._previousSelectedAttributeCell = None self._attributes = widgets.RadioButtons( options=self._availableAttributes, value=self._selectedAttribute, description='Attribute Graph:\n', disabled=False, ) self._attributes.observe(self.onAttriChange, names='value') self._frameSelector = widgets.IntSlider(value=self._currentFrame, min=parser.getFrameRange()[0], max=parser.getFrameRange()[1] - 1, step=1, description='Frame:', disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='d') self._frameSelector.observe(self.onFrameChange, names='value') self._clicking = False self._dragStartX = 0 self._dragStartY = 0 self._actionOriginX = 0 self._actionOriginY = 0 self._selectedCell = None
class Interactor: """ Base interactor class. Is an abstract class. Handles shared functionality such as canvases and graphs. """ def __init__(self, parser: Parser, width: int, height: int, colorMap, filterFunction, availableActions): """ Setup the interactor variables, should be called first in a sub class. parser - a simulation output parser width - the width of the canvas to draw to height - the height of the canvas to draw to colorMap - a function resulting in the cell colors (distinct results based on subclass, see subclass documentation for necessary return values) filterFunction - a function resulting in an array of the indicies of the cells to draw availableActions - a list of all the actions that can be performed on the canvas """ self._currentFrame = parser.getFrameRange()[0] self._canvas = Canvas(width=width, height=height) self._parser = parser self._colorMap = colorMap self._height = height self._width = width self._filterFunction = filterFunction self._cellFigure = None self._generalGraph = GeneralPlot(parser) frame = parser.getFrame(self._currentFrame) mesh = frame.environment.mesh self._availableEnvironments = [*frame.environment.current.attributes] self._canvas.on_mouse_down(self._onMouseDown) self._canvas.on_mouse_move(self._onMouseMove) self._canvas.on_mouse_up(self._onMouseUp) self._canvas.on_mouse_out(self._onMouseOut) self.action = availableActions[0] self._buttons = widgets.RadioButtons( options=availableActions, value=self.action, description='Mouse Action:', disabled=False, ) self._buttons.observe(self.onToolChange, names='value') self._visible = (constants.VISIBLE_CELL, ) self._environmentButtons = widgets.SelectMultiple( options=[constants.VISIBLE_CELL, *self._availableEnvironments], description='Visible:', disabled=False, value=[constants.VISIBLE_CELL], ) self._environmentButtons.observe(self.onVisibilityChange, names='value') self._availableAttributes = [*frame.cells.variables.keys()] self._selectedAttribute = self._availableAttributes[0] self._previousSelectedAttribute = None self._previousSelectedAttributeCell = None self._attributes = widgets.RadioButtons( options=self._availableAttributes, value=self._selectedAttribute, description='Attribute Graph:\n', disabled=False, ) self._attributes.observe(self.onAttriChange, names='value') self._frameSelector = widgets.IntSlider(value=self._currentFrame, min=parser.getFrameRange()[0], max=parser.getFrameRange()[1] - 1, step=1, description='Frame:', disabled=False, continuous_update=False, orientation='horizontal', readout=True, readout_format='d') self._frameSelector.observe(self.onFrameChange, names='value') self._clicking = False self._dragStartX = 0 self._dragStartY = 0 self._actionOriginX = 0 self._actionOriginY = 0 self._selectedCell = None def setColorMap(self, colorMap): """ Set the cell coloring function. colorMap: the cell coloring function """ self._colorMap = colorMap self.update() def setFilterFunction(self, filterFunction): """ Set the cell filtering function filterFunction: the filtering function """ self._filterFunction = filterFunction self.update() def onToolChange(self, action): """ Handle a user action which changes the canvas tool action: an ipyWidget radio button selection action """ self.action = action.new @output.capture() def onVisibilityChange(self, action): """ Handle a user action which changes the elements which are visibile on the canvas action: an ipyWidget multi selection action """ self._visible = action.new self.update() @output.capture() def onAttriChange(self, action): """ Handle a user action which changes the attribute to display for the selected cell action: an ipyWidget radio button selection action """ self._selectedAttribute = action.new self._updateCellPlot() @output.capture() def _updateCellPlot(self): """ Update the plot which shows how the currently selected attribute changes over time for the selected cell """ if (self._previousSelectedAttribute == self._selectedAttribute and self._previousSelectedAttributeCell == self._selectedCell) or self._selectedCell is None: return self._previousSelectedAttribute = self._selectedAttribute self._previousSelectedAttributeCell = self._selectedCell data = [] timestamps = [] time = 0 variables = self.getCellVariables() for frameNumber in range(*self._parser.getFrameRange()): cell = self.getSelectedCell(frameNumber) if cell.shape[0] == 0: continue data.append(cell[variables[self._selectedAttribute]]) timestamps.append(time) time += 1 if self._cellFigure is not None: plt.figure(self._cellFigure.get_label()) self._cellAx.clear() ln, = self._cellAx.plot(timestamps, data) self._cellAx.set_xlabel('time') self._cellAx.set_ylabel(self._selectedAttribute) self._cellAx.set_title(self._selectedAttribute + " for cell " + str(int(self._selectedCell))) ln.set_color('orange') def onFrameChange(self, action): """ Handle a user action which changes the frame to view action: an ipyWidget slider action """ self._currentFrame = action.new self.update() def getCellVariables(self, frame: int = None): """ Get the cell varaibles for the frame frame: int - the frame number to get the variables from """ if frame is None: frame = self._currentFrame return self._parser.getFrame(frame).cells.variables def getCell(self, cellId: int, frame: int = None): """ Get the cell from the frame (used current frame if not specified) cellId: int - the id of the cell to get frame: int = currentFrame - the frame number to get the cell from """ if frame is None: frame = self._currentFrame cells = self.getCells(frame) variables = self.getCellVariables() cellColumn = cells[variables['ID']] == cellId return cells[:, cellColumn].reshape(-1) def getCells(self, frame: int = None): """ Get the cells from the frame (uses the current frame if not specified) frame: int = currentFrame - the frame number to get the cells from """ if frame is None: frame = self._currentFrame return self._parser.getFrame(frame).cells.data def getCellsToRender(self, frame: int = None): """ Get the cells to render from the given frame (uses the current frame if not specified). Applies the current cell filtering function on the result. frame: int = currentFrame - the frame number to get the cells from """ cells = self.getCells(frame) if self._filterFunction: cellVariables = self.getCellVariables(frame) cells = cells[:, self._filterFunction(cells, cellVariables)] return cells def getSelectedCell(self, frame: int = None): """ Get the cell data for the cell which is currently selected on the specified frame (uses the current frame if not specified). Will be None if no cell is selected. frame: int = currentFrame - the frame number to get the cells from """ if self._selectedCell is None: return None return self.getCell(self._selectedCell, frame) @output.capture() def _onMouseDown(self, x: int, y: int): """ Handle user mouse down action from ipyCanvas canvas x: int - the x position the mouse event occured based on the top left corner of the canvas y: int - the y position the mouse event occured based on the top left corner of the canvas """ self._dragStartX = x self._dragStartY = y self._actionOriginX = x self._actionOriginY = y self.onMouseDown(x, y) if self.action == constants.SELECT_ACTION: self.selectCell(x, y) else: self._clicking = True def selectCell(self, x: int, y: int): """ Select the cell at the given x and y coordinates. Abstract function, should be implemented by subclass. x: int - the x position the mouse event occured based on the top left corner of the canvas y: int - the y position the mouse event occured based on the top left corner of the canvas """ pass def _onMouseUp(self, x: int, y: int): """ Handle user mouse up action from ipyCanvas canvas x: int - the x position the mouse event occured based on the top left corner of the canvas y: int - the y position the mouse event occured based on the top left corner of the canvas """ self._clicking = False self.onMouseUp(x, y) def _onMouseOut(self, x: int, y: int): """ Handle user mouse out (mouse moves off the canvas) action from ipyCanvas canvas x: int - the x position the mouse event occured based on the top left corner of the canvas y: int - the y position the mouse event occured based on the top left corner of the canvas """ self._clicking = False self.onMouseOut(x, y) @output.capture() def _onMouseMove(self, x: int, y: int): """ Handle user mouse move action from ipyCanvas canvas x: int - the x position the mouse event occured based on the top left corner of the canvas. The current X position of the mouse. y: int - the y position the mouse event occured based on the top left corner of the canvas. The current y position of the mouse. """ self.onMouseMove(x, y) def onMouseUp(self, x: int, y: int): """ Handle a mouse up event at the given x and y coordinates. Abstract function, can be implemented by subclass. x: int - the x position the mouse event occured based on the top left corner of the canvas y: int - the y position the mouse event occured based on the top left corner of the canvas """ pass def onMouseOut(self, x: int, y: int): """ Handle a mouse out event at the given x and y coordinates. Abstract function, can be implemented by subclass. x: int - the x position the mouse event occured based on the top left corner of the canvas y: int - the y position the mouse event occured based on the top left corner of the canvas """ pass def onMouseMove(self, x: int, y: int): """ Handle a mouse move event at the given x and y coordinates. Abstract function, can be implemented by subclass. x: int - the x position the mouse event occured based on the top left corner of the canvas y: int - the y position the mouse event occured based on the top left corner of the canvas """ pass def onMouseDown(self, x: int, y: int): """ Handle a mouse down event at the given x and y coordinates. Abstract function, can be implemented by subclass. x: int - the x position the mouse event occured based on the top left corner of the canvas y: int - the y position the mouse event occured based on the top left corner of the canvas """ pass def update(self): """ Update UI, should be called after subclass updates. Puts shared data onto the canas. """ canvas = self._canvas selectedCell = self.getSelectedCell() if selectedCell is not None and selectedCell.shape[0] != 0: cellVaraibles = self.getCellVariables() canvas.fill_style = '#A0A0A0' canvas.font = '10px serif' identity = selectedCell[cellVaraibles["ID"]] volume = selectedCell[cellVaraibles["total_volume"]] phase = selectedCell[cellVaraibles["current_phase"]] canvas.fill_text( f"(ID: {identity}, Volume: {volume}, Phase: {phase})", 10, self._height - 10) self._updateCellPlot() def radiusOfCells(self, cells, variables): """ Determines the radius of the cells based on the cell (3D) volume. Results in a numpy array. cells - the cells to get the radius of variables - the variables of the cells """ return (cells[variables['total_volume']] * (3 / (4 * math.pi)))**(1 / 3) def show(self): """ Displays the widgets to the screen """ display(self._canvas, self._frameSelector, self._buttons, self._environmentButtons, self._attributes, output) if self._cellFigure is None: global figureNumber fig, ax = plt.subplots() self._cellAx = ax self._cellFigure = fig figureNumber += 1 plt.figure() self._generalGraph.plotPop()
def make_canvas(): global canvas canvas = Canvas(width=CANVAS_WIDTH, height=CANVAS_HEIGHT) display(canvas)
from ipycanvas import Canvas import turtle canvas = Canvas(size=(200, 200)) t = turtle.Turtle(canvas) canvas
class SimpleImage: def __init__(self, image, scale=1, interpolation=transform.interpolation.nearest): self.__scale = scale self.__interpolation = interpolation self.__image = self.transform(image) self.__canvas = Canvas(width=self.__image.shape[1], height=self.__image.shape[0], scale=1) self.__canvas.put_image_data(self.__image, 0, 0) @property def fig(self): return self.__canvas def transform(self, image): if transform.isCHW(image) and not transform.isHWC(image): image = transform.HWC( image) #transform to HWC format for display... elif not transform.isHWC(image): raise ValueError("Argument: \"image\" must be in HWC format") if transform.is_integer(image): image = transform.to_float(image) else: image = image.astype(np.float32) #must be float32... if image.shape[-1] != 3: image = transform.colour( image, components=(1, 1, 1)) #requires HWC float format... if self.__scale != 1: image = transform.scale(image, self.__scale, interpolation=self.__interpolation) return transform.to_integer(image) #finally transform to int def display(self): box_layout = widgets.Layout(display='flex', flex_flow='row', align_items='center', width='100%') display(HBox([self.__canvas], layout=box_layout)) def update(self, image): self.set_image(image) def set_image(self, image): #TODO if this is live there might be problems... give the option of preprocessing via transform image = self.transform(image) assert image.shape == self.__image.shape #shapes must be equal after scaling self.__image = image self.__canvas.put_image_data(image) @property def widget(self): return self.__canvas def scale(self): raise NotImplementedError("TODO scale the image?")