File: __init__.py

package info (click to toggle)
pyferret 7.6.5-10
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 138,136 kB
  • sloc: fortran: 240,609; ansic: 25,235; python: 24,026; sh: 1,618; makefile: 1,123; pascal: 569; csh: 307; awk: 18
file content (997 lines) | stat: -rw-r--r-- 41,451 bytes parent folder | download | duplicates (4)
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
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
"""
A Python module for running Ferret.
For running the Ferret engine that is part of this module:
    init or start must first be called to initialize Ferret
    resize can be used to reset the maximum amount of memory
            that can be allocated for Ferret data
    run is used to submit individual Ferret commands or enter
            into Ferret's command prompting mode
    stop can be used to shutdown Ferret and free any allocated
            memory.

The FERR_* values are the possible values of err_int in the return
values from the run command.  The err_int return value FERR_OK
indicates no errors.

To transfer data and metadata between the Ferret engine and Python,
see the help message for pyferret.datamethods, whose methods are
imported into the pyferret module.

For writing Ferret external functions in Python, see the help message
for pyferret.pyefmethods, whose methods are imported into the pyferret
module.

The FerRegion, FerAxis, FerGrid, FerVar, FerPyVar, and FerDSet objects
assist in working with the Ferret engine in a Python environment,
reducing the need to know the Ferret language and syntax.

The convenience methods for executing common Ferret commands are found
under pyferret.fermethods and are imported into the pyferret module.
These methods also help reduce the need to know the Ferret language
and syntax.
"""

from __future__ import print_function


import sys
import os
import atexit
try:
    import rlcompleter
except ImportError:
    pass
import readline

# In Debian, an application should be able to start without environmental
# variables needing to be set. So set them here.
if os.environ.get('FER_GO') is None:
    os.environ['FER_GO'] = '/usr/share/ferret-vis/jnls/go'
if os.environ.get('FER_DATA') is None:
    os.environ['FER_DATA'] = '/usr/share/ferret-vis/data'
if os.environ.get('FER_DESCR') is None:
    os.environ['FER_DESCR'] = '/usr/share/ferret-vis/descr'
if os.environ.get('FER_GRIDS') is None:
    os.environ['FER_GRIDS'] = '/usr/share/ferret-vis/grids'
if os.environ.get('FER_MODEL_RUNS') is None:
    os.environ['FER_MODEL_RUNS'] = '/usr/share/ferret-vis/model_runs'
if os.environ.get('FER_LIBS') is None:
    os.environ['FER_LIBS'] = '/usr/lib/ferret-vis/efmem:/usr/lib/ferret-vis/external_functions'
if os.environ.get('FER_PALETTE') is None:
    os.environ['FER_PALETTE'] = '/usr/share/ferret-vis/ppl/palettes'
if os.environ.get('FER_FONTS') is None:
    os.environ['FER_FONTS'] = '/usr/share/ferret-vis/ppl/fonts'
if os.environ.get('FER_DSETS') is None:
    os.environ['FER_DSETS'] = '/usr/share/ferret-vis/datasets'
if os.environ.get('TMAP') is None:
    os.environ['TMAP'] = '/usr/share/ferret-vis/fmt'
if os.environ.get('SPECTRA') is None:
    os.environ['SPECTRA'] = '/usr/share/ferret-vis/ppl'
if os.environ.get('PLOTFONTS') is None:
    os.environ['PLOTFONTS'] = '/usr/share/ferret-vis/ppl/fonts'



from pyferret import libpyferret
# also import everything (not starting with an underscore) from libpyferret
# so constants in that module are seen as part of this module
from pyferret.libpyferret import *

# methods for transferring data between the Ferret engine and Python
from pyferret import datamethods
# also import the methods given in datamethods into pyferret
from pyferret.datamethods import *

# methods to assist in writing Ferret external functions written in Python
from pyferret import pyefmethods
# also import the methods given in pyefmethods into pyferret
from pyferret.pyefmethods import *

# the Fer... objects for working with Ferret from Python
from pyferret import ferregion
from pyferret.ferregion import *
from pyferret import feraxis
from pyferret.feraxis import *
from pyferret import fergrid
from pyferret.fergrid import *
from pyferret import fervar
from pyferret.fervar import *
from pyferret import ferpyvar
from pyferret.ferpyvar import *
from pyferret import ferdset
from pyferret.ferdset import *
from pyferret import feraggdset
from pyferret.feraggdset import *
from pyferret import ferfmrcdset
from pyferret.ferfmrcdset import *
from pyferret import ferfmrcvar
from pyferret.ferfmrcvar import *

# Create "the" anonymous dataset
anondset = FerDSet('', qual=ferdset._anonymous_dataset_qualifier)

# convenience methods for executing common Ferret commands
from pyferret import fermethods
from pyferret.fermethods import *

