Skip to content

Commit

Permalink
Merge pull request #119 from chris-allan/fix-missing-groups
Browse files Browse the repository at this point in the history
Fix problems with missing groups/metadata and sparse plates
  • Loading branch information
chris-allan authored Mar 1, 2022
2 parents 37cde33 + 7ac4b4f commit d6eb09e
Show file tree
Hide file tree
Showing 7 changed files with 357 additions and 146 deletions.
86 changes: 50 additions & 36 deletions src/main/java/com/glencoesoftware/bioformats2raw/Converter.java
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ public void convert()
}

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

for (Integer index : seriesList) {
Expand Down Expand Up @@ -722,8 +722,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 @@ -1345,29 +1345,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
}
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);
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);
}
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 @@ -1377,7 +1384,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 @@ -1391,61 +1400,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

0 comments on commit d6eb09e

Please sign in to comment.