Digital Micrograph로 플라스틱 쓰레기의 IR 스펙트럼 조사

8104 단어 DigitalMicrographPCA
pirika 정보
pirika라는 단어를 처음 들으신 분들은 지금 당장 앱스토어에서'pirika'를 검색해서 설치하세요.모두 근처, 고향, 여행지의 쓰레기를 줍고 투고하자.나도 요즘 시작했어.
이 pirika는 쓰레기를 줍는 응용 프로그램이지만 개발 측은 일본·지구상의 쓰레기를 줄이기 위해 다양한 활동을 하고 있다.상세한 상황은 홈페이지에 일본 각지의 미세 플라스틱 쓰레기 정보오픈 데이터로 공개가 적혀 있다.데이터는 마이크로플라스틱의 외관 사진, IR(적외선 스펙트럼) 스펙트럼으로 2018~2020 조사에서 공개됐다.이 IR 데이터를 화학적으로 분석하는 데 관심이 있어서 디지털 마이크로그래프로 처리해봤어요.temDM 플러그인을 화학 계량기로 사용하여 주성분 분석(Principle Component Analysis, PCA)을 진행한다.
IR 데이터 읽기
공개 데이터는 매년 양식이 미묘하게 다르다.이번에는 2020년 데이터를 대상으로 한다.스펙트럼 처리를 위해서는 csv 파일을 읽는 순서에 따라 배열해야 합니다.더듬으면서 쓴 스크립트가 여기 있습니다.TagGroup을 사용하여 파일 목록을 관리합니다.
open_ATRCSV.s
//read .csv as image
image readCSV(string path,number datatype,number header)//datatype=2 for real4
{
    number fileID=OpenFileForReading(path)
    object fstream=NewStreamFromFileReference(fileID,1)
    number n=0
    string text
    while(n<header)
    {
        fstream.StreamReadTextLine(0,text)
        n=n+1
    }
    number bLinesAreRows=1
    number bSizeByCount=1
    object imgSizeObj=Alloc("ImageData_ImageDataSize")
    image img:=ImageImportTextData(path,fstream,datatype,imgSizeObj,bLinesAreRows,bSizeByCount)
    return img
}

//add tag to an image
void addTg(TagGroup Tg,image img)
{
    TagGroup imgTg=img.ImageGetTagGroup()
    TagGroupCopyTagsFrom(imgTg,Tg)
}

//get path of target directory
string filename
string targetname="ATR.csv" //"ATR.CSV" for 2019 data (uppercase character)
if(!OpenDialog(Null, "Select "+targetname+" file", "*"+targetname, filename)) exit(0)
string dirpath=GetApplicationDirectory(0,0)
result("exploring the below directory\n")
result(dirpath+"\n")

//get file list in the target diectory
TagGroup fileList=GetFilesInDirectory(dirpath,1)
//filelist.TagGroupOpenBrowserWindow("file list",0)

//get file list of "*ATR.csv"
TagGroup targetList=NewTagList()
number n
string tempname
for(n=0;n<fileList.TagGroupCountTags();n++)
{
    //check file name
    fileList.TagGroupGetTagAsString("["+n+"]:Name",tempname)
    if(tempname.len()>targetname.len())
    {
        if(tempname.right(targetname.len())==targetname)
        {
            targetList.TagGroupInsertTagAsString(infinity(),tempname)
        }
    }
}
result("number of ***"+targetname+" files: "+n+"\n")
//targetList.TagGroupOpenBrowserWindow(targetname,0)

//opening csv files if file format is the same as the first one
//opened csv image is stored into a tag group "openListAsImg".
string path //file path
number datatype=2 //datatype=2 for real4 (float)
number header=1 //number of header rows in csv
image firstImg //image of the first csv file in the targetList
TagGroup openList=NewTagList() //list of the name of the opened files
TagGroup openListAsImg=NewTagList() //image list of the opened files
number x,y,x0,y0
//first csv image
targetList.TagGroupGetIndexedTagAsString(0,path)
firstImg:=readCSV(dirpath+path,datatype,header)
firstImg.GetSize(x0,y0)
openListAsImg.TagGroupInsertTagAsArray(infinity(),firstImg)
openList.TagGroupInsertTagAsString(infinity(),path)

//opening csv files
for(n=1;n<targetList.TagGroupCountTags();n++)
{
    targetList.TagGroupGetIndexedTagAsString(n,path)
    //check size of the csv file
    readCSV(dirpath+path,datatype,header).GetSize(x,y)
    if((x==x0)&&(y==y0))
    {
        openListAsImg.TagGroupInsertTagAsArray(infinity(),readCSV(dirpath+path,datatype,header))
        openList.TagGroupInsertTagAsString(infinity(),path)
    }
}

//stack all opened csv data
number z0=openListAsImg.TagGroupCountTags()
image stackImg:=RealImage(targetname,4,x0,y0,z0)
for(n=0;n<z0;n++)
{
    openListAsImg.TagGroupGetIndexedTagAsArray(n,stackImg[0,0,n,x0,y0,n+1])
}

//set openList tag to "file list" tag
TagGroup openFileList=NewTagGroup()
openFileList.TagGroupSetTagAsTagGroup("file list",openList)

//image stackImg should have (x,y,z)=(col,row,number of opened data)
result("number of opened data files: "+z0+"\n")

//wavelength as an image
image wavelength=stackImg.slice2(0,0,0,1,y0,1,2,z0,1)
wavelength.SetName("wavelenghth")
addTg(openFileList,wavelength)
wavelength.showimage()
result("wavelength range: "+wavelength.min()+" - "+wavelength.max()+"\n")

