Issues running Python script from a Ruby script

I just finished developing an IPC-2581 import Ruby script,
to clean up the data I attempted to call the simplify package,
however it doesn't work for me :(

the code is shown below:

  if _progress
  ### run simplify if it is installed...
  _Home = ENV['HOME']
  _Home = _Home.gsub(/\\+/,'/')
  _User = ENV['USER']
  unless _Home.match(_User)
     _Home = _Home + "/" + _User
  _Macro = _Home + "/KLayout/salt/simplify/pymacros/simplify.lym"
  _Macro = _Macro.gsub(/\/\//,'/')
  if File.exists? _Macro
     _progress = RBA::Macro::new(_Macro)
     if _progress
     puts _progress.interpreter_name

the puts result is 'python', but the run call fails


  • edited January 7

    Interesting point. I did not know about IPC-2581. I checked for public specs, but all I could find was a version behind a paywall. Usually that means the spec isn't made for open source implementation (as this would disclose the actual spec in a way). But I may be wrong. The pieces of the document they give out for free do not specify license conditions.

    If the spec is ready for open source implementation, I'd offer to implement it natively alongside of Gerber. Have you been in touch with the spec holders about the license status?

    I'm also mentioning this in case you plan to open source your work (which I would encourage). Checking the legal stuff beforehand saves you some trouble.

    I feel that spec holders should be interested in dissemination of their products, hence in open source support. If not, it's basically their own (bad, IMHO) decision, but my choice was not to support them at my own risk. At least as of today, given the dynamics and economical impact of open software and protocol standards in other areas, it should be clear that proprietary standards are a thing of past, dark ages.

    Anyway ...

    Regarding your problem, the issue is that you'd need to run a function from inside the .lym file, but that is not supported through the "Macro" object. You can only run a file as a whole, not specific functions from it.

    But the core functionality boils down to using the "smoothed" feature of KLayout over all cells and layers. The Ruby version of this two-folded loop is basically this:

        cv =
        ly = cv.layout
        max_err_dbu = max_err / ly.dbu
        ly.each_cell do |cell|
           ly.layer_indexes.each do |i|
              shapes = cell.shapes(i)
              r = RBA::Region::new(shapes)
              r_approx = r.smoothed(max_err_dbu)

    BTW: the code to find the .lym file above (which you probably won't need) is more portable if you write it this way:

      _AppData = RBA::Application.instance.application_data_path
      _Macro = File.join(_AppData, "salt", "simplify", "pymacros", "simplify.lym")
      if File.exists? _Macro


  • Thanks!
    I'll attempt to update my code per your feedback
    I got the spec document from

  • Cool, thanks for the link :)

    The document does not mention a license so I take it for public.

    I checked one of the public samples and the IPC-2581C version is much larger than the RS274X one (5 times). Looking at the file, the XML format is very bloated and it's no wonder the files are that huge.

    Is IPC-2581C used much in real life?

    Kind regards,


  • It's my understanding that the majority of PCB's are still built using Gerber, drill and IPC-D-356 files.

    In the late 1990's the Valor ODB++ format became the preferred data format since fabricators can read the data directly instead of adjusting/aligning the various input files.

    After Valor was acquired by Mentor Graphics ( now Siemens EDA ) the other EDA vendors (i.e. Cadence and Altium ) didn't like their competitor controlling the ODB++ format, so they started promoting IPC-2581 as an open standard...

    Other CAE vendors ( i.e. Ansys ) have standardized their preferred ECAD import format as IPC2581

    Since I developed a IPC-D-356 reader macro my client asked if I could develop an IPC2581 reader macro...

  • Getting back to the original issue...
    I have gotten my initial data input script to call the next script automatically, as shown below:
    script 1 code:

         _layout = _mw.load_layout(_PcbFile,1)
         _lv = RBA::LayoutView.current
         if _lv != nil
           _AppData = RBA::Application.instance.application_data_path
           _Macro = File.join(_AppData, "macros", "ReadIpc356.lym")
           if File.exists? _Macro
              _IpcFileName = RBA::Value::new(_IpcFile)
              _rba = RBA::Interpreter::ruby_interpreter
              _progress = RBA::Macro::new(_Macro)
              if _progress
                puts _progress.interpreter_name

    script 2 code:

      if $_IpcFileName
        IPCfile = $_IpcFileName.value
        IPCfile = RBA::FileDialog::ask_open_file_name(_version_str, _Folder, "IPC files (*.IPC *.ipc);;All files (*)")
  • Hi @mtnhomecad,

    thanks for the explanation about IPC2581.

    I don't want to spoil the fun, but your explanation sounds interesting enough so I think it makes sense to implement IPC2581 natively. But that will be a long-term goal. I won't rush, so your client can enjoy the script you made for him :)



Sign In or Register to comment.