Fastest way to see which pixel has changed when using a listener - event-listener

I am trying to get EDS spectra on every scanned pixel using STEM.
I am using the EDSStartAcquisition( 2048, 10,fexposure*2, 1) command and
I have attached the following simple listener object into the shown 1D spectrum image:
string messagemap = "data_value_changed:MyImageAction"
Class MyListenerClass1
{
String event_desc;
MyListenerClass1(Object self); //Result("\n");
~MyListenerClass1(Object self);// Result("\n");
Void MyImageAction(Object self, Number e_fl, Image Img)
{
ImageGetEventMap().DeconstructEventFlags( e_fl, event_desc )
Result(GetTime(1)+": Image message : " + event_desc + " 0x" + Binary(e_fl) + "\n" )
}
}
ListenerID1 = EDSIm.ImageAddEventListener( Listener1, messagemap)
Since speed is the issue here, I figured to try the continuous mode of the EDS acquisition. But then I would need to listen which counts belong to each scanned pixel. The following topic (How to getting acquired frames at full speed ? - Image Event Listener does not seem to be executing after every event) shows how to listen to the last pixel change of an image. But what would be the fastest way to directly see which slice of the 1D spectrum has changed on every event? Without going through every slice...
thanks in advance!

An images' data_value_changed is fired whenever a) an image locker (the object that ensures there is single access to the memory) is released, or b) a specific update-call is made in the code.
As such, when a cumulative EDS spectrum is acquired, the whole array gets "locked", then modified (on one or more positions) and then 'updated'. There is no specific information carried on where the array was modified.
Therefore, the only way to find out where the spectrum changed is by comparing a copy of the "before" with the "now" - which is not super efficient.

Related

Anylogic: Dynamically change source rate using variable/slider

I am trying to dynamically change the source Arrival rate using a variable "arrivalRate" linked to a slider (see image).
However, during the simulation the initial rate remains the same, even when I change the arrivalRate. I know that the arrivalRate variable is changing successfully (it is an int) - but this has no effect on the source rate during the simulation.
Anyone have an idea what the issue is - or how to fix it?
Whenever you see the = sign before a field, it means it's not dynamic, it is only evaluated at the start of the model or at the element creation and will not change throughout the simulation run unless you force it. In other words, the variable arrivalRate is checked only once to assign the source's arrival rate and that's it.
Now if you want to change it dynamically, in the slider's Action field, write the following:
source.set_rate( arrivalRate );

Get data from Serialport using Callback?

I am using this function:
https://es.mathworks.com/help/matlab/import_export/use-events-and-callbacks-for-serial-port-communication.html
function readSerialData(s,~)
data = readline(s);
disp(data);
end
configureCallback(s,"terminator",#readSerialData)
To get data from my connected device. The device receives new data every second or so (50 Bytes), so I get the data displayed on the command line in real time. But I want to actually use this data, but I am not sure how to gather the variables.
I can not see any "data" variable in the workspace, to store it and plot a real time graph (that´s the target)
Thank you in advance :)

How to combine two bunch of data, into one chart in Highcharts?

I'm totally new to highcharts so excuse any mistake in advance.
I have one chart which illustrates amount of bandwidth used according to datetime. (somehow like this example.) I need to show more data to the user whenever the chart is zoomed on xAxis; means new data should be popped up when we are seeing a period of time in detail. fortunately, I have access to that new data, but the main problem is that I don't know how to combine this new data with my old chart.
To make my question more vivid, lets imagine this scenario: assume that I have bandwidth usage for last 2 years in scale of month (for every month on xAxis, I have one value on yAxis), then I zoom in some part of my chart and the chart gets wider and new points pop up on xAxis (what automatically happens in highcharts when we set zoomtype: 'x'), for some of these points, I have some values corresponded to them on yAxis, which I want these new points to be considered in my chart. what shall I do to do this for large scale of data? (e.g. when I have the data for 2 years and I wanna zoom by accuracy of one minute, it is not feasible to include new points manually in between of old series.)
since my code is too large and makes it more complicated to put it here, I try to illustrate my desired result via pictures:
1) this is my chart before zoom:
2) after zoom:
3) and the final result which I do not know how to make it:
Any help would be very appreciated.
Take a look at this live demo: http://jsfiddle.net/kkulig/6gyfx6n7/
I used afterSetExtremes event to check the currently displayed time span and set the appropriate data. If it's shorter than 30 days then I add additional points. Otherwise I restore the default data. pointsAdded helps me to to control whether these operations are actually needed or not.
events: {
afterSetExtremes: function(e) {
var series = this.series[0];
if (pointsAdded && e.max - e.min > 30 * day) {
console.log('Set default data');
series.setData(data.slice());
pointsAdded = false;
} else if (!pointsAdded) {
console.log('Add points');
additionalData.forEach(function(p) {
series.addPoint(p, false);
series.chart.redraw();
pointsAdded = true;
});
}
}
}
To see it working select the last 20 days or so. Then return to the default view by clicking All button.
API references:
https://api.highcharts.com/highstock/xAxis.events.afterSetExtremes
https://api.highcharts.com/class-reference/Highcharts.Series

How to use MTLBlitCommandEncoder for copying interlaced video fields into a MTLBuffer

