├── CITATION.cff ├── LICENSE ├── README.md ├── figures ├── arc1.png ├── arc2.png ├── arc3.png ├── arc4.png ├── area1.png ├── area2.png ├── bugfix1.png ├── bugfix2.png ├── catspline1.png ├── catspline2.png ├── circle1.png ├── circle2.png ├── circle3.png ├── circle4.png ├── circle5.png ├── circle6.png ├── labsplit0.png ├── labsplit1.png ├── labsplit2.png ├── labsplit3.png ├── pie1.png ├── pie2.png ├── pie3.png ├── pie4.png ├── pie5.png ├── rotate1.png ├── rotate2.png ├── rotate3.png ├── rotate4.png ├── shapes1.png ├── shapes1_1.png ├── shapes1_2.png ├── shapes2.png ├── shapes3.png ├── shapes4.png ├── shapes5.png ├── shapes_circle1.png ├── shapes_circle2.png ├── shapes_circle3.png ├── shapes_circle4.png ├── shapes_circle5.png ├── shapes_circle6.png ├── square1.png └── square2.png └── installation ├── arc.ado ├── arc.sthlp ├── catspline.ado ├── catspline.sthlp ├── graphfunctions.pkg ├── graphfunctions.sthlp ├── labsplit.ado ├── labsplit.sthlp ├── shape.ado ├── shape.sthlp ├── shapes.ado ├── shapes.sthlp └── stata.toc /CITATION.cff: -------------------------------------------------------------------------------- 1 | cff-version: 1.2.0 2 | authors: 3 | - family-names: "Naqvi" 4 | given-names: "Asjad" 5 | title: "Stata package ``graphfunctions''" 6 | version: 1.52 7 | date-released: 2025-02-18 8 | url: "https://github.com/asjadnaqvi/stata-graphfunctions" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Asjad Naqvi 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ![StataMin](https://img.shields.io/badge/stata-2011-blue) ![issues](https://img.shields.io/github/issues/asjadnaqvi/stata-graphfunctions) ![license](https://img.shields.io/github/license/asjadnaqvi/stata-graphfunctions) ![Stars](https://img.shields.io/github/stars/asjadnaqvi/stata-graphfunctions) ![version](https://img.shields.io/github/v/release/asjadnaqvi/stata-graphfunctions) ![release](https://img.shields.io/github/release-date/asjadnaqvi/stata-graphfunctions) 3 | 4 | [Installation](#Installation) | [Examples](#Examples) | [Feedback](#Feedback) | [Change log](#Change-log) 5 | 6 | --- 7 | 8 | 9 | 10 | # graphfunctions v1.52 11 | *(18 Feb 2025)* 12 | 13 | A suite of graph functions for Stata. The program is designed to be called by other programs, but it can be used as a standalone as well. The page will provide some minimum examples, but for the full scope, see the relevant help files. 14 | 15 | Currently, this package contains: 16 | 17 | 18 | |Program|Version|Updated|Description| 19 | |----| ---- | ---- | ----- | 20 | | [labsplit](#labsplit) | 1.1 | 08 Oct 2024 | Text wrapping | 21 | | [catspline](#catspline) | 1.2 | 18 Feb 2025 | Catmull-Rom splines | 22 | | [arc](#arc) | 1.2 | 20 Nov 2024 | Draw arcs between two points | 23 | | [shapes](#shapes) | 1.3 | 05 Nov 2024 | Contains `shapes circle`, `shapes pie`, `shapes square`, `shapes rotate`, `shapes area` | 24 | 25 | 26 | The programs here are designed/upgraded/bug-fixed on a needs basis, mostly to support other packages. If you have specific requests, or find major bugs, then please open an [issue](https://github.com/asjadnaqvi/stata-graphfunctions/issues). 27 | 28 | ## Installation 29 | 30 | The package can be installed via SSC or GitHub. The GitHub version, *might* be more recent due to bug fixes, feature updates etc, and *may* contain syntax improvements and changes in *default* values. See version numbers below. Eventually the GitHub version is published on SSC. 31 | 32 | SSC (**v1.52**): 33 | 34 | ```stata 35 | ssc install graphfunctions, replace 36 | ``` 37 | 38 | GitHub (**v1.52**): 39 | 40 | ```stata 41 | net install graphfunctions, from("https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/main/installation/") replace 42 | ``` 43 | 44 | See the help file `help graphfunctions` for details. 45 | 46 | 47 | If you want to make a clean figure, then it is advisable to load a clean scheme, especially if you are not using newer Stata versions. My own setting is the following: 48 | 49 | ```stata 50 | ssc install schemepack, replace 51 | set scheme white_tableau 52 | graph set window fontface "Arial Narrow" 53 | ``` 54 | 55 | ## Examples 56 | 57 | ### labsplit 58 | *(v1.1: 08 Oct 2024)* 59 | 60 | The program allows users to split text labels based on flexible or fixed character length or word positions. 61 | 62 | Syntax: 63 | ```stata 64 | labsplit variable, [ wrap(int) word(int) strict generate(newvar) ] 65 | ``` 66 | 67 | Examples: 68 | 69 | ```stata 70 | clear 71 | set obs 5 72 | gen x = 1 73 | gen y = _n 74 | 75 | gen mylab = "" 76 | 77 | replace mylab = "Test this really-hyphenated label." in 1 78 | replace mylab = "Yet another label to test." in 2 79 | replace mylab = "This is the third label" in 3 80 | replace mylab = "How about we test this label as well" in 4 81 | replace mylab = "Finally we are at the fifth label" in 5 82 | 83 | ``` 84 | 85 | Let's test the `labsplit` command: 86 | 87 | ```stata 88 | labsplit mylab, wrap(10) gen(newlab1) 89 | labsplit mylab, wrap(10) gen(newlab2) strict 90 | labsplit mylab, word(2) gen(newlab3) 91 | ``` 92 | 93 | Code for figures: 94 | 95 | ``` 96 | twoway (scatter y x, mlabel(mylab) mlabsize(3)), title("Standard") 97 | twoway (scatter y x, mlabel(newlab1) mlabsize(3)), title("Wrapping") 98 | 99 | twoway (scatter y x, mlabel(newlab2) mlabsize(3)), title("Wrapping strict") 100 | twoway (scatter y x, mlabel(newlab3) mlabsize(3)), title("Word wrap") 101 | ``` 102 | 103 | 104 | 105 | 106 | ### catspline 107 | *(v1.2: 18 Feb 2025)* 108 | 109 | 110 | The program allows users to generate splines based on the [Catmull-Rom algorithm](https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline). 111 | 112 | Syntax: 113 | ```stata 114 | catspline y x, [ rho(num [0,1]) obs(int) close genx(newvar) geny(newvar) ] 115 | ``` 116 | 117 | Examples: 118 | 119 | ```stata 120 | clear 121 | set obs 5 122 | set seed 2021 123 | 124 | gen x = runiformint(1,5) 125 | gen y = runiformint(1,5) 126 | 127 | 128 | catspline y x 129 | 130 | twoway /// 131 | (scatter y x) /// 132 | (line _y _x, cmissing(n)) 133 | ``` 134 | 135 | 136 | 137 | ```stata 138 | cap drop _id _x _y 139 | catspline y x, close 140 | 141 | twoway /// 142 | (scatter y x) /// 143 | (line _y _x, cmissing(n)) 144 | ``` 145 | 146 | 147 | 148 | 149 | ### arc 150 | *(v1.1)* 151 | 152 | Draw minor or major arcs between two points. The arc orientation and be switched using `swap`, and major arcs can be drawn using `major`. 153 | 154 | Syntax: 155 | 156 | ```stata 157 | arc, x1(num) y1(num) x2(num) y2(num) [ radius(num) n(int) swap major genx(newvar) geny(newvar) replace ] 158 | ``` 159 | 160 | Examples: 161 | 162 | 163 | ```stata 164 | arc, y1(-2) x1(-4) y2(4) x2(2) rad(6) replace 165 | 166 | twoway /// 167 | (scatteri -2 -4) (scatteri 4 2) /// 168 | (scatteri `r(ycirc)' `r(xcirc)') /// 169 | (line _y _x) /// 170 | , legend(order(1 "Point 1" 2 "Point 2" 3 "Circumcenter" 4 "Arc") pos(6) row(1)) /// 171 | xlabel(-10(2)10) ylabel(-10(2)10) aspect(1) xsize(1) ysize(1) /// 172 | title("Right of starting point - minor") 173 | ``` 174 | 175 | 176 | 177 | ```stata 178 | arc, y1(-2) x1(-4) y2(4) x2(2) rad(6) major replace 179 | 180 | twoway /// 181 | (scatteri -2 -4) (scatteri 4 2) /// 182 | (scatteri `r(ycirc)' `r(xcirc)') /// 183 | (line _y _x) /// 184 | , legend(order(1 "Point 1" 2 "Point 2" 3 "Circumcenter" 4 "Arc") pos(6) row(1)) /// 185 | xlabel(-10(2)10) ylabel(-10(2)10) aspect(1) xsize(1) ysize(1) /// 186 | title("Right of starting point - major") 187 | 188 | ``` 189 | 190 | 191 | 192 | ```stata 193 | arc, y1(-2) x1(-4) y2(4) x2(2) rad(6) swap replace 194 | 195 | twoway /// 196 | (scatteri -2 -4) (scatteri 4 2) /// 197 | (scatteri `r(ycirc)' `r(xcirc)') /// 198 | (line _y _x) /// 199 | , legend(order(1 "Point 1" 2 "Point 2" 3 "Circumcenter" 4 "Arc") pos(6) row(1)) /// 200 | xlabel(-10(2)10) ylabel(-10(2)10) aspect(1) xsize(1) ysize(1) /// 201 | title("Left of starting point - minor") 202 | ``` 203 | 204 | 205 | 206 | ```stata 207 | arc, y1(-2) x1(-4) y2(4) x2(2) rad(6) swap major replace 208 | 209 | twoway /// 210 | (scatteri -2 -4) (scatteri 4 2) /// 211 | (scatteri `r(ycirc)' `r(xcirc)') /// 212 | (line _y _x) /// 213 | , legend(order(1 "Point 1" 2 "Point 2" 3 "Circumcenter" 4 "Arc") pos(6) row(1)) /// 214 | xlabel(-10(2)10) ylabel(-10(2)10) aspect(1) xsize(1) ysize(1) /// 215 | title("Left of starting point - Major") 216 | ``` 217 | 218 | 219 | 220 | 221 | ### shapes 222 | *(v1.3)* 223 | 224 | **Circles** 225 | 226 | 227 | Syntax: 228 | ```stata 229 | shape circle, [ n(int) rotate(degrees) radius(num) x0(num) y0(num) genx(newvar) geny(newvar) genorder(newvar) genid(newvar) replace stack/append ] 230 | ``` 231 | 232 | 233 | Examples: 234 | ```stata 235 | shapes circle, replace 236 | 237 | twoway /// 238 | (connected _y _x, mlabel(_order)) /// 239 | , xsize(1) ysize(1) aspect(1) /// 240 | xlabel(-10 10) ylabel(-10 10) 241 | ``` 242 | 243 | 244 | 245 | ```stata 246 | shapes circle, n(6) replace 247 | 248 | 249 | twoway /// 250 | (connected _y _x, mlabel(_order)) /// 251 | , xsize(1) ysize(1) aspect(1) /// 252 | xlabel(-10 10) ylabel(-10 10) 253 | ``` 254 | 255 | 256 | 257 | 258 | ```stata 259 | shapes circle, n(6) rotate(30) replace 260 | 261 | twoway /// 262 | (connected _y _x, mlabel(_order)) /// 263 | , xsize(1) ysize(1) aspect(1) /// 264 | xlabel(-10 10) ylabel(-10 10) 265 | ``` 266 | 267 | 268 | 269 | 270 | ```stata 271 | shapes circle, rotate(45) rad(8) n(4) replace 272 | 273 | twoway /// 274 | (connected _y _x, mlabel(_order)) /// 275 | , xsize(1) ysize(1) aspect(1) /// 276 | xlabel(-10 10) ylabel(-10 10) 277 | ``` 278 | 279 | 280 | 281 | 282 | ```stata 283 | shapes circle, n(100) replace 284 | 285 | twoway /// 286 | (line _y _x) /// 287 | , xsize(1) ysize(1) aspect(1) /// 288 | xlabel(-10 10) ylabel(-10 10) 289 | ``` 290 | 291 | 292 | 293 | 294 | ```stata 295 | shapes circle, n(8) replace 296 | shapes circle, rotate(30) n(6) rad(8) append 297 | shapes circle, rotate(60) n(4) rad(3) x0(1) y0(1) append 298 | 299 | twoway (connected _y _x, cmissing(n)), aspect(1) 300 | ``` 301 | 302 | 303 | 304 | **Pies** 305 | 306 | Syntax: 307 | 308 | ```stata 309 | shape pie, [ n(int) start(degrees) end(degrees) rotate(degrees) radius(num) x0(num) y0(num) genx(newvar) geny(newvar) genorder(newvar) genid(newvar) dropbase replace stack/append ] 310 | ``` 311 | 312 | Examples: 313 | ```stata 314 | shapes pie, end(60) replace 315 | 316 | twoway (area _y _x), xlabel(-10 10) ylabel(-10 10) xsize(1) ysize(1) aspect(1) 317 | ``` 318 | 319 | 320 | 321 | 322 | ```stata 323 | shapes pie, start(0) end(270) n(200) replace 324 | 325 | twoway (area _y _x), xlabel(-10 10) ylabel(-10 10) xsize(1) ysize(1) aspect(1) 326 | ``` 327 | 328 | 329 | 330 | ```stata 331 | clear 332 | shapes pie, start(0) end(45) ro(0) rad(5) replace 333 | shapes pie, start(0) end(45) ro(30) rad(6) stack 334 | shapes pie, start(0) end(45) ro(60) rad(7) stack 335 | shapes pie, start(0) end(45) ro(90) rad(8) stack 336 | shapes pie, start(0) end(45) ro(120) rad(9) stack 337 | shapes pie, start(0) end(45) ro(150) rad(10) stack 338 | 339 | 340 | twoway (area _y _x, fcolor(%90) cmissing(n) nodropbase) /// 341 | , xlabel(-10 10) ylabel(-10 10) xsize(1) ysize(1) aspect(1) 342 | ``` 343 | 344 | 345 | 346 | 347 | without base: 348 | 349 | ```stata 350 | shapes pie, start(0) end(230) rad(10) rotate(90) n(200) dropbase replace 351 | shapes pie, start(0) end(230) rad(9) rotate(90) n(200) dropbase append 352 | shapes pie, start(0) end(200) rad(8) rotate(90) n(200) dropbase append 353 | shapes pie, start(0) end(180) rad(7) rotate(90) n(200) dropbase append 354 | shapes pie, start(0) end(160) rad(6) rotate(90) n(200) dropbase append 355 | 356 | twoway (line _y _x, cmissing(n) nodropbase) /// 357 | , xlabel(-10 10) ylabel(-10 10) xsize(1) ysize(1) aspect(1) 358 | ``` 359 | 360 | 361 | 362 | without base flipped direction: 363 | 364 | ```stata 365 | shapes pie, start(0) end(350) rad(10) rotate(90) n(200) dropbase flip replace 366 | shapes pie, start(0) end(150) rad(9) rotate(90) n(200) dropbase flip append 367 | shapes pie, start(0) end(130) rad(8) rotate(90) n(200) dropbase flip append 368 | shapes pie, start(0) end(80) rad(7) rotate(90) n(200) dropbase flip append 369 | shapes pie, start(0) end(60) rad(6) rotate(90) n(200) dropbase flip append 370 | 371 | twoway (line _y _x, cmissing(n) nodropbase) /// 372 | , xlabel(-10 10) ylabel(-10 10) xsize(1) ysize(1) aspect(1) 373 | ``` 374 | 375 | 376 | 377 | 378 | **Square** 379 | 380 | ```stata 381 | shapes square, len(8) rotate(90) replace 382 | 383 | twoway /// 384 | (area _y _x, nodropbase fcolor(%50)) /// 385 | (scatter _y _x, mlab(_order)) /// 386 | , /// 387 | legend(off) /// 388 | xlabel(-10(2)10) ylabel(-10(2)10) xsize(1) ysize(1) aspect(1) 389 | ``` 390 | 391 | 392 | 393 | 394 | ```stata 395 | shapes square, x0(1) y0(1) len(10) rotate(40) replace 396 | shapes square, x0(1) y0(1) len(9) rotate(30) append 397 | shapes square, x0(1) y0(1) len(8) rotate(20) append 398 | shapes square, x0(1) y0(1) len(7) rotate(10) append 399 | shapes square, x0(1) y0(1) len(6) rotate(0) append 400 | 401 | 402 | twoway /// 403 | (area _y _x, cmissing(n) nodropbase fcolor(%100) lw(0.1) lc(white)) /// 404 | , /// 405 | legend(off) /// 406 | xlabel(-10(2)10) ylabel(-10(2)10) xsize(1) ysize(1) aspect(1) 407 | ``` 408 | 409 | 410 | 411 | 412 | 413 | **Rotate** 414 | 415 | Let's generate a basic shape: 416 | 417 | ```stata 418 | shapes square, x0( 5) y0(0) len(5) replace 419 | shapes square, x0(-5) y0(0) len(5) append 420 | 421 | twoway /// 422 | (area _y _x, cmissing(n) nodropbase fcolor(%80) lw(0.1) lc(white)) /// 423 | (scatteri 0 0) /// 424 | , /// 425 | legend(off) /// 426 | xlabel(-10(2)10) ylabel(-10(2)10) xsize(1) ysize(1) aspect(1) 427 | ``` 428 | 429 | 430 | 431 | 432 | 433 | ```stata 434 | shapes rotate _y _x, rotate(30) 435 | 436 | 437 | twoway /// 438 | (area _y _x, cmissing(n) nodropbase fcolor(%80) lw(0.1) lc(white)) /// 439 | (area ynew xnew, cmissing(n) nodropbase fcolor(%80) lw(0.1) lc(white)) /// 440 | (scatteri 0 0) /// 441 | , /// 442 | legend(off) /// 443 | xlabel(-10(2)10) ylabel(-10(2)10) xsize(1) ysize(1) aspect(1) 444 | ``` 445 | 446 | 447 | 448 | 449 | ```stata 450 | shapes rotate _y _x, rotate(30) x0(5) y0(5) genx(xnew) geny(ynew) 451 | 452 | twoway /// 453 | (area _y _x, cmissing(n) nodropbase fcolor(%80) lw(0.1) lc(white)) /// 454 | (area ynew xnew, cmissing(n) nodropbase fcolor(%80) lw(0.1) lc(white)) /// 455 | (scatteri 0 0) /// 456 | , /// 457 | legend(off) /// 458 | xlabel(-10(2)10) ylabel(-10(2)10) xsize(1) ysize(1) aspect(1) 459 | ``` 460 | 461 | 462 | 463 | 464 | ```stata 465 | shapes rotate _y _x, rotate(60) center genx(xnew2) geny(ynew2) 466 | 467 | twoway /// 468 | (area _y _x, cmissing(n) nodropbase fcolor(%80) lw(0.1) lc(white)) /// 469 | (area ynew2 xnew2, cmissing(n) nodropbase fcolor(%80) lw(0.1) lc(white)) /// 470 | (scatteri 0 0) /// 471 | , /// 472 | legend(off) /// 473 | xlabel(-10(2)10) ylabel(-10(2)10) xsize(1) ysize(1) aspect(1) 474 | ``` 475 | 476 | 477 | 478 | 479 | ```stata 480 | shapes rotate _y _x, rotate(30) center by(_id) genx(xnew3) geny(ynew3) 481 | 482 | twoway /// 483 | (area _y _x, cmissing(n) nodropbase fcolor(%80) lw(0.1) lc(white)) /// 484 | (area ynew3 xnew3, cmissing(n) nodropbase fcolor(%80) lw(0.1) lc(white)) /// 485 | (scatteri 0 0) /// 486 | , /// 487 | legend(off) /// 488 | xlabel(-10(2)10) ylabel(-10(2)10) xsize(1) ysize(1) aspect(1) 489 | ``` 490 | 491 | 492 | 493 | 494 | 495 | **Area** 496 | 497 | ```stata 498 | clear 499 | shapes pie, start(0) end(45) ro(0) rad(5) replace 500 | shapes pie, start(0) end(45) ro(30) rad(6) stack 501 | shapes pie, start(0) end(45) ro(60) rad(7) stack 502 | shapes pie, start(0) end(45) ro(90) rad(8) stack 503 | shapes pie, start(0) end(45) ro(120) rad(9) stack 504 | shapes pie, start(0) end(45) ro(150) rad(10) stack 505 | 506 | 507 | twoway (area _y _x, fcolor(%90) cmissing(n) nodropbase) /// 508 | , xlabel(-10 10) ylabel(-10 10) xsize(1) ysize(1) aspect(1) 509 | ``` 510 | 511 | 512 | 513 | 514 | calculate the areas 515 | 516 | ```stata 517 | shapes area _y _x, by(_id) 518 | ``` 519 | 520 | Generate some ranking of areas and plot 521 | 522 | 523 | ```stata 524 | xtile grps = _area, n(4) 525 | 526 | levelsof _id, local(lvls) 527 | 528 | foreach x of local lvls { 529 | colorpalette reds, nograph 530 | local myarea `myarea' (area _y _x if _id==`x', fcolor("`r(p`x')'%90") lc("`r(p`x')'") cmissing(n) nodropbase) 531 | } 532 | 533 | 534 | 535 | twoway /// 536 | `myarea' /// 537 | , /// 538 | xlabel(-10 10) ylabel(-10 10) /// 539 | legend(off) /// 540 | xsize(1) ysize(1) aspect(1) 541 | ``` 542 | 543 | 544 | 545 | 546 | ## Feedback 547 | 548 | Please open an [issue](https://github.com/asjadnaqvi/stata-graphfunctions/issues) to report errors, feature enhancements, and/or other requests. 549 | 550 | 551 | ## Change log 552 | 553 | **v1.52 (18 Feb 2025)** 554 | - `catspline` now generate the stated number of points. 555 | - `catspline` now respects `if/in` conditions. 556 | - Minor corrections and bug fixes. 557 | 558 | **v1.51 (28 Nov 2024)** 559 | - Fixed `catspline` to correct generate splines. Added options to replace variables. Change in routine to make it more efficient in computations. 560 | - Added `replace`, `append` to `arc`. Various bug fixes. 561 | - Added `append` as a substitute for `stack` in `shapes`. 562 | - Added `square` in `shapes. 563 | 564 | **v1.5 (05 Nov 2024)** 565 | - `shapes square` added for squares. Note that `shapes circle, n(4)` also returns a square but here we define the center-to-corner length using the radius, where as `shapes square` generates a side with a predefined length. Hence the area of `shapes circle, n(4) rad(5)` > `shapes square, len(5)`. 566 | - `shapes rotate` added for generation rotations at specific points or center of shapes. Note that this is a more advanced rotation than what each individual function provides. 567 | - `shapes area` added for calculating the areas (currently in undefined units) using [Meister's shoelace formula](https://en.wikipedia.org/wiki/Shoelace_formula). 568 | - Option `append` added as a substitute for `stack`. This is more in line with standard Stata syntax. 569 | - Option `flip` added to change the drawing direction. This flips from counter-clockwise (Stata default) to clockwise. 570 | - Better information added for rotations, orientations, and starting points. 571 | - Cleanup of helpfiles. 572 | 573 | **v1.4 (15 Oct 2024)** 574 | - `shapes` is now also mirrored as `shape`. 575 | - `shape circle` updated, and `shape pie` added. 576 | - In `shapes`, users can now also define an origin using `x0()` and `y0()` options. 577 | - More controls and checks. 578 | 579 | **v1.3 (13 Oct 2024)** 580 | - `shapes` added. Minor fixes to index tracking. 581 | - `arc` bug fixes plus code cleanup. 582 | 583 | **v1.2 (08 Oct 2024)** 584 | - `arc` added. 585 | - Bug fixes in `labsplit`. 586 | - Additional checks in programs. 587 | 588 | **v1.1 (04 Oct 2024)** 589 | - `catspline` added. 590 | 591 | **v1.0 (28 Sep 2024)** 592 | - `labsplit` added. 593 | - Public release. 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | -------------------------------------------------------------------------------- /figures/arc1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/arc1.png -------------------------------------------------------------------------------- /figures/arc2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/arc2.png -------------------------------------------------------------------------------- /figures/arc3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/arc3.png -------------------------------------------------------------------------------- /figures/arc4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/arc4.png -------------------------------------------------------------------------------- /figures/area1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/area1.png -------------------------------------------------------------------------------- /figures/area2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/area2.png -------------------------------------------------------------------------------- /figures/bugfix1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/bugfix1.png -------------------------------------------------------------------------------- /figures/bugfix2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/bugfix2.png -------------------------------------------------------------------------------- /figures/catspline1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/catspline1.png -------------------------------------------------------------------------------- /figures/catspline2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/catspline2.png -------------------------------------------------------------------------------- /figures/circle1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/circle1.png -------------------------------------------------------------------------------- /figures/circle2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/circle2.png -------------------------------------------------------------------------------- /figures/circle3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/circle3.png -------------------------------------------------------------------------------- /figures/circle4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/circle4.png -------------------------------------------------------------------------------- /figures/circle5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/circle5.png -------------------------------------------------------------------------------- /figures/circle6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/circle6.png -------------------------------------------------------------------------------- /figures/labsplit0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/labsplit0.png -------------------------------------------------------------------------------- /figures/labsplit1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/labsplit1.png -------------------------------------------------------------------------------- /figures/labsplit2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/labsplit2.png -------------------------------------------------------------------------------- /figures/labsplit3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/labsplit3.png -------------------------------------------------------------------------------- /figures/pie1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/pie1.png -------------------------------------------------------------------------------- /figures/pie2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/pie2.png -------------------------------------------------------------------------------- /figures/pie3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/pie3.png -------------------------------------------------------------------------------- /figures/pie4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/pie4.png -------------------------------------------------------------------------------- /figures/pie5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/pie5.png -------------------------------------------------------------------------------- /figures/rotate1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/rotate1.png -------------------------------------------------------------------------------- /figures/rotate2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/rotate2.png -------------------------------------------------------------------------------- /figures/rotate3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/rotate3.png -------------------------------------------------------------------------------- /figures/rotate4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/rotate4.png -------------------------------------------------------------------------------- /figures/shapes1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/shapes1.png -------------------------------------------------------------------------------- /figures/shapes1_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/shapes1_1.png -------------------------------------------------------------------------------- /figures/shapes1_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/shapes1_2.png -------------------------------------------------------------------------------- /figures/shapes2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/shapes2.png -------------------------------------------------------------------------------- /figures/shapes3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/shapes3.png -------------------------------------------------------------------------------- /figures/shapes4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/shapes4.png -------------------------------------------------------------------------------- /figures/shapes5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/shapes5.png -------------------------------------------------------------------------------- /figures/shapes_circle1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/shapes_circle1.png -------------------------------------------------------------------------------- /figures/shapes_circle2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/shapes_circle2.png -------------------------------------------------------------------------------- /figures/shapes_circle3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/shapes_circle3.png -------------------------------------------------------------------------------- /figures/shapes_circle4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/shapes_circle4.png -------------------------------------------------------------------------------- /figures/shapes_circle5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/shapes_circle5.png -------------------------------------------------------------------------------- /figures/shapes_circle6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/shapes_circle6.png -------------------------------------------------------------------------------- /figures/square1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/square1.png -------------------------------------------------------------------------------- /figures/square2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asjadnaqvi/stata-graphfunctions/97a92626b99a6db1a55a4b43346872aca6ea2822/figures/square2.png -------------------------------------------------------------------------------- /installation/arc.ado: -------------------------------------------------------------------------------- 1 | *! arc v1.2 (20 Nov 2024) 2 | *! Asjad Naqvi (asjadnaqvi@gmail.com) 3 | 4 | * v1.2 (20 Nov 2024): append/stack added 5 | * v1.1 (11 Oct 2024): Minor bug fixes. 6 | * v1.0 (08 Oct 2024): first release. 7 | 8 | 9 | cap program drop arc 10 | 11 | program define arc, rclass 12 | 13 | version 11 14 | 15 | syntax, /// 16 | x1(numlist max=1) y1(numlist max=1) /// // from 17 | x2(numlist max=1) y2(numlist max=1) /// // to 18 | [ n(real 40) RADius(numlist max=1 >0) major swap ] /// 19 | [ genx(string) geny(string) genid(string) genorder(string) ] /// 20 | [ replace append stack ] 21 | 22 | 23 | if `n' < 5 { 24 | display in red "The number of points n() must be greater or equal to 5." 25 | exit 26 | } 27 | 28 | 29 | quietly { 30 | 31 | // prepare the variables 32 | local xvar _x 33 | local yvar _y 34 | local idvar _id 35 | local ordervar _order 36 | 37 | 38 | if "`genx'" != "" local xvar `genx' 39 | if "`geny'" != "" local yvar `geny' 40 | if "`genid'" != "" local idvar `genid' 41 | if "`genorder'" != "" local ordervar `genorder' 42 | 43 | if "`replace'" != "" { 44 | cap drop `xvar' 45 | cap drop `yvar' 46 | cap drop `idvar' 47 | cap drop `ordervar' 48 | } 49 | 50 | cap generate double `xvar' = . 51 | cap generate double `yvar' = . 52 | cap generate `idvar' = . 53 | cap generate `ordervar' = . 54 | 55 | 56 | if "`stack'" != "" | "`append'" !="" { 57 | 58 | tempvar temp 59 | gen `temp' = _n if !missing(`ordervar') 60 | summ `temp', meanonly 61 | 62 | if r(N)!= 0 { 63 | local start = `=`r(max)' + 1' 64 | local end = `=`r(max)' + `n' + 1' 65 | 66 | if _N < `=`r(max)'+`n'+1' set obs `end' 67 | } 68 | else { 69 | local start = 1 70 | local end = `=`n' + 1' 71 | if _N < `n' set obs `end' 72 | } 73 | 74 | } 75 | else { 76 | local start = 1 77 | local end = `=`n' + 1' 78 | if _N < `n' set obs `end' 79 | } 80 | 81 | 82 | summ `idvar', meanonly 83 | 84 | if `r(N)'==0 { 85 | local k = 1 86 | } 87 | else { 88 | local k = `r(max)' + 1 89 | } 90 | 91 | // id 92 | summ `ordervar', meanonly 93 | replace `idvar' = `k' in `start'/`end' 94 | 95 | // order 96 | tempvar _temp _temp2 _seq _angle 97 | gen `_temp' = 1 98 | replace `ordervar' = sum(`_temp') if `idvar'==`k' 99 | 100 | **** core routines below **** 101 | 102 | // mid points 103 | local xm = (`x1' + `x2') / 2 104 | local ym = (`y1' + `y2') / 2 105 | 106 | // slope 107 | local dx = `x2' - `x1' 108 | local dy = `y2' - `y1' 109 | local L = sqrt(abs(`dx')^2 + abs(`dy')^2) // check why this square is not working without abs() 110 | 111 | *noisily display "`dx', `dy', `L'" 112 | 113 | // radius 114 | if "`radius'" == "" { 115 | local radius = `L' // radius = chord length 116 | display in yellow "Radius of `radius' assumed." 117 | } 118 | 119 | // validate the radius 120 | if `radius' <= `L'/2 { 121 | local mychord = `L' / 2 122 | di as error "Radius must be greater than half the chord length. Half chord length for given coordinates = `mychord'" 123 | exit 124 | } 125 | 126 | // distance from midpoint to center 127 | local h_dist = sqrt(`radius'^2 - (`L'/2)^2) 128 | 129 | 130 | // direction of the perpendicular bisector 131 | local ux_perp = -`dy' / `L' 132 | local uy_perp = `dx' / `L' 133 | 134 | local cross_prod = `dx' * `uy_perp' - `dy' * `ux_perp' 135 | 136 | // swap left to right orientation 137 | if "`swap'" == "" { 138 | local h = `xm' + `h_dist' * `ux_perp' 139 | local k = `ym' + `h_dist' * `uy_perp' 140 | } 141 | else { 142 | local h = `xm' - `h_dist' * `ux_perp' 143 | local k = `ym' - `h_dist' * `uy_perp' 144 | } 145 | 146 | 147 | // get the angles in order 148 | local angle_start = atan2(`y1' - `k', `x1' - `h') 149 | local angle_end = atan2(`y2' - `k', `x2' - `h') 150 | 151 | // bound angles between 0, 2pi 152 | if `angle_start' < 0 local angle_start = `angle_start' + 2 * _pi 153 | if `angle_end' < 0 local angle_end = `angle_end' + 2 * _pi 154 | 155 | 156 | // correct for minor vs major arc 157 | 158 | if "`swap'"!= "" { 159 | if "`major'" != "" { 160 | if (`angle_end' - `angle_start') < _pi local angle_end = `angle_end' + 2 * _pi 161 | } 162 | else { 163 | if (`angle_end' - `angle_start') > _pi local angle_end = `angle_end' - 2 * _pi 164 | } 165 | } 166 | else { 167 | if "`major'" != "" { 168 | if (`angle_end' - `angle_start') > _pi local angle_end = `angle_end' - 2 * _pi 169 | } 170 | else { 171 | if (`angle_end' - `angle_start') < _pi local angle_end = `angle_end' + 2 * _pi 172 | } 173 | if (`angle_end' - `angle_start') > 2 * _pi local angle_end = `angle_end' - 2 * _pi 174 | } 175 | 176 | local delta_theta = (`angle_end' - `angle_start') / (`n' - 1) 177 | 178 | if _N < `n' set obs `n' 179 | 180 | tempvar theta 181 | gen double `theta' = `angle_start' + (`ordervar' - 1) * `delta_theta' in `start'/`=`end'-1' 182 | 183 | 184 | replace `xvar' = `h' + `radius' * cos(`theta') in `start'/`=`end'-1' 185 | replace `yvar' = `k' + `radius' * sin(`theta') in `start'/`=`end'-1' 186 | 187 | } 188 | 189 | return local chord = `L' 190 | return local radius = `radius' 191 | return local xcirc = `h' 192 | return local ycirc = `k' 193 | 194 | end 195 | 196 | -------------------------------------------------------------------------------- /installation/arc.sthlp: -------------------------------------------------------------------------------- 1 | {smcl} 2 | {* 20Nov2024}{...} 3 | {hi:help arc}{...} 4 | {right:{browse "https://github.com/asjadnaqvi/stata-graphfunctions":graphfunctions (GitHub)}} 5 | 6 | {hline} 7 | 8 | {title:arc}: A program for generating arcs between two points. 9 | 10 | The program inputs two pairs of coordinates ({it:x1, y1}) and ({it:x2, y2}) and outputs points for the arc segment in variables {it:_x, _y}. 11 | The program is {stata help return:r-class} so type {stata return list} after running the command to see the stored locals. 12 | 13 | {marker syntax}{title:Syntax} 14 | 15 | {p 8 15 2} 16 | {cmd:arc}, {cmd:x1}({it:num}) {cmd:y1}({it:num}) {cmd:x2}({it:num}) {cmd:y2}({it:num}) {cmd:[} {cmdab:rad:ius}({it:num}) {cmd:n}({it:int}) {cmd:swap} {cmd:major} {cmdab:genx}({it:newvar}) {cmdab:geny}({it:newvar}) genid(string) genorder(string) {cmd:replace} {cmd:]} 17 | 18 | 19 | {synoptset 36 tabbed}{...} 20 | {synopthdr} 21 | {synoptline} 22 | 23 | {p2coldent : {opt arc}, x1() y1() x2() y2()}Input two coordinate pairs.{p_end} 24 | 25 | {p2coldent : {opt rad:ius(num)}}Specify the radius length. Must be at least equal to half the chord length. Stored in local {it:r(chord)}. Default is the chord length.{p_end} 26 | 27 | {p2coldent : {opt n(int)}}Number of points to generate for each arc. Default is {opt n(80)}, Must be great or equal to 5.{p_end} 28 | 29 | {p2coldent : {opt swap}}Swap the arc side. Arcs are, by default, oriented to the right of the line starting at ({it:x1, y1}) and ending at ({it:x2, y2}). 30 | Or the arc circumcenter is to the left of the line.{p_end} 31 | 32 | {p2coldent : {opt major}}Draw a major arc around the circumcenter rather than the default minor arc.{p_end} 33 | 34 | {p2coldent : {opt genx(newvar)} {opt geny(newvar)}}Custom names for the generated coordinates. Defaults are {it: _x, _y}.{p_end} 35 | 36 | {p2coldent : {opt genorder(newvar)}}Custom name for the {cmd:_order} variable.{p_end} 37 | 38 | {p2coldent : {opt genid(newvar)}}Custom name for the {cmd:_id} variable.{p_end} 39 | 40 | {p2coldent : {opt replace}}Overwrite the generated variables if they exist. Use carefully.{p_end} 41 | 42 | {synoptline} 43 | {p2colreset}{...} 44 | 45 | 46 | {title:Examples} 47 | 48 | Generate data: 49 | {stata clear} 50 | {stata arc, y1(-2) x1(-4) y2(4) x2(2) rad(6)} 51 | {stata return list} 52 | {stata twoway (scatteri -2 -4) (scatteri 4 2) (scatteri `r(ycirc)' `r(xcirc)') (line _y _x), legend(order(1 "Point 1" 2 "Point 2" 3 "Circumcenter" 4 "Arc") pos(6) row(1)) xlabel(-10(2)10) ylabel(-10(2)10) aspect(1) xsize(1) ysize(1)} 53 | 54 | More examples on {browse "https://github.com/asjadnaqvi/stata-graphfunctions":GitHub}. 55 | 56 | 57 | {title:Package details} 58 | 59 | Version : {bf:arc} v1.2 in {stata help graphfunctions:graphfunctions} 60 | This release : 20 Nov 2024 61 | First release: 08 Oct 2024 62 | Repository : {browse "https://github.com/asjadnaqvi/stata-graphfunctions":GitHub} 63 | Keywords : Stata, graph, arcs 64 | License : {browse "https://opensource.org/licenses/MIT":MIT} 65 | 66 | Author : {browse "https://github.com/asjadnaqvi":Asjad Naqvi} 67 | E-mail : asjadnaqvi@gmail.com 68 | Twitter/X : {browse "https://x.com/AsjadNaqvi":@AsjadNaqvi} 69 | 70 | 71 | {title:Feedback} 72 | 73 | Please submit bugs, errors, feature requests on {browse "https://github.com/asjadnaqvi/stata-graphfunctions/issues":GitHub} by opening a new issue. 74 | 75 | 76 | {title:Citation guidelines} 77 | 78 | See {stata help graphfunctions:graphfunctions}. 79 | 80 | 81 | {title:Other packages} 82 | 83 | {psee} 84 | {helpb arcplot}, {helpb alluvial}, {helpb bimap}, {helpb bumparea}, {helpb bumpline}, {helpb circlebar}, {helpb circlepack}, {helpb clipgeo}, {helpb delaunay}, {helpb graphfunctions}, {helpb joyplot}, 85 | {helpb marimekko}, {helpb polarspike}, {helpb sankey}, {helpb schemepack}, {helpb spider}, {helpb splinefit}, {helpb streamplot}, {helpb sunburst}, {helpb ternary}, {helpb treecluster}, {helpb treemap}, {helpb trimap}, {helpb waffle} 86 | 87 | or visit {browse "https://github.com/asjadnaqvi":GitHub}. 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /installation/catspline.ado: -------------------------------------------------------------------------------- 1 | *! catspline v1.2 (18 Feb 2025): Fixed marksample bug. 2 | *! Asjad Naqvi (asjadnaqvi@gmail.com) 3 | 4 | * v1.2 (18 Feb 2025): Fixed marksample bug. 5 | * v1.1 (28 Nov 2024): Fix an issue with observations stacking. Fixed a minor bug in sort. Added a sort(), replace variable. 6 | * v1.0 (04 Oct 2024): first release. 7 | 8 | 9 | /* 10 | to do: add option `sort()'. 11 | 12 | */ 13 | 14 | 15 | cap program drop catspline 16 | 17 | program catspline, sortpreserve 18 | 19 | version 11 20 | 21 | syntax varlist(numeric min=2 max=2) [if] [in], [ rho(numlist max=1 >=0 <=1) n(real 40) close noid genx(string) geny(string) genid(string) genorder(string) sort(varlist max=1) replace ] 22 | 23 | 24 | // prepare the variables 25 | local xvar _x 26 | local yvar _y 27 | local idvar _id 28 | local ordervar _order 29 | 30 | if "`genx'" != "" local xvar `genx' 31 | if "`geny'" != "" local yvar `geny' 32 | if "`genid'" != "" local idvar `genid' 33 | if "`genorder'" != "" local ordervar `genorder' 34 | 35 | 36 | if "`replace'" != "" { 37 | cap drop `xvar' 38 | cap drop `yvar' 39 | cap drop `idvar' 40 | cap drop `ordervar' 41 | } 42 | 43 | 44 | cap confirm var _id 45 | if !_rc { 46 | display as error "Variable {it:_id} already exists. Option {it:replace} can be used to overwrite." 47 | exit 48 | } 49 | 50 | 51 | marksample touse, strok 52 | 53 | quietly { 54 | preserve 55 | 56 | keep if `touse' 57 | 58 | keep `varlist' `sort' 59 | 60 | tokenize `varlist' 61 | local vary `1' 62 | local varx `2' 63 | 64 | 65 | 66 | drop if missing(`varx') 67 | drop if missing(`vary') 68 | 69 | 70 | if "`sort'" != "" sort `sort' 71 | 72 | gen pts = _n 73 | order pts 74 | 75 | 76 | if "`rho'" == "" local rho 0.5 77 | 78 | if `n' < 5 { 79 | display as error "The number of points n() must be greater than 5." 80 | exit 81 | } 82 | 83 | 84 | if _N < `n' set obs `n' 85 | 86 | 87 | 88 | gen id = _n - 1 89 | 90 | 91 | 92 | 93 | levelsof pts, local(points) 94 | local last = r(r) 95 | 96 | foreach x of local points { 97 | 98 | // define the four points based on positioning 99 | 100 | local pt0 = `x' 101 | local pt1 = `x' + 1 102 | local pt2 = `x' + 2 103 | local pt3 = `x' + 3 104 | 105 | if `pt1' > `last' local pt1 = `pt1' - `last' 106 | if `pt2' > `last' local pt2 = `pt2' - `last' 107 | if `pt3' > `last' local pt3 = `pt3' - `last' 108 | 109 | // control points indexed 0, 1, 2, 3 110 | 111 | forval i = 0/3 { 112 | summ `varx' if pts==`pt`i'', meanonly 113 | local x`i' = r(mean) 114 | 115 | summ `vary' if pts==`pt`i'', meanonly 116 | local y`i' = r(mean) 117 | } 118 | 119 | // generate the ts 120 | tempvar t0 t1 t2 t3 121 | 122 | gen `t0' = 0 123 | gen double `t1' = (((`x1' - `x0')^2 + (`y1' - `y0')^2)^`rho') + `t0' 124 | gen double `t2' = (((`x2' - `x1')^2 + (`y2' - `y1')^2)^`rho') + `t1' 125 | gen double `t3' = (((`x3' - `x2')^2 + (`y3' - `y2')^2)^`rho') + `t2' 126 | 127 | local diff = abs(`t2' - `t1') / (`n' - 1) 128 | 129 | *local diff = abs(`n') / (`n' - 1) 130 | 131 | gen double t`x' = `t1' + (`diff' * id) in 1/`n' 132 | 133 | 134 | **** calculate the As 135 | forval i = 1/3 { 136 | local j = `i' - 1 137 | 138 | tempvar A`i'x A`i'y 139 | 140 | gen double `A`i'x' = (((`t`i'' - t`x') / (`t`i'' - `t`j'')) * `x`j'') + (((t`x' - `t`j'') / (`t`i'' - `t`j'')) * `x`i'') 141 | gen double `A`i'y' = (((`t`i'' - t`x') / (`t`i'' - `t`j'')) * `y`j'') + (((t`x' - `t`j'') / (`t`i'' - `t`j'')) * `y`i'') 142 | 143 | } 144 | 145 | **** calculate the Bs 146 | forval i = 1/2 { 147 | local j = `i' - 1 148 | local k = `i' + 1 149 | 150 | tempvar B`i'x B`i'y 151 | 152 | gen double `B`i'x' = (((`t`k'' - t`x') / (`t`k'' - `t`j'')) * `A`i'x') + (((t`x' - `t`j'') / (`t`k'' - `t`j'')) * `A`k'x') 153 | gen double `B`i'y' = (((`t`k'' - t`x') / (`t`k'' - `t`j'')) * `A`i'y') + (((t`x' - `t`j'') / (`t`k'' - `t`j'')) * `A`k'y') 154 | 155 | } 156 | 157 | **** calculate the Cs 158 | gen double `xvar'`x' = (((`t2' - t`x') / (`t2' - `t1')) * `B1x') + (((t`x' - `t1') / (`t2' - `t1')) * `B2x') 159 | gen double `yvar'`x' = (((`t2' - t`x') / (`t2' - `t1')) * `B1y') + (((t`x' - `t1') / (`t2' - `t1')) * `B2y') 160 | 161 | } 162 | 163 | 164 | cap drop `varlist' pts id 165 | 166 | drop if t1==. 167 | 168 | 169 | 170 | set obs `= `n'+ 1' // add an empty row 171 | 172 | 173 | gen `ordervar' = _n 174 | 175 | 176 | 177 | 178 | reshape long `xvar' `yvar' t, i(`ordervar') j(`idvar') 179 | 180 | order `idvar' `ordervar' 181 | sort `idvar' `ordervar' 182 | 183 | 184 | if "`close'" == "" { 185 | summ `idvar' 186 | drop if `idvar'==r(max)-1 187 | } 188 | 189 | drop t 190 | 191 | 192 | tempfile mysplines 193 | save `mysplines', replace 194 | 195 | summ `idvar', meanonly 196 | local block1 = r(max) 197 | 198 | summ `ordervar', meanonly 199 | local block2 = r(max) 200 | 201 | restore 202 | 203 | local obs2 = `block1' * `block2' 204 | if _N < `obs2' set obs `obs2' 205 | 206 | egen `idvar' = seq(), b(`block2') // id 207 | egen `ordervar' = seq(), f(1) t(`block2') // order 208 | 209 | merge m:1 `idvar' `ordervar' using `mysplines' 210 | drop _merge 211 | 212 | */ 213 | 214 | } 215 | 216 | end 217 | 218 | ********************************* 219 | ******** END OF PROGRAM ********* 220 | ********************************* 221 | -------------------------------------------------------------------------------- /installation/catspline.sthlp: -------------------------------------------------------------------------------- 1 | {smcl} 2 | {* 18Feb2025}{...} 3 | {hi:help catspline}{...} 4 | {right:{browse "https://github.com/asjadnaqvi/stata-graphfunctions":graphfunctions (GitHub)}} 5 | 6 | {hline} 7 | 8 | {title:catspline}: A program for generating {browse "https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline":Catmull-Rom splines}. 9 | 10 | The program inputs two numeric variables and outputs four variables ({it:_id, _order, _x, _y}). 11 | 12 | 13 | 14 | {marker syntax}{title:Syntax} 15 | 16 | {p 8 15 2} 17 | {cmd:catspline} {it:y x}, {cmd:[} {cmd:rho}({it:num [0,1]}) {cmd:n}({it:int}) {cmd:close} {cmd:sort}({it:var}) {cmdab:genx}({it:newvar}) {cmdab:geny}({it:newvar}) {cmd:replace} {cmd:]} 18 | 19 | 20 | {synoptset 36 tabbed}{...} 21 | {synopthdr} 22 | {synoptline} 23 | 24 | {p2coldent : {opt catspline} y x}Input a coordinate pair.{p_end} 25 | 26 | {p2coldent : {opt rho(num)}}Smoothing parameter bounded between 0 and 1. Default is {opt rho(0.5)}.{p_end} 27 | 28 | {p2coldent : {opt n(int)}}Number of points to generate for each spline. Default is {opt n(40)}.{p_end} 29 | 30 | {p2coldent : {opt sort(var)}}Sort the drawing order defined by the {opt sort()} variable.{p_end} 31 | 32 | {p2coldent : {opt close}}Close the loop between the starting and the ending points.{p_end} 33 | 34 | {p2coldent : {opt genx(newvar)}, {opt geny(newvar)}}Custom names for the {cmd:_x} and {cmd:_y} variables.{p_end} 35 | 36 | {p2coldent : {opt genorder(newvar)}}Custom name for the {cmd:_order} variable.{p_end} 37 | 38 | {p2coldent : {opt genid(newvar)}}Custom name for the {cmd:_id} variable.{p_end} 39 | 40 | {p2coldent : {opt replace}}Replace the variables.{p_end} 41 | 42 | {synoptline} 43 | {p2colreset}{...} 44 | 45 | 46 | {title:Examples} 47 | 48 | Generate data: 49 | {stata clear} 50 | {stata set obs 5} 51 | {stata set seed 2021} 52 | {stata gen x = runiformint(1,5)} 53 | {stata gen y = runiformint(1,5)} 54 | 55 | Run the program: 56 | {stata catspline y x, close rho(0.4)} 57 | 58 | Plot the data: 59 | {stata twoway (scatter y x) (line _y _x, cmissing(n))} 60 | 61 | More examples on {browse "https://github.com/asjadnaqvi/stata-graphfunctions":GitHub}. 62 | 63 | 64 | {title:Package details} 65 | 66 | Version : {bf:catspline} v1.2 in {stata help graphfunctions:graphfunctions} 67 | This release : 18 Feb 2025 68 | First release: 04 Oct 2024 69 | Repository : {browse "https://github.com/asjadnaqvi/stata-graphfunctions":GitHub} 70 | Keywords : Stata, graph, splines, catmull rom function 71 | License : {browse "https://opensource.org/licenses/MIT":MIT} 72 | 73 | Author : {browse "https://github.com/asjadnaqvi":Asjad Naqvi} 74 | E-mail : asjadnaqvi@gmail.com 75 | Twitter/X : {browse "https://x.com/AsjadNaqvi":@AsjadNaqvi} 76 | 77 | 78 | {title:Feedback} 79 | 80 | Please submit bugs, errors, feature requests on {browse "https://github.com/asjadnaqvi/stata-graphfunctions/issues":GitHub} by opening a new issue. 81 | 82 | 83 | {title:Citation guidelines} 84 | 85 | See {stata help graphfunctions:graphfunctions}. 86 | 87 | 88 | {title:Other packages} 89 | 90 | {psee} 91 | {helpb arcplot}, {helpb alluvial}, {helpb bimap}, {helpb bumparea}, {helpb bumpline}, {helpb circlebar}, {helpb circlepack}, {helpb clipgeo}, {helpb delaunay}, {helpb graphfunctions}, {helpb joyplot}, 92 | {helpb marimekko}, {helpb polarspike}, {helpb sankey}, {helpb schemepack}, {helpb spider}, {helpb splinefit}, {helpb streamplot}, {helpb sunburst}, {helpb ternary}, {helpb treecluster}, {helpb treemap}, {helpb trimap}, {helpb waffle} 93 | 94 | or visit {browse "https://github.com/asjadnaqvi":GitHub}. 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /installation/graphfunctions.pkg: -------------------------------------------------------------------------------- 1 | v 1.52 2 | d {bf:GRAPHFUNCTIONS}: A collection of functions to extend graph functionality in Stata 3 | d 4 | d Requires: Stata version 11 or higher. 5 | d 6 | d KW: Stata 7 | d KW: graphs 8 | d KW: figures 9 | d KW: text wrap 10 | d KW: splines 11 | d KW: shapes 12 | d 13 | d Distribution-Date: 20250218 14 | d License: MIT 15 | d 16 | d Author: Asjad Naqvi (asjadnaqvi@gmail.com) 17 | d 18 | f graphfunctions.sthlp 19 | f labsplit.ado 20 | f labsplit.sthlp 21 | f catspline.ado 22 | f catspline.sthlp 23 | f arc.ado 24 | f arc.sthlp 25 | f shape.ado 26 | f shape.sthlp 27 | f shapes.ado 28 | f shapes.sthlp -------------------------------------------------------------------------------- /installation/graphfunctions.sthlp: -------------------------------------------------------------------------------- 1 | {smcl} 2 | {* 18Feb2025}{...} 3 | {hi:help graphfunctions}{...} 4 | {right:{browse "https://github.com/asjadnaqvi/stata-graphfunctions":graphfunctions v1.52 (GitHub)}} 5 | 6 | 7 | {title:GRAPH FUNCTIONS}: 8 | 9 | {p 4 4 2} 10 | This package contains the following program(s): 11 | 12 | {hline} 13 | 14 | {stata help labsplit:labsplit} v1.1 (08 Oct 2024) Various options for wrapping labels. 15 | {stata help catspline:catspline} v1.2 (18 Feb 2025) Generate Catmull-Rom splines. 16 | {stata help arc:arc} v1.2 (20 Nov 2024) Draw an arc between two points. 17 | {stata help shapes:shapes} v1.3 (05 Nov 2024) Draw shapes. Contains several sub programs. 18 | 19 | {hline} 20 | 21 | 22 | {title:Examples} 23 | 24 | See {browse "https://github.com/asjadnaqvi/stata-graphfunctions":GitHub}. 25 | 26 | 27 | {title:Feedback} 28 | 29 | Please submit bugs, errors, feature requests on {browse "https://github.com/asjadnaqvi/stata-graphfunctions/issues":GitHub} by opening a new issue. 30 | 31 | 32 | {title:Citation guidelines} 33 | 34 | See {browse "https://ideas.repec.org/c/boc/bocode/s459379.html"} for the official SSC citation. 35 | Please note that the GitHub version might be newer than the SSC version. 36 | 37 | 38 | {title:Package details} 39 | 40 | Version : {bf:graphfunctions} v1.52 41 | This release : 18 Feb 2025 42 | First release: 28 Sep 2024 43 | Repository : {browse "https://github.com/asjadnaqvi/stata-graphfunctions":GitHub} 44 | License : {browse "https://opensource.org/licenses/MIT":MIT} 45 | 46 | Author : {browse "https://github.com/asjadnaqvi":Asjad Naqvi} 47 | E-mail : asjadnaqvi@gmail.com 48 | Twitter/X : {browse "https://x.com/AsjadNaqvi":@AsjadNaqvi} 49 | 50 | 51 | {title:Other visualization packages} 52 | {psee} 53 | {helpb arcplot}, {helpb alluvial}, {helpb bimap}, {helpb bumparea}, {helpb bumpline}, {helpb circlebar}, {helpb circlepack}, {helpb clipgeo}, {helpb delaunay}, {helpb graphfunctions}, {helpb geoboundary}, {helpb geoflow}, {helpb joyplot}, 54 | {helpb marimekko}, {helpb polarspike}, {helpb sankey}, {helpb schemepack}, {helpb spider}, {helpb splinefit}, {helpb streamplot}, {helpb sunburst}, {helpb ternary}, {helpb tidytuesday}, {helpb treecluster}, {helpb treemap}, {helpb trimap}, {helpb waffle} 55 | 56 | Visit {browse "https://github.com/asjadnaqvi":GitHub} for further information. 57 | -------------------------------------------------------------------------------- /installation/labsplit.ado: -------------------------------------------------------------------------------- 1 | *! labsplit v1.1 (08 Oct 2024) 2 | *! Asjad Naqvi (asjadnaqvi@gmail.com) 3 | 4 | * v1.1 (08 Oct 2024): bug fixes 5 | * v1.0 (28 Sep 2024): first release. 6 | 7 | 8 | cap program drop labsplit 9 | 10 | program labsplit 11 | version 11 12 | 13 | syntax varlist(max=1) [if] [in], [ wrap(numlist max=1 >0 integer) word(numlist max=1 >0 integer) strict GENerate(string) ] 14 | 15 | // error checks 16 | 17 | if "`wrap'" == "" & "`word'" == "" { 18 | display as error "Please specify one of {ul:wrap()} or {ul:word}. See {stata help labsplit}." 19 | exit 20 | } 21 | 22 | if "`wrap'" != "" & "`word'" != "" { 23 | display as error "Both {ul:wrap()} and {ul:word()} cannot be specified together." 24 | exit 25 | } 26 | 27 | 28 | quietly { 29 | 30 | if "`generate'" != "" { 31 | gen `generate' = "" 32 | local _myvar `generate' 33 | } 34 | else { 35 | gen _labsplit = "" 36 | local _myvar _labsplit 37 | } 38 | 39 | if "`wrap'" != "" { 40 | 41 | if "`strict'" != "" { 42 | tempvar _length 43 | gen `_length' = length(`varlist') if !missing(`varlist') 44 | summ `_length', meanonly 45 | local _wraprounds = floor(`r(max)' / `wrap') 46 | 47 | replace `_myvar' = `varlist' // copy 48 | 49 | forval i = 1 / `_wraprounds' { 50 | local wraptag = `wrap' * `i' 51 | replace `_myvar' = substr(`_myvar', 1, `wraptag') + "`=char(10)'" + substr(`_myvar', `=`wraptag' + 1', .) if `_length' > `wraptag' & !missing(`_length') 52 | } 53 | } 54 | else { 55 | tempvar current_line _words _tempword length length0 length1 56 | 57 | gen `current_line' = word(`varlist', 1) if !missing(`varlist') 58 | 59 | 60 | gen `length0' = . 61 | gen `length1' = . 62 | gen `_words' = wordcount(`varlist') 63 | 64 | summ `_words', meanonly 65 | local items = `r(max)' 66 | 67 | forval i = 2/`items' { 68 | 69 | cap drop `_tempword' 70 | gen `_tempword' = word(`varlist', `i') if !missing(`varlist') 71 | 72 | 73 | replace `length0' = length(`current_line') if !missing(`varlist') 74 | replace `length1' = length(`_tempword') if !missing(`varlist') 75 | 76 | replace `current_line' = `current_line' + " " + `_tempword' if (`length0' + `length1' + 1) <= `wrap' 77 | replace `_myvar' = `_myvar' + `current_line' + "`=char(10)'" if (`length0' + `length1' + 1) > `wrap' & `_tempword'!="" 78 | replace `current_line' = `_tempword' if (`length0' + `length1' + 1) > `wrap' & `_tempword'!="" 79 | 80 | } 81 | 82 | 83 | replace `_myvar' = `_myvar' + `current_line' if !missing(`current_line') & `_myvar' != "" 84 | replace `_myvar' = word(`varlist', 1) if `_words'==1 85 | replace `_myvar' = `varlist' if missing(`_myvar') 86 | } 87 | } 88 | 89 | if "`word'" != "" { 90 | tempvar _part1 _part2 _words 91 | 92 | gen `_words' = wordcount(`varlist') 93 | 94 | gen `_part1' = "" if `_words' > `word' 95 | gen `_part2' = `varlist' if `_words' > `word' 96 | 97 | 98 | forval i = 1 /`word' { 99 | replace `_part1' = `_part1' + word(`varlist', `i') + " " if `_words' > `word' 100 | replace `_part2' = trim(ustrregexrf(`_part2', word(`varlist', `i'), "", .)) if `_words' > `word' 101 | } 102 | 103 | replace `_myvar' = `_part1' + "`=char(10)'" + `_part2' if `_words' > `word' 104 | replace `_myvar' = trim(`varlist') if `_words' <= `word' 105 | 106 | 107 | } 108 | } 109 | 110 | end 111 | 112 | 113 | **** END OF DOFILE **** 114 | -------------------------------------------------------------------------------- /installation/labsplit.sthlp: -------------------------------------------------------------------------------- 1 | {smcl} 2 | {* 28Sep2024}{...} 3 | {hi:help labsplit}{...} 4 | {right:{browse "https://github.com/asjadnaqvi/stata-graphfunctions":graphfunctions (GitHub)}} 5 | 6 | {hline} 7 | 8 | {title:labsplit}: A program for text and word wrapping. 9 | 10 | 11 | {marker syntax}{title:Syntax} 12 | 13 | {p 8 15 2} 14 | {cmd:labsplit} {it:variable}, {cmd:[} {cmd:wrap}({it:int}) {cmd:word}({it:int}) {cmd:strict} {cmdab:gen:erate}({it:newvar}) {cmd:]} 15 | 16 | 17 | {synoptset 36 tabbed}{...} 18 | {synopthdr} 19 | {synoptline} 20 | 21 | {p2coldent : {opt labsplit} variable}The command requires a string variable.{p_end} 22 | 23 | {p2coldent : {opt wrap(int)}}Wrap after {it:int} characters. The program will repect word boundaries and will not cut them off 24 | unless {opt strict} is specified.{p_end} 25 | 26 | {p2coldent : {opt strict}}This option will chop off words defined by {opt wrap()} to maintain a strict text length per line.{p_end} 27 | 28 | {p2coldent : {opt word(int)}}Wrap at the {it:int-th} word.{p_end} 29 | 30 | {p2coldent : {opt gen:erate(newvar)}}Generate a new variable name with wrapped labels. If not specified, the program will 31 | save a new variable called {it:_labsplit}.{p_end} 32 | 33 | {synoptline} 34 | {p2colreset}{...} 35 | 36 | 37 | {title:Examples} 38 | 39 | See {browse "https://github.com/asjadnaqvi/stata-graphfunctions":GitHub}. 40 | 41 | 42 | {title:Package details} 43 | 44 | Version : {bf:labsplit} v1.1 in {stata help graphfunctions:graphfunctions} 45 | This release : 08 Oct 2024 46 | First release: 28 Sep 2024 47 | Repository : {browse "https://github.com/asjadnaqvi/stata-graphfunctions":GitHub} 48 | Keywords : Stata, graph, label wrap, text wrap, word wrap 49 | License : {browse "https://opensource.org/licenses/MIT":MIT} 50 | 51 | Author : {browse "https://github.com/asjadnaqvi":Asjad Naqvi} 52 | E-mail : asjadnaqvi@gmail.com 53 | Twitter/X : {browse "https://x.com/AsjadNaqvi":@AsjadNaqvi} 54 | 55 | 56 | 57 | {title:Feedback} 58 | 59 | Please submit bugs, errors, feature requests on {browse "https://github.com/asjadnaqvi/stata-graphfunctions/issues":GitHub} by opening a new issue. 60 | 61 | 62 | {title:Citation guidelines} 63 | 64 | See {stata help graphfunctions:graphfunctions}. 65 | 66 | 67 | {title:Other packages} 68 | 69 | {psee} 70 | {helpb arcplot}, {helpb alluvial}, {helpb bimap}, {helpb bumparea}, {helpb bumpline}, {helpb circlebar}, {helpb circlepack}, {helpb clipgeo}, {helpb delaunay}, {helpb graphfunctions}, {helpb joyplot}, 71 | {helpb marimekko}, {helpb polarspike}, {helpb sankey}, {helpb schemepack}, {helpb spider}, {helpb splinefit}, {helpb streamplot}, {helpb sunburst}, {helpb ternary}, {helpb treecluster}, {helpb treemap}, {helpb trimap}, {helpb waffle} 72 | 73 | or visit {browse "https://github.com/asjadnaqvi":GitHub}. 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /installation/shape.ado: -------------------------------------------------------------------------------- 1 | *! shapes v1.2 (15 Oct 2024) 2 | *! Asjad Naqvi (asjadnaqvi@gmail.com) 3 | 4 | **** duplicate of shapes 5 | 6 | cap program drop shape 7 | 8 | program shape 9 | shapes `0' 10 | end 11 | 12 | 13 | *** END OF PROGRAM *** -------------------------------------------------------------------------------- /installation/shape.sthlp: -------------------------------------------------------------------------------- 1 | .h shapes -------------------------------------------------------------------------------- /installation/shapes.ado: -------------------------------------------------------------------------------- 1 | *! shapes v1.3 (05 Nov 2024) 2 | *! Asjad Naqvi (asjadnaqvi@gmail.com) 3 | 4 | * v1.3 (05 Nov 2024): add append as sub for stack. Added square. 5 | * v1.2 (15 Oct 2024): added support for generating pies. added x0,y0 to control center points. 6 | * v1.1 (13 Oct 2024): Fixed a bug where an existing _N was resulting in additional rows being added below. This version tracks indices much better. 7 | * v1.0 (11 Oct 2024): first release. 8 | 9 | 10 | cap program drop shapes 11 | 12 | program define shapes 13 | 14 | version 11 15 | gettoken subcmd 0: 0, parse(", ") 16 | 17 | // draw 18 | if "`subcmd'" == "circle" _circle `0' 19 | if "`subcmd'" == "pie" _pie `0' 20 | if "`subcmd'" == "square" _square `0' 21 | 22 | // modify 23 | if "`subcmd'" == "rotate" _rotate `0' 24 | 25 | // generate 26 | if "`subcmd'" == "area" _area `0' 27 | 28 | end 29 | 30 | ************** 31 | *** circle *** 32 | ************** 33 | 34 | program define _circle 35 | version 11 36 | 37 | syntax [, x0(real 0) y0(real 0) n(real 100) ROtate(real 0) RADius(real 10) genx(string) geny(string) genid(string) genorder(string) replace stack append ] 38 | 39 | 40 | quietly { 41 | 42 | 43 | // prepare the variables 44 | local xvar _x 45 | local yvar _y 46 | local idvar _id 47 | local ordervar _order 48 | 49 | 50 | if "`genx'" != "" local xvar `genx' 51 | if "`geny'" != "" local yvar `geny' 52 | if "`genid'" != "" local idvar `genid' 53 | if "`genorder'" != "" local ordervar `genorder' 54 | 55 | if "`replace'" != "" { 56 | cap drop `xvar' 57 | cap drop `yvar' 58 | cap drop `idvar' 59 | cap drop `ordervar' 60 | 61 | } 62 | 63 | cap generate double `xvar' = . 64 | cap generate double `yvar' = . 65 | cap generate `idvar' = . 66 | cap generate `ordervar' = . 67 | 68 | 69 | if "`stack'" != "" | "`append'" !="" { 70 | 71 | tempvar temp 72 | gen `temp' = _n if !missing(`ordervar') 73 | summ `temp', meanonly 74 | 75 | if r(N)!= 0 { 76 | local start = `=`r(max)' + 1' 77 | local end = `=`r(max)' + `n' + 2' 78 | 79 | if _N < `=`r(max)'+`n'+2' set obs `end' 80 | } 81 | else { 82 | local start = 1 83 | local end = `=`n' + 2' 84 | if _N < `n' set obs `end' 85 | } 86 | 87 | } 88 | else { 89 | local start = 1 90 | local end = `=`n' + 2' 91 | if _N < `n' set obs `end' 92 | } 93 | 94 | 95 | summ `idvar', meanonly 96 | 97 | if `r(N)'==0 { 98 | local k = 1 99 | } 100 | else { 101 | local k = `r(max)' + 1 102 | } 103 | 104 | summ `ordervar', meanonly 105 | replace `idvar' = `k' in `start'/`end' 106 | 107 | 108 | // generate the indices 109 | tempvar _temp _temp2 _seq _angle 110 | gen `_temp' = 1 111 | replace `ordervar' = sum(`_temp') if `idvar'==`k' 112 | 113 | gen `_temp2' = _n 114 | 115 | summ `_temp2' if `idvar'==`k', meanonly 116 | local end = `end' - 2 117 | 118 | // add shape 119 | local rotate = `rotate' * _pi / 180 120 | 121 | gen double `_angle' = (`ordervar' * 2 * _pi / `n') + `rotate' in `start'/`end' 122 | 123 | replace `xvar' = `x0' + `radius' * cos(`_angle') in `start'/`end' 124 | replace `yvar' = `y0' + `radius' * sin(`_angle') in `start'/`end' 125 | 126 | 127 | // duplicate first row to complete the shape 128 | summ `xvar' in `start', meanonly 129 | replace `xvar' = `r(min)' in `=`end' + 1' 130 | 131 | summ `yvar' in `start', meanonly 132 | replace `yvar' = `r(min)' in `=`end' + 1' 133 | 134 | 135 | } 136 | 137 | 138 | end 139 | 140 | 141 | 142 | ************** 143 | *** pie *** 144 | ************** 145 | 146 | program define _pie 147 | version 11 148 | 149 | syntax, [ x0(real 0) y0(real 0) RADius(real 10) start(real 0) end(real 30) n(real 30) ROtate(real 0) ] /// 150 | [ genx(string) geny(string) genid(string) genorder(string) replace stack dropbase append flip ] 151 | 152 | 153 | // prepare the variables 154 | local xvar _x 155 | local yvar _y 156 | local idvar _id 157 | local ordervar _order 158 | 159 | if `n' < 2 { 160 | display as error "n() should be greater or equal to 2." 161 | exit 162 | } 163 | 164 | if "`replace'" != "" { 165 | cap drop `xvar' 166 | cap drop `yvar' 167 | cap drop `idvar' 168 | cap drop `ordervar' 169 | } 170 | 171 | if "`genx'" != "" local xvar `genx' 172 | if "`geny'" != "" local yvar `geny' 173 | if "`genid'" != "" local idvar `genid' 174 | if "`genorder'" != "" local ordervar `genorder' 175 | 176 | quietly { 177 | 178 | if "`replace'" != "" { 179 | cap drop `xvar' 180 | cap drop `yvar' 181 | cap drop `idvar' 182 | cap drop `ordervar' 183 | } 184 | 185 | cap generate double `xvar' = . 186 | cap generate double `yvar' = . 187 | cap generate `idvar' = . 188 | cap generate `ordervar' = . 189 | 190 | 191 | if "`flip'" != "" local end = `end' * -1 192 | 193 | // Calculate the range of angles from the starting angle to the ending angle in radians 194 | 195 | local theta_start = (`start' + `rotate') * _pi / 180 196 | local theta_end = (`end' + `rotate') * _pi / 180 197 | 198 | 199 | if "`stack'" != "" | "`append'" !="" { 200 | 201 | tempvar temp 202 | gen `temp' = _n if !missing(`ordervar') 203 | summ `temp', meanonly 204 | 205 | if r(N)!= 0 { 206 | local start = `=`r(max)' + 1' 207 | local end = `=`r(max)' + `n' + 4' 208 | 209 | if _N < `=`r(max)'+`n'+4' set obs `end' 210 | } 211 | else { 212 | local start = 1 213 | local end = `=`n' + 4' 214 | if _N < `n' set obs `end' 215 | } 216 | 217 | } 218 | else { 219 | local start = 1 220 | local end = `=`n' + 4' 221 | if _N < `n' set obs `end' 222 | } 223 | 224 | summ `idvar', meanonly 225 | 226 | if `r(N)'==0 { 227 | local k = 1 228 | } 229 | else { 230 | local k = `r(max)' + 1 231 | } 232 | 233 | replace `idvar' = `k' in `start'/`end' 234 | 235 | 236 | // generate the indices 237 | tempvar _temp _temp2 _seq _angle 238 | gen `_temp' = 1 239 | replace `ordervar' = sum(`_temp') if `idvar'==`k' 240 | 241 | gen `_temp2' = _n 242 | 243 | summ `_temp2' if `idvar'==`k', meanonly 244 | local end = `end' - 3 245 | 246 | tempvar theta 247 | gen double `theta' = `theta_start' + ((`ordervar'-1) /`n') * (`theta_end' - `theta_start') in `start'/`end' 248 | 249 | // Calculate the x and y coordinates for this angle 250 | replace `xvar' = `x0' + `radius' * cos(`theta') in `start'/`end' 251 | replace `yvar' = `y0' + `radius' * sin(`theta') in `start'/`end' 252 | 253 | 254 | if "`dropbase'" == "" { 255 | // pad the centers 256 | replace `xvar' = `x0' in `=`end'+1' 257 | replace `yvar' = `y0' in `=`end'+1' 258 | 259 | 260 | // pad the starting value 261 | sum `xvar' if `ordervar'==1 & `idvar'==`k', meanonly 262 | replace `xvar' = `r(min)' in `=`end'+2' 263 | 264 | sum `yvar' if `ordervar'==1 & `idvar'==`k', meanonly 265 | replace `yvar' = `r(min)' in `=`end'+2' 266 | } 267 | } 268 | 269 | end 270 | 271 | 272 | ***************** 273 | *** square *** 274 | ***************** 275 | 276 | 277 | program define _square 278 | version 11 279 | 280 | syntax, [ x0(real 0) y0(real 0) LENgth(real 10) ROtate(real 0) ] /// 281 | [ genx(string) geny(string) genid(string) genorder(string) replace stack append flip ] 282 | 283 | 284 | // prepare the variables 285 | local xvar _x 286 | local yvar _y 287 | local idvar _id 288 | local ordervar _order 289 | local n = 4 290 | 291 | quietly { 292 | if "`genx'" != "" local xvar `genx' 293 | if "`geny'" != "" local yvar `geny' 294 | if "`genid'" != "" local idvar `genid' 295 | if "`genorder'" != "" local ordervar `genorder' 296 | 297 | if "`replace'" != "" { 298 | cap drop `xvar' 299 | cap drop `yvar' 300 | cap drop `idvar' 301 | cap drop `ordervar' 302 | } 303 | 304 | 305 | cap generate double `xvar' = . 306 | cap generate double `yvar' = . 307 | cap generate `idvar' = . 308 | cap generate `ordervar' = . 309 | 310 | if "`stack'" != "" | "`append'" !="" { 311 | tempvar temp 312 | gen `temp' = _n if !missing(`ordervar') 313 | summ `temp', meanonly 314 | 315 | if r(N)!= 0 { 316 | local start = `=`r(max)' + 1' 317 | local end = `=`r(max)' + `n' + 2' 318 | 319 | if _N < `=`r(max)'+`n'+2' set obs `end' 320 | } 321 | else { 322 | local start = 1 323 | local end = `=`n' + 2' 324 | if _N < `n' set obs `end' 325 | } 326 | 327 | } 328 | else { 329 | local start = 1 330 | local end = `=`n' + 2' 331 | if _N < `n' set obs `end' 332 | } 333 | 334 | summ `idvar', meanonly 335 | 336 | if `r(N)'==0 { 337 | local k = 1 338 | } 339 | else { 340 | local k = `r(max)' + 1 341 | } 342 | 343 | replace `idvar' = `k' in `start'/`end' 344 | 345 | tempvar _temp 346 | gen `_temp' = 1 347 | replace `ordervar' = sum(`_temp') if `idvar'==`k' 348 | 349 | 350 | // add the coordinates 351 | replace `xvar' = ( `length' / 2) in `start' 352 | replace `yvar' = ( `length' / 2) in `start' 353 | 354 | replace `xvar' = (-`length' / 2) in `=`start' + 1' 355 | replace `yvar' = ( `length' / 2) in `=`start' + 1' 356 | 357 | replace `xvar' = (-`length' / 2) in `=`start' + 2' 358 | replace `yvar' = (-`length' / 2) in `=`start' + 2' 359 | 360 | replace `xvar' = ( `length' / 2) in `=`start' + 3' 361 | replace `yvar' = (-`length' / 2) in `=`start' + 3' 362 | 363 | replace `xvar' = ( `length' / 2) in `=`start' + 4' // duplicate of the first row 364 | replace `yvar' = ( `length' / 2) in `=`start' + 4' 365 | 366 | // rotation 367 | 368 | tempvar _mymod _angle 369 | 370 | gen `_mymod' = mod(`ordervar', 4) // index 371 | recode `_mymod' (0=4) 372 | 373 | local rotate = (-45 + `rotate') * _pi / 180 // compensate for square shape 374 | gen double `_angle' = (`_mymod' * 2 * _pi / `n') + `rotate' in `start'/`end' 375 | 376 | local _radius = sqrt(2) * `length' / 2 377 | 378 | replace `xvar' = `x0' + `_radius' * cos(`_angle') in `start'/`=`start' + 4' 379 | replace `yvar' = `y0' + `_radius' * sin(`_angle') in `start'/`=`start' + 4' 380 | 381 | 382 | } 383 | end 384 | 385 | 386 | 387 | cap program drop _rotate 388 | 389 | program _rotate, sortpreserve 390 | 391 | version 11 392 | 393 | syntax varlist(numeric min=2 max=2), [ ROtate(real 0) by(varname) x0(real 0) y0(real 0) replace genx(string) geny(string) center ] 394 | 395 | tokenize `varlist' 396 | local vary `1' 397 | local varx `2' 398 | 399 | quietly { 400 | 401 | if "`center'" != "" { 402 | if "`by'" == "" { 403 | summ `varx', meanonly 404 | local x0 = (`r(min)' + `r(max)') / 2 405 | 406 | summ `vary', meanonly 407 | local y0 = (`r(min)' + `r(max)') / 2 408 | } 409 | else { 410 | tempvar _meanx _meany _minx _miny _maxx _maxy 411 | sort `by' _id _order 412 | 413 | by `by': egen `_minx' = min(`varx') 414 | by `by': egen `_miny' = min(`vary') 415 | 416 | by `by': egen `_maxx' = max(`varx') 417 | by `by': egen `_maxy' = max(`vary') 418 | 419 | gen double `_meanx' = (`_minx' + `_maxx') / 2 420 | gen double `_meany' = (`_miny' + `_maxy') / 2 421 | 422 | } 423 | 424 | } 425 | 426 | 427 | local angle = `rotate' * _pi / 180 428 | 429 | 430 | local xvar _x_rot // default names 431 | local yvar _y_rot 432 | 433 | if "`genx'" != "" local xvar `genx' 434 | if "`geny'" != "" local yvar `geny' 435 | 436 | 437 | tempvar _x0 _y0 x_rot_t y_rot_t 438 | 439 | if "`by'" != "" { // by() defined 440 | local x0 `_meanx' 441 | local y0 `_meany' 442 | } 443 | 444 | 445 | gen double `_x0' = `varx' - `x0' 446 | gen double `_y0' = `vary' - `y0' 447 | 448 | gen double `x_rot_t' = `_x0' * cos(`angle') - `_y0' * sin(`angle') 449 | gen double `y_rot_t' = `_x0' * sin(`angle') + `_y0' * cos(`angle') 450 | 451 | if "`replace'" != "" { // here replace is replacing the original variables. use carefully. 452 | replace `varx' = `x_rot_t' + `x0' 453 | replace `vary' = `y_rot_t' + `y0' 454 | } 455 | else { 456 | cap drop `xvar' 457 | cap drop `yvar' 458 | 459 | generate `xvar' = `x_rot_t' + `x0' 460 | generate `yvar' = `y_rot_t' + `y0' 461 | } 462 | 463 | 464 | } 465 | 466 | end 467 | 468 | 469 | 470 | cap program drop _area 471 | 472 | program _area, sortpreserve 473 | 474 | 475 | // apply the Meister's shoelace formula (shoelace formula: https://en.wikipedia.org/wiki/Shoelace_formula) 476 | 477 | version 11 478 | syntax varlist(numeric min=2 max=2), by(varname) [ replace GENerate(string) ] 479 | 480 | tokenize `varlist' 481 | local y `1' 482 | local x `2' 483 | 484 | quietly { 485 | local myvar _area 486 | 487 | if "`generate'" != "" local myvar `generate' 488 | if "`replace'" != "" capture drop `myvar' 489 | 490 | tempvar _values 491 | 492 | bysort `by': gen double `_values' = ((`y' * `x'[_n+1]) - (`y'[_n+1] * `x')) /2 493 | bysort `by': replace `_values' = ((`y' * `x'[2]) - (`y'[2] * `x')) /2 if `_values'!=. 494 | 495 | bysort `by': egen double `myvar' = sum(`_values') 496 | } 497 | 498 | end 499 | 500 | ********************************* 501 | ******** END OF PROGRAM ********* 502 | ********************************* 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | -------------------------------------------------------------------------------- /installation/shapes.sthlp: -------------------------------------------------------------------------------- 1 | {smcl} 2 | {* 05Nov2024}{...} 3 | {hi:help shapes}{...} 4 | {right:{browse "https://github.com/asjadnaqvi/stata-graphfunctions":graphfunctions (GitHub)}} 5 | 6 | {hline} 7 | 8 | {title:shapes}: A program for generating, transforming, and calculating features of shapes. 9 | 10 | {it:Notes:} 11 | 1. {cmd:shape} can also be used as a substitute for {cmd:shapes}. 12 | 2. All shapes start at the 3 o' clock position (Stata default) relative to the origin. 13 | 3. All shapes are drawn counter-clockwise. Option {opt flip} can be used to change the drawing orientation in some cases. 14 | 4. The default origin is {cmd:(0,0)}. 15 | 5. Rotation is always around the origin. 16 | 6. Positive rotation values will result in counter-clockwise adjustments (Stata default). Negative angles are therefore clockwise. 17 | 7. Each shape will generate four variables {cmd:_x}, {cmd:_y}, {cmd:_order}, and {cmd:_id}. These represent the coordinates, point order, and shape identifier respectively. 18 | 19 | This program is currenly {it:beta} and does not have all the checks. 20 | 21 | {marker syntax}{title:Syntax} 22 | 23 | {pstd} 24 | Generating shapes: 25 | 26 | {p 8 15 2} 27 | {cmd:shapes} circle, {cmd:[} {help shapes##circle:{it:circle_options}} {help shapes##common:{it:common_options}} {cmd:]} 28 | 29 | {p 8 15 2} 30 | {cmd:shapes} pie, {cmd:[} {help shapes##pie:{it:pie_options}} {help shapes##common:{it:common_options}} {cmd:]} 31 | 32 | {p 8 15 2} 33 | {cmd:shapes} square, {cmd:[} {help shapes##square:{it:square_options}} {help shapes##common:{it:common_options}} {cmd:]} 34 | 35 | 36 | {pstd} 37 | Transforming shapes: 38 | 39 | {p 8 15 2} 40 | {cmd:shapes} rotate y x, {opt ro:tate(degrees)} {cmd:[} {help shapes##rotate:{it:rotate_options}} {cmd:]} 41 | 42 | 43 | {pstd} 44 | Calculating shape features: 45 | 46 | {p 8 15 2} 47 | {cmd:shapes} area y x, {opt by(variable)} {cmd:[} {help shapes##area:{it:area_options}} {cmd:]} 48 | 49 | 50 | 51 | {synoptset 36 tabbed}{...} 52 | {marker circle}{synopthdr:circle_options} 53 | {synoptline} 54 | 55 | {p2coldent : {opt rad:ius(num)}}Specify the radius length. Default is {opt rad(10)}.{p_end} 56 | 57 | {p2coldent : {opt n(int)}}Number of points to evaluate for the shape. Default is {opt n(100)}. Smaller values, e.g. {opt n(6)} will generate a hexagon.{p_end} 58 | 59 | {p2coldent : {opt ro:tate(degrees)}}Rotate the shape counter-clockwise by {it:degrees}. Default is {opt ro(0)}.{p_end} 60 | 61 | {p2coldent : {opt x0(num)}, {opt y0(num)}}Center points. Defaults are {opt x0(0)} and {opt y0(0)}.{p_end} 62 | 63 | {synoptline} 64 | 65 | 66 | 67 | {synoptset 36 tabbed}{...} 68 | {marker pie}{synopthdr:pie_options} 69 | {synoptline} 70 | 71 | {p2coldent : {opt start(degrees)}}Starting angle of the pie arc. Default is {opt start(0)}.{p_end} 72 | 73 | {p2coldent : {opt end(degrees)}}Ending angle of the pie arc. Default is {opt end(30)}.{p_end} 74 | 75 | {p2coldent : {opt rad:ius(num)}}Specify the radius length. Default is {opt rad(10)}.{p_end} 76 | 77 | {p2coldent : {opt n(int)}}Number of points to evaluate for the arc. Default is {opt n(30)}.{p_end} 78 | 79 | {p2coldent : {opt ro:tate(degrees)}}Rotate the shape by {it:degrees}. Default is {opt ro(0)}.{p_end} 80 | 81 | {p2coldent : {opt x0(num)}, {opt y0(num)}}Points of the arc origin. Defaults are {opt x0(0)} and {opt y0(0)}.{p_end} 82 | 83 | {p2coldent : {opt dropbase}}Drop the pie starting values (x0,y0), or, just generate an arc.{p_end} 84 | 85 | {p2coldent : {opt flip}}Flips the drawing direction to clockwise.{p_end} 86 | 87 | {synoptline} 88 | 89 | 90 | 91 | {synoptset 36 tabbed}{...} 92 | {marker square}{synopthdr:square_options} 93 | {synoptline} 94 | 95 | {p2coldent : {opt x0(num)}, {opt y0(num)}}Center points. Defaults are {opt x0(0)} and {opt y0(0)}.{p_end} 96 | 97 | {p2coldent : {opt len:gth(num)}}Specify the square edge length. Default is {opt len(10)}.{p_end} 98 | 99 | {p2coldent : {opt ro:tate(degrees)}}Rotate the shape by {it:degrees} at the center. Default is {opt ro(0)}.{p_end} 100 | 101 | {synoptline} 102 | 103 | 104 | 105 | {synoptset 36 tabbed}{...} 106 | {marker common}{synopthdr:common_options} 107 | {synoptline} 108 | 109 | {p2coldent : {opt genx(newvar)}, {opt geny(newvar)}}Custom names for the {cmd:_x} and {cmd:_y} variables.{p_end} 110 | 111 | {p2coldent : {opt genorder(newvar)}}Custom name for the {cmd:_order} variable.{p_end} 112 | 113 | {p2coldent : {opt genid(newvar)}}Custom name for the {cmd:_id} variable.{p_end} 114 | 115 | {p2coldent : {opt stack} {it:or} {opt append}}Append the shape variables. Can be used for generating a set of shapes.{p_end} 116 | 117 | {p2coldent : {opt replace}}Replace the variables.{p_end} 118 | 119 | {synoptline} 120 | 121 | {p2colreset}{...} 122 | 123 | 124 | 125 | {synoptset 36 tabbed}{...} 126 | {marker rotate}{synopthdr:rotate_options} 127 | {synoptline} 128 | 129 | {p2coldent : {opt shapes rotate y x, rotate(degrees)}}Minimum required syntax.{p_end} 130 | 131 | {p2coldent : {opt ro:tate(degrees)}}Rotate the shape by {it:degrees} at the center. Default is {opt ro(30)}.{p_end} 132 | 133 | {p2coldent : {opt x0(num)}, {opt y0(num)}}Rotation points. Defaults are {opt x0(0)} and {opt y0(0)}.{p_end} 134 | 135 | {p2coldent : {opt center}}Rotate on the mean of {varlist} variables.{p_end} 136 | 137 | {p2coldent : {opt by(variable)}}Rotate each {opt by()} level individual. Can only be combined with {opt center}.{p_end} 138 | 139 | {p2coldent : {opt genx(newvar)}, {opt geny(newvar)}}Custom names for the {cmd:_x} and {cmd:_y} variables.{p_end} 140 | 141 | {synoptline} 142 | 143 | 144 | 145 | {synoptset 36 tabbed}{...} 146 | {marker area}{synopthdr:area_options} 147 | {synoptline} 148 | 149 | {p2coldent : {opt shapes area y x, by(var)}}Minimum required syntax.{p_end} 150 | 151 | {p2coldent : {opt by(variable)}}Generate areas using {by()}. For default variable names, this is the {opt by(_id)} variable.{p_end} 152 | 153 | {p2coldent : {opt gen:erate(newvar)}}Custom name for the {cmd:_area} variable.{p_end} 154 | 155 | {synoptline} 156 | 157 | 158 | 159 | 160 | {title:Examples} 161 | 162 | Please see {browse "https://github.com/asjadnaqvi/stata-graphfunctions":GitHub} for a comprehensive set of examples. 163 | 164 | Circles: 165 | {stata shape circle, n(8) ro(22.5) rad(8) replace} 166 | {stata twoway (connected _y _x), xsize(1) ysize(1) aspect(1) xlabel(-10 10) ylabel(-10 10)} 167 | 168 | Pies: 169 | {stata shape pie, start(0) end(60) ro(30) rad(8) replace} 170 | {stata twoway (area _y _x, fcolor(%90) cmissing(n) nodropbase), xsize(1) ysize(1) aspect(1) xlabel(-10 10) ylabel(-10 10)} 171 | 172 | 173 | 174 | {title:Package details} 175 | 176 | Version : {bf:shapes} v1.3 in {stata help graphfunctions:graphfunctions} 177 | This release : 05 Nov 2024 178 | First release: 11 Oct 2024 179 | Repository : {browse "https://github.com/asjadnaqvi/stata-graphfunctions":GitHub} 180 | Keywords : Stata, graph, shapes 181 | License : {browse "https://opensource.org/licenses/MIT":MIT} 182 | 183 | Author : {browse "https://github.com/asjadnaqvi":Asjad Naqvi} 184 | E-mail : asjadnaqvi@gmail.com 185 | Twitter/X : {browse "https://x.com/AsjadNaqvi":@AsjadNaqvi} 186 | 187 | 188 | {title:Feedback} 189 | 190 | Please submit bugs, errors, feature requests on {browse "https://github.com/asjadnaqvi/stata-graphfunctions/issues":GitHub} by opening a new issue. 191 | 192 | 193 | {title:Citation guidelines} 194 | 195 | See {stata help graphfunctions:graphfunctions}. 196 | 197 | 198 | {title:Other packages} 199 | 200 | {psee} 201 | {helpb arcplot}, {helpb alluvial}, {helpb bimap}, {helpb bumparea}, {helpb bumpline}, {helpb circlebar}, {helpb circlepack}, {helpb clipgeo}, {helpb delaunay}, {helpb graphfunctions}, {helpb joyplot}, 202 | {helpb marimekko}, {helpb polarspike}, {helpb sankey}, {helpb schemepack}, {helpb spider}, {helpb splinefit}, {helpb streamplot}, {helpb sunburst}, {helpb ternary}, {helpb treecluster}, {helpb treemap}, {helpb trimap}, {helpb waffle} 203 | 204 | or visit {browse "https://github.com/asjadnaqvi":GitHub}. 205 | 206 | 207 | 208 | -------------------------------------------------------------------------------- /installation/stata.toc: -------------------------------------------------------------------------------- 1 | v 1.51 2 | d GRAPHFUNCTIONS: Added functionality for graphs. 3 | d Distribution-Date: 20241128 4 | d 5 | d Asjad Naqvi 6 | d asjadnaqvi@gmail.com 7 | 8 | 9 | --------------------------------------------------------------------------------