示例#1
0
        /// <summary>
        /// Build the HTTP content for the request based on the parameters
        /// </summary>
        /// <returns>The request.</returns>
        public HttpContent BuildRequest(BlastRequestParameters blastParams)
        {
            if (string.IsNullOrWhiteSpace(blastParams.Database))
            {
                throw new ArgumentException("Database must be supplied.");
            }

            if (string.IsNullOrWhiteSpace(blastParams.Program))
            {
                throw new ArgumentException("Program must be supplied.");
            }

            if (blastParams.Sequences.Count == 0)
            {
                throw new ArgumentException("Must have at least one sequence.");
            }

            // Check that all sequences are same alphabet
            if (blastParams.Sequences.Count > 1)
            {
                ISequence primary = blastParams.Sequences[0];
                for (int i = 1; i < blastParams.Sequences.Count; i++)
                {
                    if (!Alphabets.CheckIsFromSameBase(primary.Alphabet, blastParams.Sequences[i].Alphabet))
                    {
                        throw new ArgumentException("Sequences must all share the same base alphabet.");
                    }
                }
            }

            var data = new List <KeyValuePair <string, string> > {
                this.CreateKVP("CMD", "Put")
            };

            if (blastParams.Program == BlastProgram.Megablast)
            {
                data.Add(this.CreateKVP("PROGRAM", BlastProgram.Blastn));
                data.Add(this.CreateKVP("MEGABLAST", "ON"));
            }
            else
            {
                data.Add(this.CreateKVP("PROGRAM", blastParams.Program));
            }
            data.Add(this.CreateKVP("DATABASE", blastParams.Database));

            data.AddRange(blastParams.ExtraParameters);

            // Add the sequences.
            StringBuilder sb = new StringBuilder();

            foreach (var seq in blastParams.Sequences)
            {
                sb.Append(seq.ConvertToString());
            }

            data.Add(this.CreateKVP("QUERY", sb.ToString()));

            return(new FormUrlEncodedContent(data));
        }
示例#2
0
        /// <summary>
        /// Executes the BLAST search request.
        /// </summary>
        /// <param name="bp">Parameters</param>
        /// <param name="token">Cancellation token</param>
        /// <returns>XML data as a string</returns>
        public async Task<Stream> ExecuteAsync(BlastRequestParameters bp, CancellationToken token)
        {
            if (string.IsNullOrWhiteSpace(this.EndPoint))
                throw new ArgumentException("EndPoint must be set.");
            if (this.TimeoutInSeconds <= 0)
                throw new ArgumentException("Timeout must be >= 1");

            this.Log("Posting request to {0}", this.EndPoint);

            var content = this.BuildRequest(bp);
            this.Log(await content.ReadAsStringAsync());

            var client = new HttpClient();
            var result = await client.PostAsync(this.EndPoint, content, token);
            result.EnsureSuccessStatusCode();

            this.Log("Reading initial response - looking for Request Id.");
            string response = await result.Content.ReadAsStringAsync();
            if (string.IsNullOrWhiteSpace(response))
            {
                this.Log("Failed to find Request Id in: {0}", response);
                throw new HttpRequestException("No data returned.");
            }

            // Get the request ID and Estimated time to completion
            Regex ridExpr = new Regex(@"QBlastInfoBegin\s+RID = (\w+)\s+RTOE = (\w+)");
            var matches = ridExpr.Matches(response);
            if (matches.Count != 1
                || matches[0].Groups.Count != 3)
                throw new HttpRequestException("Unrecognized format returned, no Request Id located.");

            var match = matches[0];
            string rid = match.Groups[1].Value;
            string ttl = match.Groups[2].Value;

            this.Log("RequestId: {0}, Estimated Time to Completion: {1} secs.", rid, ttl);

            // Calculate our max time.
            DateTime timeoutValue = DateTime.Now.AddSeconds(this.TimeoutInSeconds);

            // Get the time to completion - we'll wait that long before
            // starting our polling.
            int seconds;
            if (Int32.TryParse(ttl, out seconds)) 
            {
                seconds = Math.Min(seconds, this.TimeoutInSeconds);
                this.Log("Waiting for {0} seconds", seconds);
                await Task.Delay(seconds * 1000, token);
            }

            Regex statusExpr = new Regex(@"QBlastInfoBegin\s+Status=(\w+)");

            // Begin our polling operation; this isn't the most efficient, but NCBI doesn't
            // provide any other mechanism.
            while (true) {
                // Check on our request.
                this.Log("Checking on request {0}", rid);
                response = await client.GetStringAsync(
                    string.Format("{0}?CMD=Get&FORMAT_OBJECT=SearchInfo&RID={1}", this.EndPoint, rid));
                var statusMatch = statusExpr.Matches(response);
                if (statusMatch.Count == 1) {
                    string state = statusMatch[0].Groups[1].Value;
                    this.Log("Processing response: {0}", response);
                    if (state == "FAILED")
                        throw new Exception("Search " + rid + " failed; please report to [email protected].");
                    if (state == "UNKNOWN")
                        throw new OperationCanceledException("Search " + rid + " expired.");
                    if (state == "READY") {
                        Regex hasHitsExpr = new Regex(@"QBlastInfoBegin\s+ThereAreHits=yes");
                        if (!hasHitsExpr.IsMatch(response)) 
                        {
                            return null; // no hits
                        }
                        break;
                    }
                }
                else
                {
                    this.Log("Did not find Status in response: {0}", response);
                }

                // Go to sleep and try again.
                this.Log("Waiting 2 seconds.", response);
                await Task.Delay(2000, token);

                // Check at the end so we get at least one attempt.
                token.ThrowIfCancellationRequested();

                // Check the timeout value.
                if (DateTime.Now > timeoutValue)
                    throw new OperationCanceledException("Timeout value exceeded.");
            }

            // Retrieve the response.
            this.Log("Retrieving final response for Request Id {0}", rid);
            return await client.GetStreamAsync(
                string.Format("{0}?CMD=Get&FORMAT_TYPE=XML&RID={1}", this.EndPoint, rid));
        }