We are working with interlaced HD video. The metal color attachment I use for rendering has the dimensions of one field (1920*540 RGBA).
When I try to copy two rendered fields into the same MTLBuffer that has the size of 1920*1080*4 = 8294400 bytes it works only if the destination offset is zero.
let commandBuffer = commandQueue.makeCommandBuffer()
let blitEncoder = commandBuffer.makeBlitCommandEncoder()
blitEncoder.copy(from: attachmentTexture,
sourceSlice: 0,
sourceLevel: 0,
sourceOrigin: MTLOriginMake(0, 0, 0),
sourceSize: MTLSizeMake(attachmentTexture.width, attachmentTexture.height, 1),
to: destinationBuffer,
destinationOffset: 1920*4,
destinationBytesPerRow: 1920*4*2,
destinationBytesPerImage: destinationBuffer.length)
blitEncoder.endEncoding()
commandBuffer.commit()
For the first field where the destination offset is zero the function works well. The destination buffer is filled for every second row.
But when I want to write the second field with the same code into the same MTLBuffer object only with the destinationOffset set to 1920*4 like you see in the code above (to start with the second row in the buffer) then I get an assertion like this:
-[MTLDebugBlitCommandEncoder validateCopyFromTexture:sourceSlice:sourceLevel:sourceOrigin:sourceSize:toBuffer:destinationOffset:destinationBytesPerRow:destinationBytesPerImage:options:]:677:
failed assertion `totalBytesUsed(8302080) must be <=
destinationBuffer length.'
The totalBytesUsed are exactly the destination buffer length in bytes plus the offset. So every offset I use in this function will result in this assertion error.
Can someone explain me how to use this function correctly because the other way around like creating two MTLTexture objects (odd and even fields) for an incoming video frame works well with similar parameters.
I ran into something like this recently, too.
You're passing destinationBuffer.length to the destinationBytesPerImage: parameter. As you've noticed, Metal is adding together the offset and the bytes-per-image value and comparing that against the length of the to: destination buffer (destinationBuffer). It's noticing that offset plus bytes-per-image won't fit into the buffer and refusing to accept that.
You may be able to simply pass 0 for destinationBytesPerImage:, since you're not working with a 3D or 2D array texture. If that doesn't work, pass destinationBuffer.length - 1920*4.

MATLAB undo a command

I am currently developing a basic image processing application on MATLAB. I have to implement undo to previous state feature. I searched net there is uiundo but it only undos GUI actions. Is there a simple command to undo. Thanks.
If you have plenty of memory to spare, you could store all of your program states in a structure and then push this structure into a circular buffer. The number of elements in the buffer would determine the number of levels of undo.
It seems to me that you would have to implement your own multi-level (or one-level) undo by using the Command pattern.
This would require you to wrap your operations into objects that contain the logic to perform the action and to restore the state. No silver bullet, hard work needed.
General undo will be complicated, but if you are only interested in saving the state of MATLAB variables and returning to a saved state, this might be one possible solution:
save_state.m:
SavedStateFolder = '/home/user/matlab_saved_states_folder/';
save([ SavedStateFolder, 'saved_state_', sprintf('%06d', (size(dir(SavedStateFolder), 1) - 1)) ]);
fprintf('state saved in saved_state_%s.mat\n', sprintf('%06d', (size(dir(SavedStateFolder), 1) - 2)));
undo_index.m:
function undo_index()
SavedStateFolder = '/home/user/matlab_saved_states_folder/';
FilesStruct = dir(SavedStateFolder);
LastSavedStateIndex = size(FilesStruct, 1) - 2;
if (LastSavedStateIndex < 1)
fprintf('No saved states available.\n');
else
fprintf('Index of last saved state is %06d\n', LastSavedStateIndex);
end
return
undo.m:
SavedStateFolder = '/home/user/matlab_saved_states_folder/';
load([ SavedStateFolder, 'saved_state_', sprintf('%06d', input('Enter saved state index ')) ]);
Then you can use save_state to save the state of MATLAB variables or you can even prefix all your commands with save_state; if you want to keep track of all changes. When you want to return to a previous state of variables, you can run undo_index to find out the index of last saved state and then you can run undo and input the index given by undo_index, or alternatively any smaller positive integer to return to an earlier state of variables. The first saved state file will be named saved_state_000001.mat, then saved_state_000002.mat and so on... Note that save_state saves everything to disk, so using SSD or RAM disk might be a good idea if you want to try this in a loop with a lot of data. Note also that the previous content of variable called SavedStateFolder is lost when you run save_state or undo. To avoid this, you can replace all instances of SavedStateFolder in save.state.m and undo.m with hard-coded folder names, for example:
save_state.m:
save([ '/home/user/matlab_saved_states_folder/', 'saved_state_', sprintf('%06d', (size(dir('/home/user/matlab_saved_states_folder/'), 1) - 1)) ]);
fprintf('state saved in saved_state_%s.mat\n', sprintf('%06d', (size(dir('/home/user/matlab_saved_states_folder/'), 1) - 2)));
undo.m:
load([ '/home/user/matlab_saved_states_folder/', 'saved_state_', sprintf('%06d', input('Enter saved state index ')) ]);
Note also that save_state, undo_index and undo assume that in SavedStateFolder there are no other files except ., .. and saved_state_*.mat files. Also the number of saved_state_*.mat files and the running index to be saved is found out this way, so if you delete some previous saved_state_*.mat files without eg. creating equal number of empty files to replace them, the counts don't match and save_state might save the state on top of an already existing saved state file.