def distribute_pixels(self, edges, length, width): corners = self.get_corners() reg_path = Path(corners) # Get region boundaries. bounds = reg_path.get_extents().get_points() [[x_min_bound, y_min_bound], [x_max_bound, y_max_bound]] = bounds # For cases when the boundary pixels are not integers: x_min_bound = floor(x_min_bound) y_min_bound = floor(y_min_bound) x_max_bound = ceil(x_max_bound) y_max_bound = ceil(y_max_bound) pixels_in_bins = [] for x in range(max(0, x_min_bound), min(x_max_bound+1, width)): for y in range(max(0, y_min_bound), min(y_max_bound+1, length)): if reg_path.contains_point((x, y)): x_nonrotated, y_nonrotated = rotate_point(self.x0, self.y0, x - self.x0, y - self.y0, -self.angle) dist_from_box_bottom = self.height/2. - \ (self.y0 - y_nonrotated) for i, edge in enumerate(edges[1:]): if edge > dist_from_box_bottom: pixels_in_bins.append((y, x, i)) break return pixels_in_bins
def init(): """Initialization""" global config, first_names, last_names, aggregate_url, open_hds_connection, odk_connection global area_polygon, area_extent, locations_per_social_group, individuals_per_social_group global pop_size_baseline, site, min_age_head_of_social_group, proportion_females, birth_rate, death_rate global min_age_marriage with open(os.path.join(conf_dir, 'config.json')) as config_file: config = json.load(config_file) with open(os.path.join(conf_dir, 'site.json')) as site_file: site = json.load(site_file) open_hds_connection = MySQLdb.connect(host=config['open_hds_server']['db_host'], user=config['open_hds_server']['db_user'], passwd=config['open_hds_server']['db_password'], db=config['open_hds_server']['db_name'], cursorclass=MySQLdb.cursors.DictCursor) open_hds_connection.autocommit(True) odk_connection = MySQLdb.connect(host=config['odk_server']['db_host'], user=config['odk_server']['db_user'], passwd=config['odk_server']['db_password'], db=config['odk_server']['db_name'], cursorclass=MySQLdb.cursors.DictCursor) odk_connection.autocommit(True) aggregate_url = config['odk_server']['aggregate_url'] with open(os.path.join(conf_dir, 'firstnames.csv')) as f: first_names = list(f.read().splitlines(False)) with open(os.path.join(conf_dir, 'lastnames.csv')) as f: last_names = list(f.read().splitlines(False)) area_outline_vertices = [] for point in site['general']['area_polygon']: area_outline_vertices.append(point) area_polygon = Path(area_outline_vertices) area_extent = area_polygon.get_extents().get_points() pop_size_baseline = site['general']['pop_size_baseline'] locations_per_social_group = site['socialgroup']['locations_per_social_group'] individuals_per_social_group = site['socialgroup']['individuals_per_social_group'] min_age_head_of_social_group = site['socialgroup']['min_age_head'] min_age_marriage = site['relationship']['min_age_marriage'] proportion_females = 1 / (1 + site['general']['sex_ratio']) birth_rate = site['general']['birth_rate'] death_rate = site['general']['death_rate'] if config['general']['clean_db_on_init']: clean_db() create_fws(site['fieldworker']) create_location_hierarchy(site['locationhierarchy'])
def plot(self, ax: Axes) -> Axes: """Plot the curve.""" xmin, xmax = ax.get_xlim() ymin, ymax = ax.get_ylim() if not self.x_data or not self.y_data or not _between_limits( self.x_data, self.y_data, xmin, xmax, ymin, ymax): self._print_err( '{} (label:{}) Not between limits ([{}, {}, {}, {}]) ' '-> x:{}, y:{}'.format(self._type_curve, self._label, xmin, xmax, ymin, ymax, self.x_data, self.y_data)) return ax if self._is_patch and self.y_data is not None: assert len(self.y_data) > 2 verts = list(zip(self.x_data, self.y_data)) codes = ([Path.MOVETO] + [Path.LINETO] * (len(self.y_data) - 2) + [Path.CLOSEPOLY]) path = Path(verts, codes) patch = patches.PathPatch(path, **self.style) ax.add_patch(patch) if self._label is not None: bbox_p = path.get_extents() text_x = .5 * (bbox_p.x0 + bbox_p.x1) text_y = .5 * (bbox_p.y0 + bbox_p.y1) style = { 'ha': 'center', 'va': 'center', "backgroundcolor": [1, 1, 1, .4] } if 'edgecolor' in self.style: style['color'] = mod_color(self.style['edgecolor'], -25) self._annotate_label(ax, self._label, text_x, text_y, 0, style) else: ax.plot(self.x_data, self.y_data, **self.style) if self._label is not None: self.add_label(ax) return ax
def plot(self, ax: Axes) -> Axes: """Plot the curve.""" xmin, xmax = ax.get_xlim() ymin, ymax = ax.get_ylim() if (self.x_data is None or self.y_data is None or not _between_limits( self.x_data, self.y_data, xmin, xmax, ymin, ymax)): logging.info( f"{self._type_curve} (label:{self._label}) Not between limits " f"([{xmin}, {xmax}, {ymin}, {ymax}]) " f"-> x:{self.x_data}, y:{self.y_data}") return ax if self._is_patch and self.y_data is not None: assert len(self.y_data) > 2 verts = list(zip(self.x_data, self.y_data)) codes = ([Path.MOVETO] + [Path.LINETO] * (len(self.y_data) - 2) + [Path.CLOSEPOLY]) path = Path(verts, codes) patch = patches.PathPatch(path, **self.style) ax.add_patch(patch) if self._label is not None: bbox_p = path.get_extents() text_x = 0.5 * (bbox_p.x0 + bbox_p.x1) text_y = 0.5 * (bbox_p.y0 + bbox_p.y1) style = { "ha": "center", "va": "center", "backgroundcolor": [1, 1, 1, 0.4], } if "edgecolor" in self.style: style["color"] = mod_color(self.style["edgecolor"], -25) self._annotate_label(ax, self._label, text_x, text_y, 0, style) else: ax.plot(self.x_data, self.y_data, **self.style) if self._label is not None: self.add_label(ax) return ax
def get_nodule_mask(img, rois): """ Given an image and its roi (list of contour boundary points), returns a 2D binary mask for the image :param img: 2D numpy array of CT image :param rois: 1D numpy array of list of boundary points defining ROI returns: 2D numpy array of image's binary contour """ x, y = np.mgrid[:img.shape[1], :img.shape[0]] # mesh grid to a list of points points = np.vstack((x.ravel(), y.ravel())).T # empty mask mask = np.zeros(img.shape[0] * img.shape[1]) try: # iteratively add roi regions to mask for roi in rois: # from roi to a matplotlib path path = Path(roi) xmin, ymin, xmax, ymax = np.asarray(path.get_extents(), dtype=int).ravel() # add points to mask included in the path mask = np.logical_or(mask, np.array(path.contains_points(points))) # except if image is w/o ROIs (empty mask) except TypeError: pass # reshape mask mask = np.array([float(m) for m in mask]) img_mask = mask.reshape(x.shape).T return img_mask
def __str__(self): if self.shape in ['rectangle', 'ellipse']: x, y, wid, hgt = self.geometry text = '{0}: ({1:.4G}, {2:.4G}), {3:.4G}, {4:.4G}' text = text.format(self.shape.capitalize(), x, y, wid, hgt) elif self.shape == 'lasso': if not self.geometry: return '' path = Path(self.geometry) extents = path.get_extents() x, y = extents.p0 text = 'Lasso: ({0:.4G}, {1:.4G}), {2:.4G}, {3:.4G}' text = text.format(x, y, extents.width, extents.height) elif self.shape == 'line' and not self.data is None: p1, p2 = self.geometry if p1[0] > p2[0]: p1, p2 = p2, p1 dx = p2[0] - p1[0] dy = p1[1] - p2[1] dist = np.hypot(dx, dy) angle = np.arctan2(dy, dx) * 180. / np.pi text = 'Line: {0:.4G}, {1} deg, ({2:.4G}, {3:.4G})' text = text.format(dist, int(angle), p1[0], p1[1]) elif self.shape == 'point': x, y = self.geometry if not self.data is None: text = 'Point: {0:.4G} @ ({1:.4G}, {2:.4G})' try: text = text.format(self.data[5, 5], x, y) except (ValueError, IndexError): pass else: text = 'Point: ({0:.4G}, {1:.4G})'.format(x, y) else: text = object.__str__(self) return text
def test_empty_closed_path(): path = Path(np.zeros((0, 2)), closed=True) assert path.vertices.shape == (0, 2) assert path.codes is None assert_array_equal(path.get_extents().extents, transforms.Bbox.null().extents)
def selectroi(img2): global img_formask global start global coordinates global stop global grayscale img_formask = img2 # img_formask = cv2.imread('Eyee.png',-1) if grayscale == 1: img_formask=cv2.cvtColor(img_formask,cv2.COLOR_BGR2GRAY) coordinates=[] cv2.namedWindow('image') cv2.setMouseCallback('image',draw_circle) while(1): cv2.imshow('image',img_formask) k = cv2.waitKey(20) & 0xFF if (k == 27) or (stop==1) : # print('i stopped sir') cv2.destroyAllWindows() break coordinates=np.asarray(coordinates) path = Path(coordinates) xmin, ymin, xmax, ymax = np.asarray(path.get_extents(), dtype=int).ravel() x, y = np.mgrid[:img.shape[1], :img.shape[0]] points = np.vstack((x.ravel(), y.ravel())).T mask = path.contains_points(points) path_points = points[np.where(mask)] img_mask = mask.reshape(x.shape).T img_mask1=img1 * img_mask[..., None] img_mask2=img_mask1 if grayscale==1: limit=1 else: limit=3 for k in range(0,limit): for i in range(0,img_mask2.shape[0]): for j in range(0,img_mask2.shape[1]): if img_mask1[i,j,k] != 0: img_mask2[i,j,k]=255 else: img_mask2[i,j,k]=0 return img_mask2
def test_extents_with_ignored_codes(ignored_code): # Check that STOP and CLOSEPOLY points are ignored when calculating extents # of a path with only straight lines path = Path([[0, 0], [1, 1], [2, 2]], [Path.MOVETO, Path.MOVETO, ignored_code]) assert np.all(path.get_extents().extents == (0., 0., 1., 1.))
plot_dims = np.r_[np.diff(ax.get_xbound()), np.diff(ax.get_ybound())] # create MNE clipping mask mne_path = TextPath((0, 0), 'MNE') dims = mne_path.vertices.max(0) - mne_path.vertices.min(0) vert = mne_path.vertices - dims / 2. mult = (plot_dims / dims).min() mult = [mult, -mult] # y axis is inverted (origin at top left) offset = plot_dims / 2. - center_fudge mne_clip = Path(offset + vert * mult, mne_path.codes) # apply clipping mask to field gradient and lines im.set_clip_path(mne_clip, transform=im.get_transform()) for coll in cs.collections: coll.set_clip_path(mne_clip, transform=im.get_transform()) # get final position of clipping mask mne_corners = mne_clip.get_extents().corners() # add tagline rcParams.update({'font.sans-serif': ['Cooper Hewitt'], 'font.weight': 'light'}) tag_path = TextPath((0, 0), 'MEG + EEG ANALYSIS & VISUALIZATION') dims = tag_path.vertices.max(0) - tag_path.vertices.min(0) vert = tag_path.vertices - dims / 2. mult = tagline_scale_fudge * (plot_dims / dims).min() mult = [mult, -mult] # y axis is inverted offset = mne_corners[-1] - np.array([mne_clip.get_extents().size[0] / 2., -dims[1]]) - tagline_offset_fudge tag_clip = Path(offset + vert * mult, tag_path.codes) tag_patch = PathPatch(tag_clip, facecolor='k', edgecolor='none', zorder=10) ax.add_patch(tag_patch) yl = ax.get_ylim() yy = np.max([tag_clip.vertices.max(0)[-1],
import pandas as pd import scipy import seaborn as sns import bruno_util.plotting as bplt figure_size = bplt.use_cell_style(mpl.rcParams) km_color = sns.color_palette('colorblind')[0] interior_color = sns.color_palette('colorblind')[1] interior_linestyle = '-.' # make cool legends where stair lines and straight lines are treated # differently stair_path = Path([[-1, -1], [-1 / 3, -1], [-1 / 3, 1], [1 / 3, 1], [1 / 3, -1], [1, -1], [1, 1], [5 / 3, 1]]) bbox = stair_path.get_extents() make_unit = Affine2D() \ .translate(-bbox.x0, -bbox.y0) \ .scale(1/bbox.width, 1/bbox.height) stair_path = make_unit.transform_path(stair_path) def _int_win_from_obs(obs, state): interior = obs.loc[(obs['state'] == state) & (obs['wait_type'] == 'interior'), ['wait_time', 'window_size']] return interior.wait_time.values, interior.window_size.values def _ext_from_obs(obs, state): exterior = obs.loc[(obs['state'] == state)
plot_dims = np.r_[np.diff(ax.get_xbound()), np.diff(ax.get_ybound())] # create MNE clipping mask mne_path = TextPath((0, 0), 'MNE') dims = mne_path.vertices.max(0) - mne_path.vertices.min(0) vert = mne_path.vertices - dims / 2. mult = (plot_dims / dims).min() mult = [mult, -mult] # y axis is inverted (origin at top left) offset = plot_dims / 2. - center_fudge mne_clip = Path(offset + vert * mult, mne_path.codes) # apply clipping mask to field gradient and lines im.set_clip_path(mne_clip, transform=im.get_transform()) for coll in cs.collections: coll.set_clip_path(mne_clip, transform=im.get_transform()) # get final position of clipping mask mne_corners = mne_clip.get_extents().corners() # add tagline rcParams.update({'font.sans-serif': ['Cooper Hewitt'], 'font.weight': 'light'}) tag_path = TextPath((0, 0), 'MEG + EEG ANALYSIS & VISUALIZATION') dims = tag_path.vertices.max(0) - tag_path.vertices.min(0) vert = tag_path.vertices - dims / 2. mult = tagline_scale_fudge * (plot_dims / dims).min() mult = [mult, -mult] # y axis is inverted offset = mne_corners[-1] - np.array( [mne_clip.get_extents().size[0] / 2., -dims[1]]) - tagline_offset_fudge tag_clip = Path(offset + vert * mult, tag_path.codes) tag_patch = PathPatch(tag_clip, facecolor='k', edgecolor='none', zorder=10) ax.add_patch(tag_patch) yl = ax.get_ylim() yy = np.max([tag_clip.vertices.max(0)[-1], tag_clip.vertices.min(0)[-1]])
response = pbclient.update_app(app) check_api_error(response) except: format_error("pbclient.update_app", response) if args.create_tasks: response = pbclient.find_app(short_name='RuralGeolocator') app = response[0] app_id = app.id #polygon around area to be tasked, as list of (lat, long) lists rusingaOutlineData = json.load(open('data/area.json')) rusingaOutlineVertices = [] for point in rusingaOutlineData: rusingaOutlineVertices.append(point) islandPolygon = Path(rusingaOutlineVertices) points = islandPolygon.get_extents().get_points() #The northern, southern, western, and eastern bounds of the area to work on. nb = points[1][0] wb = points[0][1] sb = points[0][0] eb = points[1][1] print (nb, wb, sb, eb) #Size of the tasks, into how many rows and columns should the area be divided. task_cols = 40 task_rows = 30 ns_step = (sb - nb) / task_cols we_step = (eb - wb) / task_rows task_counter = 0 for row in range(task_rows): wbr = wb + row * we_step ebr = wb + (row + 1) * we_step
(0.2, 1.), # P1 (1.0, 1.0), # P2 (1.5, 1.0), # P3 (1.7, 2.0) # P4 ] codes = [ Path.MOVETO, Path.CURVE3, Path.CURVE3, Path.CURVE3, Path.CURVE3, ] path = Path(verts, codes) print(path.get_extents()) fig = plt.figure() ax = fig.add_subplot(111) patch = patches.PathPatch(path, facecolor='none', lw=2) ax.add_patch(patch) xs, ys = zip(*verts) print(*verts) ax.plot(xs, ys, 'x--', lw=2, color='black', ms=10) ax.text(-0.05, -0.05, 'P0') ax.text(0.15, 1.05, 'P1') ax.text(1.05, 0.85, 'P2') ax.text(1.55, 1.05, 'P3') ax.text(1.75, 1.05, 'P4')
def sequence_logo(score_matrix, order="value", width=1.0, ax=None, sequence_type=Genome, font_properties=None, color_scheme=None, **kwargs): """Plots a sequence logo for visualizing motifs. Parameters ---------- score_matrix : np.ndarray An :math:`L \\times N` array (where :math:`L` is the length of the sequence, and :math:`N` is the size of the alphabet) containing the scores for each base occuring at each position. order : {'alpha', 'value'} The manner by which to sort the bases stacked at each position in the sequence logo plot. * 'alpha' - Bases go in the order they are found in the\ sequence alphabet. * 'value' - Bases go in the order of their value, with the\ largest at the bottom. width : float, optional Default is 1. The width of each character in the plotted logo. A value of 1 will mean that there is no gap between each the characters at each position. A value of 0 will not draw any characters. ax : matplotlib.pyplot.Axes or None, optional Default is `None`. The axes to plot on. If left as `None`, a new axis will be created. sequence_type : class, optional Default is `selene_sdk.sequences.Genome`. The type of sequence that the *in silico* mutagenesis results are associated with. This should generally be a subclass of `selene_sdk.sequences.Sequence`. font_properties : matplotlib.font_manager.FontProperties or None, optional Default is `None`. A `matplotlib.font_manager.FontProperties` object that specifies the properties of the font to use for plotting the motif. If `None`, no font will be used, and the text will be rendered by a path. This method of rendering paths is preferred, as it ensures all character heights correspond to the actual values, and that there are no extra gaps between the tops and bottoms of characters at each position in the sequence logo. If the user opts to use a value other than `None`, then no such guarantee can be made. color_scheme : list(str) or None, optional Default is `None`. A list containing the hex codes or names of colors to use, appearing in the order of the bases of the sequence type. If left as `None`, a default palette will be made with `seaborn.color_palette`, and will have as many colors as there are characters in the input sequence alphabet. Returns ------- matplotlib.pyplot.Axes The axes containing the sequence logo plot. Raises ------ ValueError If the number of columns in `score_matrix` does not match the number of characters in the alphabet of `sequence_type`. ValueError If the number of colors in `color_palette` does not match the number of characters in the alphabet of `sequence_type`. Examples -------- We have included an example of the output from a`sequence_logo` plot below: .. image:: ../../docs/source/_static/img/sequence_logo_example.png """ # Note that everything will break if we do not deepcopy. score_matrix = deepcopy(score_matrix) score_matrix = score_matrix.transpose() if font_properties is not None: warnings.warn( "Specifying a value for `font_properties` (other than `None`) " "will use the `matplotlib`-based character paths, and causes " "distortions in the plotted motif. We recommend leaving " "`font_properties=None`. See the documentation for details.", UserWarning) if color_scheme is None: color_scheme = sns.color_palette("Set1", n_colors=len(sequence_type.BASES_ARR)) color_scheme = color_scheme.as_hex() if len(color_scheme) < len(sequence_type.BASES_ARR): raise ValueError( "Color scheme is shorter than number of bases in sequence.") if score_matrix.shape[0] != len(sequence_type.BASES_ARR): raise ValueError( "Got score with {0} bases for sequence with {1} bases.".format( score_matrix.shape[0], len(sequence_type.BASES_ARR))) if ax is None: _, ax = plt.subplots(figsize=score_matrix.shape) # Determine offsets depending on sort order. positive_offsets = np.zeros_like(score_matrix) negative_offsets = np.zeros_like(score_matrix) bases = np.empty(score_matrix.shape, dtype=object) bases[:, :] = "?" # This ensures blanks are visually obvious. # Change ordering of things based on input arguments. if order == "alpha": for i in range(score_matrix.shape[0]): bases[i, :] = sequence_type.BASES_ARR[i] elif order == "value": if np.sum(score_matrix < 0) != 0: sorted_scores = np.zeros_like(score_matrix) for j in range(score_matrix.shape[1]): # Sort the negative values and put them at bottom. div = np.sum(score_matrix[:, j] < 0.) negative_idx = np.argwhere(score_matrix[:, j] < 0.).flatten() negative_sort_idx = np.argsort(score_matrix[negative_idx, j], axis=None) sorted_scores[:div, j] = score_matrix[ negative_idx[negative_sort_idx], j] bases[:div, j] = sequence_type.BASES_ARR[ negative_idx[negative_sort_idx]].flatten() # Sort the positive values and stack atop the negatives. positive_idx = np.argwhere(score_matrix[:, j] >= 0.).flatten() positive_sort_idx = np.argsort(score_matrix[positive_idx, j], axis=None) sorted_scores[div:, j] = score_matrix[ positive_idx[positive_sort_idx], j] bases[div:, j] = sequence_type.BASES_ARR[ positive_idx[positive_sort_idx]].flatten() score_matrix = sorted_scores else: for j in range(score_matrix.shape[1]): sort_idx = np.argsort(score_matrix[:, j], axis=None)[::-1] bases[:, j] = sequence_type.BASES_ARR[sort_idx] score_matrix[:, j] = score_matrix[sort_idx, j] # Create offsets for each bar. for i in range(score_matrix.shape[0] - 1): y_coords = score_matrix[i, :] if i > 0: negative_offsets[i + 1, :] = negative_offsets[i, :] positive_offsets[i + 1, :] = positive_offsets[i, :] neg_idx = np.argwhere(y_coords < 0.) pos_idx = np.argwhere(y_coords >= 0.) negative_offsets[i + 1, neg_idx] += y_coords[neg_idx] positive_offsets[i + 1, pos_idx] += y_coords[pos_idx] for i in range(score_matrix.shape[0]): x_coords = np.arange(score_matrix.shape[1]) + 0.5 y_coords = score_matrix[i, :] # Manage negatives and positives separately. offsets = np.zeros(score_matrix.shape[1]) negative_idx = np.argwhere(y_coords < 0.) positive_idx = np.argwhere(y_coords >= 0.) offsets[negative_idx] = negative_offsets[i, negative_idx] offsets[positive_idx] = positive_offsets[i, positive_idx] bars = ax.bar(x_coords, y_coords, color="black", width=width, bottom=offsets) for j, bar in enumerate(bars): base = bases[i, j] bar.set_color(color_scheme[sequence_type.BASE_TO_INDEX[base]]) bar.set_edgecolor(None) # Iterate over the barplot's bars and turn them into letters. new_patches = [] for i, bar in enumerate(ax.patches): base_idx = i // score_matrix.shape[1] seq_idx = i % score_matrix.shape[1] base = bases[base_idx, seq_idx] # We construct a text path that tracks the bars in the barplot. # Thus, the barplot takes care of scaling and translation, # and we just copy it. if font_properties is None: text = Path(_SVG_PATHS[base][0], _SVG_PATHS[base][1]) else: text = TextPath((0., 0.), base, fontproperties=font_properties) b_x, b_y, b_w, b_h = bar.get_extents().bounds t_x, t_y, t_w, t_h = text.get_extents().bounds scale = (b_w / t_w, b_h / t_h) translation = (b_x - t_x, b_y - t_y) text = PathPatch(text, facecolor=bar.get_facecolor(), lw=0.) bar.set_facecolor("none") text.set_path_effects([_TextPathRenderingEffect(bar)]) transform = transforms.Affine2D().translate(*translation).scale(*scale) text.set_transform(transform) new_patches.append(text) for patch in new_patches: ax.add_patch(patch) ax.set_xlim(0, score_matrix.shape[1]) ax.set_xticks(np.arange(score_matrix.shape[1]) + 0.5) ax.set_xticklabels(np.arange(score_matrix.shape[1])) return ax
def cleaned_textpath(text_path): """Prepare a matplotlib.textpath.TextPath for intersection checking There's a rather nasty little bug hidden in matplotlib's TextPath code which causes path intersections to fail. This works around it by cleaning up (and simplifying) the paths. It is not perfect, as you would see if you were to try displaying the resulting paths. The basic problem is that vertices associated with a CLOSEPOLY path code are supposed to be ignored. They are in the case of rendering the path (which is what made this bug so horrible to track down) but not when you are doing other operations, like path intersection or simplifying. Since TextPath (for whatever reason) associates gibberish vertices with CLOSEPOLY codes, path intersection checks will behave strangely. This code splits compound paths into separate paths, and moves the vertex for a CLOSEPOLY to the first vertex in the path. This eliminates holes in letters such as `e' or `O' but that's a price we have to pay. Args: text_path: A matplotlib.textpath.TextPath Returns: A list of cleaned up paths. """ paths = list() verts = list() codes = list() for v,c in text_path.iter_segments(curves=False, simplify=False): if c == Path.CLOSEPOLY: vert = verts[0] else: vert = v if c == Path.MOVETO and len(verts) > 0: # We've started a new path. newpath = Path(verts, codes) newbox = newpath.get_extents() if len(paths) == 0: # If there are no paths we definitely add this one.\ paths.append(newpath) else: lastbox = paths[-1].get_extents() if bbox_covers(newbox, lastbox): # If this path covers the last one, replace it. paths[-1] = newpath elif not bbox_covers(lastbox, newbox): # If the last path doesn't cover this one, throw it out. paths.append(newpath) verts = [vert] codes = [c] else: verts.append(vert) codes.append(c) # Finally, deal with the last path, which may not be explicitly closed. if len(verts) > 0: newpath = Path(verts, codes) newbox = newpath.get_extents() if len(paths) == 0: paths.append(newpath) else: lastbox = paths[-1].get_extents() if bbox_covers(newbox, lastbox): paths[-1] = newpath elif not bbox_covers(lastbox, newbox): paths.append(newpath) return paths
for (vertex, code) in path.iter_segments(simplify = True): vertices.append(vertex.tolist()) codes.append(code) # <codecell> cleanpath = Path(vertices, codes) len(cleanpath) # <codecell> codes[-1] = Path.CLOSEPOLY # <codecell> bbox = cleanpath.get_extents() print bbox # <codecell> bbox.bounds # <codecell> hemi_masked = path.contains_points( hemi_kp ) hemi_kp_masked = hemi_kp[ np.where(hemi_masked) ] # <codecell> fig, axs = plt.subplots(1, 2, figsize = (15, 15))