From d590e74a1e7e0a40825bdf32366fea11993e1fd8 Mon Sep 17 00:00:00 2001 From: Daniel Ribeiro Santiago Date: Sat, 28 Aug 2021 23:40:49 -0300 Subject: [PATCH 01/17] Add grid feature support to 2D plots --- build.gradle | 4 +- .../com/github/sh0nk/matplotlib4j/Plot.java | 2 + .../github/sh0nk/matplotlib4j/PlotImpl.java | 7 ++++ .../matplotlib4j/builder/GridBuilder.java | 29 +++++++++++++++ .../matplotlib4j/builder/GridBuilderImpl.java | 37 +++++++++++++++++++ .../github/sh0nk/matplotlib4j/MainTest.java | 13 +++++++ 6 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilder.java create mode 100644 src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilderImpl.java diff --git a/build.gradle b/build.gradle index f64fb04..fc589ca 100644 --- a/build.gradle +++ b/build.gradle @@ -3,8 +3,8 @@ apply plugin: "maven-publish" apply plugin: "maven" apply plugin: "signing" -group 'com.github.sh0nk' -version '0.5.1-SNAPSHOT' +group 'io.github.daniel-tucano' +version '0.5.1' archivesBaseName = "matplotlib4j" description = "Matplotlib for java: A simple graph plot library for java with powerful python matplotlib" diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java b/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java index d12574b..d621466 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java @@ -15,6 +15,8 @@ static Plot create(PythonConfig pythonConfig) { return new PlotImpl(pythonConfig, false); } + GridBuilder grid(); + LegendBuilder legend(); /** diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java index 13d647f..d428269 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java @@ -43,6 +43,13 @@ public void title(String title) { registeredBuilders.add(new ArgsBuilderImpl("title", title)); } + @Override + public GridBuilder grid() { + GridBuilder builder = new GridBuilderImpl(); + registeredBuilders.add(builder); + return builder; + } + @Override public LabelBuilder xlabel(String label) { LabelBuilder builder = LabelBuilderImpl.xLabelBuilder(label); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilder.java new file mode 100644 index 0000000..fe96fff --- /dev/null +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilder.java @@ -0,0 +1,29 @@ +package com.github.sh0nk.matplotlib4j.builder; + + +import com.github.sh0nk.matplotlib4j.kwargs.TextArgsBuilder; + +/** + * matplotlib.pyplot.grid(b=None, which='major', axis='both', **kwargs)[source] + */ +public interface GridBuilder extends Builder, TextArgsBuilder { + + enum WhichType { + major, + minor, + both + } + + enum AxisType { + both, + x, + y + } + + GridBuilder b (Boolean bol); + + GridBuilder which (WhichType arg); + + GridBuilder axis (AxisType arg); + +} diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilderImpl.java new file mode 100644 index 0000000..716573a --- /dev/null +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilderImpl.java @@ -0,0 +1,37 @@ +package com.github.sh0nk.matplotlib4j.builder; + +public class GridBuilderImpl implements GridBuilder{ + + private CompositeBuilder innerBuilder = new CompositeBuilder<>(this); + + // -------------------------------- Optional Arguments -------------------------------- + @Override + public GridBuilder b(Boolean bol) { + innerBuilder.addToKwargs("b", bol); + return this; + } + + @Override + public GridBuilder which(WhichType arg) { + innerBuilder.addToKwargs("which", arg.toString()); + return this; + } + + @Override + public GridBuilder axis(AxisType arg) { + innerBuilder.addToKwargs("axis", arg.toString()); + return this; + } + + // TODO("Add kwargs") + + @Override + public String build() { + return innerBuilder.build(); + } + + @Override + public String getMethodName() { + return "grid"; + } +} diff --git a/src/test/java/com/github/sh0nk/matplotlib4j/MainTest.java b/src/test/java/com/github/sh0nk/matplotlib4j/MainTest.java index 3d7d725..d95b6cf 100644 --- a/src/test/java/com/github/sh0nk/matplotlib4j/MainTest.java +++ b/src/test/java/com/github/sh0nk/matplotlib4j/MainTest.java @@ -1,6 +1,7 @@ package com.github.sh0nk.matplotlib4j; import com.github.sh0nk.matplotlib4j.builder.ContourBuilder; +import com.github.sh0nk.matplotlib4j.builder.GridBuilder; import com.github.sh0nk.matplotlib4j.builder.HistBuilder; import com.github.sh0nk.matplotlib4j.builder.ScaleBuilder; import org.junit.Assert; @@ -213,4 +214,16 @@ public void testSubplots() throws IOException, PythonExecutionException { plt.show(); } + + @Test + public void testGrid() throws IOException, PythonExecutionException { + Plot plt = new PlotImpl(DRY_RUN); + + plt.plot() + .add(Arrays.asList(1, 2, 3), Arrays.asList(1, 4, 9)); + + plt.grid().axis(GridBuilder.AxisType.both).which(GridBuilder.WhichType.minor).b(true); + + plt.show(); + } } From ff648b19a847c1f1b77d147ec2163698f6af1947 Mon Sep 17 00:00:00 2001 From: Nico Mexis Date: Sun, 3 Sep 2023 21:11:27 +0200 Subject: [PATCH 02/17] Ignore more files --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index ff92d61..386cca9 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,7 @@ hs_err_pid* # idea .idea + +# Gradle +.gradle/ +build/ From 7dc16d2a8038237b1eebdd416266cb12b0a902ec Mon Sep 17 00:00:00 2001 From: Nico Mexis Date: Sun, 3 Sep 2023 21:12:01 +0200 Subject: [PATCH 03/17] Update Gradle --- build.gradle | 52 ++-- gradle/wrapper/gradle-wrapper.jar | Bin 54417 -> 63721 bytes gradle/wrapper/gradle-wrapper.properties | 7 +- gradlew | 301 ++++++++++++++--------- gradlew.bat | 56 +++-- 5 files changed, 256 insertions(+), 160 deletions(-) diff --git a/build.gradle b/build.gradle index fc589ca..4786875 100644 --- a/build.gradle +++ b/build.gradle @@ -1,27 +1,37 @@ apply plugin: 'java' -apply plugin: "maven-publish" -apply plugin: "maven" -apply plugin: "signing" +apply plugin: 'maven-publish' +apply plugin: 'signing' group 'io.github.daniel-tucano' version '0.5.1' -archivesBaseName = "matplotlib4j" -description = "Matplotlib for java: A simple graph plot library for java with powerful python matplotlib" +description = 'Matplotlib for Java: A simple graph plot library for Java using matplotlib for Python' -sourceCompatibility = 1.8 +base { + archivesName = 'matplotlib4j' +} + +java { + sourceCompatibility = JavaVersion.VERSION_1_8 + targetCompatibility = JavaVersion.VERSION_1_8 +} + +tasks.register('sourceJar', Jar) { + from sourceSets.main.allSource +} + +tasks.withType(JavaCompile) { + options.deprecation = true + options.compilerArgs << '-Xlint:unchecked' +} -task sourceJar(type: Jar) { - from sourceSets.main.allJava +java { + withJavadocJar() + withSourcesJar() } -publishing { - publications { - mavenJava(MavenPublication) { - from components.java - artifact sourceJar { - classifier "sources" - } - } +publishing.publications { + mavenJava(MavenPublication) { + from components.java } } @@ -30,10 +40,10 @@ repositories { } dependencies { - compile group: 'com.google.guava', name: 'guava', version: '15.0' - compile group: 'org.slf4j', name: 'slf4j-api', version: '1.7.7' - compile group: 'org.slf4j', name: 'slf4j-log4j12', version: '1.7.7' - compile group: 'log4j', name: 'log4j', version: '1.2.17' + implementation group: 'com.google.guava', name: 'guava', version: '32.1.2-jre' + implementation group: 'org.slf4j', name: 'slf4j-api', version: '2.0.7' + implementation group: 'org.slf4j', name: 'slf4j-reload4j', version: '2.0.7' + implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.20.0' - testCompile group: 'junit', name: 'junit', version: '4.12' + testImplementation group: 'junit', name: 'junit', version: '4.13.2' } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 758de960ec7947253b058ff79c88ce51f3abe08a..7f93135c49b765f8051ef9d0a6055ff8e46073d8 100644 GIT binary patch literal 63721 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鯊%1Et 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⁢ zv5o9#E7!G0XmdzfsS{efPNi`1b44~SZ4Z8fuX!I}#8g+(wxzQwUT#Xb2(tbY1+EUhGKoT@KEU9Ktl>_0 z%bjDJg;#*gtJZv!-Zs`?^}v5eKmnbjqlvnSzE@_SP|LG_PJ6CYU+6zY6>92%E+ z=j@TZf-iW4(%U{lnYxQA;7Q!b;^brF8n0D>)`q5>|WDDXLrqYU_tKN2>=#@~OE7grMnNh?UOz-O~6 z6%rHy{#h9K0AT+lDC7q4{hw^|q6*Ry;;L%Q@)Ga}$60_q%D)rv(CtS$CQbpq9|y1e zRSrN4;$Jyl{m5bZw`$8TGvb}(LpY{-cQ)fcyJv7l3S52TLXVDsphtv&aPuDk1OzCA z4A^QtC(!11`IsNx_HnSy?>EKpHJWT^wmS~hc^p^zIIh@9f6U@I2 zC=Mve{j2^)mS#U$e{@Q?SO6%LDsXz@SY+=cK_QMmXBIU)j!$ajc-zLx3V60EXJ!qC zi<%2x8Q24YN+&8U@CIlN zrZkcT9yh%LrlGS9`G)KdP(@9Eo-AQz@8GEFWcb7U=a0H^ZVbLmz{+&M7W(nXJ4sN8 zJLR7eeK(K8`2-}j(T7JsO`L!+CvbueT%izanm-^A1Dn{`1Nw`9P?cq;7no+XfC`K(GO9?O^5zNIt4M+M8LM0=7Gz8UA@Z0N+lg+cX)NfazRu z5D)~HA^(u%w^cz+@2@_#S|u>GpB+j4KzQ^&Wcl9f z&hG#bCA(Yk0D&t&aJE^xME^&E-&xGHhXn%}psEIj641H+Nl-}boj;)Zt*t(4wZ5DN z@GXF$bL=&pBq-#vkTkh>7hl%K5|3 z{`Vn9b$iR-SoGENp}bn4;fR3>9sA%X2@1L3aE9yTra;Wb#_`xWwLSLdfu+PAu+o3| zGVnpzPr=ch{uuoHjtw7+_!L_2;knQ!DuDl0R`|%jr+}jFzXtrHIKc323?JO{l&;VF z*L1+}JU7%QJOg|5|Tc|D8fN zJORAg=_vsy{ak|o);@)Yh8Lkcg@$FG3k@ep36BRa^>~UmnRPziS>Z=`Jb2x*Q#`%A zU*i3&Vg?TluO@X0O;r2Jl6LKLUOVhSqg1*qOt^|8*c7 zo(298@+r$k_wQNGHv{|$tW(T8L+4_`FQ{kEW5Jgg{yf7ey4ss_(SNKfz(N9lx&a;< je(UuV8hP?p&}TPdm1I$XmG#(RzlD&B2izSj9sl%y5~4qc literal 54417 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index ff553dc..ac72c34 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ -#Wed Oct 23 10:40:47 UTC 2019 -distributionUrl=https\://services.gradle.org/distributions/gradle-4.8.1-all.zip distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index cccdd3d..0adc8e1 100755 --- a/gradlew +++ b/gradlew @@ -1,78 +1,127 @@ -#!/usr/bin/env sh +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null - -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -81,92 +130,120 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=$((i+1)) + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=$(save "$@") - -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" fi +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index e95643d..6689b85 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,4 +1,20 @@ -@if "%DEBUG%" == "" @echo off +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -9,19 +25,23 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +55,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,38 +65,26 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal From 98e271625aebb3d61bf4267672992efe93c4d433 Mon Sep 17 00:00:00 2001 From: Nico Mexis Date: Sun, 3 Sep 2023 21:12:11 +0200 Subject: [PATCH 04/17] Fix deprecation --- src/main/java/com/github/sh0nk/matplotlib4j/PyCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/PyCommand.java b/src/main/java/com/github/sh0nk/matplotlib4j/PyCommand.java index 5d65c0a..3f19ef5 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/PyCommand.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/PyCommand.java @@ -89,13 +89,13 @@ private void command(List commands) throws IOException, PythonExecutionE } private void writeFile(String pythonScript, File script) throws IOException { - BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(script), StandardCharsets.UTF_8)); + BufferedWriter bw = Files.newWriter(script, StandardCharsets.UTF_8); bw.write(pythonScript); bw.close(); } public void execute(String pythonScript) throws IOException, PythonExecutionException { - File tmpDir = Files.createTempDir(); + File tmpDir = java.nio.file.Files.createTempDirectory("matplotlib4j").toFile(); tmpDir.deleteOnExit(); File script = new File(tmpDir, "exec.py"); From a85bcfc9c0b40b5dfeaff80e9626cf836804e1aa Mon Sep 17 00:00:00 2001 From: Nico Mexis Date: Sun, 3 Sep 2023 21:12:26 +0200 Subject: [PATCH 05/17] Add support for axlines --- .../com/github/sh0nk/matplotlib4j/Plot.java | 4 + .../github/sh0nk/matplotlib4j/PlotImpl.java | 14 ++++ .../matplotlib4j/builder/AxLineBuilder.java | 17 ++++ .../builder/AxLineBuilderImpl.java | 78 +++++++++++++++++++ 4 files changed, 113 insertions(+) create mode 100644 src/main/java/com/github/sh0nk/matplotlib4j/builder/AxLineBuilder.java create mode 100644 src/main/java/com/github/sh0nk/matplotlib4j/builder/AxLineBuilderImpl.java diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java b/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java index d621466..d7a71cb 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java @@ -45,6 +45,10 @@ static Plot create(PythonConfig pythonConfig) { TextBuilder text(double x, double y, String s); + AxLineBuilder axvline(); + + AxLineBuilder axhline(); + PlotBuilder plot(); ContourBuilder contour(); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java index d428269..f98940c 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java @@ -109,6 +109,20 @@ public TextBuilder text(double x, double y, String s) { return builder; } + @Override + public AxLineBuilder axvline() { + AxLineBuilder builder = new AxLineBuilderImpl("v", "x"); + registeredBuilders.add(builder); + return builder; + } + + @Override + public AxLineBuilder axhline() { + AxLineBuilder builder = new AxLineBuilderImpl("h", "y"); + registeredBuilders.add(builder); + return builder; + } + @Override public PlotBuilder plot() { PlotBuilder builder = new PlotBuilderImpl(); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/AxLineBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/AxLineBuilder.java new file mode 100644 index 0000000..bd80a3f --- /dev/null +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/AxLineBuilder.java @@ -0,0 +1,17 @@ +package com.github.sh0nk.matplotlib4j.builder; + +import com.github.sh0nk.matplotlib4j.kwargs.Line2DBuilder; +import java.util.List; + + +/** + * matplotlib.pyplot.plot(*args, **kwargs) + */ +public interface AxLineBuilder extends Builder, Line2DBuilder { + + AxLineBuilder at(Number value); + + AxLineBuilder min(Number value); + + AxLineBuilder max(Number value); +} diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/AxLineBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/AxLineBuilderImpl.java new file mode 100644 index 0000000..32350cf --- /dev/null +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/AxLineBuilderImpl.java @@ -0,0 +1,78 @@ +package com.github.sh0nk.matplotlib4j.builder; + +import com.github.sh0nk.matplotlib4j.kwargs.Line2DBuilder; +import com.github.sh0nk.matplotlib4j.kwargs.Line2DBuilderImpl; +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class AxLineBuilderImpl implements AxLineBuilder { + + private final static Logger LOGGER = LoggerFactory.getLogger(AxLineBuilderImpl.class); + + private CompositeBuilder innerBuilder = new CompositeBuilder<>(this); + private Line2DBuilder line2DBuilder = new Line2DBuilderImpl<>(innerBuilder); + private final String direction; + private final String axis; + + public AxLineBuilderImpl(String direction, String axis) { + this.direction = direction; + this.axis = axis; + } + + @Override + public AxLineBuilder at(Number value) { + return innerBuilder.addToKwargs(axis, value); + } + + @Override + public AxLineBuilder min(Number value) { + return innerBuilder.addToKwargs(axis + "min", value); + } + + @Override + public AxLineBuilder max(Number value) { + return innerBuilder.addToKwargs(axis + "max", value); + } + + @Override + public AxLineBuilder linestyle(String arg) { + return line2DBuilder.linestyle(arg); + } + + @Override + public AxLineBuilder ls(String arg) { + return line2DBuilder.ls(arg); + } + + @Override + public AxLineBuilder linewidth(double arg) { + return line2DBuilder.linewidth(arg); + } + + @Override + public AxLineBuilder lw(double arg) { + return line2DBuilder.lw(arg); + } + + @Override + public AxLineBuilder label(String arg) { + return line2DBuilder.label(arg); + } + + @Override + public AxLineBuilder color(String arg) { + return line2DBuilder.color(arg); + } + + @Override + public String build() { + return innerBuilder.build(); + } + + @Override + public String getMethodName() { + return "ax" + direction + "line"; + } +} From c8c57b6a357d89976fcfbf68d7b7c6a61b4ceaf5 Mon Sep 17 00:00:00 2001 From: Nico Mexis Date: Mon, 4 Sep 2023 00:28:44 +0200 Subject: [PATCH 06/17] Use isEmpty() --- .../com/github/sh0nk/matplotlib4j/builder/HistBuilderImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/HistBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/HistBuilderImpl.java index 402c027..962bc6b 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/HistBuilderImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/HistBuilderImpl.java @@ -124,7 +124,7 @@ public HistBuilder label(String arg) { @Override public String build() { - Preconditions.checkArgument(xList.size() > 0, ".add() is needed to be called at least once."); + Preconditions.checkArgument(!xList.isEmpty(), ".add() is needed to be called at least once."); innerBuilder.addToArgsWithoutQuoting(xList.toString()); return innerBuilder.build(); } From d31b31c2b6593c78ba37ceb5d10b1500226359b3 Mon Sep 17 00:00:00 2001 From: Nico Mexis Date: Mon, 4 Sep 2023 13:11:30 +0200 Subject: [PATCH 07/17] Fix tests --- .../matplotlib4j/builder/GridBuilder.java | 6 +-- .../matplotlib4j/builder/GridBuilderImpl.java | 6 +-- .../github/sh0nk/matplotlib4j/MainTest.java | 44 +++++++++---------- .../sh0nk/matplotlib4j/NumpyUtilsTest.java | 10 ++--- .../sh0nk/matplotlib4j/SaveFigTest.java | 5 --- 5 files changed, 29 insertions(+), 42 deletions(-) diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilder.java index fe96fff..3d33e25 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilder.java @@ -20,10 +20,10 @@ enum AxisType { y } - GridBuilder b (Boolean bol); + GridBuilder visible(Boolean bol); - GridBuilder which (WhichType arg); + GridBuilder which(WhichType arg); - GridBuilder axis (AxisType arg); + GridBuilder axis(AxisType arg); } diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilderImpl.java index 716573a..61e46e5 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilderImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilderImpl.java @@ -1,13 +1,13 @@ package com.github.sh0nk.matplotlib4j.builder; -public class GridBuilderImpl implements GridBuilder{ +public class GridBuilderImpl implements GridBuilder { private CompositeBuilder innerBuilder = new CompositeBuilder<>(this); // -------------------------------- Optional Arguments -------------------------------- @Override - public GridBuilder b(Boolean bol) { - innerBuilder.addToKwargs("b", bol); + public GridBuilder visible(Boolean bol) { + innerBuilder.addToKwargs("visible", bol); return this; } diff --git a/src/test/java/com/github/sh0nk/matplotlib4j/MainTest.java b/src/test/java/com/github/sh0nk/matplotlib4j/MainTest.java index d95b6cf..0c59678 100644 --- a/src/test/java/com/github/sh0nk/matplotlib4j/MainTest.java +++ b/src/test/java/com/github/sh0nk/matplotlib4j/MainTest.java @@ -5,9 +5,7 @@ import com.github.sh0nk.matplotlib4j.builder.HistBuilder; import com.github.sh0nk.matplotlib4j.builder.ScaleBuilder; import org.junit.Assert; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,9 +22,6 @@ public class MainTest { private final static Logger LOGGER = LoggerFactory.getLogger(MainTest.class); - @Rule - public ExpectedException expectedException = ExpectedException.none(); - @Test public void testPlot() throws IOException, PythonExecutionException { Plot plt = new PlotImpl(DRY_RUN); @@ -156,27 +151,28 @@ public void testPlotTwoHistogram() throws IOException, PythonExecutionException } @Test - public void testPlotHistogramNoXError() throws IOException, PythonExecutionException { - expectedException.expect(IllegalArgumentException.class); - - Plot plt = new PlotImpl(DRY_RUN); - plt.hist(); - plt.xlim(-5, 5); - plt.title("histogram"); - plt.legend().loc("upper right"); - plt.show(); + public void testPlotHistogramNoXError() { + Assert.assertThrows(IllegalArgumentException.class, () -> { + Plot plt = new PlotImpl(DRY_RUN); + plt.hist(); + plt.xlim(-5, 5); + plt.title("histogram"); + plt.legend().loc("upper right"); + plt.show(); + }); } + /* Test is failing on newer matplotlib versions @Test - public void testThirdArgError() throws IOException, PythonExecutionException { - expectedException.expect(PythonExecutionException.class); - - Plot plt = Plot.create(); - plt.plot().add(Arrays.asList(1.3, 2)) - .add(Arrays.asList(1.3, 2)) - .add(Arrays.asList(1.3, 2)); - plt.show(); - } + public void testThirdArgError() { + Assert.assertThrows(PythonExecutionException.class, () -> { + Plot plt = Plot.create(); + plt.plot().add(Arrays.asList(1.3, 2)) + .add(Arrays.asList(1.3, 2)) + .add(Arrays.asList(1.3, 2)); + plt.show(); + }); + }*/ @Test public void testBoundaryValuesCauseNoException() throws IOException, PythonExecutionException { @@ -222,7 +218,7 @@ public void testGrid() throws IOException, PythonExecutionException { plt.plot() .add(Arrays.asList(1, 2, 3), Arrays.asList(1, 4, 9)); - plt.grid().axis(GridBuilder.AxisType.both).which(GridBuilder.WhichType.minor).b(true); + plt.grid().axis(GridBuilder.AxisType.both).which(GridBuilder.WhichType.minor).visible(true); plt.show(); } diff --git a/src/test/java/com/github/sh0nk/matplotlib4j/NumpyUtilsTest.java b/src/test/java/com/github/sh0nk/matplotlib4j/NumpyUtilsTest.java index eaf7ae5..dab7cf2 100644 --- a/src/test/java/com/github/sh0nk/matplotlib4j/NumpyUtilsTest.java +++ b/src/test/java/com/github/sh0nk/matplotlib4j/NumpyUtilsTest.java @@ -1,9 +1,7 @@ package com.github.sh0nk.matplotlib4j; import org.junit.Assert; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import java.util.Arrays; import java.util.List; @@ -11,9 +9,6 @@ public class NumpyUtilsTest { - @Rule - public ExpectedException expectedException = ExpectedException.none(); - @Test public void testLinspace() throws Exception { assertListDouble(Arrays.asList(2.0, 10.0), NumpyUtils.linspace(2, 10, 2)); @@ -23,8 +18,9 @@ public void testLinspace() throws Exception { @Test public void testLinspaceFail() throws Exception { - expectedException.expect(IllegalArgumentException.class); - assertListDouble(Arrays.asList(10.0, 7.0, 4.0, 1.0), NumpyUtils.linspace(10, -1, -3)); + Assert.assertThrows(IllegalArgumentException.class, () -> { + assertListDouble(Arrays.asList(10.0, 7.0, 4.0, 1.0), NumpyUtils.linspace(10, -1, -3)); + }); } @Test diff --git a/src/test/java/com/github/sh0nk/matplotlib4j/SaveFigTest.java b/src/test/java/com/github/sh0nk/matplotlib4j/SaveFigTest.java index 98777aa..89fea18 100644 --- a/src/test/java/com/github/sh0nk/matplotlib4j/SaveFigTest.java +++ b/src/test/java/com/github/sh0nk/matplotlib4j/SaveFigTest.java @@ -1,9 +1,7 @@ package com.github.sh0nk.matplotlib4j; import org.junit.Assert; -import org.junit.Rule; import org.junit.Test; -import org.junit.rules.ExpectedException; import java.io.File; import java.io.IOException; @@ -13,9 +11,6 @@ public class SaveFigTest { private static final boolean DRY_RUN = true; - @Rule - public ExpectedException expectedException = ExpectedException.none(); - @Test public void testSaveFig() throws IOException, PythonExecutionException { File tmpFile = File.createTempFile("savefig", ".png"); From 73bf149feddfe83dfaac55220766fa6dab0606b1 Mon Sep 17 00:00:00 2001 From: Nico Mexis Date: Mon, 4 Sep 2023 13:11:44 +0200 Subject: [PATCH 08/17] Change group back --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 4786875..8cdec3e 100644 --- a/build.gradle +++ b/build.gradle @@ -2,8 +2,8 @@ apply plugin: 'java' apply plugin: 'maven-publish' apply plugin: 'signing' -group 'io.github.daniel-tucano' -version '0.5.1' +group 'com.github.sh0nk' +version '0.5.1-SNAPSHOT' description = 'Matplotlib for Java: A simple graph plot library for Java using matplotlib for Python' base { From b765cd7bc214d7bf89e5018f193b9f0e4777eb8f Mon Sep 17 00:00:00 2001 From: Nico Mexis Date: Mon, 4 Sep 2023 13:12:02 +0200 Subject: [PATCH 09/17] Fully migrate to Java 8 Files API --- src/main/java/com/github/sh0nk/matplotlib4j/PyCommand.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/PyCommand.java b/src/main/java/com/github/sh0nk/matplotlib4j/PyCommand.java index 3f19ef5..c026a34 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/PyCommand.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/PyCommand.java @@ -2,7 +2,7 @@ import com.google.common.base.Strings; import com.google.common.collect.Lists; -import com.google.common.io.Files; +import java.nio.file.Files; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -89,13 +89,13 @@ private void command(List commands) throws IOException, PythonExecutionE } private void writeFile(String pythonScript, File script) throws IOException { - BufferedWriter bw = Files.newWriter(script, StandardCharsets.UTF_8); + BufferedWriter bw = Files.newBufferedWriter(script.toPath(), StandardCharsets.UTF_8); bw.write(pythonScript); bw.close(); } public void execute(String pythonScript) throws IOException, PythonExecutionException { - File tmpDir = java.nio.file.Files.createTempDirectory("matplotlib4j").toFile(); + File tmpDir = Files.createTempDirectory("matplotlib4j").toFile(); tmpDir.deleteOnExit(); File script = new File(tmpDir, "exec.py"); From 61471d5c6c609eb782f31dd050bd796f2df7c3c7 Mon Sep 17 00:00:00 2001 From: Nico Mexis Date: Mon, 4 Sep 2023 13:12:12 +0200 Subject: [PATCH 10/17] Update logging properly --- build.gradle | 4 ++-- src/main/resources/log4j.properties | 6 ------ src/main/resources/log4j2.properties | 21 +++++++++++++++++++++ 3 files changed, 23 insertions(+), 8 deletions(-) delete mode 100644 src/main/resources/log4j.properties create mode 100644 src/main/resources/log4j2.properties diff --git a/build.gradle b/build.gradle index 8cdec3e..52f0bbf 100644 --- a/build.gradle +++ b/build.gradle @@ -41,9 +41,9 @@ repositories { dependencies { implementation group: 'com.google.guava', name: 'guava', version: '32.1.2-jre' - implementation group: 'org.slf4j', name: 'slf4j-api', version: '2.0.7' - implementation group: 'org.slf4j', name: 'slf4j-reload4j', version: '2.0.7' + implementation group: 'org.apache.logging.log4j', name: 'log4j-api', version: '2.20.0' implementation group: 'org.apache.logging.log4j', name: 'log4j-core', version: '2.20.0' + implementation group: 'org.apache.logging.log4j', name: 'log4j-slf4j2-impl', version: '2.20.0' testImplementation group: 'junit', name: 'junit', version: '4.13.2' } diff --git a/src/main/resources/log4j.properties b/src/main/resources/log4j.properties deleted file mode 100644 index fd0b37b..0000000 --- a/src/main/resources/log4j.properties +++ /dev/null @@ -1,6 +0,0 @@ -log4j.rootLogger = INFO, stdout - -log4j.logger.com.github = DEBUG - -log4j.appender.stdout = org.apache.log4j.ConsoleAppender -log4j.appender.stdout.layout = org.apache.log4j.SimpleLayout \ No newline at end of file diff --git a/src/main/resources/log4j2.properties b/src/main/resources/log4j2.properties new file mode 100644 index 0000000..48545e8 --- /dev/null +++ b/src/main/resources/log4j2.properties @@ -0,0 +1,21 @@ +status = warn +name = matplotlib4j +filters = threshold + +filter.threshold.type = ThresholdFilter +filter.threshold.level = debug + +appender.console.type = Console +appender.console.name = STDOUT +appender.console.layout.type = PatternLayout +appender.console.layout.pattern = %-5p [%t]: %m%n + +rootLogger.level = info +rootLogger.appenderRefs = stdout +rootLogger.appenderRef.stdout.ref = STDOUT + +logger.com.name = com.github +logger.com.level = debug +logger.com.additivity = false +logger.com.appenderRefs = stdout +logger.com.appenderRef.stdout.ref = STDOUT From dbe6fa6fc8e511c0057be9ef7fb6c523fa383fd7 Mon Sep 17 00:00:00 2001 From: Nico Mexis Date: Thu, 7 Sep 2023 13:34:54 +0200 Subject: [PATCH 11/17] Add scatter implementation --- .../com/github/sh0nk/matplotlib4j/Plot.java | 2 + .../github/sh0nk/matplotlib4j/PlotImpl.java | 7 ++ .../matplotlib4j/builder/ScatterBuilder.java | 37 ++++++++ .../builder/ScatterBuilderImpl.java | 87 +++++++++++++++++++ 4 files changed, 133 insertions(+) create mode 100644 src/main/java/com/github/sh0nk/matplotlib4j/builder/ScatterBuilder.java create mode 100644 src/main/java/com/github/sh0nk/matplotlib4j/builder/ScatterBuilderImpl.java diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java b/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java index d7a71cb..80ecfc2 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java @@ -57,6 +57,8 @@ static Plot create(PythonConfig pythonConfig) { HistBuilder hist(); + ScatterBuilder scatter(); + CLabelBuilder clabel(ContourBuilder contour); SaveFigBuilder savefig(String fname); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java index f98940c..e6d26ae 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java @@ -151,6 +151,13 @@ public HistBuilder hist() { return builder; } + @Override + public ScatterBuilder scatter() { + ScatterBuilder builder = new ScatterBuilderImpl(); + registeredBuilders.add(builder); + return builder; + } + @Override public CLabelBuilder clabel(ContourBuilder contour) { CLabelBuilder builder = new CLabelBuilderImpl(contour); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/ScatterBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/ScatterBuilder.java new file mode 100644 index 0000000..f1ffb04 --- /dev/null +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/ScatterBuilder.java @@ -0,0 +1,37 @@ +package com.github.sh0nk.matplotlib4j.builder; + +import com.github.sh0nk.matplotlib4j.kwargs.Line2DBuilder; + +import java.util.List; + + +/** + * matplotlib.pyplot.scatter(*args, **kwargs) + */ +public interface ScatterBuilder extends Builder { + + ScatterBuilder add(List x); + + ScatterBuilder s(double s); + + ScatterBuilder c(String color); + + ScatterBuilder marker(String marker); + + ScatterBuilder cmap(String cmap); + + ScatterBuilder norm(String norm); + + ScatterBuilder vmin(double vmin); + + ScatterBuilder vmax(double vmax); + + ScatterBuilder alpha(double alpha); + + ScatterBuilder linewidths(double linewidths); + + ScatterBuilder edgecolors(String edgecolors); + + ScatterBuilder plotnonfinite(boolean plotnonfinite); + +} diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/ScatterBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/ScatterBuilderImpl.java new file mode 100644 index 0000000..451d04d --- /dev/null +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/ScatterBuilderImpl.java @@ -0,0 +1,87 @@ +package com.github.sh0nk.matplotlib4j.builder; + +import com.github.sh0nk.matplotlib4j.kwargs.Line2DBuilder; +import com.github.sh0nk.matplotlib4j.kwargs.Line2DBuilderImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.List; + + +public class ScatterBuilderImpl implements ScatterBuilder { + + private final static Logger LOGGER = LoggerFactory.getLogger(ScatterBuilderImpl.class); + + private CompositeBuilder innerBuilder = new CompositeBuilder<>(this); + private Line2DBuilder line2DBuilder = new Line2DBuilderImpl<>(innerBuilder); + + @Override + public ScatterBuilder add(List x) { + return innerBuilder.addToArgs(x); + } + + @Override + public ScatterBuilder s(double s) { + return innerBuilder.addToKwargs("s", s); + } + + @Override + public ScatterBuilder c(String color) { + return innerBuilder.addToKwargs("c", color); + } + + @Override + public ScatterBuilder marker(String marker) { + return innerBuilder.addToKwargs("marker", marker); + } + + @Override + public ScatterBuilder cmap(String cmap) { + return innerBuilder.addToKwargs("cmap", cmap); + } + + @Override + public ScatterBuilder norm(String norm) { + return innerBuilder.addToKwargs("norm", norm); + } + + @Override + public ScatterBuilder vmin(double vmin) { + return innerBuilder.addToKwargs("vmin", vmin); + } + + @Override + public ScatterBuilder vmax(double vmax) { + return innerBuilder.addToKwargs("vmax", vmax); + } + + @Override + public ScatterBuilder alpha(double alpha) { + return innerBuilder.addToKwargs("alpha", alpha); + } + + @Override + public ScatterBuilder linewidths(double linewidths) { + return innerBuilder.addToKwargs("linewidths", linewidths); + } + + @Override + public ScatterBuilder edgecolors(String edgecolors) { + return innerBuilder.addToKwargs("edgecolors", edgecolors); + } + + @Override + public ScatterBuilder plotnonfinite(boolean plotnonfinite) { + return innerBuilder.addToKwargs("plotnonfinite", plotnonfinite); + } + + @Override + public String build() { + return innerBuilder.build(); + } + + @Override + public String getMethodName() { + return "scatter"; + } +} From 8d0bfd085d512720645d07ef529bd7a8188c36e1 Mon Sep 17 00:00:00 2001 From: Nico Mexis Date: Thu, 7 Sep 2023 14:10:02 +0200 Subject: [PATCH 12/17] Add more grid args --- .../matplotlib4j/builder/GridBuilder.java | 3 +- .../matplotlib4j/builder/GridBuilderImpl.java | 34 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilder.java index 3d33e25..b1e319a 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilder.java @@ -1,12 +1,13 @@ package com.github.sh0nk.matplotlib4j.builder; +import com.github.sh0nk.matplotlib4j.kwargs.Line2DBuilder; import com.github.sh0nk.matplotlib4j.kwargs.TextArgsBuilder; /** * matplotlib.pyplot.grid(b=None, which='major', axis='both', **kwargs)[source] */ -public interface GridBuilder extends Builder, TextArgsBuilder { +public interface GridBuilder extends Builder, TextArgsBuilder, Line2DBuilder { enum WhichType { major, diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilderImpl.java index 61e46e5..53b2296 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilderImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilderImpl.java @@ -1,8 +1,12 @@ package com.github.sh0nk.matplotlib4j.builder; +import com.github.sh0nk.matplotlib4j.kwargs.Line2DBuilder; +import com.github.sh0nk.matplotlib4j.kwargs.Line2DBuilderImpl; + public class GridBuilderImpl implements GridBuilder { private CompositeBuilder innerBuilder = new CompositeBuilder<>(this); + private Line2DBuilder line2DBuilder = new Line2DBuilderImpl<>(innerBuilder); // -------------------------------- Optional Arguments -------------------------------- @Override @@ -23,6 +27,36 @@ public GridBuilder axis(AxisType arg) { return this; } + @Override + public GridBuilder linestyle(String arg) { + return line2DBuilder.linestyle(arg); + } + + @Override + public GridBuilder ls(String arg) { + return line2DBuilder.ls(arg); + } + + @Override + public GridBuilder linewidth(double arg) { + return line2DBuilder.linewidth(arg); + } + + @Override + public GridBuilder lw(double arg) { + return line2DBuilder.lw(arg); + } + + @Override + public GridBuilder label(String arg) { + return line2DBuilder.label(arg); + } + + @Override + public GridBuilder color(String arg) { + return line2DBuilder.color(arg); + } + // TODO("Add kwargs") @Override From a8d81eb3ed5610c5638d06f6357f752b0486b1ff Mon Sep 17 00:00:00 2001 From: Nico Mexis Date: Tue, 12 Sep 2023 13:46:42 +0200 Subject: [PATCH 13/17] Add bar --- .../com/github/sh0nk/matplotlib4j/Plot.java | 2 + .../github/sh0nk/matplotlib4j/PlotImpl.java | 7 +++ .../matplotlib4j/builder/BarBuilder.java | 14 +++++ .../matplotlib4j/builder/BarBuilderImpl.java | 61 +++++++++++++++++++ 4 files changed, 84 insertions(+) create mode 100644 src/main/java/com/github/sh0nk/matplotlib4j/builder/BarBuilder.java create mode 100644 src/main/java/com/github/sh0nk/matplotlib4j/builder/BarBuilderImpl.java diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java b/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java index 80ecfc2..823ce8a 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java @@ -57,6 +57,8 @@ static Plot create(PythonConfig pythonConfig) { HistBuilder hist(); + BarBuilder bar(); + ScatterBuilder scatter(); CLabelBuilder clabel(ContourBuilder contour); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java index e6d26ae..45f7341 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java @@ -151,6 +151,13 @@ public HistBuilder hist() { return builder; } + @Override + public BarBuilder bar() { + BarBuilder builder = new BarBuilderImpl(); + registeredBuilders.add(builder); + return builder; + } + @Override public ScatterBuilder scatter() { ScatterBuilder builder = new ScatterBuilderImpl(); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/BarBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/BarBuilder.java new file mode 100644 index 0000000..6b2370f --- /dev/null +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/BarBuilder.java @@ -0,0 +1,14 @@ +package com.github.sh0nk.matplotlib4j.builder; + +import com.github.sh0nk.matplotlib4j.kwargs.Line2DBuilder; +import java.util.List; + + +/** + * matplotlib.pyplot.bar(*args, **kwargs) + */ +public interface BarBuilder extends Builder, Line2DBuilder { + + BarBuilder add(List nums); + +} diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/BarBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/BarBuilderImpl.java new file mode 100644 index 0000000..41d6491 --- /dev/null +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/BarBuilderImpl.java @@ -0,0 +1,61 @@ +package com.github.sh0nk.matplotlib4j.builder; + +import com.github.sh0nk.matplotlib4j.kwargs.Line2DBuilder; +import com.github.sh0nk.matplotlib4j.kwargs.Line2DBuilderImpl; +import java.util.List; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + + +public class BarBuilderImpl implements BarBuilder { + + private final static Logger LOGGER = LoggerFactory.getLogger(BarBuilderImpl.class); + + private CompositeBuilder innerBuilder = new CompositeBuilder<>(this); + private Line2DBuilder line2DBuilder = new Line2DBuilderImpl<>(innerBuilder); + + @Override + public BarBuilder add(List nums) { + return innerBuilder.addToArgs(nums); + } + + @Override + public BarBuilder linestyle(String arg) { + return line2DBuilder.linestyle(arg); + } + + @Override + public BarBuilder ls(String arg) { + return line2DBuilder.ls(arg); + } + + @Override + public BarBuilder linewidth(double arg) { + return line2DBuilder.linewidth(arg); + } + + @Override + public BarBuilder lw(double arg) { + return line2DBuilder.lw(arg); + } + + @Override + public BarBuilder label(String arg) { + return line2DBuilder.label(arg); + } + + @Override + public BarBuilder color(String arg) { + return line2DBuilder.color(arg); + } + + @Override + public String build() { + return innerBuilder.build(); + } + + @Override + public String getMethodName() { + return "bar"; + } +} From 7e7e4676cb7a17cad66792888f2908dea3a9e80a Mon Sep 17 00:00:00 2001 From: Nico Mexis Date: Sat, 16 Sep 2023 14:59:09 +0200 Subject: [PATCH 14/17] Add more custom commands and properties --- .../com/github/sh0nk/matplotlib4j/Plot.java | 4 + .../github/sh0nk/matplotlib4j/PlotImpl.java | 10 ++ .../matplotlib4j/builder/AxLineBuilder.java | 4 +- .../builder/AxLineBuilderImpl.java | 25 +++++ .../matplotlib4j/builder/BarBuilder.java | 3 +- .../matplotlib4j/builder/BarBuilderImpl.java | 25 +++++ .../sh0nk/matplotlib4j/builder/Builder.java | 8 ++ .../matplotlib4j/builder/CLabelBuilder.java | 4 +- .../builder/CLabelBuilderImpl.java | 27 ++++++ .../builder/CompositeBuilder.java | 8 +- .../matplotlib4j/builder/ContourBuilder.java | 3 +- .../builder/ContourBuilderImpl.java | 25 +++++ .../matplotlib4j/builder/CustomBuilder.java | 18 ++++ .../builder/CustomBuilderImpl.java | 93 +++++++++++++++++++ .../matplotlib4j/builder/GridBuilder.java | 3 +- .../matplotlib4j/builder/GridBuilderImpl.java | 26 +++++- .../matplotlib4j/builder/HistBuilder.java | 3 +- .../matplotlib4j/builder/HistBuilderImpl.java | 25 +++++ .../matplotlib4j/builder/LabelBuilder.java | 3 +- .../builder/LabelBuilderImpl.java | 27 ++++++ .../matplotlib4j/builder/LegendBuilder.java | 4 +- .../builder/LegendBuilderImpl.java | 27 ++++++ .../matplotlib4j/builder/PColorBuilder.java | 3 +- .../builder/PColorBuilderImpl.java | 25 +++++ .../matplotlib4j/builder/PlotBuilder.java | 3 +- .../matplotlib4j/builder/PlotBuilderImpl.java | 25 +++++ .../matplotlib4j/builder/SaveFigBuilder.java | 4 +- .../builder/SaveFigBuilderImpl.java | 27 ++++++ .../matplotlib4j/builder/ScaleBuilder.java | 3 +- .../builder/ScaleBuilderImpl.java | 27 ++++++ .../matplotlib4j/builder/ScatterBuilder.java | 3 +- .../builder/ScatterBuilderImpl.java | 25 +++++ .../matplotlib4j/builder/SubplotBuilder.java | 4 +- .../builder/SubplotBuilderImpl.java | 27 ++++++ .../matplotlib4j/builder/TextBuilder.java | 4 +- .../matplotlib4j/builder/TextBuilderImpl.java | 26 ++++++ .../matplotlib4j/builder/TicksBuilder.java | 3 +- .../builder/TicksBuilderImpl.java | 25 +++++ .../matplotlib4j/kwargs/KwArgsBuilder.java | 18 ++++ .../matplotlib4j/kwargs/KwargsBuilder.java | 5 - .../matplotlib4j/kwargs/Line2DBuilder.java | 2 +- .../matplotlib4j/kwargs/PatchBuilder.java | 2 +- .../matplotlib4j/kwargs/TextArgsBuilder.java | 2 +- 43 files changed, 609 insertions(+), 29 deletions(-) create mode 100644 src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomBuilder.java create mode 100644 src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomBuilderImpl.java create mode 100644 src/main/java/com/github/sh0nk/matplotlib4j/kwargs/KwArgsBuilder.java delete mode 100644 src/main/java/com/github/sh0nk/matplotlib4j/kwargs/KwargsBuilder.java diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java b/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java index 823ce8a..81e6117 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java @@ -15,6 +15,10 @@ static Plot create(PythonConfig pythonConfig) { return new PlotImpl(pythonConfig, false); } + CustomBuilder cmd(String key); + + CustomBuilder cmd(String methodPrefix, String key, Boolean returns); + GridBuilder grid(); LegendBuilder legend(); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java index 45f7341..8010bbd 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java @@ -26,6 +26,16 @@ public class PlotImpl implements Plot { this(PythonConfig.systemDefaultPythonConfig(), dryRun); } + @Override + public CustomBuilder cmd(String key) { + return new CustomBuilderImpl(key); + } + + @Override + public CustomBuilder cmd(String methodPrefix, String key, Boolean returns) { + return new CustomBuilderImpl(methodPrefix, key, returns); + } + @Override public LegendBuilder legend() { LegendBuilder builder = new LegendBuilderImpl(); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/AxLineBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/AxLineBuilder.java index bd80a3f..35d2333 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/AxLineBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/AxLineBuilder.java @@ -1,13 +1,13 @@ package com.github.sh0nk.matplotlib4j.builder; +import com.github.sh0nk.matplotlib4j.kwargs.KwArgsBuilder; import com.github.sh0nk.matplotlib4j.kwargs.Line2DBuilder; -import java.util.List; /** * matplotlib.pyplot.plot(*args, **kwargs) */ -public interface AxLineBuilder extends Builder, Line2DBuilder { +public interface AxLineBuilder extends Builder, Line2DBuilder, KwArgsBuilder { AxLineBuilder at(Number value); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/AxLineBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/AxLineBuilderImpl.java index 32350cf..4d49823 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/AxLineBuilderImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/AxLineBuilderImpl.java @@ -66,6 +66,31 @@ public AxLineBuilder color(String arg) { return line2DBuilder.color(arg); } + @Override + public AxLineBuilder addToKwargs(String k, String v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public AxLineBuilder addToKwargsWithoutQuoting(String k, String v) { + return innerBuilder.addToKwargsWithoutQuoting(k, v); + } + + @Override + public AxLineBuilder addToKwargs(String k, Number n) { + return innerBuilder.addToKwargs(k, n); + } + + @Override + public AxLineBuilder addToKwargs(String k, List v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public AxLineBuilder addToKwargs(String k, boolean v) { + return innerBuilder.addToKwargs(k, v); + } + @Override public String build() { return innerBuilder.build(); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/BarBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/BarBuilder.java index 6b2370f..8c39da7 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/BarBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/BarBuilder.java @@ -1,5 +1,6 @@ package com.github.sh0nk.matplotlib4j.builder; +import com.github.sh0nk.matplotlib4j.kwargs.KwArgsBuilder; import com.github.sh0nk.matplotlib4j.kwargs.Line2DBuilder; import java.util.List; @@ -7,7 +8,7 @@ /** * matplotlib.pyplot.bar(*args, **kwargs) */ -public interface BarBuilder extends Builder, Line2DBuilder { +public interface BarBuilder extends Builder, Line2DBuilder, KwArgsBuilder { BarBuilder add(List nums); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/BarBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/BarBuilderImpl.java index 41d6491..e2038d6 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/BarBuilderImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/BarBuilderImpl.java @@ -49,6 +49,31 @@ public BarBuilder color(String arg) { return line2DBuilder.color(arg); } + @Override + public BarBuilder addToKwargs(String k, String v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public BarBuilder addToKwargsWithoutQuoting(String k, String v) { + return innerBuilder.addToKwargsWithoutQuoting(k, v); + } + + @Override + public BarBuilder addToKwargs(String k, Number n) { + return innerBuilder.addToKwargs(k, n); + } + + @Override + public BarBuilder addToKwargs(String k, List v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public BarBuilder addToKwargs(String k, boolean v) { + return innerBuilder.addToKwargs(k, v); + } + @Override public String build() { return innerBuilder.build(); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/Builder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/Builder.java index 6aa5e29..d405157 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/Builder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/Builder.java @@ -3,5 +3,13 @@ public interface Builder { String build(); + default boolean returns() { + return true; + } + + default String getMethodPrefix() { + return "plt."; + } + String getMethodName(); } diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/CLabelBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/CLabelBuilder.java index b7026db..1420bcc 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/CLabelBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/CLabelBuilder.java @@ -1,6 +1,8 @@ package com.github.sh0nk.matplotlib4j.builder; -public interface CLabelBuilder extends Builder { +import com.github.sh0nk.matplotlib4j.kwargs.KwArgsBuilder; + +public interface CLabelBuilder extends Builder, KwArgsBuilder { CLabelBuilder fontsize(String arg); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/CLabelBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/CLabelBuilderImpl.java index b08bfe0..add9995 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/CLabelBuilderImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/CLabelBuilderImpl.java @@ -1,5 +1,7 @@ package com.github.sh0nk.matplotlib4j.builder; +import java.util.List; + public class CLabelBuilderImpl implements CLabelBuilder { private final CompositeBuilder innerBuilder = new CompositeBuilder<>(this); @@ -48,6 +50,31 @@ public CLabelBuilder useClabeltext(boolean arg) { return innerBuilder.addToKwargs("use_clabeltext", arg); } + @Override + public CLabelBuilder addToKwargs(String k, String v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public CLabelBuilder addToKwargsWithoutQuoting(String k, String v) { + return innerBuilder.addToKwargsWithoutQuoting(k, v); + } + + @Override + public CLabelBuilder addToKwargs(String k, Number n) { + return innerBuilder.addToKwargs(k, n); + } + + @Override + public CLabelBuilder addToKwargs(String k, List v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public CLabelBuilder addToKwargs(String k, boolean v) { + return innerBuilder.addToKwargs(k, v); + } + @Override public String build() { return innerBuilder.build(); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/CompositeBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/CompositeBuilder.java index 28399e0..89755ce 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/CompositeBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/CompositeBuilder.java @@ -1,6 +1,7 @@ package com.github.sh0nk.matplotlib4j.builder; import com.github.sh0nk.matplotlib4j.TypeConversion; +import com.github.sh0nk.matplotlib4j.kwargs.KwArgsBuilder; import com.google.common.base.Joiner; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -14,7 +15,7 @@ * * @param Owner builder class */ -public class CompositeBuilder implements Builder { +public class CompositeBuilder implements Builder, KwArgsBuilder { private final static Logger LOGGER = LoggerFactory.getLogger(CompositeBuilder.class); @@ -107,9 +108,10 @@ public String build() { } // retName - sb.append(retName).append(" = "); + if (ownerBuilder.returns()) + sb.append(retName).append(" = "); - sb.append("plt."); + sb.append(ownerBuilder.getMethodPrefix()); sb.append(ownerBuilder.getMethodName()); sb.append("("); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/ContourBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/ContourBuilder.java index 8ad803c..365ab6a 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/ContourBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/ContourBuilder.java @@ -1,8 +1,9 @@ package com.github.sh0nk.matplotlib4j.builder; +import com.github.sh0nk.matplotlib4j.kwargs.KwArgsBuilder; import java.util.List; -public interface ContourBuilder extends Builder { +public interface ContourBuilder extends Builder, KwArgsBuilder { /** * Equivalent to {@code pyplot.contour(Z)} diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/ContourBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/ContourBuilderImpl.java index e031667..3cec643 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/ContourBuilderImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/ContourBuilderImpl.java @@ -48,6 +48,31 @@ public String getRetName() { return innerBuilder.getRetName(); } + @Override + public ContourBuilder addToKwargs(String k, String v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public ContourBuilder addToKwargsWithoutQuoting(String k, String v) { + return innerBuilder.addToKwargsWithoutQuoting(k, v); + } + + @Override + public ContourBuilder addToKwargs(String k, Number n) { + return innerBuilder.addToKwargs(k, n); + } + + @Override + public ContourBuilder addToKwargs(String k, List v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public ContourBuilder addToKwargs(String k, boolean v) { + return innerBuilder.addToKwargs(k, v); + } + @Override public String build() { return innerBuilder.build(); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomBuilder.java new file mode 100644 index 0000000..7f852d0 --- /dev/null +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomBuilder.java @@ -0,0 +1,18 @@ +package com.github.sh0nk.matplotlib4j.builder; + +import com.github.sh0nk.matplotlib4j.kwargs.KwArgsBuilder; +import java.util.List; + +public interface CustomBuilder extends Builder, KwArgsBuilder { + + CustomBuilder addToArgs(List objs); + + CustomBuilder add2DimListToArgs(List> numbers); + + CustomBuilder addToArgs(String v); + + CustomBuilder addToArgsWithoutQuoting(String v); + + CustomBuilder addToArgs(Number n); + +} diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomBuilderImpl.java new file mode 100644 index 0000000..78538a6 --- /dev/null +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomBuilderImpl.java @@ -0,0 +1,93 @@ +package com.github.sh0nk.matplotlib4j.builder; + +import java.util.List; + +public class CustomBuilderImpl implements CustomBuilder { + + private final CompositeBuilder innerBuilder = new CompositeBuilder<>(this); + private final String key; + private final String methodPrefix; + private final Boolean returns; + + public CustomBuilderImpl(String key) { + this(null, key, null); + } + + public CustomBuilderImpl(String methodPrefix, String key, Boolean returns) { + this.methodPrefix = methodPrefix; + this.key = key; + this.returns = returns; + } + + @Override + public CustomBuilder addToArgs(List objs) { + return innerBuilder.addToArgs(objs); + } + + @Override + public CustomBuilder add2DimListToArgs(List> numbers) { + return innerBuilder.addToArgs(numbers); + } + + @Override + public CustomBuilder addToArgs(String v) { + return innerBuilder.addToArgs(v); + } + + @Override + public CustomBuilder addToArgsWithoutQuoting(String v) { + return innerBuilder.addToArgsWithoutQuoting(v); + } + + @Override + public CustomBuilder addToArgs(Number n) { + return innerBuilder.addToArgs(n); + } + + @Override + public CustomBuilder addToKwargs(String k, String v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public CustomBuilder addToKwargsWithoutQuoting(String k, String v) { + return innerBuilder.addToKwargsWithoutQuoting(k, v); + } + + @Override + public CustomBuilder addToKwargs(String k, Number n) { + return innerBuilder.addToKwargs(k, n); + } + + @Override + public CustomBuilder addToKwargs(String k, List v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public CustomBuilder addToKwargs(String k, boolean v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public String build() { + return innerBuilder.build(); + } + + @Override + public boolean returns() { + if (returns != null) return returns; + return CustomBuilder.super.returns(); + } + + @Override + public String getMethodPrefix() { + if (methodPrefix != null) return methodPrefix; + return CustomBuilder.super.getMethodPrefix(); + } + + @Override + public String getMethodName() { + return key; + } +} diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilder.java index b1e319a..fdfffe9 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilder.java @@ -1,13 +1,14 @@ package com.github.sh0nk.matplotlib4j.builder; +import com.github.sh0nk.matplotlib4j.kwargs.KwArgsBuilder; import com.github.sh0nk.matplotlib4j.kwargs.Line2DBuilder; import com.github.sh0nk.matplotlib4j.kwargs.TextArgsBuilder; /** * matplotlib.pyplot.grid(b=None, which='major', axis='both', **kwargs)[source] */ -public interface GridBuilder extends Builder, TextArgsBuilder, Line2DBuilder { +public interface GridBuilder extends Builder, TextArgsBuilder, Line2DBuilder, KwArgsBuilder { enum WhichType { major, diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilderImpl.java index 53b2296..f7eb8af 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilderImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/GridBuilderImpl.java @@ -2,6 +2,7 @@ import com.github.sh0nk.matplotlib4j.kwargs.Line2DBuilder; import com.github.sh0nk.matplotlib4j.kwargs.Line2DBuilderImpl; +import java.util.List; public class GridBuilderImpl implements GridBuilder { @@ -57,7 +58,30 @@ public GridBuilder color(String arg) { return line2DBuilder.color(arg); } - // TODO("Add kwargs") + @Override + public GridBuilder addToKwargs(String k, String v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public GridBuilder addToKwargsWithoutQuoting(String k, String v) { + return innerBuilder.addToKwargsWithoutQuoting(k, v); + } + + @Override + public GridBuilder addToKwargs(String k, Number n) { + return innerBuilder.addToKwargs(k, n); + } + + @Override + public GridBuilder addToKwargs(String k, List v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public GridBuilder addToKwargs(String k, boolean v) { + return innerBuilder.addToKwargs(k, v); + } @Override public String build() { diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/HistBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/HistBuilder.java index 07ffd68..e342c87 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/HistBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/HistBuilder.java @@ -1,5 +1,6 @@ package com.github.sh0nk.matplotlib4j.builder; +import com.github.sh0nk.matplotlib4j.kwargs.KwArgsBuilder; import com.github.sh0nk.matplotlib4j.kwargs.PatchBuilder; import java.util.List; @@ -8,7 +9,7 @@ /** * matplotlib.pyplot.hist(x, **kwargs) */ -public interface HistBuilder extends Builder, PatchBuilder { +public interface HistBuilder extends Builder, PatchBuilder, KwArgsBuilder { enum HistType { bar, diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/HistBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/HistBuilderImpl.java index 962bc6b..0747104 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/HistBuilderImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/HistBuilderImpl.java @@ -122,6 +122,31 @@ public HistBuilder label(String arg) { return patchBuilder.label(arg); } + @Override + public HistBuilder addToKwargs(String k, String v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public HistBuilder addToKwargsWithoutQuoting(String k, String v) { + return innerBuilder.addToKwargsWithoutQuoting(k, v); + } + + @Override + public HistBuilder addToKwargs(String k, Number n) { + return innerBuilder.addToKwargs(k, n); + } + + @Override + public HistBuilder addToKwargs(String k, List v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public HistBuilder addToKwargs(String k, boolean v) { + return innerBuilder.addToKwargs(k, v); + } + @Override public String build() { Preconditions.checkArgument(!xList.isEmpty(), ".add() is needed to be called at least once."); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/LabelBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/LabelBuilder.java index e13bc84..fd79ab8 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/LabelBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/LabelBuilder.java @@ -1,5 +1,6 @@ package com.github.sh0nk.matplotlib4j.builder; +import com.github.sh0nk.matplotlib4j.kwargs.KwArgsBuilder; import com.github.sh0nk.matplotlib4j.kwargs.TextArgsBuilder; @@ -7,7 +8,7 @@ * matplotlib.pyplot.xlabel(s, *args, **kwargs) * matplotlib.pyplot.ylabel(s, *args, **kwargs) */ -public interface LabelBuilder extends Builder, TextArgsBuilder { +public interface LabelBuilder extends Builder, TextArgsBuilder, KwArgsBuilder { } diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/LabelBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/LabelBuilderImpl.java index 8f111c1..1321ca6 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/LabelBuilderImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/LabelBuilderImpl.java @@ -1,5 +1,7 @@ package com.github.sh0nk.matplotlib4j.builder; +import java.util.List; + public class LabelBuilderImpl implements LabelBuilder { private CompositeBuilder innerBuilder = new CompositeBuilder<>(this); @@ -18,6 +20,31 @@ public static LabelBuilderImpl yLabelBuilder(String label) { return new LabelBuilderImpl(label, "ylabel"); } + @Override + public LabelBuilder addToKwargs(String k, String v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public LabelBuilder addToKwargsWithoutQuoting(String k, String v) { + return innerBuilder.addToKwargsWithoutQuoting(k, v); + } + + @Override + public LabelBuilder addToKwargs(String k, Number n) { + return innerBuilder.addToKwargs(k, n); + } + + @Override + public LabelBuilder addToKwargs(String k, List v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public LabelBuilder addToKwargs(String k, boolean v) { + return innerBuilder.addToKwargs(k, v); + } + @Override public String build() { return innerBuilder.build(); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/LegendBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/LegendBuilder.java index 399f3d0..97a504a 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/LegendBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/LegendBuilder.java @@ -1,9 +1,11 @@ package com.github.sh0nk.matplotlib4j.builder; +import com.github.sh0nk.matplotlib4j.kwargs.KwArgsBuilder; + /** * matplotlib.pyplot.legend(*args, **kwargs) */ -public interface LegendBuilder extends Builder { +public interface LegendBuilder extends Builder, KwArgsBuilder { LegendBuilder loc(int arg); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/LegendBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/LegendBuilderImpl.java index 5876621..632411a 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/LegendBuilderImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/LegendBuilderImpl.java @@ -1,5 +1,7 @@ package com.github.sh0nk.matplotlib4j.builder; +import java.util.List; + public class LegendBuilderImpl implements LegendBuilder { private CompositeBuilder innerBuilder = new CompositeBuilder<>(this); @@ -19,6 +21,31 @@ public LegendBuilder loc(double x, double y) { return innerBuilder.addToKwargsWithoutQuoting("loc", String.format("(%d, %d)", x, y)); } + @Override + public LegendBuilder addToKwargs(String k, String v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public LegendBuilder addToKwargsWithoutQuoting(String k, String v) { + return innerBuilder.addToKwargsWithoutQuoting(k, v); + } + + @Override + public LegendBuilder addToKwargs(String k, Number n) { + return innerBuilder.addToKwargs(k, n); + } + + @Override + public LegendBuilder addToKwargs(String k, List v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public LegendBuilder addToKwargs(String k, boolean v) { + return innerBuilder.addToKwargs(k, v); + } + @Override public String build() { return innerBuilder.build(); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/PColorBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/PColorBuilder.java index 1f50309..12f1c21 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/PColorBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/PColorBuilder.java @@ -1,8 +1,9 @@ package com.github.sh0nk.matplotlib4j.builder; +import com.github.sh0nk.matplotlib4j.kwargs.KwArgsBuilder; import java.util.List; -public interface PColorBuilder extends Builder { +public interface PColorBuilder extends Builder, KwArgsBuilder { /** * Equivalent to {@code pyplot.pcolor(C)} diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/PColorBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/PColorBuilderImpl.java index 6132c12..50d40c3 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/PColorBuilderImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/PColorBuilderImpl.java @@ -48,6 +48,31 @@ public String getRetName() { return innerBuilder.getRetName(); } + @Override + public PColorBuilder addToKwargs(String k, String v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public PColorBuilder addToKwargsWithoutQuoting(String k, String v) { + return innerBuilder.addToKwargsWithoutQuoting(k, v); + } + + @Override + public PColorBuilder addToKwargs(String k, Number n) { + return innerBuilder.addToKwargs(k, n); + } + + @Override + public PColorBuilder addToKwargs(String k, List v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public PColorBuilder addToKwargs(String k, boolean v) { + return innerBuilder.addToKwargs(k, v); + } + @Override public String build() { return innerBuilder.build(); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/PlotBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/PlotBuilder.java index 7f70a8c..760903f 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/PlotBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/PlotBuilder.java @@ -1,5 +1,6 @@ package com.github.sh0nk.matplotlib4j.builder; +import com.github.sh0nk.matplotlib4j.kwargs.KwArgsBuilder; import com.github.sh0nk.matplotlib4j.kwargs.Line2DBuilder; import java.util.List; @@ -8,7 +9,7 @@ /** * matplotlib.pyplot.plot(*args, **kwargs) */ -public interface PlotBuilder extends Builder, Line2DBuilder { +public interface PlotBuilder extends Builder, Line2DBuilder, KwArgsBuilder { PlotBuilder add(List nums); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/PlotBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/PlotBuilderImpl.java index 90dab0e..d83b4d7 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/PlotBuilderImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/PlotBuilderImpl.java @@ -63,6 +63,31 @@ public PlotBuilder color(String arg) { return line2DBuilder.color(arg); } + @Override + public PlotBuilder addToKwargs(String k, String v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public PlotBuilder addToKwargsWithoutQuoting(String k, String v) { + return innerBuilder.addToKwargsWithoutQuoting(k, v); + } + + @Override + public PlotBuilder addToKwargs(String k, Number n) { + return innerBuilder.addToKwargs(k, n); + } + + @Override + public PlotBuilder addToKwargs(String k, List v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public PlotBuilder addToKwargs(String k, boolean v) { + return innerBuilder.addToKwargs(k, v); + } + @Override public String build() { return innerBuilder.build(); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/SaveFigBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/SaveFigBuilder.java index 425544b..2e47757 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/SaveFigBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/SaveFigBuilder.java @@ -1,9 +1,11 @@ package com.github.sh0nk.matplotlib4j.builder; +import com.github.sh0nk.matplotlib4j.kwargs.KwArgsBuilder; + /** * matplotlib.pyplot.savefig(fname, **kwargs) */ -public interface SaveFigBuilder extends Builder { +public interface SaveFigBuilder extends Builder, KwArgsBuilder { enum Orientation { horizontal, diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/SaveFigBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/SaveFigBuilderImpl.java index 6bb93d0..d20232e 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/SaveFigBuilderImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/SaveFigBuilderImpl.java @@ -1,5 +1,7 @@ package com.github.sh0nk.matplotlib4j.builder; +import java.util.List; + public class SaveFigBuilderImpl implements SaveFigBuilder { private final CompositeBuilder innerBuilder = new CompositeBuilder<>(this); @@ -48,6 +50,31 @@ public SaveFigBuilder bboxInches(double arg) { return innerBuilder.addToKwargs("bboxInches", arg); } + @Override + public SaveFigBuilder addToKwargs(String k, String v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public SaveFigBuilder addToKwargsWithoutQuoting(String k, String v) { + return innerBuilder.addToKwargsWithoutQuoting(k, v); + } + + @Override + public SaveFigBuilder addToKwargs(String k, Number n) { + return innerBuilder.addToKwargs(k, n); + } + + @Override + public SaveFigBuilder addToKwargs(String k, List v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public SaveFigBuilder addToKwargs(String k, boolean v) { + return innerBuilder.addToKwargs(k, v); + } + @Override public String build() { return innerBuilder.build(); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/ScaleBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/ScaleBuilder.java index 1c584a4..c65232f 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/ScaleBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/ScaleBuilder.java @@ -1,12 +1,13 @@ package com.github.sh0nk.matplotlib4j.builder; +import com.github.sh0nk.matplotlib4j.kwargs.KwArgsBuilder; import com.github.sh0nk.matplotlib4j.kwargs.TextArgsBuilder; /** * matplotlib.pyplot.xscale(scale, **kwargs) * matplotlib.pyplot.yscale(scale, **kwargs) */ -public interface ScaleBuilder extends Builder, TextArgsBuilder { +public interface ScaleBuilder extends Builder, TextArgsBuilder, KwArgsBuilder { enum Scale { linear, diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/ScaleBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/ScaleBuilderImpl.java index ae7d948..6049bcd 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/ScaleBuilderImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/ScaleBuilderImpl.java @@ -1,5 +1,7 @@ package com.github.sh0nk.matplotlib4j.builder; +import java.util.List; + public class ScaleBuilderImpl implements ScaleBuilder { private CompositeBuilder innerBuilder = new CompositeBuilder<>(this); @@ -18,6 +20,31 @@ public static ScaleBuilderImpl yScaleBuilder(Scale scale) { return new ScaleBuilderImpl(scale, "yscale"); } + @Override + public ScaleBuilder addToKwargs(String k, String v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public ScaleBuilder addToKwargsWithoutQuoting(String k, String v) { + return innerBuilder.addToKwargsWithoutQuoting(k, v); + } + + @Override + public ScaleBuilder addToKwargs(String k, Number n) { + return innerBuilder.addToKwargs(k, n); + } + + @Override + public ScaleBuilder addToKwargs(String k, List v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public ScaleBuilder addToKwargs(String k, boolean v) { + return innerBuilder.addToKwargs(k, v); + } + @Override public String build() { return innerBuilder.build(); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/ScatterBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/ScatterBuilder.java index f1ffb04..9079504 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/ScatterBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/ScatterBuilder.java @@ -1,5 +1,6 @@ package com.github.sh0nk.matplotlib4j.builder; +import com.github.sh0nk.matplotlib4j.kwargs.KwArgsBuilder; import com.github.sh0nk.matplotlib4j.kwargs.Line2DBuilder; import java.util.List; @@ -8,7 +9,7 @@ /** * matplotlib.pyplot.scatter(*args, **kwargs) */ -public interface ScatterBuilder extends Builder { +public interface ScatterBuilder extends Builder, KwArgsBuilder { ScatterBuilder add(List x); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/ScatterBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/ScatterBuilderImpl.java index 451d04d..4666aa2 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/ScatterBuilderImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/ScatterBuilderImpl.java @@ -75,6 +75,31 @@ public ScatterBuilder plotnonfinite(boolean plotnonfinite) { return innerBuilder.addToKwargs("plotnonfinite", plotnonfinite); } + @Override + public ScatterBuilder addToKwargs(String k, String v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public ScatterBuilder addToKwargsWithoutQuoting(String k, String v) { + return innerBuilder.addToKwargsWithoutQuoting(k, v); + } + + @Override + public ScatterBuilder addToKwargs(String k, Number n) { + return innerBuilder.addToKwargs(k, n); + } + + @Override + public ScatterBuilder addToKwargs(String k, List v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public ScatterBuilder addToKwargs(String k, boolean v) { + return innerBuilder.addToKwargs(k, v); + } + @Override public String build() { return innerBuilder.build(); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/SubplotBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/SubplotBuilder.java index 34af2ea..654af26 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/SubplotBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/SubplotBuilder.java @@ -1,4 +1,6 @@ package com.github.sh0nk.matplotlib4j.builder; -public interface SubplotBuilder extends Builder { +import com.github.sh0nk.matplotlib4j.kwargs.KwArgsBuilder; + +public interface SubplotBuilder extends Builder, KwArgsBuilder { } diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/SubplotBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/SubplotBuilderImpl.java index 14287df..68e7189 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/SubplotBuilderImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/SubplotBuilderImpl.java @@ -1,5 +1,7 @@ package com.github.sh0nk.matplotlib4j.builder; +import java.util.List; + public class SubplotBuilderImpl implements SubplotBuilder { private final CompositeBuilder innerBuilder = new CompositeBuilder<>(this); @@ -9,6 +11,31 @@ public SubplotBuilderImpl(int nrows, int ncols, int index) { innerBuilder.addToArgs(index); } + @Override + public SubplotBuilder addToKwargs(String k, String v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public SubplotBuilder addToKwargsWithoutQuoting(String k, String v) { + return innerBuilder.addToKwargsWithoutQuoting(k, v); + } + + @Override + public SubplotBuilder addToKwargs(String k, Number n) { + return innerBuilder.addToKwargs(k, n); + } + + @Override + public SubplotBuilder addToKwargs(String k, List v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public SubplotBuilder addToKwargs(String k, boolean v) { + return innerBuilder.addToKwargs(k, v); + } + @Override public String build() { return innerBuilder.build(); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/TextBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/TextBuilder.java index 8e5ac7d..cae9447 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/TextBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/TextBuilder.java @@ -1,4 +1,6 @@ package com.github.sh0nk.matplotlib4j.builder; -public interface TextBuilder extends Builder { +import com.github.sh0nk.matplotlib4j.kwargs.KwArgsBuilder; + +public interface TextBuilder extends Builder, KwArgsBuilder { } diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/TextBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/TextBuilderImpl.java index a48e197..153656e 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/TextBuilderImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/TextBuilderImpl.java @@ -2,6 +2,7 @@ import com.github.sh0nk.matplotlib4j.kwargs.TextArgsBuilder; import com.github.sh0nk.matplotlib4j.kwargs.TextArgsBuilderImpl; +import java.util.List; public class TextBuilderImpl implements TextBuilder { @@ -15,6 +16,31 @@ public TextBuilderImpl(double x, double y, String s) { innerBuilder.addToArgs(s); } + @Override + public TextBuilder addToKwargs(String k, String v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public TextBuilder addToKwargsWithoutQuoting(String k, String v) { + return innerBuilder.addToKwargsWithoutQuoting(k, v); + } + + @Override + public TextBuilder addToKwargs(String k, Number n) { + return innerBuilder.addToKwargs(k, n); + } + + @Override + public TextBuilder addToKwargs(String k, List v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public TextBuilder addToKwargs(String k, boolean v) { + return innerBuilder.addToKwargs(k, v); + } + @Override public String build() { return innerBuilder.build(); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/TicksBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/TicksBuilder.java index 7cd28e7..12f5e9a 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/TicksBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/TicksBuilder.java @@ -1,5 +1,6 @@ package com.github.sh0nk.matplotlib4j.builder; +import com.github.sh0nk.matplotlib4j.kwargs.KwArgsBuilder; import com.github.sh0nk.matplotlib4j.kwargs.TextArgsBuilder; import java.util.List; @@ -9,7 +10,7 @@ * matplotlib.pyplot.xticks(ticks=None, labels=None, **kwargs) * matplotlib.pyplot.yticks(ticks=None, labels=None, **kwargs) */ -public interface TicksBuilder extends Builder, TextArgsBuilder { +public interface TicksBuilder extends Builder, TextArgsBuilder, KwArgsBuilder { TicksBuilder labels(List labels); } diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/TicksBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/TicksBuilderImpl.java index 421484a..d56920b 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/TicksBuilderImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/TicksBuilderImpl.java @@ -35,6 +35,31 @@ public static TicksBuilderImpl yTicksBuilder(List ticks) { return new TicksBuilderImpl(ticks, "yticks"); } + @Override + public TicksBuilder addToKwargs(String k, String v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public TicksBuilder addToKwargsWithoutQuoting(String k, String v) { + return innerBuilder.addToKwargsWithoutQuoting(k, v); + } + + @Override + public TicksBuilder addToKwargs(String k, Number n) { + return innerBuilder.addToKwargs(k, n); + } + + @Override + public TicksBuilder addToKwargs(String k, List v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public TicksBuilder addToKwargs(String k, boolean v) { + return innerBuilder.addToKwargs(k, v); + } + @Override public String build() { return innerBuilder.build(); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/kwargs/KwArgsBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/kwargs/KwArgsBuilder.java new file mode 100644 index 0000000..7194f05 --- /dev/null +++ b/src/main/java/com/github/sh0nk/matplotlib4j/kwargs/KwArgsBuilder.java @@ -0,0 +1,18 @@ +package com.github.sh0nk.matplotlib4j.kwargs; + +import com.github.sh0nk.matplotlib4j.builder.Builder; +import java.util.List; + +public interface KwArgsBuilder { + + T addToKwargs(String k, String v); + + T addToKwargsWithoutQuoting(String k, String v); + + T addToKwargs(String k, Number n); + + T addToKwargs(String k, List v); + + T addToKwargs(String k, boolean v); + +} diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/kwargs/KwargsBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/kwargs/KwargsBuilder.java deleted file mode 100644 index bc908dc..0000000 --- a/src/main/java/com/github/sh0nk/matplotlib4j/kwargs/KwargsBuilder.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.github.sh0nk.matplotlib4j.kwargs; - -public interface KwargsBuilder { - -} diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/kwargs/Line2DBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/kwargs/Line2DBuilder.java index eb62521..4606f08 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/kwargs/Line2DBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/kwargs/Line2DBuilder.java @@ -2,7 +2,7 @@ import com.github.sh0nk.matplotlib4j.builder.Builder; -public interface Line2DBuilder extends KwargsBuilder { +public interface Line2DBuilder { T linestyle(String arg); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/kwargs/PatchBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/kwargs/PatchBuilder.java index 0b48512..e9fb0bb 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/kwargs/PatchBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/kwargs/PatchBuilder.java @@ -2,7 +2,7 @@ import com.github.sh0nk.matplotlib4j.builder.Builder; -public interface PatchBuilder extends KwargsBuilder { +public interface PatchBuilder { T linestyle(String arg); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/kwargs/TextArgsBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/kwargs/TextArgsBuilder.java index b95977d..d1fc050 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/kwargs/TextArgsBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/kwargs/TextArgsBuilder.java @@ -2,7 +2,7 @@ import com.github.sh0nk.matplotlib4j.builder.Builder; -public interface TextArgsBuilder extends KwargsBuilder { +public interface TextArgsBuilder { } From b66e75a70020f03a6977316f1d7176c899a63727 Mon Sep 17 00:00:00 2001 From: Nico Mexis Date: Sun, 17 Sep 2023 08:44:59 +0200 Subject: [PATCH 15/17] Fix custom builder --- src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java index 8010bbd..b6673c9 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java @@ -28,12 +28,16 @@ public class PlotImpl implements Plot { @Override public CustomBuilder cmd(String key) { - return new CustomBuilderImpl(key); + CustomBuilder builder = new CustomBuilderImpl(key); + registeredBuilders.add(builder); + return builder; } @Override public CustomBuilder cmd(String methodPrefix, String key, Boolean returns) { - return new CustomBuilderImpl(methodPrefix, key, returns); + CustomBuilder builder = new CustomBuilderImpl(methodPrefix, key, returns); + registeredBuilders.add(builder); + return builder; } @Override From 16d956ab78fbd1dfa756943ff2e84dce92561c6a Mon Sep 17 00:00:00 2001 From: Nico Mexis Date: Mon, 18 Sep 2023 20:18:36 +0200 Subject: [PATCH 16/17] Add custom py lines --- .../com/github/sh0nk/matplotlib4j/Plot.java | 6 +- .../github/sh0nk/matplotlib4j/PlotImpl.java | 15 ++- .../matplotlib4j/builder/CustomBuilder.java | 22 +---- .../builder/CustomBuilderImpl.java | 77 ++------------- .../builder/CustomCmdBuilder.java | 18 ++++ .../builder/CustomCmdBuilderImpl.java | 93 +++++++++++++++++++ 6 files changed, 137 insertions(+), 94 deletions(-) create mode 100644 src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomCmdBuilder.java create mode 100644 src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomCmdBuilderImpl.java diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java b/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java index 81e6117..da333b2 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java @@ -15,9 +15,11 @@ static Plot create(PythonConfig pythonConfig) { return new PlotImpl(pythonConfig, false); } - CustomBuilder cmd(String key); + CustomBuilder py(String cmd); - CustomBuilder cmd(String methodPrefix, String key, Boolean returns); + CustomCmdBuilder cmd(String key); + + CustomCmdBuilder cmd(String methodPrefix, String key, Boolean returns); GridBuilder grid(); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java index b6673c9..831353a 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java @@ -27,15 +27,22 @@ public class PlotImpl implements Plot { } @Override - public CustomBuilder cmd(String key) { - CustomBuilder builder = new CustomBuilderImpl(key); + public CustomBuilder py(String cmd) { + CustomBuilder builder = new CustomBuilderImpl(cmd); registeredBuilders.add(builder); return builder; } @Override - public CustomBuilder cmd(String methodPrefix, String key, Boolean returns) { - CustomBuilder builder = new CustomBuilderImpl(methodPrefix, key, returns); + public CustomCmdBuilder cmd(String key) { + CustomCmdBuilder builder = new CustomCmdBuilderImpl(key); + registeredBuilders.add(builder); + return builder; + } + + @Override + public CustomCmdBuilder cmd(String methodPrefix, String key, Boolean returns) { + CustomCmdBuilder builder = new CustomCmdBuilderImpl(methodPrefix, key, returns); registeredBuilders.add(builder); return builder; } diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomBuilder.java index 7f852d0..5c6d710 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomBuilder.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomBuilder.java @@ -1,18 +1,4 @@ -package com.github.sh0nk.matplotlib4j.builder; - -import com.github.sh0nk.matplotlib4j.kwargs.KwArgsBuilder; -import java.util.List; - -public interface CustomBuilder extends Builder, KwArgsBuilder { - - CustomBuilder addToArgs(List objs); - - CustomBuilder add2DimListToArgs(List> numbers); - - CustomBuilder addToArgs(String v); - - CustomBuilder addToArgsWithoutQuoting(String v); - - CustomBuilder addToArgs(Number n); - -} +package com.github.sh0nk.matplotlib4j.builder; + +public interface CustomBuilder extends Builder { +} diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomBuilderImpl.java index 78538a6..501fe74 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomBuilderImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomBuilderImpl.java @@ -1,93 +1,30 @@ package com.github.sh0nk.matplotlib4j.builder; -import java.util.List; - public class CustomBuilderImpl implements CustomBuilder { - private final CompositeBuilder innerBuilder = new CompositeBuilder<>(this); - private final String key; - private final String methodPrefix; - private final Boolean returns; - - public CustomBuilderImpl(String key) { - this(null, key, null); - } - - public CustomBuilderImpl(String methodPrefix, String key, Boolean returns) { - this.methodPrefix = methodPrefix; - this.key = key; - this.returns = returns; - } - - @Override - public CustomBuilder addToArgs(List objs) { - return innerBuilder.addToArgs(objs); - } - - @Override - public CustomBuilder add2DimListToArgs(List> numbers) { - return innerBuilder.addToArgs(numbers); - } - - @Override - public CustomBuilder addToArgs(String v) { - return innerBuilder.addToArgs(v); - } - - @Override - public CustomBuilder addToArgsWithoutQuoting(String v) { - return innerBuilder.addToArgsWithoutQuoting(v); - } + private final String cmd; - @Override - public CustomBuilder addToArgs(Number n) { - return innerBuilder.addToArgs(n); - } - - @Override - public CustomBuilder addToKwargs(String k, String v) { - return innerBuilder.addToKwargs(k, v); - } - - @Override - public CustomBuilder addToKwargsWithoutQuoting(String k, String v) { - return innerBuilder.addToKwargsWithoutQuoting(k, v); - } - - @Override - public CustomBuilder addToKwargs(String k, Number n) { - return innerBuilder.addToKwargs(k, n); - } - - @Override - public CustomBuilder addToKwargs(String k, List v) { - return innerBuilder.addToKwargs(k, v); - } - - @Override - public CustomBuilder addToKwargs(String k, boolean v) { - return innerBuilder.addToKwargs(k, v); + public CustomBuilderImpl(String cmd) { + this.cmd = cmd; } @Override public String build() { - return innerBuilder.build(); + return cmd; } @Override public boolean returns() { - if (returns != null) return returns; - return CustomBuilder.super.returns(); + return false; } @Override public String getMethodPrefix() { - if (methodPrefix != null) return methodPrefix; - return CustomBuilder.super.getMethodPrefix(); + return null; } @Override public String getMethodName() { - return key; + return null; } } diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomCmdBuilder.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomCmdBuilder.java new file mode 100644 index 0000000..5ce33ea --- /dev/null +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomCmdBuilder.java @@ -0,0 +1,18 @@ +package com.github.sh0nk.matplotlib4j.builder; + +import com.github.sh0nk.matplotlib4j.kwargs.KwArgsBuilder; +import java.util.List; + +public interface CustomCmdBuilder extends Builder, KwArgsBuilder { + + CustomCmdBuilder addToArgs(List objs); + + CustomCmdBuilder add2DimListToArgs(List> numbers); + + CustomCmdBuilder addToArgs(String v); + + CustomCmdBuilder addToArgsWithoutQuoting(String v); + + CustomCmdBuilder addToArgs(Number n); + +} diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomCmdBuilderImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomCmdBuilderImpl.java new file mode 100644 index 0000000..2a30d09 --- /dev/null +++ b/src/main/java/com/github/sh0nk/matplotlib4j/builder/CustomCmdBuilderImpl.java @@ -0,0 +1,93 @@ +package com.github.sh0nk.matplotlib4j.builder; + +import java.util.List; + +public class CustomCmdBuilderImpl implements CustomCmdBuilder { + + private final CompositeBuilder innerBuilder = new CompositeBuilder<>(this); + private final String key; + private final String methodPrefix; + private final Boolean returns; + + public CustomCmdBuilderImpl(String key) { + this(null, key, null); + } + + public CustomCmdBuilderImpl(String methodPrefix, String key, Boolean returns) { + this.methodPrefix = methodPrefix; + this.key = key; + this.returns = returns; + } + + @Override + public CustomCmdBuilder addToArgs(List objs) { + return innerBuilder.addToArgs(objs); + } + + @Override + public CustomCmdBuilder add2DimListToArgs(List> numbers) { + return innerBuilder.addToArgs(numbers); + } + + @Override + public CustomCmdBuilder addToArgs(String v) { + return innerBuilder.addToArgs(v); + } + + @Override + public CustomCmdBuilder addToArgsWithoutQuoting(String v) { + return innerBuilder.addToArgsWithoutQuoting(v); + } + + @Override + public CustomCmdBuilder addToArgs(Number n) { + return innerBuilder.addToArgs(n); + } + + @Override + public CustomCmdBuilder addToKwargs(String k, String v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public CustomCmdBuilder addToKwargsWithoutQuoting(String k, String v) { + return innerBuilder.addToKwargsWithoutQuoting(k, v); + } + + @Override + public CustomCmdBuilder addToKwargs(String k, Number n) { + return innerBuilder.addToKwargs(k, n); + } + + @Override + public CustomCmdBuilder addToKwargs(String k, List v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public CustomCmdBuilder addToKwargs(String k, boolean v) { + return innerBuilder.addToKwargs(k, v); + } + + @Override + public String build() { + return innerBuilder.build(); + } + + @Override + public boolean returns() { + if (returns != null) return returns; + return CustomCmdBuilder.super.returns(); + } + + @Override + public String getMethodPrefix() { + if (methodPrefix != null) return methodPrefix; + return CustomCmdBuilder.super.getMethodPrefix(); + } + + @Override + public String getMethodName() { + return key; + } +} From 22123a233433d84805a2bc334f4833148bcef7e9 Mon Sep 17 00:00:00 2001 From: Nico Mexis Date: Mon, 18 Sep 2023 20:23:54 +0200 Subject: [PATCH 17/17] Allow changing pyplot import name --- .../java/com/github/sh0nk/matplotlib4j/Plot.java | 8 ++++++++ .../java/com/github/sh0nk/matplotlib4j/PlotImpl.java | 12 +++++++++--- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java b/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java index da333b2..2ab22fe 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/Plot.java @@ -11,10 +11,18 @@ static Plot create() { return new PlotImpl(PythonConfig.systemDefaultPythonConfig(), false); } + static Plot create(String mplImportName) { + return new PlotImpl(PythonConfig.systemDefaultPythonConfig(), false, mplImportName); + } + static Plot create(PythonConfig pythonConfig) { return new PlotImpl(pythonConfig, false); } + static Plot create(PythonConfig pythonConfig, String mplImportName) { + return new PlotImpl(pythonConfig, false, mplImportName); + } + CustomBuilder py(String cmd); CustomCmdBuilder cmd(String key); diff --git a/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java b/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java index 831353a..940a3bf 100644 --- a/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java +++ b/src/main/java/com/github/sh0nk/matplotlib4j/PlotImpl.java @@ -15,10 +15,16 @@ public class PlotImpl implements Plot { private final boolean dryRun; private final PythonConfig pythonConfig; + private final String pplImportName; - PlotImpl(PythonConfig pythonConfig, boolean dryRun) { + PlotImpl(PythonConfig pythonConfig, boolean dryRun, String pplImportName) { this.pythonConfig = pythonConfig; this.dryRun = dryRun; + this.pplImportName = pplImportName; + } + + PlotImpl(PythonConfig pythonConfig, boolean dryRun) { + this(pythonConfig, dryRun, "plt"); } @VisibleForTesting @@ -223,7 +229,7 @@ public void executeSilently() throws IOException, PythonExecutionException { scriptLines.add("import numpy as np"); scriptLines.add("import matplotlib as mpl"); scriptLines.add("mpl.use('Agg')"); - scriptLines.add("import matplotlib.pyplot as plt"); + scriptLines.add("import matplotlib.pyplot as " + pplImportName); registeredBuilders.forEach(b -> scriptLines.add(b.build())); showBuilders.forEach(b -> scriptLines.add(b.build())); PyCommand command = new PyCommand(pythonConfig); @@ -242,7 +248,7 @@ public void show() throws IOException, PythonExecutionException { scriptLines.add("import matplotlib as mpl"); scriptLines.add("mpl.use('Agg')"); } - scriptLines.add("import matplotlib.pyplot as plt"); + scriptLines.add("import matplotlib.pyplot as " + pplImportName); registeredBuilders.forEach(b -> scriptLines.add(b.build())); // show