示例#3
0
        /// <summary>
        /// Build the HTTP content for the request based on the parameters
        /// </summary>
        /// <returns>The request.</returns>
        public HttpContent BuildRequest(BlastRequestParameters blastParams)
        {
            if (string.IsNullOrWhiteSpace(blastParams.Database))
                throw new ArgumentException("Database must be supplied.");

            if (string.IsNullOrWhiteSpace(blastParams.Program))
                throw new ArgumentException("Program must be supplied.");

            if (blastParams.Sequences.Count == 0)
                throw new ArgumentException("Must have at least one sequence.");

            // Check that all sequences are same alphabet
            if (blastParams.Sequences.Count > 1)
            {
                ISequence primary = blastParams.Sequences[0];
                for (int i = 1; i < blastParams.Sequences.Count; i++)
                {
                    if (!Alphabets.CheckIsFromSameBase(primary.Alphabet, blastParams.Sequences[i].Alphabet))
                        throw new ArgumentException("Sequences must all share the same base alphabet.");
                }
            }

            var data = new List<KeyValuePair<string, string>> { this.CreateKVP("CMD", "Put") };
            if (blastParams.Program == BlastProgram.Megablast)
            {
                data.Add(this.CreateKVP("PROGRAM", BlastProgram.Blastn));
                data.Add(this.CreateKVP("MEGABLAST", "ON"));
            }
            else
                data.Add(this.CreateKVP("PROGRAM", blastParams.Program));
            data.Add(this.CreateKVP("DATABASE", blastParams.Database));

            data.AddRange(blastParams.ExtraParameters);

            // Add the sequences.
            StringBuilder sb = new StringBuilder();
            foreach (var seq in blastParams.Sequences)
                sb.Append(seq.ConvertToString());

            data.Add(this.CreateKVP("QUERY", sb.ToString()));

            return new FormUrlEncodedContent(data);
        }
示例#4
0
 /// <summary>
 /// Initializes a new instance of the WebServiceInputEventArgs class
 /// </summary>
 /// <param name="serviceName">Web service name</param>
 /// <param name="parameters">the selected service parameters</param>
 public WebServiceInputEventArgs(string serviceName, BlastRequestParameters parameters)
 {
     this.ServiceName = serviceName;
     this.Parameters = parameters;
 }