# bindings for the PyQt-based graphics engines
import pipedviewer.pyferretbindings
try:
    # the one-time setting of multiprocessing start method, 
    # if supported, set to spawn to avoid Qt issues
    import multiprocessing
    multiprocessing.set_start_method('spawn')
except:
    pass

from pyferret import graphbind
from pyferret import regrid


def _addtoenvdirlist(envname, dirname):
    """
    Adds the directory path given by dirname to the list of directory
    paths given in the environment variable envname.  The directory 
    path is added to the beginning of the environment value, but 
    immediately after '.'  if that is the first directory in the list.
    If the environment variable given in envname does not exist, it 
    is initialized to '.' before adding the given directory path. 
    No checking or modification of the directory path is performed.
    """
    currval = os.getenv(envname, '.')
    # Spaces in directory names are a problem for ferret 
    # so do not worry about it here. 
    dirlist = currval.split()
    if dirlist[0] == '.':
        dirlist.insert(1, dirname)
    else:
        dirlist.insert(0, dirname);
    os.environ[envname] = ' '.join(dirlist)


def addenv(FER_DIR=None, FER_DAT=None, FER_DATA=None, FER_DESCR=None, 
           FER_GRIDS=None, FER_GO=None, FER_FONTS=None, FER_PALETTE=None):
    """
    A convenience method that adds the specified directory paths to the 
    current Ferret environment variables in the current Python session. 
    Each value should be a single directory path.  More directories can 
    be added to an environment variable, if appropriate, by calling this 
    method again.  

    Except for FER_DIR, FER_DAT, and FER_FONTS (see below), the directory 
    specified will be added to the beginning of the list of directory paths 
    given by the environment variable, but immediately after '.' (which 
    represents the current working directory) if that is the first directory 
    in the list.  If an enviroment variable is not defined, it will be 
    initialized to '.' before adding the given directory path.

    The value for FER_DIR, FER_DAT or FER_FONTS, if specified, replaces 
    the current value (if any) for these environment variables. (These 
    values are each suppose to be a single directory path).  

    The value for FER_DIR (which actually is not used directly in PyFerret)
    is also used to construct directory paths to be added, if the subdirectory 
    exists, to the enviroment variables: 
        FER_GO ("$FER_DIR/go"), 
        FER_PALETTE ("$FER_DIR/ppl"), 
        FER_FONTS ("$FER_DIR/ppl/fonts"), and 
        LD_LIBRARY_PATH ("$FER_DIR/lib/pythonX.x/site-packages/pyferret", 
                         where X and x are the major and minor version 
                         numbers of this python). 
    These directory paths will be added prior to any directories specified 
    by other arguments.

    The value for FER_DAT (which actually is not used directly in PyFerret) 
    is also used to construct directory paths to be added, if the subdirectory 
    exists, to the environment variables:
        FER_DATA ("$FER_DAT/data"),
        FER_DESCR ("$FER_DAT/descr"), and
        FER_GRIDS ("$FER_DAT/grids")
    These directory paths will be added prior to any directories specified 
    by other arguments.

    Directory paths can use '~/' and '~user/' constructs, as well as shell 
    variables of the form '$var' and '${var}'.  Relative paths can also be 
    specified and will be used as-is (they are not converted to absolute 
    paths).

    Use os.environ to reset a Ferret environment variable to some specific
    value; for example, 
        os.environ['FER_DATA'] = '. /path/to/my/datasets'

    To replicate setting most of the environment variables assigned by the 
    ferret_paths scripts, call this method with the FER_DIR and FER_DAT
    arguments assigned the values used in generating the ferret_paths
    scripts.  So a python session using pyferret without using the 
    ferret_paths scripts will first require adding the 
        pyferret/lib/pythonX.x/site-packages 
    directory path, if not in a standard python location, to either the 
    shell environment variable PYTHONPATH or the Python list of paths given 
    in sys.path so the pyferret module can be found.  The rest of the
    session will look something like:
        import pyferret
        pyferret.addenv(FER_DIR='/path/to/pyferret/dir', 
                        FER_DAT='/path/to/ferret/datasets/dir')
        pyferret.start()
    """
    if FER_DIR:
        myferdir = os.path.expandvars(os.path.expanduser(FER_DIR))
        if not os.path.isdir(myferdir):
            raise ValueError('FER_DIR is given but is not a directory: %s' % myferdir)
        os.environ['FER_DIR'] = myferdir
        # Set FER_FONTS to ppl/fonts subdir
        myferfonts = os.path.join(myferdir, 'ppl', 'fonts')
        if os.path.isdir(myferfonts):
            os.environ['FER_FONTS'] = myferfonts
        # Add go subdir to FER_GO
        dirtoadd = os.path.join(myferdir, 'go')
        if os.path.isdir(dirtoadd):
            _addtoenvdirlist('FER_GO', dirtoadd)
        # Add ppl subdir to FER_PALETTE
        dirtoadd = os.path.join(myferdir, 'ppl')
        if os.path.isdir(dirtoadd):
            _addtoenvdirlist('FER_PALETTE', dirtoadd)
        # Add lib/pythonX.x/site-packages/pyferret subdir to LD_LIBRARY_PATH
        # but separate with appropriate separator (':') and do not worry about '.'
        dirtoadd = os.path.join(myferdir, 'lib', 'python%d.%d' % sys.version_info[:2], 
                                'site-packages', 'pyferret')
        currlist = os.getenv('LD_LIBRARY_PATH')
        if not currlist:
            os.environ['LD_LIBRARY_PATH'] = dirtoadd
        else:
            os.environ['LD_LIBRARY_PATH'] = dirtoadd + os.pathsep + currlist
    if FER_DAT:
        myferdat = os.path.expandvars(os.path.expanduser(FER_DAT))
        if not os.path.isdir(myferdat):
            raise ValueError('FER_DAT is given but is not a directory: %s' % myferdat)
        os.environ['FER_DAT'] = myferdat
        # Add data subdir to FER_DATA
        dirtoadd = os.path.join(myferdat, 'data')
        if os.path.isdir(dirtoadd):
            _addtoenvdirlist('FER_DATA', dirtoadd)
        # Add descr subdir to FER_DESCR
        dirtoadd = os.path.join(myferdat, 'descr')
        if os.path.isdir(dirtoadd):
            _addtoenvdirlist('FER_DESCR', dirtoadd)
        # Add grids subdir to FER_GRIDS
        dirtoadd = os.path.join(myferdat, 'grids')
        if os.path.isdir(dirtoadd):
            _addtoenvdirlist('FER_GRIDS', dirtoadd)
    if FER_FONTS:
        myferfonts = os.path.expandvars(os.path.expanduser(FER_FONTS))
        if not os.path.isdir(myferfonts):
            raise ValueError('FER_FONTS is given but is not a directory: %s' % myferfonts)
        os.environ['FER_FONTS'] = myferfonts
    if FER_GO:
        dirtoadd = os.path.expandvars(os.path.expanduser(FER_GO))
        if not os.path.isdir(dirtoadd):
            raise ValueError('FER_GO is given but is not a directory: %s' % dirtoadd)
        _addtoenvdirlist('FER_GO', dirtoadd)
    if FER_PALETTE:
        dirtoadd = os.path.expandvars(os.path.expanduser(FER_PALETTE))
        if not os.path.isdir(dirtoadd):
            raise ValueError('FER_PALETTE is given but is not a directory: %s' % dirtoadd)
        _addtoenvdirlist('FER_PALETTE', dirtoadd)
    if FER_DATA:
        dirtoadd = os.path.expandvars(os.path.expanduser(FER_DATA))
        if not os.path.isdir(dirtoadd):
            raise ValueError('FER_DATA is given but is not a directory: %s' % dirtoadd)
        _addtoenvdirlist('FER_DATA', dirtoadd)
    if FER_DESCR:
        dirtoadd = os.path.expandvars(os.path.expanduser(FER_DESCR))
        if not os.path.isdir(dirtoadd):
            raise ValueError('FER_DESCR is given but is not a directory: %s' % dirtoadd)
        _addtoenvdirlist('FER_DESCR', dirtoadd)
    if FER_GRIDS:
        dirtoadd = os.path.expandvars(os.path.expanduser(FER_GRIDS))
        if not os.path.isdir(dirtoadd):
            raise ValueError('FER_GRIDS is given but is not a directory: %s' % dirtoadd)
        _addtoenvdirlist('FER_GRIDS', dirtoadd)


