Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Separate draw_samples and draw_sequence #533

Merged
merged 32 commits into from
Jun 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
0f32556
separate draw_samples and draw_sequence
dakk Jun 7, 2023
daafc55
rebase
dakk Jun 7, 2023
4501e77
restore target rendering
dakk Jun 7, 2023
91166cf
fix linters and types
dakk Jun 7, 2023
2fb542d
move measurement drawing and draw_interp_pts to draw_sequenece
dakk Jun 8, 2023
76276e1
- add time_slots of type target to ChannelSamples
dakk Jun 9, 2023
9ee018f
Fix samples.py typing
dakk Jun 9, 2023
63ab9e4
remove useless comments
dakk Jun 9, 2023
807c8e8
- fix _seq_drawer parameters names
dakk Jun 9, 2023
0bcbf57
fix linting
dakk Jun 9, 2023
ab4f2e3
move optional register drawing to draw_samples
dakk Jun 9, 2023
09c580e
splitting of drawing of target regions
dakk Jun 12, 2023
1363f2c
fix linters
dakk Jun 12, 2023
b7b725f
move draw_phase_shifts outside the loop
dakk Jun 12, 2023
3f4afd4
remove duplicate code from draw_sequence
dakk Jun 12, 2023
6757303
separate draw_channel_content from draw_samples
dakk Jun 12, 2023
2bd97b6
restore _seq_drawer boxes definition position
dakk Jun 12, 2023
70b3d2c
minor edits on seq_drawer
dakk Jun 12, 2023
652484d
adapt draw_phase_area for using sampled_seq in _seq_drawer
dakk Jun 13, 2023
e89d060
- move gather_data to draw_channel_content
dakk Jun 13, 2023
0309a42
- add _basis_ref to SequenceSamples
dakk Jun 13, 2023
3f56a89
- move phase_str into _draw_channel_content
dakk Jun 13, 2023
69e9a1f
refactoring of _seq_drawer
dakk Jun 13, 2023
2a7cf7e
Refactoring of _seq_drawer.py
dakk Jun 13, 2023
ae3b974
fix typo
dakk Jun 13, 2023
4706247
fix EOM drawing in draw_sequence
dakk Jun 13, 2023
33b598e
remove useless if
dakk Jun 13, 2023
38834ab
- test_draw_samples
dakk Jun 16, 2023
f67d642
- add eom_start_buffers and eom_end_buffers in ChannelSamples
dakk Jun 19, 2023
a0c3692
preserve backward compatibility for _TargetSlot
dakk Jun 19, 2023
6c22203
Pin numpy version to < 1.25
dakk Jun 19, 2023
b39a25d
use eom_blocks for eom_intervals_ti creation
dakk Jun 19, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pulser-core/pulser/sampler/sampler.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,5 +56,6 @@ def sample(
list(seq.declared_channels.keys()),
samples_list,
seq.declared_channels,
seq._basis_ref,
**optionals,
)
45 changes: 41 additions & 4 deletions pulser-core/pulser/sampler/samples.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@
from pulser.channels.base_channel import Channel
from pulser.channels.eom import BaseEOM
from pulser.register import QubitId
from pulser.sequence._basis_ref import _QubitRef

if TYPE_CHECKING:
from pulser.sequence._schedule import _EOMSettings
from pulser.sequence._schedule import _EOMSettings, _TimeSlot

"""Literal constants for addressing."""
_GLOBAL = "Global"
Expand Down Expand Up @@ -58,7 +59,7 @@ def _default_to_regular(d: dict | defaultdict) -> dict:


@dataclass
class _TargetSlot:
class _PulseTargetSlot:
dakk marked this conversation as resolved.
Show resolved Hide resolved
"""Auxiliary class to store target information.

Recopy of the sequence._TimeSlot but without the unrelevant `type` field,
Expand Down Expand Up @@ -89,9 +90,11 @@ class ChannelSamples:
amp: np.ndarray
det: np.ndarray
phase: np.ndarray
slots: list[_TargetSlot] = field(default_factory=list)
slots: list[_PulseTargetSlot] = field(default_factory=list)
eom_blocks: list[_EOMSettings] = field(default_factory=list)
initial_targets: set[QubitId] = field(default_factory=set)
eom_start_buffers: list[tuple[int, int]] = field(default_factory=list)
eom_end_buffers: list[tuple[int, int]] = field(default_factory=list)
target_time_slots: list[_TimeSlot] = field(default_factory=list)
HGSilveri marked this conversation as resolved.
Show resolved Hide resolved

def __post_init__(self) -> None:
assert len(self.amp) == len(self.det) == len(self.phase)
Expand All @@ -102,6 +105,15 @@ def __post_init__(self) -> None:
for t1, t2 in zip(self.slots, self.slots[1:]):
assert t1.tf <= t2.ti # no overlaps on a given channel

@property
def initial_targets(self) -> set[QubitId]:
"""Returns the initial targets."""
return (
self.target_time_slots[0].targets
if self.target_time_slots
else set()
)

def extend_duration(self, new_duration: int) -> ChannelSamples:
"""Extends the duration of the samples.

