test_multilocus.rb 15.8 KB
Newer Older
1
# coding: utf-8
2
load 'vidjil_browser.rb'
3
load 'browser_test.rb'
Marc Duez's avatar
Marc Duez committed
4

5
#browser test suite
6
class TestMultilocus < BrowserTest
7
8

  def setup
9
    super
Mikaël Salson's avatar
Mikaël Salson committed
10
    if not defined? $b
11
      set_browser("/doc/analysis-example.vidjil")
Mikaël Salson's avatar
Mikaël Salson committed
12
    end
13
14
  end

15

16
  def after_tests
17
  end
Mikaël Salson's avatar
Mikaël Salson committed
18
  
19
  def test_00_info_segmentation
20
    assert ($b.div(:id => 'info_segmented').text.include?  '742 377 (94.35%)'), ' Incorrect number of segmented reads'
21
  end
Marc Duez's avatar
Marc Duez committed
22

Marc Duez's avatar
Marc Duez committed
23

24
  def test_00_info_reads
25
    assert ($b.div(:id => 'info_segmented').title.include? '786 861'), 'Incorrect number of reads'
26
27
28
  end

  def test_00_default_point_name
Marc Duez's avatar
Marc Duez committed
29
    assert ($b.div(:id => 'info_point').text.include? 'helloworld'), 'Incorrect point name in info box'
30
31
32
  end

  def test_00_germline
33
    assert ($b.div(:id => 'info').span(:class => 'systemBoxNameMenu', :index => 1).text.include? 'TRA'), 'missing system TRA'
34
35
36
  end

  def test_00_legend_scatterplot
Marc Duez's avatar
Marc Duez committed
37
38
39
40
    assert ($b.scatterplot_x_legend(0).text == 'TRBV1'), "Bad legend for scatterplot"
    assert ($b.scatterplot_x_legend(4).text == '?'), "Bad legend for scatterplot"
    assert ($b.scatterplot_y_legend(0).text == 'TRBJ1-1'), "Bad legend for scatterplot"
    assert ($b.scatterplot_y_legend(9).text == '?'), "Bad legend for scatterplot"
41
  end
Marc Duez's avatar
Marc Duez committed
42

43
  def test_00_info_point
44
    assert (not $b.div(:id => 'info_timepoint').present?), "Info timepoint should not be present"
45
    $b.info_point.i.click
46
47
48
    assert ($b.div(:id => 'info_timepoint').visible?), "After clicking info timepoint should be visible"

    table = $b.div(:id => 'info_timepoint').table
Marc Duez's avatar
Marc Duez committed
49
50
    assert (table[1][1].text == '786861'), "Incorrect  number of reads in infopoint"
    assert (table[2][1].text.include? '742377'), "Incorrect  number of reads in infopoint"
51
    $b.div(:class => 'data-container').span(:class => 'closeButton').click
Marc Duez's avatar
Marc Duez committed
52
    assert (not $b.div(:id => 'info_timepoint').present?), "Info timepoint should not be present"
53
  end
Marc Duez's avatar
Marc Duez committed
54

Mikaël Salson's avatar
Mikaël Salson committed
55
  def test_01_init
Marc Duez's avatar
Marc Duez committed
56
57
58
59
60
61

      assert ( $b.clone_in_list('25').exists?), ">>fail init : clone 0 missing in list"
      assert ( $b.clone_in_scatterplot('25').exists?), ">>fail init : clone 0 missing in scatterplot"
      #assert ( $b.clone_in_graph('25').exists?), ">>fail init : clone 0 missing in graph"
      assert ( $b.clone_in_list('25').text.include? '0.130%' ) , ">>fail init : wrong clone size "

Mikaël Salson's avatar
Mikaël Salson committed
62
  end
63

Mikaël Salson's avatar
Mikaël Salson committed
64
65
66
67
68
69
70
  def test_02_fold_left_menu
    assert ($b.div(:id => "left-container").present?), ">> fail : left menu should be visible"
    $b.div(:id => "vertical-separator").click
    assert (not $b.div(:id => "left-container").present?), ">> fail : left menu is still visible"
    $b.div(:id => "vertical-separator").click
    assert ($b.div(:id => "left-container").present?), ">> fail : left menu did not reappear"
  end
71

Mikaël Salson's avatar
Mikaël Salson committed
72
  def test_03_rename_clone_by_clicking
