NCBI C++ ToolKit
compare_with_biosample.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: compare_with_biosample.cpp 47573 2023-10-03 14:50:44Z asztalos $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Igor Filippov
27  */
28 #include <ncbi_pch.hpp>
29 #include <corelib/ncbi_system.hpp>
30 
33 
37 #include <objmgr/seqdesc_ci.hpp>
38 #include <objmgr/util/sequence.hpp>
40 
42 
47 
48 
51 
56 
57 #include <wx/msgdlg.h>
58 #include <wx/filedlg.h>
59 #include <wx/filename.h>
60 #include <wx/dir.h>
61 #include <wx/scrolwin.h>
62 #include <sstream>
63 
66 
67 IMPLEMENT_DYNAMIC_CLASS( CCompareWithBiosample, wxFrame )
68 
69 BEGIN_EVENT_TABLE( CCompareWithBiosample, wxFrame )
71  EVT_BUTTON( wxID_CANCEL, CCompareWithBiosample::OnClickCancel )
82 
84 {
85  Init();
86 }
87 
88 // https://svn.ncbi.nlm.nih.gov/viewvc/toolkit/trunk/c%2B%2B/src/app/biosample_chk/
90  CSeq_entry_Handle seh, ICommandProccessor* cmdProcessor, bool all_records,
91  wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
92  : m_TopSeqEntry(seh), m_CmdProcessor(cmdProcessor), m_all_records(all_records)
93 {
94  x_LoadData();
95 
96  Init();
97  Create(parent, id, caption, pos, size, style);
99  LoadSettings();
100 }
101 
103 {
104  m_DiffVec.clear();
105  m_Cache.clear();
106  m_ids.clear();
107 
108  size_t num_processed;
109  vector<string> unprocessed_ids;
110  //bool use_dev_server(true); // DEBUG
111  bool use_dev_server(false);
112  bool compare_structured_comments(false);
113 
115  for (CBioseq_CI b_iter(m_TopSeqEntry, CSeq_inst::eMol_na); b_iter; ++b_iter)
116  {
117  biosample_util::TBiosampleFieldDiffList diff_vec = biosample_util::GetBioseqDiffs(*b_iter, kEmptyStr, num_processed, unprocessed_ids, use_dev_server, compare_structured_comments, kEmptyStr, &cache);
118  for (auto diff : diff_vec)
119  {
120  string seq_id = diff->GetSequenceId();
121  string field = diff->GetFieldName();
122  string source = diff->GetSrcVal();
123  string sample = diff->GetPureSampleVal();
124  string sample_id = diff->GetBioSample();
125 
126  set<string> set_source, set_sample;
127  tie(set_source, set_sample) = m_DiffVec[{sample_id, field}][seq_id];
128  if (!source.empty())
129  set_source.insert(source);
130  if (!sample.empty())
131  set_sample.insert(sample);
132  m_DiffVec[{sample_id, field}][seq_id] = make_pair(set_source, set_sample);
133  }
134 
135  string label;
137  vector<CRef <CSeq_id> > id_list;
138  ITERATE(CBioseq_Handle::TId, it, b_iter->GetId())
139  {
140  CConstRef<CSeq_id> ir = (*it).GetSeqId();
141  if (ir->IsGenbank())
142  {
143  id = ir;
144  }
145  CRef<CSeq_id> ic(const_cast<CSeq_id *>(ir.GetPointer()));
146  id_list.push_back(ic);
147  }
148  if (!id)
149  {
150  id = FindBestChoice(id_list, CSeq_id::BestRank);
151  }
152  if (id)
153  {
154  id->GetLabel(&label);
155  m_ids[label] = id;
156  }
157 
158  if (!m_all_records)
159  break;
160  }
161 }
162 
163 bool CCompareWithBiosample::Create( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
164 {
165  SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
166  wxFrame::Create( parent, id, caption, pos, size, style );
167  wxVisualAttributes attr = wxPanel::GetClassDefaultAttributes();
168  if (attr.colBg != wxNullColour) {
169  SetOwnBackgroundColour(attr.colBg);
170  }
171  CreateControls();
172  if (GetSizer())
173  {
174  GetSizer()->SetSizeHints(this);
175  }
176  Centre();
177  return true;
178 }
179 
180 
182 {
183  SaveSettings();
184 }
185 
186 
187 /*!
188  * Member initialisation
189  */
190 
192 {
195  m_Grid=NULL;
196  m_GridPanel = NULL;
197  m_source_col = 0;
198  m_sample_col = 0;
199  m_field_col = 0;
200  m_sample_id_col = 0;
201  m_modified_sample = false;
202  m_modified_source = false;
204 }
205 
206 
208 {
209  CCompareWithBiosample* itemDialog1 = this;
210 
211  wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
212  itemDialog1->SetSizer(itemBoxSizer2);
213 
214  m_ScrolledWindow = new wxScrolledWindow(itemDialog1, wxID_ANY, wxDefaultPosition, wxSize(840, 870), wxHSCROLL| wxVSCROLL);
215  itemBoxSizer2->Add(m_ScrolledWindow, 1, wxGROW | wxALL, 0);
216 
217  m_ScrolledWindow->SetScrollbars(1, 1, 0, 0);
218 
219  wxBoxSizer* top_sizer = new wxBoxSizer(wxVERTICAL);
220  m_ScrolledWindow->SetSizer(top_sizer);
221 
222  m_GridPanelSizer = new wxBoxSizer(wxHORIZONTAL);
223  top_sizer->Add(m_GridPanelSizer, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
224 
225  if (m_DiffVec.empty())
226  {
227  wxMessageBox(wxT("No differences found for resolved Biosample IDs"), wxT("Info"), wxOK);
228  NCBI_THROW( CException, eUnknown, "No differences found for compare with Biosample" );
229  }
230 
232  if (values_table->GetNum_rows() < 1)
233  {
234  wxMessageBox(wxT("No differences found for resolved Biosample IDs"), wxT("Info"), wxOK);
235  NCBI_THROW( CException, eUnknown, "No differences found for compare with Biosample" );
236  }
237 
238  x_AddTablePanel(values_table);
239  wxArrayString itemChoiceStrings, itemChoiceStringsWritable;
240  int pos = 0;
241  ITERATE (CSeq_table::TColumns, it, values_table->GetColumns())
242  {
243  if (pos > 0)
244  {
245  if ((*it)->IsSetHeader() && (*it)->GetHeader().IsSetTitle() )
246  {
247  string title = (*it)->GetHeader().GetTitle();
248  if (!title.empty())
249  {
250  itemChoiceStrings.Add(wxString(title));
251  if (!IsReadOnlyColumn(title))
252  itemChoiceStringsWritable.Add(wxString(title));
253  }
254  }
255  }
256  pos++;
257  }
258 
259  wxBoxSizer* itemBoxSizer16 = new wxBoxSizer(wxHORIZONTAL);
260  top_sizer->Add(itemBoxSizer16, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 0);
261 
262  wxButton* itemButton24 = new wxButton(m_ScrolledWindow, ID_ADD_TO_SOURCE, _("+<<"), wxDefaultPosition, wxDefaultSize, 0 );
263  itemBoxSizer16->Add(itemButton24, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
264  if (ShowToolTips())
265  itemButton24->SetToolTip(_("Append to BioSource values"));
266 
267  wxButton* itemButton17 = new wxButton(m_ScrolledWindow, ID_COPY_TO_SOURCE, _("<<"), wxDefaultPosition, wxDefaultSize, 0 );
268  itemBoxSizer16->Add(itemButton17, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
269  if (ShowToolTips())
270  itemButton17->SetToolTip(_("Overwrite BioSource values"));
271 
272  wxButton* itemButton18 = new wxButton(m_ScrolledWindow, ID_SYNC, _("sync"), wxDefaultPosition, wxDefaultSize, 0 );
273  itemBoxSizer16->Add(itemButton18, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
274  if (ShowToolTips())
275  itemButton18->SetToolTip(_("Fill the blanks in either BioSample or BioSource values"));
276 
277  wxButton* itemButton19 = new wxButton(m_ScrolledWindow, ID_COPY_TO_SAMPLE, _(">>"), wxDefaultPosition, wxDefaultSize, 0 );
278  itemBoxSizer16->Add(itemButton19, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
279  if (ShowToolTips())
280  itemButton19->SetToolTip(_("Overwrite BioSample values"));
281 
282  wxButton* itemButton25 = new wxButton(m_ScrolledWindow, ID_ADD_TO_SAMPLE, _(">>+"), wxDefaultPosition, wxDefaultSize, 0 );
283  itemBoxSizer16->Add(itemButton25, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
284  if (ShowToolTips())
285  itemButton25->SetToolTip(_("Append to BioSample values"));
286 
287  wxBoxSizer* itemBoxSizer4 = new wxBoxSizer(wxHORIZONTAL);
288  top_sizer->Add(itemBoxSizer4, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
289 
290  m_StringConstraintPanel = new CStringConstraintSelect(m_ScrolledWindow, m_GridPanel, itemChoiceStrings, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
291  itemBoxSizer4->Add(m_StringConstraintPanel, 0, wxALIGN_TOP|wxALL|wxFIXED_MINSIZE, 0);
292 
293  wxBoxSizer* itemBoxSizer5 = new wxBoxSizer(wxHORIZONTAL);
294  top_sizer->Add(itemBoxSizer5, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
295 
296  m_AecrPanel = new CApplyEditconvertPanel(m_ScrolledWindow, m_GridPanel, itemChoiceStringsWritable, 0, true, wxID_ANY, wxDefaultPosition, wxSize(1000, 190));
297  itemBoxSizer5->Add(m_AecrPanel, 0, wxALIGN_TOP|wxALL|wxFIXED_MINSIZE, 1); // 1128, 219
298 
299  wxBoxSizer* itemBoxSizer13 = new wxBoxSizer(wxHORIZONTAL);
300  top_sizer->Add(itemBoxSizer13, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 0);
301 
302  wxButton* itemButton14 = new wxButton(m_ScrolledWindow, ID_UPDATE_BIOSOURCE, _("Update BioSource"), wxDefaultPosition, wxDefaultSize, 0 );
303  itemBoxSizer13->Add(itemButton14, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
304 
305  wxButton* itemButton20 = new wxButton(m_ScrolledWindow, ID_CREATE_BIOSAMPLE, _("Create Biosample Update"), wxDefaultPosition, wxDefaultSize, 0 );
306  itemBoxSizer13->Add(itemButton20, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
307 
308  wxButton* itemButton21 = new wxButton(m_ScrolledWindow, ID_MAKE_REPORT, _("Make Report"), wxDefaultPosition, wxDefaultSize, 0 );
309  itemBoxSizer13->Add(itemButton21, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
310 
311  m_RefreshButton = new wxButton(m_ScrolledWindow, ID_REFRESH_BIOSAMPLE, _("Refresh"), wxDefaultPosition, wxDefaultSize, 0);
312  itemBoxSizer13->Add(m_RefreshButton, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
314 
315  wxButton* itemButton23 = new wxButton(m_ScrolledWindow, ID_APIKEY_BIOSAMPLE, _("Get BioSample API Key"), wxDefaultPosition, wxDefaultSize, 0);
316  itemBoxSizer13->Add(itemButton23, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
317 
318  wxButton* itemButton15 = new wxButton(m_ScrolledWindow, wxID_CANCEL, _("Close"), wxDefaultPosition, wxDefaultSize, 0 );
319  itemBoxSizer13->Add(itemButton15, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
320 
321  m_ScrolledWindow->FitInside();
322 }
323 
325 {
326  m_GridPanelSizer->Clear(true);
327 
328  CRef<CSeq_table> choices = GetChoices(values_table);
329  int glyph_col = GetCollapsible();
330  m_GridPanel = new CSeqTableGridPanel(m_ScrolledWindow, values_table, choices, glyph_col);
331  m_GridPanelSizer->Add(m_GridPanel, 0, wxALIGN_TOP|wxALL, 5);
333  CSeqTableGrid *gridAdapter = new CSeqTableGrid(values_table);
334  m_Grid->SetTable(gridAdapter, true);
335  m_Grid->AutoSizeColumns();
336  int l_height = m_Grid->GetColLabelSize();
337  m_Grid->SetColLabelSize( 2 * l_height );
338 
339  int pos = 0;
340  ITERATE (CSeq_table::TColumns, it, values_table->GetColumns())
341  {
342  if (pos > 0)
343  {
344  if ((*it)->IsSetHeader() && (*it)->GetHeader().IsSetTitle() )
345  {
346  string title = (*it)->GetHeader().GetTitle();
347  if (IsReadOnlyColumn(title))
348  m_GridPanel->MakeColumnReadOnly(pos - 1, true);
349  }
350  }
351  pos++;
352  }
353 
354  if (glyph_col >= 0 && glyph_col+1 < m_Grid->GetNumberCols())
355  {
356  m_GridPanel->InitColumnCollapse(glyph_col+1);
357  }
358  Layout();
359  Fit();
360 }
361 
363 {
365  m_id_col->SetHeader().SetField_id(CSeqTable_column_info::eField_id_location_id);
366  m_id_col->SetHeader().SetTitle(kSequenceIdColLabel);
367 
368  CRef<CSeqTable_column> expand_col(new CSeqTable_column());
369  expand_col->SetHeader().SetTitle("");
370  expand_col->SetHeader().SetField_name("expand");
371  expand_col->SetData().SetString();
372 
374  name_col->SetHeader().SetTitle("Field");
375  name_col->SetHeader().SetField_name("field");
376  name_col->SetData().SetString();
377 
378  CRef<CSeqTable_column> source_col(new CSeqTable_column());
379  source_col->SetHeader().SetTitle("Source");
380  source_col->SetHeader().SetField_name("source");
381  source_col->SetData().SetString();
382 
383  CRef<CSeqTable_column> sample_col(new CSeqTable_column());
384  sample_col->SetHeader().SetTitle("Sample");
385  sample_col->SetHeader().SetField_name("Sample");
386  sample_col->SetData().SetString();
387 
388  CRef<CSeqTable_column> sample_id_col(new CSeqTable_column());
389  sample_id_col->SetHeader().SetTitle("Biosample Id");
390  sample_id_col->SetHeader().SetField_name("biosample_id");
391  sample_id_col->SetData().SetString();
392 
394  table->SetColumns().push_back(m_id_col);
395  table->SetColumns().push_back(expand_col);
396  table->SetColumns().push_back(name_col);
397  table->SetColumns().push_back(source_col);
398  table->SetColumns().push_back(sample_col);
399  table->SetColumns().push_back(sample_id_col);
400 
401  m_field_col = 1;
402  m_source_col = 2;
403  m_sample_col = 3;
404  m_sample_id_col = 4;
405  size_t num_rows = 0;
406  for (const auto &diff : m_DiffVec)
407  {
408  string field, sample_id;
409  tie(sample_id, field) = diff.first;
410  for (const auto &row : diff.second)
411  {
412  string seq_id = row.first;
413  set<string> set_source, set_sample;
414  tie(set_source, set_sample) = row.second;
415 
416  string source = NStr::Join(set_source, "|");
417  string sample = NStr::Join(set_sample, "|");
418 
419  CRef<CSeq_id> id;
420  if (m_ids.find(seq_id) != m_ids.end())
421  {
422  id.Reset(new CSeq_id);
423  id->Assign(*m_ids[seq_id]);
424  }
425  else
426  {
427  id.Reset(new CSeq_id(seq_id, CSeq_id::fParse_Default));
428  }
429 
430  m_id_col->SetData().SetId().push_back(id);
431  expand_col->SetData().SetString().push_back("");
432  name_col->SetData().SetString().push_back(field);
433  source_col->SetData().SetString().push_back(source);
434  sample_col->SetData().SetString().push_back(sample);
435  sample_id_col->SetData().SetString().push_back(sample_id);
436  ++num_rows;
437  }
438  }
439 
440  table->SetNum_rows(static_cast<CSeq_table::TNum_rows>(num_rows));
441 
442  return table;
443 }
444 
445 void CCompareWithBiosample::OnClickOk( wxCommandEvent& event )
446 {
447  if (!m_TopSeqEntry)
448  return;
449  CScope &scope = m_TopSeqEntry.GetScope();
451  Freeze();
452  int collapsed_col = m_GridPanel->GetCollapseColAndExpand();
453  auto num_rows = m_Grid->GetNumberRows();
454  for (auto row = 0; row < num_rows; ++row)
455  {
456  CBioseq_Handle bsh = scope.GetBioseqHandle(*m_id_col->GetData().GetId()[row]);
457  string field = m_Grid->GetCellValue(row, m_field_col).ToStdString();
458  string value = m_Grid->GetCellValue(row, m_source_col).ToStdString();
459  values[bsh][field] = value;
460  }
461  m_GridPanel->CollapseByCol(collapsed_col);
462  Thaw();
463  m_Grid->Refresh();
464 
465  CRef<CCmdComposite> composite(new CCmdComposite("Update Biosource from Biosample"));
466 
467  for (map<CBioseq_Handle, map<string, string> >::iterator it = values.begin(); it != values.end(); ++it)
468  {
469  CSeqdesc_CI src_desc_ci(it->first, CSeqdesc::e_Source);
470  CRef<CSeqdesc> new_desc(new CSeqdesc);
471  new_desc->Assign(*src_desc_ci);
472  CBioSource& biosource = new_desc->SetSource();
473 
474  for (map<string, string>::iterator fi = it->second.begin(); fi != it->second.end(); ++fi)
475  {
476  string field = fi->first;
477  string value = fi->second;
478 
479  if (NStr::EqualNocase(field, "Organism Name"))
480  {
481  if (!NStr::IsBlank(value))
482  {
483  biosource.SetOrg().SetTaxname(value);
484  }
485  else
486  {
487  biosource.SetOrg().ResetTaxname();
488  }
489  if (biosource.GetOrg().IsSetOrgname() && biosource.GetOrg().GetOrgname().IsSetName())
490  {
491  biosource.SetOrg().SetOrgname().ResetName();
492  }
493  }
494  else if (NStr::EqualNocase(field, "Tax ID"))
495  {
497  if (taxid > 0)
498  biosource.SetOrg().SetTaxId(taxid);
499  }
500  else
501  {
502  list<string> vals;
504 
505  bool found = false;
506  try
507  {
509  biosource.RemoveOrgMod(subtype);
510  for (const auto &v : vals)
511  {
512  if (CBioSource::IsStopWord(v))
513  continue;
514  if (!NStr::IsBlank(v))
515  {
516  CRef<COrgMod> mod(new COrgMod());
517  mod->SetSubtype(subtype);
518  mod->SetSubname(v);
519  biosource.SetOrg().SetOrgname().SetMod().push_back(mod);
520  }
521  }
522  found = true;
523  } catch(const CException&)
524  {
525  found = false;
526  }
527  catch (const exception&)
528  {
529  found = false;
530  }
531  if (!found)
532  {
533  try
534  {
536  biosource.RemoveSubSource(subtype);
537  for (const auto &v : vals)
538  {
539  if (CBioSource::IsStopWord(v))
540  continue;
541  if (!NStr::IsBlank(v))
542  {
543  CRef<CSubSource> sub(new CSubSource());
544  sub->SetSubtype(subtype);
545  sub->SetName(v);
546  biosource.SetSubtype().push_back(sub);
547  }
548  }
549  found = true;
550  }
551  catch(const CException&)
552  {
553  found = false;
554  }
555  catch (const exception&)
556  {
557  found = false;
558  }
559  }
560  if (!found)
561  {
562  wxMessageBox(wxT("Unknown field name ") + wxString(field), wxT("Error"), wxOK);
563  return;
564  }
565  }
566  }
567 
568  biosource.AutoFix();
569 
570  CRef<CCmdChangeSeqdesc> cmd(new CCmdChangeSeqdesc(src_desc_ci.GetSeq_entry_Handle(), *src_desc_ci, *new_desc));
571  composite->AddCommand(*cmd);
572  }
573 
574  m_CmdProcessor->Execute(composite);
575  m_modified_source = false;
576 }
577 
578 
580 {
581  return "Invalid operation in Compare with Biosample";
582 }
583 
584 
585 /*!
586  * Should we show tooltips?
587  */
588 
590 {
591  return true;
592 }
593 
594 /*!
595  * Get bitmap resources
596  */
597 
598 wxBitmap CCompareWithBiosample::GetBitmapResource( const wxString& name )
599 {
600  // Bitmap retrieval
601 ////@begin CCompareWithBiosample bitmap retrieval
602  wxUnusedVar(name);
603  return wxNullBitmap;
604 ////@end CCompareWithBiosample bitmap retrieval
605 }
606 
607 /*!
608  * Get icon resources
609  */
610 
611 wxIcon CCompareWithBiosample::GetIconResource( const wxString& name )
612 {
613  // Icon retrieval
614 ////@begin CCompareWithBiosample icon retrieval
615  wxUnusedVar(name);
616  return wxNullIcon;
617 ////@end CCompareWithBiosample icon retrieval
618 }
619 
620 void CCompareWithBiosample::OnClickCancel( wxCommandEvent& event )
621 {
623  if (modified) {
624  wxMessageDialog dlg(this,_("Discard modifications?"), _("Attention"),wxOK|wxCANCEL|wxCENTRE);
625  if (dlg.ShowModal() == wxID_OK) {
626  Close();
627  }
628  }
629  else {
630  Close();
631  }
632 }
633 
634 void CCompareWithBiosample::GetSelectedRows(std::set<int> &selected)
635 {
636  if (!m_Grid->IsSelection())
637  {
638  return;
639  }
640  wxArrayInt wx_selected = m_Grid->GetSelectedRows();
641  if (wx_selected.IsEmpty())
642  {
643  if (m_Grid->GetSelectionBlockTopLeft().size() == 1 && m_Grid->GetSelectionBlockTopLeft().size() == m_Grid->GetSelectionBlockBottomRight().size())
644  {
645  int top_row = m_Grid->GetSelectionBlockTopLeft()[0].GetRow();
646  int bot_row = m_Grid->GetSelectionBlockBottomRight()[0].GetRow();
647  for (int i = top_row; i <= bot_row; i++)
648  {
649  selected.insert(i);
650  }
651  }
652  }
653  else
654  {
655  for (unsigned int i = 0; i < wx_selected.GetCount(); i++)
656  {
657  selected.insert(wx_selected.Item(i));
658  }
659  }
660 }
661 
662 
663 void CCompareWithBiosample::OnSyncButtonClick( wxCommandEvent& event )
664 {
665  Freeze();
666  int collapsed_col = m_GridPanel->GetCollapseColAndExpand();
667 
668  std::set<int> selected;
669  GetSelectedRows(selected);
670  if (selected.empty())
671  {
672  wxMessageBox(wxT("Nothing selected"), wxT("Info"), wxOK);
673  m_GridPanel->CollapseByCol(collapsed_col);
674  Thaw();
675  m_Grid->Refresh();
676  return;
677  }
678 
679  for (std::set<int>::const_iterator i = selected.begin(); i != selected.end(); ++i)
680  if (m_Grid->IsRowShown(*i))
681  {
682  wxString source_value = m_Grid->GetCellValue(*i, m_source_col);
683  wxString sample_value = m_Grid->GetCellValue(*i, m_sample_col);
684 
685  if (sample_value.IsEmpty() && !source_value.IsEmpty())
686  {
687  m_Grid->SetCellTextColour(*i, m_sample_col, wxColour(255, 160, 0));
688  m_Grid->SetCellValue(*i, m_sample_col, source_value);
689  m_modified_sample = true;
690  }
691 
692  if (!sample_value.IsEmpty() && source_value.IsEmpty())
693  {
694  m_Grid->SetCellTextColour(*i, m_source_col, wxColour(255, 160, 0));
695  m_Grid->SetCellValue(*i, m_source_col, sample_value);
696  m_modified_source = true;
697  }
698  }
699 
700  m_GridPanel->CollapseByCol(collapsed_col);
701  Thaw();
702  m_Grid->Refresh();
703 }
704 
706 {
707  Freeze();
708  int collapsed_col = m_GridPanel->GetCollapseColAndExpand();
709 
710  std::set<int> selected;
711  GetSelectedRows(selected);
712  if (selected.empty())
713  {
714  wxMessageBox(wxT("Nothing selected"), wxT("Info"), wxOK);
715  m_GridPanel->CollapseByCol(collapsed_col);
716  Thaw();
717  m_Grid->Refresh();
718  return;
719  }
720 
721  for (std::set<int>::const_iterator i = selected.begin(); i != selected.end(); ++i)
722  if (m_Grid->IsRowShown(*i))
723  {
724  wxString source_value = m_Grid->GetCellValue(*i, m_source_col);
725  wxString sample_value = m_Grid->GetCellValue(*i, m_sample_col);
726 
727  if (!sample_value.IsEmpty() && source_value != sample_value)
728  {
729  m_Grid->SetCellTextColour(*i, m_source_col, wxColour(255, 160, 0));
730  m_Grid->SetCellValue(*i, m_source_col, sample_value);
731  m_modified_source = true;
732  }
733  }
734 
735  m_GridPanel->CollapseByCol(collapsed_col);
736  Thaw();
737  m_Grid->Refresh();
738 }
739 
741 {
742  Freeze();
743  int collapsed_col = m_GridPanel->GetCollapseColAndExpand();
744 
745  std::set<int> selected;
746  GetSelectedRows(selected);
747  if (selected.empty())
748  {
749  wxMessageBox(wxT("Nothing selected"), wxT("Info"), wxOK);
750  m_GridPanel->CollapseByCol(collapsed_col);
751  Thaw();
752  m_Grid->Refresh();
753  return;
754  }
755 
756  for (std::set<int>::const_iterator i = selected.begin(); i != selected.end(); ++i)
757  if (m_Grid->IsRowShown(*i))
758  {
759  wxString source_value = m_Grid->GetCellValue(*i, m_source_col);
760  wxString sample_value = m_Grid->GetCellValue(*i, m_sample_col);
761 
762  if (sample_value != source_value && !source_value.IsEmpty())
763  {
764  m_Grid->SetCellTextColour(*i, m_sample_col, wxColour(255, 160, 0));
765  m_Grid->SetCellValue(*i, m_sample_col, source_value);
766  m_modified_sample = true;
767  }
768 
769  }
770 
771  m_GridPanel->CollapseByCol(collapsed_col);
772  Thaw();
773  m_Grid->Refresh();
774 }
775 
776 void CCompareWithBiosample::OnAddToSource( wxCommandEvent& event )
777 {
778  Freeze();
779  int collapsed_col = m_GridPanel->GetCollapseColAndExpand();
780 
781  std::set<int> selected;
782  GetSelectedRows(selected);
783  if (selected.empty())
784  {
785  wxMessageBox(wxT("Nothing selected"), wxT("Info"), wxOK);
786  m_GridPanel->CollapseByCol(collapsed_col);
787  Thaw();
788  m_Grid->Refresh();
789  return;
790  }
791 
792  for (std::set<int>::const_iterator i = selected.begin(); i != selected.end(); ++i)
793  if (m_Grid->IsRowShown(*i))
794  {
795  wxString source_value = m_Grid->GetCellValue(*i, m_source_col);
796  wxString sample_value = m_Grid->GetCellValue(*i, m_sample_col);
797  wxString field = m_Grid->GetCellValue(*i, m_field_col);
798 
799  if (!sample_value.IsEmpty() && source_value != sample_value && field != _("Organism Name") && field != _("Tax ID"))
800  {
801  list<string> old_vals;
802  NStr::Split(source_value.ToStdString(), "|", old_vals, NStr::fSplit_Tokenize);
803  list<string> new_vals;
804  NStr::Split(sample_value.ToStdString(), "|", new_vals, NStr::fSplit_Tokenize);
805  set<string> vals(old_vals.begin(), old_vals.end());
806  vals.insert(new_vals.begin(), new_vals.end());
807  string new_val = NStr::Join(vals, "|");
808  if (new_val != source_value)
809  {
810  m_Grid->SetCellTextColour(*i, m_source_col, wxColour(255, 160, 0));
811  m_Grid->SetCellValue(*i, m_source_col, new_val);
812  m_modified_source = true;
813  }
814  }
815  }
816 
817  m_GridPanel->CollapseByCol(collapsed_col);
818  Thaw();
819  m_Grid->Refresh();
820 }
821 
822 void CCompareWithBiosample::OnAddToSample( wxCommandEvent& event )
823 {
824  Freeze();
825  int collapsed_col = m_GridPanel->GetCollapseColAndExpand();
826 
827  std::set<int> selected;
828  GetSelectedRows(selected);
829  if (selected.empty())
830  {
831  wxMessageBox(wxT("Nothing selected"), wxT("Info"), wxOK);
832  m_GridPanel->CollapseByCol(collapsed_col);
833  Thaw();
834  m_Grid->Refresh();
835  return;
836  }
837 
838  for (std::set<int>::const_iterator i = selected.begin(); i != selected.end(); ++i)
839  if (m_Grid->IsRowShown(*i))
840  {
841  wxString source_value = m_Grid->GetCellValue(*i, m_source_col);
842  wxString sample_value = m_Grid->GetCellValue(*i, m_sample_col);
843  wxString field = m_Grid->GetCellValue(*i, m_field_col);
844 
845  if (sample_value != source_value && !source_value.IsEmpty() && field != _("Organism Name") && field != _("Tax ID"))
846  {
847  list<string> old_vals;
848  NStr::Split(sample_value.ToStdString(), "|", old_vals, NStr::fSplit_Tokenize);
849  list<string> new_vals;
850  NStr::Split(source_value.ToStdString(), "|", new_vals, NStr::fSplit_Tokenize);
851  set<string> vals(old_vals.begin(), old_vals.end());
852  vals.insert(new_vals.begin(), new_vals.end());
853  string new_val = NStr::Join(vals, "|");
854  if (new_val != sample_value)
855  {
856  m_Grid->SetCellTextColour(*i, m_sample_col, wxColour(255, 160, 0));
857  m_Grid->SetCellValue(*i, m_sample_col, new_val);
858  m_modified_sample = true;
859  }
860  }
861 
862  }
863 
864  m_GridPanel->CollapseByCol(collapsed_col);
865  Thaw();
866  m_Grid->Refresh();
867 }
868 
869 void CCompareWithBiosample::MakeReport(wxCommandEvent& event)
870 {
871  wxString msg;
872  msg << "Seq-id\tField\tSource\tSample\tBiosample Id\n";
873  for (const auto &diff : m_DiffVec)
874  {
875  string field, sample_id;
876  tie(sample_id, field) = diff.first;
877  for (const auto &row : diff.second)
878  {
879  string seq_id = row.first;
880  set<string> set_source, set_sample;
881  tie(set_source, set_sample) = row.second;
882 
883  string source = NStr::Join(set_source, "|");
884  string sample = NStr::Join(set_sample, "|");
885 
886  msg << seq_id <<"\t"<<field<<"\t"<<source<<"\t"<<sample<<"\t"<<sample_id<<"\n";
887  }
888  }
889 
890  CGenericReportDlg* report = new CGenericReportDlg(NULL);
891  report->SetTitle(wxT("Compare with Biosample Report"));
892  report->SetText(msg);
893  report->Show(true);
894 }
895 
896 
897 static const char* kRegPath = "Dialogs.Edit.CompareWithBiosample";
898 static const char* kApiKeyPath = "APIKEY_Path";
899 
901 {
902  if (m_PathToApiKey.empty())
903  return;
904 
906  CRegistryWriteView view = gui_reg.GetWriteView(kRegPath);
907 
909 }
910 
912 {
914  CRegistryReadView view = gui_reg.GetReadView(kRegPath);
915 
918 }
919 
920 static const int chunk_size = 100;
921 
923 {
924  if (m_BioSampleApiKey.empty()) {
926  }
927 
928  if (m_BioSampleApiKey.empty()) {
929  wxMessageBox(wxT("Current BioSample API key is empty. Please specify a new one."), wxT("Error"), wxOK);
930  return;
931  }
932 
933  wxString msg;
934  {
935  wxBusyCursor wait;
936  map<pair<string, string>, list<string> > new_values;
937  {
938  Freeze();
939  int collapsed_col = m_GridPanel->GetCollapseColAndExpand();
940  auto num_rows = m_Grid->GetNumberRows();
941  for (auto row = 0; row < num_rows; ++row)
942  {
943  string seq_id_str = m_id_col->GetData().GetId()[row]->GetSeqIdString();
944  string field = m_Grid->GetCellValue(row, m_field_col).ToStdString();
945  string sample = m_Grid->GetCellValue(row, m_sample_col).ToStdString();
946  string sample_id = m_Grid->GetCellValue(row, m_sample_id_col).ToStdString();
947  list<string> sample_list;
948  NStr::Split(sample, "|", sample_list, NStr::fSplit_Tokenize);
949  sample_list.sort();
950  new_values[pair<string, string>(sample_id, field)] = sample_list;
951  }
952  m_GridPanel->CollapseByCol(collapsed_col);
953  Thaw();
954  m_Grid->Refresh();
955  }
956 
957  unordered_map<string, map<string, vector<string> > > delete_value, add_value;
958  set<string> ids;
959  unordered_map<string, string> change_organism;
960  for (const auto &diff : m_DiffVec)
961  {
962  string field, sample_id;
963  tie(sample_id, field) = diff.first;
964  list<string> new_sample;
965  if (new_values.find(diff.first) != new_values.end())
966  new_sample = new_values[diff.first];
967 
968  set<string> set_source, old_sample;
969  tie(set_source, old_sample) = diff.second.begin()->second;
970 
971 
972  NStr::ReplaceInPlace(field, "-", "_");
973 
974  vector<string> deleted_values;
975  set_difference(old_sample.begin(), old_sample.end(), new_sample.begin(), new_sample.end(), inserter(deleted_values, deleted_values.end()));
976 
977  vector<string> added_values;
978  set_difference(new_sample.begin(), new_sample.end(), old_sample.begin(), old_sample.end(), inserter(added_values, added_values.end()));
979 
980  if (field == "Organism Name")
981  {
982  if (added_values.size() == 1 && deleted_values.size() == 1)
983  {
984  change_organism[sample_id] = added_values.front();
985  ids.insert(sample_id);
986  }
987  continue;
988  }
989  if (!deleted_values.empty())
990  {
991  delete_value[sample_id][field] = deleted_values;
992  ids.insert(sample_id);
993  }
994 
995  if (!added_values.empty())
996  {
997  add_value[sample_id][field] = added_values;
998  ids.insert(sample_id);
999  }
1000  }
1001  for (const auto &diff : new_values)
1002  {
1003  string field, sample_id;
1004  tie(sample_id, field) = diff.first;
1005  vector<string> new_sample(diff.second.begin(), diff.second.end());
1006 
1007  if (m_DiffVec.find(diff.first) != m_DiffVec.end())
1008  {
1009  continue;
1010  }
1011 
1012  if (new_sample.empty())
1013  {
1014  continue;
1015  }
1016 
1017  NStr::ReplaceInPlace(field, "-", "_");
1018  add_value[sample_id][field] = new_sample;
1019  ids.insert(sample_id);
1020  }
1021  int response_timeout = CGuiRegistry::GetInstance().GetInt("GBENCH.System.SeqConfigTimeout", 40);
1022  //string sUrl = "https://dev-api-int.ncbi.nlm.nih.gov/biosample/update/"; // DEBUG
1023  string sUrl = "https://api-int.ncbi.nlm.nih.gov/biosample/update/";
1024  string sContentType = "application/json; charset=utf-8";
1025 
1026  auto sample_id_it = ids.begin();
1027  while (sample_id_it != ids.end())
1028  {
1029  int count = 0;
1030  CJson_Document req;
1031  CJson_Object top_obj = req.SetObject();
1032  CJson_Array biosample_array = top_obj.insert_array("update");
1033  for (; sample_id_it != ids.end() && count < chunk_size; ++sample_id_it)
1034  {
1035  auto sample_id = *sample_id_it;
1036  CJson_Object obj1 = biosample_array.push_back_object();
1037  obj1.insert("samples", sample_id);
1038  if (!delete_value[sample_id].empty())
1039  {
1040  CJson_Array del_arr = obj1.insert_object("delete").insert_array("attribute");
1041  for (const auto &kv : delete_value[sample_id])
1042  {
1043  const string &field = kv.first;
1044  for (const auto &v : kv.second)
1045  {
1046  CJson_Object obj2 = del_arr.push_back_object();
1047  obj2.insert("name", field);
1048  obj2.insert("old_value", v);
1049  count++;
1050  }
1051  }
1052  }
1053  if ( !change_organism[sample_id].empty())
1054  {
1055  CJson_Object chg_obj = obj1.insert_object("change");
1056  CJson_Object chg_org = chg_obj.insert_object("organism");
1057  chg_org.insert("new_value", change_organism[sample_id]);
1058  count++;
1059  }
1060  if (!add_value[sample_id].empty())
1061  {
1062  CJson_Array add_arr = obj1.insert_object("add").insert_array("attribute");
1063  for (const auto &kv : add_value[sample_id])
1064  {
1065  const string &field = kv.first;
1066  for (const auto &v : kv.second)
1067  {
1068  CJson_Object obj2 = add_arr.push_back_object();
1069  obj2.insert("name", field);
1070  obj2.insert("new_value", v);
1071  count++;
1072  }
1073  }
1074  }
1075  }
1076  top_obj.insert_object("options").insert("attribute_synonyms", true);
1077 
1078  string sData = req.ToString();
1079  //cout << "REQUEST" << endl;
1080  //cout << sData << endl;
1081 
1082  CUrl curl(sUrl);
1083  CHttpHeaders headers;
1084  headers.SetValue("NCBI-BioSample-Authorization", m_BioSampleApiKey);
1085  CHttpResponse response = g_HttpPost(curl, headers, sData, sContentType); // send biosample request
1086  if (response.GetStatusCode() != 200) {
1087  stringstream ss;
1088  NcbiStreamCopy(ss, response.ErrorStream());
1089  string err = ss.str();
1090  if (err.empty())
1091  err = "Unable to connect - server down?";
1092  wxMessageBox(wxString(err), wxT("Error"), wxOK);
1093  break;
1094  }
1095 
1096  stringstream ss;
1097  NcbiStreamCopy(ss, response.ContentStream());
1098  bool has_error = false;
1099  auto rep_update = x_ReportBiosampleUpdate(ss.str(), has_error);
1100  if (has_error) {
1101  wxMessageBox(wxT("Current BioSample API key was not recognized. Please specify a new one."), wxT("Error"), wxOK);
1102  break;
1103  }
1104  else {
1105  msg << rep_update;
1106  }
1107  }
1108  }
1109 
1110  m_modified_sample = false;
1111  if (!msg.IsEmpty()) {
1112  CGenericReportDlg *report = new CGenericReportDlg(this);
1113  report->SetTitle(wxT("Biosample Update Report"));
1114  report->SetText(msg);
1115  report->Show(true);
1116  report->Raise();
1117  wxYieldIfNeeded();
1118  }
1119  else {
1120  wxWindow *win = FindWindowByLabel(wxT("Biosample Update Report"), this);
1121  if (win) {
1122  CGenericReportDlg *report = dynamic_cast<CGenericReportDlg *>(win);
1123  if (report)
1124  report->Close();
1125  }
1126  }
1127  x_ReloadTable();
1128 
1129 }
1130 
1131 void CCompareWithBiosample::OnNewAPIKey(wxCommandEvent& event)
1132 {
1133  x_DoUpdateAPIKey();
1134 }
1135 
1137 {
1138  CFileLocDialog dlg(this);
1139  if (dlg.ShowModal() == wxID_OK) {
1140  m_PathToApiKey = dlg.GetFilename();
1142  }
1143 }
1144 
1146 {
1147  CNcbiIfstream istr(m_PathToApiKey.data());
1148  if (istr.good()) {
1149  istr >> m_BioSampleApiKey;
1150  }
1151 }
1152 
1154 {
1155 /*
1156  int collapsed_col = m_GridPanel->GetCollapseColAndExpand();
1157  vector<pair<wxString, wxColour> > redo_values;
1158  for (int row = 0; row < m_Grid->GetNumberRows(); row++) {
1159  if (!m_Grid->IsReadOnly(row, m_source_col) && m_Grid->IsRowShown(row)) {
1160  redo_values.push_back(make_pair(m_Grid->GetCellValue(row, m_source_col),
1161  m_Grid->GetCellTextColour(row, m_source_col)));
1162  }
1163  }
1164 */
1165 
1166 
1167  x_LoadData();
1168 
1169  if (m_DiffVec.empty())
1170  {
1171  wxMessageBox(wxT("No differences found for resolved Biosample IDs"), wxT("Info"), wxOK);
1172  Close();
1173  return;
1174  }
1176  if (values_table->GetNum_rows() < 1)
1177  {
1178  wxMessageBox(wxT("No differences found for resolved Biosample IDs"), wxT("Info"), wxOK);
1179  Close();
1180  return;
1181  }
1182  x_AddTablePanel(values_table);
1183 /*
1184  for (int row = 0; row < redo_values.size(); row++)
1185  {
1186  wxString val = redo_values[row].first;
1187  wxColour colour = redo_values[row].second;
1188  m_Grid->SetCellTextColour(row, m_source_col, colour);
1189  m_Grid->SetCellValue(row, m_source_col, val);
1190  }
1191  m_GridPanel->CollapseByCol(collapsed_col);
1192 */
1193 }
1194 
1195 void CCompareWithBiosample::OnRefresh(wxCommandEvent& event)
1196 {
1197  wxWindow *win = FindWindowByLabel(wxT("Biosample Update Report"), this);
1198  if (win)
1199  {
1200  CGenericReportDlg *report = dynamic_cast<CGenericReportDlg *>(win);
1201  if (report)
1202  report->Close();
1203  }
1204 
1205  if (m_timer.IsRunning()) {
1206  m_timer.Stop();
1207  }
1208  m_RefreshButton->Disable();
1209  x_ReloadTable();
1210  if (!m_timer.IsRunning()) {
1211  m_timer.Start(3000);
1212  }
1213 }
1214 
1215 wxString CCompareWithBiosample::x_ReportBiosampleUpdate(const string &str, bool& has_error)
1216 {
1217  //cout << "REPLY" <<endl;
1218  //cout << str << endl;
1219  has_error = false;
1220  wxString report;
1221  CJson_Document doc;
1222  doc.ParseString(str);
1223 
1224  if (!doc.ReadSucceeded() || !doc.IsObject())
1225  return report;
1226 
1227  CJson_ConstObject obj = doc.GetObject();
1228 
1229  auto error_it = obj.find("has_error");
1230  if (error_it != obj.end() && error_it->value.GetValue().GetBool() == true) {
1231  auto msg_it = obj.find("messages");
1232  if (msg_it != obj.end() && msg_it->value.IsArray() && !msg_it->value.GetArray().empty()) {
1233  const auto& messages = msg_it->value.GetArray();
1234  for (const auto& resp_it : messages) {
1235  if (resp_it.IsObject()) {
1236  const auto& resp_obj = resp_it.GetObject();
1237  auto level_it = resp_obj.find("level");
1238  auto message_it = resp_obj.find("message");
1239  if ((level_it != resp_obj.end()) &&
1240  (message_it != resp_obj.end()) &&
1241  (level_it->value.GetValue().GetString() == "error") &&
1242  (NStr::StartsWith(message_it->value.GetValue().GetString(), "Please sign in to NCBI", NStr::eNocase))){
1243  has_error = true;
1244  return report;
1245  }
1246  }
1247  }
1248  }
1249  }
1250 
1251  CJson_ConstObject::const_iterator it = obj.find("messages");
1252  if (it == obj.end() || !it->value.IsArray() || it->value.GetArray().empty())
1253  return report;
1254 
1255  unordered_map<string, vector<string> > messages;
1256  for ( CJson_ConstArray::const_iterator it2 = it->value.GetArray().begin(); it2 != it->value.GetArray().end(); ++it2)
1257  {
1258  CJson_ConstObject obj2 = it2->GetObject();
1259  if (obj2.find("level") != obj2.end() && obj2.find("message") != obj2.end())
1260  {
1261  string level = obj2["level"].GetValue().GetString();
1262  string msg = obj2["message"].GetValue().GetString();
1263  messages[level].push_back(msg);
1264  }
1265  }
1266 
1267 
1268  it = obj.find("validation_report");
1269  if (it != obj.end() && it->value.IsObject() && !it->value.GetObject().empty())
1270  {
1271  map<string, map<string, string> > validation_error, validation_warning;
1272  for ( CJson_ConstObject::const_iterator it2 = it->value.GetObject().begin(); it2 != it->value.GetObject().end(); ++it2)
1273  {
1274  string name(it2->name);
1275  for ( CJson_ConstArray::const_iterator it3 = it2->value.GetArray().begin(); it3 != it2->value.GetArray().end(); ++it3)
1276  {
1277  CJson_ConstObject obj2 = it3->GetObject();
1278  if (obj2.find("message") == obj2.end())
1279  {
1280  continue;
1281  }
1282 
1283  string validation_msg;
1284  if (obj2.find("type") != obj2.end())
1285  {
1286  string type = obj2["type"].GetValue().GetString();
1287  if (type == "attribute_error" && obj2.find("attribute_name") != obj2.end())
1288  {
1289  string attribute_name = obj2["attribute_name"].GetValue().GetString();
1290  validation_msg += " " + attribute_name;
1291  if (obj2.find("attribute_value") != obj2.end())
1292  {
1293  string attribute_value = obj2["attribute_value"].GetValue().GetString();
1294  if (!attribute_value.empty())
1295  validation_msg += ":" + attribute_value;
1296  }
1297  }
1298  }
1299 
1300  string msg = obj2["message"].GetValue().GetString();
1301  bool is_warning = false;
1302  if (obj2.find("is_warning") != obj2.end())
1303  is_warning = obj2["is_warning"].GetValue().GetBool();
1304  if (obj2.find("name") != obj2.end())
1305  {
1306  string short_name = obj2["name"].GetValue().GetString();
1307  msg += " (" + short_name + ")";
1308  if (short_name == "taxonomy_error_warning" || short_name == "tax_consult_warning" || short_name == "taxonomy_service_failure_warning")
1309  {
1310  wxMessageBox(wxString(msg), wxT("Taxonomy Consult Warning"), wxOK);
1311  }
1312  }
1313  if (is_warning)
1314  validation_warning[msg][name] = validation_msg;
1315  else
1316  validation_error[msg][name] = validation_msg;
1317  }
1318  }
1319  for (const auto &m : validation_error)
1320  {
1321  messages["error"].push_back(m.first);
1322  for (const auto &name : m.second)
1323  {
1324  string str = name.first;
1325  if (!name.second.empty())
1326  str += " - " + name.second;
1327  messages["error"].push_back(str);
1328  }
1329  }
1330  for (const auto &m : validation_warning)
1331  {
1332  messages["warning"].push_back(m.first);
1333  for (const auto &name : m.second)
1334  {
1335  string str = name.first;
1336  if (!name.second.empty())
1337  str += " - " + name.second;
1338  messages["warning"].push_back(str);
1339  }
1340  }
1341  }
1342 
1343  if (messages.empty())
1344  return report;
1345 
1346  if (!messages["error"].empty())
1347  {
1348  report << "Error:\n";
1349  for (const auto &m : messages["error"])
1350  report << m << "\n";
1351  report << "\n";
1352  }
1353  if (!messages["warning"].empty())
1354  {
1355  report << "Warning:\n";
1356  for (const auto &m : messages["warning"])
1357  report << m << "\n";
1358  report << "\n";
1359  }
1360  if (!messages["info"].empty())
1361  {
1362  report << "Info:\n";
1363  for (const auto &m : messages["info"])
1364  report << m << "\n";
1365  report << "\n";
1366  }
1367  return report;
1368 }
1369 
1370 
1371 /*
1372  * CFileLocDialog type definition
1373  */
1374 
1375 IMPLEMENT_DYNAMIC_CLASS(CFileLocDialog, wxDialog)
1376 
1377 
1378 /*
1379  * CFileLocDialog event table definition
1380  */
1381 
1382 BEGIN_EVENT_TABLE(CFileLocDialog, wxDialog)
1383 
1385 
1386 
1388 {
1389  Init();
1390 }
1391 
1392 CFileLocDialog::CFileLocDialog(wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style)
1393 {
1394  Init();
1395  Create(parent, id, caption, pos, size, style);
1396 }
1397 
1398 bool CFileLocDialog::Create(wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style)
1399 {
1400  ////@begin CFileLocDialog creation
1401  SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
1402  wxDialog::Create(parent, id, caption, pos, size, style);
1403 
1404  CreateControls();
1405  if (GetSizer())
1406  {
1407  GetSizer()->SetSizeHints(this);
1408  }
1409  Centre();
1410  ////@end CFileLocDialog creation
1411  return true;
1412 }
1413 
1415 {
1416  m_Filename = nullptr;
1417 }
1418 
1420 {
1421  CFileLocDialog* itemDialog1 = this;
1422 
1423  wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
1424  itemDialog1->SetSizer(itemBoxSizer2);
1425 
1426  wxBoxSizer* itemBoxSizer4 = new wxBoxSizer(wxHORIZONTAL);
1427  itemBoxSizer2->Add(itemBoxSizer4, 0, wxEXPAND | wxALL, 0);
1428 
1429  m_Filename = new wxTextCtrl(itemDialog1, ID_FILELOCTEXTCTRL, wxEmptyString, wxDefaultPosition, wxSize(300, -1), 0);
1430  itemBoxSizer4->Add(m_Filename, 1, wxALIGN_LEFT | wxALL, 5);
1431 
1432  wxButton* itemButton5 = new wxBitmapButton(itemDialog1, wxID_ANY, wxArtProvider::GetBitmap(wxT("menu::open")), wxDefaultPosition, wxDefaultSize, wxBU_AUTODRAW);
1433  itemButton5->SetToolTip(wxT("Choose a file..."));
1434  itemBoxSizer4->Add(itemButton5, 0, wxALIGN_CENTER_VERTICAL | wxTOP |wxBOTTOM | wxRIGHT, 5);
1435  itemButton5->Bind(wxEVT_BUTTON, &CFileLocDialog::OnOpenFile, this);
1436 
1437 
1438  wxBoxSizer* itemBoxSizer6 = new wxBoxSizer(wxHORIZONTAL);
1439  itemBoxSizer2->Add(itemBoxSizer6, 0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5);
1440 
1441  wxButton* itemButton7 = new wxButton(itemDialog1, wxID_OK, _("OK"), wxDefaultPosition, wxDefaultSize, 0);
1442  itemBoxSizer6->Add(itemButton7, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
1443 
1444  wxButton* itemButton8 = new wxButton(itemDialog1, wxID_CANCEL, _("Cancel"), wxDefaultPosition, wxDefaultSize, 0);
1445  itemBoxSizer6->Add(itemButton8, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
1446 }
1447 
1448 void CFileLocDialog::OnOpenFile(wxCommandEvent& event)
1449 {
1450  wxFileDialog dlg(this, wxT("Select file"), wxEmptyString, wxEmptyString, _("All files (*.*)|*.*"), wxFD_OPEN | wxFD_FILE_MUST_EXIST);
1451 
1452  if (dlg.ShowModal() == wxID_OK) {
1453  auto mapped_path = GetAbsolutePath(dlg.GetPath());
1454  m_Filename->SetValue(mapped_path);
1455  }
1456 }
1457 
1459 {
1460  return ToStdString(m_Filename->GetValue());
1461 }
1462 
1463 
1464 /*
1465  * Should we show tooltips?
1466  */
1467 
1469 {
1470  return true;
1471 }
1472 
1473 /*
1474  * Get bitmap resources
1475  */
1476 
1477 wxBitmap CFileLocDialog::GetBitmapResource(const wxString& name)
1478 {
1479  // Bitmap retrieval
1480 ////@begin CLoginDialog bitmap retrieval
1481  wxUnusedVar(name);
1482  return wxNullBitmap;
1483  ////@end CLoginDialog bitmap retrieval
1484 }
1485 
1486 /*
1487  * Get icon resources
1488  */
1489 
1490 wxIcon CFileLocDialog::GetIconResource(const wxString& name)
1491 {
1492  // Icon retrieval
1493 ////@begin CLoginDialog icon retrieval
1494  wxUnusedVar(name);
1495  return wxNullIcon;
1496  ////@end CLoginDialog icon retrieval
1497 }
1498 
1499 //TODO: deal with fields which can appear multiple times within the same bioseq.
1500 
1501 
1502 
vector< CRef< CBiosampleFieldDiff > > TBiosampleFieldDiffList
map< string, CRef< CSeq_descr > > TBioSamples
TBiosampleFieldDiffList GetBioseqDiffs(CBioseq_Handle bh, const string &biosample_accession, size_t &num_processed, vector< string > &unprocessed_ids, bool use_dev_server=false, bool compare_structured_comments=false, const string &expected_prefix="", TBioSamples *cache=NULL)
void AutoFix()
Definition: BioSource.cpp:1392
static bool IsStopWord(const string &value)
Definition: BioSource.cpp:1382
bool RemoveOrgMod(int subtype)
Definition: BioSource.cpp:1636
bool RemoveSubSource(int subtype)
Definition: BioSource.cpp:1591
CBioseq_CI –.
Definition: bioseq_ci.hpp:69
CBioseq_Handle –.
void AddCommand(IEditCommand &command)
void OnAddToSample(wxCommandEvent &event)
void OnAddToSource(wxCommandEvent &event)
CRef< objects::CSeq_table > GetChoices(CRef< objects::CSeq_table > values_table)
CStringConstraintSelect * m_StringConstraintPanel
wxScrolledWindow * m_ScrolledWindow
void OnSyncButtonClick(wxCommandEvent &event)
ICommandProccessor * m_CmdProcessor
void CreateBiosampleUpdateWebService(wxCommandEvent &event)
wxIcon GetIconResource(const wxString &name)
Retrieves icon resources.
CRef< objects::CSeq_table > GetValuesTableFromSeqEntry()
CRef< objects::CSeqTable_column > m_id_col
void OnRefresh(wxCommandEvent &event)
void OnClickCancel(wxCommandEvent &event)
void x_AddTablePanel(CRef< objects::CSeq_table > values_table)
map< pair< string, string >, unordered_map< string, pair< set< string >, set< string > > > > m_DiffVec
void Init()
Initialises member variables.
CSeqTableGridPanel * m_GridPanel
void OnCopyToSourceButtonClick(wxCommandEvent &event)
void OnNewAPIKey(wxCommandEvent &event)
map< string, CConstRef< CSeq_id > > m_ids
wxString x_ReportBiosampleUpdate(const string &str, bool &has_error)
bool IsReadOnlyColumn(string column_name)
void GetSelectedRows(std::set< int > &selected)
biosample_util::TBioSamples m_Cache
void CreateControls()
Creates the controls and sizers.
void OnCopyToSampleButtonClick(wxCommandEvent &event)
CApplyEditconvertPanel * m_AecrPanel
bool Create(wxWindow *parent, wxWindowID id=wxID_ANY, const wxString &caption=_("Compare with Biosample"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=wxMINIMIZE_BOX|wxMAXIMIZE_BOX|wxCLOSE_BOX|wxCAPTION|wxCLIP_CHILDREN|wxRESIZE_BORDER)
Creation.
wxBitmap GetBitmapResource(const wxString &name)
Retrieves bitmap resources.
void MakeReport(wxCommandEvent &event)
void OnClickOk(wxCommandEvent &event)
static bool ShowToolTips()
Should we show tooltips?
void OnOpenFile(wxCommandEvent &event)
wxBitmap GetBitmapResource(const wxString &name)
Retrieves bitmap resources.
CFileLocDialog()
Constructors.
wxIcon GetIconResource(const wxString &name)
Retrieves icon resources.
static bool ShowToolTips()
Should we show tooltips?
void CreateControls()
Creates the controls and sizers.
void Init()
Initialises member variables.
bool Create(wxWindow *parent, wxWindowID id=13000, const wxString &caption=_("Select File with BioSample API Key"), const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxSize(400, 300), long style=wxCAPTION|wxRESIZE_BORDER|wxSYSTEM_MENU|wxCLOSE_BOX|wxTAB_TRAVERSAL)
Creation.
void SetText(const wxString &text)
CRegistryWriteView GetWriteView(const string &section)
get a read-write view at a particular level.
Definition: registry.cpp:462
static CGuiRegistry & GetInstance()
access the application-wide singleton
Definition: registry.cpp:400
CRegistryReadView GetReadView(const string &section) const
get a read-only view at a particular level.
Definition: registry.cpp:428
int GetInt(const string &key, int default_val=0) const
retrieve values by section and key.
Definition: registry.cpp:133
HTTP response.
CJson_Object push_back_object(void)
Add object type element to the end of the array.
Random-access iterator to access const JSON array element.
const_iterator begin(void) const
Return a random-access iterator to the first element in the array.
bool empty(void) const
Test if the array is empty.
const_iterator end(void) const
Return a random-access iterator that points just beyond the end of the array.
bool IsObject(void) const
CJson_ConstObject GetObject(void) const
Get JSON object contents of the node.
bool IsArray(void) const
CJson_ConstArray GetArray(void) const
Get JSON array contents of the node.
std::string ToString(TJson_Write_Flags flags=fJson_Write_IndentWithSpace, unsigned int indent_char_count=4) const
Convert the contents of the node into string.
CJson_ConstValue GetValue(void) const
Get JSON value contents of the node.
Bidirectional iterator to access const JSON object element.
const CJson_ConstNode value
CJson_Object.
bool empty(void) const
Test if the object is empty.
const_iterator find(const CJson_Node::TKeyType &name) const
Return an iterator that points to the location of the element.
const_iterator begin(void) const
Return an iterator that points to the first element in the object.
const_iterator end(void) const
Return an iterator that points to the location after the last element.
bool GetBool(void) const
Get primitive value data.
TStringType GetString(void) const
bool ParseString(const TStringType &v)
Read JSON data from a UTF8 string.
bool ReadSucceeded(void) const
Test if the most recent read was successful.
CJson_Object SetObject(void)
Get JSON object contents of the node.
CJson_Array insert_array(const CJson_Node::TKeyType &name)
Insert array type element into the object.
void insert(const CJson_Node::TKeyType &name)
Insert null element into the object.
CJson_Object insert_object(const CJson_Node::TKeyType &name)
Insert object type element into the object.
@OrgMod.hpp User-defined methods of the data storage class.
Definition: OrgMod.hpp:54
static TSubtype GetSubtypeValue(const string &str, EVocabulary vocabulary=eVocabulary_raw)
Definition: OrgMod.cpp:62
class CRegistryReadView provides a nested hierarchical view at a particular key.
Definition: reg_view.hpp:58
string GetString(const string &key, const string &default_val=kEmptyStr) const
Definition: reg_view.cpp:246
void Set(const string &key, int val)
access a named key at this level, with no recursion
Definition: reg_view.cpp:533
CScope –.
Definition: scope.hpp:92
void MakeColumnReadOnly(int pos, bool val=true)
void CollapseByCol(int col)
int GetCollapseColAndExpand(void)
wxGrid * GetGrid(void)
void InitColumnCollapse(int col)
CSeq_entry_Handle –.
CSeqdesc_CI –.
Definition: seqdesc_ci.hpp:65
static TSubtype GetSubtypeValue(const string &str, EVocabulary vocabulary=eVocabulary_raw)
Definition: SubSource.cpp:126
CUrl –.
Definition: ncbi_url.hpp:353
Undo/Redo interface for editing operations.
virtual void Execute(IEditCommand *command, wxWindow *window=0)=0
const_iterator begin() const
Definition: map.hpp:151
const_iterator end() const
Definition: map.hpp:152
bool empty() const
Definition: map.hpp:149
void clear()
Definition: map.hpp:169
const_iterator find(const key_type &key) const
Definition: map.hpp:153
Definition: map.hpp:338
iterator_bool insert(const value_type &val)
Definition: set.hpp:149
const_iterator begin() const
Definition: set.hpp:135
const_iterator end() const
Definition: set.hpp:136
USING_SCOPE(objects)
static const int chunk_size
static const char * kRegPath
static const char * kApiKeyPath
#define ID_COPY_TO_SAMPLE
#define ID_ADD_TO_SOURCE
#define ID_CREATE_BIOSAMPLE
#define ID_UPDATE_BIOSOURCE
#define ID_FILELOCTEXTCTRL
#define ID_SYNC
#define ID_ADD_TO_SAMPLE
#define ID_REFRESH_BIOSAMPLE
#define ID_COPY_TO_SOURCE
#define ID_MAKE_REPORT
#define ID_APIKEY_BIOSAMPLE
#define _(proto)
Definition: ct_nlmzip_i.h:78
#define wxFIXED_MINSIZE
const char * kSequenceIdColLabel
static CS_COMMAND * cmd
Definition: ct_dynamic.c:26
static void Init(void)
Definition: cursor6.c:76
static const char * str(char *buf, int n)
Definition: stats.c:84
#define ITERATE(Type, Var, Cont)
ITERATE macro to sequence through container elements.
Definition: ncbimisc.hpp:815
#define NULL
Definition: ncbistd.hpp:225
#define NCBI_THROW(exception_class, err_code, message)
Generic macro to throw an exception, given the exception class, error code and message string.
Definition: ncbiexpt.hpp:704
virtual void Assign(const CSerialObject &source, ESerialRecursionMode how=eRecursive)
Set object to copy of another one.
CNcbiIstream & ContentStream(void) const
Get input stream.
int GetStatusCode(void) const
Get response status code.
void SetValue(CHeaderNameConverter name, CTempString value)
Remove all existing values with the name, set the new value.
CNcbiIstream & ErrorStream(void) const
Get input stream containing error message (e.g.
CHttpResponse g_HttpPost(const CUrl &url, CTempString data, const CHttpParam &param=CHttpParam())
Shortcut for POST request.
static int BestRank(const CRef< CSeq_id > &id)
Definition: Seq_id.hpp:774
@ fParse_Default
By default in ParseIDs and IsValid, allow raw parsable non-numeric accessions and plausible local acc...
Definition: Seq_id.hpp:102
CBioseq_Handle GetBioseqHandle(const CSeq_id &id)
Get bioseq handle by seq-id.
Definition: scope.cpp:95
vector< CSeq_id_Handle > TId
CScope & GetScope(void) const
Get scope this handle belongs to.
CSeq_entry_Handle GetSeq_entry_Handle(void) const
Definition: seqdesc_ci.cpp:326
TObjectType * GetPointer(void) const THROWS_NONE
Get pointer,.
Definition: ncbiobj.hpp:1684
void Reset(void)
Reset reference object.
Definition: ncbiobj.hpp:773
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
IO_PREFIX::ifstream CNcbiIfstream
Portable alias for ifstream.
Definition: ncbistre.hpp:439
bool NcbiStreamCopy(CNcbiOstream &os, CNcbiIstream &is)
Copy the entire contents of stream "is" to stream "os".
Definition: ncbistre.cpp:211
#define kEmptyStr
Definition: ncbistr.hpp:123
static int StringToInt(const CTempString str, TStringToNumFlags flags=0, int base=10)
Convert string to int.
Definition: ncbistr.cpp:630
static list< string > & Split(const CTempString str, const CTempString delim, list< string > &arr, TSplitFlags flags=0, vector< SIZE_TYPE > *token_pos=NULL)
Split a string using specified delimiters.
Definition: ncbistr.cpp:3452
static bool IsBlank(const CTempString str, SIZE_TYPE pos=0)
Check if a string is blank (has no text).
Definition: ncbistr.cpp:106
static string Join(const TContainer &arr, const CTempString &delim)
Join strings using the specified delimiter.
Definition: ncbistr.hpp:2699
static bool StartsWith(const CTempString str, const CTempString start, ECase use_case=eCase)
Check if a string starts with a specified prefix value.
Definition: ncbistr.hpp:5406
static bool EqualNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2)
Case-insensitive equality of a substring with another string.
Definition: ncbistr.hpp:5347
static string & ReplaceInPlace(string &src, const string &search, const string &replace, SIZE_TYPE start_pos=0, SIZE_TYPE max_replace=0, SIZE_TYPE *num_replace=0)
Replace occurrences of a substring within a string.
Definition: ncbistr.cpp:3396
@ fConvErr_NoThrow
Do not throw an exception on error.
Definition: ncbistr.hpp:285
@ fSplit_Tokenize
All delimiters are merged and trimmed, to get non-empty tokens only.
Definition: ncbistr.hpp:2510
@ eNocase
Case insensitive compare.
Definition: ncbistr.hpp:1206
C::value_type FindBestChoice(const C &container, F score_func)
Find the best choice (lowest score) for values in a container.
Definition: ncbiutil.hpp:250
static const char label[]
void SetSubtype(TSubtype value)
Assign a value to Subtype data member.
Definition: SubSource_.hpp:319
const TOrg & GetOrg(void) const
Get the Org member data.
Definition: BioSource_.hpp:509
void SetOrg(TOrg &value)
Assign a value to Org data member.
Definition: BioSource_.cpp:108
void SetName(const TName &value)
Assign a value to Name data member.
Definition: SubSource_.hpp:359
TSubtype & SetSubtype(void)
Assign a value to Subtype data member.
Definition: BioSource_.hpp:545
bool IsSetOrgname(void) const
Check if a value has been assigned to Orgname data member.
Definition: Org_ref_.hpp:529
bool IsSetName(void) const
Check if a value has been assigned to Name data member.
Definition: OrgName_.hpp:759
const TOrgname & GetOrgname(void) const
Get the Orgname member data.
Definition: Org_ref_.hpp:541
const TColumns & GetColumns(void) const
Get the Columns member data.
Definition: Seq_table_.hpp:433
void SetHeader(THeader &value)
Assign a value to Header data member.
vector< CRef< CSeqTable_column > > TColumns
Definition: Seq_table_.hpp:92
void SetData(TData &value)
Assign a value to Data data member.
TNum_rows GetNum_rows(void) const
Get the Num_rows member data.
Definition: Seq_table_.hpp:393
bool IsGenbank(void) const
Check if variant Genbank is selected.
Definition: Seq_id_.hpp:841
TSource & SetSource(void)
Select the variant.
Definition: Seqdesc_.cpp:572
@ e_Source
source of materials, includes Org-ref
Definition: Seqdesc_.hpp:133
@ eMol_na
just a nucleic acid
Definition: Seq_inst_.hpp:113
<!DOCTYPE HTML >< html > n< header > n< title > PubSeq Gateway Help Page</title > n< style > n table
END_EVENT_TABLE()
int i
#define wxT(x)
Definition: muParser.cpp:41
void ReportUsage(const wxString &dialog_name)
Report opening & accepting events in the editing package.
constexpr bool empty(list< Ts... >) noexcept
const struct ncbi::grid::netcache::search::fields::SIZE size
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1227
const CharType(& source)[N]
Definition: pointer.h:1149
Int mod(Int i, Int j)
Definition: njn_integer.hpp:67
#define count
static static static wxID_ANY
static SLJIT_INLINE sljit_ins msg(sljit_gpr r, sljit_s32 d, sljit_gpr x, sljit_gpr b)
#define row(bind, expected)
Definition: string_bind.c:73
Definition: type.c:6
wxString GetAbsolutePath(const wxString &localpath)
Definition: wx_utils.cpp:188
string ToStdString(const wxString &s)
Definition: wx_utils.hpp:161
Modified on Fri Sep 20 14:57:22 2024 by modify_doxy.py rev. 669887