示例#5
0
        /// <summary>
        /// This event is fired on click of the submit button on the dialog,
        /// this would validate the parameters accordingly and on success would initiate adding
        /// of the parameters to the given service parameters
        /// </summary>
        /// <param name="sender">submit button</param>
        /// <param name="e">Event Data</param>
        private void OnBtnSubmitClick(object sender, RoutedEventArgs e)
        {
            var serviceParam = new BlastRequestParameters();
            bool valid = this.AddServiceParams(ref serviceParam, this.firstStk);

            if (valid)
                valid = this.AddServiceParams(ref serviceParam, this.secondStk);

            if (valid)
                valid = this.AddServiceParams(ref serviceParam, this.thirdColumnParams);

            if (valid)
                valid = this.AddServiceParams(ref serviceParam, this.commonParamsStk);

            if (valid && this.serviceParams.Visibility == Visibility.Visible)
                valid = this.AddServiceParams(ref serviceParam, this.serviceParams);

            if (valid)
            {
                var args = new WebServiceInputEventArgs(this.serviceName, serviceParam);
                this.WebServiceInputArgs = args;
                if (this.ExecuteSearch != null)
                {
                    this.ExecuteSearch.Invoke(this, args);
                    this.Close();
                }
                else
                    this.Close();
            }
        }
示例#6
0
        /// <summary>
        /// This method validates the gap cost input
        /// and on success adds the gap cost to the service parameters
        /// </summary>
        /// <param name="serviceParam">service param to add the param</param>
        /// <returns>whether the gap cost was valid and added or not</returns>
        private bool CheckNAddGapCostField(ref BlastRequestParameters serviceParam)
        {
            int number;
            if (!Int32.TryParse(this.gapOpenTxt.Text, out number) && number != 0)
            {
                MessageBox.Show(
                    Properties.Resources.INVALID_TEXT + GAPCOSTS + Properties.Resources.VALUE_TEXT,
                    Properties.Resources.CAPTION,
                    MessageBoxButton.OK,
                    MessageBoxImage.Error);
                return false;
            }

            if (!Int32.TryParse(this.gapOpenTxt.Text, out number) && number != 0)
            {
                MessageBox.Show(
                    Properties.Resources.INVALID_TEXT + GAPCOSTS + Properties.Resources.VALUE_TEXT,
                    Properties.Resources.CAPTION,
                    MessageBoxButton.OK,
                    MessageBoxImage.Error);
                return false;
            }

            serviceParam.ExtraParameters.Add(GAPCOSTS, this.gapOpenTxt.Text + " " + this.gapExtendedTxt.Text);

            return true;
        }
示例#7
0
        /// <summary>
        /// This method would add service params to the given service param,
        /// The would get all the children items from the stack panel and would read the param values
        /// and add to the search service parameters.
        /// </summary>
        /// <param name="serviceParam">Service parameter</param>
        /// <param name="panel">Stack panel</param>
        /// <returns>returns whether the given param was added or not</returns>
        private bool AddServiceParams(ref BlastRequestParameters serviceParam, StackPanel panel)
        {
            bool valid = true;

            foreach (UIElement element in panel.Children)
            {
                var txtBox = element as TextBox;
                var lstBox = element as ListBox;
                var chkbox = element as CheckBox;
                if (txtBox != null)
                {
                    valid = AddValidServiceParams(ref serviceParam, txtBox.Tag.ToString(), txtBox.Text);
                }
                else if (lstBox != null)
                {
                }
                else if (chkbox != null)
                {
                }
                else
                {
                    var combo = element as ComboBox;
                    if (combo != null && combo.Visibility == Visibility.Visible)
                    {
                        valid = AddValidServiceParams(
                            ref serviceParam,
                            combo.Tag.ToString(),
                            combo.SelectedValue.ToString());
                    }
                }

                if (!valid)
                {
                    break;
                }
            }

            // checks the gap cost field
            if (valid)
            {
                valid = this.CheckNAddGapCostField(ref serviceParam);
            }

            return valid;
        }
示例#8
0
 /// <summary>
 /// This method would validate and add the params to the service
 /// parameters for the requested search
 /// </summary>
 /// <param name="serviceParam">Service parameter</param>
 /// <param name="paramName">Param name</param>
 /// <param name="paramValue">Param value</param>
 /// <returns>whether the parameter was valid</returns>
 private static bool AddValidServiceParams(ref BlastRequestParameters serviceParam, string paramName, string paramValue)
 {
     return false;
 }
