/******************************************************************************* A PROGRAM TO CONTROL CCD CAMERA - HYUNG-MIN PARK(hmpark@kasi.re.kr) modified - Juhyung Kang(jhkang@kasi.re.kr) DESCRIPTION : THE FILE INCLUDE FUNCTIONS TO OPERATE CCD CAMERA. THIS FILE CONSISTS OF TWO PARTS, ONE IS CCD CONTROL, ANOTHER IS VIEWER. *REVISION HISTORY JAN 10 2006: ADD FUNCTIONS - DISPLAY BITMAP() JAN 19 2006: ADD FUNCTIONS - OPEN BITMAP() JAN 22 2006: FIRST SUCCESS TO OPERATE CCD CAMERA - TURN ON/DISPLAY IMAGE JAN 29 2006: REALIZE SOME FUNCTIONS - OPEN, GET CCD INFORMAITON, SET, CLOSE, DISPLAY - FLIP IMAGE(UPSIDE DOWN) FEB 14 2006: START TO WRITE FITS READ FUNCTION FEB 21 2006: SAVE THE DATA AS FITS FORMAT -INCLUDE BYTE CHANGE, BYTE SCALE, FLIP -USE TIME INFORMATIONS AS FITS FILE NAME MAR 12 2006: START TO REALIZE SEQUENTIAL OBSERVATION BY USING CVI TIMER MAR 14 2006: ADD SOME FUNCTIONS TO TAKEIMAGE() MAR 19 2006: COMPLETE SEQUENTIAL OBSERVATION BY USING TIMER MAR 26 2006: ADD CCD COOLING FUNCTION APR 23 2006: ADD BINNING FUNCTION MODIFY TWO FUNCTIONS - DISPALYIMAGE, TAKEIMAGE MAY 02 2006: REALIZE KINETIC MODE OF CCD MAY 15 2006: MODIFY TAKEIMAGE(), TAKEIMAGE() AND SAVEFITS() -ADD FRAMENUMBER, MAY 21 2006: ADD SHUTTER CONTROL FUNCTION MAY 25 2006: REALIZE FRAME TRANSFER MODE JUN 04 2006: REALIZE REAL TIME OPERATION BY USING THREAD FROM STANDARD C CODE AUG 30 2006: SUCCESS TO DISPLAY DATA FROM CCD CAMERA BY USING NI-VISION LIBRARY NOV 15 2006: MODIFY SOME FUNCTIONS - BYTEDISPLAY(MIN, MAX) NOV 20 2006: ADD 3D DISPLAY FUNCTION NOV 23 2006: SUCCESS TO DISPLAY DATA ON PANNEL PICTURE COMPONENT(CVI FUNCTION) NOV 28 2006: MODIFY SAVEFITS FUNCTION(3D DATA SAVE) JAN 16 2008: REALIZE VIEWER FUNCTION DISPLAY BMP AND FITS FORMAT 2D(OPENFITS()),3D(OPENFITS1()) CONSIDER 2 CAMERA CONNECTION MAR 19 2008: ADD DISPLAY HISTOGRAM ADD READ MOUSE POSITION BY USING TIMER MAY 20 2008: MODIFY PROGRAM - CONSIDER PROCESS SPEED JUL 16 2008: COMPLETE INCREASE PROCESSING SPEED JUL 28 2008: MODIFY GUI- INPUT WINDOW ADD SCANNER CONTROL PROGRAM AUG 02 2008: DISPLAY 3D DATA ON PICTURE RING COMPONENT AUG 04 2008: INTEGRATE TWO FUNCTIONS OPENFITS() AND OPENFITS1() AUG 06 2008: MAKE VIDEO MODE BY USING CVI THREAD FUNCTION AUG 08 2008: READ FITS FILE AS 2D OR 3D BY USING SELECT BUTTON AUG 20 2008: MODIFY HISTOGRAM - ADD REFRESH FUNCTION OCT 22 2008: CHANGE SDK VERSION - 2.78 OCT 28 2008: RENAME FILENAME NOV 06 2008: INTEGRATION PARAMETERS BETWEEN CCD AND SCANNER(SUPERPOSITION) FEB 09 2009: ADD DATA PATH BY USING ANDOR CCD FUNCTION MAR 11 2009: MODIFY DISPLAYIMAGE() APR 01 2009: COMPLETE FITS DISPLAY JUL 01 2009: INTEGRATE CCD_SCANNER PROGRAM AND GRATING/CCD CONTROL PROGRAM SEP 15 2009: MODIFY PROGRAM - SCANNER THREAD, MENU SIMPLIFY, SEP 22 2009: DEBUG HISTOGRAM FUNCTION ADD LINE PROFILE DISPLAY FUNCTION NOV 11 2009: CHANGE THE ROUTINE - USE NASA CFITSIO FITS LIBRARY REDUCE FITS SAVE TIME FROM ABOUT ~13 SEC TO ABOUT ~3 SEC DEC 02 2009: MODIFY SOME FUNCTIONS - CONSIDER 2 CAMERA USING SETCAMERAPARAM() - ADD ONE PARAMETER - CAMERA HANDLE DATADUMP() - ADD 1 PARAMETER - G_PRAWDATA2 Dec 19 2019: Hugely modified. At this time, the CVI graphic pannel is deleted and scanner and grating are splitted out from this code. This code will be exported as DLL, then it can be used any other code that supprt the DLL loading. (modified by J. Kang) ********************************************************************************/ #ifndef _CRT_SECURE_NO_WARNINGS #define _CRT_SECURE_NO_WARNINGS #endif #define CCD_EXPORT #include #include #include #include #include "Atmcd32d.h" #include "CCD.h" #include "fitsio.h" int errorValue; LARGE_INTEGER gliFreq, gliStart, gliEnd; #ifdef __cplusplus extern "C" { #endif char* isot2fname(char* isot); //initialize camera CCD_API int OpenCamera(CCDInfo* CCD, AndorCapabilities* caps) { CCD->status = -1; caps->ulSize = sizeof(AndorCapabilities); SetCurrentCamera(CCD->camera); //작업 폴더를 지정하는 부분 GetCurrentDirectoryA(256, CCD->CCDPath); // Look in current working directory (cvi func) //Turn on CCD system errorValue=Initialize(CCD->CCDPath); // Initialize driver in current directory if (errorValue!=DRV_SUCCESS) { // MessagePopup("Error","Initialize Error"); //cvi function return ERR_initialize; } //SetCurrentCamera((*CCD).camera); errorValue=GetDetector(&CCD->CCD_XPix, &CCD->CCD_YPix); if(errorValue!=DRV_SUCCESS) { // MessagePopup("Error","Get Detector information Error"); return ERR_getDetectorInfo; } errorValue=GetHeadModel(CCD->ccdName); if(errorValue!=DRV_SUCCESS) return ERR_getHeadModel; CCD->status = 1; if(!QueryPerformanceFrequency(&gliFreq)) return ERR_setGliFreq; return 1; } //프로그램을 수행하는 과정에서 실질적으로 필요가 없는 함수 //단지 하드웨어의 사양과 기본설정을 확인하는 함수 //Get hardware information from CCD and Frame Grabber Card CCD_API int GetCameraInfo(char* array, AndorCapabilities* caps) { char ccd_model[32]; // headmodel char buffer[100]; int VSNumber;// = 0; // Vertical Speed Index int HSNumber;// = 0; // Horizontal Speed Index unsigned int PCB, Flex, dum1,dum2,dum3,dum4; // Information of hardware version unsigned int eprom, cofFile, vxdRev,vxdVer,dllRev,dllVer; int minTemp, maxTemp; //get (min,max)temperature int XPixels, YPixels; int index; int iSpeed; float speed; int lowGain, highGain,curgain; int ampgain; int nAD,iAD,ADNumber; float STemp; // Get camera capabilities errorValue=GetCapabilities(caps); if(errorValue!=DRV_SUCCESS) return ERR_getCapabilities; // Get Head Model errorValue=GetHeadModel(ccd_model); if(errorValue!=DRV_SUCCESS) return ERR_getHeadModel; sprintf(array,"Head Model : %s\n",ccd_model); // Get detector information errorValue=GetDetector(&XPixels, &YPixels); if(errorValue!=DRV_SUCCESS) return ERR_getDetectorInfo; sprintf(buffer, "Size of CCD : %d X %d pixels\n", XPixels, YPixels); strcat(array, buffer); // // Set Vertical speed to max -> g_nVSNumber // STemp = 0.0; VSNumber = 0; GetNumberVSSpeeds(&index); //index=5, what? for(iSpeed=0; iSpeed STemp) { STemp = speed; VSNumber = iSpeed; } } /* VSNumber is 4*/ sprintf(buffer, "VSNumber is %d\n", VSNumber); strcat(array, buffer); GetVSSpeed(VSNumber, &speed); sprintf(buffer, "Vertical Speed : %g microseconds per pixel shift\n",speed); strcat(array, buffer); STemp = 0.0; HSNumber = 0; ADNumber = 0; errorValue=GetNumberADChannels(&nAD); if(errorValue!=DRV_SUCCESS) return ERR_getNumADChannels; else { for(iAD=0;iADSTemp) { STemp=speed; HSNumber=iSpeed; ADNumber=iAD; } } } } sprintf(buffer,"ADNumber is %d\n",ADNumber); strcat(array,buffer); sprintf(buffer,"HSNumber is %d\n",HSNumber); strcat(array,buffer); GetHSSpeed(0,0,HSNumber, &speed); if(caps->ulCameraType==1) sprintf(buffer, "Horizontal Speed : %g MHz\n", speed); else sprintf(buffer, "Horizontal Speed : %g microseconds per pixel shift\n", speed); strcat(array, buffer); GetHardwareVersion(&PCB,&Flex,&dum1,&dum2,&dum3,&dum4); sprintf(buffer,"Plug-in card version : %.2f\n" ,(double)PCB); strcat(array,buffer); sprintf(buffer, "Flex 10K file version : %.1f\n", (double)Flex); strcat(array,buffer); sprintf(buffer, "Camera FirmWare Version :%.2f\n", (double)dum3); strcat(array,buffer); sprintf(buffer, "Cam Firmware Build No : %.2f\n", (double)dum4); strcat(array,buffer); GetSoftwareVersion(&eprom,&cofFile,&vxdRev,&vxdVer,&dllRev,&dllVer); sprintf(buffer,"EPROM_ver : %.1f\n",(double)eprom); strcat(array,buffer); sprintf(buffer, "COF_file_ver : %.1f\n", (double)cofFile); strcat(array,buffer); sprintf(buffer, "Driver_revision_num : %.1f\n", (double)vxdRev); strcat(array,buffer); sprintf(buffer, "Driver_ver : %.1f\n", (double)vxdVer); strcat(array,buffer); sprintf(buffer,"DLL_revision_number : %.1f\n", (double)dllRev); strcat(array,buffer); sprintf(buffer, "DLL_ver : %.1f\n",(double)dllVer); strcat(array,buffer); GetTemperatureRange(&minTemp,&maxTemp); sprintf(buffer,"Temperature range : From %d C to %d C\n", minTemp, maxTemp); strcat(array,buffer); GetEMGainRange(&lowGain, &highGain); sprintf(buffer, "EM Gain range : From %d to %d\n", lowGain, highGain); strcat(array,buffer); GetEMCCDGain(&curgain); sprintf(buffer,"Current EMGain value :%d\n", curgain); strcat(array,buffer); GetNumberPreAmpGains(&gain); sprintf(buffer, "pre amp gain :%d\n", ampgain); strcat(array, buffer); if(caps->ulTriggerModes & AC_TRIGGERMODE_CONTINUOUS) strcat(array,"Correct Hardware for Continuous Mode\n"); else strcat(array,"InCorrect HardWare for Continuous Mode\n"); errorValue=IsTriggerModeAvailable(10); if(errorValue==DRV_SUCCESS) strcat(array,"Software Trigger Mode Available\n"); else strcat(array,"Not Valid Mode for Software Trigger\n"); //GetNumberADChannels(&nIndex); //printf("ADChannel Index:%d\n",nIndex); return 1; } //카메라 세팅을 하는 부분 CCD_API int SetCameraParam(CCDInfo* CCD, char* statOut) { float fAccumTime, cycletime; //get accumate time, cycle time; int ttl, openclose; //associate with shutter setting int hStart, vStart, hEnd, vEnd; char buffer[100]; int framesize; /////////////////////////////////////// //this part come from TakeImage function /////////////////////////////////////// int nBytePerPixel = 2; //because the dynamic range of CCD Camera is 14bits (need to 16bit : 2byte) int nByteSize; int nPixelSize; int g_nVSNumber; int g_nHSNumber = 0; hStart=1; //start horizontal pixel position on CCD chip vStart=1; //start vertical pixel position on CCD chip SetCurrentCamera(CCD->camera); if(CCD->CCD_XPix>1000) //dv885 { g_nVSNumber = 3; //0; //the value determinid is 3, in case of dv885 hEnd = CCD->CCD_XPix; vEnd = CCD->CCD_YPix-2; CCD->nx = ((hEnd-hStart+1)/CCD->HBin)/2; //actual horizontal size on CCD chip CCD->ny = ((vEnd-vStart+1)/CCD->VBin)/2; //actual vertical size on CCD chip // vEnd=g_nYPixels1; // nhDim=((hEnd-hStart+1)/HBin); //actual horizontal size on CCD chip // nvDim=((vEnd-vStart+1)/VBin); //actual vertical size on CCD chip } else //dv887 { g_nVSNumber = 4; //0; //the value determinid is 4, in case of dv887 hEnd = CCD->CCD_XPix; vEnd = CCD->CCD_YPix; CCD->nx = (hEnd-hStart+1)/CCD->HBin; //actual horizontal size on CCD chip CCD->ny = (vEnd-vStart+1)/CCD->VBin; //actual vertical size on CCD chip } framesize = CCD->nx * CCD->ny; if(CCD->ScanNum > 0) //for Single Mode nPixelSize = framesize * CCD->ScanNum; else if(CCD->ScanNum == 0) //for video mode nPixelSize = framesize; nByteSize = nPixelSize * nBytePerPixel; //CCD->RawData = NULL; CCD->RawData = (WORD*)malloc(nByteSize * sizeof(unsigned short)); //allocate the memory to store image memset(CCD->RawData, 0, nByteSize); if(CCD->AcqMode==0 || CCD->AcqMode==1 || CCD->AcqMode==10) { SetFrameTransferMode(0); //turn off frame transfer mode errorValue =SetAcquisitionMode(1); if(errorValue!=DRV_SUCCESS) return ERR_setAcqMode; } else if (CCD->AcqMode==6) //frame transfer mode { SetFrameTransferMode(1); errorValue=SetNumberKinetics(CCD->ScanNum); if(errorValue!=DRV_SUCCESS) return ERR_setFrameNum; } else if (CCD->AcqMode==8) // this mode is not currently available. { SetFrameTransferMode(0); //turn off frame transfer mode errorValue = SetAcquisitionMode(1); if(errorValue!=DRV_SUCCESS) return ERR_setAcqMode; // SetFrameTransferMode(1); // errorValue=SetNumberKinetics(1); // if(errorValue!=DRV_SUCCESS) // MessagePopup("Error","Set number Frames error"); } // else if (acquisition==0) // { // SetFrameTransferMode(0); // SetAcquisitionMode(acquisition); // SetKineticCycleTime(0); // } // set to take image, track, line, etc : 찍는 대상을 어떻게 찍을 것인지 적용시키는 부분 errorValue=SetReadMode(CCD->ReadMode); if(errorValue!=DRV_SUCCESS) return ERR_setReadMode; // //CCD 구동속도와 관련된 부분 //이 부분은 현재 적용된 값을 쓰는 것이 최대 성능을 발휘 한다. errorValue = SetVSSpeed(g_nVSNumber); errorValue = SetADChannel(0); //0,1 for 897, 0 for 885 errorValue = SetHSSpeed(0, g_nHSNumber); //////////////////// //shutter setting //////////////////// ttl=1; // 0:output TTL low signal to open shutter openclose=1; // millisecond errorValue=SetShutter(ttl, CCD->ShutterMode, openclose, openclose); if(errorValue!=DRV_SUCCESS) return ERR_setShutter; errorValue=SetPreAmpGain(CCD->PGain); //CCD가 Dynamin Range안의 값을 푠현하기 위해 필요한 부분 //이 부분이 세팅되지 않으면 얻어지는 값의 크기가 작아진다. if(errorValue!=DRV_SUCCESS) return ERR_setPreAmpGain; // Set EMCCD Gain errorValue = SetEMCCDGain(CCD->Gain); if (errorValue != DRV_SUCCESS) return ERR_setGain; Sleep(250); // Set to image size and binning on CCD chip // //Binning parameter //hBin, vBin : 비닝비율(가로, 세로) //hStart, hEnd : CCD chipset에서 가로축의 시작/끝 위치 //vStart, vEnd : CCD chipset에서 세로축의 시작/끝 위치 if(CCD->CCD_XPix>1000) //DV885 errorValue=SetImage(CCD->HBin*2, CCD->VBin*2, hStart, hEnd, vStart, vEnd); // errorValue=SetImage(HBin*1,VBin*1,hStart,hEnd,vStart,vEnd); else //DV997 errorValue=SetImage(CCD->HBin, CCD->VBin, hStart, hEnd, vStart, vEnd); errorValue=SetTriggerMode(CCD->Trigger); if(errorValue!=DRV_SUCCESS) return ERR_setTriggerMode; //set to acqual parameters such as exposure time, accumulation time and kinetic time sprintf(statOut, "\nsetting exposure time is %f\n", CCD->exptime); // Apply actual Exposure Time errorValue = SetExposureTime(CCD->exptime); if (errorValue != DRV_SUCCESS) return ERR_setExpTime; //Bias Level과 관련된 부분 //이 부분이 세팅되지 않으면 특정값(ex 800부근)을 기준으로 //그보다 작은 값은 0으로 잘라버리는 역할을 한다. //노출시간이 작더라도 원하는 영상을 얻기 위해선 현재의 세팅을 사용하는 것이 좋다. // errorValue=SetBaselineClamp(1); // if(errorValue == DRV_SUCCESS) // { // SetCtrlVal(mainPanel, PANEL_TB_Text_Monitor,"BaseLine Clamp Setting enalbe\n"); // errorValue=SetBaselineOffset(1000); // if(errorValue != DRV_SUCCESS) // SetCtrlVal(mainPanel, PANEL_TB_Text_Monitor,"Not Set Baseline Clamp\n"); // } // if(baseline == 0) // { // errorValue=SetBaselineClamp(0); // SetCtrlVal(mainPanel, PANEL_TB_Text_Monitor,"SetBaseline Clamp Off\n"); // } // if(baseline == 1) // { errorValue=SetBaselineClamp(1); if(errorValue == DRV_SUCCESS) errorValue=SetBaselineOffset(1000); // } /* This function will return the current "Valid" acquisition timing information. This function shoudl be used after all the acquisitions settings have been set, e.g. SetExposureTime, SetKineticCycleTime, SetReadMode etc. The Values returned are the actual times used in subsequent acquisitions. It is necessary to get the actual times as the system will calculate the nearest possible time. E.g, if you set exposure time to be 0, the system will use the closest value(around 0.00002s) */ GetAcquisitionTimings(&CCD->exptime, &fAccumTime, &cycletime); sprintf(buffer, "\nactual exposure time is %f,\nvalid kinetic cycle time is %f\n", CCD->exptime, cycletime); strcat(statOut, buffer); //SetCtrlVal(mainPanel, PANEL_TB_Text_Monitor,"Setting Complete\n"); // errorValue=StartAcquisition(); // if(errorValue!=DRV_SUCCESS) // { // MessagePopup("Error","Start acquisition error"); // AbortAcquisition(); // return; // } return 1; } //////////// CCD_API int TakeBiasDark(CCDInfo* CCD) { //BiasDark 찍기 전에 SetCameraParam 함수가 적어도 한 번 선행되어야 한다. int nStatus; int ttl, openclose; //associate with shutter setting int framesize; int nByteSize; int number=100; int acquisition=6; int shutter=2;//close int fan=0; int trigger=0; int i,j,nStartPoint; unsigned short* BiasDarkTemp; double diff_time; SetCurrentCamera(CCD->camera); framesize = CCD->nx * CCD->ny; nByteSize = framesize * sizeof(unsigned short); CCD->BiasDark = (unsigned short*)malloc(nByteSize); BiasDarkTemp = (unsigned short*)malloc(nByteSize * number); memset(CCD->BiasDark, 0, nByteSize); memset(BiasDarkTemp, 0, nByteSize* number); //errorValue =SetAcquisitionMode(acquisition); SetAcquisitionMode(6); SetFrameTransferMode(1); SetNumberKinetics(number); SetExposureTime(CCD->exptime); ttl = 1; // 0:output TTL low signal to open shutter openclose = 1; // millisecond errorValue = SetShutter(ttl, shutter, openclose, openclose); Sleep(250); errorValue = StartAcquisition(); if(errorValue!=DRV_SUCCESS) { AbortAcquisition(); return ERR_startAcq; } do { errorValue = GetStatus(&nStatus); if(errorValue!=DRV_SUCCESS) return ERR_getStatus; } while (nStatus != DRV_IDLE); GetAcquiredData16(BiasDarkTemp, framesize*number); for(i=0;iBiasDark[j] += BiasDarkTemp[j+nStartPoint]; } for(i=0;iBiasDark[i] = CCD->BiasDark[i]/number; SaveBiasDark(*CCD, &diff_time); if(BiasDarkTemp) { free(BiasDarkTemp); BiasDarkTemp = NULL; } return 1; } //////////// int SaveBiasDark(CCDInfo CCD, double* diff_time) { //------------------------- char pFileName[128]; char temp1[50],temp2[50]; char ftemp[50]; //using nasa fits library fitsfile *fptr; int status=0; /////////////////////////////// long naxis[2], fpixel[2], nelements; char filename[512]; naxis[0] = CCD.nx; naxis[1] = CCD.ny; fpixel[0] = fpixel[1] = 1; nelements = naxis[0] * naxis[1]; memset(pFileName, NULL, 128 * sizeof(char)); strcat(pFileName, CCD.FilePath); strcat(pFileName, "\\"); //------------------------- //determine during process sprintf(ftemp, marktime(temp1, &gliStart)); //------------------------- //get systime to write file sprintf(filename, "%sFISS_%s_%.1s_BiasDark.fts", pFileName, ftemp, CCD.camID); //SDO like fits_create_file(&fptr, filename, &status); fits_create_img(fptr, SHORT_IMG, 2, naxis, &status); //fits_write_date(fptr, &status); fits_write_key(fptr,TSTRING, "DATE", temp1, "file creation date (YYYY-MM-DDThh:mm:ss.ddd UT)", &status); fits_write_key(fptr,TFLOAT,"EXPTIME", &CCD.exptime, "Second", &status); fits_write_key(fptr,TUINT,"HBINNING", &CCD.HBin, "", &status); fits_write_key(fptr,TUINT,"VBINNING", &CCD.VBin,"",&status); fits_write_key(fptr,TUINT,"EMGAIN", &CCD.Gain,"Value Range: 0-255",&status); SetCurrentCamera(CCD.camera); GetTemperature(&CCD.Temperature); fits_write_key(fptr,TINT,"CCDTEMP", &CCD.Temperature,"Cooling Temperature of CCD",&status); fits_write_key(fptr,TSTRING,"CCDNAME", CCD.ccdName,"Productname of CCD",&status); fits_write_key(fptr,TUINT,"PAMPGAIN", &CCD.PGain,"Value Range: 0-2",&status); fits_write_key(fptr,TFLOAT,"GRATWVLN", &CCD.gWv,"Grating wavelength for CAM 1", &status); fits_write_key(fptr,TINT,"GRATSTEP", &CCD.gStep,"Grating step count", &status); fits_write_key(fptr,TFLOAT,"GRATANGL", &CCD.gAngle,"Grating angle", &status); fits_write_pix(fptr,TSHORT,fpixel,nelements,CCD.BiasDark,&status); fits_delete_key(fptr,"COMMENT",&status); fits_delete_key(fptr,"COMMENT",&status); fits_close_file(fptr,&status); //------------------------- marktime(temp2, &gliEnd); *diff_time = time_difference(gliStart, gliEnd); return 1; } CCD_API int TakeImage(void) { //*************************************** //start to take picture //*************************************** errorValue = StartAcquisition(); if(errorValue != DRV_SUCCESS) { AbortAcquisition(); return ERR_startAcq; } return 1; //한 컷을 찍고 다음 컷을 찍기까지 필요한 시간. //CCD에서 얻은 데이터를 컴퓨터 메모리로 옮기는 함수 (찍는 함수 옮기는 건 DUMP) } //Dump the data from camera to memory we already allocated CCD_API int DataDump(CCDInfo* CCD, int i) { int nStatus; int nPixelSize; do { errorValue = GetStatus(&nStatus); if(errorValue != DRV_SUCCESS) return ERR_getStatus; } while (nStatus != DRV_IDLE); nPixelSize = CCD->nx * CCD->ny; errorValue = GetAcquiredData16(CCD->RawData+nPixelSize*i, nPixelSize); } CCD_API int TakeImage_FTmode(CCDInfo* CCD) { int nStatus; int nPixelSize = (*CCD).nx * (*CCD).ny * (*CCD).ScanNum; errorValue = StartAcquisition(); if(errorValue != DRV_SUCCESS) { AbortAcquisition(); return ERR_startAcq; } do { errorValue = GetStatus(&nStatus); if(errorValue!=DRV_SUCCESS) return ERR_getStatus; } while (nStatus != DRV_IDLE); errorValue = GetAcquiredData16(CCD->RawData, nPixelSize); return 1; } /*void BiasDarkCorrection(CCDInfo CCD, int framenumber) { int i; int pixelsize = CCD.nx*CCD.ny; int startpoint = pixelsize*framenumber; //due to consumption of time, we adjust this function display spectrograph for(i=0;icamera); Sleep(100); do { errorValue = GetStatus(&nStatus); if(errorValue != DRV_SUCCESS) return ERR_getStatus; } while (nStatus != DRV_IDLE); //////////////////// //shutter setting //////////////////// errorValue=SetShutter(1, 0, 1, 1); if(errorValue!=DRV_SUCCESS) return ERR_setShutter; errorValue=SetFanMode(2); //fan off if(errorValue!=DRV_SUCCESS) return ERR_setFan; errorValue=ShutDown(); if(errorValue!=DRV_SUCCESS) return ERR_shutDown; if (CCD->RawData) { free(CCD->RawData); } if (CCD->BiasDark) { free(CCD->BiasDark); } CCD->status = 0; return 1; } CCD_API char* SaveFits(CCDInfo CCD) { //------------------------- char pFileName[128]; char temp1[50]; char* ftemp; //using nasa fits library fitsfile *fptr; int status=0; /////////////////////////////// long naxis[3], fpixel[3], nelements, naxis_one[2],fpixel_one[2]; //int value; // int waveselect; char filename[512]; //scanner parameter //extern int Sacnner_status; //extern int scan_mode; memset(pFileName,NULL,128*sizeof(char)); strcat(pFileName, CCD.FilePath); strcat(pFileName,"\\"); if(CCD.ScanNum==1) { naxis_one[0]=CCD.nx; naxis_one[1]=CCD.ny; fpixel_one[0]=fpixel_one[1]=1; nelements=naxis_one[0]*naxis_one[1]; } else if(CCD.ScanNum>1) { naxis[0]=CCD.nx; naxis[1]=CCD.ny; naxis[2]=CCD.ScanNum; fpixel[0]=fpixel[1]=fpixel[2]=1; nelements=naxis[0]*naxis[1]*naxis[2]; } //QueryPerformanceCounter(&gliStart); marktime(temp1, &gliStart); ftemp = isot2fname(CCD.stTime); //------------------------- //get systime to write file /* sprintf(pFileName, "FISS_%04d%02d%02d_%02d%02d%02d_A.fts", systime.wYear, systime.wMonth, systime.wDay, systime.wHour, systime.wMinute, systime.wSecond); //old ver sprintf(pFileName, "FISS_%04d%02d%02d_%02d%02d%02d.%03d_A.fts", systime.wYear, systime.wMonth, systime.wDay, systime.wHour, systime.wMinute, systime.wSecond, systime.wMilliseconds); //with msec */ sprintf(filename, "%sFISS_%s_%s.fts", pFileName, ftemp, CCD.camID); fits_create_file(&fptr, filename, &status); if(CCD.ScanNum>1) fits_create_img(fptr, SHORT_IMG, 3, naxis, &status); else if(CCD.ScanNum==1) fits_create_img(fptr, SHORT_IMG, 2, naxis_one, &status); fits_write_key(fptr,TSTRING, "DATE", temp1, "file creation date (YYYY-MM-DDThh:mm:ss.ddd UT)", &status); fits_write_key(fptr,TFLOAT,"EXPTIME",&CCD.exptime,"Second",&status); fits_write_key(fptr,TUINT,"HBINNING",&CCD.HBin,"",&status); fits_write_key(fptr,TUINT,"VBINNING",&CCD.VBin,"",&status); fits_write_key(fptr,TUINT,"EMGAIN", &CCD.Gain,"Value Range: 0-255",&status); fits_write_key(fptr,TSTRING,"STRTIME",CCD.stTime,"Scan Start Time",&status); fits_write_key(fptr,TSTRING,"ENDTIME",CCD.edTime,"Scan Finish Time", &status); fits_write_key(fptr,TFLOAT,"ELAPTIME",&CCD.elapseTime,"Elapse Time During Scanning(Second)",&status); switch(CCD.ScanMode) { case 0: //spectrograph mode fits_write_key_str(fptr,"FISSMODE","Spectrograph","FISS Mode",&status); fits_write_key(fptr,TFLOAT,"STEPTIME",&CCD.stepTime,"1 Step Duration time(millisecond)",&status); fits_write_key(fptr,TFLOAT,"STEPSIZE",&CCD.stepSize,"1 Step size to move scanner(micrometer)",&status); break; case 1: //imaging mode fits_write_key_str(fptr,"FISSMODE","Imaging","FISS Mode",&status); fits_write_key(fptr,TFLOAT,"SCNSPEED",&CCD.scanSpeed,"Scan Speed(micrometer/second)",&status); fits_write_key(fptr,TFLOAT,"SCANDIST",&CCD.scanDist,"Distance to Scan(millimeter)",&status); break; case -1: //None fits_write_key_str(fptr,"FISSMODE","None(Only CCD)","FISS Mode",&status); break; } SetCurrentCamera(CCD.camera); GetTemperature(&CCD.Temperature); fits_write_key(fptr,TINT,"CCDTEMP", &CCD.Temperature,"Cooling Temperature of CCD",&status); fits_write_key(fptr,TSTRING,"CCDNAME", CCD.ccdName,"Productname of CCD",&status); fits_write_key(fptr,TUINT,"CCD_XPIX", &CCD.CCD_XPix,"Full Pixel Size of X",&status); fits_write_key(fptr,TUINT,"CCD_YPIX", &CCD.CCD_YPix,"Full Pixel Size of Y",&status); fits_write_key(fptr,TUINT,"PAMPGAIN", &CCD.PGain,"Value Range: 0-2",&status); fits_write_key(fptr,TFLOAT,"GRATWVLN", &CCD.gWv,"Grating wavelength for CAM 1", &status); fits_write_key(fptr,TINT,"GRATSTEP", &CCD.gStep,"Grating step count", &status); fits_write_key(fptr,TFLOAT,"GRATANGL", &CCD.gAngle,"Grating angle", &status); if(CCD.ScanNum==1) fits_write_pix(fptr, TSHORT, fpixel_one, nelements, CCD.RawData, &status); else if(CCD.ScanNum>1) fits_write_pix(fptr, TSHORT, fpixel, nelements, CCD.RawData, &status); fits_delete_key(fptr,"COMMENT",&status); fits_delete_key(fptr,"COMMENT",&status); fits_delete_key(fptr,"EXTEND",&status); fits_write_key(fptr, TSTRING, "OBSERVER", CCD.Observer, "The Name of Main Observer",&status); fits_write_key(fptr, TSTRING, "TARGET", CCD.Target, "Observation Target", &status); // fits_write_key(fptr, TFLOAT, "CAM1WVLN", fits_contents, "Wavelength center from grating position",&waveselect); /* switch(value) { case -1: //none fits_write_key(fptr, TSTRING, "TARGET", "NONE", "NONE", &status); break; case 0: //near disk center fits_write_key(fptr, TSTRING, "TARGET", "Near Disk Center", "Observation Target", &status); break; case 1: //close to or on the limb fits_write_key(fptr, TSTRING, "TARGET", "Close to or on the Limb", "Observation Target", &status); break; case 2: //quiet region fits_write_key(fptr, TSTRING, "TARGET", "Quiet Region", "Observation Target", &status); break; case 3: //active region fits_write_key(fptr, TSTRING, "TARGET", "Active Region", "Observation Target", &status); GetCtrlVal(TabPanelHandle, setMISC_MISC_ARNumber, fits_contents); fits_write_key(fptr, TSTRING, "ARNUMBER",fits_contents, "Active Region Number",&status); break; case 4: //corona hole fits_write_key(fptr, TSTRING, "TARGET", "Corona Hole", "Observation Target", &status); break; case 5: //sunspot fits_write_key(fptr, TSTRING, "TARGET", "Sunspot", "Observation Target", &status); break; case 6: //filament fits_write_key(fptr, TSTRING, "TARGET", "Filament", "Observation Target", &status); break; case 7: //prominence fits_write_key(fptr, TSTRING, "TARGET", "Prominence", "Observation Target", &status); break; case 8: //user defined object GetCtrlVal(TabPanelHandle, setMISC_MISC_Target, fits_contents); fits_write_key(fptr, TSTRING, "TARGET", fits_contents, "Observation Target", &status); break; } */ fits_write_key(fptr, TINT, "TEL_XPOS", &CCD.TelXpos, "X position of Telescope on the Sun", &status); fits_write_key(fptr, TINT, "TEL_YPOS" ,&CCD.TelYpos, "Y position of Telescope on the Sun", &status); fits_close_file(fptr,&status); return filename; } CCD_API int SaveFlatFits(CCDInfo CCD, int number) { //------------------------- char temp[250]; //------------------------- char pFileName[128]; char temp1[50]; char* ftemp; char filename[512]; //using nasa fits library fitsfile *fptr; int status=0; /////////////////////////////// long nelements, naxis[3],fpixel[3]; long naxis_one[2],fpixel_one[2],nelements_one; //for saving 2d images int PixelByte=32; //int memset(pFileName,NULL,128*sizeof(char)); strcat(pFileName, CCD.FilePath); strcat(pFileName, "\\"); naxis[0] = CCD.nx; naxis[1] = CCD.ny; naxis[2] = number; fpixel[0] = fpixel[1]=fpixel[2]=1; nelements = naxis[0]*naxis[1]*naxis[2]; naxis_one[0] = CCD.nx; naxis_one[1] = CCD.ny; fpixel_one[0] = fpixel_one[1]=1; nelements_one = naxis_one[0]*naxis_one[1]; //------------------------- //determine during process marktime(temp1, &gliStart); ftemp = isot2fname(CCD.stTime); //------------------------- sprintf(filename, "%sFISS_%s_%.1s_Flat.fts", pFileName, ftemp, CCD.camID); //SDO like fits_create_file(&fptr, filename, &status); if(number==1) fits_create_img(fptr,FLOAT_IMG, 2,naxis_one, &status); else fits_create_img(fptr, FLOAT_IMG, 3,naxis, &status); fits_write_key(fptr,TSTRING, "DATE", temp1, "file creation date (YYYY-MM-DDThh:mm:ss.ddd UT)", &status); //fits_write_date(fptr,&status); fits_write_key(fptr,TFLOAT,"EXPTIME",&CCD.exptime,"Second",&status); fits_write_key(fptr,TUINT,"HBINNING",&CCD.HBin,"",&status); fits_write_key(fptr,TUINT,"VBINNING",&CCD.VBin,"",&status); fits_write_key(fptr,TUINT,"EMGAIN", &CCD.Gain,"Value Range: 0-255",&status); fits_write_key(fptr,TSTRING,"STRTIME",CCD.stTime,"Scan Start Time",&status); fits_write_key(fptr,TSTRING,"ENDTIME",CCD.edTime,"Scan Finish Time", &status); fits_write_key(fptr,TFLOAT,"ELAPTIME",&CCD.elapseTime,"Elapse Time During Scanning(Second)",&status); //fits_write_key(fptr,TINT,"BITPIX",&PixelByte,"number of bits per data pixel",&status); SetCurrentCamera(CCD.camera); GetTemperature(&CCD.Temperature); fits_write_key(fptr,TINT,"CCDTEMP",&CCD.Temperature,"Cooling Temperature of CCD",&status); fits_write_key(fptr,TSTRING,"CCDNAME",CCD.ccdName,"Productname of CCD",&status); fits_write_key(fptr,TUINT,"CCD_XPIX",&CCD.CCD_XPix,"Full Pixel Size of X",&status); fits_write_key(fptr,TUINT,"CCD_YPIX",&CCD.CCD_YPix,"Full Pixel Size of Y",&status); fits_write_key(fptr,TUINT,"PAMPGAIN", &CCD.PGain,"Value Range: 0-2",&status); fits_write_key(fptr,TFLOAT,"GRATWVLN", &CCD.gWv,"Grating wavelength for CAM 1", &status); fits_write_key(fptr,TINT,"GRATSTEP", &CCD.gStep,"Grating step count", &status); fits_write_key(fptr,TFLOAT,"GRATANGL", &CCD.gAngle,"Grating angle", &status); if(number==1) fits_write_pix(fptr,TFLOAT, fpixel_one,nelements_one,CCD.FlatCube,&status); else fits_write_pix(fptr,TFLOAT,fpixel, nelements, CCD.FlatCube,&status); fits_delete_key(fptr,"COMMENT",&status); fits_delete_key(fptr,"COMMENT",&status); fits_delete_key(fptr,"EXTEND",&status); fits_write_comment(fptr,"BiasDark Subtracted",&status); sprintf(temp,"averaged image : %d at each grating angle",CCD.ScanNum-1); fits_write_comment(fptr, temp,&status); //fits_write_key(fptr,TUINT,"INTG_FRM",&number,"Number of Integrated Images",&status); fits_close_file(fptr, &status); return 1; } CCD_API char* marktime(char* timestring, LARGE_INTEGER* gTime) { SYSTEMTIME systime; char fname[50]; GetSystemTime(&systime); sprintf(timestring,"%04d-%02d-%02dT%02d:%02d:%02d.%03d", systime.wYear, systime.wMonth, systime.wDay, systime.wHour, systime.wMinute, systime.wSecond, systime.wMilliseconds); sprintf(fname, "%04d%02d%02d_%02d%02d%02d.%03d", systime.wYear, systime.wMonth, systime.wDay, systime.wHour, systime.wMinute, systime.wSecond, systime.wMilliseconds); QueryPerformanceCounter(gTime); return fname; } CCD_API float time_difference(LARGE_INTEGER gStart, LARGE_INTEGER gEnd) { float timediff; if(!gliFreq.QuadPart) QueryPerformanceFrequency(&gliFreq); timediff=(float)(((double)gEnd.QuadPart-(double)gStart.QuadPart)/(double)(gliFreq.QuadPart)); return timediff; } CCD_API int TempSet(CCDInfo CCD, int OnOff, int Temp) { unsigned int errorValue; Sleep(100); SetCurrentCamera(CCD.camera); errorValue = SetFanMode(CCD.FanSpeed); if(errorValue!=DRV_SUCCESS) return ERR_setFan; SetTemperature(Temp); if(OnOff) errorValue=CoolerON(); else errorValue=CoolerOFF(); if(errorValue!=DRV_SUCCESS) return 0; return 1; } char* isot2fname(char* isot) { char tmp[20]; char* fname = malloc(sizeof(char)*20); tmp[0] = isot[0]; tmp[1] = isot[1]; tmp[2] = isot[2]; tmp[3] = isot[3]; tmp[4] = isot[5]; tmp[5] = isot[6]; tmp[6] = isot[8]; tmp[7] = isot[9]; tmp[8] = '_'; tmp[9] = isot[11]; tmp[10] = isot[12]; tmp[11] = isot[14]; tmp[12] = isot[15]; tmp[13] = isot[17]; tmp[14] = isot[18]; tmp[15] = isot[19]; tmp[16] = isot[20]; tmp[17] = isot[21]; tmp[18] = isot[22]; tmp[19] = '\0'; strcpy(fname, tmp); return fname; } #ifdef __cplusplus } #endif CCD_API void StructTestCCD(CCDInfo* CCD) { CCD->nx = 123; CCD->ny = 456; CCD->CCD_YPix = 45; CCD->CCD_XPix = 12; CCD->TelYpos = 987; CCD->Temperature = -29; CCD->TelXpos = -333; CCD->camera = 6748; CCD->status = -1; CCD->FanSpeed = 90; CCD->Gain = 255; CCD->exptime = 0.03; sprintf(CCD->FilePath, "C:\\test"); sprintf(CCD->camID, "A"); CCD->gWv = 6562.817; CCD->ReadMode = 4; CCD->PGain = 1; CCD->stepTime = 12.98; sprintf(CCD->stTime, marktime(CCD->edTime, &gliStart)); sprintf(CCD->Target, "AR"); CCD->HBin = 2; CCD->ScanNum = 100; CCD->VBin = 3; CCD->ShutterMode = 5; CCD->wvIndex = 99; CCD->Trigger = 11; CCD->gAngle = 30.2; sprintf(CCD->Observer, "J. Kang"); CCD->RawData = (unsigned short*)malloc(600 * sizeof(unsigned short)); memset(CCD->RawData, 0, 600 * sizeof(unsigned short)); sprintf(CCD->ccdName, "DV887"); CCD->elapseTime = 17.58; CCD->scanSpeed = 23.18; CCD->gStep = 19; sprintf(CCD->CCDPath, "C:\\test_c"); CCD->BiasDark = (unsigned short*)malloc(800 * sizeof(unsigned short)); CCD->AcqMode = 52; CCD->FlatCube = (float*)malloc(400 * sizeof(float)); CCD->stepSize = 15.7; CCD->scanDist = 42.195; }