Exemplo n.º 1
0
def get_synonyms(ipni_id: str) -> list:
    """
    Fetches all synonyms for this IPNI ID from plantsoftheworldonline.org via their API. If the query returns, that this
    ID itself is a synonym, the corresponding accepted name is used instead for another query, which result is then
    returned. If the input is an empty string, this function returns immediately with an empty list. If anything fails,
    also an empty list is returned.

    :return: a list of synonyms, if found any; an empty list otherwise
    """
    res = []
    if ipni_id is not '':
        print('Querying plantsoftheworldonline.org for synonyms of "{}"...'.
              format(ipni_id))
        try:
            lookup_res = powo.lookup(ipni_id)
        except RequestException as e:
            print('ERROR: Query failed: {}. Going directly to GTS.'.format(e),
                  file=sys.stderr)
        else:
            if lookup_res['taxonomicStatus'] == 'Accepted':
                if 'synonyms' in lookup_res.keys():
                    res = [syn['name'] for syn in lookup_res['synonyms']]
                    print('Retrieved list of {} synonyms: '.format(len(res)))
                    for r in res:
                        print(r)
                    print()
                else:
                    print('Retrieved list of 0 synonyms.')
            elif lookup_res['taxonomicStatus'] == 'Synonym':
                print(
                    'In fact, this itself is a synonym of accepted species {}. Looking up synonyms for that...'
                    .format(lookup_res['accepted']['name']))
                try:
                    res = [
                        syn['name'] for syn in powo.lookup(
                            lookup_res['accepted']['fqId'])['synonyms']
                    ]
                    if 'synonyms' in lookup_res.keys():
                        res = [syn['name'] for syn in lookup_res['synonyms']]
                        print('Retrieved {} synonyms: '.format(len(res)))
                        for r in res:
                            print(r)
                        print()
                    else:
                        print('Retrieved 0 synonyms.')
                except RequestException as e:
                    print('ERROR: Query failed: {}. Going directly to GTS.'.
                          format(e),
                          file=sys.stderr)

    return res
def get_synonyms(genus, species):

    p_query = {Name.genus: genus, Name.species: species}

    name = []
    synonyms = []

    results = ipni.search(p_query)
    spec = []
    try:
        for r in results:
            if r['rank'] == 'spec.':
                spec.append(r)
    except AttributeError:
        pass

    for s in spec:
        powo_result = powo.lookup(s['fqId'])
        try:
            for synonym in powo_result['synonyms']:
                synonyms.append(synonym)
        except KeyError:
            return None

    return synonyms
Exemplo n.º 3
0
def get_species_kew(fq_id):
    """Get the species information from kew"""
    result = powo.lookup(fq_id, include=['distribution'])
    return result
Exemplo n.º 4
0
def get_taxa_from_kew_databases(plant_name_pattern: str, local_results: list,
                                search_for_genus: bool):
    """searches term in kew's international plant name index (ipni) and plants of the world (powo) databases and
    returns results in web-format; ignores entries included in the local_results list"""

    # first step: search for ids in kew's international plant names index (ipni) which has more items than powo
    if not search_for_genus:
        ipni_search = ipni.search(plant_name_pattern)
    else:
        ipni_query = {Name.genus: plant_name_pattern, Name.rank: 'gen.'}
        ipni_search = ipni.search(ipni_query)
    if ipni_search.size() > 30:
        msg = f'Too many search results for search term "{plant_name_pattern}": {ipni_search.size()}'
        raise TooManyResultsError(msg)

    elif ipni_search.size() == 0:
        return []

    kew_results = []
    for item in ipni_search:

        # check if that item is already included in the local results
        if [
                r for r in local_results
                if not r['is_custom'] and r['fqId'] == item['fqId']
        ]:
            continue

        # build additional results from kew data
        result = {
            'source': SOURCE_KEW,
            'id': None,  # determined upon saving by database
            'count':
            None,  # count of plants assigned the taxon in local extensions
            'is_custom': False,
            'authors': item.get('authors'),
            'family': item.get('family'),
            'name': item.get('name'),
            'rank': item.get('rank'),
            'fqId': item['fqId'],  # ipni id
            'genus': item.get('genus'),
            'species': item.get('species'),
            'namePublishedInYear': item.get('publicationYear')
        }

        # add information from powo if available
        # powo uses the same id as ipni
        powo_lookup = powo.lookup(item.get('fqId'), include=['distribution'])
        if 'error' in powo_lookup:
            logger.warning(f'No kew powo result for fqId {item.get("fqId")}')
            result['synonym'] = False
            result['powo_id'] = None
        else:
            result['powo_id'] = item.get('fqId')
            if 'namePublishedInYear' in powo_lookup:
                result['namePublishedInYear'] = powo_lookup[
                    'namePublishedInYear']
            result['phylum'] = powo_lookup.get('phylum')
            result['synonym'] = powo_lookup.get('synonym')
            result['author'] = powo_lookup.get(
                'authors')  # overwrite as powo author has more information
            if powo_lookup.get('synonym'):
                try:
                    result[
                        'synonyms_concat'] = get_synonym_label_if_only_a_synonym(
                            powo_lookup['accepted']['name'])
                except KeyError:
                    result['synonyms_concat'] = 'Accepted: unknown'
            else:
                result['synonyms_concat'] = get_synonyms_concat(powo_lookup)

            result['distribution_concat'] = get_distribution_concat(
                powo_lookup)

        kew_results.append(result)
    logger.info(
        f'Found {len(kew_results)} results from ipni/powo search for search term "{plant_name_pattern}".'
    )
    return kew_results
