adamcohenlab / luminos-microscopy

Bi-directional microscopy software
https://luminosmicroscopy.com
3 stars 0 forks source link

Can't acquisition #4

Open Luorong37 opened 2 months ago

Luorong37 commented 2 months ago

Hi,

I encountered an issue with the GUI in the browser when I attempt to initiate the app by tapping app = Control_App(). After setting the waveform, I tapped Start Acquisition, which resulted in an error being thrown in both the browser window and the Matlab command window. The details of the error are attached below. Could it be related to the clock settings?

If I need to use the internal clock in the DAQ for this process which has two cameras, could you advise on how to configure it correctly?

Additionally, I have a query regarding the acquisition settings in the GUI. From my understanding, the Exposure (s) is the exposure time, and the Frames indicate the total number of frames for the movie I want to record. However, I am unsure about the role of Frame Periods (ms) when the Frame Trigger is set to DAQ. I noticed that the Frame Periods (ms) cannot exceed the Exposure (s), which implies it is not the duration of each frame. Could you clarify what does the Frame Periods (ms) means and how the FPS is determined? Is it simply the reciprocal of Exposure (s)?

Thanks for your ansower!

In browser :

Acquisition failed. The condition input argument must be convertible to a scalar logical.

In Matlab :

Warning: No device of type DMD found. In Rig_Control_App/getDevice (line 82) In Waveform_Camera_Sync_Acquisition (line 11) In cam_acquisition_js (line 10) In JS_Server/runAndWriteBack (line 171) In JS_Server/msgRcvCallback (line 69) In JS_Server>@(src,evt)msgRcvCallback(obj,src,evt) (line 22) In matlabshared.transportlib.internal.client/GenericClient/callbackFunction (line 887) In matlabshared.transportlib.internal.client.GenericClient>@(varargin)obj.callbackFunction(varargin{:}) (line 583) In matlabshared.transportclients.internal.StringClient/StringClient/DataAvailableCallback In matlabshared.transportclients.internal.StringClient.StringClient>@(varargin)obj.DataAvailableCallback(varargin{:}) In matlabshared.transportlib.internal.client/EventHandler/onDataReceived (line 113) In tcpserver.internal/EventHandler/onDataReceived (line 54) In matlabshared.transportlib.internal.client.ChannelClient>@(src,evt)obj.EventHandler.onDataReceived(src,evt) (line 241) In matlabshared.asyncio.internal/Channel/onDataReceived (line 548) In matlabshared.asyncio.internal.Channel>@(source,data)obj.onDataReceived() (line 458) Warning: No device of type Scanning_Device found. In Rig_Control_App/getDevice (line 82) In Waveform_Camera_Sync_Acquisition (line 12) In cam_acquisition_js (line 10) In JS_Server/runAndWriteBack (line 171) In JS_Server/msgRcvCallback (line 69) In JS_Server>@(src,evt)msgRcvCallback(obj,src,evt) (line 22) In matlabshared.transportlib.internal.client/GenericClient/callbackFunction (line 887) In matlabshared.transportlib.internal.client.GenericClient>@(varargin)obj.callbackFunction(varargin{:}) (line 583) In matlabshared.transportclients.internal.StringClient/StringClient/DataAvailableCallback In matlabshared.transportclients.internal.StringClient.StringClient>@(varargin)obj.DataAvailableCallback(varargin{:}) In matlabshared.transportlib.internal.client/EventHandler/onDataReceived (line 113) In tcpserver.internal/EventHandler/onDataReceived (line 54) In matlabshared.transportlib.internal.client.ChannelClient>@(src,evt)obj.EventHandler.onDataReceived(src,evt) (line 241) In matlabshared.asyncio.internal/Channel/onDataReceived (line 548) In matlabshared.asyncio.internal.Channel>@(source,data)obj.onDataReceived() (line 458) Warning: No device of type Laser_Device found. In Rig_Control_App/getDevice (line 82) In Waveform_Camera_Sync_Acquisition (line 16) In cam_acquisition_js (line 10) In JS_Server/runAndWriteBack (line 171) In JS_Server/msgRcvCallback (line 69) In JS_Server>@(src,evt)msgRcvCallback(obj,src,evt) (line 22) In matlabshared.transportlib.internal.client/GenericClient/callbackFunction (line 887) In matlabshared.transportlib.internal.client.GenericClient>@(varargin)obj.callbackFunction(varargin{:}) (line 583) In matlabshared.transportclients.internal.StringClient/StringClient/DataAvailableCallback In matlabshared.transportclients.internal.StringClient.StringClient>@(varargin)obj.DataAvailableCallback(varargin{:}) In matlabshared.transportlib.internal.client/EventHandler/onDataReceived (line 113) In tcpserver.internal/EventHandler/onDataReceived (line 54) In matlabshared.transportlib.internal.client.ChannelClient>@(src,evt)obj.EventHandler.onDataReceived(src,evt) (line 241) In matlabshared.asyncio.internal/Channel/onDataReceived (line 548) In matlabshared.asyncio.internal.Channel>@(source,data)obj.onDataReceived() (line 458) Error using assert The condition input argument must be convertible to a scalar logical.

