Exemple #1
0
 def calculate_wake_distance(self):
     horizontal_line_image_coords = self.image_canvas.canvas.canvas_shape_coords_to_image_coords(self.variables.horizontal_line_id)
     sicd_meta = self.variables.image_reader.base_reader.sicd_meta
     points = np.asarray(np.reshape(horizontal_line_image_coords, (2, 2)))
     ecf_ground_points = point_projection.image_to_ground(points, sicd_meta)
     geo_ground_point_1 = geocoords.ecf_to_geodetic((ecf_ground_points[0, 0], ecf_ground_points[0, 1], ecf_ground_points[0, 2]))
     geo_ground_point_2 = geocoords.ecf_to_geodetic((ecf_ground_points[1, 0], ecf_ground_points[1, 1], ecf_ground_points[1, 2]))
     distance = math.sqrt( (ecf_ground_points[0, 0] - ecf_ground_points[1, 0])**2 +
                           (ecf_ground_points[0, 1] - ecf_ground_points[1, 1])**2 +
                           (ecf_ground_points[0, 2] - ecf_ground_points[1, 2])**2)
     return distance
Exemple #2
0
    def test_ecf_to_geodetic(self):
        out = geocoords.ecf_to_geodetic(ecf[0, :])
        with self.subTest(msg="basic shape check"):
            self.assertEqual(out.shape, (3, ))
        with self.subTest(msg="basic value check"):
            self.assertTrue(numpy.all(numpy.abs(out - llh[0, :]) < tolerance))

        out2 = geocoords.ecf_to_geodetic(ecf)
        with self.subTest(msg="2d shape check"):
            self.assertEqual(out2.shape, ecf.shape)
        with self.subTest(msg="2d value check"):
            self.assertTrue(numpy.all(numpy.abs(out2 - llh) < tolerance))

        with self.subTest(msg="error check"):
            self.assertRaises(ValueError, geocoords.ecf_to_geodetic, numpy.arange(4))
Exemple #3
0
    def set_reference_point(self, reference_point=None):
        """
        Sets the reference point, which must be provided in ECF coordinates.

        Parameters
        ----------
        reference_point : None|numpy.ndarray
            The reference point (origin) of the planar grid. If None, then the
            `sicd.GeoData.SCP.ECF` will be used.

        Returns
        -------
        None
        """

        if reference_point is None:
            if self.sicd.RadarCollection.Area is None:
                reference_point = self.sicd.GeoData.SCP.ECF.get_array()
            else:
                reference_point = self.sicd.RadarCollection.Area.Plane.RefPt.ECF.get_array(
                )

        if not (isinstance(reference_point, numpy.ndarray)
                and reference_point.ndim == 1 and reference_point.size == 3):
            raise ValueError('reference_point must be a vector of size 3.')
        self._reference_point = reference_point
        # set the reference hae
        ref_llh = ecf_to_geodetic(reference_point)
        self._reference_hae = ref_llh[2]
Exemple #4
0
 def get_geo_lon_lat(self):
     if hasattr(self.meta, "GeoData"):
         try:
             scp = [
                 self.meta.GeoData.SCP.ECF.X, self.meta.GeoData.SCP.ECF.Y,
                 self.meta.GeoData.SCP.ECF.Z
             ]
         except Exception as e:
             logging.error(
                 "Unable to get geolocation data in ECF form {}".format(e))
     # TODO: might take this out if it's not part of the SICD standard
     elif hasattr(self.meta, "SRP"):
         if self.meta.SRP.SRPType == "FIXEDPT":
             scp = self.meta.SRP.FIXEDPT.SRPPT
             scp = [scp.X, scp.Y, scp.Z]
         elif self.meta.SRP.SRPType == "PVTPOLY":
             # TODO: implement this for the case where we need to do a polynomial
             pass
     try:
         lla = geocoords.ecf_to_geodetic(scp)
         lat = lla[0]
         lon = lla[1]
     except Exception as e:
         logging.error(
             "could not find latitude and longitude information in the SICD metadata. {}"
             .format(e))
     return lat, lon
Exemple #5
0
 def _derive_corner_from_plane(self):
     # try to define the corner points - for SICD 0.5.
     if self.Corner is not None:
         return  # nothing to be done
     if self.Plane is None:
         return  # nothing to derive from
     corners = self.Plane.get_ecf_corner_array()
     self.Corner = [
         LatLonHAECornerRestrictionType(**{'Lat': entry[0], 'Lon': entry[1], 'HAE': entry[2], 'index': i+1})
         for i, entry in enumerate(geocoords.ecf_to_geodetic(corners))]
