Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add tags in events that will be added to metadata. #91

Merged
merged 6 commits into from
Jun 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>org.micro-manager.acqengj</groupId>
<artifactId>AcqEngJ</artifactId>
<version>0.27.0</version>
<version>0.28.0</version>
<packaging>jar</packaging>
<name>AcqEngJ</name>
<description>Java-based Acquisition engine for Micro-Manager</description>
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/org/micromanager/acqj/internal/Engine.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import mmcorej.org.json.JSONException;
import org.micromanager.acqj.api.AcquisitionAPI;
import org.micromanager.acqj.main.AcquisitionEvent;
import org.micromanager.acqj.api.AcquisitionHook;
Expand Down Expand Up @@ -534,6 +535,12 @@ private void acquireImages(final AcquisitionEvent event) throws HardwareControlE
//add metadata
AcqEngMetadata.addImageMetadata(ti.tags, correspondingEvent,
currentTime - correspondingEvent.acquisition_.getStartTime_ms(), exposure);
try {
correspondingEvent.acquisition_.addTagsToTaggedImage(ti.tags,
correspondingEvent.getTags());
} catch (JSONException jse) {
core_.logMessage("Error adding tags to image metadata", false);
}
correspondingEvent.acquisition_.addToImageMetadata(ti.tags);

correspondingEvent.acquisition_.addToOutput(ti);
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/org/micromanager/acqj/main/AcqEngMetadata.java
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,11 @@ public class AcqEngMetadata {
public static final String CORE_XYSTAGE = "Core-XYStage";
public static final String CORE_FOCUS = "Core-Focus";
public static final String AXES = "Axes";

public static final String CHANNEL_AXIS = "channel";
public static final String TIME_AXIS = "time";
public static final String Z_AXIS = "z";
public static final String TAGS = "tags";

private static final String ACQUISITION_EVENT = "Event";


Expand Down
54 changes: 41 additions & 13 deletions src/main/java/org/micromanager/acqj/main/Acquisition.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
//
package org.micromanager.acqj.main;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.*;
import java.util.function.Consumer;

Expand Down Expand Up @@ -156,11 +158,35 @@ public void addToImageMetadata(JSONObject tags) {
}
}

/**
* Add provided tags (Key-Value pairs of type String) to the Tagged Image tags.
* These will appear as JSONObjects under the key:
* {@link org.micromanager.acqj.main.AcqEngMetadata#TAGS "Tags"}.
*
* @param tags Tagged Image tags
* @param moreTags User-provided tags as Key-Value pairs
*/
public void addTagsToTaggedImage(JSONObject tags, HashMap<String, String> moreTags)
throws JSONException {
if (moreTags.isEmpty()) {
return;
}
JSONObject moreTagsObject = new JSONObject();
for (Map.Entry<String, String> entry : moreTags.entrySet()) {
try {
moreTagsObject.put(entry.getKey(), entry.getValue());
} catch (JSONException e) {
e.printStackTrace();
}
}
tags.put(AcqEngMetadata.TAGS, moreTagsObject);
}

@Override
public Future submitEventIterator(Iterator<AcquisitionEvent> evt) {
if (!started_) {
start();
}
}
return Engine.getInstance().submitEventIterator(evt);
}

