def hvplot(self, ptype="shape"): """ Plots the shape (Notices, it requries holoviews) Parameters ---------- :param ptype str: Plot type. The following are excepted: "shape": Plots the shape-edges with equal aspect-ratio "vectors": Plots shape-edges, as well as panel-centers and tangential and normal vectors. """ try: import holoviews as hv except ImportError: raise ImportError( "To use the plot method holoviews is requried, see more here: http://holoviews.org/" ) if ptype == "shape": # Shape of airfoil (edges) return hv.Curve(self.xy).opts(aspect='equal', width=1000, height=500, padding=0.1) elif ptype == "vectors": # Vectors at panel centeres pc = hv.Scatter(np.array([self.px, self.py]).T, kdims="px", vdims="py").opts(size=5) vf = hv.VectorField(np.array( [self.px, self.py, np.angle(self.tan), np.abs(self.tan)]).T, label="Tangent") vf.opts(rescale_lengths=False, magnitude=hv.dim('Magnitude') * 0.01 * self.scale, pivot="tail") vfnor = hv.VectorField(np.array( [self.px, self.py, np.angle(self.nor), np.abs(self.nor)]).T, label="Normal") vfnor.opts(rescale_lengths=False, magnitude=hv.dim('Magnitude') * 0.01 * self.scale, pivot="tail", color="red") # , label="Normal") return self.plot("shape") * pc * vf * vfnor
def vectorfield(self, tap=True): """Show gradients as a `hv.VectorField` object""" if self._vectorfield is None: vf_list = [] for sel_one2D in self.combine_all: peak2D = self.peak.sel(sel_one2D) style = self._get_style(peak2D) vf_list.append( hv.VectorField( peak2D, vdims=['angle', 'weight'], kdims=['xtrack', 'atrack'], ).opts(pivot='mid', arrow_heads=False, magnitude='weight', aspect='equal', **style)) # manual legend, to have a style per dimension legends = [] dummy_line = [(0, 0), (0.01, 0)] for st in self.styles_names: label = self.peak[st].dims[0] for item in self.peak[st]: style = { 'line_dash': 'solid', 'line_width': 1, 'line_color': 'k' } style.update({st: item.item()}) legends.append( hv.Curve(dummy_line, label="%s %s" % (label, item[label].item())).redim.label( x='xtrack', y='atrack').opts(**style)) self._vectorfield = hv.Overlay(vf_list + legends).opts( active_tools=['wheel_zoom', 'pan']) if tap: atrack = self.peak.atrack.values[self.peak.atrack.size // 2] xtrack = self.peak.xtrack.values[self.peak.xtrack.size // 2] self._mouse_stream = hv.streams.Tap(x=xtrack, y=atrack, source=self._vectorfield) return self._vectorfield * hv.DynamicMap( self._get_windows, streams=[self._mouse_stream]) return self._vectorfield
def background(func, size=(500, 500)): """ Given the ODE y'=f(x,y), bg,vec,xaxis_line,yaxis_line = background() returns a grayscale image of the slopes y', a vector field representation of the slopes, and a set of axis lines for -5<x<5, -5<y<5 """ # compute the data vals = np.linspace(-5, 5, num=150) X, Y = np.meshgrid(vals, vals) clines = func(X, Y) # f(x,y) theta = np.arctan2(clines, 1) # angle of the slope y' at x,y # Obtain the vector field (subsample the grid) h, w = size vf_opts = dict(size_index=3, height=h, width=w, xticks=9, yticks=9, alpha=0.3, muted_alpha=0.05) vec_field = hv.VectorField( (vals[::3], vals[::3], theta[::3, ::3], 0 * clines[::3, ::3] + 1), label='vector_field').options(**vf_opts) # Normalize the given array so that it can be used with the RGB element's alpha channel def norm(arr): arr = (arr - arr.min()) return arr / arr.max() normXY = norm(clines) img_field = hv.RGB( (vals, vals, normXY, normXY, normXY, 0*clines+0.1), vdims=['R','G','B','A'] )\ .options(width=size[0], height=size[1], shared_axes=False) # finally, we add the axes as VLine, HLine and return an array of the plot Elements hv_opts = dict(color='k', alpha=0.8, line_width=1.5) return [ img_field, vec_field, hv.HLine(0).options(**hv_opts), hv.VLine(0).options(**hv_opts) ]
def field2inplane_vectorfield(field, slice_axis, slice_coord): """ field2hv(field, slice_axis, slice_coord) This function constructs a Holoviews object which shows the in plane Magnetisation and out of plane Magnetisation Inputs ====== field: Path to an OMF file or object of type discretisedfield.Field slice_axis: The axis along which the vector field will be sliced given as a string. Must be one of ['x', 'y', 'z'] slice_coord: The coordinate along the slice_axis where the field is sliced """ # Construct a field object if not a field object if isinstance(field, str): field = discretisedfield.read_oommf_file(field, normalisedto=1) field.normalise() if slice_axis == 'z': axis = (0, 1, 2) elif slice_axis == 'y': axis = (0, 2, 1) elif slice_axis == 'x': axis = (1, 2, 0) else: raise ValueError("Slice Axis must be one of 'x', 'y' ,'z'") dims = ['x', 'y', 'z'] x, y, vec, coords = field.slice_field(slice_axis, slice_coord) X, Y = np.meshgrid(x, y) flat = vec.flatten() modm = (flat[axis[0]::3]**2 + flat[axis[1]::3]**2).reshape( (len(x), len(y))) angm = np.arctan2(flat[axis[1]::3], flat[axis[0]::3]).reshape( (len(x), len(y))) kdims = kdims = [dims[axis[0]], dims[axis[1]]] return hv.VectorField([X, Y, angm, modm], kdims=kdims, vdims=['xyfield'], label='In-plane Magnetisation')
def reprojection_diff(isd, cube, nx=4, ny=8): """ """ hv.extension('bokeh') isdjson = json.load(open(isd)) nlines = isdjson['image_lines'] nsamples = isdjson['image_samples'] # generate meshgrid xs, ys = np.mgrid[0:nsamples:nsamples / nx, 0:nlines:nlines / ny] xs, ys = xs.flatten(), ys.flatten() csmcam = csm.create_csm(isd) # CS101 C++ programming class style dividers ############################## isis_pts = point_info(cube, xs, ys, 'image') isisgnds = np.asarray( [g[1]['BodyFixedCoordinate'].value for g in isis_pts]) csm_pts = np.asarray([[p.samp, p.line] for p in [ csmcam.groundToImage(csmapi.EcefCoord(*(np.asarray(bf) * 1000))) for bf in isisgnds ]]) isis2csm_diff = csm_pts - np.asarray([xs, ys]).T isis2csm_diffmag = np.linalg.norm(isis2csm_diff, axis=1) isis2csm_angles = np.arctan2(*isis2csm_diff.T[::-1]) data = np.asarray([ csm_pts.T[0], csm_pts.T[1], xs, ys, isis2csm_diff.T[0], isis2csm_diff.T[1], isis2csm_diffmag, isis2csm_angles ]).T data = pd.DataFrame(data, columns=[ 'x', 'y', 'isisx', 'isisy', 'diffx', 'diffy', 'magnitude', 'angles' ]) isis2ground2csm_plot = hv.VectorField( (data['x'], data['y'], data['angles'], data['magnitude']), group='isis2ground2csmimage').opts( opts.VectorField(pivot='tail', colorbar=True, cmap='coolwarm', title='ISIS2Ground->CSM2Image Pixel Diff', arrow_heads=True, magnitude='Magnitude', color=dim('Magnitude'))) isis2ground2csm_plot = isis2ground2csm_plot.redim(x='sample', y='line') isis2ground2csm_plot = isis2ground2csm_plot.opts( plot=dict(width=500, height=1000)) isis2ground2csm_plot = isis2ground2csm_plot * hv.Points( data, group='isis2ground2csmimage').opts( size=5, tools=['hover'], invert_yaxis=True) isis2ground2csm_plot = isis2ground2csm_plot.redim.range( a=(data['magnitude'].min(), data['magnitude'].max())) ############################## ############################## csmgnds = np.asarray([[p.x, p.y, p.z] for p in [ csmcam.imageToGround(csmapi.ImageCoord(y, x), 0) for x, y in zip(xs, ys) ]]) csmlon, csmlat, _ = reproject(csmgnds.T, isdjson['radii']['semimajor'], isdjson['radii']['semiminor'], 'geocent', 'latlong') isis_imgpts = point_info(cube, csmlon, csmlat, 'ground') isis_imgpts = np.asarray([(p[1]['Sample'], p[1]['Line']) for p in isis_imgpts]) csm2isis_diff = isis_imgpts - np.asarray([xs, ys]).T csm2isis_diffmag = np.linalg.norm(csm2isis_diff, axis=1) csm2isis_angles = np.arctan2(*csm2isis_diff.T[::-1]) csm2isis_data = np.asarray([ xs, ys, isis_imgpts.T[0], isis_imgpts.T[1], csm2isis_diff.T[0], csm2isis_diff.T[1], csm2isis_diffmag, csm2isis_angles ]).T csm2isis_data = pd.DataFrame(csm2isis_data, columns=[ 'x', 'y', 'csmx', 'csmy', 'diffx', 'diffy', 'magnitude', 'angles' ]) csm2ground2isis_plot = hv.VectorField( (csm2isis_data['x'], csm2isis_data['y'], csm2isis_data['angles'], csm2isis_data['magnitude']), group='csmground2image2isis').opts( opts.VectorField(pivot='tail', colorbar=True, cmap='coolwarm', title='CSM2Ground->ISIS2Image Pixel Diff', arrow_heads=True, magnitude='Magnitude', color=dim('Magnitude'))) csm2ground2isis_plot = csm2ground2isis_plot.redim(x='sample', y='line') csm2ground2isis_plot = csm2ground2isis_plot.opts( plot=dict(width=500, height=1000)) csm2ground2isis_plot = csm2ground2isis_plot * hv.Points( csm2isis_data, group='csmground2image2isis').opts( size=5, tools=['hover'], invert_yaxis=True) ############################### ############################### isis_lonlat = np.asarray([[ p[1]['PositiveEast360Longitude'].value, p[1]['PlanetocentricLatitude'].value ] for p in isis_pts]) csm_lonlat = np.asarray([csmlon + 360, csmlat]).T isiscsm_difflatlon = isis_lonlat - csm_lonlat isiscsm_difflatlonmag = np.linalg.norm(isiscsm_difflatlon, axis=1) isiscsm_angleslatlon = np.arctan2(*isiscsm_difflatlon.T[::-1]) isiscsm_latlondata = np.asarray([ isis_lonlat.T[0], isis_lonlat.T[1], csm_lonlat.T[0], csm_lonlat.T[1], isiscsm_difflatlon.T[0], isiscsm_difflatlon.T[1], isiscsm_difflatlonmag, isiscsm_angleslatlon ]).T isiscsm_latlondata = pd.DataFrame(isiscsm_latlondata, columns=[ 'isislon', 'isislat', 'csmlon', 'csmlat', 'difflon', 'difflat', 'magnitude', 'angles' ]) isiscsm_plotlatlon = hv.VectorField( (isiscsm_latlondata['isislon'], isiscsm_latlondata['isislat'], isiscsm_latlondata['angles'], isiscsm_latlondata['magnitude']), group='isisvscsmlatlon').opts( opts.VectorField(pivot='tail', colorbar=True, cmap='coolwarm', title='Image2Ground latlon Diff', arrow_heads=True, magnitude='Magnitude', color=dim('Magnitude'))) isiscsm_plotlatlon = isiscsm_plotlatlon.redim(x='longitude', y='latitude') isiscsm_plotlatlon = isiscsm_plotlatlon.opts( plot=dict(width=500, height=1000)) isiscsm_plotlatlon = isiscsm_plotlatlon * hv.Points( isiscsm_latlondata, ['isislon', 'isislat'], group='isisvscsmlatlon').opts( size=5, tools=['hover'], invert_yaxis=True) ############################### return isis2ground2csm_plot, csm2ground2isis_plot, isiscsm_plotlatlon, data, csm2isis_data, isiscsm_latlondata