如何科學的養倉鼠--倉鼠跑輪數據分析

過年放假,我也買了一個倉鼠稍微玩幾天。。

但是因為有一點點嚙齒類動物行為研究的小小的經歷,所以對倉鼠都在幹啥的行為非常感興趣,倉鼠會在籠子里跑來跑去,來回翻騰,不過最好玩的莫過於看倉鼠跑輪了,跑輪也是最容易量化的老鼠的行為了。所以就簡簡單單,用一下研究老鼠行為的方式,量化一下老鼠「跑輪」這個行為。

為了研究老鼠跑輪的行為,我主要採用紅外對管模塊,測量跑輪轉一圈時對紅外對管信號的遮擋,來計算跑輪次數,我利用樹莓派不斷檢測紅外對管的信號,同時記錄溫度、時間登數據,這樣可以得到更全面的數據。

跑輪記錄設備的製作

改造老鼠跑輪。

改造老鼠跑輪,利用熱熔膠固定一點藥片盒的鋁箔,在對面位置也固定一點熱熔膠,讓跑輪平衡

主要方法是利用熱熔膠固定一些擋光片鋁箔。

固定U型紅外對管模塊,並調整擋光片的位置,使得其正好能夠觸發光電模塊。

連接紅外對管模塊、三色LED模塊以及DHT11溫度計模塊到樹莓派GPIO上。

跑輪記錄程序

通過Python編寫樹莓派GPIO操作程序,利用GPIO中斷控制程序來實現計數,利用紅外對管模塊輸出信號的上沿來觸發計數變數ctx.Count的增加,利用上下沿來改變led燈的顏色,

最基本的思路是10分鐘(600s)初始化一次計數程序,啟動一次計數結果輸出與溫度記錄程序,實現以十分鐘為單位的計數

主要代碼如下:

import datetimeimport timeimport RPi.GPIO as GPIOimport DHT11Reader as DHT11PIPin = 11Gpin = 12Rpin = 13Tpin = 16ctx = Nonedef detect(chn): #print("detected something") if ctx != None: x = GPIO.input(PIPin) ctx.Led(x) ctx.MainCounter(x) else: print("class not init properly")class BlockCounter(object): filepath = "/pi/HamsterDev/Rig1.txt" f = None count = 0 start_time = time.time() time_T = 600 subjid = 0000 def __init__(self, filepath = "/home/pi/HamsterDev/Rig1.txt",time_T=600,subjid = 1001): self.f = open(filepath,a) self.time_T = time_T self.subjid = subjid GPIO.setmode(GPIO.BOARD) # Numbers GPIOs by physical location GPIO.setup(Gpin, GPIO.OUT) # Set Green Led Pin mode to output GPIO.setup(Rpin, GPIO.OUT) # Set Red Led Pin mode to output GPIO.setup(Tpin, GPIO.OUT) GPIO.setup(PIPin, GPIO.IN, pull_up_down=GPIO.PUD_UP) # Set BtnPins mode is input, and pull up to high level(3.3V) GPIO.add_event_detect(PIPin, GPIO.BOTH, callback=detect, bouncetime=100) def MainCounter(self,x): if x == 1: if time.time()-self.start_time < self.time_T: self.count = self.count + 1 #print("count:%d no print"%(self.count)) #else: #print("Now we are going to print something") #self.PrintTXT() #self.Countinit() def Countinit(self): self.count = 0 self.start_time = time.time() def PrintTXT(self): now = datetime.datetime.now() datestr = now.strftime(%Y-%m-%d %H:%M:%S) isSuss,Temp,Humd = DHT11.TempRead(GPIO,Tpin) GPIO.setup(Tpin, GPIO.OUT) print("subj:%s time:%s count:%s TEMP:%.1f HUMD:%d isSuss:%d"%(self.subjid,datestr,self.count,Temp,Humd,isSuss)) self.f.write("
subj:%s time:%s count:%s TEMP:%.1f HUMD:%d"%(self.subjid,datestr,self.count,Temp,Humd)) if isSuss==0: self.f.write(" IsSuss=0") else: self.f.write(" IsSuss=1") def Led(self,x): if x == 0: GPIO.output(Rpin,1) GPIO.output(Gpin,0) if x == 1: GPIO.output(Rpin,0) GPIO.output(Gpin,1) def Destroy(self): print("Now we are going to close the count program") if self.f!=None: self.f.close() GPIO.output(Gpin, GPIO.HIGH) # Green led off GPIO.output(Rpin, GPIO.HIGH) # Red led off GPIO.cleanup()def loop(): while True: if time.time()-ctx.start_time>ctx.time_T: ctx.PrintTXT() ctx.Countinit() else: passif __name__ == __main__: # Program start from here ctx = BlockCounter(filepath="/home/pi/HamsterDev/Rig1.txt",time_T=600,subjid = 1001) try: loop() except KeyboardInterrupt: # When Ctrl+C is pressed, the child program destroy() will be executed. ctx.Destroy()

