def compute_residuals(network, sensors): """ Compute the error in the observations by taking the difference between the ground points groundToImage projections and measure values. Parameters ---------- network : DataFrame The control network as a dataframe generated by plio sensors : dict A dictionary that maps ISIS serial numbers to CSM sensors Returns ------- V : np.array The control network dataframe with updated ground points """ num_meas = len(network) V = np.zeros((num_meas, 2)) for i in range(num_meas): row = network.iloc[i] serial = row["serialnumber"] ground_pt = row[["adjustedX", "adjustedY", "adjustedZ"]].values ground_pt = csmapi.EcefCoord(ground_pt[0], ground_pt[1], ground_pt[2]) sensor = sensors[serial] img_coord = sensor.groundToImage(ground_pt) V[i, :] = [ row['line'] - img_coord.line, row['sample'] - img_coord.samp ] V = V.reshape(num_meas * 2) return V
def compute_sensor_partials(sensor, parameters, ground_pt): """ Compute the partial derivatives of the line and sample with respect to a set of parameters. Parameters ---------- sensor : CSM sensor The CSM sensor model parameters : list The list of CsmParameter to compute the partials W.R.T. ground_pt : array The (x, y, z) ground point to compute the partial derivatives at Returns ------- : ndarray The 2 x n array of partial derivatives. The first array is the line partials and the second array is the sample partials. The partial derivatives are in the same order as the parameter list passed in. """ partials = np.zeros((2, len(parameters))) csm_ground = csmapi.EcefCoord(ground_pt[0], ground_pt[1], ground_pt[2]) for i in range(len(parameters)): partials[:, i] = sensor.computeSensorPartials(parameters[i].index, csm_ground) return partials
def compute_ground_partials(sensor, ground_pt): """ Compute the partial derivatives of the line and sample with respect to a ground point. Parameters ---------- sensor : CSM sensor The CSM sensor model ground_pt : array The (x, y, z) ground point to compute the partial derivatives W.R.T. Returns ------- : ndarray The 2 x 3 array of partial derivatives. The first array is the line partials and the second array is the sample partials. The partial derivatives are in (x, y, z) order. """ csm_ground = csmapi.EcefCoord(ground_pt[0], ground_pt[1], ground_pt[2]) partials = np.array(sensor.computeGroundPartials(csm_ground)) return np.reshape(partials, (2, 3))
def test_bad_ground_to_image(model): gnd_coord = csmapi.EcefCoord(-1, -1, 0) with pytest.warns(Warning) as w: img = model.groundToImage(gnd_coord, 0) assert len(w) == 1
def test_ground_to_image(model): assert hasattr(model, 'groundToImage') gnd_coord = csmapi.EcefCoord(0, 0, 0) img = model.groundToImage(gnd_coord, 0) assert img.samp == 0 assert img.line == 0
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
def reprojection_diff(isd, cube, nx=10, ny=50, width=500, height=500): """ """ 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) # get data for isis image to ground, csm ground to image isis_pts = point_info(cube, xs, ys, 'image') isisgnds = np.asarray([np.asarray(g[1]['BodyFixedCoordinate'].value)*1000 for g in isis_pts]) csm_pts = np.asarray([[p.samp, p.line] for p in [csmcam.groundToImage(csmapi.EcefCoord(*bf)) for bf in isisgnds]]) isis2csm_diff = np.asarray([xs,ys]).T - csm_pts isis2csm_diffmag = np.linalg.norm(isis2csm_diff, axis=1) isis2csm_angles = np.arctan2(*isis2csm_diff.T[::-1]) isis2csm_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 isis2csm_data = pd.DataFrame(isis2csm_data, columns=['csm sample', 'csm line', 'isis sample','isis line', 'diff sample', 'diff line', 'magnitude', 'angles']) isis2csm_plot = plot_diff(isis2csm_data, colx='isis sample', coly='isis line', coldx='diff sample', coldy='diff line', title="ISIS2Ground->CSM2Image", width=width, height=height) # get data for csm image to ground, isis ground to image 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']['semimajor'], 'geocent', 'latlong') isis_imgpts = point_info(cube, (csmlon+360)%360, csmlat, 'ground') isis_imgpts = np.asarray([(p[1]['Sample'], p[1]['Line']) for p in isis_imgpts]) csm2isis_diff = np.asarray([xs,ys]).T - isis_imgpts csm2isis_diffmag = np.linalg.norm(csm2isis_diff, axis=1) csm2isis_angles = np.arctan2(*(csm2isis_diff/csm2isis_diffmag[:,np.newaxis]).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=['csm sample', 'csm line', 'isis sample','isis line', 'diff sample', 'diff line', 'magnitude', 'angles']) csm2isis_plot = plot_diff(csm2isis_data, colx='csm sample', coly='csm line', coldx='diff sample', coldy='diff line', title="CSM2Ground->ISIS2Image", width=width, height=height) # get data for footprint comparison isis_lonlat = np.asarray([[p[1]['PositiveEast360Longitude'].value, p[1]['PlanetocentricLatitude'].value] for p in isis_pts]) csm_lonlat = np.asarray([(csmlon+360)%360, csmlat]).T isiscsm_difflatlon = csm_lonlat - isis_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=['isis lon', 'isis lat', 'csm lon','csm lat', 'diff lon', 'diff lat', 'magnitude', 'angles']) isiscsm_latlonplot = plot_diff(isiscsm_latlondata, colx='isis lon', coly='isis lat', coldx='diff lon', coldy='diff lat', title="ISIS Lat/Lon vs CSM Lat/Lon", width=width, height=height) isiscsm_diffbf = isisgnds - csmgnds isiscsm_diffbfmag = np.linalg.norm(isiscsm_diffbf, axis=1) isiscsm_anglesbf = np.arctan2(*isiscsm_diffbf.T[::-1]) isiscsm_bfdata = np.asarray([isisgnds.T[0], isisgnds.T[1], isisgnds.T[2], csmgnds.T[0], csmgnds.T[1], csmgnds.T[2], isiscsm_diffbf.T[0], isiscsm_diffbf.T[1], isiscsm_diffbf.T[2], isiscsm_diffbfmag, isiscsm_anglesbf]).T isiscsm_bfdata = pd.DataFrame(isiscsm_bfdata, columns=['isisx', 'isisy', 'isisz', 'csmx','csmy', 'csmz', 'diffx', 'diffy', 'diffz', 'magnitude', 'angles']) isiscsm_bfplot = plot_diff_3d(isiscsm_bfdata, colx='isisx', coly='isisy', colz='isisz', title='ISIS Body-Fixed vs CSM Body-Fixed', width=width, height=height) return isis2csm_plot, csm2isis_plot, isiscsm_latlonplot, isiscsm_bfplot, isis2csm_data, csm2isis_data, isiscsm_latlondata, isiscsm_bfdata