'Access a lexical unit by its ID. luName, frameID, and frameName are used
only in the event that the LU does not have a file in the database
(which is the case for LUs with "Problem" status); in this case,
a placeholder LU is created which just contains its name, ID, and frame.
Usage examples:
>>> from nltk.corpus import framenet as fn
>>> fn.lu(256).name
\'foresee.v\'
>>> fn.lu(256).definition
\'COD: be aware of beforehand; predict.\'
>>> fn.lu(256).frame.name
\'Expectation\'
>>> pprint(list(map(PrettyDict, fn.lu(256).lexemes)))
[{\'POS\': \'V\', \'breakBefore\': \'false\', \'headword\': \'false\', \'name\': \'foresee\', \'order\': 1}]
>>> fn.lu(227).exemplars[23]
exemplar sentence (352962):
[sentNo] 0
[aPos] 59699508
<BLANKLINE>
[LU] (227) guess.v in Coming_to_believe
<BLANKLINE>
[frame] (23) Coming_to_believe
<BLANKLINE>
[annotationSet] 2 annotation sets
<BLANKLINE>
[POS] 18 tags
<BLANKLINE>
[POS_tagset] BNC
<BLANKLINE>
[GF] 3 relations
<BLANKLINE>
[PT] 3 phrases
<BLANKLINE>
[Other] 1 entry
<BLANKLINE>
[text] + [Target] + [FE]
<BLANKLINE>
When he was inside the house , Culley noticed the characteristic
Content
<BLANKLINE>
he would n\'t have guessed at .
Co                        C1 [Evidence:INI]
(Co=Cognizer, C1=Content)
<BLANKLINE>
<BLANKLINE>
The dict that is returned from this function will contain most of the
following information about the LU. Note that some LUs do not contain
all of these pieces of information - particularly \'totalAnnotated\' and
\'incorporatedFE\' may be missing in some LUs:
- \'name\'       : the name of the LU (e.g. \'merger.n\')
- \'definition\' : textual definition of the LU
- \'ID\'         : the internal ID number of the LU
- \'_type\'      : \'lu\'
- \'status\'     : e.g. \'Created\'
- \'frame\'      : Frame that this LU belongs to
- \'POS\'        : the part of speech of this LU (e.g. \'N\')
- \'totalAnnotated\' : total number of examples annotated with this LU
- \'incorporatedFE\' : FE that incorporates this LU (e.g. \'Ailment\')
- \'sentenceCount\'  : a dict with the following two keys:
- \'annotated\': number of sentences annotated with this LU
- \'total\'    : total number of sentences with this LU
- \'lexemes\'  : a list of dicts describing the lemma of this LU.
Each dict in the list contains these keys:
- \'POS\'     : part of speech e.g. \'N\'
- \'name\'    : either single-lexeme e.g. \'merger\' or
multi-lexeme e.g. \'a little\'
- \'order\': the order of the lexeme in the lemma (starting from 1)
- \'headword\': a boolean (\'true\' or \'false\')
- \'breakBefore\': Can this lexeme be separated from the previous lexeme?
Consider: "take over.v" as in:
Germany took over the Netherlands in 2 days.
Germany took the Netherlands over in 2 days.
In this case, \'breakBefore\' would be "true" for the lexeme
"over". Contrast this with "take after.v" as in:
Mary takes after her grandmother.
*Mary takes her grandmother after.
In this case, \'breakBefore\' would be "false" for the lexeme "after"
- \'lemmaID\'    : Can be used to connect lemmas in different LUs
- \'semTypes\'   : a list of semantic type objects for this LU
- \'subCorpus\'  : a list of subcorpora
- Each item in the list is a dict containing the following keys:
- \'name\' :
- \'sentence\' : a list of sentences in the subcorpus
- each item in the list is a dict with the following keys:
- \'ID\':
- \'sentNo\':
- \'text\': the text of the sentence
- \'aPos\':
- \'annotationSet\': a list of annotation sets
- each item in the list is a dict with the following keys:
- \'ID\':
- \'status\':
- \'layer\': a list of layers
- each layer is a dict containing the following keys:
- \'name\': layer name (e.g. \'BNC\')
- \'rank\':
- \'label\': a list of labels for the layer
- each label is a dict containing the following keys:
- \'start\': start pos of label in sentence \'text\' (0-based)
- \'end\': end pos of label in sentence \'text\' (0-based)
- \'name\': name of label (e.g. \'NN1\')
Under the hood, this implementation looks up the lexical unit information
in the *frame* definition file. That file does not contain
corpus annotations, so the LU files will be accessed on demand if those are
needed. In principle, valence patterns could be loaded here too,
though these are not currently supported.
:param fn_luid: The id number of the lexical unit
:type fn_luid: int
:param ignorekeys: The keys to ignore. These keys will not be
included in the output. (optional)
:type ignorekeys: list(str)
:return: All information about the lexical unit
:rtype: dict'

def lu(self, fn_luid, ignorekeys=[], luName=None, frameID=None, frameName=None):

    if (not self._lu_idx):
        self._buildluindex()
    OOV = object()
    luinfo = self._lu_idx.get(fn_luid, OOV)
    if (luinfo is OOV):
        self._warn(u'LU    ID    not    found:    {0}    ({1})    in    {2}    ({3})'.format(luName, fn_luid, frameName, frameID))
        luinfo = AttrDict({u'_type': u'lu', u'ID': fn_luid, u'name': luName, u'frameID': frameID, u'status': u'Problem'})
        f = self.frame_by_id(luinfo.frameID)
        assert (f.name == frameName), (f.name, frameName)
        luinfo[u'frame'] = f
        self._lu_idx[fn_luid] = luinfo
    elif (u'_type' not in luinfo):
        f = self.frame_by_id(luinfo.frameID)
        luinfo = self._lu_idx[fn_luid]
    if ignorekeys:
        return AttrDict(dict(((k, v) for (k, v) in luinfo.items() if (k not in ignorekeys))))
    return luinfo