Marc Duez's avatar
Marc Duez committed
73
    clone_name = $b.clone_info('25')[:name]
74
75
    assert (clone_name.title == 'TRBV29*01 -1/0/-0 TRBD1*01 -2/0/-5 TRBJ2-5*01'), " >> clone name is not correct : " + clone_name.title
    assert (clone_name.text == 'TRBV29 1//0 D1 2//5 J2-5'), " >> clone short name is not correct : " + clone_name.text
Mikaël Salson's avatar
Mikaël Salson committed
76
    clone_name.double_click
77

78
    $b.clone_name_editor.set 'renamed_click'
Mikaël Salson's avatar
Mikaël Salson committed
79
    $b.clone_name_saver.click
80
    assert (clone_name.text == 'renamed_click'), " >> clone name (click) has not changed"
81
82

    $b.unselect
Mikaël Salson's avatar
Mikaël Salson committed
83
  end
84

Mikaël Salson's avatar
Mikaël Salson committed
85
  def test_04_rename_clone_by_enter
86
    sleep 1
87
    clone_name = $b.clone_info('24')[:name]
Mikaël Salson's avatar
Mikaël Salson committed
88
    clone_name.double_click
89

90
    $b.clone_name_editor.set 'renamed_return'
Mikaël Salson's avatar
Mikaël Salson committed
91
    $b.send_keys :return
92
    assert (clone_name.text == 'renamed_return'), " >> clone name (return) has not changed"
93

Mikaël Salson's avatar
Mikaël Salson committed
94
95
    $b.unselect
  end
96

Mikaël Salson's avatar
Mikaël Salson committed
97
  def check_when_list_or_scatterplot_focused
Marc Duez's avatar
Marc Duez committed
98
99
    assert ( $b.clone_in_scatterplot('25', :class => 'circle_focus').exists?), ">> fail to focus correct plot after hovering a clone in the list"
    assert ( $b.clone_in_graph('25', :class => "graph_focus").exists?), ">> fail to focus correct graphLine after hovering a clone in the list"
100

Marc Duez's avatar
Marc Duez committed
101
    clone_name = $b.clone_info('25')[:name]
Mikaël Salson's avatar
Mikaël Salson committed
102
103
    assert ( $b.infoline.text == clone_name.text), ">> Clone name is not correct in focus div"
  end
Marc Duez's avatar
Marc Duez committed
104

Mikaël Salson's avatar
Mikaël Salson committed
105
106
107
108
  def test_05_focus_in_list
    begin
      $b.unselect
      #test hover a clone in the list
Marc Duez's avatar
Marc Duez committed
109
110
      $b.clone_in_scatterplot('25').wait_until_present
      $b.clone_in_list('25').hover
Mikaël Salson's avatar
Mikaël Salson committed
111
112

      check_when_list_or_scatterplot_focused
Marc Duez's avatar
Marc Duez committed
113
    end
Mikaël Salson's avatar
Mikaël Salson committed
114
  end
115

Mikaël Salson's avatar
Mikaël Salson committed
116
117
118
  def test_05_focus_in_scatterplot
    begin
      $b.unselect
Marc Duez's avatar
Marc Duez committed
119
120
      $b.clone_in_scatterplot('25').wait_until_present
      $b.clone_in_scatterplot('25').hover
121

Mikaël Salson's avatar
Mikaël Salson committed
122
      check_when_list_or_scatterplot_focused
123
    end
Mikaël Salson's avatar
Mikaël Salson committed
124
  end
125

Mikaël Salson's avatar
Mikaël Salson committed
126
  def check_when_list_or_scatterplot_clicked
Marc Duez's avatar
Marc Duez committed
127
    clone_name = $b.clone_info('25')[:name]
128
    assert ( $b.infoline.text == clone_name.title), ">> Clone name is not correct in focus div"
129
    assert ( $b.clone_in_list('25').class_name.include? "list_select" ), ">> Incorrect class name, clone is not selected"
Marc Duez's avatar
Marc Duez committed
130
131
132
    assert ( $b.clone_in_scatterplot('25', :class => "circle_select").exists?)
    assert ( $b.clone_in_graph('25', :class=> "graph_select").exists?)
    assert ( $b.clone_in_segmenter('25').exists? ), ">> fail to add clone to segmenter by clicking on the list or scatterplot"