為了實現溫度的同時記錄,還需要自己添加一個DHT11Reader的溫度計驅動模塊,我修改的網上DHT11模塊的代碼,如下:

import RPi.GPIO as GPIOimport timedef TempRead(GPIO, channel): data = [] j = 0 GPIO.output(channel, GPIO.LOW) time.sleep(0.02) GPIO.output(channel, GPIO.HIGH) GPIO.setup(channel, GPIO.IN) while GPIO.input(channel) == GPIO.HIGH: continue while GPIO.input(channel) == GPIO.LOW: continue while GPIO.input(channel) == GPIO.HIGH: continue while j < 40: k = 0 while GPIO.input(channel) == GPIO.LOW: continue while GPIO.input(channel) == GPIO.HIGH: k += 1 if k > 100: break if k < 10: data.append(0) else: data.append(1) j += 1 humidity_bit = data[0:8] humidity_point_bit = data[8:16] temperature_bit = data[16:24] temperature_point_bit = data[24:32] check_bit = data[32:40] humidity = 0 humidity_point = 0 temperature = 0 temperature_point = 0 check = 0 for i in range(8): humidity += humidity_bit[i] * 2 ** (7 - i) humidity_point += humidity_point_bit[i] * 2 ** (7 - i) temperature += temperature_bit[i] * 2 ** (7 - i) temperature_point += temperature_point_bit[i] * 2 ** (7 - i) check += check_bit[i] * 2 ** (7 - i) tmp = humidity + humidity_point + temperature + temperature_point temp = temperature + 0.1*temperature_point humd = humidity + 0.1*humidity_point if check == tmp: return 1, temp, humd else: return 0, temp, humd print("temperature: %d temperature point: %d humidity %d humidity point: %d sum %d"%(temperature,temperature_point,humidity,humidity_point,check))

在樹莓派/pi/HamsterDev 放入這兩個python程序,再創建一個空的txt文件,比如Rig1.txt,前面幾行(5行)可以寫一些自定義的說明內容,數據分析程序會從第六行開始分析。

運行程序後,效果如下:

會在自動列印數據的同時,吧數據寫入txt文件夾內,大家可以注意到,在多的時候老鼠10分鐘可以跑超過900圈跑輪。

跑輪數據分析

分析跑輪數據主要分為下面兩個部分:

通過MATLAB從txt文本中拾取數據,然後轉換為matlab table格式、篩選數據(比如去掉0的數值點),保存為csv格式。

拾取文本轉換為table格式代碼如下:

