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

Fix problems with missing groups/metadata and sparse plates #119

Merged
merged 14 commits into from
Mar 1, 2022
Merged
Show file tree
Hide file tree
Changes from 13 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
84 changes: 49 additions & 35 deletions src/main/java/com/glencoesoftware/bioformats2raw/Converter.java
Original file line number Diff line number Diff line change
Expand Up @@ -627,7 +627,7 @@ public void convert()
}

if (!noHCS) {
scaleFormatString = "%d/%d/%d/%d";
scaleFormatString = "%s/%s/%d/%d";
}

for (Integer index : seriesList) {
Expand Down Expand Up @@ -711,8 +711,8 @@ private Object[] getScaleFormatStringArgs(
List<Object> args = new ArrayList<Object>();
if (!noHCS) {
HCSIndex index = hcsIndexes.get(series);
args.add(index.getWellRowIndex());
args.add(index.getWellColumnIndex());
args.add(index.getRowPath());
args.add(index.getColumnPath());
args.add(index.getFieldIndex());
args.add(resolution);
}
Expand Down Expand Up @@ -1331,29 +1331,36 @@ private void saveHCSMetadata(IMetadata meta) throws IOException {
List<Map<String, Object>> rows = new ArrayList<Map<String, Object>>();

// try to set plate dimensions based upon Plate.Rows/Plate.Columns
// if not possible, use well data later on
try {
for (int r=0; r<meta.getPlateRows(plate).getValue(); r++) {
Map<String, Object> row = new HashMap<String, Object>();
String rowName = String.valueOf(r);
row.put("name", rowName);
rows.add(row);
root.createSubGroup(rowName);
// if not possible, use well data
PositiveInteger plateRows = meta.getPlateRows(plate);
if (plateRows == null) {
plateRows = new PositiveInteger(1);
for (int wellIndex=0; wellIndex<meta.getWellCount(plate); wellIndex++) {
plateRows = new PositiveInteger(Math.max(
meta.getWellRow(plate, wellIndex).getNumberValue().intValue(),
plateRows.getNumberValue().intValue()));
}
}
catch (NullPointerException e) {
// expected when Plate.Rows not set
for (int r=0; r<plateRows.getValue(); r++) {
Map<String, Object> row = new HashMap<String, Object>();
String rowName = HCSIndex.getRowName(r);
row.put("name", rowName);
rows.add(row);
}
try {
for (int c=0; c<meta.getPlateColumns(plate).getValue(); c++) {
Map<String, Object> column = new HashMap<String, Object>();
String columnName = String.valueOf(c);
column.put("name", columnName);
columns.add(column);
PositiveInteger plateColumns = meta.getPlateColumns(plate);
if (plateColumns == null) {
plateColumns = new PositiveInteger(1);
for (int wellIndex=0; wellIndex<meta.getWellCount(plate); wellIndex++) {
plateColumns = new PositiveInteger(Math.max(
meta.getWellColumn(plate, wellIndex).getNumberValue().intValue(),
plateColumns.getNumberValue().intValue()));
}
}
catch (NullPointerException e) {
// expected when Plate.Columns not set
for (int c=0; c<plateColumns.getValue(); c++) {
Map<String, Object> column = new HashMap<String, Object>();
String columnName = HCSIndex.getColumnName(c);
column.put("name", columnName);
columns.add(column);
}

List<Map<String, Object>> acquisitions =
Expand All @@ -1363,7 +1370,9 @@ private void saveHCSMetadata(IMetadata meta) throws IOException {
acquisition.put("id", String.valueOf(pa));
acquisitions.add(acquisition);
}
plateMap.put("acquisitions", acquisitions);
if (acquisitions.size() > 0) {
plateMap.put("acquisitions", acquisitions);
}

List<Map<String, Object>> wells = new ArrayList<Map<String, Object>>();
int maxField = Integer.MIN_VALUE;
Expand All @@ -1377,61 +1386,66 @@ private void saveHCSMetadata(IMetadata meta) throws IOException {

List<Map<String, Object>> imageList =
new ArrayList<Map<String, Object>>();
ZarrGroup wellGroup = root.createSubGroup(wellPath);
String rowPath = index.getRowPath();
ZarrGroup rowGroup = root.createSubGroup(rowPath);
String columnPath = index.getColumnPath();
ZarrGroup columnGroup = rowGroup.createSubGroup(columnPath);
for (HCSIndex field : hcsIndexes) {
if (field.getPlateIndex() == index.getPlateIndex() &&
field.getWellRowIndex() == index.getWellRowIndex() &&
field.getWellColumnIndex() == index.getWellColumnIndex())
{
Map<String, Object> image = new HashMap<String, Object>();
int plateAcq = field.getPlateAcquisitionIndex();
image.put("acquisition", plateAcq);
Integer plateAcq = field.getPlateAcquisitionIndex();
if (plateAcq != null) {
image.put("acquisition", plateAcq);
}
image.put("path", String.valueOf(field.getFieldIndex()));
imageList.add(image);
}
}

Map<String, Object> wellMap = new HashMap<String, Object>();
wellMap.put("images", imageList);
Map<String, Object> attributes = wellGroup.getAttributes();
Map<String, Object> attributes = columnGroup.getAttributes();
attributes.put("well", wellMap);
wellGroup.writeAttributes(attributes);
columnGroup.writeAttributes(attributes);

// make sure the row/column indexes are added to the plate attributes
// this is necessary when Plate.Rows or Plate.Columns is not set
int column = index.getWellColumnIndex();
int row = index.getWellRowIndex();
String column = index.getColumnPath();
String row = index.getRowPath();

int columnIndex = -1;
for (int c=0; c<columns.size(); c++) {
if (columns.get(c).get("name").equals(String.valueOf(column))) {
if (columns.get(c).get("name").equals(column)) {
columnIndex = c;
break;
}
}
if (columnIndex < 0) {
Map<String, Object> colMap = new HashMap<String, Object>();
colMap.put("name", String.valueOf(column));
colMap.put("name", column);
columnIndex = columns.size();
columns.add(colMap);
}

int rowIndex = -1;
for (int r=0; r<rows.size(); r++) {
if (rows.get(r).get("name").equals(String.valueOf(row))) {
if (rows.get(r).get("name").equals(row)) {
rowIndex = r;
break;
}
}
if (rowIndex < 0) {
Map<String, Object> rowMap = new HashMap<String, Object>();
rowMap.put("name", String.valueOf(row));
rowMap.put("name", row);
rowIndex = rows.size();
rows.add(rowMap);
}

well.put("row_index", rowIndex);
well.put("column_index", columnIndex);
well.put("rowIndex", rowIndex);
well.put("columnIndex", columnIndex);
wells.add(well);
}

Expand Down
103 changes: 53 additions & 50 deletions src/main/java/com/glencoesoftware/bioformats2raw/HCSIndex.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@

public class HCSIndex {

private int plate = -1;
private int plateAcquisition = -1;
private int wellRow = -1;
private int wellColumn = -1;
private int field = -1;
private final int plate;
private final Integer plateAcquisition;
private final int wellRow;
private final int wellColumn;
private final int field;

/**
* Construct an HCSIndex object representing an Image/series,
Expand All @@ -25,6 +25,7 @@ public class HCSIndex {
* @param series OME Image/Bio-Formats series index
*/
public HCSIndex(IMetadata meta, int series) {
Integer thePlateAcquisition = null;
for (int p=0; p<meta.getPlateCount(); p++) {
for (int w=0; w<meta.getWellCount(p); w++) {
for (int ws=0; ws<meta.getWellSampleCount(p, w); ws++) {
Expand All @@ -39,19 +40,22 @@ public HCSIndex(IMetadata meta, int series) {
for (int s=0; s<meta.getWellSampleRefCount(p, pa); s++) {
String refID = meta.getPlateAcquisitionWellSampleRef(p, pa, s);
if (id.equals(refID)) {
plateAcquisition = pa;
thePlateAcquisition = pa;
break;
}
}
if (plateAcquisition >= 0) {
if (thePlateAcquisition >= 0) {
break;
}
}
plateAcquisition = thePlateAcquisition;
return;
}
}
}
}
throw new IllegalArgumentException(
"Series " + series + " not present in metadata!");
}

/**
Expand All @@ -62,46 +66,20 @@ public int getPlateIndex() {
}

/**
* Set plate index.
*
* @param plateIndex plate index
*/
public void setPlateIndex(int plateIndex) {
this.plate = plateIndex;
}

/**
* @return plate acquisition index
* @return plate acquisition index or <code>null</code> if no related plate
* acquisition can be found
*/
public int getPlateAcquisitionIndex() {
public Integer getPlateAcquisitionIndex() {
return plateAcquisition;
}

/**
* Set plate acquisition index.
*
* @param plateAcquisitionIndex plate acquisition index
*/
public void setPlateAcquisitionIndex(int plateAcquisitionIndex) {
this.plateAcquisition = plateAcquisitionIndex;
}

/**
* @return well row index
*/
public int getWellRowIndex() {
return wellRow;
}

/**
* Set well row index.
*
* @param wellRowIndex well row index
*/
public void setWellRowIndex(int wellRowIndex) {
this.wellRow = wellRowIndex;
}

/**
* @return well column index
*/
Expand All @@ -110,35 +88,31 @@ public int getWellColumnIndex() {
}

/**
* Set well column index.
*
* @param wellColumnIndex well column index
* @return field index
*/
public void setWellColumnIndex(int wellColumnIndex) {
this.wellColumn = wellColumnIndex;
public int getFieldIndex() {
return field;
}

/**
* @return field index
* @return row path relative to the plate group
*/
public int getFieldIndex() {
return field;
public String getRowPath() {
return getRowName(getWellRowIndex());
}

/**
* Set field (well sample) index.
*
* @param fieldIndex field index
* @return column path relative to the row group
*/
public void setFieldIndex(int fieldIndex) {
this.field = fieldIndex;
public String getColumnPath() {
return getColumnName(getWellColumnIndex());
}

/**
* @return well path relative to the plate group
*/
public String getWellPath() {
return String.format("%d/%d", getWellRowIndex(), getWellColumnIndex());
return String.format("%s/%s", getRowPath(), getColumnPath());
}

@Override
Expand All @@ -151,4 +125,33 @@ public String toString() {
getFieldIndex());
}

/**
* Get a row name for the specified 0-based row index.
* The name is a single upper-case letter starting with A
* if the row index is less than 26, and two upper-case letters
* starting with AA for indexes greater than or equal to 26.
*
* @param rowIndex row index
* @return row name
*/
public static String getRowName(int rowIndex) {
String name = String.valueOf((char) ('A' + (rowIndex % 26)));
if (rowIndex >= 26) {
name = (char) ('A' + ((rowIndex / 26) - 1)) + name;
}
return name;
}

/**
* Get a column name for the specified 0-based column index.
* The name is a string representation of the corresponding
* 1-based index.
*
* @param colIndex column index
* @return column name
*/
public static String getColumnName(int colIndex) {
return String.format("%d", colIndex + 1);
}

}
Loading