public IImageProcessor GetImageProcessor(IRobot robot, IProcessingInfo processingInfo) { IPlateInfo plateInfo = _pip.GetPlateInfo(robot, processingInfo.PlateID); IPlateType plateType = _pip.GetPlateType(robot, plateInfo.PlateTypeID); return(new ImageProcessor2(robot, processingInfo, plateInfo, plateType)); }
/// <summary> /// Initializes a new instance of the <see cref="Plate"/> class. /// </summary> /// <param name="type">The type.</param> /// <param name="content">The content.</param> public Plate(IPlateType type, Well[] content = null) { if (type == null || !type.Format.IsValid()) { throw new ArgumentException("Must contain valid plate format", "type"); } if (content == null) { Content = new Well[type.Format.Width * type.Format.Height]; // fill in Content for (int i = 0; i < Content.Length; i++) { Content[i] = new Well(i / type.Format.Width, i % type.Format.Width); } } else { if (content.Length != type.Format.Width * type.Format.Height) throw new ArgumentException("Content doesn't match provided format", "content"); Content = content; } Created = LastChanged = DateTime.Now; Type = type; }
/// <summary> /// Construct an IImageProcessor instance for the specified IRobot and IProcessingInfo. /// </summary> /// <param name="robot">The Robot that took the images to be processed by this IImageProcessor instance</param> /// <param name="processingInfo">The description of the images to be processed by this IImageProcessor instance</param> public ImageProcessor2(IRobot robot, IProcessingInfo processingInfo, IPlateInfo plateInfo, IPlateType plateType) { // Get Logger. _log = LogManager.GetLogger(this.GetType()); _dateImaged = DateTime.MinValue; _lightPath = 0; _robot = robot; _processingInfo = processingInfo; _plateInfo = plateInfo; _plateType = plateType; _captureInfo = null; SetRegionName(_processingInfo.RegionID); SetProfileName(_processingInfo.ProfileID); _log.Info( "DropNumber=" + processingInfo.DropNumber + ";ImagingID=\"" + processingInfo.ImagingID + "\"" + ";PlatedID=\"" + processingInfo.PlateID + "\"" + ";ProfileID=\"" + processingInfo.ProfileID + "\"" + ";RegionID=\"" + processingInfo.RegionID + "\"" + ";RegionType=" + processingInfo.RegionType.ToString() + ";WellNumber=" + processingInfo.WellNumber + ";Robot.Name=\"" + _robot.Name + "\""); }
/// <summary> /// Convert WellNumber to standard row/col reference, eg 1 => A01. /// </summary> /// <param name="plateType">The plateType to use for the conversion</param> /// <param name="wellNumber">The wellNumber to convert</param> /// <returns>The string representation of wellNumber for the specified plateType</returns> /// <remarks> /// <c>WellNumber</c> definition: /// <code> /// |-X----------------- /// Y 0,0 /// | 1 2 3 4 /// | /------------ /// | / | /// | A | 1 2 3 4 | /// | | | /// | B | 5 6 7 8 | /// /// 1, 2, 3, 4 are columns. A, B, C are rows. /// /// WellNumber = starts at one and proceeds along rows and columns /// X = distance along the columns /// Y = distance along the rows /// Z = distance down into the plate /// Width = size in the X direction /// Height = size in the Y direction /// </code> /// /// TODO: Handle larger plates /// </remarks> public static string WellNumberToString(IPlateType plateType, int wellNumber) { if (null == plateType) { throw new NullReferenceException("plateType must not be null"); } if ((1 > wellNumber) || (wellNumber > (plateType.NumRows * plateType.NumColumns))) { throw new InvalidOperationException("Invalid wellNumber: " + wellNumber + " for " + plateType.NumColumns + " x " + plateType.NumRows + " plate"); } if (26 < plateType.NumRows) { throw new NotImplementedException("Cannot handle plates with more the 26 rows"); } int zeroBasedWellNumber = wellNumber - 1; // Zero-based row (ie 0 = A, 1 = B, etc.) int row = (int)(zeroBasedWellNumber / plateType.NumColumns); // Zero-based col int col = zeroBasedWellNumber % plateType.NumColumns; // Build string return(String.Format("{0}{1:D2}", (char)(row + 65), col + 1)); }
private void btnGetPlateType_Click(object sender, System.EventArgs e) { // Cursor to wait this.Cursor = Cursors.WaitCursor; IPlateType pt = pip.GetPlateType(getRobot(), getBarcode()); txtOutput.Text = ""; if (pt == null) { txtOutput.AppendText("GetPlateType(robot, plateTypeID) returned null"); } else { txtOutput.AppendText("ID = " + pt.ID + "\r\n"); txtOutput.AppendText("Name = " + pt.Name + "\r\n"); txtOutput.AppendText("NumColumns = " + pt.NumColumns + "\r\n"); txtOutput.AppendText("NumDrops = " + pt.NumDrops + "\r\n"); txtOutput.AppendText("NumRows = " + pt.NumRows + "\r\n"); } // Cursor to default this.Cursor = Cursors.Default; }
/// <summary> /// This method is intended to cause any resources that are no /// longer necessary to be released /// </summary> void IDisposable.Dispose() { _regionName = null; _profileName = null; _captureInfo = null; _robot = null; _processingInfo = null; _plateInfo = null; _plateType = null; }
public void GetFilenameTest1() { IImageInfo imageInfo = null; // TODO: Initialize to an appropriate value IProcessingInfo processingInfo = null; // TODO: Initialize to an appropriate value IPlateInfo plateInfo = null; // TODO: Initialize to an appropriate value IPlateType plateType = null; // TODO: Initialize to an appropriate value string expected = string.Empty; // TODO: Initialize to an appropriate value string actual; actual = FileUtils.GetFilename(imageInfo, processingInfo, plateInfo, plateType); Assert.AreEqual(expected, actual); Assert.Inconclusive("Verify the correctness of this test method."); }
/// <summary> /// Called once per lifetime before any calls to SetImageInfo. /// </summary> /// <param name="captureInfo">The ICaptureInfo to use</param> public void SetCaptureInfo(ICaptureInfo captureInfo) { _captureInfo = captureInfo; _log.Info("SetCaptureInfo(captureInfo=" + CaptureInfo.ToString(captureInfo) + ")"); ICaptureInfoExtendedProperties iceip = captureInfo as ICaptureInfoExtendedProperties; if (null != iceip) { _log.Debug("captureInfo is an ICaptureInfoExtendedProperties!"); this._dateImaged = iceip.DateImaged.ToUniversalTime(); this._lightPath = iceip.LightPath; this._plateInfo = iceip.PlateInfo; this._plateType = iceip.PlateType; } else { // JMD Had to change the default //int lightPath = 0; int lightPath = 1; foreach (IProperty p in _captureInfo.Properties) { //_log.Info(p.Name + "=" + p.Value); // JMD Broken as of 31/03/2011 //if (p.Name.EndsWith("UV")) //{ // lightPath = 1; // break; //} // Try again looking for a visible-only property if (("ImagingCondenser".Equals(p.Name)) || ("ImagingPolarizer".Equals(p.Name))) { lightPath = 0; break; } } _lightPath = lightPath; } }
protected virtual void Dispose(bool disposing) { if (!this.disposed) { if (disposing) { // dispose managed resources } // free native resources _regionName = null; _profileName = null; _captureInfo = null; _robot = null; _processingInfo = null; _plateInfo = null; _plateType = null; disposed = true; } }
/* * Added in Formulatrix.Integrations.ImagerLink.dll v2.0.0.73 (RockImager v2.0.3.18), * which is supposed to be more recent than v2.0.1.136 (RockImager v2.0.1.136). */ /// <summary> /// Gets an <c>ICapturePointList</c> to image for this plateID on the specified <c>imagingID</c>. /// </summary> /// <param name="robot"></param> /// <param name="plateID"></param> /// <param name="imagingID">The imaging ID started for this run.</param> /// <param name="includeOverview"></param> /// <param name="userSelectionCaptureProfileID"></param> /// <returns></returns> /// <remarks> /// Added in Formulatrix.Integrations.ImagerLink.dll v2.0.0.73 (RockImager v2.0.3.18), /// which is supposed to be more recent than v2.0.1.136 (RockImager v2.0.1.136). /// </remarks> public ICapturePointList GetCapturePoints(Formulatrix.Integrations.ImagerLink.IRobot robot, string plateID, string imagingID, bool includeOverview, int userSelectionCaptureProfileID) { // TODO: Add CaptureProvider.GetCapturePoints implementation //return null; if (_log.IsInfoEnabled) { _log.Info("Called ICaptureProvider.GetCapturePoints(" + Robot.ToString(robot) + ", \"" + plateID + "\", \"" + imagingID + "\", " + includeOverview + ", " + userSelectionCaptureProfileID + ")"); } CapturePointList capturePointList = null; // If 0 then it is a scheduled imaging, need to find the inspection type (light path) if (userSelectionCaptureProfileID == 0) { userSelectionCaptureProfileID = GetLightPathForScheduledImaging(imagingID); } IPlateType plateType = _pip.GetPlateType(robot, _pip.GetPlateInfo(robot, plateID).PlateTypeID); int[] sampleLocations = GetSampleLocations(plateID); // OPPF Vis if (1 == userSelectionCaptureProfileID) { _log.Info("Returning ICapturePointList with CapturePoints for specific drops to be imaged, with a null ICaptureProfile (Should assume visible LightPath)"); capturePointList = new CapturePointList(); CapturePoint[] capturePoints = GetCapturePointsDetails(sampleLocations, plateType, null); capturePointList.SetCapturePoints(capturePoints); } // OPPF UV else if (2 == userSelectionCaptureProfileID) { _log.Info("Returning ICapturePointList with PlateCaptureProfile and CapturePoints set to an ICaptureProfile with one IProperty of \"LightPath\" = \"1\""); // Create the property array containing the UV LightPath property IProperty[] properties = new global::OPPF.Integrations.ImagerLink.Property[1]; properties[0] = new global::OPPF.Integrations.ImagerLink.Property("LightPath", "1"); // Create a new CaptureProfile and apply the UV LightPath property CaptureProfile captureProfile = new CaptureProfile(); captureProfile.SetProfileID("2"); captureProfile.SetProperties(properties); // Create the array of capture profiles to be used for each drop - in this case only one CaptureProfile[] captureProfiles = new CaptureProfile[1]; captureProfiles[0] = captureProfile; // Get specific well and drop numbers to be imaged CapturePoint[] capturePoints = GetCapturePointsDetails(sampleLocations, plateType, captureProfiles); // Create the CapturePointList and set the PlateCaptureProfile and CapturePoints // NB I don't think RockImager actually uses the PlateCaptureProfile capturePointList = new CapturePointList(); capturePointList.SetPlateCaptureProfile(captureProfile); capturePointList.SetCapturePoints(capturePoints); } // OPPF Teach 1 else if (3 == userSelectionCaptureProfileID) { _log.Info("Returning ICapturePointList with PlateCaptureProfile and CapturePoints set to an ICaptureProfile that only images the corners"); // Create the property array containing the UV LightPath property IProperty[] properties = new global::OPPF.Integrations.ImagerLink.Property[1]; properties[0] = new global::OPPF.Integrations.ImagerLink.Property("LightPath", "0"); // Create a new CaptureProfile and apply the UV LightPath property CaptureProfile captureProfile = new CaptureProfile(); captureProfile.SetProfileID("3"); captureProfile.SetProperties(properties); // Create the array of capture profiles to be used for each drop - in this case only one CaptureProfile[] captureProfiles = new CaptureProfile[1]; captureProfiles[0] = captureProfile; // Create a CapturePoint for each drop using RockImager's default drop position and the vis LightPath // TODO: Get number of wells and drops from plate type CapturePoint[] capturePoints = new CapturePoint[4]; capturePoints[0] = new CapturePoint(1, 1, captureProfiles, null, null, "1", RegionType.Drop); // A1 capturePoints[1] = new CapturePoint(12, 1, captureProfiles, null, null, "1", RegionType.Drop); // A12 capturePoints[2] = new CapturePoint(85, 1, captureProfiles, null, null, "1", RegionType.Drop); // H1 capturePoints[3] = new CapturePoint(96, 1, captureProfiles, null, null, "1", RegionType.Drop); // H12 // Create the CapturePointList and set the PlateCaptureProfile and CapturePoints // NB I don't think RockImager actually uses the PlateCaptureProfile capturePointList = new CapturePointList(); capturePointList.SetPlateCaptureProfile(captureProfile); capturePointList.SetCapturePoints(capturePoints); } // OPPF Teach 1-Full - Just to allow special handling in the IImageProcessor else if (4 == userSelectionCaptureProfileID) { _log.Info("Returning ICapturePointList with PlateCaptureProfile and CapturePoints set to an ICaptureProfile that only images the corners"); // Create the property array containing the UV LightPath property IProperty[] properties = new global::OPPF.Integrations.ImagerLink.Property[1]; properties[0] = new global::OPPF.Integrations.ImagerLink.Property("LightPath", "0"); // Create a new CaptureProfile and apply the UV LightPath property CaptureProfile captureProfile = new CaptureProfile(); captureProfile.SetProfileID("4"); captureProfile.SetProperties(properties); // Create the array of capture profiles to be used for each drop - in this case only one CaptureProfile[] captureProfiles = new CaptureProfile[1]; captureProfiles[0] = captureProfile; // Create a CapturePoint for each drop using RockImager's default drop position and the vis LightPath // TODO: Get number of wells and drops from plate type int wells = 96; CapturePoint[] capturePoints = new CapturePoint[wells]; for (int i = 0; i < wells; i++) { // TODO: Loop over drops - currently assumes one drop per well capturePoints[i] = new CapturePoint(i + 1, 1, captureProfiles, null, null, "1", RegionType.Drop); } // Create the CapturePointList and set the PlateCaptureProfile and CapturePoints // NB I don't think RockImager actually uses the PlateCaptureProfile capturePointList = new CapturePointList(); capturePointList.SetPlateCaptureProfile(captureProfile); capturePointList.SetCapturePoints(capturePoints); } return(capturePointList); }
/// <summary> /// Returns specific drop locations to be imaged along with light path info as an array of CapturePoint objects /// </summary> /// <param name="sampleLocations"></param> /// <param name="plateType"></param> /// <param name="captureProfiles"></param> /// <returns>CapturePoint array used by the GetCapturePoints method</returns> private CapturePoint[] GetCapturePointsDetails(int[] sampleLocations, IPlateType plateType, CaptureProfile[] captureProfiles) { CapturePoint[] capturePoints = null; int plateWells = plateType.NumRows * plateType.NumColumns; int plateDrops = plateType.NumDrops; int totalDrops = plateWells * plateDrops; // If there are specific drops we only want to image those (there should be really, even if it's every drop) if (sampleLocations != null && sampleLocations.Length > 0) { _log.Info("Received " + sampleLocations.Length + " locations, registering CapturePoints..."); capturePoints = new CapturePoint[sampleLocations.Length]; for (int i = 0; i < sampleLocations.Length; i++) { // ISPyB only stores drop numbers from the point view of 'total drops' e.g. 1-192 for a 96 well 2 drop plate // Therefore we need to figure out which specific well number and drop number to pass to RockImager e.g. well 2 drop 1 int location = sampleLocations[i]; int div = location / plateDrops; int mod = location % plateDrops; int well = 0; int drop = 0; switch (plateDrops) { case 1: well = location; drop = 1; break; default: if (mod == 0) { well = div; drop = plateDrops; } else { well = ++div; drop = mod; } break; } capturePoints[i] = new CapturePoint(well, drop, captureProfiles, null, null, "1", RegionType.Drop); _log.Info("CapturePoint(" + well + ", " + drop + ", " + ((captureProfiles != null) && (captureProfiles[0].Properties[0].Value).Equals("1") ? "UV," : "Visible,") + " null, null, " + "1, " + RegionType.Drop + ") registered"); } } // In theory we should never reach here because there should always be specified sample locations (even if it's every drop) but as a safe catch all we can image every drop (probably on error) else { _log.Error("No sample locations received! Registering CapturePoints for all drops..."); capturePoints = new CapturePoint[totalDrops]; int dropCounter = 1; int wellCounter = 1; for (int i = 0; i < totalDrops; i++) { // Loop over drops - track wells and drops independantly capturePoints[i] = new CapturePoint(wellCounter, dropCounter, captureProfiles, null, null, "1", RegionType.Drop); _log.Info("CapturePoint(" + wellCounter + ", " + dropCounter + ", " + ((captureProfiles != null) && (captureProfiles[0].Properties[0].Value).Equals("1") ? "UV," : "Visible,") + " null, null, " + "1, " + RegionType.Drop + ") registered"); if (dropCounter == plateDrops) { dropCounter = 1; wellCounter++; } else { dropCounter++; } } } return(capturePoints); }
/// <summary> /// This should result in %BARCODE-%WELL-%DROP-R%R%RTP%P-%IT[%II]-z%Z-%DATE-%TIME, eg: /// 441312000010-A01-2-R0DRP1-EF-z20-20100316-083621 /// 441312000010-A01-2-R0DRP1-FL1-z20-20100316-083621 /// </summary> /// <param name="imageInfo"></param> /// <param name="processingInfo"></param> /// <param name="plateInfo"></param> /// <param name="plateType"></param> /// <returns></returns> public static string GetFilename(IImageInfo imageInfo, IProcessingInfo processingInfo, IPlateInfo plateInfo, IPlateType plateType) { string filename = ""; filename += processingInfo.PlateID + "-"; filename += OPPF.Integrations.ImagerLink.PlateType.WellNumberToString(plateType, processingInfo.WellNumber) + "-"; filename += processingInfo.DropNumber + "-"; filename += "R" + processingInfo.RegionID; // Usually 0 switch (processingInfo.RegionType) // Usually Drop { case RegionType.Drop: filename += "DR"; break; case RegionType.Overview: filename += "OV"; break; case RegionType.RegionOfInterest: filename += "RI"; break; } filename += "P" + processingInfo.ProfileID + "-"; // Usually 1 switch (imageInfo.ImageType) { case ImageType.BestFocus: filename += "BF"; break; case ImageType.DropLocation: filename += "DL"; break; case ImageType.ExtendedFocus: filename += "EF"; break; case ImageType.FocusLevel: filename += "FL" + imageInfo.ImageIndex; break; } if (imageInfo.IsZNull) { filename += "-zN-"; } else { filename += "-z" + System.Convert.ToInt32(imageInfo.Z) + "-"; } // Assuming ImagingID is plateID-DATE-TIME format.... (with no dashes in the plateID!) filename += processingInfo.ImagingID.Remove(0, processingInfo.ImagingID.IndexOf("-") + 1); return(filename); }