Skip to content

Commit e35ca5f

80-
"File \u001b[0;32m~/bin/python/lib/python3.8/site-packages/opendssdirect/Text.py:17\u001b[0m, in \u001b[0;36mCommand\u001b[0;34m(*args)\u001b[0m\n\u001b[1;32m 14\u001b[0m Value \u001b[39m=\u001b[39m Value\u001b[39m.\u001b[39mencode(codec)\n\u001b[1;32m 16\u001b[0m lib\u001b[39m.\u001b[39mText_Set_Command(Value)\n\u001b[0;32m---> 17\u001b[0m CheckForError()\n",
81-
"File \u001b[0;32m~/bin/python/lib/python3.8/site-packages/dss/_cffi_api_util.py:128\u001b[0m, in \u001b[0;36mBase._check_for_error\u001b[0;34m(self, result)\u001b[0m\n\u001b[1;32m 126\u001b[0m error_num \u001b[39m=\u001b[39m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_errorPtr[\u001b[39m0\u001b[39m]\n\u001b[1;32m 127\u001b[0m \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_errorPtr[\u001b[39m0\u001b[39m] \u001b[39m=\u001b[39m \u001b[39m0\u001b[39m\n\u001b[0;32m--> 128\u001b[0m \u001b[39mraise\u001b[39;00m DSSException(error_num, \u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_get_string(\u001b[39mself\u001b[39m\u001b[39m.\u001b[39m_lib\u001b[39m.\u001b[39mError_Get_Description()))\n\u001b[1;32m 130\u001b[0m \u001b[39mreturn\u001b[39;00m result\n",
79+
"Cell \u001b[0;32mIn[3], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mdss\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mCommand\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mRedirect this_file_does_not_exist.dss\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n",
80+
"File \u001b[0;32m~/projects/dss/oddpy/opendssdirect/Text.py:20\u001b[0m, in \u001b[0;36mIText.Command\u001b[0;34m(self, *args)\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mtype\u001b[39m(Value) \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mbytes\u001b[39m:\n\u001b[1;32m 19\u001b[0m Value \u001b[38;5;241m=\u001b[39m Value\u001b[38;5;241m.\u001b[39mencode(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_api_util\u001b[38;5;241m.\u001b[39mcodec)\n\u001b[0;32m---> 20\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mCheckForError\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_lib\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mText_Set_Command\u001b[49m\u001b[43m(\u001b[49m\u001b[43mValue\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n",
81+
"File \u001b[0;32m~/projects/dss/dss_python/dss/_cffi_api_util.py:258\u001b[0m, in \u001b[0;36mBase._check_for_error\u001b[0;34m(self, result)\u001b[0m\n\u001b[1;32m 256\u001b[0m error_num \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_errorPtr[\u001b[38;5;241m0\u001b[39m]\n\u001b[1;32m 257\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_errorPtr[\u001b[38;5;241m0\u001b[39m] \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m0\u001b[39m\n\u001b[0;32m--> 258\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m DSSException(error_num, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_get_string(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_lib\u001b[38;5;241m.\u001b[39mError_Get_Description()))\n\u001b[1;32m 260\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m result\n",
8282
"\u001b[0;31mDSSException\u001b[0m: (#243) Redirect file not found: \"this_file_does_not_exist.dss\""
8383
]
8484
}
8585
],
8686
"source": [
87-
"dss.Text.Command('Redirect this_file_does_not_exist.dss')"
87+
"dss.Command('Redirect this_file_does_not_exist.dss')"
8888
]
8989
},
9090
{
@@ -100,15 +100,17 @@
100100
"metadata": {},
101101
"outputs": [],
102102
"source": [
103-
"dss.Text.Command('Redirect ./../../tests/data/13Bus/IEEE13Nodeckt.dss')"
103+
"dss.Command('Redirect \"./../../tests/data/13Bus/IEEE13Nodeckt.dss\"')"
104104
]
105105
},
106106
{
107107
"attachments": {},
108108
"cell_type": "markdown",
109109
"metadata": {},
110110
"source": [
111-
"👉 **In previous versions of this document, we used to recommend `dss.run_command()`. Unfortunately the error-checking from `run_command` can be confusing and we cannot change it, for historical and backwards-compatibility reasons.**"
111+
"👉 **In previous versions of this document, we used to recommend `dss.run_command()`. Unfortunately the error-checking from `run_command` can be confusing and we cannot change it, for historical and backwards-compatibility reasons.**\n",
112+
"\n",
113+
"`dss.Command` itself is a shortcut to `dss.Text.Command`, the interface function for dispatching single DSS commands. Since v0.9, when importing the `dss` instance (`from opendssdirect import dss`), one can also use just `dss('Redirect \"../../tests/data/13Bus/IEEE13Nodeckt.dss\"')` instead of `dss.Command('Redirect \"../../tests/data/13Bus/IEEE13Nodeckt.dss\"')` for an even shorter version. As an added feature, calling `dss(script_string)` also allows passing multiple commands through multi-line strings."
112114
]
113115
},
114116
{
@@ -136,7 +138,7 @@
136138
}
137139
],
138140
"source": [
139-
"dss.Text.Command('? Load.634a.kW')\n",
141+
"dss('? Load.634a.kW')\n",
140142
"dss.Text.Result()"
141143
]
142144
},
@@ -259,60 +261,6 @@
259261
"name": "stdout",
260262
"output_type": "stream",
261263
"text": [
262-
"dss.ActiveClass\n",
263-
"dss.Basic\n",
264-
"dss.Bus\n",
265-
"dss.CNData\n",
266-
"dss.CapControls\n",
267-
"dss.Capacitors\n",
268-
"dss.Circuit\n",
269-
"dss.CktElement\n",
270-
"dss.CmathLib\n",
271-
"dss.CtrlQueue\n",
272-
"dss.DSSCore\n",
273-
"dss.DSSEvents\n",
274-
"dss.DSSimComs\n",
275-
"dss.Element\n",
276-
"dss.Error\n",
277-
"dss.Executive\n",
278-
"dss.Fuses\n",
279-
"dss.Generators\n",
280-
"dss.Isource\n",
281-
"dss.LineCodes\n",
282-
"dss.LineGeometries\n",
283-
"dss.LineSpacings\n",
284-
"dss.Lines\n",
285-
"dss.LoadShape\n",
286-
"dss.Loads\n",
287-
"dss.Meters\n",
288-
"dss.Monitors\n",
289-
"dss.PDElements\n",
290-
"dss.PVsystems\n",
291-
"dss.Parallel\n",
292-
"dss.Parser\n",
293-
"dss.Progress\n",
294-
"dss.Properties\n",
295-
"dss.Reactors\n",
296-
"dss.Reclosers\n",
297-
"dss.ReduceCkt\n",
298-
"dss.RegControls\n",
299-
"dss.Relays\n",
300-
"dss.Sensors\n",
301-
"dss.Settings\n",
302-
"dss.Solution\n",
303-
"dss.Storages\n",
304-
"dss.SwtControls\n",
305-
"dss.TSData\n",
306-
"dss.Text\n",
307-
"dss.Topology\n",
308-
"dss.Transformers\n",
309-
"dss.Vsources\n",
310-
"dss.WireData\n",
311-
"dss.XYCurves\n",
312-
"dss.YMatrix\n",
313-
"dss.ZIP\n",
314-
"dss.dss\n",
315-
"dss.dss_lib\n",
316264
"dss.utils\n"
317265
]
318266
}
@@ -368,6 +316,7 @@
368316
"dss.Loads.Phases\n",
369317
"dss.Loads.RelWeighting\n",
370318
"dss.Loads.Rneut\n",
319+
"dss.Loads.Sensor\n",
371320
"dss.Loads.Spectrum\n",
372321
"dss.Loads.Status\n",
373322
"dss.Loads.Vmaxpu\n",
@@ -378,16 +327,12 @@
378327
"dss.Loads.Xneut\n",
379328
"dss.Loads.Yearly\n",
380329
"dss.Loads.ZipV\n",
381-
"dss.Loads.get_float64_array\n",
382-
"dss.Loads.get_string\n",
383-
"dss.Loads.get_string_array\n",
384330
"dss.Loads.kV\n",
385331
"dss.Loads.kVABase\n",
386332
"dss.Loads.kW\n",
387333
"dss.Loads.kWh\n",
388334
"dss.Loads.kWhDays\n",
389335
"dss.Loads.kvar\n",
390-
"dss.Loads.prepare_float64_array\n",
391336
"dss.Loads.puSeriesRL\n"
392337
]
393338
}
@@ -476,12 +421,12 @@
476421
"cell_type": "markdown",
477422
"metadata": {},
478423
"source": [
479-
"To get all `kW`, one must iterate over all the loads"
424+
"To get all `kW`, one must iterate over all the loads. v0.9+ support Python iterators, so a simple `for` will do. Remember that OpenDSS API restrictions still apply -- a simple object of this type must be active. Check [AltDSS-Python](https://github.com/dss-extensions/AltDSS-Python) for an alternative."
480425
]
481426
},
482427
{
483428
"cell_type": "code",
484-
"execution_count": 16,
429+
"execution_count": 18,
485430
"metadata": {},
486431
"outputs": [
487432
{
@@ -507,53 +452,25 @@
507452
}
508453
],
509454
"source": [
510-
"dss.Loads.First()\n",
511-
"\n",
512-
"while True:\n",
513-
" \n",
455+
"for load in dss.Loads:\n",
514456
" print(\n",
515457
" 'Name={name} \\t kW={kW}'.format(\n",
516-
" name=dss.Loads.Name(), \n",
517-
" kW=dss.Loads.kW()\n",
458+
" name=load.Name(), \n",
459+
" kW=load.kW()\n",
518460
" )\n",
519-
" )\n",
520-
" \n",
521-
" if not dss.Loads.Next() > 0:\n",
522-
" break"
461+
" )"
523462
]
524463
},
525464
{
526465
"cell_type": "markdown",
527466
"metadata": {},
528467
"source": [
529-
"The `utils` module provides an `Iterator` class as a helper function"
468+
"List comprehensions also work great:"
530469
]
531470
},
532471
{
533472
"cell_type": "code",
534-
"execution_count": 17,
535-
"metadata": {
536-
"collapsed": true
537-
},
538-
"outputs": [],
539-
"source": [
540-
"from opendssdirect.utils import Iterator"
541-
]
542-
},
543-
{
544-
"cell_type": "code",
545-
"execution_count": 18,
546-
"metadata": {
547-
"collapsed": true
548-
},
549-
"outputs": [],
550-
"source": [
551-
"load_kW = [i() for i in Iterator(dss.Loads, 'kW')]"
552-
]
553-
},
554-
{
555-
"cell_type": "code",
556-
"execution_count": 19,
473+
"execution_count": 23,
557474
"metadata": {},
558475
"outputs": [
559476
{
@@ -576,51 +493,74 @@
576493
" 120.0]"
577494
]
578495
},
579-
"execution_count": 19,
496+
"execution_count": 23,
580497
"metadata": {},
581498
"output_type": "execute_result"
582499
}
583500
],
584501
"source": [
585-
"load_kW"
502+
"[l.kW() for l in dss.Loads]"
503+
]
504+
},
505+
{
506+
"cell_type": "markdown",
507+
"metadata": {},
508+
"source": [
509+
"The (now deprecated) `Iterator` class from the `utils` module provides a similar option in pre-v0.9 version. As seen below, it has greater overhead, so prefer the usual Python iteration for new code."
586510
]
587511
},
588512
{
589513
"cell_type": "code",
590-
"execution_count": 20,
514+
"execution_count": 19,
515+
"metadata": {
516+
"collapsed": true
517+
},
518+
"outputs": [],
519+
"source": [
520+
"from opendssdirect.utils import Iterator"
521+
]
522+
},
523+
{
524+
"cell_type": "code",
525+
"execution_count": 24,
526+
"metadata": {
527+
"collapsed": true
528+
},
529+
"outputs": [
530+
{
531+
"name": "stderr",
532+
"output_type": "stream",
533+
"text": [
534+
"<magic-timeit>:1: DeprecationWarning: OpenDSSDirect.py's Iterator is deprecated; you can use native Python iterators directly now.\n"
535+
]
536+
},
537+
{
538+
"name": "stdout",
539+
"output_type": "stream",
540+
"text": [
541+
"5.59 µs ± 33.7 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n"
542+
]
543+
}
544+
],
545+
"source": [
546+
"%timeit load_kW = [i() for i in Iterator(dss.Loads, 'kW')]\n"
547+
]
548+
},
549+
{
550+
"cell_type": "code",
551+
"execution_count": 22,
591552
"metadata": {},
592553
"outputs": [
593554
{
594555
"name": "stdout",
595556
"output_type": "stream",
596557
"text": [
597-
"Name=671 \t kW=1155.0\n",
598-
"Name=634a \t kW=160.0\n",
599-
"Name=634b \t kW=120.0\n",
600-
"Name=634c \t kW=120.0\n",
601-
"Name=645 \t kW=170.0\n",
602-
"Name=646 \t kW=230.0\n",
603-
"Name=692 \t kW=170.0\n",
604-
"Name=675a \t kW=485.0\n",
605-
"Name=675b \t kW=68.0\n",
606-
"Name=675c \t kW=290.0\n",
607-
"Name=611 \t kW=170.0\n",
608-
"Name=652 \t kW=128.0\n",
609-
"Name=670a \t kW=17.0\n",
610-
"Name=670b \t kW=66.0\n",
611-
"Name=670c \t kW=120.0\n"
558+
"3.81 µs ± 24.1 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)\n"
612559
]
613560
}
614561
],
615562
"source": [
616-
"for i in Iterator(dss.Loads, 'Name'):\n",
617-
" \n",
618-
" print(\n",
619-
" 'Name={name} \\t kW={kW}'.format(\n",
620-
" name=i(), \n",
621-
" kW=dss.Loads.kW()\n",
622-
" )\n",
623-
" )"
563+
"%timeit load_kW = [l.kW() for l in dss.Loads]"
624564
]
625565
}
626566
],
@@ -640,7 +580,7 @@
640580
"name": "python",
641581
"nbconvert_exporter": "python",
642582
"pygments_lexer": "ipython3",
643-
"version": "3.8.12 | packaged by conda-forge | (default, Jan 30 2022, 23:42:07) \n[GCC 9.4.0]"
583+
"version": "3.11.4"
644584
},
645585
"vscode": {
646586
"interpreter": {