1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
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
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
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
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
###############################################################################
# Copyright (c) 2009-2024 by Altair Engineering, Inc.
# All rights reserved.
#
# Altair Engineering, Inc. makes this software available as part of the Vision
# tool platform.  As long as you are a licensee of the Vision tool platform
# you may make copies of the software and modify it to be used within the
# Vision tool platform, but you must include all of this notice on any copy.
# Redistribution without written permission to any third party, with or
# without modification, is not permitted.
# Altair Engineering, Inc. does not warrant that this software is error free
# or fit for any purpose.  Altair Engineering, Inc. disclaims any liability for
# all claims, expenses, losses, damages and costs any user may incur as a
# result of using, copying or modifying the software.
# =============================================================================
#   @userware
#       Functions to Print Data from the Analog Wave Database
#   @section
#       Miscellaneous Userware Examples
#   @description
#       Functions to print parsed data.
#   @files
#       analogWave/print_functions.tcl
#   @example
#       demo/spice/Fig24_30/Fig24_30.sp
#       demo/spice/Fig24_30/Fig24_30.csv
#   @tag
#       gui analog
###############################################################################


# -----------------------------------------------------------------------------
# print_curve_values_iterator_access - In this function we access the curve
#                                      data using an iterator.
#
# The iterator position can be set to a specific position to skip unwanted
# values.
#
# For ordinary variables the x- and y-values are returned as tuple.
# We also compute intermediate points. The returned values are interpolated.
# -----------------------------------------------------------------------------
#
proc print_curve_values_iterator_access {
    output_fp
    section_id
    curve_index
    max_nb_values
} {
    set value_vector {}

    ##
    # Here we create the iterator for a specific curve.
    #
    set iterator [af_wp_curve_value_iterator_define $section_id $curve_index]

    ##
    # The iterator can be advances to a specific position.
    #
    set nb_values [af_wp_find_curve_property $section_id $curve_index \
                        "prop_variable_number_of_values"]
    if {$nb_values > 5} {
        af_wp_curve_value_iterator_go_to_position $iterator 5
    }

    while {$max_nb_values > 0} {
        ##
        # Here we read the value at the iterator's current position.
        # Then the iterator is incremented.
        #
        set value [af_wp_curve_value_iterator_read_next $iterator]
        if {[af_wp_check_is_return_code $value]} {
            ##
            # The last position of the iterator has been reached.
            #
            break
        }
        append value_vector " (" $value ")"
        incr max_nb_values -1
    }

    puts $output_fp "  values $value_vector"

    ##
    # Evaluate curve at intermediate points.
    # The values are interpolated.
    #
    af_wp_curve_value_iterator_go_to_beginning $iterator

    set value_0 [af_wp_curve_value_iterator_read_next $iterator]
    set value_1 [af_wp_curve_value_iterator_read_next $iterator]

    set value_0 [lindex $value_0 0]
    set value_1 [lindex $value_1 0]

    if {[string is double $value_0]  && [string is double $value_1]} {
        set eval_vector {}
        for {set i 0} {$i < 10} {incr i} {
            set value_x [expr {(($i * ($value_1 - $value_0)) * 0.1) + $value_0}]
            set value_y [af_wp_evaluate_curve_value $section_id $curve_index \
                                                    $value_x]
            append eval_vector " (" $value_x " " $value_y ")"
        }
        puts $output_fp "  interpolated values $eval_vector"
    }
    af_wp_release_curve $section_id $curve_index
}


