def read_orange(user_id, records_path, antennas_path=None,
                attributes_path=None, recharges_path=None, network=False,
                describe=True, warnings=True, errors=False):
    """
    Load user records from a CSV file in *orange* format:

    ``call_record_type;basic_service;user_msisdn;call_partner_identity;datetime;call_duration;longitude;latitude``

    ``basic_service`` takes one of the following values:

    - 11: telephony;
    - 12: emergency calls;
    - 21: short message (in)
    - 22: short message (out)

    Parameters
    ----------
    user_id : str
        ID of the user (filename)

    records_path : str
        Path of the directory all the user files.

    antennas_path : str, optional
        Path of the CSV file containing (antenna_id, latitude, longitude)
        values. This allows antennas to be mapped to their locations.

    attributes_path : str, optional
        Path of the directory containing attributes files (``key, value`` CSV
        file). Attributes can for instance be variables such as like, age, or
        gender. Attributes can be helpful to compute specific metrics.

    network : bool, optional
        If network is True, bandicoot loads the network of the user's
        correspondants from the same path. Defaults to False.

    describe : boolean
        If describe is True, it will print a description of the loaded user to
        the standard output.

    errors : boolean
        If errors is True, returns a tuple (user, errors), where user is the
        user object and errors are the records which could not be loaded.
    """

    def _parse(reader):
        records = []
        antennas = dict()

        for row in reader:
            direction = 'out' if row['call_record_type'] == '1' else 'in'
            interaction = 'call' if row[
                'basic_service'] in ['11', '12'] else 'text'
            contact = row['call_partner_identity']
            date = datetime.strptime(row['datetime'], "%Y-%m-%d %H:%M:%S")
            call_duration = float(row['call_duration']) if row[
                'call_duration'] != "" else None
            lon, lat = float(row['longitude']), float(row['latitude'])
            latlon = (lat, lon)

            antenna = None
            for key, value in antennas.items():
                if latlon == value:
                    antenna = key
                    break
            if antenna is None:
                antenna = len(antennas) + 1
                antennas[antenna] = latlon

            position = Position(antenna=antenna, location=latlon)

            record = Record(direction=direction,
                            interaction=interaction,
                            correspondent_id=contact,
                            call_duration=call_duration,
                            datetime=date,
                            position=position)
            records.append(record)

        return records, antennas

    user_records = os.path.join(records_path, user_id + ".csv")
    fields = ['call_record_type', 'basic_service', 'user_msisdn',
              'call_partner_identity', 'datetime', 'call_duration',
              'longitude', 'latitude']

    with open(user_records, 'r') as f:
        reader = csv.DictReader(f, delimiter=";", fieldnames=fields)
        records, antennas = _parse(reader)

    attributes = None
    if attributes_path is not None:
        user_attributes = os.path.join(attributes_path, user_id + '.csv')
        attributes = _load_attributes(user_attributes)

    recharges = None
    if recharges_path is not None:
        user_recharges = os.path.join(recharges_path, user_id + '.csv')
        recharges = _load_recharges(user_recharges)

    user, bad_records = load(user_id, records, antennas, attributes, recharges,
                             antennas_path, attributes_path, recharges_path,
                             describe=False, warnings=warnings)

    if network is True:
        user.network = _read_network(user, records_path, attributes_path,
                                     read_orange, antennas_path, warnings)
        user.recompute_missing_neighbors()

    if describe:
        user.describe()

    if errors:
        return user, bad_records
    return user
Load user records from a CSV file in *orange* format:

    ``call_record_type;basic_service;user_msisdn;call_partner_identity;datetime;call_duration;longitude;latitude``

    ``basic_service`` takes one of the following values:

    - 11: telephony;
    - 12: emergency calls;
    - 21: short message (in)
    - 22: short message (out)

    Parameters
    ----------
    user_id : str
        ID of the user (filename)

    records_path : str
        Path of the directory all the user files.

    antennas_path : str, optional
        Path of the CSV file containing (antenna_id, latitude, longitude)
        values. This allows antennas to be mapped to their locations.

    attributes_path : str, optional
        Path of the directory containing attributes files (``key, value`` CSV
        file). Attributes can for instance be variables such as like, age, or
        gender. Attributes can be helpful to compute specific metrics.

    network : bool, optional
        If network is True, bandicoot loads the network of the user's
        correspondants from the same path. Defaults to False.

    describe : boolean
        If describe is True, it will print a description of the loaded user to
        the standard output.

    errors : boolean
        If errors is True, returns a tuple (user, errors), where user is the
        user object and errors are the records which could not be loaded.