Commit Friday evening.
PDFA and EXFO Laser are now part of the family
This commit is contained in:
6
Functions/helper_functions_community/mat2tikz/.gitignore
vendored
Normal file
6
Functions/helper_functions_community/mat2tikz/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
*.sublime-workspace
|
||||
*.tap
|
||||
test/*.test.*
|
||||
*.asv
|
||||
*.m~
|
||||
octave-workspace
|
||||
16
Functions/helper_functions_community/mat2tikz/.travis.yml
Normal file
16
Functions/helper_functions_community/mat2tikz/.travis.yml
Normal file
@@ -0,0 +1,16 @@
|
||||
language: c++
|
||||
before_install:
|
||||
- sudo add-apt-repository -y ppa:octave/stable
|
||||
- sudo apt-get update -qq
|
||||
- sudo apt-get install gdb # to capture backtrace of eventual failures
|
||||
- sudo apt-get install octave
|
||||
- sudo apt-get purge libopenblas-base # fixes PPA Octave 4.0 crash on Travis
|
||||
before_script:
|
||||
- ulimit -c unlimited -S # enable core dumps for Octave crash debugging
|
||||
script:
|
||||
- ./runtests.sh /usr/bin/octave
|
||||
notifications:
|
||||
hipchat: f4c2c5f87adc85025545e5b59b3fbe@Matlab2tikz
|
||||
after_failure:
|
||||
- COREFILE=$(find . -maxdepth 1 -name "core*" | head -n 1) # find core file
|
||||
- gdb -c "$COREFILE" -ex "thread apply all bt" -ex "set pagination 0" -batch /usr/bin/octave-cli # print stack trace
|
||||
64
Functions/helper_functions_community/mat2tikz/AUTHORS.md
Normal file
64
Functions/helper_functions_community/mat2tikz/AUTHORS.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Maintainer
|
||||
* [Egon Geerardyn](https://github.com/egeerardyn) is the current maintainer (2015 - now).
|
||||
* [Nico Schlömer](https://github.com/nschloe) designed and implemented the intial version and was the first maintainer (2008 - 2015).
|
||||
|
||||
# Contributors
|
||||
Thanks for patches, suggestions, and other contributions go to:
|
||||
|
||||
* [Ben Abbott](https://github.com/bpabbott)
|
||||
* Martijn Aben (The MathWorks)
|
||||
* [Nicolas Alt](https://github.com/nalt)
|
||||
* [Eshwar Andhavarapu](https://github.com/gontadu)
|
||||
* [Matt Bauman](https://github.com/mbauman)
|
||||
* Eike Blechschmidt
|
||||
* [Klaus Broelemann](https://github.com/Broele)
|
||||
* [Katherine Elkington](https://github.com/kelkington)
|
||||
* [Thomas Emmert](https://github.com/murmlgrmpf)
|
||||
* Andreas Gäb
|
||||
* [Egon Geerardyn](https://github.com/egeerardyn)
|
||||
* Roman Gesenhues
|
||||
* Michael Glasser (The MathWorks)
|
||||
* [David Haberthür](https://github.com/habi)
|
||||
* [Patrick Häcker](https://github.com/MagicMuscleMan)
|
||||
* [Ulrich Herter](https://github.com/ulijh)
|
||||
* [David Horsley](https://github.com/widdma)
|
||||
* Kári Hreinsson
|
||||
* [Lucas Jeub](https://github.com/LJeub)
|
||||
* [Martin Kiefel](https://github.com/mkiefel)
|
||||
* [Andreas Kloeckner](https://github.com/akloeckner)
|
||||
* Mykel Kochenderfer
|
||||
* [Oleg Komarov](https://github.com/okomarov)
|
||||
* Henk Kortier
|
||||
* [Tom Lankhorst](https://github.com/tomlankhorst)
|
||||
* [Burkart Lingner](https://github.com/burkart)
|
||||
* Theo Markettos
|
||||
* [Dragan Mitrevski](https://github.com/nidrosianDeath)
|
||||
* [Jason Monschke](https://github.com/jam4375)
|
||||
* Francesco Montorsi
|
||||
* Ricardo Santiago Mozos
|
||||
* Johannes Mueller-Roemer
|
||||
* [Ali Ozdagli](https://github.com/aliirmak)
|
||||
* [Richard Peschke](https://github.com/RPeschke)
|
||||
* [Peter Ploß](https://github.com/PeterPablo)
|
||||
* Julien Ridoux
|
||||
* [Christoph Rüdiger](https://github.com/mredd)
|
||||
* Carlos Russo
|
||||
* [Michael Schellenberger Costa](https://github.com/miscco)
|
||||
* [Manuel Schiller](https://github.com/dachziegel)
|
||||
* [Nico Schlömer](https://github.com/nschloe)
|
||||
* Johannes Schmitz
|
||||
* Michael Schoeberl
|
||||
* [Jan Taro Svejda](https://github.com/JTSvejda)
|
||||
* [José Vallet](https://github.com/josombio)
|
||||
* [Thomas Wagner](https://github.com/Aikhjarto)
|
||||
* Donghua Wang
|
||||
* [Patrick Wang](https://github.com/patrickkwang)
|
||||
* Robert Whittlesey
|
||||
* Pooya Ziraksaz
|
||||
* Bastiaan Zuurendonk (The MathWorks)
|
||||
* GitHub users: [andreas12345](https://github.com/andreas12345), [karih](https://github.com/karih), [theswitch](https://github.com/theswitch)
|
||||
|
||||
# Acknowledgements
|
||||
Matlab2tikz has once greatly profited from its ancestor: [Matfig2PGF](http://www.mathworks.com/matlabcentral/fileexchange/12962) written by Paul Wagenaars.
|
||||
|
||||
Also, the authors would like to thank [Christian Feuersänger](https://github.com/cfeuersaenger) for the [Pgfplots](http://pgfplots.sourceforge.net) package which forms the basis for the matlab2tikz output on the LaTeX side.
|
||||
439
Functions/helper_functions_community/mat2tikz/CHANGELOG.md
Normal file
439
Functions/helper_functions_community/mat2tikz/CHANGELOG.md
Normal file
@@ -0,0 +1,439 @@
|
||||
# 2016-08-15 Version 1.1.0 [Egon Geerardyn](egon.geerardyn@gmail.com)
|
||||
|
||||
* Added or improved support for:
|
||||
- Octave 4.0 (#759)
|
||||
- `scatter`, `quiver` and `errorbar` support in Octave (#669)
|
||||
- `cleanfigure` has been improved:
|
||||
* New and superior (Opheim) simplification algorithm
|
||||
* Simplification for `plot3` (3D plots) (#790)
|
||||
* Vectorized implementations (#756, #737)
|
||||
* Overall clean-up of the code (#797, #787, #776, #744)
|
||||
* Optional limitation of data precision (#791)
|
||||
* Textbox removal is being phased out (#817)
|
||||
- Quiver plots now translate to native pgfplots quivers (#679, #690)
|
||||
- Legends, especially with `plotyy`, now use `\label` (#140, #760, #773)
|
||||
- Tick labels with `datetime` (#383, #803)
|
||||
- `contourf`/`contour` plots with matrix arguments and nonstandard line widths (#592, #721, #722, #871)
|
||||
- Colored ticks and axes (#880, #908)
|
||||
- Scatter plots with different marker colors and sizes (#859, #861)
|
||||
- `colorbar` positioning and tick placement (#933, #937, #941)
|
||||
- The self-updater has been improved
|
||||
* New parameters:
|
||||
- `arrowHeadSizeFactor` for tweaking the size of arrowheads
|
||||
- `semanticLineWidths` for tweaking semantic line width conversion (e.g. `thick` instead of `0.8pt`)
|
||||
* Extra requirements:
|
||||
- Quiver plots require `\usetikzlibrary{arrows.meta}`
|
||||
* Bug fixes:
|
||||
- Errorbars without lines & markers (#813)
|
||||
- `light`/`camera` objects are now ignored (#684)
|
||||
- Draw baseline in bar/stem plots (#798)
|
||||
- Multiple annotation containers (#728, #730)
|
||||
- Legends of bode plots (#700, #702)
|
||||
- Titles of bode plots (#715, #716, #753)
|
||||
- Patch without fill/edge color (#682, #701, #740)
|
||||
- Warn about usage of faceted interp shader (#699)
|
||||
- Tick labels are properly escaped now (#711)
|
||||
- Swapped image dimensions (#714)
|
||||
- Width of bar plots was incorrect (#727, #696)
|
||||
- Stacking and placement of bar plots (#851, #845, #840, #785, #903)
|
||||
- Handling of tick labels when `parseStrings=false` (#86, #871)
|
||||
- Properly escape tick labels for LaTeX (#710, #711, #820, #821)
|
||||
- Respect edge color in `scatter` plots (#900)
|
||||
- Output directory is created automatically (#889, #929)
|
||||
- TikZ output format has been improved slightly (#936, #921, #801)
|
||||
* For developers:
|
||||
- Please check out the (guidelines)[CONTRIBUTING.md]
|
||||
- We now use `allchild` and `findall` (#718)
|
||||
- SublimeText project files
|
||||
- Test hashes can be saved selectively (#720)
|
||||
- Continuous testing for MATLAB and Octave 3.8 with Jenkins
|
||||
- Test suite timing is tracked (#738)
|
||||
- The testing reports have been improved for GitHub (#708)
|
||||
- Testing can output to different directories (#818)
|
||||
- A new tool to help track regressions (#814)
|
||||
- A new tool to consistently format the code (#808, #809)
|
||||
- `figure2dot` updated for HG2
|
||||
|
||||
# 2015-06-15 Version 1.0.0 [Egon Geerardyn](egon.geerardyn@gmail.com)
|
||||
|
||||
* Added support for:
|
||||
- Annotations (except arrows) in R2014b (#534)
|
||||
- `Histogram` in R2014b (#525)
|
||||
- Filled contour plots in R2014b (#379, #500)
|
||||
- Contour plots with color maps in R2014b (#380, #500)
|
||||
- Axes background color and overlap (#6, #509, #510)
|
||||
- Horizontal/Vertical text alignment (#491)
|
||||
* Extra requirements:
|
||||
- Patch plots now require `\usepgfplotslibrary{patchplots}` (#386, #497)
|
||||
* Bug fixes:
|
||||
- Pgfplots 1.12 (`row sep=crcr`) in combination with `externalData==true` (#548)
|
||||
- Updater has been fixed (#502)
|
||||
- 3D plot sizing takes viewing angle into account (#560, #630, #631)
|
||||
- Alpha channel (transparency) in images (#561)
|
||||
- Colorbar labels in R2014b (#429, #488)
|
||||
- Scaling of color data at axes level (#486)
|
||||
- Text formatting (for `TeX` parser) is improved (#417)
|
||||
- Support for `|` character in labels (#587, #589)
|
||||
- Legends for `stairs` and `area` plots (#601, #602)
|
||||
- `cleanfigure()` removes points outside of the axes for `stairs` plots (#226, #533)
|
||||
- `cleanfigure()` removes points outside of the axes better (#392, #400, #547)
|
||||
- Support `>` and `<` in text (#522)
|
||||
- Better text positioning (#518)
|
||||
- Text boxes on 3D graphs (#528)
|
||||
- File closing is more robust (#496, #555)
|
||||
- TikZ picture output, i.e.`imageAsPng==false`, improved (#581, #596)
|
||||
- `standalone==true` sets the font and input encoding in LaTeX (#590)
|
||||
- Legend text alignment in Octave (#668)
|
||||
- Improved Octave legend if not all lines have an entry (#607, #619, #653)
|
||||
- Legend without a drawn box in R2014b+ (#652)
|
||||
- Misc. fixes: #426, #513, #520, #665
|
||||
* For developers:
|
||||
- The testing framework has been revamped (see also `test/README.md`)
|
||||
- A lot of the tests have been updated (#604, #614, #638, ...)
|
||||
- Cyclomatic complexity of the code has been reduced (#391)
|
||||
- Repository has been moved to [matlab2tikz/matlab2tikz](https://github.com/matlab2tikz/matlab2tikz)
|
||||
- Extra files have been pruned (#616)
|
||||
|
||||
# 2014-11-02 Version 0.6.0 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Annotation support in R2014a and earlier
|
||||
* New subplot positioning approach (by Klaus Broelemann) that uses absolute instead of relative positions.
|
||||
* Support stacked bar plots and others in the same axes (needs pgfplots 1.11).
|
||||
* Support legends with multiline entries.
|
||||
* Support for the alpha channel in PNG output.
|
||||
* Test framework updated and doesn't display figures by default.
|
||||
* Major code clean-up and code complexity checks.
|
||||
* Bug fixes:
|
||||
- Cycle paths only when needed (#317, #49, #404)
|
||||
- Don't use infinite xmin/max, etc. (#436)
|
||||
- Warn about the `noSize` parameter (#431)
|
||||
- Images aren't flipped anymore (#401)
|
||||
- No scientific notation in width/height (#396)
|
||||
- Axes with custom colors (#376)
|
||||
- Mesh plots are exported properly (#382)
|
||||
- Legend colors are handled better (#389)
|
||||
- Handle Z axis properties for quiver3 (#406)
|
||||
- Better text handling, e.g. degrees (#402)
|
||||
- Don't output absolute paths into TikZ by default
|
||||
- ...
|
||||
|
||||
# 2014-10-20 Version 0.5.0 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Support for MATLAB 2014b (with it's substantial graphics changes).
|
||||
All credit goes to Egon Geerardyn.
|
||||
* Bugfixes:
|
||||
- single bar width
|
||||
- invisible bar plots
|
||||
- surface options
|
||||
- patch plots and cycling
|
||||
- patches with literal colors
|
||||
|
||||
# 2014-03-07 Version 0.4.7 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Acid tests: Remove MATLAB-based `eps2pdf`.
|
||||
* Bugfixes:
|
||||
- multiple patches
|
||||
- log plot with nonzero baseline
|
||||
- marker options for scatter plots
|
||||
- table data formatting
|
||||
- several fixes for Octave
|
||||
|
||||
# 2014-02-07 Version 0.4.6 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Set `externalData` default to `false`.
|
||||
* Properly check for required Pgfplots version.
|
||||
* Marker scaling in scatter plots.
|
||||
|
||||
# 2014-02-02 Version 0.4.5 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Arrange data in tables.
|
||||
* Optionally define custom colors.
|
||||
* Allow for strict setting of font sizes.
|
||||
* Bugfixes:
|
||||
- tick labels for log plots
|
||||
- tick labels with commas
|
||||
|
||||
# 2014-01-02 Version 0.4.4 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Support for color maps with scatter plots.
|
||||
* Support for different-length up-down error bars.
|
||||
* Input options validation.
|
||||
* Bugfixes:
|
||||
- legends for both area and line plots
|
||||
- invisible text fields
|
||||
|
||||
# 2013-10-20 Version 0.4.3 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Support for 3D quiver plots.
|
||||
* Extended support for colorbar axis options.
|
||||
* New logo!
|
||||
* Bugfixes:
|
||||
- text generation
|
||||
- extraCode option
|
||||
- join strings
|
||||
- ...
|
||||
|
||||
# 2013-09-12 Version 0.4.2 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Support for explicit color specification in 3D plots.
|
||||
* Better color handling for patch plots.
|
||||
* Support for various unicode characters.
|
||||
* Bugfixes:
|
||||
- edge colors for bar plots
|
||||
- multiple color bars
|
||||
- ...
|
||||
|
||||
# 2013-08-14 Version 0.4.1 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Replaced option `extraTikzpictureCode` by `extraCode`
|
||||
for inserting code at the beginning of the file.
|
||||
* Support for relative text positioning.
|
||||
* Improved documentation.
|
||||
* Code cleanup: moved all figure manipulations over to cleanfigure()
|
||||
* Bugfixes:
|
||||
- error bars
|
||||
- empty tick labels
|
||||
- ...
|
||||
|
||||
# 2013-06-26 Version 0.4.0 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Added `cleanfigure()` for removing unwanted entities from a plot
|
||||
before conversion
|
||||
* Add option `floatFormat` to allow for custom specification of the format
|
||||
of float numbers
|
||||
* Bugfixes:
|
||||
- linewidth for patches
|
||||
- ...
|
||||
|
||||
# 2013-04-13 Version 0.3.3 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Support for:
|
||||
- pictures in LaTeX subfloats
|
||||
* Bugfixes:
|
||||
- axes labels
|
||||
- extra* options
|
||||
- logscaled axes
|
||||
- ...
|
||||
|
||||
# 2013-03-14 Version 0.3.2 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Support for:
|
||||
- waterfall plots
|
||||
* Bugfixes:
|
||||
- axis locations
|
||||
- color handling
|
||||
- stacked bars
|
||||
- ...
|
||||
|
||||
# 2013-02-15 Version 0.3.1 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Use `table{}` for plots for cleaner output files.
|
||||
* Support for:
|
||||
- hg transformations
|
||||
- pcolor plots
|
||||
* Removed command line options:
|
||||
- `minimumPointsDistance`
|
||||
* Bugfixes:
|
||||
- legend positioning and alignment
|
||||
- tick labels
|
||||
- a bunch of fixed for Octave
|
||||
- line width for markers
|
||||
- axis labels for color bars
|
||||
- image trimming
|
||||
- subplots with bars
|
||||
- ...
|
||||
|
||||
# 2012-11-19 Version 0.3.0 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Support for:
|
||||
- area plots
|
||||
- legend position
|
||||
- inner color bars
|
||||
- log-scaled color bars
|
||||
* New command line options:
|
||||
- `standalone` (create compilable TeX file)
|
||||
- `checkForUpdates`
|
||||
* `mlint` cleanups.
|
||||
* Removed deprecated options.
|
||||
* Bugfixes:
|
||||
- colorbar-axis association
|
||||
- option parsing
|
||||
- automatic updater
|
||||
- unit 'px'
|
||||
- ...
|
||||
|
||||
# 2012-09-01 Version 0.2.3 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Multiline text for all entities.
|
||||
* Support for logical images.
|
||||
* Support for multiple legends (legends in subplots).
|
||||
* Fixed version check bug.
|
||||
* Fix `minimumPointsDistance`.
|
||||
|
||||
# 2012-07-19 Version 0.2.2 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Support for multiline titles and axis labels.
|
||||
* Respect log-scaled axes for `minimumPointsDistance`.
|
||||
* Add support for automatic graph labels via new option.
|
||||
* About 5 bugfixes.
|
||||
|
||||
# 2012-05-04 Version 0.2.1 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Support for color maps.
|
||||
* Support for native color bars.
|
||||
* Partial support for hist3 plots.
|
||||
* Support for spectrogram plots.
|
||||
* Support for rotated text.
|
||||
* Native handling of `Inf`s and `NaN`s.
|
||||
* Better info text.
|
||||
* matlab2tikz version checking.
|
||||
* Line plotting code cleanup.
|
||||
* About 10 bugfixes.
|
||||
|
||||
# 2012-03-17 Version 0.2.0 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Greatly overhauled text handling. (Burkhart Lingner)
|
||||
* Added option `tikzFileComment`.
|
||||
* Added option `parseStrings`.
|
||||
* Added option `extraTikzpictureSettings`.
|
||||
* Added proper documetion (for `help matlab2tikz`).
|
||||
* Improved legend positioning, orientation.
|
||||
* Support for horizontal bar plots.
|
||||
* Get bar widths right.
|
||||
* Doubles are plottet with 15-digit precision now.
|
||||
* Support for rectangle objects.
|
||||
* Better color handling.
|
||||
* Testing framework improvements.
|
||||
* Several bugfixes:
|
||||
- ticks handled more concisely
|
||||
- line splitting bugs
|
||||
- ...
|
||||
|
||||
# 2011-11-22 Version 0.1.4 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Support for scatter 3D plots.
|
||||
* Support for 3D parameter curves.
|
||||
* Support for 3D patches.
|
||||
* Support for minor ticks.
|
||||
* Add option `interpretTickLabelsAsTex` (default `false`).
|
||||
* Several bugfixes:
|
||||
- `%` sign in annotations
|
||||
- fixed `\omega` and friends in annotations
|
||||
- proper legend for bar plots
|
||||
- don't override PNG files if there is more than one image plot
|
||||
- don't always close patch paths
|
||||
|
||||
# 2011-08-22 Version 0.1.3 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Greatly overhauled text handling.
|
||||
* Better Octave compatibility.
|
||||
* Several bugfixes:
|
||||
- subplot order
|
||||
- environment detection
|
||||
|
||||
|
||||
# 2011-06-02 Version 0.1.2 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Support for logscaled color bar.
|
||||
* Support for truecolor images.
|
||||
* Initial support for text handles.
|
||||
* Speed up processing for line plots.
|
||||
* Several bugfixes:
|
||||
- axis labels, tick labels, etc. for z-axis
|
||||
- marker handling for scatter plots
|
||||
- fix for unicolor scatter plots
|
||||
|
||||
# 2011-04-06 Version 0.1.1 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Improved Octave compatibility.
|
||||
* Several bugfixes:
|
||||
- input parser
|
||||
|
||||
# 2011-01-31 Version 0.1.0 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Basic Octave compatibility.
|
||||
* Several bugfixes:
|
||||
- bar plots fix (thanks to Christoph Rüdiger)
|
||||
- fix legends with split graphs
|
||||
|
||||
# 2010-09-10 Version 0.0.7 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Compatibility fixes for older MATLAB installations.
|
||||
* Several bugfixes:
|
||||
- line plots with only one point
|
||||
- certain surface plots
|
||||
- orientation of triangle markers (`<` vs. `>`)
|
||||
- display of the color `purple`
|
||||
|
||||
# 2010-05-06 Version 0.0.6 [Nico Schlömer](nico.schloemer@gmail.com)
|
||||
|
||||
* Support for scatter plots.
|
||||
* Preliminary support for surface plots; thanks to Pooya.
|
||||
* Large changes in the codebase:
|
||||
- next to `matlab2tikz.m`, the file `pgfplotsEnvironment.m` is now needed as well; it provides a much better structured approach to storing and writing environments when parsing the MATLAB(R) figure
|
||||
* proper MATLAB(R) version check
|
||||
* lots of small fixes
|
||||
|
||||
# 2009-12-21 Version 0.0.5 [Nico Schlömer](nico.schloemer@ua.ac.be)
|
||||
|
||||
* Improvements in axis handling:
|
||||
- colored axes
|
||||
- allow different left and right ordinates
|
||||
* Improvements for line plots:
|
||||
- far outliers are moved toward the plot,
|
||||
avoiding `Dimension too large`-type errors in LaTeX
|
||||
- optional point reduction by new option `minimumPointsDistance`
|
||||
* Improvements for image handling:
|
||||
- creation of a PNG file, added by `\addplot graphics`
|
||||
- fixed axis orientation bug
|
||||
* Bugfixes for:
|
||||
- multiple axes
|
||||
- CMYK colors
|
||||
- legend text alignment (thanks Dragan Mitrevski)
|
||||
- transparent patches (thanks Carlos Russo)
|
||||
* Added support for:
|
||||
- background color
|
||||
- Bode plots
|
||||
- zplane plots
|
||||
- freqz plots
|
||||
|
||||
# 2009-06-09 Version 0.0.4 [Nico Schlömer](nico.schloemer@ua.ac.be)
|
||||
|
||||
* Added support for:
|
||||
- error bars (thanks Robert Whittlesey for the suggestion)
|
||||
* Improvents in:
|
||||
- legends (thanks Theo Markettos for the patch),
|
||||
- images,
|
||||
- quiver plots (thanks Robert for spotting this).
|
||||
* Improved options handling.
|
||||
* Allow for custom file encoding (thanks Donghua Wang for the suggestion).
|
||||
* Numerous bugfixes (thanks Andreas Gäb).
|
||||
|
||||
# 2009-03-08 Version 0.0.3 [Nico Schlömer](nico.schloemer@ua.ac.be)
|
||||
|
||||
* Added support for:
|
||||
- subplots
|
||||
- reverse axes
|
||||
* Completed support for:
|
||||
- images
|
||||
|
||||
# 2009-01-08 Version 0.0.2 [Nico Schlömer](nico.schloemer@ua.ac.be)
|
||||
|
||||
* Added support for:
|
||||
- quiver (arrow) plots
|
||||
- bar plots
|
||||
- stem plots
|
||||
- stairs plots
|
||||
* Added preliminary support for:
|
||||
- images
|
||||
- rose plots
|
||||
- compass plots
|
||||
- polar plots
|
||||
* Moreover, large code improvement have been introduced, notably:
|
||||
- aspect ratio handling
|
||||
- color handling
|
||||
- plot options handling
|
||||
|
||||
# 2008-11-07 Version 0.0.1 [Nico Schlömer](nico.schloemer@ua.ac.be)
|
||||
|
||||
* Initial version
|
||||
@@ -0,0 +1,66 @@
|
||||
# Contributing to matlab2tikz
|
||||
|
||||
You can contribute in many ways to `matlab2tikz`:
|
||||
|
||||
- report bugs,
|
||||
- suggest new features,
|
||||
- write documentation,
|
||||
- fix some of our bugs and implement new features.
|
||||
|
||||
The first part of this document is geared more towards users of `matlab2tikz`.
|
||||
The latter part is only relevant if you want to write some code for `matlab2tikz`.
|
||||
|
||||
## How to report a bug or ask for help
|
||||
|
||||
1. Make sure you are using the [latest release](https://github.com/matlab2tikz/matlab2tikz/releases/latest) or even the [development version](https://github.com/matlab2tikz/matlab2tikz/tree/develop) of `matlab2tikz` and check that the problem still exists.
|
||||
2. Also make sure you are using a recent version of the required LaTeX packages (especially [`pgfplots`](http://ctan.org/pkg/pgfplots) and the [`TikZ`](http://ctan.org/pkg/pgf) libraries)
|
||||
3. You can submit your bug report or question to our [issue tracker](https://github.com/matlab2tikz/matlab2tikz/issues).
|
||||
Please, have a look at "[How to Ask Questions the Smart Way](http://www.catb.org/esr/faqs/smart-questions.html)" and "[Writing Better Bug Reports](http://martiancraft.com/blog/2014/07/good-bug-reports/)" for generic guidelines. In short:
|
||||
- Mention the version of MATLAB/Octave, the operating system, `matlab2tikz`, `pgfplots` and which `LaTeX` compiler you are using.
|
||||
- Choose a descriptive title for your issue report.
|
||||
- A short MATLAB code snippet that generates a plot where the problem occurs. Please limit this to what is strictly necessary to show the issue!
|
||||
- Explain what is wrong with the conversion of the figure (or what error messages you see).
|
||||
- Often it can be useful to also include a figure, `TikZ` code, ... to illustrate your point.
|
||||
|
||||
## How to request new features
|
||||
|
||||
Please check first whether the feature hasn't been [requested](https://github.com/matlab2tikz/matlab2tikz/labels/feature%20request) before and do join the relevant topic in that case or maybe it has already been implemented in the [latest development version](https://github.com/matlab2tikz/matlab2tikz/tree/develop).
|
||||
|
||||
If your feature is something new and graphical, please also have a look at the [`pgfplots`](https://www.ctan.org/pkg/pgfplots) manual to see if it supports the feature you want.
|
||||
In some cases it is more constructive to request the feature in the [`pgfplots` bug tracker](https://sourceforge.net/p/pgfplots/bugs/).
|
||||
|
||||
Please submit you feature request as any [bug report](https://github.com/matlab2tikz/matlab2tikz/labels/feature%20request) and make sure that you include enough details in your post, e.g.:
|
||||
|
||||
- What are you trying to do?
|
||||
- What should it look like or how should it work?
|
||||
- Is there a relevant section in the `pgfplots` or `MATLAB` documentation?
|
||||
|
||||
## Submitting pull requests (PRs)
|
||||
Before you start working on a bug or new feature, you might want to check that nobody else has been assigned to the relevant issue report.
|
||||
To avoid wasted hours, please just indicate your interest to tackle the issue.
|
||||
|
||||
### Recommended workflow
|
||||
[Our wiki](https://github.com/matlab2tikz/matlab2tikz/wiki/Recommended-git-workflow) contains more elaborate details on this process. Here is the gist:
|
||||
|
||||
- It is highly recommended to start a feature branch for your work.
|
||||
- Once you have finished the work, please try to run the test suite and report on the outcome in your PR (see below).
|
||||
- Make sure that you file your pull request against the `develop` branch and *not* the `master` branch!
|
||||
- Once you have filed your PR, the review process starts. Everybody is free to join this discussion.
|
||||
- At least one other developer will review the code and signal their approval (often using a thumbs-up, :+1:) before the PR gets pulled into `develop`.
|
||||
- Once you have addressed all comments, one of the developers will merge your code into the `develop` branch.
|
||||
|
||||
If you still feel uncomfortable with `git`, please have a look at [this page](https://github.com/matlab2tikz/matlab2tikz/wiki/Learning-git) for a quick start.
|
||||
|
||||
### Running the test suite
|
||||
We know that at first the test suite can seem a bit intimidating, so we tend to be lenient during your first few PRs. However, we encourage you to run the test suite on your local computer and report on the results in your PR if any failures pop up.
|
||||
To run the test suite, please consult its [README](https://github.com/matlab2tikz/matlab2tikz/blob/develop/test/README.md).
|
||||
|
||||
## Becoming a member of [matlab2tikz](https://github.com/matlab2tikz)
|
||||
|
||||
Once you have submitted your first pull request that is of reasonable quality, you may get invited to join the [Associate Developers](https://github.com/orgs/matlab2tikz/teams/associate-developers) group.
|
||||
This group comes with *no* responsibility whatsoever and merely serves to make it easier for you to "claim" the features you want to work on.
|
||||
|
||||
Once you have gained some experience (with `git`/GitHub, our codebase, ...) and have contributed your fair share of great material, you will get invited to join the [Developers](https://github.com/orgs/matlab2tikz/teams/developers) team.
|
||||
This status gives you push access to our repository and hence comes with the responsibility to not abuse your push access.
|
||||
|
||||
If you feel you should have gotten an invite for a team, feel free to contact one of the [owners](https://github.com/orgs/matlab2tikz/teams/owners).
|
||||
24
Functions/helper_functions_community/mat2tikz/LICENSE.md
Normal file
24
Functions/helper_functions_community/mat2tikz/LICENSE.md
Normal file
@@ -0,0 +1,24 @@
|
||||
Copyright (c) 2008--2016 Nico Schlömer
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the distribution
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
95
Functions/helper_functions_community/mat2tikz/README.md
Normal file
95
Functions/helper_functions_community/mat2tikz/README.md
Normal file
@@ -0,0 +1,95 @@
|
||||
**The updater in matlab2tikz 0.6.0 (and older) no longer works.**
|
||||
**Please [update manually](http://www.mathworks.com/matlabcentral/fileexchange/22022-matlab2tikz-matlab2tikz?download=true) if you are not using matlab2tikz 1.0.0 or newer!**
|
||||
|
||||
[](https://travis-ci.org/matlab2tikz/matlab2tikz) [](http://dx.doi.org/10.5281/zenodo.18605)
|
||||

|
||||
|
||||
`matlab2tikz` is a MATLAB(R) script to convert native MATLAB(R) figures to TikZ/Pgfplots figures that integrate seamlessly in LaTeX documents.
|
||||
|
||||
To download the official releases and rate `matlab2tikz`, please visit its page on [FileExchange](http://www.mathworks.com/matlabcentral/fileexchange/22022).
|
||||
|
||||
`matlab2tikz` converts most MATLAB(R) figures, including 2D and 3D plots.
|
||||
For plots constructed with third-party packages, however, your mileage may vary.
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
1. Extract the ZIP file (or clone the git repository) somewhere you can easily reach it.
|
||||
2. Add the `src/` folder to your path in MATLAB/Octave: e.g.
|
||||
- using the "Set Path" dialog in MATLAB, or
|
||||
- by running the `addpath` function from your command window or `startup` script.
|
||||
|
||||
Make sure that your LaTeX installation is up-to-date and includes:
|
||||
|
||||
* [TikZ/PGF](http://www.ctan.org/pkg/pgf) version 3.0 or higher
|
||||
* [Pgfplots](http://www.ctan.org/pkg/pgfplots) version 1.13 or higher
|
||||
* [Amsmath](https://www.ctan.org/pkg/amsmath) version 2.14 or higher
|
||||
* [Standalone](http://www.ctan.org/pkg/standalone) (optional)
|
||||
|
||||
It is recommended to use the latest stable version of these packages.
|
||||
Older versions may work depending on the actual MATLAB(R) figure you are converting.
|
||||
|
||||
Usage
|
||||
=====
|
||||
|
||||
Typical usage of `matlab2tikz` consists of converting your MATLAB plot to a TikZ/LaTeX file and then running a LaTeX compiler to produce your document.
|
||||
|
||||
MATLAB
|
||||
------
|
||||
1. Generate your plot in MATLAB(R).
|
||||
|
||||
2. Run `matlab2tikz`, e.g. using
|
||||
|
||||
```matlab
|
||||
matlab2tikz('myfile.tex');
|
||||
```
|
||||
|
||||
LaTeX
|
||||
-----
|
||||
Add the contents of `myfile.tex` into your LaTeX source code, for example using `\input{myfile.tex}`.
|
||||
Make sure that the required packages (such as `pgfplots`) are loaded in the preamble of your document as in the example:
|
||||
|
||||
```latex
|
||||
\documentclass{article}
|
||||
|
||||
\usepackage{pgfplots}
|
||||
\pgfplotsset{compat=newest}
|
||||
%% the following commands are needed for some matlab2tikz features
|
||||
\usetikzlibrary{plotmarks}
|
||||
\usetikzlibrary{arrows.meta}
|
||||
\usepgfplotslibrary{patchplots}
|
||||
\usepackage{grffile}
|
||||
\usepackage{amsmath}
|
||||
|
||||
%% you may also want the following commands
|
||||
%\pgfplotsset{plot coordinates/math parser=false}
|
||||
%\newlength\figureheight
|
||||
%\newlength\figurewidth
|
||||
|
||||
\begin{document}
|
||||
\input{myfile.tex}
|
||||
\end{document}
|
||||
```
|
||||
|
||||
Remarks
|
||||
-------
|
||||
Most functions accept numerous options; you can check them out by inspecting their help:
|
||||
|
||||
```matlab
|
||||
help matlab2tikz
|
||||
```
|
||||
|
||||
Sometimes, MATLAB(R) plots contain some features that impede conversion to LaTeX; e.g. points that are far outside of the actual bounding box.
|
||||
You can invoke the `cleanfigure` function to remove such unwanted entities before calling `matlab2tikz`:
|
||||
|
||||
```matlab
|
||||
cleanfigure;
|
||||
matlab2tikz('myfile.tex');
|
||||
```
|
||||
|
||||
More information
|
||||
================
|
||||
|
||||
* For more information about `matlab2tikz`, have a look at our [GitHub repository](https://github.com/matlab2tikz/matlab2tikz). If you are a good MATLAB(R) programmer or LaTeX writer, you are always welcome to help improving `matlab2tikz`!
|
||||
* Some common problems and pit-falls are documented in our [wiki](https://github.com/matlab2tikz/matlab2tikz/wiki/Common-problems).
|
||||
* If you experience (other) bugs or would like to request a feature, please visit our [issue tracker](https://github.com/matlab2tikz/matlab2tikz/issues).
|
||||
@@ -0,0 +1,102 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="2083.4766"
|
||||
height="856.6734"
|
||||
id="svg3051"
|
||||
version="1.1"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="matlab2tikz.svg">
|
||||
<defs
|
||||
id="defs3053" />
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="0.5"
|
||||
inkscape:cx="1424.8959"
|
||||
inkscape:cy="275.08087"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
inkscape:window-width="1680"
|
||||
inkscape:window-height="949"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
fit-margin-top="5"
|
||||
fit-margin-left="5"
|
||||
fit-margin-right="5"
|
||||
fit-margin-bottom="5" />
|
||||
<metadata
|
||||
id="metadata3056">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(96.763877,-104.02549)">
|
||||
<path
|
||||
style="fill:#ef8200;fill-opacity:1;stroke:none"
|
||||
d="m 229.79347,889.91953 c -51.20296,-69.53548 -110.45905,-150.5284 -117.8477,-161.07762 -3.66043,-5.22621 -4.15923,-6.45766 -2.93039,-7.23468 0.81449,-0.51503 2.1559,-0.94763 2.9809,-0.96134 4.45183,-0.074 21.84491,-16.50352 39.70528,-37.5057 64.93246,-76.3547 212.14442,-292.5117 313.27925,-460 28.45805,-47.12908 55.23448,-94.70724 59.01417,-107.81682 2.21373,-7.67817 3.30364,-4.58186 5.54982,7.259 0.84717,4.46595 9.42069,39.94343 19.05225,78.83886 61.4356,248.09709 88.96885,376.22196 95.45994,444.21896 1.34274,14.06576 0.80116,31.67542 -1.06339,34.57694 -0.67969,1.05768 -29.41344,23.07306 -63.85279,48.92306 -46.63668,35.00526 -216.41083,162.82778 -297.77739,224.19582 l -3.13285,2.36286 z"
|
||||
id="path3072"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#ffd912;fill-opacity:1"
|
||||
d="M 828.49628,790.87316 C 751.45425,746.41551 656.62349,689.46978 647.33146,682.08395 c -2.47911,-1.97053 -2.52321,-2.17947 -1.05805,-5.01277 3.18772,-6.16438 4.02557,-14.85566 3.44538,-35.74002 -0.80529,-28.98647 -5.98761,-65.55929 -17.38517,-122.69097 -18.80756,-94.27528 -55.9766,-241.89492 -91.4729,-363.29152 -4.95189,-16.93533 -13.8484,-44.15875 -13.64905,-44.7568 0.19935,-0.59804 7.77507,16.91106 10.71396,23.16944 14.72516,31.35732 169.10504,368.5638 262.04653,572.37888 18.81036,41.25 35.965,78.78344 38.1214,83.40766 2.15641,4.62421 3.80419,8.50202 3.66173,8.61735 -0.14245,0.11533 -6.10901,-3.16608 -13.25901,-7.29204 z"
|
||||
id="path3070"
|
||||
inkscape:connector-curvature="0" />
|
||||
<path
|
||||
style="fill:#00b0cf;fill-opacity:1"
|
||||
d="M 98.496283,712.93087 C 76.224153,691.69469 25.659453,651.42885 -55.133796,590.59166 l -36.630081,-27.58239 14.630081,-4.80606 C 1.4604828e-5,532.86436 84.848253,489.14509 155.49628,438.33721 c 90.71369,-65.23848 211.18904,-171.14032 339.75,-298.65155 14.7125,-14.59237 30.24771,-31.09621 30.24771,-30.65137 0,1.46965 -5.56006,9.74411 -33.50167,53.6059 -117.938,185.13504 -236.74752,364.94776 -300.3065,454.5 -22.45559,31.6391 -46.86362,64.24839 -58.75719,78.5 -10.15154,12.16419 -23.13943,25.02746 -25.20109,24.95928 -0.6772,-0.0224 -4.83126,-3.47326 -9.231257,-7.6686 z"
|
||||
id="path2987"
|
||||
inkscape:connector-curvature="0" />
|
||||
<text
|
||||
xml:space="preserve"
|
||||
style="font-style:italic;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:256.08959961px;line-height:125%;font-family:'Monotype Corsiva';-inkscape-font-specification:'Monotype Corsiva Bold Italic';letter-spacing:0px;word-spacing:0px;fill:#ef8200;fill-opacity:1;stroke:none"
|
||||
x="835.56165"
|
||||
y="469.78217"
|
||||
id="text3863"
|
||||
sodipodi:linespacing="125%"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan3865"
|
||||
x="835.56165"
|
||||
y="469.78217"
|
||||
style="font-style:italic;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans Italic';fill:#000000;fill-opacity:1"><tspan
|
||||
style="font-style:normal;-inkscape-font-specification:'Liberation Sans'"
|
||||
id="tspan2999">MATLAB</tspan><tspan
|
||||
style="font-style:italic;font-weight:bold;-inkscape-font-specification:'Liberation Sans Italic'"
|
||||
id="tspan2997">2</tspan></tspan><tspan
|
||||
sodipodi:role="line"
|
||||
x="835.56165"
|
||||
y="789.89417"
|
||||
id="tspan3867"
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';fill:#ef8200;fill-opacity:1"><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';fill:#000000"
|
||||
id="tspan3875">Ti</tspan><tspan
|
||||
style="font-style:italic;-inkscape-font-specification:'Liberation Sans Italic'"
|
||||
id="tspan2995">k</tspan><tspan
|
||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-family:'Liberation Sans';-inkscape-font-specification:'Liberation Sans';fill:#000000"
|
||||
id="tspan3873">Z</tspan></tspan></text>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.8 KiB |
@@ -0,0 +1,49 @@
|
||||
{
|
||||
"folders":
|
||||
[
|
||||
{
|
||||
"path": "."
|
||||
}
|
||||
],
|
||||
"build_systems":
|
||||
[
|
||||
{
|
||||
"name": "CI tests (Octave)",
|
||||
"selector": "source.matlab",
|
||||
"working_dir": "${project_path}",
|
||||
"cmd": ["./runtests.sh", "octave"]
|
||||
},
|
||||
{
|
||||
"name": "CI tests (MATLAB)",
|
||||
"selector": "source.matlab",
|
||||
"working_dir": "${project_path}",
|
||||
"cmd": ["./runtests.sh", "matlab"]
|
||||
},
|
||||
{
|
||||
"name": "CI tests (MATLAB HG1)",
|
||||
"selector": "source.matlab",
|
||||
"working_dir": "${project_path}",
|
||||
"cmd": ["./runtests.sh", "matlab-hg1"]
|
||||
},
|
||||
{
|
||||
"name": "CI tests (MATLAB HG2)",
|
||||
"selector": "source.matlab",
|
||||
"working_dir": "${project_path}",
|
||||
"cmd": ["./runtests.sh", "matlab-hg2"]
|
||||
},
|
||||
{
|
||||
"name": "ACID: make",
|
||||
"working_dir": "${project_path}/test/tex",
|
||||
"cmd": ["make","-j8"]
|
||||
},
|
||||
{
|
||||
"name": "ACID: distclean",
|
||||
"working_dir": "${project_path}/test/tex",
|
||||
"cmd": ["make","distclean"]
|
||||
}
|
||||
],
|
||||
"settings":
|
||||
{
|
||||
"FuzzyFilePath":{}
|
||||
}
|
||||
}
|
||||
86
Functions/helper_functions_community/mat2tikz/runtests.sh
Normal file
86
Functions/helper_functions_community/mat2tikz/runtests.sh
Normal file
@@ -0,0 +1,86 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Test script runner for MATLAB2TIKZ continuous integration
|
||||
#
|
||||
# You can influence the execution by passing one or two parameters
|
||||
# to this function, as
|
||||
#
|
||||
# ./runtests.sh RUNNER SWITCHES
|
||||
#
|
||||
# Arguments:
|
||||
# - RUNNER: (path of) the binary you want to use to execute the tests
|
||||
# default value: "octave"
|
||||
# - SWITCHES: switches you want to pass to the executable
|
||||
# default value: * "-nodesktop -r" if runner contains "matlab"
|
||||
# * "--no-gui --eval" if runner contains "octave" and otherwise
|
||||
#
|
||||
|
||||
# Used resources:
|
||||
# - http://askubuntu.com/questions/299710/how-to-determine-if-a-string-is-a-substring-of-another-in-bash
|
||||
# - http://www.thegeekstuff.com/2010/07/bash-case-statement/
|
||||
# - http://stackoverflow.com/questions/229551/string-contains-in-bash
|
||||
# - http://stackoverflow.com/questions/2870992/automatic-exit-from-bash-shell-script-on-error
|
||||
# - http://www.davidpashley.com/articles/writing-robust-shell-scripts/
|
||||
# - http://stackoverflow.com/questions/13998941/how-can-i-propagate-an-exit-status-from-expect-to-its-parent-bash-script
|
||||
# - http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-8.html
|
||||
|
||||
## Make sure some failures are detected by the CI runners
|
||||
function exitIfError {
|
||||
# pass "$?" as argument: i.e. the exit status of the last call
|
||||
if [ "$1" -ne 0 ]; then
|
||||
exit $1;
|
||||
fi
|
||||
}
|
||||
|
||||
## Handle Runner and Switches variables
|
||||
Runner=$1
|
||||
Switches=$2
|
||||
if [ -z "$Runner" ] ; then
|
||||
Runner="octave"
|
||||
fi
|
||||
if [ -z "$Switches" ] ; then
|
||||
case "$Runner" in
|
||||
*matlab* )
|
||||
Switches="-nodesktop -r"
|
||||
;;
|
||||
|
||||
*octave* )
|
||||
Switches="--no-gui --eval"
|
||||
;;
|
||||
|
||||
* )
|
||||
# Fall back to Octave switches
|
||||
Switches="--no-gui --eval"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
## Make sure MATLAB/Octave know the intent
|
||||
# note: the export is required
|
||||
export CONTINUOUS_INTEGRATION=true
|
||||
export CI=true
|
||||
|
||||
## Actually run the test suite
|
||||
cd test
|
||||
TESTDIR=`pwd`
|
||||
# also CD in MATLAB/Octave to make sure that startup files
|
||||
# cannot play any role in setting the path
|
||||
${Runner} ${Switches} "cd('${TESTDIR}'); runMatlab2TikzTests"
|
||||
exitIfError $?
|
||||
cd ..
|
||||
|
||||
## Post-processing
|
||||
|
||||
# convert MD report into HTML using pandoc if available
|
||||
MDFILE="test/results.test.md"
|
||||
if [ ! -z `which pandoc` ]; then
|
||||
if [ -f $MDFILE ]; then
|
||||
HTMLFILE=${MDFILE/md/html}
|
||||
# replace the emoji while we're at it
|
||||
pandoc -f markdown -t html $MDFILE -o $HTMLFILE
|
||||
sed -i -- 's/:heavy_exclamation_mark:/❗️/g' $HTMLFILE
|
||||
sed -i -- 's/:white_check_mark:/✅/g' $HTMLFILE
|
||||
sed -i -- 's/:grey_question:/❔/g' $HTMLFILE
|
||||
fi
|
||||
fi
|
||||
|
||||
1294
Functions/helper_functions_community/mat2tikz/src/cleanfigure.m
Normal file
1294
Functions/helper_functions_community/mat2tikz/src/cleanfigure.m
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,87 @@
|
||||
function formatWhitespace(filename)
|
||||
% FORMATWHITESPACE Formats whitespace and indentation of a document
|
||||
%
|
||||
% FORMATWHITESPACE(FILENAME)
|
||||
% Indents currently active document if FILENAME is empty or not
|
||||
% specified. FILENAME must be the name of an open document in the
|
||||
% editor.
|
||||
%
|
||||
% Rules:
|
||||
% - Smart-indent with all function indent option
|
||||
% - Indentation is 4 spaces
|
||||
% - Remove whitespace in empty lines
|
||||
% - Preserve indentantion after line continuations, i.e. ...
|
||||
%
|
||||
import matlab.desktop.editor.*
|
||||
|
||||
if nargin < 1, filename = ''; end
|
||||
|
||||
d = getDoc(filename);
|
||||
oldLines = textToLines(d.Text);
|
||||
|
||||
% Smart indent as AllFunctionIndent
|
||||
% Using undocumented feature from http://undocumentedmatlab.com/blog/changing-system-preferences-programmatically
|
||||
editorProp = 'EditorMFunctionIndentType';
|
||||
oldVal = com.mathworks.services.Prefs.getStringPref(editorProp);
|
||||
com.mathworks.services.Prefs.setStringPref(editorProp, 'AllFunctionIndent');
|
||||
restoreSettings = onCleanup(@() com.mathworks.services.Prefs.setStringPref(editorProp, oldVal));
|
||||
d.smartIndentContents()
|
||||
|
||||
% Preserve crafted continuations of line
|
||||
lines = textToLines(d.Text);
|
||||
iContinuation = ~cellfun('isempty',strfind(lines, '...'));
|
||||
iComment = ~cellfun('isempty',regexp(lines, '^ *%([^%]|$)','once'));
|
||||
pAfterDots = find(iContinuation & ~iComment)+1;
|
||||
for ii = 1:numel(pAfterDots)
|
||||
% Carry over the change in space due to smart-indenting from the
|
||||
% first continuation line to the last
|
||||
p = pAfterDots(ii);
|
||||
nWhiteBefore = find(~isspace(oldLines{p-1}),1,'first');
|
||||
nWhiteAfter = find(~isspace(lines{p-1}),1,'first');
|
||||
df = nWhiteAfter - nWhiteBefore;
|
||||
if df > 0
|
||||
lines{p} = [blanks(df) oldLines{p}];
|
||||
elseif df < 0
|
||||
df = min(abs(df)+1, find(~isspace(oldLines{p}),1,'first'));
|
||||
lines{p} = oldLines{p}(df:end);
|
||||
else
|
||||
lines{p} = oldLines{p};
|
||||
end
|
||||
end
|
||||
|
||||
% Remove whitespace lines
|
||||
idx = cellfun('isempty',regexp(lines, '[^ \t\n]','once'));
|
||||
lines(idx) = {''};
|
||||
|
||||
d.Text = linesToText(lines);
|
||||
end
|
||||
|
||||
function d = getDoc(filename)
|
||||
import matlab.desktop.editor.*
|
||||
|
||||
if ~ischar(filename)
|
||||
error('formatWhitespace:charFilename','The FILENAME should be a char.')
|
||||
end
|
||||
|
||||
try
|
||||
isEditorAvailable();
|
||||
catch
|
||||
error('formatWhitespace:noEditorApi','Check that the Editor API is available.')
|
||||
end
|
||||
|
||||
if isempty(filename)
|
||||
d = getActive();
|
||||
else
|
||||
% TODO: open file if it isn't open in the editor already
|
||||
d = findOpenDocument(filename);
|
||||
try
|
||||
[~,filenameFound] = fileparts(d.Filename);
|
||||
catch
|
||||
filenameFound = '';
|
||||
end
|
||||
isExactMatch = strcmp(filename, filenameFound);
|
||||
if ~isExactMatch
|
||||
error('formatWhitespace:filenameNotFound','Filename "%s" not found in the editor.', filename)
|
||||
end
|
||||
end
|
||||
end
|
||||
123
Functions/helper_functions_community/mat2tikz/src/figure2dot.m
Normal file
123
Functions/helper_functions_community/mat2tikz/src/figure2dot.m
Normal file
@@ -0,0 +1,123 @@
|
||||
function figure2dot(filename, varargin)
|
||||
%FIGURE2DOT Save figure in Graphviz (.dot) file.
|
||||
% FIGURE2DOT(filename) saves the current figure as dot-file.
|
||||
%
|
||||
% FIGURE2DOT(filename, 'object', HGOBJECT) constructs the graph representation
|
||||
% of the specified object (default: gcf)
|
||||
%
|
||||
% You can visualize the constructed DOT file using:
|
||||
% - [GraphViz](http://www.graphviz.org) on your computer
|
||||
% - [WebGraphViz](http://www.webgraphviz.com) online
|
||||
% - [Gravizo](http://www.gravizo.com) for your markdown files
|
||||
% - and a lot of other software such as OmniGraffle
|
||||
%
|
||||
% See also: matlab2tikz, cleanfigure, uiinspect, inspect
|
||||
|
||||
ipp = m2tInputParser();
|
||||
ipp = ipp.addRequired(ipp, 'filename', @ischar);
|
||||
ipp = ipp.addParamValue(ipp, 'object', gcf, @ishghandle);
|
||||
ipp = ipp.parse(ipp, filename, varargin{:});
|
||||
args = ipp.Results;
|
||||
|
||||
filehandle = fopen(args.filename, 'w');
|
||||
finally_fclose_filehandle = onCleanup(@() fclose(filehandle));
|
||||
|
||||
% start printing
|
||||
fprintf(filehandle, 'digraph simple_hierarchy {\n\n');
|
||||
fprintf(filehandle, 'node[shape=box];\n\n');
|
||||
|
||||
% define the root node
|
||||
node_number = 0;
|
||||
p = get(args.object, 'Parent');
|
||||
% define root element
|
||||
type = get(p, 'Type');
|
||||
fprintf(filehandle, 'N%d [label="%s"]\n\n', node_number, type);
|
||||
|
||||
% start recursion
|
||||
plot_children(filehandle, p, node_number);
|
||||
|
||||
% finish off
|
||||
fprintf(filehandle, '}');
|
||||
|
||||
% ----------------------------------------------------------------------------
|
||||
function plot_children(fh, h, parent_node)
|
||||
|
||||
children = allchild(h);
|
||||
|
||||
for h = children(:)'
|
||||
if shouldSkip(h), continue, end;
|
||||
node_number = node_number + 1;
|
||||
|
||||
label = {};
|
||||
label = addHGProperty(label, h, 'Type', '');
|
||||
try
|
||||
hClass = class(handle(h));
|
||||
label = addProperty(label, 'Class', hClass);
|
||||
catch
|
||||
% don't do anything
|
||||
end
|
||||
label = addProperty(label, 'Handle', sprintf('%g', double(h)));
|
||||
label = addHGProperty(label, h, 'Title', '');
|
||||
label = addHGProperty(label, h, 'Axes', []);
|
||||
label = addHGProperty(label, h, 'String', '');
|
||||
label = addHGProperty(label, h, 'Tag', '');
|
||||
label = addHGProperty(label, h, 'DisplayName', '');
|
||||
label = addHGProperty(label, h, 'Visible', 'on');
|
||||
label = addHGProperty(label, h, 'HandleVisibility', 'on');
|
||||
|
||||
% print node
|
||||
fprintf(fh, 'N%d [label="%s"]\n', ...
|
||||
node_number, m2tstrjoin(label, '\n'));
|
||||
|
||||
% connect to the child
|
||||
fprintf(fh, 'N%d -> N%d;\n\n', parent_node, node_number);
|
||||
|
||||
% recurse
|
||||
plot_children(fh, h, node_number);
|
||||
end
|
||||
end
|
||||
end
|
||||
% ==============================================================================
|
||||
function bool = shouldSkip(h)
|
||||
% returns TRUE for objects that can be skipped
|
||||
objType = get(h, 'Type');
|
||||
bool = ismember(lower(objType), guitypes());
|
||||
end
|
||||
% ==============================================================================
|
||||
function label = addHGProperty(label, h, propName, default)
|
||||
% get a HG property and assign it to a GraphViz node label
|
||||
if ~exist('default','var') || isempty(default)
|
||||
shouldOmit = @isempty;
|
||||
elseif isa(default, 'function_handle')
|
||||
shouldOmit = default;
|
||||
else
|
||||
shouldOmit = @(v) isequal(v,default);
|
||||
end
|
||||
|
||||
if isprop(h, propName)
|
||||
propValue = get(h, propName);
|
||||
if numel(propValue) == 1 && ishghandle(propValue) && isprop(propValue, 'String')
|
||||
% dereference Titles, labels, ...
|
||||
propValue = get(propValue, 'String');
|
||||
elseif ishghandle(propValue)
|
||||
% dereference other HG objects to their raw handle value (double)
|
||||
propValue = double(propValue);
|
||||
elseif iscell(propValue)
|
||||
propValue = ['{' m2tstrjoin(propValue,',') '}'];
|
||||
end
|
||||
|
||||
if ~shouldOmit(propValue)
|
||||
label = addProperty(label, propName, propValue);
|
||||
end
|
||||
end
|
||||
end
|
||||
function label = addProperty(label, propName, propValue)
|
||||
% add a property to a GraphViz node label
|
||||
if isnumeric(propValue)
|
||||
propValue = num2str(propValue);
|
||||
elseif iscell(propValue)
|
||||
propValue = m2tstrjoin(propValue,sprintf('\n'));
|
||||
end
|
||||
label = [label, sprintf('%s: %s', propName, propValue)];
|
||||
end
|
||||
% ==============================================================================
|
||||
@@ -0,0 +1,231 @@
|
||||
function parser = m2tInputParser()
|
||||
%MATLAB2TIKZINPUTPARSER Input parsing for matlab2tikz.
|
||||
% This implementation exists because Octave is lacking one.
|
||||
|
||||
% Initialize the structure.
|
||||
parser = struct ();
|
||||
% Public Properties
|
||||
parser.Results = {};
|
||||
% Enabel/disable parameters case sensitivity.
|
||||
parser.CaseSensitive = false;
|
||||
% Keep parameters not defined by the constructor.
|
||||
parser.KeepUnmatched = false;
|
||||
% Enable/disable warning for parameters not defined by the constructor.
|
||||
parser.WarnUnmatched = true;
|
||||
% Enable/disable passing arguments in a structure.
|
||||
parser.StructExpand = true;
|
||||
% Names of parameters defined in input parser constructor.
|
||||
parser.Parameters = {};
|
||||
% Names of parameters not defined in the constructor.
|
||||
parser.Unmatched = struct ();
|
||||
% Names of parameters using default values.
|
||||
parser.UsingDefaults = {};
|
||||
% Names of deprecated parameters and their alternatives
|
||||
parser.DeprecatedParameters = struct();
|
||||
|
||||
% Handles for functions that act on the object.
|
||||
parser.addRequired = @addRequired;
|
||||
parser.addOptional = @addOptional;
|
||||
parser.addParamValue = @addParamValue;
|
||||
parser.deprecateParam = @deprecateParam;
|
||||
parser.parse = @parse;
|
||||
|
||||
% Initialize the parser plan
|
||||
parser.plan = {};
|
||||
end
|
||||
% =========================================================================
|
||||
function p = parser_plan (q, arg_type, name, default, validator)
|
||||
p = q;
|
||||
plan = p.plan;
|
||||
if (isempty (plan))
|
||||
plan = struct ();
|
||||
n = 1;
|
||||
else
|
||||
n = numel (plan) + 1;
|
||||
end
|
||||
plan(n).type = arg_type;
|
||||
plan(n).name = name;
|
||||
plan(n).default = default;
|
||||
plan(n).validator = validator;
|
||||
p.plan = plan;
|
||||
end
|
||||
% =========================================================================
|
||||
function p = addRequired (p, name, validator)
|
||||
p = parser_plan (p, 'required', name, [], validator);
|
||||
end
|
||||
% =========================================================================
|
||||
function p = addOptional (p, name, default, validator)
|
||||
p = parser_plan (p, 'optional', name, default, validator);
|
||||
end
|
||||
% =========================================================================
|
||||
function p = addParamValue (p, name, default, validator)
|
||||
p = parser_plan (p, 'paramvalue', name, default, validator);
|
||||
end
|
||||
% =========================================================================
|
||||
function p = deprecateParam (p, name, alternatives)
|
||||
if isempty(alternatives)
|
||||
alternatives = {};
|
||||
elseif ischar(alternatives)
|
||||
alternatives = {alternatives}; % make cellstr
|
||||
elseif ~iscellstr(alternatives)
|
||||
error('m2tInputParser:BadAlternatives',...
|
||||
'Alternatives for a deprecated parameter must be a char or cellstr');
|
||||
end
|
||||
p.DeprecatedParameters.(name) = alternatives;
|
||||
end
|
||||
% =========================================================================
|
||||
function p = parse (p, varargin)
|
||||
plan = p.plan;
|
||||
results = p.Results;
|
||||
using_defaults = {};
|
||||
if (p.CaseSensitive)
|
||||
name_cmp = @strcmp;
|
||||
else
|
||||
name_cmp = @strcmpi;
|
||||
end
|
||||
if (p.StructExpand)
|
||||
k = find (cellfun (@isstruct, varargin));
|
||||
for m = numel(k):-1:1
|
||||
n = k(m);
|
||||
s = varargin{n};
|
||||
c = [fieldnames(s).'; struct2cell(s).'];
|
||||
c = c(:).';
|
||||
if (n > 1 && n < numel (varargin))
|
||||
varargin = horzcat (varargin(1:n-1), c, varargin(n+1:end));
|
||||
elseif (numel (varargin) == 1)
|
||||
varargin = c;
|
||||
elseif (n == 1);
|
||||
varargin = horzcat (c, varargin(n+1:end));
|
||||
else % n == numel (varargin)
|
||||
varargin = horzcat (varargin(1:n-1), c);
|
||||
end
|
||||
end
|
||||
end
|
||||
if (isempty (results))
|
||||
results = struct ();
|
||||
end
|
||||
type = {plan.type};
|
||||
n = find( strcmp( type, 'paramvalue' ) );
|
||||
m = setdiff (1:numel( plan ), n );
|
||||
plan = plan ([n,m]);
|
||||
for n = 1 : numel (plan)
|
||||
found = false;
|
||||
results.(plan(n).name) = plan(n).default;
|
||||
if (~ isempty (varargin))
|
||||
switch plan(n).type
|
||||
case 'required'
|
||||
found = true;
|
||||
if (strcmpi (varargin{1}, plan(n).name))
|
||||
varargin(1) = [];
|
||||
end
|
||||
value = varargin{1};
|
||||
varargin(1) = [];
|
||||
case 'optional'
|
||||
m = find (cellfun (@ischar, varargin));
|
||||
k = find (name_cmp (plan(n).name, varargin(m)));
|
||||
if (isempty (k) && validate_arg (plan(n).validator, varargin{1}))
|
||||
found = true;
|
||||
value = varargin{1};
|
||||
varargin(1) = [];
|
||||
elseif (~ isempty (k))
|
||||
m = m(k);
|
||||
found = true;
|
||||
value = varargin{max(m)+1};
|
||||
varargin(union(m,m+1)) = [];
|
||||
end
|
||||
case 'paramvalue'
|
||||
m = find( cellfun (@ischar, varargin) );
|
||||
k = find (name_cmp (plan(n).name, varargin(m)));
|
||||
if (~ isempty (k))
|
||||
found = true;
|
||||
m = m(k);
|
||||
value = varargin{max(m)+1};
|
||||
varargin(union(m,m+1)) = [];
|
||||
end
|
||||
otherwise
|
||||
error( sprintf ('%s:parse', mfilename), ...
|
||||
'parse (%s): Invalid argument type.', mfilename ...
|
||||
)
|
||||
end
|
||||
end
|
||||
if (found)
|
||||
if (validate_arg (plan(n).validator, value))
|
||||
results.(plan(n).name) = value;
|
||||
else
|
||||
error( sprintf ('%s:invalidinput', mfilename), ...
|
||||
'%s: Input argument ''%s'' has invalid value.\n', mfilename, plan(n).name ...
|
||||
);
|
||||
end
|
||||
p.Parameters = union (p.Parameters, {plan(n).name});
|
||||
elseif (strcmp (plan(n).type, 'required'))
|
||||
error( sprintf ('%s:missinginput', mfilename), ...
|
||||
'%s: input ''%s'' is missing.\n', mfilename, plan(n).name ...
|
||||
);
|
||||
else
|
||||
using_defaults = union (using_defaults, {plan(n).name});
|
||||
end
|
||||
end
|
||||
|
||||
if ~isempty(varargin)
|
||||
% Include properties that do not match specified properties
|
||||
for n = 1:2:numel(varargin)
|
||||
if ischar(varargin{n})
|
||||
if p.KeepUnmatched
|
||||
results.(varargin{n}) = varargin{n+1};
|
||||
end
|
||||
if p.WarnUnmatched
|
||||
warning(sprintf('%s:unmatchedArgument',mfilename), ...
|
||||
'Ignoring unknown argument "%s"', varargin{n});
|
||||
end
|
||||
p.Unmatched.(varargin{n}) = varargin{n+1};
|
||||
else
|
||||
error (sprintf ('%s:invalidinput', mfilename), ...
|
||||
'%s: invalid input', mfilename)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
% Store the results of the parsing
|
||||
p.Results = results;
|
||||
p.UsingDefaults = using_defaults;
|
||||
|
||||
warnForDeprecatedParameters(p);
|
||||
end
|
||||
% =========================================================================
|
||||
function result = validate_arg (validator, arg)
|
||||
try
|
||||
result = validator (arg);
|
||||
catch %#ok
|
||||
result = false;
|
||||
end
|
||||
end
|
||||
% =========================================================================
|
||||
function warnForDeprecatedParameters(p)
|
||||
usedDeprecatedParameters = intersect(p.Parameters, fieldnames(p.DeprecatedParameters));
|
||||
|
||||
for iParam = 1:numel(usedDeprecatedParameters)
|
||||
oldParameter = usedDeprecatedParameters{iParam};
|
||||
alternatives = p.DeprecatedParameters.(oldParameter);
|
||||
|
||||
switch numel(alternatives)
|
||||
case 0
|
||||
replacements = '';
|
||||
case 1
|
||||
replacements = ['''' alternatives{1} ''''];
|
||||
otherwise
|
||||
replacements = deblank(sprintf('''%s'' and ',alternatives{:}));
|
||||
replacements = regexprep(replacements,' and$','');
|
||||
end
|
||||
if ~isempty(replacements)
|
||||
replacements = sprintf('From now on, please use %s to control the output.\n',replacements);
|
||||
end
|
||||
|
||||
message = ['\n===============================================================================\n', ...
|
||||
'You are using the deprecated parameter ''%s''.\n', ...
|
||||
'%s', ...
|
||||
'==============================================================================='];
|
||||
warning('matlab2tikz:deprecatedParameter', ...
|
||||
message, oldParameter, replacements);
|
||||
|
||||
end
|
||||
end
|
||||
216
Functions/helper_functions_community/mat2tikz/src/m2tcustom.m
Normal file
216
Functions/helper_functions_community/mat2tikz/src/m2tcustom.m
Normal file
@@ -0,0 +1,216 @@
|
||||
function [value] = m2tcustom(handle, varargin)
|
||||
% M2TCUSTOM creates user-defined options for matlab2tikz output
|
||||
%
|
||||
% M2TCUSTOM can be used to create, get and set a properly formatted data
|
||||
% structure to customize the conversion of MATLAB figures to TikZ using
|
||||
% matlab2tikz. In particular, it allows to:
|
||||
%
|
||||
% * add blocks of LaTeX/TikZ code around any HG object,
|
||||
% * add blocks of comments around any HG object,
|
||||
% * add TikZ options to any HG object,
|
||||
% * add LaTeX/TikZ code inside some HG objects (e.g. axes),
|
||||
% * provide a custom handler to convert a particular HG object.
|
||||
%
|
||||
% Note that this provides advanced functionality. Only very basic
|
||||
% sanity checks are performed such that injudicious use may produce
|
||||
% broken TikZ figures!
|
||||
%
|
||||
% It is HIGHLY recommended that you are comfortable with:
|
||||
%
|
||||
% * writing pgfplots, TikZ and LaTeX code,
|
||||
% * using the Handle Graphics (HG) framework in MATLAB/Octave, and
|
||||
% * the inner working of matlab2tikz (for custom handlers)
|
||||
%
|
||||
% when you use this function. I.e. you should know what you are doing.
|
||||
%
|
||||
%
|
||||
% Usage as a GETTER:
|
||||
% ------------------
|
||||
%
|
||||
% value = M2TCUSTOM(handle)
|
||||
% retrieves the current custom data structure from the HG object "handle"
|
||||
%
|
||||
%
|
||||
% Usage as a SETTER:
|
||||
% ------------------
|
||||
%
|
||||
% M2TCUSTOM(handle, ...)
|
||||
% value = M2TCUSTOM(handle, ...)
|
||||
% will construct the proper data structure and try to set it to the object
|
||||
% |handle| if possible. The arguments (see below) are specified in
|
||||
% key-value pairs akin to a normal |struct|, but here we do a few checks
|
||||
% and data normalization.
|
||||
%
|
||||
% If we denote BLOCK to mean either a |char| or a |cellstr|, the following
|
||||
% options can be passed. Different entries in a cellstr are assumed
|
||||
% separated by a newline. The default values are empty.
|
||||
%
|
||||
% M2TCUSTOM(handle, 'commentBefore', BLOCK, ...)
|
||||
% M2TCUSTOM(handle, 'commentAfter' , BLOCK, ...)
|
||||
% to add comments before/after the object. Our code translates newlines
|
||||
% and adds the percentage signs for you.
|
||||
%
|
||||
% M2TCUSTOM(handle, 'codeBefore', BLOCK, ...)
|
||||
% M2TCUSTOM(handle, 'codeAfter', BLOCK, ...)
|
||||
% M2TCUSTOM(handle, 'codeInsideFirst', BLOCK, ...)
|
||||
% M2TCUSTOM(handle, 'codeInsideLast', BLOCK, ...)
|
||||
% to add raw LaTeX/TikZ code respectively before, after, as first thing
|
||||
% inside or as last thing inside the pgfplots representation of the object.
|
||||
% Note that for some HG objects, (e.g. line objects), |codeInsideFirst|
|
||||
% and |codeInsideLast| do not make any sense and are hence ignored.
|
||||
%
|
||||
% M2TCUSTOM(handle, 'extraOptions', OPTIONS, ...)
|
||||
% adds extra pgfplots/TikZ options to the end of the option list. Here,
|
||||
% OPTIONS is properly formatted TikZ code in
|
||||
% - a |char| (e.g. 'color=red, line width=1pt' )
|
||||
% - a |cellstr| (e.g. {'color=red','line width=1pt'})
|
||||
%
|
||||
% M2TCUSTOM(handle, 'customHandler', FUNCTION_HANDLE, ...)
|
||||
% allows you to replace the default matlab2tikz handler for this object.
|
||||
% This is not for the faint of heart and requires intimate knowledge of
|
||||
% the matlab2tikz code base! We expect a function (either as |char| or
|
||||
% function handle) that will be called as
|
||||
%
|
||||
% [m2t, str] = feval(handler, m2t, handle, custom)
|
||||
%
|
||||
% such that the expected function signature is:
|
||||
%
|
||||
% function [m2t, str] = handler(m2t, handle, custom)
|
||||
%
|
||||
% where |m2t| is an undocumented/unstable data structure,
|
||||
% |str| is a char containing TikZ code representing the
|
||||
% HG object |handle| as generated by your handler,
|
||||
% |custom| is a structure as returned by |m2tcustom|
|
||||
% from which you only need to handle |extraOptions|,
|
||||
% |codeInsideFirst| and |codeInsideLast| when applicable.
|
||||
% A particularly useful value for |customHandler| is 'drawNothing',
|
||||
% which remove the object from the output.
|
||||
%
|
||||
%
|
||||
% Example:
|
||||
% --------
|
||||
%
|
||||
% Executing the following MATLAB code fragment:
|
||||
%
|
||||
% figure;
|
||||
% plot(1:10);
|
||||
% EOL = sprintf('\n');
|
||||
% m2tCustom(gca, 'codeBefore' , ['<codeBefore>' EOL] , ...
|
||||
% 'codeAfter' , ['<codeAfter>' EOL] , ...
|
||||
% 'commentsBefore' , '<commentsBefore>' , ...
|
||||
% 'commentsAfter' , '<commentsAfter>' , ...
|
||||
% 'codeInsideFirst' , ['<codeInsideFirst>' EOL], ...
|
||||
% 'codeInsideLast' , ['<codeInsideLast>' EOL], ...
|
||||
% 'extraOptions' , '<extraOptions>');
|
||||
%
|
||||
% matlab2tikz('test.tikz')
|
||||
%
|
||||
% Should result in a |test.tikz| file with contents that look somewhat
|
||||
% like this:
|
||||
%
|
||||
% \begin{tikzpicture}
|
||||
% %<commentsBefore>
|
||||
% <codeBefore>
|
||||
% \begin{axis}[..., <extraOptions>]
|
||||
% <codeInsideFirst>
|
||||
% \addplot{...};
|
||||
% <codeInsideLast>
|
||||
% \end{axis}
|
||||
% %<commentsAfter>
|
||||
% <codeAfter>
|
||||
% \end{tikzpicture}
|
||||
%
|
||||
% See also: matlab2tikz, setappdata, getappdata
|
||||
|
||||
%% arguments specific to this constructor function
|
||||
ipp = m2tInputParser();
|
||||
ipp = ipp.addRequired(ipp, 'handle', @isHgObject);
|
||||
|
||||
%% Declaration of the custom data structure
|
||||
ipp = ipp.addParamValue(ipp, 'codeBefore', '', @isCellstrOrChar);
|
||||
ipp = ipp.addParamValue(ipp, 'codeAfter', '', @isCellstrOrChar);
|
||||
|
||||
ipp = ipp.addParamValue(ipp, 'commentsBefore', '', @isCellstrOrChar);
|
||||
ipp = ipp.addParamValue(ipp, 'commentsAfter', '', @isCellstrOrChar);
|
||||
|
||||
ipp = ipp.addParamValue(ipp, 'codeInsideFirst', '', @isCellstrOrChar);
|
||||
ipp = ipp.addParamValue(ipp, 'codeInsideLast', '', @isCellstrOrChar);
|
||||
|
||||
ipp = ipp.addParamValue(ipp, 'extraOptions', '', @isCellstrOrChar);
|
||||
ipp = ipp.addParamValue(ipp, 'customHandler', '', @isHandler);
|
||||
|
||||
%% Parse the arguments
|
||||
ipp = ipp.parse(ipp, handle, varargin{:});
|
||||
|
||||
%% Construct custom data structure
|
||||
% We leverage the results from the input parser. It provides us
|
||||
% with validation already. We just need to remove bookkeeping fields
|
||||
value = ipp.Results;
|
||||
value = rmfield(value, {'handle'});
|
||||
|
||||
%% Normalize the actual values
|
||||
value.codeBefore = cellstr2char(value.codeBefore);
|
||||
value.codeAfter = cellstr2char(value.codeAfter);
|
||||
value.codeInsideFirst = cellstr2char(value.codeInsideFirst);
|
||||
value.codeInsideLast = cellstr2char(value.codeInsideLast);
|
||||
value.commentsBefore = cellstr2char(value.commentsBefore);
|
||||
value.commentsAfter = cellstr2char(value.commentsAfter);
|
||||
if isempty(value.customHandler)
|
||||
value = rmfield(value, 'customHandler');
|
||||
end
|
||||
% extraOptions gets normalized by |opts_append_userdefined|
|
||||
|
||||
%% Different Usage modes
|
||||
MATLAB2TIKZ = 'matlab2tikz'; % key used for application data storage
|
||||
if numel(varargin) == 0
|
||||
%% GETTER MODE
|
||||
% syntax: value = m2tcustom(h);
|
||||
if ~isempty(handle)
|
||||
object = getappdata(handle, MATLAB2TIKZ);
|
||||
else
|
||||
object = [];
|
||||
end
|
||||
if ~isempty(object)
|
||||
value = object;
|
||||
else
|
||||
% |value| contains all default (empty) values
|
||||
end
|
||||
else
|
||||
%% SETTER MODE
|
||||
% syntax: m2tcustom(h , key1, val1, ...)
|
||||
% syntax: value = m2tcustom([], key1, val1, ...)
|
||||
if ~isempty(handle)
|
||||
setappdata(handle, MATLAB2TIKZ, value);
|
||||
end
|
||||
end
|
||||
end
|
||||
% == INPUT VALIDATORS ==========================================================
|
||||
function bool = isHgObject(value)
|
||||
% true for HG object or empty (or numeric for backwards compatibility)
|
||||
bool = isempty(value) || ishghandle(value) || isnumeric(value);
|
||||
end
|
||||
function bool = isCellstrOrChar(value)
|
||||
% true for cellstr or char
|
||||
bool = ischar(value) || iscellstr(value);
|
||||
end
|
||||
function bool = isHandler(value)
|
||||
% true for char or function handle of the form [m2t, str] = f(m2t, h, opts)
|
||||
bool = isempty(value) || ischar(value) || ...
|
||||
(isa(value, 'function_handle') && ...
|
||||
atLeastOrUnknown(nargin(value), 3) && ...
|
||||
atLeastOrUnknown(nargout(value), 2));
|
||||
end
|
||||
function bool = atLeastOrUnknown(nargs, limit)
|
||||
% checks for |nargin| and |nargout| >= |limit| (or equal to -1)
|
||||
UNKNOWN = -1;
|
||||
bool = (nargs == UNKNOWN) || nargs >= limit;
|
||||
end
|
||||
% == FIELD NORMALIZATION =======================================================
|
||||
function value = cellstr2char(value)
|
||||
% convert cellstr to char (and keep char unaffected)
|
||||
if iscellstr(value)
|
||||
EOL = sprintf('\n');
|
||||
value = m2tstrjoin(value, EOL);
|
||||
end
|
||||
end
|
||||
% ==============================================================================
|
||||
7167
Functions/helper_functions_community/mat2tikz/src/matlab2tikz.m
Normal file
7167
Functions/helper_functions_community/mat2tikz/src/matlab2tikz.m
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,5 @@
|
||||
function errorUnknownEnvironment()
|
||||
% Throw an error to indicate an unknwon environment (i.e. not MATLAB/Octave).
|
||||
error('matlab2tikz:unknownEnvironment',...
|
||||
'Unknown environment "%s". Need MATLAB(R) or Octave.', getEnvironment);
|
||||
end
|
||||
@@ -0,0 +1,25 @@
|
||||
function [env, versionString] = getEnvironment()
|
||||
% Determine environment (Octave, MATLAB) and version string
|
||||
% TODO: Unify private `getEnvironment` functions
|
||||
persistent cache
|
||||
|
||||
if isempty(cache)
|
||||
isOctave = exist('OCTAVE_VERSION', 'builtin') ~= 0;
|
||||
if isOctave
|
||||
env = 'Octave';
|
||||
versionString = OCTAVE_VERSION;
|
||||
else
|
||||
env = 'MATLAB';
|
||||
vData = ver(env);
|
||||
versionString = vData.Version;
|
||||
end
|
||||
|
||||
% store in cache
|
||||
cache.env = env;
|
||||
cache.versionString = versionString;
|
||||
|
||||
else
|
||||
env = cache.env;
|
||||
versionString = cache.versionString;
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,19 @@
|
||||
function types = guitypes()
|
||||
% GUITYPES returns a cell array of MATLAB/Octave GUI object types
|
||||
%
|
||||
% Syntax
|
||||
% types = guitypes()
|
||||
%
|
||||
% These types are ignored by matlab2tikz and figure2dot.
|
||||
%
|
||||
% See also: matlab2tikz, figure2dot
|
||||
|
||||
types = {'uitoolbar', 'uimenu', 'uicontextmenu', 'uitoggletool',...
|
||||
'uitogglesplittool', 'uipushtool', 'hgjavacomponent',...
|
||||
'matlab.graphics.shape.internal.Button', ...
|
||||
'matlab.ui.controls.ToolbarPushButton', ...
|
||||
'matlab.ui.controls.ToolbarStateButton', ...
|
||||
'matlab.ui.controls.ToolbarDropdown', ...
|
||||
'matlab.ui.controls.AxesToolbar', ...
|
||||
};
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
function bool = isAxis3D(axisHandle)
|
||||
% Check if elevation is not orthogonal to xy plane
|
||||
axisView = get(axisHandle,'view');
|
||||
bool = ~ismember(axisView(2),[90,-90]);
|
||||
end
|
||||
@@ -0,0 +1,13 @@
|
||||
function isBelow = isVersionBelow(versionA, versionB)
|
||||
% Checks if versionA is smaller than versionB
|
||||
vA = versionArray(versionA);
|
||||
vB = versionArray(versionB);
|
||||
n = min(length(vA), length(vB));
|
||||
deltaAB = vA(1:n) - vB(1:n);
|
||||
difference = find(deltaAB, 1, 'first');
|
||||
if isempty(difference)
|
||||
isBelow = false; % equal versions
|
||||
else
|
||||
isBelow = (deltaAB(difference) < 0);
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,320 @@
|
||||
function m2tUpdater(about, verbose)
|
||||
%UPDATER Auto-update matlab2tikz.
|
||||
% Only for internal usage.
|
||||
|
||||
% Copyright (c) 2012--2014, Nico Schlömer <nico.schloemer@gmail.com>
|
||||
% All rights reserved.
|
||||
%
|
||||
% Redistribution and use in source and binary forms, with or without
|
||||
% modification, are permitted provided that the following conditions are
|
||||
% met:
|
||||
%
|
||||
% * Redistributions of source code must retain the above copyright
|
||||
% notice, this list of conditions and the following disclaimer.
|
||||
% * Redistributions in binary form must reproduce the above copyright
|
||||
% notice, this list of conditions and the following disclaimer in
|
||||
% the documentation and/or other materials provided with the distribution
|
||||
%
|
||||
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
% POSSIBILITY OF SUCH DAMAGE.
|
||||
% =========================================================================
|
||||
fileExchangeUrl = about.website;
|
||||
version = about.version;
|
||||
|
||||
mostRecentVersion = determineLatestRelease(version, fileExchangeUrl);
|
||||
if askToUpgrade(mostRecentVersion, version, verbose)
|
||||
tryToUpgrade(fileExchangeUrl, verbose);
|
||||
userInfo(verbose, '');
|
||||
end
|
||||
end
|
||||
% ==============================================================================
|
||||
function shouldUpgrade = askToUpgrade(mostRecentVersion, version, verbose)
|
||||
shouldUpgrade = false;
|
||||
if ~isempty(mostRecentVersion)
|
||||
userInfo(verbose, '**********************************************\n');
|
||||
userInfo(verbose, 'New version (%s) available!\n', mostRecentVersion);
|
||||
userInfo(verbose, '**********************************************\n');
|
||||
|
||||
warnAboutUpgradeImplications(version, mostRecentVersion, verbose);
|
||||
askToShowChangelog(version);
|
||||
reply = input(' *** Would you like to upgrade? y/n [n]:','s');
|
||||
shouldUpgrade = ~isempty(reply) && strcmpi(reply(1),'y');
|
||||
if ~shouldUpgrade
|
||||
userInfo(verbose, ['\nTo disable the self-updater in the future, add ' ...
|
||||
'"''checkForUpdates'',false" to the parameters.\n'] );
|
||||
end
|
||||
end
|
||||
end
|
||||
% ==============================================================================
|
||||
function tryToUpgrade(fileExchangeUrl, verbose)
|
||||
% Download the files and unzip its contents into two folders
|
||||
% above the folder that contains the current script.
|
||||
% This assumes that the file structure is something like
|
||||
%
|
||||
% src/matlab2tikz.m
|
||||
% src/[...]
|
||||
% src/private/m2tUpdater
|
||||
% src/private/[...]
|
||||
% AUTHORS
|
||||
% ChangeLog
|
||||
% [...]
|
||||
%
|
||||
% on the hard drive and the zip file. In particular, this assumes
|
||||
% that the folder on the hard drive is writable by the user
|
||||
% and that matlab2tikz.m is not symlinked from some other place.
|
||||
pathstr = fileparts(mfilename('fullpath'));
|
||||
targetPath = fullfile(pathstr, '..', '..');
|
||||
|
||||
% Let the user know where the .zip is downloaded to
|
||||
userInfo(verbose, 'Downloading and unzipping to ''%s'' ...', targetPath);
|
||||
|
||||
% Try upgrading
|
||||
try
|
||||
% List current folder structure. Will use last for cleanup
|
||||
currentFolderFiles = rdirfiles(targetPath);
|
||||
|
||||
% The FEX now forwards the download request to Github.
|
||||
% Go through the forwarding to update the download count and
|
||||
% unzip
|
||||
html = urlread([fileExchangeUrl, '?download=true']);
|
||||
expression = '(?<=\<a href=")[\w\-\/:\.]+(?=">redirected)';
|
||||
url = regexp(html, expression,'match','once');
|
||||
unzippedFiles = unzip(url, targetPath);
|
||||
|
||||
% The folder structure is additionally packed into the
|
||||
% 'MATLAB Search Path' folder defined in FEX. Retrieve the
|
||||
% top folder name
|
||||
tmp = strrep(unzippedFiles,[targetPath, filesep],'');
|
||||
tmp = regexp(tmp, filesep,'split','once');
|
||||
tmp = cat(1,tmp{:});
|
||||
topZipFolder = unique(tmp(:,1));
|
||||
|
||||
% If packed into the top folder, overwrite files into m2t
|
||||
% main directory
|
||||
if numel(topZipFolder) == 1
|
||||
unzippedFilesTarget = fullfile(targetPath, tmp(:,2));
|
||||
for ii = 1:numel(unzippedFiles)
|
||||
movefile(unzippedFiles{ii}, unzippedFilesTarget{ii})
|
||||
end
|
||||
% Add topZipFolder to current folder structure
|
||||
currentFolderFiles = [currentFolderFiles; fullfile(targetPath, topZipFolder{1})];
|
||||
end
|
||||
|
||||
cleanupOldFiles(currentFolderFiles, unzippedFilesTarget);
|
||||
|
||||
userInfo(verbose, 'Upgrade has completed successfully.');
|
||||
catch
|
||||
err = lasterror(); %#ok needed for Octave
|
||||
|
||||
userInfo(verbose, ...
|
||||
['Upgrade has failed with error message "%s".\n', ...
|
||||
'Please install the latest version manually from %s !'], ...
|
||||
err.message, fileExchangeUrl);
|
||||
end
|
||||
end
|
||||
% ==============================================================================
|
||||
function cleanupOldFiles(currentFolderFiles, unzippedFilesTarget)
|
||||
% Delete files that were there in the old folder, but that are no longer
|
||||
% present in the new release.
|
||||
newFolderStructure = [getFolders(unzippedFilesTarget); unzippedFilesTarget];
|
||||
deleteFolderFiles = setdiff(currentFolderFiles, newFolderStructure);
|
||||
for ii = 1:numel(deleteFolderFiles)
|
||||
x = deleteFolderFiles{ii};
|
||||
if exist(x, 'dir') == 7
|
||||
% First check for directories since
|
||||
% `exist(x, 'file')` also checks for directories!
|
||||
rmdir(x,'s');
|
||||
elseif exist(x, 'file') == 2
|
||||
delete(x);
|
||||
end
|
||||
end
|
||||
end
|
||||
% ==============================================================================
|
||||
function mostRecentVersion = determineLatestRelease(version, fileExchangeUrl)
|
||||
% Read in the Github releases page
|
||||
url = 'https://github.com/matlab2tikz/matlab2tikz/releases/';
|
||||
try
|
||||
html = urlread(url);
|
||||
catch %#ok
|
||||
% Couldn't load the URL -- never mind.
|
||||
html = '';
|
||||
warning('m2tUpdate:siteNotFound', ...
|
||||
['Cannot determine the latest version.\n', ...
|
||||
'Either your internet is down or something went wrong.\n', ...
|
||||
'You might want to check for updates by hand at %s.\n'], ...
|
||||
fileExchangeUrl);
|
||||
end
|
||||
|
||||
% Parse tag names which are the version number in the format ##.##.##
|
||||
% It assumes that releases will always be tagged with the version number
|
||||
expression = '(?<=matlab2tikz\/matlab2tikz\/releases\/tag\/)\d+\.\d+\.\d+';
|
||||
tags = regexp(html, expression, 'match');
|
||||
ntags = numel(tags);
|
||||
|
||||
% Keep only new releases
|
||||
inew = false(ntags,1);
|
||||
for ii = 1:ntags
|
||||
inew(ii) = isVersionBelow(version, tags{ii});
|
||||
end
|
||||
nnew = nnz(inew);
|
||||
|
||||
% One new release
|
||||
if nnew == 1
|
||||
mostRecentVersion = tags{inew};
|
||||
% Several new release, pick latest
|
||||
elseif nnew > 1
|
||||
tags = tags(inew);
|
||||
tagnum = zeros(nnew,1);
|
||||
for ii = 1:nnew
|
||||
tagnum(ii) = [10000,100,1] * versionArray(tags{ii});
|
||||
end
|
||||
[~, imax] = max(tagnum);
|
||||
mostRecentVersion = tags{imax};
|
||||
% No new
|
||||
else
|
||||
mostRecentVersion = '';
|
||||
end
|
||||
end
|
||||
% ==============================================================================
|
||||
function askToShowChangelog(currentVersion)
|
||||
% Asks whether the user wants to see the changelog and then shows it.
|
||||
reply = input(' *** Would you like to see the changelog? y/n [y]:' ,'s');
|
||||
shouldShow = isempty(reply) || ~strcmpi(reply(1),'n') ;
|
||||
if shouldShow
|
||||
fprintf(1, '\n%s\n', changelogUntilVersion(currentVersion));
|
||||
end
|
||||
end
|
||||
% ==============================================================================
|
||||
function changelog = changelogUntilVersion(currentVersion)
|
||||
% This function retrieves the chunk of the changelog until the current version.
|
||||
URL = 'https://github.com/matlab2tikz/matlab2tikz/raw/master/CHANGELOG.md';
|
||||
changelog = urlread(URL);
|
||||
currentVersion = versionString(currentVersion);
|
||||
|
||||
% Header is "# YYYY-MM-DD Version major.minor.patch [Manager](email)"
|
||||
% Just match for the part until the version number. Here, we're actually
|
||||
% matching a tiny bit too broad due to the periods in the version number
|
||||
% but the outcome should be the same if we keep the changelog format
|
||||
% identical.
|
||||
pattern = ['\#\s*[\d-]+\s*Version\s*' currentVersion];
|
||||
idxVersion = regexpi(changelog, pattern);
|
||||
if ~isempty(idxVersion)
|
||||
changelog = changelog(1:idxVersion-1);
|
||||
else
|
||||
% Just show the whole changelog if we don't find the old version.
|
||||
end
|
||||
changelog = replaceIssuesWithUrls(changelog);
|
||||
end
|
||||
% ==============================================================================
|
||||
function changelog = replaceIssuesWithUrls(changelog)
|
||||
% Replaces GitHub issues ("#...") with URLs
|
||||
baseurl = 'https://github.com/matlab2tikz/matlab2tikz/issues/';
|
||||
if strcmpi(getEnvironment(), 'MATLAB')
|
||||
replacement = sprintf('<a href="%s$1">#$1</a>', baseurl);
|
||||
changelog = regexprep(changelog, '\#(\d+)', replacement);
|
||||
end
|
||||
end
|
||||
% ==============================================================================
|
||||
function warnAboutUpgradeImplications(currentVersion, latestVersion, verbose)
|
||||
% This warns the user about the implications of upgrading as dictated by
|
||||
% Semantic Versioning.
|
||||
switch upgradeSize(currentVersion, latestVersion);
|
||||
case 'major'
|
||||
% The API might have changed in a backwards incompatible way.
|
||||
userInfo(verbose, 'This is a MAJOR upgrade!\n');
|
||||
userInfo(verbose, ' - New features may have been introduced.');
|
||||
userInfo(verbose, ' - Some old code/options may no longer work!\n');
|
||||
|
||||
case 'minor'
|
||||
% The API may NOT have changed in a backwards incompatible way.
|
||||
userInfo(verbose, 'This is a MINOR upgrade.\n');
|
||||
userInfo(verbose, ' - New features may have been introduced.');
|
||||
userInfo(verbose, ' - Some options may have been deprecated.');
|
||||
userInfo(verbose, ' - Old code should continue to work but might produce warnings.\n');
|
||||
|
||||
case 'patch'
|
||||
% No new functionality is introduced
|
||||
userInfo(verbose, 'This is a PATCH.\n');
|
||||
userInfo(verbose, ' - Only bug fixes are included in this upgrade.');
|
||||
userInfo(verbose, ' - Old code should continue to work as before.')
|
||||
end
|
||||
userInfo(verbose, 'Please check the changelog for detailed information.\n');
|
||||
userWarn(verbose, '\n!! By upgrading you will lose any custom changes !!\n');
|
||||
end
|
||||
% ==============================================================================
|
||||
function cls = upgradeSize(currentVersion, latestVersion)
|
||||
% Determines whether the upgrade is major, minor or a patch.
|
||||
currentVersion = versionArray(currentVersion);
|
||||
latestVersion = versionArray(latestVersion);
|
||||
description = {'major', 'minor', 'patch'};
|
||||
for ii = 1:numel(description)
|
||||
if latestVersion(ii) > currentVersion(ii)
|
||||
cls = description{ii};
|
||||
return
|
||||
end
|
||||
end
|
||||
cls = 'unknown';
|
||||
end
|
||||
% ==============================================================================
|
||||
function userInfo(verbose, message, varargin)
|
||||
% Display information (i.e. to stdout)
|
||||
if verbose
|
||||
userPrint(1, message, varargin{:});
|
||||
end
|
||||
end
|
||||
function userWarn(verbose, message, varargin)
|
||||
% Display warnings (i.e. to stderr)
|
||||
if verbose
|
||||
userPrint(2, message, varargin{:});
|
||||
end
|
||||
end
|
||||
function userPrint(fid, message, varargin)
|
||||
% Print messages (info/warnings) to a stream/file.
|
||||
mess = sprintf(message, varargin{:});
|
||||
|
||||
% Replace '\n' by '\n *** ' and print.
|
||||
mess = strrep( mess, sprintf('\n'), sprintf('\n *** ') );
|
||||
fprintf(fid, ' *** %s\n', mess );
|
||||
end
|
||||
% =========================================================================
|
||||
function list = rdirfiles(rootdir)
|
||||
% Recursive files listing
|
||||
s = dir(rootdir);
|
||||
list = {s.name}';
|
||||
|
||||
% Exclude .git, .svn, . and ..
|
||||
[list, idx] = setdiff(list, {'.git','.svn','.','..'});
|
||||
|
||||
% Add root
|
||||
list = fullfile(rootdir, list);
|
||||
|
||||
% Loop for sub-directories
|
||||
pdir = find([s(idx).isdir]);
|
||||
for ii = pdir
|
||||
list = [list; rdirfiles(list{ii})]; %#ok<AGROW>
|
||||
end
|
||||
|
||||
% Drop directories
|
||||
list(pdir) = [];
|
||||
end
|
||||
% =========================================================================
|
||||
function list = getFolders(list)
|
||||
% Extract the folder structure from a list of files and folders
|
||||
|
||||
for ii = 1:numel(list)
|
||||
if exist(list{ii},'file') == 2
|
||||
list{ii} = fileparts(list{ii});
|
||||
end
|
||||
end
|
||||
list = unique(list);
|
||||
end
|
||||
% =========================================================================
|
||||
@@ -0,0 +1,35 @@
|
||||
function newstr = m2tstrjoin(cellstr, delimiter, floatFormat)
|
||||
% This function joins a cell of strings to a single string (with a
|
||||
% given delimiter in between two strings, if desired).
|
||||
if ~exist('delimiter','var') || isempty(delimiter)
|
||||
delimiter = '';
|
||||
end
|
||||
if ~exist('floatFormat','var') || isempty(floatFormat)
|
||||
floatFormat = '%g';
|
||||
end
|
||||
if isempty(cellstr)
|
||||
newstr = '';
|
||||
return
|
||||
end
|
||||
|
||||
% convert all values to strings first
|
||||
nElem = numel(cellstr);
|
||||
for k = 1:nElem
|
||||
if isnumeric(cellstr{k})
|
||||
cellstr{k} = sprintf(floatFormat, cellstr{k});
|
||||
elseif iscell(cellstr{k})
|
||||
cellstr{k} = m2tstrjoin(cellstr{k}, delimiter, floatFormat);
|
||||
% this will fail for heavily nested cells
|
||||
elseif ~ischar(cellstr{k})
|
||||
error('matlab2tikz:join:NotCellstrOrNumeric',...
|
||||
'Expected cellstr or numeric.');
|
||||
end
|
||||
end
|
||||
|
||||
% inspired by strjoin of recent versions of MATLAB
|
||||
newstr = cell(2,nElem);
|
||||
newstr(1,:) = reshape(cellstr, 1, nElem);
|
||||
newstr(2,1:nElem-1) = {delimiter}; % put delimiters in-between the elements
|
||||
newstr(2,end) = {''}; % for Octave 4 compatibility
|
||||
newstr = [newstr{:}];
|
||||
end
|
||||
@@ -0,0 +1,18 @@
|
||||
function arr = versionArray(str)
|
||||
% Converts a version string to an array.
|
||||
if ischar(str)
|
||||
% Translate version string from '2.62.8.1' to [2; 62; 8; 1].
|
||||
switch getEnvironment
|
||||
case 'MATLAB'
|
||||
split = regexp(str, '\.', 'split'); % compatibility MATLAB < R2013a
|
||||
case 'Octave'
|
||||
split = strsplit(str, '.');
|
||||
otherwise
|
||||
errorUnknownEnvironment();
|
||||
end
|
||||
arr = str2num(char(split)); %#ok
|
||||
else
|
||||
arr = str;
|
||||
end
|
||||
arr = arr(:)';
|
||||
end
|
||||
@@ -0,0 +1,9 @@
|
||||
function str = versionString(arr)
|
||||
% Converts a version array to string
|
||||
if ischar(arr)
|
||||
str = arr;
|
||||
elseif isnumeric(arr)
|
||||
str = sprintf('%d.', arr);
|
||||
str = str(1:end-1); % remove final period
|
||||
end
|
||||
end
|
||||
101
Functions/helper_functions_community/mat2tikz/test/README.md
Normal file
101
Functions/helper_functions_community/mat2tikz/test/README.md
Normal file
@@ -0,0 +1,101 @@
|
||||
This test module is part of matlab2tikz.
|
||||
|
||||
Its use is mainly of interest to the matlab2tikz developers to assert that the produced output is good.
|
||||
Ideally, the tests should be run on every supported environment, i.e.:
|
||||
|
||||
* MATLAB R2014a/8.3 (or an older version)
|
||||
* MATLAB R2014b/8.4 (or a newer version)
|
||||
* Octave 3.8
|
||||
|
||||
Preparing your environment
|
||||
==========================
|
||||
|
||||
Before you can run the tests, you need to make sure that you have all relevant
|
||||
functions available on your path. From within the `/test` directory run the
|
||||
following code in your MATLAB/Octave console:
|
||||
|
||||
```matlab
|
||||
addpath(pwd); % for the test harness
|
||||
addpath(fullfile(pwd,'..','src')); % for matlab2tikz
|
||||
addpath(fullfile(pwd,'suites')); % for the test suites
|
||||
```
|
||||
|
||||
Running the tests
|
||||
=================
|
||||
|
||||
We have two kinds of tests runners available that each serve a slightly different
|
||||
purpose.
|
||||
|
||||
* "Graphical" tests produce an output report that graphically shows test
|
||||
figures as generated by MATLAB/Octave and our TikZ output.
|
||||
* "Headless" tests do not produce graphical output, but instead check the MD5
|
||||
hash of the generated TikZ files to make sure that the same output
|
||||
as before is generated.
|
||||
|
||||
It is recommended to run the headless tests first and check the problems in
|
||||
the graphical tests afterwards.
|
||||
|
||||
Headless tests
|
||||
--------------
|
||||
These tests check that the TikZ output file produced by `matlab2tikz` matches
|
||||
a reference output. The actual checking is done by hashing the file and the
|
||||
corresponding hashes are stored in `.md5` files next to the test suites.
|
||||
For each environment, different reference hashes can be stored.
|
||||
|
||||
The headless tests can be invoked using
|
||||
```matlab
|
||||
testHeadless;
|
||||
```
|
||||
, or, equivalently,
|
||||
```matlab
|
||||
makeTravisReport(testHeadless)
|
||||
```
|
||||
|
||||
There are some caveats for this method of testing:
|
||||
|
||||
* The MD5 hash is extremely brittle to small details in the output: e.g.
|
||||
extra whitespace or some other characters will change the hash.
|
||||
* This automated test does NOT test whether the output is desirable or not.
|
||||
It only checks whether the previous output is not altered!
|
||||
* Hence, when structural changes are made, the reference hash should be changed.
|
||||
This SHOULD be motivated in the pull request (e.g. with a picture)!
|
||||
|
||||
Graphical tests
|
||||
---------------
|
||||
These tests allow easy comparison of a native PDF `print` output and the
|
||||
output produced by `matlab2tikz`. For the large amount of cases, however,
|
||||
this comparison has become somewhat unwieldy.
|
||||
|
||||
You can execute the tests using
|
||||
```matlab
|
||||
testGraphical;
|
||||
```
|
||||
or, equivalently,
|
||||
```matlab
|
||||
makeLatexReport(testGraphical)
|
||||
```
|
||||
This generates a LaTeX report in `test/output/current/acid.tex` which can then be compiled.
|
||||
Compilation of this file can be done using the Makefile `test/output/current/Makefile` if you are on a Unix-like system (OS X, Linux) or have [Cygwin](https://www.cygwin.com) installed on Windows.
|
||||
|
||||
If all goes well, the result will be the file `test/output/current/acid.pdf` that contains
|
||||
a list of the test figures, exported as PDF and right next to it the matlab2tikz generated plot.
|
||||
|
||||
Advanced Use
|
||||
------------
|
||||
|
||||
Both `testHeadless` and `testGraphical` can take multiple arguments, those are documented in the raw test runner `testMatlab2tikz` that is used behind the scenes. Note that this file sits in a private directory, so `help testMatlab2tikz` will not work!
|
||||
|
||||
Also, both can be called with a single output argument, for programmatical
|
||||
access to the test results as
|
||||
```matlab
|
||||
status = testHeadless()
|
||||
```
|
||||
These test results in `status` can be passed to `saveHashTable` for updating the hash tables.
|
||||
Obviously, this should be done with the due diligence!
|
||||
|
||||
Automated Tests
|
||||
===============
|
||||
|
||||
The automated tests run on [Travis-CI](https://travis-ci.org) for Octave and on a [personal Jenkins server](https://github.com/matlab2tikz/matlab2tikz/wiki/Jenkins) for MATLAB.
|
||||
These are effectively the "headless" tests that get called by the `runMatlab2TikzTests` function.
|
||||
Without verification of those automated tests, a pull request is unlikely to get merged.
|
||||
280
Functions/helper_functions_community/mat2tikz/test/codeReport.m
Normal file
280
Functions/helper_functions_community/mat2tikz/test/codeReport.m
Normal file
@@ -0,0 +1,280 @@
|
||||
function [ report ] = codeReport( varargin )
|
||||
%CODEREPORT Builds a report of the code health
|
||||
%
|
||||
% This function generates a Markdown report on the code health. At the moment
|
||||
% this is limited to the McCabe (cyclomatic) complexity of a function and its
|
||||
% subfunctions.
|
||||
%
|
||||
% This makes use of |checkcode| in MATLAB.
|
||||
%
|
||||
% Usage:
|
||||
%
|
||||
% CODEREPORT('function', functionName) to determine which function is
|
||||
% analyzed. (default: matlab2tikz)
|
||||
%
|
||||
% CODEREPORT('complexityThreshold', integer ) to set above which complexity, a
|
||||
% function is added to the report (default: 10)
|
||||
%
|
||||
% CODEREPORT('stream', stream) to set to which stream/file to output the report
|
||||
% (default: 1, i.e. stdout). The stream is used only when no output argument
|
||||
% for `codeReport` is specified!.
|
||||
%
|
||||
% See also: checkcode, mlint
|
||||
|
||||
SM = StreamMaker();
|
||||
%% input options
|
||||
ipp = m2tInputParser();
|
||||
ipp = ipp.addParamValue(ipp, 'function', 'matlab2tikz', @ischar);
|
||||
ipp = ipp.addParamValue(ipp, 'complexityThreshold', 10, @isnumeric);
|
||||
ipp = ipp.addParamValue(ipp, 'stream', 1, SM.isStream);
|
||||
ipp = ipp.parse(ipp, varargin{:});
|
||||
|
||||
stream = SM.make(ipp.Results.stream, 'w');
|
||||
|
||||
%% generate report data
|
||||
data = checkcode(ipp.Results.function,'-cyc','-struct');
|
||||
[complexityAll, mlintMessages] = splitCycloComplexity(data);
|
||||
|
||||
%% analyze cyclomatic complexity
|
||||
categorizeComplexity = @(x) categoryOfComplexity(x, ...
|
||||
ipp.Results.complexityThreshold, ...
|
||||
ipp.Results.function);
|
||||
|
||||
complexityAll = arrayfun(@parseCycloComplexity, complexityAll);
|
||||
complexityAll = arrayfun(categorizeComplexity, complexityAll);
|
||||
|
||||
complexity = filter(complexityAll, @(x) strcmpi(x.category, 'Bad'));
|
||||
complexity = sortBy(complexity, 'line', 'ascend');
|
||||
complexity = sortBy(complexity, 'complexity', 'descend');
|
||||
|
||||
[complexityStats] = complexityStatistics(complexityAll);
|
||||
|
||||
%% analyze other messages
|
||||
%TODO: handle all mlint messages and/or other metrics of the code
|
||||
|
||||
%% format report
|
||||
dataStr = complexity;
|
||||
dataStr = arrayfun(@(d) mapField(d, 'function', @markdownInlineCode), dataStr);
|
||||
if ~isempty(dataStr)
|
||||
dataStr = addFooterRow(dataStr, 'complexity', @sum, {'line',0, 'function',bold('Total')});
|
||||
end
|
||||
dataStr = arrayfun(@(d) mapField(d, 'line', @integerToString), dataStr);
|
||||
dataStr = arrayfun(@(d) mapField(d, 'complexity', @integerToString), dataStr);
|
||||
|
||||
report = makeTable(dataStr, {'function', 'complexity'}, ...
|
||||
{'Function', 'Complexity'});
|
||||
|
||||
%% command line usage
|
||||
if nargout == 0
|
||||
if ismember(stream.name, {'stdout','stderr'})
|
||||
stream.print('%s\n', codelinks(report, ipp.Results.function));
|
||||
else
|
||||
stream.print('%s\n', report);
|
||||
end
|
||||
|
||||
figure('name',sprintf('Complexity statistics of %s', ipp.Results.function));
|
||||
h = statisticsPlot(complexityStats, 'Complexity', 'Number of functions');
|
||||
for hh = h
|
||||
plot(hh, [1 1]*ipp.Results.complexityThreshold, ylim(hh), ...
|
||||
'k--','DisplayName','Threshold');
|
||||
end
|
||||
legend(h(1),'show','Location','NorthEast');
|
||||
|
||||
clear report
|
||||
end
|
||||
|
||||
end
|
||||
%% CATEGORIZATION ==============================================================
|
||||
function [complexity, others] = splitCycloComplexity(list)
|
||||
% splits codereport into McCabe complexity and others
|
||||
filter = @(l) ~isempty(strfind(l.message, 'McCabe complexity'));
|
||||
idxComplexity = arrayfun(filter, list);
|
||||
complexity = list( idxComplexity);
|
||||
others = list(~idxComplexity);
|
||||
end
|
||||
function [data] = categoryOfComplexity(data, threshold, mainFunc)
|
||||
% categorizes the complexity as "Good", "Bad" or "Accepted"
|
||||
TOKEN = '#COMPLEX'; % token to signal allowed complexity
|
||||
|
||||
try %#ok
|
||||
helpStr = help(sprintf('%s>%s', mainFunc, data.function));
|
||||
if ~isempty(strfind(helpStr, TOKEN))
|
||||
data.category = 'Accepted';
|
||||
return;
|
||||
end
|
||||
end
|
||||
if data.complexity > threshold
|
||||
data.category = 'Bad';
|
||||
else
|
||||
data.category = 'Good';
|
||||
end
|
||||
end
|
||||
|
||||
%% PARSING =====================================================================
|
||||
function [out] = parseCycloComplexity(in)
|
||||
% converts McCabe complexity report strings into a better format
|
||||
out = regexp(in.message, ...
|
||||
'The McCabe complexity of ''(?<function>[A-Za-z0-9_]+)'' is (?<complexity>[0-9]+).', ...
|
||||
'names');
|
||||
out.complexity = str2double(out.complexity);
|
||||
out.line = in.line;
|
||||
end
|
||||
|
||||
%% DATA PROCESSING =============================================================
|
||||
function selected = filter(list, filterFunc)
|
||||
% filters an array according to a binary function
|
||||
idx = logical(arrayfun(filterFunc, list));
|
||||
selected = list(idx);
|
||||
end
|
||||
function [data] = mapField(data, field, mapping)
|
||||
data.(field) = mapping(data.(field));
|
||||
end
|
||||
function sorted = sortBy(list, fieldName, mode)
|
||||
% sorts a struct array by a single field
|
||||
% extra arguments are as for |sort|
|
||||
values = arrayfun(@(m)m.(fieldName), list);
|
||||
[dummy, idxSorted] = sort(values(:), 1, mode); %#ok
|
||||
sorted = list(idxSorted);
|
||||
end
|
||||
|
||||
function [stat] = complexityStatistics(list)
|
||||
% calculate some basic statistics of the complexities
|
||||
|
||||
stat.values = arrayfun(@(c)(c.complexity), list);
|
||||
stat.binCenter = sort(unique(stat.values));
|
||||
|
||||
categoryPerElem = {list.category};
|
||||
stat.categories = unique(categoryPerElem);
|
||||
nCategories = numel(stat.categories);
|
||||
|
||||
groupedHist = zeros(numel(stat.binCenter), nCategories);
|
||||
for iCat = 1:nCategories
|
||||
category = stat.categories{iCat};
|
||||
idxCat = ismember(categoryPerElem, category);
|
||||
groupedHist(:,iCat) = hist(stat.values(idxCat), stat.binCenter);
|
||||
end
|
||||
|
||||
stat.histogram = groupedHist;
|
||||
stat.median = median(stat.values);
|
||||
end
|
||||
function [data] = addFooterRow(data, column, func, otherFields)
|
||||
% adds a footer row to data table based on calculations of a single column
|
||||
footer = data(end);
|
||||
for iField = 1:2:numel(otherFields)
|
||||
field = otherFields{iField};
|
||||
value = otherFields{iField+1};
|
||||
footer.(field) = value;
|
||||
end
|
||||
footer.(column) = func([data(:).(column)]);
|
||||
data(end+1) = footer;
|
||||
end
|
||||
|
||||
%% FORMATTING ==================================================================
|
||||
function str = integerToString(value)
|
||||
% convert integer to string
|
||||
str = sprintf('%d',value);
|
||||
end
|
||||
function str = markdownInlineCode(str)
|
||||
% format as inline code for markdown
|
||||
str = sprintf('`%s`', str);
|
||||
end
|
||||
function str = makeTable(data, fields, header)
|
||||
% make a markdown table from struct array
|
||||
nData = numel(data);
|
||||
str = '';
|
||||
if nData == 0
|
||||
return; % empty input
|
||||
end
|
||||
%TODO: use gfmTable from makeTravisReport instead to do the formatting
|
||||
|
||||
% determine column sizes
|
||||
nFields = numel(fields);
|
||||
table = cell(nFields, nData);
|
||||
columnWidth = zeros(1,nFields);
|
||||
for iField = 1:nFields
|
||||
field = fields{iField};
|
||||
table(iField, :) = {data(:).(field)};
|
||||
columnWidth(iField) = max(cellfun(@numel, table(iField, :)));
|
||||
end
|
||||
columnWidth = max(columnWidth, cellfun(@numel, header));
|
||||
columnWidth = columnWidth + 2; % empty space left and right
|
||||
columnWidth([1,end]) = columnWidth([1,end]) - 1; % except at the edges
|
||||
|
||||
% format table inside cell array
|
||||
table = [header; table'];
|
||||
for iField = 1:nFields
|
||||
FORMAT = ['%' int2str(columnWidth(iField)) 's'];
|
||||
|
||||
for jData = 1:size(table, 1)
|
||||
table{jData, iField} = strjust(sprintf(FORMAT, ...
|
||||
table{jData, iField}), 'center');
|
||||
end
|
||||
end
|
||||
|
||||
% insert separator
|
||||
table = [table(1,:)
|
||||
arrayfun(@(n) repmat('-',1,n), columnWidth, 'UniformOutput',false)
|
||||
table(2:end,:)]';
|
||||
|
||||
% convert cell array to string
|
||||
FORMAT = ['%s' repmat('|%s', 1,nFields-1) '\n'];
|
||||
str = sprintf(FORMAT, table{:});
|
||||
|
||||
end
|
||||
|
||||
function str = codelinks(str, functionName)
|
||||
% replaces inline functions with clickable links in MATLAB
|
||||
str = regexprep(str, '`([A-Za-z0-9_]+)`', ...
|
||||
['`<a href="matlab:edit ' functionName '>$1">$1</a>`']);
|
||||
%NOTE: editing function>subfunction will focus on that particular subfunction
|
||||
% in the editor (this also works for the main function)
|
||||
end
|
||||
function str = bold(str)
|
||||
str = ['**' str '**'];
|
||||
end
|
||||
|
||||
%% PLOTTING ====================================================================
|
||||
function h = statisticsPlot(stat, xLabel, yLabel)
|
||||
% plot a histogram and box plot
|
||||
nCategories = numel(stat.categories);
|
||||
colors = colorscheme;
|
||||
|
||||
h(1) = subplot(5,1,1:4);
|
||||
hold all;
|
||||
hb = bar(stat.binCenter, stat.histogram, 'stacked');
|
||||
|
||||
for iCat = 1:nCategories
|
||||
category = stat.categories{iCat};
|
||||
|
||||
set(hb(iCat), 'DisplayName', category, 'FaceColor', colors.(category), ...
|
||||
'LineStyle','none');
|
||||
end
|
||||
|
||||
%xlabel(xLabel);
|
||||
ylabel(yLabel);
|
||||
|
||||
h(2) = subplot(5,1,5);
|
||||
hold all;
|
||||
|
||||
boxplot(stat.values,'orientation','horizontal',...
|
||||
'boxstyle', 'outline', ...
|
||||
'symbol', 'o', ...
|
||||
'colors', colors.All);
|
||||
xlabel(xLabel);
|
||||
|
||||
xlims = [min(stat.binCenter)-1 max(stat.binCenter)+1];
|
||||
c = 1;
|
||||
ylims = (ylim(h(2)) - c)/3 + c;
|
||||
|
||||
set(h,'XTickMode','manual','XTick',stat.binCenter,'XLim',xlims);
|
||||
set(h(1),'XTickLabel','');
|
||||
set(h(2),'YTickLabel','','YLim',ylims);
|
||||
linkaxes(h, 'x');
|
||||
end
|
||||
function colors = colorscheme()
|
||||
% recognizable color scheme for the categories
|
||||
colors.All = [ 0 113 188]/255;
|
||||
colors.Good = [118 171 47]/255;
|
||||
colors.Bad = [161 19 46]/255;
|
||||
colors.Accepted = [236 176 31]/255;
|
||||
end
|
||||
@@ -0,0 +1,256 @@
|
||||
function compareTimings(statusBefore, statusAfter)
|
||||
% COMPARETIMINGS compare timing of matlab2tikz test suite runs
|
||||
%
|
||||
% This function plots some analysis plots of the timings of different test
|
||||
% cases. When the test suite is run repeatedly, the median statistics are
|
||||
% reported as well as the individual runs.
|
||||
%
|
||||
% Usage:
|
||||
% COMPARETIMINGS(statusBefore, statusAfter)
|
||||
%
|
||||
% Parameters:
|
||||
% - statusBefore and statusAfter are expected to be
|
||||
% N x R cell arrays, each cell contains a status of a test case
|
||||
% where there are N test cases, repeated R times each.
|
||||
%
|
||||
% You can build such cells, e.g. with the following snippet.
|
||||
%
|
||||
% suite = @ACID
|
||||
% N = numel(suite(0)); % number of test cases
|
||||
% R = 10; % number of repetitions of each test case
|
||||
%
|
||||
% statusBefore = cell(N, R);
|
||||
% for r = 1:R
|
||||
% statusBefore(:, r) = testHeadless;
|
||||
% end
|
||||
%
|
||||
% % now check out the after commit
|
||||
%
|
||||
% statusAfter = cell(N, R);
|
||||
% for r = 1:R
|
||||
% statusAfter(:, r) = testHeadless;
|
||||
% end
|
||||
%
|
||||
% compareTimings(statusBefore, statusAfter)
|
||||
%
|
||||
% See also: testHeadless
|
||||
|
||||
%% Extract timing information
|
||||
time_cf = extract(statusBefore, statusAfter, @(s) s.tikzStage.cleanfigure_time);
|
||||
time_m2t = extract(statusBefore, statusAfter, @(s) s.tikzStage.m2t_time);
|
||||
%% Construct plots
|
||||
hax(1) = subplot(3,2,1);
|
||||
histograms(time_cf, 'cleanfigure');
|
||||
legend('show')
|
||||
|
||||
hax(2) = subplot(3,2,3);
|
||||
histograms(time_m2t, 'matlab2tikz');
|
||||
legend('show')
|
||||
linkaxes(hax([1 2]),'x');
|
||||
|
||||
hax(3) = subplot(3,2,5);
|
||||
histogramSpeedup('cleanfigure', time_cf, 'matlab2tikz', time_m2t);
|
||||
legend('show');
|
||||
|
||||
hax(4) = subplot(3,2,2);
|
||||
plotByTestCase(time_cf, 'cleanfigure');
|
||||
legend('show')
|
||||
|
||||
hax(5) = subplot(3,2,4);
|
||||
plotByTestCase(time_m2t, 'matlab2tikz');
|
||||
legend('show')
|
||||
|
||||
hax(6) = subplot(3,2,6);
|
||||
plotSpeedup('cleanfigure', time_cf, 'matlab2tikz', time_m2t);
|
||||
legend('show');
|
||||
|
||||
linkaxes(hax([4 5 6]), 'x');
|
||||
|
||||
% ------------------------------------------------------------------------------
|
||||
end
|
||||
%% Data processing
|
||||
function timing = extract(statusBefore, statusAfter, func)
|
||||
otherwiseNaN = {'ErrorHandler', @(varargin) NaN};
|
||||
|
||||
timing.before = cellfun(func, statusBefore, otherwiseNaN{:});
|
||||
timing.after = cellfun(func, statusAfter, otherwiseNaN{:});
|
||||
end
|
||||
function [names,timings] = splitNameTiming(vararginAsCell)
|
||||
names = vararginAsCell(1:2:end-1);
|
||||
timings = vararginAsCell(2:2:end);
|
||||
end
|
||||
|
||||
%% Plot subfunctions
|
||||
function [h] = histograms(timing, name)
|
||||
% plot histogram of time measurements
|
||||
colors = colorscheme;
|
||||
histostyle = {'DisplayStyle', 'bar',...
|
||||
'Normalization','pdf',...
|
||||
'EdgeColor','none',...
|
||||
'BinWidth',0.025};
|
||||
|
||||
hold on;
|
||||
h{1} = myHistogram(timing.before, histostyle{:}, ...
|
||||
'FaceColor', colors.before, ...
|
||||
'DisplayName', 'Before');
|
||||
h{2} = myHistogram(timing.after , histostyle{:}, ...
|
||||
'FaceColor', colors.after,...
|
||||
'DisplayName', 'After');
|
||||
|
||||
xlabel(sprintf('%s runtime [s]',name))
|
||||
ylabel('Empirical PDF');
|
||||
end
|
||||
function [h] = histogramSpeedup(varargin)
|
||||
% plot histogram of observed speedup
|
||||
histostyle = {'DisplayStyle', 'bar',...
|
||||
'Normalization','pdf',...
|
||||
'EdgeColor','none'};
|
||||
|
||||
[names,timings] = splitNameTiming(varargin);
|
||||
nData = numel(timings);
|
||||
h = cell(nData, 1);
|
||||
minTime = NaN; maxTime = NaN;
|
||||
for iData = 1:nData
|
||||
name = names{iData};
|
||||
timing = timings{iData};
|
||||
|
||||
hold on;
|
||||
speedup = computeSpeedup(timing);
|
||||
color = colorOptionsOfName(name, 'FaceColor');
|
||||
|
||||
h{iData} = myHistogram(speedup, histostyle{:}, color{:},...
|
||||
'DisplayName', name);
|
||||
|
||||
[minTime, maxTime] = minAndMax(speedup, minTime, maxTime);
|
||||
end
|
||||
xlabel('Speedup')
|
||||
ylabel('Empirical PDF');
|
||||
set(gca,'XScale','log', 'XLim', [minTime, maxTime].*[0.9 1.1]);
|
||||
end
|
||||
function [h] = plotByTestCase(timing, name)
|
||||
% plot all time measurements per test case
|
||||
colors = colorscheme;
|
||||
hold on;
|
||||
if size(timing.before, 2) > 1
|
||||
h{3} = plot(timing.before, '.',...
|
||||
'Color', colors.before, 'HandleVisibility', 'off');
|
||||
h{4} = plot(timing.after, '.',...
|
||||
'Color', colors.after, 'HandleVisibility', 'off');
|
||||
end
|
||||
h{1} = plot(median(timing.before, 2), '-',...
|
||||
'LineWidth', 2, ...
|
||||
'Color', colors.before, ...
|
||||
'DisplayName', 'Before');
|
||||
h{2} = plot(median(timing.after, 2), '-',...
|
||||
'LineWidth', 2, ...
|
||||
'Color', colors.after,...
|
||||
'DisplayName', 'After');
|
||||
|
||||
ylabel(sprintf('%s runtime [s]', name));
|
||||
set(gca,'YScale','log')
|
||||
end
|
||||
function [h] = plotSpeedup(varargin)
|
||||
% plot speed up per test case
|
||||
[names, timings] = splitNameTiming(varargin);
|
||||
|
||||
nDatasets = numel(names);
|
||||
minTime = NaN;
|
||||
maxTime = NaN;
|
||||
h = cell(nDatasets, 1);
|
||||
for iData = 1:nDatasets
|
||||
name = names{iData};
|
||||
timing = timings{iData};
|
||||
color = colorOptionsOfName(name);
|
||||
|
||||
hold on
|
||||
[speedup, medSpeedup] = computeSpeedup(timing);
|
||||
if size(speedup, 2) > 1
|
||||
plot(speedup, '.', color{:}, 'HandleVisibility','off');
|
||||
end
|
||||
h{iData} = plot(medSpeedup, color{:}, 'DisplayName', name, ...
|
||||
'LineWidth', 2);
|
||||
|
||||
[minTime, maxTime] = minAndMax(speedup, minTime, maxTime);
|
||||
end
|
||||
|
||||
nTests = size(speedup, 1);
|
||||
plot([-nTests nTests*2], ones(2,1), 'k','HandleVisibility','off');
|
||||
|
||||
legend('show', 'Location','NorthWest')
|
||||
set(gca,'YScale','log','YLim', [minTime, maxTime].*[0.9 1.1], ...
|
||||
'XLim', [0 nTests+1])
|
||||
xlabel('Test case');
|
||||
ylabel('Speed-up (t_{before}/t_{after})');
|
||||
end
|
||||
|
||||
%% Histogram wrapper
|
||||
function [h] = myHistogram(data, varargin)
|
||||
% this is a very crude wrapper that mimics Histogram in R2014a and older
|
||||
if ~isempty(which('histogram'))
|
||||
h = histogram(data, varargin{:});
|
||||
else % no "histogram" available
|
||||
options = struct(varargin{:});
|
||||
|
||||
minData = min(data(:));
|
||||
maxData = max(data(:));
|
||||
if isfield(options, 'BinWidth')
|
||||
numBins = ceil((maxData-minData)/options.BinWidth);
|
||||
elseif isfield(options, 'NumBins')
|
||||
numBins = options.NumBins;
|
||||
else
|
||||
numBins = 10;
|
||||
end
|
||||
[counts, bins] = hist(data(:), numBins);
|
||||
if isfield(options,'Normalization') && strcmp(options.Normalization,'pdf')
|
||||
binWidth = mean(diff(bins));
|
||||
counts = counts./sum(counts)/binWidth;
|
||||
end
|
||||
h = bar(bins, counts, 1);
|
||||
|
||||
% transfer properties as well
|
||||
names = fieldnames(options);
|
||||
for iName = 1:numel(names)
|
||||
option = names{iName};
|
||||
if isprop(h, option)
|
||||
set(h, option, options.(option));
|
||||
end
|
||||
end
|
||||
set(allchild(h),'FaceAlpha', 0.75); % only supported with OpenGL renderer
|
||||
% but this should look a bit similar with matlab2tikz then...
|
||||
end
|
||||
end
|
||||
|
||||
%% Calculations
|
||||
function [speedup, medSpeedup] = computeSpeedup(timing)
|
||||
% computes the timing speedup (and median speedup)
|
||||
dRep = 2; % dimension containing the repeated tests
|
||||
speedup = timing.before ./ timing.after;
|
||||
medSpeedup = median(timing.before, dRep) ./ median(timing.after, dRep);
|
||||
end
|
||||
function [minTime, maxTime] = minAndMax(speedup, minTime, maxTime)
|
||||
% calculates the minimum/maximum time in an array and peviously
|
||||
% computed min/max times
|
||||
minTime = min([minTime; speedup(:)]);
|
||||
maxTime = min([maxTime; speedup(:)]);
|
||||
end
|
||||
%% Color scheme
|
||||
function colors = colorscheme()
|
||||
% defines the color scheme
|
||||
colors.matlab2tikz = [161 19 46]/255;
|
||||
colors.cleanfigure = [ 0 113 188]/255;
|
||||
colors.before = [236 176 31]/255;
|
||||
colors.after = [118 171 47]/255;
|
||||
end
|
||||
function color = colorOptionsOfName(name, keyword)
|
||||
% returns a cell array with a keyword (default: 'Color') and a named color
|
||||
% if it exists in the colorscheme
|
||||
if ~exist('keyword','var') || isempty(keyword)
|
||||
keyword = 'Color';
|
||||
end
|
||||
colors = colorscheme;
|
||||
if isfield(colors,name)
|
||||
color = {keyword, colors.(name)};
|
||||
else
|
||||
color = {};
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,53 @@
|
||||
function example_bar_plot()
|
||||
test_data =[18 0; 20 0; 21 2; 30 14; 35 34; 40 57; 45 65; 50 46; 55 9; 60 2; 65 1; 70 0];
|
||||
|
||||
% Create figure
|
||||
figure1 = figure('Color',[1 1 1]);
|
||||
|
||||
subplot(1,2,1)
|
||||
|
||||
|
||||
hb=barh(test_data(:,1),test_data(:,2),'DisplayName','Test Data');
|
||||
|
||||
ylabel('parameter [units]');
|
||||
xlabel('#');
|
||||
legend('show','Location','northwest');
|
||||
subplot(1,2,2)
|
||||
|
||||
|
||||
hb=bar(test_data(:,1),test_data(:,2),'DisplayName','Test Data');
|
||||
|
||||
xlabel('parameter [units]');
|
||||
ylabel('#');
|
||||
legend('show','Location','northwest');
|
||||
|
||||
|
||||
xdata=test_data(:,1);
|
||||
barWidth=test_getBarWidthInAbsolutUnits(hb);
|
||||
|
||||
x_l=xdata-barWidth/2;
|
||||
x_u=xdata+barWidth/2;
|
||||
max_y=max(test_data(:,2))*1.2;
|
||||
x=[];
|
||||
y=[];
|
||||
for i=1:length(x_l)
|
||||
x = [x , x_l(i),x_l(i),nan,x_u(i),x_u(i),nan];
|
||||
y = [y, 0,max_y ,nan,0 ,max_y ,nan];
|
||||
|
||||
|
||||
end
|
||||
hold on
|
||||
plot(x,y,'r');
|
||||
|
||||
matlab2tikz('figurehandle',figure1,'filename','example_v_bar_plot.tex' ,'standalone', true);
|
||||
|
||||
|
||||
function BarWidth=test_getBarWidthInAbsolutUnits(h)
|
||||
% astimates the width of a bar plot
|
||||
XData_bar=get(h,'XData');
|
||||
length_bar = length(XData_bar);
|
||||
BarWidth= get(h, 'BarWidth');
|
||||
if length_bar > 1
|
||||
BarWidth = min(diff(XData_bar))*BarWidth;
|
||||
end
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
%% Quiver calculations
|
||||
% These are calculations for the quiver dimensions as implemented in MATLAB
|
||||
% (HG1) as in the |quiver.m| function.
|
||||
%
|
||||
% For HG2 and Octave, the situation might be different.
|
||||
%
|
||||
% A single quiver is defined as:
|
||||
%
|
||||
% C
|
||||
% \
|
||||
% \
|
||||
% A ----------------- B
|
||||
% /
|
||||
% /
|
||||
% D
|
||||
%
|
||||
% To know the dimensions of the arrow head, MATLAB defines the quantities
|
||||
% alpha = beta = 0.33 that determine the coordinates of C and D as given below.
|
||||
|
||||
clc;
|
||||
clear variables;
|
||||
close all;
|
||||
|
||||
%% Parameters
|
||||
try
|
||||
syms x y z u v w alpha beta epsilon real
|
||||
catch
|
||||
warning('Symbolic toolbox not found. Interpret the values with care!');
|
||||
x = randn(); y = randn(); z = randn();
|
||||
u = randn(); v = randn(); w = randn();
|
||||
end
|
||||
alpha = 0.33;
|
||||
beta = alpha;
|
||||
epsilon = 0;
|
||||
is2D = true;
|
||||
|
||||
%% Coordinates as defined in MATLAB
|
||||
% Note that in 3D, the arrow head is oriented in a weird way. Let' just ignore
|
||||
% that and only focus on 2D and use the same in 3D. Due to the lack
|
||||
% of [u,v,w]-symmetry in those equations, the angle is bound to depend on the
|
||||
% length of |delta|, i.e. something we don't know beforehand.
|
||||
A = [x y z].';
|
||||
delta = [u v w].';
|
||||
B = A + delta;
|
||||
C = B - alpha*[u+beta*(v+epsilon);
|
||||
v-beta*(u+epsilon)
|
||||
w];
|
||||
D = B - alpha*[u-beta*(v+epsilon);
|
||||
v+beta*(u+epsilon)
|
||||
w];
|
||||
|
||||
if is2D
|
||||
A = A(1:2);
|
||||
B = B(1:2);
|
||||
C = C(1:2);
|
||||
D = D(1:2);
|
||||
delta = delta(1:2);
|
||||
end
|
||||
|
||||
%% Calculating the angle of the arrowhead
|
||||
% Calculate the cos(angle) using the inner product
|
||||
unitVector = @(v) v/norm(v);
|
||||
cosAngleBetween = @(a,b,c) unitVector(a-b).' * unitVector(c-b);
|
||||
|
||||
cosTwiceTheta = cosAngleBetween(C,B,D);
|
||||
if isa(cosTwiceTheta, 'sym')
|
||||
cosTwiceTheta = simplify(cosTwiceTheta);
|
||||
end
|
||||
|
||||
theta = acos(cosTwiceTheta) / 2
|
||||
|
||||
radToDeg = @(rads) (rads * 180 / pi);
|
||||
|
||||
thetaVal = radToDeg(theta)
|
||||
try
|
||||
thetaVal = double(thetaVal)
|
||||
end
|
||||
|
||||
% For the MATLAB parameters alpha=beta=0.33, we get theta = 18.263 degrees.
|
||||
|
||||
@@ -0,0 +1,222 @@
|
||||
function makeLatexReport(status, output)
|
||||
% generate a LaTeX report
|
||||
%
|
||||
%
|
||||
if ~exist('output','var')
|
||||
output = m2troot('test','output','current');
|
||||
end
|
||||
% first, initialize the tex output
|
||||
SM = StreamMaker();
|
||||
stream = SM.make(fullfile(output, 'acid.tex'), 'w');
|
||||
|
||||
texfile_init(stream);
|
||||
|
||||
printFigures(stream, status);
|
||||
printSummaryTable(stream, status);
|
||||
printErrorMessages(stream, status);
|
||||
printEnvironmentInfo(stream, status);
|
||||
|
||||
texfile_finish(stream);
|
||||
end
|
||||
% =========================================================================
|
||||
function texfile_init(stream)
|
||||
|
||||
stream.print(['\\documentclass[landscape]{scrartcl}\n' , ...
|
||||
'\\pdfminorversion=6\n\n' , ...
|
||||
'\\usepackage{amsmath} %% required for $\\text{xyz}$\n\n', ...
|
||||
'\\usepackage{hyperref}\n' , ...
|
||||
'\\usepackage{graphicx}\n' , ...
|
||||
'\\usepackage{epstopdf}\n' , ...
|
||||
'\\usepackage{tikz}\n' , ...
|
||||
'\\usetikzlibrary{plotmarks}\n\n' , ...
|
||||
'\\usepackage{pgfplots}\n' , ...
|
||||
'\\pgfplotsset{compat=newest}\n\n' , ...
|
||||
'\\usepackage[margin=0.5in]{geometry}\n' , ...
|
||||
'\\newlength\\figurewidth\n' , ...
|
||||
'\\setlength\\figurewidth{0.4\\textwidth}\n\n' , ...
|
||||
'\\begin{document}\n\n']);
|
||||
|
||||
end
|
||||
% =========================================================================
|
||||
function texfile_finish(stream)
|
||||
stream.print('\\end{document}');
|
||||
end
|
||||
% =========================================================================
|
||||
function printFigures(stream, status)
|
||||
for k = 1:length(status)
|
||||
texfile_addtest(stream, status{k});
|
||||
end
|
||||
end
|
||||
% =========================================================================
|
||||
function printSummaryTable(stream, status)
|
||||
texfile_tab_completion_init(stream)
|
||||
for k = 1:length(status)
|
||||
stat = status{k};
|
||||
testNumber = stat.index;
|
||||
% Break table up into pieces if it gets too long for one page
|
||||
%TODO: use booktabs instead
|
||||
%TODO: maybe just write a function to construct the table at once
|
||||
% from a cell array (see makeTravisReport for GFM counterpart)
|
||||
if ~mod(k,35)
|
||||
texfile_tab_completion_finish(stream);
|
||||
texfile_tab_completion_init(stream);
|
||||
end
|
||||
|
||||
stream.print('%d & \\texttt{%s}', testNumber, name2tex(stat.function));
|
||||
if stat.skip
|
||||
stream.print(' & --- & skipped & ---');
|
||||
else
|
||||
for err = [stat.plotStage.error, ...
|
||||
stat.saveStage.error, ...
|
||||
stat.tikzStage.error]
|
||||
if err
|
||||
stream.print(' & \\textcolor{red}{failed}');
|
||||
else
|
||||
stream.print(' & \\textcolor{green!50!black}{passed}');
|
||||
end
|
||||
end
|
||||
end
|
||||
stream.print(' \\\\\n');
|
||||
end
|
||||
texfile_tab_completion_finish(stream);
|
||||
end
|
||||
% =========================================================================
|
||||
function printErrorMessages(stream, status)
|
||||
if errorHasOccurred(status)
|
||||
stream.print('\\section*{Error messages}\n\\scriptsize\n');
|
||||
for k = 1:length(status)
|
||||
stat = status{k};
|
||||
testNumber = stat.index;
|
||||
if isempty(stat.plotStage.message) && ...
|
||||
isempty(stat.saveStage.message) && ...
|
||||
isempty(stat.tikzStage.message)
|
||||
continue % No error messages for this test case
|
||||
end
|
||||
|
||||
stream.print('\n\\subsection*{Test case %d: \\texttt{%s}}\n', testNumber, name2tex(stat.function));
|
||||
print_verbatim_information(stream, 'Plot generation', stat.plotStage.message);
|
||||
print_verbatim_information(stream, 'PDF generation' , stat.saveStage.message);
|
||||
print_verbatim_information(stream, 'matlab2tikz' , stat.tikzStage.message);
|
||||
end
|
||||
stream.print('\n\\normalsize\n\n');
|
||||
end
|
||||
end
|
||||
% =========================================================================
|
||||
function printEnvironmentInfo(stream, status)
|
||||
[env,versionString] = getEnvironment();
|
||||
|
||||
testsuites = unique(cellfun(@(s) func2str(s.testsuite) , status, ...
|
||||
'UniformOutput', false));
|
||||
testsuites = name2tex(m2tstrjoin(testsuites, ', '));
|
||||
|
||||
stream.print(['\\newpage\n',...
|
||||
'\\begin{tabular}{ll}\n',...
|
||||
' Suite & ' testsuites ' \\\\ \n', ...
|
||||
' Created & ' datestr(now) ' \\\\ \n', ...
|
||||
' OS & ' OSVersion ' \\\\ \n',...
|
||||
' ' env ' & ' versionString ' \\\\ \n', ...
|
||||
VersionControlIdentifier, ...
|
||||
' TikZ & \\expandafter\\csname ver@tikz.sty\\endcsname \\\\ \n',...
|
||||
' Pgfplots & \\expandafter\\csname ver@pgfplots.sty\\endcsname \\\\ \n',...
|
||||
'\\end{tabular}\n']);
|
||||
|
||||
end
|
||||
% =========================================================================
|
||||
function print_verbatim_information(stream, title, contents)
|
||||
if ~isempty(contents)
|
||||
stream.print(['\\subsubsection*{%s}\n', ...
|
||||
'\\begin{verbatim}\n%s\\end{verbatim}\n'], ...
|
||||
title, contents);
|
||||
end
|
||||
end
|
||||
% =========================================================================
|
||||
function texfile_addtest(stream, status)
|
||||
% Actually add the piece of LaTeX code that'll later be used to display
|
||||
% the given test.
|
||||
if ~status.skip
|
||||
|
||||
ref_error = status.plotStage.error;
|
||||
gen_error = status.tikzStage.error;
|
||||
|
||||
ref_file = status.saveStage.texReference;
|
||||
gen_file = status.tikzStage.pdfFile;
|
||||
|
||||
stream.print(...
|
||||
['\\begin{figure}\n' , ...
|
||||
' \\centering\n' , ...
|
||||
' \\begin{tabular}{cc}\n' , ...
|
||||
' %s & %s \\\\\n' , ...
|
||||
' reference rendering & generated\n' , ...
|
||||
' \\end{tabular}\n' , ...
|
||||
' \\caption{%s \\texttt{%s}, \\texttt{%s(%d)}.%s}\n', ...
|
||||
'\\end{figure}\n' , ...
|
||||
'\\clearpage\n\n'],...
|
||||
include_figure(ref_error, 'includegraphics', ref_file), ...
|
||||
include_figure(gen_error, 'includegraphics', gen_file), ...
|
||||
status.description, ...
|
||||
name2tex(status.function), name2tex(status.testsuite), status.index, ...
|
||||
formatIssuesForTeX(status.issues));
|
||||
end
|
||||
end
|
||||
% =========================================================================
|
||||
function str = include_figure(errorOccured, command, filename)
|
||||
if errorOccured
|
||||
str = sprintf(['\\tikz{\\draw[red,thick] ', ...
|
||||
'(0,0) -- (\\figurewidth,\\figurewidth) ', ...
|
||||
'(0,\\figurewidth) -- (\\figurewidth,0);}']);
|
||||
else
|
||||
switch command
|
||||
case 'includegraphics'
|
||||
strFormat = '\\includegraphics[width=\\figurewidth]{%s}';
|
||||
case 'input'
|
||||
strFormat = '\\input{%s}';
|
||||
otherwise
|
||||
error('Matlab2tikz_acidtest:UnknownFigureCommand', ...
|
||||
'Unknown figure command "%s"', command);
|
||||
end
|
||||
str = sprintf(strFormat, filename);
|
||||
end
|
||||
end
|
||||
% =========================================================================
|
||||
function texfile_tab_completion_init(stream)
|
||||
|
||||
stream.print(['\\clearpage\n\n' , ...
|
||||
'\\begin{table}\n' , ...
|
||||
'\\centering\n' , ...
|
||||
'\\caption{Test case completion summary}\n' , ...
|
||||
'\\begin{tabular}{rlccc}\n' , ...
|
||||
'No. & Test case & Plot & PDF & TikZ \\\\\n' , ...
|
||||
'\\hline\n']);
|
||||
|
||||
end
|
||||
% =========================================================================
|
||||
function texfile_tab_completion_finish(stream)
|
||||
|
||||
stream.print( ['\\end{tabular}\n' , ...
|
||||
'\\end{table}\n\n' ]);
|
||||
|
||||
end
|
||||
% =========================================================================
|
||||
function texName = name2tex(matlabIdentifier)
|
||||
% convert a MATLAB identifier/function handle to a TeX string
|
||||
if isa(matlabIdentifier, 'function_handle')
|
||||
matlabIdentifier = func2str(matlabIdentifier);
|
||||
end
|
||||
texName = strrep(matlabIdentifier, '_', '\_');
|
||||
end
|
||||
% =========================================================================
|
||||
function str = formatIssuesForTeX(issues)
|
||||
% make links to GitHub issues for the LaTeX output
|
||||
issues = issues(:)';
|
||||
if isempty(issues)
|
||||
str = '';
|
||||
return
|
||||
end
|
||||
BASEURL = 'https://github.com/matlab2tikz/matlab2tikz/issues/';
|
||||
SEPARATOR = sprintf(' \n');
|
||||
strs = arrayfun(@(n) sprintf(['\\href{' BASEURL '%d}{\\#%d}'], n,n), issues, ...
|
||||
'UniformOutput', false);
|
||||
strs = [strs; repmat({SEPARATOR}, 1, numel(strs))];
|
||||
str = sprintf('{\\color{blue} \\texttt{%s}}', [strs{:}]);
|
||||
end
|
||||
% ==============================================================================
|
||||
@@ -0,0 +1,74 @@
|
||||
function makeTapReport(status, varargin)
|
||||
% Makes a Test Anything Protocol report
|
||||
%
|
||||
% This function produces a testing report of HEADLESS tests for
|
||||
% display on Jenkins (or any other TAP-compatible system)
|
||||
%
|
||||
% MAKETAPREPORT(status) produces the report from the `status` output of
|
||||
% `testHeadless`.
|
||||
%
|
||||
% MAKETAPREPORT(status, 'stream', FID, ...) changes the filestream to use
|
||||
% to output the report to. (Default: 1 (stdout)).
|
||||
%
|
||||
% TAP Specification: https://testanything.org
|
||||
%
|
||||
% See also: testHeadless, makeTravisReport, makeLatexReport
|
||||
|
||||
%% Parse input arguments
|
||||
SM = StreamMaker();
|
||||
ipp = m2tInputParser();
|
||||
|
||||
ipp = ipp.addRequired(ipp, 'status', @iscell);
|
||||
ipp = ipp.addParamValue(ipp, 'stream', 1, SM.isStream);
|
||||
|
||||
ipp = ipp.parse(ipp, status, varargin{:});
|
||||
arg = ipp.Results;
|
||||
|
||||
%% Construct stream
|
||||
stream = SM.make(arg.stream, 'w');
|
||||
|
||||
%% build report
|
||||
printTAPVersion(stream);
|
||||
printTAPPlan(stream, status);
|
||||
for iStatus = 1:numel(status)
|
||||
printTAPReport(stream, status{iStatus}, iStatus);
|
||||
end
|
||||
end
|
||||
% ==============================================================================
|
||||
function printTAPVersion(stream)
|
||||
% prints the TAP version
|
||||
stream.print('TAP version 13\n');
|
||||
end
|
||||
function printTAPPlan(stream, statuses)
|
||||
% prints the TAP test plan
|
||||
firstTest = 1;
|
||||
lastTest = numel(statuses);
|
||||
stream.print('%d..%d\n', firstTest, lastTest);
|
||||
end
|
||||
function printTAPReport(stream, status, testNum)
|
||||
% prints a TAP test case report
|
||||
message = status.function;
|
||||
|
||||
if hasTestFailed(status)
|
||||
result = 'not ok';
|
||||
else
|
||||
result = 'ok';
|
||||
end
|
||||
directives = getTAPDirectives(status);
|
||||
|
||||
stream.print('%s %d %s %s\n', result, testNum, message, directives);
|
||||
|
||||
%TODO: we can provide more information on the failure using YAML syntax
|
||||
end
|
||||
function directives = getTAPDirectives(status)
|
||||
% add TAP directive (a todo or skip) to the test directives
|
||||
directives = {};
|
||||
if status.skip
|
||||
directives{end+1} = '# SKIP skipped';
|
||||
end
|
||||
if status.unreliable
|
||||
directives{end+1} = '# TODO unreliable';
|
||||
end
|
||||
directives = strtrim(m2tstrjoin(directives, ' '));
|
||||
end
|
||||
% ==============================================================================
|
||||
@@ -0,0 +1,360 @@
|
||||
function [nErrors] = makeTravisReport(status, varargin)
|
||||
% Makes a readable report for Travis/Github of test results
|
||||
%
|
||||
% This function produces a testing report of HEADLESS tests for
|
||||
% display on GitHub and Travis.
|
||||
%
|
||||
% MAKETRAVISREPORT(status) produces the report from the `status` output of
|
||||
% `testHeadless`.
|
||||
%
|
||||
% MAKETRAVISREPORT(status, 'stream', FID, ...) changes the filestream to use
|
||||
% to output the report to. (Default: 1 (stdout)).
|
||||
%
|
||||
% MAKETRAVISREPORT(status, 'length', CHAR, ...) changes the report length.
|
||||
% A few values are possible that cover different aspects in less/more detail.
|
||||
% - 'default': all unreliable tests, failed & skipped tests and summary
|
||||
% - 'short' : only show the brief summary
|
||||
% - 'long' : all tests + summary
|
||||
%
|
||||
% See also: testHeadless, makeLatexReport
|
||||
|
||||
SM = StreamMaker();
|
||||
%% Parse input arguments
|
||||
ipp = m2tInputParser();
|
||||
|
||||
ipp = ipp.addRequired(ipp, 'status', @iscell);
|
||||
ipp = ipp.addParamValue(ipp, 'stream', 1, SM.isStream);
|
||||
ipp = ipp.addParamValue(ipp, 'length', 'default', @isReportLength);
|
||||
|
||||
ipp = ipp.parse(ipp, status, varargin{:});
|
||||
arg = ipp.Results;
|
||||
arg.length = lower(arg.length);
|
||||
stream = SM.make(arg.stream, 'w');
|
||||
|
||||
%% transform status data into groups
|
||||
S = splitStatuses(status);
|
||||
|
||||
%% build report
|
||||
stream.print(gfmHeader(describeEnvironment));
|
||||
reportUnreliableTests(stream, arg, S);
|
||||
reportReliableTests(stream, arg, S);
|
||||
displayTestSummary(stream, S);
|
||||
|
||||
%% set output arguments if needed
|
||||
if nargout >= 1
|
||||
nErrors = countNumberOfErrors(S.reliable);
|
||||
end
|
||||
end
|
||||
% == INPUT VALIDATOR FUNCTIONS =================================================
|
||||
function bool = isReportLength(val)
|
||||
% validates the report length
|
||||
bool = ismember(lower(val), {'default','short','long'});
|
||||
end
|
||||
% == GITHUB-FLAVORED MARKDOWN FUNCTIONS ========================================
|
||||
function str = gfmTable(data, header, alignment)
|
||||
% Construct a Github-flavored Markdown table
|
||||
%
|
||||
% Arguments:
|
||||
% - data: nRows x nCols cell array that represents the data
|
||||
% - header: cell array with the (nCol) column headers
|
||||
% - alignment: alignment specification per column
|
||||
% * 'l': left-aligned (default)
|
||||
% * 'c': centered
|
||||
% * 'r': right-aligned
|
||||
% When not enough entries are specified, the specification is repeated
|
||||
% cyclically.
|
||||
%
|
||||
% Output: table as a string
|
||||
%
|
||||
% See https://help.github.com/articles/github-flavored-markdown/#tables
|
||||
|
||||
% input argument validation and normalization
|
||||
nCols = size(data, 2);
|
||||
if ~exist('alignment','var') || isempty(alignment)
|
||||
alignment = 'l';
|
||||
end
|
||||
if numel(alignment) < nCols
|
||||
% repeat the alignment specifications along the columns
|
||||
alignment = repmat(alignment, 1, nCols);
|
||||
alignment = alignment(1:nCols);
|
||||
end
|
||||
|
||||
% calculate the required column width
|
||||
cellWidth = cellfun(@length, [header(:)' ;data]);
|
||||
columnWidth = max(max(cellWidth, [], 1),3); % use at least 3 places
|
||||
|
||||
% prepare the table format
|
||||
COLSEP = '|'; ROWSEP = sprintf('\n');
|
||||
rowformat = [COLSEP sprintf([' %%%ds ' COLSEP], columnWidth) ROWSEP];
|
||||
alignmentRow = formatAlignment(alignment, columnWidth);
|
||||
|
||||
% actually print the table
|
||||
fullTable = [header; alignmentRow; data];
|
||||
strs = cell(size(fullTable,1), 1);
|
||||
for iRow = 1:numel(strs)
|
||||
thisRow = fullTable(iRow,:);
|
||||
%TODO: maybe preprocess thisRow with strjust first
|
||||
strs{iRow} = sprintf(rowformat, thisRow{:});
|
||||
end
|
||||
str = [strs{:}];
|
||||
|
||||
%---------------------------------------------------------------------------
|
||||
function alignRow = formatAlignment(alignment, columnWidth)
|
||||
% Construct a row of dashes to specify the alignment of each column
|
||||
% See https://help.github.com/articles/github-flavored-markdown/#tables
|
||||
DASH = '-'; COLON = ':';
|
||||
N = numel(columnWidth);
|
||||
alignRow = arrayfun(@(w) repmat(DASH, 1, w), columnWidth, ...
|
||||
'UniformOutput', false);
|
||||
for iColumn = 1:N
|
||||
thisAlign = alignment(iColumn);
|
||||
thisSpec = alignRow{iColumn};
|
||||
switch lower(thisAlign)
|
||||
case 'l'
|
||||
thisSpec(1) = COLON;
|
||||
case 'r'
|
||||
thisSpec(end) = COLON;
|
||||
case 'c'
|
||||
thisSpec([1 end]) = COLON;
|
||||
otherwise
|
||||
error('gfmTable:BadAlignment','Unknown alignment "%s"',...
|
||||
thisAlign);
|
||||
end
|
||||
alignRow{iColumn} = thisSpec;
|
||||
end
|
||||
end
|
||||
end
|
||||
function str = gfmCode(str, inline, language)
|
||||
% Construct a GFM code fragment
|
||||
%
|
||||
% Arguments:
|
||||
% - str: code to be displayed
|
||||
% - inline: - true -> formats inline
|
||||
% - false -> formats as code block
|
||||
% - [] -> automatic mode (default): picks one of the above
|
||||
% - language: which language the code is (enforces a code block)
|
||||
%
|
||||
% Output: GFM formatted string
|
||||
%
|
||||
% See https://help.github.com/articles/github-flavored-markdown
|
||||
if ~exist('inline','var')
|
||||
inline = [];
|
||||
end
|
||||
if ~exist('language','var') || isempty(language)
|
||||
language = '';
|
||||
else
|
||||
inline = false; % highlighting is not supported for inline code
|
||||
end
|
||||
if isempty(inline)
|
||||
inline = isempty(strfind(str, sprintf('\n')));
|
||||
end
|
||||
|
||||
if inline
|
||||
prefix = '`';
|
||||
postfix = '`';
|
||||
else
|
||||
prefix = sprintf('\n```%s\n', language);
|
||||
postfix = sprintf('\n```\n');
|
||||
if str(end) == sprintf('\n')
|
||||
postfix = postfix(2:end); % remove extra endline
|
||||
end
|
||||
end
|
||||
|
||||
str = sprintf('%s%s%s', prefix, str, postfix);
|
||||
end
|
||||
function str = gfmHeader(str, level)
|
||||
% Constructs a GFM/Markdown header
|
||||
if ~exist('level','var')
|
||||
level = 1;
|
||||
end
|
||||
str = sprintf('\n%s %s\n', repmat('#', 1, level), str);
|
||||
end
|
||||
function symbols = githubEmoji()
|
||||
% defines the emojis to signal the test result
|
||||
symbols = struct('pass', ':white_check_mark:', ...
|
||||
'fail', ':heavy_exclamation_mark:', ...
|
||||
'skip', ':grey_question:');
|
||||
end
|
||||
% ==============================================================================
|
||||
function S = splitStatuses(status)
|
||||
% splits a cell array of statuses into a struct of cell arrays
|
||||
% of statuses according to their value of "skip", "reliable" and whether
|
||||
% an error has occured.
|
||||
% See also: splitUnreliableTests, splitPassFailSkippedTests
|
||||
S = struct('all', {status}); % beware of cell array assignment to structs!
|
||||
|
||||
[S.reliable, S.unreliable] = splitUnreliableTests(status);
|
||||
[S.passR, S.failR, S.skipR] = splitPassFailSkippedTests(S.reliable);
|
||||
[S.passU, S.failU, S.skipU] = splitPassFailSkippedTests(S.unreliable);
|
||||
end
|
||||
% ==============================================================================
|
||||
function [short, long] = describeEnvironment()
|
||||
% describes the environment in a short and long format
|
||||
[env, ver] = getEnvironment;
|
||||
[dummy, VCID] = VersionControlIdentifier(); %#ok
|
||||
if ~isempty(VCID)
|
||||
VCID = [' commit ' VCID(1:10)];
|
||||
end
|
||||
OS = OSVersion;
|
||||
short = sprintf('%s %s (%s)', env, ver, OS, VCID);
|
||||
long = sprintf('Test results for m2t%s running with %s %s on %s.', ...
|
||||
VCID, env, ver, OS);
|
||||
end
|
||||
% ==============================================================================
|
||||
function reportUnreliableTests(stream, arg, S)
|
||||
% report on the unreliable tests
|
||||
if ~isempty(S.unreliable) && ~strcmpi(arg.length, 'short')
|
||||
stream.print(gfmHeader('Unreliable tests',2));
|
||||
stream.print('These do not cause the build to fail.\n\n');
|
||||
displayTestResults(stream, S.unreliable);
|
||||
end
|
||||
end
|
||||
function reportReliableTests(stream, arg, S)
|
||||
% report on the reliable tests
|
||||
switch arg.length
|
||||
case 'long'
|
||||
tests = S.reliable;
|
||||
message = '';
|
||||
case 'default'
|
||||
tests = [S.failR; S.skipR];
|
||||
message = 'Passing tests are not shown (only failed and skipped tests).\n\n';
|
||||
case 'short'
|
||||
return; % don't show this part
|
||||
end
|
||||
|
||||
stream.print(gfmHeader('Reliable tests',2));
|
||||
stream.print('Only the reliable tests determine the build outcome.\n');
|
||||
stream.print(message);
|
||||
displayTestResults(stream, tests);
|
||||
end
|
||||
% ==============================================================================
|
||||
function displayTestResults(stream, status)
|
||||
% display a table of specific test outcomes
|
||||
headers = {'Testcase', 'Name', 'OK', 'Status'};
|
||||
data = cell(numel(status), numel(headers));
|
||||
symbols = githubEmoji;
|
||||
for iTest = 1:numel(status)
|
||||
data(iTest,:) = fillTestResultRow(status{iTest}, symbols);
|
||||
end
|
||||
str = gfmTable(data, headers, 'llcl');
|
||||
stream.print('%s', str);
|
||||
end
|
||||
function row = fillTestResultRow(oneStatus, symbol)
|
||||
% format the status of a single test for the summary table
|
||||
testNumber = oneStatus.index;
|
||||
testSuite = func2str(oneStatus.testsuite);
|
||||
summary = '';
|
||||
if oneStatus.skip
|
||||
summary = 'SKIPPED';
|
||||
passOrFail = symbol.skip;
|
||||
else
|
||||
stages = getStagesFromStatus(oneStatus);
|
||||
for jStage = 1:numel(stages)
|
||||
thisStage = oneStatus.(stages{jStage});
|
||||
if ~thisStage.error
|
||||
continue;
|
||||
end
|
||||
stageName = strrep(stages{jStage},'Stage','');
|
||||
switch stageName
|
||||
case 'plot'
|
||||
summary = sprintf('%s plot failed', summary);
|
||||
case 'tikz'
|
||||
summary = sprintf('%s m2t failed', summary);
|
||||
case 'hash'
|
||||
summary = sprintf('new hash %32s != expected (%32s) %s', ...
|
||||
thisStage.found, thisStage.expected, summary);
|
||||
otherwise
|
||||
summary = sprintf('%s %s FAILED', summary, thisStage);
|
||||
end
|
||||
end
|
||||
if isempty(summary)
|
||||
passOrFail = symbol.pass;
|
||||
else
|
||||
passOrFail = symbol.fail;
|
||||
end
|
||||
summary = strtrim(summary);
|
||||
end
|
||||
row = { gfmCode(sprintf('%s(%d)', testSuite, testNumber)), ...
|
||||
gfmCode(oneStatus.function), ...
|
||||
passOrFail, ...
|
||||
summary};
|
||||
end
|
||||
% ==============================================================================
|
||||
function displayTestSummary(stream, S)
|
||||
% display a table of # of failed/passed/skipped tests vs (un)reliable
|
||||
|
||||
% compute number of cases per category
|
||||
reliableSummary = cellfun(@numel, {S.passR, S.failR, S.skipR});
|
||||
unreliableSummary = cellfun(@numel, {S.passU, S.failU, S.skipU});
|
||||
|
||||
% make summary table + calculate totals
|
||||
summary = [unreliableSummary numel(S.unreliable);
|
||||
reliableSummary numel(S.reliable);
|
||||
reliableSummary+unreliableSummary numel(S.all)];
|
||||
|
||||
% put results into cell array with proper layout
|
||||
summary = arrayfun(@(v) sprintf('%d',v), summary, 'UniformOutput', false);
|
||||
table = repmat({''}, 3, 5);
|
||||
header = {'','Pass','Fail','Skip','Total'};
|
||||
table(:,1) = {'Unreliable','Reliable','Total'};
|
||||
table(:,2:end) = summary;
|
||||
|
||||
% print table
|
||||
[envShort, envDescription] = describeEnvironment(); %#ok
|
||||
stream.print(gfmHeader('Test summary', 2));
|
||||
stream.print('%s\n', envDescription);
|
||||
stream.print('%s\n', gfmCode(generateCode(S),false,'matlab'));
|
||||
stream.print(gfmTable(table, header, 'lrrrr'));
|
||||
|
||||
% print overall outcome
|
||||
symbol = githubEmoji;
|
||||
nErrors = numel(S.failR);
|
||||
if nErrors == 0
|
||||
stream.print('\nBuild passes. %s\n', symbol.pass);
|
||||
else
|
||||
stream.print('\nBuild fails with %d errors. %s\n', nErrors, symbol.fail);
|
||||
end
|
||||
end
|
||||
function code = generateCode(S)
|
||||
% generates some MATLAB code to easily replicate the results
|
||||
code = sprintf('%s = %s;\n', ...
|
||||
'suite', ['@' func2str(S.all{1}.testsuite)], ...
|
||||
'alltests', testNumbers(S.all), ...
|
||||
'reliable', testNumbers(S.reliable), ...
|
||||
'unreliable', testNumbers(S.unreliable), ...
|
||||
'failReliable', testNumbers(S.failR), ...
|
||||
'passUnreliable', testNumbers(S.passU), ...
|
||||
'skipped', testNumbers([S.skipR; S.skipU]));
|
||||
% --------------------------------------------------------------------------
|
||||
function str = testNumbers(status)
|
||||
str = intelligentVector( cellfun(@(s) s.index, status) );
|
||||
end
|
||||
end
|
||||
function str = intelligentVector(numbers)
|
||||
% Produce a string that is an intelligent vector notation of its arguments
|
||||
% e.g. when numbers = [ 1 2 3 4 6 7 8 9 ], it should return '[ 1:4 6:9 ]'
|
||||
% The order in the vector is not retained!
|
||||
|
||||
if isempty(numbers)
|
||||
str = '[]';
|
||||
else
|
||||
numbers = sort(numbers(:).');
|
||||
delta = diff([numbers(1)-1 numbers]);
|
||||
% place virtual bounds at the first element and beyond the last one
|
||||
bounds = [1 find(delta~=1) numel(numbers)+1];
|
||||
idx = 1:(numel(bounds)-1); % start index of each segment
|
||||
start = numbers(bounds(idx ) );
|
||||
stop = numbers(bounds(idx+1)-1);
|
||||
parts = arrayfun(@formatRange, start, stop, 'UniformOutput', false);
|
||||
str = sprintf('[%s]', strtrim(sprintf('%s ', parts{:})));
|
||||
end
|
||||
end
|
||||
function str = formatRange(start, stop)
|
||||
% format a range [start:stop] of integers in MATLAB syntax
|
||||
if start==stop
|
||||
str = sprintf('%d',start);
|
||||
else
|
||||
str = sprintf('%d:%d',start, stop);
|
||||
end
|
||||
end
|
||||
% ==============================================================================
|
||||
4
Functions/helper_functions_community/mat2tikz/test/output/.gitignore
vendored
Normal file
4
Functions/helper_functions_community/mat2tikz/test/output/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
# This is a directory for testing output. Nothing in here should ever
|
||||
# be committed, except the .gitignore to enforce all of this.
|
||||
*
|
||||
!.gitignore
|
||||
@@ -0,0 +1,36 @@
|
||||
function [formatted, OSType, OSVersion] = OSVersion()
|
||||
% determines the OS type and its (kernel) version number
|
||||
if ismac
|
||||
OSType = 'Mac OS';
|
||||
[dummy, OSVersion] = system('sw_vers -productVersion'); %#ok
|
||||
% Output like "10.10.4" for OS X Yosemite
|
||||
|
||||
elseif ispc
|
||||
OSType = 'Windows';
|
||||
[dummy, rawVersion] = system('ver'); %#ok
|
||||
% Output like "Microsoft Windows [Version 6.3.9600]" for Win8.1
|
||||
pattern = '(?<=Version )[0-9.]+';
|
||||
OSVersion = regexpi(rawVersion, pattern, 'match', 'once');
|
||||
|
||||
elseif isunix
|
||||
[dummy, OSType] = system('uname -s'); %#ok
|
||||
% This returns the kernal name
|
||||
% e.g. "Linux" on Linux, "Darwin" on Mac, "SunOS" on Solaris
|
||||
[dummy, OSVersion] = system('uname -r'); %#ok
|
||||
% Returns the kernel version. Many Linux distributions
|
||||
% include an identifier, e.g. "4.0.7-2-ARCH" on Arch Linux
|
||||
|
||||
% TODO: also use `lsb_release` in Linux for distro info
|
||||
else
|
||||
warning('OSVersion:UnknownOS', 'Could not recognize OS.');
|
||||
OSType = 'Unknown OS';
|
||||
OSVersion = '';
|
||||
|
||||
end
|
||||
|
||||
EOL = sprintf('\n');
|
||||
OSType = strrep(OSType, EOL, '');
|
||||
OSVersion = strrep(OSVersion, EOL, '');
|
||||
|
||||
formatted = strtrim([OSType ' ' OSVersion]);
|
||||
end
|
||||
@@ -0,0 +1,74 @@
|
||||
function SM = StreamMaker()
|
||||
% StreamMaker (Factory for fie/input/output Streams)
|
||||
%
|
||||
% A StreamMaker can make Stream PseudoObjects based on either
|
||||
% an "fid" or "filename" (and extra arguments for `fopen`).
|
||||
% The StreamMaker also contains a method `isStream` to validate whether
|
||||
% the value passed is a valid stream specifier.
|
||||
%
|
||||
% Usage
|
||||
%
|
||||
% SM = StreamMaker;
|
||||
%
|
||||
% Stream = SM.make(fid)
|
||||
% Stream = SM.make(filename, ...)
|
||||
%
|
||||
% This returns a PseudoObject Stream with the following properties:
|
||||
% - name: (file) name of the stream
|
||||
% - fid: handle (fid) of the stream
|
||||
%
|
||||
% and methods:
|
||||
% - print: prints to the stream, i.e. fprintf
|
||||
% - close: closes the stream, i.e. fclose
|
||||
%
|
||||
% It may also contain a field to automatically close the Stream when it goes
|
||||
% out of scope.
|
||||
%
|
||||
SM = PseudoObject('StreamMaker', ...
|
||||
'isStream', @isStream, ...
|
||||
'make', @constructStream);
|
||||
end
|
||||
|
||||
function PseudoObj = PseudoObject(T, varargin)
|
||||
% construct a Pseudo-Object with type T (no other fields yet)
|
||||
PseudoObj = struct('Type', T, varargin{:});
|
||||
end
|
||||
|
||||
function bool = isStream(value)
|
||||
bool = ischar(value) || ismember(value, [1,2,fopen('all')]);
|
||||
%TODO: allow others kinds of streams
|
||||
% Stream -> clipboard (write on close)
|
||||
% Stream -> string variable
|
||||
% e.g. a quick-and-dirty way would be to write the file to `tempname`
|
||||
% putting a flag to read that file back upon completion.
|
||||
end
|
||||
|
||||
function Stream = constructStream(streamSpecifier, varargin)
|
||||
% this is the actual constructor of a stream
|
||||
if ~isStream(streamSpecifier)
|
||||
error('StreamMaker:NotAStream', 'Invalid stream specifier "%s"', ...
|
||||
streamSpecifier);
|
||||
end
|
||||
|
||||
Stream = PseudoObject('Stream');
|
||||
closeAfterUse = false;
|
||||
if ischar(streamSpecifier)
|
||||
Stream.name = streamSpecifier;
|
||||
Stream.fid = fopen(Stream.name, varargin{:});
|
||||
closeAfterUse = true;
|
||||
elseif isnumeric(streamSpecifier)
|
||||
Stream.fid = streamSpecifier;
|
||||
Stream.name = fopen(Stream.fid);
|
||||
end
|
||||
|
||||
if Stream.fid == -1
|
||||
error('Stream:InvalidStream', ...
|
||||
'Unable to create stream "%s"!', streamSpecifier);
|
||||
end
|
||||
|
||||
Stream.print = @(varargin) fprintf(Stream.fid, varargin{:});
|
||||
Stream.close = @() fclose(Stream.fid);
|
||||
if closeAfterUse
|
||||
Stream.closeAfterUse = onCleanup(Stream.close);
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,47 @@
|
||||
function [formatted,treeish] = VersionControlIdentifier()
|
||||
% This function gives the (git) commit ID of matlab2tikz
|
||||
%
|
||||
% This assumes the standard directory structure as used by Nico's master branch:
|
||||
% SOMEPATH/src/matlab2tikz.m with a .git directory in SOMEPATH.
|
||||
%
|
||||
% The HEAD of that repository is determined from file system information only
|
||||
% by following dynamic references (e.g. ref:refs/heds/master) in branch files
|
||||
% until an absolute commit hash (e.g. 1a3c9d1...) is found.
|
||||
% NOTE: Packed branch references are NOT supported by this approach
|
||||
MAXITER = 10; % stop following dynamic references after a while
|
||||
formatted = '';
|
||||
REFPREFIX = 'ref:';
|
||||
isReference = @(treeish)(any(strfind(treeish, REFPREFIX)));
|
||||
treeish = [REFPREFIX 'HEAD'];
|
||||
try
|
||||
% get the matlab2tikz directory
|
||||
privateDir = fileparts(mfilename('fullpath'));
|
||||
gitDir = fullfile(privateDir,'..','..','.git');
|
||||
|
||||
nIter = 1;
|
||||
while isReference(treeish)
|
||||
refName = treeish(numel(REFPREFIX)+1:end);
|
||||
branchFile = fullfile(gitDir, refName);
|
||||
|
||||
if exist(branchFile, 'file') && nIter < MAXITER
|
||||
% The FID is reused in every iteration, so `onCleanup` cannot
|
||||
% be used to `fclose(fid)`. But since there is very little that
|
||||
% can go wrong in a single `fscanf`, it's probably best to leave
|
||||
% this part as it is for the time being.
|
||||
fid = fopen(branchFile,'r');
|
||||
treeish = fscanf(fid,'%s');
|
||||
fclose(fid);
|
||||
nIter = nIter + 1;
|
||||
else % no branch file or iteration limit reached
|
||||
treeish = '';
|
||||
return;
|
||||
end
|
||||
end
|
||||
catch %#ok
|
||||
treeish = '';
|
||||
end
|
||||
if ~isempty(treeish)
|
||||
formatted = [' Commit & ' treeish ' \\\\ \n'];
|
||||
end
|
||||
%TODO: do the formatting somewhere else!
|
||||
end
|
||||
@@ -0,0 +1,35 @@
|
||||
function hash = calculateMD5Hash(filename)
|
||||
% CALCULATEMD5HASH calculate a MD5 hash of a file
|
||||
%
|
||||
% This functionality is built-in into Octave but uses Java in MATLAB.
|
||||
|
||||
switch getEnvironment
|
||||
case 'Octave'
|
||||
hash = md5sum(filename);
|
||||
|
||||
case 'MATLAB'
|
||||
% There are some MD5 implementations in MATLAB, but those
|
||||
% tend to be slow and licensing is unclear.
|
||||
% Rolling our own implementation is unwanted, especially since this
|
||||
% is a cryptographic hash, even though its security has been
|
||||
% broken. Instead we make use of the Java libraries.
|
||||
% Unless the "-nojvm" flag is specified, this should work well.
|
||||
|
||||
MD5 = java.security.MessageDigest.getInstance('MD5');
|
||||
|
||||
% Open the file
|
||||
fid = fopen(filename, 'r');
|
||||
|
||||
% Make sure fid is closed
|
||||
finally_close = onCleanup(@()fclose(fid));
|
||||
|
||||
% Faster file digest based on code by Jan Simon as in
|
||||
% http://www.mathworks.com/matlabcentral/fileexchange/31272-datahash
|
||||
data = fread(fid, '*uint8');
|
||||
MD5.update(data);
|
||||
|
||||
hash = reshape(dec2hex(typecast(MD5.digest(),'uint8')).', 1, 32);
|
||||
end
|
||||
|
||||
hash = lower(hash);
|
||||
end
|
||||
@@ -0,0 +1,19 @@
|
||||
function cleanFiles(cleanBefore)
|
||||
% clean output files in ./tex using make
|
||||
%FIXME: this file appears to be unused (but it is useful)
|
||||
%FIXME: adapt this file to take the output directory into account
|
||||
if cleanBefore && exist(fullfile('tex','Makefile'),'file')
|
||||
fprintf(1, 'Cleaning output files...\n');
|
||||
cwd = pwd;
|
||||
try
|
||||
cd('tex');
|
||||
[exitCode, output] = system('make distclean');
|
||||
fprintf(1,'%s\n', output);
|
||||
assert(exitCode==0, 'Exit code 0 means correct execution');
|
||||
catch
|
||||
% This might happen when make is not present
|
||||
fprintf(2, '\tNot completed succesfully\n\n');
|
||||
end
|
||||
cd(cwd);
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
function nErrors = countNumberOfErrors(status)
|
||||
% counts the number of errors in a status cell array
|
||||
nErrors = sum(hasTestFailed(status));
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
function stage = emptyStage()
|
||||
% constructs an empty (workflow) stage struct
|
||||
stage = struct('message', '', 'error' , false);
|
||||
end
|
||||
@@ -0,0 +1,24 @@
|
||||
function defaultStatus = emptyStatus(testsuite, testNumber)
|
||||
% constructs an empty status struct
|
||||
defaultStatus = struct(...
|
||||
'function', '', ...
|
||||
'description', '',...
|
||||
'testsuite', testsuite ,...
|
||||
'index', testNumber, ...
|
||||
'issues', [],...
|
||||
'unreliable', false, ...
|
||||
'skip', false, ... % skipped this test?
|
||||
'closeall', false, ... % call close all after?
|
||||
'extraOptions', {cell(0)}, ...
|
||||
'extraCleanfigureOptions',{cell(0)}, ...
|
||||
'plotStage', emptyStage(), ...
|
||||
'saveStage', emptyStage(), ...
|
||||
'tikzStage', emptyStage(), ...
|
||||
'hashStage', emptyStage() ...
|
||||
);
|
||||
|
||||
% for reliable tests explicitly define width and height, see #659
|
||||
% TODO: Remove explicitly setting this option.
|
||||
% After #641 is merged, this might be not needed anyhow.
|
||||
defaultStatus.extraCleanfigureOptions = {'targetResolution', [1000,500]};
|
||||
end
|
||||
@@ -0,0 +1,41 @@
|
||||
function [stage, errorHasOccurred] = errorHandler(e)
|
||||
% common error handler code: save and print to console
|
||||
errorHasOccurred = true;
|
||||
stage = emptyStage();
|
||||
stage.message = format_error_message(e);
|
||||
stage.error = errorHasOccurred;
|
||||
|
||||
disp_error_message(stage.message);
|
||||
end
|
||||
% ==============================================================================
|
||||
function msg = format_error_message(e)
|
||||
msg = '';
|
||||
if ~isempty(e.message)
|
||||
msg = sprintf('%serror: %s\n', msg, e.message);
|
||||
end
|
||||
if ~isempty(e.identifier)
|
||||
if strfind(lower(e.identifier),'testmatlab2tikz:')
|
||||
% When "errors" occur in the test framework, i.e. a hash mismatch
|
||||
% or no hash provided, there is no need to be very verbose.
|
||||
% So we don't return the msgid and the stack trace in those cases!
|
||||
return % only return the message
|
||||
end
|
||||
msg = sprintf('%serror: %s\n', msg, e.identifier);
|
||||
end
|
||||
if ~isempty(e.stack)
|
||||
msg = sprintf('%serror: called from:\n', msg);
|
||||
for ee = e.stack(:)'
|
||||
msg = sprintf('%serror: %s at line %d, in function %s\n', ...
|
||||
msg, ee.file, ee.line, ee.name);
|
||||
end
|
||||
end
|
||||
end
|
||||
% ==============================================================================
|
||||
function disp_error_message(msg)
|
||||
stderr = 2;
|
||||
% The error message should not contain any more escape sequences and
|
||||
% hence can be output literally to stderr.
|
||||
|
||||
fprintf(stderr, '%s', msg);
|
||||
end
|
||||
% ==============================================================================
|
||||
@@ -0,0 +1,16 @@
|
||||
function errorOccurred = errorHasOccurred(status)
|
||||
% determines whether an error has occurred from a status struct OR cell array
|
||||
% of status structs
|
||||
errorOccurred = false;
|
||||
if iscell(status)
|
||||
for iStatus = 1:numel(status)
|
||||
errorOccurred = errorOccurred || errorHasOccurred(status{iStatus});
|
||||
end
|
||||
else
|
||||
stages = getStagesFromStatus(status);
|
||||
for iStage = 1:numel(stages)
|
||||
thisStage = status.(stages{iStage});
|
||||
errorOccurred = errorOccurred || thisStage.error;
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,34 @@
|
||||
function [status] = execute_hash_stage(status, ipp)
|
||||
% test stage: check recorded hash checksum
|
||||
calculated = '';
|
||||
expected = '';
|
||||
try
|
||||
expected = getReferenceHash(status, ipp);
|
||||
calculated = calculateMD5Hash(status.tikzStage.texFile);
|
||||
|
||||
% do the actual check
|
||||
if ~strcmpi(expected, calculated)
|
||||
% throw an error to signal the testing framework
|
||||
error('testMatlab2tikz:HashMismatch', ...
|
||||
'The hash "%s" does not match the reference hash "%s"', ...
|
||||
calculated, expected);
|
||||
end
|
||||
catch %#ok
|
||||
e = lasterror('reset'); %#ok
|
||||
[status.hashStage] = errorHandler(e);
|
||||
end
|
||||
status.hashStage.expected = expected;
|
||||
status.hashStage.found = calculated;
|
||||
end
|
||||
% ==============================================================================
|
||||
function hash = getReferenceHash(status, ipp)
|
||||
% retrieves a reference hash from a hash table
|
||||
% WARNING: do not make `hashTable` persistent, since this is slower
|
||||
|
||||
hashTable = loadHashTable(ipp.Results.testsuite);
|
||||
if isfield(hashTable.contents, status.function)
|
||||
hash = hashTable.contents.(status.function);
|
||||
else
|
||||
hash = '';
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,45 @@
|
||||
function [status] = execute_plot_stage(defaultStatus, ipp)
|
||||
% plot a test figure
|
||||
testsuite = ipp.Results.testsuite;
|
||||
testNumber = defaultStatus.index;
|
||||
|
||||
% open a window
|
||||
fig_handle = figure('visible',ipp.Results.figureVisible);
|
||||
errorHasOccurred = false;
|
||||
|
||||
% plot the figure
|
||||
try
|
||||
status = testsuite(testNumber);
|
||||
|
||||
catch %#ok
|
||||
e = lasterror('reset'); %#ok
|
||||
|
||||
status.description = '\textcolor{red}{Error during plot generation.}';
|
||||
[status.plotStage, errorHasOccurred] = errorHandler(e);
|
||||
|
||||
% Automaticall mark the test as unreliable
|
||||
%
|
||||
% Since metadata is not set in this case, also stat.unreliable is
|
||||
% not returned. So ideally, we should
|
||||
% FIXME: implement #484 to get access to the meta data
|
||||
% but we can work around this issue by forcefully setting that value.
|
||||
% The rationale for setting this to true:
|
||||
% - the plot part is not the main task of M2T
|
||||
% (so breaking a single test is less severe in this case),
|
||||
% - if the plotting fails, the test is not really reliable anyway,
|
||||
% - this allows to get full green on Travis.
|
||||
status.unreliable = true;
|
||||
|
||||
end
|
||||
|
||||
status = fillStruct(status, defaultStatus);
|
||||
if isempty(status.function)
|
||||
allFuncs = testsuite(0);
|
||||
status.function = func2str(allFuncs{testNumber});
|
||||
end
|
||||
status.plotStage.fig_handle = fig_handle;
|
||||
|
||||
if status.skip || errorHasOccurred
|
||||
close(fig_handle);
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,63 @@
|
||||
function [status] = execute_save_stage(status, ipp)
|
||||
% save stage: saves the figure to EPS/PDF depending on env
|
||||
testNumber = status.index;
|
||||
|
||||
basepath = fullfile(ipp.Results.output,'data','reference');
|
||||
reference_eps = fullfile(basepath, sprintf('test%d-reference.eps', testNumber));
|
||||
reference_pdf = fullfile(basepath, sprintf('test%d-reference.pdf', testNumber));
|
||||
% the reference below is for inclusion in LaTeX! Use UNIX conventions!
|
||||
reference_fig = sprintf('data/reference/test%d-reference', testNumber);
|
||||
|
||||
% Save reference output as PDF
|
||||
try
|
||||
switch getEnvironment
|
||||
case 'MATLAB'
|
||||
% MATLAB does not generate properly cropped PDF files.
|
||||
% So, we generate EPS files that are converted later on.
|
||||
print(gcf, '-depsc2', reference_eps);
|
||||
|
||||
fixLineEndingsInWindows(reference_eps);
|
||||
|
||||
case 'Octave'
|
||||
% In Octave, figures are properly cropped when using print().
|
||||
print(reference_pdf, '-dpdf', '-S415,311', '-r150');
|
||||
pause(1.0)
|
||||
otherwise
|
||||
error('matlab2tikz:UnknownEnvironment', ...
|
||||
'Unknown environment. Need MATLAB(R) or GNU Octave.')
|
||||
end
|
||||
catch %#ok
|
||||
e = lasterror('reset'); %#ok
|
||||
[status.saveStage] = errorHandler(e);
|
||||
end
|
||||
status.saveStage.epsFile = reference_eps;
|
||||
status.saveStage.pdfFile = reference_pdf;
|
||||
status.saveStage.texReference = reference_fig;
|
||||
end
|
||||
% ==============================================================================
|
||||
function fixLineEndingsInWindows(filename)
|
||||
% On R2014b Win, line endings in .eps are Unix style (LF) instead of Windows
|
||||
% style (CR+LF). This causes problems in the MikTeX `epstopdf` for some files
|
||||
% as dicussed in:
|
||||
% * https://github.com/matlab2tikz/matlab2tikz/issues/370
|
||||
% * http://tex.stackexchange.com/questions/208179
|
||||
if ispc
|
||||
fid = fopen(filename,'r+');
|
||||
finally_fclose_fid = onCleanup(@() fclose(fid));
|
||||
testline = fgets(fid);
|
||||
CRLF = sprintf('\r\n');
|
||||
endOfLine = testline(end-1:end);
|
||||
if ~strcmpi(endOfLine, CRLF)
|
||||
endOfLine = testline(end); % probably an LF
|
||||
|
||||
% Rewind, read the whole
|
||||
fseek(fid,0,'bof');
|
||||
str = fread(fid,'*char')';
|
||||
|
||||
% Replace, overwrite and close
|
||||
str = strrep(str, endOfLine, CRLF);
|
||||
fseek(fid,0,'bof');
|
||||
fprintf(fid,'%s',str);
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,43 @@
|
||||
function [status] = execute_tikz_stage(status, ipp)
|
||||
% test stage: TikZ file generation
|
||||
testNumber = status.index;
|
||||
datapath = fullfile(ipp.Results.output,'data','converted');
|
||||
gen_tex = fullfile(datapath, sprintf('test%d-converted.tex', testNumber));
|
||||
% the value below is for inclusion into LaTeX report! Use UNIX convention.
|
||||
gen_pdf = sprintf('data/converted/test%d-converted.pdf', testNumber);
|
||||
cleanfigure_time = NaN;
|
||||
m2t_time = NaN;
|
||||
|
||||
% now, test matlab2tikz
|
||||
try
|
||||
%TODO: remove this once text removal has been removed
|
||||
oldWarn = warning('off','cleanfigure:textRemoval');
|
||||
|
||||
cleanfigure_time = tic;
|
||||
cleanfigure(status.extraCleanfigureOptions{:});
|
||||
cleanfigure_time = toc(cleanfigure_time);
|
||||
|
||||
warning(oldWarn);
|
||||
|
||||
m2t_time = tic;
|
||||
matlab2tikz('filename', gen_tex, ...
|
||||
'showInfo', false, ...
|
||||
'checkForUpdates', false, ...
|
||||
'dataPath', datapath, ...
|
||||
'standalone', true, ...
|
||||
ipp.Results.extraOptions{:}, ...
|
||||
status.extraOptions{:} ...
|
||||
);
|
||||
m2t_time = toc(m2t_time);
|
||||
catch %#ok
|
||||
e = lasterror('reset'); %#ok
|
||||
% Remove (corrupted) output file. This is necessary to avoid that the
|
||||
% Makefile tries to compile it and fails.
|
||||
delete(gen_tex)
|
||||
[status.tikzStage] = errorHandler(e);
|
||||
end
|
||||
status.tikzStage.texFile = gen_tex;
|
||||
status.tikzStage.pdfFile = gen_pdf;
|
||||
status.tikzStage.m2t_time = m2t_time;
|
||||
status.tikzStage.cleanfigure_time = cleanfigure_time;
|
||||
end
|
||||
@@ -0,0 +1,15 @@
|
||||
function [status] = execute_type_stage(status, ipp)
|
||||
try
|
||||
filename = status.tikzStage.texFile;
|
||||
stream = 1; % stdout
|
||||
if errorHasOccurred(status) && exist(filename, 'file')
|
||||
shortname = strrep(filename, m2troot, '$(M2TROOT)');
|
||||
fprintf(stream, '\n%%%%%%%% BEGIN FILE "%s" %%%%%%%%\n', shortname);
|
||||
type(filename);
|
||||
fprintf(stream, '\n%%%%%%%% END FILE "%s" %%%%%%%%\n', shortname);
|
||||
end
|
||||
catch
|
||||
e = lasterror('reset');
|
||||
[status.typeStage] = errorHandler(e);
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,10 @@
|
||||
function [status] = fillStruct(status, defaultStatus)
|
||||
% fills non-existant fields of |data| with those of |defaultData|
|
||||
fields = fieldnames(defaultStatus);
|
||||
for iField = 1:numel(fields)
|
||||
field = fields{iField};
|
||||
if ~isfield(status,field)
|
||||
status.(field) = defaultStatus.(field);
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,25 @@
|
||||
function [env, versionString] = getEnvironment()
|
||||
% Determine environment (Octave, MATLAB) and version string
|
||||
% TODO: Unify private `getEnvironment` functions
|
||||
persistent cache
|
||||
|
||||
if isempty(cache)
|
||||
isOctave = exist('OCTAVE_VERSION', 'builtin') ~= 0;
|
||||
if isOctave
|
||||
env = 'Octave';
|
||||
versionString = OCTAVE_VERSION;
|
||||
else
|
||||
env = 'MATLAB';
|
||||
vData = ver(env);
|
||||
versionString = vData.Version;
|
||||
end
|
||||
|
||||
% store in cache
|
||||
cache.env = env;
|
||||
cache.versionString = versionString;
|
||||
|
||||
else
|
||||
env = cache.env;
|
||||
versionString = cache.versionString;
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,5 @@
|
||||
function stages = getStagesFromStatus(status)
|
||||
% retrieves the different (names of) stages of a status struct
|
||||
fields = fieldnames(status);
|
||||
stages = fields(cellfun(@(f) ~isempty(strfind(f,'Stage')), fields));
|
||||
end
|
||||
@@ -0,0 +1,13 @@
|
||||
function bool = hasTestFailed(status)
|
||||
% returns true when the test has failed
|
||||
|
||||
if iscell(status) % allow for vectorization of the call
|
||||
bool = cellfun(@hasTestFailed, status, 'UniformOutput', true);
|
||||
else
|
||||
stages = getStagesFromStatus(status);
|
||||
bool = false;
|
||||
for jStage = 1:numel(stages)
|
||||
bool = bool || status.(stages{jStage}).error;
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,55 @@
|
||||
function filename = hashTableName(suite)
|
||||
% determines the file name of a hash table
|
||||
%
|
||||
% The MD5 file is assumed to be in the same directory as the test suite.
|
||||
% It has a file name "$SUITE.$ENV.$VER.md5"
|
||||
% where the following fields are filled:
|
||||
% $ENV: the environment (either "MATLAB" or "Octave")
|
||||
% $VER: the version (e.g. "3.8.0" for Octave, "8.3" for MATLAB 2014a)
|
||||
% $SUITE: the name (and path) of the test suite
|
||||
%
|
||||
% For the $VER-part, a fall-back mechanism is present that prefers the exact
|
||||
% version but will use the closest available file if such file does not
|
||||
% exist.
|
||||
[pathstr,name, ext] = fileparts(which(func2str(suite)));
|
||||
[env, version] = getEnvironment();
|
||||
ext = sprintf('.%s.%s.md5', env, version);
|
||||
relFilename = [name ext];
|
||||
filename = fullfile(pathstr, relFilename);
|
||||
|
||||
if ~exist(filename,'file')
|
||||
% To avoid having to create a file for each release of the environment,
|
||||
% also other versions are tried. The file for different releases are checked
|
||||
% in the following order:
|
||||
% 1. the currently running version (handled above!)
|
||||
% 2. the newest older version (e.g. use R2014b's file in R2015a)
|
||||
% 3. the oldest newer version (e.g. use R2014a's file in R2013a)
|
||||
pattern = sprintf('%s.%s.*.md5', name, env);
|
||||
candidates = dir(fullfile(pathstr, pattern));
|
||||
|
||||
% We just need the file names.
|
||||
filenames = arrayfun(@(c)c.name, candidates, 'UniformOutput', false);
|
||||
|
||||
% Add the expected version to the results, and sort the names by
|
||||
% version (this is the same as alphabetically).
|
||||
filenames = sort([filenames; {relFilename}]);
|
||||
nFiles = numel(filenames);
|
||||
iCurrent = find(ismember(filenames, relFilename));
|
||||
% determine the fall-back candidates:
|
||||
iNewestOlder = iCurrent - 1;
|
||||
iOldestNewer = iCurrent + 1;
|
||||
|
||||
inRange = @(idx)(idx <= nFiles && idx >= 1);
|
||||
if inRange(iNewestOlder)
|
||||
% use the newest older version
|
||||
relFilename = filenames{iNewestOlder};
|
||||
elseif inRange(iOldestNewer)
|
||||
% use the oldest newer version
|
||||
relFilename = filenames{iOldestNewer};
|
||||
else
|
||||
% use the exact version anyhow
|
||||
end
|
||||
|
||||
filename = fullfile(pathstr, relFilename);
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,99 @@
|
||||
function [orig] = initializeGlobalState()
|
||||
% Initialize global state. Set working directory and various properties of
|
||||
% the graphical root to ensure reliable output of the ACID testsuite.
|
||||
% See #542 and #552
|
||||
%
|
||||
% 1. Working directory
|
||||
% 2. Bring get(0,'Default') in line with get(0,'Factory')
|
||||
% 3. Set specific properties, required by matlab2tikz
|
||||
fprintf('Initialize global state...\n');
|
||||
orig = struct();
|
||||
|
||||
%--- Extract user defined default properties and set factory state
|
||||
default = get(0,'Default');
|
||||
factory = get(0,'Factory');
|
||||
|
||||
f = fieldnames(default); % fields of user's default state
|
||||
for i = 1:length(f)
|
||||
factory_property_name = strrep(f{i},'default','factory');
|
||||
factory_property_value = factory.(factory_property_name);
|
||||
orig.(f{i}).val = ...
|
||||
swapPropertyState(0, f{i}, factory_property_value);
|
||||
end
|
||||
|
||||
%--- Define desired global state properties
|
||||
% defaultAxesColorOrder: on HG1 'default' and 'factory' differ and
|
||||
% HG1 differs from HG2. Consequently use HG2 colors (the new standard).
|
||||
new.defaultAxesColorOrder.val = [0.000 0.447 0.741; ...
|
||||
0.850 0.325 0.098; ...
|
||||
0.929 0.694 0.125; ...
|
||||
0.494 0.184 0.556; ...
|
||||
0.466 0.674 0.188; ...
|
||||
0.301 0.745 0.933; ...
|
||||
0.635 0.0780 0.184];
|
||||
new.defaultAxesColorOrder.ignore= false;
|
||||
|
||||
% defaultFigurePosition: width and height influence cleanfigure() and
|
||||
% the number/location of axis ticks
|
||||
new.defaultFigurePosition.val = [300,200,560,420];
|
||||
new.defaultFigurePosition.ignore= false;
|
||||
|
||||
% ScreenPixelsPerInch: TODO: determine, if necessary
|
||||
% (probably needed for new line simplification algorithm)
|
||||
% not possible in octave
|
||||
new.ScreenPixelsPerInch.val = 96;
|
||||
new.ScreenPixelsPerInch.ignore = strcmpi(getEnvironment,'octave');
|
||||
|
||||
% MATLAB's factory values differ from their default values of a clean
|
||||
% MATLAB installation (observed on R2014a, Linux)
|
||||
new.defaultAxesColor.val = [1 1 1];
|
||||
new.defaultAxesColor.ignore = false;
|
||||
new.defaultLineColor.val = [0 0 0];
|
||||
new.defaultLineColor.ignore = false;
|
||||
new.defaultTextColor.val = [0 0 0];
|
||||
new.defaultTextColor.ignore = false;
|
||||
new.defaultAxesXColor.val = [0 0 0];
|
||||
new.defaultAxesXColor.ignore = false;
|
||||
new.defaultAxesYColor.val = [0 0 0];
|
||||
new.defaultAxesYColor.ignore = false;
|
||||
new.defaultAxesZColor.val = [0 0 0];
|
||||
new.defaultAxesZColor.ignore = false;
|
||||
new.defaultFigureColor.val = [0.8 0.8 0.8];
|
||||
new.defaultFigureColor.ignore = false;
|
||||
new.defaultPatchEdgeColor.val = [0 0 0];
|
||||
new.defaultPatchEdgeColor.ignore = false;
|
||||
new.defaultPatchFaceColor.val = [0 0 0];
|
||||
new.defaultPatchFaceColor.ignore = false;
|
||||
new.defaultFigurePaperType.val = 'A4';
|
||||
new.defaultFigurePaperType.ignore = false;
|
||||
new.defaultFigurePaperSize.val = [20.9840 29.6774];
|
||||
new.defaultFigurePaperSize.ignore = false;
|
||||
new.defaultFigurePaperUnits.val = 'centimeters';
|
||||
new.defaultFigurePaperUnits.ignore = false;
|
||||
|
||||
%--- Extract relevant properties and set desired state
|
||||
f = fieldnames(new); % fields of new state
|
||||
for i = 1:length(f)
|
||||
% ignore property on specified environments
|
||||
if ~new.(f{i}).ignore
|
||||
val = swapPropertyState(0, f{i}, new.(f{i}).val);
|
||||
|
||||
% store original value only, if not set by user's defaults
|
||||
if ~isfield(orig,f{i})
|
||||
orig.(f{i}).val = val;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
% =========================================================================
|
||||
function old = swapPropertyState(h, property, new)
|
||||
% read current property of graphical object
|
||||
% set new value, if not empty
|
||||
if nargin < 3, new = []; end
|
||||
|
||||
old = get(h, property);
|
||||
|
||||
if ~isempty(new)
|
||||
set(h, property, new);
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,19 @@
|
||||
function hashTable = loadHashTable(suite)
|
||||
% loads a reference hash table from disk
|
||||
hashTable.suite = suite;
|
||||
hashTable.contents = struct();
|
||||
filename = hashTableName(suite);
|
||||
if exist(filename, 'file')
|
||||
fid = fopen(filename, 'r');
|
||||
finally_fclose_fid = onCleanup(@() fclose(fid));
|
||||
|
||||
data = textscan(fid, '%s : %s');
|
||||
if ~isempty(data) && ~all(cellfun(@isempty, data))
|
||||
functions = cellfun(@strtrim, data{1},'UniformOutput', false);
|
||||
hashes = cellfun(@strtrim, data{2},'UniformOutput', false);
|
||||
for iFunc = 1:numel(functions)
|
||||
hashTable.contents.(functions{iFunc}) = hashes{iFunc};
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,30 @@
|
||||
function rootpath = m2troot(varargin)
|
||||
% M2TROOT produces paths inside the matlab2tikz repository
|
||||
%
|
||||
% Usage:
|
||||
% There are two ways to call this function, the base syntax is:
|
||||
%
|
||||
% * rootpath = m2troot()
|
||||
%
|
||||
% where |rootpath| points towards the root of the repository.
|
||||
%
|
||||
% The other syntax:
|
||||
%
|
||||
% * path = m2troot(...)
|
||||
%
|
||||
% is equivalent to |fullfile(m2troot, ...)| and as such allows to
|
||||
% easily produce a path to any file within the repository.
|
||||
|
||||
m2t = which('matlab2tikz');
|
||||
if isempty(m2t)
|
||||
error('M2TRoot:NotFound', 'Matlab2tikz was not found on the PATH!')
|
||||
end
|
||||
|
||||
[srcpath] = fileparts(m2t); % this should be $(m2troot)/src
|
||||
[rootpath, srcdir] = fileparts(srcpath); % this should be $(m2troot)
|
||||
assert(strcmpi(srcdir,'src'));
|
||||
|
||||
if nargin >= 1
|
||||
rootpath = fullfile(rootpath, varargin{:});
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,24 @@
|
||||
function [ newstr ] = m2tstrjoin( cellstr, delimiter )
|
||||
%M2TSTRJOIN This function joins a cellstr with a separator
|
||||
%
|
||||
% This is an alternative implementation for MATLAB's `strjoin`, since that
|
||||
% one is not available before R2013a.
|
||||
%
|
||||
% See also: strjoin
|
||||
|
||||
%TODO: Unify the private `m2tstrjoin` functions
|
||||
%FIXME: differs from src/private/m2tstrjoin in functionality !!!
|
||||
|
||||
nElem = numel(cellstr);
|
||||
if nElem == 0
|
||||
newstr = '';
|
||||
return % m2tstrjoin({}, ...) -> ''
|
||||
end
|
||||
|
||||
newstr = cell(2,nElem);
|
||||
newstr(1,:) = reshape(cellstr, 1, nElem);
|
||||
newstr(2,1:nElem-1) = {delimiter}; % put delimiters in-between the elements
|
||||
newstr(2, end) = {''}; % for Octave 4 compatibility
|
||||
newstr = [newstr{:}];
|
||||
|
||||
end
|
||||
@@ -0,0 +1,11 @@
|
||||
function restoreGlobalState(orig)
|
||||
% Restore original properties of global state.
|
||||
% See #542 and #552
|
||||
fprintf('Restore global state...\n');
|
||||
|
||||
% Restore relevant properties
|
||||
state_fields = fieldnames(orig);
|
||||
for i = 1:length(state_fields)
|
||||
set(0, state_fields{i}, orig.(state_fields{i}).val);
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,10 @@
|
||||
function [passedTests, failedTests, skippedTests] = splitPassFailSkippedTests(status)
|
||||
% splits tests between passed, failed and skippedtests
|
||||
skipped = cellfun(@(s) s.skip, status);
|
||||
status_notSkipped = status(~skipped);
|
||||
failed = hasTestFailed(status_notSkipped);
|
||||
|
||||
passedTests = status_notSkipped(~failed);
|
||||
failedTests = status_notSkipped(failed);
|
||||
skippedTests = status(skipped);
|
||||
end
|
||||
@@ -0,0 +1,7 @@
|
||||
function [reliableTests, unreliableTests] = splitUnreliableTests(status)
|
||||
% splits tests between reliable and unreliable tests
|
||||
knownToFail = cellfun(@(s)s.unreliable, status);
|
||||
|
||||
unreliableTests = status( knownToFail);
|
||||
reliableTests = status(~knownToFail);
|
||||
end
|
||||
@@ -0,0 +1,146 @@
|
||||
function [status, parameters] = testMatlab2tikz(varargin)
|
||||
%TESTMATLAB2TIKZ unit test driver for matlab2tikz
|
||||
%
|
||||
% This function should NOT be called directly by the user (or even developer).
|
||||
% If you are a developer, please use some of the following functions instead:
|
||||
% * `testHeadless`
|
||||
% * `testGraphical`
|
||||
%
|
||||
% The following arguments are supported, also for the functions above.
|
||||
%
|
||||
% TESTMATLAB2TIKZ('testFunctionIndices', INDICES, ...) or
|
||||
% TESTMATLAB2TIKZ(INDICES, ...) runs the test only for the specified
|
||||
% indices. When empty, all tests are run. (Default: []).
|
||||
%
|
||||
% TESTMATLAB2TIKZ('extraOptions', {'name',value, ...}, ...)
|
||||
% passes the cell array of options to MATLAB2TIKZ. Default: {}
|
||||
%
|
||||
% TESTMATLAB2TIKZ('figureVisible', LOGICAL, ...)
|
||||
% plots the figure visibly during the test process. Default: false
|
||||
%
|
||||
% TESTMATLAB2TIKZ('testsuite', FUNCTION_HANDLE, ...)
|
||||
% Determines which test suite is to be run. Default: @ACID
|
||||
% A test suite is a function that takes a single integer argument, which:
|
||||
% when 0: returns a cell array containing the N function handles to the tests
|
||||
% when >=1 and <=N: runs the appropriate test function
|
||||
% when >N: throws an error
|
||||
%
|
||||
% TESTMATLAB2TIKZ('output', DIRECTORY, ...)
|
||||
% Sets the output directory where the output files are places.
|
||||
% The default directory is $M2TROOT/test/output/current
|
||||
%
|
||||
% See also matlab2tikz, ACID
|
||||
|
||||
% In which environment are we?
|
||||
env = getEnvironment();
|
||||
|
||||
% -----------------------------------------------------------------------
|
||||
ipp = m2tInputParser;
|
||||
|
||||
ipp = ipp.addOptional(ipp, 'testFunctionIndices', [], @isfloat);
|
||||
ipp = ipp.addParamValue(ipp, 'extraOptions', {}, @iscell);
|
||||
ipp = ipp.addParamValue(ipp, 'figureVisible', false, @islogical);
|
||||
ipp = ipp.addParamValue(ipp, 'actionsToExecute', @(varargin) varargin{1}, @isFunction);
|
||||
ipp = ipp.addParamValue(ipp, 'testsuite', @ACID, @isFunction );
|
||||
ipp = ipp.addParamValue(ipp, 'output', m2troot('test','output','current'), @ischar);
|
||||
|
||||
ipp = ipp.parse(ipp, varargin{:});
|
||||
|
||||
ipp = sanitizeInputs(ipp);
|
||||
parameters = ipp.Results;
|
||||
|
||||
% -----------------------------------------------------------------------
|
||||
if strcmpi(env, 'Octave')
|
||||
if ~ipp.Results.figureVisible
|
||||
% Use the gnuplot backend to work around an fltk bug, see
|
||||
% <http://savannah.gnu.org/bugs/?43429>.
|
||||
graphics_toolkit gnuplot
|
||||
end
|
||||
|
||||
if ispc
|
||||
% Prevent three digit exponent on Windows Octave
|
||||
% See https://github.com/matlab2tikz/matlab2tikz/pull/602
|
||||
setenv ('PRINTF_EXPONENT_DIGITS', '2')
|
||||
end
|
||||
end
|
||||
|
||||
% copy output template into output directory
|
||||
if ~exist(ipp.Results.output,'dir')
|
||||
mkdir(ipp.Results.output);
|
||||
end
|
||||
template = m2troot('test','template');
|
||||
copyfile(fullfile(template,'*'), ipp.Results.output);
|
||||
|
||||
% start overall timing
|
||||
elapsedTimeOverall = tic;
|
||||
status = runIndicatedTests(ipp);
|
||||
|
||||
% print out overall timing
|
||||
elapsedTimeOverall = toc(elapsedTimeOverall);
|
||||
stdout = 1;
|
||||
fprintf(stdout, 'overall time: %4.2fs\n\n', elapsedTimeOverall);
|
||||
end
|
||||
% INPUT VALIDATION =============================================================
|
||||
function bool = isFunction(f)
|
||||
bool = isa(f,'function_handle');
|
||||
end
|
||||
function ipp = sanitizeInputs(ipp)
|
||||
% sanitize all input arguments
|
||||
ipp = sanitizeFunctionIndices(ipp);
|
||||
ipp = sanitizeFigureVisible(ipp);
|
||||
end
|
||||
function ipp = sanitizeFunctionIndices(ipp)
|
||||
% sanitize the passed function indices to the range of the test suite
|
||||
% query the number of test functions
|
||||
testsuite = ipp.Results.testsuite;
|
||||
n = length(testsuite(0));
|
||||
|
||||
if ~isempty(ipp.Results.testFunctionIndices)
|
||||
indices = ipp.Results.testFunctionIndices;
|
||||
% kick out the illegal stuff
|
||||
I = find(indices>=1 & indices<=n);
|
||||
indices = indices(I); %#ok
|
||||
else
|
||||
indices = 1:n;
|
||||
end
|
||||
ipp.Results.testFunctionIndices = indices;
|
||||
end
|
||||
function ipp = sanitizeFigureVisible(ipp)
|
||||
% sanitizes the figure visible option from boolean to ON/OFF
|
||||
if ipp.Results.figureVisible
|
||||
ipp.Results.figureVisible = 'on';
|
||||
else
|
||||
ipp.Results.figureVisible = 'off';
|
||||
end
|
||||
end
|
||||
% TEST RUNNER ==================================================================
|
||||
function status = runIndicatedTests(ipp)
|
||||
% run all indicated tests in the test suite
|
||||
% cell array to accomodate different structure
|
||||
indices = ipp.Results.testFunctionIndices;
|
||||
testsuite = ipp.Results.testsuite;
|
||||
testsuiteName = func2str(testsuite);
|
||||
stdout = 1;
|
||||
status = cell(length(indices), 1);
|
||||
|
||||
for k = 1:length(indices)
|
||||
testNumber = indices(k);
|
||||
|
||||
fprintf(stdout, 'Executing %s test no. %d...\n', testsuiteName, indices(k));
|
||||
|
||||
status{k} = emptyStatus(testsuite, testNumber);
|
||||
|
||||
elapsedTime = tic;
|
||||
|
||||
status{k} = feval(ipp.Results.actionsToExecute, status{k}, ipp);
|
||||
|
||||
elapsedTime = toc(elapsedTime);
|
||||
status{k}.elapsedTime = elapsedTime;
|
||||
fprintf(stdout, '%s ', status{k}.function);
|
||||
if status{k}.skip
|
||||
fprintf(stdout, 'skipped (%4.2fs).\n\n', elapsedTime);
|
||||
else
|
||||
fprintf(stdout, 'done (%4.2fs).\n\n', elapsedTime);
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,38 @@
|
||||
function statusAll = runMatlab2TikzTests(varargin)
|
||||
%% This file runs the complete MATLAB2TIKZ test suite.
|
||||
% It is mainly used for testing on a continuous integration server, but it can
|
||||
% also be used on a development machine.
|
||||
|
||||
CI_MODE = strcmpi(getenv('CONTINUOUS_INTEGRATION'),'true') || strcmp(getenv('CI'),'true');
|
||||
isJenkins = ~isempty(getenv('JENKINS_URL'));
|
||||
|
||||
%% Set path
|
||||
addpath(fullfile(pwd,'..','src'));
|
||||
addpath(fullfile(pwd,'suites'));
|
||||
|
||||
%% Select functions to run
|
||||
suite = @ACID;
|
||||
allTests = 1:numel(suite(0));
|
||||
|
||||
%% Prepare environment
|
||||
if strcmpi(getEnvironment(), 'Octave')
|
||||
% Ensure that paging is disabled
|
||||
% https://www.gnu.org/software/octave/doc/interpreter/Paging-Screen-Output.html
|
||||
more off
|
||||
end
|
||||
|
||||
%% Run tests
|
||||
status = testHeadless('testFunctionIndices', allTests,...
|
||||
'testsuite', suite, varargin{:});
|
||||
|
||||
if isJenkins
|
||||
makeTapReport(status, 'stream', 'results.test.tap');
|
||||
makeTravisReport(status, 'stream', 'results.test.md');
|
||||
end
|
||||
|
||||
nErrors = makeTravisReport(status);
|
||||
|
||||
%% Calculate exit code
|
||||
if CI_MODE
|
||||
exit(nErrors);
|
||||
end
|
||||
@@ -0,0 +1,164 @@
|
||||
function saveHashTable(status, varargin)
|
||||
% SAVEHASHTABLE saves the references hashes for the Matlab2Tikz tests
|
||||
%
|
||||
% Usage:
|
||||
% SAVEHASHTABLE(status)
|
||||
%
|
||||
% SAVEHASHTABLE(status, 'dryrun', BOOL, ...) determines whether or not to
|
||||
% write the constructed hash table to file (false) or to stdout (true).
|
||||
% Default: false
|
||||
%
|
||||
% SAVEHASHTABLE(status, 'removedTests', CHAR, ...) specifies which action to
|
||||
% execute on "removed tests" (i.e. test that have a hash recorded in the file,
|
||||
% but which are not present in `status`). Three values are possible:
|
||||
% - 'ask' (default): Ask what to do for each such test.
|
||||
% - 'remove': Remove the test from the file.
|
||||
% This is appropriate if the test has been removed from the suite.
|
||||
% - 'keep': Keep the test hash in the file.
|
||||
% This is appropriate when the test has not executed all tests.
|
||||
%
|
||||
% Inputs:
|
||||
% - status: output cell array of the testing functions
|
||||
%
|
||||
% See also: runMatlab2TikzTests, testMatlab2tikz
|
||||
ipp = m2tInputParser();
|
||||
ipp = ipp.addRequired(ipp, 'status', @iscell);
|
||||
ipp = ipp.addParamValue(ipp, 'dryrun', false, @islogical);
|
||||
ipp = ipp.addParamValue(ipp, 'removedTests', 'ask', @isValidAction);
|
||||
ipp = ipp.parse(ipp, status, varargin{:});
|
||||
|
||||
%% settings
|
||||
suite = status{1}.testsuite; %TODO: handle multiple test suites in a single array
|
||||
filename = hashTableName(suite);
|
||||
READFORMAT = '%s : %s';
|
||||
WRITEFORMAT = [READFORMAT '\n'];
|
||||
|
||||
%% process the hash table
|
||||
oldHashes = readHashesFromFile(filename);
|
||||
newHashes = updateHashesFromStatus(oldHashes, status);
|
||||
writeHashesToFile(filename, newHashes);
|
||||
|
||||
% --------------------------------------------------------------------------
|
||||
function hashes = updateHashesFromStatus(hashes, status)
|
||||
% update hashes from the test results in status
|
||||
oldFunctions = fieldnames(hashes);
|
||||
newFunctions = cellfun(@(s) s.function, status, 'UniformOutput', false);
|
||||
|
||||
% add hashes from all executed tests
|
||||
for iFunc = 1:numel(status)
|
||||
S = status{iFunc};
|
||||
thisFunc = S.function;
|
||||
thisHash = '';
|
||||
if isfield(S.hashStage,'found')
|
||||
thisHash = S.hashStage.found;
|
||||
elseif S.skip
|
||||
if isfield(hashes, thisFunc)
|
||||
% Test skipped, but reference hash present in file
|
||||
% Probably this means that the developer doesn't have access
|
||||
% to a certain toolbox.
|
||||
warning('SaveHashTable:CannotUpdateSkippedTest', ...
|
||||
'Test "%s" was skipped. Cannot update hash!',...
|
||||
thisFunc);
|
||||
else
|
||||
% Test skipped and reference hash absent.
|
||||
% Probably the test is skipped because something is tested
|
||||
% that relies on HG1/HG2/Octace-specific features and we are
|
||||
% in the wrong environment for the test.
|
||||
end
|
||||
else
|
||||
warning('SaveHashTable:NoHashFound',...
|
||||
'No hash found for "%s"!', thisFunc);
|
||||
end
|
||||
if ~isempty(thisHash)
|
||||
hashes.(thisFunc) = thisHash;
|
||||
end
|
||||
end
|
||||
|
||||
% ask what to do with tests for which we have a hash, but no test results
|
||||
removedTests = setdiff(oldFunctions, newFunctions);
|
||||
if ~isempty(removedTests)
|
||||
fprintf(1, 'Some tests in the file were not in the build status.\n');
|
||||
end
|
||||
for iTest = 1:numel(removedTests)
|
||||
thisTest = removedTests{iTest};
|
||||
|
||||
action = askActionToPerformOnRemovedTest(thisTest);
|
||||
switch action
|
||||
case 'remove'
|
||||
% useful for test that no longer exist
|
||||
fprintf(1, 'Removed hash for "%s"\n', thisTest);
|
||||
hashes = rmfield(hashes, thisTest);
|
||||
|
||||
case 'keep'
|
||||
% useful when not all tests were executed by the tester
|
||||
fprintf(1, 'Kept hash for "%s"\n', thisTest);
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
function action = askActionToPerformOnRemovedTest(testName)
|
||||
% ask which action to carry out on a removed test
|
||||
action = lower(ipp.Results.removedTests);
|
||||
while ~isActualAction(action)
|
||||
query = sprintf('Keep or remove "%s"? [Kr]:', testName);
|
||||
answer = strtrim(input(query,'s'));
|
||||
|
||||
if isempty(answer) || strcmpi(answer(1), 'K')
|
||||
action = 'keep';
|
||||
elseif strcmpi(answer(1), 'R')
|
||||
action = 'remove';
|
||||
else
|
||||
action = 'ask again';
|
||||
% just keep asking until we get a reasonable answer
|
||||
end
|
||||
end
|
||||
end
|
||||
function writeHashesToFile(filename, hashes)
|
||||
% write hashes to a file (or stdout when dry-running)
|
||||
if ~ipp.Results.dryrun
|
||||
fid = fopen(filename, 'w+');
|
||||
finally_fclose_fid = onCleanup(@() fclose(fid));
|
||||
else
|
||||
fid = 1; % Use stdout to print everything
|
||||
fprintf(fid, '\n\n Output: \n\n');
|
||||
end
|
||||
|
||||
funcNames = sort(fieldnames(hashes));
|
||||
for iFunc = 1:numel(funcNames)
|
||||
func = funcNames{iFunc};
|
||||
fprintf(fid, WRITEFORMAT, func, hashes.(func));
|
||||
end
|
||||
end
|
||||
function hashes = readHashesFromFile(filename)
|
||||
% read hashes from a file
|
||||
if exist(filename,'file')
|
||||
fid = fopen(filename, 'r');
|
||||
finally_fclose_fid = onCleanup(@() fclose(fid));
|
||||
|
||||
data = textscan(fid, READFORMAT);
|
||||
% data is now a cell array with 2 elements, each a (row) cell array
|
||||
% - the first is all the function names
|
||||
% - the second is all the hashes
|
||||
|
||||
% Transform `data` into {function1, hash1, function2, hash2, ...}'
|
||||
% First step is to transpose the data concatenate both fields under
|
||||
% each other. Since MATLAB indexing uses "column major order",
|
||||
% traversing the concatenated array is in the order we want.
|
||||
data = [data{:}]';
|
||||
allValues = data(:)';
|
||||
else
|
||||
allValues = {};
|
||||
end
|
||||
hashes = struct(allValues{:});
|
||||
end
|
||||
end
|
||||
% ==============================================================================
|
||||
function bool = isValidAction(str)
|
||||
% returns true for valid actions (keep/remove/ask) on "removedTests":
|
||||
bool = ismember(lower(str), {'keep','remove','ask'});
|
||||
end
|
||||
function bool = isActualAction(str)
|
||||
% returns true for actual actions (keep/remove) on "removedTests"
|
||||
bool = ismember(lower(str), {'keep','remove'});
|
||||
end
|
||||
% ==============================================================================
|
||||
@@ -0,0 +1,104 @@
|
||||
alphaImage : c1f655e08814b6737d14fc62401464d2
|
||||
alphaTest : 636ce0a35bfc181f47970031f00f6b72
|
||||
annotationAll : b600c6654bf983288dd25a24d17b277b
|
||||
annotationSubplots : c6c07fabe6ef6fc5fb4d0a00f3a98bd2
|
||||
annotationText : 0e479d484171cbe71208f132319a9dfb
|
||||
annotationTextUnits : 212301f6fab8fc44936a1d6c8dd3ac59
|
||||
areaPlot : 53cc00dd9f6059d734722dc7d521be39
|
||||
axesColors : 863530544e1bd5d2ac2a40d115b0d89c
|
||||
axesLocation : e7dac4ed9f58c31612496b3dd191b2fe
|
||||
bars : b6c9b6bd0884fd9041c50ce57486a730
|
||||
besselImage : 2478d41afe2dbb5e3c7c3ca35433df4b
|
||||
bodeplots : e58a307dacc26ad38259cff98c141352
|
||||
clownImage : 50cf1ed3d5954ea574ee1dcf850d2291
|
||||
colorbarLabelTitle : bb5e997230a6b1330c749d737b73f03b
|
||||
colorbarLogplot : 4cb17bffe972526eac63da33a9222f6d
|
||||
colorbarManualLocationLeftIn : 34c149317117365e93c2d4bc87342a36
|
||||
colorbarManualLocationLeftOut : 61df87739df57ce09e1ff941cede9b11
|
||||
colorbarManualLocationRightIn : 43929d243b1ce12aecfda3d130edf359
|
||||
colorbarManualLocationRightOut : ec8ed1290c5a3f45d4cb3795a66c0f1f
|
||||
colorbars : 271fdd43648c30b49861e5ac492bfe37
|
||||
compassplot : 746fe6816c8f5e91bc30b748937ddf5f
|
||||
contourPenny : bd9fe77201617c2aeec42680cf3db0cb
|
||||
croppedImage : a7df6401799a09cb2868babe95ce4c77
|
||||
customLegend : cd7e76a0e4394ae7e166b0a38c81be2b
|
||||
decayingharmonic : 5f430cbacf89268a100b9f0bc6b92874
|
||||
double_axes : b8d4a8ac79d6de3ff26a8e7b4e1f4cb2
|
||||
double_axes2 : 481f3f1c2e52f55a82193a39c6f8de28
|
||||
double_colorbar : 95740167b4b9fe7e082f5e6ff075b0f1
|
||||
errorBars : e156bb17b2c4938e683d1415cfd539b4
|
||||
errorBars2 : ca4bd1a1f0e835cb6628c92082534205
|
||||
fill3plot : 801300e07b52eb484e67abe761b6a0a4
|
||||
freqResponsePlot : d18c2174642550ca7373be8e207a43e7
|
||||
herrorbarPlot : f383b91e61b3fbc586b5c02ce2bafbfc
|
||||
hgTransformPlot : e32beea57daf9940ffd74ae8b1a83403
|
||||
hist3d : 867f35c157a81cf207d63e558cf167e5
|
||||
imageOrientation_PNG : c90e5e7bd1575ab8f504a8370a43a21e
|
||||
imageOrientation_inline : 9f8624bfd743ea0c3c19557e3b8319c5
|
||||
imagescplot : d1a7958ac53afd332e6fa934eee963f5
|
||||
imagescplot2 : fad5b247a605964440b150202d4c5a7a
|
||||
latexInterpreter : 061001fe023e6e404d4fe024ce28d245
|
||||
latexmath2 : 082e5416e213056d6ebe4a1bccd4286d
|
||||
legendplot : b005a57b62d43c3808abc57693090ddc
|
||||
legendplotBoxoff : a6552f6438efa5ae5c1e1b2bd3742d09
|
||||
legendsubplots : e656f45706bd476cf2401824d1014f8c
|
||||
linesWithOutliers : 0aa11947614995837eb1ce45265b45f5
|
||||
logbaseline : 23e4ebf3d9457aa26f940aca27fc32dd
|
||||
logicalImage : 843c396ce40a2c255d915b87b9b6bc53
|
||||
logplot : 15455204620fc850b94d721f1f79cacc
|
||||
mandrillImage : c3d5f63087be1e587af0f3b1f5efa573
|
||||
manualAlignment : a66a4d684ec5af5b3b967fbd9f9eba40
|
||||
many_random_points : 44f79b07c32fe2d334cb4d41bb245a2a
|
||||
markerSizes : c80e1e82fcd9d7cbcb52265cd966273b
|
||||
markerSizes2 : 2bc71206cca5fecdd89ee0ca6e7dec9a
|
||||
meshPlot : 390a65be331e6aeab8f4164b36b85e30
|
||||
mixedBarLine : 1562c32dfa41afadd5e890cc844ce139
|
||||
multiline_labels : 31fbbf1dcc63516bafa8479c14812706
|
||||
multipleAxes : c7c64c5f627f8633ee89ae02ba0b487e
|
||||
multiplePatches : d20f5bcb061e68e4e7848f2115d8589b
|
||||
myBoxplot : 1811640f9161ebbed0cec285ba423f7d
|
||||
overlappingPlots : 7e9618c8abc6eef40000202f12e201f8
|
||||
pColorPlot : edba1f3b39503095cace3d7053ad22a6
|
||||
parameterCurve3d : 79b6bfee183a996894c7964a023e312f
|
||||
parameterSurf : f65ce01c7e7a560205ee69e01d318b14
|
||||
peaks_contour : f6f964a8759939d5948e8fad796d481a
|
||||
peaks_contourf : 9e960b9d128dfbd102a8bbe2c5ab15ef
|
||||
pixelLegend : 3ac112865f3b1a50c62fb0b5f19d4215
|
||||
plain_cos : 9a8455b8cc710436572bc825de0cec78
|
||||
plotyyLegends : 9ed8515333235d8f84692a7d874e1d57
|
||||
polarplot : 35bcc693ce44029933edc6039ee4e652
|
||||
quiver3plot : 49ff594d23510463b75103fd099acf62
|
||||
quiveroverlap : 2e63a73822cc65d8086d90e23d52cbcf
|
||||
quiverplot : 7dbf0db4142bdbf7d421e83a66c149a5
|
||||
randomWithLines : 5227e4b38ad2503e9bae3ec6e566ac4a
|
||||
rectanglePlot : 0d9b3ef5dd01905fa987d81d139ec5fa
|
||||
removeOutsideMarker : c5c22d6ad18cb05dff6e0ef9bf0f20bf
|
||||
rlocusPlot : b2f0237a3bc42ca1f9305dc411437949
|
||||
roseplot : 3c61d3d9cd107a135ac958e3a2aa5d6c
|
||||
scatter3Plot : a3c58f7801a9cd7805a0bf888321d570
|
||||
scatterPlot : c7f71e9961a43df1047e938ff00f45cd
|
||||
scatterPlotMarkers : 4035e2da2a8e1ddeb4badeede264858c
|
||||
scatterPlotRandom : 60feab8df90afa2b60d79f98e98b58bc
|
||||
sine_with_annotation : a770a5ab9552941d0a663d7850785807
|
||||
sine_with_markers : 003c40a83b2dfaf7b6dfbcb9d74a505d
|
||||
spectro : 330dde4cc92550a49ea3df07455e6d9c
|
||||
spherePlot : 93eeb7042de0a8a18a59208d0e50df23
|
||||
stackedBarsWithOther : 708cb63f69815f47a31b9918c9c2c715
|
||||
stairsplot : 95ff3a04e9d5fec297d4b52dc895779d
|
||||
stemplot : e1d5c43f90a3c34b0c0463c10dcd8edd
|
||||
stemplot2 : 8cbf11bd5d2f388b4b572844f6960e60
|
||||
subplot2x2b : 71c072af504b2bb208c8d7743ae0e5a2
|
||||
subplotCustom : 606bc283da5b9c0319c4105910393050
|
||||
superkohle : 84ab937a68f0969598247b7b19b18cc3
|
||||
surfPlot : 652c4e1f83e0165199f952b8f1c412bb
|
||||
surfPlot2 : 026acc60aab65d0567052cbf870a9704
|
||||
texInterpreter : b67b59f407a551196fa1448d9c35e9e7
|
||||
texcolor : 7a8b8c01525fc11ac4f1186c803748a9
|
||||
texrandom : 4cc05e583bb3cfbc9884ed5f03f10e5a
|
||||
textAlignment : 6d51ee2120803e85237a57a25b6b43e7
|
||||
textext : 5be451a1b3314c54ee8ba519f6d2cae9
|
||||
xAxisReversed : 610fc5e22fa2c7efbdf788115cc7eb2d
|
||||
ylabels : 6daba91575bb4a6c2ff58d8d9a171526
|
||||
zoom : 4b140788bbd7c2e0f1a4d8b46640c9eb
|
||||
zplanePlot1 : 44a119eb5b2266b5e765bac21e6a488e
|
||||
zplanePlot2 : 95db146feb3d517f9e2540a551a50659
|
||||
@@ -0,0 +1,104 @@
|
||||
alphaImage : 14978e97c02baf045fb05ed6b4a5b391
|
||||
alphaTest : d194e2297b5dd5a0bb1282f9142ddda7
|
||||
annotationAll : 0a8a1578d17a16b3a5db57434069c6fc
|
||||
annotationSubplots : 30c06f8d5e3d30bbf1ccf8df29576f16
|
||||
annotationText : 9f293eb4bb31ac29c44d1c772b05ac74
|
||||
annotationTextUnits : 68f570a8fa1d3a0cec44ef2a1d58aa3b
|
||||
areaPlot : 3c36bd59014ca6346d6cbbbb6f78943a
|
||||
axesColors : 863530544e1bd5d2ac2a40d115b0d89c
|
||||
axesLocation : e7dac4ed9f58c31612496b3dd191b2fe
|
||||
bars : aa8ef10df99c7d750c92c7ba95a73814
|
||||
besselImage : c5a0696550fda36e7d2eba7d91643716
|
||||
bodeplots : a2d8208c81d7f449b51107907c43e053
|
||||
clownImage : 50cf1ed3d5954ea574ee1dcf850d2291
|
||||
colorbarLabelTitle : 3ff06d0ee178a052429194d184ee0182
|
||||
colorbarManualLocationLeftIn : fce39178f29dcdab800d6c99edc70bed
|
||||
colorbarManualLocationLeftOut : 0b35797bac696ec978b1dcac2c5baa20
|
||||
colorbarManualLocationRightIn : 776fbc67733cbd2104384d76de954eda
|
||||
colorbarManualLocationRightOut : fd1a74e61c95b0c185ac26d1cffee4a3
|
||||
colorbars : 0795ee171bf5954ff7e36d3ddc3867d5
|
||||
compassplot : bfdceefee37557845bbc0b4c7609ff50
|
||||
contourPenny : 11b3f1178d9585112b4d40f47a334de0
|
||||
croppedImage : c3a4a5e6ac11450d797c259a867dfd72
|
||||
customLegend : cc43f95e60cd8ff447c61fdebbaef18f
|
||||
decayingharmonic : 2d9be9791b36efc6e1d052769dba3369
|
||||
double_axes : af07a7caf0effe5eb70fd23f21137ebb
|
||||
double_axes2 : 6cd1b9ea3b7ae29801738674446e5f64
|
||||
double_colorbar : 47eaadfd2b100239e63c3175382c0598
|
||||
errorBars : 9a959889b00bdc80a18aae4cef6fff24
|
||||
errorBars2 : ee08727841633566b12ee1553f587b98
|
||||
fill3plot : 801300e07b52eb484e67abe761b6a0a4
|
||||
freqResponsePlot : f307eac45a335d76278beb4209b7f335
|
||||
herrorbarPlot : 9f7e3880d3d77af312f5af20ab45d427
|
||||
hgTransformPlot : 8c0a136c4bb0ec5ff02a344bc9ef9bf0
|
||||
hist3d : 867f35c157a81cf207d63e558cf167e5
|
||||
histogramPlot : a96b7898c7c426edc4d8ba680dd4b4c2
|
||||
imageOrientation_PNG : 94b2656bb5235d842d65085094f0dfc7
|
||||
imageOrientation_inline : 8f6b04de03cdc80a3ba1b5a35832e8a7
|
||||
imagescplot : d1a7958ac53afd332e6fa934eee963f5
|
||||
imagescplot2 : fad5b247a605964440b150202d4c5a7a
|
||||
latexInterpreter : 827313b6ff9dceb1ca27e814e5d7cc81
|
||||
latexmath2 : 5359827e1d218311bf80228f89deffdf
|
||||
legendplot : a61471a19448f4d097c3053de5d4ca13
|
||||
legendplotBoxoff : a6552f6438efa5ae5c1e1b2bd3742d09
|
||||
legendsubplots : 474a38fa9ddcf06bfab08a53ddc42032
|
||||
linesWithOutliers : 0aa11947614995837eb1ce45265b45f5
|
||||
logbaseline : 86f6627cae4fd5ca8891de0fff521ff4
|
||||
logicalImage : 843c396ce40a2c255d915b87b9b6bc53
|
||||
logplot : 5d5c676b2a3338558939d0407171edc6
|
||||
mandrillImage : c3d5f63087be1e587af0f3b1f5efa573
|
||||
manualAlignment : a66a4d684ec5af5b3b967fbd9f9eba40
|
||||
many_random_points : 44f79b07c32fe2d334cb4d41bb245a2a
|
||||
markerSizes : c80e1e82fcd9d7cbcb52265cd966273b
|
||||
markerSizes2 : 2bc71206cca5fecdd89ee0ca6e7dec9a
|
||||
meshPlot : 390a65be331e6aeab8f4164b36b85e30
|
||||
mixedBarLine : dfcba35ebc32c940566368ea83323add
|
||||
multiline_labels : d81ea3e1c07d9010027a40854f4e0e4d
|
||||
multipleAxes : c7c64c5f627f8633ee89ae02ba0b487e
|
||||
multiplePatches : e8a187bc7c133435cfad346eb7957a9d
|
||||
myBoxplot : abdb5d198d82e79940999cf61563099f
|
||||
overlappingPlots : 27f112e843ef7c8835cee164c70f2b1e
|
||||
pColorPlot : 0dbd6a9f0cc5dd2691d7d3767b831f68
|
||||
parameterCurve3d : 6aead7a8377449e056856f5b7d6fb9ed
|
||||
parameterSurf : 0bc50b54c2bff6e22ddf7e9a2a479f7c
|
||||
peaks_contour : 5e6873909d68b0e397c14eb2deb58e4f
|
||||
peaks_contourf : 8532510c96c15f96b9a8ad3843446c20
|
||||
pixelLegend : 3ac112865f3b1a50c62fb0b5f19d4215
|
||||
plain_cos : 3b0a06de2ae24b7242eef8840acfaca2
|
||||
plotyyLegends : 9ed8515333235d8f84692a7d874e1d57
|
||||
polarplot : e232124afee0fdf260dea1cdbb497275
|
||||
quiver3plot : 5dd5d89ff4c5d3de0c000a999814d10a
|
||||
quiveroverlap : f977afb99d073b7ea4a54bd7cc254300
|
||||
quiverplot : 95e36d3db46c861ccfcca981af846aa6
|
||||
randomWithLines : 9857814e260c4a929f5f0e9e92ba896d
|
||||
rectanglePlot : 0d9b3ef5dd01905fa987d81d139ec5fa
|
||||
removeOutsideMarker : f9330795ff85ba1ce4753a700825ab8c
|
||||
rlocusPlot : 03d2da6924f15785a9f803e0cbe88252
|
||||
roseplot : b095b86b171a56d817834d803e9e4b6a
|
||||
scatter3Plot : ed343b46e0c71f8b87b71bd32e645a17
|
||||
scatterPlot : 5d0b1fca0e65b2f8b16bfa5872f3ba1a
|
||||
scatterPlotMarkers : 4035e2da2a8e1ddeb4badeede264858c
|
||||
scatterPlotRandom : 60feab8df90afa2b60d79f98e98b58bc
|
||||
sine_with_annotation : 98cd4228e6a58210dc10768bc3d48298
|
||||
sine_with_markers : 003c40a83b2dfaf7b6dfbcb9d74a505d
|
||||
spectro : 954d57a5d3e0a6b71ed4b530295829c7
|
||||
spherePlot : a0728a993418536015482b6e2262f530
|
||||
stackedBarsWithOther : 24f65175516e4af409e0b5a344e69590
|
||||
stairsplot : 681cd9b7ec346c36ae53de4294148153
|
||||
stemplot : b20a8531bc0a24b7b9ed161e150c15ff
|
||||
stemplot2 : ce57617afde9d61311536fb018fc2ace
|
||||
subplot2x2b : 55c61c78e5b58bea889f6dc4c53cad8e
|
||||
subplotCustom : ebba99c098189a9e90a69925b4f842c2
|
||||
superkohle : 6f3903621fbfc0e52c6e5ef379e6cadc
|
||||
surfPlot : 4b3c88fd47161c784ce117e08e0a4c8c
|
||||
surfPlot2 : ea785ea64ce8763913edff0ff1846ed1
|
||||
texInterpreter : b67b59f407a551196fa1448d9c35e9e7
|
||||
texcolor : 7a8b8c01525fc11ac4f1186c803748a9
|
||||
texrandom : 111d9b06c1440d1ecf80df9498fb4daf
|
||||
textAlignment : 8b0a62113daf8ec03a711d1dc7f47e2b
|
||||
textext : 5be451a1b3314c54ee8ba519f6d2cae9
|
||||
xAxisReversed : 610fc5e22fa2c7efbdf788115cc7eb2d
|
||||
ylabels : 0f03d59d01b31956b87861e5705c28f2
|
||||
zoom : 731634a7fd3efbe0bfc72405614ae3fd
|
||||
zplanePlot1 : 4d974fa9a55b6298d0637654fd7d86ce
|
||||
zplanePlot2 : 6b7848acad9ce16f9d3ce303ff85cc17
|
||||
@@ -0,0 +1,87 @@
|
||||
alphaImage : a51ff2c6514fb5606ee2fcb732edc7ea
|
||||
alphaTest : bd2d78b8d373342d5285132b607a2f46
|
||||
annotationAll : 719ee5b81452f375afa95b757226f6ec
|
||||
annotationSubplots : aa261262dff0a1f26487d4a0f06cd828
|
||||
annotationText : c7185fe122b2e3fa5335fbc51bb89103
|
||||
annotationTextUnits : 1d29851134c715342efc36a690d5b396
|
||||
areaPlot : e04438af8498d2aa6fba5d242a8290ed
|
||||
axesColors : 45751a2a4fd30e0c888237721c0ae018
|
||||
axesLocation : 5189186c3185e8b3fa52622af950a0fd
|
||||
bars : 15a269e905602896394eabd367040ce1
|
||||
besselImage : 0ffc3e10adb87029b44cbeb4bc435e07
|
||||
colorbarLabelTitle : 272a4d2f645b296e43c01f4ab2ae25a4
|
||||
colorbarLogplot : cb326bbb54e486a40d387acfe82f1b72
|
||||
colorbarManualLocationLeftIn : d2d90ddaa56b9f13d009a595c21e9601
|
||||
colorbarManualLocationLeftOut : dea8de2bdf0d866dc3f4f2b8327ea494
|
||||
colorbarManualLocationRightIn : c8866d76fee1a0876cf3f46aa5bb5761
|
||||
colorbarManualLocationRightOut : 81b67065a6281c3de6c1a9181d4dfcbc
|
||||
colorbars : 13b6b31da1f9aef218ef68a6a2c4bbc5
|
||||
compassplot : 94efa27f5503d3a56e6b40a0ca0f75d1
|
||||
contourPenny : 3dab076bb0f089b4c30f321a8b732331
|
||||
customLegend : 7b0d1d80a2f72bc920d869151ffe96c1
|
||||
decayingharmonic : faaac45ba8f9262cf8a879323d3bf253
|
||||
double_axes : 243d26b1446d316955cded4098ef76df
|
||||
double_axes2 : 1fb2d96e2845da4935e251d2e860135c
|
||||
errorBars : 50b3272a0eff1a540911265dc86840e7
|
||||
errorBars2 : af50a7241d97ac9e2c78a4f157e056a2
|
||||
herrorbarPlot : aca7b04d007f2da41617eb027c15b0ef
|
||||
imageOrientation_PNG : 8086dd5610c028cf75501954cbaccf2c
|
||||
imageOrientation_inline : 02c0fb3e810aab39cb690e0fa3f8b7eb
|
||||
imagescplot : 88328b4f32c5ed1cc4e0ad09ea7f47cb
|
||||
imagescplot2 : 39ce8c49f28f3ce90a6bd5a9d0f1cd42
|
||||
latexInterpreter : e02f1a2468683a3893b0ba5622ba556d
|
||||
latexmath2 : 0453c91a38ab2e002b7744825c1aa0e9
|
||||
legendplot : 5f351094a8e4cd2192fe7cbb2859fd5c
|
||||
legendplotBoxoff : 9b2f5fb5630b53c4f7e0cbade5c8a719
|
||||
legendsubplots : 17c08345bafc58e1562984b37d4e01c9
|
||||
linesWithOutliers : 21dd1eb9763a12d1367a43f2e4314057
|
||||
logbaseline : 8d62e25d03732cdfc8cb2dd419e0b1b5
|
||||
logicalImage : 82e9e5ed998aa1ecd78b514d801dc914
|
||||
logplot : ecb205ea014ba6d0042579c3d608d978
|
||||
manualAlignment : 91b81ccba3a733f1660de692f1a24ead
|
||||
many_random_points : 465f2cfaf13757239404db65e9c49da8
|
||||
markerSizes : f0853e39d2cc6c67ca23306fdb32b6c0
|
||||
markerSizes2 : ee9ceeb6e9d413b80c070f267914f479
|
||||
meshPlot : 0ed5e09884b72b670f4d67b134f714f2
|
||||
mixedBarLine : 124b6efc0a9b4d350e0f179bdcc794c9
|
||||
multiline_labels : 113098f446ba5b37be05b2e495753a38
|
||||
multipleAxes : 33ea385933a0e54967fdfd2a763116d6
|
||||
multiplePatches : 5136db15994352b537d5261586efb68e
|
||||
overlappingPlots : 6372bbcaaf0f9831a9a371c154c68510
|
||||
pColorPlot : ea8de8ae9a060827a15589640a7c2af2
|
||||
parameterCurve3d : d74674982f8de1a07e2d91690442c640
|
||||
peaks_contour : a08b52735b11941aef4194d42c50ca95
|
||||
peaks_contourf : bae99cfb0c6d76fbb9eda7cf3253c861
|
||||
pixelLegend : 88bcddd20a3c5626ef158e2252685ec9
|
||||
plain_cos : 83d0268e8b3115003942bd1bdaf2672f
|
||||
plotyyLegends : 4195fadd2c55b022391f8addbbfc2dd5
|
||||
polarplot : a663c1b56d3073601536d4dacae5e8a0
|
||||
quiver3plot : 2262caf036feb9b926af20dccee4674d
|
||||
quiveroverlap : b565fbfd750ff33aa3e24500218458c4
|
||||
quiverplot : 5183781255b220415251eb7bcb5d8707
|
||||
randomWithLines : 152796f6be5be2a94832bfb5ea126483
|
||||
rectanglePlot : 0a6f4e29891fdd8492d821df65ed727f
|
||||
removeOutsideMarker : c26260549046c7a885617d03c1a6e714
|
||||
roseplot : 526bbf61758a3ac158b2f1de6a39de73
|
||||
scatter3Plot : 85a3d342f218f8ec4b0734bbefa13d0c
|
||||
scatterPlotMarkers : 5dada75b14206174059f357028f82de5
|
||||
scatterPlotRandom : a8bc3cbcd74de1e38783b974586d875d
|
||||
sine_with_annotation : 0b0f9823c6c36cae49d5053d8b984884
|
||||
sine_with_markers : d8761700c3dbfb3a496dc962c9d3ec64
|
||||
spherePlot : 42ab300428e3248d03105b83cac2b312
|
||||
stackedBarsWithOther : ac3c350f5af365630e0aaf4352108dd8
|
||||
stairsplot : 9338e729f5569578228a7bac2d123a9a
|
||||
stemplot : 557cad38e474e0cd7878b4680c33d291
|
||||
stemplot2 : 7450fcbc9332ecbd8ac9e801aad4d8fc
|
||||
subplot2x2b : 7db858e541e4edc35e9721226d8a0f5a
|
||||
subplotCustom : 588c7323ed9a6a69cbf71849a84d961f
|
||||
surfPlot : 5f6735d7f3ae960526c10335d3b232b6
|
||||
surfPlot2 : 30a4abfa8829ce6562f6bceb9e702b74
|
||||
texInterpreter : 64e4b7edcb6f21f14f3b60544a1f48bc
|
||||
texcolor : 8b5363038aa4454372cf03ae13f3a91a
|
||||
texrandom : f85439ecf43d7dc6f150a9977f1900ff
|
||||
textAlignment : 5e75059b1f661be10d3d790983f20f40
|
||||
textext : 730e7111a60f2f5fa0a9aa1a4445e242
|
||||
xAxisReversed : b7c279800afb84deb37cb9208a657a24
|
||||
ylabels : b7180ba11dd0428064340ab39935e9b1
|
||||
zoom : 7777afa78e6ee6169841ccd5a894c942
|
||||
@@ -0,0 +1,87 @@
|
||||
alphaImage : a51ff2c6514fb5606ee2fcb732edc7ea
|
||||
alphaTest : 0aabea57e8351373e2c3090fa1929435
|
||||
annotationAll : 5139104b005a70d3650c6dedb8f1dc7e
|
||||
annotationSubplots : 3da2ff3cadd2167ab1726c88f18a8a63
|
||||
annotationText : efe23b1567345ec24564b598c0d2c146
|
||||
annotationTextUnits : 0c874e12ee2167ffe041b48ab2124417
|
||||
areaPlot : cdb88d8449ea9275c7eeed21c236e055
|
||||
axesColors : 45751a2a4fd30e0c888237721c0ae018
|
||||
axesLocation : 27dd4473cb5871188a20d7e6cbc0d171
|
||||
bars : 15a269e905602896394eabd367040ce1
|
||||
besselImage : 0ffc3e10adb87029b44cbeb4bc435e07
|
||||
colorbarLabelTitle : 272a4d2f645b296e43c01f4ab2ae25a4
|
||||
colorbarLogplot : cb326bbb54e486a40d387acfe82f1b72
|
||||
colorbarManualLocationLeftIn : d2d90ddaa56b9f13d009a595c21e9601
|
||||
colorbarManualLocationLeftOut : dea8de2bdf0d866dc3f4f2b8327ea494
|
||||
colorbarManualLocationRightIn : c8866d76fee1a0876cf3f46aa5bb5761
|
||||
colorbarManualLocationRightOut : 81b67065a6281c3de6c1a9181d4dfcbc
|
||||
colorbars : 13b6b31da1f9aef218ef68a6a2c4bbc5
|
||||
compassplot : 94efa27f5503d3a56e6b40a0ca0f75d1
|
||||
contourPenny : fbd639280f4c31dcce7d463e4eac27f4
|
||||
customLegend : 7b0d1d80a2f72bc920d869151ffe96c1
|
||||
decayingharmonic : a5551e12b79edd8f32bd5d91ae5fa561
|
||||
double_axes : 125855bab62dbd8a599bfb6d9d2a041f
|
||||
double_axes2 : 6cd1b9ea3b7ae29801738674446e5f64
|
||||
errorBars : 5d31dee2340e12e5b48aad2d93f89b3f
|
||||
errorBars2 : 85a015a7afc2c6a7046053c887cce43a
|
||||
herrorbarPlot : f2eaee609ad23ad02d03e78912a5f23a
|
||||
imageOrientation_PNG : 8086dd5610c028cf75501954cbaccf2c
|
||||
imageOrientation_inline : 02c0fb3e810aab39cb690e0fa3f8b7eb
|
||||
imagescplot : 88328b4f32c5ed1cc4e0ad09ea7f47cb
|
||||
imagescplot2 : 39ce8c49f28f3ce90a6bd5a9d0f1cd42
|
||||
latexInterpreter : 73b51aed59a6644c15f1561e51ecbf6d
|
||||
latexmath2 : 5359827e1d218311bf80228f89deffdf
|
||||
legendplot : 5f351094a8e4cd2192fe7cbb2859fd5c
|
||||
legendplotBoxoff : 2654de1ee49ac8f4d2546eb6f254952f
|
||||
legendsubplots : 17c08345bafc58e1562984b37d4e01c9
|
||||
linesWithOutliers : 0aa11947614995837eb1ce45265b45f5
|
||||
logbaseline : f23182b1e230b1b21244ad9364475863
|
||||
logicalImage : 82e9e5ed998aa1ecd78b514d801dc914
|
||||
logplot : 5d5c676b2a3338558939d0407171edc6
|
||||
manualAlignment : ff6a5307120276310c01fb6f9c223d77
|
||||
many_random_points : 46b09dca92fc4f2517a198427f44b874
|
||||
markerSizes : e0d2628d90419f38457b7ee71d178bb1
|
||||
markerSizes2 : 560cc9e62fe361aa5456ef87fb715649
|
||||
meshPlot : 390a65be331e6aeab8f4164b36b85e30
|
||||
mixedBarLine : 124b6efc0a9b4d350e0f179bdcc794c9
|
||||
multiline_labels : 113098f446ba5b37be05b2e495753a38
|
||||
multipleAxes : c7c64c5f627f8633ee89ae02ba0b487e
|
||||
multiplePatches : 4d77a30b4a6b14772505e0e9c2a727cf
|
||||
overlappingPlots : 714f8029c2ad4fc86a8fb5323f35b0e4
|
||||
pColorPlot : ce623ad5a9ebf4b3c74d5954027f0631
|
||||
parameterCurve3d : ce2a304c64eb5283a40779f6f410d6ba
|
||||
peaks_contour : a08b52735b11941aef4194d42c50ca95
|
||||
peaks_contourf : bfe49f12ff8710df9fbf6bd9672ca124
|
||||
pixelLegend : 2afe53d2be6f01a41b74c5bd892fda83
|
||||
plain_cos : defebe18ad95f9f1b1f823ad96bd12bd
|
||||
plotyyLegends : 96cb3c09f470251db4ddf24f59e8e9f4
|
||||
polarplot : a663c1b56d3073601536d4dacae5e8a0
|
||||
quiver3plot : 5dd5d89ff4c5d3de0c000a999814d10a
|
||||
quiveroverlap : f446d413254f3f1e8e4ec449b8a7f813
|
||||
quiverplot : 22d70477697462b313c3d56ef78ac9c8
|
||||
randomWithLines : e96d8488671951033bc98d94163a06cb
|
||||
rectanglePlot : 045df69771942ea322873279a61c7b9f
|
||||
removeOutsideMarker : f0606cd40ecafc645b10b706d84aa874
|
||||
roseplot : 526bbf61758a3ac158b2f1de6a39de73
|
||||
scatter3Plot : c9cc13e983b56272dcbb3c90edd1f8c1
|
||||
scatterPlotMarkers : a5ec68437ee9e103ec849bdd1ab6657c
|
||||
scatterPlotRandom : 3dc985fcb9773a82a156321e12e6460b
|
||||
sine_with_annotation : 0b0f9823c6c36cae49d5053d8b984884
|
||||
sine_with_markers : 2cf4b72e72482e4b192012c4165ef5b5
|
||||
spherePlot : 5b0e48733101f43996cc70c2962b52d8
|
||||
stackedBarsWithOther : ac3c350f5af365630e0aaf4352108dd8
|
||||
stairsplot : 73051cf170b77661c4ea464718af1ded
|
||||
stemplot : fcf6f58d74e51684f5aedd090506b562
|
||||
stemplot2 : 7450fcbc9332ecbd8ac9e801aad4d8fc
|
||||
subplot2x2b : 7db858e541e4edc35e9721226d8a0f5a
|
||||
subplotCustom : 14bbb2edbd657c7386139bfd7085f8c9
|
||||
surfPlot : 2aadedca0c9e2fe866252a5969fdd08a
|
||||
surfPlot2 : 30a4abfa8829ce6562f6bceb9e702b74
|
||||
texInterpreter : b67b59f407a551196fa1448d9c35e9e7
|
||||
texcolor : 7a8b8c01525fc11ac4f1186c803748a9
|
||||
texrandom : 4dacf9590338ff73553c4a82a78e09bf
|
||||
textAlignment : 5e75059b1f661be10d3d790983f20f40
|
||||
textext : 5be451a1b3314c54ee8ba519f6d2cae9
|
||||
xAxisReversed : 1448dd92ba4ca7c492f060e3d585d340
|
||||
ylabels : 9e68a9002553bcfe576a22d60ec7c5e9
|
||||
zoom : 7777afa78e6ee6169841ccd5a894c942
|
||||
@@ -0,0 +1,87 @@
|
||||
alphaImage : a51ff2c6514fb5606ee2fcb732edc7ea
|
||||
alphaTest : 0aabea57e8351373e2c3090fa1929435
|
||||
annotationAll : 5139104b005a70d3650c6dedb8f1dc7e
|
||||
annotationSubplots : 3da2ff3cadd2167ab1726c88f18a8a63
|
||||
annotationText : efe23b1567345ec24564b598c0d2c146
|
||||
annotationTextUnits : 0c874e12ee2167ffe041b48ab2124417
|
||||
areaPlot : cdb88d8449ea9275c7eeed21c236e055
|
||||
axesColors : 45751a2a4fd30e0c888237721c0ae018
|
||||
axesLocation : 27dd4473cb5871188a20d7e6cbc0d171
|
||||
bars : 15a269e905602896394eabd367040ce1
|
||||
besselImage : 0ffc3e10adb87029b44cbeb4bc435e07
|
||||
colorbarLabelTitle : 272a4d2f645b296e43c01f4ab2ae25a4
|
||||
colorbarLogplot : cb326bbb54e486a40d387acfe82f1b72
|
||||
colorbarManualLocationLeftIn : d2d90ddaa56b9f13d009a595c21e9601
|
||||
colorbarManualLocationLeftOut : dea8de2bdf0d866dc3f4f2b8327ea494
|
||||
colorbarManualLocationRightIn : c8866d76fee1a0876cf3f46aa5bb5761
|
||||
colorbarManualLocationRightOut : 81b67065a6281c3de6c1a9181d4dfcbc
|
||||
colorbars : 13b6b31da1f9aef218ef68a6a2c4bbc5
|
||||
compassplot : 94efa27f5503d3a56e6b40a0ca0f75d1
|
||||
contourPenny : fbd639280f4c31dcce7d463e4eac27f4
|
||||
customLegend : 7b0d1d80a2f72bc920d869151ffe96c1
|
||||
decayingharmonic : a5551e12b79edd8f32bd5d91ae5fa561
|
||||
double_axes : 125855bab62dbd8a599bfb6d9d2a041f
|
||||
double_axes2 : 6cd1b9ea3b7ae29801738674446e5f64
|
||||
errorBars : 52e1abac8c4ba10d9427cebc9e6845db
|
||||
errorBars2 : c0750114ad1821a37a833e378217ef5b
|
||||
herrorbarPlot : 92c6a3ebd7e6194362b31117b1e52d92
|
||||
imageOrientation_PNG : 8086dd5610c028cf75501954cbaccf2c
|
||||
imageOrientation_inline : 02c0fb3e810aab39cb690e0fa3f8b7eb
|
||||
imagescplot : 88328b4f32c5ed1cc4e0ad09ea7f47cb
|
||||
imagescplot2 : 39ce8c49f28f3ce90a6bd5a9d0f1cd42
|
||||
latexInterpreter : 73b51aed59a6644c15f1561e51ecbf6d
|
||||
latexmath2 : 5359827e1d218311bf80228f89deffdf
|
||||
legendplot : 5f351094a8e4cd2192fe7cbb2859fd5c
|
||||
legendplotBoxoff : 2654de1ee49ac8f4d2546eb6f254952f
|
||||
legendsubplots : 17c08345bafc58e1562984b37d4e01c9
|
||||
linesWithOutliers : 0aa11947614995837eb1ce45265b45f5
|
||||
logbaseline : f23182b1e230b1b21244ad9364475863
|
||||
logicalImage : 82e9e5ed998aa1ecd78b514d801dc914
|
||||
logplot : 5d5c676b2a3338558939d0407171edc6
|
||||
manualAlignment : ff6a5307120276310c01fb6f9c223d77
|
||||
many_random_points : 44f79b07c32fe2d334cb4d41bb245a2a
|
||||
markerSizes : c80e1e82fcd9d7cbcb52265cd966273b
|
||||
markerSizes2 : 2bc71206cca5fecdd89ee0ca6e7dec9a
|
||||
meshPlot : 390a65be331e6aeab8f4164b36b85e30
|
||||
mixedBarLine : 124b6efc0a9b4d350e0f179bdcc794c9
|
||||
multiline_labels : 113098f446ba5b37be05b2e495753a38
|
||||
multipleAxes : c7c64c5f627f8633ee89ae02ba0b487e
|
||||
multiplePatches : 4d77a30b4a6b14772505e0e9c2a727cf
|
||||
overlappingPlots : 714f8029c2ad4fc86a8fb5323f35b0e4
|
||||
pColorPlot : ce623ad5a9ebf4b3c74d5954027f0631
|
||||
parameterCurve3d : ce2a304c64eb5283a40779f6f410d6ba
|
||||
peaks_contour : a08b52735b11941aef4194d42c50ca95
|
||||
peaks_contourf : bae99cfb0c6d76fbb9eda7cf3253c861
|
||||
pixelLegend : 2afe53d2be6f01a41b74c5bd892fda83
|
||||
plain_cos : defebe18ad95f9f1b1f823ad96bd12bd
|
||||
plotyyLegends : 96cb3c09f470251db4ddf24f59e8e9f4
|
||||
polarplot : a663c1b56d3073601536d4dacae5e8a0
|
||||
quiver3plot : 5dd5d89ff4c5d3de0c000a999814d10a
|
||||
quiveroverlap : f446d413254f3f1e8e4ec449b8a7f813
|
||||
quiverplot : 22d70477697462b313c3d56ef78ac9c8
|
||||
randomWithLines : 9857814e260c4a929f5f0e9e92ba896d
|
||||
rectanglePlot : 045df69771942ea322873279a61c7b9f
|
||||
removeOutsideMarker : f9330795ff85ba1ce4753a700825ab8c
|
||||
roseplot : 526bbf61758a3ac158b2f1de6a39de73
|
||||
scatter3Plot : cede4e9f5248013f47b95e589d805ea8
|
||||
scatterPlotMarkers : b9f6262dba1b2035eb14abda46194ba7
|
||||
scatterPlotRandom : 4b47c90b5493c5e53c3e60a4681e93fd
|
||||
sine_with_annotation : 0b0f9823c6c36cae49d5053d8b984884
|
||||
sine_with_markers : 2cf4b72e72482e4b192012c4165ef5b5
|
||||
spherePlot : 5b0e48733101f43996cc70c2962b52d8
|
||||
stackedBarsWithOther : ac3c350f5af365630e0aaf4352108dd8
|
||||
stairsplot : 73051cf170b77661c4ea464718af1ded
|
||||
stemplot : 983fded97cd2f6cb3286bbcbc5002473
|
||||
stemplot2 : 7450fcbc9332ecbd8ac9e801aad4d8fc
|
||||
subplot2x2b : 7db858e541e4edc35e9721226d8a0f5a
|
||||
subplotCustom : 14bbb2edbd657c7386139bfd7085f8c9
|
||||
surfPlot : 2aadedca0c9e2fe866252a5969fdd08a
|
||||
surfPlot2 : 30a4abfa8829ce6562f6bceb9e702b74
|
||||
texInterpreter : b67b59f407a551196fa1448d9c35e9e7
|
||||
texcolor : 7a8b8c01525fc11ac4f1186c803748a9
|
||||
texrandom : 4dacf9590338ff73553c4a82a78e09bf
|
||||
textAlignment : 5e75059b1f661be10d3d790983f20f40
|
||||
textext : 5be451a1b3314c54ee8ba519f6d2cae9
|
||||
xAxisReversed : 1448dd92ba4ca7c492f060e3d585d340
|
||||
ylabels : 9e68a9002553bcfe576a22d60ec7c5e9
|
||||
zoom : 7777afa78e6ee6169841ccd5a894c942
|
||||
2819
Functions/helper_functions_community/mat2tikz/test/suites/ACID.m
Normal file
2819
Functions/helper_functions_community/mat2tikz/test/suites/ACID.m
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,43 @@
|
||||
function [ status ] = issues( k )
|
||||
%ISSUES M2T Test cases related to issues
|
||||
%
|
||||
% Issue-related test cases for matlab2tikz
|
||||
%
|
||||
% See also: ACID, matlab2tikz_acidtest
|
||||
testfunction_handles = {
|
||||
@scatter3Plot3
|
||||
};
|
||||
|
||||
numFunctions = length( testfunction_handles );
|
||||
|
||||
if (k<=0)
|
||||
status = testfunction_handles;
|
||||
return; % This is used for querying numFunctions.
|
||||
|
||||
elseif (k<=numFunctions)
|
||||
status = testfunction_handles{k}();
|
||||
status.function = func2str(testfunction_handles{k});
|
||||
|
||||
else
|
||||
error('issues:outOfBounds', ...
|
||||
'Out of bounds (number of testfunctions=%d)', numFunctions);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
% =========================================================================
|
||||
function [stat] = scatter3Plot3()
|
||||
stat.description = 'Scatter3 plot with 2 colors';
|
||||
stat.issues = 292;
|
||||
|
||||
hold on;
|
||||
x = sin(1:5);
|
||||
y = cos(3.4 *(1:5));
|
||||
z = x.*y;
|
||||
scatter3(x,y,z,150,...
|
||||
'MarkerEdgeColor','none','MarkerFaceColor','k');
|
||||
scatter3(-x,y,z,150,...
|
||||
'MarkerEdgeColor','none','MarkerFaceColor','b');
|
||||
end
|
||||
|
||||
% =========================================================================
|
||||
@@ -0,0 +1,25 @@
|
||||
function [env, versionString] = getEnvironment()
|
||||
% Determine environment (Octave, MATLAB) and version string
|
||||
% TODO: Unify private `getEnvironment` functions
|
||||
persistent cache
|
||||
|
||||
if isempty(cache)
|
||||
isOctave = exist('OCTAVE_VERSION', 'builtin') ~= 0;
|
||||
if isOctave
|
||||
env = 'Octave';
|
||||
versionString = OCTAVE_VERSION;
|
||||
else
|
||||
env = 'MATLAB';
|
||||
vData = ver(env);
|
||||
versionString = vData.Version;
|
||||
end
|
||||
|
||||
% store in cache
|
||||
cache.env = env;
|
||||
cache.versionString = versionString;
|
||||
|
||||
else
|
||||
env = cache.env;
|
||||
versionString = cache.versionString;
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,167 @@
|
||||
function hh = herrorbar(x, y, l, u, symbol)
|
||||
%HERRORBAR Horizontal Error bar plot.
|
||||
% HERRORBAR(X,Y,L,R) plots the graph of vector X vs. vector Y with
|
||||
% horizontal error bars specified by the vectors L and R. L and R contain the
|
||||
% left and right error ranges for each point in X. Each error bar
|
||||
% is L(i) + R(i) long and is drawn a distance of L(i) to the right and R(i)
|
||||
% to the right the points in (X,Y). The vectors X,Y,L and R must all be
|
||||
% the same length. If X,Y,L and R are matrices then each column
|
||||
% produces a separate line.
|
||||
%
|
||||
% HERRORBAR(X,Y,E) or HERRORBAR(Y,E) plots X with error bars [X-E X+E].
|
||||
% HERRORBAR(...,'LineSpec') uses the color and linestyle specified by
|
||||
% the string 'LineSpec'. See PLOT for possibilities.
|
||||
%
|
||||
% H = HERRORBAR(...) returns a vector of line handles.
|
||||
%
|
||||
% Example:
|
||||
% x = 1:10;
|
||||
% y = sin(x);
|
||||
% e = std(y)*ones(size(x));
|
||||
% herrorbar(x,y,e)
|
||||
% draws symmetric horizontal error bars of unit standard deviation.
|
||||
%
|
||||
% This code is based on ERRORBAR provided in MATLAB.
|
||||
%
|
||||
% See also ERRORBAR
|
||||
|
||||
% Jos van der Geest
|
||||
% email: jos@jasen.nl
|
||||
%
|
||||
% File history:
|
||||
% August 2006 (Jos): I have taken back ownership. I like to thank Greg Aloe from
|
||||
% The MathWorks who originally introduced this piece of code to the
|
||||
% Matlab File Exchange.
|
||||
% September 2003 (Greg Aloe): This code was originally provided by Jos
|
||||
% from the newsgroup comp.soft-sys.matlab:
|
||||
% http://newsreader.mathworks.com/WebX?50@118.fdnxaJz9btF^1@.eea3ff9
|
||||
% After unsuccessfully attempting to contact the orignal author, I
|
||||
% decided to take ownership so that others could benefit from finding it
|
||||
% on the MATLAB Central File Exchange.
|
||||
|
||||
if min(size(x))==1,
|
||||
npt = length(x);
|
||||
x = x(:);
|
||||
y = y(:);
|
||||
if nargin > 2,
|
||||
if ~ischar(l),
|
||||
l = l(:);
|
||||
end
|
||||
if nargin > 3
|
||||
if ~ischar(u)
|
||||
u = u(:);
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
[npt,n] = size(x);
|
||||
end
|
||||
|
||||
if nargin == 3
|
||||
if ~ischar(l)
|
||||
u = l;
|
||||
symbol = '-';
|
||||
else
|
||||
symbol = l;
|
||||
l = y;
|
||||
u = y;
|
||||
y = x;
|
||||
[m,n] = size(y);
|
||||
x(:) = (1:npt)'*ones(1,n);;
|
||||
end
|
||||
end
|
||||
|
||||
if nargin == 4
|
||||
if ischar(u),
|
||||
symbol = u;
|
||||
u = l;
|
||||
else
|
||||
symbol = '-';
|
||||
end
|
||||
end
|
||||
|
||||
if nargin == 2
|
||||
l = y;
|
||||
u = y;
|
||||
y = x;
|
||||
[m,n] = size(y);
|
||||
x(:) = (1:npt)'*ones(1,n);;
|
||||
symbol = '-';
|
||||
end
|
||||
|
||||
u = abs(u);
|
||||
l = abs(l);
|
||||
|
||||
if ischar(x) || ischar(y) || ischar(u) || ischar(l)
|
||||
error('Arguments must be numeric.')
|
||||
end
|
||||
|
||||
if ~isequal(size(x),size(y)) || ~isequal(size(x),size(l)) || ~isequal(size(x),size(u)),
|
||||
error('The sizes of X, Y, L and U must be the same.');
|
||||
end
|
||||
|
||||
tee = (max(y(:))-min(y(:)))/100; % make tee .02 x-distance for error bars
|
||||
% changed from errorbar.m
|
||||
xl = x - l;
|
||||
xr = x + u;
|
||||
ytop = y + tee;
|
||||
ybot = y - tee;
|
||||
n = size(y,2);
|
||||
% end change
|
||||
|
||||
% Plot graph and bars
|
||||
hold_state = ishold;
|
||||
cax = newplot;
|
||||
next = lower(get(cax,'NextPlot'));
|
||||
|
||||
% build up nan-separated vector for bars
|
||||
% changed from errorbar.m
|
||||
xb = zeros(npt*9,n);
|
||||
xb(1:9:end,:) = xl;
|
||||
xb(2:9:end,:) = xl;
|
||||
xb(3:9:end,:) = NaN;
|
||||
xb(4:9:end,:) = xl;
|
||||
xb(5:9:end,:) = xr;
|
||||
xb(6:9:end,:) = NaN;
|
||||
xb(7:9:end,:) = xr;
|
||||
xb(8:9:end,:) = xr;
|
||||
xb(9:9:end,:) = NaN;
|
||||
|
||||
yb = zeros(npt*9,n);
|
||||
yb(1:9:end,:) = ytop;
|
||||
yb(2:9:end,:) = ybot;
|
||||
yb(3:9:end,:) = NaN;
|
||||
yb(4:9:end,:) = y;
|
||||
yb(5:9:end,:) = y;
|
||||
yb(6:9:end,:) = NaN;
|
||||
yb(7:9:end,:) = ytop;
|
||||
yb(8:9:end,:) = ybot;
|
||||
yb(9:9:end,:) = NaN;
|
||||
% end change
|
||||
|
||||
|
||||
[ls,col,mark,msg] = colstyle(symbol);
|
||||
if ~isempty(msg)
|
||||
error(msg);
|
||||
end
|
||||
if isempty(col)
|
||||
col = '';
|
||||
end
|
||||
symbol = [ls mark col]; % Use marker only on data part
|
||||
esymbol = ['-' col]; % Make sure bars are solid
|
||||
if ~isempty(strfind(symbol,'none'))
|
||||
symbol = 'none';
|
||||
end
|
||||
if ~isempty(strfind(esymbol,'none'))
|
||||
esymbol = 'none';
|
||||
end
|
||||
h = plot(xb,yb,'LineStyle',esymbol); hold on
|
||||
h = [h;plot(x,y,'LineStyle',symbol)];
|
||||
|
||||
if ~hold_state
|
||||
hold off;
|
||||
end
|
||||
|
||||
if nargout>0
|
||||
hh = h;
|
||||
end
|
||||
@@ -0,0 +1,46 @@
|
||||
function bool = isEnvironment(wantedEnvironment, varargin)
|
||||
% ISENVIRONMENT check for a particular environment (MATLAB/Octave)
|
||||
%
|
||||
% This function returns TRUE when it is run within the "wantedEnvironment"
|
||||
% (e.g. MATLAB or Octave). This environment can be tested to be a particular
|
||||
% version or be older/newer than a specified version.
|
||||
%
|
||||
% Usage:
|
||||
%
|
||||
% ISENVIRONMENT(ENV)
|
||||
% ISENVIRONMENT(ENV, VERSION)
|
||||
% ISENVIRONMENT(ENV, OP, VERSION)
|
||||
%
|
||||
% Parameters:
|
||||
% - `ENV`: the expected environment (e.g. 'MATLAB' or 'Octave')
|
||||
% - `VERSION`: a version number or string to compare against
|
||||
% e.g. "3.4" or equivalently [3,4]
|
||||
% - `OP`: comparison operator (e.g. '==', '<=', '<', ...) to define a range
|
||||
% of version numbers that return a TRUE value
|
||||
%
|
||||
% When `OP` is not specified, "==" is used.
|
||||
% When no `VERSION` is specified, all versions pass the check.
|
||||
%
|
||||
% See also: isMATLAB, isOctave, versionCompare
|
||||
[env, thisVersion] = getEnvironment();
|
||||
bool = strcmpi(env, wantedEnvironment);
|
||||
|
||||
switch numel(varargin)
|
||||
case 0 % nothing to be done
|
||||
return
|
||||
|
||||
case 1 % check equality
|
||||
version = varargin{1};
|
||||
operator = '==';
|
||||
bool = bool && versionCompare(thisVersion, operator, version);
|
||||
|
||||
case 2
|
||||
operator = varargin{1};
|
||||
version = varargin{2};
|
||||
bool = bool && versionCompare(thisVersion, operator, version);
|
||||
|
||||
otherwise
|
||||
error('isEnvironment:BadNumberOfArguments', ...
|
||||
'"isEnvironment" was called with an incorrect number of arguments.');
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,4 @@
|
||||
function bool = isMATLAB(varargin)
|
||||
%ISMATLAB Determines whether (a certain) version of MATLAB is being used
|
||||
% See also: isEnvironment, isOctave
|
||||
bool = isEnvironment('MATLAB', varargin{:});
|
||||
@@ -0,0 +1,5 @@
|
||||
function bool = isOctave(varargin)
|
||||
%ISOCTAVE Determines whether (a certain) version of Octave is being used
|
||||
%
|
||||
% See also: isEnvironment, isMATLAB
|
||||
bool = isEnvironment('Octave', varargin{:});
|
||||
@@ -0,0 +1,38 @@
|
||||
function isBelow = isVersionBelow(versionA, versionB)
|
||||
% Checks if versionA is smaller than versionB
|
||||
vA = versionArray(versionA);
|
||||
vB = versionArray(versionB);
|
||||
n = min(length(vA), length(vB));
|
||||
deltaAB = vA(1:n) - vB(1:n);
|
||||
difference = find(deltaAB, 1, 'first');
|
||||
if isempty(difference)
|
||||
isBelow = false; % equal versions
|
||||
else
|
||||
isBelow = (deltaAB(difference) < 0);
|
||||
end
|
||||
end
|
||||
% ==============================================================================
|
||||
function arr = versionArray(str)
|
||||
% Converts a version string to an array.
|
||||
if ischar(str)
|
||||
% Translate version string from '2.62.8.1' to [2; 62; 8; 1].
|
||||
switch getEnvironment
|
||||
case 'MATLAB'
|
||||
split = regexp(str, '\.', 'split'); % compatibility MATLAB < R2013a
|
||||
case 'Octave'
|
||||
split = strsplit(str, '.');
|
||||
otherwise
|
||||
errorUnknownEnvironment();
|
||||
end
|
||||
arr = str2num(char(split)); %#ok
|
||||
else
|
||||
arr = str;
|
||||
end
|
||||
arr = arr(:)';
|
||||
end
|
||||
% ==============================================================================
|
||||
function errorUnknownEnvironment()
|
||||
error('matlab2tikz:unknownEnvironment',...
|
||||
'Unknown environment "%s". Need MATLAB(R) or Octave.', getEnvironment);
|
||||
end
|
||||
% ==============================================================================
|
||||
@@ -0,0 +1,20 @@
|
||||
function bool = versionCompare( vA, operator, vB )
|
||||
%VERSIONCOMPARE Performs a version comparison operation
|
||||
switch operator
|
||||
case '<'
|
||||
bool = isVersionBelow(vA, vB);
|
||||
case '>'
|
||||
bool = isVersionBelow(vB, vA);
|
||||
case {'<=', '=<'}
|
||||
bool = ~isVersionBelow(vB, vA);
|
||||
case {'>=', '=>'}
|
||||
bool = ~isVersionBelow(vA, vB);
|
||||
case {'=', '=='}
|
||||
bool = ~isVersionBelow(vA, vB) && ~isVersionBelow(vB, vA);
|
||||
case {'~=', '!='}
|
||||
bool = isVersionBelow(vA, vB) || isVersionBelow(vB, vA);
|
||||
otherwise
|
||||
error('versionCompare:UnknownOperator',...
|
||||
'"%s" is not a known comparison operator', operator);
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,121 @@
|
||||
function status = testPatches(k)
|
||||
% TESTPATCHES Test suite for patches
|
||||
%
|
||||
% See also: ACID, matlab2tikz_acidtest
|
||||
|
||||
testfunction_handles = {
|
||||
@patch01;
|
||||
@patch02;
|
||||
@patch03;
|
||||
@patch04;
|
||||
@patch05;
|
||||
@patch06;
|
||||
@patch07;
|
||||
@patch08;
|
||||
};
|
||||
|
||||
numFunctions = length( testfunction_handles );
|
||||
|
||||
if nargin < 1 || isempty(k) || k <= 0
|
||||
status = testfunction_handles;
|
||||
return; % This is used for querying numFunctions.
|
||||
|
||||
elseif (k<=numFunctions)
|
||||
status = testfunction_handles{k}();
|
||||
status.function = func2str(testfunction_handles{k});
|
||||
|
||||
else
|
||||
error('patchTests:outOfBounds', ...
|
||||
'Out of bounds (number of testfunctions=%d)', numFunctions);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
% =========================================================================
|
||||
function p = patch00()
|
||||
% DO NOT INCLUDE IN ACID LIST
|
||||
% Base patch plot for following tests
|
||||
xdata = [2 2 0 2 5; 2 8 2 4 5; 8 8 2 4 8];
|
||||
ydata = [4 4 4 2 0; 8 4 6 2 2; 4 0 4 0 0];
|
||||
zdata = ones(3,5)*2;
|
||||
p = patch(xdata,ydata,zdata);
|
||||
end
|
||||
% =========================================================================
|
||||
function stat = patch01()
|
||||
stat.description = 'Set face color red';
|
||||
|
||||
p = patch00();
|
||||
set(p,'FaceColor','r')
|
||||
end
|
||||
% =========================================================================
|
||||
function stat = patch02()
|
||||
stat.description = 'Flat face colors scaled in clim [0,40]';
|
||||
|
||||
p = patch00();
|
||||
set(gca,'CLim',[0 40])
|
||||
cdata = [15 30 25 2 60];
|
||||
set(p,'FaceColor','flat','CData',cdata,'CDataMapping','scaled')
|
||||
end
|
||||
% =========================================================================
|
||||
function stat = patch03()
|
||||
stat.description = 'Flat face colors direct in clim [0,40]';
|
||||
|
||||
p = patch00();
|
||||
set(gca,'CLim',[0 40])
|
||||
cdata = [15 30 25 2 60];
|
||||
set(p,'FaceColor','flat','CData',cdata,'CDataMapping','direct')
|
||||
end
|
||||
% =========================================================================
|
||||
function stat = patch04()
|
||||
stat.description = 'Flat face colors with 3D (truecolor) CData';
|
||||
|
||||
p = patch00();
|
||||
cdata(:,:,1) = [0 0 1 0 0.8];
|
||||
cdata(:,:,2) = [0 0 0 0 0.8];
|
||||
cdata(:,:,3) = [1 1 1 0 0.8];
|
||||
set(p,'FaceColor','flat','CData',cdata)
|
||||
end
|
||||
% =========================================================================
|
||||
function stat = patch05()
|
||||
stat.description = 'Flat face color, scaled edge colors in clim [0,40]';
|
||||
|
||||
p = patch00();
|
||||
set(gca,'CLim',[0 40])
|
||||
cdata = [15 30 25 2 60; 12 23 40 13 26; 24 8 1 65 42];
|
||||
set(p,'FaceColor','flat','CData',cdata,'EdgeColor','flat','LineWidth',5,'CDataMapping','scaled')
|
||||
end
|
||||
% =========================================================================
|
||||
function stat = patch06()
|
||||
stat.description = 'Flat face color, direct edge colors in clim [0,40]';
|
||||
|
||||
p = patch00();
|
||||
set(gca,'CLim',[0 40])
|
||||
cdata = [15 30 25 2 60; 12 23 40 13 26; 24 8 1 65 42];
|
||||
set(p,'FaceColor','flat','CData',cdata,'EdgeColor','flat','LineWidth',5,'CDataMapping','direct')
|
||||
end
|
||||
% =========================================================================
|
||||
function stat = patch07()
|
||||
stat.description = 'Flat face color with 3D CData and interp edge colors';
|
||||
|
||||
p = patch00();
|
||||
cdata(:,:,1) = [0 0 1 0 0.8;
|
||||
0 0 1 0.2 0.6;
|
||||
0 1 0 0.4 1];
|
||||
cdata(:,:,2) = [0 0 0 0 0.8;
|
||||
1 1 1 0.2 0.6;
|
||||
1 0 0 0.4 0];
|
||||
cdata(:,:,3) = [1 1 1 0 0.8;
|
||||
0 1 0 0.2 0.6;
|
||||
1 0 1 0.4 0];
|
||||
set(p,'FaceColor','flat','CData',cdata,'EdgeColor','interp','LineWidth',5)
|
||||
end
|
||||
% =========================================================================
|
||||
function stat = patch08()
|
||||
stat.description = 'Interp face colors, flat edges, scaled CData in clims [0,40]';
|
||||
|
||||
p = patch00();
|
||||
set(gca,'CLim',[0 40])
|
||||
cdata = [15 30 25 2 60; 12 23 40 13 26; 24 8 1 65 42];
|
||||
set(p,'FaceColor','interp','CData',cdata,'EdgeColor','flat','LineWidth',5,'CDataMapping','scaled')
|
||||
end
|
||||
% =========================================================================
|
||||
@@ -0,0 +1,102 @@
|
||||
function status = testSurfshader(k)
|
||||
% TESTSURFSHADER Test suite for Surf/mesh shaders (coloring)
|
||||
%
|
||||
% See also: ACID, matlab2tikz_acidtest
|
||||
|
||||
testfunction_handles = {
|
||||
@surfShader1;
|
||||
@surfShader2;
|
||||
@surfShader3;
|
||||
@surfShader4;
|
||||
@surfShader5;
|
||||
@surfNoShader;
|
||||
@surfNoPlot;
|
||||
@surfMeshInterp;
|
||||
@surfMeshRGB;
|
||||
};
|
||||
|
||||
numFunctions = length( testfunction_handles );
|
||||
|
||||
if nargin < 1 || isempty(k) || k <= 0
|
||||
status = testfunction_handles;
|
||||
return; % This is used for querying numFunctions.
|
||||
|
||||
elseif (k<=numFunctions)
|
||||
status = testfunction_handles{k}();
|
||||
status.function = func2str(testfunction_handles{k});
|
||||
|
||||
else
|
||||
error('patchTests:outOfBounds', ...
|
||||
'Out of bounds (number of testfunctions=%d)', numFunctions);
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
% =========================================================================
|
||||
function [stat] = surfShader1()
|
||||
stat.description = 'shader=flat/(flat mean) | Fc: flat | Ec: none';
|
||||
|
||||
[X,Y,Z] = peaks(5);
|
||||
surf(X,Y,Z,'FaceColor','flat','EdgeColor','none')
|
||||
end
|
||||
% =========================================================================
|
||||
function [stat] = surfShader2()
|
||||
stat.description = 'shader=interp | Fc: interp | Ec: none';
|
||||
|
||||
[X,Y,Z] = peaks(5);
|
||||
surf(X,Y,Z,'FaceColor','interp','EdgeColor','none')
|
||||
end
|
||||
% =========================================================================
|
||||
function [stat] = surfShader3()
|
||||
stat.description = 'shader=faceted | Fc: flat | Ec: RGB';
|
||||
|
||||
[X,Y,Z] = peaks(5);
|
||||
surf(X,Y,Z,'FaceColor','flat','EdgeColor','green')
|
||||
end
|
||||
% =========================================================================
|
||||
function [stat] = surfShader4()
|
||||
stat.description = 'shader=faceted | Fc: RGB | Ec: interp';
|
||||
if isMATLAB('<', [8,4]); %R2014a and older
|
||||
warning('m2t:ACID:surfShader4',...
|
||||
'The MATLAB EPS export may behave strangely for this case');
|
||||
end
|
||||
|
||||
[X,Y,Z] = peaks(5);
|
||||
surf(X,Y,Z,'FaceColor','blue','EdgeColor','interp')
|
||||
end
|
||||
% =========================================================================
|
||||
function [stat] = surfShader5()
|
||||
stat.description = 'shader=faceted interp | Fc: interp | Ec: flat';
|
||||
|
||||
[X,Y,Z] = peaks(5);
|
||||
surf(X,Y,Z,'FaceColor','interp','EdgeColor','flat')
|
||||
end
|
||||
% =========================================================================
|
||||
function [stat] = surfNoShader()
|
||||
stat.description = 'no shader | Fc: RGB | Ec: RGB';
|
||||
|
||||
[X,Y,Z] = peaks(5);
|
||||
surf(X,Y,Z,'FaceColor','blue','EdgeColor','yellow')
|
||||
end
|
||||
% =========================================================================
|
||||
function [stat] = surfNoPlot()
|
||||
stat.description = 'no plot | Fc: none | Ec: none';
|
||||
|
||||
[X,Y,Z] = peaks(5);
|
||||
surf(X,Y,Z,'FaceColor','none','EdgeColor','none')
|
||||
end
|
||||
% =========================================================================
|
||||
function [stat] = surfMeshInterp()
|
||||
stat.description = 'mesh | Fc: none | Ec: interp';
|
||||
|
||||
[X,Y,Z] = peaks(5);
|
||||
surf(X,Y,Z,'FaceColor','none','EdgeColor','interp')
|
||||
end
|
||||
% =========================================================================
|
||||
function [stat] = surfMeshRGB()
|
||||
stat.description = 'mesh | Fc: none | Ec: RGB';
|
||||
|
||||
[X,Y,Z] = peaks(5);
|
||||
surf(X,Y,Z,'FaceColor','none','EdgeColor','green')
|
||||
end
|
||||
% =========================================================================
|
||||
6
Functions/helper_functions_community/mat2tikz/test/template/.gitignore
vendored
Normal file
6
Functions/helper_functions_community/mat2tikz/test/template/.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
# just ignore all generate files
|
||||
acid.*
|
||||
*.log
|
||||
*.aux
|
||||
*.pdf
|
||||
*.tex
|
||||
@@ -0,0 +1,33 @@
|
||||
# ./Makefile
|
||||
|
||||
ECHOCMD:=/bin/echo -e
|
||||
LATEX:=pdflatex --shell-escape
|
||||
TARGET:=acid
|
||||
|
||||
main:
|
||||
cd data/reference/ && $(MAKE)
|
||||
cd data/converted/ && $(MAKE)
|
||||
@$(LATEX) $(TARGET)
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
@rm -f $(TARGET).aux \
|
||||
$(TARGET).log \
|
||||
$(TARGET).nav \
|
||||
$(TARGET).out \
|
||||
$(TARGET).snm \
|
||||
$(TARGET).toc \
|
||||
$(TARGET).vrb \
|
||||
$(TARGET).pdf \
|
||||
$(TARGET).dvi \
|
||||
$(TARGET).ps \
|
||||
missfont.log
|
||||
@rm -f *~
|
||||
cd data/reference/ && $(MAKE) clean
|
||||
cd data/converted/ && $(MAKE) clean
|
||||
|
||||
distclean: clean
|
||||
@rm -f $(TARGET).tex
|
||||
cd data/reference/ && $(MAKE) distclean
|
||||
cd data/converted/ && $(MAKE) distclean
|
||||
8
Functions/helper_functions_community/mat2tikz/test/template/data/.gitignore
vendored
Normal file
8
Functions/helper_functions_community/mat2tikz/test/template/data/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
# just ignore all generated files
|
||||
*.log
|
||||
*.aux
|
||||
*.pdf
|
||||
*.eps
|
||||
*.png
|
||||
*.tex
|
||||
*.tsv
|
||||
@@ -0,0 +1,23 @@
|
||||
# ./Makefile
|
||||
|
||||
ECHOCMD:=/bin/echo -e
|
||||
LATEX:=pdflatex --shell-escape -interaction=batchmode
|
||||
|
||||
TEST_SRCS:=$(wildcard test*-converted.tex)
|
||||
TEST_PDFS:=$(TEST_SRCS:.tex=.pdf)
|
||||
|
||||
default: $(TEST_PDFS)
|
||||
|
||||
%.pdf: %.tex
|
||||
@$(LATEX) $<
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
rm -f test*-converted.aux \
|
||||
test*-converted.log \
|
||||
test*-converted.pdf
|
||||
|
||||
distclean: clean
|
||||
rm -f test*-converted.tex \
|
||||
test*-converted*.png
|
||||
@@ -0,0 +1,19 @@
|
||||
# ./Makefile
|
||||
|
||||
EPSTOPDF:=epstopdf
|
||||
|
||||
REFERENCE_EPSS:=$(wildcard test*-reference.eps)
|
||||
REFERENCE_PDFS:=$(REFERENCE_EPSS:.eps=.pdf)
|
||||
|
||||
default: $(REFERENCE_PDFS)
|
||||
|
||||
%.pdf: %.eps
|
||||
$(EPSTOPDF) $<
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
clean:
|
||||
rm -f test*-reference.pdf
|
||||
|
||||
distclean: clean
|
||||
rm -f test*-reference.eps
|
||||
@@ -0,0 +1,47 @@
|
||||
function [ status ] = testGraphical( varargin )
|
||||
%TESTGRAPHICAL Runs the M2T test suite to produce graphical output
|
||||
%
|
||||
% This is quite a thin wrapper around testMatlab2tikz to run the test suite to
|
||||
% produce a PDF side-by-side report.
|
||||
%
|
||||
% Its allowed arguments are the same as those of testMatlab2tikz.
|
||||
%
|
||||
% Usage:
|
||||
%
|
||||
% status = testGraphical(...) % gives programmatical access to the data
|
||||
%
|
||||
% testGraphical(...); % automatically invokes makeLatexReport afterwards
|
||||
%
|
||||
% See also: testMatlab2tikz, testHeadless, makeLatexReport
|
||||
|
||||
[state] = initializeGlobalState();
|
||||
finally_restore_state = onCleanup(@() restoreGlobalState(state));
|
||||
|
||||
[status, args] = testMatlab2tikz('actionsToExecute', @actionsToExecute, ...
|
||||
varargin{:});
|
||||
|
||||
if nargout == 0
|
||||
makeLatexReport(status, args.output);
|
||||
end
|
||||
end
|
||||
% ==============================================================================
|
||||
function status = actionsToExecute(status, ipp)
|
||||
status = execute_plot_stage(status, ipp);
|
||||
|
||||
if status.skip
|
||||
return
|
||||
end
|
||||
|
||||
status = execute_save_stage(status, ipp);
|
||||
status = execute_tikz_stage(status, ipp);
|
||||
%status = execute_hash_stage(status, ipp); %cannot work with files in
|
||||
%standalone mode!
|
||||
status = execute_type_stage(status, ipp);
|
||||
|
||||
if ~status.closeall && ~isempty(status.plotStage.fig_handle)
|
||||
close(status.plotStage.fig_handle);
|
||||
else
|
||||
close all;
|
||||
end
|
||||
end
|
||||
% ==============================================================================
|
||||
@@ -0,0 +1,62 @@
|
||||
function [ status ] = testHeadless( varargin )
|
||||
%TESTGRAPHICAL Runs the M2T test suite without graphical output
|
||||
%
|
||||
% This is quite a thin wrapper around testMatlab2tikz to run the test suite to
|
||||
% produce a textual report and checks for regressions by checking the MD5 hash
|
||||
% of the output
|
||||
%
|
||||
% Its allowed arguments are the same as those of testMatlab2tikz.
|
||||
%
|
||||
% Usage:
|
||||
%
|
||||
% status = TESTHEADLESS(...) % gives programmatical access to the data
|
||||
%
|
||||
% TESTHEADLESS(...); % automatically invokes makeTravisReport afterwards
|
||||
%
|
||||
% See also: testMatlab2tikz, testGraphical, makeTravisReport
|
||||
|
||||
% The width and height are specified to circumvent different DPIs in developer
|
||||
% machines. The float format reduces the probability that numerical differences
|
||||
% in the order of numerical precision disrupt the output.
|
||||
extraOptions = {'width' ,'\figureWidth', ...
|
||||
'height','\figureHeight',...
|
||||
'floatFormat', '%4g', ... % see #604
|
||||
'extraCode',{ ...
|
||||
'\newlength\figureHeight \setlength{\figureHeight}{6cm}', ...
|
||||
'\newlength\figureWidth \setlength{\figureWidth}{10cm}'}
|
||||
};
|
||||
|
||||
[state] = initializeGlobalState();
|
||||
finally_restore_state = onCleanup(@() restoreGlobalState(state));
|
||||
|
||||
status = testMatlab2tikz('extraOptions', extraOptions, ...
|
||||
'actionsToExecute', @actionsToExecute, ...
|
||||
varargin{:});
|
||||
|
||||
if nargout == 0
|
||||
makeTravisReport(status);
|
||||
end
|
||||
end
|
||||
% ==============================================================================
|
||||
function status = actionsToExecute(status, ipp)
|
||||
status = execute_plot_stage(status, ipp);
|
||||
|
||||
if status.skip
|
||||
return
|
||||
end
|
||||
|
||||
status = execute_tikz_stage(status, ipp);
|
||||
status = execute_hash_stage(status, ipp);
|
||||
status = execute_type_stage(status, ipp);
|
||||
|
||||
if ~status.closeall && ~isempty(status.plotStage.fig_handle)
|
||||
try
|
||||
close(status.plotStage.fig_handle);
|
||||
catch
|
||||
close('all');
|
||||
end
|
||||
else
|
||||
close all;
|
||||
end
|
||||
end
|
||||
% ==============================================================================
|
||||
Reference in New Issue
Block a user