//spetrum as an image
image spc=stackImg.slice2(1,0,0,1,y0,1,2,z0,1)
spc.SetName("spectrum")
addTg(openFileList,spc)
spc.showimage()

//spectrum as an spestrum imaging type data (3D)
image spccube=stackimg.slice3(1,0,0,2,z0,1,0,1,1,1,y0,1)
spccube.SetName("spectrum cube")
addTg(openFileList,spccube)
spccube.showimage()
데이터 사전 처리
출력된 2020년의 데이터를 보면 때로는 절대치가 1을 초과하기도 한다.나는 출력 데이터의 계산 방법을 모르겠지만 투사율로 1을 넘으면 이상하다.데이터로서도 이상하지 않다. 많은 데이터가 1에 미만하고 주성분 해석 편리치가 약하기 때문에 절대치가 1을 초과한 데이터는 잠시 무시한다.마이너스가 나올 줄도 몰랐지만 마이너스 수치는 잠시 보류했다.
delete_invalid_spc.s
//delete data which has a value larger than one
image in:=getFrontImage() //"spectrum cube" should be the front.
number x,y,z
in.Get3DSize(x,y,z)
string name
in.GetName(name)

TagGroup inTg=in.ImageGetTagGroup()
TagGroup originalFileList
inTg.TagGroupGetTagAsTagGroup("file list",originalFileList)
TagGroup cpTg=originalFileList.TagGroupClone() //copy

//store image into tag group
TagGroup imgTg=NewTagList()
image temp
number n
for(n=x-1;n>=0;n--)
{
    temp=in.slice1(n,0,0,2,z,1)
    if(temp.abs().max()>1)
    {
        cpTg.TagGroupDeleteTagWithIndex(n)
    }
    else
    {
        imgTg.TagGroupInsertTagAsArray(0,temp)
    }
}

number nn=cpTg.TagGroupCountTags()
image delImg:=RealImage(name+" del",4,nn,y,z)

for(n=0;n<nn;n++)
{
    imgTg.TagGroupGetIndexedTagAsArray(n,temp)
    delImg[n,0,0,n+1,y,z]=temp.slice3(0,0,0,1,1,1,2,1,1,0,z,1)
}

TagGroup resultTg=delImg.ImageGetTagGroup()
resultTg.TagGroupSetTagAsTagGroup("file list",cpTg)

delImg.showimage()
PCA
이곳에서 생성된 데이터에 대해 주성분 분석을 진행하다.데이터만 만들면temDM으로 클릭하면 해석이 완료됩니다.scree plot(variaance)를 보면 대체로 세 번째 성분이 주요 스펙트럼이지만 로드의 형태를 확인하면 상당히 높은 단계에 스펙트럼 정보가 남아 있다.참고로variance는log가 표시하기 때문에 이 데이터는 마이너스입니다.


나는 여기에 나타난 주요 성분의 해석을 잘 모른다.첫 번째 주성분(PCA1)은 스펙트럼 모양이 예쁘지 않고 매우 기울어져 있으며 주로 배경의 강도를 나타내는 성분이다.PCA2, PCA3은 플러스와 마이너스를 무시하면 최고치의 위치가 비슷해 어느 것이든 PE처럼 보인다.인자가 회전하면 언뜻 보면 PE 스펙트럼과 배경 성분으로 나뉘는데 두 종류의 PE 스펙트럼으로 해석해야 할지 모르겠다.PC4는 PP의 스펙트럼을 반영하는 것으로 보인다.나는 PC5가 앞으로 어떻게 설명해야 할지 전혀 모르겠다.pirika가 정리한 자료를 보면 PE, PP 이외의 PS, Nylon 등도 상응하는 비율로 포함되어 있지만 PCA로 이 스펙트럼을 추출하는 것은 어려워 보인다.데이터 처리는 이미 끝났지만 설명할 수 없으니 여기까지입니다.쓰레기를 분류해라!의욕은 있지만 내 힘으로는 소용없다.서운하다
PCA의 2
살려줘.여기에temDM을 사용해 PCA를 계산했고, 디지털 마이크로그래프의 새 버전에는 가탄 독자 MSA(multi-variate statistical analysis) 기능이 추가돼 PCA도 가능하다.GMS3.4 이후의 새로운 기능이기 때문에 GMS3입니다.x의 초기에는 아마 안 될 것이다.temDM이라면 입력 데이터가 3차원으로 변하지 않으면 이동하지 않지만, 가탄의 함수라면 스펙트럼을 배열한 2차원 데이터라도 입력을 받아들인다.
msa.s
image spc:=GetFrontImage() //2D image can be loaded

image score,load,scree
MSA_PCA(spc,score,load,scree,0)

scree.setname("scree")
score.setname("score")
load.setname("load")

scree.showimage()
score.showimage()
load.showimage()
출력 결과로 보아 score와load의 이름이 바뀌었습니다. MSAPCA()가 함수에 들어오는 순서를 변경해야 할 수도 있습니다.Gatan 공식 문서에서 이 순서는 다음과 같습니다.
void MSA_PCA( BasicImage src, BasicImage scoreStack, BasicImage loadStack, BasicImage eigenValuesLog10, Boolean
useDoublePrecision )
PCA뿐만 아니라 varimax 회전과 ICA(independent component analysis/blind source separation)도 계산할 수 있어 사용할 수 있을 것 같지만 솔직히temDM만 있으면 되지 않을까...

좋은 웹페이지 즐겨찾기