133

Mikaël Salson's avatar
Mikaël Salson committed
134
135
    stats = $b.statsline
    assert (stats.text.include? '1 clone'), ">> Incorrect stats, should have one clone"
Marc Duez's avatar
Marc Duez committed
136
137
    assert (stats.text.include? '962 reads'), ">> Incorrect stats, should have 962 reads"
    assert (stats.text.include? '0.130%'), ">> Incorrect stats, should be at 0.130%"
Mikaël Salson's avatar
Mikaël Salson committed
138
  end
139

Mikaël Salson's avatar
Mikaël Salson committed
140
141
  def test_08_click_in_list
    #test select a clone in the list
Marc Duez's avatar
Marc Duez committed
142
143
    $b.clone_in_scatterplot('25').wait_until_present
    $b.clone_info('25')[:name].click()
144

Mikaël Salson's avatar
Mikaël Salson committed
145
    check_when_list_or_scatterplot_clicked
146

Mikaël Salson's avatar
Mikaël Salson committed
147
    $b.unselect
148
    assert (not $b.clone_in_list('25').class_name.include? "list_select"), ">> Incorrect class name, clone is not unselected'"
Mikaël Salson's avatar
Mikaël Salson committed
149
  end
150

Mikaël Salson's avatar
Mikaël Salson committed
151
  def test_08_click_in_scatterplot
Marc Duez's avatar
Marc Duez committed
152
153
    $b.clone_in_scatterplot('25').wait_until_present
    $b.clone_in_scatterplot('25').click
154

Mikaël Salson's avatar
Mikaël Salson committed
155
    check_when_list_or_scatterplot_clicked
156

Mikaël Salson's avatar
Mikaël Salson committed
157
    $b.unselect
158
    assert (not $b.clone_in_list('25').class_name.include? "list_select"), ">> Incorrect class name, clone is not unselected'"
Mikaël Salson's avatar
Mikaël Salson committed
159
  end
Marc Duez's avatar
Marc Duez committed
160

Mikaël Salson's avatar
Mikaël Salson committed
161
  def test_09_normalize
Marc Duez's avatar
Marc Duez committed
162
    $b.clone_info('25')[:star].click
Mikaël Salson's avatar
Mikaël Salson committed
163
164
165
    $b.tag_selector_edit_normalisation.wait_until_present
    $b.tag_selector_edit_normalisation.set('0.01')
    $b.tag_selector_normalisation_validator.click 
166
    
Marc Duez's avatar
Marc Duez committed
167
    assert ( $b.clone_info('25')[:size].text == '1.000%' ) , ">> fail normalize on : wrong clone size "
168
    
Mikaël Salson's avatar
Mikaël Salson committed
169
170
    $b.menu_settings.click 
    $b.radio(:id => 'reset_norm').click
Marc Duez's avatar
Marc Duez committed
171
    assert ( $b.clone_info('25')[:size].text == '0.130%' ) , ">> fail normalize off : wrong clone size "
172
173

    $b.unselect
Mikaël Salson's avatar
Mikaël Salson committed
174
175
  end

176
  def test_0a_shortcuts_numpad
177
178
179
    $b.clone_in_scatterplot('25').wait_until_present
    $b.clone_in_scatterplot('25').click

Mathieu Giraud's avatar
Mathieu Giraud committed
180
    assert ($b.preset_selector.selected? "[0] V/J (genes)"), ">> preset selector badly set"
181
    $b.send_keys :numpad2
Mathieu Giraud's avatar
Mathieu Giraud committed
182
    assert ($b.preset_selector.selected? "[2] V/N length"), ">> preset selector not properly changed"
183
184
  end

Mikaël Salson's avatar
Mikaël Salson committed
185
186
  def test_10_imgt
    begin
Marc Duez's avatar
Marc Duez committed
187
188
      $b.clone_in_scatterplot('25').wait_until_present
      $b.clone_in_scatterplot('25').click
Mikaël Salson's avatar
Mikaël Salson committed
189
190
191
192
193
194
      
      $b.span(:id => "toIMGT" ).click
      
      assert ( $b.window(:title => "IMGT/V-QUEST").exists? ) , ">> fail opening IMGT "
      $b.window(:title => "IMGT/V-QUEST").use do
        assert ($b.text.include? "Number of analysed sequences: 1"), ">> fail IMGT analysis"