Exemple #6
0
def _write_collection_wedge(kmz_document, sicd, time_args, arp_llh, time_array,
                            folder):
    """
    Writes the collection wedge.

    Parameters
    ----------
    kmz_document : Document
    sicd : SICDType
    time_args : dict
    arp_llh : None|numpy.ndarray
    time_array : None|numpy.ndarray
    folder : minidom.Element

    Returns
    -------
    None
    """

    if time_array is None or arp_llh is None:
        return

    if sicd.Position is not None and sicd.Position.GRPPoly is not None:
        grp = sicd.Position.GRPPoly(time_array)
    elif sicd.GeoData is not None and sicd.GeoData.SCP is not None:
        grp = numpy.reshape(sicd.GeoData.SCP.ECF.get_array(), (1, 3))
    else:
        return
    frm = '{1:0.8f},{0:0.8f},{2:0.2f}'
    grp_llh = ecf_to_geodetic(grp)

    if numpy.any(~numpy.isfinite(grp_llh)):
        logging.error(
            'There are nonsense entries (nan or +/- infinity) in the scp/ground range locations.'
        )

    coord_array = [frm.format(*el) for el in arp_llh]
    if len(grp_llh) > 1:
        coord_array.extend(frm.format(*el) for el in grp_llh[::-1, :])
    else:
        coord_array.append(frm.format(*grp_llh[0, :]))
    coord_array.append(frm.format(*arp_llh[0, :]))
    coords = ' '.join(coord_array)
    placemark = kmz_document.add_container(
        par=folder,
        description='collection wedge for {}'.format(_get_sicd_name(sicd)),
        styleUrl='#collection',
        **time_args)
    kmz_document.add_polygon(coords,
                             par=placemark,
                             extrude=False,
                             tesselate=False,
                             altitudeMode='absolute')
Exemple #7
0
    def from_sicd(cls, sicd):
        """
        Construct the sensor info from a sicd structure

        Parameters
        ----------
        sicd : SICDType

        Returns
        -------
        SensorInfoType
        """

        transmit_freq_proc = sicd.ImageFormation.TxFrequencyProc
        center_freq = transmit_freq_proc.center_frequency * 1e-9
        bandwidth = transmit_freq_proc.bandwidth * 1e-9
        polarization = sicd.ImageFormation.get_polarization().replace(':', '')
        look = 'Left' if sicd.SCPCOA.SideOfTrack == 'L' else 'Right'
        arp_pos_llh = ecf_to_geodetic(sicd.SCPCOA.ARPPos.get_array())

        # calculate heading
        heading_ned = ecf_to_ned(sicd.SCPCOA.ARPVel.get_array(),
                                 sicd.SCPCOA.ARPPos.get_array(),
                                 absolute_coords=False)
        heading = numpy.rad2deg(numpy.arctan2(heading_ned[1], heading_ned[0]))
        # calculate track angle
        first_pos_ecf = sicd.Position.ARPPoly(0)
        last_pos_ecf = sicd.Position.ARPPoly(sicd.Timeline.CollectDuration)
        diff_ned = ecf_to_ned(last_pos_ecf - first_pos_ecf,
                              sicd.SCPCOA.ARPPos.get_array(),
                              absolute_coords=False)
        track_angle = numpy.rad2deg(numpy.arctan2(diff_ned[1], diff_ned[0]))

        return SensorInfoType(
            Name=sicd.CollectionInfo.CollectorName,
            Type='SAR',
            Mode=sicd.CollectionInfo.RadarMode.ModeType,
            Band=sicd.ImageFormation.get_transmit_band_name(),
            Bandwidth=bandwidth,
            CenterFrequency=center_freq,
            Polarization=polarization,
            Range=sicd.SCPCOA.SlantRange,
            DepressionAngle=sicd.SCPCOA.GrazeAng,
            Aimpoint=sicd.GeoData.SCP.LLH.get_array(),
            AircraftHeading=heading,
            AircraftTrackAngle=track_angle,
            Look=look,
            SquintAngle=SquintAngleType(SlantPlane=sicd.SCPCOA.DopplerConeAng,
                                        GroundPlane=sicd.SCPCOA.Squint),
            AircraftLocation=arp_pos_llh,
            AircraftVelocity=sicd.SCPCOA.ARPVel.get_array())