# -----------------------------------------------------------------------------
# print_curve_values_vector_access - In this function we access the curve data
#                                    directly as a vector.performed
# -----------------------------------------------------------------------------
#
proc print_curve_values_vector_access {
    output_fp
    section_id
    curve_index
    max_nb_values
} {
    ##
    # In this function we access the curve data using the function
    # get_curve_value_vector.
    # It returns a Tcl list with a range of values.
    #
    set nb_values [af_wp_find_curve_property $section_id $curve_index \
                                    "prop_variable_number_of_values"]
    if {$nb_values > $max_nb_values} {
        set nb_values $max_nb_values
    }
    set values_vector [af_wp_get_curve_value_vector $section_id \
                                                    $curve_index 0 $nb_values]
    puts $output_fp "  values $values_vector"
    af_wp_release_curve $section_id $curve_index
}


# -----------------------------------------------------------------------------
# print_instance_subinstances - In this function we traverse and print the
#                               sub-instances of an instance.
#
# The sub-instances are instances themselves. This defines a complete curve
# hierarchy.
# -----------------------------------------------------------------------------
#
proc print_instance_subinstances {output_fp section_id instance_index} {
    ##
    # An instance contains a vector of sub-instances and curves.
    # Here we traverse and print the sub-instance list.
    #
    set subinstances {}
    set nb_subinstances [af_wp_find_instance_property $section_id \
                        $instance_index "prop_instance_number_of_sub_instances"]
    if {$nb_subinstances > 0} {
        for {set sub_inst_index 0} \
            {$sub_inst_index<$nb_subinstances} \
            {incr sub_inst_index} \
        {
            set sub_inst [af_wp_get_sub_instance_index $section_id \
                                                $instance_index $sub_inst_index]
            append subinstances " " $sub_inst
        }
        puts $output_fp "  sub instances $subinstances"
    }
}


# -----------------------------------------------------------------------------
# print_instance_variables - In this function we traverse and print the curves
#                            of an instance.
#
# The sub-instances are instances themselves. This defines a complete curve
# hierarchy.
# -----------------------------------------------------------------------------
#
proc print_instance_variables {output_fp section_id instance_index} {
    ##
    # An instance contains a vector of sub-instances and curves.
    # Here we traverse and print the curve list.
    #
    set variables {}
    set nb_variables [af_wp_find_instance_property $section_id $instance_index \
                                    "prop_instance_number_of_variables"]
    if {$nb_variables > 0} {
        for {set var_index 0} {$var_index<$nb_variables} {incr var_index} {
            set var [af_wp_get_instance_curve_index $section_id \
                                                    $instance_index $var_index]
            append variables " " $var
        }
        puts $output_fp "  variables $variables"
    }
}


# -----------------------------------------------------------------------------
# print_instance_properties - In this function we traverse and print all
#                             instance properties for a given instance.
# -----------------------------------------------------------------------------
#
proc print_instance_properties {output_fp section_id instance_index} {
    ##
    # All access to instance data must use the section identifier and the
    # instance index.
    #
    for {set property_index 0} {$property_index<1000} {incr property_index} {
        ##
        # This function is called for property_index = 0, 1, ....
        # until it returns a string
        # which is a return code.
        #
        set prop [af_wp_get_instance_property $section_id $instance_index \
                                                $property_index]
        if {[af_wp_check_is_return_code $prop]} {
            break
        }
        puts $output_fp "     prop #$property_index == $prop"
    }
}


# -----------------------------------------------------------------------------
# print_curve_properties - In this function we traverse and print all curve
#                          properties for a curve given by it's section_id and
#                          curve_index.
# -----------------------------------------------------------------------------
#
proc print_curve_properties {output_fp section_id curve_index} {
    ##
    # All access to curve data must use the section identifier and the curve
    # index.
    #
    for {set property_index 0} {$property_index<1000} {incr property_index} {
        ##
        # This function is called for property_index = 0, 1, ....
        # until it returns a string
        # which is a return code.
        #
        set prop [af_wp_get_curve_property $section_id $curve_index \
                                            $property_index]
        if {[af_wp_check_is_return_code $prop]} {
            break
        }
        puts $output_fp "     prop #$property_index == $prop"
    }
}


