# Path: py/fiberassign/utils.py
# def option_list(opts):
# def assert_isoformat_utc(time_str):
# def get_date_cutoff(datetype, cutoff_case):
# def get_svn_version(svn_dir):
# def get_last_line(fn):
# def read_ecsv_keys(fn):
# 
# Path: py/fiberassign/hardware.py
# def radec2xy(hw, tile_ra, tile_dec, tile_obstime, tile_obstheta, tile_obsha,
#              ra, dec, use_cs5, threads=0):
#     '''
#     For the tile pointed at (tilera, tiledec), project the (ra, dec)
#     value into X/Y mm.
# 
#     Args:
#       hw: Hardware object
#       tile_ra (float): Tile RA
#       tile_dec (float): Tile Dec
#       tile_obstime (string): Tile observation time, YYYY-MM-DDTHH:MM:SS / Astropy "isot" format.
#       tile_obstheta (float): Tile "fieldrot" rotation angle.
#       tile_obsha (float): Tile designed Hour Angle, in degrees.
#       ra (numpy array): RA to project, in degrees
#       dec (numpy array): Dec to project, in degrees
#       use_CS5 (bool):  If True, return CS5 coordinates, else curved.
#       threads=0 (int): currently unused; for backward compatibility.
# 
#     Returns:
#       x, y: numpy arrays: the (X, Y) projected locations.
#     '''
#     #xy = hw.radec2xy_multi(
#     #    tile_ra, tile_dec, tile_obstheta, ra, dec, use_cs5, threads=0
#     #)
#     #x = np.array([x for x,y in xy])
#     #y = np.array([y for x,y in xy])
#     from astropy.time import Time
#     from desimeter.fiberassign import fiberassign_radec2xy_cs5, fiberassign_radec2xy_flat
#     # Note that MJD is only used for precession, so no need for
#     # high precision.
#     t = Time(tile_obstime, format='isot')
#     mjd = t.mjd
# 
#     # Don't pass adc[12]: Let desimeter use its pm-alike routines
#     if use_cs5:
#         x, y = fiberassign_radec2xy_cs5(ra, dec, tile_ra, tile_dec, mjd,
#                                         tile_obsha, tile_obstheta)
#     else:
#         x, y = fiberassign_radec2xy_flat(ra, dec, tile_ra, tile_dec, mjd,
#                                          tile_obsha, tile_obstheta)
#     return x,y
# 
# def cs52xy(x, y):
#     '''
#     Converts from CS5 coordinates (mm) into curved focal-plane X,Y coordinates in mm.
# 
#     Args:
#     cs5x (numpy array): CS5 X coord (mm)
#     cs5y (numpy array): CS5 Y coord (mm)
# 
#     Returns:
#     x (numpy array): X coord (mm)
#     y (numpy array): Y coord (mm)
#     '''
#     # There's a change in terminology between the focal-plane team and
#     # the outside world here...
#     from desimeter.transform.pos2ptl import ptl2flat
#     return ptl2flat(x, y)


import numpy as np
import fitsio
from desitarget.targetmask import desi_mask, mws_mask
from desitarget.cmx.cmx_targetmask import cmx_mask
from desitarget.sv1.sv1_targetmask import desi_mask as sv1_mask
from desitarget.sv1.sv1_targetmask import scnd_mask as sv1_scnd_mask
from desitarget.sv2.sv2_targetmask import desi_mask as sv2_mask
from desitarget.sv3.sv3_targetmask import desi_mask as sv3_mask
from desitarget.targets import main_cmx_or_sv
from .utils import Logger, Timer
from .hardware import radec2xy, cs52xy
from ._internal import (TARGET_TYPE_SCIENCE, TARGET_TYPE_SKY,
                        TARGET_TYPE_STANDARD, TARGET_TYPE_SAFE,
                        TARGET_TYPE_SUPPSKY,
                        Target, Targets, TargetsAvailable,
                        LocationsAvailable)