示例#9
0
        /// <summary>
        /// Executes the BLAST search request.
        /// </summary>
        /// <param name="bp">Parameters</param>
        /// <param name="token">Cancellation token</param>
        /// <returns>XML data as a string</returns>
        public async Task <Stream> ExecuteAsync(BlastRequestParameters bp, CancellationToken token)
        {
            if (string.IsNullOrWhiteSpace(this.EndPoint))
            {
                throw new ArgumentException("EndPoint must be set.");
            }
            if (this.TimeoutInSeconds <= 0)
            {
                throw new ArgumentException("Timeout must be >= 1");
            }

            this.Log("Posting request to {0}", this.EndPoint);

            var content = this.BuildRequest(bp);

            this.Log(await content.ReadAsStringAsync());

            var client = new HttpClient();
            var result = await client.PostAsync(this.EndPoint, content, token);

            result.EnsureSuccessStatusCode();

            this.Log("Reading initial response - looking for Request Id.");
            string response = await result.Content.ReadAsStringAsync();

            if (string.IsNullOrWhiteSpace(response))
            {
                this.Log("Failed to find Request Id in: {0}", response);
                throw new HttpRequestException("No data returned.");
            }

            // Get the request ID and Estimated time to completion
            Regex ridExpr = new Regex(@"QBlastInfoBegin\s+RID = (\w+)\s+RTOE = (\w+)");
            var   matches = ridExpr.Matches(response);

            if (matches.Count != 1 ||
                matches[0].Groups.Count != 3)
            {
                throw new HttpRequestException("Unrecognized format returned, no Request Id located.");
            }

            var    match = matches[0];
            string rid   = match.Groups[1].Value;
            string ttl   = match.Groups[2].Value;

            this.Log("RequestId: {0}, Estimated Time to Completion: {1} secs.", rid, ttl);

            // Calculate our max time.
            DateTime timeoutValue = DateTime.Now.AddSeconds(this.TimeoutInSeconds);

            // Get the time to completion - we'll wait that long before
            // starting our polling.
            int seconds;

            if (Int32.TryParse(ttl, out seconds))
            {
                seconds = Math.Min(seconds, this.TimeoutInSeconds);
                this.Log("Waiting for {0} seconds", seconds);
                await Task.Delay(seconds * 1000, token);
            }

            Regex statusExpr = new Regex(@"QBlastInfoBegin\s+Status=(\w+)");

            // Begin our polling operation; this isn't the most efficient, but NCBI doesn't
            // provide any other mechanism.
            while (true)
            {
                // Check on our request.
                this.Log("Checking on request {0}", rid);
                response = await client.GetStringAsync(
                    string.Format("{0}?CMD=Get&FORMAT_OBJECT=SearchInfo&RID={1}", this.EndPoint, rid));

                var statusMatch = statusExpr.Matches(response);
                if (statusMatch.Count == 1)
                {
                    string state = statusMatch[0].Groups[1].Value;
                    this.Log("Processing response: {0}", response);
                    if (state == "FAILED")
                    {
                        throw new Exception("Search " + rid + " failed; please report to [email protected].");
                    }
                    if (state == "UNKNOWN")
                    {
                        throw new OperationCanceledException("Search " + rid + " expired.");
                    }
                    if (state == "READY")
                    {
                        Regex hasHitsExpr = new Regex(@"QBlastInfoBegin\s+ThereAreHits=yes");
                        if (!hasHitsExpr.IsMatch(response))
                        {
                            return(null); // no hits
                        }
                        break;
                    }
                }
                else
                {
                    this.Log("Did not find Status in response: {0}", response);
                }

                // Go to sleep and try again.
                this.Log("Waiting 2 seconds.", response);
                await Task.Delay(2000, token);

                // Check at the end so we get at least one attempt.
                token.ThrowIfCancellationRequested();

                // Check the timeout value.
                if (DateTime.Now > timeoutValue)
                {
                    throw new OperationCanceledException("Timeout value exceeded.");
                }
            }

            // Retrieve the response.
            this.Log("Retrieving final response for Request Id {0}", rid);
            return(await client.GetStreamAsync(
                       string.Format("{0}?CMD=Get&FORMAT_TYPE=XML&RID={1}", this.EndPoint, rid)));
        }