Marc Duez's avatar
Marc Duez committed
195
196
        assert ($b.text.include? "Homsap TRBV28*01"), ">> IMGT expected V not found"
        assert ($b.text.include? "Homsap TRBJ2-5*01"), ">> IMGT expected J not found"
Mikaël Salson's avatar
Mikaël Salson committed
197
198
      end
      
Mathieu Giraud's avatar
Mathieu Giraud committed
199
      $b.window(:title => "analysis-example").use
Mikaël Salson's avatar
Mikaël Salson committed
200
      
201
202
203
204
205
206
207
208
209
210
211
212
213
      $b.window(:title => "IMGT/V-QUEST").close

      $b.clone_in_scatterplot('26').click
      $b.span(:id => "toIMGT" ).click
      assert ( $b.window(:title => "IMGT/V-QUEST").exists? ) , ">> fail opening second IMGT "

      $b.window(:title => "IMGT/V-QUEST").use do
        assert ($b.text.include? "Number of analysed sequences: 1"), ">> fail IMGT analysis"
        assert ($b.text.include? "Homsap IGHV3-9*01"), ">> IMGT expected V not found"
        assert ($b.text.include? "Homsap IGHJ6*02"), ">> IMGT expected J not found"
      end
      $b.window(:title => "analysis-example").use

Mikaël Salson's avatar
Mikaël Salson committed
214
215
    end
  end
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240

  def test_10bis_imgt_post
    begin
      $b.clone_in_scatterplot('25').click
      $b.span(:id => "toIMGTSeg" ).click
      $b.segmenter_checkbox_imgt_vdj.wait_until_present

      clone_info = $b.clone_info_segmenter('25')
      productive_html = clone_info[:info].map(&:html)
      assert (productive_html.grep(/productive/).any?), "IMGT should tell us the productivity of the sequence"

      clone_segmenter = $b.clone_in_segmenter('25')
      $b.segmenter_checkbox_imgt_vdj.click
      highlights = clone_segmenter.spans(:class => 'highlight_border')
      assert (highlights.size >= 2 && highlights.size <= 3), "We should have the V(D)J genes highlighted, we had %d highlights" % highlights.size
      for h in highlights
        assert (h.style('width').to_i >= 100), "Highlights should have a reasonable width, found to be %s" % h.style('width')
      end

      clone_info[:identity].element(:text => "NaN%").wait_while_present
      assert ((clone_info[:identity].text =~ /^[0-9\.]+%$/) == 0 ), "We should have identity rate (found: %s)" % clone_info[:identity].text

      $b.unselect
    end
  end
Mikaël Salson's avatar
Mikaël Salson committed
241
242
243
244
  
  
  def test_11_igBlast
    begin
Marc Duez's avatar
Marc Duez committed
245
246
      $b.clone_in_scatterplot('25').wait_until_present
      $b.clone_in_scatterplot('25').click
Mikaël Salson's avatar
Mikaël Salson committed
247
248
249
250
251
      
      $b.span(:id => "toIgBlast" ).click
      
      assert ( $b.window(:title => "IgBLAST Search Results").exists? ) , ">> fail opening igblast "
      $b.window(:title => "IgBLAST Search Results").use do
Marc Duez's avatar
Marc Duez committed
252
253
254
        assert ($b.text.include? "Length=180"), ">> igblast: was not launched on the correct sequence"
        assert ($b.text.include? "TRBV28*01"), ">> igblast: expected V not found"
        assert ($b.text.include? "TRBJ2-5*01"), ">> igblast: expected Js not found"
Mikaël Salson's avatar
Mikaël Salson committed
255
      end
256
257
258
259
260
261
262
263
264
265
266
267
268
      $b.window(:title => "IgBLAST Search Results").close

      $b.window(:title => "analysis-example").use


      $b.clone_in_scatterplot('26').click
      $b.span(:id => 'toIgBlast').click
      assert ( $b.window(:title => "IgBLAST Search Results").exists? ) , ">> fail opening second igblast "
      $b.window(:title => "IgBLAST Search Results").use do
        assert ($b.text.include? "Length=318"), ">> igblast: was not launched on the correct sequence"
        assert ($b.text.include? "IGHV3-9*01"), ">> igblast: expected V not found"
        assert ($b.text.include? "IGHJ6*02"), ">> igblast: expected Js not found"
      end