# -----------------------------------------------------------------------------
# print_section_properties - In this function we traverse and print all section
#                            properties for a section given by it's section_id.
# -----------------------------------------------------------------------------
#
proc print_section_properties {output_fp section_id} {
    ##
    # All access to section data must use the section identifier.
    #
    for {set property_index 0} {$property_index<1000} {incr property_index} {
        ##
        # This function is called for property_index = 0, 1, ....
        # until it returns a string
        # which is a return code.
        #
        set prop [af_wp_get_section_property $section_id $property_index]
        if {[af_wp_check_is_return_code $prop]} {
            break
        }
        puts $output_fp "     prop #$property_index == $prop"
    }
}


# -----------------------------------------------------------------------------
# print_global_properties - In this function we traverse and print all global
#                           properties.
# -----------------------------------------------------------------------------
#
proc print_global_properties {output_fp} {
    for {set property_index 0} {$property_index<1000} {incr property_index} {
        set prop [af_wp_get_global_property $property_index]
        if {[af_wp_check_is_return_code $prop]} {
            break
        }
        puts $output_fp "     global prop #$property_index == $prop"
    }
}


# -----------------------------------------------------------------------------
# print_section - In this function we traverse and print all data that is
#                 available for a section defined by it's section_id.
# -----------------------------------------------------------------------------
#
proc print_section {output_fp section_index max_nb_values} {
    ##
    # The section_id must be used instead of section_index to access all data.
    #
    set section_id [af_wp_get_section_identifier $section_index]

    puts $output_fp "---------- section ID : ${section_id}"

    ##
    # Print all properties associated to the section.
    #
    print_section_properties $output_fp $section_id

    set nb_sweep_variables [af_wp_find_section_property $section_id \
                                    "prop_section_number_of_sweep_variables"]
    set nb_all_variables [af_wp_find_section_property $section_id \
                                    "prop_section_total_number_of_variables"]
    set nb_instances [af_wp_find_section_property $section_id \
                                    "prop_section_number_of_instances"]

    ##
    # Print information on sweep variables.
    # In most cases there is just 1 sweep variable.
    #
    puts $output_fp "$nb_sweep_variables sweep variables :"
    for {set curve_index 0} \
        {$curve_index<$nb_sweep_variables} \
        {incr curve_index} \
    {
        puts $output_fp "---------- curve #${curve_index}"
        print_curve_properties $output_fp $section_id $curve_index
        print_curve_values_vector_access $output_fp $section_id $curve_index \
                                                                $max_nb_values
        print_curve_values_iterator_access $output_fp $section_id $curve_index \
                                                                $max_nb_values
    }

    ##
    # Print information on the ordinary variables.
    #
    puts $output_fp "$nb_all_variables variables"
    for {set curve_index $nb_sweep_variables} \
        {$curve_index<$nb_all_variables} \
        {incr curve_index} \
    {
        puts $output_fp "---------- curve #${curve_index}"
        print_curve_properties $output_fp $section_id $curve_index
        print_curve_values_vector_access $output_fp $section_id $curve_index \
                                                                $max_nb_values
        print_curve_values_iterator_access $output_fp $section_id $curve_index \
                                                                $max_nb_values
    }

    ##
    # If instances have been defined, we traverse these instances and print the
    # associated sub-instances and curves.
    #
    puts $output_fp "$nb_instances instances"
    for {set instance_index 0} \
        {$instance_index<$nb_instances} \
        {incr instance_index} \
    {
        puts $output_fp "---------- instance #${instance_index}"
        print_instance_properties $output_fp $section_id $instance_index
        print_instance_subinstances $output_fp $section_id $instance_index
        print_instance_variables $output_fp $section_id $instance_index
    }
}