Exemple #8
0
def _write_arp_location(kmz_document, sicd, time_args, time_array, folder):
    """

    Parameters
    ----------
    kmz_document : Document
    sicd : SICDType
    time_args : dict
    time_array : None|numpy.ndarray
    folder : minidom.Element

    Returns
    -------
    None|Numpy.ndarray
    """

    if time_array is None:
        return None

    if sicd.Position is not None and sicd.Position.ARPPoly is not None:
        arp_pos = sicd.Position.ARPPoly(time_array)
    elif sicd.SCPCOA.ARPPos is not None and sicd.SCPCOA.ARPVel is not None:
        arp_pos = sicd.SCPCOA.ARPPos.get_array() + numpy.outer(
            time_array, sicd.SCPCOA.ARPVel.get_array())
    else:
        return None

    arp_llh = ecf_to_geodetic(arp_pos)
    if numpy.any(~numpy.isfinite(arp_llh)):
        logging.error(
            'There are nonsense entries (nan or +/- infinity) in the aperture location.'
        )
    coords = ['{1:0.8f},{0:0.8f},{2:0.2f}'.format(*el) for el in arp_llh]
    whens = [
        str(
            sicd.Timeline.CollectStart.astype('datetime64[us]') +
            int_func(el * 1e6)) + 'Z' for el in time_array
    ]
    placemark = kmz_document.add_container(
        par=folder,
        description='aperture position for {}'.format(_get_sicd_name(sicd)),
        styleUrl='#arp',
        **time_args)
    kmz_document.add_gx_track(coords,
                              whens,
                              par=placemark,
                              extrude=True,
                              tesselate=True,
                              altitudeMode='absolute')
    return arp_llh
    def North(self):
        """
        float: The north angle.
        """

        lat, lon, hae = ecf_to_geodetic(self.SCP)
        lat_r = numpy.deg2rad(lat)
        lon_r = numpy.deg2rad(lon)
        N = numpy.array(
            [-numpy.sin(lat_r)*numpy.cos(lon_r),
             -numpy.sin(lat_r)*numpy.sin(lon_r),
             numpy.cos(lat_r)])
        Nprime = N - self.slant_z*(N.dot(self.normal_vector)/self.slant_z.dot(self.normal_vector))
        return numpy.rad2deg(numpy.arctan2(self.col_vector.dot(Nprime), self.row_vector.dot(Nprime)))
Exemple #10
0
    def _split_lat_lon_quad(ll_quad, split_fractions):
        """
        Helper method for recursively splitting the lat/lon quad box.

        Parameters
        ----------
        ll_quad : numpy.ndarray
        split_fractions : list|tuple

        Returns
        -------
        numpy.ndarray
        """

        r1, r2, c1, c2 = split_fractions
        # [0] corresponds to (max_row, 0)
        # [1] corresponds to (max row, max_col)
        # [2] corresponds to (0, max_col)
        # [3] corresponds to (0, 0)

        # do row split
        # [0] = r2*[0] + (1-r2)*[3]
        # [1] = r2*[1] + (1-r2)*[2]
        # [2] = r1*[1] + (1-r1)*[2]
        # [3] = r1*[0] + (1-r1)*[3]
        row_split = numpy.array([
            [r2, 0, 0, 1-r2],
            [0, r2, 1-r2, 0],
            [0, r1, 1-r1, 0],
            [r1, 0, 0, 1-r1],
        ], dtype='float64')

        # do column split
        # [0] = (1-c1)*[0] + c1*[1]
        # [1] = (1-c2)*[0] + c2*[1]
        # [2] = c2*[2] + (1-c2)*[3]
        # [3] = c1*[2] + (1-c1)*[3]
        col_split = numpy.array([
            [1-c1, c1, 0, 0],
            [1-c2, c2, 0, 0],
            [0, 0, c2, 1-c2],
            [0, 0, c1, 1-c1],], dtype='float64')

        split = col_split.dot(row_split)

        llh_temp = numpy.zeros((4, 3))
        llh_temp[:, :2] = ll_quad
        ecf_coords = geodetic_to_ecf(llh_temp)
        split_ecf = split.dot(ecf_coords)
        return ecf_to_geodetic(split_ecf)[:, :2]