Expand Down Expand Up @@ -283,19 +309,21 @@ public void waitForCompletion() {
* 3) Initialize data sink.
*/
protected void initialize() {
JSONObject summaryMetadata = AcqEngMetadata.makeSummaryMD(this);
addToSummaryMetadata(summaryMetadata);
if (core_ != null) {
JSONObject summaryMetadata = AcqEngMetadata.makeSummaryMD(this);
addToSummaryMetadata(summaryMetadata);

try {
// Make a local in copy in case something else modifies it
summaryMetadata_ = new JSONObject(summaryMetadata.toString());
} catch (JSONException ex) {
System.err.print("Couldn't copy summaary metadata");
ex.printStackTrace();
}
if (dataSink_ != null) {
//It could be null if not using saving and viewing and diverting with custom processor
dataSink_.initialize(this, summaryMetadata);
try {
// Make a local in copy in case something else modifies it
summaryMetadata_ = new JSONObject(summaryMetadata.toString());
} catch (JSONException ex) {
System.err.print("Couldn't copy summaary metadata");
ex.printStackTrace();
}
if (dataSink_ != null) {
//It could be null if not using saving and viewing and diverting with custom processor
dataSink_.initialize(this, summaryMetadata);
}
}
}

Expand Down
44 changes: 40 additions & 4 deletions src/main/java/org/micromanager/acqj/main/AcquisitionEvent.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import mmcorej.org.json.JSONArray;
Expand Down Expand Up @@ -64,6 +66,8 @@ enum SpecialFlag {
private HashMap<String, Double> stageCoordinates_ = new HashMap<String, Double>();
// Mapping from device names to axis names
private HashMap<String, String> stageDeviceNamesToAxisNames_ = new HashMap<String, String>();
// tags to be added to the acquired image
private final HashMap<String, String> tags_ = new HashMap<String, String>();

//Option to not acquire an image for SLM events
private Boolean acquireImage_ = null;
Expand Down Expand Up @@ -142,6 +146,7 @@ public AcquisitionEvent copy() {
e.acquireImage_ = acquireImage_;
e.properties_ = new TreeSet<ThreeTuple>(this.properties_);
e.camera_ = camera_;
e.setTags(tags_);
return e;
}

Expand Down Expand Up @@ -213,6 +218,14 @@ private static JSONObject eventToJSON(AcquisitionEvent e) {
json.put("camera", e.camera_);
}

if (e.getTags() != null) {
JSONObject jsonTags = new JSONObject();
for (Map.Entry<String, String> entry : e.getTags().entrySet()) {
jsonTags.put(entry.getKey(), entry.getValue());
}
json.put("tags", jsonTags);
}

//TODO: galvo
//TODO: more support for imperative API calls (i.e. SLM set image)
//Arbitrary extra properties
Expand All @@ -223,7 +236,7 @@ private static JSONObject eventToJSON(AcquisitionEvent e) {
prop.put(t.prop);
prop.put(t.val);
props.put(prop);
}
}
if (props.length() > 0) {
json.put("properties", props);
}
Expand Down Expand Up @@ -318,6 +331,17 @@ private static AcquisitionEvent eventFromJSON(JSONObject json, AcquisitionAPI ac
event.camera_ = json.getString("camera");
}

if (json.has("tags")) {
HashMap<String, String> tags = new HashMap<>();
JSONObject jsonTags = json.getJSONObject("tags");
Iterator<String> keys = jsonTags.keys();
while (keys.hasNext()) {
String key = keys.next();
tags.put(key, jsonTags.getString(key));
}
event.setTags(tags);
}

//TODO: galvo, etc (i.e. other aspects of imperative API)


Expand Down Expand Up @@ -434,9 +458,9 @@ public void setProperty(String device, String property, String value) {
}

/**
* Set the minimum start time in ms relative to when the acq started
* Set the minimum start time in ms relative to when the acq started.
*
* @param l
* @param l Minimum start time in ms.
*/
public void setMinimumStartTime(Long l) {
miniumumStartTime_ms_ = l;
Expand Down Expand Up @@ -544,7 +568,7 @@ public Double getZPosition() {
}

/**
* get the minimum start timein system time
* Get the minimum start time in system time.
*
* @return
*/
Expand Down Expand Up @@ -621,6 +645,18 @@ public void setY(double y) {
yPosition_ = y;
}

public void setTags(HashMap<String, String> tags) {
tags_.clear();
if (tags != null) {
tags_.putAll(tags);
}
}
public HashMap<String, String> getTags () {
HashMap<String, String> tags = new HashMap<>(tags_.size());
tags.putAll(tags_);
return tags;
}


//For debugging
@Override
Expand Down
41 changes: 41 additions & 0 deletions tests/org/micromanager/acqj/main/TestAcquisitionEvent.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package org.micromanager.acqj.main;

import java.util.HashMap;
import mmcorej.org.json.JSONObject;
import org.junit.Assert;
import org.junit.Test;
import org.micromanager.acqj.example.BlackHoleDataSink;

public class TestAcquisitionEvent {
@Test
public void testSetupIsSane() {
Assert.assertTrue("must be true", true);
}

@Test
public void testEventSerialization() {
BlackHoleDataSink bhds = new BlackHoleDataSink();
Acquisition acq = new Acquisition(bhds);
AcquisitionEvent event = new AcquisitionEvent(acq);
final int z = 2;
event.setZ(z, z * 0.5);
final int t = 3;
event.setTimeIndex(t);
final long minimumStartTime = 892567265;
event.setMinimumStartTime(minimumStartTime);
HashMap<String, String> tags = new HashMap<>();
tags.put("test", "test");
tags.put("test2", "test2");

JSONObject eventSerial = event.toJSON();
AcquisitionEvent eventCopy = AcquisitionEvent.fromJSON(eventSerial, acq);

Assert.assertTrue(eventCopy.getZIndex() == z);
Assert.assertEquals(eventCopy.getZPosition(), z * 0.5, 0.0000001);
Assert.assertTrue(eventCopy.getTIndex() == t);
Assert.assertEquals(eventCopy.getMinimumStartTimeAbsolute(), minimumStartTime, 2000);
Assert.assertEquals(eventCopy.getTags().get("test"), event.getTags().get("test"));
Assert.assertEquals(eventCopy.getTags().get("test2"), event.getTags().get("test2"));
}
}