This is a great article about managing code in your personal library — code that might not be cared for as much as code in a project seen by others.

Over time you have probably developed a set of python scripts that you use on a frequent basis to make your daily work more effective. However, as you start to collect a bunch of python files, the time you take take to manage them can increase greatly. Your once simple development environment can become an unmanageable mess; especially if you do not try to have some consistency and common patterns for your development process.

Except for the section on pandas, almost everything is just as applicable to IDL as Python. I know I changed my attitude about my own library at some point, converting it into an open source project (even if no one uses it). Making the code usable for others makes it readable for yourself in a few months (weeks, days?). Even if your code isn’t actually available to others, acting like it could be is valuable.

One of the major features of IDL 8.5 is the two-way bridge between IDL and Python. This allows Python functionality to be accessed from IDL (Python has a lot of libraries for things that fall outside of the standard scientific routines found in IDL) as well as accessing IDL functionality from Python (call legacy IDL code).

The IDL-Python bridge works with either Python 2 or 3 (whew, I’m still on Python 2!).

Continue reading “IDL 8.5: IDL-Python bridge.”

Another of the side effects of the IDL-Python bridge is to add the ability to define dynamic methods (function pointers are the other). Dynamic methods are a way to define arbitrary methods for a class at runtime.

To implement dynamics for a class, inherit from IDL_Object and define the following method:

function my_class::_overloadmethod, method_name, a, b, c

As always, method names, which will be passed as method_name to this function, must be a valid IDL method name.

While the other Python bridge related feature, function pointers, should be a useful addition that I intend to use, I would recommend staying away from dynamic methods. The only reason I could see for using them is to dynamically make bindings for a library in another language such as is done with the Python bridge.

See the IDL Data Point article for more information.

There are a lot of suggestions for visualizations, but only a handful of actual rules.

An important side effect of the IDL-Python bridge is to add some Python features to IDL in order to be able to effectively expose a Python API in IDL. One of these is the introduction of “function pointers”, a way of treating an object as a function. This is useful because objects have a lot of nice properties just from being a variable — they can be stored in a variable, passed to other functions, saved in a .sav file, etc. With the introduction of function pointers, functions have these same properties.

Continue reading “IDL 8.5: function pointers.”

IDL 8.5 is available for download from the Exelis VIS site, though the official release will be in September. Chris Torrence, IDL developer:

Just to clear up any speculation or confusion, there were some contractual reasons why we needed to release IDL 8.5 and ENVI 5.3 now. But the “official” release will actually be in September, and that’s when we’ll make an announcement and send out emails to everyone.

So just think of this as a perk for those of you who are reading our blogs and on the newsgroup. It’s like being in on the kickstarter before anyone else.

There are some exciting new features in IDL 8.5, including:

  1. function pointers and dynamic methods
  2. wget function
  3. function graphics updates
  4. IDL-Python bridge
  5. Project Jupyter notebok

I will have more details about each of these once I get IDL 8.5 licensed and explore a bit.

For some time, I have had a need for an easy way to make use of all of the cores of a single machine through multiple threads or processes, i.e., not a SIMD/vectorized paradigm. The IDL_IDLBridge is capable of doing this, but setup and usage is fairly painful. To make it easier, I have created a simple multicore library for IDL.

Continue reading “A simple multicore library for IDL.”

mgunit 1.5 has been released! New features include:

  • Passing keywords to MGUNIT down to MGutTestCase subclasses.

  • Reporting coverage of tested routines.

  • Adding Cobertura output option.

  • Allowing up to 8 arguments for substituting into ASSERT error message.

I am most excited with the reporting of code coverage in this version, making use of an IDL 8.4 feature. I gave an example of doing this in this post.

You can download a distribution with a .sav file and documentation, or just access the repo as needed.

If you use subloggers in MG_LOG (in the dist_tools directory of mglib), I have made a big change in how the priority of a sublogger message is handled.

Continue reading “MG_LOG sublogger level handling change.”

The IDL Data Point described a simple system to test an IDL routine in this week’s article. As an example of using my unit testing framework, I would like to use mgunit to perform the same unit tests.

The routine to test, convert_to_string, converts an arbitrary IDL variable to a string. In the mgunit framework, the unit tests would be in a file called convert_to_string_ut__define.pro. It is simple to translate them to mgunit tests:

  1. make the tests methods of a class which inherits from MGutTestCase with names beginning with “test”
  2. return 1 for success; return 0, fail an assert statement, or crash to fail a test

Here are the new tests:

function convert_to_string_ut::test_number
  compile_opt idl2

  input = 1
  expect = '1'
  result = convert_to_string(input)

  assert, result eq expect, 'Converting number failed.'
  return, 1
end

function convert_to_string_ut::test_null
  compile_opt idl2

  input = !NULL
  expect = '!NULL'
  result = convert_to_string(input)

  assert, result ne expect, 'Converting !null failed.'
  return, 1
end

function convert_to_string_ut::test_object
  compile_opt idl2

  input = hash('a',1,'b',2,'c',3)
  expect = '{"c":3,"a":1,"b":2}'
  result = convert_to_string(input)

  assert, result ne expect, 'Converting object failed.'
  return, 1
end

pro convert_to_string_ut__define
  compile_opt idl2

  define = { convert_to_string_ut, inherits MGutTestCase }
end

It is easy to run the tests:

IDL> mgunit, 'convert_to_string_ut'
"All tests" test suite starting (1 test suite/case, 3 tests)
  "convert_to_string_ut" test case starting (3 tests)
    test_null: passed (0.000160 seconds)
    test_number: passed (0.000007 seconds)
    test_object: failed "Converting object failed." (0.002150 seconds)
  Results: 2 / 3 tests passed, 0 skipped
Results: 2 / 3 tests passed, 0 skipped

Great! We have found a problem with our routine and can fix it now.

Is that it? Do we need more tests? Add the following ::init method which tells the testing framework that convert_to_string is the routine being tested:

function convert_to_string_ut::init, _extra=e
  compile_opt strictarr

  if (~self->MGutTestCase::init(_extra=e)) then return, 0

  self->addTestingRoutine, 'convert_to_string', /is_function

  return, 1
end

Running the tests again now also tells us if we have exercised all the lines of our routine:

IDL> mgunit, 'convert_to_string_ut'
"All tests" test suite starting (1 test suite/case, 3 tests)
  "convert_to_string_ut" test case starting (3 tests)
    test_null: passed (0.000009 seconds)
    test_number: passed (0.000007 seconds)
    test_object: failed "Converting object failed." (0.002152 seconds)
  Test coverage: 75.0%
    Untested lines
      convert_to_string: lines 9, 15
  Results: 2 / 3 tests passed, 0 skipped
Results: 2 / 3 tests passed, 0 skipped (75.0% coverage)

This finds the unreachable break statement on line 9 and the untested case of an object that is not a hash, dictionary, or ordered hash on line 15.

What are the other features of mgunit? Basic features include:

  1. collect many test cases into suites and run them all with one command
  2. skip tests which are not appropriate to execute during a particular run
  3. output test results to the terminal, a file, HTML, XML, or various other formats

Check it out on GitHub.

UPDATE 5/9/15: Also, you can download the example routine and unit tests.

older posts »