Exemplo n.º 5
0
def copy_taxon_from_kew(fq_id: str, has_custom_name: bool,
                        name_incl_addition: str, db: Session):
    """try to find fqId in taxon table and return if existing;
    otherwise retrieve information from kew databases and create new extensions entry"""
    # make sure the entry really does not exist, yet
    # in case of custom name, the (conceptual) key consists of name + is_custom==True
    if has_custom_name:
        taxon = db.query(Taxon).filter(Taxon.name == name_incl_addition,
                                       Taxon.is_custom is True).first()
    # otherwise, the (conceptual) key consists of the fqId + is_custom==False
    else:
        taxon = db.query(Taxon).filter(Taxon.fq_id == fq_id,
                                       Taxon.is_custom is False).first()
    if taxon:
        logger.warning('Taxon unexpectedly found in database.')
        return taxon

    logger.info(f'Copying taxon {fq_id} from kew databases powo and ipni.')
    # get taxon information from pew databases ipni and powo
    # ipni always returns a result (otherwise we wouldn't come here), powo is optional
    ipni_lookup = ipni.lookup_name(fq_id)
    powo_lookup = powo.lookup(fq_id, include=['distribution'])
    if 'error' in powo_lookup:
        powo_lookup = None

    taxon = Taxon(name=name_incl_addition
                  if has_custom_name else ipni_lookup.get('name'),
                  is_custom=True if has_custom_name else False,
                  fq_id=fq_id,
                  powo_id=powo_lookup.get('fqId') if powo_lookup else None,
                  subsp=ipni_lookup.get('subsp'),
                  species=ipni_lookup.get('species'),
                  subgen=ipni_lookup.get('subgen'),
                  genus=ipni_lookup.get('genus'),
                  family=ipni_lookup.get('family'),
                  phylum=powo_lookup.get('phylum') if powo_lookup else None,
                  kingdom=powo_lookup.get('kingdom') if powo_lookup else None,
                  rank=ipni_lookup.get('rank'),
                  taxonomic_status=powo_lookup.get('taxonomicStatus')
                  if powo_lookup else None,
                  name_published_in_year=powo_lookup.get('namePublishedInYear')
                  if powo_lookup else ipni_lookup.get('publicationYear'),
                  synonym=powo_lookup.get('synonym') if powo_lookup else None,
                  authors=powo_lookup.get('authors')
                  if powo_lookup else ipni_lookup.get('authors'),
                  hybrid=ipni_lookup.get('hybrid'),
                  hybridgenus=ipni_lookup.get('hybridGenus'),
                  basionym=powo_lookup['basionym'].get('name')
                  if powo_lookup and 'basionym' in powo_lookup else None,
                  distribution_concat=get_distribution_concat(powo_lookup)
                  if powo_lookup else None)
    if powo_lookup and not powo_lookup.get('synonym'):
        taxon.synonyms_concat = get_synonyms_concat(powo_lookup)
    elif powo_lookup and powo_lookup.get('synonym'):
        taxon.synonyms_concat = get_synonym_label_if_only_a_synonym(
            powo_lookup['accepted']['name'])
    else:
        taxon.synonyms_concat = None

    # distribution
    dist = []
    if powo_lookup and 'distribution' in powo_lookup and powo_lookup[
            'distribution']:
        # collect native and introduced distribution into one list
        if 'natives' in powo_lookup['distribution']:
            dist.extend(powo_lookup['distribution']['natives'])
        if 'introduced' in powo_lookup['distribution']:
            dist.extend(powo_lookup['distribution']['introduced'])

    if not dist:
        logger.info(f'No distribution info found for {taxon.name}.')
    else:
        for area in dist:
            record = Distribution(name=area.get('name'),
                                  establishment=area.get('establishment'),
                                  feature_id=area.get('featureId'),
                                  tdwg_code=area.get('tdwgCode'),
                                  tdwg_level=area.get('tdwgLevel'))
            taxon.distribution.append(record)

        logger.info(f'Found {len(dist)} areas for {taxon.name}.')

    db.add(taxon)
    db.commit()  # upon commit (flush), the ids are determined
    logger.info(
        f'Retrieved data from kew databases and created taxon {taxon.name} in database.'
    )

    return taxon