I'm using twisted python tcp server
I encoded the byte string with
byte.hex()
data_1 = 78 78 11 01 0 XXXXXXXXXXXXXXX 80 00 21 21 00 00 38 54 0d0a
data_2 = 78 78 11 01 0 XXXXXXXXXXXXXXX 80 00 21 21 00 32 2a c5 0d0a
7878 -> Start bit
11 -> Packet length
01 -> Protocol Number
XX..XX -> IMEI
0d0a -> End bit
I find problem in decoding this part 8000212100322ac5 according to their documentation its a login packet and I should send some response to it.
For C# GPS Socket communication (CONCOX)
I'm in need of algorithm or a decoding method in python
For GT-800 this i think this will help you
class TcpGpsReceiver(protocol.Protocol):
""" Event driven callback handler
"""
def __init__(self):
"""Constructor
"""
self.imei_no = ''
def gt_800(self, decoded_data):
""" Decode the GT-800 Device Data
"""
if decoded_data[4:6].decode() == '11': # Check if login
print('Login')
self.imei_no = decoded_data[9:24]
data = codecs.decode('7878050100059FF80D0A', encoding='hex', errors='strict')
self.transport.write(data)
if decoded_data[4:6].decode().upper() == '0A':
print('Heat beat received')
serial_number = hex(int(decoded_data[18:22], 16))[2:]
data = codecs.decode('78780513{}670E0D0A'.format(get_serial_number(serial_number)),
encoding='hex', errors='strict')
print(decoded_data[18:22], ' -> serial number')
self.transport.write(data)
if decoded_data[4:6].decode() == '22':
print('Decoding')
s_no = hex(int(decoded_data[66:70], 16))[2:]
date_time = decoded_data[8:20]
latitude = int(decoded_data[23:30], 16) / 1800000
longitude = int(decoded_data[31:38], 16) / 1800000
timestamp = datetime(year=int(date_time[0:2], 16),
month=int(date_time[2:4], 16),
day=int(date_time[4:6], 16),
hour=int(date_time[6:8], 16),
minute=int(date_time[8:10], 16),
second=int(date_time[10:12], 16)).strftime('%Y-%m-%d %H:%M:%S')
location = dict(device_id=self.imei_no.decode(), imei=self.imei_no.decode(), timestamp=timestamp,
location=[latitude, longitude],
speed=0, course=0, state=0, altitude=0)
print(location)
# Code to access location data
self.imei_no = ''
self.transport.loseConnection()
if decoded_data[6:8].decode().upper() == '8A':
print('Date time requested')
s_no = hex(int(decoded_data[8:12], 16))[2:]
now = datetime.now()
month_hex = '0' + hex(now.month)[2:]
print(decoded_data[12:16], hex(int(decoded_data[12:16], 16))[2:])
date_string = '{}{}{}{}{}{}{}{}'.format(hex(int(str(now.year)[2:]))[2:], month_hex, return_date_hex(now.day),
return_date_hex(now.hour), return_date_hex(now.minute),
return_date_hex(now.second),
get_serial_number(s_no), get_serial_number(hex(int(decoded_data[12:16],
16))[2:]))
print(date_string)
data = codecs.decode('78780B8A{}0D0A'.format(date_string), encoding='hex', errors='strict')
self.transport.write(data)
def dataReceived(self, data):
""" Called when data is received across a transport
"""
decoded_data = codecs.encode(data, encoding='hex', errors='strict')
print(datetime.now())
self.gt_800(decoded_data)
def get_serial_number(s_no):
"""Decoding serial No
"""
if len(s_no) == 1:
return '000' + s_no
if len(s_no) == 2:
return '00' + s_no
if len(s_no) == 3:
return '0' + s_no
if len(s_no) > 4:
return '0000'
return s_no
def retrun_date_hex(data):
print(data)
if len(str(hex(data)[2:])) == 2:
return hex(data)[2:]
else:
return '0' + hex(data)[2:]
class TcpGpsReceiverFactory(protocol.Factory):
""" Persistent configuration information, inherits from protocol.Factory
"""
def buildProtocol(self, addr):
""" Creates a protocol for each new connection
"""
return TcpGpsReceiver()
if _name_ == '_main_':
# Called when the module ran directly
reactor.listenTCP(10206, TcpGpsReceiverFactory())
reactor.run()
Related
def inflow(G_inflow, sink, neigh_nodes) :
print(f'G_inflow:{list(G_inflow)}')
i = 0
j = 1
z = 0
print(f'neighbour node value: {neigh_nodes}')
cnt = len(neigh_nodes)
print(f'type of neigh nodes: {type(sink),}')
while j <= cnt :
val = G_inflow[sink][j]['flow']
j+=1
return z
Following is the edge structure : {'capacity': 8545, 'flow': 4869}, when trying to access G_inflow[sink][j]['flow'] getting KeyError from __getitem__(self, key). Let me know is there any other way to resolve this issue.
<ipython-input-46-66e02fb8ffba> in inflow(G_inflow, sink, neigh_nodes)
42 cnt = operator.length_hint(neigh_nodes)
43 while j <= cnt :
---> 44 print(f'Sink data {sink}-{j}: {G_inflow[sink][j]}')
45 z += G_inflow[sink][j]['flow']
46 j+=1
/usr/local/lib/python3.7/dist-packages/networkx/classes/coreviews.py in __getitem__(self, key)
52
53 def __getitem__(self, key):
---> 54 return self._atlas[key]
55
56 def copy(self):
KeyError: 1
I have tried to access the 'flow' value of a Graph edge attribute. This access of Graph edge value('flow') is throwing an exception.
I'm doing some tests to check if some choices from my sampling algorithm is better changing its values.
As I was doing them(till this moment without a hitch) and tried to run a couple more tests for more results I got the MemoryError.
MemoryError Traceback (most recent call last)
<ipython-input-66-1ab060bc6067> in <module>
22 for g in range(0,10000):
23 # sample
---> 24 sample_df = stratified_sample(df,test,size=38, keep_index=False)
25 pathaux = "C://Users//Pedro//Desktop//EscolhasAlgoritmos//Stratified//Stratified_Tests//"
26 example = "exampleFCUL"
<ipython-input-10-7aba847839db> in stratified_sample(df, strata, size, seed, keep_index)
79 # final dataframe
80 if first:
---> 81 stratified_df = df.query(qry).sample(n=n, random_state=seed).reset_index(drop=(not keep_index))
82 first = False
83 else:
D:\Anaconda\lib\site-packages\pandas\core\frame.py in query(self, expr, inplace, **kwargs)
3182 kwargs["level"] = kwargs.pop("level", 0) + 1
3183 kwargs["target"] = None
-> 3184 res = self.eval(expr, **kwargs)
3185
3186 try:
D:\Anaconda\lib\site-packages\pandas\core\frame.py in eval(self, expr, inplace, **kwargs)
3298 kwargs["target"] = self
3299 kwargs["resolvers"] = kwargs.get("resolvers", ()) + tuple(resolvers)
-> 3300 return _eval(expr, inplace=inplace, **kwargs)
3301
3302 def select_dtypes(self, include=None, exclude=None):
D:\Anaconda\lib\site-packages\pandas\core\computation\eval.py in eval(expr, parser, engine, truediv, local_dict, global_dict, resolvers, level, target, inplace)
325 eng = _engines[engine]
326 eng_inst = eng(parsed_expr)
--> 327 ret = eng_inst.evaluate()
328
329 if parsed_expr.assigner is None:
D:\Anaconda\lib\site-packages\pandas\core\computation\engines.py in evaluate(self)
68
69 # make sure no names in resolvers and locals/globals clash
---> 70 res = self._evaluate()
71 return _reconstruct_object(
72 self.result_type, res, self.aligned_axes, self.expr.terms.return_type
D:\Anaconda\lib\site-packages\pandas\core\computation\engines.py in _evaluate(self)
117 truediv = scope["truediv"]
118 _check_ne_builtin_clash(self.expr)
--> 119 return ne.evaluate(s, local_dict=scope, truediv=truediv)
120 except KeyError as e:
121 # python 3 compat kludge
D:\Anaconda\lib\site-packages\numexpr\necompiler.py in evaluate(ex, local_dict, global_dict, out, order, casting, **kwargs)
814 expr_key = (ex, tuple(sorted(context.items())))
815 if expr_key not in _names_cache:
--> 816 _names_cache[expr_key] = getExprNames(ex, context)
817 names, ex_uses_vml = _names_cache[expr_key]
818 arguments = getArguments(names, local_dict, global_dict)
D:\Anaconda\lib\site-packages\numexpr\necompiler.py in getExprNames(text, context)
705
706 def getExprNames(text, context):
--> 707 ex = stringToExpression(text, {}, context)
708 ast = expressionToAST(ex)
709 input_order = getInputOrder(ast, None)
D:\Anaconda\lib\site-packages\numexpr\necompiler.py in stringToExpression(s, types, context)
282 else:
283 flags = 0
--> 284 c = compile(s, '<expr>', 'eval', flags)
285 # make VariableNode's for the names
286 names = {}
MemoryError:
My question is, what is the best way of solving this memory error, without changing number of parameters? With all the search I did here and on Google I have no clear answser.
Code:
def transform(multilevelDict):
return {"t"+'_'+str(key) : (transform(value) if isinstance(value, dict) else value) for key, value in multilevelDict.items()}
df = pd.read_csv('testingwebsitedata6.csv', sep=';')
df['Element_Count'] = df['Element_Count'].apply((json.loads))
df['Tag_Count'] = df['Tag_Count'].apply((json.loads))
for i in range(len(df['Tag_Count'])):
df['Tag_Count'][i] = transform(df['Tag_Count'][i])
df1 = pd.DataFrame(df['Element_Count'].values.tolist())
df2 = pd.DataFrame(df['Tag_Count'].values.tolist())
df = pd.concat([df.drop('Element_Count', axis=1), df1], axis=1)
df= pd.concat([df.drop('Tag_Count', axis=1), df2], axis=1)
df= df.fillna(0)
df[df.select_dtypes(include=['float64']).columns]= df.select_dtypes(include=['float64']).astype(int)
df
test= ['link', 'document', 'heading', 'form', 'textbox', 'button', 'list', 'listitem', 'img', 'navigation', 'banner', 'main', 'article', 'contentinfo', 'checkbox', 'table', 'rowgroup', 'row', 'cell', 'listbox', 'presentation', 'figure', 'columnheader', 'separator', 'group', 'region', 't_html', 't_head', 't_title', 't_meta', 't_link', 't_script', 't_style', 't_body', 't_a', 't_div', 't_h1', 't_form', 't_label', 't_input', 't_ul', 't_li', 't_i', 't_img', 't_nav', 't_header', 't_span', 't_article', 't_p', 't_footer', 't_h3', 't_br', 't_noscript', 't_em', 't_strong', 't_button', 't_h2', 't_ol', 't_time', 't_center', 't_table', 't_tbody', 't_tr', 't_td', 't_font', 't_select', 't_option', 't_b', 't_figure', 't_figcaption', 't_u', 't_iframe', 't_caption', 't_thead', 't_th', 't_h5', 't_sup', 't_map', 't_area', 't_hr', 't_h4', 't_blockquote', 't_sub', 't_fieldset', 't_legend', 't_pre', 't_main', 't_section', 't_small', 't_tfoot', 't_textarea', 't_inserir', 't_s']
print('test1')
print('\n')
for g in range(0,10000):
# sample
sample_df = stratified_sample(df,test,size=38, keep_index=False)
pathaux = "C://Users//Pedro//Desktop//EscolhasAlgoritmos//Stratified//Stratified_Tests//"
example = "exampleFCUL"
randomnumber = g+1
csv = ".csv"
path = pathaux + '26'+'//'+ example +str(randomnumber) + csv
chosencolumns= ["Uri"]
sample_df.to_csv(path,sep=';', index = False, columns =chosencolumns, header = False)
Stratifed Sampling function used:
def stratified_sample(df, strata, size=None, seed=None, keep_index= True):
'''
It samples data from a pandas dataframe using strata. These functions use
proportionate stratification:
n1 = (N1/N) * n
where:
- n1 is the sample size of stratum 1
- N1 is the population size of stratum 1
- N is the total population size
- n is the sampling size
Parameters
----------
:df: pandas dataframe from which data will be sampled.
:strata: list containing columns that will be used in the stratified sampling.
:size: sampling size. If not informed, a sampling size will be calculated
using Cochran adjusted sampling formula:
cochran_n = (Z**2 * p * q) /e**2
where:
- Z is the z-value. In this case we use 1.96 representing 95%
- p is the estimated proportion of the population which has an
attribute. In this case we use 0.5
- q is 1-p
- e is the margin of error
This formula is adjusted as follows:
adjusted_cochran = cochran_n / 1+((cochran_n -1)/N)
where:
- cochran_n = result of the previous formula
- N is the population size
:seed: sampling seed
:keep_index: if True, it keeps a column with the original population index indicator
Returns
-------
A sampled pandas dataframe based in a set of strata.
Examples
--------
>> df.head()
id sex age city
0 123 M 20 XYZ
1 456 M 25 XYZ
2 789 M 21 YZX
3 987 F 40 ZXY
4 654 M 45 ZXY
...
# This returns a sample stratified by sex and city containing 30% of the size of
# the original data
>> stratified = stratified_sample(df=df, strata=['sex', 'city'], size=0.3)
Requirements
------------
- pandas
- numpy
'''
population = len(df)
size = __smpl_size(population, size)
tmp = df[strata]
tmp['size'] = 1
tmp_grpd = tmp.groupby(strata).count().reset_index()
tmp_grpd['samp_size'] = round(size/population * tmp_grpd['size']).astype(int)
# controlling variable to create the dataframe or append to it
first = True
for i in range(len(tmp_grpd)):
# query generator for each iteration
qry=''
for s in range(len(strata)):
stratum = strata[s]
value = tmp_grpd.iloc[i][stratum]
n = tmp_grpd.iloc[i]['samp_size']
if type(value) == str:
value = "'" + str(value) + "'"
if s != len(strata)-1:
qry = qry + stratum + ' == ' + str(value) +' & '
else:
qry = qry + stratum + ' == ' + str(value)
# final dataframe
if first:
stratified_df = df.query(qry).sample(n=n, random_state=seed).reset_index(drop=(not keep_index))
first = False
else:
tmp_df = df.query(qry).sample(n=n, random_state=seed).reset_index(drop=(not keep_index))
stratified_df = stratified_df.append(tmp_df, ignore_index=True)
return stratified_df
def stratified_sample_report(df, strata, size=None):
'''
Generates a dataframe reporting the counts in each stratum and the counts
for the final sampled dataframe.
Parameters
----------
:df: pandas dataframe from which data will be sampled.
:strata: list containing columns that will be used in the stratified sampling.
:size: sampling size. If not informed, a sampling size will be calculated
using Cochran adjusted sampling formula:
cochran_n = (Z**2 * p * q) /e**2
where:
- Z is the z-value. In this case we use 1.96 representing 95%
- p is the estimated proportion of the population which has an
attribute. In this case we use 0.5
- q is 1-p
- e is the margin of error
This formula is adjusted as follows:
adjusted_cochran = cochran_n / 1+((cochran_n -1)/N)
where:
- cochran_n = result of the previous formula
- N is the population size
Returns
-------
A dataframe reporting the counts in each stratum and the counts
for the final sampled dataframe.
'''
population = len(df)
size = __smpl_size(population, size)
tmp = df[strata]
tmp['size'] = 1
tmp_grpd = tmp.groupby(strata).count().reset_index()
tmp_grpd['samp_size'] = round(size/population * tmp_grpd['size']).astype(int)
return tmp_grpd
def __smpl_size(population, size):
'''
A function to compute the sample size. If not informed, a sampling
size will be calculated using Cochran adjusted sampling formula:
cochran_n = (Z**2 * p * q) /e**2
where:
- Z is the z-value. In this case we use 1.96 representing 95%
- p is the estimated proportion of the population which has an
attribute. In this case we use 0.5
- q is 1-p
- e is the margin of error
This formula is adjusted as follows:
adjusted_cochran = cochran_n / 1+((cochran_n -1)/N)
where:
- cochran_n = result of the previous formula
- N is the population size
Parameters
----------
:population: population size
:size: sample size (default = None)
Returns
-------
Calculated sample size to be used in the functions:
- stratified_sample
- stratified_sample_report
'''
if size is None:
cochran_n = round(((1.96)**2 * 0.5 * 0.5)/ 0.02**2)
n = round(cochran_n/(1+((cochran_n -1) /population)))
elif size >= 0 and size < 1:
n = round(population * size)
elif size < 0:
raise ValueError('Parameter "size" must be an integer or a proportion between 0 and 0.99.')
elif size >= 1:
n = size
return n
(Anything that I have forgot to mention that u feel is important to understand the problem please say and I will edit it in)
I'm trying to implement a dual task. Both task ask to judge a number. The stimuli appear shortly after one another with a variable interval (a_soa).
I need to collect the reaction times to the stimuli which are given on the keyboard (first task: y or x key; second task: , or . key). I'm currently struggeling to implement this because for the first task the program needs to start waiting for a response before the second task is even drawn. Then the second stimulus appears and marks the beginning of a possible response to the second task.
The code for both functions that I'm using and the main function are included below.
def StimPresent(a_soa, b_s1, c_s2):
"""
Function StimPresent(a, b, c) presents stimulus_1 (b) for SOA ((a) number of frames),
then it adds stimulus_2 (d) and shows both for max 60 frames
and returns time of stimulus onset (tim)
"""
if event.getKeys(keyList='escape'):
myWin.close()
core.quit()
for frameN in range(a_soa):
b_s1.draw()
fixation.draw()
if frameN == 0: # RT S1 starting immediately after flip
onsetS1 = RT1.getTime()
myWin.flip()
for frameN in range(a_soa, (a_soa+60)):
b_s1.draw()
fixation.draw()
c_s2.draw()
if frameN == (a_soa+1):
onsetS2 = RT2.getTime() #RT S2 starting immediately after soa flip
myWin.flip()
for frameN in range((a_soa+60), 300):
fixation.draw()
myWin.flip()
return [b_s1, onsetS1, c_s2, onsetS2, a_soa]
def GetRTs(onS1, onS2):
allkeys = []
event.clearEvents()
while len(allkeys)!=2:
if event.getKeys(['y']):
buttonR1 = 55
allkeys.append(buttonR1)
buttonR1Time = RT1.getTime()
theRT1 = buttonR1Time - onS1
elif event.getKeys(['x']):
buttonR1 = 44
allkeys.append(buttonR1)
buttonR1Time = RT1.getTime()
theRT1 = buttonR1Time - onS1
else:
buttonR1 = 666
allkeys.append(buttonR1)
buttonR1Time = 'NaN'
theRT1 = 'NaN'
if event.getKeys(','):
buttonR2 = 44
allkeys.append(buttonR1)
buttonR2Time = RT2.getTime()
theRT2 = buttonR2Time - onS2
elif event.getKeys('.'):
buttonR2 = 55
allkeys.append(buttonR1)
buttonR2Time = RT2.getTime()
theRT2 = buttonR2Time - onS2
else:
buttonR2 = 666
allkeys.append(buttonR1)
buttonR2Time = 'NaN'
theRT2 = 'NaN'
if RT2.getTime() - onS2 > 210:
break
elif event.getKeys(['escape']):
myWin.close()
core.quit()
return [buttonR1, buttonR1Time, buttonR2, buttonR2Time, theRT1, theRT2]
main program
for b in range(block < 2):
for thisTrial in trials:
"""
---------------------
Start des Durchgangs
---------------------
"""
RSIFix()
showChar = StimPresent(thisTrial.SOA, thisTrial.Stimulus_1, thisTrial.Stimulus_2)
s1 = showChar[0]
s1onset = showChar[1]
s2 = showChar[2]
s2onset = showChar[3]
soa = showChar[4]
responses = GetRTs(s1onset, s2onset)
Thanks for any help :)
If using the Psychopy's event module to collect responses, you need to integrate the checking for keypresses into your drawing loop. i.e. check for a keypress once for every win.flip() call, so that you are effectively checking for responses once per screen refresh (and effectively getting a very granular time resolution, typically at 16.67 ms for a 60 Hz display).
The way the event.getKeys() function works is that the timestamp is the time at which the function is called, not the time at which the key was pressed. i.e. in your current code, the key could have been pressed during the stimuli and be just sitting in a buffer waiting for you to process it. So all of your reaction times will appear to be after the stimuli have finished being shown.
Having said that, best practice now (from PsychoPy 3.1 onwards) is not to use the event module if reaction times are important. Instead, use the new Keyboard class:
https://www.psychopy.org/api/hardware/keyboard.html
This was ported from the Psychtoolbox project and has far better timing performance. And importantly, the timestamp reflects the actual time the key was pressed, regardless of when you check for responses, and doesn't have its resolution tied to the display refresh rate.
Thanks a lot, your comment helped me! I rewrote the code with the keyboard class but now I'm running into another problem: The function is only returning 666 as buttonR1Code and buttonR2Code. These should only be given if now response was collected.
How can I fix this? Any suggestions?
def StimPresent(a_soa, b_s1, c_s2):
"""
Function StimPresent(a, b, c) presents stimulus_1 (b) for SOA ((a) number of frames),
then it adds stimulus_2 (d) and shows both for max 60 frames
and returns time of stimulus onset (tim)
"""
kbR1 = keyboard.Keyboard()
kbR2 = keyboard.Keyboard()
allkeys = 0
while allkeys < 2:
if event.getKeys(keyList='escape'):
myWin.close()
core.quit()
for frameN in range(a_soa):
b_s1.draw()
fixation.draw()
if frameN == 0: # RT S1 starting immediately after flip
onsetS1 = RT1.getTime()
kbR1.clock.reset()
keyR1 = kbR1.getKeys(['y', 'x'], waitRelease=True)
if keyR1 == 'y':
buttonR1 = 55
allkeys += 1
buttonR1Iden = keyR1.name
buttonR1Dur = keyR1.duration
theRT1 = keyR1.rt
elif keyR1 == 'x':
buttonR1 = 44
allkeys += 1
buttonR1Iden = keyR1.name
buttonR1Dur = keyR1.duration
theRT1 = keyR1.rt
myWin.flip()
for frameN in range(a_soa, (a_soa+60)):
b_s1.draw()
fixation.draw()
c_s2.draw()
if frameN == (a_soa+1):
onsetS2 = RT2.getTime() #RT S2 starting immediately after soa flip
kbR2.clock.reset()
keyR1 = kbR1.getKeys(['y', 'x'], waitRelease=True)
keyR2 = kbR2.getKeys(['.', ','], waitRelease=True)
if allkeys == 0:
if keyR1 == 'y':
buttonR1 = 55
allkeys += 1
buttonR1Iden = keyR1.name
buttonR1Dur = keyR1.duration
theRT1 = keyR1.rt
elif keyR1 == 'x':
buttonR1 = 44
allkeys += 1
buttonR1Iden = keyR1.name
buttonR1Dur = keyR1.duration
theRT1 = keyR1.rt
if allkeys == 1:
if kbR2.getKeys(keyList=['.'], waitRelease=True):
buttonR2 = 55
allkeys += 1
buttonR2Iden = kbR2.name
buttonR2Dur = kbR2.duration
theRT2 = kbR2.rt
elif kbR2.getKeys(keyList=[','], waitRelease=True):
buttonR2 = 44
allkeys += 1
buttonR2Iden = kbR2.name
buttonR2Dur = kbR2.duration
theRT2 = kbR2.rt
myWin.flip()
for frameN in range((a_soa+60), 300):
fixation.draw()
deadlineS1 = 210
deadlineS2 = 210
keyR1 = kbR1.getKeys(['y', 'x'], waitRelease=True)
keyR2 = kbR2.getKeys(['.', ','], waitRelease=True)
if allkeys == 0:
if keyR1 == 'y':
buttonR1 = 55
allkeys += 1
buttonR1Iden = keyR1.name
buttonR1Dur = keyR1.duration
theRT1 = keyR1.rt
elif keyR1 == 'x':
buttonR1 = 44
allkeys += 1
buttonR1Iden = keyR1.name
buttonR1Dur = keyR1.duration
theRT1 = keyR1.rt
elif frameN > deadlineS1:
buttonR1 = 666
allkeys += 1
buttonR1Iden = 'NaN'
buttonR1Dur = 'NaN'
theRT1 = 'NaN'
if allkeys == 1:
if kbR2.getKeys(keyList=['.'], waitRelease=True):
buttonR2 = 55
allkeys += 1
buttonR2Iden = kbR2.name
buttonR2Dur = kbR2.duration
theRT2 = kbR2.rt
elif kbR2.getKeys(keyList=[','], waitRelease=True):
buttonR2 = 44
allkeys += 1
buttonR2Iden = kbR2.name
buttonR2Dur = kbR2.duration
theRT2 = kbR2.rt
elif frameN > deadlineS2:
buttonR2 = 666
allkeys += 1
buttonR2Iden = 'NaN'
buttonR2Dur = 'NaN'
theRT2 = 'NaN'
myWin.flip()
return [b_s1, onsetS1, buttonR1, buttonR1Iden, buttonR1Dur, theRT1, c_s2, onsetS2, buttonR1, buttonR1Iden, buttonR1Dur, theRT2, a_soa]
Thanks :)
I've just started to play around with Reinforcement Learning these days and I found the Natural Evolution Strategy, I kind of understand how it works, but I'm very new with Python and I found this code which basically implements the NES algorithm
https://github.com/huseinzol05/Stock-Prediction-Models/blob/master/agent/updated-NES-google.ipynb
import numpy as np
import pandas as pd
import time
import matplotlib.pyplot as plt
import seaborn as sns
import random
sns.set()
# CSV containing the TSLA stock predictions in the form of
# [Date, Open, High, Low, Close, Adj Close, Volume] from
# Yahoo! Finance
df = pd.read_csv('TSLA.csv')
df.head()
def get_state(data, t, n):
d = t - n + 1
block = data[d : t + 1] if d >= 0 else -d * [data[0]] + data[0 : t + 1]
res = []
for i in range(n - 1):
res.append(block[i + 1] - block[i])
return np.array([res])
close = df.Close.values.tolist()
window_size = 30
skip = 1
l = len(close) - 1
class Deep_Evolution_Strategy:
inputs = None
def __init__(
self, weights, reward_function, population_size, sigma, learning_rate
):
self.weights = weights
self.reward_function = reward_function
self.population_size = population_size
self.sigma = sigma
self.learning_rate = learning_rate
def _get_weight_from_population(self, weights, population):
weights_population = []
for index, i in enumerate(population):
jittered = self.sigma * i
weights_population.append(weights[index] + jittered)
return weights_population
def get_weights(self):
return self.weights
def train(self, epoch = 100, print_every = 1):
lasttime = time.time()
for i in range(epoch):
population = []
rewards = np.zeros(self.population_size)
for k in range(self.population_size):
x = []
for w in self.weights:
x.append(np.random.randn(*w.shape))
population.append(x)
for k in range(self.population_size):
weights_population = self._get_weight_from_population(self.weights, population[k])
rewards[k] = self.reward_function(weights_population)
rewards = (rewards - np.mean(rewards)) / np.std(rewards)
for index, w in enumerate(self.weights):
A = np.array([p[index] for p in population])
self.weights[index] = (
w
+ self.learning_rate
/ (self.population_size * self.sigma)
* np.dot(A.T, rewards).T
)
class Model:
def __init__(self, input_size, layer_size, output_size):
self.weights = [
np.random.randn(input_size, layer_size),
np.random.randn(layer_size, output_size),
np.random.randn(layer_size, 1),
np.random.randn(1, layer_size),
]
def predict(self, inputs):
feed = np.dot(inputs, self.weights[0]) + self.weights[-1]
decision = np.dot(feed, self.weights[1])
buy = np.dot(feed, self.weights[2])
return decision, buy
def get_weights(self):
return self.weights
def set_weights(self, weights):
self.weights = weights
class Agent:
POPULATION_SIZE = 15
SIGMA = 0.1
LEARNING_RATE = 0.03
def __init__(self, model, money, max_buy, max_sell):
self.model = model
self.initial_money = money
self.max_buy = max_buy
self.max_sell = max_sell
self.es = Deep_Evolution_Strategy(
self.model.get_weights(),
self.get_reward,
self.POPULATION_SIZE,
self.SIGMA,
self.LEARNING_RATE,
)
def act(self, sequence):
decision, buy = self.model.predict(np.array(sequence))
return np.argmax(decision[0]), int(buy[0])
def get_reward(self, weights):
initial_money = self.initial_money
starting_money = initial_money
self.model.weights = weights
state = get_state(close, 0, window_size + 1)
inventory = []
quantity = 0
for t in range(0, l, skip):
action, buy = self.act(state)
next_state = get_state(close, t + 1, window_size + 1)
if action == 1 and initial_money >= close[t]:
if buy < 0:
buy = 1
if buy > self.max_buy:
buy_units = self.max_buy
else:
buy_units = buy
total_buy = buy_units * close[t]
initial_money -= total_buy
inventory.append(total_buy)
quantity += buy_units
elif action == 2 and len(inventory) > 0:
if quantity > self.max_sell:
sell_units = self.max_sell
else:
sell_units = quantity
quantity -= sell_units
total_sell = sell_units * close[t]
initial_money += total_sell
state = next_state
return ((initial_money - starting_money) / starting_money) * 100
def fit(self, iterations, checkpoint):
self.es.train(iterations, print_every = checkpoint)
def buy(self):
initial_money = self.initial_money
state = get_state(close, 0, window_size + 1)
starting_money = initial_money
states_sell = []
states_buy = []
inventory = []
quantity = 0
for t in range(0, l, skip):
action, buy = self.act(state)
next_state = get_state(close, t + 1, window_size + 1)
if action == 1 and initial_money >= close[t]:
if buy < 0:
buy = 1
if buy > self.max_buy:
buy_units = self.max_buy
else:
buy_units = buy
total_buy = buy_units * close[t]
initial_money -= total_buy
inventory.append(total_buy)
quantity += buy_units
states_buy.append(t)
elif action == 2 and len(inventory) > 0:
bought_price = inventory.pop(0)
if quantity > self.max_sell:
sell_units = self.max_sell
else:
sell_units = quantity
if sell_units < 1:
continue
quantity -= sell_units
total_sell = sell_units * close[t]
initial_money += total_sell
states_sell.append(t)
try:
invest = ((total_sell - bought_price) / bought_price) * 100
except:
invest = 0
state = next_state
invest = ((initial_money - starting_money) / starting_money) * 100
model = Model(window_size, 500, 3)
agent = Agent(model, 10000, 5, 5)
agent.fit(500, 10)
agent.buy()
As you can see, it is being used for stock prediction and it only uses the Close column, but I would like to try it with more parameters, let's say High and Low.
I'm struggling when I need to change it to use this 2 dimensional list. I've tried a simple change:
close = df.loc[:,['Close','Open']].values.tolist()
Which adds one more property at every row of the list. But when I run the code I start to see errors when I execute the agent.fit() call:
agent.fit(iterations = 500, checkpoint = 10)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-225-d97697984016> in <module>()
----> 1 agent.fit(iterations = 500, checkpoint = 10)
<ipython-input-223-35d9fbba5756> in fit(self, iterations, checkpoint)
66
67 def fit(self, iterations, checkpoint):
---> 68 self.es.train(iterations, print_every = checkpoint)
69
70 def buy(self):
<ipython-input-220-84ca345091f4> in train(self, epoch, print_every)
33 self.weights, population[k]
34 )
---> 35 rewards[k] = self.reward_function(weights_population)
36 rewards = (rewards - np.mean(rewards)) / np.std(rewards)
37
<ipython-input-223-35d9fbba5756> in get_reward(self, weights)
36
37 self.model.weights = weights
---> 38 state = get_state(self.close, 0, self.window_size + 1)
39 inventory = []
40 quantity = 0
<ipython-input-219-0df8d8be24a9> in get_state(data, t, n)
4 res = []
5 for i in range(n - 1):
----> 6 res.append(block[i + 1] - block[i])
7 return np.array([res])
TypeError: unsupported operand type(s) for -: 'list' and 'list'
I assume that the first step is that I need to update my Model class to use a different input_size parameter right?
Any help would be appreciated! Thanks
BACKGROUND
I have a piece of hardware that returns an ascii stream & the user can choose
the number of timesteps
the number of channels
One packet = [ADDRESS][MSB][LSB][CHECKSUM]
One timestamp = [TIME_PACKET][CH1_PACKET][CH2_PACKET][CH3_PACKET][CH4_PACKET][CH5_PACKET][CH6_PACKET][CH7_PACKET]
Below is some stripped down code that I use to create 7 plus time arrays to then plot via matplotlib. The issue is, it takes a fair amount of time to process... 2.7seconds for 30,000 samples & 7 channels. I have used cython and I compiled this block down as a C extension and it isn't that much faster...
COMPLETE time is 2.7seconds.
Disable Checksum is 1.8seconds # this one test is 0.9seconds
Disable sign extend is 1.8seconds # this one test is 0.9 seconds
Disable all checks is 1.0 seconds
so roughly half the time is splitting the data
1/4 of the time is Checksum check on each packet
1/4 of the time is sign extend check on each packet
those checks are quite important as they help identify framing errors w.r.t. the USB link & also any noise pickup on the piece of test equipment (so the top 4bits then start being incorrectly set...)
Is the below code reasonably efficient and should I live with it or is it really really bad...
import numpy as np
import time
BIT_LENGTH=16 # payload bitlength
num_samples=30000 # number of samples
packet = 4 # 4 bytes
chT = b'\x01\x00\x05\xfb' # timestep of 5 # 1
ch1 = b'\x03\x00\x11\xed' # data 17 # 3
ch2 = b'\x04\x00\x07\xfc' # data 7 # 4
ch3 = b'\x08\x00\x17\xe0' # data 23 # 8
ch4 = b'\x0c\x00e\x96' # data 101 # 12
ch5 = b'\x0e\x00\x01\xf0' # data 1 # 14
ch6 = b'\x13\x04\x00\xe8' # data 1024 # 19
ch7 = b'\x14\x04\xd2=' # data 1234 # 20
stream = chT+ch1+ch2+ch3+ch4+ch5+ch6+ch7
stream = stream*num_samples
req = [1,3,4,8,12,14,19,20] # array of channel addresses.
req_array = [np.zeros(num_samples) for i in req] # init np arrays.
fpga_error_codes = {
'\x80\x00\x01':'ERR 1',
'\x80\x00\x02':'ERR 2',
'\x80\x00\x04':'ERR 3',
'\x80\x00\x08':'ERR 4',
'\x80\x00\x10':'ERR 5',
'\x80\x00\x20':'ERR 6',
'\x80\x00\x40':'ERR 7',
}
class PacketError(Exception):
def __init__(self, value):
self.parameter = value
def __str__(self):
return repr(self.parameter)
### FUNCTIONS USED
def checksum(data):
return (~(data[0] ^ data[1] ^ data[2]) & 0xff).to_bytes(1,byteorder='big',signed=False)
def check_packet_bits(data, s=None, nbits=BIT_LENGTH):
''' additional method to assist with error detection'''
int_data = int.from_bytes(data[1:-1],byteorder='big',signed=True)
if s=='unsigned':
if int_data > (2**nbits)-1:
return True # ERROR!
else:
return False
elif s == 'signed':
hi = 2**(nbits -1) -1
lo = -1 * 2**(nbits-1)
return True if int_data < lo else True if int_data > hi else False
def check_packet(addr, data, num_bits=BIT_LENGTH, sign_type='signed'):
'''Method to determine whether an ITI packet is valid'''
if checksum(data[:-1]) != data[-1].to_bytes(1,byteorder='big',signed=False):
msg = 'Checksum Error: %s' % ( ' '.join([hex(i) for i in data]) )
raise PacketError(msg)
elif data[0] == '\x80':
msg = "%sd %s" %(fpga_error_codes.get(data[:3],'Unspecified Error'),' '.join([hex(i) for i in data]) )
raise PacketError(msg)
elif data[0] != addr:
msg = "Wrong addr. Got: %d Want: %d %s" % (data[0],addr,' '.join([hex(i) for i in data]) )
raise PacketError(msg)
elif check_packet_bits(data,s=sign_type, nbits=num_bits):
msg = "Target FPGA sent a corrupted payload addr: %d, page: %d Data: 0x%02x%02x" %(addr, self.present_page,data[1],data[2])
raise PacketError(msg)
else:
return int.from_bytes(data[1:-1],byteorder='big',signed=True)
t0= time.time()
### CODE IN QUESTION
timestep_iter = zip(*(iter(stream),)*packet*len(req))
for entry,time_window in enumerate(timestep_iter):
packet_iter = zip(*(iter(bytes(time_window)),)*packet)
tmp = [check_packet(i,bytes(next(packet_iter)),sign_type=['signed','unsigned'][0],num_bits=12,) for i in req]
for index,addr in enumerate(req):
req_array[index][entry] = tmp[index]
req_array[0] = req_array[0].cumsum() - req_array[0]
### CODE IN QUESTION
print(time.time()-t0)