Exemple #11
0
    def get_llh_image_corners(self) -> Optional[numpy.ndarray]:
        """
        The corner points of the overall ortho-rectified output in Lat/Lon/HAE
        coordinates. The ordering of these points follows the SICD convention.

        Returns
        -------
        None|numpy.ndarray
        """

        ecf_corners = self.get_ecf_image_corners()
        if ecf_corners is None:
            return None
        else:
            return ecf_to_geodetic(ecf_corners)
Exemple #12
0
    def ortho_to_llh(self, ortho_coords):
        """
        Get the lat/lon/hae coordinates for the point(s) in ortho-rectified coordinates.

        Parameters
        ----------
        ortho_coords : numpy.ndarray
            Point(s) in the ortho-recitified coordinate system, of the form
            `(ortho_row, ortho_column)`.

        Returns
        -------
        numpy.ndarray
        """

        ecf = self.ortho_to_ecf(ortho_coords)
        return ecf_to_geodetic(ecf)
Exemple #13
0
def interpolate_corner_points_string(entry, rows, cols, icp):
    """
    Interpolate the corner points for the given subsection from
    the given corner points. This supplies entries for the NITF headers.

    Parameters
    ----------
    entry : numpy.ndarray
        The corner pints of the form `(row_start, row_stop, col_start, col_stop)`
    rows : int
        The number of rows in the parent image.
    cols : int
        The number of cols in the parent image.
    icp : the parent image corner points in geodetic coordinates.

    Returns
    -------
    str
    """

    if icp is None:
        return ''

    if icp.shape[1] == 2:
        icp_new = numpy.zeros((icp.shape[0], 3), dtype=numpy.float64)
        icp_new[:, :2] = icp
        icp = icp_new
    icp_ecf = geodetic_to_ecf(icp)

    const = 1. / (rows * cols)
    pattern = entry[numpy.array([(0, 2), (1, 2), (1, 3), (0, 3)],
                                dtype=numpy.int64)]
    out = []
    for row, col in pattern:
        pt_array = const * numpy.sum(
            icp_ecf *
            (numpy.array([rows - row, row, row, rows - row]) * numpy.array(
                [cols - col, cols - col, col, col]))[:, numpy.newaxis],
            axis=0)

        pt = LatLonType.from_array(ecf_to_geodetic(pt_array)[:2])
        dms = pt.dms_format(frac_secs=False)
        out.append('{0:02d}{1:02d}{2:02d}{3:s}'.format(*dms[0]) +
                   '{0:03d}{1:02d}{2:02d}{3:s}'.format(*dms[1]))
    return ''.join(out)
Exemple #14
0
def sarpy2ortho(ro, pix, decimation=10):

    nx = ro.sicdmeta.ImageData.FullImage.NumCols
    ny = ro.sicdmeta.ImageData.FullImage.NumRows

    nx_dec = round(nx / decimation)
    ny_dec = round(ny / decimation)

    xv, yv = np.meshgrid(range(nx), range(ny), indexing='xy')
    xv = xv[::decimation, ::decimation]
    yv = yv[::decimation, ::decimation]
    npix = xv.size

    xv = np.reshape(xv, (npix, 1))
    yv = np.reshape(yv, (npix, 1))
    im_points = np.concatenate([yv, xv], axis=1)

    ground_coords = image_to_ground(im_points, ro.sicdmeta)
    ground_coords = ecf_to_geodetic(ground_coords)

    minx = np.min(ground_coords[:, 1])
    maxx = np.max(ground_coords[:, 1])
    miny = np.min(ground_coords[:, 0])
    maxy = np.max(ground_coords[:, 0])

    xi, yi = create_ground_grid(minx, maxx, miny, maxy, nx_dec, ny_dec)

    ground_coords[:, [0, 1]] = ground_coords[:, [1, 0]]
    pix = np.reshape(pix, npix)
    gridded = griddata(ground_coords[:, 0:2], pix, (xi, yi),
                       method='nearest').astype(np.uint8)

    ul = [maxy, minx]
    lr = [miny, maxx]

    extent = [ul, lr]

    extent_poly = bounds_2_shapely_polygon(min_x=minx,
                                           max_x=maxx,
                                           min_y=miny,
                                           max_y=maxy)
    geot = world_poly_to_geo_t(extent_poly, npix_x=nx_dec, npix_y=ny_dec)

    return gridded, extent, geot
