@@ -78,14 +78,16 @@ public class BioTekReader extends FormatReader {
7878 // -- Fields --
7979
8080 private MinimalTiffReader helperReader ;
81- private Location parent ;
8281 private List <BioTekWell > wells = new ArrayList <BioTekWell >();
8382
8483 // seriesMap[seriesIndex] = {wellIndex, fieldIndex}
8584 private int [][] seriesMap ;
8685
8786 private List <String > xptFiles = new ArrayList <String >();
8887
88+ private transient Map <String , Element > xmlRoots =
89+ new HashMap <String , Element >();
90+
8991 // -- Constructor --
9092
9193 /** Constructs a new BioTek reader. */
@@ -163,10 +165,10 @@ public void close(boolean fileOnly) throws IOException {
163165 }
164166 if (!fileOnly ) {
165167 helperReader = null ;
166- parent = null ;
167168 wells .clear ();
168169 xptFiles .clear ();
169170 seriesMap = null ;
171+ xmlRoots .clear ();
170172 }
171173 }
172174
@@ -209,7 +211,7 @@ protected void initFile(String id) throws FormatException, IOException {
209211 super .initFile (id );
210212
211213 Location currentPath = new Location (id ).getAbsoluteFile ();
212- parent = currentPath .getParentFile ();
214+ Location parent = currentPath .getParentFile ();
213215
214216 findXPTFiles (parent );
215217
@@ -282,6 +284,9 @@ protected void initFile(String id) throws FormatException, IOException {
282284
283285 ArrayList <String > foundWellSamples = new ArrayList <String >();
284286
287+ boolean foundBrightfield = false ;
288+ boolean foundFluorescence = false ;
289+
285290 for (String absolutePath : files ) {
286291 String f = new Location (absolutePath ).getName ();
287292 Matcher m = regexA .matcher (f );
@@ -292,17 +297,19 @@ protected void initFile(String id) throws FormatException, IOException {
292297 int z = 0 ;
293298 int t = 0 ;
294299 String channelName = "" ;
300+ int channelNameGroupIndex = 6 ;
295301
296302 if (m .matches ()) {
297303 rowIndex = getWellRow (m .group (1 ));
298304 colIndex = Integer .parseInt (m .group (2 )) - 1 ;
299305 fieldIndex = Integer .parseInt (m .group (5 )) - 1 ;
300- channelName = m .group (6 );
306+ channelName = m .group (channelNameGroupIndex );
301307 }
302308 else {
303309 m = regexB .matcher (f );
304310 if (!m .matches ()) {
305311 m = regexZ .matcher (f );
312+ channelNameGroupIndex = 5 ;
306313 }
307314
308315 if (m .matches ()) {
@@ -321,7 +328,7 @@ protected void initFile(String id) throws FormatException, IOException {
321328 }
322329 // recorded T index may be negative if no timepoints
323330 t = (int ) Math .max (0 , Integer .parseInt (m .group (8 )) - 1 );
324- channelName += m .group (6 );
331+ channelName += m .group (channelNameGroupIndex );
325332 }
326333 else {
327334 m = regexROI .matcher (f );
@@ -374,7 +381,16 @@ protected void initFile(String id) throws FormatException, IOException {
374381 well .setFieldCount (fieldIndex + 1 );
375382 }
376383 int c = well .addChannelName (fieldIndex , channelName );
377- well .addFile (new PlaneIndex (fieldIndex , z , c , t ), absolutePath );
384+ Element root = getXMLRoot (absolutePath );
385+ boolean brightfield = isBrightField (root );
386+ if (!foundBrightfield ) {
387+ foundBrightfield = brightfield ;
388+ }
389+ if (!foundFluorescence ) {
390+ foundFluorescence = !brightfield ;
391+ }
392+ well .addFile (
393+ new PlaneIndex (fieldIndex , z , c , t , brightfield ), absolutePath );
378394
379395 if (rowIndex > maxRow ) {
380396 maxRow = rowIndex ;
@@ -397,6 +413,7 @@ protected void initFile(String id) throws FormatException, IOException {
397413 validWellRowCol .sort (null );
398414
399415 // split brightfield channels into a separate plate acquisition
416+ // if both brightfield and fluorescence data was found
400417 maxField .put (1 , -1 );
401418 int originalWellCount = wells .size ();
402419 Set <Integer > removedChannels = new HashSet <Integer >();
@@ -409,11 +426,10 @@ protected void initFile(String id) throws FormatException, IOException {
409426 LOGGER .trace ("found file {} for well index {}, field index {}" ,
410427 file , well , f );
411428 Element root = getXMLRoot (file );
412- boolean brightfield = isBrightField (root );
413429
414430 PlaneIndex index = w .getIndex (file );
415431
416- if (brightfield ) {
432+ if (index . brightfield && foundBrightfield && foundFluorescence ) {
417433 LOGGER .trace ("found brightfield file: {}" , file );
418434 w .removeFile (index , file );
419435 removedChannels .add (index .c );
@@ -444,7 +460,7 @@ protected void initFile(String id) throws FormatException, IOException {
444460 }
445461 }
446462 }
447- // correct the channel indexes in the non-brightfield plate acquisition
463+ // correct the channel indexes in the first plate acquisition
448464 for (BioTekWell well : wells ) {
449465 if (well .getPlateAcquisition () == 0 ) {
450466 Map <PlaneIndex , Integer > planeMap = well .getFilePlaneMap ();
@@ -550,10 +566,10 @@ protected void initFile(String id) throws FormatException, IOException {
550566 FormatTools .getMaxFieldCount (maxField .get (pa ) + 1 );
551567 store .setPlateAcquisitionMaximumFieldCount (fieldCount , 0 , pa );
552568
553- if (pa == 0 ) {
569+ if (pa == 0 && foundFluorescence ) {
554570 store .setPlateAcquisitionName ("Fluorescence" , 0 , pa );
555571 }
556- else if ( pa == 1 ) {
572+ else {
557573 store .setPlateAcquisitionName ("Bright-field" , 0 , pa );
558574 }
559575 }
@@ -652,6 +668,9 @@ private int getFieldIndex(int seriesIndex) {
652668 }
653669
654670 private Element getXMLRoot (String file ) throws FormatException , IOException {
671+ if (xmlRoots .containsKey (file )) {
672+ return xmlRoots .get (file );
673+ }
655674 try (TiffParser p = new TiffParser (file )) {
656675 String xml = p .getComment ();
657676 if (xml == null ) {
@@ -665,6 +684,7 @@ private Element getXMLRoot(String file) throws FormatException, IOException {
665684 catch (ParserConfigurationException |SAXException e ) {
666685 throw new FormatException (e );
667686 }
687+ xmlRoots .put (file , root );
668688 return root ;
669689 }
670690 }
@@ -1011,16 +1031,24 @@ public int getSizeT(int field) {
10111031 }
10121032
10131033 public String getFile (int fieldIndex , int [] zct ) {
1034+ PlaneIndex [] indexes = filePlaneMap .keySet ().toArray (new PlaneIndex [0 ]);
1035+ Arrays .sort (indexes );
10141036 if (zct == null ) {
1015- for (PlaneIndex p : filePlaneMap . keySet () ) {
1037+ for (PlaneIndex p : indexes ) {
10161038 if (p .fieldIndex == fieldIndex ) {
10171039 return getAllFiles ().get (filePlaneMap .get (p ));
10181040 }
10191041 }
10201042 }
1021- PlaneIndex p = new PlaneIndex (fieldIndex , zct [0 ], zct [1 ], zct [2 ]);
1022- Integer index = filePlaneMap .get (p );
1023- return index == null ? null : getAllFiles ().get (index );
1043+ for (PlaneIndex p : indexes ) {
1044+ if (p .fieldIndex == fieldIndex &&
1045+ p .z == zct [0 ] && p .c == zct [1 ] && p .t == zct [2 ])
1046+ {
1047+ Integer index = filePlaneMap .get (p );
1048+ return index == null ? null : getAllFiles ().get (index );
1049+ }
1050+ }
1051+ return null ;
10241052 }
10251053
10261054 public PlaneIndex getIndex (String file ) {
@@ -1038,48 +1066,76 @@ public PlaneIndex getIndex(String file) {
10381066 }
10391067 }
10401068
1041- class PlaneIndex {
1069+ class PlaneIndex implements Comparable < PlaneIndex > {
10421070 public int fieldIndex ;
10431071 public int z ;
10441072 public int c ;
10451073 public int t ;
1074+ public boolean brightfield = false ;
10461075
10471076 public PlaneIndex (int f , int z , int c , int t ) {
1077+ this (f , z , c , t , false );
1078+ }
1079+
1080+ public PlaneIndex (int f , int z , int c , int t , boolean brightfield ) {
10481081 this .fieldIndex = f ;
10491082 this .z = z ;
10501083 this .c = c ;
10511084 this .t = t ;
1085+ this .brightfield = brightfield ;
10521086 }
10531087
10541088 public PlaneIndex (PlaneIndex copy ) {
10551089 this .fieldIndex = copy .fieldIndex ;
10561090 this .z = copy .z ;
10571091 this .c = copy .c ;
10581092 this .t = copy .t ;
1093+ this .brightfield = copy .brightfield ;
10591094 }
10601095
10611096 @ Override
10621097 public int hashCode () {
1063- int fc = (fieldIndex & 0xff ) << 24 ;
1098+ int fc = (fieldIndex & 0x7f ) << 24 ;
10641099 int zc = (z & 0xff ) << 16 ;
10651100 int cc = (c & 0xff ) << 8 ;
10661101 int tc = (t & 0xff );
1067- return fc | zc | cc | tc ;
1102+ int coord = fc | zc | cc | tc ;
1103+ return brightfield ? coord | 0x80000000 : 0 ;
10681104 }
10691105
10701106 @ Override
10711107 public boolean equals (Object o ) {
10721108 if (o instanceof PlaneIndex ) {
10731109 PlaneIndex p = (PlaneIndex ) o ;
10741110 return p .fieldIndex == fieldIndex && p .z == z &&
1075- p .c == c && p .t == t ;
1111+ p .c == c && p .t == t && p . brightfield == brightfield ;
10761112 }
10771113 return false ;
10781114 }
10791115
1116+ @ Override
1117+ public int compareTo (PlaneIndex o ) {
1118+ if (this .equals (o )) {
1119+ return 0 ;
1120+ }
1121+ if (this .brightfield != o .brightfield ) {
1122+ return this .brightfield ? 1 : -1 ;
1123+ }
1124+ if (this .fieldIndex != o .fieldIndex ) {
1125+ return this .fieldIndex - o .fieldIndex ;
1126+ }
1127+ if (this .z != o .z ) {
1128+ return this .z - o .z ;
1129+ }
1130+ if (this .c != o .c ) {
1131+ return this .c - o .c ;
1132+ }
1133+ return this .t - o .t ;
1134+ }
1135+
10801136 public String toString () {
10811137 return "fieldIndex=" + fieldIndex + ", z=" + z +
1082- ", c=" + c + ", t=" + t ;
1138+ ", c=" + c + ", t=" + t + ", brightfield=" + brightfield ;
10831139 }
10841140
10851141 }
0 commit comments