def run(self, dag: DAGCircuit):
        """Run the measurement alignment pass on `dag`.

        Args:
            dag (DAGCircuit): DAG to be checked.

        Returns:
            DAGCircuit: DAG with consistent timing and op nodes annotated with duration.

        Raises:
            TranspilerError: If circuit is not scheduled.
        """
        time_unit = self.property_set["time_unit"]

        if not _check_alignment_required(dag, self.alignment, Measure):
            # return input as-is to avoid unnecessary scheduling.
            # because following procedure regenerate new DAGCircuit,
            # we should avoid continuing if not necessary from performance viewpoint.
            return dag

        # if circuit is not yet scheduled, schedule with ALAP method
        if dag.duration is None:
            raise TranspilerError(
                f"This circuit {dag.name} may involve a delay instruction violating the "
                "pulse controller alignment. To adjust instructions to "
                "right timing, you should call one of scheduling passes first. "
                "This is usually done by calling transpiler with scheduling_method='alap'."
            )

        # the following lines are basically copied from ASAPSchedule pass
        #
        # * some validations for non-scheduled nodes are dropped, since we assume scheduled input
        # * pad_with_delay is called only with non-delay node to avoid consecutive delay
        new_dag = dag._copy_circuit_metadata()

        qubit_time_available = defaultdict(int)  # to track op start time
        qubit_stop_times = defaultdict(int)  # to track delay start time for padding
        clbit_readable = defaultdict(int)
        clbit_writeable = defaultdict(int)

        def pad_with_delays(qubits: List[int], until, unit) -> None:
            """Pad idle time-slots in ``qubits`` with delays in ``unit`` until ``until``."""
            for q in qubits:
                if qubit_stop_times[q] < until:
                    idle_duration = until - qubit_stop_times[q]
                    new_dag.apply_operation_back(Delay(idle_duration, unit), [q])

        for node in dag.topological_op_nodes():
            # choose appropriate clbit available time depending on op
            clbit_time_available = (
                clbit_writeable if isinstance(node.op, Measure) else clbit_readable
            )
            # correction to change clbit start time to qubit start time
            delta = node.op.duration if isinstance(node.op, Measure) else 0
            start_time = max(
                itertools.chain(
                    (qubit_time_available[q] for q in node.qargs),
                    (clbit_time_available[c] - delta for c in node.cargs + node.op.condition_bits),
                )
            )

            if isinstance(node.op, Measure):
                if start_time % self.alignment != 0:
                    start_time = ((start_time // self.alignment) + 1) * self.alignment

            if not isinstance(node.op, Delay):  # exclude delays for combining consecutive delays
                pad_with_delays(node.qargs, until=start_time, unit=time_unit)
                new_dag.apply_operation_back(node.op, node.qargs, node.cargs)

            stop_time = start_time + node.op.duration
            # update time table
            for q in node.qargs:
                qubit_time_available[q] = stop_time
                if not isinstance(node.op, Delay):
                    qubit_stop_times[q] = stop_time
            for c in node.cargs:  # measure
                clbit_writeable[c] = clbit_readable[c] = stop_time
            for c in node.op.condition_bits:  # conditional op
                clbit_writeable[c] = max(start_time, clbit_writeable[c])

        working_qubits = qubit_time_available.keys()
        circuit_duration = max(qubit_time_available[q] for q in working_qubits)
        pad_with_delays(new_dag.qubits, until=circuit_duration, unit=time_unit)

        new_dag.name = dag.name
        new_dag.metadata = dag.metadata

        # set circuit duration and unit to indicate it is scheduled
        new_dag.duration = circuit_duration
        new_dag.unit = time_unit

        return new_dag