def __init__(self, parent, on_gens, cartan_type=None,
                 virtualization=None, scaling_factors=None,
                 gens=None, check=True):
        """
        Construct a crystal morphism.

        TESTS::

            sage: B = crystals.infinity.Tableaux(['B',2])
            sage: C = crystals.infinity.NakajimaMonomials(['B',2])
            sage: psi = B.crystal_morphism(C.module_generators)

            sage: B = crystals.Tableaux(['B',3], shape=[1])
            sage: C = crystals.Tableaux(['D',4], shape=[2])
            sage: H = Hom(B, C)
            sage: psi = H(C.module_generators)
        """
        if cartan_type is None:
            cartan_type = parent.domain().cartan_type()
        if isinstance(on_gens, dict):
            gens = on_gens.keys()
        I = cartan_type.index_set()
        if gens is None:
            if cartan_type == parent.domain().cartan_type():
                gens = parent.domain().highest_weight_vectors()
            else:
                gens = tuple(x for x in parent.domain() if x.is_highest_weight(I))
            self._hw_gens = True
        elif check:
            self._hw_gens = all(x.is_highest_weight(I) for x in gens)
        else:
            self._hw_gens = False
        CrystalMorphismByGenerators.__init__(self, parent, on_gens, cartan_type,
                                             virtualization, scaling_factors,
                                             gens, check)
    def __init__(self, parent, on_gens, cartan_type=None,
                 virtualization=None, scaling_factors=None,
                 gens=None, check=True):
        """
        Construct a crystal morphism.

        TESTS::

            sage: B = crystals.infinity.Tableaux(['B',2])
            sage: C = crystals.infinity.NakajimaMonomials(['B',2])
            sage: psi = B.crystal_morphism(C.module_generators)

            sage: B = crystals.Tableaux(['B',3], shape=[1])
            sage: C = crystals.Tableaux(['D',4], shape=[2])
            sage: H = Hom(B, C)
            sage: psi = H(C.module_generators)
        """
        if cartan_type is None:
            cartan_type = parent.domain().cartan_type()
        if isinstance(on_gens, dict):
            gens = on_gens.keys()
        I = cartan_type.index_set()
        if gens is None:
            if cartan_type == parent.domain().cartan_type():
                gens = parent.domain().highest_weight_vectors()
            else:
                gens = tuple(x for x in parent.domain() if x.is_highest_weight(I))
            self._hw_gens = True
        elif check:
            self._hw_gens = all(x.is_highest_weight(I) for x in gens)
        else:
            self._hw_gens = False
        CrystalMorphismByGenerators.__init__(self, parent, on_gens, cartan_type,
                                             virtualization, scaling_factors,
                                             gens, check)
    def _call_(self, x):
        """
        Return the image of ``x`` under ``self``.

        TESTS::

            sage: B = crystals.infinity.Tableaux(['B',2])
            sage: C = crystals.infinity.NakajimaMonomials(['B',2])
            sage: psi = B.crystal_morphism(C.module_generators)
            sage: b = B.highest_weight_vector()
            sage: psi(b)
            1
            sage: c = psi(b.f_string([1,1,1,2,2,1,2,2])); c
            Y(1,0)^-4 Y(2,0)^4 Y(2,1)^-4
            sage: c == C.highest_weight_vector().f_string([1,1,1,2,2,1,2,2])
            True

            sage: B = crystals.Tableaux(['B',3], shape=[1])
            sage: C = crystals.Tableaux(['D',4], shape=[2])
            sage: H = Hom(B, C)
            sage: psi = H(C.module_generators)
            sage: psi(B.module_generators[0])
            [[1, 1]]

        We check with the morphism defined on the lowest weight vector::

            sage: B = crystals.Tableaux(['A',2], shape=[1])
            sage: La = RootSystem(['A',2]).weight_lattice().fundamental_weights()
            sage: T = crystals.elementary.T(['A',2], La[2])
            sage: Bp = T.tensor(B)
            sage: C = crystals.Tableaux(['A',2], shape=[2,1])
            sage: H = Hom(Bp, C)
            sage: x = C.module_generators[0].f_string([1,2])
            sage: psi = H({Bp.lowest_weight_vectors()[0]: x})
            sage: psi
            ['A', 2] Crystal morphism:
              From: Full tensor product of the crystals
                [The T crystal of type ['A', 2] and weight Lambda[2],
                 The crystal of tableaux of type ['A', 2] and shape(s) [[1]]]
              To:   The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]]
              Defn: [Lambda[2], [[3]]] |--> [[1, 3], [2]]
            sage: psi(Bp.highest_weight_vector())
            [[1, 1], [2]]
        """
        if not self._hw_gens:
            return CrystalMorphismByGenerators._call_(self, x)
        mg, path = x.to_highest_weight(self._cartan_type.index_set())
        cur = self._on_gens(mg)
        for i in reversed(path):
            if cur is None:
                return None
            s = []
            sf = self._scaling_factors[i]
            for j in self._virtualization[i]:
                s += [j] * sf
            cur = cur.f_string(s)
        return cur
    def _call_(self, x):
        """
        Return the image of ``x`` under ``self``.

        TESTS::

            sage: B = crystals.infinity.Tableaux(['B',2])
            sage: C = crystals.infinity.NakajimaMonomials(['B',2])
            sage: psi = B.crystal_morphism(C.module_generators)
            sage: b = B.highest_weight_vector()
            sage: psi(b)
            1
            sage: c = psi(b.f_string([1,1,1,2,2,1,2,2])); c
            Y(1,0)^-4 Y(2,0)^4 Y(2,1)^-4 
            sage: c == C.highest_weight_vector().f_string([1,1,1,2,2,1,2,2])
            True

            sage: B = crystals.Tableaux(['B',3], shape=[1])
            sage: C = crystals.Tableaux(['D',4], shape=[2])
            sage: H = Hom(B, C)
            sage: psi = H(C.module_generators)
            sage: psi(B.module_generators[0])
            [[1, 1]]

        We check with the morphism defined on the lowest weight vector::

            sage: B = crystals.Tableaux(['A',2], shape=[1])
            sage: La = RootSystem(['A',2]).weight_lattice().fundamental_weights()
            sage: T = crystals.elementary.T(['A',2], La[2])
            sage: Bp = T.tensor(B)
            sage: C = crystals.Tableaux(['A',2], shape=[2,1])
            sage: H = Hom(Bp, C)
            sage: x = C.module_generators[0].f_string([1,2])
            sage: psi = H({Bp.lowest_weight_vectors()[0]: x})
            sage: psi
            ['A', 2] Crystal morphism:
              From: Full tensor product of the crystals
                [The T crystal of type ['A', 2] and weight Lambda[2],
                 The crystal of tableaux of type ['A', 2] and shape(s) [[1]]]
              To:   The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]]
              Defn: [Lambda[2], [[3]]] |--> [2, 1, 3]
            sage: psi(Bp.highest_weight_vector())
            [[1, 1], [2]]
        """
        if not self._hw_gens:
            return CrystalMorphismByGenerators._call_(self, x)
        mg, path = x.to_highest_weight(self._cartan_type.index_set())
        cur = self._on_gens(mg)
        for i in reversed(path):
            if cur is None:
                return None
            s = []
            sf = self._scaling_factors[i]
            for j in self._virtualization[i]:
                s += [j]*sf
            cur = cur.f_string(s)
        return cur