# -----------------------------------------------------------------------------
# print_type_properties - In this function we traverse and print all type
#                         properties for a type given by it's type_index.
# -----------------------------------------------------------------------------
#
proc print_type_properties {output_fp type_index} {
    for {set property_index 0} {$property_index<1000} {incr property_index} {
        ##
        # This function is called for property_index = 0, 1, ....
        # until it returns a string
        # which is a return code.
        #
        set prop [af_wp_get_type_property $type_index $property_index]
        if {[af_wp_check_is_return_code $prop]} {
            break
        }
        puts $output_fp "     prop #$property_index == $prop"
    }
}


# -----------------------------------------------------------------------------
# print_type - In this function we traverse and print all data that is
#              available for a type defined by it's index.
# -----------------------------------------------------------------------------
#
proc print_type {output_fp type_index} {
    puts $output_fp "---------- type #$type_index"

    ##
    # Print all properties associated to the section.
    #
    print_type_properties $output_fp $type_index

    set sub_types {}
    set sub_type_names {}
    set nb_sub_types [af_wp_find_type_property $type_index \
                                               "prop_type_number_of_sub_types"]
    if {$nb_sub_types > 0} {
        for {set sub_type_index 0} \
            {$sub_type_index<$nb_sub_types} \
            {incr sub_type_index} \
        {
            set sub_type [af_wp_get_sub_type_index $type_index $sub_type_index]
            append sub_types " " $sub_type
            set sub_type_name [af_wp_find_type_property $sub_type \
                                                        "prop_type_name"]
            append sub_type_names  " " $sub_type_name
        }
        puts $output_fp "  sub_types : $sub_types"
        puts $output_fp "  sub_type_names : $sub_type_names"
    }
}


# -----------------------------------------------------------------------------
# print_data - In this function we traverse and print all data that is
#              available for all sections.
#
# The parameter max_nb_values limits the number of curve values that is printed
# to the screen.
# -----------------------------------------------------------------------------
#
proc print_data {output_fp max_nb_values} {
    ##
    # Several files can be parsed. Each file generates a data section.
    # Some files might  generate several data sections.
    #
    set nb_sections [af_wp_get_number_of_sections]

    ##
    # We traverse the data sections and print every information they contain.
    #
    for {set section_index 0} \
        {$section_index < $nb_sections} \
        {incr section_index} \
    {
        print_section $output_fp $section_index $max_nb_values
    }

    ##
    # Several types have been generated when parsing the files.
    #
    set nb_types [af_wp_find_global_property "prop_global_number_of_types"]
    puts $output_fp "number of types : $nb_types"

    ##
    # We traverse the types and print every information they contain.
    #
    for {set type_index 0} {$type_index<$nb_types} {incr type_index} {
        print_type $output_fp $type_index
    }
}


# -----------------------------------------------------------------------------
# print_search_results - In this function we access the results of a curve
#                        search.
# -----------------------------------------------------------------------------
#
proc print_search_results {output_fp search_string search_results} {
    puts $output_fp "------- List of search results"
    puts $output_fp "  obtained for the search string \"$search_string\""

    set nb_results [llength $search_results]
    set i 0
    while {$i<$nb_results} {
        set section_id [lindex $search_results $i]
        incr i
        set curve_index [lindex $search_results $i]
        incr i

        set section_name [af_wp_find_section_property $section_id \
                                                      "prop_section_name"]
        set is_sweep_variable [af_wp_find_curve_property $section_id \
                                    $curve_index "prop_variable_sweep_variable"]
        if {$is_sweep_variable == 1} {
            ##
            # a sweep variable might not have a name, take the unit instead
            #
            set variable_name [af_wp_find_curve_property $section_id \
                                    $curve_index "prop_variable_y_axis_unit"]
        } else {
            set variable_name [af_wp_find_curve_property $section_id \
                                            $curve_index "prop_variable_name"]
        }

        set    txt "  section == \"$section_name\", variable_name = "
        append txt "\"$variable_name\"."
        puts $output_fp $txt
    }
}