Error in Waveform_Camera_Sync_Acquisition (line 18) assert(~contains(cam(2).clock, 'Ctr'), 'Master Camera Cannot Use A Counter as a Clock! Change to equivalent PFI.')

Error in cam_acquisition_js (line 10) Waveform_Camera_Sync_Acquisition(app, 1, 'tag', folder);

Error in JS_Server/runAndWriteBack (line 171) feval(methodName, msgObj, args{:});

Error in JS_Server/msgRcvCallback (line 69) obj.runAndWriteBack(msg.return_event, msg.method, obj.app, msg.args);

Error in JS_Server>@(src,evt)msgRcvCallback(obj,src,evt) (line 22) configureCallback(obj.server_socket, "terminator", @(src, evt)msgRcvCallback(obj, src, evt));

Error in matlabshared.transportlib.internal.client.GenericClient/callbackFunction (line 887) obj.BytesAvailableFcn(obj.CallbackSource, dataAvailableInfo);

Error in matlabshared.transportlib.internal.client.GenericClient>@(varargin)obj.callbackFunction(varargin{:}) (line 583) obj.ClientImpl.StringReadFcn = @obj.callbackFunction;

Error in matlabshared.transportclients.internal.StringClient.StringClient/DataAvailableCallback

Error in matlabshared.transportclients.internal.StringClient.StringClient>@(varargin)obj.DataAvailableCallback(varargin{:})

Error in matlabshared.transportlib.internal.client.EventHandler/onDataReceived (line 113) obj.BytesAvailableFcn(obj.Transport,...

Error in tcpserver.internal.EventHandler/onDataReceived (line 54) onDataReceived(obj.SharedEventHandler);

Error in matlabshared.transportlib.internal.client.ChannelClient>@(src,evt)obj.EventHandler.onDataReceived(src,evt) (line 241) @(src, evt)obj.EventHandler.onDataReceived(src, evt));

Error in matlabshared.asyncio.internal.Channel/onDataReceived (line 548) notify(obj.InputStream, 'DataWritten', ...

Error in matlabshared.asyncio.internal.Channel>@(source,data)obj.onDataReceived() (line 458) @(source, data) obj.onDataReceived()); Error msg: method: 'cam_acquisition_js' args: [1×1 struct] type: 'app_method' return_event: 'ev73633557579'

philbrooksIII commented 1 month ago

Hi,

  1. All the initial MATLAB warnings in your error log can be ignored. The first error explains what's going on:

    Error in Waveform_Camera_Sync_Acquisition (line 18)
    assert(~contains(cam(2).clock, 'Ctr'), 'Master Camera Cannot Use A Counter as a Clock! Change to equivalent PFI.')

    So I'd guess that you specified your camera clock as a counter, which isn't allowed. Instead, look at the pinout for your DAQ (open NIMAX, right click on device in left panel, select "Device Pinouts": see example attached) image Find the PFI channel that corresponds to the counter you have assigned and use the PFI channel instead of the CTR name. This way, you don't have to change any physical cabling.

  2. For two cameras run off the internal clock, you'll need to set the clock to "Internal" on the waveforms tab (i.e., the DAQ will run off its own internal clock). The trigger mode should probably be "Self-Trigger", with "Write on trigger" set to the DAQ output corresponding to the camera trigger connector(s). I assume both cameras should share the same trigger from a "Tee" connector, Let me know if this is not the case, as it will require more thought.

3a. Disclaimer: The current public release may be a bit buggy when using the DAQ frametrigger mode. It may work, but has been improved in our internal lab version, which we hope to release very soon (i.e. in the next month or less, we hope).

3b. When a Frame Trigger Mode (other than "Off") is selected, the exposure time setting at the top of the camera panel has no effect except in setting the live view exposure time and providing the input for the auto_N function. The Frame Period (ms) sets the period of the trigger waveform that will be sent out of the DAQ. It should not be limited by the exposure time setting at the top of the panel, and will not be so limited in our new release. If the limit is a problem, just increase the exposure time setting. So if you set the frame period to 1 ms, the DAQ will send a trigger out every 1 ms. With Hamamatsu cameras, this trigger pulse will initiate readout of the previous frame and start exposure of the next frame (see the section on Synchronous readout trigger mode in your camera manual). So FPS will be the exact reciprocal of the frame period setting.

Let me know if this helps.

philbrooksIII commented 1 month ago

And I neglected to mention that I just committed a few changes to the waveform_Camera_sync_acquisition script that fix some potential bugs relating to what you want to do. I don't think they would have caused the issues you report, but they would have been problems down the line. Pull down the most recent version before proceeding.

Luorong37 commented 1 month ago

The initial issue with PFI and Counter was resolved after configuration.

Now, we're encountering another problem: the window becomes unresponsive after clicking Start Acquisition, displaying the message Acquiring data.... This error occurs regardless of whether the clock and counter are set, or whether the Frame Trigger is off or DAQ. During this state, the camera's status light turns orange, and a blank DCIMG file is created. However, clicking Snap successfully captures an image.