Exemple #15
0
    def callback_save_kml(self, event):
        kml_save_fname = tkinter.filedialog.asksaveasfilename(
            initialdir=os.path.expanduser("~/Downloads"))

        kml_util = KmlUtil()

        canvas_shapes = self.canvas_demo_image_panel.canvas.variables.shape_ids
        for shape_id in canvas_shapes:
            image_coords = self.canvas_demo_image_panel.canvas.get_shape_image_coords(
                shape_id)
            shape_type = self.canvas_demo_image_panel.canvas.get_shape_type(
                shape_id)
            if image_coords:
                sicd_meta = self.canvas_demo_image_panel.canvas.variables.canvas_image_object.reader_object.sicdmeta
                image_points = numpy.zeros((int(len(image_coords) / 2), 2))
                image_points[:, 0] = image_coords[0::2]
                image_points[:, 1] = image_coords[1::2]

                ground_points_ecf = point_projection.image_to_ground(
                    image_points, sicd_meta)
                ground_points_latlon = geocoords.ecf_to_geodetic(
                    ground_points_ecf)

                world_y_coordinates = ground_points_latlon[:, 0]
                world_x_coordinates = ground_points_latlon[:, 1]

                xy_point_list = [
                    (x, y)
                    for x, y in zip(world_x_coordinates, world_y_coordinates)
                ]

                if shape_id == self.canvas_demo_image_panel.canvas.variables.zoom_rect_id:
                    pass
                elif shape_type == self.canvas_demo_image_panel.canvas.variables.select_rect_id:
                    pass
                elif shape_type == self.canvas_demo_image_panel.canvas.SHAPE_TYPES.POINT:
                    kml_util.add_point(str(shape_id), xy_point_list[0])
                elif canvas_shapes == self.canvas_demo_image_panel.canvas.SHAPE_TYPES.LINE:
                    kml_util.add_linestring(str(shape_id), xy_point_list)
                elif shape_type == self.canvas_demo_image_panel.canvas.SHAPE_TYPES.POLYGON:
                    kml_util.add_polygon(str(shape_id), xy_point_list)
                elif shape_type == self.canvas_demo_image_panel.canvas.SHAPE_TYPES.RECT:
                    kml_util.add_polygon(str(shape_id), xy_point_list)
        kml_util.write_to_file(kml_save_fname)
Exemple #16
0
    def test_values_both_ways(self):
        shp = (8, 5)
        rand_llh = numpy.empty(shp + (3, ), dtype=numpy.float64)
        rand_llh[:, :, 0] = 180 * (numpy.random.rand(*shp) - 0.5)
        rand_llh[:, :, 1] = 360 * (numpy.random.rand(*shp) - 0.5)
        rand_llh[:, :, 2] = 1e5 * numpy.random.rand(*shp)

        rand_ecf = geocoords.geodetic_to_ecf(rand_llh)
        rand_llh2 = geocoords.ecf_to_geodetic(rand_ecf)
        rand_ecf2 = geocoords.geodetic_to_ecf(rand_llh2)

        llh_diff = numpy.abs(rand_llh - rand_llh2)
        ecf_diff = numpy.abs(rand_ecf - rand_ecf2)

        with self.subTest(msg="llh match"):
            self.assertTrue(numpy.all(llh_diff < tolerance))

        with self.subTest(msg="ecf match"):
            self.assertTrue(numpy.all(ecf_diff < tolerance))
 def extract_location():
     ll_coords = None
     if isinstance(sidd, SIDDType2):
         try:
             ll_coords = sidd.GeoData.ImageCorners.get_array(
                 dtype=numpy.dtype('float64'))
         except AttributeError:
             pass
     elif isinstance(sidd, SIDDType1):
         try:
             ll_coords = sidd.GeographicAndTarget.GeographicCoverage.Footprint.get_array(
                 dtype=numpy.dtype('float64'))
         except AttributeError:
             pass
     if ll_coords is not None:
         llh_coords = numpy.zeros((ll_coords.shape[0], 3),
                                  dtype=numpy.float64)
         llh_coords[:, :2] = ll_coords
         ecf_coords = geodetic_to_ecf(llh_coords)
         coords = ecf_to_geodetic(numpy.mean(ecf_coords, axis=0))
         variables['lat'] = coords[0]
         variables['lon'] = coords[1]
