nanophotonics / nplab

Core functions and instrument scripts for the Nanophotonics lab experimental scripts
GNU General Public License v3.0
38 stars 15 forks source link

Andor multiple cameras #83

Closed YagoDel closed 4 years ago

YagoDel commented 4 years ago

DLLs cannot be opened multiple times. So you cannot open multiple instances of the Andor class to control different cameras connected to the same computer.

Possible solutions:

wdeacon commented 4 years ago

Hey man, Thoughts on having a _current_dll object in the Andor file, same as in the data_file class, which allows andor classes to check if a dll is open and grab it indepently.

YagoDel commented 4 years ago

Hmmm, probably. This would essentially have a global-ish object that gets initialised if it doesn't exist and gets grabbed if it does, right? I think it will be the "correct" way of doing it, but I think it still has the con that I said above.

To be more explicit, in the Andor SDK you need to call SetCurrentCamera to make sure your function calls go to the correct camera. So if you're calling StartAcquisition, you need to first tell it what camera you want to acquire from. Once you set it, you can make multiple function calls and they all go to the same place.

So now imagine you open two cameras. They both point to the same open DLL library. Now you want to acquire from camera 1, so you would want to do something like camera1.raw_image() But since the two cameras have been opened independently, you don't know if the DLL is currently pointing to camera1 or camera2. To ensure you are acquiring from camera1 you need to set CurrentCamera=1 beforehand, and I think that would require setting CurrentCamera before every function call?

Not sure if the overhead will matter

wdeacon commented 4 years ago

Essentaily that's all correct, it would be a module level object contained in nplab...Andor. My guess would be the overhead shouldn't matter too much as it is how the DLL is meant to operate, however, this could be laying too much faith in Oxford Instruments. It would be nice to embed the switch into the AndorParameter class which would then propagate to all properties, but not to all functions. It will also work for any function that calls a property at start of its operation but obviously not for any others which would require a SetCurrent call. Any way we could inherit it into all functions?

There's a little bit of info on that here but I don't know if its worth it.

Assuming creating decorator/inheritence are a pain, I would try to implement it to AndorParameter and then the required functions, but the hack will clearly work for now, it should probably just not become the done thing for this type of problem. Maybe its something we should handle at Instrument level? create a DLLInstrument class which helps wrap up these kind of problems?

YagoDel commented 4 years ago

Yeah, I think I don't fully understand either how DLLs work, or how this one works in particular. I'd be interested to see if anyone in the group has multiple instruments going to the same DLL

For the Andor, I think you'd have to propagate it to all functions (think StartAcquisition). But it's possible to have a SetCurrent call before all functions since everything goes via the method _dll_wrapper. And yeah, some sort of switch might be able to reduce the overhead, but not sure yet. Either way, the python3 branch now has a hack that creates a temporary DLL file. I hate the hack, but it works.

And finally, I'm how to do it in a more general situation, since I haven't encountered this problem before so I don't know what's general to all DLLs and what's specific to this DLL. One possibility is actually using "nice" temporary files that get cleaned up with garbage collection (see tempfile.TemporaryFile) when opening DLLs? But I still feel it's a hack

YagoDel commented 4 years ago

Done. Fixed at eeef461bcd6710be7243991ef0be2cbdaa2c2119 in the Python3 branch Haven't bothered trying to measure any overhead though