def addpath(newdir):
    """
    A convenience method that replicates the Ferret Faddpath script by 
    adding the given directory to the environment variables FER_GO, 
    FER_DATA, FER_DESCR, and FER_GRIDS in the current Python session. 
    """
    addenv(FER_GO=newdir, FER_DATA=newdir, FER_DESCR=newdir, FER_GRIDS=newdir)


pyferret_help_message = \
"""

    Usage:  pyferret  [-memsize <N>]  [-nodisplay]  [-png]  [-nojnl]  [-noverify]
                      [-secure]  [-server]  [-python]  [-version]  [-help]
                      [-quiet]  [-linebuffer]  [-script <scriptname> [ <scriptarg> ... ]]

       -memsize:     maximum amount of memory that can be allocated for Ferret data 
                     in mega (10^6) floats (where 1 float = 8 bytes); default is 125 == 1Gb

       -nodisplay    do not display to the console; a drawing can be saved using the 
                     FRAME command in any of the supported file formats.  The /QUALITY 
                     option of SET WINDOW will be ignored when this is specified.

       -png          do not display to the console and only raster (PNG) images can be 
                     saved.  Implies -nodisplay and removes support for deletion of 
                     parts (segments) of a plot; however, plots will be generated faster.

       -nojnl:       on startup do not open a journal file (can be turned on later with 
                     SET MODE JOURNAL)

       -noverify:    on startup turn off verify mode (can be turned on later with 
                     SET MODE VERIFY)

       -secure:      restrict Ferret's capabilities (e.g., SPAWN and EXIT /TOPYTHON 
                     are not permitted)

       -server:      run in server mode (don't stop on message commands)

       -python:      start at the Python prompt instead of the Ferret prompt.
                     The Ferret prompt can be obtained using 'pyferret.run()'

       -version:     print the Ferret header with version number and quit

       -help:        print this help message and quit

       -quiet        do not display the startup header

       -linebuffer   print each line of output or error messages as soon as a full 
                     line is written.  Useful when redirecting both types of messages 
                     to a single file.
                     Note:
                       the environment variable GFORTRAN_UNBUFFERED_PRECONNECTED
                       needs to be set to 1 in order to unbuffer the Fortran
                       units for output and error messages

       -script:      execute the script with any arguments specified and exit. 
                     (THIS MUST BE SPECIFIED LAST.)  The -script option also implies 
                     the -nojnl, -noverify, -server, and -quiet options.

       Deprecated command-line options:

           -gif:         this option is now an alias for -png

           -unmapped:    this option is now an alias for -nodisplay

           -batch:       name of file to draw to (default "ferret.png") instead of 
                         displaying to the console.  The file format will be guessed 
                         from the filename extension.  When using this option, new 
                         windows should not be created and the FRAME command should 
                         not be used.

           -transparent: use a transparent background instead of opaque white when 
                         saving to the file given by -batch

        Use of -batch and -transparent options is strongly discouraged.  Instead,
        use the -nodisplay option and the FRAME /FILE=<filename> [ /TRANSPARENT ]
        Ferret command.

"""