Exemple #18
0
    def from_sicd(cls, sicd):
        """
        Construct the sensor info from a sicd structure

        Parameters
        ----------
        sicd : SICDType

        Returns
        -------
        DetailSensorInfoType
        """

        transmit_freq_proc = sicd.ImageFormation.TxFrequencyProc
        center_freq = 0.5 * (transmit_freq_proc.MinProc +
                             transmit_freq_proc.MaxProc) * 1e-9
        polarization = sicd.ImageFormation.get_polarization().replace(':', '')
        look = 'Left' if sicd.SCPCOA.SideOfTrack == 'L' else 'Right'
        slant_squint = 90 - sicd.SCPCOA.DopplerConeAng
        ground_squint = 90 - numpy.rad2deg(
            numpy.arccos(
                numpy.cos(numpy.deg2rad(sicd.SCPCOA.DopplerConeAng)) /
                numpy.cos(numpy.deg2rad(sicd.SCPCOA.GrazeAng))))
        arp_pos_llh = ecf_to_geodetic(sicd.SCPCOA.ARPPos.get_array())
        return DetailSensorInfoType(
            Name=sicd.CollectionInfo.CollectorName,
            Type='SAR',
            Mode=sicd.CollectionInfo.RadarMode.ModeType,
            Band=sicd.ImageFormation.get_transmit_band_name(),
            CenterFrequency=center_freq,
            Polarization=polarization,
            Range=sicd.SCPCOA.SlantRange,
            DepressionAngle=sicd.SCPCOA.GrazeAng,
            Aimpoint=sicd.GeoData.SCP.LLH.get_array(),
            Look=look,
            SquintAngle=SquintAngleType(SlantPlane=slant_squint,
                                        GroundPlane=ground_squint),
            AircraftLocation=arp_pos_llh,
            AircraftVelocity=sicd.SCPCOA.ARPVel.get_array())
        def extract_global():
            if cphd.Global is None:
                return

            try:
                variables['collect_start'] = cphd.Global.CollectStart
            except AttributeError:
                pass

            try:
                variables['collect_duration'] = cphd.Global.CollectDuration
            except AttributeError:
                pass

            try:
                llh_coords = cphd.Global.ImageArea.Corner.get_array(
                    dtype=numpy.dtype('float64'))
                ecf_coords = geodetic_to_ecf(llh_coords)
                coords = ecf_to_geodetic(numpy.mean(ecf_coords, axis=0))
                variables['lat'] = coords[0]
                variables['lon'] = coords[1]
            except AttributeError:
                pass
Exemple #20
0
def best_physical_location_fit(
        structs: Sequence[Union[SICDType, SIDDType1,
                                SIDDType2]], locs: Union[numpy.ndarray, list,
                                                         tuple],
        **minimization_args) -> Tuple[numpy.ndarray, float, Any]:
    """
    Given a collection of SICD and/or SIDDs and a collection of image coordinates, 
    each of which identifies the pixel location of the same feature in the 
    respective image, determine the (best fit) geophysical location of this feature. 

    This assumes that any adjustable parameters used for the SICD/SIDD projection 
    model have already been applied (via :func:`define_coa_projection`).

    Parameters
    ----------
    structs : Sequence[SICDType|SIDDType1|SIDDType2]
        The collection of sicds/sidds, of length `N`
    locs : numpy.ndarray|list|tuple
        The image coordinate collection, of shape `(N, 2)`
    minimization_args
        The keyword arguments (after `args` argument) passed through to
        :func:`scipy.optimize.minimize`. This will default to `'Powell'` 
        optimization, which seems generally much more reliable for this 
        problem than the steepest descent based approaches.

    Returns
    -------
    ecf_location : numpy.ndarray
        The location in question, in ECF coordinates
    residue : float
        The mean square residue of the physical distance between the given
        location and the image locations projected into the surface of
        given HAE value
    result
        The minimization result object
    """
    def get_mean_location(hae_value, log_residue=False):
        ecf_locs = numpy.zeros((points, 3), dtype='float64')
        for i, (loc, struct) in enumerate(zip(locs, structs)):
            ecf_locs[i, :] = struct.project_image_to_ground(
                loc, projection_type='HAE', hae0=hae_value)
        ecf_mean = numpy.mean(ecf_locs, axis=0)
        diff = ecf_locs - ecf_mean
        residue = numpy.sum(diff * diff, axis=1)
        if log_residue:
            logger.info(
                'best physical location residues [m^2]\n{}'.format(residue))

        avg_residue = numpy.mean(residue)
        return ecf_mean, avg_residue

    def average_residue(hae_value):
        return get_mean_location(hae_value)[1]

    points = len(structs)
    if points < 2:
        raise ValueError(
            'At least 2 structs must be present to determine the best location'
        )
    if points != locs.shape[0]:
        raise ValueError(
            'The number of structs must match the number of locations')

    struct0 = structs[0]
    if isinstance(struct0, SICDType):
        h0 = struct0.GeoData.SCP.LLH.HAE
    elif isinstance(struct0, (SIDDType1, SIDDType2)):
        ref_ecf = struct0.Measurement.ReferencePoint.ECEF.get_array()
        h0 = ecf_to_geodetic(ref_ecf)[2]
    else:
        raise TypeError('Got unexpected structure type {}'.format(
            type(struct0)))

    if 'method' not in minimization_args:
        minimization_args['method'] = 'Powell'

    result = minimize(average_residue, h0, **minimization_args)
    if not result.success:
        raise ValueError('Optimization failed {}'.format(result))

    values = get_mean_location(result.x, log_residue=True)
    return values[0], values[1], result
