From 0e896c4531c4947198659ff73b85e0a9d186eae2 Mon Sep 17 00:00:00 2001 From: Christopher Langfield Date: Mon, 12 Aug 2024 09:43:20 -0700 Subject: [PATCH 1/8] uhd --- src/neuropixel.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/neuropixel.py b/src/neuropixel.py index 1d8c7a0..68e88e6 100644 --- a/src/neuropixel.py +++ b/src/neuropixel.py @@ -4,6 +4,7 @@ from typing import Any import warnings import traceback +import numbers import scipy.signal import numpy as np @@ -60,7 +61,11 @@ NC = 384 SITES_COORDINATES: np.array # channel layouts for neuropixel probes as a function of the major version (1 or 2) -CHANNEL_GRID = {1: dict(DX=16, X0=11, DY=20, Y0=20), 2: dict(DX=32, X0=27, DY=15, Y0=20)} +CHANNEL_GRID = { + 1: dict(DX=16, X0=11, DY=20, Y0=20), + 2: dict(DX=32, X0=27, DY=15, Y0=20), + "uhd": dict(DX=6, X0=0, DY=6, Y0=0) +} def _deprecated_sites_coordinates() -> np.array: @@ -97,7 +102,8 @@ def xy2rc(x, y, version=1): :param version: neuropixel major version 1 or 2 :return: dictionary with keys x and y """ - grid = CHANNEL_GRID[np.floor(version)] + version = np.floor(version) if isinstance(version, numbers.Number) else version + grid = CHANNEL_GRID[version] col = (x - grid['X0']) / grid['DX'] row = (y - grid['Y0']) / grid['DY'] return {"col": col, "row": row} @@ -111,7 +117,8 @@ def rc2xy(row, col, version=1): :param version: neuropixel major version 1 or 2 :return: dictionary with keys x and y """ - grid = CHANNEL_GRID[np.floor(version)] + version = np.floor(version) if isinstance(version, numbers.Number) else version + grid = CHANNEL_GRID[version] x = col * grid['DX'] + grid['X0'] y = row * grid['DY'] + grid['Y0'] return {"x": x, "y": y} @@ -131,6 +138,9 @@ def dense_layout(version=1, nshank=1): if version == 1: # version 1 has a dense layout, checkerboard pattern ch.update({"col": np.tile(np.array([2, 0, 3, 1]), int(NC / 4))}) + elif version == "uhd": # UHD has 8 columns with square grid spacing + ch.update({"row": np.floor(np.arange(NC) / 8)}) + ch.update({"col": np.tile(np.arange(8), int(NC / 8))}) elif ( np.floor(version) == 2 and nshank == 1 ): # single shank NP1 has 2 columns in a dense patter From 98a4bace6242a6e4c30effc47880cbd8184ae83a Mon Sep 17 00:00:00 2001 From: Christopher Langfield Date: Mon, 12 Aug 2024 13:33:58 -0700 Subject: [PATCH 2/8] uhd adc --- src/neuropixel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/neuropixel.py b/src/neuropixel.py index 68e88e6..1d0af16 100644 --- a/src/neuropixel.py +++ b/src/neuropixel.py @@ -199,7 +199,7 @@ def adc_shifts(version=1, nc=NC): :param version: neuropixel major version 1 or 2 :param nc: number of channels """ - if version == 1: + if version == 1 or version == "uhd": adc_channels = 12 n_cycles = 13 # version 1 uses 32 ADC that sample 12 channels each From ce394bdf00197d5946c100a44dbb8e5eff6fee9a Mon Sep 17 00:00:00 2001 From: Christopher Langfield Date: Thu, 15 Aug 2024 08:20:45 -0700 Subject: [PATCH 3/8] probe geom tests --- src/tests/unit/cpu/test_neuropixel.py | 70 +++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/src/tests/unit/cpu/test_neuropixel.py b/src/tests/unit/cpu/test_neuropixel.py index 73e136d..e76cb1c 100644 --- a/src/tests/unit/cpu/test_neuropixel.py +++ b/src/tests/unit/cpu/test_neuropixel.py @@ -15,3 +15,73 @@ def test_adc_shifts(): h24 = neuropixel.trace_header(version=2.4) np.testing.assert_equal(h24["sample_shift"], h21["sample_shift"]) np.testing.assert_equal(np.unique(h21["sample_shift"] * 16), np.arange(16)) + # test ADC shifts uhd + hUHD = neuropixel.trace_header(version="uhd") + np.testing.assert_equal(hUHD["sample_shift"], h1["sample_shift"]) + + +def test_geom_np1(): + gt = dict( + ind=np.arange(384), + shank=np.zeros(384), + row=np.repeat(np.arange(192), 2), + col=np.tile(np.array([2, 0, 3, 1]), 96), + x=np.tile(np.array([43, 11, 59, 27]), 96), + y=np.repeat(np.arange(0, 3840, 20), 2) + 20 + ) + + h = neuropixel.trace_header(1) + for k, v in gt.items(): + np.testing.assert_equal(v, h[k]) + + +def test_geom_np2_1shank(): + gt = dict( + ind=np.arange(384), + shank=np.zeros(384), + row=np.repeat(np.arange(192), 2), + col=np.tile(np.array([0, 1]), 192), + x=np.tile(np.array([27, 59]), 192), + y=np.repeat(np.arange(0, 2880, 15), 2) + 20 + ) + + h = neuropixel.trace_header(2, 1) + for k, v in gt.items(): + np.testing.assert_equal(v, h[k]) + + +def test_geom_np2_4shank(): + depth_blocks = np.vstack( + [ + np.repeat(np.arange(24), 2), + np.repeat(np.arange(24, 48), 2) + ] + ) + row_ind = np.concatenate([depth_blocks[i] for i in [0, 0, 1, 1, 0, 0, 1, 1]]) + gt = dict( + ind=np.arange(384), + shank=np.repeat(np.array([0, 1, 0, 1, 2, 3, 2, 3]), 48), + row=row_ind, + col=np.tile(np.array([0, 1]), 192), + x=np.tile(np.array([27, 59]), 192), + y=row_ind * 15 + 20 + ) + + h = neuropixel.trace_header(2, 4) + for k, v in gt.items(): + np.testing.assert_equal(v, h[k]) + + +def test_geom_npultra(): + gt = dict( + ind=np.arange(384), + shank=np.zeros(384), + row=np.repeat(np.arange(48), 8), + col=np.tile(np.arange(8), 48), + x=np.tile(np.arange(0, 48, 6), 48), + y=np.repeat(np.arange(0, 288, 6), 8) + ) + + h = neuropixel.trace_header("uhd") + for k, v in gt.items(): + np.testing.assert_equal(v, h[k]) From da7bf202edfcd27a3dacb761c18eea05d4b83259 Mon Sep 17 00:00:00 2001 From: Christopher Langfield Date: Thu, 15 Aug 2024 09:32:29 -0700 Subject: [PATCH 4/8] src/spikeglx.py --- src/spikeglx.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/spikeglx.py b/src/spikeglx.py index a800f28..6417bbb 100644 --- a/src/spikeglx.py +++ b/src/spikeglx.py @@ -563,6 +563,8 @@ def _get_neuropixel_version_from_meta(md): # Neuropixel 2.0 four shank elif prb_type == 24 or prb_type == 2013: return "NP2.4" + elif prb_type == 1100: + return "NPultra" def _get_sync_trace_indices_from_meta(md): From 57ecc35b51fbe808d8d99aea6f670e75e76cea7e Mon Sep 17 00:00:00 2001 From: owinter Date: Wed, 21 Aug 2024 13:51:32 +0100 Subject: [PATCH 5/8] add channel label plotting capabilities to investigate npultra --- src/ibldsp/plots.py | 39 +++++++++++++++++++++++++++++++++++++++ src/ibldsp/voltage.py | 7 +++++-- 2 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 src/ibldsp/plots.py diff --git a/src/ibldsp/plots.py b/src/ibldsp/plots.py new file mode 100644 index 0000000..d4dd05a --- /dev/null +++ b/src/ibldsp/plots.py @@ -0,0 +1,39 @@ +import numpy as np +import matplotlib.pyplot as plt +import scipy.signal + + +def show_channels_labels(raw, fs, channel_labels, xfeats): + """ + Shows the features side by side a snippet of raw data + :param sr: + :return: + """ + nc, ns = raw.shape + ns_plot = np.minimum(ns, 3000) + sos_hp = scipy.signal.butter(**{"N": 3, "Wn": 300 / fs * 2, "btype": "highpass"}, output="sos") + butt = scipy.signal.sosfiltfilt(sos_hp, raw) + fig, ax = plt.subplots(1, 5, figsize=(14, 6), gridspec_kw={'width_ratios': [1, 1, 1, 4, .2]}) + ax[0].plot(xfeats['xcor_hf'], np.arange(nc)) + ax[0].plot(xfeats['xcor_hf'][iko := channel_labels == 1], np.arange(nc)[iko], 'r*') + ax[0].plot([- .5, -.5], [0, nc], 'r--') + ax[0].set(ylabel='channel #', xlabel='high coherence', ylim=[0, nc], title='a) dead channel') + ax[1].plot(xfeats['psd_hf'], np.arange(nc)) + ax[1].plot(xfeats['psd_hf'][iko := channel_labels == 2], np.arange(nc)[iko], 'r*') + ax[1].plot([.02, .02], [0, nc], 'r--') + + ax[1].set(yticklabels=[], xlabel='PSD', ylim=[0, nc], title='b) noisy channel') + ax[1].sharey(ax[0]) + ax[2].plot(xfeats['xcor_lf'], np.arange(nc)) + ax[2].plot(xfeats['xcor_lf'][iko := channel_labels == 3], np.arange(nc)[iko], 'r*') + ax[2].plot([-.75, -.75], [0, nc], 'r--') + ax[2].set(yticklabels=[], xlabel='low coherence', ylim=[0, nc], title='c) outside') + ax[2].sharey(ax[0]) + imkwargs = dict(origin='lower', cmap='PuOr', aspect='auto', vmin=-20, vmax=20, extent=[0, ns_plot / fs * 1e3, 0, nc]) + im = ax[3].imshow(butt[:, :ns_plot] * 1e6, **imkwargs) + ax[3].set(yticklabels=[], title='d) Raw data', xlabel='time (ms)', ylim=[0, nc]) + ax[3].grid(False) + ax[3].sharey(ax[0]) + plt.colorbar(im, cax=ax[4], shrink=0.8).ax.set(ylabel='(uV)') + fig.tight_layout() + return fig, ax diff --git a/src/ibldsp/voltage.py b/src/ibldsp/voltage.py index 0c27d35..e59496d 100644 --- a/src/ibldsp/voltage.py +++ b/src/ibldsp/voltage.py @@ -15,6 +15,7 @@ import ibldsp.fourier as fourier import ibldsp.utils as utils +import ibldsp.plots def agc(x, wl=0.5, si=0.002, epsilon=1e-8, gpu=False): @@ -639,7 +640,7 @@ def my_function(i_chunk, n_chunk): np.save(output_qc_path.joinpath("_iblqc_ephysSaturation.samples.npy"), saturation_data) -def detect_bad_channels(raw, fs, similarity_threshold=(-0.5, 1), psd_hf_threshold=None): +def detect_bad_channels(raw, fs, similarity_threshold=(-0.5, 1), psd_hf_threshold=None, display=False): """ Bad channels detection for Neuropixel probes Labels channels @@ -651,6 +652,7 @@ def detect_bad_channels(raw, fs, similarity_threshold=(-0.5, 1), psd_hf_threshol :param fs: sampling frequency :param similarity_threshold: :param psd_hf_threshold: + :param display: optinal (False) will show a plot of features alongside a raw data snippet :return: labels (numpy vector [nc]), xfeats: dictionary of features [nc] """ @@ -751,6 +753,8 @@ def nxcor(x, ref): ichannels[inoisy] = 2 # from ibllib.plots.figures import ephys_bad_channels # ephys_bad_channels(x, 30000, ichannels, xfeats) + if display: + ibldsp.plots.show_channels_labels(raw, fs, ichannels, xfeats) return ichannels, xfeats @@ -783,7 +787,6 @@ def detect_bad_channels_cbin(bin_file, n_batches=10, batch_duration=0.3, display if display: raw = sr[sl, :nc].TO from ibllib.plots.figures import ephys_bad_channels - ephys_bad_channels(raw, sr.fs, channel_flags, xfeats_med) return channel_flags From 4ad38197dc971b8b689d8bd15033476de17d9b7e Mon Sep 17 00:00:00 2001 From: owinter Date: Wed, 21 Aug 2024 14:29:33 +0100 Subject: [PATCH 6/8] adjust display parameters faulty channels --- src/ibldsp/plots.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/ibldsp/plots.py b/src/ibldsp/plots.py index d4dd05a..2973d98 100644 --- a/src/ibldsp/plots.py +++ b/src/ibldsp/plots.py @@ -11,9 +11,10 @@ def show_channels_labels(raw, fs, channel_labels, xfeats): """ nc, ns = raw.shape ns_plot = np.minimum(ns, 3000) + vaxis_uv = 75 sos_hp = scipy.signal.butter(**{"N": 3, "Wn": 300 / fs * 2, "btype": "highpass"}, output="sos") butt = scipy.signal.sosfiltfilt(sos_hp, raw) - fig, ax = plt.subplots(1, 5, figsize=(14, 6), gridspec_kw={'width_ratios': [1, 1, 1, 4, .2]}) + fig, ax = plt.subplots(1, 5, figsize=(18, 6), gridspec_kw={'width_ratios': [1, 1, 1, 8, .2]}) ax[0].plot(xfeats['xcor_hf'], np.arange(nc)) ax[0].plot(xfeats['xcor_hf'][iko := channel_labels == 1], np.arange(nc)[iko], 'r*') ax[0].plot([- .5, -.5], [0, nc], 'r--') @@ -29,8 +30,8 @@ def show_channels_labels(raw, fs, channel_labels, xfeats): ax[2].plot([-.75, -.75], [0, nc], 'r--') ax[2].set(yticklabels=[], xlabel='low coherence', ylim=[0, nc], title='c) outside') ax[2].sharey(ax[0]) - imkwargs = dict(origin='lower', cmap='PuOr', aspect='auto', vmin=-20, vmax=20, extent=[0, ns_plot / fs * 1e3, 0, nc]) - im = ax[3].imshow(butt[:, :ns_plot] * 1e6, **imkwargs) + im = ax[3].imshow(butt[:, :ns_plot] * 1e6, origin='lower', cmap='PuOr', aspect='auto', + vmin=-vaxis_uv, vmax=vaxis_uv, extent=[0, ns_plot / fs * 1e3, 0, nc]) ax[3].set(yticklabels=[], title='d) Raw data', xlabel='time (ms)', ylim=[0, nc]) ax[3].grid(False) ax[3].sharey(ax[0]) From 9daf9ccab2a4e0aa7143b52c483f2d6b171b79ec Mon Sep 17 00:00:00 2001 From: Christopher Langfield Date: Wed, 28 Aug 2024 18:41:14 -0700 Subject: [PATCH 7/8] npultra sample meta file --- src/neuropixel.py | 6 +++--- src/spikeglx.py | 2 +- src/tests/unit/cpu/test_neuropixel.py | 4 ++-- src/tests/unit/cpu/test_spikeglx.py | 17 +++++++++++++++++ 4 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/neuropixel.py b/src/neuropixel.py index 1d0af16..6cb2b0a 100644 --- a/src/neuropixel.py +++ b/src/neuropixel.py @@ -64,7 +64,7 @@ CHANNEL_GRID = { 1: dict(DX=16, X0=11, DY=20, Y0=20), 2: dict(DX=32, X0=27, DY=15, Y0=20), - "uhd": dict(DX=6, X0=0, DY=6, Y0=0) + "NPultra": dict(DX=6, X0=0, DY=6, Y0=0) } @@ -138,7 +138,7 @@ def dense_layout(version=1, nshank=1): if version == 1: # version 1 has a dense layout, checkerboard pattern ch.update({"col": np.tile(np.array([2, 0, 3, 1]), int(NC / 4))}) - elif version == "uhd": # UHD has 8 columns with square grid spacing + elif version == "NPultra": # NPultra has 8 columns with square grid spacing ch.update({"row": np.floor(np.arange(NC) / 8)}) ch.update({"col": np.tile(np.arange(8), int(NC / 8))}) elif ( @@ -199,7 +199,7 @@ def adc_shifts(version=1, nc=NC): :param version: neuropixel major version 1 or 2 :param nc: number of channels """ - if version == 1 or version == "uhd": + if version == 1 or version == "NPultra": adc_channels = 12 n_cycles = 13 # version 1 uses 32 ADC that sample 12 channels each diff --git a/src/spikeglx.py b/src/spikeglx.py index 6417bbb..f6a3c55 100644 --- a/src/spikeglx.py +++ b/src/spikeglx.py @@ -518,7 +518,7 @@ def _get_serial_number_from_meta(md): def _get_neuropixel_major_version_from_meta(md): - MAJOR_VERSION = {"3A": 1, "3B2": 1, "3B1": 1, "NP2.1": 2, "NP2.4": 2.4} + MAJOR_VERSION = {"3A": 1, "3B2": 1, "3B1": 1, "NP2.1": 2, "NP2.4": 2.4, "NPultra": "NPultra"} version = _get_neuropixel_version_from_meta(md) if version is not None: return MAJOR_VERSION[version] diff --git a/src/tests/unit/cpu/test_neuropixel.py b/src/tests/unit/cpu/test_neuropixel.py index e76cb1c..8043ad0 100644 --- a/src/tests/unit/cpu/test_neuropixel.py +++ b/src/tests/unit/cpu/test_neuropixel.py @@ -16,7 +16,7 @@ def test_adc_shifts(): np.testing.assert_equal(h24["sample_shift"], h21["sample_shift"]) np.testing.assert_equal(np.unique(h21["sample_shift"] * 16), np.arange(16)) # test ADC shifts uhd - hUHD = neuropixel.trace_header(version="uhd") + hUHD = neuropixel.trace_header(version="NPultra") np.testing.assert_equal(hUHD["sample_shift"], h1["sample_shift"]) @@ -82,6 +82,6 @@ def test_geom_npultra(): y=np.repeat(np.arange(0, 288, 6), 8) ) - h = neuropixel.trace_header("uhd") + h = neuropixel.trace_header("NPultra") for k, v in gt.items(): np.testing.assert_equal(v, h[k]) diff --git a/src/tests/unit/cpu/test_spikeglx.py b/src/tests/unit/cpu/test_spikeglx.py index cdcff66..99b7de7 100644 --- a/src/tests/unit/cpu/test_spikeglx.py +++ b/src/tests/unit/cpu/test_spikeglx.py @@ -404,6 +404,17 @@ def test_read_NP24(self): ) self.assert_read_glx(bin_3b) + def test_read_NPultra(self): + with tempfile.TemporaryDirectory(prefix="glx_test") as tdir: + bin_3b = spikeglx._mock_spikeglx_file( + Path(tdir).joinpath("sampleNPultra_g0_t0.imec0.ap.bin"), + self.workdir / "sampleNPultra_g0_t0.imec0.ap.meta", + ns=32, + nc=385, + sync_depth=16, + ) + self.assert_read_glx(bin_3b) + def test_check_ephys_file(self): self.tdir = tempfile.TemporaryDirectory(prefix="glx_test") self.addCleanup(self.tdir.cleanup) @@ -517,6 +528,12 @@ def testGetRevisionAndType(self): self.assertTrue(len(md.keys()) >= 37) if meta_data_file.name.split(".")[-2] in ["lf", "ap"]: + # NPultra: non-numerical + if "NPultra" in meta_data_file.name: + self.assertEqual("NPultra", spikeglx._get_neuropixel_version_from_meta(md)) + self.assertEqual("NPultra", spikeglx._get_neuropixel_major_version_from_meta(md)) + continue + # for ap and lf look for version number # test getting revision revision = meta_data_file.name[6:8] From dbc4987dba8fc9de05358548e7e8b6d4867d0a4c Mon Sep 17 00:00:00 2001 From: Christopher Langfield Date: Wed, 28 Aug 2024 18:42:00 -0700 Subject: [PATCH 8/8] fix fn --- .../sampleNPultra_g0_t0.imec0.ap.meta | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100755 src/tests/unit/cpu/fixtures/sampleNPultra_g0_t0.imec0.ap.meta diff --git a/src/tests/unit/cpu/fixtures/sampleNPultra_g0_t0.imec0.ap.meta b/src/tests/unit/cpu/fixtures/sampleNPultra_g0_t0.imec0.ap.meta new file mode 100755 index 0000000..f132946 --- /dev/null +++ b/src/tests/unit/cpu/fixtures/sampleNPultra_g0_t0.imec0.ap.meta @@ -0,0 +1,51 @@ +acqApLfSy=384,384,1 +appVersion=20201024 +fileCreateTime=2021-05-01T15:44:27 +fileName=D:/data/ZYE_0021/2021-05-01/p1_g0/p1_g0_t0.imec0.ap.bin +fileSHA1=F133F01D38ABF8DA6E5615237D146C7554F7ACD7 +fileSizeBytes=93331077840 +fileTimeSecs=4040.3064 +firstSample=89223960 +gateMode=Immediate +imAiRangeMax=0.6 +imAiRangeMin=-0.6 +imCalibrated=true +imDatApi=3.31 +imDatBs_fw=2.0.137 +imDatBsc_fw=3.2.176 +imDatBsc_hw=2.1 +imDatBsc_pn=NP2_QBSC_00 +imDatBsc_sn=483 +imDatFx_hw=4.13 +imDatFx_pn=NP2_FLEX_0 +imDatHs_fw=5.1 +imDatHs_pn=NP2_HS_30 +imDatHs_sn=986 +imDatPrb_dock=1 +imDatPrb_pn=NP1100 +imDatPrb_port=4 +imDatPrb_slot=3 +imDatPrb_sn=20088317081 +imDatPrb_type=1100 +imLEDEnable=false +imMaxInt=512 +imRoFile= +imSampRate=30000 +imStdby= +imTrgRising=true +imTrgSource=0 +nDataDirs=1 +nSavedChans=385 +snsApLfSy=384,0,1 +snsSaveChanSubset=0:383,768 +syncImInputSlot=3 +syncSourceIdx=0 +syncSourcePeriod=1 +trigMode=Immediate +typeImEnabled=1 +typeNiEnabled=0 +typeThis=imec +userNotes= +~imroTbl=(1100,384)(0 0 0 500 250 1)(1 0 0 500 250 1)(2 0 0 500 250 1)(3 0 0 500 250 1)(4 0 0 500 250 1)(5 0 0 500 250 1)(6 0 0 500 250 1)(7 0 0 500 250 1)(8 0 0 500 250 1)(9 0 0 500 250 1)(10 0 0 500 250 1)(11 0 0 500 250 1)(12 0 0 500 250 1)(13 0 0 500 250 1)(14 0 0 500 250 1)(15 0 0 500 250 1)(16 0 0 500 250 1)(17 0 0 500 250 1)(18 0 0 500 250 1)(19 0 0 500 250 1)(20 0 0 500 250 1)(21 0 0 500 250 1)(22 0 0 500 250 1)(23 0 0 500 250 1)(24 0 0 500 250 1)(25 0 0 500 250 1)(26 0 0 500 250 1)(27 0 0 500 250 1)(28 0 0 500 250 1)(29 0 0 500 250 1)(30 0 0 500 250 1)(31 0 0 500 250 1)(32 0 0 500 250 1)(33 0 0 500 250 1)(34 0 0 500 250 1)(35 0 0 500 250 1)(36 0 0 500 250 1)(37 0 0 500 250 1)(38 0 0 500 250 1)(39 0 0 500 250 1)(40 0 0 500 250 1)(41 0 0 500 250 1)(42 0 0 500 250 1)(43 0 0 500 250 1)(44 0 0 500 250 1)(45 0 0 500 250 1)(46 0 0 500 250 1)(47 0 0 500 250 1)(48 0 0 500 250 1)(49 0 0 500 250 1)(50 0 0 500 250 1)(51 0 0 500 250 1)(52 0 0 500 250 1)(53 0 0 500 250 1)(54 0 0 500 250 1)(55 0 0 500 250 1)(56 0 0 500 250 1)(57 0 0 500 250 1)(58 0 0 500 250 1)(59 0 0 500 250 1)(60 0 0 500 250 1)(61 0 0 500 250 1)(62 0 0 500 250 1)(63 0 0 500 250 1)(64 0 0 500 250 1)(65 0 0 500 250 1)(66 0 0 500 250 1)(67 0 0 500 250 1)(68 0 0 500 250 1)(69 0 0 500 250 1)(70 0 0 500 250 1)(71 0 0 500 250 1)(72 0 0 500 250 1)(73 0 0 500 250 1)(74 0 0 500 250 1)(75 0 0 500 250 1)(76 0 0 500 250 1)(77 0 0 500 250 1)(78 0 0 500 250 1)(79 0 0 500 250 1)(80 0 0 500 250 1)(81 0 0 500 250 1)(82 0 0 500 250 1)(83 0 0 500 250 1)(84 0 0 500 250 1)(85 0 0 500 250 1)(86 0 0 500 250 1)(87 0 0 500 250 1)(88 0 0 500 250 1)(89 0 0 500 250 1)(90 0 0 500 250 1)(91 0 0 500 250 1)(92 0 0 500 250 1)(93 0 0 500 250 1)(94 0 0 500 250 1)(95 0 0 500 250 1)(96 0 0 500 250 1)(97 0 0 500 250 1)(98 0 0 500 250 1)(99 0 0 500 250 1)(100 0 0 500 250 1)(101 0 0 500 250 1)(102 0 0 500 250 1)(103 0 0 500 250 1)(104 0 0 500 250 1)(105 0 0 500 250 1)(106 0 0 500 250 1)(107 0 0 500 250 1)(108 0 0 500 250 1)(109 0 0 500 250 1)(110 0 0 500 250 1)(111 0 0 500 250 1)(112 0 0 500 250 1)(113 0 0 500 250 1)(114 0 0 500 250 1)(115 0 0 500 250 1)(116 0 0 500 250 1)(117 0 0 500 250 1)(118 0 0 500 250 1)(119 0 0 500 250 1)(120 0 0 500 250 1)(121 0 0 500 250 1)(122 0 0 500 250 1)(123 0 0 500 250 1)(124 0 0 500 250 1)(125 0 0 500 250 1)(126 0 0 500 250 1)(127 0 0 500 250 1)(128 0 0 500 250 1)(129 0 0 500 250 1)(130 0 0 500 250 1)(131 0 0 500 250 1)(132 0 0 500 250 1)(133 0 0 500 250 1)(134 0 0 500 250 1)(135 0 0 500 250 1)(136 0 0 500 250 1)(137 0 0 500 250 1)(138 0 0 500 250 1)(139 0 0 500 250 1)(140 0 0 500 250 1)(141 0 0 500 250 1)(142 0 0 500 250 1)(143 0 0 500 250 1)(144 0 0 500 250 1)(145 0 0 500 250 1)(146 0 0 500 250 1)(147 0 0 500 250 1)(148 0 0 500 250 1)(149 0 0 500 250 1)(150 0 0 500 250 1)(151 0 0 500 250 1)(152 0 0 500 250 1)(153 0 0 500 250 1)(154 0 0 500 250 1)(155 0 0 500 250 1)(156 0 0 500 250 1)(157 0 0 500 250 1)(158 0 0 500 250 1)(159 0 0 500 250 1)(160 0 0 500 250 1)(161 0 0 500 250 1)(162 0 0 500 250 1)(163 0 0 500 250 1)(164 0 0 500 250 1)(165 0 0 500 250 1)(166 0 0 500 250 1)(167 0 0 500 250 1)(168 0 0 500 250 1)(169 0 0 500 250 1)(170 0 0 500 250 1)(171 0 0 500 250 1)(172 0 0 500 250 1)(173 0 0 500 250 1)(174 0 0 500 250 1)(175 0 0 500 250 1)(176 0 0 500 250 1)(177 0 0 500 250 1)(178 0 0 500 250 1)(179 0 0 500 250 1)(180 0 0 500 250 1)(181 0 0 500 250 1)(182 0 0 500 250 1)(183 0 0 500 250 1)(184 0 0 500 250 1)(185 0 0 500 250 1)(186 0 0 500 250 1)(187 0 0 500 250 1)(188 0 0 500 250 1)(189 0 0 500 250 1)(190 0 0 500 250 1)(191 0 0 500 250 1)(192 0 0 500 250 1)(193 0 0 500 250 1)(194 0 0 500 250 1)(195 0 0 500 250 1)(196 0 0 500 250 1)(197 0 0 500 250 1)(198 0 0 500 250 1)(199 0 0 500 250 1)(200 0 0 500 250 1)(201 0 0 500 250 1)(202 0 0 500 250 1)(203 0 0 500 250 1)(204 0 0 500 250 1)(205 0 0 500 250 1)(206 0 0 500 250 1)(207 0 0 500 250 1)(208 0 0 500 250 1)(209 0 0 500 250 1)(210 0 0 500 250 1)(211 0 0 500 250 1)(212 0 0 500 250 1)(213 0 0 500 250 1)(214 0 0 500 250 1)(215 0 0 500 250 1)(216 0 0 500 250 1)(217 0 0 500 250 1)(218 0 0 500 250 1)(219 0 0 500 250 1)(220 0 0 500 250 1)(221 0 0 500 250 1)(222 0 0 500 250 1)(223 0 0 500 250 1)(224 0 0 500 250 1)(225 0 0 500 250 1)(226 0 0 500 250 1)(227 0 0 500 250 1)(228 0 0 500 250 1)(229 0 0 500 250 1)(230 0 0 500 250 1)(231 0 0 500 250 1)(232 0 0 500 250 1)(233 0 0 500 250 1)(234 0 0 500 250 1)(235 0 0 500 250 1)(236 0 0 500 250 1)(237 0 0 500 250 1)(238 0 0 500 250 1)(239 0 0 500 250 1)(240 0 0 500 250 1)(241 0 0 500 250 1)(242 0 0 500 250 1)(243 0 0 500 250 1)(244 0 0 500 250 1)(245 0 0 500 250 1)(246 0 0 500 250 1)(247 0 0 500 250 1)(248 0 0 500 250 1)(249 0 0 500 250 1)(250 0 0 500 250 1)(251 0 0 500 250 1)(252 0 0 500 250 1)(253 0 0 500 250 1)(254 0 0 500 250 1)(255 0 0 500 250 1)(256 0 0 500 250 1)(257 0 0 500 250 1)(258 0 0 500 250 1)(259 0 0 500 250 1)(260 0 0 500 250 1)(261 0 0 500 250 1)(262 0 0 500 250 1)(263 0 0 500 250 1)(264 0 0 500 250 1)(265 0 0 500 250 1)(266 0 0 500 250 1)(267 0 0 500 250 1)(268 0 0 500 250 1)(269 0 0 500 250 1)(270 0 0 500 250 1)(271 0 0 500 250 1)(272 0 0 500 250 1)(273 0 0 500 250 1)(274 0 0 500 250 1)(275 0 0 500 250 1)(276 0 0 500 250 1)(277 0 0 500 250 1)(278 0 0 500 250 1)(279 0 0 500 250 1)(280 0 0 500 250 1)(281 0 0 500 250 1)(282 0 0 500 250 1)(283 0 0 500 250 1)(284 0 0 500 250 1)(285 0 0 500 250 1)(286 0 0 500 250 1)(287 0 0 500 250 1)(288 0 0 500 250 1)(289 0 0 500 250 1)(290 0 0 500 250 1)(291 0 0 500 250 1)(292 0 0 500 250 1)(293 0 0 500 250 1)(294 0 0 500 250 1)(295 0 0 500 250 1)(296 0 0 500 250 1)(297 0 0 500 250 1)(298 0 0 500 250 1)(299 0 0 500 250 1)(300 0 0 500 250 1)(301 0 0 500 250 1)(302 0 0 500 250 1)(303 0 0 500 250 1)(304 0 0 500 250 1)(305 0 0 500 250 1)(306 0 0 500 250 1)(307 0 0 500 250 1)(308 0 0 500 250 1)(309 0 0 500 250 1)(310 0 0 500 250 1)(311 0 0 500 250 1)(312 0 0 500 250 1)(313 0 0 500 250 1)(314 0 0 500 250 1)(315 0 0 500 250 1)(316 0 0 500 250 1)(317 0 0 500 250 1)(318 0 0 500 250 1)(319 0 0 500 250 1)(320 0 0 500 250 1)(321 0 0 500 250 1)(322 0 0 500 250 1)(323 0 0 500 250 1)(324 0 0 500 250 1)(325 0 0 500 250 1)(326 0 0 500 250 1)(327 0 0 500 250 1)(328 0 0 500 250 1)(329 0 0 500 250 1)(330 0 0 500 250 1)(331 0 0 500 250 1)(332 0 0 500 250 1)(333 0 0 500 250 1)(334 0 0 500 250 1)(335 0 0 500 250 1)(336 0 0 500 250 1)(337 0 0 500 250 1)(338 0 0 500 250 1)(339 0 0 500 250 1)(340 0 0 500 250 1)(341 0 0 500 250 1)(342 0 0 500 250 1)(343 0 0 500 250 1)(344 0 0 500 250 1)(345 0 0 500 250 1)(346 0 0 500 250 1)(347 0 0 500 250 1)(348 0 0 500 250 1)(349 0 0 500 250 1)(350 0 0 500 250 1)(351 0 0 500 250 1)(352 0 0 500 250 1)(353 0 0 500 250 1)(354 0 0 500 250 1)(355 0 0 500 250 1)(356 0 0 500 250 1)(357 0 0 500 250 1)(358 0 0 500 250 1)(359 0 0 500 250 1)(360 0 0 500 250 1)(361 0 0 500 250 1)(362 0 0 500 250 1)(363 0 0 500 250 1)(364 0 0 500 250 1)(365 0 0 500 250 1)(366 0 0 500 250 1)(367 0 0 500 250 1)(368 0 0 500 250 1)(369 0 0 500 250 1)(370 0 0 500 250 1)(371 0 0 500 250 1)(372 0 0 500 250 1)(373 0 0 500 250 1)(374 0 0 500 250 1)(375 0 0 500 250 1)(376 0 0 500 250 1)(377 0 0 500 250 1)(378 0 0 500 250 1)(379 0 0 500 250 1)(380 0 0 500 250 1)(381 0 0 500 250 1)(382 0 0 500 250 1)(383 0 0 500 250 1) +~snsChanMap=(384,384,1)(AP0;0:0)(AP1;1:1)(AP2;2:2)(AP3;3:3)(AP4;4:4)(AP5;5:5)(AP6;6:6)(AP7;7:7)(AP8;8:8)(AP9;9:9)(AP10;10:10)(AP11;11:11)(AP12;12:12)(AP13;13:13)(AP14;14:14)(AP15;15:15)(AP16;16:16)(AP17;17:17)(AP18;18:18)(AP19;19:19)(AP20;20:20)(AP21;21:21)(AP22;22:22)(AP23;23:23)(AP24;24:24)(AP25;25:25)(AP26;26:26)(AP27;27:27)(AP28;28:28)(AP29;29:29)(AP30;30:30)(AP31;31:31)(AP32;32:32)(AP33;33:33)(AP34;34:34)(AP35;35:35)(AP36;36:36)(AP37;37:37)(AP38;38:38)(AP39;39:39)(AP40;40:40)(AP41;41:41)(AP42;42:42)(AP43;43:43)(AP44;44:44)(AP45;45:45)(AP46;46:46)(AP47;47:47)(AP48;48:48)(AP49;49:49)(AP50;50:50)(AP51;51:51)(AP52;52:52)(AP53;53:53)(AP54;54:54)(AP55;55:55)(AP56;56:56)(AP57;57:57)(AP58;58:58)(AP59;59:59)(AP60;60:60)(AP61;61:61)(AP62;62:62)(AP63;63:63)(AP64;64:64)(AP65;65:65)(AP66;66:66)(AP67;67:67)(AP68;68:68)(AP69;69:69)(AP70;70:70)(AP71;71:71)(AP72;72:72)(AP73;73:73)(AP74;74:74)(AP75;75:75)(AP76;76:76)(AP77;77:77)(AP78;78:78)(AP79;79:79)(AP80;80:80)(AP81;81:81)(AP82;82:82)(AP83;83:83)(AP84;84:84)(AP85;85:85)(AP86;86:86)(AP87;87:87)(AP88;88:88)(AP89;89:89)(AP90;90:90)(AP91;91:91)(AP92;92:92)(AP93;93:93)(AP94;94:94)(AP95;95:95)(AP96;96:96)(AP97;97:97)(AP98;98:98)(AP99;99:99)(AP100;100:100)(AP101;101:101)(AP102;102:102)(AP103;103:103)(AP104;104:104)(AP105;105:105)(AP106;106:106)(AP107;107:107)(AP108;108:108)(AP109;109:109)(AP110;110:110)(AP111;111:111)(AP112;112:112)(AP113;113:113)(AP114;114:114)(AP115;115:115)(AP116;116:116)(AP117;117:117)(AP118;118:118)(AP119;119:119)(AP120;120:120)(AP121;121:121)(AP122;122:122)(AP123;123:123)(AP124;124:124)(AP125;125:125)(AP126;126:126)(AP127;127:127)(AP128;128:128)(AP129;129:129)(AP130;130:130)(AP131;131:131)(AP132;132:132)(AP133;133:133)(AP134;134:134)(AP135;135:135)(AP136;136:136)(AP137;137:137)(AP138;138:138)(AP139;139:139)(AP140;140:140)(AP141;141:141)(AP142;142:142)(AP143;143:143)(AP144;144:144)(AP145;145:145)(AP146;146:146)(AP147;147:147)(AP148;148:148)(AP149;149:149)(AP150;150:150)(AP151;151:151)(AP152;152:152)(AP153;153:153)(AP154;154:154)(AP155;155:155)(AP156;156:156)(AP157;157:157)(AP158;158:158)(AP159;159:159)(AP160;160:160)(AP161;161:161)(AP162;162:162)(AP163;163:163)(AP164;164:164)(AP165;165:165)(AP166;166:166)(AP167;167:167)(AP168;168:168)(AP169;169:169)(AP170;170:170)(AP171;171:171)(AP172;172:172)(AP173;173:173)(AP174;174:174)(AP175;175:175)(AP176;176:176)(AP177;177:177)(AP178;178:178)(AP179;179:179)(AP180;180:180)(AP181;181:181)(AP182;182:182)(AP183;183:183)(AP184;184:184)(AP185;185:185)(AP186;186:186)(AP187;187:187)(AP188;188:188)(AP189;189:189)(AP190;190:190)(AP191;191:191)(AP192;192:192)(AP193;193:193)(AP194;194:194)(AP195;195:195)(AP196;196:196)(AP197;197:197)(AP198;198:198)(AP199;199:199)(AP200;200:200)(AP201;201:201)(AP202;202:202)(AP203;203:203)(AP204;204:204)(AP205;205:205)(AP206;206:206)(AP207;207:207)(AP208;208:208)(AP209;209:209)(AP210;210:210)(AP211;211:211)(AP212;212:212)(AP213;213:213)(AP214;214:214)(AP215;215:215)(AP216;216:216)(AP217;217:217)(AP218;218:218)(AP219;219:219)(AP220;220:220)(AP221;221:221)(AP222;222:222)(AP223;223:223)(AP224;224:224)(AP225;225:225)(AP226;226:226)(AP227;227:227)(AP228;228:228)(AP229;229:229)(AP230;230:230)(AP231;231:231)(AP232;232:232)(AP233;233:233)(AP234;234:234)(AP235;235:235)(AP236;236:236)(AP237;237:237)(AP238;238:238)(AP239;239:239)(AP240;240:240)(AP241;241:241)(AP242;242:242)(AP243;243:243)(AP244;244:244)(AP245;245:245)(AP246;246:246)(AP247;247:247)(AP248;248:248)(AP249;249:249)(AP250;250:250)(AP251;251:251)(AP252;252:252)(AP253;253:253)(AP254;254:254)(AP255;255:255)(AP256;256:256)(AP257;257:257)(AP258;258:258)(AP259;259:259)(AP260;260:260)(AP261;261:261)(AP262;262:262)(AP263;263:263)(AP264;264:264)(AP265;265:265)(AP266;266:266)(AP267;267:267)(AP268;268:268)(AP269;269:269)(AP270;270:270)(AP271;271:271)(AP272;272:272)(AP273;273:273)(AP274;274:274)(AP275;275:275)(AP276;276:276)(AP277;277:277)(AP278;278:278)(AP279;279:279)(AP280;280:280)(AP281;281:281)(AP282;282:282)(AP283;283:283)(AP284;284:284)(AP285;285:285)(AP286;286:286)(AP287;287:287)(AP288;288:288)(AP289;289:289)(AP290;290:290)(AP291;291:291)(AP292;292:292)(AP293;293:293)(AP294;294:294)(AP295;295:295)(AP296;296:296)(AP297;297:297)(AP298;298:298)(AP299;299:299)(AP300;300:300)(AP301;301:301)(AP302;302:302)(AP303;303:303)(AP304;304:304)(AP305;305:305)(AP306;306:306)(AP307;307:307)(AP308;308:308)(AP309;309:309)(AP310;310:310)(AP311;311:311)(AP312;312:312)(AP313;313:313)(AP314;314:314)(AP315;315:315)(AP316;316:316)(AP317;317:317)(AP318;318:318)(AP319;319:319)(AP320;320:320)(AP321;321:321)(AP322;322:322)(AP323;323:323)(AP324;324:324)(AP325;325:325)(AP326;326:326)(AP327;327:327)(AP328;328:328)(AP329;329:329)(AP330;330:330)(AP331;331:331)(AP332;332:332)(AP333;333:333)(AP334;334:334)(AP335;335:335)(AP336;336:336)(AP337;337:337)(AP338;338:338)(AP339;339:339)(AP340;340:340)(AP341;341:341)(AP342;342:342)(AP343;343:343)(AP344;344:344)(AP345;345:345)(AP346;346:346)(AP347;347:347)(AP348;348:348)(AP349;349:349)(AP350;350:350)(AP351;351:351)(AP352;352:352)(AP353;353:353)(AP354;354:354)(AP355;355:355)(AP356;356:356)(AP357;357:357)(AP358;358:358)(AP359;359:359)(AP360;360:360)(AP361;361:361)(AP362;362:362)(AP363;363:363)(AP364;364:364)(AP365;365:365)(AP366;366:366)(AP367;367:367)(AP368;368:368)(AP369;369:369)(AP370;370:370)(AP371;371:371)(AP372;372:372)(AP373;373:373)(AP374;374:374)(AP375;375:375)(AP376;376:376)(AP377;377:377)(AP378;378:378)(AP379;379:379)(AP380;380:380)(AP381;381:381)(AP382;382:382)(AP383;383:383)(SY0;768:768) +~snsShankMap=(1,8,48)(0:0:0:1)(0:1:0:1)(0:2:0:1)(0:3:0:1)(0:4:0:1)(0:5:0:1)(0:6:0:1)(0:7:0:1)(0:0:1:1)(0:1:1:1)(0:2:1:1)(0:3:1:1)(0:4:1:1)(0:5:1:1)(0:6:1:1)(0:7:1:1)(0:0:2:1)(0:1:2:1)(0:2:2:1)(0:3:2:1)(0:4:2:1)(0:5:2:1)(0:6:2:1)(0:7:2:1)(0:0:3:1)(0:1:3:1)(0:2:3:1)(0:3:3:1)(0:4:3:1)(0:5:3:1)(0:6:3:1)(0:7:3:1)(0:0:4:1)(0:1:4:1)(0:2:4:1)(0:3:4:1)(0:4:4:1)(0:5:4:1)(0:6:4:1)(0:7:4:1)(0:0:5:1)(0:1:5:1)(0:2:5:1)(0:3:5:1)(0:4:5:1)(0:5:5:1)(0:6:5:1)(0:7:5:1)(0:0:6:1)(0:1:6:1)(0:2:6:1)(0:3:6:1)(0:4:6:1)(0:5:6:1)(0:6:6:1)(0:7:6:1)(0:0:7:1)(0:1:7:1)(0:2:7:1)(0:3:7:1)(0:4:7:1)(0:5:7:1)(0:6:7:1)(0:7:7:1)(0:0:8:1)(0:1:8:1)(0:2:8:1)(0:3:8:1)(0:4:8:1)(0:5:8:1)(0:6:8:1)(0:7:8:1)(0:0:9:1)(0:1:9:1)(0:2:9:1)(0:3:9:1)(0:4:9:1)(0:5:9:1)(0:6:9:1)(0:7:9:1)(0:0:10:1)(0:1:10:1)(0:2:10:1)(0:3:10:1)(0:4:10:1)(0:5:10:1)(0:6:10:1)(0:7:10:1)(0:0:11:1)(0:1:11:1)(0:2:11:1)(0:3:11:1)(0:4:11:1)(0:5:11:1)(0:6:11:1)(0:7:11:1)(0:0:12:1)(0:1:12:1)(0:2:12:1)(0:3:12:1)(0:4:12:1)(0:5:12:1)(0:6:12:1)(0:7:12:1)(0:0:13:1)(0:1:13:1)(0:2:13:1)(0:3:13:1)(0:4:13:1)(0:5:13:1)(0:6:13:1)(0:7:13:1)(0:0:14:1)(0:1:14:1)(0:2:14:1)(0:3:14:1)(0:4:14:1)(0:5:14:1)(0:6:14:1)(0:7:14:1)(0:0:15:1)(0:1:15:1)(0:2:15:1)(0:3:15:1)(0:4:15:1)(0:5:15:1)(0:6:15:1)(0:7:15:1)(0:0:16:1)(0:1:16:1)(0:2:16:1)(0:3:16:1)(0:4:16:1)(0:5:16:1)(0:6:16:1)(0:7:16:1)(0:0:17:1)(0:1:17:1)(0:2:17:1)(0:3:17:1)(0:4:17:1)(0:5:17:1)(0:6:17:1)(0:7:17:1)(0:0:18:1)(0:1:18:1)(0:2:18:1)(0:3:18:1)(0:4:18:1)(0:5:18:1)(0:6:18:1)(0:7:18:1)(0:0:19:1)(0:1:19:1)(0:2:19:1)(0:3:19:1)(0:4:19:1)(0:5:19:1)(0:6:19:1)(0:7:19:1)(0:0:20:1)(0:1:20:1)(0:2:20:1)(0:3:20:1)(0:4:20:1)(0:5:20:1)(0:6:20:1)(0:7:20:1)(0:0:21:1)(0:1:21:1)(0:2:21:1)(0:3:21:1)(0:4:21:1)(0:5:21:1)(0:6:21:1)(0:7:21:1)(0:0:22:1)(0:1:22:1)(0:2:22:1)(0:3:22:1)(0:4:22:1)(0:5:22:1)(0:6:22:1)(0:7:22:1)(0:0:23:1)(0:1:23:1)(0:2:23:1)(0:3:23:1)(0:4:23:1)(0:5:23:1)(0:6:23:1)(0:7:23:1)(0:0:24:1)(0:1:24:1)(0:2:24:1)(0:3:24:1)(0:4:24:1)(0:5:24:1)(0:6:24:1)(0:7:24:1)(0:0:25:1)(0:1:25:1)(0:2:25:1)(0:3:25:1)(0:4:25:1)(0:5:25:1)(0:6:25:1)(0:7:25:1)(0:0:26:1)(0:1:26:1)(0:2:26:1)(0:3:26:1)(0:4:26:1)(0:5:26:1)(0:6:26:1)(0:7:26:1)(0:0:27:1)(0:1:27:1)(0:2:27:1)(0:3:27:1)(0:4:27:1)(0:5:27:1)(0:6:27:1)(0:7:27:1)(0:0:28:1)(0:1:28:1)(0:2:28:1)(0:3:28:1)(0:4:28:1)(0:5:28:1)(0:6:28:1)(0:7:28:1)(0:0:29:1)(0:1:29:1)(0:2:29:1)(0:3:29:1)(0:4:29:1)(0:5:29:1)(0:6:29:1)(0:7:29:1)(0:0:30:1)(0:1:30:1)(0:2:30:1)(0:3:30:1)(0:4:30:1)(0:5:30:1)(0:6:30:1)(0:7:30:1)(0:0:31:1)(0:1:31:1)(0:2:31:1)(0:3:31:1)(0:4:31:1)(0:5:31:1)(0:6:31:1)(0:7:31:1)(0:0:32:1)(0:1:32:1)(0:2:32:1)(0:3:32:1)(0:4:32:1)(0:5:32:1)(0:6:32:1)(0:7:32:1)(0:0:33:1)(0:1:33:1)(0:2:33:1)(0:3:33:1)(0:4:33:1)(0:5:33:1)(0:6:33:1)(0:7:33:1)(0:0:34:1)(0:1:34:1)(0:2:34:1)(0:3:34:1)(0:4:34:1)(0:5:34:1)(0:6:34:1)(0:7:34:1)(0:0:35:1)(0:1:35:1)(0:2:35:1)(0:3:35:1)(0:4:35:1)(0:5:35:1)(0:6:35:1)(0:7:35:1)(0:0:36:1)(0:1:36:1)(0:2:36:1)(0:3:36:1)(0:4:36:1)(0:5:36:1)(0:6:36:1)(0:7:36:1)(0:0:37:1)(0:1:37:1)(0:2:37:1)(0:3:37:1)(0:4:37:1)(0:5:37:1)(0:6:37:1)(0:7:37:1)(0:0:38:1)(0:1:38:1)(0:2:38:1)(0:3:38:1)(0:4:38:1)(0:5:38:1)(0:6:38:1)(0:7:38:1)(0:0:39:1)(0:1:39:1)(0:2:39:1)(0:3:39:1)(0:4:39:1)(0:5:39:1)(0:6:39:1)(0:7:39:1)(0:0:40:1)(0:1:40:1)(0:2:40:1)(0:3:40:1)(0:4:40:1)(0:5:40:1)(0:6:40:1)(0:7:40:1)(0:0:41:1)(0:1:41:1)(0:2:41:1)(0:3:41:1)(0:4:41:1)(0:5:41:1)(0:6:41:1)(0:7:41:1)(0:0:42:1)(0:1:42:1)(0:2:42:1)(0:3:42:1)(0:4:42:1)(0:5:42:1)(0:6:42:1)(0:7:42:1)(0:0:43:1)(0:1:43:1)(0:2:43:1)(0:3:43:1)(0:4:43:1)(0:5:43:1)(0:6:43:1)(0:7:43:1)(0:0:44:1)(0:1:44:1)(0:2:44:1)(0:3:44:1)(0:4:44:1)(0:5:44:1)(0:6:44:1)(0:7:44:1)(0:0:45:1)(0:1:45:1)(0:2:45:1)(0:3:45:1)(0:4:45:1)(0:5:45:1)(0:6:45:1)(0:7:45:1)(0:0:46:1)(0:1:46:1)(0:2:46:1)(0:3:46:1)(0:4:46:1)(0:5:46:1)(0:6:46:1)(0:7:46:1)(0:0:47:1)(0:1:47:1)(0:2:47:1)(0:3:47:1)(0:4:47:1)(0:5:47:1)(0:6:47:1)(0:7:47:1)