def init(arglist=None, enterferret=True):
    """
    Interprets the traditional Ferret options given in arglist and calls 
    pyferret.start appropriately.  Detailed information about the strings 
    that can be given in arglist can be obtained by printing the 
    pyferret.pyferret_help_message string. 

    If '-script' is given with a script filename, this method calls the 
    pyferret.run method with the Ferret go command, the script filename, 
    and any arguments, then exits completely (exits python).

    Otherwise, if enterferret is False, this method just returns the success 
    return value of the run method: (FERR_OK, '')

    If enterferret is True (unless '-python' is given in arglist) this routine 
    calls the run method with no arguments in order to enter into Ferret 
    command-line processing.  The value returned from call to the run method 
    is then returned when the Ferret command EXIT /TOPY is made.
    """

    my_metaname = None
    my_transparent = False
    my_unmapped = False
    my_pngonly = False
    my_memsize = 125
    my_journal = True
    my_verify = True
    my_restrict = False
    my_server = False
    my_quiet = False
    my_linebuffer = False
    my_enterferret = enterferret
    script = None
    # To be compatible with traditional Ferret command-line options
    # (that are still supported), we need to parse the options by hand.
    if arglist:
        print_help = False
        just_exit = False
        try:
            k = 0
            while k < len(arglist):
                opt = arglist[k]
                if opt == "-memsize":
                    k += 1
                    try:
                        my_memsize = float(arglist[k])
                    except:
                        raise ValueError("a positive number must be given for a -memsize value")
                    if my_memsize <= 0.0:
                        raise ValueError("a positive number must be given for a -memsize value")
                elif opt == "-batch":
                    my_metaname = "ferret.png"
                    k += 1
                    # -batch has an optional argument
                    try:
                        if arglist[k][0] != '-':
                            my_metaname = arglist[k]
                        else:
                            k -= 1
                    except:
                        k -= 1
                elif opt == "-transparent":
                    my_transparent = True
                elif opt == "-nodisplay":
                    my_unmapped = True
                elif opt == "-unmapped":
                    my_unmapped = True
                elif opt == "-png":
                    my_unmapped = True
                    my_pngonly = True
                elif opt == "-gif":
                    my_unmapped = True
                    my_pngonly = True
                elif opt == "-nojnl":
                    my_journal = False
                elif opt == "-noverify":
                    my_verify = False
                elif opt == "-secure":
                    my_restrict = True
                elif opt == "-server":
                    my_server = True
                elif opt == "-quiet":
                    my_quiet = True
                elif opt == "-linebuffer":
                    my_linebuffer = True
                elif opt == "-python":
                    my_enterferret = False
                elif opt == "-version":
                    just_exit = True
                    break
                elif (opt == "-help") or (opt == "-h") or (opt == "--help"):
                    print_help = True
                    break
                elif opt == "-script":
                    my_journal = False
                    my_verify = False
                    my_server = True
                    my_quiet = True
                    k += 1
                    try:
                        script = arglist[k:]
                        if len(script) == 0:
                            raise ValueError("a script filename must be given for the -script value")
                    except:
                        raise ValueError("a script filename must be given for the -script value")
                    break
                else:
                    raise ValueError("unrecognized option '%s'" % opt)
                k += 1
        except ValueError as errmsg:
            # print the error message, then print the help message
            print("\n%s" % errmsg, file=sys.stderr)
            print_help = True
        if print_help:
            # print the help message, then mark for exiting
            print(pyferret_help_message, file=sys.stderr)
            just_exit = True
        if just_exit:
            # print the ferret header then exit completely
            if not start(journal=False, verify=False, unmapped=True):
                raise ValueError('pyferret has already been started')
            result = run("exit /program")
            # should not get here
            raise SystemExit

    # start ferret
    if not start(memsize=my_memsize, journal=my_journal, verify=my_verify,
                 restrict=my_restrict, server=my_server, unmapped=my_unmapped,
                 pngonly=my_pngonly, quiet=my_quiet, linebuffer=my_linebuffer,
                 metaname=my_metaname, transparent=my_transparent):
        raise ValueError("pyferret has already been started")

    # if a command-line script is given, run the script and exit completely
    if script != None:
        # put double quotes around every script argument
        script_line = '"' + '" "'.join(script) + '"'
        try:
            result = run('go ' + script_line)
        except:
            print(" **Error: exception raised in running script %s" % script_line, file=sys.stderr)
        # force shutdown
        result = run('exit /program')
        # should not get here
        raise SystemExit

    if my_restrict or my_enterferret:
        # go into Ferret command-line processing until "exit /topy" (if not restricted) or "exit /program"
        result = run()
    else:
        # if they don't want to enter ferret, just return the success value from run
        result = (libpyferret.FERR_OK, '')
    return result