Exemple #21
0
 def ECF(self, value):
     if value is not None:
         self._ECF = _parse_serializable(value, 'ECF', self, XYZType)
         self._LLH = LatLonHAERestrictionType.from_array(
             ecf_to_geodetic(self._ECF.get_array()))
    def create_ortho(
        self,
        output_ny,
        output_nx,
    ):

        input_image_data = self.display_image
        display_image_nx = input_image_data.shape[1]
        display_image_ny = input_image_data.shape[0]

        image_points = np.zeros((display_image_nx * display_image_ny, 2))
        canvas_coords_1d = np.zeros(2 * display_image_nx * display_image_ny)

        tmp_x_vals = np.arange(0, display_image_ny)
        tmp_y_vals = np.zeros(display_image_ny)
        for x in range(display_image_nx):
            start_index = display_image_ny * 2 * x + 1
            end_index = start_index + display_image_ny * 2
            canvas_coords_1d[start_index:end_index:2] = tmp_x_vals
            canvas_coords_1d[display_image_ny * x *
                             2::2][0:display_image_ny] = tmp_y_vals + x

        full_image_coords = self.canvas_coords_to_full_image_yx(
            canvas_coords_1d)

        image_points[:, 0] = full_image_coords[0::2]
        image_points[:, 1] = full_image_coords[1::2]

        sicd_meta = self.reader_object.sicd_meta
        ground_points_ecf = point_projection.image_to_ground(
            image_points, sicd_meta)
        ground_points_latlon = geocoords.ecf_to_geodetic(ground_points_ecf)

        world_y_coordinates = ground_points_latlon[:, 0]
        world_x_coordinates = ground_points_latlon[:, 1]

        x = np.ravel(world_x_coordinates)
        y = np.ravel(world_y_coordinates)
        z = np.ravel(np.transpose(input_image_data))

        ground_x_grid, ground_y_grid = self._create_ground_grid(
            min(x), max(x), min(y), max(y), output_nx, output_ny)

        ortho_image = interp.griddata((x, y),
                                      z, (ground_x_grid, ground_y_grid),
                                      method='nearest')

        s = np.zeros((output_nx * output_ny, 3))
        s[:, 0] = ground_y_grid.ravel()
        s[:, 1] = ground_x_grid.ravel()
        s[:, 2] = ground_points_latlon[0, 2]

        s_ecf = geocoords.geodetic_to_ecf(s)

        gridded_image_pixels = point_projection.ground_to_image(
            s_ecf, sicd_meta)

        full_image_coords_y = full_image_coords[0::2]
        full_image_coords_x = full_image_coords[1::2]

        mask = np.ones_like(gridded_image_pixels[0][:, 0])
        indices_1 = np.where(
            gridded_image_pixels[0][:, 0] < min(full_image_coords_y))
        indices_2 = np.where(
            gridded_image_pixels[0][:, 1] < min(full_image_coords_x))
        indices_3 = np.where(
            gridded_image_pixels[0][:, 0] > max(full_image_coords_y))
        indices_4 = np.where(
            gridded_image_pixels[0][:, 1] > max(full_image_coords_x))

        mask[indices_1] = 0
        mask[indices_2] = 0
        mask[indices_3] = 0
        mask[indices_4] = 0

        mask_2d = np.reshape(mask, (output_ny, output_nx))

        return ortho_image * mask_2d