Mikaël Salson's avatar
Mikaël Salson committed
269
      
Mathieu Giraud's avatar
Mathieu Giraud committed
270
      $b.window(:title => "analysis-example").use
271
    end
Mikaël Salson's avatar
Mikaël Salson committed
272
  end
273
274


Mikaël Salson's avatar
Mikaël Salson committed
275
276
  def test_12_tag
    begin
Marc Duez's avatar
Marc Duez committed
277
      $b.clone_info('25')[:star].click
278
279
280
281
      name = $b.tag_item('0')[:name]
      name.wait_until_present
      name.click
      name.wait_while_present
282

Marc Duez's avatar
Marc Duez committed
283
      assert ($b.clone_info('25')[:name].style('color') ==  'rgba(220, 50, 47, 1)' ) , ">> fail tag : clone color hasn't changed"
Marc Duez's avatar
Marc Duez committed
284
    end
Mikaël Salson's avatar
Mikaël Salson committed
285
  end
286
287
288
289
290
291
292
293
294
295
296
297
298
299

  def test_13_export_fasta
    $b.clone_in_scatterplot('77').click
    $b.clone_in_scatterplot('25').click(:control)
    $b.clone_in_scatterplot('88').click(:control)

    $b.menu_item_export_fasta.click
    assert ( $b.window(:title => "").exists? ) , ">> fail opening fasta export "
    $b.window(:title => "").use do
      assert ($b.text.include? ">TRBV29*01 -1/0/-0 TRBD1*01 -2/0/-5 TRBJ2-5*01"), "header name"
      assert ($b.text.include? "YYGGGYYACGYAYAGCGGYGYTTYYCCTYTYTGYTYTGCYAAAYAACYYYYTGTGYCTYTGTGCYGYGTTYCCCGGYYYAAACYCYCYYCCTYG\nGCYAGGYCYGG"), "sequence"
    end
  end

300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
  def test_14_export_sample_report

    assert ($b.scatterplot_x_legend(0).text.include? 'TRB'), "Current system should be TRB"

    # Select a clone
    $b.clone_in_scatterplot('43').click

    $b.menu_item_export('export_sample_report').click

    assert ($b.window(:title => "analysis-example.vidjil – helloworld").exists?), ">> Report didn't show up"

    $b.window(:title => "analysis-example.vidjil – helloworld").use do
      # Check that all loci are there
      assert ($b.element(:id => 'segmentation-report').text.include? "TRA"), "TRA should be present"
      assert ($b.element(:id => 'segmentation-report').text.include? "TRB"), "TRB should be present"
      assert ($b.element(:id => 'segmentation-report').text.include? "TRD"), "TRD should be present"
      assert ($b.element(:id => 'segmentation-report').text.include? "IGH"), "IGH should be present"
      assert (not $b.element(:id => 'segmentation-report').text.include? "TRG"), "TRG should not be present"
      assert (not $b.element(:id => 'segmentation-report').text.include? "IGH+"), "IGH+ should not be present"
      assert ($b.element(:class => 'clone_name').text.include? "TRBV13-1*02 -0/1/-0 TRBD1*01 -6/0/-0 TRBJ1-3*01"), "segmentation should be the one provided in the .vidjil file"

      n_gene = $b.element(:class => 'n_gene', :index => 0)
      # This is true with a 0-based index, which is the case for the vidjil
      # JSON version used
      assert (n_gene.text == 'A'), ("N1 should be A, it is '" + n_gene.text + "'")

      n_gene = $b.element(:class => 'n_gene', :index => 1)
      assert (n_gene.text == ''), ("N2 should be empty, it is '" + n_gene.text + "'")

      assert($b.element(:class => 'j_gene').text == 'YYGYYTYYAATGTYCYYCCYAG')
      assert($b.element(:class => 'v_gene').text == 'YTYTYAYTGGTGCTGGYACCTYAAAYGYYTGYCCTYTGGGYYAGGCYCYYAYACGYAYAYCTYTYCYCTGCTGYATTGGCTYYCCYYAYYYTTTGYCTYTGTGCYGYGTYTGCGGYYTYTGYAAYCGCYYTTTTGYYAGYAGCCGGCY')
    end
    $b.window(:title => "analysis-example.vidjil – helloworld").close

    $b.window(:title => "analysis-example").use

    assert ($b.scatterplot_x_legend(0).text.include? 'TRB'), "Current system should not have changed"

    assert (not $b.element(:class => 'waiting_msg').present?), "The ``generating report'' message should not be present anymore"
  end