def start(memsize=125, journal=True, verify=False, restrict=False,
          server=False, unmapped=False, pngonly=False, quiet=False, 
          linebuffer=False, metaname=None, transparent=False):
    """
    Initializes Ferret from the arguments given.  If not restricted,
    executes any Ferret commands given in ./.ferret if it exists,
    or $HOME/.ferret if it exists and ./.ferret does not exist.

    Arguments:
        memsize: (number)     the maximum amount on memory, in mega (10^6) floats 
                              (where 1 float = 8 bytes) that can be allocated for 
                              data in Ferret.

        journal: (boolean)    turn on Ferret's journal mode? (can be changed later 
                              using SET or CANCEL MODE JOURNAL)

        verify: (boolean)     turn on Ferret's verify mode? (can be changed later 
                              using SET or CANCEL MODE VERIFY)

        restrict: (boolean)   restrict Ferret's capabilities? (e.g., SPAWN and
                              EXIT /TOPYTHON are not permitted)

        server: (boolean)     run in server mode? (don't stop on message commands,
                              don't enable command-line completion and history)

        unmapped: (boolean)   if True, do not display to the console; the /QUALITY 
                              option of SET WINDOW will be ignored.  A drawing can 
                              be saved using the FRAME command in any of the supported 
                              file formats. 

        pngonly: (boolean)    if True, do not display to the console and only raster (PNG) 
                              images can be saved; plots will be generated faster but 
                              removes support for deletion of parts (segments) of a plot.

        quiet: (boolean)      do not display the Ferret start-up header?

        linebuffer: (boolean) if True, prints each line of an output or error message 
                              as soon as a full line is written; useful when redirecting 
                              these messages to a file.
                              Note:
                                the enviroment variable GFORTRAN_UNBUFFERED_PRECONNECTED
                                needs to be set to 1 in order to unbuffer the Fortran
                                units for output and error messages

       Deprecated:
           metaname: (string) name of file to draw to (default "ferret.png") instead of 
                              displaying to the console.  The file format will be guessed 
                              from the filename extension.  When using this option, new 
                              windows should not be created and the FRAME command should 
                              not be used.

           transparent: (boolean) use a transparent background instead of opaque white 
                                  when saving to the file given by metaname

       Use of metaname and transparent is strongly discouraged.  Instead, set unmapped 
       to True and use the FRAME /FILE=<filename> [ /TRANSPARENT ] Ferret command.

    Returns:
        True is successful
        False if Ferret has already been started
    Raises:
        ValueError if memsize if not a positive number
        IOError if unable to open the journal file
    """
    # check memsize
    try:
        flt_memsize = float(memsize)
        if flt_memsize <= 0.0:
            raise ValueError
    except:
        raise ValueError("memsize must be a positive number")
    # check metaname
    if metaname == None:
        str_metaname = ""
    elif not isinstance(metaname, str):
        raise ValueError("metaname must either be None or a string")
    elif metaname.isspace():
        str_metaname = ""
    else:
        str_metaname = metaname

    # Get the known viewer bindings
    knownengines = graphbind.knownPyFerretEngines()
    # Add PViewerPQPyFerretBindings, as "PipedViewerPQ" to the known bindings
    if not ("PipedViewerPQ" in knownengines):
        graphbind.addPyFerretBindings("PipedViewerPQ",
                  pipedviewer.pyferretbindings.PViewerPQPyFerretBindings)
    # Add PImagerPQPyFerretBindings, as "PipedImagerPQ" to the known bindings
    if not ("PipedImagerPQ" in knownengines):
        graphbind.addPyFerretBindings("PipedImagerPQ",
                  pipedviewer.pyferretbindings.PImagerPQPyFerretBindings)

    # the actual call to ferret's start - do not turn on journaling or verify at this time
    if not libpyferret._start(flt_memsize, False, False,
                              bool(restrict), bool(server), str_metaname,
                              bool(transparent), bool(unmapped),
                              bool(pngonly), bool(quiet), bool(linebuffer)):
        return False

    # register the libpyferret._quit function with atexit to ensure
    # open viewer windows do not hang a Python shutdown
    atexit.register(libpyferret._quit)

    # Use tab completion for readline
    if 'libedit' in readline.__doc__:
        # Mac OS X actually uses libedit for system readline
        readline.parse_and_bind('bind ^I rl_complete');
    else:
        # GNU readline
        readline.parse_and_bind('tab: complete');

    # Create the list of standard PyEFs to create
    std_pyefs = [ ]
    # stats_* functions that do not need scipy
    std_pyefs.append("stats.stats_histogram")
    # stats_* functions that depend on scipy
    try:
        import scipy
        std_pyefs.extend((
                  "stats.stats_beta_cdf",
                  "stats.stats_beta_isf",
                  "stats.stats_beta_pdf",
                  "stats.stats_beta_ppf",
                  "stats.stats_beta_rvs",
                  "stats.stats_beta_sf",
                  "stats.stats_binom_cdf",
                  "stats.stats_binom_isf",
                  "stats.stats_binom_pmf",
                  "stats.stats_binom_ppf",
                  "stats.stats_binom_rvs",
                  "stats.stats_binom_sf",
                  "stats.stats_cauchy_cdf",
                  "stats.stats_cauchy_isf",
                  "stats.stats_cauchy_pdf",
                  "stats.stats_cauchy_ppf",
                  "stats.stats_cauchy_rvs",
                  "stats.stats_cauchy_sf",
                  "stats.stats_chi_cdf",
                  "stats.stats_chi_isf",
                  "stats.stats_chi_pdf",
                  "stats.stats_chi_ppf",
                  "stats.stats_chi_rvs",
                  "stats.stats_chi_sf",
                  "stats.stats_chi2_cdf",
                  "stats.stats_chi2_isf",
                  "stats.stats_chi2_pdf",
                  "stats.stats_chi2_ppf",
                  "stats.stats_chi2_rvs",
                  "stats.stats_chi2_sf",
                  "stats.stats_expon_cdf",
                  "stats.stats_expon_isf",
                  "stats.stats_expon_pdf",
                  "stats.stats_expon_ppf",
                  "stats.stats_expon_rvs",
                  "stats.stats_expon_sf",
                  "stats.stats_exponweib_cdf",
                  "stats.stats_exponweib_isf",
                  "stats.stats_exponweib_pdf",
                  "stats.stats_exponweib_ppf",
                  "stats.stats_exponweib_rvs",
                  "stats.stats_exponweib_sf",
                  "stats.stats_f_cdf",
                  "stats.stats_f_isf",
                  "stats.stats_f_pdf",
                  "stats.stats_f_ppf",
                  "stats.stats_f_rvs",
                  "stats.stats_f_sf",
                  "stats.stats_gamma_cdf",
                  "stats.stats_gamma_isf",
                  "stats.stats_gamma_pdf",
                  "stats.stats_gamma_ppf",
                  "stats.stats_gamma_rvs",
                  "stats.stats_gamma_sf",
                  "stats.stats_geom_cdf",
                  "stats.stats_geom_isf",
                  "stats.stats_geom_pmf",
                  "stats.stats_geom_ppf",
                  "stats.stats_geom_rvs",
                  "stats.stats_geom_sf",
                  "stats.stats_hypergeom_cdf",
                  "stats.stats_hypergeom_isf",
                  "stats.stats_hypergeom_pmf",
                  "stats.stats_hypergeom_ppf",
                  "stats.stats_hypergeom_rvs",
                  "stats.stats_hypergeom_sf",
                  "stats.stats_invgamma_cdf",
                  "stats.stats_invgamma_isf",
                  "stats.stats_invgamma_pdf",
                  "stats.stats_invgamma_ppf",
                  "stats.stats_invgamma_rvs",
                  "stats.stats_invgamma_sf",
                  "stats.stats_laplace_cdf",
                  "stats.stats_laplace_isf",
                  "stats.stats_laplace_pdf",
                  "stats.stats_laplace_ppf",
                  "stats.stats_laplace_rvs",
                  "stats.stats_laplace_sf",
                  "stats.stats_lognorm_cdf",
                  "stats.stats_lognorm_isf",
                  "stats.stats_lognorm_pdf",
                  "stats.stats_lognorm_ppf",
                  "stats.stats_lognorm_rvs",
                  "stats.stats_lognorm_sf",
                  "stats.stats_nbinom_cdf",
                  "stats.stats_nbinom_isf",
                  "stats.stats_nbinom_pmf",
                  "stats.stats_nbinom_ppf",
                  "stats.stats_nbinom_rvs",
                  "stats.stats_nbinom_sf",
                  "stats.stats_norm_cdf",
                  "stats.stats_norm_isf",
                  "stats.stats_norm_pdf",
                  "stats.stats_norm_ppf",
                  "stats.stats_norm_rvs",
                  "stats.stats_norm_sf",
                  "stats.stats_pareto_cdf",
                  "stats.stats_pareto_isf",
                  "stats.stats_pareto_pdf",
                  "stats.stats_pareto_ppf",
                  "stats.stats_pareto_rvs",
                  "stats.stats_pareto_sf",
                  "stats.stats_poisson_cdf",
                  "stats.stats_poisson_isf",
                  "stats.stats_poisson_pmf",
                  "stats.stats_poisson_ppf",
                  "stats.stats_poisson_rvs",
                  "stats.stats_poisson_sf",
                  "stats.stats_randint_cdf",
                  "stats.stats_randint_isf",
                  "stats.stats_randint_pmf",
                  "stats.stats_randint_ppf",
                  "stats.stats_randint_rvs",
                  "stats.stats_randint_sf",
                  "stats.stats_t_cdf",
                  "stats.stats_t_isf",
                  "stats.stats_t_pdf",
                  "stats.stats_t_ppf",
                  "stats.stats_t_rvs",
                  "stats.stats_t_sf",
                  "stats.stats_uniform_cdf",
                  "stats.stats_uniform_isf",
                  "stats.stats_uniform_pdf",
                  "stats.stats_uniform_ppf",
                  "stats.stats_uniform_rvs",
                  "stats.stats_uniform_sf",
                  "stats.stats_weibull_cdf",
                  "stats.stats_weibull_isf",
                  "stats.stats_weibull_pdf",
                  "stats.stats_weibull_ppf",
                  "stats.stats_weibull_rvs",
                  "stats.stats_weibull_sf",
                  "stats.stats_cdf",
                  "stats.stats_isf",
                  "stats.stats_pdf",
                  "stats.stats_pmf",
                  "stats.stats_ppf",
                  "stats.stats_rvs",
                  "stats.stats_sf",
                  "stats.stats_chisquare",
                  "stats.stats_fit",
                  "stats.stats_kstest1",
                  "stats.stats_kstest2",
                  "stats.stats_linregress",
                  "stats.stats_pearsonr",
                  "stats.stats_percentilesofscores",
                  "stats.stats_probplotvals",
                  "stats.stats_stats",
                  "stats.stats_scoresatpercentiles",
                  "stats.stats_spearmanr",
                  "stats.stats_ttest1",
                  "stats.stats_ttest2ind",
                  "stats.stats_ttest2rel",
                  "stats.stats_zscore",
                  "stats.stats_helper",
                  ))
    except ImportError:
        pass
    # shapefile_* functions
    try:
        import shapefile
        std_pyefs.extend((
                  "fershp.shapefile_readxy",
                  "fershp.shapefile_readxyval",
                  "fershp.shapefile_readxyz",
                  "fershp.shapefile_readxyzval",
                  "fershp.shapefile_writeval",
                  "fershp.shapefile_writexyval",
                  "fershp.shapefile_writexyzval",
                  ))
    except ImportError:
        pass
    # regrid functions
    try:
        import ESMP
        std_pyefs.extend((
                  "regrid.curv2rect",
                  "regrid.curv3srect",
                  ))
    except ImportError:
        pass

    # define all the Ferret standard Python external functions
    for fname in std_pyefs:
        result = run("define pyfunc pyferret.%s" % fname)

    # if not in a restricted environment, run the ./.ferret if it exists, 
    # or ${HOME}/.ferret script if exists and ./ferret does not
    if not restrict:
        if os.path.exists('./.ferret'):
            try:
                result = run('go "./.ferret"; exit /topy')
            except:
                print(" **Error: exception raised in runnning script ./.ferret", file=sys.stderr)
                result = run('exit /program')
                # should not get here
                raise SystemExit
        else:
            home_val = os.getenv('HOME')
            if home_val:
                init_script = os.path.join(home_val, '.ferret')
                if os.path.exists(init_script):
                    try:
                        result = run('go "%s"; exit /topy' % init_script)
                    except:
                        print(" **Error: exception raised in runnning script %s" % init_script, file=sys.stderr)
                        result = run('exit /program')
                        # should not get here
                        raise SystemExit

    # if journaling desired, turn it on now
    if journal:
        result = run("set mode journal")

    # if verify desired, turn it on now
    if verify:
        result = run("set mode verify")

    return True