# -----------------------------------------------------------------------------
# print_referenced_files - In this function we traverse all sections and curves.
#                          If a curve contains information on referenced files
#                          this information is printed.
# -----------------------------------------------------------------------------
#
proc print_referenced_files {output_fp} {
    set nb_sections [af_wp_get_number_of_sections]

    ##
    # We traverse the data sections
    #
    for {set section_index 0} \
        {$section_index < $nb_sections} \
        {incr section_index} \
    {
        set section_id [af_wp_get_section_identifier $section_index]
        set nb_all_variables [af_wp_find_section_property $section_id \
                                    "prop_section_total_number_of_variables"]

        ##
        # we traverse the variables
        #
        for {set var_index 0} {$var_index<$nb_all_variables} {incr var_index} {
            puts $output_fp "== variable $var_index"

            ##
            # we retrieve the type_index associated to the curve
            #
            set type_index [af_wp_find_curve_property $section_id $var_index \
                                            "prop_variable_y_axis_type_index"]
            if {$type_index >= 0} {
                ##
                # we search for the field 'dataFile' in the type of the curve
                #       we will only get a valid index if the data type is a
                # 'data_scalar_struct' data type and the field 'dataFile'
                # exists.
                #
                set type_field [af_wp_find_type_struct_field_position \
                                                        $type_index "dataFile"]

                ##
                # check if type_field is valid
                #
                if {$type_field >= 0} {
                    ##
                    # create an iterator for the curve and go to the
                    # appropriate position
                    #
                    set iterator [af_wp_curve_value_iterator_define \
                                                        $section_id $var_index]
                    af_wp_curve_value_iterator_go_to_position $iterator \
                                                              $type_field

                    ##
                    # read the value of the curve for the struct field
                    # 'dataFile'
                    #
                    set value [af_wp_curve_value_iterator_read_next $iterator]
                    if {! [af_wp_check_is_return_code $value]} {
                        ##
                        # the iterator returned a valid entry => print it
                        #
                        set value_y [lindex $value 1]
                        set    txt "the curve $var_index in section $section_id"
                        append txt "references the file \"$value_y\""
                        puts $output_fp $txt
                    }

                    ##
                    # destroy the iterator
                    #
                    af_wp_curve_value_iterator_release $iterator
                }
            }
        }
    }
}


# -----------------------------------------------------------------------------
# print_sweep_hierarchy - In this function we traverse all sections.
#                         We print all run parameters and parent sections.
#
# This information might be important if results from a parameter sweep are
# parsed.
# -----------------------------------------------------------------------------
#
proc print_sweep_hierarchy {output_fp} {
    ##
    # Several files can be parsed. Each file generates a data section.
    # Some files might generate several data sections.
    #
    set nb_sections [af_wp_get_number_of_sections]

    ##
    # We traverse the data sections
    #
    for {set section_index 0} \
        {$section_index<$nb_sections} \
        {incr section_index} \
    {
        set section_id [af_wp_get_section_identifier $section_index]
        set parent_section_id [af_wp_find_section_property $section_id \
                                            "prop_section_parent_section_id"]

        if {[string is integer $parent_section_id]} {
            set    txt "     the section $section_id has the parent section "
            append txt "$parent_section_id."
        } else {
            set txt "     the section $section_id has no parent section."
        }
        puts $output_fp $txt

        for {set property_index 0} \
            {$property_index < 1000} \
            {incr property_index} \
        {
            ##
            # This function is called for property_index = 0, 1, ....
            # until it returns a string
            # which is a return code.
            #
            set prop [af_wp_get_section_property $section_id $property_index]
            if {[af_wp_check_is_return_code $prop]} {
                break
            }
            set prop_name [lindex $prop 0]
            if {[string first "_run_parameter" $prop_name] >= 0} {
                set prop_value [lindex $prop 1]
                set    txt "     prop #${property_index} ${prop_name} "
                append txt "== ${prop_value}"
                puts $output_fp $txt
            }
        }
    }
}