341
342
343
344
345
346
347
348
349
350
351
352
353
354
  def test_15_smaller_clones
    for i in 0..3
      smaller = $b.list.li(:index => i)

      assert (smaller.text.include?("smaller clones")), "We should have smaller clones at index %d of the list, instead we have %s " % [i, smaller.text]

      assert (smaller.visible?), "Smaller clones #%d should be visible, it is not" % [i]
      smaller.hover
      assert (smaller.visible?), "Smaller clones #%d should still be visible after hovering it" % [i]

      assert (not $b.clone_in_scatterplot(smaller.id).visible?), "Smaller clone %d should not be visible in scatterplot" % [i]
    end
  end

355
356
357
358
359
360
  def test_16_select_unsegmented
    clone_id = '10'
    $b.clone_in_scatterplot(clone_id).click

    assert ($b.clone_in_segmenter(clone_id).exists?), "Clone %s is not in segmenter" % clone_id
  end
Mikaël Salson's avatar
Mikaël Salson committed
361
362
  

363
  def TODO_test_14_edit_tag
Mikaël Salson's avatar
Mikaël Salson committed
364
    begin
Mathieu Giraud's avatar
Mathieu Giraud committed
365
      ## rename Tag 0
Marc Duez's avatar
Marc Duez committed
366
      $b.clone_info('25')[:star].click
Mathieu Giraud's avatar
Mathieu Giraud committed
367

Mikaël Salson's avatar
Mikaël Salson committed
368
369
370
      edit = $b.tag_item('0')[:edit]
      edit.wait_until_present
      edit.click
Mathieu Giraud's avatar
Mathieu Giraud committed
371
      $b.tag_selector_edit_name.set 'renamed_click'
Mikaël Salson's avatar
Mikaël Salson committed
372
373
      $b.tag_selector_name_validator.click

Mathieu Giraud's avatar
Mathieu Giraud committed
374
375
376
377
378
379
380
      $b.tag_selector_close.click
      $b.tag_selector.wait_while_present

      ## rename Tag 1 (on another clone)
      $b.clone_info('24')[:star].click

      edit = $b.tag_item('1')[:edit]
Marc Duez's avatar
Marc Duez committed
381
382
      edit.wait_until_present
      edit.click
Mathieu Giraud's avatar
Mathieu Giraud committed
383
      $b.tag_selector_edit_name.set 'renamed_return'
Mikaël Salson's avatar
Mikaël Salson committed
384
      $b.send_keys :return
Marc Duez's avatar
Marc Duez committed
385

Mikaël Salson's avatar
Mikaël Salson committed
386
      $b.tag_selector_close.click
Mathieu Giraud's avatar
Mathieu Giraud committed
387
      $b.tag_selector.wait_while_present
Marc Duez's avatar
Marc Duez committed
388

Mathieu Giraud's avatar
Mathieu Giraud committed
389
390
391
392
393
394
395
396
397
398
      ## check renames (on again another clone)
      $b.clone_info('23')[:star].click
      edit = $b.tag_item('1')[:edit]
      edit.wait_until_present

      assert ($b.tag_selector.text.include? 'renamed_click'),  "fail edit tag with mouse : tag name in tag selector hasn't changed"
      assert ($b.tag_selector.text.include? 'renamed_return'), "fail edit tag with keyboard : tag name in tag selector hasn't changed"

      $b.tag_selector_close.click
      $b.tag_selector.wait_while_present
399
    end
Mikaël Salson's avatar
Mikaël Salson committed
400
  end
Marc Duez's avatar
Marc Duez committed
401

402
403
404
  # Not really a test
  def test_zz_close
    close_everything
Mikaël Salson's avatar
Mikaël Salson committed
405
  end
Marc Duez's avatar
Marc Duez committed
406
407
end

Marc Duez's avatar
Marc Duez committed
408
409
410
411
412
413
414
415
416
417
418
419
420
=begin
    TODO
    save_analysis
    clipboard
    edit tag
    change axis scatterplot
    edit name
    change color method
    change color palette
    change scatterplot/graph size
    
    check x/y clone position on scatterplot
    check clone path 
421
=end