def getFluxVol(self, length_unit=3): """returns volume within flux surface. This is not implemented in LIUQE as default output. So we use contour and GREEN theorem to get the area within a default grid of the PSI. Then we compute the volume by multipling for 2pi * VolLCFS / AreaLCFS. Keyword Args: length_unit (String or 3): unit for plasma volume. Defaults to 3, indicating default volumetric unit (typically m^3). Returns: fluxVol (Array): [nt,npsi] array of volume within flux surface. Raises: ValueError: if module cannot retrieve data from MDS tree. """ if self._fluxVol is None: try: # first determine npsi nPsi = self.getRmidPsi().shape[1] # then the psi from psiGrid psiRZ = self.getFluxGrid() # the rGrid, zGrid in an appropriate mesh R, Z = scipy.meshgrid(self.getRGrid(), self.getZGrid()) # read the LCFS Volume and Area and compute # the appropriate twopi R rUsed = self.getVolLCFS() / self.getAreaLCFS() # define the output volumes = scipy.zeros((psiRZ.shape[0], nPsi)) outArea = scipy.zeros(nPsi) # now we start to iterate over the times for i in range(psiRZ.shape[0]): psi = psiRZ[i] # define the levels levels = scipy.linspace(psi.max(), 0, nPsi) c = cntr.Cntr(R, Z, psi) for j in range(nPsi - 1): nlist = c.trace(levels[j + 1]) segs = nlist[: len(nlist) // 2] outArea[j + 1] = abs(greenArea(segs[0])) volumes[i, :] = outArea * rUsed[i] # then the levels for the contours self._fluxVol = volumes # Units aren't properly stored in the tree for this one! self._defaultUnits['_fluxVol'] = 'm^3' except TreeException: raise ValueError('data retrieval failed.') # Default units are m^3, but aren't stored in the tree! unit_factor = self._getLengthConversionFactor( self._defaultUnits['_fluxVol'], length_unit) return unit_factor * self._fluxVol.copy()
def draw_core_line(R, Z, psi, psi_val, sep_pts): num_lines = int(len(cntr.Cntr(R, Z, psi).trace(psi_val)) / 2) if num_lines == 1: # then we're definitely dealing with a surface inside the seperatrix x, y = draw_contour_line(R, Z, psi, psi_val, 0) else: # we need to find which of the surfaces is inside the seperatrix for j, line in enumerate( cntr.Cntr(R, Z, psi).trace(psi_val)[:num_lines]): x, y = draw_contour_line(R, Z, psi, psi_val, j) if (np.amax(x) < np.amax(sep_pts[:, 0]) and np.amin(x) > np.amin(sep_pts[:, 0]) and np.amax(y) < np.amax(sep_pts[:, 1]) and np.amin(y) > np.amin(sep_pts[:, 1])): # then it's an internal flux surface break pts = np.column_stack((x, y)) line = LineString(pts) out_pt = pts[np.argmax(pts, axis=0)[0]] in_pt = pts[np.argmin(pts, axis=0)[0]] top_pt = pts[np.argmax(pts, axis=0)[1]] bot_pt = pts[np.argmin(pts, axis=0)[1]] fs_axis = [(out_pt[0] + in_pt[0]) / 2, (out_pt[1] + in_pt[1]) / 2] return line, fs_axis
def plot_ccurve_cusp(ax1, Mag, alpha_x, alpha_y): [dyy, dxx] = np.meshgrid(Mag.y[10:-10] / 4.413, Mag.x[10:-10] / 4.413) levels = [0, 1] # c1 = ax1.contour(dxx,dyy,Mag.data[10:-10,10:-10],colors = 'y',levels=levels) level = 0 c1 = cntr.Cntr(dxx, dyy, Mag.data[10:-10, 10:-10]) nlist = c1.trace(level, level, 0) segs = nlist[:len(nlist) // 2] x_cr, y_cr, x_cusp, y_cusp = [], [], [], [] for i in range(len(segs)): x = segs[i][:, 0] y = segs[i][:, 1] x1, y1 = cusp(x, y, alpha_x, alpha_y) ax1 = curve(ax1, x, y, x1, y1) return ax1
def _region(smooth, level): if smooth.pdf.ndim != 2: raise ValueError('Should be a 2D data set.') xgrid, ygrid = smooth.grid c = cntr.Cntr(xgrid, ygrid, smooth.pdf) vertex = c.trace(level) vertex = vertex[:len(vertex)/2] polygon = [] for vert in vertex: polygon.append((vert, None)) return MultiPolygon(polygon)
def isodose_display(self): """ Display isodoses on the DICOM Image. """ slider_id = self.slider.value() curr_slice_uid = self.main_window.dict_UID[slider_id] z = self.main_window.dataset[slider_id].ImagePositionPatient[2] grid = get_dose_grid(self.main_window.dataset['rtdose'], float(z)) if not (grid == []): x, y = np.meshgrid(np.arange(grid.shape[1]), np.arange(grid.shape[0])) # Instantiate the isodose generator for this slice isodosegen = cntr.Cntr(x, y, grid) # sort selected_doses in ascending order so that the high dose isodose washes # paint over the lower dose isodose washes for sd in sorted(self.main_window.selected_doses): dose_level = sd * self.main_window.rxdose / \ (self.main_window.dataset['rtdose'].DoseGridScaling * 10000) contours = isodosegen.trace(dose_level) contours = contours[:len(contours) // 2] polygons = self.calc_dose_polygon( self.main_window.dose_pixluts[curr_slice_uid], contours) brush_color = self.isod_color[sd] with open('src/data/line&fill_configuration', 'r') as stream: elements = stream.readlines() if len(elements) > 0: iso_line = int(elements[2].replace('\n', '')) iso_opacity = int(elements[3].replace('\n', '')) line_width = float(elements[4].replace('\n', '')) else: iso_line = 2 iso_opacity = 5 line_width = 2.0 stream.close() iso_opacity = int((iso_opacity / 100) * 255) brush_color.setAlpha(iso_opacity) pen_color = QtGui.QColor(brush_color.red(), brush_color.green(), brush_color.blue()) pen = self.get_qpen(pen_color, iso_line, line_width) for i in range(len(polygons)): self.scene.addPolygon(polygons[i], pen, QBrush(brush_color))
def get_stability_region(solver_list=['Euler'], xgrid=(-11, 1, 200), ygrid=(-6, 6, 200)): Y, X = np.mgrid[ygrid[0]:ygrid[1]:ygrid[2] * 1j, xgrid[0]:xgrid[1]:xgrid[2] * 1j] Z = X.astype(np.float64) + 1j * Y.astype(np.float64) X0 = np.ones((1, ygrid[2], xgrid[2]), dtype=np.complex128) x = sp.Symbol('x') tst_sys = ODE(x=[x], f=[x]) contour_list = [] for solver in solver_list: traj = getattr(tst_sys, solver)(h=Z, nsteps=1, X0=X0) bla = cntr.Cntr(X, Y, np.abs(traj[1, 0])) res = bla.trace(1.0) contour_list.append(res[:len(res) / 2]) return contour_list
def contourLines(self, stepCont=20, maxNodesPerWay=0, noZero=False, minCont=None, maxCont=None, rdpEpsilon=None, rdpMaxVertexDistance=None): """generates contour lines using matplotlib. <stepCont> is height difference of contiguous contour lines in meters <maxNodesPerWay>: the maximum number of nodes contained in each way <noZero>: if True, the 0 m contour line is discarded <minCont>: lower limit of the range to generate contour lines for <maxCont>: upper limit of the range to generate contour lines for <rdpEpsilon>: epsilon to use in RDP contour line simplification <rdpMaxVertexDistance>: maximal vertex distance in RDP simplification A list of elevations and a ContourObject is returned. """ def getContLimit(ele, step): """returns a proper value for the lower or upper limit to generate contour lines for. """ if ele%step == 0: return ele corrEle = ele + step - ele % step return corrEle minCont = minCont or getContLimit(self.minEle, stepCont) maxCont = maxCont or getContLimit(self.maxEle, stepCont) contourSet = [] if noZero: levels = [l for l in range(int(minCont), int(maxCont), stepCont) if l!=0] else: levels = range(int(minCont), int(maxCont), stepCont) x, y = numpy.meshgrid(self.xData, self.yData) # z data is a masked array filled with nan. z = numpy.ma.array(self.zData, mask=self.mask, fill_value=float("NaN"), keep_mask=True) if mplversion < "2.0.0": Contours = ContourObject(_cntr.Cntr(x, y, z.filled(), None), maxNodesPerWay, self.transform, self.polygon, rdpEpsilon, rdpMaxVertexDistance) else: corner_mask = True nchunk = 0 Contours = ContourObject( _contour.QuadContourGenerator(x, y, z.filled(), self.mask, corner_mask, nchunk), maxNodesPerWay, self.transform, self.polygon, rdpEpsilon, rdpMaxVertexDistance) return levels, Contours
def show_fit(p): ax1.cla() ## make alpha alpha = p/float(10) #### setup current points and print T = (1-alpha)*X1 + alpha*X2 # custom colors red = 'salmon' # custom color for plotting purposes blue = 'cornflowerblue' # custom color for plotting purposes # plot points on desired panel ax1.scatter(T[self.ind0,0],T[self.ind0,1],s = 60, color = blue, edgecolor = 'k') artist = ax1.scatter(T[self.ind1,0],T[self.ind1,1],s = 60, color = red, edgecolor = 'k') #### setup separator and print sep1 = (1-alpha)*a + alpha*f1 sep2 = (1-alpha)*b + alpha*f2 # the cntr command grabs a contour without plotting it c = cntr.Cntr(sep1, sep2, z) res = c.trace(0) # here trace grabs a contour at slice z = value # plot points for k in range(len(res) - 1): data = res[k] # extract the right array from the trace object ax1.plot(data[:,0],data[:,1],'k', linewidth = 3) ### setup current grid and print grid = (1-alpha)*grid1 + alpha*grid2 # plot points for i in range(80): ax1.plot(grid[200*i:(i+1)*200,0],grid[200*i:(i+1)*200,1],color = [0.75,0.75,0.75],linewidth = 1,zorder = 0) ### set axis limits for current dataset hgap = (max(T[:,0]) - min(T[:,0]))*0.05 vgap = (max(T[:,1]) - min(T[:,1]))*0.05 ax1.set_xlim([min(T[:,0])-hgap,max(T[:,0])+hgap]) ax1.set_ylim([min(T[:,1])-vgap,max(T[:,1])+vgap]) ax1.axis('off') fig.subplots_adjust(left=0,right=1,bottom=0,top=1) ## gets rid of the white space around image return artist,
def critical_curve_caustics(self, kwargs_lens, compute_window=5, grid_scale=0.01): """ :param kwargs_lens: lens model kwargs :param compute_window: window size in arcsec where the critical curve is computed :param grid_scale: numerical grid spacing of the computation of the critical curves :return: lists of ra and dec arrays corresponding to different disconnected critical curves and their caustic counterparts """ numPix = int(compute_window / grid_scale) x_grid_high_res, y_grid_high_res = util.make_grid(numPix, deltapix=grid_scale, subgrid_res=1) mag_high_res = util.array2image(self.magnification(x_grid_high_res, y_grid_high_res, kwargs_lens)) #import numpy.ma as ma #z = ma.asarray(z, dtype=np.float64) # Import if want filled contours. # Non-filled contours (lines only). level = 0.5 import matplotlib._cntr as cntr c = cntr.Cntr(util.array2image(x_grid_high_res), util.array2image(y_grid_high_res), mag_high_res) nlist = c.trace(level, level, 0) segs = nlist[:len(nlist) // 2] # print segs # x,y coords of contour points. #cs = ax.contour(util.array2image(x_grid_high_res), util.array2image(y_grid_high_res), mag_high_res, [0], # alpha=0.0) #paths = cs.collections[0].get_paths() paths = segs ra_crit_list = [] dec_crit_list = [] ra_caustic_list = [] dec_caustic_list = [] for p in paths: #v = p.vertices v = p ra_points = v[:, 0] dec_points = v[:, 1] ra_crit_list.append(ra_points) dec_crit_list.append(dec_points) ra_caustics, dec_caustics = self.ray_shooting(ra_points, dec_points, kwargs_lens) ra_caustic_list.append(ra_caustics) dec_caustic_list.append(dec_caustics) return ra_crit_list, dec_crit_list, ra_caustic_list, dec_caustic_list
def get_fluxsurface(self, psiN, Rref=1.5, Zref=0.0): """ Get R,Z coordinates of a flux surface at psiN """ R, Z = scipy.meshgrid(self.R, self.Z) c = cntr.Cntr(R, Z, self.psiN[:]) nlist = c.trace(psiN) segs = nlist[:len(nlist) // 2] if len(segs) > 1: if len(segs[1]) > 20: R = segs[1].transpose()[0] Z = segs[1].transpose()[1] else: R = segs[0].transpose()[0] Z = segs[0].transpose()[1] else: R = segs[0].transpose()[0] Z = segs[0].transpose()[1] return fluxSurface(R=R, Z=Z)
def extract_contour_lines(self, levels): """ Extract contour lines from grid :param levels: list or array, contour line values :return: list with instances of :class:`MultiLineData` """ import matplotlib._cntr as cntr contour_engine = cntr.Cntr(self.lons, self.lats, self.values) contour_lines = [] for level in levels: nlist = contour_engine.trace(level, level, 0) nseg = len(nlist) // 2 segs = nlist[:nseg] contour_line = MultiLineData([], []) for seg in segs: cl = LineData(seg[:,0], seg[:,1], value=level) contour_line.append(cl) contour_lines.append(contour_line) return contour_lines
def __init__(self, levelset): x,y = np.mgrid[:levelset.shape[0],:levelset.shape[1]] c = cntr.Cntr(x,y,levelset) res = c.trace(.5) super(self.__class__, self).__init__(res[0][...,::-1])
def _mask_to_polygon(mask, x=None, y=None, gdir=None): """Converts a mask to a single polygon. The mask should be a single entity with nunataks: I didnt test for more than one "blob". Parameters ---------- mask: 2d array with ones and zeros the mask to convert x: 2d array with the coordinates if not given it will be generated, give it for optimisation y: 2d array with the coordinates if not given it will be generated, give it for optimisation gdir: GlacierDirectory for logging Returns ------- (poly, poly_no_nunataks) Shapely polygons """ if (x is None) or (y is None): # do it yourself ny, nx = mask.shape x = np.arange(0, nx, 1) y = np.arange(0, ny, 1) x, y = np.meshgrid(x, y) regions, nregions = label(mask, structure=LABEL_STRUCT) if nregions > 1: log.debug('%s: we had to cut a blob from the catchment', gdir.rgi_id) # Check the size of those region_sizes = [np.sum(regions == r) for r in np.arange(1, nregions+1)] am = np.argmax(region_sizes) # Check not a strange glacier sr = region_sizes.pop(am) for ss in region_sizes: if (ss / sr) > 0.2: log.warning('%s: this blob was unusually large', gdir.rgi_id) mask[:] = 0 mask[np.where(regions == (am+1))] = 1 c = cntr.Cntr(x, y, mask) nlist = c.trace(0.5) if len(nlist) == 0: raise RuntimeError('Mask polygon is empty') # The first half are the coordinates. The other stuffs I dont know ngeoms = len(nlist)//2 - 1 # First is the exterior, the rest are nunataks e_line = shpg.LinearRing(nlist[0]) i_lines = [shpg.LinearRing(ipoly) for ipoly in nlist[1:ngeoms+1]] poly = shpg.Polygon(e_line, i_lines).buffer(0) if not poly.is_valid: raise RuntimeError('Mask polygon not valid.') poly_no = shpg.Polygon(e_line).buffer(0) if not poly_no.is_valid: raise RuntimeError('Mask polygon not valid.') return poly, poly_no
np.floor(hrange[0] / cint) * cint + datum, np.ceil(hrange[1] / cint) * cint + datum, cint) contourLevels.update({c: '101' for c in cheights}) #Generate index contours (overwrite normal contours) if (cargs.index[0] > 0): iint = cint * cargs.index[0] idatum = datum + cargs.idatum[ 0] * cint #Datum for index contours is main datum + a number of normal contour intervals iheights = np.arange( np.floor(hrange[0] / iint) * iint + idatum, np.ceil(hrange[1] / iint) * iint + idatum, iint) contourLevels.update({i: '102' for i in iheights}) #Set up contour class contourdata = cntr.Cntr(x, y, z) #Calculate window size map grad = np.gradient(z) grad = (grad[0]**2 + grad[1]**2)**0.5 grad = ndimage.uniform_filter(grad, size=grad_smooth_win) grad[grad == 0] = 0.001 wsize = gradientFactor * cwin_max / grad wsize[wsize > cwin_max] = cwin_max wsize[wsize < 0.0] = 0.0 for cheight in contourLevels: clist = contourdata.trace(cheight, cheight, 0) clist = clist[:len(clist) // 2] print('Processing ' + str(len(clist)) + ' ' + str(cheight) + 'm contours as symbol ' + contourLevels[cheight])
def minimize_gof_grid(self, center_coordinates, grid_size, areas_observed, pmt_selection=None, square_syst_errors=None, statistic='chi2gamma', plot=False, cls=None): """Return (spatial position which minimizes goodness of fit parameter, gof at that position, errors on that position) minimum is found by minimizing over a grid centered at center_coordinates and extending by grid_size in all dimensions. Errors are optionally calculated by tracing contours at given confidence levels, from the resulting set of points the distances to the minimum are calculated for each dimension and the mean of these distances is reported as (dx, dy). All other parameters like compute_gof """ gofs, lowest_indices = self.compute_gof_grid(center_coordinates, grid_size, areas_observed, pmt_selection, square_syst_errors, statistic, plot) min_index = np.unravel_index(np.nanargmin(gofs), gofs.shape) # Convert index back to position result = [] for dimension_i, i_of_minimum in enumerate(min_index): x = self._index_to_coordinate( lowest_indices[dimension_i] + i_of_minimum, dimension_i) result.append(x) # Compute confidence level contours (but only in 2D) n_dim = len(min_index) # Store contours for plotting only cl_segments = [] # Store (dx, dy) for each CL for output confidence_tuples = [] if cls is not None and n_dim == 2 and _cntr is not None: x, y = np.mgrid[:gofs.shape[0], :gofs.shape[1]] # Use matplotlib _Cntr module to trace contours (without plotting) c = _cntr.Cntr(x, y, gofs) for cl in cls: ct = ConfidenceTuple() ct.level = cl # Trace at the required value cl_trace = c.trace(gofs[min_index] + cl) # Check for failure if len(cl_trace) == 0: confidence_tuples.append(ct) continue # Get the actual contour, the first half of cl_trace is an array of (x, y) pairs half_length = int(len(cl_trace) // 2) cl_segment = np.array(cl_trace[:half_length][0]) # Extract the x values and y values seperately, also convert to the TPC coordinate system x_values = np.array([ self._index_to_coordinate(lowest_indices[0] + x, 0) for x in cl_segment[:, 0] ]) y_values = np.array([ self._index_to_coordinate(lowest_indices[1] + y, 1) for y in cl_segment[:, 1] ]) if np.all(np.isnan(x_values)) or np.all(np.isnan(y_values)): self.log.debug( "Cannot compute confidence contour: all x or y values are Nan!" ) # If we'd now call nanmin, we get an annoying numpy runtime warning. else: # Calculate the confidence tuple for this CL ct.x0 = np.nanmin(x_values) ct.y0 = np.nanmin(y_values) ct.dx = abs(np.nanmax(x_values) - np.nanmin(x_values)) ct.dy = abs(np.nanmax(y_values) - np.nanmin(y_values)) # Does the contour touch the edge of the TPC if np.isnan(x_values).any() or np.isnan(y_values).any(): ct.at_edge = True confidence_tuples.append(ct) # The contour points, only for plotting if plot: contour_points = np.array([x_values, y_values]).T # Take out point if x or y is nan contour_points = [ p for p in contour_points if not np.isnan(p).any() ] cl_segments.append(contour_points) if plot and n_dim == 2: plt.scatter(*[[r] for r in result], marker='*', s=20, color='orange', label='Grid minimum') for i, contour in enumerate(cl_segments): if len(contour) == 0: continue color = lambda x: 'w' if x % 2 == 0 else 'r' p = plt.Polygon(contour, fill=False, color=color(i), label=str(cls[i])) plt.gca().add_artist(p) # plt.savefig("plot_%.2f_%.2f.pdf" % (result[0], result[1]), dpi=150) return result, gofs[min_index], confidence_tuples
def contourLines(self, stepCont=20, maxNodesPerWay=0, noZero=False, minCont=None, maxCont=None, rdpEpsilon=None, rdpMaxVertexDistance=None, scale=1, smooth=0): """generates contour lines using matplotlib. <stepCont> is height difference of contiguous contour lines in meters <maxNodesPerWay>: the maximum number of nodes contained in each way <noZero>: if True, the 0 m contour line is discarded <minCont>: lower limit of the range to generate contour lines for <maxCont>: upper limit of the range to generate contour lines for <rdpEpsilon>: epsilon to use in RDP contour line simplification <rdpMaxVertexDistance>: maximal vertex distance in RDP simplification A list of elevations and a ContourObject is returned. """ def getContLimit(ele, step): """returns a proper value for the lower or upper limit to generate contour lines for. """ if ele % step == 0: return ele corrEle = ele + step - ele % step return corrEle minCont = minCont or getContLimit(self.minEle, stepCont) maxCont = maxCont or getContLimit(self.maxEle, stepCont) contourSet = [] if noZero: levels = [ l for l in range(int(minCont), int(maxCont), stepCont) if l != 0 ] else: levels = range(int(minCont), int(maxCont), stepCont) x, y = numpy.meshgrid(self.xData, self.yData) # z data is a masked array filled with nan. z = numpy.ma.array(self.zData, mask=self.mask, fill_value=float("NaN"), keep_mask=True) #Get smoother contours by a) interpolating SRTM data (with scale factor scale), # Then smooth the data using a Gaussian filter. #scale=4 x2 = numpy.linspace(self.xData[0], self.xData[-1], len(self.xData) * scale) y2 = numpy.linspace(self.yData[0], self.yData[-1], len(self.yData) * scale) xnew, ynew = numpy.meshgrid(x2, y2) #znew = f(xnew, ynew) import scipy.ndimage from scipy.ndimage.filters import gaussian_filter sm = int(smooth * scale) #znew = scipy.ndimage.grey_dilation(scipy.ndimage.grey_erosion(scipy.ndimage.zoom(z, scale),size=(sm,sm)), size=(sm,sm)) #sigma = 4.0 # this depends on how noisy your data is, play with it! #znew = gaussian_filter(znew, sigma) znew = gaussian_filter(scipy.ndimage.zoom(z, scale), sm) if mplversion < "2.0.0": Contours = ContourObject(_cntr.Cntr(xnew, ynew, znew, None), maxNodesPerWay, self.transform, self.polygon, rdpEpsilon, rdpMaxVertexDistance) else: corner_mask = True nchunk = 0 Contours = ContourObject( _contour.QuadContourGenerator(xnew, ynew, znew, self.mask, corner_mask, nchunk), #_contour.QuadContourGenerator(x, y, z.filled(), self.mask, corner_mask, nchunk), maxNodesPerWay, self.transform, self.polygon, rdpEpsilon, rdpMaxVertexDistance) return levels, Contours
Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1) Z = 10.0 * (Z2 - Z1) levels = np.arange(-1.2, 1.6, 0.2) # Set up the gateway - this connects to the GraphExplorer.jar JVM # which needs to be running from py4j.java_gateway import JavaGateway gateway = JavaGateway(auto_convert=True) p = gateway.jvm.kcl.waterloo.plot.WPlot.contour(None) contourObject = gateway.jvm.kcl.waterloo.graphics.plots2D.contour.ContourExtra.createInstance( ) # Set up the contours: # Generate the contour lines using matplotlib CS = cntr.Cntr(X, Y, Z) for k in np.arange(1, len(levels)): list = CS.trace(levels[k]) if len(list) > 0: contourObject.addContour(list.pop(0), levels[k]) # Turn off filling of contours - it's on by default p.getPlot().setFilled(False) # Fill clipping should be off for Python-generated contours # (if setFilled is true). p.getPlot().setFillClipping(False) # The ContourExtra object has some non-standard properties that # cause the "normal" line color settings to be ignored and paint all # positive and all negative levels to be painted with the set color... contourObject.setNegativeLineColor(gateway.jvm.java.awt.Color.BLUE.darker())
def extract_geometry(mask): def add_antemeridian(inIndex, outIndex): # this segment crosses the x axis (prime meridian or antemeridian) frac = (-x0) / (x1 - x0) yMid = (1. - frac) * ys[inIndex] + frac * ys[inIndex + 1] if yMid > 0: # segment crosses the prime meridian, so that's fine return # segment crosses the antemeridian # break it into 6 segments, including the south pole if x0 < x1: newLon = [-180., -180., 0., 180., 180.] else: newLon = [180., 180., 0., -180., -180.] latMid = (1. - frac) * lats[outIndex] + frac * lats[outIndex + 1] newLat = [latMid, -90, -90., -90, latMid] for i in range(5): lons.insert(outIndex + 1, newLon[i]) lats.insert(outIndex + 1, newLat[i]) outIndex += 1 print(x0, x1, frac) print(ys[inIndex], ys[inIndex + 1], yMid) print(lats[outIndex - 5:outIndex + 2], latMid) print(lons[outIndex - 5:outIndex + 2]) pyplot.figure(1) pyplot.plot(xs, ys) pyplot.figure(2) pyplot.plot(lons, lats) pyplot.show() floatMask = numpy.zeros(mask.shape) floatMask[1:-1, 1:-1] = numpy.array(mask[1:-1, 1:-1], float) floatMask = 2. * floatMask - 1. distance = skfmm.distance(floatMask) print(name, 'distance', numpy.amin(distance), numpy.amax(distance)) pyplot.imsave('%s_distance.png' % name, distance, vmin=-1., vmax=1., origin='lower') # smooth it a little distance = gaussian_filter(distance, sigma=0.5) print(name, 'distance smoothed', numpy.amin(distance), numpy.amax(distance)) pyplot.imsave('%s_distance_smoothed.png' % name, distance, vmin=-1., vmax=1., origin='lower') contourObj = cntr.Cntr(X, Y, distance) contours = contourObj.trace(0.) vertexLists = contours[0:len(contours) / 2] polys = [] for v in vertexLists: xs = v[:, 0] ys = v[:, 1] lons = list(numpy.arctan2(xs, ys) * 180. / numpy.pi) # avoid seam lats = list(basemap_interp(Lat, x, y, xs, ys)) inIndex = 0 outIndex = 0 while (inIndex < len(xs) - 1): x0 = xs[inIndex] x1 = xs[inIndex + 1] if (x0 >= 0) != (x1 >= 0): add_antemeridian(inIndex, outIndex) inIndex += 1 outIndex += 1 poly = Polygon([(i[0], i[1]) for i in zip(lons, lats)]) if poly.is_valid: polys.append(poly) else: print(f"invalid shape with {v.shape[0]:d} vertices") return mapping(unary_union(polys))
def draw_contour_line(R, Z, array, val, pathnum): res = cntr.Cntr(R, Z, array).trace(val)[pathnum] x = res[:, 0] y = res[:, 1] return x, y
def sep_lines(self, inp, R, Z, psi): # find x-point location dpsidR = np.gradient(psi, R[0, :], axis=1) dpsidZ = np.gradient(psi, Z[:, 0], axis=0) d2psidR2 = np.gradient(dpsidR, R[0, :], axis=1) d2psidZ2 = np.gradient(dpsidZ, Z[:, 0], axis=0) # find line(s) where dpsidR=0 self.dpsidR_0 = cntr.Cntr(R, Z, dpsidR).trace(0.0) # find line(s) where dpsidZ=0 self.dpsidZ_0 = cntr.Cntr(R, Z, dpsidZ).trace(0.0) for i, path1 in enumerate(self.dpsidR_0): for j, path2 in enumerate(self.dpsidZ_0): try: # find intersection points between curves for dpsidR=0 and dpsidZ=0 ints = LineString(path1).intersection(LineString(path2)) # if there is only one intersection ('Point'), then we're probably not # dealing with irrelevant noise in psi if ints.type == 'Point': # check if local maximum or minimum d2psidR2_pt = griddata(np.column_stack( (R.flatten(), Z.flatten())), d2psidR2.flatten(), [ints.x, ints.y], method='cubic') d2psidZ2_pt = griddata(np.column_stack( (R.flatten(), Z.flatten())), d2psidZ2.flatten(), [ints.x, ints.y], method='cubic') if d2psidR2_pt > 0 and d2psidZ2_pt > 0: # we've found the magnetic axis self.m_axis = np.array([ints.x, ints.y]) elif d2psidR2_pt < 0 and d2psidZ2_pt < 0: # we've found a magnet. Do nothing. pass elif ints.y < 0: # we've probably found our x-point, although this isn't super robust # and obviously only applies to a single-diverted, lower-null configuration # TODO: make this more robust, I could easily see this failing on some shots self.xpt = np.array([ints.x, ints.y]) # uncomment this line when debugging # print list(ints.coords), d2psidR2(ints.x, ints.y), d2psidZ2(ints.x, ints.y) except: pass # normalize psi psi_shift = psi + abs(np.amin(psi)) # set center to zero psi_shift_xpt = griddata(np.column_stack((R.flatten(), Z.flatten())), psi_shift.flatten(), self.xpt, method='cubic') # psi_shift_xpt = interp2d(R, Z, psi_shift, kind='linear')(xpt[0], xpt[1]) # get new value at sep self.psi_norm_raw = psi_shift / psi_shift_xpt # create lines for seperatrix and divertor legs of seperatrix num_lines = int(len(cntr.Cntr(R, Z, self.psi_norm_raw).trace(1.0)) / 2) if num_lines == 1: # in this case, the contour points that matplotlib returned constitute # a single line from inboard divertor to outboard divertor. We need to # add in the x-point in at the appropriate locations and split into a # main and a lower seperatrix line, each of which will include the x-point. x_psi, y_psi = draw_contour_line(R, Z, self.psi_norm_raw, 1.0, 0) loc1 = np.argmax(y_psi > self.xpt[1]) loc2 = len(y_psi) - np.argmin(y_psi[::-1] < self.xpt[1]) x_psi = np.insert(x_psi, (loc1, loc2), self.xpt[0]) y_psi = np.insert(y_psi, (loc1, loc2), self.xpt[1]) psi_1_pts = np.column_stack((x_psi, y_psi)) self.main_sep_pts = psi_1_pts[loc1:loc2 + 1, :] self.main_sep_line = LineString(self.main_sep_pts[:-1]) self.main_sep_line_closed = LineString(self.main_sep_pts) # get the inboard and outboard divertor legs seperately. This is so that # everything that includes the x-point can start with the x-point, which # elliminates the risk of tiny triangles in the vicinity of the x-point self.inboard_div_sep = np.flipud(psi_1_pts[:loc1 + 1]) self.outboard_div_sep = psi_1_pts[loc2 + 1:] # cut inboard line at the wall and add intersection point to wall_line line = LineString(self.inboard_div_sep) int_pt = line.intersection(inp.wall_line) self.ib_div_line = line self.ib_div_line_cut = cut(line, line.project(int_pt, normalized=True))[0] # self.ib_div_line_cut = line # TODO: add point to wall line # cut inboard line at the wall and add intersection point to wall_line line = LineString(self.outboard_div_sep) int_pt = line.intersection(inp.wall_line) self.ob_div_line = line self.ob_div_line_cut = cut(line, line.project(int_pt, normalized=True))[0] ib_div_pts = np.flipud(np.asarray(self.ib_div_line_cut.xy).T) sep_pts = np.asarray(self.main_sep_line.xy).T ob_div_pts = np.asarray(self.ob_div_line_cut.xy).T entire_sep_pts = np.vstack( (ib_div_pts, sep_pts[1:, :], ob_div_pts)) self.entire_sep_line = LineString(entire_sep_pts) # these are useful later self.obmp_pt = self.main_sep_pts[np.argmax(self.main_sep_pts, axis=0)[0]] self.ibmp_pt = self.main_sep_pts[np.argmin(self.main_sep_pts, axis=0)[0]] self.top_pt = self.main_sep_pts[np.argmax(self.main_sep_pts, axis=0)[1]] self.bot_pt = self.main_sep_pts[np.argmin(self.main_sep_pts, axis=0)[1]] self.geo_axis = [(self.obmp_pt[0] + self.ibmp_pt[0]) / 2, (self.obmp_pt[1] + self.ibmp_pt[1]) / 2] self.R0_a = self.geo_axis[0] # TODO: Is this how a is actually defined? # a is used by nbeams. I'm not sure it's used anywhere else. self.a = self.obmp_pt[0] - self.R0_a # TODO: add point to wall line elif num_lines == 2: # in this case, we have a lower seperatrix trace (line 0), and a main # seperatrix trace (line 1). # first do lower seperatrix line x_psi, y_psi = draw_contour_line(R, Z, self.psi_norm_raw, 1.0, 0) loc = np.argmax(x_psi > self.xpt[0]) x_psi = np.insert(x_psi, loc, self.xpt[0]) y_psi = np.insert(y_psi, loc, self.xpt[1]) psi_1_pts = np.column_stack((x_psi, y_psi)) self.inboard_div_sep = np.flipud(psi_1_pts[:loc + 1]) self.outboard_div_sep = psi_1_pts[loc + 1:] #cut inboard line at the wall and add intersection point to wall_line line = LineString(self.inboard_div_sep) int_pt = line.intersection(inp.wall_line) self.ib_div_line = line self.ib_div_line_cut = cut(line, line.project(int_pt, normalized=True))[0] #cut inboard line at the wall and add intersection point to wall_line line = LineString(self.outboard_div_sep) int_pt = line.intersection(inp.wall_line) self.ob_div_line = line self.ob_div_line_cut = cut(line, line.project(int_pt, normalized=True))[0] #TODO: add point to wall line #now to main seperatrix line x_psi, y_psi = draw_contour_line(R, Z, self.psi_norm_raw, 1.0, 1) self.main_sep_pts = np.insert(np.column_stack((x_psi, y_psi)), 0, self.xpt, axis=0) self.main_sep_line = LineString(self.main_sep_pts[:-1]) self.main_sep_line_closed = LineString(self.main_sep_pts) entire_sep_pts = np.vstack( (ib_div_pts, sep_pts[1:, :], ob_div_pts)) self.entire_sep_line = LineString(entire_sep_pts)
def flightEn(U_range, omega_range, propeller_funcs, propeller, plane, atmosphere): """ Finds all possible propeller rotation speeds, flight speeds and propeller torque values for a given propeller and plane within a range of speeds and rotation speeds. """ C_T_interp = propeller_funcs['C_T_interp'] C_Q_interp = propeller_funcs['C_Q_interp'] bounds = propeller_funcs['bounds'] #We make a grid of rotational speeds and flight speeds representing the possible flight envelope X, Y = np.meshgrid(omega_range, U_range) #We calculate the thrust surface at every single one of these shits Ts = np.array([ propT(x, y, C_T_interp, bounds, propeller, atmosphere) for x, y in zip(np.ravel(X), np.ravel(Y)) ]) Tsurf = Ts.reshape(X.shape) #Z=T#C_T_interp(X,Y) # Calculate the drag surface Ds = np.array([ dragFunc(y, plane, atmosphere) for x, y in zip(np.ravel(X), np.ravel(Y)) ]) Dsurf = Ds.reshape(X.shape) # Take the difference between the two surface heights and find the contour # where that surface is zero. diffSurf = Dsurf - Tsurf #The contour represents the possible flight speeds and rotation speeds that result in level flight #This includes reynolds number and advance ratio effects on the thrust coefficient. c = cntr.Cntr(X, Y, diffSurf) # trace a contour at z == 0.0 res = c.trace(0.0) # result is a list of arrays of vertices and path codes nseg = len(res) // 2 if nseg == 0: print( 'No intersection of drag and thrust surface for given U and omega range found.' ) return segments, codes = res[:nseg], res[nseg:] #Suck out the points on this contour omega_flight = segments[0][:, 0] U_flight = segments[0][:, 1] if np.isnan(omega_flight).any(): print('UGH F**K') print(omega_range) print(U_range) print(Dsurf) if np.isnan(U_flight).any(): print('SHIT') # print('length is ' + str(len(omega_flight))) #Improve our results by repeating within the limits of the outputted flight envolope #We expand the envelope slightly to ensure we capture the edges properly. omega_range = np.linspace(0.9 * min(omega_flight), max(omega_flight) * 1.1, len(omega_range)) U_range = np.linspace(0.9 * min(U_flight), max(U_flight) * 1.1, len(U_range)) X, Y = np.meshgrid(omega_range, U_range) Ts = np.array([ propT(x, y, C_T_interp, bounds, propeller, atmosphere) for x, y in zip(np.ravel(X), np.ravel(Y)) ]) Tsurf = Ts.reshape(X.shape) Ds = np.array([ dragFunc(y, plane, atmosphere) for x, y in zip(np.ravel(X), np.ravel(Y)) ]) Dsurf = Ds.reshape(X.shape) diffSurf = Dsurf - Tsurf c = cntr.Cntr(X, Y, diffSurf) res = c.trace(0.0) nseg = len(res) // 2 if nseg == 0: print( 'No intersection of drag and thrust surface for given U and omega range found.' ) return segments, codes = res[:nseg], res[nseg:] #Suck out the points on this contour omega_flight = segments[0][:, 0] U_flight = segments[0][:, 1] #For each point we find the torque # print('resolved length is ' + str(len(omega_flight))) Q_flight = np.array([ propQ(x, y, C_Q_interp, bounds, propeller, atmosphere) for x, y in zip(omega_flight, U_flight) ]) return omega_flight, U_flight, Q_flight.reshape(U_flight.shape)
def unit_sphere(outfile,gf=True,ell=False): ''' Compute stuff on a unit sphere ''' ''' If ell = True, computes observed ellipticity ''' ''' If ell = False, computes correction factors ''' ''' Here we have specialized to the triaxial case ''' ## ======================================================================= ## 1. Create maps of the correction factor and ellipticity over sphere ## Using T = 0.55 ba=0.733 ca=0.4 ang = 0.5 (n, m) = (160,160) fac=1. # Meshing a unit sphere according to n, m phi = np.linspace(0, 2 * np.pi, num=n, endpoint=False) theta = np.linspace(np.pi * 1./(m+1), np.pi*(1-1./(m+1)), num=m, endpoint=False) phi, theta = np.meshgrid(phi, theta) phi, theta = phi.ravel(), theta.ravel() phi = np.append(phi, [0.]) # Adding the north pole... theta = np.append(theta, [0.]) phi = np.append(phi, [0.]) # Adding the south pole... theta = np.append(theta, [np.pi]) mesh_x, mesh_y = (theta*np.cos(phi), theta*np.sin(phi)) triangles = mtri.Triangulation(mesh_x, mesh_y).triangles x, y, z = fac*np.sin(theta)*np.cos(phi), fac*np.sin(theta)*np.sin(phi), fac*np.cos(theta) # Defining a custom color scalar field sphM = cJ.PaperModel(1.,0.999,rh,slos,True) sph = sphM.J_factor(0.,0.,D,ang,False,False)[0] pM = cJ.PaperModel(ba,ca,rh,slos,True) ## We have the option of colouring the sphere according to J-factor or ## ellipticity -- if ell = True colour by ellipticity def fnn(M,Th,Ph): if(ell): return M.ellipticity(Th,Ph) else: sphl = sph if(gf): sm = cJ.PaperModel(1.,1.,rh*np.sqrt(M.ellipticity(Th,Ph)),slos,True) sphl = sm.J_factor(Th,Ph,D,ang,False,False)[0] print Th,Ph,sphl return M.J_factor(Th,Ph,D,ang,False,False)[0]/sphl ## Create a mesh that only covers an octant of the sphere -- as triaxial phi2 = np.linspace(0, np.pi/2., num=n/4+1, endpoint=True) theta2 = np.linspace(np.pi * 1./(m+1), np.pi/2., num=m/2+1, endpoint=True) phi2, theta2 = np.meshgrid(phi2, theta2) phi2, theta2 = phi2.ravel(), theta2.ravel() phi2 = np.append(phi2, [0.]) # Adding the north pole... theta2 = np.append(theta2, [0.]) vals = np.array(map(lambda t,p:fnn(pM,t,p),theta2,phi2)) ## Now stack the results to cover the whole sphere allvals= np.reshape(vals[:-1],(m/2+1,n/4+1)) allvals = np.hstack((allvals,allvals[:,::-1][:,1:])) allvals = np.hstack((allvals,allvals[:,1:-1])) allvals = np.vstack((allvals,allvals[::-1,:][1:-1,:])) allvals = np.append(np.append(allvals,vals[-1]),vals[-1]) allvals = allvals.ravel() ## The colour is the average over the values on the triangle colors = np.mean(np.log10(allvals[triangles]), axis=1) if(ell): colors = np.mean(allvals[triangles], axis=1) ## Create a map of the ellipticity on the sphere ellip = np.array(map(lambda t,p:pM.ellipticity(t,p),theta2,phi2)) ellip_all= np.reshape(ellip[:-1],(m/2+1,n/4+1)) ellip_all = np.hstack((ellip_all,ellip_all[:,::-1][:,1:])) ellip_all = np.hstack((ellip_all,ellip_all[:,1:-1])) ellip_all = np.vstack((ellip_all,ellip_all[::-1,:][1:-1,:])) ellip_all = np.append(np.append(ellip_all,ellip[-1]),ellip[-1]) ellip_all = ellip_all.ravel() ## ======================================================================= ## 2. Plot the colour map fig = plt.figure(figsize=[3.5,4.]) ax = fig.gca(projection='3d') ax.set_aspect('equal') cmap = sns.cubehelix_palette(8,start=.5,rot=-.75,as_cmap=True) triang = mtri.Triangulation(x, y, triangles) collec = ax.plot_trisurf(triang, z, cmap=cmap, shade=False, linewidth=0.,zorder=0) collec.set_array(colors) collec.autoscale() lbl = r'$\mathcal{F}_\mathrm{J}$' if(ell): lbl = r'$1-e$' plt.colorbar(collec,orientation='horizontal',label=lbl) # ax = plt.gca() ax.set_xticklabels([]) ax.set_yticklabels([]) ax.set_zticklabels([]) ax.dist=7. max_range = np.array([x.max()-x.min(), y.max()-y.min(), z.max()-z.min()]).max() / 2.0 mean_x = x.mean() mean_y = y.mean() mean_z = z.mean() ax.set_xlim(mean_x - max_range, mean_x + max_range) ax.set_ylim(mean_y - max_range, mean_y + max_range) ax.set_zlim(mean_z - max_range, mean_z + max_range) ## ======================================================================= ## 3. Add axes #draw a vector from matplotlib.patches import FancyArrowPatch from mpl_toolkits.mplot3d import proj3d class Arrow3D(FancyArrowPatch): def __init__(self, xs, ys, zs, *args, **kwargs): FancyArrowPatch.__init__(self, (0,0), (0,0), *args, **kwargs) self._verts3d = xs, ys, zs def draw(self, renderer): xs3d, ys3d, zs3d = self._verts3d xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, renderer.M) self.set_positions((xs[0],ys[0]),(xs[1],ys[1])) FancyArrowPatch.draw(self, renderer) a = Arrow3D([-.8,-.8],[-.85,-.85],[.85,1.2], mutation_scale=40, lw=1, arrowstyle="-|>", color="k") ax.add_artist(a) ax.text(-.83,-.95,1.125, r"$z$") a = Arrow3D([-.8,-.45],[-.85,-.85],[.85,.85], mutation_scale=40, lw=1, arrowstyle="-|>", color="k") ax.text(-.62,-.9,0.77, r"$x$") ax.add_artist(a) a = Arrow3D([-.8,-.8],[-.85,-.5],[.85,.85], mutation_scale=40, lw=1, arrowstyle="-|>", color="k") ax.text(-.83,-.62,0.9, r"$y$") ax.add_artist(a) ## ======================================================================= ## 4. Make a small ellipsoidal inset that shows isodensity phis = np.linspace(0, 2 * np.pi, num=n/(n/40), endpoint=False) thetas = np.linspace(np.pi * 1./(m+1), np.pi*(1-1./(m+1)), num=m/(m/40), endpoint=False) phis, thetas = np.meshgrid(phis, thetas) phis, thetas = phis.ravel(), thetas.ravel() phis = np.append(phis, [0.]) # Adding the north pole... thetas = np.append(thetas, [0.]) phis = np.append(phis, [0.]) # Adding the south pole... thetas = np.append(thetas, [np.pi]) xs, ys, zs = fac*np.sin(thetas)*np.cos(phis), fac*np.sin(thetas)*np.sin(phis), fac*np.cos(thetas) mesh_xs, mesh_ys = (thetas*np.cos(phis)-.7, thetas*np.sin(phis)*ba-.7) triangles = mtri.Triangulation(mesh_xs, mesh_ys).triangles fac = 0.3 triangs = mtri.Triangulation(fac*xs-.7, fac*ba*ys-.7, triangles) collec = ax.plot_trisurf(triangs, fac*ca*zs-.9, color=sns.color_palette()[0],shade=True, linewidth=0.1,zorder=1) ax.view_init(28,-62) ax.dist=7. ## ======================================================================= ## 5. Plot contours of constant observed ellipticity -- note we need to ## mask out those behind the sphere ae = ax.azim,ax.elev ae = np.deg2rad(ae) ae[1] = np.pi/2.-ae[1] ae[0] = ae[0]-np.pi def dotpp(Th,Ph): r = np.array([np.sin(ae[1])*np.cos(ae[0]),np.sin(ae[1])*np.sin(ae[0]),np.cos(ae[1])]) vv = np.array([np.sin(Th)*np.cos(Ph),np.sin(Th)*np.sin(Ph),np.cos(Th)]) return np.dot(r,vv) phi = np.reshape(phi[:-2],(n,m)) ellip_all = np.reshape(ellip_all[:-2],(n,m)) theta = np.reshape(theta[:-2],(n,m)) phi = phi[:,3*n/40:25*n/40] theta = theta[:,3*n/40:25*n/40] ellip_all = ellip_all[:,3*n/40:25*n/40] ## add contours C=cntr.Cntr(phi,theta,ellip_all) contour_list = [0.5,0.6,0.7,0.8,0.9] def plot_contour(th,ph): doo = np.array(map(lambda t,p:dotpp(t,p),th,ph)) th = th[doo>0.] ph = ph[doo>0.] fac = 1. x,y,z = fac*np.sin(th)*np.cos(ph-np.pi), fac*np.sin(th)*np.sin(ph-np.pi), fac*np.cos(th) ax.plot(x,y,z,color='k',zorder=1,lw=0.5) for cc in contour_list: res = C.trace(cc) nseg = len(res) // 2 segs, codes = res[:nseg], res[nseg:] ss = segs[0] ss = res[0] for j in ss: th,ph=ss.T[1],ss.T[0] plot_contour(th,ph) plot_contour(np.pi-th,ph) plot_contour(th,np.pi-ph) plot_contour(np.pi-th,np.pi-ph) # plot_contour(th,ph+np.pi) plot_contour(np.pi-th,ph+np.pi) plot_contour(th,2.*np.pi-ph) plot_contour(np.pi-th,2.*np.pi-ph) th,ph = np.pi/2.-0.03,-np.pi/2.-0.3 ax.text3D(np.sin(th)*np.cos(ph),np.sin(th)*np.cos(ph),np.cos(th),r'$e=0.5$',zdir=np.array([-np.sin(ph),np.cos(ph),0.1]),fontsize=6,color='k') th,ph = np.pi/2.-0.4,-np.pi/2.-0.3 ax.text3D(np.sin(th)*np.cos(ph),np.sin(th)*np.cos(ph),np.cos(th),r'$e=0.4$',zdir=np.array([-np.sin(ph),np.cos(ph),0.]),fontsize=6,color='k') th,ph = np.pi/2.-0.68,-np.pi/2.-0.1 ax.text3D(np.sin(th)*np.cos(ph),np.sin(th)*np.cos(ph),np.cos(th),r'$e=0.3$',zdir=np.array([-np.sin(ph),np.cos(ph),-0.65]),fontsize=6,color='k') th,ph = np.pi/2.-0.6,-np.pi/2.+0.22 ax.text3D(np.sin(th)*np.cos(ph),np.sin(th)*np.cos(ph),np.cos(th),r'$e=0.2$',zdir=np.array([-np.sin(ph),np.cos(ph),-1.85]),fontsize=6,color='k') th,ph = np.pi/2.-0.5,-np.pi/2.+0.36 ax.text3D(np.sin(th)*np.cos(ph),np.sin(th)*np.cos(ph),np.cos(th),r'$e=0.1$',zdir=np.array([-np.sin(ph),np.cos(ph),-1.8]),fontsize=6,color='k') plt.savefig(outfile,bbox_inches='tight',dpi=1000)
#z1 = np.average(points[:, :, 1], axis=1) #ravg = np.average(np.sqrt((points[:, :, 0] - R1[0])**2 + (points[:, :, 1] - z1[0])**2), axis=1) #q = eqh.rhopol_to_q(t, rhos)['q'] #r2q = interp1d(ravg, q, bounds_error=False, fill_value=np.nan) #def dqdr(x, h=0.0001): # return (r2q(x+h)-r2q(x-h))/(2*h) #s = ravg/q * dqdr(ravg) rhomat = np.sqrt((pfm - psiAx[tidx])/(psiSep[tidx]-psiAx[tidx])) if 'rhomid' not in globals(): rhomid = np.zeros((trange.size,R.size)) smid = np.zeros((trange.size,R.size)) tmp = interp2d(R,z,sl) Rnew,znew = np.meshgrid(R,z) c = _cntr.Cntr(Rnew, znew, rhomat) #THIS IS TO CALCUALTE S_L(THETA) FOR DISTINCT RHOS /NOT NEEDED FOR 2D PLOT trace = c.trace(0.98)[1] s98[ti,:trace.shape[0]] = np.array([tmp(trace[i,0], trace[i,1]) for i in range(len(trace))]).flatten() theta98[ti,:trace.shape[0]] = np.array([np.arctan2(trace[i,1] - zmag, trace[i,0] - Rmag) for i in range(len(trace))])/np.pi*180 trace = c.trace(0.985)[1] s985[ti,:trace.shape[0]] = np.array([tmp(trace[i,0], trace[i,1]) for i in range(len(trace))]).flatten() theta985[ti,:trace.shape[0]] = np.array([np.arctan2(trace[i,1] - zmag, trace[i,0] - Rmag) for i in range(len(trace))])/np.pi*180 trace = c.trace(0.99)[1] s99[ti,:trace.shape[0]] = np.array([tmp(trace[i,0], trace[i,1]) for i in range(len(trace))]).flatten() theta99[ti,:trace.shape[0]] = np.array([np.arctan2(trace[i,1] - zmag, trace[i,0] - Rmag) for i in range(len(trace))])/np.pi*180
def pfr_lines(self, inp, R, Z, core): num_lines = int( len(cntr.Cntr(R, Z, core.psi_norm_raw).trace(0.99)) / 2) if num_lines == 1: #then we're definitely dealing with a surface inside the seperatrix print 'Did not find PFR flux surface. Stopping.' sys.exit() else: #we need to find the surface that is contained within the private flux region for j, line in enumerate( cntr.Cntr(R, Z, core.psi_norm_raw).trace(0.99)[:num_lines]): #for j, line in enumerate(cntr.Cntr(R, Z, self.psi_norm_raw).trace(v)): x, y = draw_line(R, Z, core.psi_norm_raw, 0.99, j) if (np.amax(y) < np.amin(core.main_sep_pts[:, 1])): #then it's a pfr flux surface, might need to add additional checks later pfr_line_raw = LineString(np.column_stack((x, y))) #find cut points cut_pt1 = pfr_line_raw.intersection(inp.wall_line)[0] dist1 = pfr_line_raw.project(cut_pt1, normalized=True) cutline_temp = cut(pfr_line_raw, dist1)[1] #reverse line point order so we can reliably find the second intersection point cutline_temp_rev = LineString( np.flipud(np.asarray(cutline_temp.xy).T)) cut_pt2 = cutline_temp_rev.intersection(inp.wall_line) dist2 = cutline_temp_rev.project(cut_pt2, normalized=True) cutline_final_rev = cut(cutline_temp_rev, dist2)[1] #reverse again for final pfr flux line pfr_flux_line = LineString( np.flipud(np.asarray(cutline_final_rev.xy).T)) #add pfr_line intersection points on inboard side #for some reason, union freaks out when I try to do inboard and outboard #at the same time. union = inp.wall_line.union(cut(pfr_line_raw, 0.5)[0]) result = [geom for geom in polygonize(union)][0] inp.wall_line = LineString(result.exterior.coords) #add pfr line intersection points on outboard side union = inp.wall_line.union(cut(pfr_line_raw, 0.5)[1]) result = [geom for geom in polygonize(union)][0] inp.wall_line = LineString(result.exterior.coords) #cut out pfr section of wall line wall_pts = np.asarray(inp.wall_line.xy).T #ib_int_pt = np.asarray(self.ib_div_line.intersection(inp.wall_line).xy).T #ob_int_pt = self.ob_div_line.intersection(inp.wall_line) wall_start_pos = np.where( (wall_pts == cut_pt2).all(axis=1))[0][0] wall_line_rolled = LineString( np.roll(wall_pts, -wall_start_pos, axis=0)) wall_line_cut_pfr = cut( wall_line_rolled, wall_line_rolled.project(cut_pt1, normalized=True))[0] #create LineString with pfr line and section of wall line self.pfr_line = linemerge( (pfr_flux_line, wall_line_cut_pfr)) break
def __init__(self, ax, *args, **kwargs): """ Draw contour lines or filled regions, depending on whether keyword arg 'filled' is False (default) or True. The first argument of the initializer must be an axes object. The remaining arguments and keyword arguments are described in ContourSet.contour_doc. """ self.ax = ax self.levels = kwargs.get('levels', None) self.filled = kwargs.get('filled', False) self.linewidths = kwargs.get('linewidths', None) self.linestyles = kwargs.get('linestyles', None) self.alpha = kwargs.get('alpha', 1.0) self.origin = kwargs.get('origin', None) self.extent = kwargs.get('extent', None) cmap = kwargs.get('cmap', None) self.colors = kwargs.get('colors', None) norm = kwargs.get('norm', None) self.extend = kwargs.get('extend', 'neither') self.antialiased = kwargs.get('antialiased', True) self.nchunk = kwargs.get('nchunk', 0) self.locator = kwargs.get('locator', None) if (isinstance(norm, colors.LogNorm) or isinstance(self.locator, ticker.LogLocator)): self.logscale = True if norm is None: norm = colors.LogNorm() if self.extend is not 'neither': raise ValueError( 'extend kwarg does not work yet with log scale') else: self.logscale = False if self.origin is not None: assert (self.origin in ['lower', 'upper', 'image']) if self.extent is not None: assert (len(self.extent) == 4) if cmap is not None: assert (isinstance(cmap, colors.Colormap)) if self.colors is not None and cmap is not None: raise ValueError('Either colors or cmap must be None') if self.origin == 'image': self.origin = mpl.rcParams['image.origin'] if isinstance(args[0], ContourSet): C = args[0].Cntr if self.levels is None: self.levels = args[0].levels else: x, y, z = self._contour_args(*args) x0 = ma.minimum(x) x1 = ma.maximum(x) y0 = ma.minimum(y) y1 = ma.maximum(y) self.ax.update_datalim([(x0, y0), (x1, y1)]) self.ax.autoscale_view() _mask = ma.getmask(z) if _mask is ma.nomask: _mask = None C = _cntr.Cntr(x, y, z.filled(), _mask) self.Cntr = C self._process_levels() if self.colors is not None: cmap = colors.ListedColormap(self.colors, N=len(self.layers)) if self.filled: self.collections = cbook.silent_list('collections.PathCollection') else: self.collections = cbook.silent_list('collections.LineCollection') # label lists must be initialized here self.labelTexts = [] self.labelCValues = [] kw = {'cmap': cmap} if norm is not None: kw['norm'] = norm cm.ScalarMappable.__init__(self, **kw) # sets self.cmap; self._process_colors() if self.filled: if self.linewidths is not None: warnings.warn('linewidths is ignored by contourf') lowers = self._levels[:-1] uppers = self._levels[1:] for level, level_upper in zip(lowers, uppers): nlist = C.trace(level, level_upper, nchunk=self.nchunk) nseg = len(nlist) // 2 segs = nlist[:nseg] kinds = nlist[nseg:] paths = self._make_paths(segs, kinds) col = collections.PathCollection( paths, antialiaseds=(self.antialiased, ), edgecolors='none', alpha=self.alpha) self.ax.add_collection(col) self.collections.append(col) else: tlinewidths = self._process_linewidths() self.tlinewidths = tlinewidths tlinestyles = self._process_linestyles() for level, width, lstyle in zip(self.levels, tlinewidths, tlinestyles): nlist = C.trace(level) nseg = len(nlist) // 2 segs = nlist[:nseg] #kinds = nlist[nseg:] col = collections.LineCollection(segs, linewidths=width, linestyle=lstyle, alpha=self.alpha) col.set_label('_nolegend_') self.ax.add_collection(col, False) self.collections.append(col) self.changed() # set the colors
def DEMOTEDcreateObjIndicatorMatrix(objid,PLOT=False,sampleNworkers=-1,PRINT=False,EXCLUDE_BBG=True,overlap_threshold=0.5): # Ji_tbl (bb_info) is the set of all workers that annotated object i bb_objects = bb_info[bb_info["object_id"]==objid] if EXCLUDE_BBG: bb_objects = bb_objects[bb_objects.worker_id!=3] # Sampling Data from Ji table if sampleNworkers>0 and sampleNworkers<len(bb_objects): bb_objects = bb_objects.sample(n=sampleNworkers)#,random_state=111) # Create a masked image for the object # where each of the worker BB is considered a mask and overlaid on top of each other img_name = img_info[img_info.id==int(object_tbl[object_tbl.id==objid]["image_id"])]["filename"].iloc[0] fname = "../../web-app/app/static/"+img_name+".png" img=mpimg.imread(fname) width,height = get_size(fname) mega_mask = np.zeros((height,width)) obj_x_locs = [process_raw_locs([x,y])[0] for x,y in zip(bb_objects["x_locs"],bb_objects["y_locs"])] obj_y_locs = [process_raw_locs([x,y])[1] for x,y in zip(bb_objects["x_locs"],bb_objects["y_locs"])] for x_locs, y_locs in zip(obj_x_locs,obj_y_locs): img = Image.new('L', (width, height), 0) ImageDraw.Draw(img).polygon(zip(x_locs,y_locs), outline=1, fill=1) mask = np.array(img)==1 # plt.imshow(mask) mega_mask+=mask if PLOT: # Visualize mega_mask plt.figure() plt.imshow(mega_mask,interpolation="none")#,cmap="rainbow") plt.colorbar() # Create masks for single valued tiles (so that they are more disconnected) from matplotlib import _cntr as cntr tiles = [] # list of coordinates of all the tiles extracted unique_tile_values = np.unique(mega_mask) # print unique_tile_values for tile_value in unique_tile_values[1:]: #exclude 0 singly_masked_img = np.zeros_like(mega_mask) for x,y in zip(*np.where(mega_mask==tile_value)): singly_masked_img[x][y]=1 #Extract a set of contours from these masks x, y = np.mgrid[:singly_masked_img.shape[0], :singly_masked_img.shape[1]] c = cntr.Cntr(x, y, singly_masked_img) # trace a contour at z ~= 1 res = c.trace(0.9) #if PLOT: plot_trace_contours(singly_masked_img,res) for segment in res: if segment.dtype!=np.uint8 and len(segment)>2: #Take the transpose of the tile graph polygon because during the tile creation process the xy was flipped tile= Polygon(zip(segment[:,1],segment[:,0])) # print tile.area # if tile.area>=1: #FOR DEBUGGING PURPOSES tiles.append(segment) # Convert set of tiles to indicator matrix for all workers and tiles # by checking if the worker's BB contains the tile pieces # The indicator matrix is a (N + 1) X M matrix, # with first N rows indicator vectors for each annotator and # the last row being region sizes M = len(tiles) worker_lst = list(bb_objects.worker_id) N = len(worker_lst) if PRINT: print "Number of non-overlapping tile regions (M) : ",M print "Number of workers (N) : ",N indicator_matrix = np.zeros((N+1,M),dtype=int) for wi in range(N): worker_id = worker_lst[wi] worker_bb_info = bb_objects[bb_objects["worker_id"]==worker_id] worker_BB_polygon = Polygon(zip(*process_raw_locs([worker_bb_info["x_locs"].values[0],worker_bb_info["y_locs"].values[0]]))).buffer(0) # Check if worker's polygon contains this tile for tile_i in range(M): # tile = Polygon(tiles[tile_i]) tile= Polygon(zip(tiles[tile_i][:,1],tiles[tile_i][:,0])) # Check that tiles are indeed close to BB (no mis-alignment issue) # if PLOT and tile_i==0: # plt.figure() # plot_coords(tile) # plot_coords(worker_BB_polygon,color="blue") # if worker_BB_polygon.contains(tile): #or tile.contains(worker_BB_polygon): # Tried worker_BB_polygon expansion method but this led to too many votes among workers in the indicator matrix # worker_BB_polygon= worker_BB_polygon.buffer(1.0) tileBB_overlap = tile.intersection(worker_BB_polygon).area/float(tile.area) #If either centroid is not contained in the polygon or overlap is too low, then its prob not a containment tile # if tileBB_overlap>=0.8: if worker_BB_polygon.contains(tile.centroid) or tileBB_overlap>=overlap_threshold: #if worker_BB_polygon.contains(tile.centroid): #or tile.contains(worker_BB_polygon): # plt.figure() # plot_coords(worker_BB_polygon,color="green") # plot_coords(tile,color="blue") # y,x =tile.centroid.xy # plt.plot(x[0],y[0],'x',color='red') indicator_matrix[wi][tile_i]=1 # The last row of the indicator matrix is the tile area for tile_i in range(M): tile= Polygon(zip(tiles[tile_i][:,1],tiles[tile_i][:,0])) indicator_matrix[-1][tile_i]=tile.area # Debug plotting all tiles that have not been voted by workers all_unvoted_tiles=np.where(np.sum(indicator_matrix[:-1],axis=0)==0)[0] if PRINT: print "all unvoted tiles:",all_unvoted_tiles print "all unvoted workers:",np.where(np.sum(indicator_matrix,axis=1)==0)[0] # delete_tile_idx = np.where(np.sum(indicator_matrix[:-1],axis=0)==0)[0] # if PRINT: print "Deleting ", len(delete_tile_idx),"tiles: ",delete_tile_idx # indicator_matrix = np.delete(indicator_matrix,delete_tile_idx,axis=1) # for tile_i in delete_tile_idx: # tile= Polygon(tiles[tile_i]) # plot_coords(tile) # # print "Tile",tile_i # # print tile.intersection(worker_BB_polygon).area # # print worker_BB_polygon.intersection(tile).area # # print float(tile.area) # print tile.area # tiles.pop(tile_i) #remove corresponding tile information # colors=cm.rainbow(np.linspace(0,1,len(np.where(np.sum(indicator_matrix[:-1],axis=0)==0)[0]))) # Debug Visualizing what the bad bounding boxes look like # os.chdir("..") # visualize_bb_objects(objid,img_bkgrnd=False,gtypes=['worker']) # os.chdir("TileEM/") # for tile_idx,c in zip(all_unvoted_tiles,colors): # plt.plot(tiles[tile_idx][:,1],tiles[tile_idx][:,0],color=c,linewidth=3,linestyle='--') # bad_tile = Polygon(tiles[tile_idx]) # shrunk_bad_tile=bad_tile.buffer(-0.5) # plot_coords(shrunk_bad_tile) # if len(all_unvoted_tiles)!=0: # for tile_idx in all_unvoted_tiles : # tile = Polygon(zip(tiles[tile_idx][:,1],tiles[tile_idx][:,0])) # overlap_lst=[] # max_overlap=True # for wi in range(len(worker_lst)): # worker_id = worker_lst[wi] # worker_bb_info = bb_objects[bb_objects["worker_id"]==worker_id] # worker_BB_polygon = Polygon(zip(*process_raw_locs([worker_bb_info["x_locs"].values[0],worker_bb_info["y_locs"].values[0]]))).buffer(0) # tileBB_overlap = tile.intersection(worker_BB_polygon).area/float(tile.area) # overlap_lst.append(tileBB_overlap) # if tileBB_overlap>0.9: # indicator_matrix[wi][tile_idx]=1 # max_overlap=False # if max_overlap: # most_overlapping_workerBB = np.argmax(overlap_lst) # indicator_matrix[most_overlapping_workerBB][tile_idx]=1 # # #visually checking that tiles that don't pass the threshold and we pick from max overlap is decent # worker_bb_info = bb_objects[bb_objects["worker_id"]==worker_lst[most_overlapping_workerBB]] # worker_BB_polygon = Polygon(zip(*process_raw_locs([worker_bb_info["x_locs"].values[0],worker_bb_info["y_locs"].values[0]]))).buffer(0) # # plt.figure() # # plt.title(str(overlap_lst[most_overlapping_workerBB])) # # plot_coords(tile) # # plot_coords(worker_BB_polygon,color="blue") # for wi in np.where(np.sum(indicator_matrix,axis=1)==0)[0]: # worker_id = worker_lst[wi] # worker_bb_info = bb_objects[bb_objects["worker_id"]==worker_id] # worker_BB_polygon = Polygon(zip(*process_raw_locs([worker_bb_info["x_locs"].values[0],worker_bb_info["y_locs"].values[0]]))).buffer(0) # for tile_idx in range(len(tiles)): # tile = Polygon(zip(tiles[tile_idx][:,1],tiles[tile_idx][:,0])) # tileBB_overlap = tile.intersection(worker_BB_polygon).area/float(tile.area) # if tileBB_overlap>0.9: # indicator_matrix[wi][tile_idx]=1 # # plt.figure() # # # plt.title(str(overlap_lst[most_overlapping_workerBB])) # # plt.title(str(tileBB_overlap)) # # plot_coords(tile) # # plot_coords(worker_BB_polygon,color="blue") # if PRINT: # print "After overlap adding" # print "all unvoted tiles:",np.where(np.sum(indicator_matrix[:-1],axis=0)==0)[0] # print "all unvoted workers:",np.where(np.sum(indicator_matrix,axis=1)==0)[0] # #for all the workers with all-zero rows # for wi in np.where(np.sum(indicator_matrix,axis=1)==0)[0]: # worker_id = worker_lst[wi] # worker_bb_info = bb_objects[bb_objects["worker_id"]==worker_id] # worker_BB_polygon = Polygon(zip(*process_raw_locs([worker_bb_info["x_locs"].values[0],worker_bb_info["y_locs"].values[0]]))) # dist_lst = [] # if len(np.where(np.sum(indicator_matrix[:-1],axis=0)==0)[0])==0: # tile_candidates= range(len(tiles)) # else: # tile_candidates=np.where(np.sum(indicator_matrix[:-1],axis=0)==0)[0] # # for tile_i in range(len(tiles)): # # Pick from the tiles that have not yet been voted by any worker yet # for tile_i in tile_candidates: # #Take the transpose of the tile graph polygon because during the tile creation process the xy was flipped # tile = Polygon(zip(tiles[tile_i][:,1],tiles[tile_i][:,0])) # #Find the closest tile that corresponds to that worker # dist_lst.append(worker_BB_polygon.distance(tile)) # argmin_dist_idx = np.where(dist_lst==min(np.array(dist_lst)))[0] # for min_dist_idx in argmin_dist_idx: # indicator_matrix[wi][tile_i]=1 # # Throw out all tiles that have not yet been voted by any worker # try: # delete_tile_idx = np.where(np.sum(indicator_matrix[:-1],axis=0)==0)[0] # if PRINT: print "Deleting ", len(delete_tile_idx),"tiles: ",delete_tile_idx # indicator_matrix = np.delete(indicator_matrix,delete_tile_idx,axis=1) # for _i in delete_tile_idx: tiles.pop(_i) #remove corresponding tile information # except(IndexError): # print "IndexError" # pass if PLOT or PRINT: print "Object ",objid sanity_check(indicator_matrix,PLOT) return tiles,indicator_matrix
hlims = [np.amin(z), np.amax(z)] hrange = np.ptp(z) cint = max(PREF_INTERVALS) layers = int(np.ceil(hrange / cint)) for try_i in PREF_INTERVALS: try_layers = int(np.ceil(hrange / try_i)) if try_layers > layers and try_layers < DEF_MAX_LAYERS: cint = try_i layers = try_layers print('{} layers. {}m interval'.format(layers, cint)) cheights = np.arange( np.floor(hlims[0] / cint) * cint, np.ceil(hlims[1] / cint) * cint, cint) #Generate contours contourdata = cntr.Cntr(hdata.x, hdata.y, z) cvs = pyx.canvas.canvas() cvs.text(0, 0, "Hello, world!") cvs.stroke(pyx.path.line(0, 0, 2, 0)) for cheight in cheights: clist = contourdata.trace(cheight, cheight, 0) clist = clist[:len(clist) // 2] print('Level {}m, {} contours'.format(cheight, len(clist))) for contour in clist: contour = contour * SCALE path = [pyx.path.moveto(*contour[0]) ] + [pyx.path.lineto(*c) for c in contour[1:]] cvs.stroke(pyx.path.path(*path))
def core_nT_ntrl(self, inp, R, Z, psi): #CREATE ARRAYS OF POINTS, DENSITIES AND TEMPERATURES FOR THE NEUTRALS CALCULATION #Master arrays that will contain all the points we'll use to get n, T #throughout the plasma chamber via 2-D interpolation self.ni_pts = np.zeros((0, 3), dtype='float') self.ne_pts = np.zeros((0, 3), dtype='float') self.Ti_kev_pts = np.zeros((0, 3), dtype='float') self.Te_kev_pts = np.zeros((0, 3), dtype='float') ########################################## #Calculate n, T throughout the core plasma using radial profile input files, uniform on flux surface ni = UnivariateSpline(inp.ni_data[:, 0], inp.ni_data[:, 1], k=5, s=2.0) ne = UnivariateSpline(inp.ne_data[:, 0], inp.ne_data[:, 1], k=5, s=2.0) Ti_kev = UnivariateSpline(inp.Ti_data[:, 0], inp.Ti_data[:, 1], k=5, s=2.0) Te_kev = UnivariateSpline(inp.Te_data[:, 0], inp.Te_data[:, 1], k=5, s=2.0) #get approximate rho values associated with the psi values we're using #draw line between magnetic axis and the seperatrix at the outboard midplane rho_line = LineString([Point(self.m_axis), Point(self.obmp_pt)]) rho_pts = np.concatenate((np.linspace(0, 0.95, 20, endpoint=False), np.linspace(0.95, 1, 50, endpoint=False)), axis=0) thetapts = np.linspace(0, 1, 100, endpoint=False) for i, rho in enumerate(rho_pts): #get n, T information at the point by interpolating the rho-based input file data ni_val = ni(rho) ne_val = ne(rho) Ti_kev_val = Ti_kev(rho) Te_kev_val = Te_kev(rho) #get R, Z coordinates of each point along the rho_line pt_coords = np.asarray( rho_line.interpolate(rho, normalized=True).coords)[0] #get psi value at that point psi_val = griddata(np.column_stack((R.flatten(), Z.flatten())), self.psi_norm_raw.flatten(), pt_coords, method='linear') #map this n, T data to every point on the corresponding flux surface num_lines = int( len(cntr.Cntr(R, Z, self.psi_norm_raw).trace(psi_val)) / 2) if num_lines == 1: #then we're definitely dealing with a surface inside the seperatrix x, y = draw_contour_line(R, Z, self.psi_norm_raw, psi_val, 0) surf = LineString(np.column_stack((x, y))) else: #we need to find which of the surfaces is inside the seperatrix for j, line in enumerate( cntr.Cntr( R, Z, self.psi_norm_raw).trace(psi_val)[:num_lines]): #for j, line in enumerate(cntr.Cntr(R, Z, self.psi_norm_raw).trace(v)): x, y = draw_contour_line(R, Z, self.psi_norm_raw, psi_val, j) if (np.amax(x) < np.amax(self.main_sep_pts[:, 0]) and \ np.amin(x) > np.amin(self.main_sep_pts[:, 0]) and \ np.amax(y) < np.amax(self.main_sep_pts[:, 1]) and \ np.amin(y) > np.amin(self.main_sep_pts[:, 1])): #then it's an internal flux surface surf = LineString(np.column_stack((x, y))) break for j, theta_norm in enumerate(thetapts): pt = np.asarray( surf.interpolate(theta_norm, normalized=True).coords).T self.ni_pts = np.vstack((self.ni_pts, np.append(pt, ni_val))) self.ne_pts = np.vstack((self.ne_pts, np.append(pt, ne_val))) self.Ti_kev_pts = np.vstack( (self.Ti_kev_pts, np.append(pt, Ti_kev_val))) self.Te_kev_pts = np.vstack( (self.Te_kev_pts, np.append(pt, Te_kev_val))) #Do seperatrix separately so we don't accidentally assign the input n, T data to the divertor legs self.ni_sep_val = ni(1.0) self.ne_sep_val = ne(1.0) self.Ti_kev_sep_val = Ti_kev(1.0) self.Te_kev_sep_val = Te_kev(1.0) self.Ti_J_sep_val = self.Ti_kev_sep_val * 1.0E3 * 1.6021E-19 self.Te_J_sep_val = self.Te_kev_sep_val * 1.0E3 * 1.6021E-19 for j, theta_norm in enumerate(thetapts): pt = np.asarray(self.main_sep_line.interpolate( theta_norm, normalized=False).coords, dtype='float').T self.ni_pts = np.vstack( (self.ni_pts, np.append(pt, self.ni_sep_val))) self.ne_pts = np.vstack( (self.ne_pts, np.append(pt, self.ne_sep_val))) self.Ti_kev_pts = np.vstack( (self.Ti_kev_pts, np.append(pt, self.Ti_kev_sep_val))) self.Te_kev_pts = np.vstack( (self.Te_kev_pts, np.append(pt, self.Te_kev_sep_val)))
def rho2rz(self, rho_in, t_in=None, coord_in='rho_pol', all_lines=False): """Get R, Z coordinates of a flux surfaces contours Input ---------- t_in : float or 1darray time rho_in : 1darray,float rho coordinates of the searched flux surfaces coord_in: str mapped coordinates - rho_pol or rho_tor all_lines: bool: True - return all countours , False - return longest contour Output ------- rho : array of lists of arrays [npoinst,2] list of times containg list of surfaces for different rho and every surface is decribed by 2d array [R,Z] """ if not self.eq_open: return if t_in is None: t_in = self.t_eq tarr = np.atleast_1d(t_in) rhoin = np.atleast_1d(rho_in) self._read_pfm() self._read_scalars() rho_in = self.rho2rho(rhoin, t_in=t_in, \ coord_in=coord_in, coord_out='Psi', extrapolate=True ) try: import matplotlib._cntr as cntr except: #slower option import matplotlib._contour as _contour nr = len(self.Rmesh) nz = len(self.Zmesh) R, Z = np.meshgrid(self.Rmesh, self.Zmesh) Rsurf = np.empty(len(tarr), dtype='object') zsurf = np.empty(len(tarr), dtype='object') unique_idx, idx = self._get_nearest_index(tarr) for i in unique_idx: jt = np.where(idx == i)[0] Flux = rho_in[jt[0]] # matplotlib's contour creation try: c = cntr.Cntr(R, Z, self.pfm[i].T) except: #slower option gen = _contour.QuadContourGenerator(R, Z, self.pfm[i].T, np.bool_(Z * 0), False, 0) Rs_t = [] zs_t = [] for jfl, fl in enumerate(Flux): try: nlist = c.trace(level0=fl, level1=fl, nchunk=0) nlist = nlist[:len(nlist) / 2] except: #slower option nlist = gen.create_contour(fl) j_ctrs = len(nlist) if j_ctrs == 0: if fl == self.psi0[i]: Rs_t.append(np.atleast_1d(self.ssq['Rmag'][i])) zs_t.append(np.atleast_1d(self.ssq['Zmag'][i])) else: Rs_t.append(np.zeros(1)) zs_t.append(np.zeros(1)) continue elif all_lines: # for open field lines line = np.vstack([ np.vstack(((np.nan, ) * 2, l)) for l in nlist[:j_ctrs] ])[1:] else: #longest filed line line = [] for l in nlist[:j_ctrs]: if len(l) > len(line): line = l R_surf, z_surf = list(zip(*line)) R_surf = np.array(R_surf, dtype=np.float32) z_surf = np.array(z_surf, dtype=np.float32) if not all_lines: ind = (z_surf >= self.ssq['Zunt'][i]) if len(ind) > 1: R_surf = R_surf[ind] z_surf = z_surf[ind] Rs_t.append(R_surf) zs_t.append(z_surf) for j in jt: Rsurf[j] = Rs_t zsurf[j] = zs_t return Rsurf, zsurf
def OnPaint(self, evt): """Update the panel when it needs to be refreshed.""" # Bind motion event when the panel has been painted to avoid a blank # image on Windows if a file is loaded too quickly before the plugin # is initialized self.Bind(wx.EVT_MOTION, self.OnMouseMotion) # Special case for Windows to account for flickering # if and only if images are loaded if (guiutil.IsMSWindows() and len(self.images)): dc = wx.BufferedPaintDC(self) self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM) else: dc = wx.PaintDC(self) width, height = self.GetClientSize() try: gc = wx.GraphicsContext.Create(dc) except NotImplementedError: dc.DrawText( "This build of wxPython does not support the " "wx.GraphicsContext family of classes.", 25, 25) return # If we have images loaded, process and show the image if len(self.images): # Save the original drawing state gc.PushState() # Scale the image by the zoom factor gc.Scale(self.zoom, self.zoom) # Redraw the background on Windows if guiutil.IsMSWindows(): gc.SetBrush(wx.Brush(wx.Colour(0, 0, 0))) gc.SetPen(wx.Pen(wx.Colour(0, 0, 0))) gc.DrawRectangle(0, 0, width, height) image = guiutil.convert_pil_to_wx( self.images[self.imagenum - 1].GetImage( self.window, self.level)) bmp = wx.Bitmap(image) self.bwidth, self.bheight = image.GetSize() # Center the image transx = self.pan[0] + (width - self.bwidth * self.zoom) / (2 * self.zoom) transy = self.pan[1] + (height - self.bheight * self.zoom) / (2 * self.zoom) gc.Translate(transx, transy) gc.DrawBitmap(bmp, 0, 0, self.bwidth, self.bheight) gc.SetBrush(wx.Brush(wx.Colour(0, 0, 255, 30))) gc.SetPen(wx.Pen(wx.Colour(0, 0, 255, 30))) # Draw the structures if present imdata = self.images[self.imagenum - 1].GetImageData() self.z = '%.2f' % imdata['position'][2] # Determine whether the patient is prone or supine if 'p' in imdata['patientposition'].lower(): prone = True else: prone = False # Determine whether the patient is feet first or head first if 'ff' in imdata['patientposition'].lower(): feetfirst = True else: feetfirst = False for id, structure in self.structures.items(): self.DrawStructure(structure, gc, self.z, prone, feetfirst) # Draw the isodoses if present if len(self.isodoses): grid = self.dose.GetDoseGrid(float(self.z)) if not (grid == []): x, y = np.meshgrid(np.arange(grid.shape[1]), np.arange(grid.shape[0])) # Instantiate the isodose generator for this slice isodosegen = cntr.Cntr(x, y, grid) for id, isodose in iter(sorted(self.isodoses.items())): self.DrawIsodose(isodose, gc, isodosegen) # Restore the translation and scaling gc.PopState() # Prepare the font for drawing the information text font = wx.SystemSettings.GetFont(wx.SYS_DEFAULT_GUI_FONT) if guiutil.IsMac(): font.SetPointSize(10) gc.SetFont(font, wx.WHITE) # Draw the information text imtext = "Image: " + str(self.imagenum) + "/" + str( len(self.images)) te = gc.GetFullTextExtent(imtext) gc.DrawText(imtext, 10, 7) impos = "Position: " + str(self.z) + " mm" gc.DrawText(impos, 10, 7 + te[1] * 1.1) if ("%.3f" % self.zoom == "1.000"): zoom = "1" else: zoom = "%.3f" % self.zoom imzoom = "Zoom: " + zoom + ":1" gc.DrawText(imzoom, 10, height - 17) imsize = "Image Size: " + str(self.bheight) + "x" + str( self.bwidth) + " px" gc.DrawText(imsize, 10, height - 17 - te[1] * 1.1) imwinlevel = "W/L: " + str(self.window) + ' / ' + str(self.level) te = gc.GetFullTextExtent(imwinlevel) gc.DrawText(imwinlevel, width - te[0] - 7, 7) impatpos = "Patient Position: " + imdata['patientposition'] te = gc.GetFullTextExtent(impatpos) gc.DrawText(impatpos, width - te[0] - 7, height - 17) # Send message with the current image number and various properties pub.sendMessage( '2dview.updated.image', msg={ 'number': self.imagenum, # slice number 'z': self.z, # slice location 'window': self.window, # current window value 'level': self.level, # curent level value 'gc': gc, # wx.GraphicsContext 'scale': self.zoom, # current zoom level 'transx': transx, # current x translation 'transy': transy, # current y translation 'imdata': imdata, # image data dictionary 'patientpixlut': self.structurepixlut })