def METHOD_NAME(self):
    output_spec = self._outputs()
    assert output_spec is not None
    outputs = output_spec.get()
    inputs = [
        (fieldname, None, getattr(self.inputs, fieldname))
        for fieldname in self._dictkeys
        if isdefined(getattr(self.inputs, fieldname))
    ]
    inputs.extend(
        [
            (fieldname, key, getattr(self.inputs, key))
            for fieldname, keys in self._keys.items()
            for key in keys
            if isdefined(getattr(self.inputs, key))
        ]
    )
    if len(inputs) == 0:
        outputs["resultdicts"] = []
        return outputs
    fieldnames, keys, values = map(list, zip(*inputs))
    # remove undefined
    undefined_indices = set()
    for i in range(len(values)):
        value = values[i]
        if isinstance(value, list):
            for j, v in enumerate(value):
                if not isdefined(v):
                    undefined_indices.add(j)
    for i in range(len(values)):
        value = values[i]
        if isinstance(value, list):
            for j in sorted(undefined_indices, reverse=True):
                del value[j]
    # determine broadcasting rule
    maxlen = 1
    nbroadcast = None
    for i in range(len(values)):
        if keys[i] in self._nobroadcastkeys:
            continue
        value = values[i]
        if isinstance(value, (list, tuple)):
            if all(isinstance(elem, (list, tuple)) for elem in value):
                size = len(ravel(value))
                lens = tuple(len(elem) for elem in value)
                if nbroadcast is None:
                    nbroadcast = lens
                else:
                    nbroadcast = tuple(max(a, b) for a, b in zip(lens, nbroadcast))
            else:
                size = len(value)
            if size > maxlen:
                maxlen = size
    # broadcast values if necessary
    for i in range(len(values)):
        if isinstance(values[i], tuple):
            values[i] = list(values[i])
        if not isinstance(values[i], list):
            values[i] = [values[i]]
        if len(values[i]) == 1:  # broadcasting
            values[i] *= maxlen
        if len(values[i]) == 0:
            values[i] = [None] * maxlen
        if len(values[i]) != maxlen and len(ravel(values[i])) != maxlen:
            if (
                nbroadcast is not None
                and len(values[i]) < maxlen
                and len(values[i]) == len(nbroadcast)
            ):
                values[i] = ravel([[v] * m for m, v in zip(nbroadcast, values[i])])
            else:
                raise ValueError(
                    f"Can't broadcast lists of lengths {len(values[i]):d} and {maxlen:d}"
                )
    # flatten
    for i in range(len(values)):
        if keys[i] in self._nobroadcastkeys:
            continue
        values[i] = ravel(values[i])
    # make resultdicts
    resultdicts = []
    for valuetupl in zip(*values):
        resultdict = defaultdict(dict)
        for f, k, v in zip(fieldnames, keys, valuetupl):
            if k is None:
                resultdict[f].update(v)
        # filter tags
        resultdict["tags"] = {
            k: v for k, v in resultdict["tags"].items() if k in resultdict_entities
        }
        for f, k, v in zip(fieldnames, keys, valuetupl):
            # actually add values
            if k is not None and v not in self._missingvalues:
                resultdict[f][k] = v
        resultdicts.append(resultdict)
    # apply composite attr rule
    for i in range(len(resultdicts)):
        newimages = dict()
        for k, v in resultdicts[i]["images"].items():
            m = composite_attr.fullmatch(k)
            if m is not None:  # apply rule
                newresultsdict = deepcopy(resultdicts[i])
                k = m.group("attr")
                if k in ["ortho"]:
                    newresultsdict["tags"]["stat"] = m.group("tag")
                else:
                    newresultsdict["tags"]["desc"] = m.group("tag")
                newresultsdict["images"] = {k: v}
                resultdicts.append(newresultsdict)
            else:
                newimages[k] = v
        resultdicts[i]["images"] = newimages
    # delete keys
    for f, keys in self._keys.items():
        for k in keys:
            if k in self._deletekeys:
                for i in range(len(resultdicts)):
                    if k in resultdicts[i][f]:
                        del resultdicts[i][f][k]
    # validate
    for i in range(len(resultdicts)):
        assert len(resultdict_schema.validate(resultdicts[i])) == 0
    outputs["resultdicts"] = resultdicts
    outputs["vals"] = resultdicts[0]["vals"]
    return outputs