<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def eci2ecef(eci: np.ndarray, time: datetime, useastropy: bool = True) -> np.ndarray: """ Observer => Point ECI => ECEF Parameters eci : tuple of float Nx3 target ECI location (x,y,z) [meters] time : datetime.datetime time of obsevation (UTC) useastropy : bool, optional use AstroPy for conversion Results ------- x : float target x ECEF coordinate y : float target y ECEF coordinate z : float target z ECEF coordinate """

    useastropy = useastropy and Time

    if useastropy:
        gst = Time(time).sidereal_time('apparent', 'greenwich').radian
    else:
        gst = datetime2sidereal(time, 0.)

    gst = np.atleast_1d(gst)
    assert gst.ndim == 1 and isinstance(gst[0], float)  # must be in radians!

    eci = np.atleast_2d(eci)
    assert eci.shape[0] == gst.size, 'length of time does not match number of ECI positions'

    N, trip = eci.shape
    if eci.ndim > 2 or trip != 3:
        raise ValueError('eci triplets must be shape (N,3)')

    ecef = np.empty_like(eci)

    for i in range(N):
        ecef[i, :] = _rottrip(gst[i]) @ eci[i, :]

    return ecef.squeeze()