// //---------------------------- ASCap ImageJ Capture Macro Tool ------------------------------- var ASCapV=170425; // ImageJ Macro for capturing FITS images from CCD cameras using an ASCOM driver on Windows computers. // A windows application can be executed after each image eg "Orient.vbs" to reset sample orientation // Please use the latest version on http://neutronoptics.com/ASCap.txt email:alan.hewat@neutronoptics.com // The ImageJ Macro Language is described on http://rsbweb.nih.gov/ij/developer/macro/macros.html // This macro was developed from http://rsb.info.nih.gov/ij/macros/tools/VideoCaptureTool.txt // And the VBScript example on http://www.easysky.de/ASCOM/Image/create.vbs // Copyright ©2012-17 Alan Hewat. May be copied for non-commercial use provided this notice is displayed. // // (1) Install the ASCOM Platform 6 environment from http://www.ascom-standards.org/ // (2) Download the FITS.DLL from http://www.easysky.de/ASCOM/Image/FITS.htm and register it // (3) Download http://neutronoptics.com/ASCap.vbs to a VBScript directory above the ImageJ directory // (4) Download http://neutronoptics.com/ASCap.txt and copy it to the \ImageJ\macros\toolsets directory // (5) Click the >> icon in the ImageJ toolbar and select the ASCap tool // (6) Right-click the Camera Capture tool icon that appears, select the camera & capture options. // (7) Left-click the camera icon to capture a FITS image and display it with ImageJ var IJDir=""; var SysDir=substring(getDirectory('startup'),0,2); //SysDir will normally be C: File.makeDirectory(SysDir+"\\temp"); //Make sure temp dir exists var nImage=1; var ifBreak="false"; var nBin=call("ij.Prefs.get", "captureTool.nBin",1); //Bin number var nCapture=call("ij.Prefs.get", "captureTool.nCapture",1); //Capture number var captureGray = parseInt(call("ij.Prefs.get","captureTool.toGrayScale",false)); //Convert to 32-bit greyScale var ifDespec = call("ij.Prefs.get","captureTool.ifDespec",true); //If ImageJ despeckle var ifDeinterlace = call("ij.Prefs.get","captureTool.ifDeinterlace",false); //If ImageJ deinterlce var ifSwap = call("ij.Prefs.get","captureTool.ifSwap",false); //If ImageJ swap var Rotate90 = call("ij.Prefs.get","captureTool.Rotate90",false); //Rotate 90 degrees var flipVertical = call("ij.Prefs.get","captureTool.flipVertical",false); //Flip vertical var flipHorizontal = call("ij.Prefs.get","captureTool.flipHorizontal",false); //Flip horizontal var sTemperature = call("ij.Prefs.get", "captureTool.sTemperature","20.00"); //Capture time (seconds) var captureTime = call("ij.Prefs.get", "captureTool.captureTime","1.00"); //Capture time (seconds) var captureDir = call("ij.Prefs.get", "captureTool.captureDir",SysDir+"\\temp\\"); //Default Working Directory var fileN = call("ij.Prefs.get", "captureTool.fileN","snap"); //File name var fileB = call("ij.Prefs.get", "captureTool.fileB",""); //Background file name var fileM = call("ij.Prefs.get", "captureTool.fileM",""); //Orientation file name var ifBack = call("ij.Prefs.get", "captureTool.ifBack",false); //If ImageJ autocorrect B/G var ifLoop = call("ij.Prefs.get", "captureTool.ifLoop",false); //If Continuous Exposure Loop //var setSaturate = call("ij.Prefs.get", "captureTool.setSaturate",false); //Set percent of saturated pixels var kT = 0; var DriverID = newArray("","","") //The ASCOM IDs of the CCDs var Time = newArray(3600); var Temperature = newArray(3600); var CoolerPower = newArray(3600); var xloc=200; var yloc=200; var nDevices = call("ij.Prefs.get", "captureTool.nDevices","1"); //Number of Devices var K1 = call("ij.Prefs.get", "captureTool.K1","0.0"); //K1 for lens correction var K2 = call("ij.Prefs.get", "captureTool.K2","0.0"); //K2 for lens correction var aRotate = call("ij.Prefs.get", "captureTool.aRotate","0.0"); //Rotation angle CCD#1 var bRotate = call("ij.Prefs.get", "captureTool.bRotate","0.0"); //Rotation angle CCD#2 var xOff = call("ij.Prefs.get", "captureTool.xO1","0"); //Relative x-offset CCD#2 var yOff = call("ij.Prefs.get", "captureTool.yO1","0"); //Relative y-offset CCD#2 var xS=newArray(2); var yS=newArray(2); //X,Y scale factors for the CCDs var type="fits"; var Correction=""; //Correction is plugin function ifError() { iout = indexOf(status,"ERROR"); if(iout >=0) { showMessage("ERROR: No CCD found connected!\nTry connecting to a different USB port."); exit; } } function getCScriptPath() //use "%windir%\SysWOW64\cscript.exe" instead of "cscript" on 64 bit systems { if (File.exists(SysDir+"\\Windows\\SysWOW64\\cscript.exe")) return SysDir+"\\Windows\\SysWOW64\\cscript.exe"; else return "cscript"; } macro 'NeutronOptics ASCOM Capture (right click to set options, left click to capture) Action Tool - C000F14faF24faP4461b1d40Cfffo5577' { setBatchMode(true); run("Brightness/Contrast..."); while(File.exists(captureDir+fileN+nImage+"-"+1+"."+type)) {nImage=nImage+1;} showStatus("Capture in progress... Please Wait ! Esc to exit."); status=exec("taskkill /FI \"Imagename eq ASCOM*\""); // wait(100); //Close any active ASCOM processes status=exec("taskkill /FI \"Imagename eq cscript*\""); wait(100); //Close any active VBScript processes status=exec("taskkill /FI \"Imagename eq cscript*\""); wait(100); //Close any active VBScript processes if(indexOf(status,"kill")>=0) showMessage("Unable to kill Windows cscript\nIf the problem persists, logout and login again"); if(DriverID[0]=="") { showMessage("No CCD selected or found\nPlease right-click camera icon"); exit; } //--------------------------------------------------------------------------------------------------------- //For two CCDs, acquire images in the background and correct together if(nDevices==2) { if (!isKeyDown("alt")) { //Else use pre-recorded images to re-make the montage image1=" "+IJDir+"VBScripts\\ASCap.vbs "+DriverID[0]+" "+captureDir+fileN+"1."+type+" "+captureTime+" "+nBin+" "+sTemperature; image2=" "+IJDir+"VBScripts\\ASCap.vbs "+DriverID[1]+" "+captureDir+fileN+"2."+type+" "+captureTime+" "+nBin+" "+sTemperature; ifOK1=File.delete(captureDir+fileN+"1."+type); ifOK2=File.delete(captureDir+fileN+"2."+type); result=call("fork.Exec",getCScriptPath()+image1); wait(1000); result=call("fork.Exec",getCScriptPath()+image2); for (i=1; icaptureTime+29) { if (File.exists(captureDir+DriverID[0]+".txt")) showMessage(File.openAsString(captureDir+DriverID[0]+".txt")); if (File.exists(captureDir+DriverID[1]+".txt")) showMessage(File.openAsString(captureDir+DriverID[1]+".txt")); exit; } if (File.exists(captureDir+fileN+"1."+type)) if(File.exists(captureDir+fileN+"2."+type)) i=captureTime+31; } } if(K1>0) { //Apply Spline Deformation Generatorafter obligatory despeckle to remove high intensity noise List.setCommands; //Check if Correction installed if (List.get("SplineDeformationGenerator ")!="") Correction="SplineDeformationGenerator "; //Original Correctrion if (List.get("Spline Deformation Generator")!="") Correction="Spline Deformation Generator"; //Latest Correction if(Correction=="") {showMessage("Please copy \"http://imagej.net/Spline_Deformation_Generator\" jar file to Plugins"); exit;} for (i=1; i<=2; i++) { open(captureDir+fileN+i+"."+type); run("Despeckle"); if(ifDeinterlace) run("Deinterlace ", "method=[Evan field only]"); saveAs(type,captureDir+fileN+i+"."+type); close(); } run(Correction,"-barrel "+captureDir+fileN+"1."+type+" "+K1+" "+K2+" "+captureDir+fileN+"1."+type); if (!File.exists(captureDir+fileN+"1.tif")) {showMessage("Please copy \"http://imagej.net/Spline_Deformation_Generator\" jar file to Plugins"); exit;} open(captureDir+fileN+"1.tif"); //Open TIF file produced by new SplineDeformationGenerator run("16-bit"); //Convert 32-bit TIF file to 16-bits saveAs(type,captureDir+fileN+"1."+type); //Save as FITS file run(Correction,"-barrel "+captureDir+fileN+"2."+type+" "+K1+" "+K2+" "+captureDir+fileN+"2."+type); open(captureDir+fileN+"2.tif"); //Open TIF file produced by new SplineDeformationGenerator run("16-bit"); //Convert 32-bit TIF file to 16-bits saveAs(type,captureDir+fileN+"2."+type); //Save as FITS file } makeMontage(); exit; } //--------------------------------------------------------------------------------------------------------- //If continuous acquisition loop, acquire one image, then paste over it 1000 times or until "Esc" key pressed nCaptured=nCapture; if(ifLoop) nCaptured=1000; //In any case, capture and write nCaptured separate images, summing them at the end if not aborted earlier for (n=1; n0) { if(kT<3600) kT=kT+1; Temperature[kT]=parseFloat(substring(result, iout+16, iout+20)); if (isNaN(Temperature[kT])) Temperature[kT]=parseFloat(substring(result, iout+16, iout+18)); Time[kT]=getTime()/1000.0-Time[0]; Plot.create("CCD Temperature (blue) and Cooling Power (green)", "Time (s)", "Temperature (C) & Power (0-100%)"); Plot.setFrameSize(380,250); Tscale=100*(captureTime+1.0); Toff=5; if (Time[kT]>Tscale-10) Toff=Tscale-5-Time[kT]; Plot.setLimits(Time[1]-Toff,Tscale-Toff,0,25); Plot.setLineWidth(2); Plot.setColor("blue"); if (Temperature[kT]>25) {Temperature[kT]=25; Plot.setColor("red");} Plot.add("circles", Time, Temperature); Plot.drawLine(Time[1]-Toff, sTemperature, Tscale-Toff, sTemperature); if(jout>0) { CoolerPower[kT]=0.25*parseFloat(substring(result+" ", jout+13, jout+16)); Plot.setColor("green"); Plot.add("circles", Time, CoolerPower); } // showStatus("Elapsed Time:"+Time[kT]+" Cooler Power:"+4*CoolerPower[kT]+" CCD Temperature:"+Temperature[kT]); } //....................................................................................... if (isOpen(fileN+nImage+"-"+n-1+"."+type)) { selectWindow(fileN+nImage+"-"+n-1+"."+type); getLocationAndSize(xloc, yloc, width, height); close(fileN+nImage+"-"+n-1+"."+type); } if (File.exists(captureDir+fileN+nImage+"-"+n+"."+type)) open(captureDir+fileN+nImage+"-"+n+"."+type); else { showMessage("Acquisition FAILED for file "+captureDir+fileN+nImage+"-"+n+"."+type+"\nClose other applications. If the problem persists\n Try changing the USB socket or logging out and in again"); exit; } selectWindow(fileN+nImage+"-"+n+"."+type); setLocation(xloc,yloc); // if(ifDespec) run("Remove Outliers...", "radius=2 threshold=50 which=Bright"); if(ifDespec) run("Despeckle"); if(ifDeinterlace) run("Deinterlace ", "method=[Evan field only]"); //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^Correct for lens distortion if required.^^^^^^^^^^^^^^^^ if(K1>0) { List.setCommands; //Check if Correction installed if (List.get("SplineDeformationGenerator ")!="") Correction="SplineDeformationGenerator "; //Original Correctrion if (List.get("Spline Deformation Generator")!="") Correction="Spline Deformation Generator"; //Latest Correction if(Correction=="") {showMessage("Please copy \"http://imagej.net/Spline_Deformation_Generator\" jar file to Plugins"); exit;} saveAs(type,captureDir+fileN+nImage+"-"+n+"."+type); //Save this deformed image close(); //Close this deformed image run(Correction,"-barrel "+captureDir+fileN+nImage+"-"+n+"."+type+" "+K1+" "+K2+" "+captureDir+fileN+nImage+"-"+n+"."+type); if (!File.exists(captureDir+fileN+nImage+"-"+n+".tif")) {showMessage("Please copy \"http://imagej.net/Spline_Deformation_Generator\" jar file to Plugins"); exit;} open(captureDir+fileN+nImage+"-"+n+".tif"); //Open TIF file produced by new SplineDeformationGenerator run("16-bit"); //Convert 32-bit TIF file to 16-bits saveAs("TIF",captureDir+fileN+nImage+"-"+n+".tif"); //Save as 16-bit TIF file saveAs(type,captureDir+fileN+nImage+"-"+n+"."+type); //Save as FITS file } //....................................................................................... run("Enhance Contrast", "saturated=0.35"); if(Rotate90) run("Rotate 90 Degrees Left"); if(flipVertical) run("Flip Vertically"); if(flipHorizontal) run("Flip Horizontally"); if(ifBack) run("Subtract Background...", "rolling=50"); if(fileB!="") { if (! File.exists(captureDir+fileB+"."+type)) { showMessage(captureDir+fileB+"."+type+" background file was not found!"); exit;} else { showMessageWithCancel("Subtract background image "+captureDir+fileB+"."+type+" ?"); open(captureDir+fileB+"."+type); // wait(100); run("Select All"); run("Copy"); close(); if (isOpen(fileN+nImage+"-"+n+"."+type)) selectWindow(fileN+nImage+"-"+n+"."+type); setPasteMode("Subtract"); run("Paste"); } } setBatchMode(false); selectWindow(fileN+nImage+"-"+n+"."+type); saveAs("FITS",captureDir+fileN+nImage+"-"+n+"."+type); if(Temperature[kT]>-300.0) { Plot.update(); selectWindow("CCD Temperature (blue) and Cooling Power (green)"); if(n==1) setLocation(10,10); } if (isOpen(fileN+nImage+"-"+n+"."+type)) selectWindow(fileN+nImage+"-"+n+"."+type); if (isOpen("B&C")) selectWindow("B&C"); //The following delays appear necessary in Windows-10 to close the MS VBScript wait(700); status=exec("taskkill /FI \"Imagename eq ASCOM*\""); //Close any active ASCOM tasks status=exec("taskkill /FI \"Imagename eq cscript*\""); //Close any active VBScript tasks while(indexOf(status,"kill")>=0) status=exec("taskkill /FI \"Imagename eq cscript*\""); if(File.exists(fileM)) { showStatus("Executing "+fileM+". Hold down Alt to sum, Esc to exit."); status=exec(getCScriptPath()+" "+fileM); } wait(2000); } if (nCaptured>1) { for (n=1; n1) if (isKeyDown("alt")) SecondCCD(); // set CCD relative params Dialog.create("Capture Options"); Dialog.addMessage("V."+ASCapV+"-http://neutronoptics.com/ASCap.html"); Dialog.addMessage("Please specify the following capture options:"); Dialog.addString("Directory for images ", captureDir,15); Dialog.addString("Image file root name ", fileN,15); Dialog.addNumber("Set CCD temperature ",sTemperature,1,4,"(or blank)"); Dialog.addNumber("Bin adjacent pixels 1-8 ",nBin,0,4,"(eg 1)"); Dialog.addNumber("Exposure time (secs) ",captureTime,3,4,"(eg 1.0)"); if(nDevices==1) { Dialog.addNumber("Number of Exposures ",nCapture,0,4,"(eg 1)"); Dialog.addCheckbox("Continous exposure loop (ESC to stop)", ifLoop); Dialog.addCheckbox("Rotate Left", Rotate90); Dialog.addCheckbox("Flip Vertical", flipVertical); Dialog.addCheckbox("Flip Horizontal", flipHorizontal); } Dialog.addCheckbox("Despeckle to remove isolated white pixels", ifDespec); Dialog.addCheckbox("Deinterlace if you have an interlaced CCD", ifDeinterlace); Dialog.addCheckbox("Calculate Background or input File name", ifBack); Dialog.addString("Background File name ", fileB,15); Dialog.addString("Turntable File name ", fileM,15); Dialog.addMessage("Set K1=0 to skip Barrel/Pincushion corrections"); Dialog.addNumber("Barrel/Pincushion Corr K1", K1,3,6,"(0.13)"); Dialog.addNumber("Barrel/Pincushion Corr K2", K2,3,6,"(0.00)"); Dialog.addMessage("To change CCD selection, reload the macro"); Dialog.addMessage("Click OK, left-click the camera icon to expose"); Dialog.addHelp("http://www.neutronoptics.com/ascom.html"); Dialog.show(); captureDir = Dialog.getString(); if (!endsWith(captureDir,"\\")) captureDir=captureDir+"\\"; if (!File.exists(captureDir)) File.makeDirectory(captureDir); if (!File.exists(captureDir)) showMessage("Unable to create directory:"+captureDir); fileN = Dialog.getString(); if (fileN=="") fileN="snap"; sTemperature = Dialog.getNumber(); if(sTemperature>25.0) sTemperature=25.0; // if(sTemperature<0.0) sTemperature=0.0; if(isNaN(sTemperature)) sTemperature=""; if(nDevices>1) if(DriverID[1]==DriverID[0]) sTemperature=""; //Otherwise problem writing T-file nBin = Dialog.getNumber(); if (nBin<1) nBin=1; if (nBin>8) nBin=8; captureTime = Dialog.getNumber(); if (captureTime<0.001) captureTime=0.001; if(nDevices==1) { nCapture = Dialog.getNumber(); if(isNaN(nCapture)) nCapture=1; ifLoop= Dialog.getCheckbox(); if(ifLoop) nCapture=1; Rotate90= Dialog.getCheckbox(); flipVertical= Dialog.getCheckbox(); flipHorizontal= Dialog.getCheckbox(); call("ij.Prefs.set", "captureTool.nCapture",nCapture); call("ij.Prefs.set", "captureTool.ifLoop",ifLoop); call("ij.Prefs.set", "captureTool.Rotate90",Rotate90); call("ij.Prefs.set", "captureTool.flipVertical",flipVertical); call("ij.Prefs.set", "captureTool.flipHorizontal",flipHorizontal); } ifDespec = Dialog.getCheckbox(); ifDeinterlace = Dialog.getCheckbox(); ifBack = Dialog.getCheckbox(); fileB = Dialog.getString(); if(fileB!="") {ifBack=0; if(!File.exists(fileB)) showMessage("File:"+fileB+" does not exist");} fileM = Dialog.getString(); if(fileM!="") {if(!File.exists(fileM)) showMessage("File:"+fileM+" does not exist");} K1= Dialog.getNumber(); K2= Dialog.getNumber(); call("ij.Prefs.set", "captureTool.captureDir",captureDir); call("ij.Prefs.set", "captureTool.fileN",fileN); call("ij.Prefs.set", "captureTool.sTemperature",sTemperature); call("ij.Prefs.set", "captureTool.nBin",nBin); call("ij.Prefs.set", "captureTool.captureTime",captureTime); call("ij.Prefs.set", "captureTool.ifSwap",ifSwap); call("ij.Prefs.set", "captureTool.ifDespec",ifDespec); call("ij.Prefs.set", "captureTool.ifDeinterlace",ifDeinterlace); call("ij.Prefs.set", "captureTool.ifBack",ifBack); call("ij.Prefs.set", "captureTool.fileB",fileB); call("ij.Prefs.set", "captureTool.fileM",fileM); call("ij.Prefs.set", "captureTool.K1",K1); call("ij.Prefs.set", "captureTool.K2",K2); call("ij.Prefs.set", "captureTool.nDevices",nDevices); kT=0; Time[0]=getTime()/1000.0; for (i=0; i<3600; i++) { Temperature[i]=-300.0; CoolerPower[i]=-100.0; } status=exec("taskkill /FI \"Imagename eq ASCOM*\""); wait(100); //Close any active ASCOM tasks status=exec("taskkill /FI \"Imagename eq cscript*\""); wait(100); //Close any active VBScript tasks }