from fiberassign.utils import assert_isoformat_utc, get_date_cutoff
from datetime import datetime
from astropy.time import Time
    from scipy.spatial import KDTree
    4 types used internally in assignment (science, standard, sky, safe).

    This classification is controlled by applying bitmasks to the specified
    data column.  Alternatively, all targets in the file can be forced to one
    type.

    Args:
        tgs (Targets): The targets object on which to append this data.
        tgdata (Table): A table or recarray with the target properties.
        survey (str):  The survey type.  If None, query from columns.
        typeforce (int): If specified, it must equal one of the TARGET_TYPE_*
            values.  All targets read from the file will be assigned this type.
        typecol (str): Optional column to use for bitmask matching (default
            uses the result of main_cmx_or_sv from desitarget).
        sciencemask (int): Bitmask for classifying targets as science.
        stdmask (int): Bitmask for classifying targets as a standard.
        skymask (int): Bitmask for classifying targets as sky.
        suppskymask (int): Bitmask for classifying targets as suppsky.
        safemask (int): Bitmask for classifying targets as a safe location.
        excludemask (int): Bitmask for excluding targets.
        gaia_stdmask (int): Bitmask for classifying targets as a Gaia standard.
        rundate (optional, defaults to None): yyyy-mm-ddThh:mm:ss+00:00 rundate
            for focalplane with UTC timezone formatting (string)

    Returns:
        None

    Notes:
        20210930 : include rundate argument, for default_main_stdmask().
    """

# Path: py/fiberassign/utils.py
# def option_list(opts):
# def assert_isoformat_utc(time_str):
# def get_date_cutoff(datetype, cutoff_case):
# def get_svn_version(svn_dir):
# def get_last_line(fn):
# def read_ecsv_keys(fn):
# 
# Path: py/fiberassign/hardware.py
# def radec2xy(hw, tile_ra, tile_dec, tile_obstime, tile_obstheta, tile_obsha,
#              ra, dec, use_cs5, threads=0):
#     '''
#     For the tile pointed at (tilera, tiledec), project the (ra, dec)
#     value into X/Y mm.
# 
#     Args:
#       hw: Hardware object
#       tile_ra (float): Tile RA
#       tile_dec (float): Tile Dec
#       tile_obstime (string): Tile observation time, YYYY-MM-DDTHH:MM:SS / Astropy "isot" format.
#       tile_obstheta (float): Tile "fieldrot" rotation angle.
#       tile_obsha (float): Tile designed Hour Angle, in degrees.
#       ra (numpy array): RA to project, in degrees
#       dec (numpy array): Dec to project, in degrees
#       use_CS5 (bool):  If True, return CS5 coordinates, else curved.
#       threads=0 (int): currently unused; for backward compatibility.
# 
#     Returns:
#       x, y: numpy arrays: the (X, Y) projected locations.
#     '''
#     #xy = hw.radec2xy_multi(
#     #    tile_ra, tile_dec, tile_obstheta, ra, dec, use_cs5, threads=0
#     #)
#     #x = np.array([x for x,y in xy])
#     #y = np.array([y for x,y in xy])
#     from astropy.time import Time
#     from desimeter.fiberassign import fiberassign_radec2xy_cs5, fiberassign_radec2xy_flat
#     # Note that MJD is only used for precession, so no need for
#     # high precision.
#     t = Time(tile_obstime, format='isot')
#     mjd = t.mjd
# 
#     # Don't pass adc[12]: Let desimeter use its pm-alike routines
#     if use_cs5:
#         x, y = fiberassign_radec2xy_cs5(ra, dec, tile_ra, tile_dec, mjd,
#                                         tile_obsha, tile_obstheta)
#     else:
#         x, y = fiberassign_radec2xy_flat(ra, dec, tile_ra, tile_dec, mjd,
#                                          tile_obsha, tile_obstheta)
#     return x,y
# 
# def cs52xy(x, y):
#     '''
#     Converts from CS5 coordinates (mm) into curved focal-plane X,Y coordinates in mm.
# 
#     Args:
#     cs5x (numpy array): CS5 X coord (mm)
#     cs5y (numpy array): CS5 Y coord (mm)
# 
#     Returns:
#     x (numpy array): X coord (mm)
#     y (numpy array): Y coord (mm)
#     '''
#     # There's a change in terminology between the focal-plane team and
#     # the outside world here...
#     from desimeter.transform.pos2ptl import ptl2flat
#     return ptl2flat(x, y)


# Path: py/fiberassign/targets.py
import numpy as np
import fitsio
from desitarget.targetmask import desi_mask, mws_mask
from desitarget.cmx.cmx_targetmask import cmx_mask
from desitarget.sv1.sv1_targetmask import desi_mask as sv1_mask
from desitarget.sv1.sv1_targetmask import scnd_mask as sv1_scnd_mask
from desitarget.sv2.sv2_targetmask import desi_mask as sv2_mask
from desitarget.sv3.sv3_targetmask import desi_mask as sv3_mask
from desitarget.targets import main_cmx_or_sv
from .utils import Logger, Timer
from .hardware import radec2xy, cs52xy
from ._internal import (TARGET_TYPE_SCIENCE, TARGET_TYPE_SKY,
                        TARGET_TYPE_STANDARD, TARGET_TYPE_SAFE,
                        TARGET_TYPE_SUPPSKY,
                        Target, Targets, TargetsAvailable,
                        LocationsAvailable)
from fiberassign.utils import assert_isoformat_utc, get_date_cutoff
from datetime import datetime
from astropy.time import Time
    from scipy.spatial import KDTree

    4 types used internally in assignment (science, standard, sky, safe).

    This classification is controlled by applying bitmasks to the specified
    data column.  Alternatively, all targets in the file can be forced to one
    type.

    Args:
        tgs (Targets): The targets object on which to append this data.
        tgdata (Table): A table or recarray with the target properties.
        survey (str):  The survey type.  If None, query from columns.
        typeforce (int): If specified, it must equal one of the TARGET_TYPE_*
            values.  All targets read from the file will be assigned this type.
        typecol (str): Optional column to use for bitmask matching (default
            uses the result of main_cmx_or_sv from desitarget).
        sciencemask (int): Bitmask for classifying targets as science.
        stdmask (int): Bitmask for classifying targets as a standard.
        skymask (int): Bitmask for classifying targets as sky.
        suppskymask (int): Bitmask for classifying targets as suppsky.
        safemask (int): Bitmask for classifying targets as a safe location.
        excludemask (int): Bitmask for excluding targets.
        gaia_stdmask (int): Bitmask for classifying targets as a Gaia standard.
        rundate (optional, defaults to None): yyyy-mm-ddThh:mm:ss+00:00 rundate
            for focalplane with UTC timezone formatting (string)

    Returns:
        None

    Notes:
        20210930 : include rundate argument, for default_main_stdmask().
    """

    log = Logger.get()