Commit d38ea91c authored by Roelofsen, Hans's avatar Roelofsen, Hans
Browse files

Merge branch 'workingHans' into 'master'

Working hans

See merge request !9
parents 6499858e 284ec736
import pandas as pd
import os
import pathlib
import sys
sys.path.append('..')
class TabularSpecies:
"""
Class holding pandas data frame and helper dicts on all MNP species
"""
def __init__(self):
filepath = pathlib.Path(__file__)
# De volledige Species tabel als Pandas dataframe
benb_dir = os.path.dirname(os.path.dirname(filepath))
self.df = pd.read_csv(os.path.join(benb_dir, r'resources\mnp_species.csv'), sep=',', comment='#')
# Dictionaries tussen code, lokale naam, wetenschappelijke naam
self.code2local = dict(zip(self.df.Species_code, self.df.Local_name))
self.local2code = dict(zip(self.df.Local_name, self.df.Species_code))
self.code2scientific = dict(zip(self.df.Species_code, self.df.Scientific_name))
self.scientific2code = dict(zip(self.df.Scientific_name, self.df.Species_code))
self.local2scientific = dict(zip(self.df.Local_name, self.df.Scientific_name))
self.scientific2local = dict(zip(self.df.Scientific_name, self.df.Local_name))
self.code2taxon = dict(zip(self.df.Species_code, self.df.taxon))
# Dictionaries to self, is usefull sometimes. Trust me...
self.local2local = dict(zip(self.df.Local_name, self.df.Local_name))
self.code2code = dict(zip(self.df.Species_code, self.df.Species_code))
self.scientific2scientific = dict(zip(self.df.Scientific_name, self.df.Scientific_name))
# Dict between species code and boolean species list
self.code2sel468 = dict(zip(self.df.Species_code, self.df.sel468.map({1: True, 0: False})))
self.code2selall = dict(zip(self.df.Species_code, self.df.selall.map({1: True, 0: False})))
self.code2sel281 = dict(zip(self.df.Species_code, self.df.sel281.map({1: True, 0: False})))
self.code2sel146 = dict(zip(self.df.Species_code, self.df.sel146.map({1: True, 0: False})))
class IndividualSpecies:
"""
Class for holding properties of a single species instance.
Hans Roelofsen, WEnR, 12 jan 2022
"""
def __init__(self, x):
"""
Initiate for a species.
:param x: species code, local name or scientific name
"""
species_tab = TabularSpecies()
species_identifiers_full = ['Species_code', 'Local_name', 'Scientific_name']
species_identifiers_brief = ['code', 'local', 'scientific']
try:
# Determine if X is a species code, local name, scientific name or not-existing
isin = [x in getattr(species_tab.df, col).values for col
in species_identifiers_full].index(True)
typer = species_identifiers_brief[isin]
except ValueError:
print('{} is not a recognized species'.format(x))
raise
self.taxondict = {'S02': 'V', 'S06': 'E', 'S09': 'P'}
# Set all relevant attributes
self.code = getattr(species_tab, '{}2code'.format(typer))[x] # Species code
self.local = getattr(species_tab, '{}2local'.format(typer))[x] # Species local name
self.scientific = getattr(species_tab, '{}2scientific'.format(typer))[x] # Species Scientific name
self.taxon = self.taxondict[self.code[:3]]
self.sel281 = species_tab.code2sel281[self.code] # boolean, species is part of 281 selection?
self.sel468 = species_tab.code2sel468[self.code] # idem for 468 selection
self.sel146 = species_tab.code2sel146[self.code] # idem foo 146 selection
self.selall = species_tab.code2selall[self.code] # catch all
self.groupinfo = '146:{0} - 281:{1} - 468:{2}'.format(self.sel146, self.sel281, self.sel468)
\ No newline at end of file
"""
python program for quering MNP draagkracht file
Hans Roelofsen, jan 2022
"""
import pandas as pd
import os
from fix_bt import fix_bt
from snl_beheertypen import get_snl_beheertypen_list
from snl_beheertypen import btcode2description
from Classes import Species as species
# from Classes.Species import TabSpeciesInstance as mnps
species_table = species.TabularSpecies()
class DraagKracht:
def __init__(self):
self.dkdir = r'W:\PROJECTS\QMAR\MNP-SNL-ParameterSet\Parameters_v05_2021_04_08'
self.defaultdk = r'03_MNP_versie5_par_density_factors_BT2021_v3.csv'
self.snl_bt = get_snl_beheertypen_list(of='full')
self.use_default = True
self.bt_column = 'Land_type_code'
self.dk = None
def read_dk(self, dk_file='default', bt_column=None):
"""
Read a draagkrachten file
:param dk_file: name of a draagrkachten file
:param bt_column: name of column in non-default file with BT codes
:return: pd dataframe
"""
if dk_file != 'default':
self.use_default = False
self.bt_column = bt_column
target = dk_file
else:
target = self.defaultdk
setattr(self, "dk", pd.read_csv(os.path.join(self.dkdir, target)))
def query4bt(self, bt_lst: list, of, sp_sel='281'):
"""
query the draagkrachten for a specific beheertype
:param bt_lst: beheertype code
:param of: output format
:param sp_sel: use which species list? 1018, 468 or 281?
:return: str to stdout
"""
for bt in bt_lst:
query = '({0} in {1}) and selection == True'.format(self.bt_column, [fix_bt(bt, as_mnp=True)])
sel = self.dk.assign(selection=self.dk.Species_code.map(getattr(species_table, 'code2sel{}'.format(sp_sel)))) \
.query(query)
counts = sel.Species_code.map(species_table.code2taxon).value_counts()
print('{0}-{1}: {2} vogel, {3} vlinder {4} plant. {5} total (out of {6}).'\
.format(bt, btcode2description(bt), counts.get('V', 0), counts.get('E', 0), counts.get('P', 0),
sel.shape[0], sp_sel if sp_sel != 'all' else '1081'))
if of == 'full':
print(sel.assign(local=sel.Species_code.map(species_table.code2local),
taxon=sel.Species_code.map(species_table.code2taxon))\
.sort_values(by=['taxon', 'local']) \
.loc[:, ['Species_code', 'taxon', 'Land_type_quality', 'local']] \
.to_csv(sep='\t', index=False, header=False))
def query4species(self, species_lst: list, of):
"""
query draagkrachten for one or more species
:param species_lst:
:param of:
:return:
"""
for x in species_lst:
sp = species.IndividualSpecies(x)
query = 'Species_code in ["{0}"]'.format(sp.code)
sel = self.dk.query(query)
print("{0} ({1}-{2}. Listed in: {3}): {4} beheertypen".format(sp.local, sp.scientific, sp.code,
sp.groupinfo, sel.shape[0]))
if of == 'full':
print(sel.assign(desc=getattr(sel, self.bt_column).map(btcode2description)) \
.loc[:, ['Land_type_quality', self.bt_column, 'desc']] \
.sort_values(by=self.bt_column) \
.to_csv(sep='\t', index=False, header=False))
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--qbt', nargs='+', type=str)
parser.add_argument('--qsp', nargs='+', type=str)
parser.add_argument('--of', choices=['full', 'sparse'], default='full')
parser.add_argument('--sp_list', choices=['281', '468', '146', 'all'], default='281', type=str)
args = parser.parse_args()
hans = DraagKracht()
hans.read_dk()
if args.qbt:
hans.query4bt(bt_lst=args.qbt, of=args.of, sp_sel=args.sp_list)
if args.qsp:
hans.query4species(species_lst=args.qsp, of=args.of)
d = {'S02': 'V',
'S06': 'E',
'S09': 'P'}
full = pd.read_csv(r'w:\PROJECTS\QMAR\MNP-SNL-ParameterSet\Parameters_v06_2019_12_09\01_Base_species_name.csv', sep=',', comment='#')
full.set_index(keys='Species_code', drop=False, inplace=True)
full['taxon'] = full.index.str.slice(0,3).map(d)
sel468 = pd.read_csv(r'W:\PROJECTS\QMAR\MNP-SNL-ParameterSet\Parameters_v05_2021_04_08\09_MNP_versie4_Group_Species_valid model_468.csv', sep=',', index_col='Species_code')
sel281 = pd.read_csv(r'W:\PROJECTS\QMAR\MNP-SNL-ParameterSet\Parameters_v05_2021_04_08\09_MNP_versie4_Species_group_valid_model_280.csv', sep=',', index_col='Species_code')
sel146 = pd.read_csv(r'W:\PROJECTS\QMAR\MNP-SNL-ParameterSet\Parameters_v06_2019_12_09\09_MNP_versie4_Species_group_valid_model_typisch_146.csv', sep=',', index_col='Species_code')
in468 = full.index.intersection(sel468.index)
in281 = full.index.intersection(sel281.index)
in146 = full.index.intersection(sel146.index)
full.loc[:, 'sel468'] = 0
full.loc[in468, 'sel468'] = 1
full.loc[:, 'sel281'] = 0
full.loc[in281, 'sel281'] = 1
full.loc[:, 'sel146'] = 0
full.loc[in146, 'sel146'] = 1
full.loc[:, 'sel1018'] = 1
full.loc[:, 'selall'] = 1
full.to_clipboard(sep=',', index=False)
import numbers import numbers
def fix_bt(code_in, as_mnp=False):
def fix_bt(code_in, as_mnp=False, verbose=False, strict=True):
""" """
Parser for Beheertype codes to repair abbreviated codes and/or MNP extension Parser for Beheertype codes to repair abbreviated codes and/or MNP extension
eg. 02.01 --> N02.01 if as_mnp==False eg. 02.01 --> N02.01 if as_mnp==False
...@@ -17,44 +18,61 @@ def fix_bt(code_in, as_mnp=False): ...@@ -17,44 +18,61 @@ def fix_bt(code_in, as_mnp=False):
N04.02.00 is equivalent to N04.02 N04.02.00 is equivalent to N04.02
:param code_in: beheertypecode in any format :param code_in: beheertypecode in any format
:param as_mnp: return MNP style beheertypecode, default=False :param as_mnp: return MNP style beheertypecode, default=False
:param verbose: verbose feedback
:param strict: raise error if bt code is unexpected
:return: beheertypecode :return: beheertypecode
""" """
if verbose:
print('from {}'.format(code_in), end=' ')
if isinstance(code_in, numbers.Number): if isinstance(code_in, numbers.Number):
code_in = str(code_in) code_in = str(code_in)
# Identify parts of code # Identify parts of code
parts = code_in.split(".") parts = code_in.split(".")
if len(parts) == 1: if len(parts) == 1:
raise AssertionError("Unexpected BT code: {}".format(code_in)) if strict:
raise AssertionError("1. Unexpected BT code: {}".format(code_in))
else:
return None
elif len(parts) == 2: elif len(parts) == 2:
top, sub = parts top, sub = parts
neer = None neer = None
elif len(parts) == 3: elif len(parts) == 3:
top, sub, neer = parts top, sub, neer = parts
else: else:
raise AssertionError("Unexpected BT code: {}".format(code_in)) if strict:
raise AssertionError("2. Unexpected BT code: {}".format(code_in))
else:
return None
# Verify TOP and add "N" is required # Verify TOP and add "N" is required
if top.isdigit(): assert top[0].upper() in ['N', 'W', 'S', 'T', 'A', 'L'], "3. Unexpected BT Code: {}".format(code_in)
top = "N{0}".format(top.zfill(2)) if top[0].islower():
else: top = top.capitalize()
assert top[0].isupper(), "Unexpected BT Code format: {}".format(code_in) assert top[1].isdigit(), '3. Unexpected BT code: {}'.format(code_in)
assert top[2].isdigit(), '3. Unexpected BT code: {}'.format(code_in)
assert len(top) == 3, "3. Unexpected BT Code: {}".format(code_in)
# Verify SUB # Verify SUB
assert sub.isdigit and len(sub) == 2, "Unexpected BT Code format: {}".format(code_in) assert sub.isdigit and len(sub) == 2, "4. Unexpected BT Code: {}".format(code_in)
# Verify NEER and check if it is neergeschaald or not # Verify NEER and check if it is neergeschaald or not
keep_neer = False keep_neer = False
if neer: if neer:
assert neer.isdigit and len(neer) == 2, "Unexpected BT Code format: {}".format(code_in) assert neer.isdigit and len(neer) == 2, "5. Unexpected BT Code: {}".format(code_in)
if int(neer) > 0: if int(neer) > 0:
keep_neer = True keep_neer = True
# Construct output # Construct output
head = "{}.{}".format(top, sub) head = "{}.{}".format(top, sub)
if keep_neer: if keep_neer:
return "{}.{}".format(head, neer) output = "{}.{}".format(head, neer)
elif as_mnp: elif as_mnp:
return "{}.00".format(head) output = "{}.00".format(head)
else: else:
return head output = head
if verbose:
print('to {}'.format(output))
return output
\ No newline at end of file
"""
Module to read MNP species CSV tab and provide several helper dictionaries
"""
import pandas as pd
import os
import pathlib
filepath = pathlib.Path(__file__)
# De volledige Species tabel als Pandas dataframe
species_tab = pd.read_csv(os.path.join(os.path.dirname(filepath), r'resources\mnp_species.csv'), sep=',', comment='#')
# Dictionaries tussen code, lokale naam, wetenschappelijke naam
code2local = dict(zip(species_tab.Species_code, species_tab.Local_name))
local2code = dict(zip(species_tab.Local_name, species_tab.Species_code))
code2scientific = dict(zip(species_tab.Species_code, species_tab.Scientific_name))
scientific2code = dict(zip(species_tab.Scientific_name, species_tab.Species_code))
local2scientific = dict(zip(species_tab.Local_name, species_tab.Scientific_name))
scientific2local = dict(zip(species_tab.Scientific_name, species_tab.Local_name))
code2taxon = dict(zip(species_tab.Species_code, species_tab.taxon))
# Dictionaries to self, is usefull sometimes. Trust me...
local2local = dict(zip(species_tab.Local_name, species_tab.Local_name))
code2code = dict(zip(species_tab.Species_code, species_tab.Species_code))
scientific2scientific = dict(zip(species_tab.Scientific_name, species_tab.Scientific_name))
# Dict between species code and boolean species list
code2sel468 = dict(zip(species_tab.Species_code, species_tab.sel468.map({1: True, 0: False})))
code2sel281 = dict(zip(species_tab.Species_code, species_tab.sel281.map({1: True, 0: False})))
code2sel146 = dict(zip(species_tab.Species_code, species_tab.sel146.map({1: True, 0: False})))
code2selall = dict(zip(species_tab.Species_code, species_tab.selall.map({1: True, 0: False})))
This diff is collapsed.
...@@ -4,14 +4,31 @@ Hans Roelofsen, 14/07/2021 ...@@ -4,14 +4,31 @@ Hans Roelofsen, 14/07/2021
""" """
import os import os
from pathlib import Path import pathlib
import pandas as pd import pandas as pd
import sys
from fix_bt import fix_bt # this only works if the dir containing benb_utils has already been appended to
# sys.path
filepath = pathlib.Path(__file__)
def get_snl_beheertypen_list(benb_dir):
df = pd.read_csv(os.path.join(os.path.dirname(filepath), r'resources/snl_beheertypen.csv'), sep=',', comment='#', quotechar='"')
def get_snl_beheertypen_list(df=df, of='sparse'):
""" """
return snl beheertypen list as pandas df return snl beheertypen list as pandas df
:param benb_dir: directory of benb_utils :param benb_dir: directory of benb_utils
:return: pandas dataframe :return: pandas dataframe
""" """
os.chdir(benb_dir) mnp_codes = df.LAND_TYPE_CODE.apply(fix_bt, as_mnp=True)
return pd.read_csv(r'./resources/snl_beheertypen.csv', sep=',', comment='#', quotechar='"') return {'full': df.assign(mnp_code=mnp_codes),
\ No newline at end of file 'sparse': df}[of]
def btcode2description(code):
# Note: dit hoeft niet perse in een functie te staan.
try:
return dict(zip(df.LAND_TYPE_CODE.apply(fix_bt, as_mnp=True),
df.LST_NAME))[fix_bt(code, as_mnp=True)]
except KeyError as e:
print('\n{} is not a valid beheertype\n'.format(code))
sys.exit(0)
\ No newline at end of file
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment