2022年11月21日

用紙條與組花片類比DNA與轉錄轉譯蛋白質

 要對小學生談DNA是什麼,甚至說基因是什麼樣的東西。到底要怎樣做呢?


想到了一個類比方式,似乎還不錯。事先準備了塑膠蛋殼,每個蛋內都有一個塑膠袋,塑膠袋裡有一張紙條。



每個學生拿一個蛋

把蛋打開,塑膠袋打開來,拿出裏頭的紙條,接下來按照紙條上的指示,找到對應的花片組合起來
品名是五彩小花片,320元,有950片。


裡頭共有五色,五種形狀。




這個類比是簡化過的,首先蛋就是類比細胞,蛋內的塑膠袋類比細胞核,而紙條則是類比DNA,上頭有著遺傳訊息(要拚出特定顏色和形狀),而花片則是類比胺基酸。

前一篇提到了要做DNA萃取的工作,則是讓學生先能理解【紙條在蛋內的塑膠袋內】,所以要拿出DNA就像是要把蛋打開、拆開塑膠袋那樣,把細胞弄開、打開細胞核。

我給學生拼花片的紙條,是每個學生都不一樣的。這是用python寫code產生。code如下,預設輸出六十組字串,每組字串都是十種花片,會輸出到output.txt文字檔儲存:
import random
color = ["紅","綠","白","黃","藍"]
shape = ["長方","正方","橢圓","三角","星星"]
colorIdx = int(random.random()*len(color))
shapeIdx = int(random.random()*len(shape))

def brick():
    colorIdx = int(random.random()*len(color))
    shapeIdx = int(random.random()*len(shape))
    return color[colorIdx]+shape[shapeIdx]


segN = 10
amount = 60

path = 'output.txt'
f = open(path, 'w')


for i in range(amount):
    seq =""
    for j in range(segN):
        seq +=  brick() + "-"
        

    print(seq[:-1])
    f.write(seq[:-1] + "\n")
f.close()


萃取DNA的簡易方式

 最近應泛科學之邀,到坪林國小去辦了一個科學營隊。對象是從小二到小六的小學生,其中一個實驗要做DNA萃取。若是要用以前教科書的流程來進行,我可是完全無法備料,什麼果汁機打水果啦、添加酵素啦、使用冰酒精之類的。

為了備料方便,我測試了好幾種材料和方法,總算是找到簡單的方法了啊。

  1. 萃取時所需要的萃取液,可以略過酵素、鹽,其實只要洗碗精就可以。
  2. 酒精:不需要使用冰的,也不需要使用95%的,只需要一般消毒用的75%濃度。
  3. 材料:金黃奇異果最方便,一顆可以切給六七個人使用。
  4. 果汁機?不用,只要用冰棒棍和塑膠杯就可以把奇異果壓碎。

整理一下所需要的材料:
  1. 一瓶75%酒精
  2. 一瓶已調好的DNA萃取液(600g水、4.8克鹽、10克洗碗精),事先加好水以外的東西,要實驗前才添加水。以方便攜帶與備料。(其實連鹽也可以不用)
  3. 每人兩個小塑膠杯 、冰棒棍、紗布(藥局購買4吋*4吋的紗布,一包有10片,一片剪開後,可給兩人使用),牙籤和小離心管(收集DNA使用)


1.每杯放入一片奇異果片,不需去皮


2.加入萃取液,蓋過果片就可以。用冰棒棍將果肉壓爛


3.將紗布蓋在另一個小塑膠杯上準備過濾

4.把壓爛的奇異果倒入紗布中

5.拎起紗布四角將果肉撈起,並用冰棒棍輕壓,將果汁濾出。得到一個加了鹽和洗碗精的奇異果汁。


6.準備與奇異果汁等量的消毒酒精(左)倒入奇異果汁(右)


7.一分鐘內,就可以看到上層逐漸出現成團膠狀的物質,此為粗萃取的DNA,內容物還有很多雜質。


這部影片有全部的製作流程




酵素消化藥分解粉圓的小實驗

學期初的酵素分解實驗可真是頭痛,疫情期間是要怎麼吐口水做實驗呢?想來想去,不如去買個含消化酵素的腸胃藥來試試看吧?本來打算買膠囊狀或是藥粉狀的,比較方便處理,結果我跑了好幾間藥局,就只能找到錠狀的藥品,不如就買了吧。

 


180元十顆


結果發現沒辦法拿來做實驗啊!為什麼呢?它有乳糖啊,加了本氏液自己就變色了啊。

既然不能拿來做實驗,還是想想看可以拿來做什麼吧。拿研缽磨成粉,加些水變成水溶液。

冰箱裡有別人請的珍珠奶茶,不如來做個分解珍珠的實驗看看,看看效果如何,如果速度夠快,未來也能變成課堂操作的實驗。

先挑選十顆差不多大小的珍珠

接著放在酵素溶液裏頭,另一杯則是放在水裡頭

過了十幾分鐘再拿出來,大小果然是有差。只是本來想像是可以完全分解掉,但是卻只有變小一點點啊。

結論是喔,這個藥品拿來取代教科書實驗的唾液,顯然不可。但是拿來做分解澱粉的實驗是可以的喔。



2022年10月5日

模擬考結果的視覺化呈現

上週看到了模擬考的結果表格,有每個班級、每個科目、每個題目的每個選項的選答率、班級答對率、全校答對率、區域答對率、全體答對率。還有全體的基礎、待加強、精熟族群的答對率。資料很詳盡,但其實很難一眼看出來差異,以及拿來應用。



因此就需要將資料轉換成有意義的資訊囉,首先確認目標是要在各班之中看到各班對不同題目的反應如何。也就是有些班要特別注意某些題目,要多提醒他們。 可是那些是什麼題目呢?

於是我就把所有資料匯集後,用python畫出了這樣的圖,每個題目就是一張這樣的圖。上半的圖中,可以看到三條灰虛線,代表全體精熟、基礎、待加強的族群中,它們的答對率是多少,灰色實線則是全體的答對率。這可以用來評估這題的難易度。

接著有綠線和黃線分別代表區域和校內的答對率。透過位置的差異可以直觀看出在這道題目之中,學校的表現和區域、全體的表現差異為何。

再來是圖中的有數字的灰色圓圈,則是班級的答對率。可以看看在這題目上,不同班級的答對率的差異為何,也能知道相對位置,是不是跟全體答對率差不多,還是遠低於全體答對率。如果是比全體答對率還低,也許就要多注意看看。

下方的長條圖,則是每班在每個選項的選答率,對於答對率相似的兩個班級來說,其不同選項的選答率不會一樣喔,如果看到某些選項有特別高的選答率就需要特別注意了。不過圖中的數字是選答率,以每班30人來算,高了10%的選答率,實質上就是多了三個人選這個選項。



用Google街景歷史功能看植物生長

 今天在看Google 街景的時候發現,拿它的歷史功能也可以作定點觀察,像是觀察一棵樹的成長。

可以試試看找行道樹,但是常常會遇到下一個時間點變成其他樹了,因為本來的樹倒了、死了。找那種比較沒人管理的地方,機會大一點。



像圖片這棵樹,就是一個巷子拐進去的巷弄角落看到的黑板樹,2009年拍攝時,應該是前1-2年樹頂被截切,所以長了好幾個不定枝。成長十三年之後,可能也長成了被截頂之前的樣子。

2022年9月13日

用Google Apps Script彙整試算表多張活頁的成績

同事使用Google表單設計測驗給學生進行週考,每週約有6-7科,每次考試都存至同一個Google試算表的不同活頁。

同事需要每週抓該週的數次考試成績彙整成單個試算表,做週考成績表的統整與發放。若是手工進行, 需要每頁抓取資料後排序再統整,但若遇上有一些學生缺考某些科,則需要再多花時間調整。

假設一學期週考15次,每次需要20分鐘彙整,共兩學期,這樣至少要花600分鐘進行這項工作。由於是重複的工作,應當使用程式來完成,因此我就用Google Apps script幫他寫了一隻程式。程式碼我會直接貼在此文後。

程式的邏輯是這樣:

  1. 事先在目的試算表先建立好所有學生的資料,重點是要有email欄位,因為測驗表單會紀錄學生的email,每位學生只會考一次,所以可以使用email作為index。
  2. 把目的試算表的所有email先存成array,命名為emailArray,以便後續作業。
  3. 指定來源試算表的url,讀取指定的那些活頁。讀取每個活頁,儲存活頁的名稱,歷遍每個row(每個學生的單次考試資料),取得每個row的email和分數,然後用email去找它在emailArray中的哪個位置(使用indexOf),這可以幫助定位出「這筆學生分數應該放在目的試算表的哪個row)
  4. 在目的試算表的Column部份,其欄名使用來源試算表的活頁名稱,並將該次該科學生的成績按照上一步驟得到的位址資訊填入目的試算表的該欄
  5. 當該科考試的成績填完之後,再讀取下一個指定的活頁,直到指定的活頁都讀取完。
  6. 其中會發現有些來源資料表的email未被列在目的資料表的emailArray中(使用indexOf會return -1),遇到這樣的資料則將之Logger.log印出。


使用此程式之後,每週只需要更改需要讀取的活頁index,即可快速彙整成績

程式如下。需在Google Apps Script中使用,並允許一些試算表的讀取權限。


var sourceUrl = 'https://docs.google.com/spreadsheets/d/XXXXXX/';  //成績來源試算表
var targetUrl = 'https://docs.google.com/spreadsheets/d/oooooo/';  //登錄在哪個試算表


var startSheet = 37;     //從第幾個sheet開始登錄成績
var sheetNum = 6;        //共有幾個sheet要登錄成績
var targetSheetIndex = 0 //登錄在第幾個sheet(第一個Sheet的index為0)


var emailCol = 5;        //email在第幾欄(E欄為第5欄)
var subjectColumn = 6;   //登錄從第幾欄開始(F欄為第6欄)

function getData() {
  var sourceSS = SpreadsheetApp.openByUrl(sourceUrl);
  var sourceSheets = sourceSS.getSheets();

  var targetSS = SpreadsheetApp.openByUrl(targetUrl);
  var targetSheets = targetSS.getSheets();  
  var targetRowNum = targetSheets[targetSheetIndex].getLastRow();

  // 從targetSheet獲取email array。從2d array變成 1d array
  var emailArray = targetSheets[targetSheetIndex].getRange(2,emailCol,targetRowNum-1,1).getValues().flat();
  
  //歷遍每個週考的sheet
  for(var i = startSheeti < startSheet + sheetNum ; i++) {
    var subject = sourceSheets[i].getName();

    // 在targetSheet寫入科目欄名
    targetSheets[targetSheetIndex].getRange(1,subjectColumn ,1 ,1).setValue(subject);

    //尋找該科目在array的哪個index
    var rowNum = sourceSheets[i].getLastRow();
    
    // 到每頁成績表的每列找資料,紀錄email欄位和科目欄位
    for (var j = 2j <= rowNumj++) {
      var email = sourceSheets[i].getRange(j2).getValue();
      var score = sourceSheets[i].getRange(j3).getValue();

      // 到彙整試算表找email相等的欄位,填入對應的科目分數
      var emailPos = emailArray.indexOf(email);
      if (emailPos > -1) {
        targetSheets[targetSheetIndex].getRange(emailPos + 2subjectColumn).setValue(score);
      }
      else{
        Logger.log(email + " " + subject + " "score);
      }
    }
    subjectColumn += 1;
  }
}

function main(){
  getData();
}

2022年9月5日

會考分析的程式實作方法

上週把心測中心的資料用程式做出了一個分析檔案,詳見此篇

以下就紀錄一些整個文件的製作想法。

分析後的結果內容是一個PDF,按照答題率高低分頁,每頁一題共三張圖,圖一是把各題的選項答題率畫成折線圖,圖二是把通過率和鑑別度畫成散佈圖再把該題的位置標上去,圖三再加上題目截圖,

其實完全可以用手工製作,但是做完應該會往生。我做了四個年度的考題分析,以111年度的考題共有214題,而108~109的題目數量則較多一些。每題要三張圖。所以共計大約要900張圖。如果做錯一個部份的話,就要再從來一次。所以盡可能都要用程式去完成,才能省工。

首先是試題分析word檔,因為是直接透過雲端硬碟開啟的,所以我是從google文件上複製下來,再貼到gnumeric上存成ods檔,然後再用python讀取每一題的每一選項的答題率和鑑別度、通過率這些。由於我工作電腦是linux,所以使用gnumeric和ods檔對我最方便,若是在windos電腦上,使用xlsx亦可。

讀取後存成dataframe,再去讀取每一題的標準答案,將每一題的標準答案畫在圖表的第一個位置,再將剩下三個選項按照全體答題率的順序畫出。其他群題如基礎或待加強的學生的選項順序也是依照全體的資料來排。這可以讓使用者直接看到各個不同群體和全體的差異是什麼?若是以最簡單的題目來看,則這些群體的答題曲線都是類似的。而通過率越低的題目,它的答題曲線就會越特別。

接下來的第二張圖的繪製,以前就寫了程式,所以直接複製過來就行。讀取該科該年段所有題目的通過率和鑑別度畫成散布圖,再以每一題的資料各自畫出一張圖。好處是你可以看到整體題目的分佈,是不是有離群值?大致分佈的通過率範圍在哪裡?都可以一目了然。

第三張圖不過就是題目截圖,花了一些時間研究如何達成。先用python解析pdf文檔,解析完會得到許多文字框的資訊,包含文字框的座標和內容。但PDF文字框的規則不知道是怎麼做的?有些是一整個題目就是一個文字框,但有些又不是。而我需要的是找出每一題的座標在哪裡,作法是在歷遍各個文字框的內容找出「題號」和「D選項」分別在哪些文字框中,紀錄該文字框所在的頁面、Y座標。然後再根據這些Y座標找出每一題的起訖座標,再根據這些座標截圖下來。這邊要提醒的是,座標原點在左下角,所以Y座標是向上為正。

本來這樣的邏輯應該可以順利解出所有的題目圖檔,但是偏偏各科的排版方式都不太一樣,所以我會再人工檢查每一題的圖檔是否正確,若是有錯則是人工再截圖過。

做完以上三張圖之後,其實工作就完成了八九成了,剩下就是把三張圖合成一張圖,再根據通過率的高低,排出一個PDF檔。