Expand Down Expand Up @@ -160,6 +172,23 @@ def _generate_std_samples(self) -> ChannelSamples:

return replace(self, **new_samples)

def get_eom_mode_intervals(self) -> list[tuple[int, int]]:
"""Returns EOM mode intervals."""
return [
(
block.ti,
block.tf if block.tf is not None else self.duration,
)
for block in self.eom_blocks
]

def in_eom_mode(self, slot: _TimeSlot | _PulseTargetSlot) -> bool:
"""States if a time slot is inside an EOM mode block."""
return any(
start <= slot.ti < end
for start, end in self.get_eom_mode_intervals()
)

def modulate(
self, channel_obj: Channel, max_duration: Optional[int] = None
) -> ChannelSamples:
Expand Down Expand Up @@ -292,6 +321,9 @@ class SequenceSamples:
channels: list[str]
samples_list: list[ChannelSamples]
_ch_objs: dict[str, Channel]
_basis_ref: dict[str, dict[QubitId, _QubitRef]] = field(
default_factory=dict
)
_slm_mask: _SlmMask = field(default_factory=_SlmMask)
_magnetic_field: np.ndarray | None = None
_measurement: str | None = None
Expand Down Expand Up @@ -396,3 +428,8 @@ def __repr__(self) -> str:
for chname, cs in zip(self.channels, self.samples_list)
]
return "\n\n".join(blocks)


# This is just to preserve backwards compatibility after the renaming of
# _TargetSlot to _PulseTarget slot
_TargetSlot = _PulseTargetSlot
51 changes: 46 additions & 5 deletions pulser-core/pulser/sequence/_schedule.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
from pulser.channels.base_channel import Channel
from pulser.pulse import Pulse
from pulser.register.base_register import QubitId
from pulser.sampler.samples import ChannelSamples, _TargetSlot
from pulser.sampler.samples import ChannelSamples, _PulseTargetSlot
from pulser.waveforms import ConstantWaveform


Expand Down Expand Up @@ -137,8 +137,17 @@ def get_samples(
channel_slots = [s for s in self.slots if isinstance(s.type, Pulse)]
dt = self.get_duration()
amp, det, phase = np.zeros(dt), np.zeros(dt), np.zeros(dt)
slots: list[_TargetSlot] = []
initial_targets = self.slots[0].targets if self.slots else set()
slots: list[_PulseTargetSlot] = []
target_time_slots: list[_TimeSlot] = [
s for s in self.slots if s.type == "target"
]
# Extracting the EOM Buffers
eom_intervals_ti = [block.ti for block in self.eom_blocks]
nb_eom_intervals = len(eom_intervals_ti)
eom_start_buffers = [(0, 0) for _ in range(nb_eom_intervals)]
eom_end_buffers = [(0, 0) for _ in range(nb_eom_intervals)]
in_eom_mode = False
eom_block_n = -1

for ind, s in enumerate(channel_slots):
pulse = cast(Pulse, s.type)
Expand All @@ -156,7 +165,7 @@ def get_samples(
if ind < len(channel_slots) - 1
else fall_time
)
slots.append(_TargetSlot(s.ti, tf, s.targets))
slots.append(_PulseTargetSlot(s.ti, tf, s.targets))

if ignore_detuned_delay_phase and self.is_detuned_delay(pulse):
# The phase of detuned delays is not considered
Expand All @@ -182,8 +191,40 @@ def get_samples(
# the same, so the last phase is automatically kept till the end
phase[t_start:] = pulse.phase

# Create EOM start and end buffers
for s in self.slots:
if s.ti == -1:
continue

# If slot is not the first element in schedule
if self.in_eom_mode(s):
# EOM mode starts
if not in_eom_mode:
in_eom_mode = True
eom_block_n += 1
elif in_eom_mode:
# Buffer when EOM mode is disabled and next slot has 0 amp
in_eom_mode = False
if amp[s.ti] == 0:
eom_end_buffers[eom_block_n] = (s.ti, s.tf)
if (
eom_block_n + 1 < nb_eom_intervals
and s.tf == eom_intervals_ti[eom_block_n + 1]
and det[s.tf - 1]
== self.eom_blocks[eom_block_n + 1].detuning_off
):
# Buffer if next is eom and final det matches det_off
eom_start_buffers[eom_block_n + 1] = (s.ti, s.tf)

return ChannelSamples(
amp, det, phase, slots, self.eom_blocks, initial_targets
amp,
det,
phase,
slots,
self.eom_blocks,
eom_start_buffers,
eom_end_buffers,
target_time_slots,
)

@overload
Expand Down
Loading