Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F122057918
protocols.py
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Tue, Jul 15, 12:50
Size
6 KB
Mime Type
text/x-python
Expires
Thu, Jul 17, 12:50 (1 d, 23 h)
Engine
blob
Format
Raw Data
Handle
27428699
Attached To
R4670 PySONIC (old)
protocols.py
View Options
# -*- coding: utf-8 -*-
# @Author: Theo Lemaire
# @Email: theo.lemaire@epfl.ch
# @Date: 2019-11-12 18:04:45
# @Last Modified by: Theo Lemaire
# @Last Modified time: 2020-02-18 20:33:46
import
numpy
as
np
from
..utils
import
si_format
,
StimObject
from
.batches
import
Batch
class
TimeProtocol
(
StimObject
):
def
__init__
(
self
,
tstim
,
toffset
):
''' Class constructor.
:param tstim: pulse duration (s)
:param toffset: offset duration (s)
'''
self
.
tstim
=
tstim
self
.
toffset
=
toffset
@property
def
tstim
(
self
):
return
self
.
_tstim
@tstim.setter
def
tstim
(
self
,
value
):
value
=
self
.
checkFloat
(
'tstim'
,
value
)
self
.
checkPositiveOrNull
(
'tstim'
,
value
)
self
.
_tstim
=
value
@property
def
toffset
(
self
):
return
self
.
_toffset
@toffset.setter
def
toffset
(
self
,
value
):
value
=
self
.
checkFloat
(
'toffset'
,
value
)
self
.
checkPositiveOrNull
(
'toffset'
,
value
)
self
.
_toffset
=
value
@property
def
ttotal
(
self
):
return
self
.
tstim
+
self
.
toffset
def
__eq__
(
self
,
other
):
if
not
isinstance
(
other
,
self
.
__class__
):
return
False
return
self
.
tstim
==
other
.
tstim
and
self
.
toffset
==
other
.
toffset
def
__repr__
(
self
):
params
=
[
f
'{si_format(x, 1, space="")}s'
for
x
in
[
self
.
tstim
,
self
.
toffset
]]
return
f
'{self.__class__.__name__}({", ".join(params)})'
@property
def
desc
(
self
):
return
f
'{si_format(self.tstim, 1)}s stim, {si_format(self.toffset, 1)}s offset'
@property
def
filecodes
(
self
):
return
{
'tstim'
:
f
'{(self.tstim * 1e3):.0f}ms'
,
'toffset'
:
None
}
@staticmethod
def
inputs
():
return
{
'tstim'
:
{
'desc'
:
'stimulus duration'
,
'label'
:
't_{stim}'
,
'unit'
:
'ms'
,
'factor'
:
1e3
,
'precision'
:
0
},
'toffset'
:
{
'desc'
:
'offset duration'
,
'label'
:
't_{offset}'
,
'unit'
:
'ms'
,
'factor'
:
1e3
,
'precision'
:
0
}
}
@classmethod
def
createQueue
(
cls
,
durations
,
offsets
):
''' Create a serialized 2D array of all parameter combinations for a series of individual
parameter sweeps.
:param durations: list (or 1D-array) of stimulus durations
:param offsets: list (or 1D-array) of stimulus offsets (paired with durations array)
:return: list of parameters (list) for each simulation
'''
return
[
cls
(
*
item
)
for
item
in
Batch
.
createQueue
(
durations
,
offsets
)]
class
PulsedProtocol
(
TimeProtocol
):
def
__init__
(
self
,
tstim
,
toffset
,
PRF
=
100.
,
DC
=
1.
):
''' Class constructor.
:param tstim: pulse duration (s)
:param toffset: offset duration (s)
:param PRF: pulse repetition frequency (Hz)
:param DC: pulse duty cycle (-)
'''
super
()
.
__init__
(
tstim
,
toffset
)
self
.
DC
=
DC
self
.
PRF
=
PRF
@property
def
DC
(
self
):
return
self
.
_DC
@DC.setter
def
DC
(
self
,
value
):
value
=
self
.
checkFloat
(
'DC'
,
value
)
self
.
checkBounded
(
'DC'
,
value
,
(
0.
,
1.
))
self
.
_DC
=
value
@property
def
PRF
(
self
):
return
self
.
_PRF
@PRF.setter
def
PRF
(
self
,
value
):
value
=
self
.
checkFloat
(
'PRF'
,
value
)
self
.
checkPositiveOrNull
(
'PRF'
,
value
)
if
self
.
DC
<
1.
:
self
.
checkBounded
(
'PRF'
,
value
,
(
1
/
self
.
tstim
,
np
.
inf
))
self
.
_PRF
=
value
def
__eq__
(
self
,
other
):
if
not
isinstance
(
other
,
self
.
__class__
):
return
False
return
super
()
.
__eq__
(
other
)
and
self
.
PRF
==
other
.
PRF
and
self
.
DC
==
other
.
DC
def
__repr__
(
self
):
params
=
[
f
'{si_format(self.PRF, 1, space="")}Hz'
,
f
'{self.DC:.2f}'
]
return
f
'{super().__repr__()[:-1]}, {", ".join(params)})'
@property
def
T_ON
(
self
):
return
self
.
DC
/
self
.
PRF
@property
def
T_OFF
(
self
):
return
(
1
-
self
.
DC
)
/
self
.
PRF
@property
def
npulses
(
self
):
return
int
(
np
.
round
(
self
.
tstim
*
self
.
PRF
))
@property
def
desc
(
self
):
s
=
super
()
.
desc
if
self
.
DC
<
1
:
s
+=
f
', {si_format(self.PRF, 2)}Hz PRF, {(self.DC * 1e2):.1f}% DC'
return
s
@property
def
isCW
(
self
):
return
self
.
DC
==
1.
@property
def
nature
(
self
):
return
'CW'
if
self
.
isCW
else
'PW'
@property
def
filecodes
(
self
):
if
self
.
isCW
:
d
=
{
'PRF'
:
None
,
'DC'
:
None
}
else
:
d
=
{
'PRF'
:
f
'PRF{self.PRF:.2f}Hz'
,
'DC'
:
f
'DC{self.DC * 1e2:04.1f}%'
}
return
{
**
super
()
.
filecodes
,
**
d
}
@staticmethod
def
inputs
():
d
=
{
'PRF'
:
{
'desc'
:
'pulse repetition frequency'
,
'label'
:
'PRF'
,
'unit'
:
'Hz'
,
'factor'
:
1e0
,
'precision'
:
0
},
'DC'
:
{
'desc'
:
'duty cycle'
,
'label'
:
'DC'
,
'unit'
:
'%'
,
'factor'
:
1e2
,
'precision'
:
2
}
}
return
{
**
TimeProtocol
.
inputs
(),
**
d
}
@classmethod
def
createQueue
(
cls
,
durations
,
offsets
,
PRFs
,
DCs
):
''' Create a serialized 2D array of all parameter combinations for a series of individual
parameter sweeps, while avoiding repetition of CW protocols for a given PRF sweep.
:param durations: list (or 1D-array) of stimulus durations
:param offsets: list (or 1D-array) of stimulus offsets (paired with durations array)
:param PRFs: list (or 1D-array) of pulse-repetition frequencies
:param DCs: list (or 1D-array) of duty cycle values
:return: list of parameters (list) for each simulation
'''
DCs
=
np
.
array
(
DCs
)
queue
=
[]
if
1.0
in
DCs
:
queue
+=
Batch
.
createQueue
(
durations
,
offsets
,
min
(
PRFs
),
1.0
)
if
np
.
any
(
DCs
!=
1.0
):
queue
+=
Batch
.
createQueue
(
durations
,
offsets
,
PRFs
,
DCs
[
DCs
!=
1.0
])
queue
=
[
cls
(
*
item
)
for
item
in
queue
]
return
queue
Event Timeline
Log In to Comment