def resize(memsize):
    """
    Resets the the maximum amount of memory that can be allocated for Ferret data.

    Arguments:
        memsize: the new size, in mega (10^) floats (where a "float" is 8 bytes),
                 for Ferret data.
    Returns:
        True if successful - Ferret has the new memory limit
        False if unsuccessful - Ferret has the previous memory limit
    Raises:
        ValueError if memsize if not a positive number
    """
    # check memsize
    try:
        flt_memsize = float(memsize)
        if flt_memsize <= 0.0:
            raise ValueError
    except:
        raise ValueError("memsize must be a positive number")
    # the actual call - now just a ferret command handled internally
    return libpyferret._run("SET MEMORY /SIZE=%d" % flt_memsize)


FERRET_READLINE_DELIMS = ' \t\n\'"\\`@$><=;|&{('
def run(command=None):
    """
    Runs a Ferret command just as if entering a command at the Ferret prompt.

    If the command is not given, is None, or is a blank string, Ferret will
    prompt you for commands until "EXIT /TOPYTHON" is given.  In this case,
    the return tuple will be for the last error, if any, that occurred in
    the sequence of commands given to Ferret.  Also, when at the Ferret 
    prompt, the readline library's default filename completion will be used 
    but with word delimiters given in pyferret.FERRET_READLINE_DELIMS. 
    At startup the word delimiters are the readline default delimiters: 
        ' \\t\\n\\'"\\\\`@$><=;|&{('
    This string can be modified if desired.

    Arguments:
        command: the Ferret command to be executed.
    Returns:
        (err_int, err_string)
            err_int: one of the FERR_* data values (FERR_OK if there are no errors)
            err_string: error or warning message (can be empty)
        Error messages normally start with "**ERROR"
        Warning messages normally start with "*** NOTE:"
    Raises:
        ValueError if command is neither None nor a String
    """
    # check command
    if command == None:
        str_command = ""
    elif not isinstance(command, str):
        raise ValueError("command must either be None or a string")
    elif command.isspace():
        str_command = ""
    else:
        str_command = command
    # if going into Ferret-command mode,
    # use the filename completer for readline name completion
    if str_command == "":
        old_delims = readline.get_completer_delims()
        old_completer = readline.get_completer()
        # set to the readline default completer (filename completion)
        readline.set_completer(None)
        # set the word delimitors appropriate for Ferret
        readline.set_completer_delims(FERRET_READLINE_DELIMS)
    # the actual Ferret function call
    retval = libpyferret._run(str_command)
    # return to the original readline completer
    if str_command == "":
        readline.set_completer_delims(old_delims)
        readline.set_completer(old_completer)
    return retval


def stop():
    """
    Runs a series of Ferret commands to return Ferret to
    its default state, then shuts down and releases all
    memory used by Ferret.  After calling this function do
    not call any Ferret functions except start, which will
    restart Ferret and re-enable the other functions.

    Returns:
        False if Ferret has not been started or has already been stopped
        True otherwise
    """
    # If it had been started, shut down ESMP and delete the log file
    try:
        regrid.ESMPControl().stopESMP(True)
    except Exception:
        pass

    # clear "the" anonymous dataset
    pyferret.anondset.close()

    # Continue with Ferret shutdown
    return libpyferret._stop()


def _readline(myprompt):
    """
    Prompts the user for input and returns the line read.

    Used for reading commands in the Ferret command loop.
    Just uses the built-in function raw_input.  Since the
    readline module was imported, readline features are
    provided.

    Arguments:
        myprompt - prompt string to use
    Returns:
        the string read in, or None if an Exception occurs
    """
    try:
        if sys.version_info[0] > 2:
            if myprompt:
                myline = input(myprompt)
            else:
                myline = input()
        else:
            if myprompt:
                myline = raw_input(myprompt)
            else:
                myline = raw_input()
    except Exception:
        myline = None

    return myline