We also observed that if the Waveform is not set, the browser throws the error Waveforms are empty. Add waveforms before building, after clicking Start Acquisition, even when the Frame Trigger is off.

We seek detailed guidance on setting up the Clock and Counter. We've noticed the settings in Example_Multi_Camera.json, which designate one master camera as the clock. If we intend to trigger two cameras using DAQ, is the clock unnecessary? In what scenarios should the Counter be configured? Could you provide a guide on the physical connections?

Additionally, we would appreciate an explanation of each parameter in the JSON configuration file, as there are no corresponding notes in {Device}_Initializer.m.

Thank you!

DanItkis commented 1 month ago

Hi,

From your description of the issue it sounds to me like a trigger problem between the DAQ and the camera, as you've correctly intuited. Here are some tips on how I would address this. The issue is that the camera is expecting a trigger from the DAQ, which doesn't seem to arrive. So this is presumably an issue of correctly setting the wiring (physically) and triggers (Luminos GUI). It’s possible that either the physical connections are not set up properly, or the configuration settings in your system do not match the needs of your setup. Here’s a breakdown to help you troubleshoot:

Make sure that the DAQ's trigger out is correctly connected to the camera's trigger in. Check that the parameters in your .json configuration file should match the hardware and logical setup. In the example Example_Multi_Camera.json for instance, the camera trigger is set to "trigger": "Dev1/port0/line7", for both cameras. That means in order to run the camera(s), you would need to connect that DAQ output to the camera trigger input. You need to adjust this trigger DAQ output to match your setup.

In Frame Trigger off mode, the camera(s) expect a single trigger pulse at the start of the recording. In Frame Trigger DAQ mode, the camera expects a trigger pulse at the start of every frame (this helps better synchronize the recording). I suggest you first try getting the off mode to work. If the wiring is correct but the issue persists, you can use a oscilloscope to check if the DAQ is in fact outputting a pulse.

As to your second point that "if the Waveform is not set, the browser throws the error", that is by design. This is in order to prevent accidental empty recordings, as with no waveform set the camera (and all other devices) would never get a starting signal and could never start recording.

Please let me know if this helps or you have further questions.

Luorong37 commented 1 month ago

Hi.

After the Timing on camera and the PFI0 were connected (which was set in .json as "daqTrigCounter": "/Dev1/PFI0"), the Start Acquisition can be done in the Frame Trigger off mode.

However, in the Frame Trigger DAQ mode, the Start Acquisition throws the following error: NI Error -200430: I/O type of the physical channel does not match the I/O type required for the virtual channel you are creating. Physical Channel Name: PFI0 Virtual Channel Name: Camtrig Counter I/O Type Required for Virtual Channel: DAQmx_Val_CO Task Name: _unnamedTask<87> Status Code: -200430

Thanks for your answer!

Luorong37 commented 1 month ago

I noticed the configuration in Example_Multi_Camera.json. The Camera Fusion was set with "clock": "/Dev1/PFI0", "vsync": "Dev1/Ctr3", and "daqTrigCounter": "Dev1/Ctr0", while the Camera Flash was set with "vsync": "Dev1/Ctr1" and "daqTrigCounter": "Dev1/Ctr0". Does this mean I should connect the Timing port on Camera 1 to PFI0, Ctr3, and Ctr0, and connect Camera 2 to Ctr1 and Ctr0, so that the two cameras can be synchronized in Frame Trigger DAQ mode?

Thanks!

DanItkis commented 1 month ago

Hi,

Great that you got the Frame Trigger off mode to work. From what I'm understanding about your error with Frame Trigger DAQ, it sounds like you're trying to use "/Dev1/PFI0" to send pulses to the camera. The issue seems to be that this PFI is input-only, so it's not designed to output pulses and throws an error if you try. The solution would be to switch to a different line that is capable of handling outputs. You can find your model of NI DAQ and the respective inputs/output roles on the NI website, see e.g. https://www.ni.com/en/support/documentation/supplemental/18/features-and-differences-of-ni-multifunction-daq-pfi-lines.html and adjust accordingly, or try a couple lines until you find one that works (adjust the .json if you do change lines!). Please let me know if you need help figuring out which lines to use (I would need to know your DAQ model for this).

As an example from Example_Multi_Camera.json, you can see that clock (the clock output of the camera that is used as an input to the DAQ) is connected to a PFI. This is an input, not an output of the DAQ. On the other hand the trigger (so a output of the DAQ) uses line7, not a PFI.

  "trigger": "Dev1/port0/line7",
  "clock": "/Dev1/PFI0",
DanItkis commented 1 month ago

As for the configuration in Example_Multi_Camera.json: The triggers are shared across both cameras so the frames on both cameras are started simultaneously, though this could in principle be decoupled. I believe the rest of what you wrote is correct. I will take photos of one of our setups tomorrow to clear up any ambiguity here.