_assert_particle_type_tuple(::Tuple{}) = nothing _assert_particle_type_tuple(t::Tuple{AbstractParticleType,Vararg}) = _assert_particle_type_tuple(t[2:end]) _assert_particle_type_tuple(t::Any) = throw(InvalidInputError("invalid input, provide a tuple of AbstractParticleTypes to construct a GenericQEDProcess")) struct GenericQEDProcess{INT,OUTT} <: QEDbase.AbstractProcessDefinition where {INT<:Tuple,OUTT<:Tuple} incoming_particles::INT outgoing_particles::OUTT function GenericQEDProcess(in_particles::INT, out_particles::OUTT) where {INT<:Tuple,OUTT<:Tuple} _assert_particle_type_tuple(in_particles) _assert_particle_type_tuple(out_particles) return new{INT,OUTT}(in_particles, out_particles) end """ GenericQEDProcess(in_ph::Int, out_ph::Int, in_el::Int, out_el::Int, in_po::Int, out_po::Int) Convenience constructor from numbers of input/output photons, electrons and positrons. """ function GenericQEDProcess(in_ph::Int, out_ph::Int, in_el::Int, out_el::Int, in_po::Int, out_po::Int) in_p = ntuple(i -> i <= in_ph ? Photon() : i <= in_ph + in_el ? Electron() : Positron(), in_ph + in_el + in_po) out_p = ntuple(i -> i <= out_ph ? Photon() : i <= out_ph + out_el ? Electron() : Positron(), out_ph + out_el + out_po) return GenericQEDProcess(in_p, out_p) end end QEDprocesses.incoming_particles(proc::GenericQEDProcess{INT,OUTT}) where {INT,OUTT} = proc.incoming_particles QEDprocesses.outgoing_particles(proc::GenericQEDProcess{INT,OUTT}) where {INT,OUTT} = proc.outgoing_particles function isphysical(proc::GenericQEDProcess) return (number_particles(proc, Incoming(), Electron()) + number_particles(proc, Outgoing(), Positron()) == number_particles(proc, Incoming(), Positron()) + number_particles(proc, Outgoing(), Electron())) && number_particles(proc, Incoming()) + number_particles(proc, Outgoing()) >= 2 end function matrix_element(proc::GenericQEDProcess, psp::PhaseSpacePoint) return nothing end