%% Import data tabledatatable = importdata(Rig1.txt);%% Getout the datestr, count, temp, humddata = cell(length(datatable)-5,6);for i=6:length(datatable) time_posi = strfind(datatable{i},time:)+5; count_posi = strfind(datatable{i},count:)+6; temp_posi = strfind(datatable{i},TEMP:)+5; humd_posi = strfind(datatable{i},HUMD:)+5; time_str = datatable{i}(time_posi:time_posi+18); % time_str count = str2double(datatable{i}(count_posi:temp_posi-7))*6; % counts temp = str2double(datatable{i}(temp_posi:humd_posi-7)); % temp humd = str2double(datatable{i}(humd_posi:humd_posi+2)); % humd data{i-5,1} = i-5; data{i-5,2} = count; data{i-5,3} = temp; data{i-5,4} = humd; data{i-5,5} = time_str; time2 = datevec(time_str); time2 = time2(4)+time2(5)/60; data{i-5,6} = time2;end%% data -> table sumnamestr = {num,Count,Temperature,Humitity,TimeString,Time};data = cell2table(data,VariableNames,namestr);writetable(data,humster_data.csv)

去掉count為0的數據的代碼如下:

%% remove zerosrows = data.Count>0;data_counts = data{rows,Count};data_temp = data{rows,Temperature};data_Humi = data{rows,Humitity};%%%plot(data_temp,data_counts,o)temp_and_counts = [data_counts,data_temp,data_Humi];temp_and_counts = array2table(temp_and_counts,VariableNames,{Count,Temperature,Humitity});writetable(temp_and_counts,temp_and_counts.csv)

這就完成了基本的數據分析,接著吧兩個csv文件導入R語言的程序中,然後利用R的ggplot畫圖。不得不說ggplot真的是太簡單易用了,matlab出這樣的圖不知道要寫多少代碼。寒假自學了一些r的ggplot真的是太管用了

R的代碼如下:

## Humster Stufflibrary(ggplot2)# Load Humster Datahumster_data<-read.table("/Users/apple/Documents/PYTHON/HamsterDev/humster_data.csv",header = T,sep=",")temp_and_counts<-read.table("/Users/apple/Documents/PYTHON/HamsterDev/temp_and_counts.csv",header = T,sep=",")# Plot counts-time figggplot(humster_data, aes(x=Time,y=Count,color=Temperature)) + stat_smooth(method="loess", span=0.3, se=TRUE, alpha=0.3) + theme_bw()+ geom_point() + geom_vline(xintercept = 7.45)+ geom_vline(xintercept = 18.48) + labs(x="Time/h",y="Rolling Count/h",title = "Humster subj 1001 activity history") + annotate("text", x=5, y=6000, label="Night") + annotate("text", x=12, y=6000, label="Day") + annotate("text", x=23, y=6000, label="Night")# Plot temp-count dotsp2<-ggplot(data=temp_and_counts,aes(x=Temperature,y=Count,color=Humitity))p2 + geom_point() + stat_smooth(method=lm) + labs(x="Temperature",y="Rolling Count",title = "Humster subj 1001 activity history")

基本上到這兒就結束啦,這就是我搭建、編程、分析數據的全過程,最後讓我po一下我的圖

這個圖的橫軸是時間,0點到24點,縱軸是老鼠當下跑輪的速度,按照每小時多少圈計算,最高時候老鼠跑輪速度超過了6000圈每小時!

兩條豎線,一條代表日出時間,一條代表日落時間,可以看出來非常明顯的老鼠夜行規律。

此外,點的顏色代表了溫度,可以看出非常明顯的白天家裡溫度的升高,以及夜晚溫度的降低。

為了進一步的看看老鼠的活躍程度和溫度的關係,我還畫了老鼠轉圈速度vs溫度的圖,如下

可以看出,或許可能有溫度越高,老鼠跑的越多的correlation,但是這個相關好弱好弱,不過我的數據只有兩天,包含非常多的無關變數,(比如開關燈,這個影響我覺得很大),還有更嚴重的,比如這兩天過年放炮的聲音。

如果能長時間再記錄上環境噪音程度,光照強度等信息,肯定會有更多可以發掘的東西!

好啦到這兒基本就結束了,大家也可以根據這個小教程,自己diy一個設備分析小倉鼠的行為啦~

最後,大家新年快樂,再見!


推薦閱讀:

TAG:樹莓派RaspberryPi | 倉鼠 | 神經科學 |