public void AddTile(Tile tile)
        {
            Contract.Requires(Tiles.FirstOrDefault((t) => t.Id == tile.Id) == null);

            tile.PropertyChanged += Tile_Changed;

            _tiles.Add(tile);

            tile.Group = this;

            RaiseTileDataChanged(tile, TileStateChangeAction.Add);
            OnCollectionChangedAdd(TileCollectionChanged, tile);

            ObserveIncomplete(tile);
        }
 protected void RaiseTileDataChanged(Tile tile, TileStateChangeAction action)
 {
     RaiseTileDataChanged(new TileChangedEventArgs(tile, action));
 }
        public static Tile Create(string tileFullPath, string groupRelativePath, double minTiffSize = 0.0, int channelCount = 2)
        {
            List<string> parts = tileFullPath.Trim().Split(Path.DirectorySeparatorChar).ToList();

            if (parts.Count() > 0 && parts.Last().Length == 5)
            {
                int tileIndex;

                if (Int32.TryParse(parts.Last(), out tileIndex))
                {
                    Tile tile = new Tile() { Id = tileIndex };

                    tile.FullPath = tileFullPath;
                    tile.RelativePath = Path.Combine(groupRelativePath, parts.Last());
                    tile.ExpectedChannelCount = channelCount;
                    tile.MinTiffFileSize = minTiffSize;

                    return tile;
                }
            }

            return null;
        }
        public bool RemoveTile(Tile tile)
        {
            foreach (TileDay day in Days)
            {
                if (day.RemoveTile(tile))
                    return true;
            }

            return false;
        }
        private void ObserveIncomplete(Tile tile, bool isRemoval = false)
        {
            if ((tile.IsComplete || isRemoval) && _incompleteTiles.ContainsKey(tile.Id))
            {
                Tile unused;

                if (_incompleteTiles.TryRemove(tile.Id, out unused))
                {
                    RaiseTileDataChanged(tile, TileStateChangeAction.Complete);
                    OnCollectionChangedRemove(IncompleteCollectionChanged, tile);
                }
            }
            else if (tile.IsEvaluated && !tile.IsComplete && !_incompleteTiles.ContainsKey(tile.Id))
            {
                if (_incompleteTiles.TryAdd(tile.Id, tile))
                {
                    RaiseTileDataChanged(tile, TileStateChangeAction.Incomplete);
                    OnCollectionChangedAdd(IncompleteCollectionChanged, tile);
                }
            }
        }
 public ThumbnailEventArgs(int index, Tile tile)
     : base()
 {
     Index = index;
     Tile = tile;
 }
        public bool RemoveTile(Tile tile)
        {
            if (!Tiles.Contains(tile))
                return false;

            tile.PropertyChanged -= Tile_Changed;

            _tiles.Remove(tile);

            ObserveIncomplete(tile, true);

            RaiseTileDataChanged(tile, TileStateChangeAction.Remove);
            OnCollectionChangedRemove(TileCollectionChanged, tile);

            return true;
        }
        public TileChangedEventArgs(Tile tile, TileStateChangeAction action)
        {
            _context = new TileChangedMonitorContext(tile, action);

            _context._day.Tile = tile;
        }
 public void QueueTiff(string file, Tile tile, int channelIndex, bool generateThumbnail)
 {
     QueueTiff(new ChannelImageQueueItem() { FileName = file, Tile = tile, Channel = channelIndex, ShouldGenerateThumbnail = generateThumbnail });
 }
 public TileChangedDayContext(Tile tile)
 {
     Tile = tile;
 }
 public TileChangedMonitorContext(Tile tile, TileStateChangeAction action)
 {
     _day = new TileChangedDayContext(tile);
     _day.Action = action;
 }
        private bool ProcessTile(Tile tile)
        {
            if (this.IsEmerging && !tile.IsEvaluated)
            {
                Trace.TraceInformation("Processing emerging tile {0}.", tile.FullPath);
            }

            bool wasEvaluated = tile.IsEvaluated;

            if (tile.IsComplete)
            {
                Trace.TraceInformation("Skipping complete tile {0}.", tile.FullPath);
                return true;
            }

            // Check for removal
            if (wasEvaluated && !Directory.Exists(tile.FullPath))
            {
                if (tile.Group != null)
                {
                    tile.Group.RemoveTile(tile);
                }

                return true;
            }

            try
            {
                tile.BeginCoalescePropertyEvents();

                foreach (var file in Directory.GetFiles(tile.FullPath))
                {
                    switch (Path.GetExtension(file))
                    {
                        case ".acquisition":
                            {
                                if (!tile.HaveAcquisition)
                                    tile.EvaluateAcquisition(file);
                            }
                            break;
                        case ".microscope":
                            {
                                if (!tile.HaveMicroscope)
                                    tile.EvaluateMicroscope(file);
                            }
                            break;
                        case ".tif":
                            {
                                // Query frame count if asked for in the options and either:
                                //   1) This is an emerging worker and the tile has never been evaluated (the often-idle emerging queue is sometimes used
                                //      for other tasks such as re-evaluating incomplete tiles)
                                //   2) We aren't using implicit values for existing, or we haven't yet established an implicit value.
                                bool shouldQueryFrameCount = UserOptions.Default.QueryTiffMetadata && UserOptions.Default.QueryTiffFrameCount
                                    && ((IsEmerging && !wasEvaluated) || !UserOptions.Default.UseImplicitTIFFMetaData || !HaveImplicitFrameCount());

                                int channel = tile.EvaluateChannel(file, (UserOptions.Default.QueryTiffMetadata && !IsEmerging), shouldQueryFrameCount);

                                if (channel > -1)
                                {
                                    if (UserOptions.Default.UseImplicitTIFFMetaData)
                                    {
                                        // If using an implicit frame count we either
                                        // 1) Don't have one, just queried the current tile, and may now have a value to use moving forward
                                        // or
                                        // 2) Skipped b/c we already have a value and need to update the tile with the implicit version
                                        if (shouldQueryFrameCount)
                                        {
                                            ManageImplicitMetadata(tile.Contents.ImageContents[channel]);
                                        }
                                        else if (!IsEmerging && HaveImplicitFrameCount())
                                        {
                                            if (tile.Contents.ImageContents[channel].FileSize == ImplicitChannelFileSize)
                                            {
                                                ImageContent content = tile.Contents.ImageContents[channel];
                                                content.FrameCount = ImplicitChannelFrameCount;
                                                tile.SetImageContents(channel, content);
                                            }
                                        }
                                    }

                                    if (UserOptions.Default.QueryTiffContents && (IsEmerging || !UserOptions.Default.OnlyQueryEmergingTiffContents))
                                    {
                                        TiffEvaluateWorker queue = IsEmerging ? TiffEvaluateWorker.EmergingManager : TiffEvaluateWorker.ExistingManager;

                                        // Queue tiff file for mean pixel value and possibly thumbnail preview.  Be careful of already evaluated tiles
                                        // submitted to the "emerging" queue to take advantage of idleness.
                                        bool createThumbnail = (UserOptions.Default.ThumbnailsForExistingQueue || (IsEmerging && !wasEvaluated)) && (channel == ChannelForThumbnails);
                                        queue.QueueTiff(file, tile, channel, createThumbnail);
                                    }
                                }
                            }
                            break;
                    }
                }

                tile.IsEvaluated = true;

                tile.EndCoalescePropertyEvents();
            }
            catch (Exception e)
            {
                Trace.TraceInformation("Tile processing exception: {0}", e.Message);
            }

            return tile.IsComplete;
        }
 private void EvaluateTile(Tile tile)
 {
     try
     {
         // If failed to load or otherwise exists but is considered incomplete, put back in the queue to try again later.
         if (ProcessTile(tile))
             ProcessedCount++;
         else
             IncompleteQueue.Enqueue(tile);
     }
     catch (Exception e)
     {
         Trace.TraceInformation("An exception occurred during tile evaluation.  There may be an issue with the tile, but the worker will continue.\r\n\tException: {0}", e.Message);
         IncompleteQueue.Enqueue(tile);
     }
 }
        public bool RemoveTile(Tile tile)
        {
            foreach (var group in Groups)
            {
                if (group.RemoveTile(tile))
                    return true;
            }

            return false;
        }